Initial conversion to markdown
This commit is contained in:
parent
a96a114403
commit
5e10794a24
362 changed files with 67353 additions and 0 deletions
150
53-04.md
Normal file
150
53-04.md
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](53-03.html) [Table of Contents](index.html) [Next](54-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
**LISTING 53.2 OLIST.C**
|
||||
|
||||
/* Object list-related functions. */
|
||||
#include <stdio.h>
|
||||
#include “polygon.h”
|
||||
|
||||
/* Set up the empty object list, with sentinels at both ends to
|
||||
terminate searches */
|
||||
void InitializeObjectList()
|
||||
{
|
||||
ObjectListStart.NextObject = &ObjectListEnd;
|
||||
ObjectListStart.PreviousObject = NULL;
|
||||
ObjectListStart.CenterInView.Z = INT-TO-FIXED(-32768);
|
||||
ObjectListEnd.NextObject = NULL;
|
||||
ObjectListEnd.PreviousObject = &ObjectListStart;
|
||||
ObjectListEnd.CenterInView.Z = 0x7FFFFFFFL;
|
||||
NumObjects = 0;
|
||||
}
|
||||
|
||||
/* Adds an object to the object list, sorted by center Z coord. */
|
||||
void AddObject(Object *ObjectPtr)
|
||||
{
|
||||
Object *ObjectListPtr = ObjectListStart.NextObject;
|
||||
|
||||
/* Find the insertion point. Guaranteed to terminate because of
|
||||
the end sentinel */
|
||||
while (ObjectPtr->CenterInView.Z > ObjectListPtr->CenterInView.Z) {
|
||||
ObjectListPtr = ObjectListPtr->NextObject;
|
||||
}
|
||||
|
||||
/* Link in the new object */
|
||||
ObjectListPtr->PreviousObject->NextObject = ObjectPtr;
|
||||
ObjectPtr->NextObject = ObjectListPtr;
|
||||
ObjectPtr->PreviousObject = ObjectListPtr->PreviousObject;
|
||||
ObjectListPtr->PreviousObject = ObjectPtr;
|
||||
NumObjects++;
|
||||
}
|
||||
|
||||
/* Resorts the objects in order of ascending center Z coordinate in view space,
|
||||
by moving each object in turn to the correct position in the object list. */
|
||||
void SortObjects()
|
||||
{
|
||||
int i;
|
||||
Object *ObjectPtr, *ObjectCmpPtr, *NextObjectPtr;
|
||||
|
||||
/* Start checking with the second object */
|
||||
ObjectCmpPtr = ObjectListStart.NextObject;
|
||||
ObjectPtr = ObjectCmpPtr->NextObject;
|
||||
for (i=1; i<NumObjects; i++) {
|
||||
/* See if we need to move backward through the list */
|
||||
if (ObjectPtr->CenterInView.Z < ObjectCmpPtr->CenterInView.Z) {
|
||||
/* Remember where to resume sorting with the next object */
|
||||
NextObjectPtr = ObjectPtr->NextObject;
|
||||
/* Yes, move backward until we find the proper insertion
|
||||
point. Termination guaranteed because of start sentinel */
|
||||
do {
|
||||
ObjectCmpPtr = ObjectCmpPtr->PreviousObject;
|
||||
} while (ObjectPtr->CenterInView.Z <
|
||||
ObjectCmpPtr->CenterInView.Z);
|
||||
|
||||
/* Now move the object to its new location */
|
||||
/* Unlink the object at the old location */
|
||||
ObjectPtr->PreviousObject->NextObject =
|
||||
ObjectPtr->NextObject;
|
||||
ObjectPtr->NextObject->PreviousObject =
|
||||
ObjectPtr->PreviousObject;
|
||||
|
||||
/* Link in the object at the new location */
|
||||
ObjectCmpPtr->NextObject->PreviousObject = ObjectPtr;
|
||||
ObjectPtr->PreviousObject = ObjectCmpPtr;
|
||||
ObjectPtr->NextObject = ObjectCmpPtr->NextObject;
|
||||
ObjectCmpPtr->NextObject = ObjectPtr;
|
||||
|
||||
/* Advance to the next object to sort */
|
||||
ObjectCmpPtr = NextObjectPtr->PreviousObject;
|
||||
ObjectPtr = NextObjectPtr;
|
||||
} else {
|
||||
/* Advance to the next object to sort */
|
||||
ObjectCmpPtr = ObjectPtr;
|
||||
ObjectPtr = ObjectPtr->NextObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#### Rounding {#Heading6}
|
||||
|
||||
FIXED.ASM contains the equate **ROUNDING-ON**. When this equate is 1,
|
||||
the results of multiplications and divisions are rounded to the nearest
|
||||
fixed-point values; when it’s 0, the results are truncated. The
|
||||
difference between the results produced by the two approaches is, at
|
||||
most, 2^-16^; you wouldn’t think that would make much difference, now,
|
||||
would you? But it does. When the animation is run with rounding
|
||||
disabled, the cubes start to distort visibly after a few minutes, and
|
||||
after a few minutes more they look like they’ve been run over. In
|
||||
contrast, I’ve never seen any significant distortion with rounding on,
|
||||
even after a half-hour or so. I think the difference with rounding is
|
||||
not that it’s so much more accurate, but rather that the errors are
|
||||
evenly distributed; with truncation, the errors are biased, and biased
|
||||
errors become very visible when they’re applied to right-angle objects.
|
||||
Even with rounding, though, the errors will eventually creep in, and
|
||||
reorthogonalization will become necessary at some point.
|
||||
|
||||
The performance cost of rounding is small, and the benefits are highly
|
||||
visible. Still, truncation errors become significant only when they
|
||||
accumulate over time, as, for example, when rotation matrices are
|
||||
repeatedly concatenated over the course of many transformations. Some
|
||||
time could be saved by rounding only in such cases. For example,
|
||||
division is performed only in the course of projection, and the results
|
||||
do not accumulate over time, so it would be reasonable to disable
|
||||
rounding for division.
|
||||
|
||||
#### Having a Ball {#Heading7}
|
||||
|
||||
So far in our exploration of 3-D animation, we’ve had nothing to look at
|
||||
but triangles and cubes. It’s time for something a little more visually
|
||||
appealing, so the demonstration program now features a 72-sided ball.
|
||||
What’s particularly interesting about this ball is that it’s created by
|
||||
the GENBALL.C program in the BALL subdirectory of X-Sharp, and both the
|
||||
size of the ball and the number of bands of faces are programmable.
|
||||
GENBALL.C spits out to a file all the arrays of vertices and faces
|
||||
needed to create the ball, ready for inclusion in INITBALL.C. True, if
|
||||
you change the number of bands, you must change the Colors array in
|
||||
INITBALL.C to match, but that’s a tiny detail; by and large, the process
|
||||
of generating a ball-shaped object is now automated. In fact, we’re not
|
||||
limited to ball-shaped objects; substitute a different vertex and face
|
||||
generation program for GENBALL.C, and you can make whatever convex
|
||||
polyhedron you want; again, all you have to do is change the **Colors**
|
||||
array correspondingly. You can easily create multiple versions of the
|
||||
base object, too; INITCUBE.C is an example of this, creating 11
|
||||
different cubes.
|
||||
|
||||
What we have here is the first glimmer of an object-editing system.
|
||||
GENBALL.C is the prototype for object definition, and INITBALL.C is the
|
||||
prototype for general-purpose object instantiation. Certainly, it would
|
||||
be nice to someday have an interactive 3-D object editing tool and
|
||||
resource management setup. We have our hands full with the drawing end
|
||||
of things at the moment, though, and for now it’s enough to be able to
|
||||
create objects in a semiautomated way.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](53-03.html) [Table of Contents](index.html) [Next](54-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
Loading…
Reference in a new issue