home *** CD-ROM | disk | FTP | other *** search
- General
-
- 3dF is an extract of TerraBase, a system for
- manipulating terrain models. Several people
- expressed an interest in the part that does
- real-time orthographic rendering of a piece of
- terrain as a `floating net' with hidden lines
- removed, so I provide this code and executable
- for information and experimentation.
-
- It is reasonably fast. On a 4.77Mhz 8088, it
- draws one frame of a 30x30 grid in 2.3 seconds.
- On a 16Mhz 80486, it looks like about 4-5 frames
- a second; quite smooth.
-
- Since most folks will not have terrain data,
- I've glued on a front end that accepts an
- expression in x and y and calculates f(x,y) to
- form the net heights. The total user interface
- is the command line plus the cursor keys that
- control the view angle for the orthographic image.
- Hence a command line editor is a huge convenience.
-
- The result is a very good test and experimentation
- base for the surface rendering code and a marginal
- F(x,y) sketcher; calculus teachers may find it
- useful, for instance.
-
- Usage
-
- Just type 3DF for a demo.
-
- Here is the help, which may also be obtained
- with `3DF /?' at the MSDOS prompt.
-
- --
-
- Usage: 3df [[options] expression]
- options:
- /x<real> -- x of domain center (default 0)
- /y<real> -- y of domain center (default 0)
- /s<posReal> -- x and y size of domain (default 1)
- /? -- This help.
- expression: Optionally "quoted" function of x and y.
- Operators by precedence:
- a^b - a to b power, b >= 0 or int < 0 right associative
- -a - negate a
- a*b - a times b a/b - a divided by b left associative
- a+b - a plus b a-b - a minus b left associative
- Functions:
- Sin(a), Cos(a), Ln(a), Exp(a), Sqrt(a), Atan(a), Abs(a),
- Min(a,b), Max(a,b). Case is ignored.
- Example:
- 3df /x1 /y1.2 /s2 min(2,sqrt(abs(1-x^2-y^2)))
-
- --
-
- The optional quotes are to convince shells
- that the expression is not something else. 4DOS,
- for instance, is upset by the ^ character unless
- the formula is quoted.
-
- Once the function is calculated and the image is in
- view, note the arrow is pointing in the positive y
- direction. The left/right cursor keys affect
- rate of rotation about the F axis. Up and down
- increment/decrement the elevation of the view angle.
- PgUp and PgDn magnify and shrink along the F axis.
- Home sets just the rotation speed back to the small
- initial value. End sets everything, angles and
- magnification back to initial values.
-
- The Code
-
- As noted in the comments, the code is not pretty.
- It was written primarily on a dare from someone
- who wanted to buy some expensive hardware to do
- the same thing as this program; there wasn't much
- time to get it done.
-
- Those who have the patience to plow through it
- will see that the algorithms are really quite
- simple; I think the Pascal could be about half
- its current size and faster if one were to give
- some careful thought to a rewrite. The assembly
- code is pretty tight, but optimized for 8088; there
- should be some changes for 803|486. Again sorry for
- the lack of comments.
-
- The line-drawing code is a standard Bresenham algorithm
- that computes pixel masks and addresses incrementally
- rather than computing (x,y)s, then computing a mask and
- address for each point. This makes it faster than most
- libraries, the BGI for instance. The other thing that
- helps speed is that there is no clipping or chopping;
- the image MUST remain on the screen or the CPU generally
- goes to LaLaLand.
-
- Lines are written into a 16k buffer, then the buffer is
- blasted onto the screen when an image is complete. This
- approach was the only one possible with the CGA, as we
- didn't want to watch the drawing in progress. The copy
- requires only 18 milliseconds on my 8088 by a crude
- benchmark, and having the buffer be contiguous rather
- than in even and odd scan lines makes the line-drawing
- code much simpler.
-
- The other thing the line code does is hidden line removal.
- The Pascal code ensures that the image is drawn `front
- to back' no matter what the rotation angle. That's the
- reason for the four copies of the surface heights; it was
- easier to make the copies than to fiddle with four different
- loop increment schemes depending on the view angle.
- (I told you it was nasty code ;-} )
-
- Given front to back drawing, all we need is a vector of
- 640 words to hold the y of the top-most dot drawn so far
- for each x. Before drawing each dot, we consult the vector
- to see if there's already a dot higher (smaller y since y
- is 0 at the top of the screen) for that x. If so, the new
- dot is `hidden' and we don't plot it. If not, its `visible'
- so we draw the dot and update the vector. The area
- under (of greater y than) the vector values is considered
- to be `the cloud'. You never draw anything on the cloud, only
- add to its top fringe.
-
- Actually two vectors are necessary to keep track of the
- cloud, one with old values and one with new. As we draw,
- the old one is consulted to make the visibility decision
- and the new one is updated. After each row of net squares
- is drawn (in some cases between squares), we update the
- old cloud with the new one and continue. Only the stretch
- of vector values that were actually changed is copied; this
- little optimization improves speed quite a bit. The
- `obvious' improvement of accessing the vectors through
- pointers and just swapping pointers as necessary doesn't
- pan out when you think about it a bit.
-
- There are many, many improvements possible. The first is
- that we're tracking only the top of the cloud, when a more
- general approach is to track the top and bottom using four
- vectors, and add to both the bottom and top fringe as we
- draw. What would this buy us? Well, we wouldn't need
- the `skirt' along the edges that runs down to the min F
- value; we would correctly see visible sections of the
- underside of the surface from low view angles. (If the
- skirt weren't there now, visible portions of the underside
- would simply be missing. In fact with this mod there would
- be no reason to restrict view angles to be above the x-y
- plane. We could look up from below just as easily as we
- now soar above. Unfortunately this puts a new comparison
- and possible vector update in the inner loop, so there will
- be significant performance degredation; my guess is 10%.
-
- Axes and labels could be added. You could invent a simple
- stroke font or borrow one of Borland's, transform points
- the same way as image points, and get orthographically
- projected text. This has to be drawn at the right time;
- first if it's in front and last if it's at the back of
- the image; and you have to make this decision based
- on view angle.
-
- A major project would be to add clipping and then perspective
- so one could fly over, under, and through the surface.
- Clever assembly language hacking should keep it fast. Recall
- that flight simulators do it, though they handle smaller
- images than our 900+ points and 1800+ line segments.
-
- Gene Ressler
- ressler@cs.cornell.edu
- 124 Pine Tree Road,
- Ithaca, NY 14580
-
- April 91