home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************************
- *
- * File : dostank.c
- *
- * Abstract : A very simple, sample RenderWare application for
- * MS-Dos / PC-Dos. This application has very little
- * functionality, but is simply intended as a demonstration
- * of how to use the RenderWare API.
- *
- * This application had been written to be compatible with
- * both the fixed and floating-point versions of the
- * RenderWare library, i.e., it uses the macros CREAL,
- * INT2REAL, RAdd, RDiv, RSub etc. If your application is
- * intended for the floating-point version of the library
- * only these macros are not necessary.
- *
- * Please note that this application is intended for
- * demonstration purposes only. No support will be
- * provided for this code and it comes with no warranty.
- *
- * This file is a product of Criterion Software Ltd.
- *
- * This file is provided as is with no warranties of any kind and is
- * provided without any obligation on Criterion Software Ltd. or
- * Canon Inc. to assist in its use or modification.
- *
- * Criterion Software Ltd. and Canon Inc. will not, under any
- * circumstances, be liable for any lost revenue or other damages arising
- * from the use of this file.
- *
- * Copyright (c) 1991, 1992, 1993. Canon Inc.
- * All Rights Reserved.
- *
- **********************************************************************/
-
- /****************************************************************************
- Includes
- */
-
- #include <stdlib.h>
- #include <string.h>
- #include <i86.h>
- #include <math.h> /* Required for floating point */
-
- #include "rwlib.h"
- #include "rwdos.h"
- #include "doswrap.h"
-
- /****************************************************************************
- Types
- */
-
- /**********************************************************************
- *
- * Application constants.
- *
- **********************************************************************/
-
- #define M_2PI 6.28318
-
- #define EXPLOSION_VEL CREAL(0.01)
- #define FORCE_OF_GRAVITY 0.0005
-
-
- /*
- * Bullet Defines
- */
-
- #define BULLET_SCALE CREAL(0.03)
- #define BULLET_SPEED CREAL(0.1)
- #define BULLET_LIFE 100
-
- /* When bullets hits another bullet */
-
- #define BULLET_BITS 5
- #define BULLET_STILL_BITS 6
- #define NON_EXPLOSION_BITS 5
-
- /*
- * And the rest
- */
-
- #define DELETE 8
- #define BOOL int
-
- /*
- * MS Windows compatible defines
- */
-
- #define MK_CONTROL 0x4
- #define MK_SHIFT 0x2
-
- /*
- * Default distance of the camera from the origin.
- */
-
- #define DEFAULT_CAMERA_DISTANCE CREAL(-7.0)
-
- /* PI !*/
-
- #define PI 3.141592654
-
- /* */
-
- #define MAX_GROUND_TEXTURES 26
- #define MAX_GROUND_THINGS 20
-
- #define GROUND_WIDTH 16
- #define GROUND_HEIGHT 16
- #define GROUND_SPLIT 2
-
- #define GROUND_DISP_WIDTH 11
- #define GROUND_DISP_HEIGHT 11
- #define GROUND_SIZE CREAL(10.0)
-
- #define MAX_BULLETS 20
-
- /* Tank mode types - computer control modes */
- /* General operations */
-
- #define TANK_CONTROL_FORWARD 0
- #define TANK_CONTROL_ROTATE 1
- #define TANK_CONTROL_WAIT 2
- #define TANK_CONTROL_FOLLOW 3
-
- /* Other characteristics */
-
- #define TANK_CONTROL_AIM 8
- #define TANK_CONTROL_ATTACK 16
-
- /* Objects */
-
- #define MAX_MOVE_OBJECTS 20
- #define MAX_TANKS 7
-
- #define TANK_CLOSE_FLIP CREAL(1.0)
-
- /* MINIMUM TANKS in scene */
-
- #define MIN_TANKS 6
-
- /* Tank defines */
-
- #define TANK_SCALE CREAL(0.07)
- #define TANK_HITS 4
- #define TANK_EXPLOSION_BITS 15
- #define TANK_FIRE_RATE 60
-
- /* Still Objects */
-
- #define MAX_STILL_OBJECTS 30
-
- /* Tank control defines */
-
- #define OP_ROT_BASE 1
- #define OP_MOVE 2
- #define OP_ROT_TURRET 3
- #define OP_MOVE_GUN 4
- #define OP_SET_TURRET 5
- #define OP_FIRE 6
-
- /* Display Modes */
-
- #define DISPLAY_OUTSIDE 1
- #define DISPLAY_FIRST 2
- #define DISPLAY_FLOAT 3
- #define DISPLAY_BEHIND 4
-
- #define DISPLAY_TIME 64
-
- /* Object types */
-
- #define TYPE_TANK 1
- #define TYPE_BULLET 2
- #define TYPE_BIT 3
-
- /* Amount of frames for tank firing */
-
- #define FIRE_TIME 10
-
- #define TANK_BACK_FORCE CREAL(0.1)
-
- /* Bits defines */
-
- #define MAX_BITS 30
- #define BIT_SIZE CREAL(0.03)
- #define BIT_LIFE 50
-
- /**********************************************************************
- *
- * Type definitions.
- *
- **********************************************************************/
-
- /****************************************************************************
- Stack Class
- */
-
- typedef struct StackTag {
- int nElementSize;
- char *pData;
- char *pCurPtr;
- int nAmoElements;
- int nCurElement;
- } Stack;
-
-
- /***************************************************************************/
-
- /*
- * StillObject
- */
-
- typedef struct StillObjectTag {
- RwClump *cpGeo;
- RwV3d vPos;
- RwReal nSize;
- struct StillObjectTag *sopNext;
- } StillObject;
-
-
- /*
- * The ground plane element type
- */
-
- typedef struct GroundEleTag {
- RwTexture *tpTex;
- RwUV uvPos;
- StillObject *sopObj;
- } GroundEle;
-
- /*
- * The entire ground plane
- */
-
- typedef struct GroundTag {
- RwReal nXPos;
- RwReal nZPos;
- int nWidth;
- int nHeight;
- int nX;
- int nY;
- int nDispWidth;
- int nDispHeight;
- int nSplit;
- /* Ground */
- RwReal nSize;
- RwReal nStepSize;
- GroundEle *pGround;
- RwTexture *tpaTex[MAX_GROUND_TEXTURES];
- int nAmoTextures;
- /* Things */
- RwClump *cpaGeo[MAX_GROUND_THINGS];
- int nAmoThings;
- RwReal naScale[MAX_GROUND_THINGS];
- /* The polygon array */
- RwPolygon3d **paPolyData;
- /* The Grounds geometry */
- RwClump *cpGeo;
- /* Pos of the ground */
- RwMatrix4d *mpPos;
- /* The width of a texture element */
- RwReal nTexStep;
- /* World coord size */
- RwReal nWorldWidth;
- RwReal nWorldHeight;
- } Ground;
-
-
- /*
- * MoveObject
- */
-
- typedef struct MoveObjectTag {
- int nType;
- void *pObject;
- RwClump *cpGeo;
- RwV3d vPos;
- RwReal nSize;
- RwV3d vVel;
- RwMatrix4d *mpRot,*mpPos;
- } MoveObject;
-
- /*
- * Tank
- */
-
- typedef struct TankTag {
- int nMode; /* When computer controlled */
- int nParam1; /* Some control parameter */
- RwReal nParam2;
- int nHit;
- int nFireCount;
- MoveObject moBase;
- RwClump *cpTurret;
- RwMatrix4d *mpTurretRotPos;
- RwClump *cpGun;
- RwReal nTurretAngle;
- RwMatrix4d *mpGunRotPos;
- } Tank;
-
- /*
- * All Move Objects
- */
-
- typedef struct AllMoveObjTag {
- Stack sDisplay;
- Stack sDisplayed;
- Stack sToDisplay;
- Stack sDestroy;
- } AllMoveObj;
-
- /*
- * All Still Objects
- */
-
- typedef struct AllStillObjTag {
- Stack sStillDisplayed;
- Stack sStillToDisplay;
- } AllStillObj;
-
-
- /*
- * All Tanks
- */
-
- typedef struct AllTanksTag {
- Stack sFree;
- Stack sUsed;
- Tank *tpTanks;
- } AllTanks;
-
- /*
- * Bit
- */
-
- typedef struct BitTag {
- int nLife;
- MoveObject moBase;
- } Bit;
-
- /*
- * All Non interacting 'Bits'
- */
-
- typedef struct AllBitsTag {
- Stack sFree;
- Stack sUsed;
- Bit *bpBits;
- } AllBits;
-
-
- /*
- * Display Class
- */
-
- typedef struct DisplayTag {
- RwReal nBehindDist;
- RwReal nBehindTilt;
- RwReal nBehindPan;
- RwV3d vFloatPos;
- int nDisplayMode;
- RwReal nMinHeight;
- RwReal nMaxX;
- RwReal nMaxZ;
- } Display;
-
- /*
- * Bullet
- */
-
- typedef struct BulletTag {
- int nLife;
- Tank *tpTank;
- MoveObject moBase;
- } Bullet;
-
- /*
- * All Bullets
- */
-
- typedef struct AllBulletsTag {
- Stack sFree;
- Stack sUsed;
- Bullet *bpBullets;
- } AllBullets;
-
- /**********************************************************************
- *
- * Application global variables.
- *
- **********************************************************************/
-
- /* Current button status */
-
- static int bButtonDown = 0;
- static int LastX;
- static int LastY;
-
- /*
- * Ground plane texture map
- */
-
- static char sGGroundMap[]="\
- aaaaabaaaaaaaaaa\
- aaaaabaaaaaaaaaa\
- aaaaabaaaaaaaaaa\
- aaaaabaaaaaccccc\
- aaaaabaaaaaaaaaa\
- aaaaabaaaaaaaaaa\
- aaaaabaaaaaaaaaa\
- aaaaabaaaaaaaaaa\
- aaaaabaaaaaaaaaa\
- aaaaabaaaaaaaaaa\
- cccccdcccccccccc\
- aaaaabaaaaaaaaaa\
- aaaaabaaaaaaaaaa\
- aaaaabaaaaaaaaaa\
- aaaaabaaaaaaaaaa\
- aaaaabaaaaaaaaaa\
- ";
-
- /* Globals */
-
- static Ground gGGround;
- static AllMoveObj amoGObjects;
- static AllTanks atGTanks;
- static Display dGDisplay;
- static AllBullets abGBullets;
- static AllStillObj asoGObjects;
- static AllMoveObj amoGBits;
- static AllBits abGBits;
-
- static int nGDemoMode; /* Non zero => demo mode */
- static int nGDisplayTime; /* Counter for view point flip */
- static int nGDisplay; /* Current view point counter */
-
- /*
- * Texts colour
- */
-
- static int nGTextColour;
-
-
- /*
- * Global RenderWare object pointers. In this simple application we
- * make use of only a single scene, camera and light.
- */
- static RwScene *Scene = NULL;
- static RwCamera *Camera = NULL;
- static RwLight *Light = NULL;
-
- /*
- * This variable tells us what kind of action to take on a mouse move.
- * The action depends on the object that was picked when the mouse button
- * went down, and on the selection of virtual keys that were depressed at
- * that time. By default no action is taken on mouse move.
- */
-
- /*
- * Current distance the camera is from the origin. This is stored to
- * help us pan and zoom the camera.
- */
- static RwReal CameraDistance = DEFAULT_CAMERA_DISTANCE;
-
- /*
- * Current animation frame number. This is incremented each time a
- * frame is drawn on timer expiry. The purpose of this variable is
- * to enable us to periodically (based on the number of frames) call
- * RwOrthoNormalizeMatrix() to correct any errors which have crept
- * into the clump's joint matrix because of the inevitable
- * restrictions on the accuracy of fixed-point numbers. See
- * HandleTimer for more details.
- */
- static int nGFrameNumber = 0;
-
- /* The size of the screen
- */
-
- static int nGScrWidth;
- static int nGScrHeight;
-
- /* Fire Counter */
-
- static int nGFireCount;
-
- /****************************************************************************
- Proto types
- */
-
- /* Other prototypes */
-
- void TankControl(Tank *tpTank,
- int nOperation,
- RwReal nParam1);
- void MoveObjectCreate(MoveObject *mopObj,
- RwReal nScale,
- RwClump *cpGeo,
- int nType,
- void *pObject);
- int AllTanksAddTank(AllTanks *atpTanks,
- RwReal nXPos,
- RwReal nZPos);
-
- /* Stack Prototypes */
- int StackCreate(Stack *spStack,int nEleSize,int nAmoEle);
- void StackClear(Stack *spStack);
- void *StackData(Stack *spStack);
- int StackElements(Stack *spStack);
- void *StackFront(Stack *spStack,void *pData);
- int StackDestroy(Stack *spStack);
- void *StackPush(Stack *spStack,void *pData);
- int StackPop(Stack *spStack,void *pData);
- void StackForAll(Stack *spStack,void (*Func)(void *pData,void *pUser),
- void *pUser);
- int StackRemove(Stack *spStack,void *pEle);
- void *StackFind(Stack *spStack,void *pEle);
- int StackTop(Stack *spStack,void *pData);
-
- /****************************************************************************
- BitCreate
-
- On entry : Bit
- : Scale
- : Clump
- On exit :
- */
-
- void BitCreate(Bit *bpBit,RwReal nScale,RwClump *cpGeo)
- {
- MoveObjectCreate(&bpBit->moBase,nScale,cpGeo,TYPE_BIT,(void *)bpBit);
- }
-
- /*************************************************************************
- BitColour - Sets polygon to a random colour
- (called from RwForAllPolygonsInClump)
-
- On entry : Polygon
- On exit :
- */
-
- static void BitColour(RwPolygon3d *p)
- {
- static int zippy = 0;
-
- switch ((rand()>>4) % 7)
- {
- case 0: RwSetPolygonColor(p, CREAL(0.7), CREAL(0.0), CREAL(0.0)); break;
- case 1: RwSetPolygonColor(p, CREAL(0.8), CREAL(0.1), CREAL(0.2)); break;
- case 2: RwSetPolygonColor(p, CREAL(0.9), CREAL(0.6), CREAL(0.3)); break;
- case 3: RwSetPolygonColor(p, CREAL(0.9), CREAL(0.0), CREAL(0.2)); break;
- case 4: RwSetPolygonColor(p, CREAL(0.7), CREAL(0.7), CREAL(0.0)); break;
- case 5: RwSetPolygonColor(p, CREAL(0.6), CREAL(0.5), CREAL(0.0)); break;
- case 6: RwSetPolygonColor(p, CREAL(0.7), CREAL(0.7), CREAL(0.2)); break;
- }
- zippy++;
- }
-
- /****************************************************************************
- AllBitsCreate
-
- On entry : AllBits
- On exit :
- */
-
- void AllBitsCreate(AllBits *abpBits)
- {
- Bit *bpBit;
- int nCount;
- RwClump *cpBit;
- RwClump *cpClump;
-
- RwModelBegin();
- RwClumpBegin();
- RwSetSurface(CREAL(0.4), CREAL(0.7), CREAL(0.0));
- RwSetSurfaceColor(CREAL(1.0),CREAL(1.0),CREAL(1.0));
- RwSetHints(0);
-
- RwVertex(CREAL(0.866),CREAL(0.5),CREAL(0));
- RwVertex(CREAL(-0.866),CREAL(0.5),CREAL(0));
- RwVertex(CREAL(0),CREAL(1.0),CREAL(0));
-
- RwTriangle(1,2,3);
- RwTriangle(3,2,1);
-
- RwClumpEnd(&cpClump);
- RwModelEnd();
-
- abpBits->bpBits = (Bit *) malloc(sizeof(Bit) *MAX_BITS);
-
- StackCreate(&abpBits->sFree,sizeof(Bit *),MAX_BITS);
- StackCreate(&abpBits->sUsed,sizeof(Bit *),MAX_BITS);
-
- bpBit = abpBits->bpBits;
- for (nCount =0;nCount<MAX_BITS;nCount++) {
- cpBit = RwDuplicateClump(cpClump);
- RwForAllPolygonsInClump(cpBit,BitColour);
-
- BitCreate(bpBit,BIT_SIZE,cpBit);
- StackPush(&abpBits->sFree,&bpBit);
- bpBit++;
- };
-
- RwDestroyClump(cpClump);
- }
-
- /*****************************************************************************
- AllBitsAddBit
-
- On entry : All bits structure
- : position
- : velocity
- On exit :
- */
-
- int AllBitsAddBit(AllBits *abpBits,
- RwV3d *vpPos,
- RwV3d *vpDir,
- int nLife)
- {
- Bit *bpBit;
- MoveObject *mopBit;
-
- if (!StackPop(&abpBits->sFree,&bpBit)) {
- StackPush(&abpBits->sUsed,&bpBit);
-
- bpBit->moBase.vPos = (*vpPos);
- bpBit->moBase.vVel = (*vpDir);
-
- bpBit->nLife = nLife;
-
- /* Place on the display stack */
-
- mopBit = &bpBit->moBase;
- StackPush(&amoGBits.sDisplay,(void *)&mopBit);
- return 0;
- } else {
- return 1;
- };
- }
-
- /****************************************************************************
- AllBitsRemoveBit
-
- On entry : AllBullets
- : Bullet to remove
- On exit :
- */
-
- void AllBitsRemoveBit(AllBits *abpBits,
- Bit *bpBit)
- {
- MoveObject *mopTmp = &bpBit->moBase;
-
- /* Stop the warnings */
-
- abpBits = abpBits;
-
- /* Remove from display */
-
- StackPush(&amoGBits.sDestroy,&mopTmp);
- }
-
- /****************************************************************************
- AllBitsHandle
-
- On entry : All Bits
- On exit :
- */
-
- void AllBitsHandle(AllBits *abpBits)
- {
- Bit **bppBit;
- Bit *bpBit;
- int nAmoBits;
- int nCount;
- RwReal nHitHeight;
-
- bppBit = (Bit **)StackData(&abpBits->sUsed);
- nAmoBits = StackElements(&abpBits->sUsed);
-
- nHitHeight = RMul(BIT_SIZE,CREAL(1.5));
-
- for (nCount=0;nCount<nAmoBits;nCount++) {
- bpBit = (*bppBit);
-
- RwTransformMatrix(bpBit->moBase.mpPos,bpBit->moBase.mpRot,rwPOSTCONCAT);
- /* Handle it */
-
- bpBit->nLife--;
- if ((bpBit->nLife<0)) {
- /* Destroy the bullet */
- AllBitsRemoveBit(abpBits,bpBit);
- } else {
- RwAddVector(&bpBit->moBase.vPos,&bpBit->moBase.vVel,
- &bpBit->moBase.vPos);
- bpBit->moBase.vVel.y -= CREAL(FORCE_OF_GRAVITY);
-
- if ((bpBit->moBase.vPos.y < nHitHeight) &&
- (bpBit->moBase.vVel.y<CREAL(0)) ) {
- bpBit->moBase.vPos.y = nHitHeight;
- bpBit->moBase.vVel.y = -RMul(bpBit->moBase.vVel.y,CREAL(0.5));
- };
- };
-
- bppBit++;
- };
-
- AllMoveObjClean(&amoGBits);
- }
-
- /****************************************************************************
- AllBitsExplosion
-
- On entry : All Bits
- : Position
- : Velocity
- : Amount of Bits
- On exit :
- */
-
- void AllBitsExplosion(AllBits *abpBits,
- RwV3d *vpPos,
- RwV3d *vpVel,
- int nAmoBits)
- {
- int nCount;
- int nLife=0;
- RwReal nRand;
- Bit *bpBit;
- RwV3d vTmp;
-
- for (nCount=0;nCount<nAmoBits;nCount++) {
- if (AllBitsAddBit(abpBits,vpPos,vpVel,BIT_LIFE+(nLife&7))) {
- break;
- };
-
- StackTop(&abpBits->sUsed,&bpBit);
-
- nLife++;
-
- RandomVec(&vTmp);
-
- RwRotateMatrix(bpBit->moBase.mpRot,vTmp.x,vTmp.y,vTmp.z,
- RMul(RSub(RDiv(INT2REAL(rand()),CREAL(16384.0)), CREAL(1.0)),CREAL(15.0)),
- rwREPLACE);
-
- nRand = RDiv(INT2REAL(rand()>>1),CREAL(16384.0));
- bpBit->moBase.vVel.x += RSub(RMul(RAdd(EXPLOSION_VEL,EXPLOSION_VEL),nRand),
- EXPLOSION_VEL);
-
- nRand = RDiv(INT2REAL(rand()>>1),CREAL(16384.0));
- bpBit->moBase.vVel.y += RSub(RMul(RAdd(EXPLOSION_VEL,EXPLOSION_VEL),nRand),
- EXPLOSION_VEL);
-
- nRand = RDiv(INT2REAL(rand()>>1),CREAL(16384.0));
- bpBit->moBase.vVel.z += RSub(RMul(RAdd(EXPLOSION_VEL,EXPLOSION_VEL),nRand),
- EXPLOSION_VEL);
- };
- }
-
- /****************************************************************************
- DisplayModeSet
-
- On entry : Display Structure
- Display Mode required
- On exit :
- */
-
- void DisplayModeSet(Display *dpDisp,
- int nMode)
- {
- dpDisp->nDisplayMode = nMode;
-
- switch(nMode) {
- case DISPLAY_OUTSIDE: {
- RwSetCameraLookUp(Camera,CREAL(1.0),CREAL(0.0),CREAL(0.0));
- RwSetCameraPosition(Camera,CREAL(0.0),CREAL(1.0),CREAL(0.0));
- RwPointCamera(Camera,CREAL(0.0),CREAL(0.0),CREAL(0.0));
- break;
- };
- case DISPLAY_FIRST: {
- RwSetCameraLookUp(Camera,CREAL(0.0),CREAL(1.0),CREAL(0.0));
- break;
- };
- case DISPLAY_FLOAT: {
- RwSetCameraLookUp(Camera,CREAL(1.0),CREAL(0.0),CREAL(0.0));
- RwSetCameraPosition(Camera,CREAL(2.0),CREAL(1.0),CREAL(0.0));
- RwPointCamera(Camera,CREAL(0.0),CREAL(0.0),CREAL(0.0));
- break;
- };
- case DISPLAY_BEHIND: {
- RwSetCameraLookUp(Camera,CREAL(0.0),CREAL(1.0),CREAL(0.0));
- break;
- };
- };
- }
-
- /****************************************************************************
- DisplayCreate
-
- On entry : Display
- On exit :
- */
-
- void DisplayModeCreate(Display *dpDisp)
- {
- dpDisp->nBehindDist = CREAL(-0.5);
- dpDisp->nBehindPan = CREAL(0.0);
- dpDisp->nBehindTilt = CREAL(15.0);
-
- dpDisp->vFloatPos.x = CREAL(0.0);
- dpDisp->vFloatPos.y = CREAL(1.0);
- dpDisp->vFloatPos.z = CREAL(0.0);
-
- dpDisp->nMinHeight = CREAL(0.3);
- dpDisp->nMaxX = RMul(GROUND_SIZE,CREAL(0.25));
- dpDisp->nMaxZ = RMul(GROUND_SIZE,CREAL(0.25));
- }
-
- /****************************************************************************
- AllMoveObjCreate
-
- On entry : AllMoveObj
- On exit :
- */
-
- void AllMoveObjCreate(AllMoveObj *amopObj,int nMax)
- {
- StackCreate(&amopObj->sDisplay,sizeof(MoveObject *),nMax);
- StackCreate(&amopObj->sDisplayed,sizeof(MoveObject *),nMax);
- StackCreate(&amopObj->sToDisplay,sizeof(MoveObject *),nMax);
- StackCreate(&amopObj->sDestroy,sizeof(MoveObject *),nMax);
- }
-
- /****************************************************************************
- AllMoveObjClean
-
- On entry : AllMoveObj
- On exit :
- */
-
- void AllMoveObjClean(AllMoveObj *amopObj)
- {
- MoveObject *mopObj;
- void *pFind;
-
- while(!StackPop(&amopObj->sDestroy,&mopObj)) {
- pFind = StackFind(&amopObj->sDisplay,&mopObj);
-
- if (pFind) {
- StackRemove(&amopObj->sDisplay,pFind);
-
- switch (mopObj->nType) {
- case TYPE_BULLET: {
- /* Remove from active bullets */
- StackRemove(&abGBullets.sUsed,StackFind(&abGBullets.sUsed,&mopObj->pObject));
- /* Add to free bullets */
- StackPush(&abGBullets.sFree,&mopObj->pObject);
- break;
- };
- case TYPE_TANK: {
- /* Remove from active bullets */
- StackRemove(&atGTanks.sUsed,StackFind(&atGTanks.sUsed,&mopObj->pObject));
- /* Add to free bullets */
- StackPush(&atGTanks.sFree,&mopObj->pObject);
- break;
- };
- case TYPE_BIT: {
- /* Remove from active bullets */
- StackRemove(&abGBits.sUsed,StackFind(&abGBits.sUsed,&mopObj->pObject));
- /* Add to free bullets */
- StackPush(&abGBits.sFree,&mopObj->pObject);
- break;
- };
- };
- };
- };
- }
-
- /****************************************************************************
- AllStillObjCreate
-
- On entry : AllMoveObj
- On exit :
- */
-
- void AllStillObjCreate(AllStillObj *asopObj)
- {
- StackCreate(&asopObj->sStillDisplayed,sizeof(StillObject *),MAX_STILL_OBJECTS);
- StackCreate(&asopObj->sStillToDisplay,sizeof(StillObject *),MAX_STILL_OBJECTS);
- }
-
-
- /****************************************************************************
- AddObjectToScene
-
- On entry : Position
- : Rotation
- : Clump
- On exit :
- */
-
- void PosObjectInScene(RwV3d *vpPos,
- RwMatrix4d *mpPos,
- RwClump *cpClump)
- {
- RwPushScratchMatrix();
- RwCopyMatrix(mpPos,RwScratchMatrix());
- RwTranslateMatrix(RwScratchMatrix(),
- (vpPos->x-gGGround.nXPos),
- vpPos->y,
- (vpPos->z-gGGround.nZPos), rwPOSTCONCAT);
- RwTransformClump(cpClump, RwScratchMatrix(), rwREPLACE);
- RwPopScratchMatrix();
- }
-
- /****************************************************************************
- AllMoveObjDisplay
-
- On entry : AllMoveObj
- On exit :
- */
-
- int _AllMoveObjDisplay(void *pA,void *pB)
- {
- return (((*(int *)pA))-((*(int *)pB)));
- }
-
- void AllMoveObjDisplay(AllMoveObj *amopObj,Ground *gpGrou)
- {
- MoveObject *mopObj;
- RwReal nMinX,nMaxX,nMinZ,nMaxZ;
- Stack sTmp;
- int nDisp;
- int nToDisp;
- MoveObject **mopDisp;
- MoveObject **mopToDisp;
- Tank *tpTank;
-
- tpTank = *((Tank **)StackData(&atGTanks.sUsed));
-
- nMinX = RSub(gpGrou->nXPos,RDiv(gpGrou->nSize,CREAL(2)));
- nMinZ = RSub(gpGrou->nZPos,RDiv(gpGrou->nSize,CREAL(2)));
- nMaxX = nMinX + gpGrou->nSize;
- nMaxZ = nMinZ + gpGrou->nSize;
-
- StackClear(&amopObj->sToDisplay);
-
- mopDisp = (MoveObject **)StackData(&amopObj->sDisplay);
- nDisp = StackElements(&amopObj->sDisplay);
-
- for (;nDisp;nDisp--) {
- mopObj = (*mopDisp);
- mopDisp++;
- if ((mopObj->vPos.x<nMinX) ||
- (mopObj->vPos.x>nMaxX) ||
- (mopObj->vPos.z<nMinZ) ||
- (mopObj->vPos.z>nMaxZ)) {
- continue;
- };
-
- if ((dGDisplay.nDisplayMode==DISPLAY_FIRST)&&
- (mopObj==(&tpTank->moBase))) {
- /* If first person, then dont display your tank */
- continue;
- };
- StackPush(&amopObj->sToDisplay,(void *) &mopObj);
- };
-
- /* Sort the stacks for later comparison */
-
- qsort(StackData(&amopObj->sToDisplay),
- StackElements(&amopObj->sToDisplay),
- sizeof(MoveObject *),_AllMoveObjDisplay);
-
- /* Find what needs to be added and removed from scene */
-
- mopToDisp = (MoveObject **) StackData(&amopObj->sToDisplay);
- nToDisp = StackElements(&amopObj->sToDisplay);
-
- mopDisp = (MoveObject **)StackData(&amopObj->sDisplayed);
- nDisp = StackElements(&amopObj->sDisplayed);
-
- while (nToDisp&&nDisp) {
- if ((*mopDisp)==(*mopToDisp)) {
- PosObjectInScene(&((*mopToDisp)->vPos),
- (*mopToDisp)->mpPos,
- (*mopToDisp)->cpGeo);
-
- mopDisp++;
- mopToDisp++;
- nToDisp--;
- nDisp--;
- } else {
- if ((*mopDisp)<(*mopToDisp)) {
- RwRemoveClumpFromScene((*mopDisp)->cpGeo);
-
- nDisp--;
- mopDisp++;
- } else {
- RwAddClumpToScene(Scene,(*mopToDisp)->cpGeo);
- PosObjectInScene(&(*mopToDisp)->vPos,
- (*mopToDisp)->mpPos,
- (*mopToDisp)->cpGeo);
-
- nToDisp--;
- mopToDisp++;
- };
- };
- };
-
- if (nDisp) {
- for (;nDisp;nDisp--) {
- RwRemoveClumpFromScene((*mopDisp)->cpGeo);
- mopDisp++;
- };
- };
-
- if (nToDisp) {
- for (;nToDisp;nToDisp--) {
- RwAddClumpToScene(Scene,(*mopToDisp)->cpGeo);
- PosObjectInScene(&(*mopToDisp)->vPos,
- (*mopToDisp)->mpPos,
- (*mopToDisp)->cpGeo);
- mopToDisp++;
- };
- };
-
- /* Switch stacks - to remove a qsort!*/
-
- sTmp = amopObj->sDisplayed;
- amopObj->sDisplayed = amopObj->sToDisplay;
- amopObj->sToDisplay = sTmp;
- }
-
- /****************************************************************************
- AllMoveObjBound
-
- On entry : All move objects
- Ground
- On exit :
- */
-
- void AllMoveObjBound(AllMoveObj *amopObj,
- Ground *gpGrou)
- {
- MoveObject **moppCur;
- int nAmoObj;
- RwReal nMinX,nMaxX,nMinZ,nMaxZ;
-
- moppCur = (MoveObject **)StackData(&amopObj->sDisplay);
- nAmoObj = StackElements(&amopObj->sDisplay);
-
- nMinX = CREAL(0);
- nMinZ = CREAL(0);
- nMaxX = RSub(gpGrou->nWorldWidth,CREAL(0.001));
- nMaxZ = RSub(gpGrou->nWorldHeight,CREAL(0.001));
-
- for (;nAmoObj;nAmoObj--) {
- if ((*moppCur)->nType==TYPE_TANK) {
- if ((*moppCur)->vPos.x<nMinX) {
- (*moppCur)->vPos.x = nMinX;
- };
- if ((*moppCur)->vPos.x>nMaxX) {
- (*moppCur)->vPos.x = nMaxX;
- };
- if ((*moppCur)->vPos.z<nMinZ) {
- (*moppCur)->vPos.z = nMinZ;
- };
- if ((*moppCur)->vPos.z>nMaxZ) {
- (*moppCur)->vPos.z = nMaxZ;
- };
- };
-
- moppCur++;
- };
- }
-
- /****************************************************************************
- AllMoveObjCollision
-
- On entry : All move objects
- On exit :
- */
-
- void AllMoveObjCollision(AllMoveObj *amopObj)
- {
- MoveObject **moppCur;
- MoveObject **moppCheck;
- int nCount,nCount2;
- int nAmoObj;
- RwReal nCurSize,nMinSize;
- RwV3d vCur;
- RwV3d vTmp,vVel;
- RwReal nDist;
- Tank *tpTank;
- Bullet *bpBull;
- RwV3d vExpDir,vExpPos;
-
- vVel.x = CREAL(0);
- vVel.y = CREAL(0);
- vVel.z = CREAL(0);
-
- moppCur = (MoveObject **)StackData(&amopObj->sDisplay);
- nAmoObj = StackElements(&amopObj->sDisplay);
-
- for (nCount=nAmoObj-1;nCount>0;nCount--) {
- moppCheck = moppCur+1;
- vCur = (*moppCur)->vPos;
- nCurSize = (*moppCur)->nSize;
- for (nCount2=0;nCount2<nCount;nCount2++) {
- RwSubtractVector(&vCur,&(*moppCheck)->vPos,&vTmp);
-
- nMinSize = nCurSize + (*moppCheck)->nSize;
-
- if ((vTmp.x>nMinSize)||
- (vTmp.x<-nMinSize)||
- (vTmp.z>nMinSize)||
- (vTmp.z<-nMinSize)) {
- moppCheck++;
- continue;
- };
-
- nDist = RSqrt( RAdd(RMul(vTmp.x,vTmp.x),
- RMul(vTmp.z,vTmp.z)) );
-
- if (nDist<nMinSize) {
- if ((*moppCur)->nType==(*moppCheck)->nType) {
- if (((*moppCur)->nType == TYPE_TANK)) {
- /* Two tanks */
- nDist= RMul(RSub(nDist,nMinSize),CREAL(0.5));
-
- RwNormalize(&vTmp);
- vTmp.x = RMul(vTmp.x,nDist);
- vTmp.z = RMul(vTmp.z,nDist);
-
- RwAddVector(&(*moppCheck)->vPos,&vTmp,&(*moppCheck)->vPos);
- RwSubtractVector(&(*moppCur)->vPos,&vTmp,&(*moppCur)->vPos);
- } else {
- /* Two bullets */
- AllBitsExplosion(&abGBits,&(*moppCur)->vPos,&vVel,BULLET_BITS);
-
- AllBulletsRemoveBullet(&abGBullets,(*moppCur)->pObject);
- AllBulletsRemoveBullet(&abGBullets,(*moppCheck)->pObject);
- };
- } else {
- /* a tank is destroyed */
- if ((*moppCur)->nType==TYPE_TANK) {
- tpTank = (Tank *)((*moppCur)->pObject);
- bpBull = (Bullet *)((*moppCheck)->pObject);
- } else {
- tpTank = (Tank *)((*moppCheck)->pObject);
- bpBull = (Bullet *)((*moppCur)->pObject);
- };
-
- if ( (bpBull->tpTank == tpTank) || (nDist<RMul(nMinSize,CREAL(0.5))) ) {
- /* A firing tank cannot hit itself */
- /* Make it tricky to hit */
- moppCheck++;
- continue;
- };
-
- if (tpTank == *((Tank **)StackData(&atGTanks.sUsed))) {
- /* You've been hit */
- /* Make sure you dont die */
-
- tpTank->nHit = TANK_HITS;
- };
-
-
- if (tpTank->nHit) {
- tpTank->nHit--;
-
- /* Blast back effect */
- vExpDir = bpBull->moBase.vVel;
-
- vExpDir.x = RMul(vExpDir.x,CREAL(-0.1));
- vExpDir.y = RMul(vExpDir.y,CREAL(-0.1));
- vExpDir.z = RMul(vExpDir.z,CREAL(-0.1));
-
- AllBitsExplosion(&abGBits,&bpBull->moBase.vPos,
- &vExpDir,
- NON_EXPLOSION_BITS);
-
- vExpDir = bpBull->moBase.vVel;
- RwNormalize(&vExpDir);
-
- vExpDir.x = RMul(vExpDir.x,TANK_BACK_FORCE);
- vExpDir.y = RMul(vExpDir.y,TANK_BACK_FORCE);
- vExpDir.z = RMul(vExpDir.z,TANK_BACK_FORCE);
-
- RwAddVector(&tpTank->moBase.vPos,&vExpDir,&tpTank->moBase.vPos);
-
- AllBulletsRemoveBullet(&abGBullets,bpBull);
- } else {
- /* Tank is destroyed */
- vExpDir.x = CREAL(0);
- vExpDir.y = CREAL(0.01); /* Make it go up !*/
- vExpDir.z = CREAL(0);
-
- vExpPos = tpTank->moBase.vPos;
- vExpPos.y += RDiv(tpTank->moBase.nSize,CREAL(2));
-
- AllBitsExplosion(&abGBits,&vExpPos,
- &vExpDir,
- TANK_EXPLOSION_BITS);
- AllBulletsRemoveBullet(&abGBullets,bpBull);
- AllTanksRemoveTank(&atGTanks,tpTank);
- };
- };
- };
-
- moppCheck++;
- };
- moppCur++;
- };
-
- /* Delete unwanted entries */
-
- AllMoveObjClean(amopObj);
- }
-
- /****************************************************************************
- AllMoveObjCollisionStill
-
- On entry : All move objects
- : Ground structure
- On exit :
- */
-
- void AllMoveObjCollisionStill(AllMoveObj *amopObj,
- Ground *gpGrou)
- {
- MoveObject **moppObj;
- MoveObject *mopObj;
- int nAmoObj;
- GroundEle *gepGrou,*gepCur;
- int nStride;
- int nXPos;
- int nZPos;
- StillObject *sopObj;
- RwReal nWX,nWZ;
- RwReal nDist;
- RwV3d vTmp,vExpDir;
-
- gepGrou = gpGrou->pGround;
- nStride = gpGrou->nWidth*gpGrou->nSplit;
-
- moppObj = (MoveObject **)StackData(&amopObj->sDisplay);
- nAmoObj = StackElements(&amopObj->sDisplay);
-
- for(;nAmoObj;nAmoObj--) {
- mopObj = (*moppObj);
-
- if ((mopObj->vPos.x<CREAL(0))||
- (mopObj->vPos.z<CREAL(0))||
- (mopObj->vPos.x>gpGrou->nWorldWidth)||
- (mopObj->vPos.z>gpGrou->nWorldHeight)) {
- /* Object not in world */
- moppObj++;
- continue;
- };
-
- nXPos = REAL2INT(RDiv(mopObj->vPos.x,gpGrou->nStepSize));
- nZPos = REAL2INT(RDiv(mopObj->vPos.z,gpGrou->nStepSize));
-
- nWX = RMul(INT2REAL(nXPos),gpGrou->nStepSize);
- nWZ = RMul(INT2REAL(nZPos),gpGrou->nStepSize);
-
- gepCur = gepGrou+((nStride*nZPos)+(nXPos));
- sopObj = gepCur->sopObj;
-
- while (sopObj) {
-
- vTmp = sopObj->vPos;
- vTmp.x += nWX;
- vTmp.z += nWZ;
-
- vTmp.x -= mopObj->vPos.x;
- vTmp.z -= mopObj->vPos.z;
-
- nDist = RSqrt(RAdd(RMul(vTmp.x,vTmp.x),RMul(vTmp.z,vTmp.z)));
-
- if (nDist<RAdd(mopObj->nSize,sopObj->nSize)) {
- switch (mopObj->nType) {
- case TYPE_TANK: {
- RwNormalize(&vTmp);
- vTmp.x = RMul(vTmp.x,nDist-(mopObj->nSize+sopObj->nSize));
- vTmp.z = RMul(vTmp.z,nDist-(mopObj->nSize+sopObj->nSize));
-
- RwAddVector(&mopObj->vPos,&vTmp,&mopObj->vPos);
- break;
- };
- case TYPE_BULLET: {
- vExpDir = mopObj->vVel;
- vExpDir.x = RMul(vExpDir.x,CREAL(-0.1));
- vExpDir.y = RMul(vExpDir.y,CREAL(-0.1));
- vExpDir.z = RMul(vExpDir.z,CREAL(-0.1));
-
- AllBitsExplosion(&abGBits,&mopObj->vPos,&vExpDir,BULLET_STILL_BITS);
- AllBulletsRemoveBullet(&abGBullets,mopObj->pObject);
- break;
- };
- default: {
- };
- };
- };
- sopObj = sopObj->sopNext;
- };
-
- moppObj++;
- };
-
- AllMoveObjClean(amopObj);
- }
-
- /****************************************************************************
- StillObjectCreate
-
- On entry : StillObject
- : Scale
- : Clump
- */
-
- /*
- * StillObject
- */
-
- void StillObjectCreate(StillObject *sopObj,RwReal nScale,RwClump *cpGeo)
- {
- RwPushScratchMatrix();
-
- sopObj->nSize = RMul(nScale,CREAL(0.8));
-
- RwScaleMatrix(RwScratchMatrix(),nScale,nScale,nScale,rwREPLACE);
- RwTransformClumpJoint(cpGeo,RwScratchMatrix(),rwREPLACE);
-
- sopObj->vPos.x = CREAL(0.0);
- sopObj->vPos.y = CREAL(0.0);
- sopObj->vPos.z = CREAL(0.0);
-
- sopObj->cpGeo = cpGeo;
-
- sopObj->sopNext = NULL;
- RwPopScratchMatrix();
- }
-
- /****************************************************************************
- MoveObjectCreate
-
- On entry : MoveObject
- : Objects Scale
- : Object in Question
- : Data
- On exit :
- */
-
- void MoveObjectCreate(MoveObject *mopObj,
- RwReal nScale,
- RwClump *cpGeo,
- int nType,
- void *pObject)
- {
- RwPushScratchMatrix();
-
- mopObj->nSize = RMul(nScale,CREAL(1.0));
-
- RwIdentityMatrix(mopObj->mpRot=RwCreateMatrix());
- RwIdentityMatrix(mopObj->mpPos=RwCreateMatrix());
-
- RwScaleMatrix(RwScratchMatrix(),nScale,nScale,nScale,rwREPLACE);
- RwTransformClumpJoint(cpGeo,RwScratchMatrix(),rwREPLACE);
-
- mopObj->vPos.x = CREAL(0.0);
- mopObj->vPos.y = CREAL(0.0);
- mopObj->vPos.z = CREAL(0.0);
-
- mopObj->vVel.x = CREAL(0.0);
- mopObj->vVel.y = CREAL(0.0);
- mopObj->vVel.z = CREAL(0.0);
-
- mopObj->cpGeo = cpGeo;
-
- mopObj->pObject = pObject;
- mopObj->nType = nType;
-
- RwPopScratchMatrix();
- }
-
- /****************************************************************************
- TankAim
-
- On entry : Tank
- : Vector to look at
- On exit : Direction to aim
- */
-
- RwReal TankAim(Tank *tpTank,RwV3d *vpDir)
- {
- RwV3d vDirNeed;
- RwV3d vDirTank;
- RwV3d vOut;
- RwReal nCosDir;
- RwReal nAngle;
-
- vDirNeed = (*vpDir);
- RwSubtractVector(&vDirNeed,&tpTank->moBase.vPos,&vDirNeed);
- RwNormalize(&vDirNeed);
-
- vDirTank.x = CREAL(1.0);
- vDirTank.y = CREAL(0.0);
- vDirTank.z = CREAL(0.0);
-
- RwTransformVector(&vDirTank,tpTank->moBase.mpPos);
-
- nCosDir = RwDotProduct(&vDirTank,&vDirNeed);
- if (nCosDir>CREAL(0.999)) {
- nCosDir=CREAL(0.999);
- };
- if (nCosDir<CREAL(-0.999)) {
- nCosDir = CREAL(-0.999);
- };
-
- RwCrossProduct(&vDirTank,&vDirNeed,&vOut);
-
- nAngle = RMul(RDiv(CREAL(180),CREAL(PI)),FL2REAL(acos(REAL2FL(nCosDir))) );
- if (vOut.y<CREAL(0.0)) {
- nAngle=-nAngle;
- };
-
- return nAngle;
- }
-
-
-
- /****************************************************************************
- TankGivePurpose
-
- On entry : Tank
- On exit :
- */
-
- void TankGivePurpose(Tank *tpTank)
- {
- int nRand;
- int nRand2;
- int nValue;
-
- nRand = rand();
- nRand2= rand();
- nValue = nRand&255;
-
- if (nValue<90) {
- tpTank->nMode = TANK_CONTROL_FORWARD;
- tpTank->nParam1 = nRand2&63;
- tpTank->nParam2 = RDiv(INT2REAL(((nRand2>>8)&31)-15),CREAL(1000));
- } else if (nValue<130) {
- tpTank->nMode = TANK_CONTROL_ROTATE;
- tpTank->nParam1 = nRand2&7;
- tpTank->nParam2 = RDiv(INT2REAL(((nRand2>>8)&511)-255),CREAL(64));
- } else if (nValue<170) {
- tpTank->nMode = TANK_CONTROL_WAIT;
- tpTank->nParam1 = nRand2&31;
- } else {
- tpTank->nMode = TANK_CONTROL_FOLLOW;
- tpTank->nParam1 = nRand2&63;
- };
-
- nValue = (nRand>>8)&15;
-
- if (((nRand>>8)&15)<5) {
- tpTank->nMode|=TANK_CONTROL_AIM;
- };
- if (((nRand>>12)&15)<5) {
- tpTank->nMode|=TANK_CONTROL_ATTACK;
- };
- }
-
- /****************************************************************************
- TankAct
-
- On entry : Tank Structure
- On exit :
- */
-
- void TankAct(Tank *tpTank)
- {
- Tank *tpTarget;
- RwV3d vDirNeed;
- RwV3d vDirTank;
- RwReal nValue;
-
- if (tpTank->nParam1--<0) {
- TankGivePurpose(tpTank);
- };
-
- if (tpTank->nFireCount) {
- tpTank->nFireCount--;
- };
-
- tpTarget = *((Tank **)StackData(&atGTanks.sUsed));
-
- switch(tpTank->nMode&3) {
- case TANK_CONTROL_FORWARD: {
- TankControl(tpTank,OP_MOVE,tpTank->nParam2);
- break;
- };
- case TANK_CONTROL_ROTATE: {
- TankControl(tpTank,OP_ROT_BASE,tpTank->nParam2);
- break;
- };
- case TANK_CONTROL_WAIT: {
- break;
- };
- case TANK_CONTROL_FOLLOW: {
-
- vDirNeed = tpTarget->moBase.vPos;
-
- RwSubtractVector(&vDirNeed,&tpTank->moBase.vPos,&vDirNeed);
- RwNormalize(&vDirNeed);
-
- vDirTank.x = CREAL(0.0);
- vDirTank.y = CREAL(0.0);
- vDirTank.z = CREAL(1.0);
-
- RwTransformVector(&vDirTank,tpTank->moBase.mpPos);
-
- if (RwDotProduct(&vDirTank,&vDirNeed)<CREAL(0.0)) {
- TankControl(tpTank,OP_ROT_BASE,CREAL(2));
- } else {
- TankControl(tpTank,OP_ROT_BASE,CREAL(-2));
- };
-
- TankControl(tpTank,OP_MOVE,CREAL(0.01));
-
- if ( ((RAbs(tpTarget->moBase.vPos.x-tpTank->moBase.vPos.x))<TANK_CLOSE_FLIP)&&
- ((RAbs(tpTarget->moBase.vPos.x-tpTank->moBase.vPos.x))<TANK_CLOSE_FLIP) ) {
- /* Its very close so time to back off - probably */
- if (rand()&255<20) {
- TankGivePurpose(tpTank);
- };
- };
-
- break;
- };
- };
-
-
- if (tpTank->nMode&TANK_CONTROL_AIM) {
- vDirNeed = tpTarget->moBase.vPos;
-
- RwSubtractVector(&vDirNeed,&tpTank->moBase.vPos,&vDirNeed);
- RwNormalize(&vDirNeed);
-
- vDirTank.x = CREAL(0.0);
- vDirTank.y = CREAL(0.0);
- vDirTank.z = CREAL(1.0);
-
- RwTransformVector(&vDirTank,tpTank->moBase.mpPos);
-
- RwPushScratchMatrix();
- RwGetClumpJointMatrix(tpTank->cpTurret,RwScratchMatrix());
- RwTransformVector(&vDirTank,RwScratchMatrix());
- vDirTank.y = CREAL(0);
- RwPopScratchMatrix();
-
- if ((nValue = RwDotProduct(&vDirTank,&vDirNeed))<CREAL(0.0)) {
- TankControl(tpTank,OP_ROT_TURRET,CREAL(2));
- } else {
- TankControl(tpTank,OP_ROT_TURRET,CREAL(-2));
- };
-
- if (tpTank->nMode&TANK_CONTROL_ATTACK) {
- if ( (RAbs(tpTank->moBase.vPos.x-tpTarget->moBase.vPos.x)<
- RDiv(gGGround.nSize,CREAL(2)) ) &&
- (RAbs(tpTank->moBase.vPos.z-tpTarget->moBase.vPos.z)<
- RDiv(gGGround.nSize,CREAL(2)) ) && (!tpTank->nFireCount)) {
-
- if (nValue<CREAL(0.2)) {
- TankControl(tpTank,OP_FIRE,CREAL(0));
-
- tpTank->nFireCount = TANK_FIRE_RATE;
- };
- };
- };
- };
- }
-
-
- /****************************************************************************
- TankCreate
-
- On entry : Tank
- : Scale
- : Clump
- */
-
- RwClump *_TankCreate(RwClump *cpClump,void *pData)
- {
- Tank *tpTank = (Tank *)pData;
-
- if (!tpTank->cpGun) {
- tpTank->cpGun = cpClump;
- } else {
- if (!tpTank->cpTurret) {
- tpTank->cpTurret = cpClump;
- };
- };
- return NULL;
- }
-
- void TankCreate(Tank *tpTank,RwReal nScale,RwClump *cpGeo)
- {
- MoveObjectCreate(&tpTank->moBase,nScale,cpGeo,TYPE_TANK,(void *)tpTank);
-
- RwIdentityMatrix(tpTank->mpTurretRotPos=RwCreateMatrix());
- RwIdentityMatrix(tpTank->mpGunRotPos=RwCreateMatrix());
-
- tpTank->nTurretAngle = CREAL(0.0);
-
- tpTank->cpGun = NULL; /* Mark as unused */
- tpTank->cpTurret = NULL; /* Mark as unused */
-
- RwForAllClumpsInHierarchyPointer(cpGeo,_TankCreate,(void *)tpTank);
-
- tpTank->nHit = TANK_HITS;
- tpTank->nFireCount = 0;
-
- TankGivePurpose(tpTank);
- }
-
- /****************************************************************************
- TankGunEndDirection
-
- On entry : Tank
- : (OUT) direction vector
- On exit :
- */
-
- void TankGunEndDirection(Tank *tpTank,
- RwV3d *vpEnd,
- RwV3d *vpDir)
- {
- RwV3d vTmp;
-
- RwPushScratchMatrix();
-
- vpEnd->x = CREAL(1.0);
- vpEnd->y = CREAL(0.0);
- vpEnd->z = CREAL(0.0);
-
- RwGetClumpLTM(tpTank->cpGun,RwScratchMatrix());
- RwTransformPoint(vpEnd,RwScratchMatrix());
-
- vTmp.x = CREAL(0.5);
- vTmp.y = CREAL(0.0);
- vTmp.z = CREAL(0.0);
-
- RwTransformPoint(&vTmp,RwScratchMatrix());
-
- RwSubtractVector(vpEnd,&vTmp,vpDir);
- RwNormalize(vpDir);
-
- RwPopScratchMatrix();
- }
-
- /****************************************************************************
- AllTanksLaunch
-
- On entry : AllTanks
- On exit :
- */
-
- void AllTanksLaunch(AllTanks *atpTanks)
- {
- int nAmoTanks;
- Tank *tpTank;
- RwReal nX,nZ,nXDist,nZDist;
- int nValue;
-
- tpTank = *(Tank **)StackData(&atpTanks->sUsed);
- nAmoTanks = StackElements(&atpTanks->sUsed);
-
- if (nAmoTanks<MIN_TANKS) {
- nValue = rand()&0xff;
- if (nValue<4) {
- nX = RMul(RDiv(INT2REAL(rand()&255),INT2REAL(255) ),
- gGGround.nWorldWidth);
- nZ = RMul(RDiv(INT2REAL(rand()&255),INT2REAL(255) ),
- gGGround.nWorldHeight);
-
- nXDist = tpTank->moBase.vPos.x-nX;
- nZDist = tpTank->moBase.vPos.z-nZ;
-
- if ((nXDist>RMul(INT2REAL(gGGround.nDispWidth/2),gGGround.nStepSize))||
- (nXDist<-RMul(INT2REAL(gGGround.nDispWidth/2),gGGround.nStepSize))||
- (nZDist>RMul(INT2REAL(gGGround.nDispHeight/2),gGGround.nStepSize))||
- (nZDist<-RMul(INT2REAL(gGGround.nDispHeight/2),gGGround.nStepSize))) {
-
- AllTanksAddTank(atpTanks,nX,nZ);
- };
- };
- };
- }
-
- /****************************************************************************
- AllTanksCreate
-
- On entry : AllTanks
- On exit :
- */
-
- void AllTanksCreate(AllTanks *atpTanks)
- {
- Tank *tpTanks;
- int nCount;
- char saFileNames[][10]={"tank.rwx",
- "tank.rwx"};
- int nNames = 2;
- RwClump *cpaClumps[MAX_TANKS];
-
- for (nCount = 0;nCount<nNames;nCount++) {
- cpaClumps[nCount] = RwReadShape(saFileNames[nCount]);
- };
-
- atpTanks->tpTanks = (Tank *) malloc(sizeof(Tank) *MAX_TANKS);
-
- StackCreate(&atpTanks->sFree,sizeof(Tank *),MAX_TANKS);
- StackCreate(&atpTanks->sUsed,sizeof(Tank *),MAX_TANKS);
-
- tpTanks = atpTanks->tpTanks;
- for (nCount =0;nCount<MAX_TANKS;nCount++) {
- TankCreate(tpTanks,TANK_SCALE,RwDuplicateClump(cpaClumps[nCount%nNames]));
-
- StackPush(&atpTanks->sFree,&tpTanks);
- tpTanks++;
- };
-
- for (nCount = 0;nCount<nNames;nCount++) {
- RwDestroyClump(cpaClumps[nCount]);
- };
- }
-
- /****************************************************************************
- AllTanksHandle
-
- On entry : AllTanks
- On exit :
- */
-
- void AllTanksHandle(AllTanks *atpTanks)
- {
- int nCount;
- Tank **tppTank;
- int nAmoTanks;
-
- tppTank = ((Tank **)StackData(&atpTanks->sUsed));
-
- nAmoTanks = StackElements(&atpTanks->sUsed);
-
- if (nGDemoMode) {
- nCount=0;
- } else {
- nCount=1;
- tppTank++;
- };
-
- for (nCount=1;nCount<nAmoTanks;nCount++) {
- TankAct((*tppTank));
- tppTank++;
- };
- }
-
- /****************************************************************************
- Tank Control
-
- On entry : TanksStructure
- : Operation
- : Param1
- On exit :
- */
-
- void TankControl(Tank *tpTank,
- int nOperation,
- RwReal nParam1)
- {
- RwV3d vTmp;
- RwV3d vPos,vDir;
-
- RwPushScratchMatrix();
-
- switch(nOperation) {
- case OP_ROT_BASE: {
- RwCopyMatrix(tpTank->moBase.mpPos,RwScratchMatrix());
- RwRotateMatrix(RwScratchMatrix(),CREAL(0),CREAL(1),CREAL(0),nParam1,
- rwPOSTCONCAT);
- RwCopyMatrix(RwScratchMatrix(),tpTank->moBase.mpPos);
- break;
- };
- case OP_MOVE: {
- vTmp.x = nParam1;
- vTmp.y = CREAL(0.0);
- vTmp.z = CREAL(0.0);
-
- RwTransformVector(&vTmp,tpTank->moBase.mpPos);
-
- tpTank->moBase.vPos.x+=vTmp.x;
- tpTank->moBase.vPos.z+=vTmp.z;
- break;
- };
- case OP_SET_TURRET: {
- tpTank->nTurretAngle=CREAL(0);
- /* Fall through !*/
- };
- case OP_ROT_TURRET: {
- tpTank->nTurretAngle+=nParam1;
-
- RwRotateMatrix(RwScratchMatrix(),CREAL(0),CREAL(1),CREAL(0),
- tpTank->nTurretAngle,rwREPLACE);
- RwTransformClumpJoint(tpTank->cpTurret,RwScratchMatrix(),rwREPLACE);
- break;
- };
- case OP_MOVE_GUN: {
- RwRotateMatrix(RwScratchMatrix(),CREAL(0),CREAL(0),CREAL(1),nParam1,
- rwREPLACE);
- RwTransformClumpJoint(tpTank->cpGun,RwScratchMatrix(),rwREPLACE);
- break;
- };
- case OP_FIRE: {
- TankGunEndDirection(tpTank,&vPos,&vDir);
-
- vPos.x = RAdd(vPos.x,gGGround.nXPos);
- vPos.z = RAdd(vPos.z,gGGround.nZPos);
- AllBulletsAddBullet(&abGBullets,&vPos,&vDir,tpTank);
- break;
- };
- default: {
- break;
- };
- };
-
- RwPopScratchMatrix();
- }
-
- /****************************************************************************
- AllTanksAddTank
-
- On entry : TanksStructure
- : Tank file name
- : Start x pos
- : start z pos
- On exit : 0 if all ok
- */
-
- int AllTanksAddTank(AllTanks *atpTanks,
- RwReal nXPos,
- RwReal nZPos)
- {
- MoveObject *mopTank;
- Tank *tpTank;
-
- if (!StackPop(&atpTanks->sFree,&tpTank)) {
- StackPush(&atpTanks->sUsed,&tpTank);
-
-
- tpTank->moBase.vPos.x = nXPos;
- tpTank->moBase.vPos.z = nZPos;
-
- tpTank->nHit = TANK_HITS;
-
- mopTank = &tpTank->moBase;
-
- StackPush(&amoGObjects.sDisplay,(void *)&mopTank);
-
- return 0;
- } else {
- return 1;
- };
- }
-
- /****************************************************************************
- AllTanksRemoveTank
-
- On entry : All Tanks
- : Tank to destroy
- On exit :
- */
-
- void AllTanksRemoveTank(AllTanks *atpTanks,
- Tank *tpTank)
- {
- MoveObject *mopTmp;
-
- /* Stop warnings */
-
- atpTanks = atpTanks;
-
- mopTmp = &tpTank->moBase;
-
- /* Remove from Display */
- StackPush(&amoGObjects.sDestroy,&mopTmp);
- }
-
- /****************************************************************************
- BulletCreate
-
- On entry : Bullet
- On exit :
- */
-
- void BulletCreate(Bullet *bpBull,RwReal nScale,RwClump *cpGeo)
- {
- MoveObjectCreate(&bpBull->moBase,nScale,cpGeo,TYPE_BULLET,(void *)bpBull);
- }
-
- /****************************************************************************
- AllBulletsCreate
-
- On entry : all bullets
- On exit :
- */
-
- void AllBulletsCreate(AllBullets *abpBull)
- {
- int nCount;
- Bullet *bpBull;
- RwClump *cpBullet,*cpClump;
-
- cpBullet = RwReadShape("shell.rwx");
-
- abpBull->bpBullets = malloc(sizeof(Bullet)*MAX_BULLETS);
-
- StackCreate(&abpBull->sUsed,sizeof(Bullet *),MAX_BULLETS);
- StackCreate(&abpBull->sFree,sizeof(Bullet *),MAX_BULLETS);
-
- bpBull = abpBull->bpBullets;
- for (nCount=0;nCount<MAX_BULLETS;nCount++) {
- cpClump = RwDuplicateClump(cpBullet);
- BulletCreate(bpBull,BULLET_SCALE,cpClump);
-
- StackPush(&abpBull->sFree,&bpBull);
- bpBull++;
- };
-
- RwDestroyClump(cpBullet);
- }
-
- /****************************************************************************
- AllBulletsAddBullet
-
- On entry : All bullets
- : Starting position
- : Direction of motion
- On exit :
- */
-
- int AllBulletsAddBullet(AllBullets *abpBull,
- RwV3d *vpPos,
- RwV3d *vpDir,
- Tank *tpTank)
- {
- Bullet *bpBull;
- MoveObject *mopBullet;
- RwReal naEle[4][4];
-
- if (!StackPop(&abpBull->sFree,&bpBull)) {
- StackPush(&abpBull->sUsed,&bpBull);
-
- bpBull->moBase.vPos = (*vpPos);
- bpBull->moBase.vVel = (*vpDir);
-
- bpBull->tpTank = tpTank;
-
- bpBull->nLife = BULLET_LIFE;
-
- /* Make the bullets clump face in the correct direction */
-
- RwIdentityMatrix(bpBull->moBase.mpPos);
- RwGetMatrixElements(bpBull->moBase.mpPos,naEle);
-
- *(RwV3d *)naEle[0] = (*vpDir);
- RwCrossProduct((RwV3d *)naEle[0],(RwV3d *)naEle[1],(RwV3d *)naEle[2]);
-
- RwSetMatrixElements(bpBull->moBase.mpPos,naEle);
- RwOrthoNormalizeMatrix(bpBull->moBase.mpPos,bpBull->moBase.mpPos);
-
- /* Find the Bullets speed */
-
- RwScaleVector(vpDir,BULLET_SPEED,vpDir);
- bpBull->moBase.vVel = (*vpDir);
-
- /* Place on the display stack */
-
- mopBullet = &bpBull->moBase;
- StackPush(&amoGObjects.sDisplay,(void *)&mopBullet);
- return 0;
- } else {
- return 1;
- };
- }
-
- /****************************************************************************
- AllBulletsRemoveBullet
-
- On entry : AllBullets
- : Bullet to remove
- On exit :
- */
-
- void AllBulletsRemoveBullet(AllBullets *abpBull,
- Bullet *bpBull)
- {
- MoveObject *mopTmp = &bpBull->moBase;
-
- /* Stop warnings */
-
- abpBull = abpBull;
-
- /* Remove from display */
-
- StackPush(&amoGObjects.sDestroy,&mopTmp);
- }
-
- /****************************************************************************
- AllBulletsHandle
-
- On entry : All Bullets
- On exit :
- */
-
- void AllBulletsHandle(AllBullets *abpBull)
- {
- Bullet **bppBull;
- Bullet *bpBull;
- int nAmoBullets;
- int nCount;
-
- bppBull = (Bullet **)StackData(&abpBull->sUsed);
- nAmoBullets = StackElements(&abpBull->sUsed);
-
- for (nCount=0;nCount<nAmoBullets;nCount++) {
- bpBull = (*bppBull);
- /* Handle it */
-
- bpBull->nLife--;
- if ((bpBull->nLife<0)||
- (bpBull->moBase.vPos.x<CREAL(0))||
- (bpBull->moBase.vPos.z<CREAL(0))||
- (bpBull->moBase.vPos.x>gGGround.nWorldWidth)||
- (bpBull->moBase.vPos.z>gGGround.nWorldHeight)) {
- /* Destroy the bullet */
- AllBulletsRemoveBullet(abpBull,bpBull);
- } else {
- RwAddVector(&bpBull->moBase.vPos,&bpBull->moBase.vVel,
- &bpBull->moBase.vPos);
- };
-
- bppBull++;
- };
-
- AllMoveObjClean(&amoGObjects);
- }
-
- /****************************************************************************
- GroundGetTextures
-
- On entry : Ground structure
- On exit :
- */
-
- void GroundGetTextures(Ground *gpGrou)
- {
- char saTextureFiles[][14]={
- "rough",
- "groad1",
- "groad2",
- "groad3"};
- int nAmoNames=4;
- int nCount;
-
- gpGrou->nAmoTextures = nAmoNames;
-
- for (nCount=0;nCount<gpGrou->nAmoTextures;nCount++) {
- gpGrou->tpaTex[nCount] = RwReadNamedTexture(saTextureFiles[nCount]);
- };
- }
-
- /****************************************************************************
- GroundGetThings
-
- ( It is assumed that all 'things' are normalised to 1.0 size )
-
- On entry : Ground structure
- On exit :
- */
-
- void GroundGetThings(Ground *gpGrou)
- {
- char saThingFiles[][14]={
- "tree.rwx",
- "tankhous.rwx",
- "tankhou2.rwx",
- "tree2.rwx"};
- RwReal naThingScale[]={
- CREAL(0.2),
- CREAL(0.3),
- CREAL(0.3),
- CREAL(0.25)};
- int nAmoThings=4;
- int nCount;
-
- gpGrou->nAmoThings = nAmoThings;
-
- for (nCount=0;nCount<nAmoThings;nCount++) {
- gpGrou->cpaGeo[nCount] = RwReadShape(saThingFiles[nCount]);
-
- gpGrou->naScale[nCount] = naThingScale[nCount];
- };
- }
-
- /****************************************************************************
- GroundCreateTiles
-
- On entry : Ground Structure
- : Ground texture map
- : Ground width
- : Ground height
- : Ground split
- */
-
- void GroundCreateTiles(Ground *gpGrou,
- char *cpGroundMap,
- char *cpThingMap,
- int nWidth,
- int nHeight,
- int nSplit)
- {
- RwClump *cpGeo;
- int nCount,nCount2;
- GroundEle *gepCur;
- int nX,nY;
- int nTex;
- char *cpCur;
- char *cpThing;
- StillObject *sopThing;
-
- gpGrou->pGround = (GroundEle *)
- malloc(sizeof(GroundEle)*nWidth*nHeight*nSplit*nSplit);
-
- gepCur = gpGrou->pGround;
- cpCur = cpGroundMap;
- cpThing = cpThingMap;
-
- gpGrou->nWidth = nWidth;
- gpGrou->nHeight = nHeight;
- gpGrou->nSplit = nSplit;
- gpGrou->nTexStep = RDiv(CREAL(1),INT2REAL(nSplit));
-
- for (nY=0;nY<nHeight;nY++) {
- for (nCount=0;nCount<nSplit;nCount++) {
- for (nX = 0; nX<nWidth;nX++) {
- for (nCount2=0;nCount2<nSplit;nCount2++) {
- nTex = (cpCur[nX])-'a';
-
- gepCur->tpTex = gpGrou->tpaTex[nTex];
- gepCur->uvPos.u = RDiv(INT2REAL(nCount2),INT2REAL(nSplit));
- gepCur->uvPos.v = RDiv(INT2REAL(nCount),INT2REAL(nSplit));
-
- /* Mark as no object on this square */
-
- if ((*cpThing)>' ') {
- sopThing = (StillObject *)malloc(sizeof(StillObject));
- gepCur->sopObj = sopThing;
-
- cpGeo = RwDuplicateClump(gpGrou->cpaGeo[(*cpThing)-'a']);
- StillObjectCreate(sopThing,gpGrou->naScale[(*cpThing)-'a'],cpGeo);
- sopThing->vPos.x += RDiv(gpGrou->nStepSize,CREAL(2));
- sopThing->vPos.z += RDiv(gpGrou->nStepSize,CREAL(2));
- } else {
- gepCur->sopObj= NULL;
- };
-
- cpThing++;
- gepCur++;
- };
- };
- };
- cpCur+=gpGrou->nWidth;
- };
- }
-
- /****************************************************************************
- AddGroundPoly
-
- On entry : Polygon
- : pointer to polygon data structure
- On exit :
- */
-
- RwPolygon3d *AddGroundPoly(RwPolygon3d *pPoly,void *pData);
-
- RwPolygon3d *AddGroundPoly(RwPolygon3d *pPoly,void *pData)
- {
- int nX;
- int nZ;
-
- Ground *gpGrou = (Ground *)pData;
- RwSetPolygonTextureModes(pPoly,rwFORESHORTEN);
-
- nZ = RwGetPolygonTag(pPoly)%(gpGrou->nDispWidth);
-
- nX = RwGetPolygonTag(pPoly)/(gpGrou->nDispWidth);
-
- gpGrou->paPolyData[nX+(nZ*gpGrou->nDispWidth)] = pPoly;
- return NULL;
- }
-
-
-
- /****************************************************************************
- GroundCreateClump
-
- On entry : Ground structure
- : Display width
- : Display height
- : Total size of the clump in world coordinates
- On exit :
- */
-
- void GroundCreateClump(Ground *gpGrou,
- int nDispWidth,
- int nDispHeight,
- RwReal nSize)
- {
- RwClump *cpGeo;
- int nX,nZ;
- RwReal nPosX,nPosZ;
- int nNum;
- RwMatrix4d *mpTmp;
-
- gpGrou->nDispWidth = nDispWidth;
- gpGrou->nDispHeight = nDispHeight;
- gpGrou->nSize = nSize;
- gpGrou->nStepSize = RDiv(nSize,INT2REAL(nDispWidth));
-
- RwModelBegin();
- RwClumpBegin();
- RwSetSurfaceColor(CREAL(1.0),CREAL(0.5),CREAL(0.0));
- RwSetSurface(CREAL(0.3),CREAL(0.4),CREAL(0.1));
- RwSetSurfaceLightSampling(rwFACET);
- RwSetSurfaceGeometrySampling(rwSOLID);
-
- RwSetHints(rwCONTAINER);
-
- nPosX = -RDiv(nSize,CREAL(2.0));
- for (nX = 0;nX <gpGrou->nDispWidth;nX++) {
- nPosZ = -RDiv(nSize,CREAL(2.0));
- for (nZ = 0;nZ<gpGrou->nDispHeight;nZ++) {
-
- RwVertex(nPosX,CREAL(0.0),nPosZ);
- RwVertex(nPosX,CREAL(0.0),RAdd(nPosZ,gpGrou->nStepSize));
- RwVertex(RAdd(nPosX,gpGrou->nStepSize),
- CREAL(0.0),RAdd(nPosZ,gpGrou->nStepSize));
- RwVertex(RAdd(nPosX,gpGrou->nStepSize),CREAL(0.0),nPosZ);
-
- nPosZ = RAdd(nPosZ,gpGrou->nStepSize);
- };
- nPosX = RAdd(nPosX,gpGrou->nStepSize);
- };
-
- /* Give it some depth ! */
-
- RwVertex(CREAL(0.0),CREAL(2.0),CREAL(0.0));
-
- for (nNum=0;nNum<(gpGrou->nDispWidth*gpGrou->nDispHeight);nNum++) {
- RwQuadExt((nNum<<2)+1,(nNum<<2)+2,(nNum<<2)+3,(nNum<<2)+4,nNum);
- };
-
- RwClumpEnd(&cpGeo);
- RwModelEnd();
-
- RwIdentityMatrix(mpTmp = RwCreateMatrix());
- RwTransformClump(cpGeo,mpTmp,rwREPLACE);
- RwTransformClumpJoint(cpGeo,mpTmp,rwREPLACE);
- RwDestroyMatrix(mpTmp);
-
- gpGrou->cpGeo = cpGeo;
-
- gpGrou->paPolyData = (RwPolygon3d **)malloc(sizeof(RwPolygon3d *)*
- gpGrou->nDispWidth*
- gpGrou->nDispHeight);
-
- RwForAllPolygonsInClumpPointer(cpGeo,AddGroundPoly,
- (void*)gpGrou);
- }
-
- /****************************************************************************
- GroundCreate
-
- On entry : Ground Structure
- : Ground map array
- : Ground texture array
- : Width
- : Height
- : Split (ie the amount of segments a texture is split to
- On exit :
- */
-
- void GroundCreate(Ground *gpGround)
- {
- char *cpThingMap;
- int nSize;
- int nCount;
-
- nSize = GROUND_WIDTH*GROUND_HEIGHT*GROUND_SPLIT*GROUND_SPLIT;
-
- cpThingMap = (char *)malloc(nSize);
- memset(cpThingMap,' ',nSize);
-
- for (nCount=0;nCount<40;nCount++) {
- cpThingMap[rand()&(nSize-1)] = 'a';
- };
-
- for (nCount=0;nCount<20;nCount++) {
- cpThingMap[rand()&(nSize-1)] = 'b';
- };
-
- for (nCount=0;nCount<20;nCount++) {
- cpThingMap[rand()&(nSize-1)] = 'c';
- };
-
- for (nCount=0;nCount<20;nCount++) {
- cpThingMap[rand()&(nSize-1)] = 'd';
- };
-
- RwIdentityMatrix(gpGround->mpPos=RwCreateMatrix());
-
- GroundGetTextures(gpGround);
- GroundGetThings(gpGround);
- GroundCreateClump(gpGround,GROUND_DISP_WIDTH,GROUND_DISP_HEIGHT,
- GROUND_SIZE);
- GroundCreateTiles(gpGround,sGGroundMap,cpThingMap,GROUND_WIDTH,GROUND_HEIGHT,GROUND_SPLIT);
-
- free(cpThingMap);
-
- gpGround->nWorldWidth =
- RMul(INT2REAL(gpGround->nWidth*gpGround->nSplit),gpGround->nStepSize);
- gpGround->nWorldHeight =
- RMul(INT2REAL(gpGround->nHeight*gpGround->nSplit),gpGround->nStepSize);
- }
-
- /****************************************************************************
- GroundDisplay
-
- On entry : Ground structure
- : Xcoord
- : Ycoord
- On exit :
- */
-
- void GroundDisplay(Ground *gpGrou,AllStillObj *asopObj,RwReal nX, RwReal nZ)
- {
- RwReal nXOff;
- RwReal nZOff;
- int nMapX;
- int nMapZ;
- int nCount,nCount2;
- RwPolygon3d **pPolys;
- GroundEle *gepCur;
- int nStride;
- RwUV uvaPos[4];
- RwReal nStepSize;
- StillObject **soppDisp;
- int nDisp;
- StillObject **soppToDisp;
- int nToDisp;
- RwReal nXStart;
- RwReal nZStart;
- RwReal nXPos;
- RwReal nZPos;
- Stack sTmp;
-
- if (nX<RDiv(gpGrou->nSize,CREAL(2)) ) {
- nX = RDiv(gpGrou->nSize,CREAL(2));
- };
- if (nZ<RDiv(gpGrou->nSize,CREAL(2)) ) {
- nZ = RDiv(gpGrou->nSize,CREAL(2));
- };
-
- if (nX> gpGrou->nWorldWidth-RDiv(gpGrou->nSize,CREAL(2)) ) {
- nX = gpGrou->nWorldWidth-RDiv(gpGrou->nSize,CREAL(2));
- };
-
- if (nZ> gpGrou->nWorldWidth-RDiv(gpGrou->nSize,CREAL(2)) ) {
- nZ = gpGrou->nWorldWidth-RDiv(gpGrou->nSize,CREAL(2));
- };
-
- gpGrou->nXPos = nX;
- gpGrou->nZPos = nZ;
-
- nStepSize = (gpGrou->nStepSize);
-
- nXOff = RDiv(RSub(nX,RDiv(gpGrou->nSize,CREAL(2))),nStepSize);
- nZOff = RDiv(RSub(nZ,RDiv(gpGrou->nSize,CREAL(2))),nStepSize);
-
- nMapX = REAL2INT(nXOff);
- nMapZ = REAL2INT(nZOff);
-
- nXOff = RMul(RSub(nXOff,INT2REAL(nMapX)),nStepSize);
- nZOff = RMul(RSub(nZOff,INT2REAL(nMapZ)),nStepSize);
-
- nXStart = -nXOff;
- nZStart = -nZOff;
-
- RwTranslateMatrix(gpGrou->mpPos, nXStart,CREAL(0),nZStart,rwREPLACE);
-
- RwTransformClump(gpGrou->cpGeo,gpGrou->mpPos,rwREPLACE);
-
- nXStart = RSub(nXStart,RDiv(gpGrou->nSize,CREAL(2)) );
- nZStart = RSub(nZStart,RDiv(gpGrou->nSize,CREAL(2)) );
-
- nStride = gpGrou->nWidth*gpGrou->nSplit;
-
- pPolys = gpGrou->paPolyData;
- gepCur = gpGrou->pGround + (nMapX+(nMapZ*nStride));
-
- StackClear(&asopObj->sStillToDisplay);
-
- RwPushScratchMatrix();
- RwIdentityMatrix(RwScratchMatrix());
-
- nZPos = nZStart;
- for (nCount2=0;nCount2<gpGrou->nDispHeight;nCount2++) {
- nXPos = nXStart;
- for (nCount=0;nCount<gpGrou->nDispWidth;nCount++) {
-
- RwSetPolygonTexture((*pPolys),gepCur->tpTex);
- uvaPos[0] = gepCur->uvPos;
- uvaPos[1] = gepCur->uvPos;
- uvaPos[1].v= RAdd(uvaPos[1].v,gpGrou->nTexStep);
- uvaPos[2] = uvaPos[1];
- uvaPos[2].u = RAdd(uvaPos[2].u,gpGrou->nTexStep);
- uvaPos[3] = uvaPos[2];
- uvaPos[3].v= RSub(uvaPos[3].v,gpGrou->nTexStep);
-
- RwSetPolygonUV((*pPolys),uvaPos);
-
- if (gepCur->sopObj) {
- RwTranslateMatrix(RwScratchMatrix(),
- RAdd(nXPos,gepCur->sopObj->vPos.x),
- gepCur->sopObj->vPos.y,
- RAdd(nZPos,gepCur->sopObj->vPos.z),
- rwREPLACE);
- RwTransformClump(gepCur->sopObj->cpGeo, RwScratchMatrix(), rwREPLACE);
-
- StackPush(&asopObj->sStillToDisplay,&gepCur->sopObj);
- };
-
- nXPos += gpGrou->nStepSize;
- pPolys++;
- gepCur++;
- };
- nZPos += gpGrou->nStepSize;
- gepCur+=nStride-gpGrou->nDispWidth;
- };
-
- RwPopScratchMatrix();
-
- /* Do the adding and removing of clumps to the scene */
-
- /* Sort the stacks for later comparison */
-
- qsort(StackData(&asopObj->sStillToDisplay),
- StackElements(&asopObj->sStillToDisplay),sizeof(StillObject **),_AllMoveObjDisplay);
-
- /* Find what needs to be added and removed from scene */
-
- soppToDisp = (StillObject **) StackData(&asopObj->sStillToDisplay);
- nToDisp = StackElements(&asopObj->sStillToDisplay);
-
- soppDisp = (StillObject **)StackData(&asopObj->sStillDisplayed);
- nDisp = StackElements(&asopObj->sStillDisplayed);
-
- while (nToDisp&&nDisp) {
- if ((*soppDisp)==(*soppToDisp)) {
- soppDisp++;
- soppToDisp++;
- nToDisp--;
- nDisp--;
- } else {
- if ((*soppDisp)<(*soppToDisp)) {
- RwRemoveClumpFromScene((*soppDisp)->cpGeo);
-
- nDisp--;
- soppDisp++;
- } else {
- RwAddClumpToScene(Scene,(*soppToDisp)->cpGeo);
-
- nToDisp--;
- soppToDisp++;
- };
- };
- };
-
- if (nDisp) {
- for (;nDisp;nDisp--) {
- RwRemoveClumpFromScene((*soppDisp)->cpGeo);
- soppDisp++;
- };
- };
-
- if (nToDisp) {
- for (;nToDisp;nToDisp--) {
- RwAddClumpToScene(Scene,(*soppToDisp)->cpGeo);
- soppToDisp++;
- };
- };
-
- /* Switch stacks - to remove a qsort!*/
-
- sTmp = asopObj->sStillDisplayed;
- asopObj->sStillDisplayed = asopObj->sStillToDisplay;
- asopObj->sStillToDisplay = sTmp;
- }
-
- /****************************************************************************
- StackCreate
-
- On entry : Pointer to stack structure
- On exit : 0 if all went to plan
- */
-
- int StackCreate(Stack *spStack,int nEleSize,int nAmoEle)
- {
- if (!(spStack->pData = (char *) malloc (nEleSize*nAmoEle))) {
- return 1;
- };
- spStack->nCurElement = 0;
- spStack->pCurPtr = spStack->pData;
- spStack->nAmoElements = nAmoEle;
- spStack->nElementSize = nEleSize;
-
- return 0;
- }
-
- /****************************************************************************
- StackClear
-
- emptys the stack
-
- On entry : Stack to clear
- */
-
- void StackClear(Stack *spStack)
- {
- spStack->nCurElement = 0;
- spStack->pCurPtr = spStack->pData;
- }
-
- /****************************************************************************
- StackData
-
- On entry : Stack
- On exit : Stacks contents as an array bottom element first
- */
-
- void *StackData(Stack *spStack)
- {
- return spStack->pData;
- }
-
-
- /****************************************************************************
- StackElements
-
- On entry : Stack
- On exit : Amount of entries in the stack
- */
-
- int StackElements(Stack *spStack)
- {
- return spStack->nCurElement;
- }
-
- /****************************************************************************
- StackFront
-
- On entry : Stack
- : Element too stick on the bottom of the stack
- On exit : Pointer to entry on stack,NULL for fail
- */
-
- void *StackFront(Stack *spStack,void *pData)
- {
- char *pTmp;
- int nCount;
-
- if (spStack->nCurElement==spStack->nAmoElements) {
- return NULL;
- } else {
- pTmp = spStack->pCurPtr;
-
- for (nCount=0;nCount<spStack->nCurElement;nCount++) {
- memcpy(pTmp,pTmp-spStack->nElementSize,spStack->nElementSize);
- pTmp -= spStack->nElementSize;
- };
-
- memcpy(spStack->pData,pData,spStack->nElementSize);
-
- spStack->pCurPtr+=spStack->nElementSize;
- spStack->nCurElement++;
-
- return spStack->pData;
- };
- }
-
- /****************************************************************************
- StackDestroy
-
- On entry : Stack
- On exit : 0 if all went to plan
- */
-
- int StackDestroy(Stack *spStack)
- {
- free(spStack->pData);
-
- return 0;
- }
-
- /****************************************************************************
- StackPush
-
- On entry : Stack
- : Pointer to element to push
- On exit : Pointer to Saved object if all ok else NULL
- */
-
- void *StackPush(Stack *spStack,void *pData)
- {
- void *pSave;
-
- if (spStack->nCurElement==spStack->nAmoElements) {
- return NULL;
- } else {
- pSave = spStack->pCurPtr;
- memcpy(pSave,pData,spStack->nElementSize);
-
- spStack->pCurPtr+=spStack->nElementSize;
- spStack->nCurElement++;
-
- return pSave;
- };
- }
-
- /****************************************************************************
- StackPop
-
- On entry : Stack
- On exit : 0 if all ok
- */
-
- int StackPop(Stack *spStack,void *pData)
- {
- if (!spStack->nCurElement) {
- return 1;
- } else {
- spStack->nCurElement--;
- spStack->pCurPtr-=spStack->nElementSize;
-
- memcpy(pData,spStack->pCurPtr,spStack->nElementSize);
- return 0;
- };
- }
-
- /****************************************************************************
- StackTop
-
- On entry : Stack
- On exit : 0 if all ok
- */
-
- int StackTop(Stack *spStack,void *pData)
- {
- if (!spStack->nCurElement) {
- return 1;
- } else {
- memcpy(pData,
- spStack->pCurPtr-spStack->nElementSize,spStack->nElementSize);
- return 0;
- };
- }
-
- /****************************************************************************
- StackForAll
-
- Goes from top of stack to bottom
-
- On entry : Stack
- : Function to be called
- : Pointer to user data
- */
-
- void StackForAll(Stack *spStack,void (*Func)(void *pData,void *pUser),
- void *pUser)
- {
- char *pData;
- int nCount;
-
- pData = spStack->pCurPtr-spStack->nElementSize;
- for (nCount=spStack->nCurElement;nCount--;nCount) {
- (*Func)(pData,pUser);
- pData-=spStack->nElementSize;
- };
- }
-
- /****************************************************************************
- StackRemove
-
- Removes an entry from the stack
-
- On entry : Stack
- : Element to remove
- On exit : 0 if all ok
- */
-
- int StackRemove(Stack *spStack,void *pEle)
- {
- char *pData=(char *)pEle;
-
- while (pData!=(spStack->pCurPtr-spStack->nElementSize)) {
- memcpy(pData,pData+spStack->nElementSize,spStack->nElementSize);
- pData+=spStack->nElementSize;
- };
-
- spStack->pCurPtr-=spStack->nElementSize;
- spStack->nCurElement--;
-
- return 0;
- }
-
- /****************************************************************************
- StackFind
-
- On entry : Stack
- : Data entry to find
- On exit : Pointer to element (NULL if not found)
- */
-
- void *StackFind(Stack *spStack,void *pEle)
- {
- int nCount,nCount2;
- char *pData,*pData2 = (char *)pEle;
-
- pData = spStack->pData;
-
- for (nCount=0;nCount<spStack->nCurElement;nCount++) {
- for (nCount2=0;nCount2<spStack->nElementSize;nCount2++) {
- if (pData[nCount2] != pData2[nCount2]) {
- break;
- };
- };
-
- if (nCount2>=spStack->nElementSize) {
- return pData;
- };
-
- pData+=spStack->nElementSize;
- };
-
- return NULL;
- }
-
- /***************************************************************************
- RandomVec - create a random vector
-
- On entry : Random vector to create
- On exit :
- */
-
- static void RandomVec(RwV3d *vec)
- {
- vec->x = RSub(RDiv(INT2REAL(rand()),CREAL(16384.0)), CREAL(1.0));
- vec->y = RSub(RDiv(INT2REAL(rand()),CREAL(16384.0)), CREAL(1.0));
- vec->z = RSub(RDiv(INT2REAL(rand()),CREAL(16384.0)), CREAL(1.0));
- }
-
- /****************************************************************************
- DosShiftCtrl
-
- On entry :
- On exit : Bit Meaning
- 0 Right Shift
- 1 Left Shift
- 2 Ctrl
- 3 Alt
- 4 Scroll Lock
- 5 Num Lock
- 6 Caps Lock
- 7 Insert on
- */
-
- int DosShiftCtrl(void)
- {
- union REGPACK rp;
-
- memset(&rp,0,sizeof(rp));
-
- rp.h.ah=0x02;
- intr(0x16,&rp);
-
- return ((int)rp.h.al);
- }
-
-
- /****************************************************************************
- DosPrintString
-
- On entry : xcord
- : ycord
- : string
- : colour
- On exit :
- */
-
- void DosPrintString(int nX,int nY,char *sString,int nCol)
- {
- RwPrintChar pcPrint;
-
- pcPrint.x = nX;
- pcPrint.y = nY;
- pcPrint.color = nCol;
-
- for (;(*sString);sString++) {
- pcPrint.c = (*sString);
- RwDeviceControl(rwPRINTCHAR,0,&pcPrint,sizeof(pcPrint));
- pcPrint.x+=8;
- };
- }
-
-
- /****************************************************************************
- DosGetKey
-
- Get the ascii key code of any depressed key. (Do not wait for a key press.
- -> return 0 if no key is pressed)
-
- On entry :
- On exit : Key pressed in ascii (or 0 if no key pressed)
- */
-
- int DosGetKey(void)
- {
- union REGPACK rp;
-
- memset(&rp,0,sizeof(rp));
- rp.h.ah = 0x06;
- rp.h.dl = 0xff;
-
- intr(0x21,&rp);
-
- if (!(rp.w.flags & 0x40 )) { /* Check Z flag */
- /* Got key */
-
- if (rp.h.al) {
- return ((int)rp.h.al);
- };
-
- memset(&rp,0,sizeof(rp));
- rp.h.ah = 0x06;
- rp.h.dl = 0xff;
- intr(0x21,&rp);
-
- if (!(rp.w.flags & 0x40)) {
- return ((int)rp.h.al);
- };
-
- return (rp.h.al|0x80);
- };
-
- return 0;
- }
-
-
- /**********************************************************************/
-
- /*
- * This function initializes the 3D (i.e. RenderWare) components of the
- * application. This function opens the RenderWare library, creates a
- * camera, a scene, a light and a matrix for spinning. A user-draw may
- * also be created if USERDRAW_LABELS is defined.
- */
- static BOOL
- Init3D(char *sFilename)
- {
- char windowText[128];
- char version[30];
- char buffer[128];
- int param;
- int i;
- RwReal naWhite[]={CREAL(1.0),CREAL(1.0),CREAL(1.0)};
- long nError;
- RwRaster *rpRaster;
-
- /*
- * Attempt to open (and initialize) the RenderWare library.
- */
- if (!RwOpen("DOSMOUSE", &nError))
- {
- printf("Unable to access renderware!!\n");
- switch (nError) {
- case E_RW_DOS_MODE_UNAVAILABLE: {
- printf("The installed VESA card is unable to switch to the resolution");
- printf(" requested.\n");
- printf("Either install a different video adapter or use a ");
- printf("supported video mode.");
- break;
- };
- case E_RW_DOS_NO_VESA_BIOS: {
- printf("A VESA bios is unavailable on this machine.\n");
- printf("Either use a VESA compatible Video Adapter or install a ");
- printf("VESA bios emulation TSR.\n");
- break;
- };
- case E_RW_DOS_INCOMPATIBLE_BIOS: {
- printf("The VESA bios on this machine is not of high enough version ");
- printf("to function\ncorrectly with RenderWare. Use a version 1.0 or");
- printf(" higher VESA bios or TSR.\n");
- break;
- };
- case E_RW_DOS_NO_MOUSE: {
- printf("No Microsoft compatible mouse driver present.\n");
- printf("Install a microsoft compatible mouse driver and try again.\n");
- break;
- };
- default: {
- printf("Unknown Error !!!!!!!!!!!!!!!\n");
- break;
- };
- };
- return FALSE;
- }
-
- /* Set up character set */
-
- RwGetDeviceInfo(rwSCRHEIGHT,&nGScrHeight,sizeof(nGScrHeight));
- RwGetDeviceInfo(rwSCRWIDTH,&nGScrWidth,sizeof(nGScrWidth));
- nGTextColour = RwDeviceControl(rwSCRGETCOLOR,0,naWhite,sizeof(naWhite));
-
- /*--- Only look for scripts and textures in subdirectories under the current
- one. RWSHAPEPATH need not be set then */
-
- RwSetShapePath(".",rwPRECONCAT);
-
- strcpy(buffer,sFilename);
-
- i = strlen(buffer);
- while((buffer[i] != '\\')&&(i>=0)) {
- i--;
- };
-
-
- if (i>=0) {
- buffer[i+1] = 0;
- strcat(buffer, "TEXTURES");
- RwSetShapePath(buffer, rwPOSTCONCAT);
-
- buffer[i+1] = 0;
- strcat(buffer, "SCRIPTS");
- RwSetShapePath(buffer, rwPOSTCONCAT);
- };
-
- RwSetShapePath("SCRIPTS", rwPRECONCAT);
- RwSetShapePath("TEXTURES", rwPRECONCAT);
-
-
- /*
- * Label the display with information about the version of
- * RenderWare being used. Its rather unlikely that
- * RwGetSystemInfo() will fail so we ignore its return value.
- */
- RwGetSystemInfo(rwVERSIONSTRING, &version,sizeof(version));
- RwGetSystemInfo(rwFIXEDPOINTLIB, ¶m,sizeof(param));
- sprintf(windowText, "DosTank V%s %s",
- version, (param ? "Fixed" : "Float"));
- DosPrintString(0,nGScrHeight-16,windowText,nGTextColour);
-
- /*
- * Create the camera which will be used for rendering.
- */
-
- Camera = RwCreateCamera(nGScrWidth,nGScrHeight-24, NULL);
- if (!Camera)
- {
- /*
- * As with RwOpen(), the most common cause for a failure to create
- * a camera is insufficient memory so we will explicitly check for
- * this condition and report it. Otherwise a general error is issued.
- */
- if (RwGetError() == E_RW_NOMEM)
- {
- RwClose();
- printf("Insufficient memory to create the RenderWare(tm) camera\n");
- }
- else
- {
- RwClose();
- printf("Error creating the RenderWare(tm) camera\n");
- }
- exit(-1);
- }
-
- RwSetCameraViewport(Camera, 0, 0, nGScrWidth, nGScrHeight-24);
-
-
-
- /*
- * Set the camera's background color to blue.
- */
- RwSetCameraBackColor(Camera, CREAL(0.0), CREAL(0.0), CREAL(0.3));
-
- /*
- * By default, the camera lies on the X-Z plane and points down Z
- * into the screen. We shall retain the camera's orientation, but move
- * the camera DEFAULT_CAMERA_DISTANCE units down Z away from the screen.
- */
-
- RwVCMoveCamera(Camera, CREAL(0.0), CREAL(2.0), CameraDistance);
-
- /*
- * Another change from previous versions of RenderWare is the amount of
- * prespective generated by the default viewwindow size. When converting
- * applications from previous versions of RenderWare the simple rule is
- * to divide the viewwindow size by five to get the same prespective effect
- * as given under previous versions.
- */
- if (nGScrWidth >= nGScrHeight) {
- RwSetCameraViewwindow(Camera,
- CREAL(1.0),
- RMul(CREAL(1.0),
- RDiv(INT2REAL(nGScrHeight),
- INT2REAL(nGScrWidth))));
- } else {
- RwSetCameraViewwindow(Camera,
- RMul(CREAL(1.0),
- RDiv(INT2REAL(nGScrWidth),
- INT2REAL(nGScrHeight))),
- CREAL(1.0));
- };
-
- /*
- * Create a scene which will contain the clumps to be rendered and the
- * light or lights illuminating those clumps . In this very simple
- * application it would be perfectly acceptable to use the default scene
- * (as returned by RwDefaultScene()) for rendering. However, it is good
- * practice to always create a scene which will be used for your rendering
- * and only use the default scene as a bag for currently unused clumps and
- * lights.
- */
-
- Scene = RwCreateScene();
- if (!Scene)
- {
- RwDestroyCamera(Camera);
- RwClose();
- printf("Error creating the RenderWare(tm) scene\n");
- exit(-1);
- }
-
- /*
- * Our scene will be illuminated by a directional light. The illumination
- * vector of the light is (-1.0, -1.0, -1.0) and its brightness will be 1.0.
- */
-
- Light = RwCreateLight(rwDIRECTIONAL, CREAL(-1.0), CREAL(-1.0), CREAL(-1.0),
- CREAL(1.0));
- if (!Light)
- {
- RwDestroyScene(Scene);
- RwDestroyCamera(Camera);
- RwClose();
- printf("Error creating the RenderWare(tm) light\n");
- exit(-1);
- }
-
- /*
- * Add the new light to our scene.
- */
- RwAddLightToScene(Scene, Light);
-
- /* Add backdrop */
-
- rpRaster = RwReadRaster("mount.bmp",rwGAMMARASTER|rwDITHERRASTER);
-
- if (rpRaster) {
- /* Make it the backdrop */
- RwSetCameraBackdrop(Camera,rpRaster);
- RwSetCameraBackdropViewportRect(Camera,0,0,nGScrWidth,nGScrHeight-24);
- };
-
- /*
- * All the 3D components are now successfully initialized, so
- * work can begin...
- */
-
- return TRUE;
- }
-
- /**********************************************************************/
-
- /*
- * This function shuts down the 3D (i.e. RenderWare) components of the
- * application in a polite fashion.
- */
-
- static void
- TidyUp3D()
- {
-
- /*
- * Destroy the scene. This will destroy the contents of the scene,
- * i.e. any clumps and lights in that scene. In this case destroying
- * the scene will destroy the light we created in Init3D, and any
- * clumps we have loaded and not already destroyed.
- */
- RwDestroyScene(Scene);
-
- /*
- * Destroy the camera.
- */
- RwDestroyCamera(Camera);
-
- /*
- * Close the library. This will free up any internal resources and
- * textures loaded.
- */
- RwClose();
- }
-
- /****************************************************************************
- DisplayMode
-
- On entry :
- On exit :
- */
-
- void DisplayMode(void)
- {
- if (nGDemoMode) {
- DosPrintString(0,nGScrHeight-8,"Demo Mode On ",nGTextColour);
- } else {
- DosPrintString(0,nGScrHeight-8,"Demo Mode Off",nGTextColour);
- };
- }
-
- /**********************************************************************/
-
- /*
- * This functions handles the left mouse button going down. Its main
- * job is to determine the kind of action to be taken when the mouse
- * moves, such as spinning a clump, or panning the camera. This involves
- * examining the virtual keys that were depressed when the mouse button
- * went down and attempting to pick a clump under the mouse pointer
- * position.
- */
- static void
- HandleLeftButtonDown(int x, int y, int vKeys)
- {
- /* Stop warnings */
-
- x=x;
- vKeys = vKeys;
-
- bButtonDown |=1;
-
- if (y>nGScrHeight-8) {
- if (nGDemoMode) {
- nGDemoMode = 0;
- DisplayMode();
- } else {
- nGDemoMode = 1;
- DisplayMode();
- };
- };
- }
-
- /**********************************************************************/
-
- /*
- * This functions handles the right mouse button going down. Its main
- * job is to determine the kind of action to be taken when the mouse
- * moves such as panning the camera.
- */
- static void
- HandleRightButtonDown(int x, int y, int vKeys)
- {
- /* Stop warnings */
-
- x=x;
- y=y;
- vKeys = vKeys;
-
- bButtonDown |= 2;
- if (!nGFireCount) {
- nGFireCount = FIRE_TIME;
- };
- }
-
-
- /**********************************************************************/
-
- /*
- * Handle the left mouse button comming back up. The basic action is
- * to turn off mouse move actions and release mouse capture.
- */
-
- static void
- HandleLeftButtonUp(void)
- {
- bButtonDown &= ~1;
- }
-
- /**********************************************************************/
-
- /*
- * Handle the right mouse button comming back up. The basic action is
- * to turn of mouse move actions and release mouse capture.
- */
- static void
- HandleRightButtonUp(void)
- {
- bButtonDown &= ~2;
- }
-
- /*************************************************************************
- DisplayBound
-
- On entry : Display
- On exit :
- */
-
- void DisplayBound(Display *dpDisp)
- {
- RwV3d vPos;
-
- RwGetCameraPosition(Camera,&vPos);
-
- if (vPos.y<dpDisp->nMinHeight) {
- vPos.y = dpDisp->nMinHeight;
- };
-
- if (vPos.x>dpDisp->nMaxX) {
- vPos.x = dpDisp->nMaxX;
- };
- if (vPos.x<-dpDisp->nMaxX) {
- vPos.x = -dpDisp->nMaxX;
- };
-
- if (vPos.z>dpDisp->nMaxZ) {
- vPos.z = dpDisp->nMaxZ;
- };
- if (vPos.z<-dpDisp->nMaxZ) {
- vPos.z = -dpDisp->nMaxZ;
- };
-
- RwSetCameraPosition(Camera,vPos.x,vPos.y,vPos.z);
- }
-
- /****************************************************************************
- TrackbackdropToCamera
-
- On entry : CAmera
- On exit :
- */
-
- static BOOL
- TrackBackdropToCamera(RwCamera *camera)
- {
- RwRaster *backdrop;
- int backdropWidth;
- int backdropHeight;
- RwV3d at;
- RwReal angle;
- int xOffset;
- int yOffset;
- RwInt32 windowWidth;
- RwInt32 windowHeight;
-
- backdrop = RwGetCameraBackdrop(camera);
-
- /*
- * No-op if the camera has no backdrop.
- */
- if (backdrop != NULL)
- {
- /*
- * Get the window and backdrop dimensions.
- */
- RwGetCameraViewport(camera, NULL, NULL, &windowWidth, &windowHeight);
-
- backdropWidth = RwGetRasterWidth(backdrop);
- backdropHeight = RwGetRasterHeight(backdrop);
-
- /*
- * We use the look at vector for determining both
- * horizontal and vertical positioning.
- */
- RwGetCameraLookAt(camera, &at);
-
- /*
- * Compute the horizontal position. This is done
- * by compute the camera's angle of rotate about
- * the Z axis. The angle is then directly converted
- * into a horizontal backdrop offset.
- */
-
- /*
- * Compute the angle in the range 0 => PI.
- */
- at.y = CREAL(0.0);
- RwNormalize(&at);
- if (at.z > CREAL(1.0))
- at.z = CREAL(1.0);
- else if (at.z < CREAL(-1.0))
- at.z = CREAL(-1.0);
- angle = FL2REAL(acos(REAL2FL(at.z)));
-
- /*
- * Get the angle in the range 0 => 2 PI
- */
- if (at.x < CREAL(0.0))
- angle = RSub(CREAL(M_2PI), angle);
-
- /*
- * The backdrop X offset is derived simply from
- * the angle computed above.
- */
- xOffset = -REAL2INT(RDiv(RMul(angle, INT2REAL(backdropWidth)), CREAL(M_2PI)));
-
- /*
- * Compute the vertical position. This is done by getting
- * the angle between the look at vector and the Y axis. We
- * simply use the dot product (cosine of the angle) multiplied
- * by a scale factor to compute the vertical offset.
- */
- RwGetCameraLookAt(Camera, &at);
- yOffset = REAL2INT(RAdd(INT2REAL(windowHeight / 2), RMul(RMul(at.y, CREAL(1.5)), INT2REAL(windowHeight / 2)))) - (backdropHeight / 2);
-
- yOffset-=30;
-
- RwSetCameraBackdropOffset(Camera, xOffset, 0);
- RwSetCameraBackdropViewportRect(Camera, 0, yOffset, windowWidth, backdropHeight);
- }
- return TRUE;
- }
-
-
- /**********************************************************************/
-
- /*
- * Handle MS Window's timer expiry. This function will perform any
- * animation actions necessary, including spinning clumps and animating
- * textures.
- */
- static void
- HandleTimer(void) {
- Tank *tpTank;
- RwV3d vAt,vPos;
- RwReal naEle[4][4];
-
- /* Hanle Computer controlled tanks */
-
- AllTanksLaunch(&atGTanks);
-
- AllTanksHandle(&atGTanks);
-
- AllMoveObjCollisionStill(&amoGObjects,&gGGround);
-
- AllMoveObjCollision(&amoGObjects);
- AllBulletsHandle(&abGBullets);
- AllBitsHandle(&abGBits);
-
-
- /* Handle the display */
-
- tpTank = *((Tank **)StackData(&atGTanks.sUsed));
-
- switch (dGDisplay.nDisplayMode) {
- case DISPLAY_FLOAT: {
- RwPushScratchMatrix();
-
- RwRotateMatrix(RwScratchMatrix(),
- CREAL(0),CREAL(1),CREAL(0),CREAL(2),rwREPLACE);
- RwGetCameraPosition(Camera,&vPos);
- RwTransformVector(&vPos,RwScratchMatrix());
- RwSetCameraPosition(Camera,vPos.x,vPos.y,vPos.z);
-
- RwSetCameraLookUp(Camera,CREAL(0.0),CREAL(1.0),CREAL(0.0));
- RwPointCamera(Camera,CREAL(0.0),CREAL(0.0),CREAL(0.0));
-
- GroundDisplay(&gGGround,&asoGObjects,
- tpTank->moBase.vPos.x,
- tpTank->moBase.vPos.z );
- RwPopScratchMatrix();
- break;
- };
- case DISPLAY_FIRST: {
- vAt.x = CREAL(1.0);
- vAt.y = CREAL(0.0);
- vAt.z = CREAL(0.0);
-
- RwTransformVector(&vAt,tpTank->moBase.mpPos);
-
- RwSetCameraLookAt(Camera,vAt.x,vAt.y,vAt.z);
- RwSetCameraLookUp(Camera,CREAL(0.0),CREAL(1.0),CREAL(0.0));
- RwSetCameraPosition(Camera,CREAL(0.0),RDiv(TANK_SCALE,CREAL(2)),CREAL(0.0));
-
- GroundDisplay(&gGGround,&asoGObjects,
- tpTank->moBase.vPos.x,tpTank->moBase.vPos.z);
- break;
- };
- case DISPLAY_OUTSIDE: {
- GroundDisplay(&gGGround,&asoGObjects,
- tpTank->moBase.vPos.x,tpTank->moBase.vPos.z);
- break;
- };
- case DISPLAY_BEHIND: {
- RwPushScratchMatrix();
- RwGetClumpMatrix(tpTank->moBase.cpGeo,RwScratchMatrix());
- RwTranslateMatrix(RwScratchMatrix(),
- CREAL(0),
- RDiv(tpTank->moBase.nSize,CREAL(2)),
- CREAL(0),
- rwPOSTCONCAT);
- RwRotateMatrix(RwScratchMatrix(),
- CREAL(0),CREAL(1),CREAL(0),CREAL(-90),rwPOSTCONCAT);
-
- RwGetMatrixElements(RwScratchMatrix(),naEle);
-
-
- RwSetCameraPosition(Camera,naEle[3][0],naEle[3][1],naEle[3][2]);
- RwSetCameraLookAt(Camera,-naEle[2][0],-naEle[2][1],-naEle[2][2]);
- RwSetCameraLookUp(Camera,naEle[1][0],naEle[1][1],naEle[1][2]);
-
- RwPopScratchMatrix();
- RwPanCamera(Camera,dGDisplay.nBehindPan);
- RwTiltCamera(Camera,dGDisplay.nBehindTilt);
-
- RwVCMoveCamera(Camera,CREAL(0),
- CREAL(0),
- dGDisplay.nBehindDist);
-
- GroundDisplay(&gGGround,&asoGObjects,
- tpTank->moBase.vPos.x,tpTank->moBase.vPos.z);
- break;
- };
- default: {
- break;
- };
- };
-
- /* Place in ground plane boundary */
-
- AllMoveObjBound(&amoGObjects,&gGGround);
-
- /* Add to scene as necessary */
-
- AllMoveObjDisplay(&amoGObjects,&gGGround);
- AllMoveObjDisplay(&amoGBits,&gGGround);
-
- /*
- * Animate textures. Enumerate over all the textures in the texture
- * dictionary stack calling RwTextureNextFrame() to bump the
- * current frame pointer of each texture. For single frame textures
- * this is a no-op.
- */
-
- RwForAllNamedTextures(RwTextureNextFrame);
-
- TrackBackdropToCamera(Camera);
-
- /*
- * See the description of HandlePaint() for a description of this common
- * RenderWare cliche for rendering a scene and copying it to the display.
- */
- RwBeginCameraUpdate(Camera,NULL);
- RwClearCameraViewport(Camera);
- RwRenderScene(Scene);
- RwEndCameraUpdate(Camera);
- RwShowCameraImage(Camera, NULL);
-
- nGFrameNumber++;
- }
-
- /****************************************************************************
- TankMouseControl
-
- On entry : Mouse X
- : Mouse Y
- On exit :
- */
-
- void TankMouseControl(int nX,int nY)
- {
- Tank *tpTank;
-
- if (!nGDemoMode) {
- tpTank = *((Tank **)StackData(&atGTanks.sUsed));
-
- if (bButtonDown&1) {
- TankControl(tpTank,OP_ROT_BASE,
- RMul(RDiv(INT2REAL(nX),INT2REAL(nGScrWidth))-CREAL(0.5),CREAL(-5)) );
-
- TankControl(tpTank,OP_MOVE,
- RMul(RDiv(INT2REAL(nY),INT2REAL(nGScrHeight))-CREAL(0.5),CREAL(-0.04)) );
- };
-
- if (nGFireCount==FIRE_TIME) {
- TankControl(tpTank,OP_FIRE,CREAL(0));
- };
-
- if (nGFireCount) {
- nGFireCount--;
- };
- };
- }
-
- /****************************************************************************
- Handle Mouse Move
-
- On entry : Mouse X
- : Mouse Y
- On exit :
- */
-
- static void
- HandleMouseMove(int nX, int nY,int nShiftCtrl)
- {
- int nDx,nDy;
-
- nDx = nX - LastX;
- nDy = nY - LastY;
-
- switch(dGDisplay.nDisplayMode) {
- case DISPLAY_OUTSIDE: {
- switch (bButtonDown) {
- case 1: {
- /* Move in X-Z plane */
- RwVCMoveCamera(Camera,
- RMul(INT2REAL(nDx),CREAL(0.01)),
- RMul(INT2REAL(nDy),CREAL(0.01)),CREAL(0.0));
-
- DisplayBound(&dGDisplay);
-
- RwPointCamera(Camera,CREAL(0.0),CREAL(0.0),CREAL(0.0));
- };
- case 2: {
- /* Zoom In and Out */
- RwVCMoveCamera(Camera,CREAL(0),CREAL(0),RMul(INT2REAL(nDy),CREAL(0.01)));
- RwPointCamera(Camera,CREAL(0.0),CREAL(0.0),CREAL(0.0));
- DisplayBound(&dGDisplay);
- break;
- };
- case 3: {
- /* Tilt */
- RwRevolveCamera(Camera,RMul(INT2REAL(nDx),CREAL(0.5)) );
- DisplayBound(&dGDisplay);
- break;
- };
- };
-
- break;
- };
- case DISPLAY_BEHIND: {
- if (nShiftCtrl&MK_SHIFT) {
- switch(bButtonDown) {
- case 1: {
- dGDisplay.nBehindTilt += RMul(INT2REAL(nDy),CREAL(0.5));
- dGDisplay.nBehindPan += RMul(INT2REAL(nDx),CREAL(0.5));
-
- if (dGDisplay.nBehindTilt<CREAL(10)) {
- dGDisplay.nBehindTilt = CREAL(10);
- };
- if (dGDisplay.nBehindTilt>CREAL(90)) {
- dGDisplay.nBehindTilt = CREAL(90);
- };
- break;
- };
- case 2: {
- dGDisplay.nBehindDist += RMul(INT2REAL(nDy),CREAL(0.01));
-
- if (dGDisplay.nBehindDist>CREAL(-0.2)) {
- dGDisplay.nBehindDist = CREAL(-0.2);
- };
- if (dGDisplay.nBehindDist<CREAL(-1.0)) {
- dGDisplay.nBehindDist = CREAL(-1.0);
- };
-
- break;
- };
- };
- } else {
- TankMouseControl(nX,nY);
- };
-
- break;
- };
- case DISPLAY_FIRST: {
- if (bButtonDown&1) {
- TankMouseControl(nX,nY);
- };
- break;
- };
- case DISPLAY_FLOAT: {
- if (bButtonDown&1) {
- /* Zoom In and Out */
- RwVCMoveCamera(Camera,CREAL(0),CREAL(0),RMul(INT2REAL(nDy),CREAL(0.01)));
- DisplayBound(&dGDisplay);
- };
-
- break;
- }
- };
- }
-
-
- /****************************************************************************
- Main
- */
-
- void main(int nArgc,char *saArgv[])
- {
- int nKey;
- int nMouseX,nMouseY,nMouseBut,nOldMouseBut;
- int nChange;
- int nShiftCtrl=0;
-
- /* Stop warnings */
-
- nArgc = nArgc;
-
- if (!Init3D(saArgv[0]))
- {
- exit(-1);
- };
-
- /* Put in demo Mode */
-
- nGDemoMode = 1;
- nGDisplayTime = DISPLAY_TIME;
- nGDisplay = 0;
- DisplayMode();
-
- /* Create the ground */
-
- DisplayModeCreate(&dGDisplay);
- DisplayModeSet(&dGDisplay,DISPLAY_BEHIND);
-
- GroundCreate(&gGGround);
-
- RwAddClumpToScene(Scene,gGGround.cpGeo);
-
- AllStillObjCreate(&asoGObjects);
- AllMoveObjCreate(&amoGObjects,MAX_MOVE_OBJECTS);
- AllTanksCreate(&atGTanks);
- AllMoveObjCreate(&amoGBits,MAX_BITS);
-
- /* The first created tank is always the user operated one */
- AllTanksAddTank(&atGTanks,CREAL(8.0),CREAL(8.0));
-
- /* Create the bullets */
-
- AllBulletsCreate(&abGBullets);
- AllBitsCreate(&abGBits);
-
- /* Create pointer */
-
- RwDPointerDisplay(&LastX,&LastY,&nOldMouseBut);
-
- nKey = DosGetKey();
-
- while (nKey!=27) { /* ESC quits */
- RwDPointerDisplay(&nMouseX,&nMouseY,&nMouseBut);
-
- /* The other bits */
-
- /* nDX =(nMouseX-LastX);
- nDY =(nMouseY-LastY);
- */
- nKey = DosGetKey();
- nShiftCtrl = DosShiftCtrl();
-
- if ((nKey>='1')&&(nKey<='4')) {
- DisplayModeSet(&dGDisplay,(nKey-'1')+1);
- };
-
- if (nGDemoMode) {
- nGDisplayTime--;
-
- if (nGDisplayTime<0) {
- DisplayModeSet(&dGDisplay,(nGDisplay&3)+1);
-
- nGDisplayTime = DISPLAY_TIME;
- nGDisplay++;
- };
- };
-
- nChange = (nMouseBut&(2+8)) | ( (nOldMouseBut&(2+8)) >>1 );
-
- switch (nChange) {
- case 0+0:
- case 2+1:
- case 8+4:
- case 8+2+4+1: {
- /* No change */
- break;
- };
- case 2:
- case 8+2+4: {
-
- /* Left Button Down */
-
- HandleLeftButtonDown(nMouseX,nMouseY,nShiftCtrl);
-
-
- break;
- };
- case 8:
- case 8+2+1: {
- /* Right Button Down */
-
-
- HandleRightButtonDown(nMouseX,nMouseY,nShiftCtrl);
-
-
- break;
- };
- case 8+1: {
- /* Right down left Up */
-
-
- HandleLeftButtonUp();
- HandleRightButtonDown(nMouseX,nMouseY,nShiftCtrl);
-
-
- break;
- };
- case 2+4: {
- /* Right up left Down */
-
-
- HandleRightButtonUp();
- HandleLeftButtonDown(nMouseX,nMouseY,nShiftCtrl);
-
-
- break;
- };
- case 8+2: {
- /* Left down RIght Down */
-
-
- HandleRightButtonDown(nMouseX,nMouseY,nShiftCtrl);
- HandleLeftButtonDown(nMouseX,nMouseY,nShiftCtrl);
-
-
- break;
- };
- case 1+4: {
- /* Left up Right Up */
-
-
- HandleRightButtonUp();
- HandleLeftButtonUp();
-
-
- break;
- };
- case 1:
- case 8+4+1: {
- /* Left up */
-
-
- HandleLeftButtonUp();
-
-
- break;
- };
- case 4:
- case 2+4+1: {
- /* Right up */
- HandleRightButtonUp();
- break;
- };
- };
-
- HandleMouseMove(nMouseX,nMouseY,nShiftCtrl);
-
- HandleTimer();
-
- LastX = nMouseX;
- LastY = nMouseY;
-
- nOldMouseBut = nMouseBut;
- };
-
- /*
- * Tidy up the 3D (RenderWare) components of the application.
- */
-
- TidyUp3D();
-
- exit(0);
- }
-
-