home *** CD-ROM | disk | FTP | other *** search
/ Learn 3D Graphics Programming on the PC / Learn_3D_Graphics_Programming_on_the_PC_Ferraro.iso / rwwin / rwsim.c_ / rwsim.bin
Text File  |  1995-11-14  |  34KB  |  1,008 lines

  1. /**********************************************************************
  2.  *
  3.  * File :     rwsim.c
  4.  *
  5.  * Abstract : RenderWare N body simulation demo. Main module
  6.  *
  7.  **********************************************************************
  8.  *
  9.  * This file is a product of Criterion Software Ltd.
  10.  *
  11.  * This file is provided as is with no warranties of any kind and is
  12.  * provided without any obligation on Criterion Software Ltd. or
  13.  * Canon Inc. to assist in its use or modification.
  14.  *
  15.  * Criterion Software Ltd. will not, under any
  16.  * circumstances, be liable for any lost revenue or other damages arising
  17.  * from the use of this file.
  18.  *
  19.  * Copyright (c) 1995 Criterion Software Ltd.
  20.  * All Rights Reserved.
  21.  *
  22.  * RenderWare is a trademark of Canon Inc.
  23.  *
  24.  ************************************************************************/
  25. #define INCLUDE_SHELLAPI_H
  26.  
  27. #include <windows.h>
  28. #include <stdlib.h>
  29. #include <stdio.h>
  30. #include <string.h>
  31. #include <math.h>
  32. #include <time.h>
  33.  
  34. #include <rwlib.h>
  35.  
  36. #include "common.h"
  37. #include "status.h"
  38. #include "resource.h"
  39.  
  40. #ifndef __WINDOWS_386__
  41. #define MK_FP32(x) (x)
  42. #endif
  43.  
  44. #define DAMPING    CREAL(0.95)
  45. #define MAXTHINGS  25
  46.  
  47. #define ERROR_DIALOG_TITLE    "RenderWare n-Body Simulation Error"
  48.  
  49. #define MAXIMUM_WINDOW_WIDTH  512
  50. #define MAXIMUM_WINDOW_HEIGHT 512
  51.  
  52. /*--- Ansi Declarations */
  53.  
  54. extern long far PASCAL MainWndProc(HWND, WORD, WPARAM, LPARAM);
  55.  
  56. typedef struct
  57. {
  58.     RwClump *geometry;
  59.     int canmove;
  60.     RwReal size;
  61.     RwV3d pos, vel;
  62.     RwMatrix4d *tumble, *rot, *antirot;
  63.     RwReal rotangle, antiangle;
  64.     RwV3d axis;
  65.     int damprot;
  66. }
  67. Thing;
  68.  
  69. Thing things[MAXTHINGS];
  70. int follow, numthings;
  71.  
  72. HANDLE hInstance;
  73. RwScene *scene;
  74. RwCamera *pCamera;
  75. RwLight *pLight;
  76.  
  77. static ThreeDInitialized = FALSE;
  78.  
  79. static long frames = 0;
  80.  
  81. /**************************************************************************
  82.     About Dialogue Box Stuff
  83. **************************************************************************/
  84. void 
  85. DlgDrawItem(DRAWITEMSTRUCT FAR * dis)
  86. {
  87.     HDC hdcMemory;
  88.     HBITMAP hbmplogo, hbmpOld;
  89.     BITMAP bm;
  90.  
  91.     hbmplogo = LoadBitmap(hInstance, "RW_LOGO");
  92.     GetObject(hbmplogo, sizeof (BITMAP), &bm);
  93.  
  94.     hdcMemory = CreateCompatibleDC(dis->hDC);
  95.     hbmpOld = SelectObject(hdcMemory, hbmplogo);
  96.  
  97.     BitBlt(dis->hDC, dis->rcItem.left, dis->rcItem.top,
  98.            dis->rcItem.right - dis->rcItem.left,
  99.            dis->rcItem.bottom - dis->rcItem.top,
  100.            hdcMemory, 0, 0, SRCCOPY);
  101.  
  102.     SelectObject(hdcMemory, hbmpOld);
  103.     DeleteDC(hdcMemory);
  104.     DeleteObject(hbmplogo);
  105. }
  106.  
  107. BOOL FAR PASCAL 
  108. AboutDlgProc(HWND hDlg, WORD message, WPARAM wParam, LPARAM lParam)
  109. {
  110.     switch (message)
  111.     {
  112.         case WM_INITDIALOG:
  113.             return TRUE;
  114.  
  115.         case WM_COMMAND:
  116.             switch (wParam)
  117.             {
  118.                 case IDOK:
  119.                 case IDCANCEL:
  120.                     EndDialog(hDlg, 0);
  121.                     return (TRUE);
  122.             }
  123.             break;
  124.  
  125.         case WM_DRAWITEM:
  126.             DlgDrawItem((DRAWITEMSTRUCT FAR *) MK_FP32((void *) lParam));
  127.             return (TRUE);
  128.     }
  129.     return (FALSE);
  130. }
  131.  
  132. /**********************************************************************/
  133. /* Handle the given menu item. */
  134. /**********************************************************************/
  135.  
  136. static void
  137. HandleMenu(HWND window, WPARAM menuItem)
  138. {
  139.  
  140.     switch (menuItem)
  141.     {
  142.         case CM_FILEEXIT:
  143.             SendMessage(window, WM_CLOSE, 0, 0L);
  144.             break;
  145.         case CM_TRACK0:
  146.             follow = 0;
  147.             break;
  148.         case CM_TRACK1:
  149.             follow = 1;
  150.             break;
  151.         case CM_TRACK2:
  152.             follow = 2;
  153.             break;
  154.         case CM_TRACK3:
  155.             follow = 3;
  156.             break;
  157.         case CM_TRACK4:
  158.             follow = 4;
  159.             break;
  160.         case CM_TRACK5:
  161.             follow = 5;
  162.             break;
  163.         case CM_TRACK6:
  164.             follow = 6;
  165.             break;
  166.         case CM_TRACK7:
  167.             follow = 7;
  168.             break;
  169.         case CM_TRACK8:
  170.             follow = 8;
  171.             break;
  172.         case CM_TRACK9:
  173.             follow = 9;
  174.             break;
  175.         case CM_HELPABOUT:
  176.             KillTimer(window, 1);
  177.             DialogBox(hInstance, "ABOUT", window, MakeProcInstance(AboutDlgProc, hInstance));
  178.             SetTimer(window, 1, 10, NULL);
  179.             break;
  180.     }
  181. }
  182.  
  183. /*********************************************************************/
  184. static void 
  185. randomvec(RwV3d * vec)
  186. {
  187.     vec->x = RANDOM_REAL(CREAL(-1.0), CREAL(1.0));
  188.     vec->y = RANDOM_REAL(CREAL(-1.0), CREAL(1.0));
  189.     vec->z = RANDOM_REAL(CREAL(-1.0), CREAL(1.0));
  190. }
  191.  
  192. /*********************************************************************/
  193. static void 
  194. assignvec(RwV3d * vec, RwReal x, RwReal y, RwReal z)
  195. {
  196.     vec->x = x;
  197.     vec->y = y;
  198.     vec->z = z;
  199. }
  200.  
  201. /*********************************************************************/
  202. static RwPolygon3d *
  203. makezippy(RwPolygon3d * p)
  204. {
  205.     static int zippy = 0;
  206.  
  207.     switch (zippy % 7)
  208.     {
  209.         case 0:
  210.             RwSetPolygonColor(p, CREAL(0.7), CREAL(0.0), CREAL(0.0));
  211.             break;
  212.         case 1:
  213.             RwSetPolygonColor(p, CREAL(0.0), CREAL(0.7), CREAL(0.0));
  214.             break;
  215.         case 2:
  216.             RwSetPolygonColor(p, CREAL(0.0), CREAL(0.0), CREAL(0.7));
  217.             break;
  218.         case 3:
  219.             RwSetPolygonColor(p, CREAL(0.7), CREAL(0.7), CREAL(0.0));
  220.             break;
  221.         case 4:
  222.             RwSetPolygonColor(p, CREAL(0.7), CREAL(0.0), CREAL(0.7));
  223.             break;
  224.         case 5:
  225.             RwSetPolygonColor(p, CREAL(0.0), CREAL(0.7), CREAL(0.7));
  226.             break;
  227.         case 6:
  228.             RwSetPolygonColor(p, CREAL(0.7), CREAL(0.7), CREAL(0.7));
  229.             break;
  230.     }
  231.     zippy++;
  232.     return (p);
  233. }
  234.  
  235. /*********************************************************************/
  236. static void 
  237. makethings(RwScene * scene, Thing * things, int num)
  238. {
  239.     RwClump *clump, *prototypes[4];
  240.     RwV3d p;
  241.     int i;
  242.     RwInt32 which;
  243.  
  244.     RwSRandom((RwInt32) clock());
  245.  
  246.     for (i = 0; i < 4; i++)
  247.     {
  248.         RwClumpBegin();
  249.         RwSetSurface(CREAL(0.4), CREAL(0.7), CREAL(0.0));
  250.         RwSetSurfaceColor(RDiv(CREAL(1.0), INT2REAL(1 + (RwRandom() % 4))),
  251.                           RDiv(CREAL(1.0), INT2REAL(1 + (RwRandom() % 4))),
  252.                           RDiv(CREAL(1.0), INT2REAL(1 + (RwRandom() % 4))));
  253.         switch (i)
  254.         {
  255.             case 0:
  256.                 RwTranslateCTM(CREAL(0.0), CREAL(-0.15 / 2), CREAL(0.0));
  257.                 RwCone(CREAL(0.15), CREAL(0.1), 12);
  258.                 RwRotateCTM(CREAL(1.0), CREAL(0.0), CREAL(0.0), CREAL(180.0));
  259.                 RwSetSurfaceColor(RDiv(CREAL(1.0), INT2REAL(1 + (RwRandom() % 4))),
  260.                            RDiv(CREAL(1.0), INT2REAL(1 + (RwRandom() % 4))),
  261.                           RDiv(CREAL(1.0), INT2REAL(1 + (RwRandom() % 4))));
  262.                 RwDisc(CREAL(0.0), CREAL(0.1), 12);
  263.                 break;
  264.             case 1:
  265.                 RwSphere(CREAL(0.1), 3);
  266.                 break;
  267.             case 2:
  268.                 RwTranslateCTM(CREAL(0.0), CREAL(-0.15 / 2), CREAL(0.0));
  269.                 RwCylinder(CREAL(0.15), CREAL(0.1), CREAL(0.1), 12);
  270.                 RwSetSurfaceColor(RDiv(CREAL(1.0), INT2REAL(1 + (RwRandom() % 4))),
  271.                            RDiv(CREAL(1.0), INT2REAL(1 + (RwRandom() % 4))),
  272.                           RDiv(CREAL(1.0), INT2REAL(1 + (RwRandom() % 4))));
  273.                 RwDisc(CREAL(0.15), CREAL(0.1), 12);
  274.                 RwRotateCTM(CREAL(1.0), CREAL(0.0), CREAL(0.0), CREAL(180.0));
  275.                 RwSetSurfaceColor(RDiv(CREAL(1.0), INT2REAL(1 + (RwRandom() % 4))),
  276.                            RDiv(CREAL(1.0), INT2REAL(1 + (RwRandom() % 4))),
  277.                           RDiv(CREAL(1.0), INT2REAL(1 + (RwRandom() % 4))));
  278.                 RwDisc(CREAL(0.0), CREAL(0.1), 12);
  279.                 break;
  280.             default:
  281.                 RwBlock(CREAL(0.1), CREAL(0.2), CREAL(0.15));
  282.                 break;
  283.         }
  284.         RwClumpEnd(&prototypes[i]);
  285.     }
  286.  
  287.     for (i = 0; i < num; i++)
  288.     {
  289.         which = RwRandom() % 4L;
  290.         clump = RwDuplicateClump(prototypes[(int) which]);
  291.         if ((RwRandom() & 7) < 2)
  292.             RwForAllPolygonsInClump(clump, makezippy);
  293.         RwAddClumpToScene(scene, clump);
  294.         things[i].geometry = clump;
  295.         things[i].size = CREAL(0.1);
  296.         RwIdentityMatrix(things[i].tumble = RwCreateMatrix());
  297.         RwIdentityMatrix(things[i].rot = RwCreateMatrix());
  298. /*
  299.    RwIdentityMatrix(things[i].antirot = RwCreateMatrix());
  300.  */
  301.         things[i].damprot = 0;
  302.         randomvec(&p);
  303.         things[i].pos.x = RMul(p.x, RSub(CREAL(1.0), things[i].size));
  304.         things[i].pos.y = RMul(p.y, RSub(CREAL(1.0), things[i].size));
  305.         things[i].pos.z = RMul(p.z, RSub(CREAL(1.0), things[i].size));
  306.         things[i].canmove = 7;
  307.         assignvec(&things[i].vel, CREAL(0.0), CREAL(0.0), CREAL(0.0));
  308.     }
  309.     for (i = 0; i < 4; i++)
  310.         RwDestroyClump(prototypes[i]);
  311. }
  312.  
  313. /*********************************************************************/
  314. static 
  315. twobody(Thing * things, int i, int j)
  316. {
  317.     RwReal length, adjust, doti, dotj, speedi, speedj;
  318.     RwV3d hit, axis, xferi, xferj;
  319.     RwV3d veli, velj;
  320.  
  321.     hit.x = RSub(things[j].pos.x, things[i].pos.x);
  322.     hit.y = RSub(things[j].pos.y, things[i].pos.y);
  323.     hit.z = RSub(things[j].pos.z, things[i].pos.z);
  324.     length = RAdd(RAdd(RMul(hit.x, hit.x), RMul(hit.y, hit.y)),
  325.                   RMul(hit.z, hit.z));
  326.     if (length > CREAL(0.0) && length < CREAL(0.2 * 0.2))
  327.     {
  328.         if (1)
  329.         {
  330.             length = RSqrt(length);
  331.             hit.x = RDiv(hit.x, length);
  332.             hit.y = RDiv(hit.y, length);
  333.             hit.z = RDiv(hit.z, length);
  334.             adjust = RDiv(RSub(CREAL(0.2), length), CREAL(2));
  335.  
  336.             veli = things[i].vel;
  337.             speedi = RAdd(RAdd(RMul(veli.x, veli.x), RMul(veli.y, veli.y)),
  338.                           RMul(veli.z, veli.z));
  339.             if (speedi != CREAL(0.0))
  340.             {
  341.                 speedi = RSqrt(speedi);
  342.                 veli.x = RDiv(veli.x, speedi);
  343.                 veli.y = RDiv(veli.y, speedi);
  344.                 veli.z = RDiv(veli.z, speedi);
  345.                 doti = RwDotProduct(&hit, &veli);
  346.                 if (doti > CREAL(0))
  347.                 {
  348.                     speedi = RMul(speedi, RMul(doti, DAMPING));
  349.                     xferi.x = RMul(hit.x, speedi);
  350.                     xferi.y = RMul(hit.y, speedi);
  351.                     xferi.z = RMul(hit.z, speedi);
  352.                     RwCrossProduct(&veli, &hit, &axis);
  353. /*
  354.    RwRotateMatrix(things[i].rot, axis.x,axis.y,axis.z,
  355.    RMul(speedi, RMul(RSub(CREAL(1),doti), CREAL(720.0))),
  356.    rwREPLACE);
  357.  */
  358.                     things[i].rotangle = RMul(speedi, RMul(RSub(CREAL(1), doti), CREAL(720.0)));
  359.                     things[i].axis.x = axis.x;
  360.                     things[i].axis.y = axis.y;
  361.                     things[i].axis.z = axis.z;
  362. /*
  363.    RwRotateMatrix(things[i].antirot, axis.x,axis.y,axis.z, 
  364.    RMul(speedi, RMul(RSub(CREAL(1),doti), CREAL(-4.0))),
  365.    rwREPLACE);
  366.  */
  367.                     things[i].antiangle = RMul(speedi, RMul(RSub(CREAL(1), doti), CREAL(-4.0)));
  368.                     things[i].damprot = (int) (720.0 / 4.0);
  369.                 }
  370.                 else
  371.                     xferi.x = xferi.y = xferi.z = CREAL(0.0);
  372.             }
  373.             else
  374.                 xferi.x = xferi.y = xferi.z = CREAL(0.0);
  375. /* I happen to know that -= works :-) */
  376.             if (things[i].canmove & 1)
  377.                 things[i].pos.x -= RMul(hit.x, adjust);
  378.             if (!things[j].canmove & 1)
  379.                 things[i].pos.x -= RMul(hit.x, adjust);
  380.             if (things[i].canmove & 2)
  381.                 things[i].pos.y -= RMul(hit.y, adjust);
  382.             if (!things[j].canmove & 2)
  383.                 things[i].pos.y -= RMul(hit.y, adjust);
  384.             if (things[i].canmove & 4)
  385.                 things[i].pos.z -= RMul(hit.z, adjust);
  386.             if (!things[j].canmove & 4)
  387.                 things[i].pos.z -= RMul(hit.z, adjust);
  388.  
  389.             hit.x = -hit.x;
  390.             hit.y = -hit.y;
  391.             hit.z = -hit.z;
  392.             velj = things[j].vel;
  393.             speedj = RAdd(RAdd(RMul(velj.x, velj.x), RMul(velj.y, velj.y)),
  394.                           RMul(velj.z, velj.z));
  395.             if (speedj != CREAL(0.0))
  396.             {
  397.                 speedj = RSqrt(speedj);
  398.                 velj.x = RDiv(velj.x, speedj);
  399.                 velj.y = RDiv(velj.y, speedj);
  400.                 velj.z = RDiv(velj.z, speedj);
  401.                 dotj = RwDotProduct(&hit, &velj);
  402.                 if (dotj > CREAL(0))
  403.                 {
  404.                     speedj = RMul(speedj, RMul(dotj, DAMPING));
  405.                     xferj.x = RMul(hit.x, speedj);
  406.                     xferj.y = RMul(hit.y, speedj);
  407.                     xferj.z = RMul(hit.z, speedj);
  408.                     RwCrossProduct(&velj, &hit, &axis);
  409. /*
  410.    RwRotateMatrix(things[j].rot, axis.x,axis.y,axis.z,
  411.    RMul(speedj, RMul(RSub(CREAL(1),dotj), CREAL(720.0))),
  412.    rwREPLACE);
  413.  */
  414.                     things[j].rotangle = RMul(speedj, RMul(RSub(CREAL(1), dotj), CREAL(720.0)));
  415.                     things[j].axis.x = axis.x;
  416.                     things[j].axis.y = axis.y;
  417.                     things[j].axis.z = axis.z;
  418. /*
  419.    RwRotateMatrix(things[j].antirot, axis.x,axis.y,axis.z, 
  420.    RMul(speedj, RMul(RSub(CREAL(1),dotj), CREAL(-4.0))),
  421.    rwREPLACE);
  422.  */
  423.                     things[j].antiangle = RMul(speedj, RMul(RSub(CREAL(1), dotj), CREAL(-4.0)));
  424.                     things[j].damprot = (int) (720.0 / 4.0);
  425.                 }
  426.                 else
  427.                     xferj.x = xferj.y = xferj.z = CREAL(0.0);
  428.             }
  429.             else
  430.                 xferj.x = xferj.y = xferj.z = CREAL(0.0);
  431.             if (things[j].canmove & 1)
  432.                 things[j].pos.x -= RMul(hit.x, adjust);
  433.             if (!things[i].canmove & 1)
  434.                 things[j].pos.x -= RMul(hit.x, adjust);
  435.             if (things[j].canmove & 2)
  436.                 things[j].pos.y -= RMul(hit.y, adjust);
  437.             if (!things[i].canmove & 2)
  438.                 things[j].pos.y -= RMul(hit.y, adjust);
  439.             if (things[j].canmove & 4)
  440.                 things[j].pos.z -= RMul(hit.z, adjust);
  441.             if (!things[i].canmove & 4)
  442.                 things[j].pos.z -= RMul(hit.z, adjust);
  443.  
  444. /* A little bird told me that += always works :-) */
  445.             things[i].vel.x += RSub(xferj.x, xferi.x);
  446.             things[i].vel.y += RSub(xferj.y, xferi.y);
  447.             things[i].vel.z += RSub(xferj.z, xferi.z);
  448.  
  449.             things[j].vel.x += RSub(xferi.x, xferj.x);
  450.             things[j].vel.y += RSub(xferi.y, xferj.y);
  451.             things[j].vel.z += RSub(xferi.z, xferj.z);
  452.         }
  453.         return (1);
  454.     }
  455.     return (0);
  456. }
  457.  
  458. /*********************************************************************/
  459. void 
  460. collisions(Thing * things, int num)
  461. {
  462.     int i, j;
  463.  
  464.     for (i = 0; i < num; i++)
  465.     {
  466.         for (j = i + 1; j < num; j++)
  467.         {
  468.             if (twobody(things, i, j))
  469.                 break;
  470.         }
  471.     }
  472. }
  473.  
  474. /*********************************************************************/
  475. static void 
  476. gravitatethings(Thing * things, int num, RwV3d * acc)
  477. {
  478.     int i;
  479.     RwV3d p;
  480.     RwReal val;
  481.     RwReal limit;
  482.  
  483.     RwPushScratchMatrix();
  484.     limit = CREAL(1.0 - 0.1);
  485.     for (i = 0; i < num; i++)
  486.     {
  487.         if (things[i].damprot > 0)
  488.         {
  489. /* Below is the original version of the damping code. This accumulates
  490.    a new .rot matrix by repeated multiplication with .antirot. This
  491.    causes the .rot matrix to drift causing shearing of the object.
  492.    RwMultiplyMatrix(things[i].rot, things[i].antirot, RwScratchMatrix());
  493.    RwCopyMatrix(RwScratchMatrix(), things[i].rot);
  494.  */
  495.             RwRotateMatrix(things[i].rot, things[i].axis.x, things[i].axis.y,
  496.                            things[i].axis.z,
  497.                   RSub(things[i].rotangle, things[i].antiangle), rwREPLACE);
  498.             things[i].damprot--;
  499.         }
  500.         RwMultiplyMatrix(things[i].tumble, things[i].rot, RwScratchMatrix());
  501.         if ((frames) % (num << 3) == (i << 3))
  502.             RwOrthoNormalizeMatrix(RwScratchMatrix(), RwScratchMatrix());
  503.         RwCopyMatrix(RwScratchMatrix(), things[i].tumble);
  504.         p = things[i].pos;
  505.         RwTranslateMatrix(RwScratchMatrix(), p.x, p.y, p.z, rwPOSTCONCAT);
  506.         RwTransformClump(things[i].geometry, RwScratchMatrix(), rwREPLACE);
  507.  
  508.         things[i].canmove = 0;
  509. /* += */
  510.         things[i].vel.x += acc->x;
  511.         val = things[i].pos.x += things[i].vel.x;
  512.         if (val < -limit || val > limit)
  513.         {
  514.             things[i].vel.x -= acc->x;
  515.             things[i].vel.x = RMul(-things[i].vel.x, DAMPING);
  516.             things[i].pos.x = val < CREAL(0.0) ? -limit : limit;
  517.         }
  518.         else
  519.             things[i].canmove |= 1;
  520.  
  521.         things[i].vel.y += acc->y;
  522.         val = things[i].pos.y += things[i].vel.y;
  523.         if (val < -limit || val > limit)
  524.         {
  525.             things[i].vel.y -= acc->y;
  526.             things[i].vel.y = RMul(-things[i].vel.y, DAMPING);
  527.             things[i].pos.y = val < CREAL(0.0) ? -limit : limit;
  528.         }
  529.         else
  530.             things[i].canmove |= 2;
  531.  
  532.         things[i].vel.z += acc->z;
  533.         val = things[i].pos.z += things[i].vel.z;
  534.         if (val < -limit || val > limit)
  535.         {
  536.             things[i].vel.z -= acc->z;
  537.             things[i].vel.z = RMul(-things[i].vel.z, DAMPING);
  538.             things[i].pos.z = val < CREAL(0.0) ? -limit : limit;
  539.         }
  540.         else
  541.             things[i].canmove |= 4;
  542.     }
  543.     RwPopScratchMatrix();
  544.     frames++;
  545. }
  546. /*********************************************************************/
  547. /*********************************************************************/
  548.  
  549. BOOL 
  550. InitApplication(HANDLE hInst)
  551. {
  552.     WNDCLASS wc;
  553.  
  554.     wc.style = CS_BYTEALIGNWINDOW | CS_HREDRAW | CS_VREDRAW;
  555.     wc.lpfnWndProc = (WNDPROC) MainWndProc;
  556.     wc.cbClsExtra = 0;
  557.     wc.cbWndExtra = 0;
  558.     wc.hInstance = hInst;
  559.     wc.hIcon = LoadIcon(hInst, "RW_ICON");
  560.     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  561.     wc.hbrBackground = NULL;
  562.     wc.lpszMenuName = "FILE_MENU";
  563.     wc.lpszClassName = "RwNBodyWndClass";
  564.  
  565.     return (RegisterClass(&wc));
  566. }
  567.  
  568. BOOL 
  569. InitInstance(HANDLE hInst, int nCmdShow)
  570. {
  571.     HWND hWnd;
  572.     int i, j;
  573.     RwClump *temp;
  574.  
  575.     hInstance = hInst;
  576.  
  577.     hWnd = CreateWindow("RwNBodyWndClass", "RenderWare n-Body Simulation",
  578.                         WS_OVERLAPPEDWINDOW,
  579.                         CW_USEDEFAULT, CW_USEDEFAULT, 350, 350,
  580.                         NULL, NULL, hInstance, NULL);
  581.  
  582.     if (hWnd == NULL)
  583.     {
  584.         MessageBox(NULL, "Internal Operating System Error",
  585.                    ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
  586.         return (FALSE);
  587.     }
  588.  
  589.     CheckDisplayDepth(hWnd);
  590.  
  591.     if (!RwOpen("MSWindows", NULL))
  592.     {
  593.         if (RwGetError() == E_RW_NOMEM)
  594.         {
  595.             MessageBox(hWnd,
  596.                        "Insufficient memory to open the RenderWare library",
  597.                     ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
  598.         }
  599.         else
  600.         {
  601.             MessageBox(hWnd, "Error opening the RenderWare library",
  602.                     ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
  603.         }
  604.         return (FALSE);
  605.     }
  606.  
  607.     scene = RwCreateScene();
  608.     if (scene == NULL)
  609.     {
  610.         RwClose();
  611.         MessageBox(hWnd, "Error creating the RenderWare scene",
  612.                    ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
  613.         return (FALSE);
  614.     }
  615.  
  616.     pCamera = RwCreateCamera(MAXIMUM_WINDOW_WIDTH,
  617.                              MAXIMUM_WINDOW_HEIGHT, NULL);
  618.  
  619.     if (pCamera == NULL)
  620.     {
  621.         if (RwGetError() == E_RW_NOMEM)
  622.         {
  623.             MessageBox(hWnd,
  624.                        "Insufficient memory to create the RenderWare camera",
  625.                     ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
  626.         }
  627.         else
  628.         {
  629.             MessageBox(hWnd, "Error creating the RenderWare camera",
  630.                     ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
  631.         }
  632.         RwDestroyScene(scene);
  633.         RwClose();
  634.         return (FALSE);
  635.     }
  636.  
  637.     RwClearCameraViewport(pCamera);
  638.     RwSetCameraBackColor(pCamera, CREAL(0.0), CREAL(0.0), CREAL(0.0));
  639.     RwVCMoveCamera(pCamera, CREAL(0.0), CREAL(0.0), CREAL(-7.0));
  640.     pLight = RwCreateLight(rwDIRECTIONAL, CREAL(-0.5), CREAL(-1.0), CREAL(-1.0),
  641.                            CREAL(1.2));
  642.  
  643.     if (pLight == NULL)
  644.     {
  645.         RwDestroyCamera(pCamera);
  646.         RwDestroyScene(scene);
  647.         RwClose();
  648.         MessageBox(hWnd, "Error creating the RenderWare light",
  649.                    ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
  650.         return (FALSE);
  651.     }
  652.     RwAddLightToScene(scene, pLight);
  653.  
  654.     RwClumpBegin();
  655.     RwVertex(CREAL(-1.0), CREAL(-1.005), CREAL(1.0));
  656.     RwVertex(CREAL(1.0), CREAL(-1.005), CREAL(1.0));
  657.     RwVertex(CREAL(1.0), CREAL(1.0), CREAL(1.0));
  658.     RwVertex(CREAL(-1.0), CREAL(1.0), CREAL(1.0));
  659.     RwVertex(CREAL(-1.0), CREAL(-1.005), CREAL(-1.0));
  660.     RwVertex(CREAL(1.0), CREAL(-1.005), CREAL(-1.0));
  661.     RwVertex(CREAL(1.0), CREAL(1.0), CREAL(-1.0));
  662.     RwVertex(CREAL(-1.0), CREAL(1.0), CREAL(-1.0));
  663.     RwSetSurface(CREAL(0.4), CREAL(0.6), CREAL(0.0));
  664.     RwSetSurfaceColor(CREAL(0.5), CREAL(0.5), CREAL(0.5));
  665.     RwQuad(2, 1, 4, 3);
  666.     RwSetSurfaceColor(CREAL(0.0), CREAL(0.0), CREAL(0.7));
  667.     RwQuad(6, 2, 3, 7);
  668.     RwSetSurfaceColor(CREAL(0.0), CREAL(0.7), CREAL(0.0));
  669.     RwQuad(5, 6, 7, 8);
  670.     RwSetSurfaceColor(CREAL(0.7), CREAL(0.0), CREAL(0.0));
  671.     RwQuad(1, 5, 8, 4);
  672.     RwSetSurfaceColor(CREAL(0.0), CREAL(0.7), CREAL(0.0));
  673.     RwQuad(8, 7, 3, 4);
  674.     RwTransformBegin();
  675.     RwTranslateCTM(CREAL(0.0), CREAL(-1.0), CREAL(0.0));
  676.     RwScaleCTM(CREAL(0.25), CREAL(0.0), CREAL(0.25));
  677.     for (i = -4; i <= 4; i++)
  678.         for (j = -4; j <= 4; j++)
  679.             RwVertex(INT2REAL(i), CREAL(0.0), INT2REAL(j));
  680.     for (i = 0; i < 8; i++)
  681.         for (j = 0; j < 8; j++)
  682.         {
  683.             if ((i ^ j) & 1)
  684.             {
  685.                 RwSetSurface(CREAL(0.5), CREAL(0.2), CREAL(0.0));
  686.                 RwSetSurfaceColor(CREAL(1.0), CREAL(0.0), CREAL(0.0));
  687.             }
  688.             else
  689.             {
  690.                 RwSetSurface(CREAL(0.5), CREAL(0.5), CREAL(0.0));
  691.                 RwSetSurfaceColor(CREAL(0.5), CREAL(0.5), CREAL(0.0));
  692.             }
  693.             RwQuad(9 + (i * 9) + j, 9 + (i * 9) + j + 1, 9 + ((i + 1) * 9) + j + 1, 9 + ((i + 1) * 9) + j);
  694.         }
  695.     RwTransformEnd();
  696.     RwClumpEnd(&temp);
  697.     RwAddHintToClump(temp, rwCONTAINER);
  698.     RwAddClumpToScene(scene, temp);
  699.  
  700.     numthings = 10;             /* number of objects */
  701.     makethings(scene, things, numthings);
  702.  
  703.     follow = 0;
  704.  
  705.     /* thunderbirds are go! */
  706.  
  707.     SetTimer(hWnd, 1, 50, NULL);
  708.  
  709.     ThreeDInitialized = TRUE;
  710.  
  711.     ShowWindow(hWnd, nCmdShow);
  712.     UpdateWindow(hWnd);
  713.  
  714.     return (TRUE);
  715. }
  716.  
  717. /**************************************************************************/
  718. void 
  719. OnSize(HWND hwnd, LPARAM lparam)
  720. {
  721.     RwInt32 width;
  722.     RwInt32 height;
  723.  
  724.     width = (RwInt32) LOWORD(lparam);
  725.     height = (RwInt32) HIWORD(lparam);
  726.     height = StatusAdjustHeight(hwnd, (int) height);
  727.  
  728.     /* Set the camera viewport to match the window's client area. */
  729.  
  730.     RwSetCameraViewport(pCamera, 0, 0, width, height);
  731.     RwGetCameraViewport(pCamera, NULL, NULL, &width, &height);
  732.  
  733.     /* Maintain the view window at a 1:1 aspect ratio. */
  734.  
  735.     if ((width != 0) && (height != 0))
  736.     {
  737.         if (width >= height)
  738.             RwSetCameraViewwindow(pCamera,
  739.                                   CREAL(0.2),
  740.                  RMul(CREAL(0.2), RDiv(INT2REAL(height), INT2REAL(width))));
  741.         else
  742.             RwSetCameraViewwindow(pCamera,
  743.                   RMul(CREAL(0.2), RDiv(INT2REAL(width), INT2REAL(height))),
  744.                                   CREAL(0.2));
  745.     }
  746.     ShowAppLeftStatus(hwnd, pCamera, "");
  747.     ShowAppRightStatus(hwnd, pCamera, "");
  748. }
  749.  
  750. long far PASCAL 
  751. MainWndProc(HWND hWnd, WORD message, WPARAM wParam, LPARAM lParam)
  752. {
  753.     HDC hDC;
  754.     PAINTSTRUCT ps;
  755.     static int x;
  756.     static int y;
  757.     static int bButtonDown = 0;
  758.     MINMAXINFO FAR *minmaxinfo;
  759.  
  760.     switch (message)
  761.     {
  762.         case WM_COMMAND:
  763.             if (LOWORD(lParam) == 0)
  764.                 HandleMenu(hWnd, wParam);
  765.             return 0L;
  766.  
  767.         case (WM_SIZE):
  768.             if (!ThreeDInitialized)
  769.                 break;
  770.             OnSize(hWnd, lParam);
  771.             break;
  772.  
  773.         case (WM_GETMINMAXINFO):
  774.             minmaxinfo = (MINMAXINFO FAR *) MK_FP32((void *) lParam);
  775.             minmaxinfo->ptMaxSize.x = MAXIMUM_WINDOW_WIDTH;
  776.             minmaxinfo->ptMaxSize.y = MAXIMUM_WINDOW_HEIGHT;
  777.             minmaxinfo->ptMaxTrackSize.x = MAXIMUM_WINDOW_WIDTH;
  778.             minmaxinfo->ptMaxTrackSize.y = MAXIMUM_WINDOW_HEIGHT;
  779.             break;
  780.         case (WM_LBUTTONDOWN):
  781.             if (!bButtonDown)
  782.             {
  783.                 SetCapture(hWnd);
  784.                 ShowAppLeftStatus(hWnd, pCamera, "Pan and Tilt Camera");
  785.             }
  786.             else
  787.                 /* both must be down */
  788.             {
  789.                 ShowAppLeftStatus(hWnd, pCamera, "Zoom Camera");
  790.             }
  791.             bButtonDown |= 1;
  792.             x = LOWORD(lParam);
  793.             y = HIWORD(lParam);
  794.             break;
  795.         case (WM_RBUTTONDOWN):
  796.             if (!bButtonDown)
  797.             {
  798.                 SetCapture(hWnd);
  799.                 ShowAppLeftStatus(hWnd, pCamera, "Pan and Zoom Camera");
  800.             }
  801.             else
  802.             {
  803.                 ShowAppLeftStatus(hWnd, pCamera, "Zoom Camera");
  804.             }
  805.             bButtonDown |= 2;
  806.             x = LOWORD(lParam);
  807.             y = HIWORD(lParam);
  808.             break;
  809.         case (WM_MOUSEMOVE):
  810.             if (bButtonDown)
  811.             {
  812.                 int dx, dy;
  813.  
  814.                 dx = ((short) LOWORD(lParam)) - x;
  815.                 dy = ((short) HIWORD(lParam)) - y;
  816.                 switch (bButtonDown)
  817.                 {
  818.                     case 1:
  819.                         {
  820.                             RwV3d at, up;
  821.  
  822.                             RwPushScratchMatrix();
  823.                             RwGetCameraLookUp(pCamera, &up);
  824.                             RwRotateMatrix(RwScratchMatrix(), up.x, up.y, up.z, INT2REAL(-dx),
  825.                                            rwREPLACE);
  826.                             RwGetCameraLookRight(pCamera, &at);
  827.                             RwRotateMatrix(RwScratchMatrix(), at.x, at.y, at.z, INT2REAL(-dy),
  828.                                            rwPOSTCONCAT);
  829.                             RwTransformCamera(pCamera, RwScratchMatrix(), rwPOSTCONCAT);
  830.                             RwPopScratchMatrix();
  831.                         }
  832.                         break;
  833.                     case 2:
  834.                         RwVCMoveCamera(pCamera, CREAL(0.0), CREAL(0.0), RDiv(INT2REAL(-dy),
  835.                                                               CREAL(50.0)));
  836.                         RwRotateMatrix(RwScratchMatrix(), CREAL(0.0), CREAL(1.0), CREAL(0.0),
  837.                                        INT2REAL(-dx), rwREPLACE);
  838.                         RwTransformCamera(pCamera, RwScratchMatrix(), rwPOSTCONCAT);
  839.                         break;
  840.                     case 3:
  841.                         RwVCMoveCamera(pCamera, CREAL(0.0), CREAL(0.0), RDiv(INT2REAL(-dy),
  842.                                                               CREAL(50.0)));
  843.                         break;
  844.                 }
  845.                 // InvalidateRect( hWnd, NULL, FALSE );
  846.                 x = (short) LOWORD(lParam);
  847.                 y = (short) HIWORD(lParam);
  848.             }
  849.             break;
  850.         case (WM_LBUTTONUP):
  851.             if (!ThreeDInitialized)
  852.                 break;
  853.             bButtonDown &= ~1;
  854.             if (!bButtonDown)
  855.             {
  856.                 ReleaseCapture();
  857.                 ShowAppLeftStatus(hWnd, pCamera, "");
  858.             }
  859.             else
  860.                 ShowAppLeftStatus(hWnd, pCamera, "Pan and Zoom Camera");
  861.             break;
  862.         case (WM_RBUTTONUP):
  863.             if (!ThreeDInitialized)
  864.                 break;
  865.             bButtonDown &= ~2;
  866.             if (!bButtonDown)
  867.             {
  868.                 ShowAppLeftStatus(hWnd, pCamera, "");
  869.                 ReleaseCapture();
  870.             }
  871.             else
  872.             {
  873.                 ShowAppLeftStatus(hWnd, pCamera, "Pan and Tilt Camera");
  874.             }
  875.             break;
  876.  
  877.         case (WM_PAINT):
  878.             if (!ThreeDInitialized)
  879.                 break;
  880.             hDC = BeginPaint(hWnd, &ps);
  881.             RwBeginCameraUpdate(pCamera, (void *) (DWORD) hWnd);
  882.             RwInvalidateCameraViewport(pCamera);
  883.             RwClearCameraViewport(pCamera);
  884.             RwRenderScene(scene);
  885.             RwEndCameraUpdate(pCamera);
  886.             RwShowCameraImage(pCamera, (void *) (DWORD) hDC);
  887.             EndPaint(hWnd, &ps);
  888.             ShowAppLeftStatus(hWnd, pCamera, "");
  889.             ShowAppRightStatus(hWnd, pCamera, "");
  890.             break;
  891.         case (WM_CHAR):
  892.             if (!ThreeDInitialized)
  893.                 break;
  894.             if (wParam >= '0' && wParam <= '9' && wParam < numthings + '0')
  895.             {
  896.                 follow = wParam - '0';
  897.             }
  898.             else if ((wParam == 't') || (wParam == 'T'))
  899.             {
  900.                 DWORD t, u;
  901.                 int i;
  902.                 char szBuf[255];
  903.  
  904.                 u = GetTickCount();
  905.                 while (u == (t = GetTickCount()));
  906.                 for (i = 0; i < 150; i++)
  907.                 {
  908.                     RwV3d vec;
  909.  
  910.                     collisions(things, numthings);
  911.                     RwGetCameraLookUp(pCamera, &vec);
  912.                     vec.x = RDiv(vec.x, CREAL(-200));
  913.                     vec.y = RDiv(vec.y, CREAL(-200));
  914.                     vec.z = RDiv(vec.z, CREAL(-200));
  915.                     gravitatethings(things, numthings, &vec);
  916.                     if (1)
  917.                     {
  918.                         RwGetClumpOrigin(things[follow].geometry, &vec);
  919.                         RwPointCamera(pCamera, vec.x, vec.y, vec.z);
  920.                         RwSetCameraLookUp(pCamera, CREAL(0.0), CREAL(1.0), CREAL(0.0));
  921.                     }
  922.                     RwBeginCameraUpdate(pCamera, (void *) (DWORD) hWnd);
  923.                     RwClearCameraViewport(pCamera);
  924.                     RwRenderScene(scene);
  925.                     hDC = GetDC(hWnd);
  926.                     RwEndCameraUpdate(pCamera);
  927.                     RwShowCameraImage(pCamera, (void *) (DWORD) hDC);
  928.                     ReleaseDC(hWnd, hDC);
  929.                 }
  930.                 u = GetTickCount();
  931.                 sprintf(szBuf, "Winsim took %lu ms for %d frames\n", u - t, i);
  932.                 MessageBox(hWnd, szBuf, "", MB_OK);
  933.             }
  934.             break;
  935.         case (WM_TIMER):
  936.             if (!ThreeDInitialized)
  937.                 break;
  938.             if (1)
  939.             {
  940.                 RwV3d vec;
  941.  
  942.                 collisions(things, numthings);
  943.                 RwGetCameraLookUp(pCamera, &vec);
  944.                 vec.x = RDiv(vec.x, CREAL(-200));
  945.                 vec.y = RDiv(vec.y, CREAL(-200));
  946.                 vec.z = RDiv(vec.z, CREAL(-200));
  947.                 gravitatethings(things, numthings, &vec);
  948.                 if (!bButtonDown)
  949.                 {
  950.                     RwGetClumpOrigin(things[follow].geometry, &vec);
  951.                     RwPointCamera(pCamera, vec.x, vec.y, vec.z);
  952.                     RwSetCameraLookUp(pCamera, CREAL(0.0), CREAL(1.0), CREAL(0.0));
  953.                 }
  954.                 RwBeginCameraUpdate(pCamera, (void *) (DWORD) hWnd);
  955.                 RwClearCameraViewport(pCamera);
  956.                 RwRenderScene(scene);
  957.                 hDC = GetDC(hWnd);
  958.                 RwEndCameraUpdate(pCamera);
  959.                 RwShowCameraImage(pCamera, (void *) (DWORD) hDC);
  960.                 ReleaseDC(hWnd, hDC);
  961.             }
  962.             break;
  963.         case (WM_DESTROY):
  964.             KillTimer(hWnd, 1);
  965.             PostQuitMessage(0);
  966.             break;
  967.         default:
  968.             return (DefWindowProc(hWnd, message, wParam, lParam));
  969.     }
  970.  
  971.     return (0L);
  972. }
  973.  
  974. int PASCAL 
  975. WinMain(HANDLE hInst, HANDLE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
  976. {
  977.     MSG msg;
  978.  
  979.     if (!InitApplication(hInst))
  980.     {
  981.         MessageBox(NULL, "n-Body simulation is already running...",
  982.                    ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
  983.         return (FALSE);
  984.     }
  985.  
  986.     if (!InitInstance(hInst, nCmdShow))
  987.     {
  988.         return (FALSE);
  989.     }
  990.  
  991.     while (GetMessage(&msg, (HWND) NULL, (UINT) NULL, (UINT) NULL))
  992.     {
  993.         TranslateMessage(&msg);
  994.         DispatchMessage(&msg);
  995.     }
  996.  
  997.     RwDestroyCamera(pCamera);
  998.     RwDestroyLight(pLight);
  999.     while (numthings--)
  1000.         RwDestroyClump(things[numthings].geometry);
  1001.     RwDestroyScene(scene);
  1002.  
  1003.     RwClose();
  1004.  
  1005.     UnregisterClass("RwNBodyWndClass", hInst);
  1006.     return (msg.wParam);
  1007. }
  1008.