/******************* step3.c *******************/ #include #include "3dgraph.h" // This function associates a model with our player datastructure void InitialiseModel(ObjectStruct *theModel, 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, &theModel->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, &theModel->Object_Handler,0); // Assign the coordinates of the object model to the Object Handler theModel->Object_Handler.coord2 = &theModel->Object_Coord; // Set the initial position of the object theModel->Object_Coord.coord.t[0]=nX; // X theModel->Object_Coord.coord.t[1]=nY; // Y theModel->Object_Coord.coord.t[2]=nZ; // Z // setting the players Object_Coord.flg to 0 indicates it is to be // drawn theModel->Object_Coord.flg = 0; // Other Initialisations theModel->yAngle = 0; theModel->Grip = 0; theModel->Acceleration = 0; theModel->Mass = 10; theModel->AccelerateSpeed = 2; theModel->MaxSpeed = 15; theModel->TurnSpeed = 40; } // 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 *theModel) { MATRIX tmpls, tmplw; //Get the local world and screen coordinates, needed for light // calculations GsGetLws(theModel->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(&theModel->Object_Handler,&OTable_Header[CurrentBuffer],4, (u_long*)getScratchAddr(0)); } // Function initialise a single light. 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]); } // Initialise a simple viewing system. 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); } // Initialise a simple lighting setup. 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); } // Rotate a model, generates a rounding error eventually 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; } // Rotate model by a single Vector. Needs a copy of rotations // so far stored with the object. 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; } // Rotate a model corrects rotation errors by normalising with // speedy japenese functions found in this file. void RotateModelMatrix (ObjectStruct *theModel, int nRX, int nRY, int nRZ ) { MATRIX matTmp; SVECTOR svRotate; VECTOR startVector; // 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(&theModel->Object_Coord.coord, &matTmp,&theModel->Object_Coord.coord); // set the flag to redraw the object AdjustCoordinate2(&theModel->Object_Coord); // set up the vector corresponding to the starting orientation startVector.vx = 0; startVector.vy = 0; startVector.vz = ONE; // apply the objects matrix to the start vector to give the current direction //ApplyMatrixLV(&Object_Coord->coord, &startVector, currentDirection); theModel->Direction.vx=theModel->Object_Coord.coord.m[0][2]; theModel->Direction.vy=theModel->Object_Coord.coord.m[1][2]; theModel->Direction.vz=theModel->Object_Coord.coord.m[2][2]; theModel->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; } //Move model in facing direction [[[[[ changed ]]]] void AdvanceModel(ObjectStruct *theModel, long velocity) { if(velocity != 0) { velocity = ONE/velocity; theModel->Object_Coord.coord.t[0] -= theModel->Direction.vx;// velocity; theModel->Object_Coord.coord.t[1] -= theModel->Direction.vy;// velocity; theModel->Object_Coord.coord.t[2] -= theModel->Direction.vz;// velocity; theModel->Object_Coord.flg = 0; } } void ApplyVelocity(ObjectStruct *theModel) { //Enlarge direction vector cause we have no floatind point. Then // Apply velocity. theModel->Object_Coord.coord.t[0] += theModel->Velocity.vx; theModel->Object_Coord.coord.t[1] += theModel->Velocity.vy; theModel->Object_Coord.coord.t[2] += theModel->Velocity.vz; } /************** 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 ********/ // Initialise a normal view void InitialiseStaticView(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); } // Initailise a stuck on view good for cockpit type views void InitialiseTrackerView(GsRVIEW2 *view, int nProjDist, int nRZ, int nVPX, int nVPY, int nVPZ, int nVRX, int nVRY, int nVRZ, GsCOORDINATE2 *Object_Coord) { // 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 = Object_Coord ; // Activate view GsSetRefView2(view); } // not implemented void InitialiseFollowView(GsRVIEW2 *view, int nProjDist, int nRZ, int nVPX, int nVPY, int nVPZ, int nVRX, int nVRY, int nVRZ, GsCOORDINATE2 *Object_Coord) { // 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 = Object_Coord; // Activate view GsSetRefView2(view); } // does absolutw naff all damn. To be used in conjunction with above function. void UpdateFollowView(GsRVIEW2 *view) { view->rz =-250; view->vpy =-2000; GsSetRefView2(view); }