home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-11-14 | 48.0 KB | 1,570 lines |
- /**********************************************************************
- *
- * File : rwcyber.c
- *
- * Abstract : This is the main module of the cyberstreet demo. It contains
- * the code that handles all of the user interaction and the
- * interaction between the other modules.
- *
- **********************************************************************
- *
- * 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. will not, under any
- * circumstances, be liable for any lost revenue or other damages arising
- * from the use of this file.
- *
- * Copyright (c) 1995 Criterion Software Ltd.
- * All Rights Reserved.
- *
- * RenderWare is a trademark of Canon Inc.
- *
- ************************************************************************/
-
- /*--- Include files ---*/
-
- #define DEFINE_GLOBAL
- #include "global.h" /* Application general includes */
- #include "palette.h"
-
- /*--- Magic Number Definitions ---*/
-
- #if !defined(M_PI)
- #define M_PI 3.1415926535897932
- #endif
-
- /* Default size of the viewer's window. */
-
- #define CLOSEST 0.1 /* Closest we can get to a wall */
- #define LOWEST 0.2 /* Closest we can get to the ground */
-
- #define STREET_HIGHEST 2.5 /* Maximum height we can fly above street */
- #define HALL_HIGHEST 0.4 /* Maximum height we can fly above hall */
- #define POOL_HIGHEST 1.4 /* Maximum height we can fly above pool */
-
- #define MAX_TILT 80.0 /* The maximum tilt angle for the camera */
-
- /*--- Structure and enumerated type definitions ---*/
-
- /* This enumerated type tells us what kind of action should be taken
- * on mouse events.
- */
-
- typedef enum
- {
- MMNoAction,
- MMTravelCamera,
- MMTiltCamera,
- MMChangeHeight
- } MMMode;
-
- /* This enumerated type determines which cell of the world we are
- * currently in
- */
-
- typedef enum
- {
- CELL_STREET,
- CELL_HALL,
- CELL_POOL
- } Cell;
-
- /*--- Module Global Variables ---*/
-
- /* These variables are used to hold the polygons that define the lights
- * above the billboard. The lights are turned on and off by varying the
- * ambient surface property of these polygons.
- */
-
- RwPolygon3d *ppGLight1;
- RwPolygon3d *ppGLight2;
-
- /* These variables are used to hold the textures for the billboard. Each
- * of these textures contains 2 frames. One image shows the billboard lit
- * and the other is unlit. The billboard is made to appear lit or unlit by
- * the lights defined above by varying the current texture frame.
- */
-
- RwTexture *tpGBillboardLeft;
- RwTexture *tpGBillboardRight;
-
- /* These variables hold the clumps that make up the world.
- */
-
- static RwClump *cpGCity = NULL; /* The main street clump */
- static RwClump *cpGHall = NULL; /* The hall between the street and the poolroom */
- static RwClump *cpGPool = NULL; /* The poolroom clump */
- static RwClump *cpGSky1,*cpGSky2; /* These 2 clumps are dummies that are used
- to calculate the area of the display
- that is covered by the skyline backdrop */
-
- /* The camera can fly around a predetermined path. These variables define the
- path and the control variable.
- */
-
- static RwSpline *spGPath = NULL; /* The flight path for the camera */
- static RwReal nGAlpha; /* The control variable for the path */
-
- static RwReal nGSpeed; /* The current speed of the camera */
- static RwReal nGTilt; /* The absolute tilt angle of the camera */
- static RwReal nGGroundHeight; /* The current ground height */
-
- static int nGOnPad = 0; /* If Camera is over the pad that activates
- the door then this variable is TRUE */
- static int nGDoorPos = 0; /* The current position for the door.
- 0 = closed, DOOR_OPEN = open */
-
- static RwV3d vaGDoor[20]; /* The door appears to open by having
- the vertices modified. This variable
- is used to hold the current value of
- vertices used */
- static RwInt32 naGDoor[20]; /* This variable holds the indices for the
- vertices defined above */
-
- static Cell eGWhichCell; /* The current cell (STREET, HALL or
- POOLROOM) */
- static int nGFlyCamera; /* TRUE is camera is flying, FALSE
- otherwise */
-
- /*
- * 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.
- */
-
- static MMMode mGMouseMoveMode = MMNoAction;
-
- /*
- * Global variables used to remember the last mouse X and Y coordinates
- * when involved in a pan, zoom, drag or spin.
- */
- static RwInt32 nGLastX;
- static RwInt32 nGLastY;
-
- /*--- Function Definitions ---*/
-
- /************************************************************************
- *
- * Function: GetPosHeight()
- *
- * Description: Get the height of the ground at a given position
- *
- * Parameters: vpPos - 3D position for which we want the ground
- * height.
- *
- * Return Value: height of the ground at the specified point.
- *
- ************************************************************************/
- RwReal
- GetPosHeight(RwV3d *vpPos)
- {
- RwInt32 nStep;
-
- if (vpPos->x < CREAL(RIGHT_STREET))
- {
- /* In the street */
-
- if ((vpPos->x > CREAL(LEFT_KERB)) && (vpPos->x < CREAL(RIGHT_KERB)))
- {
- return (CREAL(STREET_HEIGHT + LOWEST));
- }
- else
- {
- return (CREAL(KERB_HEIGHT + LOWEST));
- }
- }
- else
- {
- /* In pool room or on steps */
-
- nStep = REAL2INT(RDiv(RSub(vpPos->x, CREAL(RIGHT_STREET)), CREAL(STEP_WIDTH)));
- if (nStep < 0)
- {
- nStep = 0;
- }
- if (nStep > MAX_STEPS)
- {
- nStep = MAX_STEPS;
- }
- return RSub(CREAL(KERB_HEIGHT + LOWEST), RMul(INT2REAL(nStep), CREAL(STEP_HEIGHT)));
- }
- }
-
- /************************************************************************
- *
- * Function: WhichCell()
- *
- * Description: Work out which cell the given position is in.
- *
- * Parameters: vpPos - 3D point that we want the cell for
- *
- * Return Value: Cell that contains the point
- *
- ************************************************************************/
- static Cell
- WhichCell(RwV3d *vpPos)
- {
- /* Check if we are in the street */
-
- if ((vpPos->x > CREAL(LEFT_STREET)) &&
- (vpPos->x < CREAL(RIGHT_STREET)) &&
- (vpPos->z > CREAL(FAR_STREET)) &&
- (vpPos->z < CREAL(NEAR_STREET)))
- {
- /* We're in the street */
- return(CELL_STREET);
- }
-
- /* Check if we are in the hall */
-
- if ( (vpPos->x > CREAL(LEFT_HALL)) &&
- (vpPos->x < CREAL(RIGHT_HALL)) &&
- (vpPos->z > CREAL(FAR_HALL)) &&
- (vpPos->z < CREAL(NEAR_HALL)) )
- {
- /* We're in the hall */
- return(CELL_HALL);
- }
-
- /* The only place left is the poolroom */
-
- return(CELL_POOL);
- }
-
- /************************************************************************
- *
- * Function: MoveForward()
- *
- * Description: Move the global Camera forward by the specified
- * distance.
- *
- * Parameters: nDist The distance to move forward
- *
- * Return Value: None
- *
- ************************************************************************/
- static void
- MoveForward(RwReal nDist)
- {
- RwV3d vAt, vOld, vNew;
- RwReal nOldHeight;
- RwReal nNewHeight;
-
- /* Find the forward movement vector for the Camera */
-
- RwGetCameraLookAt(cpGCamera, &vAt);
-
- /* We only want to move in x & z so remove the Y component and
- renormalise the forward vector */
-
- vAt.y = CREAL(0.0);
- RwNormalize(&vAt);
-
- /* Move the camera forward and get the new position */
-
- RwGetCameraPosition(cpGCamera, &vOld);
- RwWCMoveCamera(cpGCamera,
- RMul(vAt.x, nDist), CREAL(0.0), RMul(vAt.z, nDist));
- RwGetCameraPosition(cpGCamera, &vNew);
-
- /* Find out which cell we were in */
-
- eGWhichCell = WhichCell(&vOld);
-
- switch(eGWhichCell)
- {
- case CELL_STREET:
- /* In the street so constrain movement to within street bounds */
-
- if (vNew.z < CREAL(FAR_STREET + CLOSEST))
- {
- vNew.z = CREAL(FAR_STREET + CLOSEST);
- }
- else if (vNew.z > CREAL(NEAR_STREET - CLOSEST))
- {
- vNew.z = CREAL(NEAR_STREET - CLOSEST);
- }
-
- if (vNew.x < CREAL(LEFT_STREET + CLOSEST))
- {
- vNew.x = CREAL(LEFT_STREET + CLOSEST);
- }
- else if (vNew.x > CREAL(RIGHT_STREET - CLOSEST))
- {
- /* constrain if door is not open or not in front of door */
-
- if ((nGDoorPos < DOOR_OPEN) ||
- (vNew.y > RAdd(nGGroundHeight, CREAL(DOOR_HEIGHT + CLOSEST))) ||
- (vNew.z < CREAL(FAR_HALL)) ||
- (vNew.z > CREAL(NEAR_HALL)))
- {
- vNew.x = CREAL(RIGHT_STREET - CLOSEST);
- }
- }
-
- /* check if we're over pressure pad */
-
- if ((vNew.x > CREAL(PAD_X)) &&
- (vNew.y < RAdd(nGGroundHeight, CREAL(PAD_Y))) &&
- (vNew.z > CREAL(FAR_HALL)) &&
- (vNew.z < CREAL(NEAR_HALL)))
- {
- nGOnPad = TRUE;
- }
- else
- {
- nGOnPad = FALSE;
- }
- break;
-
- case CELL_HALL:
- /* In the hall so constrain against passage walls */
-
- if (vNew.z < CREAL(FAR_HALL + CLOSEST))
- {
- vNew.z = CREAL(FAR_HALL + CLOSEST);
- }
- else if (vNew.z > CREAL(NEAR_HALL - CLOSEST))
- {
- vNew.z = CREAL(NEAR_HALL - CLOSEST);
- }
- break;
-
- case CELL_POOL:
- /* In the poolroom so constrain movement to within poolroom bounds */
-
- if (vNew.z < CREAL(FAR_POOL + CLOSEST))
- {
- vNew.z = CREAL(FAR_POOL + CLOSEST);
- }
- else if (vNew.z > CREAL(NEAR_POOL - CLOSEST))
- {
- vNew.z = CREAL(NEAR_POOL - CLOSEST);
- }
-
- if (vNew.x < CREAL(LEFT_POOL + CLOSEST))
- {
- /* constrain if not in front of door otherwise allow through
- the door */
-
- if ((vNew.y > RAdd(nGGroundHeight, CREAL(DOOR_HEIGHT - CLOSEST))) ||
- (vNew.z < CREAL(FAR_HALL)) ||
- (vNew.z > CREAL(NEAR_HALL)))
- {
- vNew.x = CREAL(LEFT_POOL + CLOSEST);
- }
- }
- else if (vNew.x > CREAL(RIGHT_POOL - CLOSEST))
- {
- vNew.x = CREAL(RIGHT_POOL - CLOSEST);
- }
- break;
- }
-
- /* The camera height follows the ground height so adjust the height
- of the camera by any change in the ground height */
-
- nOldHeight = GetPosHeight(&vOld);
- nNewHeight = GetPosHeight(&vNew);
-
- nGGroundHeight = nNewHeight;
- vNew.y += nNewHeight - nOldHeight;
-
- RwSetCameraPosition(cpGCamera, vNew.x, vNew.y, vNew.z);
- }
-
- /************************************************************************
- *
- * Function: MoveUp()
- *
- * Description: Move the global Camera up by the specified
- * distance.
- *
- * Parameters: nDist The distance to move up
- *
- * Return Value: None
- *
- ************************************************************************/
- static void
- MoveUp(RwReal up)
- {
- RwV3d vPos;
-
- /* Move the camera up (or down!) and get the new position */
-
- RwWCMoveCamera(cpGCamera, CREAL(0.0), up, CREAL(0.0));
- RwGetCameraPosition(cpGCamera, &vPos);
-
- /* Check new height against upper and lower limits. The lower limit
- is the current ground height. The upper limit is dependant on which
- cell we are in */
-
- if (vPos.y < nGGroundHeight)
- {
- /* We can't move below the ground so clamp at this height */
- vPos.y = nGGroundHeight;
- }
- else switch(eGWhichCell)
- {
- /* Check the upper limit against the current cell and clamp
- if above the limit */
-
- case CELL_STREET:
- if (vPos.y > CREAL(STREET_HEIGHT + STREET_HIGHEST))
- vPos.y = CREAL(STREET_HEIGHT + STREET_HIGHEST);
- break;
-
- case CELL_HALL:
- if (vPos.y > RAdd(nGGroundHeight, CREAL(HALL_HIGHEST)))
- vPos.y = RAdd(nGGroundHeight, CREAL(HALL_HIGHEST));
- break;
-
- case CELL_POOL:
- if (vPos.y > RAdd(nGGroundHeight, CREAL(POOL_HIGHEST)))
- vPos.y = RAdd(nGGroundHeight, CREAL(POOL_HIGHEST));
- break;
- }
- /* Move the camera to the new (possibly clamped) position */
-
- RwSetCameraPosition(cpGCamera, vPos.x, vPos.y, vPos.z);
- }
-
- /************************************************************************
- *
- * Function: RandomVec()
- *
- * Description: Generate a random vector
- *
- * Parameters: vpVec - the vector to store the random value.
- *
- * Return Value: None
- *
- ************************************************************************/
- void RandomVec(RwV3d *vpVec)
- {
- vpVec->x = RANDOM_REAL(CREAL(-1.0), CREAL(1.0));
- vpVec->y = RANDOM_REAL(CREAL(-1.0), CREAL(1.0));
- vpVec->z = RANDOM_REAL(CREAL(-1.0), CREAL(1.0));
- }
-
- /************************************************************************
- *
- * Function: DoRwReadShape()
- *
- * Description: Read a RenderWare script file and generate an
- * error on failure.
- *
- * Parameters: cpShape - the name of the script to load
- *
- * Return Value: None
- *
- ************************************************************************/
- RwClump
- *DoRwReadShape(char *cpShape)
- {
- RwClump *cpClump;
-
- cpClump = RwReadShape(cpShape);
-
- if (!cpClump)
- {
- OsError("Unable to read <%s>", cpShape);
- }
- return cpClump;
- }
-
- /************************************************************************
- *
- * Function: ResetCamera()
- *
- * Description: Move the camera back to its initial position
- * and orientation.
- *
- * Parameters: cpShape - the name of the script to load
- *
- * Return Value: None
- *
- ************************************************************************/
- void
- ResetCamera(void)
- {
- RwV3d vPos;
-
- nGSpeed = CREAL(0.0); /* Camera is stationary */
- nGTilt = CREAL(0.0); /* Camera is looking straight ahead */
-
- /* Reset camera position */
- RwSetCameraPosition(cpGCamera,
- CREAL(CAMERA_START_X),
- CREAL(CAMERA_START_Y),
- CREAL(CAMERA_START_Z));
-
- /* Camera is looking in the same direction as the -ve Z axis */
- RwSetCameraLookAt(cpGCamera, CREAL(0.0),CREAL(0.0),CREAL(-1.0));
-
- /* And is level */
- RwSetCameraLookUp(cpGCamera, CREAL(0.0),CREAL(1.0),CREAL(0.0));
-
- /* Set the ground height for this new position */
- RwGetCameraPosition(cpGCamera, &vPos);
- nGGroundHeight = GetPosHeight(&vPos);
-
- /* Set the current cell */
- eGWhichCell = WhichCell(&vPos);
-
- nGOnPad = 0; /* Not on the door pad */
- nGFlyCamera = 0; /* Not flying */
- }
-
- /************************************************************************
- *
- * Function: ToggleFlyCamera()
- *
- * Description: If camera is flying then stop it and move back to
- * the start position. Otherwise start the camera flying
- *
- * Parameters: None
- *
- * Return Value: None
- *
- ************************************************************************/
- void
- ToggleFlyCamera(void)
- {
- if (nGFlyCamera)
- {
- /* We are currently flying - so stop and reset camera */
- nGFlyCamera = 0;
- ResetCamera();
- }
- else
- {
- nGOnPad = 0; /* If we're flying then we're not on
- the door pad */
- nGFlyCamera = 1;
- eGWhichCell = CELL_STREET; /* The spline path is in the street */
- nGAlpha = CREAL(0.0); /* Reset to the start of the path */
- }
- }
-
- /************************************************************************
- *
- * Function: Render()
- *
- * Description: This function controls the rendering of the scene
- *
- * Parameters: None
- *
- * Return Value: None
- *
- ************************************************************************/
- static void
- Render(void)
- {
- RwV3d lookat;
- RwReal dot;
- RwInt32 w, h, dx, dy, cw, ch;
- static Cell eOldCell;
-
- /* If we have moved into or out of the street cell then enable or
- disable the gun */
-
- if (eOldCell != eGWhichCell)
- {
- /* We've changed cells */
-
- eOldCell = eGWhichCell;
-
- if (eGWhichCell == CELL_STREET)
- {
- /* Moving into the street - Enable the gun */
- GunEnable();
- }
- else
- {
- /* Disable the Gun */
- GunDisable();
- }
- }
-
-
- /* Only the STREET cell uses a bitmap backdrop. Enable it for this cell
- and disable for the others */
-
- switch(eGWhichCell)
- {
- case CELL_STREET:
- RwGetCameraViewport(cpGCamera, NULL, NULL, &cw, &ch);
- RwSetCameraBackdropViewportRect(cpGCamera, 0, 0, cw, ch);
- break;
- case CELL_HALL:
- case CELL_POOL:
- GunDisable(); /* the gun should never be on here */
- /* Don't need bitmap backdrop */
- RwSetCameraBackdropViewportRect(cpGCamera, 0, 0, 0, 0);
- break;
- }
-
- /* clear the old damaged areas */
-
- RwUndamageCameraViewport(cpGCamera, 0,0, (RwInt32)512, (RwInt32)512);
-
- if (eGWhichCell == CELL_STREET)
- {
- /* Determine the position of the bitmap backdrop based on the current
- camera orientation. This is achieved by assuming that the backdrop
- bitmap is applied to a cylinder which wraps around the world. Taking
- the current view direction from the camera, it is possible to calculate
- the point on the cylinder and hence the portion if the bitmap that
- should be in the centre of the screen */
-
- RwGetCameraLookAt(cpGCamera, &lookat);
-
- w = RwGetRasterWidth(RwGetCameraBackdrop(cpGCamera));
- h = RwGetRasterHeight(RwGetCameraBackdrop(cpGCamera));
-
- /* Use the Y component of the look at directly. This is accurate
- as long as the camera doesn't point directly up or down. This can't
- happen in this application */
-
- /* Set the Y offset such that for a camera angle that is parallel
- with the horizon, we are looking at the centre row of the backdrop
- bitmap */
-
- dy = REAL2INT(RMul(lookat.y, INT2REAL(-h/2)));
-
- /* Then add a little bit to move the backdrop up to where we want it */
-
- dy += h - (ch * 3)/4;
-
- /* The X component of the backdrop offset needs to take account of both
- the X and Z components of the look at vector. An range of angles from
- 0 to 360 degrees (0 - PI radians) maps onto the backdrop as 0 - w */
-
- dot = FL2REAL((M_PI - atan2(REAL2FL(lookat.x), REAL2FL(lookat.z)))/M_PI);
- dx = REAL2INT(RMul(INT2REAL(w),dot));
-
- /* Set our calculated offset */
-
- RwSetCameraBackdropOffset(cpGCamera, dx,dy);
-
- /* RwSetCameraBackdropOffset damages the backdrop portion of the camera
- we want to override this since we know that only portions of the
- backdrop are visible through the scene */
-
- /* We use 2 dummy clumps to determine which portions of the
- backdrop need updating */
-
- /* first the portion visible as sky above everything */
-
- RwGetClumpViewportRect(cpGSky1, cpGCamera, &dx ,&dy, &w, &h);
- RwDamageCameraViewport(cpGCamera, dx-32, dy, w+64, h+64);
-
- /* Then the portion visible through the fence at the end */
-
- RwGetClumpViewportRect(cpGSky2, cpGCamera, &dx ,&dy, &w, &h);
- RwDamageCameraViewport(cpGCamera, dx-32, dy, w+64, h+64);
- }
-
- if ((eGWhichCell == CELL_STREET) || (eGWhichCell == CELL_HALL))
- {
- /* If we are in the street or the hall then update all of
- these things */
-
- AllBitsUpdate();
- AllObjectsUpdate();
- GunUpdate();
- }
-
- /* Render the objects */
-
- OsBeginCameraUpdate(cpGCamera);
- RwClearCameraViewport(cpGCamera);
-
- switch (eGWhichCell)
- {
- case CELL_STREET:
- /* We're in the street */
- if (nGDoorPos)
- {
- /* The door is open so render the pool room and the hall first */
- RwRenderScene(spGPoolScene);
- RwRenderClump(cpGHall);
- }
-
- /* Render the street */
- RwRenderScene(spGScene);
-
- /* Render all the objects in the street (rats + explosions) */
- AllObjectsRender();
- break;
-
- case CELL_HALL:
- /* We're in the hall */
- /* From here we can see everything so render it all */
-
- /* Render the street */
-
- RwRenderScene(spGScene);
-
- /* Render the rats and explosions */
-
- AllObjectsRender();
-
- /* Render the pool room and the hall */
- RwRenderScene(spGPoolScene);
- RwRenderClump(cpGHall);
- break;
-
- case CELL_POOL:
- /* We're in the poolroom */
-
- /* render the hall first */
- RwRenderClump(cpGHall);
-
- /* Then the pool room */
-
- RwRenderScene(spGPoolScene);
- break;
- }
- /* Overlay the gun on top of the scene */
-
- GunRender();
-
- #ifdef WITH_SCORE
- if (GunVisible())
- {
- OsDisplayScore(NumDeadRats(), NumRats());
- }
- #endif
-
- RwEndCameraUpdate(cpGCamera);
- OsShowCameraImage();
- }
-
- /************************************************************************
- *
- * Function: AddLamppost()
- *
- * Description: Add a lampost to the street
- *
- * Parameters: x, z the position on the ground for the lamppost.
- *
- * Return Value: TRUE if lamppost added, FALSE otherwise
- *
- ************************************************************************/
- #define LAMPPOST_HEIGHT 1.5
- #define LAMPPOST_OFFSET 0.075
-
- static int AddLamppost(RwReal x, RwReal z)
- {
- if (!AddStaticObject(x, CREAL(0.1), z, "lamppost.rwx") ||
- !AddStaticObject((x < CREAL(0.0)) ? RAdd(x, CREAL(LAMPPOST_OFFSET))
- : RSub(x, CREAL(LAMPPOST_OFFSET)),
- CREAL(0.1 + LAMPPOST_HEIGHT), z, "lamplite.rwx"))
- {
- return(FALSE);
- }
- return (TRUE);
- }
-
- /************************************************************************
- *
- * Function: Init3D()
- *
- * Description: Initialise the 3D components. This function creates
- * the global camera, creates all the scenes and lights
- * and loads all of the scripts.
- *
- * Parameters: None
- *
- * Return Value: None
- *
- ************************************************************************/
- int
- Init3D(void)
- {
- RwLight *Light;
- int i;
- RwRaster *rpBackdrop;
-
-
- if (!OsOpen()) /* Open RenderWare in an OS specific way */
- return(FALSE);
-
- RwSRandom((RwInt32)time(0)); /* Seed the random number generator */
-
- /* Load the palette that this program will use. Note: this palette must
- be loaded before any of the textures that will be matched to it */
-
- if (!CheckAndReadPalette("rwcyber.pal"))
- {
- OsError("Failed to load palette file <rwcyber.pal>");
- return(FALSE);
- }
-
- /* Create the global camera that will be used for all of the rendering.
- The size of the camera is OS specific */
-
- cpGCamera = RwCreateCamera(OsMaxCameraWidth(), OsMaxCameraHeight(), NULL);
-
- if (!cpGCamera)
- {
- /*
- * 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)
- {
- OsError("Insufficient memory to create the RenderWare(tm) camera");
- }
- else
- {
- OsError("Error Creating the RenderWare camera");
- }
- RwClose();
- return FALSE;
- }
-
- /* Do the OS Specific initialisation stuff */
-
- if (!OsInit())
- {
- RwClose();
- return(FALSE);
- }
-
- /* Set the camera's background color to black.*/
-
- RwSetCameraBackColor(cpGCamera, CREAL(0.0), CREAL(0.0), CREAL(0.0));
-
- /* Read the cityscape backdrop */
-
- if (!(rpBackdrop = RwReadRaster("cityback", 0L)))
- {
- OsError("Unable to read <backdrop>");
- RwClose();
- return FALSE;
- }
- RwSetCameraBackdrop(cpGCamera, rpBackdrop);
- RwSetCameraBackdropOffset(cpGCamera, 0,0);
-
- /* Setup initial position and field of view for the camera */
- ResetCamera();
- RwSetCameraViewwindow(cpGCamera, CREAL(1.0), CREAL(0.75));
-
- /* Create a scene which will contain the clumps and lights for the
- * street
- */
-
- spGScene = RwCreateScene();
- if (!spGScene)
- {
- RwDestroyCamera(cpGCamera);
- RwClose();
- return FALSE;
- }
-
- /* Create a scene which will contain the clumps and lights for the
- * poolroom
- */
-
- spGPoolScene = RwCreateScene();
- if (!spGPoolScene)
- {
- RwDestroyCamera(cpGCamera);
- RwClose();
- return FALSE;
- }
-
- /* Create a scene which will contain the clumps which are used as targets
- * for the rats
- */
-
- spGTargetScene = RwCreateScene();
- if (!spGTargetScene)
- {
- RwDestroyCamera(cpGCamera);
- RwClose();
- return FALSE;
- }
-
- /* Create the light that will illuminate the poolroom. The light is a
- directional light with an illumination vector of (0.5, -1.0, -0.5)
- */
-
- Light = RwCreateLight(rwDIRECTIONAL, CREAL(0.5), CREAL(-1.0), CREAL(-0.5),
- CREAL(1.0));
-
- /* Add the light to the poolroom scene */
- RwAddLightToScene(spGPoolScene, Light);
-
- /* Read the geometry for the street */
- if (!(cpGCity = DoRwReadShape("city.rwx")))
- {
- RwClose();
- return FALSE;
- }
-
- /* Find the polygons that represent the billboard lights */
-
- ppGLight1 = RwFindTaggedPolygon(cpGCity, 1);
- ppGLight2 = RwFindTaggedPolygon(cpGCity, 2);
-
- /* And the textures that represent the billboard */
-
- tpGBillboardLeft = RwFindNamedTexture("bbleft");
- tpGBillboardRight = RwFindNamedTexture("bbrite");
-
- /* And add the clump to the scene */
- RwAddClumpToScene(spGScene, cpGCity);
-
- /* Get the vertices of the secret door. These are the first 18
- vertices in the street script */
- for (i=0; i<18; i++)
- {
- naGDoor[i] = i + 1;
- RwGetClumpVertex(cpGCity, naGDoor[i], &vaGDoor[i]);
- }
-
- /* Duplicate the light and add it to the default scene. This light
- will light all of the clumps not explicitly added to a scene (ie the
- rats and bits of explosions) */
-
- Light = RwDuplicateLight(Light);
- RwAddLightToScene(RwDefaultScene(), Light);
-
- /* Read the script that represents the get hallway between the street and
- the poolroom */
- if (!(cpGHall = DoRwReadShape("hall.rwx")))
- {
- RwClose();
- return FALSE;
- }
-
- /* Read the script that represents the poolroom */
- if (!(cpGPool = DoRwReadShape("pool.rwx")))
- {
- RwClose();
- return FALSE;
- }
-
- /* And add it to the poolroom scene */
- RwAddClumpToScene(spGPoolScene, cpGPool);
-
- /* Set up the rest of the objects */
-
- if (!AllObjectsSetup() ||
- !GunSetup() ||
- !ManSetup() ||
- !TrophySetup() ||
- !AllRatsSetup() ||
- !AllBitsSetup())
- {
- RwClose();
- return FALSE;
- }
-
- #ifdef WITH_SOUND
- if (!(AllSoundsSetup()))
- {
- /* Theres no sound card but dont do anything about it */
- }
- #endif
-
- /* Add all of the static objects */
-
- if (!AddStaticObject(CREAL(1.5), CREAL(0.1), CREAL(1.0), "bin.rwx") ||
- !AddStaticObject(CREAL(1.3), CREAL(0.1), CREAL(1.5), "bin.rwx") ||
- !AddStaticObject(CREAL(0.4), CREAL(0.0), CREAL(0.5), "binboxes.rwx") ||
- !AddStaticObject(CREAL(-0.2),CREAL(0.0), CREAL(0.35),"rubbish.rwx") ||
- !AddStaticObject(CREAL(1.5), CREAL(0.1), CREAL(2.0), "rubbish.rwx") ||
- !AddLamppost(CREAL(-1.35), CREAL(4.2)) ||
- !AddLamppost(CREAL(1.35), CREAL(5.5)) ||
- !AddLamppost(CREAL(-1.35), CREAL(7.6)) ||
- !AddLamppost(CREAL(1.35), CREAL(9.0)) ||
- !AddLamppost(CREAL(-1.35), CREAL(11.0)))
- {
- RwClose();
- return FALSE;
- }
-
- /* Create 2 dummy clumps. These clumps are used to determine the
- area of the viewport that represents the bitmap backdrop on each frame.
- One clump represents the Sky and the other the view of the skyline
- at the end of the alley */
-
- /* Create the Sky clump */
-
- RwModelBegin();
- RwClumpBegin();
- RwVertex(CREAL(LEFT_STREET), CREAL(3.1), CREAL(-0.5));
- RwVertex(CREAL(RIGHT_STREET), CREAL(3.1), CREAL(-0.5));
- RwVertex(CREAL(LEFT_STREET), CREAL(3.1), CREAL(NEAR_STREET));
- RwVertex(CREAL(RIGHT_STREET), CREAL(3.1), CREAL(NEAR_STREET));
- RwVertex(CREAL(0.0), CREAL(4.0), CREAL(4.0));
- RwQuad(1,3,4,2);
- RwClumpEnd(&cpGSky1);
- RwModelEnd();
-
- /* Create the End of Alley dummy clump */
-
- RwModelBegin();
- RwClumpBegin();
- RwVertex(CREAL(LEFT_STREET), CREAL(0.0), CREAL(NEAR_STREET));
- RwVertex(CREAL(RIGHT_STREET),CREAL(0.0), CREAL(NEAR_STREET));
- RwVertex(CREAL(LEFT_STREET), CREAL(4.0), CREAL(NEAR_STREET));
- RwVertex(CREAL(RIGHT_STREET),CREAL(4.0), CREAL(NEAR_STREET));
- RwQuad(1,3,4,2);
- RwClumpEnd(&cpGSky2);
- RwModelEnd();
-
- /* Create a spline that the camera will fly along in flythrough mode */
-
- #define ASSIGNVECTOR(A,X,Y,Z) A.x = CREAL(X); A.y = CREAL(Y); A.z = CREAL(Z);
-
- {
- RwV3d points[20];
-
- ASSIGNVECTOR(points[0], 1.7, 1.8, 7);
- ASSIGNVECTOR(points[1], 1, 1.0, 8);
- ASSIGNVECTOR(points[2], 0, 0.7, 5);
- ASSIGNVECTOR(points[3],-1.8, 0.5, 3);
- ASSIGNVECTOR(points[4],-1.5, 0.3, 1);
- ASSIGNVECTOR(points[5],-0.5, 0.5, 0.5);
- ASSIGNVECTOR(points[6], 0, 0.4, 1);
- ASSIGNVECTOR(points[7], 1, 0.5, 1.5);
- ASSIGNVECTOR(points[8], 1, 0.5, 4.5);
- ASSIGNVECTOR(points[9], 1, 0.5, 7.5);
- ASSIGNVECTOR(points[10], 0, 0.5, 8.5);
- ASSIGNVECTOR(points[11],-1, 0.3, 8.5);
- ASSIGNVECTOR(points[12],-1, 0.2, 7.5);
- ASSIGNVECTOR(points[13],-1, 0.2, 4.5);
- ASSIGNVECTOR(points[14],-1, 0.4, 1.5);
- ASSIGNVECTOR(points[15], 0, 0.6, 1.5);
- ASSIGNVECTOR(points[16], 1.2, 0.4, 1.5);
- ASSIGNVECTOR(points[17], 1.7, 1.5, 5.0);
-
- spGPath = RwCreateSpline(18, rwCLOSEDLOOP, points);
- }
- return TRUE;
- }
-
- /************************************************************************
- *
- * Function: TidyUp3D()
- *
- * Description: Clean Up the 3D components of the application. This
- * function destroys all the clumps, lights, scenes
- * and splines that are created in Init3D.
- *
- * Parameters: None
- *
- * Return Value: None
- *
- ************************************************************************/
- void
- TidyUp3D(void)
- {
- RwRaster *rpBackdrop;
-
- /* Tidy up the OS Specific 3D stuff */
-
- OsTidy();
-
- /* Destroy the camera's flight path */
-
- RwDestroySpline(spGPath);
-
- /* Destroy all of the 3D components created by the modules */
-
- AllBitsDestroy();
- AllRatsDestroy();
- ManDestroy();
- GunDestroy();
- AllObjectsDestroy();
-
- /* Destroy the scenes. This will destroy all the clumps and lights currently
- contained within the scenes */
-
- RwDestroyScene(spGPoolScene);
- RwDestroyScene(spGScene);
- RwDestroyScene(spGTargetScene);
-
- /* Destroy the camera and the backdrop */
-
- rpBackdrop = RwGetCameraBackdrop(cpGCamera);
- if (rpBackdrop)
- RwDestroyRaster(rpBackdrop);
- RwDestroyCamera(cpGCamera);
-
- /* Destroy everything else */
-
- if (rpGPanel)
- RwDestroyRaster(rpGPanel);
-
-
- #ifdef WITH_SOUND
- AllSoundsDestroy();
- #endif
-
- /* Close the library. This will destroy all of the clumps and lights
- * that aren't explicitly added to another Scene. All of the memory
- * allocated for internal resources and textures will also be freed.
- */
- RwClose();
- }
-
-
- /************************************************************************
- *
- * Function: HandlePaint()
- *
- * Description: Redraw the entire viewport. The viewport may be
- * larger than the camera so the backing panel is drawn
- * in sections.
- *
- * Parameters: None
- *
- * Return Value: None
- *
- ************************************************************************/
- void
- HandlePaint(void)
- {
- RwInt32 x, y;
- RwInt32 offx,offy;
- RwRaster *raster;
-
- /* Save all of the camera settings that we will modify and restore
- * them once we are finished with them.
- */
-
- RwGetCameraBackdropOffset(cpGCamera, &offx, &offy);
- raster = RwGetCameraBackdrop(cpGCamera);
-
- OsResetCameraViewport(); /* Ensure the camera behaves as a default one */
-
- /* If no panel exists then there is no surround to draw so skip this bit */
-
- if (rpGPanel)
- {
- /* Use all of the camera's viewport to draw the panel */
-
- RwSetCameraBackdrop(cpGCamera, rpGPanel);
- RwSetCameraBackdropViewportRect(cpGCamera, 0,0, OsMaxCameraWidth(), OsMaxCameraHeight());
-
- for (y=0; y < OsMaxScreenHeight(); y += OsMaxCameraHeight())
- {
- for (x=0; x < OsMaxScreenWidth(); x += OsMaxCameraWidth())
- {
- RwSetCameraViewport(cpGCamera, x,y, OsMaxCameraWidth(), OsMaxCameraHeight());
- RwSetCameraBackdropOffset(cpGCamera, x,y);
- RwInvalidateCameraViewport(cpGCamera);
- OsBeginCameraUpdate(cpGCamera);
- RwClearCameraViewport(cpGCamera);
- RwEndCameraUpdate(cpGCamera);
- OsShowCameraImage();
- }
- }
- }
-
- /* Restore the saved camera settings */
-
- OsSetCameraViewport();
- RwSetCameraBackdrop(cpGCamera, raster);
- RwSetCameraBackdropOffset(cpGCamera, offx, offy);
-
- /* We need to redraw the entire viewport next time we copy to the display */
- RwInvalidateCameraViewport(cpGCamera);
-
- }
-
- /************************************************************************
- *
- * Function: HandleLeftButtonDown()
- *
- * Description: Set up the action to be performed when
- * left mouse button is pressed.
- *
- *
- * Parameters: x, y - Camera Viewport co-ordinates for the current
- * cursor position.
- * control - the status of the Control Key.
- * TRUE = key pressed
- * shift - the status of the Shift Key.
- * TRUE = key pressed
- *
- * Return Value: None
- *
- ************************************************************************/
- void
- HandleLeftButtonDown(RwInt32 x, RwInt32 y, int control, int shift)
- {
- if (nGFlyCamera)
- {
- /* If we are flying then turn it off */
-
- nGFlyCamera = 0;
- ResetCamera();
- }
-
- /* Define the action that will be taken by subsequent mouse movements */
-
- if (control)
- {
- /* Raise or lower the Camera */
- mGMouseMoveMode = MMChangeHeight;
- }
- else if (shift)
- {
- /* Tilt the Camera */
- mGMouseMoveMode = MMTiltCamera;
- }
- else
- {
- /* Rotate the camera and move backwards and forwards */
- mGMouseMoveMode = MMTravelCamera;
- nGSpeed = CREAL(0);
- }
-
- /* Remember the current x & y position to allow a relative
- movement determination to be performed later */
- nGLastX = x;
- nGLastY = y;
- }
-
- /************************************************************************
- *
- * Function: HandleRightButtonDown()
- *
- * Description: Set up the action to be performed when
- * right mouse button is pressed. For this
- * application the action is the same as the
- * left button with the additional feature that the
- * gun also fires.
- *
- * Parameters: x, y - Camera Viewport co-ordinates for the current
- * cursor position.
- * control - the status of the Control Key.
- * TRUE = key pressed
- * shift - the status of the Shift Key.
- * TRUE = key pressed
- *
- * Return Value: None
- *
- ************************************************************************/
- void
- HandleRightButtonDown(RwInt32 x, RwInt32 y, int control, int shift)
- {
- GunFiring(TRUE);
-
- /* Define the action that will be taken by subsequent mouse movements */
-
- if (control)
- {
- /* Raise or lower the Camera */
- mGMouseMoveMode = MMChangeHeight;
- }
- else if (shift)
- {
- /* Tilt the Camera */
- mGMouseMoveMode = MMTiltCamera;
- }
- else
- {
- /* Rotate the camera and move backwards and forwards */
- mGMouseMoveMode = MMTravelCamera;
- nGSpeed = CREAL(0);
- }
-
- /* Remember the current x & y position to allow a relative
- movement determination to be performed later */
- nGLastX = x;
- nGLastY = y;
- }
-
- /************************************************************************
- *
- * Function: HandleMouseMove()
- *
- * Description: Handle a movement of the mouse. If a previous left
- * or right mouse button down event has set a mouse
- * move mode then this function will take the necessary
- * actions.
- *
- * Parameters: x, y - Camera Viewport co-ordinates for the current
- * cursor position.
- *
- * Return Value: None
- *
- ************************************************************************/
- void
- HandleMouseMove(RwInt32 x, RwInt32 y)
- {
- RwV3d vAt;
-
- /* mGMouseMoveMode tells us what kind of action to perform. */
-
- switch (mGMouseMoveMode)
- {
- case MMNoAction:
- break;
-
- case MMTravelCamera:
- /* We are travelling through the scene. Movement of the
- * mouse in the X direction will rotate the camera about the
- * Y Axis, and movement of the mouse in the Y direction will
- * move the camera forwards and backwards through the scene.
- */
-
- /* Rotate the camera by mouse X delta degrees. */
-
- RwRotateMatrix(RwScratchMatrix(), CREAL(0.0), CREAL(1.0), CREAL(0.0),
- INT2REAL(nGLastX - x), rwREPLACE);
- RwTransformCameraOrientation(cpGCamera, RwScratchMatrix());
-
- /* Move the camera forward. The speed of forward motion is deterimined
- * by the mouse Y delta divided by 100 units.
- */
-
- nGSpeed = RDiv(INT2REAL(nGLastY - y), CREAL(100.0));
- MoveForward(nGSpeed);
- break;
-
- case MMChangeHeight:
- /* Raised or lower the eyepoint of the camera */
- MoveUp(RDiv(INT2REAL(nGLastY - y),CREAL(50)));
- break;
-
- case MMTiltCamera:
- /* Movement of the mouse in the X axis rotates about the Y axis as
- * above. Movement in the Y axis tilts the camera
- */
-
- /* Rotate the camera */
- RwRotateMatrix(RwScratchMatrix(), CREAL(0.0),CREAL(1.0),CREAL(0.0),
- INT2REAL(nGLastX - x),rwREPLACE);
- RwTransformCameraOrientation(cpGCamera, RwScratchMatrix());
-
- /* Tilt the Camera by maintaining an absolute tilt value. This is
- * necessary to prevent accumulative roundoff errors and to allow the
- * amount of tilt to be limited.
- */
- nGTilt = RAdd(nGTilt, INT2REAL(y - nGLastY));
-
- if (nGTilt > CREAL(MAX_TILT))
- nGTilt = CREAL(MAX_TILT);
- else if (nGTilt < CREAL(-MAX_TILT))
- nGTilt = CREAL(-MAX_TILT);
-
- /* force the camera to lie in a plane parallel with the ground
- * plane */
- RwGetCameraLookAt(cpGCamera, &vAt);
- RwSetCameraLookAt(cpGCamera, vAt.x, CREAL(0.0), vAt.z);
- RwSetCameraLookUp(cpGCamera, CREAL(0.0), CREAL(1.0), CREAL(0.0));
- /* Then tilt it */
- RwTiltCamera(cpGCamera, nGTilt);
- break;
- }
-
- /* Remember the current X and Y for next time. */
- nGLastX = x;
- nGLastY = y;
- }
-
- /************************************************************************
- *
- * Function: HandleLeftButtonUp()
- *
- * Description: Handle the release of the left mouse button. This
- * resets any current mouse movement action.
- *
- * Parameters: None
- *
- * Return Value: None
- *
- ************************************************************************/
- void
- HandleLeftButtonUp(void)
- {
- if (mGMouseMoveMode != MMNoAction)
- {
- mGMouseMoveMode = MMNoAction;
- }
- }
-
- /************************************************************************
- *
- * Function: HandleRightButtonUp()
- *
- * Description: Handle the release of the right mouse button. This
- * has the same behaviour as the raising of the left
- * mouse button with the additional feature that the
- * gun will stop firing.
- *
- * Parameters: None
- *
- * Return Value: None
- *
- ************************************************************************/
- void
- HandleRightButtonUp()
- {
- /* Stop the gun firing */
-
- GunFiring(FALSE);
- HandleLeftButtonUp();
- }
-
- /************************************************************************
- *
- * Function: HandleTimer()
- *
- * Description: Handle the action that should be taken on each
- * frame. This includes advancing all animated clumps
- * and textures by a frame and rerendering the scene
- * based on the current camera position
- *
- * Parameters: None
- *
- * Return Value: None
- *
- ************************************************************************/
- void
- HandleTimer(void)
- {
- int i; /* temporary loop control variable */
- static int nGState = 0; /* Remember the current state of the
- billboard lights */
-
- if ((RwRandom() & 0xff) < 16)
- {
- /* At a random interval, trigger the effect of the billboard lights
- * flickering. This is achieved by altering the ambient surface
- * property of the polygons representing the light and advancing the
- * billboard textures to the next frame
- */
-
- if ((nGState++)&1)
- {
- /* Lights are off, turn them on */
- RwSetPolygonAmbient(ppGLight1,CREAL(1.0));
- RwSetPolygonAmbient(ppGLight2,CREAL(1.0));
- RwSetTextureFrame(tpGBillboardLeft, 0);
- RwSetTextureFrame(tpGBillboardRight, 0);
- }
- else
- {
- /* Lights are on, turn them off */
- RwSetPolygonAmbient(ppGLight1,CREAL(0.0));
- RwSetPolygonAmbient(ppGLight2,CREAL(0.0));
- RwSetTextureFrame(tpGBillboardLeft, 1);
- RwSetTextureFrame(tpGBillboardRight, 1);
- }
- }
-
- /* Every so often release another Rat */
- AllRatsRelease();
-
- /* If the camera is flying then advance it to the next position along
- * the spline path
- */
-
- if (nGFlyCamera)
- {
- RwV3d up;
-
- /* Force the camera to preserve the correct up direction */
- up.x = CREAL(0.0);
- up.y = CREAL(1.0);
- up.z = CREAL(0.0);
-
- /* Get the current spline transform matrix */
- RwSplineTransform(spGPath, rwSMOOTH, nGAlpha, &up, RwScratchMatrix());
-
- /* And apply it to the camera */
- RwTransformCamera(cpGCamera, RwScratchMatrix(), rwREPLACE);
-
- /* Increment the spline control variable */
- nGAlpha = RAdd(nGAlpha, CREAL(0.002));
- }
-
- /* Update the animation of the Man in the poolroom */
-
- ManUpdate();
-
- /* If we are over the pad that activates the door then open the door */
- if (nGOnPad)
- {
- if (nGDoorPos < 20)
- {
- /* The door isn't open yet. Open it some more */
- for (i=0; i<9; i++)
- {
- vaGDoor[i].z -= CREAL(0.02);
- vaGDoor[i+9].z += CREAL(0.02);
- }
- nGDoorPos++;
- RwSetClumpVertices(cpGCity, naGDoor, vaGDoor, 18);
- /* Setting clump vertices forces the rwEDITABLE hint
- * we don't need this so turn it off again
- */
- RwSetClumpHints(cpGCity, 0L);
- }
- }
- else
- {
- /* We're not over the pad. Close the door if it is open */
- if (nGDoorPos > 0)
- {
- /* The door is still open. Close it some more */
- for (i=0; i<9; i++)
- {
- vaGDoor[i].z += CREAL(0.02);
- vaGDoor[i+9].z -= CREAL(0.02);
- }
- nGDoorPos--;
- RwSetClumpVertices(cpGCity, naGDoor, vaGDoor, 18);
- /* Setting clump vertices forces the rwEDITABLE hint
- * we don't need this so turn it off again
- */
- RwSetClumpHints(cpGCity, 0L);
- }
- }
-
- /* The camera has momentum and will continue to move forward once the
- mouse button is released */
-
- if (mGMouseMoveMode == MMNoAction)
- {
- /* No mouse button is pressed. Check if the camera was moving
- forward */
-
- if (nGSpeed)
- {
- /* The camera is moving so update its position */
- MoveForward(nGSpeed);
-
- /* slow it down */
- nGSpeed = RMul(nGSpeed, CREAL(0.9));
- if (RAbs(nGSpeed) < CREAL(0.005))
- {
- nGSpeed = CREAL(0);
- }
- }
- }
- /* Call the main render function to perform the rendering of the
- * view
- */
- Render();
- }
-
-