home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Learn 3D Graphics Programming on the PC
/
Learn_3D_Graphics_Programming_on_the_PC_Ferraro.iso
/
rwdos
/
dossim.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-02-15
|
34KB
|
1,313 lines
/**********************************************************************
*
* File : dossim.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 <stdlib.h>
#include <i86.h>
#include <string.h>
#include <stdio.h>
#include <math.h> /* Required for floating point */
#include "rwlib.h"
#include "rwtypes.h"
#include "rwdos.h"
#include "doswrap.h"
/****************************************************************************
Defines
*/
/* Key code for delete key */
#define DELETE 8
#define BOOL int
/*
* MS Windows compatible defines
*/
#define MK_CONTROL 0x4
#define MK_SHIFT 0x2
/*
* Motion parameters
*/
#define DAMPING CREAL(0.95)
#define MAXTHINGS 25
/****************************************************************************
Types
*/
typedef struct
{
RwClump *geometry;
int canmove;
RwReal size;
RwV3d pos,vel;
RwMatrix4d *tumble,*rot,*antirot;
RwReal rotangle, antiangle;
RwV3d axis;
int damprot;
} Thing;
/****************************************************************************
Globals
*/
static Thing things[MAXTHINGS];
static int follow,numthings;
static RwScene *Scene;
static RwCamera *Camera;
static RwLight *Light;
static ThreeDInitialized = FALSE;
static unsigned long frames = 0;
static int bButtonDown = 0;
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;
/****************************************************************************
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);
}
/*********************************************************************/
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));
}
/*********************************************************************/
static void assignvec(RwV3d *vec,RwReal x,RwReal y,RwReal z)
{
vec->x = x;
vec->y = y;
vec->z = z;
}
/*********************************************************************/
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++;
}
/*********************************************************************/
static void makethings(RwScene *scene,Thing *things, int num)
{
RwClump *clump,*prototypes[4];
RwV3d p;
int i,which;
srand(0);
for (i=0; i<4; i++)
{
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))));
switch(i)
{
case 0:
RwTranslateCTM(CREAL(0.0), CREAL(-0.15/2), CREAL(0.0));
RwCone(CREAL(0.15), CREAL(0.1), 12);
RwRotateCTM(CREAL(1.0), CREAL(0.0), CREAL(0.0), CREAL(180.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))));
RwDisc(CREAL(0.0), CREAL(0.1), 12);
break;
case 1:
RwSphere(CREAL(0.1),3);
break;
case 2:
RwTranslateCTM(CREAL(0.0), CREAL(-0.15/2), CREAL(0.0));
RwCylinder(CREAL(0.15), CREAL(0.1), CREAL(0.1), 12);
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))));
RwDisc(CREAL(0.15), CREAL(0.1), 12);
RwRotateCTM(CREAL(1.0), CREAL(0.0), CREAL(0.0), CREAL(180.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))));
RwDisc(CREAL(0.0), CREAL(0.1), 12);
break;
default:
RwBlock(CREAL(0.1), CREAL(0.2), CREAL(0.15));
break;
}
RwClumpEnd(&prototypes[i]);
}
for (i=0; i<num ; i++)
{
which = rand() % 4;
clump = RwDuplicateClump(prototypes[which]);
if ((rand() & 7) < 2)
RwForAllPolygonsInClump(clump, makezippy);
RwAddClumpToScene(scene, clump);
things[i].geometry = clump;
things[i].size = CREAL(0.1);
RwIdentityMatrix(things[i].tumble = RwCreateMatrix());
RwIdentityMatrix(things[i].rot = RwCreateMatrix());
things[i].damprot = 0;
randomvec(&p);
things[i].pos.x = RMul(p.x, RSub(CREAL(1.0), things[i].size));
things[i].pos.y = RMul(p.y, RSub(CREAL(1.0), things[i].size));
things[i].pos.z = RMul(p.z, RSub(CREAL(1.0), things[i].size));
things[i].canmove = 7;
assignvec(&things[i].vel, CREAL(0.0),CREAL(0.0),CREAL(0.0));
}
for (i=0; i<4; i++)
RwDestroyClump(prototypes[i]);
}
/*********************************************************************/
static twobody(Thing *things, int i, int j)
{
RwReal length,adjust,doti,dotj,speedi,speedj;
RwV3d hit,axis,xferi,xferj;
RwV3d veli,velj;
hit.x = RSub(things[j].pos.x, things[i].pos.x);
hit.y = RSub(things[j].pos.y, things[i].pos.y);
hit.z = RSub(things[j].pos.z, things[i].pos.z);
length = RAdd(RAdd(RMul(hit.x, hit.x), RMul(hit.y, hit.y)),
RMul(hit.z, hit.z));
if ((length > CREAL(0.0)) && (length < CREAL(0.2*0.2)))
{
length = RSqrt(length);
hit.x = RDiv(hit.x, length);
hit.y = RDiv(hit.y, length);
hit.z = RDiv(hit.z, length);
adjust = RDiv(RSub(CREAL(0.2), length), CREAL(2.0));
veli = things[i].vel;
speedi = RAdd(RAdd(RMul(veli.x, veli.x), RMul(veli.y, veli.y)),
RMul(veli.z, veli.z));
if (speedi > CREAL(0.0)) {
speedi = RSqrt(speedi);
veli.x = RDiv(veli.x, speedi);
veli.y = RDiv(veli.y, speedi);
veli.z = RDiv(veli.z, speedi);
doti = RwDotProduct(&hit, &veli);
if (doti > CREAL(0.0)) {
speedi = RMul(speedi, RMul(doti, DAMPING));
xferi.x = RMul(hit.x, speedi);
xferi.y = RMul(hit.y, speedi);
xferi.z = RMul(hit.z, speedi);
RwCrossProduct(&veli, &hit, &axis);
things[i].rotangle = RMul(speedi,
RMul(RSub(CREAL(1.0),doti),CREAL(720.0)));
things[i].axis.x = axis.x;
things[i].axis.y = axis.y;
things[i].axis.z = axis.z;
things[i].antiangle = RMul(speedi, RMul(RSub(CREAL(1.0),doti),CREAL(-4.0)));
things[i].damprot = (int)(720.0 / 4.0);
} else {
xferi.x = xferi.y = xferi.z = CREAL(0.0);
};
} else {
xferi.x = xferi.y = xferi.z = CREAL(0.0);
};
if (things[i].canmove & 1) {
things[i].pos.x = RSub(things[i].pos.x,RMul(hit.x, adjust));
};
if (!things[j].canmove & 1) {
things[i].pos.x = RSub(things[i].pos.x,RMul(hit.x, adjust));
};
if (things[i].canmove & 2) {
things[i].pos.y = RSub(things[i].pos.y,RMul(hit.y, adjust));
};
if (!things[j].canmove & 2) {
things[i].pos.y = RSub(things[i].pos.y,RMul(hit.y, adjust));
};
if (things[i].canmove & 4) {
things[i].pos.z = RSub(things[i].pos.z,RMul(hit.z, adjust));
};
if (!things[j].canmove & 4) {
things[i].pos.z = RSub(things[i].pos.z,RMul(hit.z, adjust));
};
/*
hit.x = -hit.x;
hit.y = -hit.y;
hit.z = -hit.z;
*/
hit.x = CREAL(0.0);
hit.y = CREAL(0.0);
hit.z = CREAL(0.0);
velj = things[j].vel;
speedj = RAdd(RAdd(RMul(velj.x, velj.x), RMul(velj.y, velj.y)),
RMul(velj.z, velj.z));
if (speedj > CREAL(0.0)) {
speedj = RSqrt(speedj);
velj.x = RDiv(velj.x, speedj);
velj.y = RDiv(velj.y, speedj);
velj.z = RDiv(velj.z, speedj);
dotj = RwDotProduct(&hit, &velj);
if (dotj > CREAL(0.0)) {
speedj = RMul(speedj, RMul(dotj, DAMPING));
xferj.x = RMul(hit.x, speedj);
xferj.y = RMul(hit.y, speedj);
xferj.z = RMul(hit.z, speedj);
RwCrossProduct(&velj, &hit, &axis);
things[j].rotangle = RMul(speedj, RMul(RSub(CREAL(1.0),dotj),CREAL(720.0)));
things[j].axis.x = axis.x;
things[j].axis.y = axis.y;
things[j].axis.z = axis.z;
things[j].antiangle = RMul(speedj, RMul(RSub(CREAL(1.0),dotj),CREAL(-4.0)));
things[j].damprot=(int)(720.0 / 4.0);
} else {
xferj.x = xferj.y = xferj.z = CREAL(0.0);
};
} else {
xferj.x = xferj.y = xferj.z = CREAL(0.0);
};
if (things[j].canmove & 1) {
things[j].pos.x = RSub(things[j].pos.x,RMul(hit.x, adjust));
};
if (!things[i].canmove & 1) {
things[j].pos.x = RSub(things[j].pos.x,RMul(hit.x, adjust));
};
if (things[j].canmove & 2) {
things[j].pos.y = RSub(things[j].pos.y,RMul(hit.y, adjust));
};
if (!things[i].canmove & 2) {
things[j].pos.y = RSub(things[j].pos.y,RMul(hit.y, adjust));
};
if (things[j].canmove & 4) {
things[j].pos.z = RSub(things[j].pos.z,RMul(hit.z, adjust));
};
if (!things[i].canmove & 4) {
things[j].pos.z = RSub(things[j].pos.z,RMul(hit.z, adjust));
};
things[i].vel.x = RAdd(things[i].vel.x,RSub(xferj.x, xferi.x));
things[i].vel.y = RAdd(things[i].vel.y,RSub(xferj.y, xferi.y));
things[i].vel.z = RAdd(things[i].vel.z,RSub(xferj.z, xferi.z));
things[j].vel.x = RAdd(things[i].vel.x,RSub(xferi.x, xferj.x));
things[j].vel.y = RAdd(things[i].vel.y,RSub(xferi.y, xferj.y));
things[j].vel.z = RAdd(things[i].vel.z,RSub(xferi.z, xferj.z));
return(1);
}
return(0);
}
/*********************************************************************/
collisions(Thing *things, int num)
{
int i,j;
for (i=0; i<num; i++)
{
for (j=i+1; j<num; j++)
{
if (twobody(things,i,j)) break;
}
}
}
/*********************************************************************/
static void gravitatethings(Thing *things, int num, RwV3d *acc)
{
int i;
RwV3d p;
RwReal val;
RwReal limit;
RwPushScratchMatrix();
limit = CREAL(1.0 - 0.1);
for (i=0; i<num; i++)
{
if (things[i].damprot > 0)
{
/* Below is the original version of the damping code. This accumulates
a new .rot matrix by repeated multiplication with .antirot. This
causes the .rot matrix to drift causing shearing of the object.
RwMultiplyMatrix(things[i].rot, things[i].antirot, RwScratchMatrix());
RwCopyMatrix(RwScratchMatrix(), things[i].rot);
*/
RwRotateMatrix(things[i].rot, things[i].axis.x, things[i].axis.y,
things[i].axis.z,
RSub(things[i].rotangle, things[i].antiangle), rwREPLACE);
things[i].damprot--;
}
RwMultiplyMatrix(things[i].tumble, things[i].rot, RwScratchMatrix());
if ((frames)%(num<<3) ==(i<<3))
RwOrthoNormalizeMatrix(RwScratchMatrix(), RwScratchMatrix());
RwCopyMatrix(RwScratchMatrix(), things[i].tumble);
p = things[i].pos;
RwTranslateMatrix(RwScratchMatrix(), p.x,p.y,p.z, rwPOSTCONCAT);
RwTransformClump(things[i].geometry, RwScratchMatrix(), rwREPLACE);
things[i].canmove = 0;
/* += */
things[i].vel.x = RAdd(things[i].vel.x,acc->x);
/* things[i].vel.x += acc->x; */
val = things[i].pos.x = RAdd(things[i].pos.x,things[i].vel.x);
/* val = things[i].pos.x += things[i].vel.x; */
if (val < - limit || val > limit)
{
things[i].vel.x = RSub(things[i].vel.x,acc->x);
/* things[i].vel.x -= acc->x; */
things[i].vel.x = RMul(-things[i].vel.x, DAMPING);
things[i].pos.x = val < CREAL(0.0) ? -limit : limit;
}
else
things[i].canmove |= 1;
/* things[i].vel.y += acc->y; */
things[i].vel.y = RAdd(things[i].vel.y,acc->y);
/* val = things[i].pos.y += things[i].vel.y; */
val = things[i].pos.y = RAdd(things[i].pos.y,things[i].vel.y);
if (val < -limit || val > limit)
{
/* things[i].vel.y -= acc->y; */
things[i].vel.y = RSub(things[i].vel.y,acc->y);
things[i].vel.y = RMul(-things[i].vel.y, DAMPING);
things[i].pos.y = val < CREAL(0.0) ? -limit : limit;
}
else
things[i].canmove |= 2;
/* things[i].vel.z += acc->z; */
things[i].vel.z = RAdd(things[i].vel.z,acc->z);
/* val = things[i].pos.z += things[i].vel.z; */
val = things[i].pos.z = RAdd(things[i].pos.z,things[i].vel.z);
if (val < -limit || val > limit)
{
things[i].vel.z -= acc->z;
things[i].vel.z = RMul(-things[i].vel.z, DAMPING);
things[i].pos.z = val < CREAL(0.0) ? -limit : limit;
}
else
things[i].canmove |= 4;
}
RwPopScratchMatrix();
frames++;
}
/***************************************************************************/
/*
* 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)
{
int i,j;
int fixed, debugging;
char *title;
RwClump *temp;
RwReal naTextCol[]={CREAL(1.0),CREAL(1.0),CREAL(1.0)};
char version[30];
char buffer[128];
int param;
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 <%i> !!!!!!!!!!!!!!!\n",nError);
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.
*/
RwGetSystemInfo(rwVERSIONSTRING, &version,sizeof(version));
RwGetSystemInfo(rwFIXEDPOINTLIB, ¶m,sizeof(param));
sprintf(buffer, "RenderSim(tm) V%s %s",
version, (param ? "Fixed" : "Float"));
DosPrintString(0,nGScrHeight-16,buffer,nGTextCol);
RwGetSystemInfo(rwFIXEDPOINTLIB, &fixed,sizeof(fixed));
RwGetSystemInfo(rwDEBUGGINGLIB, &debugging,sizeof(debugging));
if ((fixed) && (debugging))
title = "n-Body (Fixed & Debugging)";
else if (fixed)
title = "n-Body (Fixed Point)";
else if (debugging)
title = "n-Body (Debugging)";
else
title = "n-Body (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.0), CREAL(-7.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 room in the simulation
*/
RwClumpBegin();
RwVertex(CREAL(-1.0),CREAL(-1.005),CREAL(1.0));
RwVertex( CREAL(1.0),CREAL(-1.005),CREAL(1.0));
RwVertex( CREAL(1.0), CREAL(1.0),CREAL(1.0));
RwVertex(CREAL(-1.0), CREAL(1.0),CREAL(1.0));
RwVertex(CREAL(-1.0),CREAL(-1.005),CREAL(-1.0));
RwVertex( CREAL(1.0),CREAL(-1.005),CREAL(-1.0));
RwVertex( CREAL(1.0), CREAL(1.0),CREAL(-1.0));
RwVertex(CREAL(-1.0), CREAL(1.0),CREAL(-1.0));
RwSetSurface(CREAL(0.4), CREAL(0.6), CREAL(0.0));
RwSetSurfaceColor(CREAL(0.5), CREAL(0.5), CREAL(0.5));
RwQuad(2,1,4,3);
RwSetSurfaceColor(CREAL(0.0), CREAL(0.0), CREAL(0.7));
RwQuad(6,2,3,7);
RwSetSurfaceColor(CREAL(0.0), CREAL(0.7), CREAL(0.0));
RwQuad(5,6,7,8);
RwSetSurfaceColor(CREAL(0.7), CREAL(0.0), CREAL(0.0));
RwQuad(1,5,8,4);
RwSetSurfaceColor(CREAL(0.0), CREAL(0.7), CREAL(0.0));
RwQuad(8,7,3,4);
RwTransformBegin();
RwTranslateCTM(CREAL(0.0), CREAL(-1.0), CREAL(0.0));
RwScaleCTM(CREAL(0.25),CREAL(0.0),CREAL(0.25));
for (i=-4; i<=4; i++)
for (j=-4; j<=4; j++)
RwVertex(INT2REAL(i), CREAL(0.0), INT2REAL(j));
for (i=0; i<8; i++)
for (j=0; j<8; j++)
{
if ((i ^ j) & 1)
{
RwSetSurface(CREAL(0.5),CREAL(0.2),CREAL(0.0));
RwSetSurfaceColor(CREAL(1.0), CREAL(0.0), CREAL(0.0));
}
else
{
RwSetSurface(CREAL(0.5),CREAL(0.5),CREAL(0.0));
RwSetSurfaceColor(CREAL(0.5), CREAL(0.5), CREAL(0.0));
}
RwQuad(9+(i*9)+j, 9+(i*9)+j+1, 9+((i+1)*9)+j+1, 9+((i+1)*9)+j);
}
RwTransformEnd();
RwClumpEnd(&temp);
RwAddHintToClump(temp, rwCONTAINER);
RwAddClumpToScene(Scene, temp);
numthings = 10; /* number of objects */
makethings(Scene, things, numthings);
follow = 0;
ThreeDInitialized = TRUE;
return( TRUE );
}
/**********************************************************************/
/*
* This function shuts down the 3D (i.e. RenderWare) components of the
* application in a polite fashion.
*/
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)
{
/* Stop warnings */
x=x;
y=y;
vKeys=vKeys;
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;
}
/****************************************************************************
HandleRightButtonDown
On entry : Mouse X
Mouse Y
Virtual Keys
On exit :
*/
static void
HandleRightButtonDown(int x, int y, int vKeys)
{
/* Stop warnings */
x=x;
y=y;
vKeys=vKeys;
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)
{
RwV3d vec;
collisions(things, numthings);
RwGetCameraLookUp(Camera, &vec);
vec.x = RDiv(vec.x, CREAL(-200));
vec.y = RDiv(vec.y, CREAL(-200));
vec.z = RDiv(vec.z, CREAL(-200));
gravitatethings(things, numthings, &vec);
if (! bButtonDown )
{
RwGetClumpOrigin(things[follow].geometry, &vec);
RwPointCamera(Camera, vec.x,vec.y,vec.z);
RwSetCameraLookUp(Camera, CREAL(0.0),CREAL(1.0),CREAL(0.0));
}
/*
* 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;
}
}
}
/****************************************************************************
HandleKey
On entry :
On exit :
*/
void HandleKey(nKey)
{
if (nKey >= '0' && nKey <= '9' && nKey < numthings + '0')
{
follow = nKey - '0';
} else if ((nKey == 't') || (nKey == 'T'))
{
int t,u;
int i;
char szBuf[255];
u = DosTimer();
while (u == (t = DosTimer()));
for (i=0; i<150; i++)
{
RwV3d vec;
collisions(things, numthings);
RwGetCameraLookUp(Camera, &vec);
vec.x = RDiv(vec.x, CREAL(-200));
vec.y = RDiv(vec.y, CREAL(-200));
vec.z = RDiv(vec.z, CREAL(-200));
gravitatethings(things, numthings, &vec);
if (1)
{
RwGetClumpOrigin(things[follow].geometry, &vec);
RwPointCamera(Camera, vec.x,vec.y,vec.z);
RwSetCameraLookUp(Camera, CREAL(0.0),CREAL(1.0),CREAL(0.0));
}
RwBeginCameraUpdate(Camera,NULL);
RwClearCameraViewport( Camera );
RwRenderScene( Scene );
RwEndCameraUpdate(Camera);
RwShowCameraImage( Camera, NULL);
}
u = DosTimer();
sprintf(szBuf, "DosSim took %lu ms for %d frames\n", u-t, i);
DosPrintString(0,nGScrHeight-8,sGClear,nGTextCol);
DosPrintString(0,nGScrHeight-8,szBuf,nGTextCol);
}
}
/****************************************************************************
Main Function
*/
void main(int nArgc,char *saArgv[])
{
int nKey;
int nOldMouseBut;
int nDX,nDY;
int nChange;
int nCtrlShift;
RwMousePointer mMouse;
/* Stop warnings */
nArgc = nArgc;
if (!Init3D(saArgv[0]))
{
exit(-1);
};
/* Create a Black outlined White pointer */
RwDeviceControl(rwPOINTERDISPLAY,0,&mMouse,sizeof(mMouse));
LastX = mMouse.x;
LastY = mMouse.y;
nOldMouseBut = mMouse.buttons;
nKey = DosGetKey();
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);
};
if (nKey) {
HandleKey(nKey);
};
HandleTimer();
LastX = mMouse.x;
LastY = mMouse.y;
nOldMouseBut = mMouse.buttons;
};
/*
* Tidy up the 3D (RenderWare) components of the application.
*/
TidyUp3D();
exit(0);
}