home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!zaphod.mps.ohio-state.edu!darwin.sura.net!jvnc.net!netnews.upenn.edu!dsinc!ub!toz!cyberman
- From: cyberman@toz.buffalo.ny.us (Cyberman)
- Newsgroups: rec.games.programmer
- Subject: R.G.P. FAQ 0.0.2
- Message-ID: <gate.3P67VB1w165w@toz.buffalo.ny.us>
- Date: 22 Dec 92 18:40:25 GMT
- Lines: 1004
- X-Maildoor: WaflineMail 1.00r
-
-
-
- ---
- * Blue Wave/QWK v2.11 *
-
- This document will be made available by mail request at a later
- date (mail server difficulties).
-
- There are currently 2 FAQ's
-
- RGP.FAQ - rec.games.programmer General Frequently
- RGP.IBM - rec.games.ibm relevant FAQ
-
- This was done so that someone who is looking for more general
- information will be able to find game programing information
- without being inundated by IBM or other computer-SPECIFIC
- information. Game source available on the net are NOT part of
- this FAQ.
-
- The current Editor is Cyberman@toz.buffalo.ny.us
-
- Changes from 0.0.1
-
- Mod format information removed this will be in a seperate archive
- to avoid any legal tangles. Several other modifications (a Mac
- addition).
-
- --------------------------------------------------------------------------------
- REC.GAMES.PROGRAMMER General FAQ Contents
- --------------------------------------------------------------------------------
- LEGAL
-
- This document is FREE! (so are dumb looks) It is for your self
- enlightenment. No warranty is provided for this information.
- The accuracy of the information contained herein is subject to
- conjecture. Therefore the editors and contributers will take NO
- liability for improper use, misuse, or abuse of this information,
- and any damage to ANYTHING or ANYONE whether physical, financial,
- etc. in no way, shape, or form can be attributed to this document.
- Use this information at you OWN risk.
-
- The above statement is to keep those who contributed and the
- editor free from personal injury for being nice.
-
- Special thanks to:
- andrean@cs.utexas.edu (Andre A. Nurwono)
- roberts@brahms.amd.com (Dave Roberts)
- sean@stat.tamu.edu (Sean Barrett)
- Cyberman@toz.buffalo.ny.us (Cyberman)
- (and anyone else I forgot to mention for that matter)
-
- If you wish to contribute CODE be sure it's something you DO NOT
- wish to COPYRIGHT!
-
- All contributions and suggestions should be sent to me at:
- Cyberman@toz.buffalo.ny.us
- place in subject header
-
- RGP.FAQ.*
- where * is any of the following
- SUGGESTION - to suggest Adding an area (I recommend that
- you send the information if you want it
- added)
- ADD - an addition (ie TBA's [see KEY for what TBA
- means])
- EDIT - for a correction somewhere (it is suggested
- contributers do there own editing)
- FLAME - complaints - I'll read these but be sure to
- be tasteful in you commentary. You may or
- may NOT get a reply.
-
- For now I'm going to use my personal mail account. So please be
- careful.
-
- Format:
- There are several categories and each category contains it's
- relevant questions as suggested.
-
- Key:
- TBA - To Be Added
-
- [Frequently Asked Questions about terminology]
- Q1.1 What are .MOD files?
- Q1.2 What is a pixel?
- Q1.3 What is a bitmap?
- Q1.4 What is flicker?
- Q1.5 What is snow?
- Q1.6 What is a frame buffer?
- Q1.7 What is a Sprite?
- Q1.8 What is vertical/horizontal retrace?
-
- [Frequently Asked Questions about Animation]
- Q2.1 How do I make sprites on my xxx?
- Q2.2 What about collision detection? TBA
- Q2.3 What about bitmap scaling? TBA
- Q2.4 What is perspective mapping? TBA
- Q2.5 What about 3d objects and manipulation?
-
- [Frequently Asked Questions about Map Generation]
- Q3.1 How do I generate a maze?
- Q3.2 How do I generate a landscape/terrain? TBA
- Q3.3 How do I generate a hex map? TBA
- Q3.4 What about random number generators?
-
- [Frequently Asked Questions about Libraries and support software]
- Q4.1 What is there for the IBM compatible?
- Q4.2 " " " " " Amiga? TBA
- Q4.3 " " " " " Atari? TBA
- Q4.4 " " " " " Macintosh? TBA
- Q4.5 " " " " " Sun/Sparc?
- Q4.6 " " " " " X? TBA
-
- Note 1: Fixing snow and flicker
- Note 2: 2 Part Tutorial on 3d graphics
-
- --------------------------------------------------------------------------------
- REC.GAMES.PROGRAMMER General FAQ Terminology
- --------------------------------------------------------------------------------
-
- Q1.1 What are .MOD files?
- A .MOD file is a file generated for the Amiga. A tracker is
- used to play the MOD. A mod consists of digitized sound and
- sequencing information to play music. Here is a BRIEF and
- incomplete text file that is somewhat informative on the
- subject.
-
- SEE ALSO - Mod Format specification file. (Modform.zoo)
-
- Q1.2 What is a Pixel?
-
- Pixel is short for Picture Element. It is a single dot
- address on a grid used to display images in television and on
- computers.
-
- Q1.3 What is a bitmap?
-
- A bitmap aka bitimage is the representation of an image in
- the form of a sequence of bits. For example most graphic
- modes on computers represent the pixels using a BITMAP.
-
- Q1.4 What is flicker?
- Flicker is a noticeable pulse or change in an image. This
- can be on a CRT (Cathode Ray Tube) or other type display
- device. The cause is that the refresh rate of the CRT is
- lower than the persistance of vision of the person observing
- it.
-
- Another form of flicker is due to rapid drawing of data on
- the screen. What happens is that the data is drawn out of
- syncronization with the horizontal and vertical scan. So
- your image apears to fade in and out of visability.
-
- SEE ALSO fixing snow and Flicker
-
- Q1.5 What is SNOW?
-
- Snow are small specals appearing on the screen that look like
- SNOW falling (hence the name).
-
- Snow is caused by a number of things. One of which is when
- one is writting to the screen while the display card is
- scanning that address of the screen, this causes a conflict
- and can produce random specals.
-
- Another cause of snow is an improperly connected monitor this
- can damage the monitor. Noise from an electro magnetic
- source can interfer with your monitor as well.
-
- SEE ALSO fixing snow and Flicker
-
- Q1.6 What is a frame buffer?
-
- Memory that contains image data that is translated to the image
- on your screen. A frame buffer does not have to be visible.
-
- Q1.7 What is a Sprite?
-
- A sprite is an image usually moveable about the screen.
- Common information stored in a sprite are, width, height,
- position, and image data.
-
- Q1.8 What is vertical/horizontal retrace?
-
- Most monitors are what is called a RASTER display. This
- means that an image is represented by setting the intensity
- of a grid of dots on the display. Each dot is called a
- pixel. In order to display the grid a CRT sweeps an electron
- beam across the display surface sending pulses corresponding
- to the intensity of the pixel. However the stream of video
- information is almost always represented left to right top to
- bottom. This mean that the beam must scan across the screen
- and then move BACK to start a line. This is called
- Horizontal retrace.
-
- Vertical retrace is when the beam finishes painting the
- screen from top to bottom again the beam must be moved to the
- top of the screen.
-
- The horizontal sweep is controlled by an electric field the
- vertical sweep is controlled usually magnetic field.
-
- --------------------------------------------------------------------------------
- REC.GAMES.PROGRAMMER General FAQ Animation
- --------------------------------------------------------------------------------
-
- [Frequently Asked Questions about Animation]
- Q2.1 How do I make sprites on my xxx?
-
- This, unfortunately, is a rather complex problem and its
- implementation is often computer-specific, however some of it
- can be addressed in the general FAQ.
-
- Sprites require one to copy pixels to the display in a
- certain area of the screen. There are various issues that
- must be addressed about this.
-
- Getting and Putting an image: getting means you copy a
- section of a screen (bitmap) to a buffer, putting means you
- dump a buffer of data (bitmap) to a screen location. These
- are often used for less sophisticated sprite animation.
-
- The problem with this technique is put destroys the
- background information. So if you want a background at all,
- there must be a way to "overlay" an image onto it without
- creating a large area around the sprite to disappear. An old
- way of "fixing" this is to copy the background of an image
- before you destroy it, then put the background back after you
- move it.
-
- Q2.2 What about collision detection? TBA
- Q2.3 What about bitmap scaling? TBA
- Q2.4 What is perspective mapping?
- What is it? Basically it takes an image and "pastes" it in
- 3d perspective onto a surface. This is much faster than
- rendering surfaces in real time. Article 7716 of r.g.p
- written by Joshua C. Jensen (sl8nl@cc.usu.edu) is an example
- of this technique (implemented in Turbo Pascal).
-
- Q2.5 What about 3d objects and manipulation?
-
- Note 2 is a pair of tutorials on this subject.
-
- --------------------------------------------------------------------------------
- REC.GAMES.PROGRAMMER General FAQ Map Generation
- --------------------------------------------------------------------------------
-
- Q3.1 How do I generate a maze?
- This is a VERY frequently asked question in rgp so we have
- a unoffical maze FAQ. It's is now posted WITH the RGP Faq.
-
- Q3.2 How do I generate a landscape/terrain? TBA
- Q3.3 How do I generate/use a hex map?
- Well this has discussed considerably on rgp. We haven't a
- FAQ for it until I get permission to use something I
- captured.
-
- Q3.4 What about random number generators?
- These are mandatory for making a "new" universe each time a
- program loads. Usually the ones included in a C compiler
- library are sufficient for most needs. However sometimes one
- must go the extra mile and use there own random number
- generator. Currently we have no FAQ on random number
- generators. (sorry)
-
- --------------------------------------------------------------------------------
- REC.GAMES.PROGRAMMER General FAQ Libraries and support software
- --------------------------------------------------------------------------------
-
- Q4.1 What is there for the IBM and Compatibles?
- There is quite a bit but for now we will have an UNOFFICIAL
- list. We are currently compiling a much better list. This
- will have to do tell then.
-
- contributed by
- andrean@cs.utexas.edu (Andre A. Nurwono)
- ==========
- --------
- Graphics
- --------
-
- *. Executable
- File(s) : TWEAK06.ZIP
- Who : Robert Schmidt (robert@solan.unit.no)
- When : 1992
- What : A program to experiment w/ VGA registers, very useful
- if you want to define new modes (like mode X & 360x400 modes)
- Where : simtel & mirrors
-
- *. Executable, (source code)
- File : SPRITE.ZIP
- Who : Billy Dalrymple
- When : 1989
- What : A sprite editor, produces sprites w/ mask in files.
- info available for $10
- source code available for $25
- Where : I forget
-
- *. Executable, Source Code
- File(s) : VGA.ZIP
- Who : wardt@a.cs.okstate.edu
- When : 1992
- What : A sprite editor, includes full source (.ASM & .C)
- Where : I forget
-
- *. Source Code, Library
- File(s) : DDJ****.ZIP, XSHARP**.ZIP
- Who : M. Abrash
- When : Aug-Dec 1991, Jun-Aug 1992
- What : Mode X introduction. Sources to do animation,
- polygon plotting, anti-aliasing, etc, on Mode X.
- Where : SIMTEL and mirrors,
- ftp.mv.com (Official DDJ site) in pub/ddj
-
- *. Source Code
- File(s) : article 7198 of rec.games.programmer
- Who : Frederick J. Haab (otto@nevada.edu)
- When : 26 Jun 92 00:17:52 GMT
- What : Scrolling in mode 13h, C program
- Where : USENET archives
-
- *. Source Code
- File(s) : article 7716 of rec.games.programmer
- Who : Joshua C. Jensen (sl8nl@cc.usu.edu)
- When : 30 Jul 92 00:02:36 GMT
- What : Bitmap manipulation (scaling + perspective), Turbo Pascal
- source w/ inline assembly.
- Where : USENET archives
-
- *. Source Code
- File(s) : VESAVGA.ZIP
- Who : Randy Buckland
- When : 6/18/92
- What : .ASM & .C source to provide fast routines for VESA VGA modes.
- Where : garbo
-
- *. Sprite Library, Code
- File(s) : STK110.LZH
- Who : Jari Karjala
- When : 1991 (v 1.1)
- What : Sprite library & toolkit for Hi-Res EGA, BW
- includes C source, demo & good docs.
- Where : simtel & mirrors
-
- *. Sprite Library, Source Code
- File : SPRITES.ZIP
- Who : Marius Kjeldahl
- When : 1991
- What : Sprite library for VGA mode $13
- includes TPU, .PAS source.
- (shareware, $69 ?)
- Where : garbo
-
- *. Sprite Library, Toolkit
- File(s) : WGT_SPR2.ZIP, WGT_TC21.ZIP, WGT_TP2.ZIP
- Who :
- When : 1992
- What : Shareware Sprite toolkit for VGA mode $13
- includes TPU (WGT_TP2.ZIP), example programs for usage
- Nag-shareware program
- Where : wuarchive, if somebody hasn't erased it yet
-
- *. I'm sure there's TONS more, but I can't search for all of them.
- Any corrections / additions is great.
-
- -------------
- Sound & Music
- -------------
-
- *. Documentation
- File(s) : Article 6077 of rec.games.programmer
- Who : Jeffrey S. Lee (jlee@smylex.uucp)
- When : 25 Feb 92 15:02:02 GMT
- What : Programming the AdLib/Sound Blaster FM Music Chips
- Where : usenet archives, also at the SB project site
- (tybalt.cco.caltech.edu), & SB mailserver
- (listserv@porter.geo.brown.edu)
-
- *. Executable, Runtime Library
- File(s) : MODTECH.ZIP
- Who : Mark J. Cox (M.J.H.Cox@bradford.ac.uk)
- When : 1991
- What : TSR Library to play .MOD files in the background
- Supports PC Speaker, SB, DisneySS, LPT DACs, etc
- Where : ftp.brad.ac.uk in /misc/msdos/mp
-
- *. Library
- File(s) : MODOBJ.ZIP
- Who : Mark J. Cox (M.J.H.Cox@bradford.ac.uk)
- When : 1992
- What : .OBJ file w/ routines to play .MOD files in the background
- Supports PC Speaker, SB, DisneySS, LPT DACs, etc
- Includes examples in TC & TP
- (shareware, $30)
- Where : ftp.brad.ac.uk in /misc/msdos/mp
-
- *. Source code
- File(s) : NH10SRC.ZIP
- Who :
- When :
- What : Eliminate noise on sound samples, incl. .C source
- Where : SB project site & mailserv site
-
- *. Source code, Executable
- File(s) : SB_OSC.ZIP
- Who :
- When :
- What : SB input scope / oscillator. Incl. .ASM source
- Where : SB project site & mailserv site
-
- *. Source code, Executable
- File(s) : SBDAC.ZIP
- Who : Jeff Bird (cejjb@marlin.jcu.edu.au)
- When : 12 Feb 92
- What : SB DAC programming using DMA. Incl. .ASM & .C source
- Where : I forget (probably on SB project sites too)
-
- *. Library Source
- File(s) : ???Xlib40???
- Who : Themie Gouthas (and company)
- When : 17 Nov 92
- What : mode X library for game, to many feature to mention
- Where : pub/MSDOS_UPLOADS@wuarchive.wustl.edu
-
- ==========
-
- Q4.2 " " " " " Amiga? TBA
-
- Q4.3 What is there for the Atari?
-
- from warwick@cs.uq.oz.au
-
- AMS library - Atari Machine Specific library
- - C++ classes for Sprites, Screen, Joysticks, Double buffering, etc.
- - beta testing now
- - contact: warwick@cs.uq.oz.au
-
- Q4.4 " " " " " Macintosh?
-
- from jmunkki@vipunen.hut.fi
-
- *. Source code
- Files : Arashi_Source.cpt.bin
- Who : ???
- When : ???
- What : source code for an arcade quality game, vector
- graphics, multichannel sound, (no sprites)
- Where : pub/mac/think-c/code@ics.uci.edu
-
- Q4.5 " " " " " Sun/Sparcs?
-
- contributed by
- andrean@cs.utexas.edu (Andre A. Nurwono)
- ==========
- --------
- Graphics
- --------
- *. Library
- What : Standard PIXRECT library
- Bitmap manipulation routines for frame buffer.
-
- -------------
- Music & Audio
- -------------
- *. Source code
- File(s) : tracker.tar.Z
- Who :
- When :
- What : .MOD file player through the audio device. Works on SPARCS
- w/ audio devices.
- Where :
-
- *. Source code
- File(s) : csound.tar.Z
- What : FFT & signal processor
-
- *. Source code
- What : MixView
- ==========
-
- Q4.6 " " " " " X TBA
-
- Additions are welcome.
-
- --------------------------------------------------------------------------------
- END OF FAQ
-
- --------------------------------------------------------------------------------
- REC.GAMES.PROGRAMMER General FAQ NOTES
- --------------------------------------------------------------------------------
-
- --------------------------------------------------------------------------------
- NOTE 1: contributed by
- --------------------------------------------------------------------------------
- sean@stat.tamu.edu (Sean Barrett)
-
- There are two things that qualify as flicker. Well, hell, to make it
- simpler, let's call it three. At the end of this list I'll give a
- rough definition of the problem.
-
- 1) You move a shape by erasing it and plotting it in a new position,
- and there is a screen refresh during the time it is erased, resulting in
- the background showing through.
-
- 2) You're using CGA and you try to write anywhere on the screen
- during retrace, causing "noise" (due to DMA problems, I guess?).
-
- 3) You're moving a shape by some sort of "one-pass" technique in which
- the screen memory is never set to the background temporarily, so (1)
- can't happen, but the screen area the shape is in is refreshed during
- the draw, so half of it gets displayed at the old location, and half
- at the new.
-
- I think a general rule would be that flicker occurs when a pixel on
- the screen is displayed with a color other than the "correct" or
- "intended" pixel value, as compared to an ideal "intended" case. (Thus,
- if you're simulating something moving, you shouldn't see the background;
- if you're trying to simulate something moving and turning on and off
- simultaneously, then you can should see it; it's all a question of
- intent.)
-
- Back to the above problems.
-
- Now, so far as I know, there are only two solutions to #2. Only redraw
- during the vertical retrace (blank), or don't support CGA. So I'm going
- to forget about this problem.
-
- You can handle #1, as I suggested in #3, by simply making sure you never
- write to the screen a value you don't want displayed. Below I'll put a
- list of ways I can think of to do this for bitmapped graphics--i.e.,
- how to avoid the erase-redraw cycle.
-
- If you really want to handle #3, then things get funky, and more power
- to you. I don't personally believe it's a problem. If it's periodic,
- so this one shape when you move it horizontally in the middle of the
- screen is always split with the top half leading the bottom half by
- a pixel, it's a problem; but if it just happens randomly once in a while
- I doubt it's noticeable. In general, though, the solutions require
- paying attention to where the screen refresh is in some way. My main
- point, the reason I'm posting this whole thing, is that *solving problem
- #1 does not require messing with knowing what section of the screen
- is being refreshed.* As far as I know, the methods to combatting #3
- are to redraw everything during vertical refresh (same as #2, but
- overkill) or drawing your shapes from top to bottom lagging about half
- the time of a screen refresh behind the refresh, or some such.
-
- Solutions to #1 that don't require timing considerations, e.g., how
- never to write a wrong pixel to the screen.
-
- o Don't use raw bitmaps, use sprite hardware.
-
- o Use hardware page flipping: display one screen, draw a new
- screen "off-screen" and when it's finished, direct the
- display hardware to display the new one. This can get messy
- for fast animation because you have to keep track of where
- sprites were the last two frames to erase and update them.
-
- o Use software page flipping; display one screen, draw a new
- screen "off-screen" and when it's finished, copy the new
- screen into screen memory.
-
- o Use techniques such as "store" sprites which overwrite the
- background. Generally an out-of-date technique now, though;
- only works for mono-color backgrounds. You simply write the
- sprite onto the screen; the sprite has enough border around
- it to overwrite its previous image. This is gross, very
- fast, and flicker-free except when shapes get on top of each
- other, at which point you get massive flicker.
-
- o Use scratch-pad calculations, a variant of software page flipping.
- Copy the section of the screen off that you need to update,
- update it offscreen, and put it back on the screen. A lengthy
- time ago I posted a discussion of how to do this effectively
- for XOR-style graphics for 8-bit type machines--you can xor
- a single image onto the screen that both erases and replots
- in a new place the old sprite. And you can calculate the
- image to do it on the fly, without additional memory, if you
- set up your shape tables, and it's faster than the normal
- draw shape with XOR to erase, draw shape with XOR to plot cycle
- because it only reads and writes screen memory once.
-
- Performance enhancements for bit blitting:
-
- o Unroll loops.
-
- o Write a custom bit blit for each shape, dedicated to that shape.
- Cuts your memory accessing down if the machine has an
- "immediate" operand mode that's faster than an index-addressed
- one.
-
- Memory performance enhancements for techniques that require many copies
- of shapes or large routines (such as pre-shifted shape tables):
-
- o If you're only using some of your shapes at any point in time
- (e.g. if you can divide your display up into "scenes"; for a
- certain period of time only these shapes are used), calculate
- the "larger" derived tables on the fly when the scene starts
- up. For large games (this is rec.games.programmer, not
- rec.graphics.programmer, right?) that have to access the disk
- anyway to change scenes, this is no big time loss. Also, if
- you write the code right then while you're idling the processor
- before starting work on the next display, you can do this stuff
- then.
-
- --------------------------------------------------------------------------------
- NOTE 2: contributed by
- --------------------------------------------------------------------------------
- sean@stat.tamu.edu (Sean Barrett)
-
- 3D graphics: Using matrices and vectors Part 1
-
-
- - Allows you to independently rotate objects and move the camera
- anywhere.
- - Does not discuss clipping.
- - Algorithm uses 9 multiplies, 2 divides, and 9 additions per point,
- plus overhead per independently located object.
- - Part 2 gives the derivation for these formulas.
-
-
- Assume a right-handed universe, with x horizontal, y
- depth, and z vertical, and a screen display unit with
- x horizontal to the right and y vertical downward.
-
-
- The following are the rotation matrices:
-
- Rx(t) Ry(t) Rz(t)
- __ __ __ __ __ __
- | 1 0 0 0 | | cos(t) 0 -sin(t) 0 | | cos(t) sin(t) 0 0 |
- | 0 cos(t) sin(t) 0 | | 0 1 0 0 | | -sin(t) cos(t) 0 0 |
- | 0 -sin(t) cos(t) 0 | | sin(t) 0 cos(t) 0 | | 0 0 1 0 |
- | 0 0 0 1 | | 0 0 0 1 | | 0 0 0 1 |
- -- -- -- -- -- --
- rotate about x rotate about y rotate about z
-
-
- The following is the translation matrix:
-
- T(a,b,c)
- __ __
- | 1 0 0 a |
- | 0 1 0 b |
- | 0 0 1 c |
- | 0 0 0 1 |
- -- --
-
- Let each object be a collection of points or lines. If lines, they
- are drawn as lines connecting two 3D points, which can each be
- individually transformed. So this derivation just handles converting
- individual points in three-space into pixel coordinates.
-
- ---- BEGIN FORMULAS ----
-
- If d is the distance from the eye to the window, h is the width
- of the window, v is the height of the window (use the sizes
- of the actual display if you don't know what else, but this is
- actually referring to the virtual camera's window); num_x
- is the number of pixels on the display in the x direction, num_y
- the number of pixels in the y direction, and (center_x,center_y)
- the location of the center of the display;
-
- let scale_x = d/h*number_of_x_pixels, scale_y = d/v*number_of_y_pixels.
-
- Then let S be defined as
- __ __
- | scale_x center_x 0 0 |
- | 0 1 0 0 |
- | 0 center_y -scale_y 0 |
- | 0 0 0 1 |
- -- --
-
- Let the camera be located at (cx,cy,cz). Let the vector E be pointing
- in the direction the camera is facing, the vector D be pointing to
- the right (along the camera's x axis), and the vector F be pointing
- up (along the camera's z axis); and let D, E, and F be of length 1.
- Then define the following matrices:
-
- matrix J matrix C
- | Dx Dy Dz 0 | | 1 0 0 -cx |
- | Ex Ey Ez 0 | | 0 1 0 -cy |
- | Fx Fy Fz 0 | | 0 0 1 -cz |
- | 0 0 0 1 | | 0 0 0 1 |
-
- and let N = S*J*C.
-
-
- Let each object i be at location cix, ciy, ciz, and let the matrix
- which holds the current rotation for that object be O(i). To rotate
- the object around the q axis by n degrees, let new O(i) = Rq(n) * O(i).
- To rotate the object about *its* q axis, let new O(i) = O(i) * Rq(n)
- (I think. I haven't looked at this closely, so it's probably wrong).
-
- Let Otemp(i) be O(i) with the rightmost column of zeros replaced by
- cix, ciy, and ciz, or in other words, the product of Temp(i)*O(i) where
- Temp(i) is
- __ __
- | 1 0 0 cix |
- | 0 1 0 ciy |
- | 0 0 1 ciz |
- | 0 0 0 1 |
- -- --
-
- Now, for each object i let M = N * Otemp(i).
-
- Now, for each point P in i, let V = M * P, that is:
-
- Vx = M[0,0]*Px + M[0,1]*Py + M[0,2]*Pz + M[0,3];
- Vy = M[1,0]*Px + M[1,1]*Py + M[1,2]*Pz + M[1,3];
- Vz = M[2,0]*Px + M[2,1]*Py + M[2,2]*Pz + M[2,3];
-
- Then the pixel to plot to is:
-
- If Vy>0
- (Vx/Vy, Vz/Vy)
-
- Done.
-
- -- 2 --
-
- 3D graphics: using matrices and vectors Part 2
-
- - Allows you to independently rotate objects and move the camera
- anywhere.
- - Does not discuss clipping.
- - Algorithm uses 16 multiplies, 2 divides, and 12 adds for each point,
- plus overhead per independently located object. Also shows how some
- of the calculations are wasted, and reduces it to 9 multiplies and 9
- additions.
-
-
- The folowomg is a derivation of some of the math for using 3D
- graphics with matrices and vectors. I don't see any way of
- explaining how to use the matrix formulas without all the extra
- context, so you'll have to wade through it. In general, you can
- simplify things by multiplying out the matrices and similar
- techniques.
-
- You have a world described by three dimensional coordinates--it
- could be lines or points or polygons, whatever. You have an
- imaginary camera in this world, and you want to draw exactly
- what this camera would see.
-
- We represent the camera as a point where an "eye" is and a window
- through which it's looking--that is, a point for the eye, a vector
- from the eye to the center of the window, and another vector to tell
- us which way is the up direction on the window. We can figure out
- the sideways direction of the window by taking a cross-product, but
- it may be better to represent it explicitly, as discussed far
- eventually below.
-
- What we want to know is where on our screen we should plot a
- particular point. The solution is to figure out where on the
- imaginary window the point would appear to be, and then to map
- the window onto our screen.
-
- Suppose the eye is at the origin, facing along the X axis, and
- the point is in the XY plane so we can only look at two dimensions
- for illustration purposes.
-
- Y axis
- | ___---
- | ___---
- | ___--- | Point
- | --- |
- eye----------+------------------ X axis
- ---___ |
- ---_|_
- window ---___
- ---___
-
- Suppose the window ranges from (d,h/2) to (d,-h/2) and the point is at
- (a,b). We want to know where the line from the point to the eye
- intersects the window line. Well, the point is only visible if
- it's in front of the eye, so assume a>0. Now, the two lines are
-
- y = (b/a)*x (from Point to eye)
- and x = d (line window is on)
-
- So the location of intersection is (d,(b/a)*d). In other words,
- the point appears on our imaginary window with horizontal position
- d*b/a if |d*b/a| <= h/2.
-
- Thus, the quick and dirty 3d graphics formula for assuming an eyepoint
- at the origin, X horizontal, positive to the right, Y vertical, positive
- up, and Z depth, positive going into the distance (this is a left-handed
- universe, whereas the rest of the derivations will be for a right handed
- universe), and screen coordinates sx horizontal, positive to the right
- sy vertical, positive down, is:
-
- if (Z>0) then
- sx = x_scale * X / Z + x_center;
- sy = - y_scale * Y / Z + y_center;
- endif
-
- where x_center, y_center is the pixel address of the center of the
- screen; x_scale is d/h*number_of_pixels_horizontally and y_scale is
- d/v*number_of_pixels_vertically; d is the distance between the eye
- and the window in the imaginary camera, h and v are the height and
- width respectively of the imaginary window.
-
- Ok, back to the messy stuff. Since our eyepoint won't necessarily
- be at the origin and facing in the right direction, we need to be
- able to handle arbitrary translations and rotations. In general,
- to rotate (a,b) into (a',b') based on a given angle t, we do
-
- a' = cos(t)*a + sin(t)*b;
- b' = cos(t)*b - sin(t)*a;
- (or switch the signs depending on which way you want to define as
- the positive direction of rotation).
-
- Now, to cleanly handle multiple rotations, we want to use matrices
- to handle this. This is the same as
-
- | cos(t) sin(t)| |a| _ |a'|
- |-sin(t) cos(t)| |b| - |b'|
-
- that is, a 2x2 matrix times a 2x1 matrix gives a 2x1 matrix. Now
- to handle an arbitrary 3D rotation, we need to rotate on any axis:
-
- rotate about x rotate about y rotate about z
-
- | 1 0 0 | | cos(t) 0 -sin(t) | | cos(t) sin(t) 0 |
- | 0 cos(t) sin(t) | | 0 1 0 | | -sin(t) cos(t) 0 |
- | 0 -sin(t) cos(t) | | sin(t) 0 cos(t) | | 0 0 1 |
-
- Now, to rotate about a particular point, we have to translate to that
- point. Say we want to rotate about (d,e,f). Then we subtract (d,e,f)
- from our point, rotate, and then add (d,e,f) again. It would be nice
- if we could do that automatically with the matrices, and there is a way
- to, a cute trick. We switch from 3x3 matrices to 4x4 matrices, and use
- 4-vectors. For the rotation matrices, the new elements are all zero,
- except the bottom right one which is 1; for example:
-
- | cos(t) sin(t) 0 0 |
- | -sin(t) cos(t) 0 0 |
- | 0 0 1 0 |
- | 0 0 0 1 |
-
- Also, all of our vectors have a fourth element, which is always 1.
- (In programming this, you can just continue to use three-vectors and
- program the 'multiply matrix by vector routine' to pretend there's
- one there.) Now, to do a translation we want:
-
- x' = x + k1;
- y' = y + k2;
- z' = z + k3;
-
- It turns out that this does the trick:
-
- | 1 0 0 k1 | | x |
- | 0 1 0 k2 | | y |
- | 0 0 1 k3 | | z |
- | 0 0 0 1 | | 1 |
-
-
- Now, let's define some matrix terms so we can compress our notation.
- Let Rx(t), Ry(t), and Rz(t) be the 4x4 rotation matrices, and let
- T(k1,k2,k3) signify the appropriate matrix as above. To rotate a point
- (a,b,c) theta around the y axis at point (d,e,f), we do the following
- in sequence: T(-d,-e,-f), Ry(theta), T(d,e,f). Now, one nice thing
- about matrices is that we can get the effect of sequential application
- by multiplying matrices; that is, if U = (a,b,c,1) and V=(a',b',c',1),
- then do T(-d,-e,-f)*U, and take that and do Ry(theta)*that, and take
- this and do T(d,e,f)*this, giving V, then this is:
-
- T(d,e,f) * ( Ry(theta) * ( T(-d,-e,-f) * U ) ) ) = V
-
- Since matrix operations are associative, this is the same as
-
- T(d,e,f) * Ry(theta) * T(-d,-e,-f) * U = V
-
- or, in other words, let M = T(d,e,f)*Ry(theta)*T(-d,-e,-f), then
- M is a matrix which performs the rotation we desire.
-
- Ok, now to wrap it all up. Suppose we have a bunch of objects in
- 3D we want to display, and the aforementioned camera. The camera
- is at (cx,cy,cz), and we have a vector E pointing in the direction
- the camera is aiming, a vector D which shows which way the window
- is pointing to the right, and a vector F which points along the window
- upward. These vectors form an orthonormal basis, so to rotate into
- the frame of reference for them we use the matrix
-
- | Dx Dy Dz |
- | Ex Ey Ez |
- | Fx Fy Fz |
-
- also, we want to use 4x4 matrices and first we want to translate
- to cx..cz, so we use
-
- matrix J matrix C
- | Dx Dy Dz 0 | | 0 0 0 -cx |
- | Ex Ey Ez 0 | | 0 0 0 -cy |
- | Fx Fy Fz 0 | | 0 0 0 -cz |
- | 0 0 0 1 | | 0 0 0 1 |
-
- So for an arbitrary point (a,b,c) in three space, the screen coordinates
- for it sx, sy are: let U = (a,b,c,1); let V = J*C*U. Then
-
- if (Vy>0) then
- sx = scale_x * Vx/Vy + center_x;
- sy = - scale_y * Vz/Vy + center_y;
- endif
-
- Generally, we want to store J and C separately. It is pretty simple
- to move the camera, now; if the camera is always moving in the direction
- its facing, use the E vector and factor direction in by hand, and
- put this into C. To rotate the camera, just multiply a rotation
- matrix on the left by J.
-
- Now, to rotate objects properly, keep a separate rotation matrix
- for each object. Then for each point in that object, rotate it and
- translate it. It's simplest to store each object with the origin
- as the center of the object. Then to calculate a point, you multiply
- by the rotation matrix and then by the translation to put the objects
- center where it should be in world space; because you're doing the
- translation second, it's easy to put it into one matrix:
-
- translation rotation
- | 1 0 0 l | | a b c 0 | | a b c l |
- | 0 1 0 m | | d e f 0 | _ | d e f m |
- | 0 0 1 n | * | g h i 0 | - | g h i n |
- | 0 0 0 1 | | 0 0 0 1 | | 0 0 0 1 |
-
- Call this matrix O(q) where q is the object number.
-
- Then, for each point in object q, the final multiply is
- V = J * C * O(q) * U.
-
- Finally, we can move some of the final calculation into a matrix.
- We have:
- sx = scale_x * Vx/Vy + center_x;
- sy = -scale_y * Vz/Vy + center_y;
-
- If we factor out Vy, we get
- sx = (scale_x * Vx + center_x * Vy)/Vy;
- sy = (-scale_y * Vz + center_y * Vy)/Vy;
-
- Suppose from V we calculate V':
- (scale_x*Vx + center_x*Vy, Vy, -scale_y*Vz + center_y*Vz, 1)
-
- Then
- sx = V'x / V'y;
- sy = V'z / V'y;
-
- Well, to get V', we just multiply V by the matrix
-
- | scale_x center_x 0 0 |
- | 0 1 0 0 |
- | 0 center_y -scale_y 0 |
- | 0 0 0 1 |
-
- Let us call this matrix S. Remember, scale_x = d/h*number_of_x_pixels,
- scale_y = d/v*number_of_y_pixels, d is distance from eye to window,
- h is width of imaginary screen, v is height of imaginary screen.
-
- So, now, the basic idea is this. To minimize calculation, let
- N = S * J * C. For each object q, let M = N * O(q). For every point
- U in q, let V = M * U. If Vy>0, then that point is at (Vx/Vy,Vz/Vy)
- on the screen.
-
- In pseudo-code, that's
-
- /* matrix_multiply (destination, left_multiplicand, right_multiplicand) */
-
- for each time slice do
- if camera has moved then
- matrix_multiply ( N, J, C);
- matrix_multiply ( N, S, N);
- endif
-
- for q an object do
- matrix_multiply( M, N, O[q]);
- for p a point in object q do
- matrix_by_vector_multiply( V, M, U[q][p]);
- do something with ( V[0]/V[1], V[2]/V[1] );
- endfor
- endfor
- endfor
-
- In truth, the matrix_by_vector_multiply wastes a bit of time, if you're
- trying to tune the code, it'd be worth tuning it. Normally, it does
- this:
-
- V0 = M00*U0 + M01*U1 + M02*U2 + M03*U3;
- V1 = M10*U0 + M11*U1 + M12*U2 + M13*U3;
- V2 = M20*U0 + M21*U1 + M22*U2 + M23*U3;
- V3 = M30*U0 + M31*U1 + M32*U2 + M33*U3;
-
- However, we know that the bottom row is never used, since V3 is always
- 1; furthermore, we know that U3 is 1, so we can just do
-
- V0 = M00*U0 + M01*U1 + M02*U2 + M03;
- V1 = M10*U0 + M11*U1 + M12*U2 + M13;
- V2 = M20*U0 + M21*U1 + M22*U2 + M23;
-
- This uses nine multiplies and nine adds, plus the two divides required
- to calculate the screen coordinate. I believe this is the minimum
- possible for arbitrary 3D graphics. (You can turn the two divides into
- one divide and two multiplies by calculating 1/Vy and multiplying by
- that, which may be a win on some machines.)
-
- ---
- * Blue Wave/QWK v2.11 *
-
-