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

  1. /**********************************************************************
  2.  *
  3.  * File :     rwvis.c
  4.  *
  5.  * Abstract : RenderWare visualisation demo
  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.  
  26. /*----    Include files    ---*/
  27. #define INCLUDE_SHELLAPI_H
  28. #include <windows.h>
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <stdarg.h>
  32. #include <string.h>
  33. #include <math.h>
  34.  
  35. #include "rwlib.h"
  36. #include "status.h"
  37. #include "common.h"
  38.  
  39. /*---    Macro Definitions    ---*/
  40.  
  41. #ifndef __WINDOWS_386__
  42. #define MK_FP32(x) (x)          /* not using Watcom */
  43. #endif
  44.  
  45. #define RWAPPNAME "Renderware Visualisation Demo"
  46.  
  47. #define MAX_WIN_WIDTH     512
  48. #define MAX_WIN_HEIGHT     512
  49.  
  50. #define DEFAULT_X SIN
  51. #define DEFAULT_Y COS
  52. #define DEFAULT_Z XADDY
  53. #define DEFAULT_R R_8
  54. #define DEFAULT_S S_SMOOTH
  55. #define DEFAULT_T T_MANDEL
  56.  
  57. #define X_MBASE 1
  58. #define Y_MBASE (X_MBASE + 10)
  59. #define Z_MBASE (Y_MBASE + 10)
  60. #define M_MBASE (Z_MBASE + 10)
  61. #define R_MBASE (M_MBASE + 10)
  62. #define S_MBASE (R_MBASE + 10)
  63. #define T_MBASE (S_MBASE + 10)
  64. #define H_MBASE (T_MBASE + 10)
  65.  
  66. #define MAX_RESOLUTION 16
  67. #define MAX_CLUMP_VERTICES (MAX_RESOLUTION * MAX_RESOLUTION + 10 * MAX_RESOLUTION + 13)
  68. #define MAX_POLY_VERTICES (MAX_RESOLUTION + 3)
  69. #define CUBE_DIMENSION 4.0
  70.  
  71. /*---    Type Definitions    ---*/
  72.  
  73. typedef enum
  74. {
  75.     S_FLAT,
  76.     S_SMOOTH
  77. }
  78. EnShading;
  79.  
  80. typedef enum
  81. {
  82.     H_ABOUT
  83. }
  84. EnHelp;
  85.  
  86. typedef enum
  87. {
  88.     T_NONE,
  89.     T_WOOD,
  90.     T_BRICK,
  91.     T_MARBLE,
  92.     T_MANDEL,
  93.     T_MANDRILL,
  94. }
  95. EnTexture;
  96.  
  97. typedef enum
  98. {
  99.     R_4,
  100.     R_8,
  101.     R_16
  102. }
  103. EnResolution;
  104.  
  105. typedef enum
  106. {
  107.     ZERO,
  108.     RAMP,
  109.     SIN,
  110.     COS,
  111.     SQUARED,
  112.     CUBED,
  113.     MAX_FUNC
  114. }
  115. EnFunc;
  116.  
  117. typedef enum
  118. {
  119.     XMULY,
  120.     XSUBY,
  121.     XADDY,
  122.     MAX_ZFUNC
  123. }
  124. EnZFunc;
  125.  
  126. typedef struct
  127. {
  128.     BOOL flag;
  129.     RwMatrix4d *m;
  130.     RwInt32 dx;
  131.     RwInt32 dy;
  132. }
  133. TyRot;
  134.  
  135. /*---    Global Variable Definitions    ---*/
  136.  
  137. RwLight *Light;
  138. char *TextureNames[] =
  139. {
  140.     NULL,
  141.     "wood008.bmp",
  142.     "stone002.bmp",
  143.     "stone004.bmp",
  144.     "mandel.bmp",
  145.     "mandrill.bmp"
  146. };                              /* must match order of EnTexture */
  147.  
  148. TyRot Rot;
  149.  
  150. EnFunc Xfunc = DEFAULT_X;
  151. EnFunc Yfunc = DEFAULT_Y;
  152. EnZFunc Zfunc = DEFAULT_Z;
  153.  
  154. EnShading Shading = DEFAULT_S;
  155. EnTexture Texture = DEFAULT_T;
  156.  
  157. HMENU Mainmenu;
  158. HINSTANCE Hinstance;
  159. RwCamera *Camera;
  160. BOOL lb = FALSE;
  161. BOOL rb = FALSE;
  162. RwInt32 Xprev;
  163. RwInt32 Yprev;
  164.  
  165. RwClump *Clump = NULL;
  166.  
  167. RwInt32 Resolution;
  168. RwInt32 Vertices;
  169. RwReal Costab[MAX_RESOLUTION + 1];
  170. RwReal Sintab[MAX_RESOLUTION + 1];
  171. RwV3d Vval[MAX_CLUMP_VERTICES];
  172. RwInt32 Vindex[MAX_CLUMP_VERTICES];
  173. int Fnoffset;
  174. RwReal Fn[512];
  175. BOOL Membrane = FALSE;
  176.  
  177. /**************************************************************************
  178.     About Dialogue Box Stuff
  179. **************************************************************************/
  180. void 
  181. DlgDrawItem(DRAWITEMSTRUCT FAR * dis)
  182. {
  183.     HDC hdcMemory;
  184.     HBITMAP hbmplogo, hbmpOld;
  185.     BITMAP bm;
  186.  
  187.     hbmplogo = LoadBitmap(Hinstance, "CRITERION_LOGO");
  188.     GetObject(hbmplogo, sizeof (BITMAP), &bm);
  189.  
  190.     hdcMemory = CreateCompatibleDC(dis->hDC);
  191.     hbmpOld = SelectObject(hdcMemory, hbmplogo);
  192.  
  193.     BitBlt(dis->hDC, dis->rcItem.left, dis->rcItem.top,
  194.            dis->rcItem.right - dis->rcItem.left,
  195.            dis->rcItem.bottom - dis->rcItem.top,
  196.            hdcMemory, 0, 0, SRCCOPY);
  197.  
  198.     SelectObject(hdcMemory, hbmpOld);
  199.     DeleteDC(hdcMemory);
  200.     DeleteObject(hbmplogo);
  201. }
  202.  
  203. BOOL FAR PASCAL 
  204. AboutDlgProc(HWND hDlg, WORD message, WORD wParam, LONG lParam)
  205. {
  206.     switch (message)
  207.     {
  208.         case WM_INITDIALOG:
  209.             return TRUE;
  210.  
  211.         case WM_COMMAND:
  212.             switch (wParam)
  213.             {
  214.                 case IDOK:
  215.                 case IDCANCEL:
  216.                     EndDialog(hDlg, 0);
  217.                     return (TRUE);
  218.             }
  219.             break;
  220.  
  221.         case WM_DRAWITEM:
  222.             DlgDrawItem((DRAWITEMSTRUCT FAR *) MK_FP32((void *) lParam));
  223.             return (TRUE);
  224.     }
  225.     return (FALSE);
  226. }
  227. /***************************************************************************
  228.     Build Internal Sin & Cos tables
  229. ***************************************************************************/
  230. void 
  231. BuildSinCosTab(void)
  232. {
  233.     int i;
  234.  
  235.     for (i = 0; i <= MAX_RESOLUTION; i++)
  236.     {
  237.         Sintab[i] = FL2REAL(sin(i * 6.283 / (float) MAX_RESOLUTION));
  238.         Costab[i] = FL2REAL(cos(i * 6.283 / (float) MAX_RESOLUTION));
  239.     }
  240. }
  241.  
  242. /***************************************************************************
  243.     Display Informational Text
  244. ***************************************************************************/
  245. void 
  246. ShowInfo(HWND hwnd)
  247. {
  248.     char str[32];
  249.  
  250.     if (Membrane)
  251.     {
  252.         sprintf(str, "Membrane");
  253.     }
  254.     else
  255.     {
  256.         sprintf(str, "z = ");
  257.         switch (Xfunc)
  258.         {
  259.             case ZERO:
  260.                 strcat(str, "0 ");
  261.                 break;
  262.             case RAMP:
  263.                 strcat(str, "x ");
  264.                 break;
  265.             case SIN:
  266.                 strcat(str, "sin(x) ");
  267.                 break;
  268.             case COS:
  269.                 strcat(str, "cos(x) ");
  270.                 break;
  271.             case SQUARED:
  272.                 strcat(str, "(x^2) ");
  273.                 break;
  274.             case CUBED:
  275.                 strcat(str, "(x^3) ");
  276.                 break;
  277.         }
  278.         switch (Zfunc)
  279.         {
  280.             case XMULY:
  281.                 strcat(str, "* ");
  282.                 break;
  283.             case XADDY:
  284.                 strcat(str, "+ ");
  285.                 break;
  286.             case XSUBY:
  287.                 strcat(str, "- ");
  288.                 break;
  289.         }
  290.         switch (Yfunc)
  291.         {
  292.             case ZERO:
  293.                 strcat(str, "0");
  294.                 break;
  295.             case RAMP:
  296.                 strcat(str, "y");
  297.                 break;
  298.             case SIN:
  299.                 strcat(str, "sin(y)");
  300.                 break;
  301.             case COS:
  302.                 strcat(str, "cos(y)");
  303.                 break;
  304.             case SQUARED:
  305.                 strcat(str, "(y^2)");
  306.                 break;
  307.             case CUBED:
  308.                 strcat(str, "(y^3)");
  309.                 break;
  310.         }
  311.     }
  312.     ShowAppRightStatus(hwnd, Camera, str);
  313. }
  314.  
  315. /***************************************************************************
  316.     Set polygon data field to indicate if it forms the box or the surface
  317. ***************************************************************************/
  318. RwPolygon3d *
  319. SetPolygonData(RwPolygon3d * p)
  320. {
  321.     RwInt32 varray[MAX_POLY_VERTICES];
  322.  
  323.     RwGetPolygonVertices(p, varray);
  324.     if (Membrane)
  325.     {
  326.         if (varray[0] <= Vertices)
  327.             RwSetPolygonData(p, varray);
  328.         else
  329.             RwSetPolygonData(p, NULL);
  330.     }
  331.     else
  332.     {
  333.         if (varray[0] <= (Resolution + 1) * (Resolution + 1))
  334.             RwSetPolygonData(p, varray);
  335.         else
  336.             RwSetPolygonData(p, NULL);
  337.     }
  338.     return (p);
  339. }
  340.  
  341. /***************************************************************************
  342.     GeneratePoints
  343. ***************************************************************************/
  344. void 
  345. GeneratePoints(void)
  346. {
  347.     RwReal temp, *xval, yval;
  348.     int x, y, v;
  349.     RwReal xyscale, xyoffset, zscale;
  350.  
  351.     xyscale = RDiv(CREAL(CUBE_DIMENSION), INT2REAL(Resolution));
  352.     xyoffset = -RMul(CREAL(CUBE_DIMENSION), CREAL(0.5));
  353.     zscale = RMul(CREAL(CUBE_DIMENSION), CREAL(0.25));
  354.  
  355.     xval = (RwReal *)malloc(sizeof (RwReal) * (Resolution + 1L));
  356.  
  357. /*---    Build Grid of Z values    ---*/
  358.  
  359.     v = 0;
  360.     for (x = 0; x <= Resolution; x++)
  361.     {
  362.         switch (Xfunc)
  363.         {
  364.             case ZERO:
  365.                 xval[x] = CREAL(0.0);
  366.                 break;
  367.             case RAMP:
  368.                 xval[x] = RDiv(INT2REAL(x - Resolution / 2), INT2REAL(Resolution / 2));
  369.                 break;
  370.             case SIN:
  371.                 xval[x] = Sintab[(int)((x % Resolution) * MAX_RESOLUTION / Resolution)];
  372.                 break;
  373.             case COS:
  374.                 xval[x] = Costab[(int)((x % Resolution) * MAX_RESOLUTION / Resolution)];
  375.                 break;
  376.             case SQUARED:
  377.                 temp = RDiv(INT2REAL(x - Resolution / 2), INT2REAL(Resolution / 2));
  378.                 xval[x] = RMul(temp, temp);
  379.                 break;
  380.             case CUBED:
  381.                 temp = RDiv(INT2REAL(x - Resolution / 2), INT2REAL(Resolution / 2));
  382.                 xval[x] = RMul(temp, RMul(temp, temp));
  383.                 break;
  384.         }
  385.     }
  386.     for (y = 0; y <= Resolution; y++)
  387.     {
  388.         switch (Yfunc)
  389.         {
  390.             case ZERO:
  391.                 yval = CREAL(0.0);
  392.                 break;
  393.             case RAMP:
  394.                 yval = RDiv(INT2REAL(y - Resolution / 2), INT2REAL(Resolution / 2));
  395.                 break;
  396.             case SIN:
  397.                 yval = Sintab[(int)((y % Resolution) * MAX_RESOLUTION / Resolution)];
  398.                 break;
  399.             case COS:
  400.                 yval = Costab[(int)((y % Resolution) * MAX_RESOLUTION / Resolution)];
  401.                 break;
  402.             case SQUARED:
  403.                 temp = RDiv(INT2REAL(y - Resolution / 2), INT2REAL(Resolution / 2));
  404.                 yval = RMul(temp, temp);
  405.                 break;
  406.             case CUBED:
  407.                 temp = RDiv(INT2REAL(y - Resolution / 2), INT2REAL(Resolution / 2));
  408.                 yval = RMul(temp, RMul(temp, temp));
  409.                 break;
  410.         }
  411.         for (x = 0; x <= Resolution; x++)
  412.         {
  413.             Vval[v].x = RAdd(xyoffset, RMul(xyscale, INT2REAL(x)));
  414.             Vval[v].y = RAdd(xyoffset, RMul(xyscale, INT2REAL(y)));
  415.             switch (Zfunc)
  416.             {
  417.                 case XMULY:
  418.                     Vval[v++].z = RMul(zscale, RMul(xval[x], yval));
  419.                     break;
  420.                 case XADDY:
  421.                     Vval[v++].z = RMul(zscale, RAdd(xval[x], yval));
  422.                     break;
  423.                 case XSUBY:
  424.                     Vval[v++].z = RMul(zscale, RSub(xval[x], yval));
  425.                     break;
  426.             }
  427.         }
  428.     }
  429.     free(xval);
  430.  
  431. /*---    Remaining vertices form box    ---*/
  432.  
  433.     /* first the base */
  434.  
  435.     y = v;
  436.     Vval[v].x = xyoffset;
  437.     Vval[v].y = xyoffset;
  438.     Vval[v++].z = CREAL(-(CUBE_DIMENSION / 2.0 + 0.1));
  439.  
  440.     Vval[v].x = xyoffset;
  441.     Vval[v].y = -xyoffset;
  442.     Vval[v++].z = CREAL(-(CUBE_DIMENSION / 2.0 + 0.1));
  443.  
  444.     Vval[v].x = -xyoffset;
  445.     Vval[v].y = -xyoffset;
  446.     Vval[v++].z = CREAL(-(CUBE_DIMENSION / 2.0 + 0.1));
  447.  
  448.     Vval[v].x = -xyoffset;
  449.     Vval[v].y = xyoffset;
  450.     Vval[v++].z = CREAL(-(CUBE_DIMENSION / 2.0 + 0.1));
  451.  
  452.     /* then the sides */
  453.     for (x = 0; x <= Resolution; x++)
  454.     {
  455.         Vval[v + 1] = Vval[(int)(x * (Resolution + 1))];
  456.         Vval[v] = Vval[v + 1];
  457.         Vval[v].z = CREAL(-(CUBE_DIMENSION / 2.0 + 0.1));
  458.         v += 2;
  459.     }
  460.     for (x = 0; x <= Resolution; x++)
  461.     {
  462.         Vval[v + 1] = Vval[(int)(((Resolution + 1) * (Resolution)) + x)];
  463.         Vval[v] = Vval[v + 1];
  464.         Vval[v].z = CREAL(-(CUBE_DIMENSION / 2.0 + 0.1));
  465.         v += 2;
  466.     }
  467.     for (x = 0; x <= Resolution; x++)
  468.     {
  469.         Vval[v + 1] = Vval[(int)((Resolution + 1 - x) * (Resolution + 1) - 1)];
  470.         Vval[v] = Vval[v + 1];
  471.         Vval[v].z = CREAL(-(CUBE_DIMENSION / 2.0 + 0.1));
  472.         v += 2;
  473.     }
  474.     for (x = 0; x <= Resolution; x++)
  475.     {
  476.         Vval[v + 1] = Vval[(int)(Resolution - x)];
  477.         Vval[v] = Vval[v + 1];
  478.         Vval[v].z = CREAL(-(CUBE_DIMENSION / 2.0 + 0.1));
  479.         v += 2;
  480.     }
  481.     Vertices = v;
  482. }
  483.  
  484. /***************************************************************************
  485.     Move Sheet
  486. ***************************************************************************/
  487. void 
  488. MoveSheet()
  489. {
  490.     RwInt32 i, j, k;
  491.  
  492.     k = (Resolution + 1) * Resolution;
  493.  
  494.     for (i = Resolution + 1; i < k; i += (Resolution + 1))
  495.         for (j = 1; j < Resolution; j++)
  496.         {
  497.             Vval[(int)(i + j)].z = Fn[(int)(((Fnoffset + (i / Resolution) + j) & 7) << 6)];
  498.         }
  499.     RwSetClumpVertices(Clump, Vindex, Vval, Vertices);
  500.  
  501.     Fnoffset++;
  502. }
  503.  
  504. /***************************************************************************
  505.     BuildSheet
  506. ***************************************************************************/
  507. void 
  508. BuildSheet(void)
  509. {
  510.     RwUV uv;
  511.     RwInt32 i, j, v;
  512.     RwInt32 box[20];
  513.     RwReal xyscale, xyoffset;
  514.  
  515.     xyscale = RDiv(CREAL(CUBE_DIMENSION), INT2REAL(Resolution));
  516.     xyoffset = -RMul(CREAL(CUBE_DIMENSION), CREAL(0.5));
  517.  
  518.     if (Clump)
  519.         RwDestroyClump(Clump);
  520.  
  521.     RwModelBegin();
  522.     RwClumpBegin();
  523.  
  524.     RwSetHints(rwHS | rwEDITABLE);
  525.     switch (Shading)
  526.     {
  527.         case S_FLAT:
  528.             RwSetSurfaceLightSampling(rwFACET);
  529.             break;
  530.         case S_SMOOTH:
  531.             RwSetSurfaceLightSampling(rwVERTEX);
  532.             break;
  533.     }
  534.     RwSetSurfaceTexture(TextureNames[Texture]);
  535.     RwSetSurface(CREAL(0.3), CREAL(0.6), CREAL(0.3));
  536.     RwSetSurfaceColor(CREAL(1.0), CREAL(0.0), CREAL(0.0));
  537.  
  538.     for (i = 0; i <= Resolution; i++)
  539.     {
  540.         for (j = 0; j <= Resolution; j++)
  541.         {
  542.                 Vval[(int)(i * (Resolution + 1) + j)].x = RAdd(xyoffset, RMul(xyscale, INT2REAL(i)));
  543.                 Vval[(int)(i * (Resolution + 1) + j)].y = RAdd(xyoffset, RMul(xyscale, INT2REAL(j)));
  544.                 Vval[(int)(i * (Resolution + 1) + j)].z = CREAL(0.0);
  545.                 uv.u = (RDiv(INT2REAL(j), INT2REAL(Resolution)));
  546.             uv.v = (RDiv(INT2REAL(i), INT2REAL(Resolution)));
  547.                 v = RwVertexExt(Vval[(int)(i * (Resolution + 1) + j)].x,
  548.                                      Vval[(int)(i * (Resolution + 1) + j)].y,
  549.                                      Vval[(int)(i * (Resolution + 1) + j)].z, &uv, NULL);
  550.         }
  551.     }
  552.     Vertices = v;
  553.     box[0] = RwVertex(xyoffset, -xyoffset, CREAL(-(CUBE_DIMENSION / 2.0 + 0.1)));
  554.     box[1] = RwVertex(-xyoffset, -xyoffset, CREAL(-(CUBE_DIMENSION / 2.0 + 0.1)));
  555.     box[2] = RwVertex(-xyoffset, -xyoffset, CREAL(-0.01));
  556.     box[3] = RwVertex(xyoffset, -xyoffset, CREAL(-0.01));
  557.  
  558.     box[4] = RwVertex(-xyoffset, xyoffset, CREAL(-(CUBE_DIMENSION / 2.0 + 0.1)));
  559.     box[5] = RwVertex(xyoffset, xyoffset, CREAL(-(CUBE_DIMENSION / 2.0 + 0.1)));
  560.     box[6] = RwVertex(xyoffset, xyoffset, CREAL(-0.01));
  561.     box[7] = RwVertex(-xyoffset, xyoffset, CREAL(-0.01));
  562.  
  563.     box[8] = RwVertex(-xyoffset, -xyoffset, CREAL(-(CUBE_DIMENSION / 2.0 + 0.1)));
  564.     box[9] = RwVertex(-xyoffset, xyoffset, CREAL(-(CUBE_DIMENSION / 2.0 + 0.1)));
  565.     box[10] = RwVertex(-xyoffset, xyoffset, CREAL(-0.01));
  566.     box[11] = RwVertex(-xyoffset, -xyoffset, CREAL(-0.01));
  567.  
  568.     box[12] = RwVertex(xyoffset, xyoffset, CREAL(-(CUBE_DIMENSION / 2.0 + 0.1)));
  569.     box[13] = RwVertex(xyoffset, -xyoffset, CREAL(-(CUBE_DIMENSION / 2.0 + 0.1)));
  570.     box[14] = RwVertex(xyoffset, -xyoffset, CREAL(-0.01));
  571.     box[15] = RwVertex(xyoffset, xyoffset, CREAL(-0.01));
  572.  
  573.     box[16] = RwVertex(-xyoffset, xyoffset, CREAL(-(CUBE_DIMENSION / 2.0 + 0.1)));
  574.     box[17] = RwVertex(-xyoffset, -xyoffset, CREAL(-(CUBE_DIMENSION / 2.0 + 0.1)));
  575.     box[18] = RwVertex(xyoffset, -xyoffset, CREAL(-(CUBE_DIMENSION / 2.0 + 0.1)));
  576.     box[19] = RwVertex(xyoffset, xyoffset, CREAL(-(CUBE_DIMENSION / 2.0 + 0.1)));
  577.  
  578.     for (i = 0; i <= Resolution - 1; i++)
  579.         for (j = 0; j <= Resolution - 1; j++)
  580.         {
  581.             RwQuad(i * (Resolution + 1) + j + 1,
  582.                    (i + 1) * (Resolution + 1) + j + 1,
  583.                    (i + 1) * (Resolution + 1) + j + 2,
  584.                    i * (Resolution + 1) + j + 2);
  585.         }
  586.     RwSetSurfaceTexture(NULL);
  587.     RwSetSurfaceColor(CREAL(0.2), CREAL(0.2), CREAL(0.2));
  588.     RwSetSurfaceLightSampling(rwFACET);
  589.     RwQuad(box[0], box[3], box[2], box[1]);
  590.     RwQuad(box[4], box[7], box[6], box[5]);
  591.     RwQuad(box[8], box[11], box[10], box[9]);
  592.     RwQuad(box[12], box[15], box[14], box[13]);
  593.     RwQuad(box[16], box[19], box[18], box[17]);
  594.     RwClumpEnd(&Clump);
  595.     RwForAllPolygonsInClump(Clump, SetPolygonData);
  596.     MoveSheet();
  597. }
  598.  
  599. /***************************************************************************
  600.     BuildClump
  601. ***************************************************************************/
  602. void 
  603. BuildClump(void)
  604. {
  605.     RwUV uv;
  606.     RwInt32 x, y;
  607.     RwInt32 v;
  608.  
  609.     if (Clump)
  610.         RwDestroyClump(Clump);
  611.  
  612.     GeneratePoints();
  613.  
  614.     RwModelBegin();
  615.     RwClumpBegin();
  616.     RwSetHints(rwHS | rwEDITABLE);
  617.     switch (Shading)
  618.     {
  619.         case S_FLAT:
  620.             RwSetSurfaceLightSampling(rwFACET);
  621.             break;
  622.         case S_SMOOTH:
  623.             RwSetSurfaceLightSampling(rwVERTEX);
  624.             break;
  625.     }
  626.     RwSetSurfaceTexture(TextureNames[Texture]);
  627.     RwSetSurface(CREAL(0.3), CREAL(0.6), CREAL(0.3));
  628.     RwSetSurfaceColor(CREAL(0.0), CREAL(0.0), CREAL(1.0));
  629.  
  630.     for (y = 0; y <= Resolution; y++)
  631.     {
  632.         for (x = 0; x <= Resolution; x++)
  633.         {
  634.             uv.u = (RDiv(INT2REAL(x), INT2REAL(Resolution)));
  635.             uv.v = (RDiv(INT2REAL(y), INT2REAL(Resolution)));
  636.                 v = RwVertexExt(Vval[(int)(y * (Resolution + 1) + x)].x,
  637.                                      Vval[(int)(y * (Resolution + 1) + x)].y,
  638.                                      Vval[(int)(y * (Resolution + 1) + x)].z, &uv, NULL);
  639.           }
  640.     }
  641.     for (; v < Vertices; v++)
  642.     {
  643.         RwVertex(Vval[(int)v].x, Vval[(int)v].y, Vval[(int)v].z);
  644.     }
  645.  
  646.     for (y = 0; y < Resolution; y++)
  647.     {
  648.         for (x = 0; x < Resolution; x++)
  649.         {
  650.             RwInt32 tl, bl;
  651.  
  652.             bl = y * (Resolution + 1) + 1 + x;
  653.             tl = bl + (Resolution + 1);
  654.             RwQuad(tl, bl, bl + 1, tl + 1);
  655.         }
  656.     }
  657.  
  658.     /* Construct Box */
  659.  
  660.     RwSetSurfaceTexture(NULL);
  661.     RwSetSurfaceColor(CREAL(0.2), CREAL(0.2), CREAL(0.2));
  662.     RwSetSurfaceLightSampling(rwFACET);
  663.  
  664.     v = (Resolution + 1) * (Resolution + 1) + 1;
  665.     RwQuad(v, v + 1, v + 2, v + 3);
  666.     v += 4;
  667.  
  668.     /* Construct sides */
  669.  
  670.     for (y = 0; y < 4; y++)
  671.     {
  672.         for (x = 0; x < Resolution; x++)
  673.         {
  674.             RwQuad(v, v + 1, v + 3, v + 2);
  675.             v += 2;
  676.         }
  677.         v += 2;
  678.     }
  679.     RwClumpEnd(&Clump);
  680.     RwModelEnd();
  681.  
  682.     RwForAllPolygonsInClump(Clump, SetPolygonData);
  683. }
  684.  
  685. /**************************************************************************
  686.     Change Resolution 
  687. **************************************************************************/
  688. void 
  689. SetResolution(EnResolution ren)
  690. {
  691.     static EnResolution r = -1;
  692.  
  693.     CheckMenuItem(Mainmenu, R_MBASE + r, MF_UNCHECKED);
  694.     switch (ren)
  695.     {
  696.         case R_4:
  697.             Resolution = 4;
  698.             break;
  699.         case R_8:
  700.             Resolution = 8;
  701.             break;
  702.         case R_16:
  703.             Resolution = 16;
  704.             break;
  705.     }
  706.     if (r != ren)               /* new resolution */
  707.     {
  708.         if (Membrane)
  709.             BuildSheet();
  710.         else
  711.             BuildClump();
  712.     }
  713.     r = ren;
  714.     CheckMenuItem(Mainmenu, R_MBASE + r, MF_CHECKED);
  715. }
  716.  
  717. /**************************************************************************
  718.     Change Polygon shading if it forms the main surface
  719. **************************************************************************/
  720. RwPolygon3d *
  721. SetPolygonTexture(RwPolygon3d * p, RwTexture * t)
  722. {
  723.     if (RwGetPolygonData(p))
  724.     {
  725.         RwSetMaterialTexture(RwGetPolygonMaterial(p), t);
  726.     }
  727.     return (p);
  728. }
  729.  
  730. /**************************************************************************
  731.     Change Polygon shading if it forms the main surface
  732. **************************************************************************/
  733. RwPolygon3d *
  734. SetPolygonShading(RwPolygon3d * p)
  735. {
  736.     if (RwGetPolygonData(p))
  737.     {
  738.         switch (Shading)
  739.         {
  740.             case S_FLAT:
  741.                 RwSetMaterialLightSampling(RwGetPolygonMaterial(p), rwFACET);
  742.                 break;
  743.             case S_SMOOTH:
  744.                 RwSetMaterialLightSampling(RwGetPolygonMaterial(p), rwVERTEX);
  745.                 break;
  746.         }
  747.     }
  748.     return (p);
  749. }
  750.  
  751. /**************************************************************************
  752.     Change Texture
  753. **************************************************************************/
  754. void 
  755. SetTexture(EnTexture t)
  756. {
  757.     RwTexture *tex;
  758.  
  759.     CheckMenuItem(Mainmenu, T_MBASE + Texture, MF_UNCHECKED);
  760.     if (Texture != t)
  761.     {
  762.         Texture = t;
  763.         if (Clump)
  764.         {
  765.             switch (t)
  766.             {
  767.                 case T_NONE:
  768.                     tex = NULL;
  769.                     break;
  770.                 default:
  771.                     tex = RwGetNamedTexture(TextureNames[t]);
  772.                     break;
  773.             }
  774.                 RwForAllPolygonsInClumpPointer(Clump,
  775.                     (RwPolygon3dFuncPointer)SetPolygonTexture, tex);
  776.         }
  777.     }
  778.     CheckMenuItem(Mainmenu, T_MBASE + Texture, MF_CHECKED);
  779. }
  780.  
  781. /**************************************************************************
  782.     Change Shading
  783. **************************************************************************/
  784. void 
  785. SetShading(EnShading s)
  786. {
  787.     CheckMenuItem(Mainmenu, S_MBASE + Shading, MF_UNCHECKED);
  788.     if (Shading != s)
  789.     {
  790.         Shading = s;
  791.         if (Clump)
  792.         {
  793.             RwForAllPolygonsInClump(Clump, SetPolygonShading);
  794.         }
  795.     }
  796.     CheckMenuItem(Mainmenu, S_MBASE + Shading, MF_CHECKED);
  797. }
  798.  
  799. /**************************************************************************
  800.     Invoke a help function
  801. **************************************************************************/
  802. void 
  803. SetHelp(HWND hwnd, EnHelp h)
  804. {
  805.     switch (h)
  806.     {
  807.         case H_ABOUT:
  808.             KillTimer(hwnd, 1);
  809.             DialogBox(Hinstance, "ABOUT", hwnd, MakeProcInstance(AboutDlgProc, Hinstance));
  810.             SetTimer(hwnd, 1, 50, NULL);
  811.             break;
  812.     }
  813. }
  814.  
  815. /**************************************************************************
  816.     Turn membrane on/off
  817. **************************************************************************/
  818. void 
  819. SetMembrane(void)
  820. {
  821.     CheckMenuItem(Mainmenu, M_MBASE, MF_UNCHECKED);
  822.     if (Membrane)               /* currently on - turn it off */
  823.     {
  824.         Membrane = FALSE;
  825.         BuildClump();
  826.     }
  827.     else
  828.     {
  829.         Membrane = TRUE;
  830.         BuildSheet();
  831.         CheckMenuItem(Mainmenu, M_MBASE, MF_CHECKED);
  832.     }
  833. }
  834. /**************************************************************************
  835.     Change X function 
  836. **************************************************************************/
  837. void 
  838. SetX(EnFunc x)
  839. {
  840.     CheckMenuItem(Mainmenu, X_MBASE + Xfunc, MF_UNCHECKED);
  841.     if (Membrane)
  842.     {
  843.         SetMembrane();
  844.     }
  845.     if (Xfunc != x)
  846.     {
  847.         Xfunc = x;
  848.         GeneratePoints();
  849.         RwSetClumpVertices(Clump, Vindex, Vval, Vertices);
  850.     }
  851.     CheckMenuItem(Mainmenu, X_MBASE + Xfunc, MF_CHECKED);
  852. }
  853.  
  854. /**************************************************************************
  855.     Change Y function 
  856. **************************************************************************/
  857. void 
  858. SetY(EnFunc y)
  859. {
  860.     CheckMenuItem(Mainmenu, Y_MBASE + Yfunc, MF_UNCHECKED);
  861.     if (Membrane)
  862.     {
  863.         SetMembrane();
  864.     }
  865.     if (Yfunc != y)
  866.     {
  867.         Yfunc = y;
  868.         GeneratePoints();
  869.         RwSetClumpVertices(Clump, Vindex, Vval, Vertices);
  870.     }
  871.     CheckMenuItem(Mainmenu, Y_MBASE + Yfunc, MF_CHECKED);
  872. }
  873.  
  874. /**************************************************************************
  875.     Change Z function 
  876. **************************************************************************/
  877. void 
  878. SetZ(EnZFunc z)
  879. {
  880.     CheckMenuItem(Mainmenu, Z_MBASE + Zfunc, MF_UNCHECKED);
  881.     if (Membrane)
  882.     {
  883.         SetMembrane();
  884.     }
  885.     if (Zfunc != z)
  886.     {
  887.         Zfunc = z;
  888.         GeneratePoints();
  889.         RwSetClumpVertices(Clump, Vindex, Vval, Vertices);
  890.     }
  891.     CheckMenuItem(Mainmenu, Z_MBASE + Zfunc, MF_CHECKED);
  892. }
  893.  
  894. /**************************************************************************
  895.     Display Image
  896. **************************************************************************/
  897. void 
  898. ShowView(HWND hwnd)
  899. {
  900.     HDC hdc;
  901.  
  902.     RwBeginCameraUpdate(Camera, (void *)(DWORD)hwnd);
  903.     RwClearCameraViewport(Camera);
  904.     if (Clump)
  905.     {
  906.         RwTransformClump(Clump, Rot.m, rwREPLACE);
  907.         RwRenderClump(Clump);
  908.     }
  909.     RwEndCameraUpdate(Camera);
  910.  
  911.     hdc = GetDC(hwnd);
  912.     RwShowCameraImage(Camera, (void *)(DWORD)hdc);
  913.     ReleaseDC(hwnd, hdc);
  914. }
  915.  
  916. /**************************************************************************
  917.     Process WM_GETMINMAXINFO messages
  918. **************************************************************************/
  919. void 
  920. OnGetMinMaxInfo(MINMAXINFO FAR * minmaxinfo)
  921. {
  922.     minmaxinfo->ptMaxSize.x = MAX_WIN_WIDTH;
  923.     minmaxinfo->ptMaxSize.y = MAX_WIN_HEIGHT;
  924.     minmaxinfo->ptMaxTrackSize.x = MAX_WIN_WIDTH;
  925.     minmaxinfo->ptMaxTrackSize.y = MAX_WIN_HEIGHT;
  926. }
  927. /**************************************************************************
  928.     Process WM_COMMAND messages
  929. **************************************************************************/
  930. void 
  931. OnCommand(HWND hwnd, WPARAM wparam)
  932. {
  933.     HCURSOR save_cursor;
  934.  
  935.     save_cursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  936.  
  937.     if (wparam < Y_MBASE)
  938.         SetX(wparam - X_MBASE);
  939.     else if (wparam < Z_MBASE)
  940.         SetY(wparam - Y_MBASE);
  941.     else if (wparam < M_MBASE)
  942.         SetZ(wparam - Z_MBASE);
  943.     else if (wparam < R_MBASE)
  944.         SetMembrane();
  945.     else if (wparam < S_MBASE)
  946.         SetResolution(wparam - R_MBASE);
  947.     else if (wparam < T_MBASE)
  948.         SetShading(wparam - S_MBASE);
  949.     else if (wparam < H_MBASE)
  950.         SetTexture(wparam - T_MBASE);
  951.     else
  952.         SetHelp(hwnd, wparam - H_MBASE);
  953.  
  954.     SetCursor(save_cursor);
  955. }
  956.  
  957. /**************************************************************************
  958.     Process WM_CREATE messages
  959. **************************************************************************/
  960. LONG 
  961. OnCreate(HWND hwnd)
  962. {
  963.     char str[64];
  964.     int i;
  965.  
  966. /*---    Create the light    ---*/
  967.  
  968.     if (!(Light = RwCreateLight(rwDIRECTIONAL,
  969.                          CREAL(0.0), CREAL(-1.0), CREAL(-1.0), CREAL(1.0))))
  970.     {
  971.         MessageBox(hwnd, "Error creating a RenderWare light",
  972.                    "Renderware Error", MB_OK | MB_ICONSTOP | MB_APPLMODAL);
  973.         return (-1);
  974.     }
  975.  
  976. /*---    Create the camera.    ---*/
  977.  
  978.     if (!(Camera = RwCreateCamera((RwInt32)MAX_WIN_WIDTH, (RwInt32)MAX_WIN_HEIGHT, NULL)))
  979.     {
  980.         MessageBox(hwnd, "Error creating a RenderWare camera",
  981.                    "Renderware Error", MB_OK | MB_ICONSTOP | MB_APPLMODAL);
  982.         return (-1);
  983.     }
  984.     RwVCMoveCamera(Camera, CREAL(0.0), CREAL(0.0), CREAL(-25.0));
  985.     RwSetCameraBackColor(Camera, CREAL(0.0), CREAL(0.0), CREAL(0.0));
  986.     RwClearCameraViewport(Camera);
  987.  
  988. /*---    Create the matrix used for rotations.    ---*/
  989.  
  990.     if (!(Rot.m = RwCreateMatrix()))
  991.     {
  992.         MessageBox(hwnd, "Error creating a RenderWare matrix",
  993.                    "Renderware Error", MB_OK | MB_ICONSTOP | MB_APPLMODAL);
  994.         return (-1);
  995.     }
  996.     RwRotateMatrix(Rot.m, CREAL(1.0), CREAL(0.0), CREAL(0.0), CREAL(-45.0), rwREPLACE);
  997.     RwRotateMatrix(Rot.m, CREAL(0.0), CREAL(1.0), CREAL(0.0), CREAL(-30.0), rwPOSTCONCAT);
  998.  
  999. /*---    Preload all Textures    ---*/
  1000.  
  1001.     for (i = 1; i < sizeof (TextureNames) / sizeof (char *); i++)
  1002.  
  1003.     {
  1004.         if (!RwGetNamedTexture(TextureNames[i]))
  1005.         {
  1006.             sprintf(str, "Error loading Renderware texture [%s]", TextureNames[i]);
  1007.             MessageBox(hwnd, str,
  1008.                     "Renderware Error", MB_OK | MB_ICONSTOP | MB_APPLMODAL);
  1009.             return (-1);
  1010.         }
  1011.     }
  1012.  
  1013. /*---    Initialise internal data structures    ---*/
  1014.  
  1015.     BuildSinCosTab();
  1016.  
  1017.     for (i = 0; i < 512; i++)
  1018.         Fn[i] = FL2REAL(sin((float) i / 512.0 * 6.2831853) / 2.0);
  1019.  
  1020.     for (i = 0; i < MAX_CLUMP_VERTICES; i++)
  1021.         Vindex[i] = i + 1;
  1022.  
  1023.     /* Start Timer */
  1024.     SetTimer(hwnd, 1, 50, NULL);
  1025.  
  1026.     SetTexture(DEFAULT_T);
  1027.     SetShading(DEFAULT_S);
  1028.     SetResolution(DEFAULT_R);
  1029.     SetX(DEFAULT_X);            /* set default X function */
  1030.     SetY(DEFAULT_Y);            /* set default Y function */
  1031.     SetZ(DEFAULT_Z);            /* set default Z function */
  1032.     ShowInfo(hwnd);
  1033.  
  1034.     return (0);
  1035. }
  1036.  
  1037. /**************************************************************************
  1038.     Process WM_LBUTTONDOWN messages
  1039. **************************************************************************/
  1040. void 
  1041. OnLeftButtonDown(HWND hwnd, LPARAM lparam)
  1042. {
  1043.     RwPickRecord record;
  1044.  
  1045.     /* Save the cursor position. */
  1046.  
  1047.     Xprev = LOWORD(lparam);
  1048.     Yprev = HIWORD(lparam);
  1049.     Rot.flag = FALSE;
  1050.  
  1051.     if (Clump && (RwPickClump(Clump, Xprev, Yprev, Camera, &record)) &&
  1052.         (record.type == rwPICKCLUMP))
  1053.     {
  1054.         ShowAppLeftStatus(hwnd, Camera, "Rotate Object");
  1055.         SetCursor(LoadCursor(NULL, IDC_SIZE));
  1056.         SetCapture(hwnd);
  1057.         lb = TRUE;
  1058.     }
  1059.     else
  1060.     {
  1061.         ShowAppLeftStatus(hwnd, Camera, "Stop Object Rotation");
  1062.     }
  1063. }
  1064.  
  1065. /**************************************************************************
  1066.     Process WM_LBUTTONUP messages
  1067. **************************************************************************/
  1068. void 
  1069. OnLeftButtonUp(HWND hwnd)
  1070. {
  1071.     if (lb)
  1072.     {
  1073.         ReleaseCapture();
  1074.         lb = FALSE;
  1075.     }
  1076.     ShowAppLeftStatus(hwnd, Camera, "");
  1077. }
  1078.  
  1079. /**************************************************************************
  1080.     Process WM_RBUTTONDOWN messages
  1081. **************************************************************************/
  1082. void 
  1083. OnRightButtonDown(HWND hwnd, LPARAM lparam)
  1084. {
  1085.     HCURSOR bulb;
  1086.  
  1087.     Xprev = LOWORD(lparam);
  1088.     Yprev = HIWORD(lparam);
  1089.  
  1090.     SetCapture(hwnd);
  1091.     bulb = LoadCursor(Hinstance, "C_BULB");
  1092.     if (bulb)
  1093.         SetCursor(bulb);
  1094.     rb = TRUE;
  1095.     ShowAppLeftStatus(hwnd, Camera, "Rotate Light");
  1096. }
  1097.  
  1098. /**************************************************************************
  1099.     Process WM_RBUTTONUP messages
  1100. **************************************************************************/
  1101. void 
  1102. OnRightButtonUp(HWND hwnd)
  1103. {
  1104.     if (rb)
  1105.     {
  1106.         ReleaseCapture();
  1107.         rb = FALSE;
  1108.     }
  1109.     ShowAppLeftStatus(hwnd, Camera, "");
  1110. }
  1111.  
  1112. /**************************************************************************
  1113.     Process WM_MOUSEMOVE messages
  1114. **************************************************************************/
  1115. void 
  1116. OnMouseMove(LPARAM lparam)
  1117. {
  1118.     RwInt32 x, y, dx, dy;
  1119.  
  1120.     x = LOWORD(lparam);
  1121.     y = HIWORD(lparam);
  1122.  
  1123.     dx = x - Xprev;
  1124.     dy = y - Yprev;
  1125.  
  1126.     if (lb)
  1127.     {
  1128.         Rot.flag = TRUE;
  1129.         Rot.dx = dx;
  1130.         Rot.dy = dy;
  1131.         RwRotateMatrix(Rot.m, CREAL(0.0), CREAL(1.0), CREAL(0.0), INT2REAL(dx), rwPOSTCONCAT);
  1132.         RwRotateMatrix(Rot.m, CREAL(1.0), CREAL(0.0), CREAL(0.0), INT2REAL(dy), rwPOSTCONCAT);
  1133.     }
  1134.     else if (rb)
  1135.     {
  1136.         RwRotateMatrix(RwScratchMatrix(), CREAL(0.0), CREAL(1.0), CREAL(0.0),
  1137.                        INT2REAL(dx), rwREPLACE);
  1138.         RwRotateMatrix(RwScratchMatrix(), CREAL(1.0), CREAL(0.0), CREAL(0.0),
  1139.                        INT2REAL(dy), rwPOSTCONCAT);
  1140.         RwTransformLight(Light, RwScratchMatrix(), rwPOSTCONCAT);
  1141.     }
  1142.     else
  1143.     {
  1144.         SetCursor(LoadCursor(NULL, IDC_ARROW));
  1145.     }
  1146.     Xprev = x;
  1147.     Yprev = y;
  1148. }
  1149.  
  1150. /**************************************************************************
  1151.     Process WM_PAINT messages
  1152. **************************************************************************/
  1153. void 
  1154. OnPaint(HWND hwnd)
  1155. {
  1156.     HDC hdc;
  1157.     PAINTSTRUCT ps;
  1158.  
  1159.     hdc = BeginPaint(hwnd, &ps);
  1160.     RwDamageCameraViewport(Camera,
  1161.                         (RwInt32) ps.rcPaint.left, (RwInt32) ps.rcPaint.top,
  1162.                            (RwInt32) (ps.rcPaint.right - ps.rcPaint.left),
  1163.                            (RwInt32) (ps.rcPaint.bottom - ps.rcPaint.top));
  1164.  
  1165.     RwShowCameraImage(Camera, (void *)(DWORD)hdc);
  1166.     ShowAppLeftStatus(hwnd, Camera, "");
  1167.     ShowInfo(hwnd);
  1168.     EndPaint(hwnd, &ps);
  1169. }
  1170.  
  1171. /**************************************************************************
  1172.     Process WM_SIZE messages
  1173. **************************************************************************/
  1174. void 
  1175. OnSize(HWND hwnd, LPARAM lparam)
  1176. {
  1177.     RwInt32 width;
  1178.     RwInt32 height;
  1179.  
  1180.     width = LOWORD(lparam);
  1181.     height = HIWORD(lparam);
  1182.  
  1183.     height = StatusAdjustHeight(hwnd, (int)height);
  1184.  
  1185.     /* Set the camera viewport to match the window's client area. */
  1186.  
  1187.     RwSetCameraViewport(Camera, 0, 0, width, height);
  1188.     RwGetCameraViewport(Camera, (RwInt32) NULL, (RwInt32) NULL, &width, &height);
  1189.  
  1190.     /* Maintain the view window at a 1:1 aspect ratio. */
  1191.  
  1192.     if ((width != 0) && (height != 0))
  1193.     {
  1194.         if (width >= height)
  1195.             RwSetCameraViewwindow(Camera,
  1196.                                   CREAL(0.2),
  1197.                  RMul(CREAL(0.2), RDiv(INT2REAL(height), INT2REAL(width))));
  1198.         else
  1199.             RwSetCameraViewwindow(Camera,
  1200.                   RMul(CREAL(0.2), RDiv(INT2REAL(width), INT2REAL(height))),
  1201.                                   CREAL(0.2));
  1202.     }
  1203.  
  1204.     /* Redisplay the scene. */
  1205.  
  1206.     ShowView(hwnd);
  1207.     ShowAppLeftStatus(hwnd, Camera, "");
  1208.     ShowInfo(hwnd);
  1209. }
  1210.  
  1211. /**************************************************************************
  1212.     Process WM_TIMER messages
  1213. **************************************************************************/
  1214. void 
  1215. OnTimer(HWND hwnd)
  1216. {
  1217.     static int rcount = 0;
  1218.  
  1219.     if (Membrane)
  1220.         MoveSheet();
  1221.  
  1222.     if ((Clump) && (!lb) && Rot.flag)
  1223.     {
  1224.         RwRotateMatrix(Rot.m, CREAL(0.0), CREAL(1.0), CREAL(0.0), INT2REAL(Rot.dx), rwPOSTCONCAT);
  1225.         RwRotateMatrix(Rot.m, CREAL(1.0), CREAL(0.0), CREAL(0.0), INT2REAL(Rot.dy), rwPOSTCONCAT);
  1226.         if (!(++rcount % 127))
  1227.             RwOrthoNormalizeMatrix(Rot.m, Rot.m);
  1228.     }
  1229.     ShowView(hwnd);
  1230. }
  1231.  
  1232. /**************************************************************************
  1233.     Process WM_DESTROY messages
  1234. **************************************************************************/
  1235. void 
  1236. OnDestroy(HWND hwnd)
  1237. {
  1238.     if (Camera)
  1239.         RwDestroyCamera(Camera);
  1240.     if (Rot.m)
  1241.         RwDestroyMatrix(Rot.m);
  1242.  
  1243.     KillTimer(hwnd, 1);
  1244.     PostQuitMessage(0);
  1245. }
  1246.  
  1247. /**************************************************************************
  1248.     Main event handler
  1249. **************************************************************************/
  1250. LONG FAR PASCAL 
  1251. WinVisProc(HWND hwnd, UINT msg,
  1252.            WPARAM wparam, LPARAM lparam)
  1253. {
  1254.     LONG ret = 0;
  1255.  
  1256.     switch (msg)
  1257.     {
  1258.         case WM_GETMINMAXINFO:
  1259.             OnGetMinMaxInfo((MINMAXINFO FAR *) MK_FP32((void *) lparam));
  1260.             break;
  1261.         case WM_COMMAND:
  1262.             OnCommand(hwnd, wparam);
  1263.             ShowInfo(hwnd);
  1264.             break;
  1265.         case WM_CREATE:
  1266.             ret = OnCreate(hwnd);
  1267.             break;
  1268.         case WM_LBUTTONDOWN:
  1269.             OnLeftButtonDown(hwnd, lparam);
  1270.             break;
  1271.         case WM_LBUTTONUP:
  1272.             OnLeftButtonUp(hwnd);
  1273.             break;
  1274.         case WM_RBUTTONDOWN:
  1275.             OnRightButtonDown(hwnd, lparam);
  1276.             break;
  1277.         case WM_RBUTTONUP:
  1278.             OnRightButtonUp(hwnd);
  1279.             break;
  1280.         case WM_MOUSEMOVE:
  1281.             OnMouseMove(lparam);
  1282.             break;
  1283.         case WM_PAINT:
  1284.             OnPaint(hwnd);
  1285.             break;
  1286.         case WM_SIZE:
  1287.             OnSize(hwnd, lparam);
  1288.             break;
  1289.         case WM_TIMER:
  1290.             OnTimer(hwnd);
  1291.             break;
  1292.         case WM_DESTROY:
  1293.             OnDestroy(hwnd);
  1294.             break;
  1295.         default:
  1296.             ret = DefWindowProc(hwnd, msg, wparam, lparam);
  1297.             break;
  1298.     }
  1299.     return (ret);
  1300. }
  1301.  
  1302. /**************************************************************************
  1303.     Windows Program Entry Point
  1304. **************************************************************************/
  1305. int PASCAL 
  1306. WinMain(HANDLE hinst, HANDLE hprevinst, LPSTR pcmdline,
  1307.         int ncmdshow)
  1308. {
  1309.     WNDCLASS wc;
  1310.     MSG msg;
  1311.     HWND hwnd;
  1312.     HMENU tempmenu;
  1313.     char buffer[64];
  1314.     int i;
  1315.  
  1316.     if (hprevinst)
  1317.     {
  1318.         MessageBox(NULL, "Application is already running", "Error", MB_OK);
  1319.         return (FALSE);
  1320.     }
  1321.  
  1322.     Hinstance = hinst;
  1323.  
  1324.     /* Register the window class.  NULL hIcon means we get an animated
  1325.        3D icon for free. */
  1326.  
  1327.     wc.style = CS_HREDRAW | CS_VREDRAW;
  1328.     wc.lpfnWndProc = (WNDPROC) WinVisProc;
  1329.     wc.cbClsExtra = 0;
  1330.     wc.cbWndExtra = 0;
  1331.     wc.hInstance = Hinstance;
  1332.     wc.hIcon = LoadIcon(Hinstance, "RW_ICON");
  1333.     wc.hCursor = NULL;
  1334.     wc.hbrBackground = NULL;
  1335.     wc.lpszMenuName = NULL;
  1336.     wc.lpszClassName = "RwWinVisClass";
  1337.  
  1338.     if (!RegisterClass(&wc))
  1339.         return (FALSE);
  1340.  
  1341.     /* Initialize RenderWare. */
  1342.  
  1343.     if (!RwOpen("MSWindows", NULL))
  1344.     {
  1345.         MessageBox(NULL, "RwOpen() failed", "Error", MB_OK);
  1346.         return (FALSE);
  1347.     }
  1348.  
  1349. /*---    Set the shape path to enable texture loading     ---*/
  1350.  
  1351.     GetModuleFileName(Hinstance, buffer, sizeof (buffer));
  1352.     i = strlen(buffer);
  1353.     while (buffer[i] != '\\')
  1354.         i--;
  1355.     buffer[i + 1] = 0;
  1356.     strcat(buffer, "TEXTURES");
  1357.     RwSetShapePath(buffer, rwREPLACE);
  1358.     RwSetShapePath(".", rwPOSTCONCAT);
  1359.  
  1360.     /* Create The menus */
  1361.  
  1362.     Mainmenu = CreateMenu();
  1363.     tempmenu = CreateMenu();
  1364.  
  1365.     AppendMenu(tempmenu, MF_STRING, X_MBASE + ZERO, "f(x) = 0");
  1366.     AppendMenu(tempmenu, MF_STRING, X_MBASE + RAMP, "f(x) = x");
  1367.     AppendMenu(tempmenu, MF_STRING, X_MBASE + SIN, "f(x) = sin(x)");
  1368.     AppendMenu(tempmenu, MF_STRING, X_MBASE + COS, "f(x) = cos(x)");
  1369.     AppendMenu(tempmenu, MF_STRING, X_MBASE + SQUARED, "f(x) = x^2");
  1370.     AppendMenu(tempmenu, MF_STRING, X_MBASE + CUBED, "f(x) = x^3");
  1371.     AppendMenu(tempmenu, MF_SEPARATOR, 0, NULL);
  1372.     AppendMenu(tempmenu, MF_STRING, Y_MBASE + ZERO, "f(y) = 0");
  1373.     AppendMenu(tempmenu, MF_STRING, Y_MBASE + RAMP, "f(y) = y");
  1374.     AppendMenu(tempmenu, MF_STRING, Y_MBASE + SIN, "f(y) = sin(y)");
  1375.     AppendMenu(tempmenu, MF_STRING, Y_MBASE + COS, "f(y) = cos(y)");
  1376.     AppendMenu(tempmenu, MF_STRING, Y_MBASE + SQUARED, "f(y) = y^2");
  1377.     AppendMenu(tempmenu, MF_STRING, Y_MBASE + CUBED, "f(y) = y^3");
  1378.     AppendMenu(tempmenu, MF_SEPARATOR, 0, NULL);
  1379.     AppendMenu(tempmenu, MF_STRING, Z_MBASE + XMULY, "f(x) * f(y)");
  1380.     AppendMenu(tempmenu, MF_STRING, Z_MBASE + XADDY, "f(x) + f(y)");
  1381.     AppendMenu(tempmenu, MF_STRING, Z_MBASE + XSUBY, "f(x) - f(y)");
  1382.     AppendMenu(tempmenu, MF_SEPARATOR, 0, NULL);
  1383.     AppendMenu(tempmenu, MF_STRING, M_MBASE, "Membrane");
  1384.     AppendMenu(Mainmenu, MF_POPUP, (UINT) tempmenu, "&Plot");
  1385.  
  1386.     tempmenu = CreateMenu();
  1387.  
  1388.     AppendMenu(tempmenu, MF_STRING, R_MBASE + R_4, "4");
  1389.     AppendMenu(tempmenu, MF_STRING, R_MBASE + R_8, "8");
  1390.     AppendMenu(tempmenu, MF_STRING, R_MBASE + R_16, "16");
  1391.     AppendMenu(Mainmenu, MF_POPUP, (UINT) tempmenu, "&Resolution");
  1392.     /* Create and show the window. */
  1393.  
  1394.     tempmenu = CreateMenu();
  1395.  
  1396.     AppendMenu(tempmenu, MF_STRING, S_MBASE + S_FLAT, "Flat");
  1397.     AppendMenu(tempmenu, MF_STRING, S_MBASE + S_SMOOTH, "Smooth");
  1398.     AppendMenu(Mainmenu, MF_POPUP, (UINT) tempmenu, "&Shading");
  1399.  
  1400.     tempmenu = CreateMenu();
  1401.  
  1402.     AppendMenu(tempmenu, MF_STRING, T_MBASE + T_NONE, "None");
  1403.     AppendMenu(tempmenu, MF_STRING, T_MBASE + T_WOOD, "Wood");
  1404.     AppendMenu(tempmenu, MF_STRING, T_MBASE + T_BRICK, "Brick");
  1405.     AppendMenu(tempmenu, MF_STRING, T_MBASE + T_MARBLE, "Marble");
  1406.     AppendMenu(tempmenu, MF_STRING, T_MBASE + T_MANDEL, "Mandelbrot");
  1407.     AppendMenu(tempmenu, MF_STRING, T_MBASE + T_MANDRILL, "Mandrill");
  1408.     AppendMenu(Mainmenu, MF_POPUP, (UINT) tempmenu, "&Texture");
  1409.  
  1410.     tempmenu = CreateMenu();
  1411.  
  1412.     AppendMenu(tempmenu, MF_STRING, H_MBASE + H_ABOUT, "About");
  1413.     AppendMenu(Mainmenu, MF_POPUP, (UINT) tempmenu, "&Help");
  1414.  
  1415.     /* Create and show the window. */
  1416.  
  1417.     if (!(hwnd = CreateWindow("RwWinVisClass", RWAPPNAME,
  1418.                               WS_OVERLAPPEDWINDOW,
  1419.                               CW_USEDEFAULT, CW_USEDEFAULT, 400, 400,
  1420.                               NULL, Mainmenu, Hinstance, NULL)))
  1421.     {
  1422.         RwClose();
  1423.         return (FALSE);
  1424.     }
  1425.  
  1426.     CheckDisplayDepth(hwnd);
  1427.  
  1428.     ShowWindow(hwnd, ncmdshow);
  1429.     UpdateWindow(hwnd);
  1430.  
  1431.     /* Main loop. */
  1432.  
  1433.     while (GetMessage(&msg, NULL, 0, 0))
  1434.     {
  1435.         TranslateMessage(&msg);
  1436.         DispatchMessage(&msg);
  1437.     }
  1438.  
  1439.     /* Terminate RenderWare. */
  1440.  
  1441.     RwClose();
  1442.  
  1443.     return (msg.wParam);
  1444. }
  1445.