home *** CD-ROM | disk | FTP | other *** search
/ Software Recommendations - 1998 Season 1 / DNBCD4.iso / hardware / opengl / sgi / OPENGL.EXE / _SETUP.1 / vcull.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-28  |  22.9 KB  |  959 lines

  1. /*
  2. ** Vertex Culling Test
  3. */
  4. #include <windows.h>
  5. #include <math.h>
  6. #include <GL/gl.h>
  7.  
  8. #if defined(GL_SGI_cull_vertex)
  9. PFNGLCULLPARAMETERFVSGIPROC CullParameterfv;
  10. #endif
  11.  
  12. #if defined(GL_SGI_compiled_vertex_array)
  13. PFNGLLOCKARRAYSSGIPROC LockArrays;
  14. PFNGLUNLOCKARRAYSSGIPROC UnlockArrays;
  15. #endif
  16.  
  17. #if !defined(M_PI)
  18. #define M_PI 3.14159265F
  19. #endif
  20.  
  21. char *className = "OpenGL";
  22. char *windowName = "Vertex Culling Test";
  23. int winX, winY;
  24. int winWidth, winHeight;
  25.  
  26. HDC hDC;
  27. HGLRC hGLRC;
  28. HPALETTE hPalette;
  29.  
  30. void (*idleFunc)(void);
  31.  
  32. GLfloat objectXform[4][4];
  33. float angle = 10.0F, axis[3] = { 0.0F, 0.0F, 1.0F };
  34.  
  35. void drawCube(void);
  36. void drawTorus(void);
  37. void drawSphere(void);
  38. #define NUM_OBJECTS (sizeof(drawObject) / sizeof(drawObject[0]))
  39. void (*drawObject[])(void) = {
  40.     drawTorus, drawSphere, drawCube,
  41. };
  42. int objectIndex;
  43.  
  44. int objectNumMajor = 24, objectNumMinor = 32;
  45. BOOL halfObject = FALSE;
  46. BOOL redrawContinue = TRUE;
  47. BOOL doubleBuffered = TRUE;
  48. BOOL depthBuffered = TRUE;
  49. BOOL drawOutlines = FALSE;
  50. BOOL textureEnabled = FALSE;
  51. BOOL textureReplace = FALSE;
  52. BOOL useVertexCull = TRUE;
  53. BOOL useFaceCull = TRUE;
  54. BOOL useVertexArray = TRUE;
  55. BOOL useVertexLocking = TRUE;
  56. BOOL useLighting = TRUE;
  57. BOOL perspectiveProj = TRUE;
  58. BOOL useFog = FALSE;
  59. enum MoveModes { MoveNone, MoveObject };
  60. enum MoveModes mode = MoveObject;
  61.  
  62. #define X_OFFSET_STEP 0.025F;
  63. #define Y_OFFSET_STEP 0.025F;
  64. GLfloat xOffset, yOffset;
  65.  
  66. void
  67. drawCube(void)
  68. {
  69.     glBegin(GL_QUADS);
  70.     glNormal3f(-1.0F, 0.0F, 0.0F);
  71.     glTexCoord2f( 0.0F, 1.0F); glVertex3f(-0.5F,-0.5F,-0.5F);
  72.     glTexCoord2f( 0.0F, 0.0F); glVertex3f(-0.5F,-0.5F, 0.5F);
  73.     glTexCoord2f( 1.0F, 0.0F); glVertex3f(-0.5F, 0.5F, 0.5F);
  74.     glTexCoord2f( 1.0F, 1.0F); glVertex3f(-0.5F, 0.5F,-0.5F);
  75.  
  76.     glNormal3f( 1.0F, 0.0F, 0.0F);
  77.     glTexCoord2f( 1.0F, 1.0F); glVertex3f( 0.5F, 0.5F, 0.5F);
  78.     glTexCoord2f( 0.0F, 1.0F); glVertex3f( 0.5F,-0.5F, 0.5F);
  79.     glTexCoord2f( 0.0F, 0.0F); glVertex3f( 0.5F,-0.5F,-0.5F);
  80.     glTexCoord2f( 1.0F, 0.0F); glVertex3f( 0.5F, 0.5F,-0.5F);
  81.  
  82.     glNormal3f( 0.0F,-1.0F, 0.0F);
  83.     glTexCoord2f( 0.0F, 1.0F); glVertex3f(-0.5F,-0.5F,-0.5F);
  84.     glTexCoord2f( 0.0F, 0.0F); glVertex3f( 0.5F,-0.5F,-0.5F);
  85.     glTexCoord2f( 1.0F, 0.0F); glVertex3f( 0.5F,-0.5F, 0.5F);
  86.     glTexCoord2f( 1.0F, 1.0F); glVertex3f(-0.5F,-0.5F, 0.5F);
  87.  
  88.     glNormal3f( 0.0F, 1.0F, 0.0F);
  89.     glTexCoord2f( 1.0F, 1.0F); glVertex3f( 0.5F, 0.5F, 0.5F);
  90.     glTexCoord2f( 0.0F, 1.0F); glVertex3f( 0.5F, 0.5F,-0.5F);
  91.     glTexCoord2f( 0.0F, 0.0F); glVertex3f(-0.5F, 0.5F,-0.5F);
  92.     glTexCoord2f( 1.0F, 0.0F); glVertex3f(-0.5F, 0.5F, 0.5F);
  93.  
  94.     glNormal3f( 0.0F, 0.0F,-1.0F);
  95.     glTexCoord2f( 0.0F, 1.0F); glVertex3f(-0.5F,-0.5F,-0.5F);
  96.     glTexCoord2f( 0.0F, 0.0F); glVertex3f(-0.5F, 0.5F,-0.5F);
  97.     glTexCoord2f( 1.0F, 0.0F); glVertex3f( 0.5F, 0.5F,-0.5F);
  98.     glTexCoord2f( 1.0F, 1.0F); glVertex3f( 0.5F,-0.5F,-0.5F);
  99.  
  100.     glNormal3f( 0.0F, 0.0F, 1.0F);
  101.     glTexCoord2f( 1.0F, 1.0F); glVertex3f( 0.5F, 0.5F, 0.5F);
  102.     glTexCoord2f( 0.0F, 1.0F); glVertex3f(-0.5F, 0.5F, 0.5F);
  103.     glTexCoord2f( 0.0F, 0.0F); glVertex3f(-0.5F,-0.5F, 0.5F);
  104.     glTexCoord2f( 1.0F, 0.0F); glVertex3f( 0.5F,-0.5F, 0.5F);
  105.     glEnd();
  106. }
  107.  
  108. void
  109. drawTorus(void)
  110. {
  111.     struct vertex {
  112.         GLfloat t[2];
  113.     GLfloat n[3];
  114.     GLfloat v[3];
  115.     };
  116.  
  117.     int numVerts = (objectNumMajor+1) * (objectNumMinor+1);
  118.     int numStrips = halfObject ? objectNumMajor / 2 : objectNumMajor;
  119.     int numPerStrip = 2 * (objectNumMinor+1);
  120.     int numElements = (objectNumMajor+1) * numPerStrip;
  121.  
  122.     static struct vertex *vertexArray, *v;
  123.     static GLuint *elementArray, *e;
  124.     static int numMajor;
  125.     static int numMinor;
  126.     int i, j;
  127.  
  128.     if (!vertexArray || numMajor!=objectNumMajor || numMinor!=objectNumMinor) {
  129.     float majorRadius = 0.6F;
  130.     float minorRadius = 0.2F;
  131.     double majorStep = 2.0F*M_PI / objectNumMajor;
  132.     double minorStep = 2.0F*M_PI / objectNumMinor;
  133.  
  134.     if (vertexArray) free(vertexArray);
  135.     vertexArray = (struct vertex *)
  136.         calloc(numVerts, sizeof(struct vertex));
  137.  
  138.     if (elementArray) free(elementArray);
  139.     elementArray = (GLuint *)
  140.         calloc(numElements, sizeof(GLuint));
  141.  
  142.     numMajor = objectNumMajor;
  143.     numMinor = objectNumMinor;
  144.  
  145.     v = vertexArray;
  146.     e = elementArray;
  147.     for (i=0; i<=numMajor; ++i) {
  148.         double a = i * majorStep;
  149.         GLfloat x = (GLfloat) cos(a);
  150.         GLfloat y = (GLfloat) sin(a);
  151.  
  152.         for (j=0; j<=numMinor; ++j) {
  153.         double b = j * minorStep;
  154.         GLfloat c = (GLfloat) cos(b);
  155.         GLfloat r = minorRadius * c + majorRadius;
  156.         GLfloat z = minorRadius * (GLfloat) sin(b);
  157.  
  158.         v->t[0] = i/(GLfloat) numMajor;
  159.         v->t[1] = j/(GLfloat) numMinor;
  160.  
  161.         v->n[0] = x*c;
  162.         v->n[1] = y*c;
  163.         v->n[2] = z/minorRadius;
  164.  
  165.         v->v[0] = x*r;
  166.         v->v[1] = y*r;
  167.         v->v[2] = z;
  168.  
  169.         v++;
  170.  
  171.         *e++ = i * (numMinor+1) + j;
  172.         *e++ = (i+1) * (numMinor+1) + j;
  173.         }
  174.     }
  175.     }
  176.  
  177.     if (useVertexArray) {
  178.     glInterleavedArrays(GL_T2F_N3F_V3F, 0, vertexArray);
  179.  
  180. #if defined(GL_SGI_compiled_vertex_array)
  181.     if (useVertexLocking && LockArrays) LockArrays(0, numVerts);
  182. #endif
  183.  
  184.     for (i=0, e=elementArray; i<numStrips; ++i, e+=numPerStrip) {
  185.         glDrawElements(GL_TRIANGLE_STRIP, numPerStrip, GL_UNSIGNED_INT, e);
  186.     }
  187.  
  188. #if defined(GL_SGI_compiled_vertex_array)
  189.     if (useVertexLocking && UnlockArrays) UnlockArrays();
  190. #endif
  191.     } else {
  192.     for (i=0, e=elementArray; i<numStrips; ++i, e+=numPerStrip) {
  193.         glBegin(GL_TRIANGLE_STRIP);
  194.         for (j=0; j<numPerStrip; ++j) {
  195.         v = &vertexArray[e[j]];
  196.  
  197.         glTexCoord2fv(v->t);
  198.         glNormal3fv(v->n);
  199.         glVertex3fv(v->v);
  200.         }
  201.         glEnd();
  202.     }
  203.     }
  204. }
  205.  
  206. void
  207. drawSphere(void)
  208. {
  209.     struct vertex {
  210.         GLfloat t[2];
  211.     GLfloat n[3];
  212.     GLfloat v[3];
  213.     };
  214.  
  215.     int numVerts = (objectNumMajor+1) * (objectNumMinor+1);
  216.     int numStrips = halfObject ? objectNumMajor / 2 : objectNumMajor;
  217.     int numPerStrip = 2 * (objectNumMinor+1);
  218.     int numElements = (objectNumMajor+1) * numPerStrip;
  219.  
  220.     static struct vertex *vertexArray, *v;
  221.     static GLuint *elementArray, *e;
  222.     static int numMajor;
  223.     static int numMinor;
  224.     int i, j;
  225.  
  226.     if (!vertexArray || numMajor!=objectNumMajor || numMinor!=objectNumMinor) {
  227.     float radius = 0.6F;
  228.     double majorStep = 2.0F*M_PI / objectNumMajor;
  229.     double minorStep = M_PI / objectNumMinor;
  230.  
  231.     if (vertexArray) free(vertexArray);
  232.     vertexArray = (struct vertex *)
  233.         calloc(numVerts, sizeof(struct vertex));
  234.  
  235.     if (elementArray) free(elementArray);
  236.     elementArray = (GLuint *)
  237.         calloc(numElements, sizeof(GLuint));
  238.  
  239.     numMajor = objectNumMajor;
  240.     numMinor = objectNumMinor;
  241.  
  242.     v = vertexArray;
  243.     e = elementArray;
  244.     for (i=0; i<=numMajor; ++i) {
  245.         double a = i * majorStep;
  246.         GLfloat x = (GLfloat) cos(a);
  247.         GLfloat y = (GLfloat) sin(a);
  248.  
  249.         for (j=0; j<=numMinor; ++j) {
  250.         double b = j * minorStep;
  251.         GLfloat c = (GLfloat) sin(b);
  252.         GLfloat r = c * radius;
  253.         GLfloat z = (GLfloat) cos(b);
  254.  
  255.         v->t[0] = i/(GLfloat) numMajor;
  256.         v->t[1] = j/(GLfloat) numMinor;
  257.  
  258.         v->n[0] = x*c;
  259.         v->n[1] = y*c;
  260.         v->n[2] = z;
  261.  
  262.         v->v[0] = x*r;
  263.         v->v[1] = y*r;
  264.         v->v[2] = z*radius;
  265.  
  266.         v++;
  267.  
  268.         *e++ = (i+1) * (numMinor+1) + j;
  269.         *e++ = i * (numMinor+1) + j;
  270.         }
  271.     }
  272.     }
  273.  
  274.     if (useVertexArray) {
  275.     glInterleavedArrays(GL_T2F_N3F_V3F, 0, vertexArray);
  276.  
  277. #if defined(GL_SGI_compiled_vertex_array)
  278.     if (useVertexLocking && LockArrays) LockArrays(0, numVerts);
  279. #endif
  280.  
  281.     for (i=0, e=elementArray; i<numStrips; ++i, e+=numPerStrip) {
  282.         glDrawElements(GL_TRIANGLE_STRIP, numPerStrip, GL_UNSIGNED_INT, e);
  283.     }
  284.  
  285. #if defined(GL_SGI_compiled_vertex_array)
  286.     if (useVertexLocking && UnlockArrays) UnlockArrays();
  287. #endif
  288.     } else {
  289.     for (i=0, e=elementArray; i<numStrips; ++i, e+=numPerStrip) {
  290.         glBegin(GL_TRIANGLE_STRIP);
  291.         for (j=0; j<numPerStrip; ++j) {
  292.         v = &vertexArray[e[j]];
  293.  
  294.         glTexCoord2fv(v->t);
  295.         glNormal3fv(v->n);
  296.         glVertex3fv(v->v);
  297.         }
  298.         glEnd();
  299.     }
  300.     }
  301. }
  302.  
  303. void
  304. setCheckTexture(void)
  305. {
  306.     int texWidth = 256;
  307.     int texHeight = 256;
  308.     GLubyte *texPixels, *p;
  309.     int texSize;
  310.     int i, j;
  311.  
  312.     texSize = texWidth*texHeight*4*sizeof(GLubyte);
  313.     if (textureReplace) {
  314.     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  315.     } else {
  316.     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  317.     }
  318.  
  319.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  320.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  321.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  322.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  323.  
  324.     texPixels = (GLubyte *) malloc(texSize);
  325.     if (texPixels == NULL) {
  326.     return;
  327.     }
  328.  
  329.     p = texPixels;
  330.     for (i=0; i<texHeight; ++i) {
  331.     for (j=0; j<texWidth; ++j) {
  332.         if ((i ^ j) & 32) {
  333.         p[0] = 0xff; p[1] = 0xff; p[2] = 0xff; p[3] = 0xff;
  334.         } else {
  335.         p[0] = 0x10; p[1] = 0x10; p[2] = 0x10; p[3] = 0xff;
  336.         }
  337.         p += 4;
  338.     }
  339.     }
  340.  
  341.     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
  342.          texWidth, texHeight, 0,
  343.          GL_RGBA, GL_UNSIGNED_BYTE, texPixels);
  344.  
  345.     free(texPixels);
  346. }
  347.  
  348. void
  349. matrixIdentity(GLfloat m[4][4])
  350. {
  351.     m[0][0] = 1.0F; m[0][1] = 0.0F; m[0][2] = 0.0F; m[0][3] = 0.0F;
  352.     m[1][0] = 0.0F; m[1][1] = 1.0F; m[1][2] = 0.0F; m[1][3] = 0.0F;
  353.     m[2][0] = 0.0F; m[2][1] = 0.0F; m[2][2] = 1.0F; m[2][3] = 0.0F;
  354.     m[3][0] = 0.0F; m[3][1] = 0.0F; m[3][2] = 0.0F; m[3][3] = 1.0F;
  355. }
  356.  
  357. void
  358. setProjection(void)
  359. {
  360.     GLfloat aspect = (GLfloat) winWidth / (GLfloat) winHeight;
  361.  
  362.     glMatrixMode(GL_PROJECTION);
  363.     glLoadIdentity();
  364.     if (perspectiveProj) {
  365.     glFrustum(-0.5F*aspect, 0.5F*aspect, -0.5F, 0.5F, 1.0F, 3.0F);
  366.  
  367. #if defined(GL_SGI_cull_vertex)
  368.     if (CullParameterfv) {
  369.         GLfloat eye[4] = { 0.0F, 0.0F, 0.0F, 1.0F };
  370.  
  371.         CullParameterfv(GL_CULL_VERTEX_EYE_POSITION_SGI, eye);
  372.     }
  373. #endif
  374.     } else {
  375.     glOrtho(-1.0F*aspect, 1.0F*aspect, -1.0F, 1.0F, 1.0F, 3.0F);
  376.  
  377. #if defined(GL_SGI_cull_vertex)
  378.     if (CullParameterfv) {
  379.         GLfloat eye[4] = { 0.0F, 0.0F, 1.0F, 0.0F };
  380.  
  381.         CullParameterfv(GL_CULL_VERTEX_EYE_POSITION_SGI, eye);
  382.     }
  383. #endif
  384.     }
  385.     glMatrixMode(GL_MODELVIEW);
  386. }
  387.  
  388. void
  389. setMaterial(void)
  390. {
  391.     GLfloat matAmb[4] = { 0.01F, 0.01F, 0.01F, 1.00F };
  392.     GLfloat matDiff[4] = { 0.45F, 0.05F, 0.65F, 0.60F };
  393.     GLfloat matSpec[4] = { 0.50F, 0.50F, 0.50F, 1.00F };
  394.     GLfloat matShine = 20.00F;
  395.  
  396.     glMaterialfv(GL_FRONT, GL_AMBIENT, matAmb);
  397.     glMaterialfv(GL_FRONT, GL_DIFFUSE, matDiff);
  398.     glMaterialfv(GL_FRONT, GL_SPECULAR, matSpec);
  399.     glMaterialf(GL_FRONT, GL_SHININESS, matShine);
  400. }
  401.  
  402. void
  403. init(void)
  404. {
  405.     GLfloat light0Pos[4] = { 0.70F, 0.70F, 1.25F, 0.00F };
  406.     GLfloat fogDensity = 2.35F*0.180F;
  407.     GLfloat fogColor[4] = {
  408.     0.4F, 0.4F, 0.5F, 1.0F,
  409.     };
  410.  
  411.     glFogi(GL_FOG_MODE, GL_EXP2);
  412.     glFogf(GL_FOG_DENSITY, fogDensity);
  413.     glFogfv(GL_FOG_COLOR, fogColor);
  414.  
  415.     setProjection();
  416.     glTranslatef(0.0F, 0.0F, -2.0F);
  417.  
  418.     setMaterial();
  419.  
  420.     glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
  421.     glLightfv(GL_LIGHT0, GL_POSITION, light0Pos);
  422.     glEnable(GL_LIGHT0);
  423.  
  424.     setCheckTexture();
  425.  
  426.     matrixIdentity(objectXform);
  427.  
  428. #if defined(GL_SGI_cull_vertex)
  429.     CullParameterfv = (PFNGLCULLPARAMETERFVSGIPROC)
  430.         wglGetProcAddress("glCullParameterfvSGI");
  431. #endif
  432.  
  433. #if defined(GL_SGI_compiled_vertex_array)
  434.     LockArrays = (PFNGLLOCKARRAYSSGIPROC)
  435.         wglGetProcAddress("glLockArraysSGI");
  436.     UnlockArrays = (PFNGLUNLOCKARRAYSSGIPROC)
  437.         wglGetProcAddress("glUnlockArraysSGI");
  438. #endif
  439. }
  440.  
  441. void
  442. resize(void)
  443. {
  444.     setProjection();
  445.     glViewport(0, 0, winWidth, winHeight);
  446. }
  447.  
  448. void
  449. doRedraw(void)
  450. {
  451.     if (useFog) {
  452.     glClearColor(0.4F, 0.4F, 0.5F, 1.0F);
  453.     glEnable(GL_FOG);
  454.     } else {
  455.     glClearColor(0.2F, 0.2F, 0.1F, 1.0F);
  456.     glDisable(GL_FOG);
  457.     }
  458.  
  459.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  460.  
  461.     /* update transformations */
  462.     if (mode == MoveObject) {
  463.     glPushMatrix();
  464.     glLoadIdentity();
  465.     glRotatef(angle, axis[0], axis[1], axis[2]);
  466.     glMultMatrixf((GLfloat *) objectXform);
  467.     glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) objectXform);
  468.     glPopMatrix();
  469.     }
  470.  
  471.     if (textureEnabled) {
  472.     glEnable(GL_TEXTURE_2D);
  473.     }
  474.     if (drawOutlines) {
  475.     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  476.     }
  477.     if (useVertexCull) {
  478.         glEnable(GL_CULL_VERTEX_SGI);
  479.     }
  480.     if (useFaceCull) {
  481.         glEnable(GL_CULL_FACE);
  482.     }
  483.     if (useLighting) {
  484.     glEnable(GL_LIGHTING);
  485.     }
  486.     glEnable(GL_DEPTH_TEST);
  487.  
  488.     glPushMatrix();
  489.     glTranslatef(xOffset, yOffset, 0.0F);
  490.     glMultMatrixf((GLfloat *) objectXform);
  491.  
  492.     (*drawObject[objectIndex])();
  493.  
  494.     glPopMatrix();
  495.  
  496.     glDisable(GL_TEXTURE_2D);
  497.     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  498.     glDisable(GL_CULL_VERTEX_SGI);
  499.     glDisable(GL_CULL_FACE);
  500.     glDisable(GL_LIGHTING);
  501.     glDisable(GL_DEPTH_TEST);
  502.  
  503.     glFlush();
  504.     SwapBuffers(hDC);
  505. }
  506.  
  507. /*****************************************************************/
  508.  
  509. void
  510. idleRedraw(void)
  511. {
  512.     if (!redrawContinue) {
  513.         idleFunc = NULL;
  514.     }
  515.     doRedraw();
  516. }
  517.  
  518. void
  519. redraw(void)
  520. {
  521.     if (!idleFunc) {
  522.     idleFunc = idleRedraw;
  523.     }
  524. }
  525.  
  526. /*****************************************************************/
  527.  
  528. /* these functions implement a simple trackball-like motion control */
  529. BOOL trackingMotion = FALSE;
  530. float lastPos[3];
  531. DWORD lastTime;
  532. int startX, startY;
  533.  
  534. void
  535. ptov(int x, int y, int width, int height, float v[3])
  536. {
  537.     float d, a;
  538.  
  539.     /* project x,y onto a hemi-sphere centered within width, height */
  540.     v[0] = (2.0F*x - width) / width;
  541.     v[1] = (height - 2.0F*y) / height;
  542.     d = (float) sqrt(v[0]*v[0] + v[1]*v[1]);
  543.     v[2] = (float) cos((M_PI/2.0F) * ((d < 1.0F) ? d : 1.0F));
  544.     a = 1.0F / (float) sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
  545.     v[0] *= a;
  546.     v[1] *= a;
  547.     v[2] *= a;
  548. }
  549.  
  550. void
  551. startMotion(DWORD time, int button, int x, int y)
  552. {
  553.     if (button == 1) {
  554.     mode = MoveObject;
  555.     } else {
  556.     return;
  557.     }
  558.  
  559.     trackingMotion = TRUE;
  560.     redrawContinue = FALSE;
  561.     startX = x;
  562.     startY = y;
  563.     ptov(x, y, winWidth, winHeight, lastPos);
  564. }
  565.  
  566. void
  567. stopMotion(DWORD time, int button, int x, int y)
  568. {
  569.     if (button == 1 && mode == MoveObject) {
  570.     trackingMotion = FALSE;
  571.     } else {
  572.     return;
  573.     }
  574.  
  575.     if (startX != x || startY != y) {
  576.     redrawContinue = TRUE;
  577.     } else {
  578.     angle = 0.0F;
  579.     redrawContinue = FALSE;
  580.     }
  581.     if (!redrawContinue) {
  582.     mode = MoveNone;
  583.     }
  584.     redraw();
  585. }
  586.  
  587. void
  588. trackMotion(DWORD time, int x, int y)
  589. {
  590.     if (trackingMotion) {
  591.     float curPos[3], dx, dy, dz;
  592.  
  593.     ptov(x, y, winWidth, winHeight, curPos);
  594.  
  595.     dx = curPos[0] - lastPos[0];
  596.     dy = curPos[1] - lastPos[1];
  597.     dz = curPos[2] - lastPos[2];
  598.     angle = 90.0F * (float) sqrt(dx*dx + dy*dy + dz*dz);
  599.  
  600.     axis[0] = lastPos[1]*curPos[2] - lastPos[2]*curPos[1];
  601.     axis[1] = lastPos[2]*curPos[0] - lastPos[0]*curPos[2];
  602.     axis[2] = lastPos[0]*curPos[1] - lastPos[1]*curPos[0];
  603.  
  604.     lastPos[0] = curPos[0];
  605.     lastPos[1] = curPos[1];
  606.     lastPos[2] = curPos[2];
  607.     redraw();
  608.     }
  609. }
  610.  
  611. /*****************************************************************/
  612.  
  613. void
  614. setupPalette(HDC hDC)
  615. {
  616.     PIXELFORMATDESCRIPTOR pfd;
  617.     LOGPALETTE* pPal;
  618.     int pixelFormat = GetPixelFormat(hDC);
  619.     int paletteSize;
  620.  
  621.     DescribePixelFormat(hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
  622.     if (!(pfd.dwFlags & PFD_NEED_PALETTE ||
  623.       pfd.iPixelType == PFD_TYPE_COLORINDEX))
  624.     {
  625.     return;
  626.     }
  627.  
  628.     paletteSize = 1 << pfd.cColorBits;
  629.     pPal = (LOGPALETTE*)
  630.     malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY));
  631.     pPal->palVersion = 0x300;
  632.     pPal->palNumEntries = paletteSize;
  633.  
  634.     /* start with a copy of the current system palette */
  635.     (void) GetSystemPaletteEntries(hDC, 0, paletteSize, &pPal->palPalEntry[0]);
  636.  
  637.     {
  638.     /* fill in an RGBA color palette */
  639.     int redMask = (1 << pfd.cRedBits) - 1;
  640.     int greenMask = (1 << pfd.cGreenBits) - 1;
  641.     int blueMask = (1 << pfd.cBlueBits) - 1;
  642.     int i;
  643.  
  644.     for (i=0; i<paletteSize; ++i) {
  645.         pPal->palPalEntry[i].peRed =
  646.             (((i >> pfd.cRedShift) & redMask) * 255) / redMask;
  647.         pPal->palPalEntry[i].peGreen =
  648.             (((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask;
  649.         pPal->palPalEntry[i].peBlue =
  650.             (((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask;
  651.         pPal->palPalEntry[i].peFlags = 0;
  652.     }
  653.     }
  654.  
  655.     hPalette = CreatePalette(pPal);
  656.     free(pPal);
  657.  
  658.     if (hPalette) {
  659.     SelectPalette(hDC, hPalette, FALSE);
  660.     RealizePalette(hDC);
  661.     }
  662. }
  663.  
  664. void
  665. setupPixelformat(HDC hDC)
  666. {
  667.     PIXELFORMATDESCRIPTOR pfd = {
  668.     sizeof(PIXELFORMATDESCRIPTOR),    /* size of this pfd */
  669.     1,                /* version num */
  670.     PFD_DRAW_TO_WINDOW |        /* support window */
  671.     PFD_SUPPORT_OPENGL,        /* support OpenGL */
  672.     PFD_TYPE_RGBA,            /* color type */
  673.     8,                /* 8-bit color depth */
  674.     0, 0, 0, 0, 0, 0,        /* color bits (ignored) */
  675.     0,                /* no alpha buffer */
  676.     0,                /* alpha bits (ignored) */
  677.     0,                /* no accumulation buffer */
  678.     0, 0, 0, 0,            /* accum bits (ignored) */
  679.     0,                /* depth buffer (filled below)*/
  680.     0,                /* no stencil buffer */
  681.     0,                /* no auxiliary buffers */
  682.     PFD_MAIN_PLANE,            /* main layer */
  683.     0,                /* reserved */
  684.     0, 0, 0,            /* no layer, visible, damage masks */
  685.     };
  686.     int SelectedPixelFormat;
  687.     BOOL retVal;
  688.  
  689.     if (doubleBuffered) {
  690.         pfd.dwFlags |= PFD_DOUBLEBUFFER;
  691.     }
  692.  
  693.     if (depthBuffered) {
  694.     pfd.cDepthBits = 16;
  695.     }
  696.  
  697.     SelectedPixelFormat = ChoosePixelFormat(hDC, &pfd);
  698.     if (SelectedPixelFormat == 0) {
  699.     MessageBox(WindowFromDC(hDC), "ChoosePixelFormat failed\n", "Error",
  700.         MB_ICONERROR | MB_OK);
  701.     exit(1);
  702.     }
  703.  
  704.     retVal = SetPixelFormat(hDC, SelectedPixelFormat, &pfd);
  705.     if (retVal != TRUE) {
  706.     MessageBox(WindowFromDC(hDC), "SetPixelFormat failed", "Error",
  707.         MB_ICONERROR | MB_OK);
  708.     exit(1);
  709.     }
  710. }
  711.  
  712. LRESULT APIENTRY
  713. WndProc(
  714.     HWND hWnd,
  715.     UINT message,
  716.     WPARAM wParam,
  717.     LPARAM lParam)
  718. {
  719.     switch (message) {
  720.     case WM_CREATE:
  721.     hDC = GetDC(hWnd);
  722.     setupPixelformat(hDC);
  723.     setupPalette(hDC);
  724.     hGLRC = wglCreateContext(hDC);
  725.     wglMakeCurrent(hDC, hGLRC);
  726.     init();
  727.     return 0;
  728.     case WM_DESTROY:
  729.     if (hGLRC) {
  730.         wglMakeCurrent(NULL, NULL);
  731.         wglDeleteContext(hGLRC);
  732.     }
  733.     idleFunc = NULL;
  734.     ReleaseDC(hWnd, hDC);
  735.     PostQuitMessage(0);
  736.     return 0;
  737.     case WM_SIZE:
  738.     if (hGLRC) {
  739.         winWidth = (int) LOWORD(lParam);
  740.         winHeight = (int) HIWORD(lParam);
  741.         resize();
  742.         return 0;
  743.     }
  744.     case WM_PALETTECHANGED:
  745.     if (hPalette != NULL && (HWND) wParam != hWnd) {
  746.         UnrealizeObject(hPalette);
  747.         SelectPalette(hDC, hPalette, FALSE);
  748.         RealizePalette(hDC);
  749.         redraw();
  750.         return 0;
  751.     }
  752.     break;
  753.     case WM_QUERYNEWPALETTE:
  754.     if (hPalette != NULL) {
  755.         UnrealizeObject(hPalette);
  756.         SelectPalette(hDC, hPalette, FALSE);
  757.         RealizePalette(hDC);
  758.         redraw();
  759.         return TRUE;
  760.     }
  761.     break;
  762.     case WM_PAINT:
  763.     if (hGLRC) {
  764.         PAINTSTRUCT ps;
  765.         BeginPaint(hWnd, &ps);
  766.         redraw();
  767.         EndPaint(hWnd, &ps);
  768.         return 0;
  769.     }
  770.     break;
  771.     case WM_LBUTTONDOWN:
  772.     if (hGLRC) {
  773.         int x = ((int) LOWORD(lParam) << 16) >> 16;
  774.         int y = ((int) HIWORD(lParam) << 16) >> 16;
  775.         SetCapture(hWnd);
  776.         startMotion(0, 1, x, y);
  777.         return 0;
  778.     }
  779.     break;
  780.     case WM_LBUTTONUP:
  781.     if (hGLRC) {
  782.         int x = ((int) LOWORD(lParam) << 16) >> 16;
  783.         int y = ((int) HIWORD(lParam) << 16) >> 16;
  784.         ReleaseCapture();
  785.         stopMotion(0, 1, x, y);
  786.         return 0;
  787.     }
  788.     break;
  789.     case WM_MOUSEMOVE:
  790.     if (hGLRC) {
  791.         int x = ((int) LOWORD(lParam) << 16) >> 16;
  792.         int y = ((int) HIWORD(lParam) << 16) >> 16;
  793.         trackMotion(0, x, y);
  794.         break;
  795.     }
  796.     case WM_CHAR:
  797.     switch ((int)wParam) {
  798.     case VK_ESCAPE:
  799.         DestroyWindow(hWnd);
  800.         return 0;
  801.     case VK_SPACE:
  802.         objectIndex = objectIndex < NUM_OBJECTS-1 ? ++objectIndex : 0;
  803.         redraw();
  804.         return 0;
  805.     case 'a':
  806.         useVertexArray = !useVertexArray;
  807.         redraw();
  808.         return 0;
  809.     case 'c':
  810.         useFaceCull = !useFaceCull;
  811.         redraw();
  812.         return 0;
  813.     case 'f':
  814.         useFog = !useFog;
  815.         redraw();
  816.         return 0;
  817.     case 'h':
  818.         halfObject = !halfObject;
  819.         redraw();
  820.         return 0;
  821.     case 'l':
  822.         useLighting = !useLighting;
  823.         redraw();
  824.         return 0;
  825.     case 'o':
  826.         perspectiveProj = !perspectiveProj;
  827.         resize();
  828.         redraw();
  829.         return 0;
  830.     case 'p':
  831.         drawOutlines = !drawOutlines;
  832.         redraw();
  833.         return 0;
  834.     case 'v':
  835.         useVertexCull = !useVertexCull;
  836.         redraw();
  837.         return 0;
  838.     case 'i':
  839.         yOffset += Y_OFFSET_STEP;
  840.         redraw();
  841.         return 0;
  842.     case 'j':
  843.         xOffset -= X_OFFSET_STEP;
  844.         redraw();
  845.         return 0;
  846.     case 'k':
  847.         xOffset += X_OFFSET_STEP;
  848.         redraw();
  849.         return 0;
  850.     case 'm':
  851.         yOffset -= Y_OFFSET_STEP;
  852.         redraw();
  853.         return 0;
  854.     case 'r':
  855.         textureReplace = !textureReplace;
  856.         redraw();
  857.         return 0;
  858.     case 't':
  859.         textureEnabled = !textureEnabled;
  860.         redraw();
  861.         return 0;
  862.     case 'x':
  863.         useVertexLocking = !useVertexLocking;
  864.         redraw();
  865.         return 0;
  866.     default:
  867.         break;
  868.     }
  869.     break;
  870.     case WM_KEYDOWN:
  871.     switch ((int)wParam) {
  872.     case VK_DOWN:
  873.         --objectNumMajor;
  874.         redraw();
  875.         break;
  876.     case VK_UP:
  877.         ++objectNumMajor;
  878.         redraw();
  879.         break;
  880.     case VK_LEFT:
  881.         --objectNumMinor;
  882.         redraw();
  883.         break;
  884.     case VK_RIGHT:
  885.         ++objectNumMinor;
  886.         redraw();
  887.         break;
  888.     default:
  889.         break;
  890.     }
  891.     if (hGLRC) redraw();
  892.     return 0;
  893.     default:
  894.     break;
  895.     }
  896.  
  897.     /* Deal with any unprocessed messages */
  898.     return DefWindowProc(hWnd, message, wParam, lParam);
  899. }
  900.  
  901. int APIENTRY
  902. WinMain(
  903.     HINSTANCE hCurrentInst,
  904.     HINSTANCE hPreviousInst,
  905.     LPSTR lpszCmdLine,
  906.     int nCmdShow)
  907. {
  908.     WNDCLASS wndClass;
  909.     HWND hWnd;
  910.     MSG msg;
  911.  
  912.     /* Define and register the window class */
  913.     wndClass.style = CS_HREDRAW | CS_VREDRAW;
  914.     wndClass.lpfnWndProc = WndProc;
  915.     wndClass.cbClsExtra = 0;
  916.     wndClass.cbWndExtra = 0;
  917.     wndClass.hInstance = hCurrentInst;
  918.     wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  919.     wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
  920.     wndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
  921.     wndClass.lpszMenuName = NULL;
  922.     wndClass.lpszClassName = className;
  923.     RegisterClass(&wndClass);
  924.  
  925.     /* Figure out a default size for the window */
  926.     winWidth = GetSystemMetrics(SM_CYSCREEN) / 3;
  927.     winHeight = GetSystemMetrics(SM_CYSCREEN) / 3;
  928.  
  929.     /* Create a window of the previously defined class */
  930.     hWnd = CreateWindow(
  931.     className, windowName,
  932.     WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
  933.     winX, winY, winWidth, winHeight,
  934.     NULL, NULL, hCurrentInst, NULL);
  935.  
  936.     /* Map the window to the screen */
  937.     ShowWindow(hWnd, nCmdShow);
  938.  
  939.     /* Force the window to repaint itself */
  940.     UpdateWindow(hWnd);
  941.  
  942.     /* Message loop */
  943.     while (1) {
  944.     while (idleFunc &&
  945.            PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) == FALSE)
  946.     {
  947.         (*idleFunc)();
  948.     }
  949.     if (GetMessage(&msg, NULL, 0, 0) != TRUE) {
  950.         break;
  951.     }
  952.     TranslateMessage(&msg);
  953.     DispatchMessage(&msg);
  954.     }
  955.     return msg.wParam;
  956. }
  957.  
  958. 
  959.