home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Learn 3D Graphics Programming on the PC
/
Learn_3D_Graphics_Programming_on_the_PC_Ferraro.iso
/
rwdos
/
dosknigh.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-02-15
|
27KB
|
1,114 lines
/**********************************************************************
*
* File : rwknight.c
*
* Abstract :
*
* 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. 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.
*
**********************************************************************/
/**********************************************************************
*
* Header files.
*
**********************************************************************/
#include <i86.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h> /* Required for floating point */
#include <string.h>
#include "rwlib.h"
#include "rwdos.h"
#include "doswrap.h"
#include "danimate.h"
#include "palette.h"
#define DEFINE_GLOBAL
#include "dknight.h"
#undef DEFINE_GLOBAL
/**********************************************************************
*
* Application constants.
*
**********************************************************************/
/*
* MS Windows compatible defines for dos keys CTRL and SHIFT
*/
#define MK_CONTROL 0x4
#define MK_SHIFT 0x2
/**********************************************************************
*
* Type definitions.
*
**********************************************************************/
typedef int BOOL;
/*
* This enumerated type tells us what kind of action should be taken
* on mouse events.
*/
typedef enum
{
MMNoAction,
MMPanCamera,
MMPanLight
} MMMode;
/**********************************************************************
*
* Application global variables.
*
**********************************************************************/
/*
* 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;
/*
* 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;
/* The size of the screen
*/
static int nGScrWidth;
static int nGScrHeight;
/* Text colour
*/
static int nGTextColour;
/*
* Line clear string
*/
static char sGClear[]=" ";
/****************************************************************************
Prototypes
*/
RwRaster *ReadBackdrop(char *filename);
/**********************************************************************
*
* Functions.
*
**********************************************************************/
/****************************************************************************
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;
};
}
/****************************************************************************
DosTimer
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 ascii key code of any depressed key. (Do not wait for a key press.
-> return 0 if no key is pressed)
On entry :
On exit : Key pressed in ascii (or 0 if no key pressed)
*/
int DosGetKey(void)
{
union REGPACK rp;
memset(&rp,0,sizeof(rp));
rp.h.ah = 0x06;
rp.h.dl = 0xff;
intr(0x21,&rp);
if (!(rp.w.flags & 0x40 )) { /* Check Z flag */
/* Got key */
if (rp.h.al) {
return ((int)rp.h.al);
};
memset(&rp,0,sizeof(rp));
rp.h.ah = 0x06;
rp.h.dl = 0xff;
intr(0x21,&rp);
if (!(rp.w.flags & 0x40)) {
return ((int)rp.h.al);
};
return (rp.h.al|0x80);
};
return 0;
}
/**********************************************************************/
/*
* This function initializes the 3D (i.e. RenderWare) components of the
* application. This function opens the RenderWare library, creates a
* camera, a scene, a light and a matrix for spinning.
*/
static BOOL
Init3D()
{
char windowText[128];
char version[30];
int depth;
RwReal naWhite[]={CREAL(1.0),CREAL(1.0),CREAL(1.0)};
long nError;
char buffer[256];
int i;
RwRaster *Raster;
RwReal naBlack[] = {CREAL(0.0),CREAL(0.0),CREAL(0.0)};
int nBlack;
RwPointerImage piImage;
/*
* 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("rwknight.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));
/*--- 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);
/* Set up display size*/
RwGetDeviceInfo(rwSCRHEIGHT,&nGScrHeight,sizeof(nGScrHeight));
RwGetDeviceInfo(rwSCRWIDTH,&nGScrWidth,sizeof(nGScrWidth));
/*
* Label the window with information about the version of
* RenderWare being used. Its rather unlikely that
* RwGetSystemInfo() or RwGetDeviceInfo() will fail so we ignore its
* return value.
*/
RwGetSystemInfo(rwVERSIONSTRING, &version,sizeof(version));
RwGetDeviceInfo(rwRENDERDEPTH, &depth,sizeof(depth));
sprintf(windowText, "DosKnight V%s %d-bit Rendering",
version, depth);
DosPrintString(0,nGScrHeight-16,windowText,nGTextColour);
DosPrintString(0,nGScrHeight-8,
"Demo Knight1 Knight2 Observer",nGTextColour);
MainCamera = RwCreateCamera(nGScrWidth,nGScrHeight-24, NULL);
if (!MainCamera)
{
/*
* 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) main camera\n");
}
else
{
RwClose();
printf("Error creating the RenderWare(tm) main camera\n");
}
exit(-1);
}
FlyCamera = RwCreateCamera(nGScrWidth,nGScrHeight-24, NULL);
if (!FlyCamera)
{
/*
* 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) main camera\n");
}
else
{
RwClose();
printf("Error creating the RenderWare(tm) main camera\n");
}
exit(-1);
}
RwSetCameraViewport(MainCamera, 0, 0, nGScrWidth, nGScrHeight-24);
RwSetCameraViewport(FlyCamera, 0, 0, nGScrWidth, nGScrHeight-24);
Camera = MainCamera;
/* now add the backdrop */
Raster = RwReadRaster("cast256.bmp", 0L);
if (Raster)
{
/* Destroy the existing backdrop raster (if any). */
if (RwGetCameraBackdrop(MainCamera))
RwDestroyRaster(RwGetCameraBackdrop(MainCamera));
/* Set the new backdrop raster. */
RwSetCameraBackdrop(MainCamera, Raster);
RwSetCameraBackdrop(FlyCamera, Raster);
}
/*
* By default, the camera lies on the X-Z plane and points down Z
* into the screen. We shall retain the camera's orientation, but move
* the camera DEFAULT_CAMERA_DISTANCE units down Z away from the screen.
*/
RwVCMoveCamera(MainCamera, CREAL(0.0), CREAL(0.0), CAMERA_DISTANCE);
if (nGScrWidth >= nGScrHeight)
{
RwSetCameraViewwindow(MainCamera, CREAL(0.4), RMul(CREAL(0.4), RDiv(INT2REAL(nGScrHeight), INT2REAL(nGScrWidth))));
RwSetCameraViewwindow(FlyCamera, CREAL(0.4), RMul(CREAL(0.4), RDiv(INT2REAL(nGScrHeight), INT2REAL(nGScrWidth))));
} else {
RwSetCameraViewwindow(MainCamera, RMul(CREAL(0.4), RDiv(INT2REAL(nGScrWidth), INT2REAL(nGScrHeight))), CREAL(0.4));
RwSetCameraViewwindow(FlyCamera, RMul(CREAL(0.4), RDiv(INT2REAL(nGScrWidth), INT2REAL(nGScrHeight))), CREAL(0.4));
};
RwSetCameraBackdropViewportRect(MainCamera, 0, 0, nGScrWidth, nGScrHeight);
RwSetCameraBackdropViewportRect(FlyCamera, 0, 0, nGScrWidth, nGScrHeight);
/*
* Create a scene which will contain the clumps to be rendered and the
* light or lights illuminating those clumps . In this very simple
* application it would be perfectly acceptable to use the default scene
* (as returned by RwDefaultScene()) for rendering. However, it is good
* practice to always create a scene which will be used for your rendering
* and only use the default scene as a bag for currently unused clumps and
* lights.
*/
Scene = RwCreateScene();
if (!Scene)
{
RwDestroyCamera(Camera);
RwClose();
printf("Error creating the RenderWare(tm) scene\n");
exit(-1);
}
/*
* Our scene will be illuminated by a directional light. The illumination
* vector of the light is (-1.0, -1.0, -1.0) and its brightness will be 1.0.
*/
Light = RwCreateLight(rwDIRECTIONAL, CREAL(-1.0), CREAL(-1.0), CREAL(-1.0),
CREAL(1.0));
if (!Light)
{
RwDestroyScene(Scene);
RwDestroyCamera(FlyCamera);
RwDestroyCamera(MainCamera);
RwClose();
printf("Error creating the RenderWare(tm) light\n\n");
return FALSE;
}
/*
* Our scene will be illuminated by a directional light. The illumination
* vector of the light is (-1.0, -1.0, -1.0) and its brightness will be 1.0.
*/
Light = RwCreateLight(rwDIRECTIONAL, CREAL(-1.0), CREAL(-1.0), CREAL(-1.0),
CREAL(1.0));
if (!Light)
{
RwDestroyScene(Scene);
RwDestroyCamera(Camera);
RwClose();
printf("Error creating the RenderWare(tm) light\n");
exit(-1);
}
/*
* Add the new light to our scene.
*/
RwAddLightToScene(Scene, Light);
/*
* All the 3D components are now successfully initialized, so
* work can begin...
*/
ThreeDInitialized = TRUE;
SetCameraState(CAM_MAIN);
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 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's backdrop (if any). Backdrops are not
* automatically destroyed by RwDestroyCamera() so we must
* manually destroy the backdrop.
*/
if (RwGetCameraBackdrop(MainCamera))
{
RwDestroyRaster(RwGetCameraBackdrop(MainCamera));
RwSetCameraBackdrop(MainCamera, NULL);
RwSetCameraBackdrop(FlyCamera, NULL);
}
/*
* Destroy the camera.
*/
RwDestroyCamera(FlyCamera);
RwDestroyCamera(MainCamera);
/*
* 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)
{
RwBeginCameraUpdate(Camera,NULL);
RwClearCameraViewport(Camera);
RwRenderScene(Scene);
RenderKnight();
RwEndCameraUpdate(Camera);
RwShowCameraImage(Camera, NULL);
}
/****************************************************************************
Load a clump
*/
RwClump *
LoadClump(char *fileName)
{
RwClump *clump;
RwTexture *texture;
char buffer[128];
RwErrorCode eCode;
DosPrintString(0,nGScrHeight-24,sGClear,nGTextColour);
DosPrintString(0,nGScrHeight-24,"Loading File...",nGTextColour);
/*
* Attempt to load the file as a script file.
*/
clump = RwReadShape(fileName);
if (!clump)
{
/*
* The load failed. This could be because of errors in the
* script file, insufficient memory, or the file containing
* garbage. We will now examine the error code returned to
* decide whether there was a script file error (in which case
* an error will be issued to the user), whether memory was
* exhausted (a different error is issued to the user), or
* the file contained garbage (in which case we will attempt
* to load the file as a texture instead of a script).
*/
eCode = RwGetError();
switch (eCode)
{
case E_RW_NOMEM:
/*
* Ran out of memory...
*/
sprintf(buffer, "Insufficient memory : %s",fileName);
buffer[40]='\0';
DosPrintString(0,nGScrHeight-24,sGClear,nGTextColour);
DosPrintString(0,nGScrHeight-24,buffer,nGTextColour);
return NULL;
case E_RW_NOFILE:
case E_RW_BADOPEN:
case E_RW_RSPARSE:
case E_RW_RSREAD:
case E_RW_READ:
/*
* We will (somewhat optimistically) assume that if we
* had a read or parse error on the stream then the
* file is not a script file but a texture instead.
* So attempt to load a texture. Note, as we use
* RwGetNamedTexture() to get the texture, the texture
* will not be reloaded if it has been previously loaded
* into RenderWare.
*/
texture = RwGetNamedTexture(fileName);
if (texture)
{
/*
* The file was indeed a texture, so attempt to
* create a decal clump using this texture.
*/
clump = RwCreateSprite(texture);
}
else
{
/*
* The texture load failed, issue an error message
* giving the general nature of the problem.
*/
switch (RwGetError())
{
case E_RW_NOFILE:
case E_RW_BADOPEN:
/*
* Could not open the file...
*/
sprintf(buffer, "Error opening %s", fileName);
buffer[40]='\0';
DosPrintString(0,nGScrHeight-24,sGClear,nGTextColour);
DosPrintString(0,nGScrHeight-24,buffer,nGTextColour);
return NULL;
case E_RW_NOMEM:
/*
* Ran out of memory...
*/
sprintf(buffer,
"No mem for texture %s",
fileName);
buffer[40]='\0';
DosPrintString(0,nGScrHeight-24,sGClear,nGTextColour);
DosPrintString(0,nGScrHeight-24,buffer,nGTextColour);
return NULL;
default:
/*
* We will not enumerate all the errors, so simply
* issue a general failure report.
*/
sprintf(buffer,
"Error reading file %s",
fileName);
buffer[40]='\0';
DosPrintString(0,nGScrHeight-24,sGClear,nGTextColour);
DosPrintString(0,nGScrHeight-24,buffer,nGTextColour);
return NULL;
}
}
break;
default:
/*
* On any other error we will assume there is an error in
* the script file.
*/
sprintf(buffer,
"Error in file %s <%i>",fileName,(int)eCode);
buffer[40]='\0';
DosPrintString(0,nGScrHeight-24,sGClear,nGTextColour);
DosPrintString(0,nGScrHeight-24,buffer,nGTextColour);
return NULL;
}
}
/*
* Return the resulting clump.
*/
DosPrintString(0,nGScrHeight-24,sGClear,nGTextColour);
return clump;
}
/**********************************************************************/
static void
HandleLeftButtonDown(int x, int y,int vKeys)
{
/* Stop warnings */
vKeys = vKeys;
if (y>nGScrHeight-8) {
switch(x>>6) {
case 0: {
/* Demo */
InterActive = (InterActive) ? FALSE : TRUE;
break;
};
case 1: {
/* Knight1 */
SetCameraState(CAM_FLY1);
break;
};
case 2: {
/* Knight2 */
SetCameraState(CAM_FLY2);
break;
};
case 3: {
/* Observer */
if (CameraState == CAM_KNIGHT1) {
SetCameraState(CAM_FLY1);
} else if (CameraState == CAM_KNIGHT2) {
SetCameraState(CAM_FLY2);
};
break;
};
default: {
break;
};
};
};
if (MouseMoveMode != MMNoAction)
{
LastX = x;
LastY = y;
}
}
/**********************************************************************/
static void
HandleRightButtonDown(int x, int y, int vKeys)
{
if (vKeys & MK_CONTROL)
{
MouseMoveMode = MMPanLight;
}
else
{
MouseMoveMode = MMPanCamera;
}
if (MouseMoveMode != MMNoAction)
{
LastX = x;
LastY = y;
}
}
/**********************************************************************/
static void
HandleMouseMove( int x, int y)
{
/*
* MouseMoveMode tells us what kind of action to perform.
*/
switch (MouseMoveMode)
{
case MMNoAction:
break;
case MMPanCamera:
RwVCMoveCamera(MainCamera, CREAL(0.0), CREAL(0.0), -CAMERA_DISTANCE);
RwPanCamera(MainCamera, INT2REAL(LastX - x));
RwVCMoveCamera(MainCamera, CREAL(0.0), CREAL(0.0), CAMERA_DISTANCE);
if (CameraState == CAM_MAIN)
SetBackdrop(MainCamera);
break;
case MMPanLight:
RwPushScratchMatrix();
RwRotateMatrix(RwScratchMatrix(), CREAL(0.0), CREAL(1.0), CREAL(0.0),
INT2REAL(LastX - x), rwREPLACE);
RwRotateMatrix(RwScratchMatrix(), CREAL(1.0), CREAL(0.0), CREAL(0.0),
INT2REAL(LastY - y), rwPOSTCONCAT);
RwTransformLight(Light, RwScratchMatrix(),rwPOSTCONCAT);
RwPopScratchMatrix();
break;
}
if (MouseMoveMode != MMNoAction)
{
LastX = x;
LastY = y;
}
}
/**********************************************************************/
static void
HandleLeftButtonUp(void)
{
if (MouseMoveMode != MMNoAction)
{
MouseMoveMode = MMNoAction;
}
}
/**********************************************************************/
static void
HandleRightButtonUp(void)
{
if (MouseMoveMode != MMNoAction)
{
MouseMoveMode = MMNoAction;
}
}
/**********************************************************************/
static void
HandleTimer()
{
AnimateScene();
AnimateCamera();
/*
* Re-render the scene and copy the results to the display.
*/
RenderScene();
}
/**********************************************************************/
/*static void
HandleMenu(HWND window, WORD menuItem)
{
RECT rect;
switch (menuItem)
{
case M_EXIT:
SendMessage(window, WM_CLOSE, 0, 0L);
break;
case M_WING:
CheckMenuItem(MainMenu, M_WING, (WingOn) ? (MF_BYCOMMAND|MF_UNCHECKED) : (MF_BYCOMMAND|MF_CHECKED));
WingOn = (WingOn) ? FALSE : TRUE;
GetWindowRect(window, &rect);
if (WingOn)
MoveWindow(window, rect.left, rect.top,
(rect.right - rect.left) * 2,
(rect.bottom - rect.top) * 2, TRUE);
else
MoveWindow(window, rect.left, rect.top,
(rect.right - rect.left) / 2,
(rect.bottom - rect.top) / 2, TRUE);
break;
case M_DEMO:
CheckMenuItem(MainMenu, M_DEMO, (!InterActive) ? (MF_BYCOMMAND|MF_UNCHECKED) : (MF_BYCOMMAND|MF_CHECKED));
InterActive = (InterActive) ? FALSE : TRUE;
break;
case M_KNIGHT1:
SetCameraState(CAM_FLY1);
break;
case M_KNIGHT2:
SetCameraState(CAM_FLY2);
break;
case M_OBSERVER:
if (CameraState == CAM_KNIGHT1)
SetCameraState(CAM_FLY1);
else if (CameraState == CAM_KNIGHT2)
SetCameraState(CAM_FLY2);
break;
case M_ABOUT:
KillTimer(window, 1);
DialogBox(AppInstance, "ABOUT", window, MakeProcInstance(AboutDlgProc, AppInstance));
SetTimer( window, 1, 20, NULL );
break;
}
} */
/**********************************************************************/
/*int PASCAL
WinMain(HANDLE instance, HANDLE prevInstance, LPSTR cmdLine, int cmdShow)
{
MSG message;
HWND window;
if (!LoadKnight(window, instance, Scene))
{
TidyUp3D();
DestroyWindow(window);
return FALSE;
}
AnimateKnight(1, "BOB1");
ShowWindow(window, cmdShow);
UpdateWindow(window);
while (GetMessage(&message, (HWND)0, NULL, NULL))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
TidyUp3D();
return message.wParam;
}
*/
void main(int nArgc,char *saArgv[])
{
int nKey;
int nOldMouseBut;
int nDX,nDY;
int nChange;
int nCtrlShift;
RwReal naWhite[]={CREAL(1.0),CREAL(1.0),CREAL(1.0)};
RwReal naBlack[]={CREAL(0.0),CREAL(0.0),CREAL(0.0)};
RwMousePointer mMouse;
int nBlack,nWhite;
/* Stop warnings */
nArgc = nArgc;
saArgv = saArgv;
if (!Init3D())
{
exit(-1);
};
nBlack = RwDeviceControl(rwSCRGETCOLOR,0,naBlack,sizeof(naBlack));
nWhite = RwDeviceControl(rwSCRGETCOLOR,0,naWhite,sizeof(naWhite));
nKey = DosGetKey();
if (!LoadKnight(Scene))
{
TidyUp3D();
exit(-1);
}
AnimateKnight(1, "BOB1");
while (nKey!=27) { /* ESC quits */
RwDeviceControl(rwPOINTERDISPLAY,0,&mMouse,sizeof(mMouse));
nKey = DosGetKey();
nCtrlShift = DosShiftCtrl();
nDX =(mMouse.x-LastX);
nDY =(mMouse.y-LastY);
nChange = (mMouse.buttons&(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(mMouse.x,mMouse.y,nCtrlShift);
break;
};
case 8:
case 8+2+1: {
/* Right Button Down */
HandleRightButtonDown(mMouse.x,mMouse.y,nCtrlShift);
break;
};
case 8+1: {
/* Right down left Up */
HandleLeftButtonUp();
HandleRightButtonDown(mMouse.x,mMouse.y,nCtrlShift);
break;
};
case 2+4: {
/* Right up left Down */
HandleRightButtonUp();
HandleLeftButtonDown(mMouse.x,mMouse.y,nCtrlShift);
break;
};
case 8+2: {
/* Left down RIght Down */
HandleRightButtonDown(mMouse.x,mMouse.y,nCtrlShift);
HandleLeftButtonDown(mMouse.x,mMouse.y,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(mMouse.x,mMouse.y);
};
HandleTimer();
LastX = mMouse.x;
LastY = mMouse.y;
nOldMouseBut = mMouse.buttons;
};
/*
* Tidy up the 3D (RenderWare) components of the application.
*/
TidyUp3D();
exit(0);
}