home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Learn 3D Graphics Programming on the PC
/
Learn_3D_Graphics_Programming_on_the_PC_Ferraro.iso
/
rwdos
/
dosexp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-02-15
|
42KB
|
1,803 lines
/**********************************************************************
*
* File : dosexp.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 "rwdos.h"
#include "doswrap.h"
/****************************************************************************
Defines
*/
/* Key code for delete key */
#define DELETE 8
/*
* MS Windows compatible defines for dos keys CTRL and SHIFT
*/
#define MK_CONTROL 0x4
#define MK_SHIFT 0x2
/*
* Maximum amount of different launch objects
*/
#define MAX_OBJECT_TYPES 20
#define MAX_OBJECTS 5
#define MAX_BITS 80
/* How high off the platform an object needs to be before it bounces */
#define OBJ_SIZE CREAL(0.5)
/* The accelleration due to gravity on an object */
#define FORCE_OF_GRAVITY 0.002
/* A bit is part of an explosion, an object is something to blow up */
#define TYPE_OBJECT 0
#define TYPE_BIT 1
/* Amount of frames after button down that fire its taken into account */
#define FIRE_FRAMES 4
/****************************************************************************
Types
*/
/*
Defines how things are launched, speeds types etc
*/
typedef struct LaunchTag
{
RwReal nMaxVel;
RwReal nMinVel;
RwReal nZOff; /* Spread */
RwReal nXOff;
RwReal nExpVel;
int nAmoLaunch;
int nMinLaunchTime;
int nMaxLaunchTime;
int nMinSetTime;
int nMaxSetTime;
RwClump *cpaObjects[MAX_OBJECT_TYPES];
int nLaunchObject;
int nAmoObjects;
int nMaxBounce;
int nSetCountDown;
int nLaunchCountDown;
int nLaunchObjCount;
} Launch;
/*
Defines a launched object either something to blow up or a bit
*/
typedef struct LaunchObjectTag
{
int nUsed;
int nType;
RwClump *cpGeo;
RwV3d vPos,vVel;
RwMatrix4d *mpRot,*mpPos;
RwV3d vAxis;
RwReal nRotAngle;
} LaunchObject;
/****************************************************************************
Globals
*/
/* Globals for handling objects and object launching */
static Launch lGLaunch;
static LaunchObject loaGLObjects[MAX_OBJECTS];
static LaunchObject loaGLBits[MAX_BITS];
/* 3d globals */
static RwScene *Scene;
static RwCamera *Camera;
static RwLight *Light;
static ThreeDInitialized = FALSE;
static unsigned long frames = 0;
/* Current button status */
static int bButtonDown = 0;
/* String for clearing */
static char sGClear[]=" ";
/*
* 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;
/*
Screen size
*/
static int nGScrWidth;
static int nGScrHeight;
/*
Colour Codes
*/
static int nGTextCol;
/* Pick info */
static RwPickRecord pGPick;
static int nGPickStatus;
/* Fire Counter */
static int nGFireCount;
/* "Score" */
static int nGTargets;
static int nGHits;
static int nGShots;
/****************************************************************************
Cursor Images
*/
/* 16 by 16 image */
#define MOUSE_ARROW_X 0
#define MOUSE_ARROW_Y 0
#define MOUSE_ARROW_W 16
#define MOUSE_ARROW_H 16
static void *pGMouseArrow;
static char sGMouseArrow[]="\
aaaa \
abbbaaa \
abbbbbbaaa \
abbbbbbbbba \
abbbbbbba \
abbbbbba \
abbbbbba \
abbbbbba \
abbaabbba \
aba abbba \
a abbba \
abbba \
abbba \
abba \
aa \
";
/* 28 x 20 */
#define MOUSE_FIRE_X 14
#define MOUSE_FIRE_Y 15
#define MOUSE_FIRE_W 28
#define MOUSE_FIRE_H 20
static void *pGMouseFire;
static char sGMouseFire[]="\
aaaaaa a aaaaa aaaaa \
abbbbba aba abbbbba abbbbba\
abaaaa aba abaaaaba abaaaa \
abaa aba abaaaaba abaa \
abbba aba abbbbba abbba \
abaa aba abaaaba abaa \
aba aba aba aba abaaaa \
aba aba aba aba abbbbba\
a a a a aaaaa \
\
aaaaaaa \
abbbbbbba \
ab ba \
ab ba \
ab ba \
ab ba \
ab ba \
ab ba \
abbbbbbba \
aaaaaaa ";
/* 12 x 10 */
#define MOUSE_SIGHT_X 6
#define MOUSE_SIGHT_Y 5
#define MOUSE_SIGHT_W 11
#define MOUSE_SIGHT_H 10
static void *pGMouseSight;
static char sGMouseSight[]="\
aaaaaaa \
abbbbbbba \
ab ba\
ab ba\
ab ba\
ab ba\
ab ba\
ab ba\
abbbbbbba \
aaaaaaa ";
/*************************************************************************
MakeZippy - Sets polygon to a random colour
(called from RwForAllPolygonsInClump)
On entry : Polygon
On exit :
*/
static void MakeZippy(RwPolygon3d *p)
{
static int zippy = 0;
switch (zippy % 7)
{
case 0: RwSetPolygonColor(p, CREAL(0.7), CREAL(0.0), CREAL(0.0)); break;
case 1: RwSetPolygonColor(p, CREAL(0.0), CREAL(0.7), CREAL(0.0)); break;
case 2: RwSetPolygonColor(p, CREAL(0.0), CREAL(0.0), CREAL(0.7)); break;
case 3: RwSetPolygonColor(p, CREAL(0.7), CREAL(0.7), CREAL(0.0)); break;
case 4: RwSetPolygonColor(p, CREAL(0.7), CREAL(0.0), CREAL(0.7)); break;
case 5: RwSetPolygonColor(p, CREAL(0.0), CREAL(0.7), CREAL(0.7)); break;
case 6: RwSetPolygonColor(p, CREAL(0.7), CREAL(0.7), CREAL(0.7)); break;
}
zippy++;
}
/****************************************************************************
MakeMaterial - Sets a polygons material to the current material
( Called from RwForAllPolygonsInClump)
On entry : Polygon
On exit :
*/
static void MakeMaterial(RwPolygon3d *p)
{
RwSetPolygonMaterial(p,RwCurrentMaterial());
}
/****************************************************************************
SetCountdown - return a random value between max and min value
On entry : Max value
: Min value
On exit : value
*/
int SetCountDown(int nMax,int nMin)
{
int nVal;
nVal = rand()%(nMax-nMin);
return nMin+nVal;
}
/****************************************************************************
SetupLaunch - Setup the launch structure (loading objects etc)
On entry : Launch structure to be set up
On exit :
*/
void SetupLaunch(Launch *plLaunch)
{
RwClump *cpDefault,*cpLoad;
char saFiles[][14]={"banana.rwx",
"ball.rwx",
"c.rwx",
"table.rwx",
"slab.rwx",
"torus.rwx",
"banana.rwx",
"lampshad.rwx",
"dummy.rwx"};
int nCount;
RwMatrix4d *mpScale;
/* Create a scale matrix */
mpScale = RwCreateMatrix();
RwScaleMatrix(mpScale,CREAL(0.05),CREAL(0.05),CREAL(0.05),rwREPLACE);
/* Amount of different objects that can be thrown up */
plLaunch->nAmoObjects = 9;
plLaunch->nMaxVel = CREAL(0.15);
plLaunch->nMinVel = CREAL(0.04);
plLaunch->nZOff = CREAL(0.01); /* Uniform distribution */
plLaunch->nXOff = CREAL(0.01);
plLaunch->nExpVel = CREAL(0.05);
plLaunch->nAmoLaunch = 2;
plLaunch->nMinLaunchTime = 20;
plLaunch->nMaxLaunchTime = 40;
plLaunch->nMinSetTime = 100;
plLaunch->nMaxSetTime = 150;
plLaunch->nLaunchObject=0;
plLaunch->nMaxBounce = 4;
/* Create a default image if the shape cannot be loaded */
RwClumpBegin();
RwSetSurface(CREAL(0.4), CREAL(0.7), CREAL(0.0));
RwSetSurfaceColor(RDiv(CREAL(1.0), INT2REAL(1 + (rand() % 4))),
RDiv(CREAL(1.0), INT2REAL(1 + (rand() % 4))),
RDiv(CREAL(1.0), INT2REAL(1 + (rand() % 4))));
RwSphere(CREAL(0.1),3);
RwClumpEnd(&cpDefault);
/* Put the clumps in the structure */
/* Save the current material */
RwPushCurrentMaterial();
/* Create a default surface type */
RwSetMaterialSurface(RwCurrentMaterial(),CREAL(0.4),CREAL(7.0),CREAL(3.0));
for (nCount=0;nCount<plLaunch->nAmoObjects;nCount++) {
/* Read in shapes - if not found use the default shape */
cpLoad = RwReadShape(saFiles[nCount]);
if (!cpLoad) {
plLaunch->cpaObjects[nCount] = RwDuplicateClump(cpDefault);
} else {
plLaunch->cpaObjects[nCount] = cpLoad;
if (nCount>=5) {
/* Give material and zippify some of the objects */
RwForAllPolygonsInClump(cpLoad, MakeMaterial);
RwForAllPolygonsInClump(cpLoad, MakeZippy);
};
};
/* Make objectunit size */
RwNormalizeClump(plLaunch->cpaObjects[nCount]);
RwTransformClump(plLaunch->cpaObjects[nCount],mpScale,rwREPLACE);
};
/* Restore material */
RwPopCurrentMaterial();
/* Destroy the scale matrix */
RwDestroyMatrix(mpScale);
/* Destroy the unwanted default clump */
RwDestroyClump(cpDefault);
/* Set random launch times */
plLaunch->nLaunchCountDown =
SetCountDown(plLaunch->nMaxLaunchTime,plLaunch->nMinLaunchTime);
plLaunch->nSetCountDown =
SetCountDown(plLaunch->nMaxSetTime,plLaunch->nMinSetTime);
plLaunch->nLaunchObjCount = 0;
for (nCount=0;nCount<MAX_OBJECTS;nCount++) {
/* Make the position (in rotation) and rotation matrixes the identity*/
RwIdentityMatrix(loaGLObjects[nCount].mpRot = RwCreateMatrix());
RwIdentityMatrix(loaGLObjects[nCount].mpPos = RwCreateMatrix());
};
}
/****************************************************************************
CreateBits - Create the explosion bits
On entry : Bits array
: Amount of bits
On exit :
*/
void CreateBits(LaunchObject *loaObject,int nAmo)
{
int nCount;
RwClump *cpBit;
RwClump *cpGeo;
RwV3d vTmp;
RwReal nSize;
/* Create the clump which is an explosion bit */
nSize = CREAL(0.05);
RwClumpBegin();
RwSetSurface(CREAL(0.4), CREAL(0.7), CREAL(0.0));
RwSetSurfaceColor(RDiv(CREAL(1.0), INT2REAL(1 + (rand() % 4))),
RDiv(CREAL(1.0), INT2REAL(1 + (rand() % 4))),
RDiv(CREAL(1.0), INT2REAL(1 + (rand() % 4))));
RwVertex(CREAL(0.0),nSize,CREAL(0.0));
RwVertex(RMul(nSize,CREAL(-0.866)),
RMul(nSize,CREAL(-0.5)),
CREAL(0.0));
RwVertex(RMul(nSize,CREAL(0.866)),
RMul(nSize,CREAL(-0.5)),
CREAL(0.0));
RwVertex(CREAL(0.0),CREAL(0.0),nSize);
RwTriangle(1,4,3);
RwTriangle(2,4,1);
RwTriangle(4,2,3);
RwTriangle(3,2,1);
RwClumpEnd(&cpBit);
/* For all explosion bits */
for (nCount=0;nCount<nAmo;nCount++) {
/* Make a copy of the bit clump */
cpGeo = RwDuplicateClump(cpBit);
if (!cpGeo) {
RwClose();
printf("Unable to duplicate bit clump.\n");
exit(-1);
};
/* Zippify the bit */
RwForAllPolygonsInClump(cpGeo, MakeZippy);
/* Mark as bit and unused */
loaObject[nCount].nUsed=0;
loaObject[nCount].nType=TYPE_BIT;
loaObject[nCount].cpGeo = cpGeo;
RwSetClumpData(cpGeo,NULL); /* Mark with Null pointer */
RwIdentityMatrix(loaObject[nCount].mpRot = RwCreateMatrix());
RwIdentityMatrix(loaObject[nCount].mpPos = RwCreateMatrix());
/* Give it a random rotation */
RandomVec(&vTmp);
RwRotateMatrix(loaObject[nCount].mpRot,vTmp.x,vTmp.y,vTmp.z,
RMul(RSub(RDiv(INT2REAL(rand()),CREAL(16384.0)), CREAL(1.0)),CREAL(10.0)),
rwREPLACE);
};
/* Destroy the default clump */
RwDestroyClump(cpBit);
}
/****************************************************************************
DisplayTargets - display the amount of targets sent up
On entry :
On exit
*/
void DisplayTargets(void)
{
char buffer[10];
sprintf(buffer,"%i ",nGTargets);
DosPrintString(9*8,nGScrHeight-16,buffer,nGTextCol);
}
/****************************************************************************
DisplayShots - display the amount of shots fired
On entry :
On exit
*/
void DisplayShots(void)
{
char buffer[10];
sprintf(buffer,"%i ",nGShots);
DosPrintString(30*8,nGScrHeight-16,buffer,nGTextCol);
}
/****************************************************************************
LaunchObject - Launch an object
On entry : Launch Structure
: Geometry to Launch
On exit :
*/
void DoLaunchObject(Launch *plLaunch,
RwClump *cpGeo)
{
int nCount;
LaunchObject *lopObject=NULL;
RwV3d vTmp;
RwReal nRand;
/* Find a free object */
for (nCount=0;nCount<MAX_OBJECTS;nCount++) {
if (!loaGLObjects[nCount].nUsed) {
lopObject = &(loaGLObjects[nCount]);
break;
};
};
/* Check that the object was actually found */
if (!lopObject) {
return;
};
/* Set up the object */
lopObject->nUsed = 1; /* Mark as used */
lopObject->nType = TYPE_OBJECT;
lopObject->cpGeo = cpGeo;
/* Point the data to this launch object */
RwSetClumpData(cpGeo,(void *)lopObject);
/* Stick it in the scene */
RwAddClumpToScene(Scene,lopObject->cpGeo);
/* place it in the centre of the launch pad */
lopObject->vPos.x = CREAL(0.0);
lopObject->vPos.y = OBJ_SIZE;
lopObject->vPos.z = CREAL(0.0);
/* Give it a random velocity */
nRand = RDiv(INT2REAL(rand()>>1),CREAL(16384.0));
lopObject->vVel.x = RSub(RMul(RAdd(plLaunch->nXOff,
plLaunch->nXOff),nRand),
plLaunch->nXOff);
nRand = RDiv(INT2REAL(rand()>>1),CREAL(16384.0));
lopObject->vVel.y =
RAdd(RMul(RSub(plLaunch->nMaxVel,
plLaunch->nMinVel),nRand),
plLaunch->nMinVel);
nRand = RDiv(INT2REAL(rand()>>1),CREAL(16384.0));
lopObject->vVel.z = RSub(RMul(RAdd(plLaunch->nZOff,
plLaunch->nZOff),nRand),
plLaunch->nZOff);
/* Give it a random rotation */
RandomVec(&vTmp);
RwRotateMatrix(lopObject->mpRot,vTmp.x,vTmp.y,vTmp.z,
RMul(RSub(RDiv(INT2REAL(rand()),CREAL(16384.0)), CREAL(1.0)),CREAL(20.0)),
rwREPLACE);
/* Increase the target counter */
nGTargets++;
DisplayTargets();
}
/****************************************************************************
DestroyObject - If it is used remove it from the scene
On entry : Object to destroy
On exit :
*/
void DestroyObject(LaunchObject *lopObject)
{
if (lopObject->nUsed) {
lopObject->nUsed =0;
RwRemoveClumpFromScene(lopObject->cpGeo);
};
}
/****************************************************************************
Handle Launch - handle the launching of objects
On entry : Launch structure
On exit : 0 if no launch
*/
int HandleLaunch(Launch *plLaunch)
{
int nLaunch=0;
if (!(plLaunch->nSetCountDown--)) {
/* Start a set launch sequence */
plLaunch->nLaunchObjCount = plLaunch->nAmoLaunch;
plLaunch->nSetCountDown =
SetCountDown(plLaunch->nMaxSetTime,plLaunch->nMinSetTime);
plLaunch->nLaunchCountDown =
SetCountDown(plLaunch->nMaxLaunchTime,plLaunch->nMinLaunchTime);
};
/* Check the launch sequence in a set */
if ((plLaunch->nLaunchObjCount)&&(!(plLaunch->nLaunchCountDown--))) {
/* Restet the object counters */
plLaunch->nLaunchCountDown =
SetCountDown(plLaunch->nMaxLaunchTime,plLaunch->nMinLaunchTime);
plLaunch->nLaunchObjCount--;
/* Initiate a launch */
DoLaunchObject(plLaunch,plLaunch->cpaObjects[plLaunch->nLaunchObject]);
nLaunch=1;
/* Change the object */
plLaunch->nLaunchObject++;
if (plLaunch->nLaunchObject>=plLaunch->nAmoObjects) {
plLaunch->nLaunchObject=0;
};
};
return nLaunch;
}
/****************************************************************************
CreateExplosion
On entry : Vector position of explosion
: Amount of Bits
On exit :
*/
void CreateExplosion(RwV3d *vpPos,RwV3d *vpVel,int nAmo)
{
int nCount;
LaunchObject *lopBit;
RwReal nRand;
lopBit = loaGLBits;
RwPushScratchMatrix();
for (nCount=0;nCount<MAX_BITS;nCount++) {
if (!lopBit->nUsed) {
/* Create an explosion bit */
/* Mark as used */
lopBit->nUsed = 2;
/* Give it a velocity and position */
lopBit->vPos = (*vpPos);
lopBit->vVel = (*vpVel);
/* Offset the velocity by a random vector */
nRand = RDiv(INT2REAL(rand()>>1),CREAL(16384.0));
lopBit->vVel.x += RSub(RMul(RAdd(lGLaunch.nExpVel,
lGLaunch.nExpVel),nRand),
lGLaunch.nExpVel);
nRand = RDiv(INT2REAL(rand()>>1),CREAL(16384.0));
lopBit->vVel.y += RSub(RMul(RAdd(lGLaunch.nExpVel,
lGLaunch.nExpVel),nRand),
lGLaunch.nExpVel);
nRand = RDiv(INT2REAL(rand()>>1),CREAL(16384.0));
lopBit->vVel.z += RSub(RMul(RAdd(lGLaunch.nExpVel,
lGLaunch.nExpVel),nRand),
lGLaunch.nExpVel);
/* Make the pos the identity matrix */
RwIdentityMatrix(lopBit->mpPos);
/* Stick it in the scene */
RwAddClumpToScene(Scene,lopBit->cpGeo);
/* Check if can create any more */
if (!(--nAmo)) {
/* Exit -> all used up */
RwPopScratchMatrix();
return;
};
};
/* Next Bit */
lopBit++;
};
RwPopScratchMatrix();
}
/****************************************************************************
MoveObjects
On entry : pointer to launch objects
: amount of objects
*/
void MoveObjects(LaunchObject *loaObject, int nAmo,Launch *lpLaunch)
{
int i;
RwV3d p;
LaunchObject *lopObject;
/* Save current matrix */
RwPushScratchMatrix();
/* For all launch objects in list */
for (i=0; i<nAmo; i++)
{
lopObject = &loaObject[i];
if (lopObject->nUsed) {
/* Apply rotation to rotation position matrix */
RwMultiplyMatrix(lopObject->mpPos,lopObject->mpRot,RwScratchMatrix());
/* Normalize matrix if its time to */
if ((frames)%(nAmo<<3) ==(i<<3)) {
RwOrthoNormalizeMatrix(RwScratchMatrix(), RwScratchMatrix());
};
/* Save rotation pos */
RwCopyMatrix(RwScratchMatrix(), lopObject->mpPos);
/* Position clump */
p = lopObject->vPos;
RwTranslateMatrix(RwScratchMatrix(), p.x,p.y,p.z, rwPOSTCONCAT);
RwTransformClump(lopObject->cpGeo, RwScratchMatrix(), rwREPLACE);
/* Take into account gravity */
lopObject->vVel.y -= CREAL(FORCE_OF_GRAVITY);
/* Apply velocity */
lopObject->vPos.x += lopObject->vVel.x;
lopObject->vPos.y += lopObject->vVel.y;
lopObject->vPos.z += lopObject->vVel.z;
/* Has it hit the platform */
if ((lopObject->vVel.y<CREAL(0.0))&&
(RAbs(lopObject->vPos.x)<CREAL(1.0)) &&
(RAbs(lopObject->vPos.z)<CREAL(1.0))) {
if (lopObject->nType==TYPE_BIT) {
/* has it hit ?*/
if (lopObject->vPos.y<CREAL(0.1)) {
if (lopObject->nUsed<=lpLaunch->nMaxBounce) {
/* Make it bounce */
lopObject->vVel.y = RDiv(-(lopObject->vVel.y),CREAL(1.5));
lopObject->nUsed++;
} else {
/* Destroy the object */
DestroyObject(lopObject);
};
};
} else {
if (lopObject->vPos.y<OBJ_SIZE) {
if (lopObject->nUsed<=lpLaunch->nMaxBounce) {
/* Make it bounce */
lopObject->vVel.y = RDiv(-(lopObject->vVel.y),CREAL(1.5));
lopObject->nUsed++;
} else {
/* Create explosion */
CreateExplosion(&lopObject->vPos,&lopObject->vVel,15);
/* Destroy object */
DestroyObject(lopObject);
};
};
};
};
/* If fallen out of scene destroy anyway */
if (lopObject->vPos.y<CREAL(-8.0)) {
DestroyObject(lopObject);
};
};
};
RwPopScratchMatrix( );
}
/****************************************************************************
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
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
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);
}
/***************************************************************************
RandomVec - create a random vector
On entry : Random vector to create
On exit :
*/
static void RandomVec(RwV3d *vec)
{
vec->x = RSub(RDiv(INT2REAL(rand()),CREAL(16384.0)), CREAL(1.0));
vec->y = RSub(RDiv(INT2REAL(rand()),CREAL(16384.0)), CREAL(1.0));
vec->z = RSub(RDiv(INT2REAL(rand()),CREAL(16384.0)), CREAL(1.0));
}
/****************************************************************************
Init3D
* 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.
On entry : Filename (hopefully including path) of executable
On exit : TRUE if all ok
*/
static int
Init3D(char *sFilename)
{
int i;
int fixed, debugging;
char *title;
RwClump *temp;
RwReal naTextCol[]={CREAL(1.0),CREAL(1.0),CREAL(1.0)};
char buffer[128];
long nError;
if (!RwOpen("DOSMOUSE", &nError))
{
printf("Unable to access renderware!!\n");
switch (nError) {
case E_RW_DOS_MODE_UNAVAILABLE: {
printf("The installed VESA card is unable to switch to the resolution");
printf(" requested.\n");
printf("Either install a different video adapter or use a ");
printf("supported video mode.");
break;
};
case E_RW_DOS_NO_VESA_BIOS: {
printf("A VESA bios is unavailable on this machine.\n");
printf("Either use a VESA compatible Video Adapter or install a ");
printf("VESA bios emulation TSR.\n");
break;
};
case E_RW_DOS_INCOMPATIBLE_BIOS: {
printf("The VESA bios on this machine is not of high enough version ");
printf("to function\ncorrectly with RenderWare. Use a version 1.0 or");
printf(" higher VESA bios or TSR.\n");
break;
};
case E_RW_DOS_NO_MOUSE: {
printf("No Microsoft compatible mouse driver present.\n");
printf("Install a microsoft compatible mouse driver and try again.\n");
break;
};
default: {
printf("Unknown Error !!!!!!!!!!!!!!!\n");
break;
};
};
return FALSE;
}
/* Set up the DOS Character Set */
RwGetDeviceInfo(rwSCRHEIGHT,&nGScrHeight,sizeof(nGScrHeight));
RwGetDeviceInfo(rwSCRWIDTH,&nGScrWidth,sizeof(nGScrWidth));
nGTextCol = RwDeviceControl(rwSCRGETCOLOR,0,naTextCol,sizeof(naTextCol));
RwSetShapePath(".",rwPRECONCAT);
strcpy(buffer,sFilename);
i = strlen(buffer);
while((buffer[i] != '\\')&&(i>=0)) {
i--;
};
if (i>=0) {
buffer[i+1] = 0;
strcat(buffer, "TEXTURES");
RwSetShapePath(buffer, rwPOSTCONCAT);
buffer[i+1] = 0;
strcat(buffer, "SCRIPTS");
RwSetShapePath(buffer, rwPOSTCONCAT);
};
RwSetShapePath("SCRIPTS", rwPRECONCAT);
RwSetShapePath("TEXTURES", rwPRECONCAT);
/*
* Label the window with information about the version of
* RenderWare being used. Its rather unlikely that
* RwGetSystemInfo() will fail so we ignore its return value.
*/
DosPrintString(0,nGScrHeight-16,"Targets:",nGTextCol);
DosPrintString(13*8,nGScrHeight-16,"Hits:",nGTextCol);
DosPrintString(24*8,nGScrHeight-16,"Shots:",nGTextCol);
RwGetSystemInfo(rwFIXEDPOINTLIB, &fixed,sizeof(fixed));
RwGetSystemInfo(rwDEBUGGINGLIB, &debugging,sizeof(debugging));
if ((fixed) && (debugging))
title = "DosExp (Fixed & Debugging)";
else if (fixed)
title = "DosExp (Fixed Point)";
else if (debugging)
title = "DosExp (Debugging)";
else
title = "DosExp (Floating Point)";
/* Temporary message !!*/
DosPrintString(0,nGScrHeight-24,title,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));
RwVCMoveCamera( Camera, CREAL(0.0), CREAL(0.1), CREAL(-6.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 (-0.5, -1.0, -1.0) and its brightness will be 1.0.
*/
Light = RwCreateLight( rwDIRECTIONAL, CREAL(-0.5), CREAL(-1.0), CREAL(-1.0),
CREAL(1.2) );
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);
/*
* Make the launch pad in the simulation
*/
RwClumpBegin();
RwVertex(CREAL(-1.0),CREAL(0.0),CREAL(-1.0));
RwVertex(CREAL(1.0),CREAL(0.0),CREAL(-1.0));
RwVertex(CREAL(1.0),CREAL(0.0),CREAL(1.0));
RwVertex(CREAL(-1.0),CREAL(0.0),CREAL(1.0));
RwVertex(CREAL(-0.8),CREAL(-0.1),CREAL(-0.8));
RwVertex(CREAL(0.8),CREAL(-0.1),CREAL(-0.8));
RwVertex(CREAL(0.8),CREAL(-0.1),CREAL(0.8));
RwVertex(CREAL(-0.8),CREAL(-0.1),CREAL(0.8));
RwSetSurface(CREAL(0.4), CREAL(0.6), CREAL(0.0));
RwSetSurfaceColor(CREAL(0.5), CREAL(0.5), CREAL(0.5));
RwQuad(4,3,2,1);
RwSetSurfaceColor(CREAL(0.0), CREAL(0.5), CREAL(0.5));
RwQuad(5,6,7,8);
RwSetSurfaceColor(CREAL(0.4), CREAL(0.0), CREAL(0.0));
RwQuad(4,8,7,3);
RwQuad(1,2,6,5);
RwSetSurfaceColor(CREAL(0.2), CREAL(0.0), CREAL(0.0));
RwQuad(2,3,7,6);
RwQuad(4,1,5,8);
RwClumpEnd(&temp);
RwAddHintToClump(temp, 0);
RwSetClumpData(temp,(void *)(&Scene)); /* Mark as hit scene */
RwAddClumpToScene(Scene, temp);
ThreeDInitialized = TRUE;
return( TRUE );
}
/****************************************************************************
Tidy3D
* This function shuts down the 3D (i.e. RenderWare) components of the
* application in a polite fashion.
On entry :
On exit :
*/
static void
TidyUp3D()
{
/*
* Destroy the scene. This will destroy the contents of the scene,
* i.e. any clumps and lights in that scene. In this case destroying
* the scene will destroy the light we created in Init3D, and any
* clumps we have loaded and not already destroyed.
*/
RwDestroyScene(Scene);
/*
* Destroy the camera.
*/
RwDestroyCamera(Camera);
/*
* Close the library. This will free up any internal resources and
* textures loaded.
*/
RwClose();
}
/****************************************************************************
HandleLeftButtonDown
On entry : Mouse X
Mouse Y
Virtual Keys
On exit :
*/
static void
HandleLeftButtonDown(int x, int y, int vKeys)
{
RwClump *cpHit;
LaunchObject *lopObject;
/* Stop warnings */
vKeys=vKeys;
x=x;
y=y;
/* Stop warnings */
nGFireCount=FIRE_FRAMES;
if ((nGPickStatus) &&(pGPick.type == rwPICKCLUMP)) {
cpHit = pGPick.object.clump.clump;
lopObject =(LaunchObject *)RwGetClumpData(cpHit);
if ((lopObject)&&(lopObject == ((LaunchObject *)(&Scene))) ) {
if (!bButtonDown)
{
DosPrintString(0,nGScrHeight-8,sGClear,nGTextCol);
DosPrintString(0,nGScrHeight-8, "Pan and Tilt Camera",nGTextCol);
}
else /* both must be down */
{
DosPrintString(0,nGScrHeight-8,sGClear,nGTextCol);
DosPrintString(0,nGScrHeight-8, "Zoom Camera",nGTextCol);
}
bButtonDown |=1;
return;
};
};
nGShots++;
DisplayShots();
}
/****************************************************************************
HandleRightButtonDown
On entry : Mouse X
Mouse Y
Virtual Keys
On exit :
*/
static void
HandleRightButtonDown(int x, int y, int vKeys)
{
/* Stop warnings */
vKeys=vKeys;
x=x;
y=y;
/* Stop warnings */
if (!bButtonDown)
{
DosPrintString(0,nGScrHeight-8,sGClear,nGTextCol);
DosPrintString(0,nGScrHeight-8, "Pan and Zoom Camera",nGTextCol);
}
else
{
DosPrintString(0,nGScrHeight-8,sGClear,nGTextCol);
DosPrintString(0,nGScrHeight-8, "Zoom Camera",nGTextCol);
}
bButtonDown |= 2;
}
/**********************************************************************/
/*
* Handle the left mouse button comming back up. The basic action is
* to turn of mouse move actions and release mouse capture.
*/
static void
HandleLeftButtonUp()
{
bButtonDown &= ~1;
if (!bButtonDown)
{
DosPrintString(0,nGScrHeight-8,sGClear,nGTextCol);
} else {
DosPrintString(0,nGScrHeight-8,sGClear,nGTextCol);
DosPrintString(0,nGScrHeight-8, "Pan and Zoom Camera",nGTextCol);
};
}
/**********************************************************************/
/*
* 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()
{
bButtonDown &= ~2;
if (!bButtonDown)
{
DosPrintString(0,nGScrHeight-8,sGClear,nGTextCol);
}
else
{
DosPrintString(0,nGScrHeight-8,sGClear,nGTextCol);
DosPrintString(0,nGScrHeight-8, "Pan and Tilt Camera",nGTextCol);
};
}
/****************************************************************************
HandleTimer
On entry :
On exit :
*/
void HandleTimer(void)
{
/*
* See the description of HandlePaint() for a description of this common
* RenderWare cliche for rendering a scene and copying it to the display.
*/
RwBeginCameraUpdate(Camera,NULL);
RwClearCameraViewport(Camera);
RwRenderScene(Scene);
RwEndCameraUpdate(Camera);
RwShowCameraImage(Camera, NULL);
}
/****************************************************************************
HandleMouseMove
* 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.
On entry : Mouse x
: Mouse y
On exit :
*/
static void
HandleMouseMove(int x, int y)
{
if ( bButtonDown)
{
int dx,dy;
dx = x - LastX;
dy = y - LastY;
switch ( bButtonDown )
{
case 1:
{
RwV3d at,up;
RwPushScratchMatrix();
RwGetCameraLookUp(Camera, &up);
RwRotateMatrix(RwScratchMatrix(), up.x, up.y, up.z, INT2REAL(-dx),
rwREPLACE);
RwGetCameraLookRight(Camera, &at);
RwRotateMatrix(RwScratchMatrix(), at.x, at.y, at.z, INT2REAL(-dy),
rwPOSTCONCAT);
RwTransformCamera(Camera, RwScratchMatrix(),rwPOSTCONCAT);
RwPopScratchMatrix();
}
break;
case 2:
RwVCMoveCamera(Camera, CREAL(0.0),CREAL(0.0), RDiv(INT2REAL(-dy),
CREAL(50.0)));
RwRotateMatrix(RwScratchMatrix(), CREAL(0.0),CREAL(1.0),CREAL(0.0),
INT2REAL(-dx), rwREPLACE);
RwTransformCamera(Camera, RwScratchMatrix(),rwPOSTCONCAT);
break;
case 3:
RwVCMoveCamera(Camera, CREAL(0.0),CREAL(0.0), RDiv(INT2REAL(-dy),
CREAL(50.0)));
break;
}
}
}
/****************************************************************************
DisplayHits
On entry :
On exit :
*/
void DisplayHits()
{
char buffer[10];
sprintf(buffer,"%i ",nGHits);
DosPrintString(18*8,nGScrHeight-16,buffer,nGTextCol);
}
/****************************************************************************
Main Function
*/
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;
RwImageConvert ciConvert;
int nBlack,nWhite;
RwClump *cpHit;
LaunchObject *lopObject;
RwPointerImage piImage;
/* Stop warnings */
nArgc = nArgc;
/* Stop warnings */
nGFireCount=0;
nGHits = 0;
nGTargets = 0;
nGShots = 0;
if (!Init3D(saArgv[0]))
{
exit(-1);
};
nBlack = RwDeviceControl(rwSCRGETCOLOR,0,naBlack,sizeof(naBlack));
nWhite = RwDeviceControl(rwSCRGETCOLOR,0,naWhite,sizeof(naWhite));
/* Create the mouse pointers */
ciConvert.inimage = sGMouseArrow;
ciConvert.w = MOUSE_ARROW_W;
ciConvert.h = MOUSE_ARROW_H;
ciConvert.colora = nBlack;
ciConvert.colorb = nWhite;
ciConvert.outstorage = NULL;
RwDeviceControl(rwCHARMAPTORAW,0,&ciConvert,sizeof(ciConvert));
pGMouseArrow = ciConvert.outstorage;
ciConvert.inimage = sGMouseFire;
ciConvert.w = MOUSE_FIRE_W;
ciConvert.h = MOUSE_FIRE_H;
ciConvert.outstorage = NULL;
RwDeviceControl(rwCHARMAPTORAW,0,&ciConvert,sizeof(ciConvert));
pGMouseFire = ciConvert.outstorage;
ciConvert.inimage = sGMouseSight;
ciConvert.w = MOUSE_SIGHT_W;
ciConvert.h = MOUSE_SIGHT_H;
ciConvert.outstorage = NULL;
RwDeviceControl(rwCHARMAPTORAW,0,&ciConvert,sizeof(ciConvert));
pGMouseSight = ciConvert.outstorage;
/* Setup the launch structure */
SetupLaunch(&lGLaunch);
CreateBits(loaGLBits,MAX_BITS);
/* Create a Black outlined White pointer */
RwDeviceControl(rwPOINTERDISPLAY,0,&mMouse,sizeof(mMouse));
LastX = mMouse.x;
LastY = mMouse.y;
nOldMouseBut = mMouse.buttons;
nKey = DosGetKey();
DisplayHits();
DisplayTargets();
DisplayShots();
while (nKey!=27) { /* ESC quits */
if (nGFireCount) {
nGFireCount--;
};
RwDeviceControl(rwPOINTERDISPLAY,0,&mMouse,sizeof(mMouse));
nKey = DosGetKey();
nCtrlShift = DosShiftCtrl();
nGPickStatus = 0;
if (mMouse.y<nGScrHeight-24) {
if (RwPickScene(Scene, mMouse.x, mMouse.y, Camera, &pGPick)) {
if (pGPick.type==rwPICKCLUMP) {
cpHit = pGPick.object.clump.clump;
lopObject =(LaunchObject *)RwGetClumpData(cpHit);
if (lopObject) {
nGPickStatus = 1;
if (lopObject == ((LaunchObject *)(&Scene))) {
/* Its the platform */
piImage.hotx = MOUSE_ARROW_X;
piImage.hoty = MOUSE_ARROW_Y;
piImage.w = MOUSE_ARROW_W;
piImage.h = MOUSE_ARROW_H;
piImage.image= pGMouseArrow;
RwDeviceControl(rwPOINTERSETIMAGE,0,&piImage,sizeof(piImage));
} else {
/* Explode the object */
piImage.hotx = MOUSE_FIRE_X;
piImage.hoty = MOUSE_FIRE_Y;
piImage.w = MOUSE_FIRE_W;
piImage.h = MOUSE_FIRE_H;
piImage.image= pGMouseFire;
RwDeviceControl(rwPOINTERSETIMAGE,0,&piImage,sizeof(piImage));
if (nGFireCount) {
/* Explode the object */
CreateExplosion(&lopObject->vPos,&lopObject->vVel,20);
DestroyObject(lopObject);
nGHits++;
DisplayHits();
};
};
};
};
};
};
if (!nGPickStatus) {
piImage.hotx = MOUSE_SIGHT_X;
piImage.hoty = MOUSE_SIGHT_Y;
piImage.w = MOUSE_SIGHT_W;
piImage.h = MOUSE_SIGHT_H;
piImage.image= pGMouseSight;
RwDeviceControl(rwPOINTERSETIMAGE,0,&piImage,sizeof(piImage));
};
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);
};
HandleLaunch(&lGLaunch);
MoveObjects(loaGLObjects, MAX_OBJECTS, &lGLaunch);
MoveObjects(loaGLBits, MAX_BITS, &lGLaunch);
HandleTimer();
LastX = mMouse.x;
LastY = mMouse.y;
nOldMouseBut = mMouse.buttons;
frames++;
};
/*
* Tidy up the 3D (RenderWare) components of the application.
*/
TidyUp3D();
exit(0);
}