/******************* graphics.c *******************/ #include #include "Tod.h" #include "graphics.h" #include ///////////////////////////////////// // TOD ANIMATION SPECIFIC FUNCTIONS// ///////////////////////////////////// // Draws all objects within Linked list void DrawObjectLink(TodOBJTABLE ObjTab) { int i; int activeBuff; GsDOBJ2 *objp; MATRIX LsMtx; /* Set the pointer to the object array */ objp = ObjTab.top; for( i = 0; i < ObjTab.nobj; i++ ) { /* flag whether the coord has changed or not*/ objp->coord2->flg = 0; if ( ( objp->id != TOD_OBJ_UNDEF ) && ( objp->tmd != 0 ) ) { /* Calculate the local screen matrix */ GsGetLs( objp->coord2, &LsMtx ); /* Set the local screen matrix to GTE */ GsSetLsMatrix( &LsMtx ); /* Set the light matrix to GTE */ GsSetLightMatrix( &LsMtx ); /* Transform the object perspectively and assign it to the OT*/ GsSortObject4( objp, /* Pointer to the object */ &OTable_Header[CurrentBuffer],/* Pointer to the OT */ 14-ORDERING_TABLE_LENGTH, /* number of bits to be shifted*/ (u_long *)getScratchAddr(0)); } objp++; } } void InitialiseModelLink(LinkObjectStruct *theObject,int Max,int nX, int nY, int nZ ,unsigned long *lModelAddress) { int i; theObject->MaxObjects = Max; /* Allocate memory */ theObject->obj_area =(GsDOBJ2 *)malloc(sizeof(GsDOBJ2)*Max); theObject->obj_coord =(GsCOORDINATE2 *)malloc(sizeof(GsCOORDINATE2)*Max); theObject->obj_cparam=(GsCOORD2PARAM *)malloc(sizeof(GsCOORD2PARAM)*Max); /* Skip the file header */ lModelAddress++; /* Map to the real address */ GsMapModelingData(lModelAddress); theObject->TmdP = lModelAddress; /* Initialize the object table */ TodInitObjTable( &theObject->objs, theObject->obj_area, theObject->obj_coord, theObject->obj_cparam, theObject->MaxObjects ); theObject->Object_Coord.coord.t[0]=nX; theObject->Object_Coord.coord.t[1]=nY; theObject->Object_Coord.coord.t[2]=nZ; //The following Doesnt do a thing arrggghh??? //GsInitCoordinate2(&theObject->Object_Coord, &theObject->obj_coord[0]); //theObject->obj_coord[0].super = &theObject->Object_Coord; //GsInitCoordinate2(&theObject->Object_Coord, &theObject->obj_area[0].coord2); //GsInitCoordinate2(&theObject->Object_Coord, &theObject->obj_area[0].coord2); //theObject->obj_area[0].coord2->super = &theObject->Object_Coord; } // Set TOD data from the memory void initTod(LinkObjectStruct *theObject,int *IDlist,int todnum,u_long * AnimAddress) { theObject->TodP[todnum] = AnimAddress; theObject->TodP[todnum]++; theObject->NumFrame[todnum] = *theObject->TodP[todnum]++; theObject->StartFrameNo[todnum] = *(theObject->TodP[todnum] + 1); theObject->ID_list = IDlist; } // Reset the objects current frame to the first frame // of the TOD animation. void ResetAnim(LinkObjectStruct *theObject,int todnum) { theObject->TodPtmp = theObject->TodP[todnum]; theObject->TodPtmp = TodSetFrame( theObject->StartFrameNo[todnum], theObject->TodPtmp, &theObject->objs,theObject->ID_list, theObject->TmdP, TOD_NOCREATE ); SetPosition(theObject); //DrawObjectLink(theObject->objs); theObject->oldFrameNo = theObject->StartFrameNo[todnum]; theObject->currentTod = todnum; } // Advance to the next frame of the animation. u_long NextFrame(LinkObjectStruct *theObject,u_long loop) { // Increment frame theObject->frameNo = *( theObject->TodPtmp + 1 ); if((theObject->frameNo+1) < (theObject->NumFrame[theObject->currentTod] + theObject->StartFrameNo[theObject->currentTod])) { // Set TOD to new frame theObject->TodPtmp = TodSetFrame(theObject->frameNo, theObject->TodPtmp, &theObject->objs, theObject->ID_list,theObject->TmdP, TOD_NOCREATE ); // Draw this frame //DrawObjectLink(theObject->objs); // save frame number theObject->oldFrameNo = theObject->frameNo; // moves the object to SetPosition(theObject); return(0); } else { if(loop == TRUE) { ResetAnim(theObject,theObject->currentTod); return(0); } else { return(1); } } } // Cycle throught the whole of the animation. Holds the // processor all to itself though !!! void drawTod(LinkObjectStruct *theObject,int todnum) { int i; int j; theObject->TodPtmp = theObject->TodP[todnum]; theObject->TodPtmp = TodSetFrame( theObject->StartFrameNo[todnum], theObject->TodPtmp, &theObject->objs,theObject->ID_list, theObject->TmdP, TOD_CREATE ); DrawObjectLink(theObject->objs); theObject->oldFrameNo = theObject->StartFrameNo[todnum]; for ( i = theObject->StartFrameNo[todnum] + 1 ; i < theObject->NumFrame[todnum] + theObject->StartFrameNo[todnum] ; i++ ) { theObject->frameNo = *( theObject->TodPtmp + 1 ); for ( j = 0 ; j < theObject->frameNo - theObject->oldFrameNo - 1 ; j++ ) { DrawObjectLink(theObject->objs); } theObject->TodPtmp = TodSetFrame(theObject->frameNo, theObject->TodPtmp, &theObject->objs, theObject->ID_list,theObject->TmdP, TOD_CREATE ); DrawObjectLink(theObject->objs); theObject->oldFrameNo = theObject->frameNo; } DrawObjectLink(theObject->objs); } // Update all object coordinates to stay the same as the // main Object_Coord. (Slow, but its the only way I can find for the // moment). void SetPosition(LinkObjectStruct *theObject) { int i; for(i=0; i < theObject->MaxObjects; i++) { //Rotate //Translate theObject->obj_coord[i].coord.t[0] += theObject->Object_Coord.coord.t[0]; theObject->obj_coord[i].coord.t[1] += theObject->Object_Coord.coord.t[1]; theObject->obj_coord[i].coord.t[2] += theObject->Object_Coord.coord.t[2]; //set flag to redraw //theObject->obj_coord[i].flg = 0; //theObject->obj_area[i].coord2->flg = 0; } } ///////////////////////////////////////////////////////////////////// /////////////// END OF TOD SPECIFIC FUNCTIONS /////////////////////// ///////////////////////////////////////////////////////////////////// // This function associates a model with our player datastructure void InitialiseModel(ObjectStruct *thePlayer, int nX, int nY, int nZ, unsigned long *lModelAddress) { //increment the pointer to past the model id. lModelAddress++; // map tmd data to its actual address GsMapModelingData(lModelAddress); // initialise the players coordinate system - set to be that of the //world GsInitCoordinate2(WORLD, &thePlayer->Object_Coord); // increment pointer twice more - to point to top of model data lModelAddress++; lModelAddress++; // link the model (tmd) with the players object handler GsLinkObject4((u_long)lModelAddress, &thePlayer->Object_Handler,0); // Assign the coordinates of the object model to the Object Handler thePlayer->Object_Handler.coord2 = &thePlayer->Object_Coord; // Set the initial position of the object thePlayer->Object_Coord.coord.t[0]=nX; // X thePlayer->Object_Coord.coord.t[1]=nY; // Y thePlayer->Object_Coord.coord.t[2]=nZ; // Z // setting the players Object_Coord.flg to 0 indicates it is to be // drawn thePlayer->Object_Coord.flg = 0; } // This function deals with setting up matrices needed for rendering // and sends the object to the ordering table so it is drawn void DrawObject(ObjectStruct *thePlayer) { MATRIX tmpls, tmplw; //Get the local world and screen coordinates, needed for light // calculations GsGetLws(thePlayer->Object_Handler.coord2, &tmplw, &tmpls); // Set the resulting light source matrix GsSetLightMatrix(&tmplw); // Set the local screen matrix for the GTE (so it works out // perspective etc) GsSetLsMatrix(&tmpls); // Send Object To Ordering Table GsSortObject4(&thePlayer->Object_Handler,&OTable_Header[CurrentBuffer],4, (u_long*)getScratchAddr(0)); } void InitialiseALight(GsF_LIGHT *flLight, int nLight, int nX, int nY, int nZ, int nRed, int nGreen, int nBlue) { // Set the direction in which light travels flLight->vx = nX;flLight->vy = nY; flLight->vz = nZ; // Set the colour flLight->r = nRed; flLight->g = nGreen; flLight->b = nBlue; // Activate light GsSetFlatLight(nLight, flLight); } // this function initialises the graphics system void Initialise3DGraphics() { // Initialise The Graphics System to PAL as opposed to NTSC SetVideoMode(MODE_PAL); // Set the Actual Size of the Video memory GsInitGraph(SCREEN_WIDTH, SCREEN_HEIGHT, GsNONINTER|GsOFSGPU, 1, 0); // Set the Top Left Coordinates Of The Two Buffers in video memory GsDefDispBuff(0, 0, 0, SCREEN_HEIGHT); // Initialise the 3D Graphics... GsInit3D(); // Before we can use the ordering table headers, // we need to... // 1. Set them to the right length OTable_Header[0].length = ORDERING_TABLE_LENGTH; OTable_Header[1].length = ORDERING_TABLE_LENGTH; // 2. Associate them with an actual ordering table OTable_Header[0].org = OTable_Array[0]; OTable_Header[1].org = OTable_Array[1]; // 3. initialise the World Ordering Table Headers and Arrays GsClearOt(0,0,&OTable_Header[0]); GsClearOt(0,0,&OTable_Header[1]); } void InitialiseView(GsRVIEW2 *view, int nProjDist, int nRZ, int nVPX, int nVPY, int nVPZ, int nVRX, int nVRY, int nVRZ) { // This is the distance between the eye // and the imaginary projection screen GsSetProjection(nProjDist); // Set the eye position or center of projection view->vpx = nVPX; view->vpy = nVPY; view->vpz = nVPZ; // Set the look at position view->vrx = nVRX; view->vry = nVRY; view->vrz = nVRZ; // Set which way is up view->rz=-nRZ; // Set the origin of the coord system in this case the world view->super = WORLD; //&TheCar.Object_Coord ; // Activate view GsSetRefView2(view); } void InitialiseLights() { InitialiseALight(&LightSource[0], 0, -100, -100, -100, 255,255,255); InitialiseALight(&LightSource[1], 1, 1000, 1000, 1000, 255,255,255); GsSetAmbient(0,0,0); GsSetLightMode(0); } void RotateModel(GsCOORDINATE2 * Object_Coord, int nRX, int nRY, int nRZ) { MATRIX matTmp; SVECTOR svRotate; svRotate.vx = nRX; svRotate.vy = nRY; svRotate.vz = nRZ; RotMatrix(&svRotate, & matTmp); MulMatrix0(&Object_Coord->coord, &matTmp, &Object_Coord->coord); Object_Coord->flg = 0; } void RotateModelVector (GsCOORDINATE2 *Object_Coord,SVECTOR *rotateVector, int nRX, int nRY, int nRZ ) { MATRIX matTmp; // reset matrix to the identity matrix Object_Coord->coord.m[0][0]=Object_Coord->coord.m[1][1]= Object_Coord->coord.m[2][2]=ONE; Object_Coord->coord.m[0][1]=Object_Coord->coord.m[0][2]= Object_Coord->coord.m[1][0]=Object_Coord->coord.m[1][2]= Object_Coord->coord.m[2][0]=Object_Coord->coord.m[2][1]=0; // Add the new rotation factors into the players rotation vector // and then set them to the remainder of division by ONE (4096) rotateVector->vx = (rotateVector->vx+nRX)%ONE; rotateVector->vy = (rotateVector->vy+nRY)%ONE; rotateVector->vz = (rotateVector->vz+nRZ)%ONE; // RotMatrix sets up the matrix coefficients for rotation RotMatrix(rotateVector, &matTmp); // Concatenate the existing objects matrix with the // rotation matrix MulMatrix0(&Object_Coord->coord, &matTmp, &Object_Coord->coord); // set the flag to redraw the object Object_Coord->flg = 0; } void RotateModelMatrix (GsCOORDINATE2 *Object_Coord, int nRX, int nRY, int nRZ ) { MATRIX matTmp; SVECTOR svRotate; // This is the vector describing the rotation svRotate.vx = nRX; svRotate.vy = nRY; svRotate.vz = nRZ; // RotMatrix sets up the matrix coefficients for rotation RotMatrix(&svRotate, &matTmp); // Concatenate the existing objects matrix with the // rotation matrix MulMatrix0(&Object_Coord->coord, &matTmp, &Object_Coord->coord); // set the flag to redraw the object AdjustCoordinate2(Object_Coord); Object_Coord->flg = 0; } // move the model void MoveModel (GsCOORDINATE2 *Object_Coord, int nX, int nY, int nZ) { Object_Coord->coord.t[0]+=nX; Object_Coord->coord.t[1]+=nY; Object_Coord->coord.t[2]+=nZ; Object_Coord->flg=0; } /************** beginning of code taken form the SCEI mirror in directory ROTATE ***/ /* s—ñŠÖ˜A Programmed by Co Nazca SOFTWARE 1996-1997 */ //¡³‹K‰» (‡•x,y,zàONE ‹ß–T‚Ì‚Ý) long NormalScale(long x,long y,long z){ long nx,ny,nz,n; nx=(x+(1<<8))>>9; ny=(y+(1<<8))>>9; nz=(z+(1<<8))>>9; n=(nx*nx+ny*ny+nz*nz+(1<<3))>>4; if(n<(1<<26)){ n*=10; n+=9<<26; n/=19; } else { n*=10; n+=11<<26; n/=21; } n=(n+(1<<13))>>14; // if(!n) n=1; return n; } // The lines beginning with // have been commented out to make the function consider // whole matrix each time ... Its very quick // if you want it to run faster uncomment these lines and get slight distortion. Peter. //¡Šî’ês—ñ‚̕Ⳡvoid AdjustCoordinate2(GsCOORDINATE2 *coord){ MATRIX *mp=&coord->coord; long x,y,z,n; #define ax mp->m[0][0] #define ay mp->m[0][1] #define az mp->m[0][2] #define bx mp->m[1][0] #define by mp->m[1][1] #define bz mp->m[1][2] #define cx mp->m[2][0] #define cy mp->m[2][1] #define cz mp->m[2][2] // switch(PSDCNT%3){ //ŒvŽZ•p“x‚Í—v’²® (Œ»Ý‚Í–ˆ‰ñ1/3‚ÂÂ) //case 0: x=by*cz-bz*cy; y=bz*cx-bx*cz; z=bx*cy-by*cx; n=NormalScale(x,y,z); x/=n; y/=n; z/=n; if(ax!=x || ay!=y || az!=z){ ax=x; ay=y; az=z; coord->flg=0; } // break; //case 1: x=cy*az-cz*ay; y=cz*ax-cx*az; z=cx*ay-cy*ax; n=NormalScale(x,y,z); x/=n; y/=n; z/=n; if(bx!=x || by!=y || bz!=z){ bx=x; by=y; bz=z; coord->flg=0; } // break; // case 2: x=ay*bz-az*by; y=az*bx-ax*bz; z=ax*by-ay*bx; n=NormalScale(x,y,z); x/=n; y/=n; z/=n; if(cx!=x || cy!=y || cz!=z){ cx=x; cy=y; cz=z; coord->flg=0; } // break; // } } /******** end of adjustCoordinate2 code ********/