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 >
C/C++ Source or Header  |  1995-02-15  |  34KB  |  1,313 lines

  1. /**********************************************************************
  2.  *
  3.  * File :     dossim.c
  4.  *
  5.  * Abstract : A very simple, sample RenderWare application for
  6.  *            MS-Dos/PC Dos. This application has very little
  7.  *            functionality, but is simply intended as a demonstration
  8.  *            of how to use the RenderWare API.
  9.  *
  10.  *            This application had been written to be compatible with
  11.  *            both the fixed and floating-point versions of the
  12.  *            RenderWare library, i.e., it uses the macros CREAL,
  13.  *            INT2REAL, RAdd, RDiv, RSub etc. If your application is
  14.  *            intended for the floating-point version of the library
  15.  *            only these macros are not necessary.
  16.  *
  17.  *            Please note that this application is intended for
  18.  *            demonstration purposes only. No support will be
  19.  *            provided for this code and it comes with no warranty.
  20.  *
  21.  * This file is a product of Criterion Software Ltd.
  22.  *
  23.  * This file is provided as is with no warranties of any kind and is
  24.  * provided without any obligation on Criterion Software Ltd. or
  25.  * Canon Inc. to assist in its use or modification.
  26.  *
  27.  * Criterion Software Ltd. and Canon Inc. will not, under any
  28.  * circumstances, be liable for any lost revenue or other damages arising
  29.  * from the use of this file.
  30.  *
  31.  * Copyright (c) 1991, 1992, 1993. Canon Inc.
  32.  * All Rights Reserved.
  33.  *
  34.  **********************************************************************/
  35.  
  36. /**********************************************************************
  37.  *
  38.  * Header files.
  39.  *
  40.  **********************************************************************/
  41.  
  42. #include <stdlib.h>
  43. #include <i86.h>
  44. #include <string.h>
  45. #include <stdio.h>
  46. #include <math.h>    /* Required for floating point */
  47.  
  48. #include "rwlib.h"
  49. #include "rwtypes.h"
  50.  
  51. #include "rwdos.h"
  52. #include "doswrap.h"
  53.  
  54. /****************************************************************************
  55.  Defines
  56.  */
  57.  
  58. /* Key code for delete key */
  59.  
  60. #define DELETE 8
  61. #define BOOL int
  62.  
  63. /*
  64.  * MS Windows compatible defines
  65.  */
  66.  
  67. #define MK_CONTROL 0x4
  68. #define MK_SHIFT 0x2
  69.  
  70. /*
  71.  * Motion parameters
  72.  */
  73.  
  74. #define DAMPING    CREAL(0.95)
  75. #define MAXTHINGS  25
  76.  
  77. /****************************************************************************
  78.  Types
  79.  */
  80.  
  81. typedef struct
  82. {
  83.   RwClump  *geometry;
  84.   int canmove;
  85.   RwReal  size;
  86.   RwV3d  pos,vel;
  87.   RwMatrix4d *tumble,*rot,*antirot;
  88.   RwReal rotangle, antiangle;
  89.   RwV3d  axis;
  90.   int damprot;
  91. } Thing;
  92.  
  93. /****************************************************************************
  94.  Globals
  95.  */
  96.  
  97. static Thing things[MAXTHINGS];
  98. static int follow,numthings;
  99.  
  100. static RwScene    *Scene;
  101. static RwCamera  *Camera;
  102. static RwLight    *Light;
  103.  
  104. static ThreeDInitialized = FALSE;
  105.  
  106. static unsigned long frames = 0;
  107.  
  108. static int bButtonDown = 0;
  109.  
  110. static char sGClear[]="                                  ";
  111.  
  112. /*
  113.  * Global variables used to remember the last mouse X and Y coordinates
  114.  * when involved in a pan, zoom, drag or spin.
  115.  */
  116. static int         LastX;
  117. static int         LastY;
  118.  
  119.  
  120. /*
  121.  Screen size
  122.  */
  123.  
  124. static int nGScrWidth;
  125. static int nGScrHeight;
  126.  
  127. /*
  128.  Colour Codes
  129.  */
  130.  
  131. static int nGTextCol;
  132.  
  133. /****************************************************************************
  134.  DosPrintString
  135.  
  136.  On entry     : xcord
  137.                         : ycord
  138.                         : string
  139.                         : colour
  140.  On exit        :
  141.  */
  142.  
  143. void DosPrintString(int nX,int nY,char *sString,int nCol)
  144. {
  145.     RwPrintChar pcPrint;
  146.  
  147.     pcPrint.x = nX;
  148.     pcPrint.y = nY;
  149.     pcPrint.color = nCol;
  150.  
  151.     for (;(*sString);sString++)  {
  152.         pcPrint.c = (*sString);
  153.     RwDeviceControl(rwPRINTCHAR,0,&pcPrint,sizeof(pcPrint));
  154.         pcPrint.x+=8;
  155.     };
  156. }
  157.  
  158.  
  159. /****************************************************************************
  160.  DosTimer
  161.  
  162.  On entry    :
  163.  On exit    : Timer (in milliseconds)
  164.  */
  165.  
  166. int DosTimer(void)
  167. {
  168.     union REGS r;
  169.     int nTime;
  170.  
  171.     r.h.ah=0;
  172.  
  173.     int386(0x1a,&r,&r);
  174.  
  175.     nTime = ((r.w.cx)<<16)|(r.w.dx);
  176.  
  177.     return (nTime*55);
  178. }
  179.  
  180. /****************************************************************************
  181.  DosGetKey
  182.  
  183.  On entry    :
  184.  On exit     : Key pressed in ascii (or 0 if no key pressed)
  185.  */
  186.  
  187. int DosGetKey(void)
  188. {
  189.     union REGPACK rp;
  190.  
  191.     memset(&rp,0,sizeof(rp));
  192.     rp.h.ah = 0x06;
  193.     rp.h.dl = 0xff;
  194.  
  195.     intr(0x21,&rp);
  196.  
  197.     if (!(rp.w.flags & 0x40 )) {       /* Check Z flag */
  198.         /* Got key */
  199.  
  200.         if (rp.h.al) {
  201.             return ((int)rp.h.al);
  202.         };
  203.  
  204.         memset(&rp,0,sizeof(rp));
  205.         rp.h.ah = 0x06;
  206.         rp.h.dl = 0xff;
  207.         intr(0x21,&rp);
  208.  
  209.         if (!(rp.w.flags & 0x40)) {
  210.             return ((int)rp.h.al);
  211.         };
  212.  
  213.         return (rp.h.al|0x80);
  214.     };
  215.  
  216.     return 0;
  217. }
  218.  
  219. /****************************************************************************
  220.  DosShiftCtrl
  221.  
  222.  On entry    :
  223.  On exit    : Bit         Meaning
  224.                         0                Right Shift
  225.                         1                Left Shift
  226.                         2                Ctrl
  227.                         3                Alt
  228.                         4       Scroll Lock
  229.                         5                Num Lock
  230.                         6             Caps Lock
  231.                         7                Insert on
  232.  */
  233.  
  234. int DosShiftCtrl(void)
  235. {
  236.     union REGPACK rp;
  237.  
  238.     memset(&rp,0,sizeof(rp));
  239.  
  240.     rp.h.ah=0x02;
  241.     intr(0x16,&rp);
  242.  
  243.     return ((int)rp.h.al);
  244. }
  245.  
  246.  
  247. /*********************************************************************/
  248. static void randomvec(RwV3d *vec)
  249. {
  250.   vec->x = RSub(RDiv(INT2REAL(rand()),CREAL(16384.0)), CREAL(1.0));
  251.   vec->y = RSub(RDiv(INT2REAL(rand()),CREAL(16384.0)), CREAL(1.0));
  252.   vec->z = RSub(RDiv(INT2REAL(rand()),CREAL(16384.0)), CREAL(1.0));
  253. }
  254.  
  255. /*********************************************************************/
  256. static void assignvec(RwV3d *vec,RwReal x,RwReal y,RwReal z)
  257. {
  258.   vec->x = x;
  259.   vec->y = y;
  260.   vec->z = z;
  261. }
  262.  
  263. /*********************************************************************/
  264. static void makezippy(RwPolygon3d *p)
  265. {
  266.   static int zippy = 0;
  267.  
  268.   switch (zippy % 7)
  269.     {
  270.     case 0: RwSetPolygonColor(p, CREAL(0.7), CREAL(0.0), CREAL(0.0)); break;
  271.     case 1: RwSetPolygonColor(p, CREAL(0.0), CREAL(0.7), CREAL(0.0)); break;
  272.     case 2: RwSetPolygonColor(p, CREAL(0.0), CREAL(0.0), CREAL(0.7)); break;
  273.     case 3: RwSetPolygonColor(p, CREAL(0.7), CREAL(0.7), CREAL(0.0)); break;
  274.     case 4: RwSetPolygonColor(p, CREAL(0.7), CREAL(0.0), CREAL(0.7)); break;
  275.     case 5: RwSetPolygonColor(p, CREAL(0.0), CREAL(0.7), CREAL(0.7)); break;
  276.     case 6: RwSetPolygonColor(p, CREAL(0.7), CREAL(0.7), CREAL(0.7)); break;
  277.     }
  278.   zippy++;
  279. }
  280.  
  281. /*********************************************************************/
  282. static void makethings(RwScene *scene,Thing *things, int num)
  283. {
  284.   RwClump *clump,*prototypes[4];
  285.   RwV3d p;
  286.   int i,which;
  287.  
  288.   srand(0);
  289.  
  290.   for (i=0; i<4; i++)
  291.   {
  292.     RwClumpBegin();
  293.     RwSetSurface(CREAL(0.4), CREAL(0.7), CREAL(0.0));
  294.     RwSetSurfaceColor(RDiv(CREAL(1.0), INT2REAL(1 + (rand() % 4))),
  295.               RDiv(CREAL(1.0), INT2REAL(1 + (rand() % 4))),
  296.               RDiv(CREAL(1.0), INT2REAL(1 + (rand() % 4))));
  297.     switch(i)
  298.     {
  299.     case 0:
  300.       RwTranslateCTM(CREAL(0.0), CREAL(-0.15/2), CREAL(0.0));
  301.       RwCone(CREAL(0.15), CREAL(0.1), 12);
  302.       RwRotateCTM(CREAL(1.0), CREAL(0.0), CREAL(0.0), CREAL(180.0));
  303.       RwSetSurfaceColor(RDiv(CREAL(1.0), INT2REAL(1 + (rand() % 4))),
  304.             RDiv(CREAL(1.0), INT2REAL(1 + (rand() % 4))),
  305.             RDiv(CREAL(1.0), INT2REAL(1 + (rand() % 4))));
  306.       RwDisc(CREAL(0.0), CREAL(0.1), 12);
  307.       break;
  308.     case 1:
  309.       RwSphere(CREAL(0.1),3);
  310.       break;
  311.     case 2:
  312.       RwTranslateCTM(CREAL(0.0), CREAL(-0.15/2), CREAL(0.0));
  313.       RwCylinder(CREAL(0.15), CREAL(0.1), CREAL(0.1), 12);
  314.       RwSetSurfaceColor(RDiv(CREAL(1.0), INT2REAL(1 + (rand() % 4))),
  315.             RDiv(CREAL(1.0), INT2REAL(1 + (rand() % 4))),
  316.             RDiv(CREAL(1.0), INT2REAL(1 + (rand() % 4))));
  317.       RwDisc(CREAL(0.15), CREAL(0.1), 12);
  318.       RwRotateCTM(CREAL(1.0), CREAL(0.0), CREAL(0.0), CREAL(180.0));
  319.       RwSetSurfaceColor(RDiv(CREAL(1.0), INT2REAL(1 + (rand() % 4))),
  320.             RDiv(CREAL(1.0), INT2REAL(1 + (rand() % 4))),
  321.             RDiv(CREAL(1.0), INT2REAL(1 + (rand() % 4))));
  322.       RwDisc(CREAL(0.0), CREAL(0.1), 12);
  323.       break;
  324.     default:
  325.       RwBlock(CREAL(0.1), CREAL(0.2), CREAL(0.15));
  326.       break;
  327.     }
  328.     RwClumpEnd(&prototypes[i]);
  329.   }
  330.  
  331.   for (i=0; i<num ; i++)
  332.   {
  333.     which = rand() % 4;
  334.     clump = RwDuplicateClump(prototypes[which]);
  335.     if ((rand() & 7) < 2)
  336.             RwForAllPolygonsInClump(clump, makezippy);
  337.     RwAddClumpToScene(scene, clump);
  338.     things[i].geometry = clump;
  339.     things[i].size = CREAL(0.1);
  340.     RwIdentityMatrix(things[i].tumble = RwCreateMatrix());
  341.     RwIdentityMatrix(things[i].rot = RwCreateMatrix());
  342.  
  343.         things[i].damprot = 0;
  344.     randomvec(&p);
  345.     things[i].pos.x = RMul(p.x, RSub(CREAL(1.0), things[i].size));
  346.     things[i].pos.y = RMul(p.y, RSub(CREAL(1.0), things[i].size));
  347.     things[i].pos.z = RMul(p.z, RSub(CREAL(1.0), things[i].size));
  348.     things[i].canmove = 7;
  349.     assignvec(&things[i].vel, CREAL(0.0),CREAL(0.0),CREAL(0.0));
  350.   }
  351.   for (i=0; i<4; i++)
  352.     RwDestroyClump(prototypes[i]);
  353. }
  354.  
  355. /*********************************************************************/
  356. static twobody(Thing *things, int i, int j)
  357. {
  358.   RwReal length,adjust,doti,dotj,speedi,speedj;
  359.   RwV3d hit,axis,xferi,xferj;
  360.   RwV3d veli,velj;
  361.  
  362.   hit.x = RSub(things[j].pos.x, things[i].pos.x);
  363.   hit.y = RSub(things[j].pos.y, things[i].pos.y);
  364.   hit.z = RSub(things[j].pos.z, things[i].pos.z);
  365.   length = RAdd(RAdd(RMul(hit.x, hit.x), RMul(hit.y, hit.y)),
  366.         RMul(hit.z, hit.z));
  367.  
  368.   if ((length > CREAL(0.0)) && (length < CREAL(0.2*0.2)))
  369.   {
  370.         length = RSqrt(length);
  371.  
  372.         hit.x = RDiv(hit.x, length);
  373.         hit.y = RDiv(hit.y, length);
  374.         hit.z = RDiv(hit.z, length);
  375.         adjust = RDiv(RSub(CREAL(0.2), length), CREAL(2.0));
  376.  
  377.         veli = things[i].vel;
  378.         speedi = RAdd(RAdd(RMul(veli.x, veli.x), RMul(veli.y, veli.y)),
  379.         RMul(veli.z, veli.z));
  380.  
  381.         if (speedi > CREAL(0.0)) {
  382.             speedi = RSqrt(speedi);
  383.             veli.x = RDiv(veli.x, speedi);
  384.             veli.y = RDiv(veli.y, speedi);
  385.             veli.z = RDiv(veli.z, speedi);
  386.  
  387.             doti = RwDotProduct(&hit, &veli);
  388.  
  389.             if (doti > CREAL(0.0)) {
  390.                 speedi = RMul(speedi, RMul(doti, DAMPING));
  391.  
  392.                 xferi.x = RMul(hit.x, speedi);
  393.                 xferi.y = RMul(hit.y, speedi);
  394.                 xferi.z = RMul(hit.z, speedi);
  395.                 RwCrossProduct(&veli, &hit, &axis);
  396.  
  397.                 things[i].rotangle = RMul(speedi,
  398.                     RMul(RSub(CREAL(1.0),doti),CREAL(720.0)));
  399.  
  400.  
  401.                 things[i].axis.x = axis.x;
  402.                 things[i].axis.y = axis.y;
  403.                 things[i].axis.z = axis.z;
  404.  
  405.  
  406.                 things[i].antiangle = RMul(speedi, RMul(RSub(CREAL(1.0),doti),CREAL(-4.0)));
  407.                 things[i].damprot = (int)(720.0 / 4.0);
  408.             } else {
  409.                 xferi.x = xferi.y = xferi.z = CREAL(0.0);
  410.             };
  411.         } else {
  412.             xferi.x = xferi.y = xferi.z = CREAL(0.0);
  413.         };
  414.  
  415.         if (things[i].canmove & 1) {
  416.             things[i].pos.x = RSub(things[i].pos.x,RMul(hit.x, adjust));
  417.         };
  418.         if (!things[j].canmove & 1) {
  419.             things[i].pos.x = RSub(things[i].pos.x,RMul(hit.x, adjust));
  420.         };
  421.  
  422.         if (things[i].canmove & 2) {
  423.             things[i].pos.y = RSub(things[i].pos.y,RMul(hit.y, adjust));
  424.         };
  425.         if (!things[j].canmove & 2) {
  426.             things[i].pos.y = RSub(things[i].pos.y,RMul(hit.y, adjust));
  427.         };
  428.  
  429.         if (things[i].canmove & 4) {
  430.             things[i].pos.z = RSub(things[i].pos.z,RMul(hit.z, adjust));
  431.         };
  432.         if (!things[j].canmove & 4) {
  433.             things[i].pos.z = RSub(things[i].pos.z,RMul(hit.z, adjust));
  434.         };
  435.  
  436.         /*
  437.         hit.x = -hit.x;
  438.         hit.y = -hit.y;
  439.         hit.z = -hit.z;
  440.         */
  441.  
  442.         hit.x = CREAL(0.0);
  443.         hit.y = CREAL(0.0);
  444.         hit.z = CREAL(0.0);
  445.  
  446.         velj = things[j].vel;
  447.         speedj = RAdd(RAdd(RMul(velj.x, velj.x), RMul(velj.y, velj.y)),
  448.         RMul(velj.z, velj.z));
  449.         if (speedj > CREAL(0.0)) {
  450.             speedj = RSqrt(speedj);
  451.             velj.x = RDiv(velj.x, speedj);
  452.             velj.y = RDiv(velj.y, speedj);
  453.             velj.z = RDiv(velj.z, speedj);
  454.             dotj = RwDotProduct(&hit, &velj);
  455.             if (dotj > CREAL(0.0)) {
  456.                 speedj = RMul(speedj, RMul(dotj, DAMPING));
  457.                 xferj.x = RMul(hit.x, speedj);
  458.                 xferj.y = RMul(hit.y, speedj);
  459.                 xferj.z = RMul(hit.z, speedj);
  460.                 RwCrossProduct(&velj, &hit, &axis);
  461.  
  462.                 things[j].rotangle = RMul(speedj, RMul(RSub(CREAL(1.0),dotj),CREAL(720.0)));
  463.  
  464.                 things[j].axis.x = axis.x;
  465.                 things[j].axis.y = axis.y;
  466.                 things[j].axis.z = axis.z;
  467.  
  468.                 things[j].antiangle = RMul(speedj, RMul(RSub(CREAL(1.0),dotj),CREAL(-4.0)));
  469.                 things[j].damprot=(int)(720.0 / 4.0);
  470.             } else {
  471.                 xferj.x = xferj.y = xferj.z = CREAL(0.0);
  472.             };
  473.         } else {
  474.             xferj.x = xferj.y = xferj.z = CREAL(0.0);
  475.         };
  476.  
  477.         if (things[j].canmove & 1) {
  478.             things[j].pos.x = RSub(things[j].pos.x,RMul(hit.x, adjust));
  479.         };
  480.  
  481.         if (!things[i].canmove & 1) {
  482.             things[j].pos.x = RSub(things[j].pos.x,RMul(hit.x, adjust));
  483.         };
  484.  
  485.         if (things[j].canmove & 2) {
  486.             things[j].pos.y = RSub(things[j].pos.y,RMul(hit.y, adjust));
  487.         };
  488.         if (!things[i].canmove & 2) {
  489.             things[j].pos.y = RSub(things[j].pos.y,RMul(hit.y, adjust));
  490.         };
  491.  
  492.         if (things[j].canmove & 4) {
  493.             things[j].pos.z = RSub(things[j].pos.z,RMul(hit.z, adjust));
  494.         };
  495.         if (!things[i].canmove & 4) {
  496.             things[j].pos.z = RSub(things[j].pos.z,RMul(hit.z, adjust));
  497.         };
  498.  
  499.         things[i].vel.x = RAdd(things[i].vel.x,RSub(xferj.x, xferi.x));
  500.         things[i].vel.y = RAdd(things[i].vel.y,RSub(xferj.y, xferi.y));
  501.         things[i].vel.z = RAdd(things[i].vel.z,RSub(xferj.z, xferi.z));
  502.  
  503.         things[j].vel.x = RAdd(things[i].vel.x,RSub(xferi.x, xferj.x));
  504.         things[j].vel.y = RAdd(things[i].vel.y,RSub(xferi.y, xferj.y));
  505.         things[j].vel.z = RAdd(things[i].vel.z,RSub(xferi.z, xferj.z));
  506.  
  507.         return(1);
  508.   }
  509.   return(0);
  510. }
  511.  
  512. /*********************************************************************/
  513. collisions(Thing *things, int num)
  514. {
  515.   int i,j;
  516.  
  517.   for (i=0; i<num; i++)
  518.   {
  519.     for (j=i+1; j<num; j++)
  520.     {
  521.       if (twobody(things,i,j)) break;
  522.     }
  523.   }
  524. }
  525.  
  526. /*********************************************************************/
  527. static void gravitatethings(Thing *things, int num, RwV3d *acc)
  528. {
  529.   int i;
  530.   RwV3d p;
  531.   RwReal val;
  532.   RwReal limit;
  533.  
  534.   RwPushScratchMatrix();
  535.   limit = CREAL(1.0 - 0.1);
  536.   for (i=0; i<num; i++)
  537.   {
  538.     if (things[i].damprot > 0)
  539.     {
  540. /* Below is the original version of the damping code. This accumulates
  541.    a new .rot matrix by repeated multiplication with .antirot. This
  542.    causes the .rot matrix to drift causing shearing of the object.
  543.       RwMultiplyMatrix(things[i].rot, things[i].antirot, RwScratchMatrix());
  544.       RwCopyMatrix(RwScratchMatrix(), things[i].rot);
  545. */
  546.       RwRotateMatrix(things[i].rot, things[i].axis.x, things[i].axis.y,
  547.              things[i].axis.z,
  548.              RSub(things[i].rotangle, things[i].antiangle), rwREPLACE);
  549.       things[i].damprot--;
  550.     }
  551.     RwMultiplyMatrix(things[i].tumble, things[i].rot, RwScratchMatrix());
  552.     if ((frames)%(num<<3) ==(i<<3))
  553.     RwOrthoNormalizeMatrix(RwScratchMatrix(), RwScratchMatrix());
  554.     RwCopyMatrix(RwScratchMatrix(), things[i].tumble);
  555.     p = things[i].pos;
  556.     RwTranslateMatrix(RwScratchMatrix(), p.x,p.y,p.z, rwPOSTCONCAT);
  557.     RwTransformClump(things[i].geometry, RwScratchMatrix(), rwREPLACE);
  558.  
  559.     things[i].canmove = 0;
  560. /* += */
  561.         things[i].vel.x = RAdd(things[i].vel.x,acc->x);
  562. /*    things[i].vel.x += acc->x; */
  563.         val = things[i].pos.x = RAdd(things[i].pos.x,things[i].vel.x);
  564. /*    val = things[i].pos.x += things[i].vel.x;  */
  565.     if (val < - limit || val > limit)
  566.     {
  567.             things[i].vel.x = RSub(things[i].vel.x,acc->x);
  568. /*      things[i].vel.x -= acc->x; */
  569.       things[i].vel.x = RMul(-things[i].vel.x, DAMPING);
  570.       things[i].pos.x = val < CREAL(0.0) ? -limit : limit;
  571.     }
  572.     else
  573.       things[i].canmove |= 1;
  574.  
  575. /*    things[i].vel.y += acc->y; */
  576.         things[i].vel.y = RAdd(things[i].vel.y,acc->y);
  577. /*    val = things[i].pos.y += things[i].vel.y; */
  578.         val = things[i].pos.y = RAdd(things[i].pos.y,things[i].vel.y);
  579.  
  580.     if (val < -limit || val > limit)
  581.     {
  582. /*      things[i].vel.y -= acc->y; */
  583.             things[i].vel.y = RSub(things[i].vel.y,acc->y);
  584.       things[i].vel.y = RMul(-things[i].vel.y, DAMPING);
  585.       things[i].pos.y = val < CREAL(0.0) ? -limit : limit;
  586.     }
  587.     else
  588.       things[i].canmove |= 2;
  589.  
  590. /*    things[i].vel.z += acc->z; */
  591.         things[i].vel.z = RAdd(things[i].vel.z,acc->z);
  592. /*    val = things[i].pos.z += things[i].vel.z; */
  593.         val = things[i].pos.z = RAdd(things[i].pos.z,things[i].vel.z);
  594.     if (val < -limit || val > limit)
  595.     {
  596.       things[i].vel.z -= acc->z;
  597.       things[i].vel.z = RMul(-things[i].vel.z, DAMPING);
  598.       things[i].pos.z = val < CREAL(0.0) ? -limit : limit;
  599.     }
  600.     else
  601.       things[i].canmove |= 4;
  602.   }
  603.   RwPopScratchMatrix();
  604.   frames++;
  605. }
  606.  
  607. /***************************************************************************/
  608. /*
  609.  * This function initializes the 3D (i.e. RenderWare) components of the
  610.  * application. This function opens the RenderWare library, creates a
  611.  * camera, a scene, a light and a matrix for spinning. A user-draw may
  612.  * also be created if USERDRAW_LABELS is defined.
  613.  */
  614.  
  615. static BOOL
  616. Init3D(char *sFilename)
  617. {
  618.   int         i,j;
  619.   int fixed, debugging;
  620.   char *title;
  621.   RwClump *temp;
  622.     RwReal naTextCol[]={CREAL(1.0),CREAL(1.0),CREAL(1.0)};
  623.   char     version[30];
  624.   char     buffer[128];
  625.   int      param;
  626.     long nError;
  627.  
  628.     if (!RwOpen("DOSMOUSE", &nError))
  629.     {
  630.         printf("Unable to access renderware!!\n");
  631.  
  632.         switch (nError) {
  633.             case E_RW_DOS_MODE_UNAVAILABLE: {
  634.                printf("The installed VESA card is unable to switch to the resolution");
  635.                 printf(" requested.\n");
  636.                 printf("Either install a different video adapter or use a ");
  637.                 printf("supported video mode.");
  638.                 break;
  639.             };
  640.             case E_RW_DOS_NO_VESA_BIOS: {
  641.                 printf("A VESA bios is unavailable on this machine.\n");
  642.                 printf("Either use a VESA compatible Video Adapter or install a ");
  643.                 printf("VESA bios emulation TSR.\n");
  644.                 break;
  645.             };
  646.             case E_RW_DOS_INCOMPATIBLE_BIOS: {
  647.                 printf("The VESA bios on this machine is not of high enough version ");
  648.                 printf("to function\ncorrectly with RenderWare. Use a version 1.0 or");
  649.                 printf(" higher VESA bios or TSR.\n");
  650.                 break;
  651.             };
  652.             case E_RW_DOS_NO_MOUSE: {
  653.                 printf("No Microsoft compatible mouse driver present.\n");
  654.                 printf("Install a microsoft compatible mouse driver and try again.\n");
  655.                 break;
  656.             };
  657.             default: {
  658.                 printf("Unknown Error <%i> !!!!!!!!!!!!!!!\n",nError);
  659.                 break;
  660.             };
  661.         };
  662.         return FALSE;
  663.     }
  664.  
  665.     /* Set up the DOS Character Set */
  666.  
  667.   RwGetDeviceInfo(rwSCRHEIGHT,&nGScrHeight,sizeof(nGScrHeight));
  668.   RwGetDeviceInfo(rwSCRWIDTH,&nGScrWidth,sizeof(nGScrWidth));
  669.  
  670.   nGTextCol = RwDeviceControl(rwSCRGETCOLOR,0,naTextCol,sizeof(naTextCol));
  671.  
  672.     RwSetShapePath(".",rwPRECONCAT);
  673.  
  674.     strcpy(buffer,sFilename);
  675.  
  676.     i = strlen(buffer);
  677.     while((buffer[i] != '\\')&&(i>=0)) {
  678.         i--;
  679.     };
  680.  
  681.  
  682.     if (i>=0) {
  683.         buffer[i+1] = 0;
  684.         strcat(buffer, "TEXTURES");
  685.         RwSetShapePath(buffer, rwPOSTCONCAT);
  686.  
  687.         buffer[i+1] = 0;
  688.         strcat(buffer, "SCRIPTS");
  689.         RwSetShapePath(buffer, rwPOSTCONCAT);
  690.     };
  691.  
  692.     RwSetShapePath("SCRIPTS", rwPRECONCAT);
  693.     RwSetShapePath("TEXTURES", rwPRECONCAT);
  694.  
  695.     /*
  696.     * Label the window with information about the version of
  697.     * RenderWare being used. Its rather unlikely that
  698.     * RwGetSystemInfo() will fail so we ignore its return value.
  699.     */
  700.  
  701.   RwGetSystemInfo(rwVERSIONSTRING, &version,sizeof(version));
  702.   RwGetSystemInfo(rwFIXEDPOINTLIB, ¶m,sizeof(param));
  703.     sprintf(buffer, "RenderSim(tm) V%s %s",
  704.         version, (param ? "Fixed" : "Float"));
  705.     DosPrintString(0,nGScrHeight-16,buffer,nGTextCol);
  706.  
  707.   RwGetSystemInfo(rwFIXEDPOINTLIB, &fixed,sizeof(fixed));
  708.   RwGetSystemInfo(rwDEBUGGINGLIB, &debugging,sizeof(debugging));
  709.     if ((fixed) && (debugging))
  710.     title = "n-Body (Fixed & Debugging)";
  711.     else if (fixed)
  712.     title = "n-Body (Fixed Point)";
  713.     else if (debugging)
  714.     title = "n-Body (Debugging)";
  715.     else
  716.     title = "n-Body (Floating Point)";
  717.  
  718.     /* Temporary message !!*/
  719.  
  720.     DosPrintString(0,nGScrHeight-24,title,nGTextCol);
  721.  
  722.     /*
  723.     * Create the camera which will be used for rendering. The initial window
  724.     * size the application will create is given by nGScrWidth and
  725.     * nGScrHeight-17 which depends on the screen res used.
  726.     */
  727.  
  728.     Camera = RwCreateCamera(nGScrWidth,nGScrHeight-17, NULL);
  729.     if (!Camera)
  730.     {
  731.     /*
  732.     * As with RwOpen(), the most common cause for a failure to create
  733.     * a camera is insufficient memory so we will explicitly check for
  734.     * this condition and report it. Otherwise a general error is issued.
  735.     */
  736.         if (RwGetError() == E_RW_NOMEM)
  737.         {
  738.             RwClose();
  739.             printf("Insufficient memory to create the RenderWare(tm) camera\n");
  740.         }
  741.         else
  742.         {
  743.             RwClose();
  744.             printf("Error creating the RenderWare(tm) camera\n");
  745.         }
  746.         exit(-1);
  747.     }
  748.  
  749.  
  750.   /*
  751.     * The window has been resized. Therefore, it is necessary to
  752.     * to modify the camera's viewport to be the same size as the
  753.     * client area of the window.
  754.     */
  755.   RwSetCameraViewport(Camera, 0, 0, nGScrWidth, nGScrHeight-24);
  756.  
  757.   RwSetCameraBackdropViewportRect(Camera, 0,0,nGScrWidth,nGScrHeight-24);
  758.  
  759.   /* aspect ratio of 1:1 */
  760.  
  761.     if (nGScrWidth >= (nGScrHeight-24)) {
  762.     RwSetCameraViewwindow(Camera,
  763.         CREAL(1.0),
  764.         RMul(CREAL(1.0), RDiv(INT2REAL(nGScrHeight-24), INT2REAL(nGScrWidth))));
  765.     } else {
  766.         RwSetCameraViewwindow(Camera,
  767.         RMul(CREAL(1.0), RDiv(INT2REAL(nGScrWidth), INT2REAL(nGScrHeight-24))),
  768.         CREAL(1.0));
  769.     };
  770.  
  771.   /*
  772.     * Set the camera's background color to cyan.
  773.     */
  774.   RwSetCameraBackColor(Camera, CREAL(0.0), CREAL(0.8), CREAL(0.8));
  775.  
  776.  
  777.   RwVCMoveCamera( Camera, CREAL(0.0), CREAL(0.0), CREAL(-7.0) );
  778.  
  779.     /*
  780.      * Create a scene which will contain the clumps to be rendered and the
  781.      * light or lights illuminating those clumps . In this very simple
  782.      * application it would be perfectly acceptable to use the default scene
  783.      * (as returned by RwDefaultScene()) for rendering. However, it is good
  784.      * practice to always create a scene which will be used for your rendering
  785.      * and only use the default scene as a bag for currently unused clumps and
  786.      * lights.
  787.      */
  788.  
  789.  
  790.     Scene = RwCreateScene();
  791.     if (!Scene)
  792.     {
  793.         RwDestroyCamera(Camera);
  794.         RwClose();
  795.         printf("Error creating the RenderWare(tm) scene\n");
  796.         exit(-1);
  797.     }
  798.  
  799.   /*
  800.     * Our scene will be illuminated by a directional light. The illumination
  801.     * vector of the light is (-0.5, -1.0, -1.0) and its brightness will be 1.0.
  802.     */
  803.  
  804.  
  805.     Light = RwCreateLight( rwDIRECTIONAL, CREAL(-0.5), CREAL(-1.0), CREAL(-1.0),
  806.              CREAL(1.2) );
  807.  
  808.     if (!Light)
  809.     {
  810.         RwDestroyScene(Scene);
  811.         RwDestroyCamera(Camera);
  812.         RwClose();
  813.         printf("Error creating the RenderWare(tm) light\n");
  814.         exit(-1);
  815.     }
  816.  
  817.   /*
  818.     * Add the new light to our scene.
  819.     */
  820.  
  821.   RwAddLightToScene(Scene, Light);
  822.  
  823.     /*
  824.      * Make the room in the simulation
  825.      */
  826.  
  827.   RwClumpBegin();
  828.   RwVertex(CREAL(-1.0),CREAL(-1.005),CREAL(1.0));
  829.   RwVertex( CREAL(1.0),CREAL(-1.005),CREAL(1.0));
  830.   RwVertex( CREAL(1.0), CREAL(1.0),CREAL(1.0));
  831.   RwVertex(CREAL(-1.0), CREAL(1.0),CREAL(1.0));
  832.   RwVertex(CREAL(-1.0),CREAL(-1.005),CREAL(-1.0));
  833.   RwVertex( CREAL(1.0),CREAL(-1.005),CREAL(-1.0));
  834.   RwVertex( CREAL(1.0), CREAL(1.0),CREAL(-1.0));
  835.   RwVertex(CREAL(-1.0), CREAL(1.0),CREAL(-1.0));
  836.   RwSetSurface(CREAL(0.4), CREAL(0.6), CREAL(0.0));
  837.   RwSetSurfaceColor(CREAL(0.5), CREAL(0.5), CREAL(0.5));
  838.   RwQuad(2,1,4,3);
  839.   RwSetSurfaceColor(CREAL(0.0), CREAL(0.0), CREAL(0.7));
  840.   RwQuad(6,2,3,7);
  841.   RwSetSurfaceColor(CREAL(0.0), CREAL(0.7), CREAL(0.0));
  842.   RwQuad(5,6,7,8);
  843.   RwSetSurfaceColor(CREAL(0.7), CREAL(0.0), CREAL(0.0));
  844.   RwQuad(1,5,8,4);
  845.   RwSetSurfaceColor(CREAL(0.0), CREAL(0.7), CREAL(0.0));
  846.   RwQuad(8,7,3,4);
  847.   RwTransformBegin();
  848.   RwTranslateCTM(CREAL(0.0), CREAL(-1.0), CREAL(0.0));
  849.   RwScaleCTM(CREAL(0.25),CREAL(0.0),CREAL(0.25));
  850.   for (i=-4; i<=4; i++)
  851.     for (j=-4; j<=4; j++)
  852.       RwVertex(INT2REAL(i), CREAL(0.0), INT2REAL(j));
  853.   for (i=0; i<8; i++)
  854.     for (j=0; j<8; j++)
  855.     {
  856.       if ((i ^ j) & 1)
  857.       {
  858.         RwSetSurface(CREAL(0.5),CREAL(0.2),CREAL(0.0));
  859.         RwSetSurfaceColor(CREAL(1.0), CREAL(0.0), CREAL(0.0));
  860.       }
  861.       else
  862.       {
  863.         RwSetSurface(CREAL(0.5),CREAL(0.5),CREAL(0.0));
  864.         RwSetSurfaceColor(CREAL(0.5), CREAL(0.5), CREAL(0.0));
  865.       }
  866.       RwQuad(9+(i*9)+j, 9+(i*9)+j+1, 9+((i+1)*9)+j+1, 9+((i+1)*9)+j);
  867.     }
  868.   RwTransformEnd();
  869.   RwClumpEnd(&temp);
  870.   RwAddHintToClump(temp, rwCONTAINER);
  871.   RwAddClumpToScene(Scene, temp);
  872.  
  873.   numthings = 10;      /* number of objects */
  874.   makethings(Scene, things, numthings);
  875.  
  876.   follow = 0;
  877.  
  878.     ThreeDInitialized = TRUE;
  879.   return( TRUE );
  880. }
  881.  
  882.  
  883. /**********************************************************************/
  884.  
  885. /*
  886.  * This function shuts down the 3D (i.e. RenderWare) components of the
  887.  * application in a polite fashion.
  888.  */
  889.  
  890. static void
  891. TidyUp3D()
  892. {
  893.     /*
  894.     * Destroy the scene. This will destroy the contents of the scene,
  895.     * i.e. any clumps and lights in that scene. In this case destroying
  896.     * the scene will destroy the light we created in Init3D, and any
  897.     * clumps we have loaded and not already destroyed.
  898.     */
  899.     RwDestroyScene(Scene);
  900.  
  901.     /*
  902.     * Destroy the camera.
  903.     */
  904.     RwDestroyCamera(Camera);
  905.  
  906.     /*
  907.     * Close the library. This will free up any internal resources and
  908.     * textures loaded.
  909.     */
  910.     RwClose();
  911. }
  912.  
  913.  
  914. /****************************************************************************
  915.  HandleLeftButtonDown
  916.  
  917.  On entry    : Mouse X
  918.                         Mouse Y
  919.                         Virtual Keys
  920.  On exit    :
  921.  */
  922.  
  923. static void
  924. HandleLeftButtonDown(int x, int y, int vKeys)
  925. {
  926.   /* Stop warnings */
  927.   x=x;
  928.   y=y;
  929.   vKeys=vKeys;
  930.  
  931.     if (!bButtonDown)
  932.     {
  933.          DosPrintString(0,nGScrHeight-8,sGClear,nGTextCol);
  934.         DosPrintString(0,nGScrHeight-8, "Pan and Tilt Camera",nGTextCol);
  935.     }
  936.     else /* both must be down */
  937.     {
  938.          DosPrintString(0,nGScrHeight-8,sGClear,nGTextCol);
  939.         DosPrintString(0,nGScrHeight-8, "Zoom Camera",nGTextCol);
  940.     }
  941.     bButtonDown |= 1;
  942. }
  943.  
  944. /****************************************************************************
  945.  HandleRightButtonDown
  946.  
  947.  On entry    : Mouse X
  948.                         Mouse Y
  949.                         Virtual Keys
  950.  On exit    :
  951.  */
  952.  
  953. static void
  954. HandleRightButtonDown(int x, int y, int vKeys)
  955. {
  956.   /* Stop warnings */
  957.   x=x;
  958.   y=y;
  959.   vKeys=vKeys;
  960.  
  961.     if (!bButtonDown)
  962.     {
  963.          DosPrintString(0,nGScrHeight-8,sGClear,nGTextCol);
  964.         DosPrintString(0,nGScrHeight-8, "Pan and Zoom Camera",nGTextCol);
  965.     }
  966.     else
  967.     {
  968.          DosPrintString(0,nGScrHeight-8,sGClear,nGTextCol);
  969.         DosPrintString(0,nGScrHeight-8, "Zoom Camera",nGTextCol);
  970.     }
  971.     bButtonDown |= 2;
  972. }
  973.  
  974. /**********************************************************************/
  975.  
  976. /*
  977.  * Handle the left mouse button comming back up. The basic action is
  978.  * to turn of mouse move actions and release mouse capture.
  979.  */
  980.  
  981. static void
  982. HandleLeftButtonUp()
  983. {
  984.   bButtonDown &= ~1;
  985.   if (!bButtonDown)
  986.   {
  987.          DosPrintString(0,nGScrHeight-8,sGClear,nGTextCol);
  988.   } else {
  989.          DosPrintString(0,nGScrHeight-8,sGClear,nGTextCol);
  990.         DosPrintString(0,nGScrHeight-8, "Pan and Zoom Camera",nGTextCol);
  991.     };
  992. }
  993.  
  994. /**********************************************************************/
  995.  
  996. /*
  997.  * Handle the right mouse button comming back up. The basic action is
  998.  * to turn of mouse move actions and release mouse capture.
  999.  */
  1000.  
  1001. static void
  1002. HandleRightButtonUp()
  1003. {
  1004.     bButtonDown &= ~2;
  1005.     if (!bButtonDown)
  1006.     {
  1007.          DosPrintString(0,nGScrHeight-8,sGClear,nGTextCol);
  1008.     }
  1009.     else
  1010.     {
  1011.          DosPrintString(0,nGScrHeight-8,sGClear,nGTextCol);
  1012.         DosPrintString(0,nGScrHeight-8, "Pan and Tilt Camera",nGTextCol);
  1013.     };
  1014. }
  1015.  
  1016.  
  1017. /****************************************************************************
  1018.  HandleTimer
  1019.  
  1020.  On entry    :
  1021.  On exit    :
  1022.  */
  1023.  
  1024. void HandleTimer(void)
  1025. {
  1026.     RwV3d vec;
  1027.  
  1028.     collisions(things, numthings);
  1029.     RwGetCameraLookUp(Camera, &vec);
  1030.     vec.x = RDiv(vec.x, CREAL(-200));
  1031.     vec.y = RDiv(vec.y, CREAL(-200));
  1032.     vec.z = RDiv(vec.z, CREAL(-200));
  1033.     gravitatethings(things, numthings, &vec);
  1034.  
  1035.     if (! bButtonDown )
  1036.     {
  1037.       RwGetClumpOrigin(things[follow].geometry, &vec);
  1038.       RwPointCamera(Camera, vec.x,vec.y,vec.z);
  1039.       RwSetCameraLookUp(Camera, CREAL(0.0),CREAL(1.0),CREAL(0.0));
  1040.     }
  1041.  
  1042.     /*
  1043.     * See the description of HandlePaint() for a description of this common
  1044.     * RenderWare cliche for rendering a scene and copying it to the display.
  1045.     */
  1046.  
  1047.  
  1048.   RwBeginCameraUpdate(Camera,NULL);
  1049.     RwClearCameraViewport(Camera);
  1050.     RwRenderScene(Scene);
  1051.     RwEndCameraUpdate(Camera);
  1052.     RwShowCameraImage(Camera, NULL);
  1053.  
  1054.  
  1055. }
  1056.  
  1057. /****************************************************************************
  1058.  HandleMouseMove
  1059.  
  1060.  * Handle a movement of the mouse. If a previous left or right mouse
  1061.  * button down event has set a mouse move mode then this function will
  1062.  * take the necessary actions. For example, pan and zooming the camera,
  1063.  * panning the light, dragging or spinning a clump etc.
  1064.  
  1065.  On entry    : Mouse x
  1066.                     : Mouse y
  1067.  On exit    :
  1068.  
  1069.  */
  1070. static void
  1071. HandleMouseMove(int x, int y)
  1072. {
  1073.     if ( bButtonDown)
  1074.     {
  1075.       int dx,dy;
  1076.       dx = x - LastX;
  1077.       dy = y - LastY;
  1078.       switch ( bButtonDown )
  1079.       {
  1080.       case 1:
  1081.         {
  1082.         RwV3d at,up;
  1083.           RwPushScratchMatrix();
  1084.           RwGetCameraLookUp(Camera, &up);
  1085.           RwRotateMatrix(RwScratchMatrix(), up.x, up.y, up.z, INT2REAL(-dx),
  1086.         rwREPLACE);
  1087.           RwGetCameraLookRight(Camera, &at);
  1088.           RwRotateMatrix(RwScratchMatrix(), at.x, at.y, at.z, INT2REAL(-dy),
  1089.         rwPOSTCONCAT);
  1090.         RwTransformCamera(Camera, RwScratchMatrix(),rwPOSTCONCAT);
  1091.           RwPopScratchMatrix();
  1092.         }
  1093.         break;
  1094.       case 2:
  1095.         RwVCMoveCamera(Camera, CREAL(0.0),CREAL(0.0), RDiv(INT2REAL(-dy),
  1096.                                 CREAL(50.0)));
  1097.         RwRotateMatrix(RwScratchMatrix(), CREAL(0.0),CREAL(1.0),CREAL(0.0),
  1098.         INT2REAL(-dx), rwREPLACE);
  1099.       RwTransformCamera(Camera, RwScratchMatrix(),rwPOSTCONCAT);
  1100.         break;
  1101.       case 3:
  1102.         RwVCMoveCamera(Camera, CREAL(0.0),CREAL(0.0), RDiv(INT2REAL(-dy),
  1103.                                 CREAL(50.0)));
  1104.         break;
  1105.       }
  1106.     }
  1107. }
  1108.  
  1109. /****************************************************************************
  1110.  HandleKey
  1111.  
  1112.  On entry    :
  1113.  On exit    :
  1114.  */
  1115.  
  1116. void HandleKey(nKey)
  1117. {
  1118.   if (nKey >= '0' && nKey <= '9' && nKey < numthings + '0')
  1119.   {
  1120.     follow = nKey - '0';
  1121.   } else if ((nKey == 't') || (nKey == 'T'))
  1122.   {
  1123.     int t,u;
  1124.     int i;
  1125.     char szBuf[255];
  1126.  
  1127.     u = DosTimer();
  1128.     while (u == (t = DosTimer()));
  1129.     for (i=0; i<150; i++)
  1130.     {
  1131.       RwV3d vec;
  1132.  
  1133.       collisions(things, numthings);
  1134.       RwGetCameraLookUp(Camera, &vec);
  1135.       vec.x = RDiv(vec.x, CREAL(-200));
  1136.       vec.y = RDiv(vec.y, CREAL(-200));
  1137.       vec.z = RDiv(vec.z, CREAL(-200));
  1138.       gravitatethings(things, numthings, &vec);
  1139.       if (1)
  1140.       {
  1141.         RwGetClumpOrigin(things[follow].geometry, &vec);
  1142.         RwPointCamera(Camera, vec.x,vec.y,vec.z);
  1143.         RwSetCameraLookUp(Camera, CREAL(0.0),CREAL(1.0),CREAL(0.0));
  1144.       }
  1145.       RwBeginCameraUpdate(Camera,NULL);
  1146.       RwClearCameraViewport( Camera );
  1147.       RwRenderScene( Scene );
  1148.       RwEndCameraUpdate(Camera);
  1149.       RwShowCameraImage( Camera, NULL);
  1150.     }
  1151.     u = DosTimer();
  1152.     sprintf(szBuf, "DosSim took %lu ms for %d frames\n", u-t, i);
  1153.          DosPrintString(0,nGScrHeight-8,sGClear,nGTextCol);
  1154.         DosPrintString(0,nGScrHeight-8,szBuf,nGTextCol);
  1155.   }
  1156. }
  1157.  
  1158. /****************************************************************************
  1159.  Main Function
  1160.  */
  1161.  
  1162. void main(int nArgc,char *saArgv[])
  1163. {
  1164.     int nKey;
  1165.     int nOldMouseBut;
  1166.     int nDX,nDY;
  1167.     int nChange;
  1168.     int nCtrlShift;
  1169.     RwMousePointer mMouse;
  1170.  
  1171.   /* Stop warnings */
  1172.  
  1173.   nArgc = nArgc;
  1174.  
  1175.     if (!Init3D(saArgv[0]))
  1176.     {
  1177.         exit(-1);
  1178.     };
  1179.  
  1180.     /* Create a Black outlined White pointer */
  1181.  
  1182.   RwDeviceControl(rwPOINTERDISPLAY,0,&mMouse,sizeof(mMouse));
  1183.     LastX = mMouse.x;
  1184.     LastY = mMouse.y;
  1185.     nOldMouseBut = mMouse.buttons;
  1186.  
  1187.     nKey = DosGetKey();
  1188.  
  1189.     while (nKey!=27) {        /* ESC quits */
  1190.     RwDeviceControl(rwPOINTERDISPLAY,0,&mMouse,sizeof(mMouse));
  1191.         nKey = DosGetKey();
  1192.  
  1193.         nCtrlShift = DosShiftCtrl();
  1194.  
  1195.         nDX =(mMouse.x-LastX);
  1196.         nDY =(mMouse.y-LastY);
  1197.  
  1198.         nChange = (mMouse.buttons&(2+8)) | ( (nOldMouseBut&(2+8)) >>1 );
  1199.  
  1200.         switch (nChange) {
  1201.             case 0+0:
  1202.             case 2+1:
  1203.             case 8+4:
  1204.             case 8+2+4+1: {
  1205.                 /* No change */
  1206.                 break;
  1207.             };
  1208.             case 2:
  1209.             case 8+2+4: {
  1210.  
  1211.                 /* Left Button Down */
  1212.  
  1213.                 HandleLeftButtonDown(mMouse.x,mMouse.y,nCtrlShift);
  1214.  
  1215.                 break;
  1216.             };
  1217.             case 8:
  1218.             case 8+2+1: {
  1219.                 /* Right Button Down */
  1220.  
  1221.  
  1222.                 HandleRightButtonDown(mMouse.x,mMouse.y,nCtrlShift);
  1223.  
  1224.                 break;
  1225.             };
  1226.             case 8+1: {
  1227.                 /* Right down left Up */
  1228.  
  1229.                 HandleLeftButtonUp();
  1230.                 HandleRightButtonDown(mMouse.x,mMouse.y,nCtrlShift);
  1231.  
  1232.                 break;
  1233.             };
  1234.             case 2+4: {
  1235.                 /* Right up left Down */
  1236.  
  1237.  
  1238.                 HandleRightButtonUp();
  1239.                 HandleLeftButtonDown(mMouse.x,mMouse.y,nCtrlShift);
  1240.  
  1241.  
  1242.                 break;
  1243.             };
  1244.             case 8+2: {
  1245.                 /* Left down RIght Down */
  1246.  
  1247.  
  1248.                 HandleRightButtonDown(mMouse.x,mMouse.y,nCtrlShift);
  1249.                 HandleLeftButtonDown(mMouse.x,mMouse.y,nCtrlShift);
  1250.  
  1251.  
  1252.                 break;
  1253.             };
  1254.             case 1+4: {
  1255.                 /* Left up Right Up */
  1256.  
  1257.  
  1258.                 HandleRightButtonUp();
  1259.                 HandleLeftButtonUp();
  1260.  
  1261.  
  1262.                 break;
  1263.             };
  1264.             case 1:
  1265.             case 8+4+1: {
  1266.                 /* Left up */
  1267.  
  1268.  
  1269.                 HandleLeftButtonUp();
  1270.  
  1271.  
  1272.                 break;
  1273.             };
  1274.             case 4:
  1275.             case 2+4+1: {
  1276.                 /* Right up */
  1277.  
  1278.  
  1279.                 HandleRightButtonUp();
  1280.  
  1281.  
  1282.                 break;
  1283.             };
  1284.         };
  1285.  
  1286.         if (nDX||nDY) {
  1287.             /* Mouse Move  */
  1288.             HandleMouseMove(mMouse.x,mMouse.y);
  1289.         };
  1290.  
  1291.  
  1292.         if (nKey) {
  1293.             HandleKey(nKey);
  1294.         };
  1295.  
  1296.         HandleTimer();
  1297.  
  1298.         LastX = mMouse.x;
  1299.         LastY = mMouse.y;
  1300.         nOldMouseBut = mMouse.buttons;
  1301.  
  1302.     };
  1303.  
  1304.     /*
  1305.     * Tidy up the 3D (RenderWare) components of the application.
  1306.     */
  1307.  
  1308.     TidyUp3D();
  1309.  
  1310.     exit(0);
  1311. }
  1312.  
  1313.