138 lines
6.3 KiB
Markdown
138 lines
6.3 KiB
Markdown
**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.
|