home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************************
- *
- * File : dosmaze.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.
- *
- **********************************************************************/
-
- /**********************************************************************
- *
- * Header files.
- *
- **********************************************************************/
-
- #include <i86.h>
-
- #include <stdlib.h>
- #include <stdio.h>
-
- #include <string.h>
- #include <math.h> /* Required for floating point */
-
-
- #include "rwlib.h"
- #include "rwtypes.h"
-
- #include "rwdos.h"
- #include "doswrap.h"
-
- #include "palette.h"
-
- /**********************************************************************
- *
- * Application constants.
- *
- **********************************************************************/
-
- /* Key code for delete key */
-
- #define DELETE 8
- #define BOOL int
-
- /*
- * MS Windows compatible defines
- */
-
- #define MK_CONTROL 0x4
- #define MK_SHIFT 0x2
-
-
- /**********************************************************************
- *
- * Type definitions.
- *
- **********************************************************************/
-
- /*
- * This enumerated type tells us what kind of action should be taken
- * on mouse events.
- */
- typedef enum
- {
- MMNoAction,
- MMPanAndZoomCamera,
- MMTiltCamera,
- MMPanLight
- } MMMode;
-
- /**********************************************************************
- *
- * Application global variables.
- *
- **********************************************************************/
-
- /*
- Screen size
- */
-
- static int nGScrWidth;
- static int nGScrHeight;
-
- /*
- Colour Codes
- */
-
- static int nGTextCol;
- static int nGMapCol;
- static int nGCrossCol;
-
- /*
- * The Menu option state
- */
- static int DrawHUD;
-
- /*
- * 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 matrix is used when spinning a clump, it is stored globally
- * so that it is not necessary to re-build the matrix for each frame of
- * animation.
- */
- static RwReal forward,pan;
-
-
- /*
- * 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 = MMNoAction;
-
- /* These are stored in the ClumpData field and specify what animation
- * to perform at each tick.
- */
- #define DONOTHING 0
- #define SPINFADE 1
- #define SPIN 2
- #define TUMBLE 3
-
- /*
- * 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;
-
- /*
- * 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 BOOL ThreeDInitialized = FALSE;
-
-
- #define DUNWIDTH 34
- #define DUNHEIGHT 29
- char map[DUNHEIGHT][DUNWIDTH] =
- {
- {".................................."},
- {"...................1@4*..........."},
- {"...................*..*..........."},
- {"...................3..2..........."},
- {"..............a*****..**d***......"},
- {"..............****......****......"},
- {"..............****......****......"},
- {"..............***C......****......"},
- {"..............3............3......"},
- {".........e*****.......a*****......"},
- {".........****.........****........"},
- {".........****.........****........"},
- {".........***B.........***A........"},
- {".........3............3..........."},
- {"......1***.........1***..........."},
- {"......*............*.............."},
- {"......b***.........b***..........."},
- {"......****.........****..........."},
- {"......****.........****..........."},
- {"......****4*.......***B4*........."},
- {"...........*............*........."},
- {"...........2.........c***........."},
- {"...........**d***....****........."},
- {".............****....****........."},
- {".............****..1*****........."},
- {".............****..*.............."},
- {"................2..3.............."},
- {"................****.............."},
- {".................................."}
- };
-
- #define CLOSEST CREAL(0.1)
- #define NORTH 1
- #define EAST 2
- #define SOUTH 4
- #define WEST 8
- typedef struct _dcell
- {
- int tag;
- RwClump *geometry,*hgeometry,*vgeometry;
- RwMatrix4d *mat;
- struct _dcell *horizontal,*vertical;
- int walls;
- RwScene *contents;
- int dobacking;
- } Dcell;
-
- Dcell dungeon[DUNHEIGHT][DUNWIDTH];
-
- /**********************************************************************
- *
- * Functions.
- *
- **********************************************************************/
-
- /****************************************************************************
- DosDrawLine
-
- Draws a line from (xcord,ycord) to (xcord2,ycord2) on a cameras image raster.
-
- On entry : Camera to write to
- : xcord1
- : ycord1
- : xcord2
- : ycord2
- : colour
- */
-
- void DosDrawLine(RwCamera *pCamera,
- int xcord,
- int ycord,
- int xcord2,
- int ycord2,
- unsigned int colour)
- {
- RwReal x1,y1,x2,y2;
- RwReal dx, dy, tmp;
- int count;
- int p, q;
- unsigned char *cpScreen;
- RwReal vpr,vpb;
- RwRaster *rpRaster;
- int nWidth,nHeight,nDepth,nStride;
-
- rpRaster = (RwRaster *) RwGetCameraImage(pCamera);
-
- nWidth = RwGetRasterWidth(rpRaster);
- nHeight = RwGetRasterHeight(rpRaster);
-
- if ((xcord<0)||(xcord>=nWidth) ||
- (ycord<0)||(ycord>=nHeight)) {
- return;
- };
-
- nDepth = RwGetRasterDepth(rpRaster);
- nStride = RwGetRasterStride(rpRaster);
-
- vpr = INT2REAL(nWidth);
- vpb = INT2REAL(nHeight);
-
- x1 = INT2REAL(xcord);
- y1 = INT2REAL(ycord);
- x2 = INT2REAL(xcord2);
- y2 = INT2REAL(ycord2);
-
- if (x2 < x1)
- {
- tmp = x1;
- x1 = x2;
- x2 = tmp;
- tmp = y1;
- y1 = y2;
- y2 = tmp;
- }
-
- if (x2 == vpr)
- {
- if (x1 == vpr){
- return;
- };
- dx = RSub(x2,x1);
- dy = RSub(y2,y1);
- dy = (dy < 0)? -dy : dy;
- if (dy > dx) {
- x2 = RSub(x2,CREAL( 1));
- };
- }
- if ((y1 == vpb)||(y2 == vpb))
- {
- if (y1==y2) {
- return;
- };
- if (y1 == vpb) {
- y1 = RSub(y1,CREAL(1));
- } else {
- dx = RSub(x2,x1);
- dy = RSub(y2,y1);
- if (dy < dx) {
- y2 = RSub(y2,CREAL(1));
- };
- }
- }
-
- dx = RSub(x2,x1);
- dy = RSub(y2,y1);
-
- p = REAL2INT(dx);
- q = REAL2INT(dy);
-
- if (q < 0) {
- q = -q;
- };
- count = p;
- if (count < q) {
- count = q;
- };
-
- /* We can get x's and y's that fall on the first pixel outside the image
- buffer. So we do some shortening here */
-
- if (count)
- {
- dx = RDiv(dx,INT2REAL(count));
- dy = RDiv(dy,INT2REAL(count));
- };
-
- count++;
-
- /* Draw the line at the correct depth */
-
- cpScreen = RwGetRasterPixels(rpRaster);
-
- if (nDepth==8) {
- while (count--)
- {
- cpScreen[nStride*(REAL2INT(y1))+(REAL2INT(x1))] = colour;
- x1 = RAdd(x1,dx);
- y1 = RAdd(y1,dy);
- }
- } else {
- /* Assume 16 bit */
- while (count--)
- {
- cpScreen[nStride*(REAL2INT(y1))+((REAL2INT(x1))<<1)] = colour;
- cpScreen[nStride*(REAL2INT(y1))+((REAL2INT(x1))<<1) +1] = (colour>>8);
- x1 = RAdd(x1,dx);
- y1 = RAdd(y1,dy);
- }
- };
- }
-
- /****************************************************************************
- DosPrintString
-
- Print a string using the DOS character printing DeviceControl.
-
- On entry : xcord
- : ycord
- : string
- : colour
- On exit :
- */
-
- void DosPrintString(int nX,int nY,char *sString,int nCol)
- {
- for (;(*sString);sString++) {
- RwDPrintChar(nX,nY,(*sString),nCol);
- nX+=8;
- };
- }
-
-
- /****************************************************************************
- 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);
- }
-
- /****************************************************************************
- DosGetKey
-
- Get the key pressed (ascii), 0 if no key 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;
- }
-
- /****************************************************************************
- DosShiftCtrl
-
- Find the status of the Shift,Ctrl etc keys.
-
- 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);
- }
-
- /**********************************************************************/
-
- /*
- * 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)
- {
- RwClump *Room,*RoomSky,*Turn,*TurnF,*TurnB,*clump;
- RwMatrix4d *mat;
- int x,y,dx,dy,i;
- char windowText[128];
- char version[30];
- char buffer[128];
- int param;
- RwReal naTextCol[]={CREAL(1.0),CREAL(1.0),CREAL(1.0)};
- RwReal naMapCol[]={CREAL(0.0),CREAL(1.0),CREAL(0.0)};
- RwReal naCrossCol[]={CREAL(1.0),CREAL(0.0),CREAL(1.0)};
- long nError;
- RwReal naBlack[] = {CREAL(0.0),CREAL(0.0),CREAL(0.0)};
- int nBlack;
- RwPointerImage piImage;
-
-
- /*
- * Attempt to open (and initialize) the RenderWare library.
- * Explicitly specifying the MS Windows driver. The MS Windows
- * device driver requires the application's instance handle so
- * this is passed in as the device specific parameter to RwOpen().
- */
-
- 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 in the palette */
-
- CheckAndReadPalette("rwmaze.pal");
-
- nGTextCol = RwDeviceControl(rwSCRGETCOLOR,0,naTextCol,sizeof(naTextCol));
- 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 = nGTextCol;
-
- RwDeviceControl(rwPOINTERSETIMAGE,0,&piImage,sizeof(piImage));
-
- /* Set up the DOS Character Set */
-
- RwGetDeviceInfo(rwSCRHEIGHT,&nGScrHeight,sizeof(nGScrHeight));
- RwGetDeviceInfo(rwSCRWIDTH,&nGScrWidth,sizeof(nGScrHeight));
-
- nGMapCol = RwDeviceControl(rwSCRGETCOLOR,0,naMapCol,sizeof(naMapCol));
- nGCrossCol = RwDeviceControl(rwSCRGETCOLOR,0,naCrossCol,sizeof(naCrossCol));
-
- 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);
-
-
- /* RwOpenDebugStream("DEBUG:"); */
-
- /*
- * Label the window 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, "DosMaze V%s %s",
- version, (param ? "Fixed" : "Float"));
- DosPrintString(0,nGScrHeight-16,windowText,nGTextCol);
-
-
- /*
- * Create the camera which will be used for rendering. The initial window
- * size the application will create is given by nGScrWidth and
- * nGScrHeight-17 which depends on the screen res used.
- */
-
- Camera = RwCreateCamera(nGScrWidth,nGScrHeight-17, 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);
- }
-
-
- /*
- * The window has been resized. Therefore, it is necessary to
- * to modify the camera's viewport to be the same size as the
- * client area of the window.
- */
- RwSetCameraViewport(Camera, 0, 0, nGScrWidth, nGScrHeight-24);
-
- RwSetCameraBackdropViewportRect(Camera, 0,0,nGScrWidth,nGScrHeight-24);
-
- /* aspect ratio of 1:1 */
-
- if (nGScrWidth >= (nGScrHeight-24)) {
- RwSetCameraViewwindow(Camera,
- CREAL(1.0),
- RMul(CREAL(1.0), RDiv(INT2REAL(nGScrHeight-24), INT2REAL(nGScrWidth))));
- } else {
- RwSetCameraViewwindow(Camera,
- RMul(CREAL(1.0), RDiv(INT2REAL(nGScrWidth), INT2REAL(nGScrHeight-24))),
- CREAL(1.0));
- };
-
- /*
- * Set the camera's background color to cyan.
- */
- RwSetCameraBackColor(Camera, CREAL(0.0), CREAL(0.8), CREAL(0.8));
-
- RwSetCameraBackdrop(Camera, RwReadRaster("backgrou", rwDITHERRASTER) );
- RwSetCameraBackdropOffset(Camera, 0,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(-0.5), CREAL(-1.0), CREAL(0.5),
- 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);
-
-
- /* Create the maze components */
- Turn = RwReadShape("turn.rwx");
- if (!Turn) {
- RwClose();
- printf("Cant find turn.rwx\n");
- exit(-1);
- };
- RwAddClumpToScene(Scene, Turn);
-
- TurnF = RwReadShape("turnf.rwx");
- if (!TurnF) {
- RwClose();
- printf("Cant find turnf.rwx\n");
- exit(-1);
- };
- RwAddClumpToScene(Scene, TurnF);
-
- TurnB = RwReadShape("turnb.rwx");
- if (!TurnB) {
- RwClose();
- printf("Cant find turnb.rwx\n");
- exit(-1);
- };
- RwAddClumpToScene(Scene, TurnB);
-
- Room = RwReadShape("mazeroom.rwx");
- if (!Room) {
- RwClose();
- printf("Cant find mazeroom.rwx\n");
- exit(-1);
- };
- RwAddClumpToScene(Scene, Room);
-
- RoomSky = RwReadShape("roomsky.rwx");
- if (!RoomSky) {
- RwClose();
- printf("Cant find roomsky.rwx\n");
- exit(-1);
- };
- RwAddClumpToScene(Scene, RoomSky);
-
- /*
- * We now scan the array map[][] and for each cell we initialise
- * the corresponding dungeon[][] entry with the appropriate
- * geometry for this cell. Since the room and corridor objects
- * are larger than a single grid square, we arrange that the
- * map[][] array specifies a tag in the top left corner of the
- * room or corridor and the switch statement below ensures the
- * related grids are initialised appropriately.
- */
-
- for (y = 0; y<DUNHEIGHT; y++)
- {
- for (x = 0; x<DUNWIDTH; x++)
- {
- switch(map[y][x])
- {
- default:
- break;
- case '@':
- RwSetCameraPosition(Camera, RAdd(CREAL(0.5),INT2REAL(x)),
- CREAL(0.3),
- RAdd(CREAL(0.5),INT2REAL(y)));
- RwSetCameraLookAt(Camera, CREAL(1.0),CREAL(0),CREAL(0));
- break;
- case '1':
- dungeon[y][x].tag = '1';
- dungeon[y][x].geometry = Turn;
- dungeon[y][x].hgeometry = TurnB;
- dungeon[y][x].vgeometry = TurnF;
- mat = RwCreateMatrix();
- RwTranslateMatrix(mat,INT2REAL(x),CREAL(0),INT2REAL(y),rwREPLACE);
- dungeon[y][x].mat = mat;
- dungeon[y][x].vertical = &dungeon[y+2][x];
- dungeon[y][x].horizontal = &dungeon[y][x+2];
- dungeon[y][x].walls = WEST | NORTH;
-
- dungeon[y][x+1] = dungeon[y][x];
- dungeon[y][x+1].walls = NORTH | SOUTH;
- dungeon[y+1][x] = dungeon[y][x];
- dungeon[y+1][x].walls = WEST | EAST;
- break;
- case '2':
- dungeon[y][x].tag = '2';
- dungeon[y][x].geometry = Turn;
- dungeon[y][x].hgeometry = TurnF;
- dungeon[y][x].vgeometry = TurnB;
- mat = RwCreateMatrix();
- RwTranslateMatrix(mat,INT2REAL(x),CREAL(0),INT2REAL(y+2),rwREPLACE);
- RwRotateMatrix(mat, CREAL(0),CREAL(1),CREAL(0),CREAL(90),rwPRECONCAT);
- dungeon[y][x].mat = mat;
- dungeon[y][x].vertical = &dungeon[y-1][x];
- dungeon[y][x].horizontal = &dungeon[y+1][x+2];
- dungeon[y][x].walls = WEST | EAST;
-
- dungeon[y+1][x] = dungeon[y][x];
- dungeon[y+1][x].walls = WEST | SOUTH;
- dungeon[y+1][x+1] = dungeon[y][x];
- dungeon[y+1][x+1].walls = NORTH | SOUTH;
- break;
- case '3':
- dungeon[y][x].tag = '3';
- dungeon[y][x].geometry = Turn;
- dungeon[y][x].hgeometry = TurnB;
- dungeon[y][x].vgeometry = TurnF;
- mat = RwCreateMatrix();
- RwTranslateMatrix(mat,INT2REAL(x+1),CREAL(0),INT2REAL(y+2),rwREPLACE);
- RwRotateMatrix(mat, CREAL(0),CREAL(1),CREAL(0),CREAL(180),rwPRECONCAT);
- dungeon[y][x].mat = mat;
- dungeon[y][x].vertical = &dungeon[y-1][x];
- dungeon[y][x].horizontal = &dungeon[y+1][x-2];
- dungeon[y][x].walls = WEST | EAST;
-
- dungeon[y+1][x-1] = dungeon[y][x];
- dungeon[y+1][x-1].walls = NORTH | SOUTH;
- dungeon[y+1][x] = dungeon[y][x];
- dungeon[y+1][x].walls = SOUTH | EAST;
- break;
- case '4':
- dungeon[y][x].tag = '4';
- dungeon[y][x].geometry = Turn;
- dungeon[y][x].hgeometry = TurnF;
- dungeon[y][x].vgeometry = TurnB;
- mat = RwCreateMatrix();
- RwTranslateMatrix(mat,INT2REAL(x+2),CREAL(0),INT2REAL(y),rwREPLACE);
- RwRotateMatrix(mat, CREAL(0),CREAL(1),CREAL(0),CREAL(-90),rwPRECONCAT);
- dungeon[y][x].mat = mat;
- dungeon[y][x].vertical = &dungeon[y+2][x+1];
- dungeon[y][x].horizontal = &dungeon[y][x-1];
- dungeon[y][x].walls = NORTH | SOUTH;
-
- dungeon[y][x+1] = dungeon[y][x];
- dungeon[y][x+1].walls = NORTH | EAST;
- dungeon[y+1][x+1] = dungeon[y][x];
- dungeon[y+1][x+1].walls = WEST | EAST;
- break;
- case 'a':
- dungeon[y][x].tag = 'a';
- dungeon[y][x].geometry = Room;
- dungeon[y][x].hgeometry = Room;
- dungeon[y][x].vgeometry = Room;
- mat = RwCreateMatrix();
- RwTranslateMatrix(mat,INT2REAL(x),CREAL(0),INT2REAL(y), rwREPLACE);
- dungeon[y][x].mat = mat;
- dungeon[y][x].vertical = &dungeon[y+4][x];
- dungeon[y][x].horizontal = &dungeon[y][x+4];
-
- dungeon[y][x].walls = 0;
- for (dy=0; dy<4; dy++)
- for (dx=0; dx<4; dx++)
- dungeon[y+dy][x+dx] = dungeon[y][x];
- for (dy=0; dy<4; dy++)
- {
- for (dx=0; dx<4; dx++)
- {
- if (dx == 0)
- dungeon[y+dy][x+dx].walls |= WEST;
- if (dx == 3)
- dungeon[y+dy][x+dx].walls |= EAST;
- if (dy == 0)
- dungeon[y+dy][x+dx].walls |= NORTH;
- if (dy == 3)
- dungeon[y+dy][x+dx].walls |= SOUTH;
- }
- }
- /* punch holes for the two doors */
- dungeon[y][x+3].walls &= ~EAST;
- dungeon[y+3][x].walls &= ~SOUTH;
- break;
- case 'b':
- dungeon[y][x].tag = 'b';
- dungeon[y][x].geometry = Room;
- dungeon[y][x].hgeometry = Room;
- dungeon[y][x].vgeometry = Room;
- mat = RwCreateMatrix();
- RwTranslateMatrix(mat,INT2REAL(x),CREAL(0),INT2REAL(y+4), rwREPLACE);
- RwRotateMatrix(mat, CREAL(0),CREAL(1),CREAL(0),CREAL(90), rwPRECONCAT);
- dungeon[y][x].mat = mat;
- dungeon[y][x].vertical = &dungeon[y-1][x];
- dungeon[y][x].horizontal = &dungeon[y+3][x+4];
-
- dungeon[y][x].walls = 0;
- for (dy=0; dy<4; dy++)
- for (dx=0; dx<4; dx++)
- dungeon[y+dy][x+dx] = dungeon[y][x];
- for (dy=0; dy<4; dy++)
- {
- for (dx=0; dx<4; dx++)
- {
- if (dx == 0)
- dungeon[y+dy][x+dx].walls |= WEST;
- if (dx == 3)
- dungeon[y+dy][x+dx].walls |= EAST;
- if (dy == 0)
- dungeon[y+dy][x+dx].walls |= NORTH;
- if (dy == 3)
- dungeon[y+dy][x+dx].walls |= SOUTH;
- }
- }
- /* punch holes for the two doors */
- dungeon[y][x].walls &= ~NORTH;
- dungeon[y+3][x+3].walls &= ~EAST;
-
- break;
- case 'c':
- dungeon[y][x].tag = 'c';
- dungeon[y][x].geometry = Room;
- dungeon[y][x].hgeometry = Room;
- dungeon[y][x].vgeometry = Room;
- mat = RwCreateMatrix();
- RwTranslateMatrix(mat,INT2REAL(x+4),CREAL(0),INT2REAL(y+4), rwREPLACE);
- RwRotateMatrix(mat, CREAL(0),CREAL(1),CREAL(0),CREAL(180), rwPRECONCAT);
- dungeon[y][x].mat = mat;
- dungeon[y][x].vertical = &dungeon[y-1][x+3];
- dungeon[y][x].horizontal = &dungeon[y+3][x-1];
-
- dungeon[y][x].walls = 0;
- for (dy=0; dy<4; dy++)
- for (dx=0; dx<4; dx++)
- dungeon[y+dy][x+dx] = dungeon[y][x];
- for (dy=0; dy<4; dy++)
- {
- for (dx=0; dx<4; dx++)
- {
- if (dx == 0)
- dungeon[y+dy][x+dx].walls |= WEST;
- if (dx == 3)
- dungeon[y+dy][x+dx].walls |= EAST;
- if (dy == 0)
- dungeon[y+dy][x+dx].walls |= NORTH;
- if (dy == 3)
- dungeon[y+dy][x+dx].walls |= SOUTH;
- }
- }
- /* punch holes for the two doors */
- dungeon[y+3][x].walls &= ~WEST;
- dungeon[y][x+3].walls &= ~NORTH;
-
- break;
- case 'd':
- dungeon[y][x].tag = 'd';
- dungeon[y][x].geometry = Room;
- dungeon[y][x].hgeometry = Room;
- dungeon[y][x].vgeometry = Room;
- mat = RwCreateMatrix();
- RwTranslateMatrix(mat,INT2REAL(x+4),CREAL(0),INT2REAL(y), rwREPLACE);
- RwRotateMatrix(mat, CREAL(0),CREAL(1),CREAL(0),CREAL(-90), rwPRECONCAT);
- dungeon[y][x].mat = mat;
- dungeon[y][x].vertical = &dungeon[y+4][x+3];
- dungeon[y][x].horizontal = &dungeon[y][x-1];
-
- dungeon[y][x].walls = 0;
- for (dy=0; dy<4; dy++)
- for (dx=0; dx<4; dx++)
- dungeon[y+dy][x+dx] = dungeon[y][x];
- for (dy=0; dy<4; dy++)
- {
- for (dx=0; dx<4; dx++)
- {
- if (dx == 0)
- dungeon[y+dy][x+dx].walls |= WEST;
- if (dx == 3)
- dungeon[y+dy][x+dx].walls |= EAST;
- if (dy == 0)
- dungeon[y+dy][x+dx].walls |= NORTH;
- if (dy == 3)
- dungeon[y+dy][x+dx].walls |= SOUTH;
- }
- }
- /* punch holes for the two doors */
- dungeon[y][x].walls &= ~WEST;
- dungeon[y+3][x+3].walls &= ~SOUTH;
-
- break;
- case 'e':
- dungeon[y][x].tag = 'e';
- dungeon[y][x].geometry = RoomSky;
- dungeon[y][x].hgeometry = RoomSky;
- dungeon[y][x].vgeometry = RoomSky;
- mat = RwCreateMatrix();
- RwTranslateMatrix(mat,INT2REAL(x),CREAL(0),INT2REAL(y), rwREPLACE);
- dungeon[y][x].mat = mat;
- dungeon[y][x].vertical = &dungeon[y+4][x];
- dungeon[y][x].horizontal = &dungeon[y][x+4];
- dungeon[y][x].dobacking = 1;
- dungeon[y][x].walls = 0;
- for (dy=0; dy<4; dy++)
- for (dx=0; dx<4; dx++)
- dungeon[y+dy][x+dx] = dungeon[y][x];
- for (dy=0; dy<4; dy++)
- {
- for (dx=0; dx<4; dx++)
- {
- if (dx == 0)
- dungeon[y+dy][x+dx].walls |= WEST;
- if (dx == 3)
- dungeon[y+dy][x+dx].walls |= EAST;
- if (dy == 0)
- dungeon[y+dy][x+dx].walls |= NORTH;
- if (dy == 3)
- dungeon[y+dy][x+dx].walls |= SOUTH;
- }
- }
- /* punch holes for the two doors */
- dungeon[y][x+3].walls &= ~EAST;
- dungeon[y+3][x].walls &= ~SOUTH;
- break;
- case 'A':
- dungeon[y][x].contents = RwCreateScene();
- for (dy=0; dy<4; dy++)
- for (dx=0; dx<4; dx++)
- dungeon[y-dy][x-dx].contents = dungeon[y][x].contents;
- RwAddLightToScene(dungeon[y][x].contents, RwDuplicateLight(Light));
- clump = RwReadShape("c.rwx");
- RwTranslateMatrix(RwScratchMatrix(),CREAL(x-2),CREAL(0),CREAL(y-2), rwREPLACE);
- RwTransformClump(clump, RwScratchMatrix(), rwREPLACE);
- RwAddClumpToScene(dungeon[y][x].contents, clump);
- RwSetClumpData(clump, SPINFADE);
-
- clump = RwReadShape("cube.rwx");
- RwTranslateMatrix(RwScratchMatrix(), CREAL(0.5),CREAL(0),CREAL(0.5), rwREPLACE);
- RwTranslateMatrix(RwScratchMatrix(), CREAL(x),CREAL(0),CREAL(y), rwPRECONCAT);
- RwTransformClump(clump, RwScratchMatrix(), rwREPLACE);
- RwAddClumpToScene(dungeon[y][x].contents, clump);
- RwSetClumpData(clump, TUMBLE);
- break;
-
- case 'B':
- dungeon[y][x].contents = RwCreateScene();
- for (dy=0; dy<4; dy++)
- for (dx=0; dx<4; dx++)
- dungeon[y-dy][x-dx].contents = dungeon[y][x].contents;
- RwAddLightToScene(dungeon[y][x].contents, RwDuplicateLight(Light));
- clump = RwReadShape("cone.rwx");
- RwTranslateMatrix(RwScratchMatrix(),CREAL(0.5),CREAL(0),CREAL(0.5), rwREPLACE);
- RwTranslateMatrix(RwScratchMatrix(), CREAL(x),CREAL(0),CREAL(y), rwPOSTCONCAT);
- RwTransformClump(clump, RwScratchMatrix(), rwREPLACE);
- RwAddClumpToScene(dungeon[y][x].contents, clump);
- RwSetClumpData(clump, TUMBLE);
-
- clump = RwReadShape("flames.rwx");
- RwTranslateMatrix(RwScratchMatrix(), CREAL(0.5),CREAL(0),CREAL(0.5), rwREPLACE);
- RwTranslateMatrix(RwScratchMatrix(), CREAL(x),CREAL(0),CREAL(y-3), rwPOSTCONCAT);
- RwTransformClump(clump, RwScratchMatrix(), rwREPLACE);
- RwAddClumpToScene(dungeon[y][x].contents, clump);
- RwSetClumpData(clump, DONOTHING);
-
- clump = RwReadShape("flames.rwx");
- RwTranslateMatrix(RwScratchMatrix(), CREAL(0.5),CREAL(0),CREAL(0.5), rwREPLACE);
- RwTranslateMatrix(RwScratchMatrix(), CREAL(x-2),CREAL(0),CREAL(y-3), rwPOSTCONCAT);
- RwTransformClump(clump, RwScratchMatrix(), rwREPLACE);
- RwAddClumpToScene(dungeon[y][x].contents, clump);
- RwSetClumpData(clump, DONOTHING);
-
- clump = RwReadShape("flames.rwx");
- RwTranslateMatrix(RwScratchMatrix(), CREAL(0.5),CREAL(0),CREAL(0.5), rwREPLACE);
- RwTranslateMatrix(RwScratchMatrix(), CREAL(x-1),CREAL(0),CREAL(y-1), rwPOSTCONCAT);
- RwTransformClump(clump, RwScratchMatrix(), rwREPLACE);
- RwAddClumpToScene(dungeon[y][x].contents, clump);
- RwSetClumpData(clump, DONOTHING);
- RwForAllPolygonsInClumpReal(clump, RwSetPolygonOpacity, CREAL(0.5));
- break;
- case 'C':
- dungeon[y][x].contents = RwCreateScene();
- for (dy=0; dy<4; dy++)
- for (dx=0; dx<4; dx++)
- dungeon[y-dy][x-dx].contents = dungeon[y][x].contents;
- RwAddLightToScene(dungeon[y][x].contents,
- RwCreateLight(rwDIRECTIONAL,CREAL(0.5),CREAL(1),CREAL(0.5),CREAL(1)));
- clump = RwReadShape("lampshade.rwx");
- RwTranslateMatrix(RwScratchMatrix(),CREAL(0.5),CREAL(0),CREAL(0.5), rwREPLACE);
- RwTranslateMatrix(RwScratchMatrix(), CREAL(x-1),CREAL(1.5),CREAL(y-1), rwPOSTCONCAT);
- RwTransformClump(clump, RwScratchMatrix(), rwREPLACE);
- RwAddClumpToScene(dungeon[y][x].contents, clump);
- RwSetClumpData(clump, TUMBLE);
- clump = RwReadShape("slab.rwx");
- RwTranslateMatrix(RwScratchMatrix(),CREAL(0.5),CREAL(0),CREAL(0.5), rwREPLACE);
- RwTranslateMatrix(RwScratchMatrix(), CREAL(x-1),CREAL(1.5),CREAL(y-1), rwPOSTCONCAT);
- RwTransformClump(clump, RwScratchMatrix(), rwREPLACE);
- RwAddClumpToScene(dungeon[y][x].contents, clump);
- RwSetClumpData(clump, DONOTHING);
- break;
- }
- }
- }
-
- /*
- * 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()
- {
- int x,y;
-
- /*
- * Re-parse the map[][] array and destroy any RenderWare objects we
- * we created in Init3D(). The geometry is all cleaned up by just
- * doing a RwDestroyScene() which will automatically destroy all
- * geometry in the scene along with any light sources.
- */
- for (y=0; y<DUNHEIGHT; y++)
- {
- for (x=0; x<DUNWIDTH; x++)
- {
- switch(map[y][x])
- {
- default:
- case '.':
- case '*':
- break;
- case '1':
- case '2':
- case '3':
- case '4':
- RwDestroyMatrix(dungeon[y][x].mat);
- break;
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- if (dungeon[y][x].contents)
- RwDestroyScene(dungeon[y][x].contents);
- RwDestroyMatrix(dungeon[y][x].mat);
- break;
- case 'R':
- if (dungeon[y][x].contents)
- RwDestroyScene(dungeon[y][x].contents);
- RwDestroyMatrix(dungeon[y][x].mat);
- break;
- }
- }
- }
-
-
- /*
- * 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();
- }
-
- /**********************************************************************/
-
- void
- render(void)
- {
- RwV3d at;
- Dcell *currcell;
- int x,y;
-
- /*
- * Get the camera position and floor() so as to find the cell
- * the camera is currently inside. We use this to limit
- * the amount of geometry we draw just to the immediate
- * vicinity of the camera to get the most performance.
- */
- RwGetCameraPosition(Camera, &at);
- x = REAL2INT(at.x);
- y = REAL2INT(at.z);
- if (x < 0 && x >= DUNWIDTH && y < 0 && y >= DUNHEIGHT)
- return;
- currcell = &dungeon[y][x];
- if (currcell == NULL)
- return;
-
- RwBeginCameraUpdate(Camera,NULL);
-
- /* if any of the cells we'll be drawing require the viewport to be cleared
- * we better do it now.
- */
- if (currcell->vertical->dobacking ||
- currcell->horizontal->dobacking ||
- currcell->dobacking)
- RwClearCameraViewport(Camera);
-
- /*
- * Here we draw the two adjoining rooms/corridors followed by the
- * the room we're currently inside. We do this by transforming the
- * referenced geometry by the previously computed matrix stored with
- * the cell, and drawing the geometry with RenderClump. Each room optionally
- * has a RwScene associated with it which contains the contents of the
- * room. Since we gaurantee that the contents is always completely inside
- * the room, we can draw the contents using RwRenderScene to
- * overpaint the walls of the room we draw using RwRenderClump().
- */
- RwTransformClump(currcell->vertical->vgeometry,currcell->vertical->mat, rwREPLACE);
- RwRenderClump(currcell->vertical->vgeometry);
- if (currcell->vertical->contents)
- RwRenderScene(currcell->vertical->contents);
-
- RwTransformClump(currcell->horizontal->hgeometry,currcell->horizontal->mat, rwREPLACE);
- RwRenderClump(currcell->horizontal->hgeometry);
- if (currcell->horizontal->contents)
- RwRenderScene(currcell->horizontal->contents);
-
-
- RwTransformClump(currcell->geometry,currcell->mat, rwREPLACE);
- RwRenderClump(currcell->geometry);
- if (currcell->contents)
- RwRenderScene(currcell->contents);
-
- RwEndCameraUpdate(Camera);
-
-
-
- /* overlay text onto RW image */
- /* draw crosshair */
- if (MouseMoveMode == MMPanAndZoomCamera)
- {
- DosDrawLine(Camera,(nGScrWidth>>1)-8,(nGScrHeight-24)>>1,
- (nGScrWidth>>1)+8,(nGScrHeight-24)>>1,nGCrossCol);
- DosDrawLine(Camera,nGScrWidth>>1,((nGScrHeight-24)>>1)-8,
- nGScrWidth>>1,((nGScrHeight-24)>>1)+8,nGCrossCol);
- }
-
- if (DrawHUD)
- {
- int dx,dy;
- int xc,yc;
-
- for (dy=-4; dy<=4; dy++)
- {
- for (dx=-4; dx<=4; dx++)
- {
- if (((x+dx) >= 0) && ((x+dx) < DUNWIDTH) &&
- ((y+dy) >= 0) && ((y+dy) < DUNHEIGHT))
- {
- xc = 100 - ((4+1+4)*10) + (dx + 4) * 10;
- yc = + (dy + 4) * 10;
- if (dungeon[y+dy][x+dx].walls & NORTH)
- {
- DosDrawLine(Camera,xc,yc,xc+10,yc,nGMapCol);
- }
- if (dungeon[y+dy][x+dx].walls & WEST)
- {
- DosDrawLine(Camera,xc,yc,xc,yc+10,nGMapCol);
- }
- if (dungeon[y+dy][x+dx].walls & SOUTH)
- {
- DosDrawLine(Camera,xc,yc+10,xc+10,yc+10,nGMapCol);
- }
- if (dungeon[y+dy][x+dx].walls & EAST)
- {
- DosDrawLine(Camera,xc+10,yc,xc+10,yc+10,nGMapCol);
- }
- /* mark spot where we are */
- if ((dx == 0) && (dy == 0)) {
- DosDrawLine(Camera,xc+1,yc+1,xc+9,yc+1,nGTextCol);
- DosDrawLine(Camera,xc+9,yc+1,xc+9,yc+9,nGTextCol);
- DosDrawLine(Camera,xc+9,yc+9,xc+1,yc+9,nGTextCol);
- DosDrawLine(Camera,xc+1,yc+9,xc+1,yc+1,nGTextCol);
- };
- }
- }
- }
- }
-
- RwShowCameraImage(Camera, NULL);
- }
-
- /**********************************************************************/
-
- /*
- * Move the camera forward. We cannot use RwVCMoveCamera() since the
- * camera is potentially tilted up or down - we want to move forward
- * only in the XZ plane. In addition we have some simple periodic
- * movement in the Y direction to give a feeling of walking.
- * We constrain the camera movement by examining the "walls" field
- * of the current cell to determine whether the camera (aka player)
- * is able to move in that direction.
- */
- void
- moveforward(RwReal forward)
- {
- RwV3d pos1,pos2;
- RwV3d at;
- int x1,y1,x2,y2;
- static int dbounce;
-
- RwGetCameraPosition(Camera, &pos1);
- x1 = REAL2INT(pos1.x);
- y1 = REAL2INT(pos1.z);
- RwGetCameraLookAt(Camera, &at);
-
- if (forward)
- {
- if (dbounce >= 8)
- dbounce = 0;
-
- RwWCMoveCamera(Camera, RMul(at.x,forward),
- dbounce >= 4 ? CREAL(0.025) : CREAL(-0.025),
- RMul(at.z,forward));
- dbounce++;
- }
-
- RwGetCameraPosition(Camera, &pos2);
- x2 = REAL2INT(pos2.x);
- y2 = REAL2INT(pos2.z);
-
-
- /* constrain movement based upon cell walls */
- if (REAL2INT(pos2.x - CLOSEST) < x1 && (dungeon[y1][x1].walls & WEST))
- {
- pos2.x = INT2REAL(REAL2INT(pos1.x));
- pos2.x += CLOSEST;
- }
- if (REAL2INT(pos2.x + CLOSEST) > x1 && (dungeon[y1][x1].walls & EAST))
- {
- pos2.x = INT2REAL(REAL2INT(pos1.x) + 1);
- pos2.x -= CLOSEST;
- }
- if (REAL2INT(pos2.z - CLOSEST) < y1 && (dungeon[y1][x1].walls & NORTH))
- {
- pos2.z = INT2REAL(REAL2INT(pos1.z));
- pos2.z += CLOSEST;
- }
- if (REAL2INT(pos2.z + CLOSEST) > y1 && (dungeon[y1][x1].walls & SOUTH))
- {
- pos2.z = INT2REAL(REAL2INT(pos1.z) + 1);
- pos2.z -= CLOSEST;
- }
-
- /* special case diagonal move which causes problems */
- if ((x1 != x2) && (y1 != y2))
- {
- if (y2 > y1)
- {
- if (dungeon[y2-1][x2].walls & SOUTH)
- {
- pos2.z = INT2REAL(REAL2INT(pos1.z) + 1);
- pos2.z -= CLOSEST;
- }
- }
- else
- {
- if (dungeon[y2+1][x2].walls & NORTH)
- {
- pos2.z = INT2REAL(REAL2INT(pos1.z));
- pos2.z += CLOSEST;
- }
- }
- }
-
- RwSetCameraPosition(Camera, pos2.x, pos2.y, pos2.z);
- }
-
-
- /**********************************************************************/
-
- /*
- * 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)
- {
-
-
- if (vKeys & MK_CONTROL)
- {
- MouseMoveMode = MMPanLight;
- }
- else if (vKeys & MK_SHIFT)
- {
- MouseMoveMode = MMTiltCamera;
- }
- else
- {
- MouseMoveMode = MMPanAndZoomCamera;
- forward = CREAL(0.0);
- pan = CREAL(0.0);
- }
-
-
- /*
- * 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 != MMNoAction)
- {
- 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)
- {
-
-
- if (vKeys & MK_CONTROL)
- {
- MouseMoveMode = MMPanLight;
- }
- else if (vKeys & MK_SHIFT)
- {
- MouseMoveMode = MMTiltCamera;
- }
- else
- {
- MouseMoveMode = MMPanAndZoomCamera;
- forward = CREAL(0.0);
- pan = CREAL(0.0);
- }
-
-
- /*
- * 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 != MMNoAction)
- {
- 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 nXCentre,nYCentre;
- RwInt32 offx,offy;
-
- nXCentre = nGScrWidth >>1;
- nYCentre = nGScrHeight >>1;
-
- /*
- * MouseMoveMode tells us what kind of action to perform.
- */
- switch (MouseMoveMode) {
- case MMNoAction:
- break;
-
- case MMPanAndZoomCamera:
- /*
- * We are panning and zooming the camera. Movement of the
- * mouse in the X direction will pan the camera about the
- * origin of world coordinate space, and movement of the mouse
- * in the Y direction will zoom the camera into and out of the
- * the scene.
- */
- /*
- * Pan the camera by mouse X delta degrees.
- */
- pan = RDiv(INT2REAL(nXCentre - x), CREAL(10.0));
-
- /*
- * Zoom the camera by changing the distance the camera
- * is from the origin of the world by mouse Y delta divided
- * by 100 units.
- */
- forward = RDiv(INT2REAL(nYCentre - y), CREAL(400.0));
- break;
-
- case MMTiltCamera:
- /*
- * Move the camera back to the origin, as we wish to tilt about
- * the origin of the world and not about the origin of the
- * camera.
- */
- /*
- * Pan the camera by mouse X delta degrees.
- */
- RwRotateMatrix(RwScratchMatrix(), CREAL(0.0),CREAL(1.0),CREAL(0.0),
- INT2REAL(LastX - x),rwREPLACE);
- RwTransformCameraOrientation(Camera, RwScratchMatrix());
- RwTiltCamera(Camera, INT2REAL(y - LastY));
-
- RwGetCameraBackdropOffset(Camera, &offx,&offy);
- RwSetCameraBackdropOffset(Camera, offx - (LastX - x)*2, offy);
-
- break;
-
- case MMPanLight:
- /*
- * 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(Light, RwScratchMatrix(),rwPOSTCONCAT);
- RwPopScratchMatrix();
- }
-
- /*
- * 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()
- {
- /*
- * If we were engaged in a mouse move action and the button has come
- * back up, then terminate the action and release mouse capture.
- */
- if (MouseMoveMode != MMNoAction)
- {
- MouseMoveMode = MMNoAction;
- }
- }
-
- /**********************************************************************/
-
- /*
- * 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()
- {
-
- RwSetCameraLookUp(Camera, CREAL(0.0),CREAL(1.0),CREAL(0.0));
-
- /*
- * If we were engaged in a mouse move action and the button has come
- * back up, then terminate the action and release mouse capture.
- */
- if (MouseMoveMode != MMNoAction)
- {
- MouseMoveMode = MMNoAction;
- }
- }
-
-
- /**********************************************************************/
-
- /*
- * Each Scene associated with a room enumerates the Clumps and calls
- * this function to perform some simple behaviour. The choice of
- * behaviour is determined by the low 8 bits of the clump's Data
- * field. The bits above the low 8 bits are used as a counter to
- * trigger when orthonormalisation must occur.
- */
- RwClump *
- dispatchbehav(RwClump *obj)
- {
- long val;
- int ortho;
- static RwV3d axis = {CREAL(1),CREAL(1),CREAL(1)};
- static RwReal theta = CREAL(0);
- static RwReal dtheta = CREAL(0.5);
- RwReal opacity;
-
- ortho = 0;
- val = (long)RwGetClumpData(obj);
- switch (val & 255)
- {
- case DONOTHING:
- break;
- case SPINFADE:
- if ((val >> 8) & 32)
- {
- opacity = RDiv(INT2REAL((val >> 8) & 15), CREAL(16));
- if (((val >> 8) & 31) >= 16)
- opacity = RSub(CREAL(1),opacity);
- }
- else
- opacity = 0;
-
- opacity = RSub(CREAL(1),opacity);
- RwForAllPolygonsInClumpReal(obj, RwSetPolygonOpacity, opacity);
- /* fall-thru */
- case SPIN:
- RwRotateMatrix(RwScratchMatrix(), CREAL(0.0),CREAL(1.0),CREAL(0.0),
- CREAL(10), rwREPLACE);
- RwTransformClumpJoint(obj, RwScratchMatrix(), rwPRECONCAT);
- ortho = 1;
- break;
- case TUMBLE:
- theta = RAdd(theta, dtheta);
- if ((theta <= CREAL(-30)) || (theta >= CREAL(30)))
- dtheta = -dtheta;
- if (theta == CREAL(0))
- {
- axis.x = rand();
- axis.y = rand();
- axis.z = rand();
- }
- RwRotateMatrix(RwScratchMatrix(), axis.x, axis.y,axis.z,
- theta, rwREPLACE);
- RwTransformClumpJoint(obj, RwScratchMatrix(), rwPRECONCAT);
- ortho = 1;
- break;
- }
-
- /* Do periodic orthonormalisation if we're using rotation */
- if (ortho)
- {
- val += 256;
- RwSetClumpData(obj, val);
- if (((val>>8) & 127) == 0)
- {
- RwGetClumpJointMatrix(obj, RwScratchMatrix());
- RwOrthoNormalizeMatrix(RwScratchMatrix(), RwScratchMatrix());
- RwTransformClumpJoint(obj, RwScratchMatrix(), rwREPLACE);
- }
- }
- return(obj);
- }
-
- /**********************************************************************/
-
- /*
- * Handle MS Window's timer expiry. This function will perform any
- * animation actions necessary, including spinning clumps and animating
- * textures.
- */
- static void
- HandleTimer(void)
- {
- static int FrameNumber = 0;
- RwInt32 dx,dy;
- RwV3d at;
- Dcell *currcell;
-
- FrameNumber++;
-
- /*
- * 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);
-
- /*
- * Perform any behaviour for each scene associated with visible
- * clumps.
- */
- RwGetCameraPosition(Camera, &at);
- dx = REAL2INT(at.x);
- dy = REAL2INT(at.z);
- currcell = &dungeon[dy][dx];
- if (currcell->vertical->contents)
- RwForAllClumpsInScene(currcell->vertical->contents, dispatchbehav);
- if (currcell->horizontal->contents)
- RwForAllClumpsInScene(currcell->horizontal->contents, dispatchbehav);
- if (currcell->contents)
- RwForAllClumpsInScene(currcell->contents, dispatchbehav);
-
-
- if (pan || forward)
- {
- RwRotateMatrix(RwScratchMatrix(), CREAL(0.0),CREAL(1.0),CREAL(0.0),pan,rwREPLACE);
- RwTransformCameraOrientation(Camera, RwScratchMatrix());
- moveforward(forward);
- RwGetCameraBackdropOffset(Camera, &dx,&dy);
- RwSetCameraBackdropOffset(Camera, dx-REAL2INT(pan)*2, dy);
- }
-
- render();
- }
-
-
- /****************************************************************************
- Main
- */
-
- void main(int nArgc,char *saArgv[])
- {
- int nKey;
- int nMouseX,nMouseY,nMouseBut,nOldMouseBut,nOldMouseX,nOldMouseY;
- int nDX,nDY;
- int nChange;
- int nCtrlShift;
-
- /* Stop warnings */
-
- nArgc = nArgc;
-
- if (!Init3D(saArgv[0]))
- {
- exit(-1);
- };
-
-
- DrawHUD=1;
-
- /*
- * Parse any command line parameters.
- */
-
- RwDPointerDisplay(&nOldMouseX,&nOldMouseY,&nOldMouseBut);
-
- nKey = DosGetKey();
-
- while (nKey!=27) { /* ESC quits */
-
- RwDPointerDisplay(&nMouseX,&nMouseY,&nMouseBut);
-
- nKey = DosGetKey();
-
- nCtrlShift = DosShiftCtrl();
-
- nDX =(nMouseX-nOldMouseX);
- nDY =(nMouseY-nOldMouseY);
-
- 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,nCtrlShift);
-
- break;
- };
- case 8:
- case 8+2+1: {
- /* Right Button Down */
-
-
- HandleRightButtonDown(nMouseX,nMouseY,nCtrlShift);
-
- break;
- };
- case 8+1: {
- /* Right down left Up */
-
- HandleLeftButtonUp();
- HandleRightButtonDown(nMouseX,nMouseY,nCtrlShift);
-
- break;
- };
- case 2+4: {
- /* Right up left Down */
-
-
- HandleRightButtonUp();
- HandleLeftButtonDown(nMouseX,nMouseY,nCtrlShift);
-
-
- break;
- };
- case 8+2: {
- /* Left down RIght Down */
-
-
- HandleRightButtonDown(nMouseX,nMouseY,nCtrlShift);
- HandleLeftButtonDown(nMouseX,nMouseY,nCtrlShift);
-
-
- 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) {
- /* Mouse Move */
- HandleMouseMove(nMouseX,nMouseY);
- };
-
-
-
- HandleTimer();
-
- nOldMouseX = nMouseX;
- nOldMouseY = nMouseY;
- nOldMouseBut = nMouseBut;
-
- };
-
- /*
- * Tidy up the 3D (RenderWare) components of the application.
- */
-
- TidyUp3D();
-
- exit(0);
- }
-
-
- /**********************************************************************/
-