191 lines
7.2 KiB
HTML
191 lines
7.2 KiB
HTML
<HTML>
|
|
<HEAD>
|
|
<META name=vsisbn content="1576101746">
|
|
<META name=vstitle content="Michael Abrash's Graphics Programming Black Book, Special Edition">
|
|
<META name=vsauthor content="Michael Abrash">
|
|
<META name=vspublisher content="The Coriolis Group">
|
|
<META name=vspubdate content="07/01/97">
|
|
<META name=vscategory content="Web and Software Development: Game Development,Web and Software Development: Graphics and Multimedia Development">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<TITLE>Michael Abrash's Graphics Programming Black Book Special Edition: Fast 3-D Animation: Meet X-Sharp</TITLE>
|
|
|
|
<!-- HEADER -->
|
|
<!-- Empty Reference Subhead -->
|
|
|
|
<!--ISBN=1576101746//-->
|
|
<!--TITLE=Michael Abrash's Graphics Programming Black Book Special Edition//-->
|
|
<!--AUTHOR=Michael Abrash//-->
|
|
<!--PUBLISHER=The Coriolis Group, Inc.//-->
|
|
<!--CHAPTER=52//-->
|
|
<!--PAGES=973-974//-->
|
|
<!--UNASSIGNED1//-->
|
|
<!--UNASSIGNED2//--></HEAD><BODY LINK=#0000FF ALINK=#000099 VLINK=#0000FF BGCOLOR=#FFFFFF>
|
|
|
|
<CENTER>
|
|
<TABLE BORDER>
|
|
<TR>
|
|
<TD><A HREF="52-01.html">Previous</A></TD>
|
|
<TD><A HREF="index.html">Table of Contents</A></TD>
|
|
<TD><A HREF="52-03.html">Next</A></TD>
|
|
</TR>
|
|
</TABLE>
|
|
</CENTER>
|
|
<P><BR></P>
|
|
<P><B>LISTING 52.1 L52-1.C</B></P>
|
|
<!-- CODE //-->
|
|
<PRE>
|
|
/* 3-D animation program to rotate 12 cubes. Uses fixed point. All C code
|
|
tested with Borland C++ in C compilation mode and the small model. */
|
|
|
|
#include <conio.h>
|
|
#include <dos.h>
|
|
#include “polygon.h”
|
|
|
|
/* base offset of page to which to draw */
|
|
unsigned int CurrentPageBase = 0;
|
|
/* clip rectangle; clips to the screen */
|
|
int ClipMinX = 0, ClipMinY = 0;
|
|
int ClipMaxX = SCREEN_WIDTH, ClipMaxY = SCREEN_HEIGHT;
|
|
static unsigned int PageStartOffsets[2] =
|
|
{PAGE0_START_OFFSET,PAGE1_START_OFFSET};
|
|
int DisplayedPage, NonDisplayedPage;
|
|
int RecalcAllXforms = 1, NumObjects = 0;
|
|
Xform WorldViewXform; /* initialized from floats */
|
|
/* pointers to objects */
|
|
Object *ObjectList[MAX_OBJECTS];
|
|
|
|
void main() {
|
|
int Done = 0, i;
|
|
Object *ObjectPtr;
|
|
union REGS regset;
|
|
|
|
InitializeFixedPoint(); /* set up fixed-point data */
|
|
InitializeCubes(); /* set up cubes and add them to object list; other
|
|
objects would be initialized now, if there were any */
|
|
Set320x240Mode(); /* set the screen to mode X */
|
|
ShowPage(PageStartOffsets[DisplayedPage = 0]);
|
|
/* Keep transforming the cube, drawing it to the undisplayed page,
|
|
and flipping the page to show it */
|
|
do {
|
|
/* For each object, regenerate viewing info, if necessary */
|
|
for (i=0; i<NumObjects; i++) {
|
|
if ((ObjectPtr = ObjectList[i])->RecalcXform ||
|
|
RecalcAllXforms) {
|
|
ObjectPtr->RecalcFunc(ObjectPtr);
|
|
ObjectPtr->RecalcXform = 0;
|
|
}
|
|
}
|
|
RecalcAllXforms = 0;
|
|
CurrentPageBase = /* select other page for drawing to */
|
|
PageStartOffsets[NonDisplayedPage = DisplayedPage ^ 1];
|
|
/* For each object, clear the portion of the non-displayed page
|
|
that was drawn to last time, then reset the erase extent */
|
|
for (i=0; i<NumObjects; i++) {
|
|
ObjectPtr = ObjectList[i];
|
|
FillRectangleX(ObjectPtr->EraseRect[NonDisplayedPage].Left,
|
|
ObjectPtr->EraseRect[NonDisplayedPage].Top,
|
|
ObjectPtr->EraseRect[NonDisplayedPage].Right,
|
|
ObjectPtr->EraseRect[NonDisplayedPage].Bottom,
|
|
CurrentPageBase, 0);
|
|
ObjectPtr->EraseRect[NonDisplayedPage].Left =
|
|
ObjectPtr->EraseRect[NonDisplayedPage].Top = 0x7FFF;
|
|
ObjectPtr->EraseRect[NonDisplayedPage].Right =
|
|
ObjectPtr->EraseRect[NonDisplayedPage].Bottom = 0;
|
|
}
|
|
/* Draw all objects */
|
|
for (i=0; i<NumObjects; i++)
|
|
ObjectList[i]->DrawFunc(ObjectList[i]);
|
|
/* Flip to display the page into which we just drew */
|
|
ShowPage(PageStartOffsets[DisplayedPage = NonDisplayedPage]);
|
|
/* Move and reorient each object */
|
|
for (i=0; i<NumObjects; i++)
|
|
ObjectList[i]->MoveFunc(ObjectList[i]);
|
|
if (kbhit())
|
|
if (getch() == 0x1B) Done = 1; /* Esc to exit */
|
|
} while (!Done);
|
|
/* Return to text mode and exit */
|
|
regset.x.ax = 0x0003; /* AL = 3 selects 80x25 text mode */
|
|
int86(0x10, &regset, &regset);
|
|
exit(1);
|
|
}
|
|
</PRE>
|
|
<!-- END CODE //-->
|
|
<P><B>LISTING 52.2 L52-2.C</B></P>
|
|
<!-- CODE //-->
|
|
<PRE>
|
|
/* Transforms all vertices in the specified polygon-based object into view
|
|
space, then perspective projects them to screen space and maps them to screen
|
|
coordinates, storing results in the object. Recalculates object->view
|
|
transformation because only if transform changes would we bother
|
|
to retransform the vertices. */
|
|
|
|
#include <math.h>
|
|
#include “polygon.h”
|
|
|
|
void XformAndProjectPObject(PObject * ObjectToXform)
|
|
{
|
|
int i, NumPoints = ObjectToXform->NumVerts;
|
|
Point3 * Points = ObjectToXform->VertexList;
|
|
Point3 * XformedPoints = ObjectToXform->XformedVertexList;
|
|
Point3 * ProjectedPoints = ObjectToXform->ProjectedVertexList;
|
|
Point * ScreenPoints = ObjectToXform->ScreenVertexList;
|
|
|
|
/* Recalculate the object->view transform */
|
|
ConcatXforms(WorldViewXform, ObjectToXform->XformToWorld,
|
|
ObjectToXform->XformToView);
|
|
/* Apply that new transformation and project the points */
|
|
for (i=0; i<NumPoints; i++, Points++, XformedPoints++,
|
|
ProjectedPoints++, ScreenPoints++) {
|
|
/* Transform to view space */
|
|
XformVec(ObjectToXform->XformToView, (Fixedpoint *) Points,
|
|
(Fixedpoint *) XformedPoints);
|
|
/* Perspective-project to screen space */
|
|
ProjectedPoints->X =
|
|
FixedMul(FixedDiv(XformedPoints->X, XformedPoints->Z),
|
|
DOUBLE_TO_FIXED(PROJECTION_RATIO * (SCREEN_WIDTH/2)));
|
|
ProjectedPoints->Y =
|
|
FixedMul(FixedDiv(XformedPoints->Y, XformedPoints->Z),
|
|
DOUBLE_TO_FIXED(PROJECTION_RATIO * (SCREEN_WIDTH/2)));
|
|
ProjectedPoints->Z = XformedPoints->Z;
|
|
/* Convert to screen coordinates. The Y coord is negated to flip from
|
|
increasing Y being up to increasing Y being down, as expected by polygon
|
|
filler. Add in half the screen width and height to center on screen. */
|
|
ScreenPoints->X = ((int) ((ProjectedPoints->X +
|
|
DOUBLE_TO_FIXED(0.5)) >> 16)) + SCREEN_WIDTH/2;
|
|
ScreenPoints->Y = (-((int) ((ProjectedPoints->Y +
|
|
DOUBLE_TO_FIXED(0.5)) >> 16))) + SCREEN_HEIGHT/2;
|
|
}
|
|
}<B></B>
|
|
</PRE>
|
|
<!-- END CODE //-->
|
|
<P><BR></P>
|
|
<CENTER>
|
|
<TABLE BORDER>
|
|
<TR>
|
|
<TD><A HREF="52-01.html">Previous</A></TD>
|
|
<TD><A HREF="index.html">Table of Contents</A></TD>
|
|
<TD><A HREF="52-03.html">Next</A></TD>
|
|
</TR>
|
|
</TABLE>
|
|
</CENTER>
|
|
|
|
<hr width="90%" size="1" noshade>
|
|
<div align="center">
|
|
<font face="Verdana,sans-serif" size="1">Graphics Programming Black Book © 2001 Michael Abrash</font>
|
|
</div>
|
|
<!-- all of the reference materials (books) have the footer and subfoot reveresed -->
|
|
<!-- reference_subfoot = footer -->
|
|
<!-- reference_footer = subfoot -->
|
|
|
|
<!-- BEGIN SUB FOOTER -->
|
|
</BODY>
|
|
</HTML>
|
|
|
|
<!-- END FOOTER -->
|
|
|
|
|