#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "threed.h" #define FIXEDILLUMINATION extern UBYTE title[] ; extern struct Custom custom; extern struct TmpRas tmpras; extern struct BitMap bitmap0; extern struct BitMap bitmap1; extern struct RastPort r[2]; extern struct RastPort *rp[2]; extern struct RasInfo ri[2]; extern struct RasInfo *rip[2]; extern struct RasInfo *irip; extern WORD pcount ; extern WORD vcount ; extern UWORD frametoggle ; extern BPTR objectsegment ; extern struct Object *Amiga ; extern long GfxBase; extern long DosBase; extern int (*subroutines[])(); /******************************************************************************/ displayuniverse(view,screen,window,cameraobjectinfo,objectinfo) struct View *view; struct Screen *screen; struct Window *window; struct Objectinfo *cameraobjectinfo; struct Objectinfo *objectinfo; { int argc = 0; char *argv[MAXNUMARGS]; struct Objectinfo *thisobjectinfo; /* set up parameter passing information for this display */ argv[0] = &thisobjectinfo; argv[1] = subroutines; argc = 2; /* PROCESS ALL THE OBJECTS IN THE LIST POINTED TO BY OBJECTINFO */ thisobjectinfo = objectinfo; while(thisobjectinfo) { int thisobjecterror = FALSE; /* process this object */ if(thisobjectinfo->objectprocedure) { int (*function)(); /* call the object's procedure */ #ifdef ODEBUG printf("do3d: object(%lx) procedure = %lx\n",thisobjectinfo,thisobjectinfo->objectprocedure); #endif function = (thisobjectinfo->objectprocedure); thisobjecterror = (*function)(argc,argv); } /* begin - rotate the object matrix - temporary */ /* yaw(thisobjectinfo->objectmatrix,SINB,COSB); */ /* pitch(thisobjectinfo->objectmatrix,SINB,COSB); */ /* roll(thisobjectinfo->objectmatrix,SINB,COSB); */ /* end - rotate the object matrix - temporary */ /* this objects's universal reference display matrix is trivial */ *thisobjectinfo->displaymatrix = *thisobjectinfo->objectmatrix; /* this objects's universal reference position is trivial */ *thisobjectinfo->displayposition = *thisobjectinfo->objectposition; /* process any subobjects dependent on this object before diplaying it */ { struct Objectinfo *thisubobjectinfo; thisubobjectinfo = thisobjectinfo->subobjectinfo; while(thisubobjectinfo) { /* display each subobject */ subdisplayuniverse(view,screen,window,cameraobjectinfo,thisobjectinfo,thisubobjectinfo); thisubobjectinfo = thisubobjectinfo->nextobjectinfo; } } { struct Coordinate centerpoint; /* concatenate this object's matrix with the camera matrix for display through camera viewpoint */ { struct UV uv; uv = *thisobjectinfo->objectmatrix; /* copy matrix */ cat(thisobjectinfo->displaymatrix,&uv,cameraobjectinfo->objectmatrix); } subvect(cameraobjectinfo->objectposition,thisobjectinfo->displayposition,¢erpoint); matrix(¢erpoint,¢erpoint,cameraobjectinfo->objectmatrix); if ( (centerpoint.z > 0) && (( (centerpoint.z) - ( (centerpoint.x < 0) ? -centerpoint.x : centerpoint.x )) > 0) && (( (centerpoint.z) - ( (centerpoint.y < 0) ? -centerpoint.y : centerpoint.y )) > 0) ) { /* rotate the 3d normals*/ #ifdef DEBUG printf("do3d: rotate the 3d normals\n"); #endif rotate(thisobjectinfo->displaymatrix,thisobjectinfo->objectnumnormals,thisobjectinfo->objectnormals,thisobjectinfo->objectbufnormals); /* rotate, translate, and perspect the 3d points */ dopoints(thisobjectinfo->displaymatrix,¢erpoint,thisobjectinfo->objectnumpoints,thisobjectinfo->objectpoints,thisobjectinfo->objectbufpoints); } else { /* this object out of 45 degree frustrum */ thisobjectinfo = thisobjectinfo->nextobjectinfo; /* so process the next object */ continue; } } /* draw the polygons by traversing the polygon list */ { WORD polycount = 0; WORD *nextcolor; struct Coordinate **nextn; struct Coordinate **nextp; struct Coordinate *lastn = 0; WORD endflag = FALSE; /* intialize buffer pointers */ nextcolor = thisobjectinfo->colorbuf; nextn = thisobjectinfo->nptrbuf; nextp = thisobjectinfo->pptrbuf; for(polycount = 0; polycount < thisobjectinfo->objectnumpolys; polycount++) { struct Polygon **np; WORD vc; struct Coordinate **v; struct Coordinate *n; struct Coordinate *c0; struct Coordinate *c1; struct Coordinate *c2; WORD bright; WORD firstx, firsty; #ifdef DEBUG printf("poly %lx: \n",polycount); #endif np = (thisobjectinfo->objectpolys+polycount); #ifdef DEBUG printf("np = %lx\n",np); #endif #ifdef DEBUG printf("vertexcount = %lx\n",(*np)->vertexcount); #endif #ifdef DRAWDEBUG printf("poly %lx: color = %lx\n",polycount,*nextcolor); #endif /* backface removal */ /* first, simple clip */ if (((*nextn)->z) > 0) { nextcolor++; nextn++; nextp = (nextp+((*np)->vertexcount)); continue; } /* now, test z component of dynamically computed polygon normal */ c0 = (struct Coordinate *)(*(nextp)); c1 = (struct Coordinate *)(*(nextp+1)); c2 = (struct Coordinate *)(*(nextp+2)); /* if polygon's normal faces away from the screen, or is perpendicular, ignore it */ #ifdef DRAWDEBUG printf("c0->x = %lx c0->y = %lx\n",c0->x,c0->y); printf("c1->x = %lx c1->y = %lx\n",c1->x,c1->y); printf("c2->x = %lx c2->y = %lx\n",c2->x,c2->y); #endif /* fine clipping */ if (((smuls(((c1->x)-(c0->x)),((c2->y)-(c1->y))))-(smuls(((c2->x)-(c1->x)),((c1->y)-(c0->y))))) >= 0) { nextcolor++; nextn++; nextp = (nextp+((*np)->vertexcount)); continue; } /* illumination */ #ifndef FIXEDILLUMINATION bright = (((-(((*nextn)->x+(*nextn)->y))>>1)+(0x4000))>>11); #else bright = (WORD)*nextcolor; #endif /* ceiling */ bright = (bright > 0xF)?0xF:bright; #ifdef DRAWDEBUG printf("poly %lx: bright = %lx\n",polycount,bright); #endif for(vc = 0; vc < (*np)->vertexcount; vc++) { WORD x,y; #ifdef DRAWDEBUG printf("vertex %lx : (thisobjectinfo->objectbufpoints+poff) = %lx\n",vc,*nextp); #endif #ifdef DRAWDEBUG printf("(thisobjectinfo->objectbufpoints+poff)->x = %lx\n",(*nextp)->x); printf("(thisobjectinfo->objectbufpoints+poff)->y = %lx\n",(*nextp)->y); printf("(thisobjectinfo->objectbufpoints+poff)->z = %lx\n",(*nextp)->z); #endif /* draw stuff in */ #ifdef DRAWDEBUG printf("SetAPen = bright\n"); #endif SetAPen(rp[frametoggle ^ 0x0001],bright); if(vc == 0) { /* open this polygon */ #ifdef DRAWDEBUG printf("call areamove...\n"); #endif x = (((*nextp)->x)+(TMPWIDTH>>1)); y = (((*nextp)->y)+(TMPHEIGHT>>1)); if (x<0) x = 0; if (y<0) y = 0; if (x>TMPWIDTH-1) x = TMPWIDTH-1; if (y>TMPHEIGHT-1) y = TMPHEIGHT-1; x -= ( ( TMPWIDTH - (window->RPort->BitMap->BytesPerRow<<3) ) >> 1 ); y -= ( ( TMPHEIGHT - (window->RPort->BitMap->Rows) ) >> 1 ); firstx = x; firsty = y; /* move into the raster that we're NOT displaying */ #ifndef FIXEDILLUMINATION if( (lastn != *nextn) && (endflag) ) { AreaEnd(rp[frametoggle ^ 0x0001]); endflag = FALSE; } #endif AreaMove(rp[frametoggle ^ 0x0001],x,y); } else { /* continue this polygon */ #ifdef DRAWDEBUG printf("call areadraw...\n"); #endif x = (((*nextp)->x)+(TMPWIDTH>>1)); y = (((*nextp)->y)+(TMPHEIGHT>>1)); if (x<0) x = 0; if (y<0) y = 0; if (x>TMPWIDTH-1) x = TMPWIDTH-1; if (y>TMPHEIGHT-1) y = TMPHEIGHT-1; x -= ( ( TMPWIDTH - (window->RPort->BitMap->BytesPerRow<<3) ) >> 1 ); y -= ( ( TMPHEIGHT - (window->RPort->BitMap->Rows) ) >> 1 ); /* draw into the raster that we're NOT displaying */ AreaDraw(rp[frametoggle ^ 0x0001],x,y); } /* increment the nextp pointer */ nextp++; } /* close this polygon */ #ifdef DRAWDEBUG printf("call areaend...\n"); #endif /* end raster that we're NOT displaying (or continue collecting polygons) */ /* last polygon displayed is this one */ lastn = *nextn; #ifndef FIXEDILLUMINATION if(lastn == *(nextn+1)) { /* last polygon displayed has same normal as next polygon to be displayed */ #ifdef DRAWDEBUG printf("last poly displayed has same normal as next polygon to be displayed...draw\n"); #endif /* draw, but do not terminate this polygon in this sequence */ /* note : need graphics 28.5 or greater to do following trick ! */ AreaDraw(rp[frametoggle ^ 0x0001],firstx,firsty); endflag = TRUE; /* if graphics 28.4 or less do this standard thing */ /* AreaEnd(rp[frametoggle ^ 0x0001]); */ /* endflag = FALSE; */ } else { /* last polygon displayed has different normal from next polygon to be displayed */ #ifdef DRAWDEBUG printf("last poly displayed has deffernt normal from next polygon to be displayed...end\n"); #endif /* terminate this polygon sequence */ AreaEnd(rp[frametoggle ^ 0x0001]); endflag = FALSE; } #else { /* terminate this polygon sequence */ AreaEnd(rp[frametoggle ^ 0x0001]); endflag = FALSE; } #endif /* increment nextcolor, nextn pointers */ nextcolor++; nextn++; } if(endflag) { /* terminate series of "same normal" polygons after polyloop exit */ #ifdef DRAWDEBUG printf("close last polygon in series...\n"); #endif AreaEnd(rp[frametoggle ^ 0x0001]); } } thisobjectinfo = thisobjectinfo->nextobjectinfo; } /* end while (thisobject) */ }