home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************************
- *
- * File : rwroller.c
- *
- * Abstract : A very simple, sample RenderWare application for
- * Microsoft Windows 3.1. 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. will not, under any
- * circumstances, be liable for any lost revenue or other damages arising
- * from the use of this file.
- *
- * Copyright (c) 1994 Criterion Software Ltd.
- * All Rights Reserved.
- *
- * RenderWare is a trademark of Canon Inc.
- *
- **********************************************************************/
-
- /**********************************************************************
- *
- * Header files.
- *
- **********************************************************************/
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <i86.h>
- #include <math.h> /* Required for floating point */
-
- #include "rwlib.h"
- #include "rwdos.h"
- #include "doswrap.h"
-
- #include "rolltype.h"
- #include "palette.h"
- #include "pick.h"
-
- /**********************************************************************
- *
- * Application constants.
- *
- **********************************************************************/
- /*
- * 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)
-
- /**********************************************************************
- *
- * Forward functions.
- *
- **********************************************************************/
-
-
- /**********************************************************************
- *
- * Type definitions.
- *
- **********************************************************************/
-
- /*
- * The camera's motion mode.
- */
- typedef enum
- {
- cmNONE, /* No camera motion. */
- cmRIDE, /* Camera "rides" the rollercoaster. */
- cmSPOTTER, /* "Spotter" camera rotates around the rollercoaster car. */
- cmTRAIL, /* Camera trails the car on the rollercoaster. */
- cmLEAD, /* Camera "leads" the car on the rollercoaster. */
- cmELEVATION, /* Camera pans around and zooms into the rollercoaster elevation. */
- cmPLAN /* Camera pans around and zooms into the rollercoaster plan. */
- } CMMode;
-
- /*
- * This enumerated type tells us what kind of action should be taken
- * on mouse events.
- */
- typedef enum
- {
- mmNONE, /* No mouse move action. */
- mmMOVECAMERA, /* Move the camera on mouse move. */
- mmALTMOVECAMERA, /* Alternative camera motion on mouse move. */
- mmMOVECONTROL, /* Move a spline control point on mouse move. */
- mmMOVELIGHT /* Move the light. */
- } MMMode;
-
- /*
- * The direction of motion of the viewer on the track.
- */
- typedef enum
- {
- vmLEVEL,
- vmCLIMBING,
- vmFALLING
- } VMMode;
-
- /**********************************************************************
- *
- * Application global variables.
- *
- **********************************************************************/
-
- /*
- * The global, single camera instance.
- */
- static RwCamera *Camera = NULL;
-
- static CMMode CameraMode = cmRIDE;
-
- static RwReal CameraAngle = CREAL(0.0);
-
- /*
- * 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 MouseMoveMode = mmNONE;
-
- /*
- * Global variables used to remember the last mouse X and Y coordinates
- * when involved in a pan, zoom, drag or spin.
- */
- static int LastX;
- static int LastY;
-
- /*
- * Line Clearing string
- */
-
- char sGClear[]=" ";
- /*
- * Screen size
- */
-
- int nGScrWidth;
- int nGScrHeight;
-
- /*
- * Default text colour
- */
-
- static int nGTextColour;
-
- /*
- * View Display Mode
- */
-
- static int nGDisplayMode=0;
-
- /*
- * 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 angle of tilt applied to the camera.
- */
- static RwReal CameraTilt = CREAL(0.0);
-
- /*
- * This flag indicates whether the 3D components of the application
- * have been successfully initialized as yet. It is used to guard
- * the message loop handler functions from being invoked before the
- * 3D components of the application are successfully initialized.
- */
- static RwBool ThreeDInitialized = FALSE;
-
-
- /*
- * The current rollercoaster.
- */
- static RollerCoasterType *CurrentCoaster = NULL;
-
- /*
- * The current control point picked (if any).
- */
- static int ControlPoint = 0;
-
- /*
- * Whether to show the coaster's car or not.
- */
- static RwBool ShowCar = TRUE;
-
- static int DrawFPS;
-
- /*
- * Name of the palette and backdrop files to load.
- */
- #define PALETTEFILENAME "rwroller.pal"
- #define BACKDROPFILENAME "mount64.bmp"
-
- /**********************************************************************
- *
- * Functions.
- *
- **********************************************************************/
-
- /****************************************************************************
- DosTimer
-
- Uses the DOS 18 per sec timer to find time in millisecs.
-
- On entry :
- On exit : Timer (in milliseconds)
- */
-
- int DosTimer(void)
- {
- union REGS r;
- int nTime;
-
- r.h.ah=0;
-
- int386(0x1a,&r,&r);
-
- nTime = ((r.w.cx)<<16)|(r.w.dx);
-
- return (nTime*55);
- }
-
-
- /****************************************************************************
- 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;
- }
-
- /**********************************************************************/
-
- static RwBool
- TrackBackdropToCamera(RwCamera *camera)
- {
- RwRaster *backdrop;
- RwInt32 backdropWidth;
- RwInt32 backdropHeight;
- RwV3d at;
- RwReal angle;
- RwInt32 xOffset;
- RwInt32 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);
-
- RwSetCameraBackdropOffset(Camera, xOffset, 0);
- RwSetCameraBackdropViewportRect(Camera, 0, yOffset, windowWidth, backdropHeight);
- }
- return TRUE;
- }
-
-
- /**********************************************************************/
-
- /*
- * Put camera into ride mode.
- */
- static void
- SwitchToRideView(void)
- {
- CameraMode = cmRIDE;
- SwitchToCoasterRideMode(CurrentCoaster);
- /*UpdateMenu(window); */
- }
-
- /**********************************************************************/
-
- /*
- * Put camera into ride mode.
- */
- static void
- SwitchToSpotterView(void)
- {
- CameraMode = cmSPOTTER;
- SwitchToCoasterRideMode(CurrentCoaster);
- /*UpdateMenu(window);*/
- }
-
- /**********************************************************************/
-
- /*
- * Put camera into trail mode.
- */
- static void
- SwitchToTrailView(void)
- {
- CameraMode = cmTRAIL;
- SwitchToCoasterRideMode(CurrentCoaster);
- /*UpdateMenu(window); */
- }
-
- /**********************************************************************/
-
- /*
- * Put camera into lead mode.
- */
- static void
- SwitchToLeadView(void)
- {
- CameraMode = cmLEAD;
- SwitchToCoasterRideMode(CurrentCoaster);
- /*UpdateMenu(window); */
- }
-
- /**********************************************************************/
-
- /*
- * Put camera into elevation mode.
- */
- static void
- SwitchToElevationView(void)
- {
- CameraMode = cmELEVATION;
- SwitchToCoasterEditMode(CurrentCoaster);
-
- RwSetCameraPosition(Camera,
- CurrentCoaster->elevationPosition.x,
- CurrentCoaster->elevationPosition.y,
- CurrentCoaster->elevationPosition.z);
- RwPointCamera(Camera,
- CREAL(0.0),
- CurrentCoaster->elevationPosition.y,
- CREAL(0.0));
- RwSetCameraLookUp(Camera,
- CREAL(0.0),
- CREAL(1.0),
- CREAL(0.0));
- TrackBackdropToCamera(Camera);
- /*UpdateMenu(window);*/
- }
-
- /**********************************************************************/
-
- /*
- * Put the camera into plan mode.
- */
- static void
- SwitchToPlanView(void)
- {
- CameraMode = cmPLAN;
- SwitchToCoasterEditMode(CurrentCoaster);
-
- RwSetCameraPosition(Camera,
- CurrentCoaster->planPosition.x,
- CurrentCoaster->planPosition.y,
- CurrentCoaster->planPosition.z);
-
- /*
- * Unsatisfactory hack to get the camera aligned in the
- * way we wish. This itself will fail if the camera's is
- * looking down the X-axis already - sigh!
- */
- RwSetCameraLookUp(Camera,
- CREAL(1.0),
- CREAL(0.0),
- CREAL(0.0));
- RwPointCamera(Camera,
- CurrentCoaster->planPosition.x,
- CREAL(0.0),
- CurrentCoaster->planPosition.z);
- RwSetCameraLookUp(Camera,
- CREAL(0.0),
- CREAL(0.0),
- CREAL(1.0));
-
- /*UpdateMenu(window); */
- }
-
- /**********************************************************************/
-
- static void
- SwitchCoaster(RollerCoasterType *coaster)
- {
- DestroyRollerCoaster(CurrentCoaster);
- CurrentCoaster = coaster;
- switch (CameraMode)
- {
- case cmRIDE:
- SwitchToRideView();
- break;
- case cmSPOTTER:
- SwitchToSpotterView();
- break;
- case cmTRAIL:
- SwitchToTrailView();
- break;
- case cmLEAD:
- SwitchToLeadView();
- break;
- case cmELEVATION:
- SwitchToElevationView();
- break;
- case cmPLAN:
- SwitchToPlanView();
- break;
- }
- if (ShowCar)
- EnableCoasterCar(CurrentCoaster);
- else
- DisableCoasterCar(CurrentCoaster);
- }
-
- /**********************************************************************/
-
- /*
- * 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.
- */
- static RwBool
- Init3D()
- {
- char version[30];
- char buffer[128];
- int param;
- int i;
- RwReal naWhite[]={CREAL(1.0),CREAL(1.0),CREAL(1.0)};
- long nError;
- char windowText[128];
- RwRaster *backdrop;
- RwReal naBlack[] = {CREAL(0.0),CREAL(0.0),CREAL(0.0)};
- int nBlack;
- RwPointerImage piImage;
- RollerCoasterType *coaster;
-
- /*
- * Attempt to open (and initialize) the RenderWare library.
- * Explicitly specifying the MS Windows driver. Previous
- * versions of RenderWare required the application instance
- * handle to be specified as the device dependent parameter
- * of RwOpen(). Version 1.3 of RenderWare has removed this
- * requirement and NULL should be passed instead.
- */
- /*
- * 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;
- }
-
- /* load the palette */
-
- CheckAndReadPalette("rwroller.pal");
-
- nGTextColour = RwDeviceControl(rwSCRGETCOLOR,0,naWhite,sizeof(naWhite));
- nBlack = RwDeviceControl(rwSCRGETCOLOR,0,naBlack,sizeof(naBlack));
-
- /* Rematch the pointer image */
-
- piImage.image = NULL;
- piImage.hotx=0;
- piImage.hoty=0;
- piImage.w = nBlack;
- piImage.h = nGTextColour;
-
- RwDeviceControl(rwPOINTERSETIMAGE,0,&piImage,sizeof(piImage));
-
- /* Set up character set */
-
- RwGetDeviceInfo(rwSCRHEIGHT,&nGScrHeight,sizeof(nGScrHeight));
- RwGetDeviceInfo(rwSCRWIDTH,&nGScrWidth,sizeof(nGScrWidth));
-
- /*--- Only look for scripts and textures in subdirectories under the current
- one. RWSHAPEPATH need not be set then */
-
- RwSetShapePath(".",rwPRECONCAT);
-
- strcpy(buffer,".");
-
- 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, "DosRoller V%s %s",
- version, (param ? "Fixed" : "Float"));
- DosPrintString(0,nGScrHeight-16,windowText,nGTextColour);
- DosPrintString(8*8,nGScrHeight-24,"Load Save New EditPlan",nGTextColour);
- DosPrintString(8*32,nGScrHeight-16,"EditSide",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.67));
-
- /*
- * 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.
- */
- RwTiltCamera(Camera, CameraTilt);
- RwVCMoveCamera(Camera, CREAL(0.0), CREAL(0.0), CameraDistance);
- RwSetCameraViewwindow(Camera, CREAL(0.8), CREAL(0.8));
-
- /*
- Set up the backdrop
- */
-
- backdrop = RwReadRaster(BACKDROPFILENAME, 0L);
- if (backdrop != NULL)
- RwSetCameraBackdrop(Camera, backdrop);
-
- /*
- * Create a new, default rollercoaster.
- */
- CurrentCoaster = CreateRollerCoaster();
- if (CurrentCoaster == NULL)
- {
- RwDestroyCamera(Camera);
- RwClose();
- return FALSE;
- }
-
- coaster = ReadRollerCoaster("track4.rrc");
- if (coaster != NULL)
- {
- SwitchCoaster(coaster);
- }
-
- SwitchToRideView();
-
- /*
- * All the 3D components are now successfully initialized, so
- * work can begin...
- */
- ThreeDInitialized = TRUE;
-
- return TRUE;
- }
-
- /**********************************************************************/
-
- /*
- * This function shuts down the 3D (i.e. RenderWare) components of the
- * application in a polite fashion.
- */
- static void
- TidyUp3D(void)
- {
- /*
- * Destroy the current coaster.
- */
- if (CurrentCoaster)
- DestroyRollerCoaster(CurrentCoaster);
-
- /*
- * Destroy the camera's backdrop (if any). Backdrops are not
- * automatically destroyed by RwDestroyCamera() so we must
- * manually destroy the backdrop.
- */
- if (RwGetCameraBackdrop(Camera))
- RwDestroyRaster(RwGetCameraBackdrop(Camera));
-
- /*
- * Destroy the camera.
- */
- RwDestroyCamera(Camera);
-
- /*
- * Close the library. This will free up any internal resources and
- * textures loaded.
- */
- RwClose();
- }
-
- /**********************************************************************/
-
- /*
- * Render the scene and copy it to the window and device context
- * given. This function encapsulates the very common RenderWare
- * for rendering and updating the display.
- */
- static void
- RenderScene(void)
- {
- /*
- * Setup the current camera and perform all necessary initialization
- * before rendering takes place.
- */
- RwBeginCameraUpdate(Camera,NULL);
-
- /*
- * Clear the areas of the camera's viewport which were damaged
- * last time round. If this call is not made, ghost images of
- * previous rendering will remain.
- */
- RwClearCameraViewport(Camera);
-
- /*
- * Re-render the entire scene.
- */
- RwRenderScene(CurrentCoaster->scene);
-
- /*
- * Perform all necessary housekeeping after rendering is complete.
- * After this call, the camera's image buffer will be ready to be
- * copied to the display.
- */
- RwEndCameraUpdate(Camera);
-
- /*
- * Copy the camera's image buffer to the output window. Under
- * MS Windows, RenderWare requires both the window handle of the
- * output window and a device context for the client area of the
- * window. Therefore, a LONG is created which holds both the
- * window handle and device context of the output window. This
- * LONG is then passed in as the device specific parameter of
- * the RwShowCameraImage() call.
- */
- RwShowCameraImage(Camera, NULL);
- }
-
- /*******************************************************************************
- ReadLine
-
- On entry : (OUT) buffer to put string in
- On exit :
- */
-
- void ReadLine(char *cpLine)
- {
- int nPos;
- int nKey;
-
- RwDPointerRemove();
- DosPrintString(0,nGScrHeight-8,sGClear,nGTextColour);
- DosPrintString(0,nGScrHeight-8,"Filename : @",nGTextColour);
-
- nPos = 0;
- cpLine[0]='\0';
-
- do {
- nKey = DosGetKey();
-
- if ((nPos>0)&&(nKey==8)) {
- RwDPrintChar((nPos+11)<<3,nGScrHeight-8,'@',nGTextColour);
- RwDPrintChar((nPos+12)<<3,nGScrHeight-8,' ',nGTextColour);
- nPos--;
- cpLine[nPos]='\0';
- };
-
- if ((nPos<25)&&(nKey>32)&&(nKey<127)) {
- cpLine[nPos]=nKey;
- nPos++;
- cpLine[nPos]='\0';
-
- RwDPrintChar((nPos+11)<<3,nGScrHeight-8,nKey,nGTextColour);
- RwDPrintChar((nPos+1+11)<<3,nGScrHeight-8,'@',nGTextColour);
- };
-
- } while (nKey!=13);
-
- DosPrintString(0,nGScrHeight-8,sGClear,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)
- {
- int nOption;
- char sBuffer[128];
- RollerCoasterType *coaster;
-
- if ((y>nGScrHeight-24)&&(y<nGScrHeight-16)) {
- nOption = (x>>6);
- switch(nOption) {
- case 0: {
- DisplayModeFlip();
- break;
- };
- case 1: {
- /* Load */
- ReadLine(sBuffer);
- coaster = ReadRollerCoaster(sBuffer);
- if (coaster != NULL)
- {
- SwitchCoaster(coaster);
- }
- break;
- };
- case 2: {
- /* Save */
- ReadLine(sBuffer);
- WriteRollerCoaster(CurrentCoaster,sBuffer);
- break;
- };
- case 3: {
- /* New */
- coaster = CreateRollerCoaster();
- if (coaster != NULL)
- {
- SwitchCoaster(coaster);
- };
- break;
- };
- case 4: {
- /* EditPlan */
- SwitchToPlanView();
- break;
- };
- default: {
- break;
- };
- };
- };
-
- if ((y>nGScrHeight-16)&&(y<nGScrHeight-8)) {
- SwitchToElevationView();
- };
-
- switch (CameraMode)
- {
- case cmRIDE:
- case cmSPOTTER:
- case cmTRAIL:
- case cmLEAD:
- /*
- * The left button does nothing when riding the
- * coaster.
- */
- MouseMoveMode = mmNONE;
- break;
-
- case cmELEVATION:
- case cmPLAN:
- /*
- * If a control point is picked, move the control
- * point, otherwise, move the camera.
- */
- ControlPoint = IsCoasterControlPointPicked(CurrentCoaster, Camera, x, y);
- if (ControlPoint == 0)
- {
- if (vKeys & MK_SHIFT)
- MouseMoveMode = mmALTMOVECAMERA;
- else
- MouseMoveMode = mmMOVECAMERA;
- }
- else
- {
- MouseMoveMode = mmMOVECONTROL;
- }
- break;
- }
-
- /*
- * If any form of action is to be taken on mouse move, remember the
- * the current x and y position of the mouse and capture future
- * mouse movement.
- */
- if (MouseMoveMode != mmNONE)
- {
- LastX = x;
- LastY = y;
- }
- }
-
- /**********************************************************************/
-
- /*
- * 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 */
-
- vKeys = vKeys;
-
- MouseMoveMode = mmMOVELIGHT;
-
- /*
- * If any form of action is to be taken on mouse move, remember the
- * the current x and y position of the mouse and capture future
- * mouse movement.
- */
- if (MouseMoveMode != mmNONE)
- {
- LastX = x;
- LastY = y;
- }
-
- }
-
- /**********************************************************************/
-
- /*
- * 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. For example, pan and zooming the camera,
- * panning the light, dragging or spinning a clump etc.
- */
- static void
- HandleMouseMove( int x, int y,int vKeys)
- {
- RwV3d position;
- RwV3d newPos;
-
- /* Stop warnings */
-
- vKeys = vKeys;
-
- /*
- * MouseMoveMode tells us what kind of action to perform.
- */
- switch (MouseMoveMode)
- {
- case mmNONE:
- break;
-
- case mmMOVECAMERA:
- switch (CameraMode)
- {
- case cmNONE:
- case cmRIDE:
- case cmSPOTTER:
- case cmTRAIL:
- case cmLEAD:
- break;
-
- case cmELEVATION:
- RwPushScratchMatrix();
- RwRotateMatrix(RwScratchMatrix(),
- CREAL(0.0),
- CREAL(1.0),
- CREAL(0.0),
- RDiv(INT2REAL(LastX - x), CREAL(5.0)),
- rwREPLACE);
- RwTransformCamera(Camera, RwScratchMatrix(), rwPOSTCONCAT);
- RwPopScratchMatrix();
- RwVCMoveCamera(Camera,
- CREAL(0.0),
- CREAL(0.0),
- RDiv(INT2REAL(LastY - y), CREAL(50.0)));
- RwGetCameraPosition(Camera, &position);
- if (position.x < CREAL(-1.5))
- position.x = CREAL(-1.5);
- if (position.x > CREAL( 1.5))
- position.x = CREAL( 1.5);
- if (position.z < CREAL(-1.5))
- position.z = CREAL(-1.5);
- if (position.z > CREAL( 1.5))
- position.z = CREAL( 1.5);
- RwSetCameraPosition(Camera, position.x, position.y, position.z);
- TrackBackdropToCamera(Camera);
- break;
-
- case cmPLAN:
- RwVCMoveCamera(Camera,
- RDiv(INT2REAL(LastX - x), CREAL(50.0)),
- RDiv(INT2REAL(y - LastY), CREAL(50.0)),
- CREAL(0.0));
- RwGetCameraPosition(Camera, &position);
- if (position.x < CREAL(-1.0))
- position.x = CREAL(-1.0);
- if (position.x > CREAL( 1.0))
- position.x = CREAL( 1.0);
- if (position.z < CREAL(-1.0))
- position.z = CREAL(-1.0);
- if (position.z > CREAL( 1.0))
- position.z = CREAL( 1.0);
- RwSetCameraPosition(Camera, position.x, position.y, position.z);
- break;
- }
- break;
-
- case mmALTMOVECAMERA:
- switch (CameraMode)
- {
- case cmNONE:
- case cmRIDE:
- case cmSPOTTER:
- case cmTRAIL:
- case cmLEAD:
- break;
-
- case cmELEVATION:
- RwVCMoveCamera(Camera,
- CREAL(0.0),
- RDiv(INT2REAL(y - LastY), CREAL(50.0)),
- CREAL(0.0));
- RwGetCameraPosition(Camera, &position);
- if (position.y < DEFAULTGROUNDLEVEL)
- position.y = DEFAULTGROUNDLEVEL;
- if (position.y > DEFAULTSKYLEVEL)
- position.y = DEFAULTSKYLEVEL;
- RwSetCameraPosition(Camera, position.x, position.y, position.z);
- TrackBackdropToCamera(Camera);
- break;
-
- case cmPLAN:
- RwVCMoveCamera(Camera,
- CREAL(0.0),
- CREAL(0.0),
- RDiv(INT2REAL(y - LastY), CREAL(50.0)));
- RwGetCameraPosition(Camera, &position);
- if (position.y < DEFAULTGROUNDLEVEL)
- position.y = DEFAULTGROUNDLEVEL;
- if (position.y > DEFAULTSKYLEVEL)
- position.y = DEFAULTSKYLEVEL;
- RwSetCameraPosition(Camera, position.x, position.y, position.z);
- break;
- }
- break;
-
- case mmMOVECONTROL:
- RwPushScratchMatrix();
- /*
- * This function (from pick.c) returns the new position for a clump which lies under
- * the given viewport coordinates. This allows as to drag control points exactly
- * under the mouse pointer.
- */
- GetClumpPositionUnderPointer(COASTERCONTROLPOINT(CurrentCoaster, ControlPoint),
- Camera, x, y, &newPos);
- RwTranslateMatrix(RwScratchMatrix(), newPos.x, newPos.y, newPos.z, rwREPLACE);
- TransformCoasterControlPoint(CurrentCoaster, ControlPoint, RwScratchMatrix());
- RwPopScratchMatrix();
- break;
-
- case mmMOVELIGHT:
- /*
- * We are panning the light about the origin. We will rotate
- * the light about the Y axis for movements of the mouse in
- * X and rotate the light about the X axis for movements of
- * the mouse in Y. In this case we will ignore the effects
- * of camera orientation changes.
- */
- RwPushScratchMatrix();
- /*
- * Replace the CTM with a rotation matrix about Y. The number
- * of degrees of rotation is given by the mouse X delta.
- */
- RwRotateMatrix(RwScratchMatrix(), CREAL(0.0), CREAL(1.0), CREAL(0.0),
- INT2REAL(LastX - x), rwREPLACE);
-
- /*
- * Postconcat another rotation onto the CTM. The new rotation
- * is a rotation about X, the angle being given by the mouse
- * Y delta.
- */
- RwRotateMatrix(RwScratchMatrix(), CREAL(1.0), CREAL(0.0), CREAL(0.0),
- INT2REAL(LastY - y), rwPOSTCONCAT);
-
- /*
- * Transform the light by the resultant rotations.
- */
- RwTransformLight(CurrentCoaster->light, RwScratchMatrix(), rwPOSTCONCAT);
- RwPopScratchMatrix();
- break;
- }
-
- if (MouseMoveMode != mmNONE)
- {
- /*
- * Re-render the scene and copy the results to the display.
- */
- RenderScene();
-
- /*
- * Remember the current X and Y for next time.
- */
- LastX = x;
- LastY = y;
- }
- }
-
- /**********************************************************************/
-
- /*
- * 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)
- {
- /*
- * If we were engaged in a mouse move action and the button has come
- * back up, then terminate the action and release mouse capture.
- */
- switch (MouseMoveMode)
- {
- case mmNONE:
- break;
-
- case mmMOVECAMERA:
- case mmALTMOVECAMERA:
- MouseMoveMode = mmNONE;
- switch (CameraMode)
- {
- case cmRIDE:
- case cmSPOTTER:
- case cmTRAIL:
- case cmLEAD:
- break;
-
- case cmELEVATION:
- RwGetCameraPosition(Camera, &CurrentCoaster->elevationPosition);
- break;
-
- case cmPLAN:
- RwGetCameraPosition(Camera, &CurrentCoaster->planPosition);
- break;
- }
- break;
-
- case mmMOVECONTROL:
- MouseMoveMode = mmNONE;
- UpdateCoasterClump(CurrentCoaster);
- RwInvalidateCameraViewport(Camera);
- RenderScene();
- break;
- }
-
-
- }
-
- /**********************************************************************/
-
- /*
- * 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()
- {
- /*
- * If we were engaged in a mouse move action and the button has come
- * back up, then terminate the action and release mouse capture.
- */
- MouseMoveMode = mmNONE;
- }
-
-
- /**********************************************************************/
-
- /*
- * Handle MS Window's timer expiry. This function will perform any
- * animation actions necessary, including spinning clumps and animating
- * textures.
- */
- static void
- OnTimer()
- {
- RwReal x;
- RwReal y;
- RwReal z;
-
- if (MouseMoveMode == mmNONE)
- {
- switch (CameraMode)
- {
- case cmRIDE:
- UpdateViewParameters(CurrentCoaster);
- RwSetCameraLookUp(Camera, CREAL(0.0), CREAL(1.0), CREAL(0.0));
- RwSetCameraLookAt(Camera,
- CurrentCoaster->tAt.x,
- CurrentCoaster->tAt.y,
- CurrentCoaster->tAt.z);
- x = RAdd(CurrentCoaster->tPosition.x, RMul(CurrentCoaster->tUp.x, CREAL(0.1)));
- y = RAdd(CurrentCoaster->tPosition.y, RMul(CurrentCoaster->tUp.y, CREAL(0.1)));
- z = RAdd(CurrentCoaster->tPosition.z, RMul(CurrentCoaster->tUp.z, CREAL(0.1)));
- RwSetCameraPosition(Camera, x, y, z);
- TrackBackdropToCamera(Camera);
- UpdateCoasterVelocity(CurrentCoaster);
- break;
-
- case cmSPOTTER:
- UpdateViewParameters(CurrentCoaster);
- RwSetCameraPosition(Camera,
- CurrentCoaster->tPosition.x,
- CurrentCoaster->tPosition.y,
- CurrentCoaster->tPosition.z);
- RwSetCameraLookUp(Camera, CREAL(0.0), CREAL(1.0), CREAL(0.0));
- RwSetCameraLookAt(Camera, CREAL(0.0), CREAL(0.0), CREAL(1.0));
- RwSetCameraLookUp(Camera, CREAL(0.0), CREAL(1.0), CREAL(0.0));
- RwPanCamera(Camera, CameraAngle);
- RwTiltCamera(Camera, CREAL(40.0));
- RwVCMoveCamera(Camera, CREAL(0.0), CREAL(0.0), CREAL(-0.20));
- TrackBackdropToCamera(Camera);
- UpdateCoasterVelocity(CurrentCoaster);
-
- CameraAngle = RAdd(CameraAngle, CREAL(5.0));
- if (CameraAngle > CREAL(360.0))
- CameraAngle = RSub(CameraAngle, CREAL(360.0));
- break;
-
- case cmTRAIL:
- UpdateViewParameters(CurrentCoaster);
- RwSetCameraPosition(Camera,
- CurrentCoaster->tPosition.x,
- CurrentCoaster->tPosition.y,
- CurrentCoaster->tPosition.z);
- RwSetCameraLookUp(Camera, CREAL(0.0), CREAL(1.0), CREAL(0.0));
- RwSetCameraLookAt(Camera,
- CurrentCoaster->tAt.x,
- CurrentCoaster->tAt.y,
- CurrentCoaster->tAt.z);
- RwSetCameraLookUp(Camera,
- CurrentCoaster->tUp.x,
- CurrentCoaster->tUp.y,
- CurrentCoaster->tUp.z);
- RwTiltCamera(Camera, CREAL(45.0));
- RwVCMoveCamera(Camera, CREAL(0.0), CREAL(0.0), CREAL(-0.15));
- TrackBackdropToCamera(Camera);
- UpdateCoasterVelocity(CurrentCoaster);
- break;
-
- case cmLEAD:
- UpdateViewParameters(CurrentCoaster);
- RwSetCameraPosition(Camera,
- CurrentCoaster->tPosition.x,
- CurrentCoaster->tPosition.y,
- CurrentCoaster->tPosition.z);
- RwSetCameraLookUp(Camera, CREAL(0.0), CREAL(1.0), CREAL(0.0));
- RwSetCameraLookAt(Camera,
- CurrentCoaster->tAt.x,
- CurrentCoaster->tAt.y,
- CurrentCoaster->tAt.z);
- RwSetCameraLookUp(Camera,
- CurrentCoaster->tUp.x,
- CurrentCoaster->tUp.y,
- CurrentCoaster->tUp.z);
- RwPanCamera(Camera, CREAL(180.0));
- RwTiltCamera(Camera, CREAL(60.0));
- RwVCMoveCamera(Camera, CREAL(0.0), CREAL(0.0), CREAL(-0.15));
- TrackBackdropToCamera(Camera);
- UpdateCoasterVelocity(CurrentCoaster);
- break;
-
- case cmELEVATION:
- case cmPLAN:
- UpdateViewParameters(CurrentCoaster);
- UpdateCoasterVelocity(CurrentCoaster);
- break;
- }
- }
-
- /*
- * Re-render the scene and copy the results to the display.
- */
- RenderScene();
- }
-
- /**********************************************************************/
-
-
- /***********************************************************************
- DisplayModeFlip
-
- On entry :
- On exit :
- */
-
- void DisplayModeFlip(void)
- {
- nGDisplayMode = (nGDisplayMode+1)&3;
-
- RwDPointerRemove();
-
- switch (nGDisplayMode) {
- case 0: {
- DosPrintString(0,nGScrHeight-24,"Ride ",nGTextColour);
- SwitchToRideView();
- break;
- };
- case 1: {
- DosPrintString(0,nGScrHeight-24,"Trail ",nGTextColour);
- SwitchToTrailView();
- break;
- };
- case 2: {
- DosPrintString(0,nGScrHeight-24,"Lead ",nGTextColour);
- SwitchToLeadView();
- break;
- };
- case 3: {
- DosPrintString(0,nGScrHeight-24,"Spotter ",nGTextColour);
- SwitchToSpotterView();
- break;
- };
- default: {
- break;
- };
- };
- }
-
- /****************************************************************************
- Main
- */
-
- void main(int nArgc,char *saArgv[])
- {
- int nKey;
- int nMouseX,nMouseY,nMouseBut,nOldMouseBut;
- int nChange;
- int nShiftCtrl=0;
- int nDX,nDY;
-
- /* Stop warnings */
-
- nArgc = nArgc;
- saArgv = saArgv;
-
- if (!Init3D())
- {
- exit(-1);
- };
-
- /* Create pointer */
-
- RwDPointerDisplay(&LastX,&LastY,&nOldMouseBut);
-
- nKey = DosGetKey();
-
- DrawFPS = 0;
-
- /* Make sure current mode is displayed on the screen */
- DisplayModeFlip();
-
- while (nKey!=27) { /* ESC quits */
- RwDPointerDisplay(&nMouseX,&nMouseY,&nMouseBut);
-
- /* The other bits */
-
- nDX =(nMouseX-LastX);
- nDY =(nMouseY-LastY);
-
- nKey = DosGetKey();
- nShiftCtrl = DosShiftCtrl();
-
- 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;
- };
- };
-
- if ((nDX)||(nDY)) {
- HandleMouseMove(nMouseX,nMouseY,nShiftCtrl);
- };
-
- OnTimer();
-
- nOldMouseBut = nMouseBut;
- };
-
- /*
- * Tidy up the 3D (RenderWare) components of the application.
- */
-
- TidyUp3D();
-
- exit(0);
- }
-