fast 3-d animation: meet x-sharp - gamedev.netdownloads.gamedev.net/pdf/gpbb/gpbb52.pdf · 2019....

18
CHAPTER 52 FAST 3-D ANIMATION: MEET X-SHARP

Upload: others

Post on 31-Dec-2020

3 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: FAST 3-D ANIMATION: MEET X-SHARP - GameDev.netdownloads.gamedev.net/pdf/gpbb/gpbb52.pdf · 2019. 10. 24. · LISTING 52.1 152- 1 .C /* 3-0 animation program to rotate 12 cubes.Uses

CHAPTER 52

FAST 3-D ANIMATION: MEET X-SHARP

Page 2: FAST 3-D ANIMATION: MEET X-SHARP - GameDev.netdownloads.gamedev.net/pdf/gpbb/gpbb52.pdf · 2019. 10. 24. · LISTING 52.1 152- 1 .C /* 3-0 animation program to rotate 12 cubes.Uses

’’. 3-D Anirnahon Package Across the lake fror few miles into upstate New York, the Ausable River has carved out a fai ive gorge known as “Ausable Chasm.” Impressive for the East, anyway; yo nk of it as the poor man’s Grand Canyon. Some time back, I did the tour and five-year-old, and it was fun, although I confess that I didn’t loosen,&y grip on my daughter’s hand until we were on the bus and

;hat gorge is deep, and the railings tend to be of the single-bar,

e straight to this wonder of nature, but Vermonters must take their cars across on the ferry; the alternative is driving three hours around the south end of Lake Champlain. No problem; the ferry ride is an hour well spent on a beau- tiful lake. Or, rather, no problem-once you’re on the ferry. Getting to New York is easy, but, as we found out, the line of cars waiting to come back from Ausable Chasm gets lengthy about mid-afternoon. The ferry can hold only so many cars, and we wound up spending an unexpected hour exploring the wonders of the ferry docks. Not a big deal, with a good-natured kid and an entertaining mom; we got ice cream, explored the beach, looked through binoculars, and told stories. It was a fun break, actually, and before we knew it, the ferry was steaming back to pick us up. A friend of mine, an elementary-school teacher, helped take 65 sixth graders to Ausable Chasm. Never mind the potential for trouble with 65 kids loose on a ferry.

97 1

Page 3: FAST 3-D ANIMATION: MEET X-SHARP - GameDev.netdownloads.gamedev.net/pdf/gpbb/gpbb52.pdf · 2019. 10. 24. · LISTING 52.1 152- 1 .C /* 3-0 animation program to rotate 12 cubes.Uses

Never mind what it was like trying to herd that group around a gorge that looks like it was designed to swallow children and small animals without a trace. The hard part was getting back to the docks and finding they’d have to wait an hour for the next ferry. As my friend put it, “Let me tell you, an hour is an eternitywith 65 sixth graders screaming the song ‘You Are My Sunshine.”’ Apart from reminding you how lucky you are to be working in a quiet, air-condi- tioned room, in front of a gently humming computer, free to think deep thoughts and eat Cheetos to your heart’s content, this story provides a useful perspective on the malleable nature of time. An hour isn’tjust an hour-it can be forever, or it can be the wink of an eye. Just think of the last hour you spent working under a deadline; I bet it went past in a flash. Which is not to say, mind you, that I recommend working in a bus full of screaming kids in order to make time pass more slowly; there are quality issues here as well. In our 3-D animation work so far, we’ve used floating-point arithmetic. Floating- point arithmetic-even with a floating-point processor but especially without one-is the microcomputer animation equivalent ofworking in a school bus: It takes forever to do anything, and you just know you’re never going to accomplish as much as you want to. In this chapter, we’ll address fixed-point arithmetic, which will give us an instant order-of-magnitude performance boost. We’ll also give our 3-D animation code a much more powerful and extensible framework, making it easy to add new and different sorts of objects. Taken together, these alterations will let us start to do some really interesting real-time animation.

This Chapter‘s Demo Program Three-dimensional animation is a complicated business, and it takes an astonishing amount of functionality just to get off the launching pad: page flipping, polygon filling, clipping, transformations, list management, and so forth. I’ve been building toward a critical mass of animation functionality over the course of this book, and this chapter’s code builds on the code from no fewer than five previous chapters. The code that’s required in order to link this chapter’s animation demo program is the following:

Listing 50. I from Chapter 50 (draw clipped line list); Listings 47.1 and 47.6 from Chapter 47 (Mode X mode set, rectangle fill); Listing 49.6 from Chapter 49; Listing 39.4 from Chapter 39 (polygon edge scan); and The FillConvexPolygon( ) function from Listing 38.1 from Chapter 38. Note that the struct keywords in FillConvexPolygon( ) must be removed to reflect the switch to typedefs in the animation header file.

As always, all required files are in this chapter’s subdirectory on the CD-ROM.

972 Chapter 52

Page 4: FAST 3-D ANIMATION: MEET X-SHARP - GameDev.netdownloads.gamedev.net/pdf/gpbb/gpbb52.pdf · 2019. 10. 24. · LISTING 52.1 152- 1 .C /* 3-0 animation program to rotate 12 cubes.Uses

LISTING 52.1 152- 1 .C /* 3-0 a n i m a t i o n p r o g r a m t o r o t a t e 1 2 c u b e s . Uses f i x e d p o i n t . All C code

t e s t e d w i t h B o r l a n d C++ i n C c o m p i l a t i o n mode and the sma l l mode l . * /

#i n c l ude <coni 0. h> #i n c l ude <dos . h> # i n c l u d e " p o l y g o n . h "

/ * b a s e o f f s e t o f p a g e t o w h i c h t o d r a w * / u n s i g n e d i n t C u r r e n t P a g e B a s e - 0: / * c l i p r e c t a n g l e ; c l i p s t o t h e s c r e e n */ i n t C l i p M i n X = 0. C l i pM inY - 0; i n t ClipMaxX = SCREEN-WIDTH. ClipMaxY - SCREEN-HEIGHT: s t a t i c u n s i g n e d i n t P a g e S t a r t O f f s e t s C 2 1 - i n t OisplayedPage. NonOisplayedPage: i n t R e c a l c A l l X f o r m s = 1. NumObjects - 0; Xform WorldViewXform: / * i n i t i a l i z e d f r o m f l o a t s */ /* p o i n t e r s t o o b j e c t s */ O b j e c t *ObjectList [MAX._OBJECTSI:

{PAGEOpSTART-OFFSET,PAGEl-STARTpOFFSET);

v o i d m a i n 0 {

O b j e c t * O b j e c t P t r ; i n t Done = 0. i:

u n i o n REGS r e g s e t ;

I n i t i a l i z e F i x e d P o i n t O : I* s e t u p f i x e d - p o i n t d a t a * / I n i t i a l i z e c u b e s o : / * s e t up cubes and add them t o o b j e c t l i s t : o t h e r

o b j e c t s w o u l d b e i n i t i a l i z e d now, Set320x240ModeO: I* s e t t h e s c r e e n t o mode X *I ShowPage(PageStartOffsetsCDisp1ayedPage = 01) : /* Keep t r a n s f o r m i n g t h e c u b e , d r a w i n g i t t o t h e u n d i s p l a y e d

do I and f l i p p i n g t h e p a g e t o show i t * /

/* For e a c h o b j e c t , r e g e n e r a t e v i e w i n g i n f o , i f necessary fo r ( i - 0 : i <NurnOb jec ts : i++) [

i f ( ( O b j e c t P t r - ObjectListCi1)->RecalcXform I I Recal cAl1 Xforrns) I

ObjectPtr->RecalcFunc(ObjectPtr): O b j e c t P t r - > R e c a l c X f o r m = 0;

1 1 R e c a l c A l l X f o r m s - 0:

i f the re were any */

CurrentPageBase - /* s e l e c t o t h e r p a g e f o r d r a w i n g t o * /

/ * F o r e a c h o b j e c t . c l e a r t h e p o r t i o n o f t h e n o n - d i s p l a y e d p a g e

f o r ( i - 0 : i < N u r n O b j e c t s ; i++) [

PageSta r tO f f se tsCNonDisp layedPage - DisplayedPage * 11:

t h a t was drawn t o l a s t t i m e , t h e n r e s e t t h e e r a s e e x t e n t * /

O b j e c t P t r = O b j e c t L i s t [ i l ; FillRectangleX~ObjectPtr->EraseRect[NonDisplayedPagel.Left,

ObjectPtr->EraseRect[NonDisplayedPagel.Top, ObjectPtr->EraseRect[NonDisplayedPagel.Right, ObjectPtr->EraseRect[NonDisplayedPagel.Bottom, CurrentPageBase. 0 ) ;

ObjectPtr->EraseRectCNonDisplayedPage].Left - Ob jec tP t r ->EraseRec t [NonD isp layedPage l .R igh t - ObjectPtr ->EraseRect [NonDisp layedPage] .Top - Ox7FFF;

ObjectPtr->EraseRect[NonDisplayedPagel.Bottom - 0: 1

Fast 3-D Animation: Meet X-Sharp 973

Page 5: FAST 3-D ANIMATION: MEET X-SHARP - GameDev.netdownloads.gamedev.net/pdf/gpbb/gpbb52.pdf · 2019. 10. 24. · LISTING 52.1 152- 1 .C /* 3-0 animation program to rotate 12 cubes.Uses

/* Draw a l l o b j e c t s * / f o r ( i - 0 : i < N u m O b j e c t s : i++)

/* F l i p t o d i s p l a y t h e p a g e i n t o w h i c h we j u s t drew * I ShowPage(PageStartOffsets1DisplayedPage - NonDisplayedPage]) : / * Move a n d r e o r i e n t e a c h o b j e c t * / f o r ( i - 0 : i<NumObjects; i++)

i f ( k b h i t 0 )

Ob jec tL i s tC i l ->DrawFunc(Ob jec tL i s tC i l ) ;

O b j e c t L i s t C i l - > M o v e F u n c ( 0 b j e c t L i s t C i 3 ) ;

i f ( g e t c h 0 - OxlB) Done - 1: /* Esc t o e x i t */ 1 w h i l e ( ! D o n e ) ; / * R e t u r n t o t e x t mode and e x i t * / r e g s e t . x . a x - 0x0003; / * AL - 3 s e l e c t s 8 0 x 2 5 t e x t mode */ i n t 8 6 ( 0 x 1 0 . & r e g s e t . & r e g s e t ) ; e x i t ( 1 ) :

1

LISTING 52.2 152-2.C /* T r a n s f o r m s a l l v e r t i c e s i n t h e s p e c i f i e d p o l y g o n - b a s e d o b j e c t i n t o v i e w

s p a c e , t h e n p e r s p e c t i v e p r o j e c t s t h e m t o s c r e e n s p a c e a n d maps them t o s c r e e n c o o r d i n a t e s , s t o r i n g r e s u l t s i n t h e o b j e c t . R e c a l c u l a t e s o b j e c t - > v i e w t r a n s f o r m a t i o n b e c a u s e o n l y i f t rans fo rm changes wou ld we b o t h e r t o r e t r a n s f o r m t h e v e r t i c e s . */

# inc lude <math .h> # inc lude "po1ygon .h "

v o i d XformAndProjectPObject(P0bject * ObjectToXform) [

i n t i. NumPoints - ObjectToXform->NumVerts: P o i n t 3 * P o i n t s - O b j e c t T o X f o r m - > V e r t e x L i s t : P o i n t 3 * XformedPoints - ObjectToXform->XformedVertexList: P o i n t 3 * P r o j e c t e d P o i n t s - ObjectToXform->Pro jec tedVer texL is t : P o i n t * S c r e e n p o i n t s - ObjectToXform-XcreenVer texL is t :

/ * R e c a l c u l a t e t h e o b j e c t - > v i e w t r a n s f o r m */ ConcatXforms(Wor1dViewXform. ObjectToXform->XformToWorld.

ObjectToXform->XformToView): /* A p p l y t h a t new t r a n s f o r m a t i o n and p r o j e c t t h e p o i n t s */ f o r ( i - 0 : i < N u m P o i n t s ; i++. Points++, XformedPoints++,

P r o j e c t e d P o i n t s + + . S c r e e n P o i n t s t t ) I /* T r a n s f o r m t o v i e w s p a c e * / XformVec(0bjectToXform->XformToView. ( F i x e d p o i n t * ) P o i n t s ,

( F i x e d p o i n t * ) X fo rmedPo in ts ) : /* P e r s p e c t i v e - p r o j e c t t o s c r e e n s p a c e * / P r o j e c t e d P o i n t s - > X -

DOUBLE~TO~FIXED(PROJECTION~RATIO * (SCREEN-WIDTH/Z))); FixedMul(FixedDiv(XformedPoints->X. Xfo rmedPo in ts ->Z) .

O O U B L E ~ T O ~ F I X E O ( P R O J E C T I O N ~ R A T I O * (SCREEN_WIOTH/E))): FixedMul(FixedDiv(XformedPoints->Y, Xfo rmedPo in ts ->Z) ,

P r o j e c t e d P o i n t s - > Y - P r o j e c t e d P o i n t s - > Z - XformedPoints->Z: / * C o n v e r t t o s c r e e n c o o r d i n a t e s . The Y c o o r d i s n e g a t e d t o f l i p f rom

i n c r e a s i n g Y b e i n g u p t o i n c r e a s i n g Y b e i n g down, as expec ted by po lygon f i l l e r . Add i n h a l f t h e s c r e e n w i d t h a n d h e i g h t t o c e n t e r on screen. * /

Sc reenPo in ts ->X - ( ( i n t ) ( ( P r o j e c t e d P o i n t s - > X +

ScreenPo in ts ->Y - ( - ( ( i n t ) ( ( P r o j e c t e d P o i n t s - > Y + DOUBLE-TO-FIXED(0.5)) >> 1 6 ) ) + SCREEN_WIDTH/2:

DOUBLE-TO-FIXED(0.5)) >> 1 6 ) ) ) + SCREEN-HEIGHT/Z; 1

1

974 Chapter 52

Page 6: FAST 3-D ANIMATION: MEET X-SHARP - GameDev.netdownloads.gamedev.net/pdf/gpbb/gpbb52.pdf · 2019. 10. 24. · LISTING 52.1 152- 1 .C /* 3-0 animation program to rotate 12 cubes.Uses

LISTING 52.3 152-3.C /* Routines to perform incremental rotations around the three axes. */

#include <math.h> t i ncl ude "polygon. h"

/ * Concatenate a rotation by Angle around the X axis to transformation in

void AppendRotationX(Xform XformToChange. double Angle) I

XformToChange. placing the result back into XformToChange. */

Fixedpoint TemplO. Templl. Templ2. TempZO. Tempel. Temp22: Fixedpoint CosTemp - DOUElLE-TO-FIXED(cos(Angle)); Fixedpoint SinTemp - DOUBLE-TO-FIXED(sin(Angle)): /* Calculate the new values of the six affected matrix entries * / TemplO - FixedMul(CosTemp. XformToChange[ll[O1) +

FixedMul(-SinTemp. XformToChange[21[01); Templl - FixedMul(CosTemp. XformToChange[ll[11) +

FixedMul(-SinTemp, XformToChange[21[1]); Temp12 - FixedMul(CosTemp. XformToChange[ll[2]) +

FixedMul(-SinTemp. XformToChange[21[21); Temp20 - FixedMul(SinTemp. XformToChange[ll[OI) +

FixedMul(CosTemp. XformToChange[21CO1); Temp21 - FixedMul(SinTemp. XformToChange[ll[ll) +

FixedMul(CosTemp. XformToChange[ZlCll): Temp22 - FixedMul(SinTemp, XformToChange[llC21) +

FixedMul(CosTemp. XformToChange[Z1[21); /* Put the results back into XformToChange */ XformToChange[11[0] - TemplO; XformToChangeC1][11 - Templl; XformToChange[l][Z] - TemplE: XformToChange[2l[Ol - Temp2D; XformToChange[21[11 - TempEl: XformToChange[2][21 - Temp22;

1 /* Concatenate a rotation by Angle around the Y axis to transformation in

void AppendRotationY(Xform XformToChange. double Angle) {

XformToChange. placing the result back into XformToChange. */

Fixedpoi nt TempOO, TempOl, Temp02, TempZO, TempLl, Temp22; Fixedpoint CosTemp - DOUELE-TO_FIXED(cos(Angle)): Fixedpoint SinTemp - DDUBLE_TD_FIXED(sin(Angle)); /* Calculate the new values of the six affected matrix entries */ TempOO - FixedMul(CosTemp. XformToChange[O1CO1) +

FixedMul (SinTemp. XformToChange[21[01); TempOl - FixedMul(CosTemp. XformToChange[Ol[11) +

FixedMul(SinTemp. XformToChange[21[11); Temp02 - FixedMul(CosTemp. XformToChangeC01C21) +

FixedMul(SinTemp. XformToChange[21[21); Temp20 - FixedMul(-SinTemp. XformToChange[01[01) +

FixedMul( CosTemp. XformToChangeC21[0]); Temp21 - FixedMul (-SinTemp. XformToChange[Ol[11) +

FixedMul(CosTemp. XformToChange[21[11); Temp22 - FixedMul(-SinTemp. XformToChange[Ol[21) +

FixedMul(CosTemp. XformToChange[Zl[Z]); /* Put the results back into XformToChange */ XformToChange[O][O] - TempOO: XformToChange[O1[11 - TempOl; XformToChange[01[2] - TempOZ; XformToChange[2l[Ol - Temp20; XformToChange[2l[ll - Temp21; XformToChange[21[21 - Temp22;

I

Fast 3-D Animation: Meet X-Sharp 975

Page 7: FAST 3-D ANIMATION: MEET X-SHARP - GameDev.netdownloads.gamedev.net/pdf/gpbb/gpbb52.pdf · 2019. 10. 24. · LISTING 52.1 152- 1 .C /* 3-0 animation program to rotate 12 cubes.Uses

/* Concatenate a r o t a t i o n by Ang le a round the 2 a x i s t o t r a n s f o r m a t i o n i n

vo id AppendRotat ionZ(Xform XformToChange. double Angle) {

X fo rmToChange , p lac ing t he resu l t back i n to X fo rmToChange . * /

F i x e d p o i n t TempOO. TempOl. TempOZ. TemplO. Templ l . Templ2: F i x e d p o i n t CosTemp - DOUBLE-TO-FIXED(cos(Angle)): F i x e d p o i n t SinTemp - DOUBLE-TO-FIXED(sin(Angle)); /* C a l c u l a t e t h e new v a l u e s o f t h e s i x a f f e c t e d m a t r i x e n t r i e s * / TempOO - FixedMul(CosTemp. XformToChange[O][Ol) +

FixedMul( -S inTemp, XformToChange[ l ] [O]) : TempOl - FixedMul(CosTemp. XformToChange[O1[11) +

F i x e d M u l ( - S i n T e m p , X f o r m T o C h a n g e ~ l l ~ 1 1 ) ; Temp02 - FixedMul(CosTemp. XformToChange[O1[El) +

FixedMul(-SinTemp. XformToChange[ l ] [21); TemplO - FixedMul(SinTemp. XformToChange[01~01) +

FixedMul(CosTernp. XformToChange[ l l [Ol) : T e m p l l - FixedMul(SinTemp. XformToChange[O1[1]) +

FixedMul(CosTernp. XformToChangeC11[11): Temp12 - FixedMul(SinTemp. XformToChange[O1[El) +

FixedMul(CosTemp. XforrnToChange[11[21): / * P u t t h e r e s u l t s b a c k i n t o XformToChange */ XformToChange[OI[O1 - TempOO; XformToChange[O1CE] - TempO2: X f o r m T o C h a n g e [ l l [ l l - T e m p l l ;

1

LISTING 52.4 152-4.C / * F i x e d p o i n t m a t r i x a r i t h m e t i c

# i n c l u d e " p o l y g o n . h"

XformToChange[0][11 - TempOl: XformToChange[l ] [O] - TemplO: XformToChange[l ] [E] - TernplZ;

f u n c t i o n s . * /

I * M a t r i x m u l t i p l i e s X f o r m b y S o u r c e V e c . and s t o r e s t h e r e s u l t i n D e s t V e c . M u l t i p l i e s a 4 x 4 m a t r i x t i m e s a 4 x 1 m a t r i x : t h e r e s u l t i s a 4 x 1 m a t r i x . C h e a t s by assuming the W c o o r d i s 1 a n d b o t t o m r o w o f m a t r i x i s 0 0 0 1. and d o e s n ' t b o t h e r t o s e t t h e W c o o r d i n a t e o f t h e d e s t i n a t i o n . * /

vo id X formVec(Xfor rn Work ingXfor rn . F ixedpo in t *SourceVec. F i x e d p o i n t * D e s t V e c )

( i n t i:

f o r ( i - 0 : i < 3 : i++) D e s t V e c C i l - FixedMul (WorkingXform[i lCOI, SourceVecCOI) +

FixedMul(WorkingXform[ilCll, SourceVecCl I ) + FixedMul(WorkingXform[iI~21~ SourceVecCEl) + Work ingXform[ i ] [3 ] ; / * no need t o m u l t i p l y by W - 1 */

1

/* M a t r i x m u l t i p l i e s S o u r c e X f o r m l b y S o u r c e X f o r m E a n d s t o r e s r e s u l t i n D e s t X f o r m . M u l t i p l i e s a 4 x 4 m a t r i x t i m e s a 4 x 4 m a t r i x ; r e s u l t i s a 4 x 4 m a t r i x . C h e a t s b y a s s u m i n g b o t t o m r o w o f e a c h m a t r i x i s 0 0 0 1. a n d d o e s n ' t b o t h e r t o s e t t h e b o t t o m r o w o f t h e d e s t i n a t i o n . * /

Xform DestXform)

i n t i. j:

f o r ( i - 0 : i < 3 ; i++) (

vo id ConcatXforms(Xform SourceXforml . X form SourceXformE,

(

f o r ( j -0 : j < 4 ; j++)

976 Chapter 52

Page 8: FAST 3-D ANIMATION: MEET X-SHARP - GameDev.netdownloads.gamedev.net/pdf/gpbb/gpbb52.pdf · 2019. 10. 24. · LISTING 52.1 152- 1 .C /* 3-0 animation program to rotate 12 cubes.Uses

D e s t X f o r m C i l [ j l - FixedMul(SourceXforml[il[Ol, SourceXform2[O][ j ] ) + FixedMul(SourceXforml[il[ll, S o u r c e X f o r m 2 ~ 1 1 ~ j l ) + FixedMul(SourceXforml[ i lC23. S o u r c e X f o r m 2 [ 2 l [ j l ) + S o u r c e X f o r m l [ i l [ 3 1 :

1 3

LISTING 52.5 152-5.C /* S e t u p b a s i c d a t a t h a t n e e d s t o b e i n f i x e d p o i n t , t o a v o i d d a t a

d e f i n i t i o n h a s s l e s . * /

#i ncl ude "po lygon. h"

/ * All v e r t i c e s i n t h e b a s i c c u b e * / s t a t i c I n t P o i n t 3 IntCubeVertsCNUM-CUBE-VERTSI - (

(15.15.15}.~15.15.-15~,~15,-15,15~,~15,-15,-153, [ - 1 5 . 1 5 . 1 5 ] . ( - 1 5 , 1 5 , - 1 5 ~ ~ ~ ~ 1 5 , ~ 1 5 , 1 5 ~ . ~ ~ 1 5 ~ ~ 1 5 , ~ 1 5 1 1 ;

/* T r a n s f o r m a t i o n f r o m w o r l d s p a c e i n t o v i e w s p a c e (no t r a n s f o r m a t i o n , c u r r e n t l y ) * /

s t a t i c i n t I n t W o r l d V i e w X f o r m [ 3 ] [ 4 1 - ( t 1 , O . O . O ) . to.1.0.01. t 0 . 0 . 1 . 0 ~ 1 :

v o i d I n i t i a l i z e F i x e d P o i n t O I

i n t i. j :

f o r ( i - 0 : i < 3 : i++) f o r ( j - 0 : j < 4 : j++)

W o r l d V i e w X f o r m [ i l [ j l - INT~TO_FIXEO(IntWorldViewXform~il[jl): f o r ( i - 0 : i<NUM-CUBE-VERTS: i++) I

CubeVer ts [ i ] .X - INT-TO-FIXED(IntCubeVertsCi1.X); CubeVer ts [ i ] .Y - INT_TO_FIXED(IntCubeVerts[il.Y): C u b e V e r t s C i l . 2 - INT-TO-FIXED(IntCubeVerts[il.Z):

1 3

LISTING 52.6 152-6.C /* Rotates and moves a p o l y g o n - b a s e d o b j e c t a r o u n d t h e t h r e e a x e s .

Movement i s i m p l e m e n t e d o n l y a l o n g t h e 2 a x i s c u r r e n t l y . * /

#i ncl ude "po lygon. h "

vo id Rota teAndMovePObjec t (P0b jec t * ObjectToMove) (

i f (--0bjectToMove->RDelayCount - 0 ) ( /* r o t a t e * / ObjectToMove->RDelayCount - ObjectToMove->RDelayCountBase: i f (ObjectToMove->Rotate.RotateX !- 0.0)

AppendRotationX(0bjectToMove->XformToWorld, Objec tToMove->Ro ta te .Ro ta teX) :

AppendRotat ionY(0bjectToMove->XformToWorld , Objec tToMove->Ro ta te .Ro ta teY) :

AppendRotationZ(0bjectToMove->XformToWorld, Objec tToMove->Ro ta te .Ro ta teZ) :

i f (ObjectToMove->Rotate.RotateY !- 0.0)

i f (Ob jec tToMove->Ro ta te .Ro ta teZ !- 0.0)

ObjectToMove->RecalcXform - 1:

Fast 3-D Animation: Meet X-Sharp 977

Page 9: FAST 3-D ANIMATION: MEET X-SHARP - GameDev.netdownloads.gamedev.net/pdf/gpbb/gpbb52.pdf · 2019. 10. 24. · LISTING 52.1 152- 1 .C /* 3-0 animation program to rotate 12 cubes.Uses

I* Move i n Z, c h e c k i n g f o r b o u n c i n g a n d s t o p p i n g *I i f ( - -0b jectToMove->MDelayCount - 0 ) {

ObjectToMove->MDelayCount - ObjectToMove->MDelayCountBase; ObjectToMove->XformToWorld[21[31 +- ObjectToMove->Move.MoveZ; i f ~ObjectToMove->XformToWorldC21C33>0bjectToMove->Move.MaxZ)

ObjectToMove->Move.MoveZ - 0; I* s t o p i f c lose enough * I ObjectToMove->RecalcXform - 1:

1 1

LISTING 52.7 152-7.C I* Draws a l l v i s i b l e f a c e s i n s p e c i f i e d p o l y g o n - b a s e d o b j e c t . O b j e c t m u s t h a v e

p r e v i o u s l y b e e n t r a n s f o r m e d a n d p r o j e c t e d , s o t h a t S c r e e n V e r t e x L i s t a r r a y i s f i l l e d i n . *I

# inc l ude "po l ygon . h "

v o i d D r a w P O b j e c t ( P 0 b j e c t * Objec tToXform)

i n t i. j . NumFaces - ObjectToXform->NumFaces. NumVer t ices ; i n t * VertNumsPtr; Face * FacePt r - Ob jec tToXfo rm->FaceL is t : P o i n t * S c r e e n p o i n t s - Ob jec tToXfo rm->ScreenVer texL is t ; l o n g v l , v 2 , w l . w2; P o i n t VerticesCMAX-POLY-LENGTH]; P o i n t L i s t H e a d e r P o l y g o n ;

I* Draw each v i s i b l e f a c e ( p o l y g o n ) o f t h e o b j e c t i n t u r n *I fo r ( i -0 ; i<NumFaces; i++. FacePtr++) {

NumVer t i ces - FacePtr->NumVerts; / * C o p y o v e r t h e f a c e ' s v e r t i c e s f r o m t h e v e r t e x l i s t *I f o r ( j - 0 , Ver tNumsPt r -FacePt r ->Ver tNums; j<NumVer t i ces ; j++)

/* Draw o n l y i f o u t s i d e f a c e s h o w i n g ( i f t h e n o r m a l t o t h e

v l - V e r t i c e s C 1 l . X - Vert icesCO1.X: w l - Ver t i cesCNumVer t i ces -1 l .X - Vert icesCO1.X: v2 - Vert icesC11.Y - Vert icesCO1.Y: w2 - VerticesCNumVertices-l1.Y - Vert icesCO1.Y; i f ( ( v l * w 2 - v2*wl ) > 0 ) (

V e r t i c e s C j l - ScreenPointsC*Ver tNumsPtr++l ;

p o l y g o n p o i n t s t o w a r d v i e w e r ; t h a t i s . h a s a p o s i t i v e Z component) *I

I* It i s f a c i n g t h e s c r e e n , so draw *I I* A p p r o p r i a t e l y a d j u s t t h e e x t e n t o f t h e r e c t a n g l e u s e d t o

e r a s e t h i s o b j e c t l a t e r * / f o r ( j - 0 ; j < N u m V e r t i c e s ; j++) {

i f ( V e r t i c e s C j 1 . X > ObjectToXform->EraseRectCNonDisplayedPagel .Right~

ObjectToXform->EraseRect [NonDisp layedPagel .Right - e l s e ObjectToXform->EraseRect [NonDisp layedPagel .Right =

i f ( V e r t i c e s C j 1 . X < SCREEN-WIDTH)

V e r t i c e s C j 1 . X ;

SCREEN-WIDTH; i f ( V e r t i c e s C j 1 . Y >

Db jec tToXfo rm->EraseRec t [NonD isp layedPage l .Bo t tom~

ObjectToXform->EraseRect [NonDisp layedPagel .Bot tom - i f ( V e r t i c e s C j 1 . Y < SCREEN-HEIGHT)

V e r t i c e s C j 1 . Y ; e l s e ObjectToXform->EraseRect [NonDisp layedPagel .Bot tom-

SCREEN-HEIGHT; i f ( V e r t i c e s C j 1 . X <

ObjectToXform->EraseRect[NonDisplayedPagel.Left)

978 Chapter 52

Page 10: FAST 3-D ANIMATION: MEET X-SHARP - GameDev.netdownloads.gamedev.net/pdf/gpbb/gpbb52.pdf · 2019. 10. 24. · LISTING 52.1 152- 1 .C /* 3-0 animation program to rotate 12 cubes.Uses

i f ( V e r t i c e s C j 1 . X > 0 ) Ob jec tToXfo rm->EraseRec t [NonD isp layedPage l .Le f t -

e l s e O b j e c t T o X f o r m - > E r a s e R e c t [ N o n D i sp l ayedPage1. Lef t -0 : V e r t i c e s C j 1 . X ;

i f ( V e r t i c e s r j 1 . Y < Ob jec tToXform->EraseRect [NonDisp layedPage l .Top)

Ob jec tToXform->EraseRectCNonDisp layedPage l .Top - e l s e Objec tToXform->EraseRect [NonDisp layedPage l .Top-O:

i f ( V e r t i c e s C j 1 . Y > 0 )

V e r t i c e s C j 1 . Y :

> / * Draw t h e p o l y g o n * / DRAW-POLYGON(Vertices. NumVer t i ces . FacePt r ->Co lo r . 0. 0 ) :

I

LISTING 52.8 152-8.C /* I n i t i a l i z e s t h e cubes and adds them t o t h e o b j e c t l i s t . * /

#i n c l u d e < s t d l i b. h> #i ncl ude <math. h> ti ncl ude "po lygon. h"

# d e f i n e ROT-6 ("PI / 30 .0) / * r o t a t e 6 d e g r e e s a t a t i m e */ # d e f i n e ROT-3 ("PI / 60.0) /* r o t a t e 3 d e g r e e s a t a t i m e */ # d e f i n e ROT-2 ("PI / 90.0) / * r o t a t e 2 d e g r e e s a t a t i m e */ # d e f i n e NUM-CUBES 12 / * d o f cubes * /

P o i n t 3 CubeVertsCNUM-CUBE-VERTSI: /* s e t e l s e w h e r e , f r o m f l o a t s * / / * v e r t e x i n d i c e s f o r i n d i v i d u a l c u b e f a c e s */ s t a t i c s t a t i c s t a t i c s t a t i c s t a t i c s t a t i c s t a t i c s t a t i c

n t F a c e l [ ] = (1.3.2.0}: n t FaceZCl - [5.7.3.11; n t Face3C1 - 14.5.1.01: n t Face4[] - (3.7.6.21: n t Face5C1 - (5.4.6.71; n t Face6CI = I0 .2 .6 .41 : n t *Ver tNumList [ ] - [Facel , FaceZ, Face3. Face4. Face5. Face61: n t V e r t s I n F a c e [ ] - { sizeof(Facel)/sizeof(int).

i i i i i i i i

s i z e o f ( F a c e 2 ) / s i z e o f ( i n t ) . sizeof(Face3)/sizeof(int), s i z e o f ( F a c e 4 ) / s i z e o f ( i n t ) . s i z e o f ( F a c e 5 ) / s i z e o f ( i n t ) . s i z e o f ( F a c e 6 ) / s i z e o f ( i n t ) I :

/* X . Y . 2 r o t a t i o n s f o r cubes * I s t a t i c R o t a t e c o n t r o l InitialRotateCNUM-CUBES] = I

{O.O.ROT_6.ROT-6), ~ROT~3,0.O,ROT~3II [ROT_3.ROT_3.0.0}, (ROT-3, -ROT-3,0.01 .I-ROT_3.ROT-2,0.01, (-ROTL6.-ROT-3.0.01, ~ R O T ~ 3 . 0 . 0 . - R O T ~ 6 ~ . ~ - R O T _ 2 . 0 . O . 0 ~ R 0 T ~ 3 J , ~ - R 0 T ~ 3 , 0 . 0 , - R 0 T ~ 3 1 , [ O . O . R O T _ 2 . - R O T ~ 2 ~ . ( O . O , - R O T _ 3 . R O T ~ 3 } , ~ O . O , - R O T ~ 6 , - R O T ~ 6 ~ , } :

s ta t ic MoveContro l In i t ia lMove[NUM-CUBES] - I [0,0.80.0.0.0,0,0,-350J,[0,0,80,0,0,0,0,0,-350J, ~0 .0 .B0 .0 .0 .0 ,0 .0 . -3501 ,~0 ,0 ,80 ,0 ,0 ,0 ,0 ,0 , -3501 , I0.0.80.0.0.0.0.0.-3501~~0,0~80.0.0.0.0.0,-3501, ~0.0.80.0.0,0.0.0.-350~,(0,0,80,0,0,0,0,0,-350), ~0,0.80.0.0.0.0.0,-3501,~0,0.80,0,0.0.0.0;3501, ~0,0,80,0.0,0,0.0.-350~,~0,0,80.0.0.0.0.0,-3501, I :

/ * f a c e c o l o r s f o r v a r i o u s c u b e s * / s t a t i c i n t Colors[NUM-CUBES][NUM_CVBE-FACESI - I

~15.14.12.11.10.9~.I1,2,3,4,5,61,~35.37,39,41,43,45~, (47.49,51.53.55.571.(59.61.63.65.67.691,(71,73,75,77,79,811, I83,85.87.89.91,93~.~95.97.99,101,103.105J,

Fast 3-D Animation: Meet X-Sharp 979

Page 11: FAST 3-D ANIMATION: MEET X-SHARP - GameDev.netdownloads.gamedev.net/pdf/gpbb/gpbb52.pdf · 2019. 10. 24. · LISTING 52.1 152- 1 .C /* 3-0 animation program to rotate 12 cubes.Uses

(107.109,111.113.115~1171,~119,121,123,125,127,1291, {131,133,135.137,139,1411,~143.145.147,149,151~1531 I ;

/* s t a r t i n g c o o r d i n a t e s for cubes i n w o r l d s p a c e */ s t a t i c i n t CubeStartCoords[NUM-CUBESIC31 - I

[ 100 .0 . -60001 . I 100 .70 .~60001 . I100 , -70 . -60001 , (33.0. -6000] . 133.70, -60001, I33. -70. -60001. I -33 .0 . -60001 . I -33 ,70 . -60001 , ~-33.-70.-60001.~-100.0.-6000~, ( -100.70. -6000) , I -100 . -70 . -60003) :

/ * d e l a y c o u n t s ( s p e e d c o n t r o l ) f o r c u b e s */ s t a t i c i n t InitRDelayCountsCNUM_CVBESI - (1.2.1,2.1.1.1.1.1.2.1.1): s t a t i c i n t BaseRDelayCountsCNUM_CUBESI - (1,2,1,2,2,1,1,1,2,2,2,11; s t a t i c i n t InitMDelayCountsCNUM_CUBESl - {1,1,1,1,1,1,1,1,1,1,1,11; s t a t i c i n t BaseMDelayCountsCNUM~CUBESl - ~1.1.1.1.1.1.1.1,1.1,1,11;

v o i d I n i t i a l i z e C u b e s O I

i n t i. j , k ; PObject *Workingcube:

f o r ( i - 0 : i<NUM-CUBES; i++) ( i f ( (Work ingcube - malloc(sizeof(P0bject))) - NULL) I

p r i n t f ( " C o u 1 d n ' t g e t m e m o r y \ n " ) : e x i t ( 1 ) ; I Workingcube->DrawFunc - DrawPObject: Work ingcube->RecalcFunc = X fo rmAndPro jec tPOb jec t : Workingcube->MoveFunc - RotateAndMovePObject ; Workingcube->RecalcXform - 1: f o r (k-0: k<2: k++) {

Workingcube->EraseRect[kl.Left - Workingcube->EraseRect [k l .Right - 0; Workingcube->EraseRect[kl.Bottom - 0:

Workingcube->EraseRect[kl.Top - Ox7FFF;

I Workingcube->RDelayCount - I n i t R D e l a y C o u n t s C i l : Workingcube->RDelayCountBase - BaseRDelayCountsCi l ; Workingcube->MDelayCount - I n i t M D e l a y C o u n t s C i l : Workingcube->MDelayCountBase - BaseMDelayCounts[ i l ; / * S e t t h e o b j e c t - > w o r l d x f o r m t o n o n e * / f o r ( j - 0 ; j < 3 ; j++)

f o r ( k - 0 ; k < 4 ; k++) Workingcube->XformToWorld[jl[kl - INT-TOpFIXED(0);

Workingcube->XformToWorld[Ol[Ol - Workingcube->XformToWorld[llCll - WorkingCube->XformToWorldC23C21 - WorkingCube->XformToWorld[31[3] - INT-TO_FIXED(l):

/ * S e t t h e i n i t i a l l o c a t i o n * / f o r ( j - 0 ; j < 3 ; j++) WorkingCube->XformToWorldCjl[31 - Workingcube->NumVerts - NUM-CUBE-VERTS: W o r k i n g c u b e - > V e r t e x L i s t - CubeVerts : Workingcube->NumFaces - NUM-CUBELFACES: Work ingcube->Rotate - I n i t i a l R o t a t e C i l : Workingcube->Move.MoveX - INT-TO~FIXED(InitialMove[i].MoveX): Workingcube->Move.MoveY - I N T ~ T O ~ F I X E D ( I n i t i a l M o v e C i l . M o v e Y ) ; Workingcube->Move.MoveZ - INT~TO~FIXEO(InitialMove[il.MoveZ); Workingcube->Move.MinX - INT~TO~FIXEO(InitialMove~il.MinX): Workingcube->Move.MinY - INT_TO-FIXED(InitialMoveCil.MinY); Workingcube->Move.MinZ - INT-TO-FIXED(InitialMoveCil.MinZ); Workingcube->Move.MaxX - INT-TO-FIXED(InitialMove[il.MaxX); Workingcube->Move.MaxY - INT-TO-FIXED(InitialMove[il.MaxY); Workingcube->Move.MaxZ - INT_TO-FIXED(InitialMove[i].MaxZ);

I N T ~ T O ~ F I X E D ( C u b e S t a r t C o o r d s C i 1 C j l ) :

980 Chapter 52

Page 12: FAST 3-D ANIMATION: MEET X-SHARP - GameDev.netdownloads.gamedev.net/pdf/gpbb/gpbb52.pdf · 2019. 10. 24. · LISTING 52.1 152- 1 .C /* 3-0 animation program to rotate 12 cubes.Uses

i f ( (Workingcube->XformedVertexList - malloc(NUM-CUBE-VERTS*sizeof(Point3))) - NULL) {

p r i n t f ( " C o u 1 d n ' t g e t m e m o r y \ n " ) ; e x i t ( 1 ) ; ) i f ( ( W o r k i n g c u b e - > P r o j e c t e d V e r t e x L i s t -

malloc(NUM-CUBE-VERTS*sizeof(Point3))) - NULL) { p r i n t f ( " C o u 1 d n ' t g e t m e m o r y \ n " ) ; e x i t ( 1 ) ; 1

i f ( (Work ingcube->ScreenVer texL is t - malloc(NUM_CUBE-VERTS*sizeof(Point))) - NULL) {

p r i n t f ( " C o u 1 d n ' t g e t m e m o r y \ n " ) ; e x i t ( 1 ) ; i f ( ( W o r k i n g c u b e - > F a c e L i s t -

malloc(NUM-CUBE_FACES*sizeof(Face))) - NULL) { p r i n t f ( " C o u 1 d n ' t g e t m e m o r y \ n " ) ; e x i t ( 1 ) ; 1

/* I n i t i a l i z e t h e f a c e s */ f o r ( j - 0 ; j<NUM-CUBE-FACES; j++) {

Work ingcube->FaceLis t [ j l .Ver tNums - V e r t N u m L i s t C j l ; Work ingcube->FaceLis tCj l .NumVerts - V e r t s I n F a c e C j l :

1 WorkingCube->FaceList[jl.Color - C o l o r s C i l [ j ] ;

ObjectListCNumObjects++l - (Object * )Work ingCube; 1

1

LISTING 52.9 152-9.ASM ; 3 8 6 - s p e c i f i c f i x e d p o i n t m u l t i p l y a n d d i v i d e .

; C n e a r - c a l l a b l e a s : F i x e d p o i n t F i x e d M u l ( F i x e d p 0 i n t M 1 . F i x e d p o i n t M 2 ) ; F i x e d p o i n t F i x e d D i v ( F i x e d p o i n t D i v i d e n d , F i x e d p o i n t D i v i s o r ) ;

; T e s t e d w i t h TASM

.model smal l

.386

.code pub1 i c -FixedMul .-Fi xedDi v

; M u l t i D l i e s t w o f i x e d - p o i n t v a l u e s t o g e t h e r . FMparms s t r u c

dw M 1 dd M2 dd FMparms ends

- FixedMul a1 i g n

push mov mov i mu1 add adc s h r POP r e t

-Fi xedMul

2 d u p ( ? ) ; r e t u r n a d d r e s s & pushed BP ? ?

2

bP p r o c n e a r

b p . w eax.[bp+M11 dword p t r Cbp+M2] ; m u l t i p l y eax , 8000h ; round by add ing 2^ ( -16) edx, 0 ; w h o l e p a r t o f r e s u l t i s i n OX e a x . 1 6 ; p u t t h e f r a c t i o n a l p a r t i n AX bP

endp ; D i v i d e s o n e f i x e d - p o i n t v a l u e b y a n o t h e r . FDparms s t r u c

D i v i d e n d d d ? D i v i s o r d d ? FDparms ends

a l i g n 2

dw 2 d u p ( ? ) ; r e t u r n a d d r e s s & pushed BP

Fast 3-D Animation: Meet X-Sharp 98 1

Page 13: FAST 3-D ANIMATION: MEET X-SHARP - GameDev.netdownloads.gamedev.net/pdf/gpbb/gpbb52.pdf · 2019. 10. 24. · LISTING 52.1 152- 1 .C /* 3-0 animation program to rotate 12 cubes.Uses

- F i xedDi v

F D P l :

FDPL:

FDP3:

push mov sub mov and j n s i nc

sub

r o l

mov sub mov and j n s dec neg d i v s h r adc dec CmP adc

and j z neg mov

s h r POP r e t

neg

- Fi xedDi v end

p r o c n e a r bp bp. SP c x , c x ;assume p o s i t i v e r e s u l t eax.Cbp+Div idendl e a x , e a x ; p o s i t i v e d i v i d e n d ? FDPl ;yes cx :mark i t ' s a n e g a t i v e d i v i d e n d eax ;make t h e d i v i d e n d p o s i t i v e edx, edx ;make it a 6 4 - b i t d i v i d e n d , t h e n s h i f t

: l e f t 16 b i t s so t h a t r e s u l t will be i n EAX e a x , 1 6 : p u t f r a c t i o n a l p a r t o f d i v i d e n d i n

: h i g h w o r d o f EAX d x , a x : p u t w h o l e p a r t o f d i v i d e n d i n DX a x . a x : c l e a r l o w w o r d o f EAX e b x . d w o r d p t r [ b p + D i v i s o r l ebx.ebx FDPZ

: p o s i t i v e d i v i s o r ? :yes

cx :mark i t ' s a n e g a t i v e d i v i s o r ebx :make d i v i s o r p o s i t i v e e b x ; d i v i d e e b x . 1 ; d i v i s o r / 2 . m i n u s 1 i f t h e d i v i s o r i s ebx.O : even ebx ebx , edx ; se t Car ry i f remainder i s a t l e a s t eax, 0 ; h a l f as l a r g e as t h e d i v i s o r , t h e n

: u s e t h a t t o r o u n d u p i f necessa ry ; s h o u l d t h e r e s u l t be made n e g a t i v e ? ;no

c x , c x FDP3 eax ;yes. negate i t edx , e a x ; r e t u r n r e s u l t i n D X : A X ; f r a c t i o n a l

e d x , 1 6 : w h o l e p a r t o f r e s u l t i n DX : p a r t i s a l r e a d y i n AX

bp

endp

LISTING 52.10 POLYG0N.H / * POLYG0N.H: Header f i l e f o r p o l y g o n - f i l l i n g c o d e , a l s o i n c l u d e s

a number o f u s e f u l i t e m s f o r 3-D a n i m a t i o n . * I

# d e f i n e MAX-OBJECTS 100 / * max s imu l taneous # o b j e c t s s u p p o r t e d */ # d e f i n e MAX-POLY-LENGTH 4 I* f o u r v e r t i c e s i s t h e max p e r p o l y * / # d e f i n e SCREEN-WIDTH 320 # d e f i n e SCREEN-HEIGHT 240 # d e f i n e PAGEO-START-OFFSET 0 # d e f i n e PAGE1-START-OFFSET (((long)SCREENLHEIGHT*SCREEN_WIDTH)/4) # d e f i n e NUM-CUBE-VERTS 8 / * # o f v e r t i c e s p e r c u b e */ # d e f i n e NUM-CUBE-FACES 6 I* # o f f a c e s p e r c u b e */ /* R a t i o : d i s t a n c e f r o m v i e w p o i n t t o p r o j e c t i o n p l a n e / w i d t h o f

p r o j e c t i o n p l a n e . D e f i n e s t h e w i d t h o f t h e f i e l d o f v i e w . Lower a b s o l u t e v a l u e s - w i d e r f i e l d s o f v i e w : h i g h e r v a l u e s - nar rower * /

# d e f i n e PROJECTION-RATIO -2 .0 / * n e g a t i v e b e c a u s e v i s i b l e 2

/ * Draws t h e p o l y g o n d e s c r i b e d b y t h e p o i n t l i s t P o i n t L i s t i n c o l o r C o l o r w i t h a l l v e r t i c e s o f f s e t by ( X . Y ) * I

# d e f i n e DRAW-POLYGON(PointList.NumPoints.Co1or.X.Y) \ Polygon.Length - NumPo in ts : Po lygon .Po in tP t r - P o i n t L i s t ; \ FillConvexPolygon(&Polygon. C o l o r , X. Y ) ;

c o o r d i n a t e s a r e n e g a t i v e * /

982 Chapter 52

Page 14: FAST 3-D ANIMATION: MEET X-SHARP - GameDev.netdownloads.gamedev.net/pdf/gpbb/gpbb52.pdf · 2019. 10. 24. · LISTING 52.1 152- 1 .C /* 3-0 animation program to rotate 12 cubes.Uses

# d e f i n e INT-TO-FIXED(x) ( ( ( l o n g ) ( i n t ) x ) << 1 6 ) # d e f i n e DOUBLE-TO-FIXED(x) ( ( l o n g ) ( x * 65536.0 + 0.5))

t y p e d e f 1 o n g F i x e d p o i n t : typede f F i xedpo in t X fo rmC31 [41 : I* D e s c r i b e s a s i n g l e 2D p o i n t *I t y p e d e f s t r u c t { i n t X : i n t Y ; 1 P o i n t : I* D e s c r i b e s a s i n g l e 3D p o i n t i n homogeneous c o o r d i n a t e s : t h e W

t y p e d e f s t r u c t I F i x e d p o i n t X . Y . Z; I P o i n t 3 : t y p e d e f s t r u c t { i n t X : i n t Y : i n t Z: I I n t P o i n t 3 : I* D e s c r i b e s a s e r i e s o f p o i n t s ( u s e d t o s t o r e a l i s t o f v e r t i c e s t h a t

d e s c r i b e a p o l y g o n : e a c h v e r t e x i s assumed t o c o n n e c t t o t h e t w o a d j a c e n t v e r t i c e s : l a s t v e r t e x i s assumed t o c o n n e c t t o f i r s t ) *I

c o o r d i n a t e i s n ' t p r e s e n t , t h o u g h : assumed t o be 1 a n d i m p l i e d *I

t y p e d e f s t r u c t { i n t L e n g t h : P o i n t * P o i n t P t r : > P o i n t L i s t H e a d e r ; / * D e s c r i b e s t h e b e g i n n i n g a n d e n d i n g X c o o r d i n a t e s o f a s i n g l e

t y p e d e f s t r u c t { i n t X S t a r t ; i n t XEnd: I HLine: I* D e s c r i b e s a L e n g t h - l o n g s e r i e s o f h o r i z o n t a l l i n e s , a l l assumed t o

h o r i z o n t a l l i n e *I

be on c o n t i g u o u s s c a n l i n e s s t a r t i n g a t Y S t a r t a n d p r o c e e d i n g downward (used t o d e s c r i b e a s c a n - c o n v e r t e d p o l y g o n t o t h e l o w - l e v e l h a r d w a r e - d e p e n d e n t d r a w i n g c o d e ) . * /

t y p e d e f s t r u c t { i n t L e n g t h : i n t Y S t a r t : H L i n e * H L i n e P t r : } H L i n e L i s t : t y p e d e f s t r u c t { i n t L e f t , T o p , R i g h t , B o t t o m : > Rec t ; I* s t r u c t u r e d e s c r i b i n g o n e f a c e o f an o b j e c t ( o n e p o l y g o n ) * / t y p e d e f s t r u c t { i n t * VertNums: i n t NumVerts; i n t C o l o r : } Face: t y p e d e f s t r u c t I doub le Ro ta teX . Ro ta teY . Ro ta teZ : 1 R o t a t e C o n t r o l ; t y p e d e f s t r u c t { F i x e d p o i n t MoveX, MoveY. MoveZ. Minx, MinY. MinZ.

MaxX. MaxY. MaxZ; I MoveCont ro l : I* f i e l d s common t o e v e r y o b j e c t * / # d e f i n e BASE-OBJECT \

v o i d ( * D r a w F u n c ) O : / * d raws ob jec t *I \ v o i d ( * R e c a l c F u n c ) ( ) : I* p r e p a r e s o b j e c t f o r d r a w i n g * / \ vo id ( *MoveFunc )O: I* moves o b j e c t *I \ i n t Reca lcXform; I* 1 t o i n d i c a t e need t o r e c a l c *I \ Rect EraseRectC21: I* r e c t a n g l e t o e r a s e i n e a c h p a g e * /

I* b a s i c o b j e c t *I t y p e d e f s t r u c t { BASELOBJECT 1 O b j e c t : I* s t r u c t u r e d e s c r i b i n g a p o l y g o n - b a s e d o b j e c t *I t y p e d e f s t r u c t I

BASE-OBJECT i n t RDelayCount. RDelayCountBase: I* c o n t r o l s r o t a t i o n s p e e d * / i n t MDelayCount, MDelayCountBase: I* c o n t r o l s movement speed * I Xform XformToWorld; / * t r a n s f o r m f r o m o b j e c t - > w o r l d s p a c e * / Xform XformToView; / * t r a n s f o r m f r o m o b j e c t - > v i e w s p a c e *I R o t a t e C o n t r o l R o t a t e : I* c o n t r o l s r o t a t i o n c h a n g e o v e r t i m e * I MoveControl Move: I* c o n t r o l s o b j e c t movement over t ime * I i n t NumVerts; / * # v e r t i c e s i n V e r t e x L i s t * I P o i n t 3 * V e r t e x L i s t : I* u n t r a n s f o r m e d v e r t i c e s * I P o i n t 3 * X f o r m e d V e r t e x L i s t ; / * t r a n s f o r m e d i n t o v i e w s p a c e *I P o i n t 3 * P r o j e c t e d V e r t e x L i s t : I* p r o j e c t e d i n t o s c r e e n s p a c e */ P o i n t * S c r e e n V e r t e x L i s t : I* c o n v e r t e d t o s c r e e n c o o r d i n a t e s *I i n t NumFaces : I* # o f f a c e s i n o b j e c t * / Face * F a c e L i s t ; /* p o i n t e r t o f a c e i n f o *I

I PObjec t :

e x t e r n v o i d X f o r m V e c ( X f o r m . F i x e d p o i n t *, F i x e d p o i n t * ) ; ex te rn vo id Conca tX fo rms(X fo rm. X fo rm, X fo rm) : e x t e r n i n t FillConvexPolygon(PointListHeader *, i n t . i n t . i n t ) : e x t e r n v o i d S e t 3 2 0 ~ 2 4 0 M o d e ( v o i d ) :

Fast 3-D Animation: Meet X-Sharp 983

Page 15: FAST 3-D ANIMATION: MEET X-SHARP - GameDev.netdownloads.gamedev.net/pdf/gpbb/gpbb52.pdf · 2019. 10. 24. · LISTING 52.1 152- 1 .C /* 3-0 animation program to rotate 12 cubes.Uses

e x t e r n v o i d S h o w P a g e ( u n s i g n e d i n t ) : e x t e r n v o i d F i l l R e c t a n g l e X ( i n t . i n t . i n t . i n t . u n s i g n e d i n t . i n t ) ; e x t e r n v o i d XformAndProjectPObject (P0bject * ) ; e x t e r n v o i d D r a w P O b j e c t ( P 0 b j e c t *) ; extern vo id AppendRota t ionX(Xform. double ) : ex tern vo id AppendRota t ionY(Xform. double ) ; ex tern vo id AppendRota t ionZ(Xform. double ) : e x t e r n n e a r F i x e d p o i n t F i x e d M u l ( F i x e d p o i n t . F i x e d p o i n t ) ; e x t e r n n e a r F i x e d p o i n t F i x e d D i v ( F i x e d p 0 i n t . F i x e d p o i n t ) ; e x t e r n v o i d InitializeFixedPoint(void); e x t e r n v o i d RotateAndMovePObject (P0bject * ) ; e x t e r n v o i d I n i t i a l i z e C u b e s ( v o i d ) ; e x t e r n i n t D i s p l a y e d P a g e , NonDi spl ayedPage. Recal cAl1 Xforms ; e x t e r n i n t N u m O b j e c t s ; extern Xform WorldViewXform; e x t e r n O b j e c t * O b j e c t L i s t [ l ; e x t e r n P o i n t 3 C u b e V e r t s C ] ;

A New Animation Framework: X-Sharp Listings 52.1 through 52.10 shown earlier represent not merely faster animation in library form, but also a nearly complete, extensible, datadriven animation frame- work. Whereas much of the earlier animation code I’ve presented in this book was hardwired to demonstrate certain concepts, this chapter’s code is intended to serve as the basis for a solid animation package. Objects are stored, in their entirety, in customizable structures; new structures can be devised for new sorts of objects. Draw- ing, preparing for drawing, and moving are all vectored functions, so that variations such as shading or texturing, or even radically different sorts of graphics objects, such as scaled bitmaps, could be supported. The cube initialization is entirely data driven; more or different cubes, or other sorts of convex polyhedrons, could be added by simply changing the initialization data in Listing 52.8. Somewhere along the way in writing the material that became this section of the book, I realized that I had a generally useful animation package by the tail and gave it a name: X-Sharp. (Xfor Mode X, sharp because good animation looks sharp, and, well, who would want a flat animation package?) Note that the X-Sharp library as presented in this chapter (and, indeed, in this book) is not a fully complete 3-D library. Movement is supported only along the Z axis in this chapter’s version, and then in a non-general fashion. More interesting move- ment isn’t supported at this point because of one of the two missing features in X-Sharp: hidden-surface removal. (The other missing feature is general 3-D clip ping.) Without hidden surface removal, nothing can safely overlap. It would actually be easy enough to perform hidden-surface removal by keeping the cubes in differ- ent Z bands and drawing them back to front, but this gets into sorting and list issues, and is not a complete solution-and I’ve crammed as much as will fit into one chapter’s code, anyway. I’m working toward a goal in this last section of the book, and there are many lessons to be learned and stories to be told along the way. So as X-Sharp grows, you’ll find its

984 Chapter 52

Page 16: FAST 3-D ANIMATION: MEET X-SHARP - GameDev.netdownloads.gamedev.net/pdf/gpbb/gpbb52.pdf · 2019. 10. 24. · LISTING 52.1 152- 1 .C /* 3-0 animation program to rotate 12 cubes.Uses

evolving implementations in the chapter subdirectories on the listings diskette. This chapter’s subdirectory, for example, contains the self-extracting archive file XSHARP14.EXE, (to extract its contents you simply run it as though it were a pro- gram) and the code in that archive is the code I’m speaking of specifically in this chapter, with all the limitations mentioned above. Chapter 53’s subdirectory, how- ever, contains the file XSHARP15.EXE, which is the next step in the evolution of X-Sharp, and it is the version that I’ll be specifically talking about in that chapter. Later chapters will have their own implementations in their respective chapter subdirectories, in files of the form XSHARPxx.EXE, where xx is an ascending num- ber indicating the version. The final and most recent X-Sharp version will be present in its own subdirectory called XSHARP22. If you’re intending to use X-Sharp in a real project, use the most recent version to be sure that you avail yourself of all new features and bug fixes.

Three Keys to Realtime Animation Performance As of the previous chapter, we were at the point where we could rotate, move, and draw a solid cube in real time. Not too shabby. ..but the code I’m presenting in this chapter goes a bit further, rotating 12 solid cubes at an update rate of about 15 frames per second (fps) on a 20 MHz 386 with a slow VGA. That’s 12 transformation matrices, 72 polygons, and 96 vertices being handled in real time; not Star Wars, granted, but a giant step beyond a single cube. Run the program if you get a chance; you may be surprised at just how effective this level of animation is. I’d like to point out, in case anyone missed it, that this is fully general 3-D. I’m not using any shortcuts or tricks, like prestoring coordinates or pregenerating bitmaps; if you were to feed in different rotations or vertices, the animation would change accordingly. The keys to the performance increase manifested in this chapter’s code are three. The first key is fixed-point arithmetic. In the previous two chapters, we worked with floating-point coordinates and transformation matrices. Those values are now stored as 32-bit fixed-point numbers, in the form 16.16 (16 bits of whole number, 16 bits of fraction). 32-bit fxed-point numbers allow sufficient precision for 3-D animation, but can be manipulated with fast integer operations, rather than by slow floating-point processor operations or excruciatingly slow floating-point emulator operations. Although the speed advantage of fixed-point varies depending on the operation, on the pro- cessor, and on whether or not a coprocessor is present, fixed-point multiplication can be as much as 100 times faster than the emulated floating-point equivalent. (I’d like to take a moment to thank Chris Hecker for his invaluable input in this area.) The second performance key is the use of the 386’s native 32-bit multiply and divide instructions. C compilers operating in real mode call library routines to perform multi- plications and divisions involving 32-bit values, and those library functions are fairly slow, especially for division. On a 386,32-bit multiplication and division can be handled with the bit of code in Listing 52.9-and most of even that code is only for rounding.

Fast 3-D Animation: Meet X-Sharp 985

Page 17: FAST 3-D ANIMATION: MEET X-SHARP - GameDev.netdownloads.gamedev.net/pdf/gpbb/gpbb52.pdf · 2019. 10. 24. · LISTING 52.1 152- 1 .C /* 3-0 animation program to rotate 12 cubes.Uses

The third performance key is maintaining and operating on only the relevant por- tions of transformation matrices and coordinates. The bottom row of every transformation matrix we’ll use (in this book) is [0 0 0 11, so why bother using or recalculating it when concatenating transforms and transforming points? Likewise for the fourth element of a 3-D vector in homogeneous coordinates, which is always 1. Basically, transformation matrices are treated as consisting of a 3x3 rotation ma- trix and a 3x1 translation vector, and coordinates are treated as 3x1 vectors. This saves a great many multiplications in the course of transforming each point. Just for fun, I reimplemented the animation of Listings 52.1 through 52.10 with floating-point instructions. Together, the preceeding optimizations improve the per- formance of the entire animation-including drawing time and overhead, and not just math-by more than ten times over the code that uses the floating-point emula- tor. Amazing what one can accomplish with a few dozen lines of assembly and a switch in number format, isn’t it? Note that no assembly code other than the native 386 multiply and divide is used in Listings 52.1 through 52.10, although the polygon fill code is of course mostly in assembly; we’ve achieved 12 cubes animated at 15 fps while doing the 3-D work almost entirely in Borland C++, and we’re still doing sine and cosine via the floating-point emulator. Happily, we’re still nowhere near the upper limit on the animation potential of the PC.

Drawbacks The techniques we’ve used to turbocharge 3-D animation are very powerful, but there’s a dark side to them as well. Obviously, native 386 instructions won’t work on 8088 and 286 machines. That’s rectifiable; equivalent multiplication and division routines could be implemented for real mode and performance would still be rea- sonable. It sure is nice to be able to plug in a 32-bit IMUL or DIV and be done with it, though. More importantly, 32-bit fixed-point arithmetic has limitations in range and accuracy. Points outside a 64Kx64Kx64K space can’t be handled, imprecision tends to creep in over the course of multiple matrix concatenations, and it’s quite possible to generate the dreaded divide by 0 interrupt if Z coordinates with absolute values less than one are used. I don’t have space to discuss these issues in detail, but here are some brief thoughts: The working 64Kx64Kx64Kfixed-point space can be paged into a larger virtual space. Imprecision of a pixel or two rarely matters in terms of display quality, and deteriora- tion of concatenated rotations can be corrected by restoring orthogonality, for example by periodically calculating one row of the matrix as the cross-product of the other two (forcing it to be perpendicular to both). Alternatively, transformations can be calculated from scratch each time an object or the viewer moves, so there’s no chance for cumulative error. 3-D clipping with a front clip plane of -1 or less can prevent divide overflow.

986 Chapter 52

Page 18: FAST 3-D ANIMATION: MEET X-SHARP - GameDev.netdownloads.gamedev.net/pdf/gpbb/gpbb52.pdf · 2019. 10. 24. · LISTING 52.1 152- 1 .C /* 3-0 animation program to rotate 12 cubes.Uses

Where the Time Goes The distribution of execution time in the animation code is no longer wildly biased toward transformation, but sine and cosine are certainly still sucking up cycles. Like- wise, the overhead in the calls to FixedMulO and FixedDivO is costly. Much of this is correctable with a little carefully crafted assembly language and a lookup table; I’ll provide that shortly. Regardless, with this chapter we have made the critical jump to a usable level of performance and a serviceable general-purpose framework. From here on out, it’s the fun stuff.

Fast 3-D Animation: Meet X-Sharp 987