Subject: Set of Ideas

From: [email-masked]
Date: Wed, 2 Sep 92 20:56:24 EDT

This is a preliminary specification of the video drivers.  No files
are available yet, but comments are invited.

--------------------------------------------------------------------------
| My life is Hardware,                    |         Dave Stampe          | 
| my destiny is Software,                 | [email-masked]    |
| my CPU is Wetware...                    | [email-masked]   | 
| Am I a techno-psychologist, or just an engineer dabbling in psychology?|
--------------------------------------------------------------------------

REND386 VIDEO DRIVER CREATION

Video drivers are compiled in pseudo-tiny mode (code, data in one
segment, stack not assumed in the same segment).  The interface is through
an assembly routine linked to REND386, and trough a calltable at the start
of the driver.

During development, the call module (vdrinte.asm) may be left out of the
REND386 link, and the video driver code itself linked in.  At this stage,
all assembly modules should use the .MODEL LARGE directive.

Once development is completed, change th memory model of the assembly code
to .MODEL TINY FARSTACK and use a batch file based on mkxvd.bat to create
the driver.  Sounds simple, right?  I wish it was.  You'll probably have to
avoid the use of C library calls in the C part of your code, as the C tiny
mode libraries assume SS=DS=CS (very nasty).  In theory, you can compile the
C code in the compact model, then link and use EXE2BIN to convert to a
single segment.

WARNING: IF YOU SEE "FIXUP REQUIRED" WHILE RUNNING EXE2BIN, YOUR DRIVER
WILL NOT WORK.

I'd appreciate it if someone more knowlwdgeable about DOS linking etc.
straightened out the link procedure, as it would be invaluable to be
able to use the COMPACT memory model in all cases.  Right now, it is
sort of iffy: the video driver needs TINY mode C compilation to work,
while the mouse pointer driver functions well with COMPACT model.
Any ideas?

-------------------------------

FUNCTIONS TO BE SUPPORTED BY VIDEO DRIVER:
Note all the FAR attributes of the prototypes: VERY IMPORTANT.
----
struct Screeninfo {
	int xmin, ymin, xmax, ymax, xcent, ycent, colors, pages, bw;
	char id[80];
	};

struct Screeninfo far * far screen_data();

This is usually the first call made by REND386 to the driver, and it should
return a far pointer to a Screeninfo structure inside the driver.  Most of
the attributes in the structure are self-explanatory.  bw is 0 if a color
palette is to be used, 1 if a monochrome palette is preferred.
----
void far set_gmode(int arg);       /* enters graphics, clears screen */
void far exit_gmode();             /* exits to text mode */

These functions are self-explanetory.  If you have multiple video
sources for a HMD, this should initialize all sources in one call.
set_gmode() may be passed a single parameter to, for example, set
the video mode on a SVGA card from the .cfg file.
----
#define MAIN_VGA  1  /* for multi-VGA only */
#define LEFT_VGA  2
#define RIGHT_VGA 4
#define ALL_VGA   7

extern void far VGA_select(int card);

This functions selects one (or all) video sources to be drawn to.
If multiple bits are set (i.e to clear all sources in parallel, or
to draw to the main monitor and one of the HMD eye sources at once,
your driver should detect and handle this appropriately.
----
extern void far vsync();                /* pause till vert. retrace */

Self explanatory.  Used to setup the Sega/switcher timing, so it may
be called from interrupt handlers.
----
extern void far set_vpage(int page);    /* set video page */

Since this may be called by an interrupt handler, it should
NOT use BIOS calls to set the visible page.
----
#define PUT 0		/* defines of VGA write modes */
#define AND 1   /* for use with setup_hdwe()  */
#define OR  2
#define XOR 3

extern void far setup_hdwe(int mode);  /* setup VGA for bunch of line */
							 /* or poly draws: once per set */

extern void far reset_hdwe();  /* reset VGA to BIOS state after drawing */

Used to initialize hardware for drawing, and reset to standard mode after.
The drawing modes are optional: passing 0 always is safest.  setup_hdwe()
will be called before rendering screen polys etc; reset_hdwe() will be called
afterwards.  It may be called at other times as well.
-----
			 /* clear video page to solid color: 10 mS */
			 /* returns -1 if bad page #		 */
extern int far clr_page(int page, int color);
-----
			/* copy one page to another for use as */
			/* background: 21 mS per call          */
			/* returns -1 if bad page #            */
extern int far copy_page(int source, int dest);
------
			/* fast VGA line draw: about 15600 24-pixel */
			/* vectors/sec (horizontal much faster)     */
extern void far vgaline(int x1, int y1, int x2, int y2, int color);
------
void far set_clip_rect(int l, int t, int r, int b);

			/* does C-S clipping and draws line   */
extern void far clipline(int x1, int y1, int x2, int y2, int color);

These functions are not currently used by REND386, and may be stubbed off
if desired.
-----
int far set_drawpage(int page);	/* set page for drawing on (0-7)   */

Use this to set page to draw to, for ALL functions that do not take a
page number as an argument.
-----
			/* N_SIDED POLY DRAW for up to 20-sided  */
			/* convex polygons.  Pass pointer to int */
			/* array with X, Y coords in that order  */
			/* and count.  No clipping, CCW order    */

void far fastpoly(int count, int far *pcoords, int color);

			/* same as fastpoly() but with color cycling */
			/* and masking (halftone).  Color cycles in  */
			/* its lowest 4 bits, up then down.  Bit 8   */
			/* has been added as a "sign" bit for the    */
			/* initial cycle direction. 0000000SHHHHCCCC */
			/* the mask is XOR'ed with the toggle every  */
			/* line for 2x8 halftone patterns            */
void far m_fastpoly(int count, int far *pcoords, int color, int gmask, int toggle);

These functions should draw filled convex polygons from the point list
given.  You can emulate them with triangle poly calls internally: the
current REND386 slices the poly into trapezoidal segments and draws these.

The special-effects poly draw shoulds at least draw halftoned polys, using
gmask as the drawing mask, and XORing it with toggle on odd lines.  The color
argument is explained above, and should cycle up then down through a 16-color
sequence.  See the assembly code for a better explanation.
-----
			/* print text in foreground only-- */
			/* reversed = 1 for right-to-left  */
			/* with x now right side of text   */
void far printxyr(int x, int y, int color, char far *pstring, int reversed);

No background clearing is performed.  Should be capable of printing at
any horizontal offset.  Reversed text prints left from start position,
normal text prints right.  Reversed text is only used if one of your
video devices will be used in horizontally-flipped mode: if none are,
you may stub it off.  (Please support for widely-used drivers!).
-----
			/* draw "+" cursor on screen      */
			/* save s screen under cursor 	  */
void far draw_cursor(int x, int y, int color, int savebuff);

				 /* restores 8x8 area saved when   */
void far erase_cursor(int savebuff); /* cursor was drawn               */

These are used for mouse cursor support.  The savebuff is device-specific,
so would be seperate for each of multiple VGA cards, for example.  During
cursor drawing, the screen under the cursor will be saved, then restore
when rase_cursor is called.  There should be as many savebuff's as there are
video pages on your device.
-----
			/* copy any byte-aligned rectangle   */
			/* this is every 8 pixels (assumed for all modes)  */
			/* x coords (left) are truncated to  */
			/* left byte boundary: x size is     */
			/* bumped up to next full 8-pixel count */
extern int far copy_block(int spage, int sx, int sy,  /* source */
					int dpage, int dx, int dy,  /* dest   */
					int xs, int ys);            /* # lines, pixels */

			/* clear any byte-aligned block       */
			/* 15-30% slower than full page clear */
			/* left edge rounded down, right edge */
			/* rounded up to nearest byte boundary */
extern int far clr_block(int left, int top, int right, int bottom,
					 int page, int color);

These should support the 8-pixel granularity as noted above for
compatibility.
-------
			/* 3 entries each for n colors: RGB, 0->63 */
			/* load always starts with slot 0          */
			/* set pal=NULL for default (still give n) */
			/* bw=1 will transform palette into B&W    */
extern void far load_DAC_colors(char far *pal, int n, int bw);

extern void far read_DEC_colors(char far *pal, int n);

These should load or save the DAC palette.  The video driver should have its
own private color table: pass NULL to use this table.  The table ideally
should support the standard REND386 color mappings (see colormap.c).
------------------------------------------------

SUGGESTIONS:

Read through the 16- and 256- color VGA driver source if in doubt.
Always debug you code by linking it into REND386 directly first.
If you have trouble, suspect the memory-model interactions, and check for
missing FAR declarations, etc.  If in doubt use TD386 to single-step
through the REND386 calls to screen_data(), set_gmode(), and load_DAC_colors.
ALWAYS check the validity of returned data.

---

From: [email-masked]
Date: Thu, 3 Sep 1992 19:46:11 +0200

Here's the set of ideas i promised earlier!

----8<-----cut here-----8<------
                      A Few ideas for Rend386
                      =======================
                               by
                      Haakan "Zap" Andersson

Hi guys! Here is a set of random ideas on how to improve rend386!!!

* NEW Stereo view types: Crossed eye & Side by side stereo.
  I suggested (and use) the Mirror stereo. However, there is big
  troubles when the mirror is in the way of itself ;-) so I would
  like a normal 'cross eye' setup where the images are side by side
  and the right image is on the left and vice versa. This is viewed
  by crossing yer eyes, wich I find easy. Some wierdos can diverge
  their eyes (I'm not one of them) and these wierdos could use a 
  side by side setup with right on ritght and left on left.

  It's probably two lines of code, e.g. not set the flip-x bit on
  one of the views in mirror mode!

  I tried it by using 'mirror mode' and looked at the metalman head on
  and crossed my eyes. It was perfect, and I find it the simplest VR
  exisiting!

* Speed improvement idea for stereo images.

  If I understand you correctly you do NOT re-use much/any of the data
  from the left view to draw the right, right ;-)

  From what I understand you actually ROTATE the scene by 'distance to
  focal point' vs. 'eye spacing' degrees and generate from scratch a new
  view.

  Not only will I prove that WRONG...

  I can think of another way to do it. Here is the basic idea:

                  +---+
                  |   |  <-  OBJECT
                  +---+
                     |\
                     | \
                     |  \ 
                     |   \
     ------------------------------------- Screen plane
                     |     \
                     |      \
                     |       \
Observer --->       (*)      (*)

                  Left eye  Right eye

    As you can see, the 'line of sight' for the right eye is not
    90 degrees to the screen. This means that the 'ultra correct'
    way to do it would be to have both views be a skew projection
    onto the view plane, so they LOOK OK when viewed at an angle
    on a flat screen.
    
    But as you see, I have placed my observer sligthtly to the 
    side to create a skew projection for one view only. And to
    generate the skew view I simply apply a simple shearing 
    operation to the verticies of the image! E.g.
    
	X = focal depth point, e.g. the point around wich you
	    previously rotated everything.

     Push verticies ->	 +---------+- -
			 |/	   | /
			/|    x	   |/
		       / |	  /|
		      ---+---------+   <- Push verticies
    
    This (naturally exaggerated) shearing operation will projected 
    on a flat screen resemble the skew projection of an object 
    closely, perhaps even exactly (Havn't boiled the math down
    all the way ;-)
    
    This way both stereo views will use the same set of trans-
    formed-to-view coordinates. Probably this shearing should
    be done before perspective is applied, but it may also
    be added after perspective but then it must naturally
    be scaled by depth.
    
    - Polygon Rejection
    
    REND386 uses normal vector polygon rejection. Now in this setup
    above, a polygon may become rejected in one view but not in an
    other. A way to solve this is to keep polygons whose normal
    vector is pointing backwards 'just a little', i.e. keep all
    polygons where the dotproduct(view_vector, normal_vector) 
    > magic, where 'magic' is calculated in some neat way.
    
    Then do another layer of polygon rejection after the skew
    thing above, by skewing the normals too and do a new rejection
    on those, or somesuch. Another nice way would be to simply check
    the drawing order of the verticies (simple for non-convex polys)
    or perhaps just draw the bastards and pray that the depth sort
    fixes things for us ;-)

* BITMAP OBJECTS and TEXTURE MAPPING

    As we all see in ultima underworld and Wolfenstein 3D texture mapping 
    in realtime isn't impossible. See it this way: If you can achieve the 
    same appearance with one texturemapped polygon as you would with 50 
    non-texturemapped polygon, wouldn't a littttttle speed penalty be 
    paiable? :-)

    (Ok, general texturemapping will probably be too slow to be worthwhile
    to implement. But keep it in the back of your head though, how "real" 
    the walls in Wolfenstein look, with stones, bricks or whatever, com-
    pared to the crude single color stuff in REND386. Just think it over. 
    Perhaps some way to add 'features' to a surface, e.g. define "this is 
    a polygon with small dots here, here, here and here, and a little circle
    here" wich are all sorted and drawn together with the main polygon, 
    without wasting sorting time (or even transformation time if the poly-
    gon is totally clipped!)
    
    BITMAP OBJECTS would be REALLY NICE. I rehacked Wolfenstein to produce 
    my own Raytracing-generated robots instead of german officers. Was quite
    nice.

    Just think about the "reality feel" of the wolfenstein objects such as
    "skeletons hanging from the ceiling" and such stuff, even if they dont
    rotate with the view as they should.
    
    True enough, since Wolfenstein has a very limited (essentialy 2d) degree
    of motion freedom, all this is much much more difficult to achieve in
    Rend386. But if I could pre-render 32x16 images of an object, as seen 
    from 32 "longditude" and 16 "latitude" viewpoints (it could be rendered
    with reflection mapping, intershadowing of the components, self-mirroring
    and texturemapping) and I could toy around with that thing in my "hand"
    (glove) in realtime, gosh would that be NICE!
    
    - OK, I know that perspective really should change, that just scaling a
      bitmap isn't "right"
    - OK, I know that 32 latitude and 16 longditude probably isn't the best
      view differentiation. Better idea left as an exercise to the reader.
      (Hint: View directions distributed evenly on an unit cube)
    - Ok, I know a lot more things you can come down on, but just THINK about
      twisting that glittering porche in your hand in RealTime....raaah!
    
    The "Ultimate" REND386 release would of course render things in full 
    detail when there was a lot of time, and store it as bitmaps to redesplay
    the bitmaps when time was limited. Hehe. (Arn't I mean? :-)

!! The ANSWER   : 42     ("Hitchhikers Guide to the Galaxy" - Douglas Adams) 
!! The QUESTION : 0x2b | ~0x2b   ("Hamlet" - William Shakespear) | Dont Worry -
!! The EMAIL    : [email-masked]  The PHONE: +46 16 96460    | Mail Zappie!

---

From: [email-masked] (Christopher Phillips)
Date: Fri, 4 Sep 92 14:45:49 WST

> * NEW Stereo view types: Crossed eye & Side by side stereo.

Cheer!  Much in favour.  'Twould be very useful, and should be
easy to implement.
 
> * Speed improvement idea for stereo images.

Sounds cool. The problem of poly's visible in one image
and not the other could be fun though.

> * BITMAP OBJECTS and TEXTURE MAPPING

Now this lot is fun.  As I understand it, the innermost loop on
the poly fill just loops over a row of pixels filling with one (or
alternating between 2) colours.  Hence horizontal bars in the shiney
surfaces.  To have true bitmap TM, this would havbe to be replaced with
hopping through a source image by apropriate steps fetching pixels to
blat onto the screen.  For poly's which have a normal in the plane
perpendicular to the scan direction (ie they would only need a rotation
around a horizontal axis to make them parallel to the view plane), the
x and y increments for stepping through the source image in order
to find the screen pixels are constant for any given scan line.
If this is not the case, then you would need to either do the mapping
in two stages (render on a bitmap with scandirection perpendicular to
normal of surface and then rotate image) or step through source image
by increments that are a function of 1/x.

All the above assumes only one source fetch per pixel plotted.
If the overheads of working out what to fetch are too high, it may just
be saner to scan source image, plotting onto screen.  If several
scales of source image were kept (at least one for every magnx2, pref more.
One for every mag by sqrt(2) takes up only twice as much total space as the
largest image stored), then this would solve aliasing problems and
minimise pixel plotting redundancy.  (as the images could be pre anti-aliased
and would take up at least 1/(scale factor)^2 of screen pixels.)

This takes up much more time than a simple loop_over_pixels_filling_with
colour.  However, with more complex scenes, the amount of time spent in the
fill_poly routine decreases with increasing scene complexity.  Something
to think about.

Christopher Jam	__________________________________________________
[email-masked]			c64 forever!!!!
300,000 c64's were sold in the fiscal year ending June 1991 :)
------------------------------------------------------------------

---

From: [email-masked]
Date: Fri, 4 Sep 1992 11:51:06 +0200

...actually, after grabbing the NEW DEMO4.ZIP, i find that side-by-side
stereo is already in there (you just set up the stereoleft and stereoright
settings correctly).

I tried it, and I have really easy to cross my eyes, and got an INTENSE
depth-feeling. Cruel!

However....

First: On my 486/33, running in sega switching mode, The image looks like it
changes a LOT MORE OFTEN than the old DEMO4. BUT: I feel like the responses
are much slower.... or did you just shorten the stepsize you do with
up-arrow/down arrow?

Secondly: The wierd Flicker-flacker-showing-pages-that-are-not-drawn-yet page
flippery errors are still there. Much less, but still there. They happen when
Rend is actually WORKING, e.g. whil I am holding down up-arrow or I am
in the process of spinning METALMAN.

Oh, and Dave.... the .PLG files I sent you earlier on....you may put them
on ftp if you havn't already done so (you remember, face.plg, e.t.c.)

P.S. How's the microsoft compatibility nowdays? I'm aching to hack up the
threedee virtual breakout game I have invented!

/Z

---

From: Mark Kenworthy <[email-masked]>
Date: Fri, 4 Sep 92 05:52:25 PDT

>fill_poly routine decreases with increasing scene complexity.  Something

My nephew has Super Nintendo's new game "Flight Wings" (I think that's
what it's called).  Anyway, that game (the only Super Nintendo game I've
seen) uses primative texture mapping on the terrain surface.  It looks
to me like they are just using the nearest location in a source image to
determine the pixel color.  This saves many calculations involving
texture detail that would otherwise need to be done pixel by pixel.  The
overall effect is not too bad.  It is kind of noisy, but you can
definately tell what it is you are looking at.  Some careful planning of
the texture pattern can help here.

Anyway, I think it would be great if rend386 added support for simple
texture polygons like described above.  The patterns add significant
information to the computed image that is worth many times less polygon
performance, assuming it is selectable (this polygon textured, this one
not and still fast).

Just my 2 cents worth.  8^)

	- Mark -

+------------------------------------------------------+
| Mark Kenworthy       |    "It's always something"    |
| [email-masked]    |     Roseanna Roseannadanna    |
+------------------------------------------------------+