The Winamp Remote Control suite
a remote control client and plugin for Winamp 2.x, 5.x
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
AboutGLDisplay.cpp
Go to the documentation of this file.
1 /*
2  winamp remote control suite ŠPatrick Michael Martin 2000, 2001, 2012
3 
4  Copyright (C) 2000,2001,2012 Patrick M. Martin
5 
6  This program is free software; you can redistribute it and/or
7  modify it under the terms of the GNU General Public License
8  as published by the Free Software Foundation; either version 2
9  of the License, or (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 
20  Patrick M. Martin may be reached by email at patrickmmartin@gmail.com.
21  */
22 
23 /*
24  * AboutGLDisplay.cpp
25  *
26  * Created on: 6 Jul 2013
27  * Author: Patrick
28  */
29 
30 #include "AboutGLDisplay.h"
31 
32 #include <GL\gl.h>
33 #include <GL\glu.h>
34 
35 #define GLF_START_LIST 20000
36 #define TORUS 1
37 #define CUBE 2
38 #define SPHERE 3
39 
40 #include <sysutils.hpp>
41 
42 const GLfloat AboutGLDisplay::X_OFFSET_STEP = 5;
43 const GLfloat AboutGLDisplay::Y_OFFSET_STEP = 5;
44 
45 AboutGLDisplay::AboutGLDisplay(HDC hDC_, int clientWidth_, int clientHeight_) :
46  m_glOptions(), glyphMetrics(), hDC(hDC_), outText(), clientWidth(
47  clientWidth_), clientHeight(clientHeight_), mode(MoveNone), objectIndex(
48  3), objectNumMajor(32), objectNumMinor(32)
49 
50 {
51 
52  outText.push_back("Winamp");
53  outText.push_back("Remote");
54  outText.push_back("Control");
55 
56  setupPixelformat();
57  setupPalette();
58 
59  hGLRC = wglCreateContext(hDC);
60  wglMakeCurrent(hDC, hGLRC);
61  init();
62 
63  startup = GetTickCount();
64 
65 }
66 
68 {
69  if (hGLRC)
70  {
71  wglMakeCurrent(NULL, NULL);
72  wglDeleteContext(hGLRC);
73  }
74 }
75 
77 {
78  return m_glOptions;
79 }
80 
81 void AboutGLDisplay::setClientArea(int clientWidth_, int clientHeight_)
82 {
83  clientWidth = clientWidth_;
84  clientHeight = clientHeight_;
85 }
86 
87 void AboutGLDisplay::CreateFontList()
88 {
89 
90  // create text display list
91  LOGFONT lf;
92  HFONT hFont, hOldFont;
93 
94  glMatrixMode(GL_MODELVIEW);
95 
96  //sets up a display list for entire character set selected into DC
97  memset(&lf, 0, sizeof(LOGFONT));
98  lf.lfHeight = -48;
99  lf.lfWeight = FW_BOLD;
100  lf.lfCharSet = ANSI_CHARSET;
101  lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
102  lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
103  lf.lfQuality = DEFAULT_QUALITY;
104  lf.lfPitchAndFamily = FF_DONTCARE | DEFAULT_PITCH;
105  lstrcpy(lf.lfFaceName, "Arial");
106 
107  hFont = CreateFontIndirect(&lf);
108  hOldFont = SelectObject(hDC, hFont);
109 
110 // Create a set of display lists based on the glyphs of the TT font we selected
111 
112  /*
113  The wglUseFontOutlines function approximates glyph outlines
114  by subdividing the quadratic B-spline curves of the outline into line segments,
115  until the distance between the outline and the interpolated midpoint is within
116  the value specified by deviation.
117  This is the final format used when format is WGL_FONT_LINES.
118  When you specify WGL_FONT_OUTLINES, the display lists created don't contain
119  any normals; thus lighting doesn't work properly.
120  To get the correct lighting of lines use WGL_FONT_POLYGONS and set
121  glPolygonMode(GL_FRONT, GL_LINE).
122  When you specify format as WGL_FONT_POLYGONS the outlines are further
123  tessellated into separate triangles, triangle fans, triangle strips, or
124  quadrilateral strips to create the surface of each glyph.
125  With WGL_FONT_POLYGONS, the created display lists call glFrontFace(GL_CW)
126  or glFrontFace(GL_CCW); thus the current front-face value might be altered.
127  For the best appearance of text with WGL_FONT_POLYGONS, cull the back faces
128  as follows:
129 
130 
131  */
132 
133  glCullFace(GL_BACK);
134  glEnable(GL_CULL_FACE);
135 
136  // Create a set of display lists based on the glyphs of the TT font we selected
137  if (!(wglUseFontOutlines(hDC, 0, 127, GLF_START_LIST, 0.0f,
138  m_glOptions.textExtrusion, WGL_FONT_POLYGONS, glyphMetrics)))
139  {
140  AnsiString error = AnsiString("wglUseFontOutlines failed!")
141  + SysErrorMessage(GetLastError());
142  OutputDebugString(error.c_str());
143  throw error.c_str();
144  }
145  DeleteObject(SelectObject(hDC, hOldFont));
146 
147 }
148 
149 void AboutGLDisplay::CreateDisplayLists(void)
150 {
151  // the cube
152  glNewList(CUBE, GL_COMPILE);
153  //
154  // Draw the six faces of the cube.
155  //
156  glBegin(GL_QUADS);
157  glNormal3f(-1.0F, 0.0F, 0.0F);
158  glTexCoord2f(0.0F, 1.0F);
159  glVertex3f(-0.5F, -0.5F, -0.5F);
160  glTexCoord2f(0.0F, 0.0F);
161  glVertex3f(-0.5F, -0.5F, 0.5F);
162  glTexCoord2f(1.0F, 0.0F);
163  glVertex3f(-0.5F, 0.5F, 0.5F);
164  glTexCoord2f(1.0F, 1.0F);
165  glVertex3f(-0.5F, 0.5F, -0.5F);
166 
167  glNormal3f(1.0F, 0.0F, 0.0F);
168  glTexCoord2f(1.0F, 1.0F);
169  glVertex3f(0.5F, 0.5F, 0.5F);
170  glTexCoord2f(0.0F, 1.0F);
171  glVertex3f(0.5F, -0.5F, 0.5F);
172  glTexCoord2f(0.0F, 0.0F);
173  glVertex3f(0.5F, -0.5F, -0.5F);
174  glTexCoord2f(1.0F, 0.0F);
175  glVertex3f(0.5F, 0.5F, -0.5F);
176 
177  glNormal3f(0.0F, -1.0F, 0.0F);
178  glTexCoord2f(0.0F, 1.0F);
179  glVertex3f(-0.5F, -0.5F, -0.5F);
180  glTexCoord2f(0.0F, 0.0F);
181  glVertex3f(0.5F, -0.5F, -0.5F);
182  glTexCoord2f(1.0F, 0.0F);
183  glVertex3f(0.5F, -0.5F, 0.5F);
184  glTexCoord2f(1.0F, 1.0F);
185  glVertex3f(-0.5F, -0.5F, 0.5F);
186 
187  glNormal3f(0.0F, 1.0F, 0.0F);
188  glTexCoord2f(1.0F, 1.0F);
189  glVertex3f(0.5F, 0.5F, 0.5F);
190  glTexCoord2f(0.0F, 1.0F);
191  glVertex3f(0.5F, 0.5F, -0.5F);
192  glTexCoord2f(0.0F, 0.0F);
193  glVertex3f(-0.5F, 0.5F, -0.5F);
194  glTexCoord2f(1.0F, 0.0F);
195  glVertex3f(-0.5F, 0.5F, 0.5F);
196 
197  glNormal3f(0.0F, 0.0F, -1.0F);
198  glTexCoord2f(0.0F, 1.0F);
199  glVertex3f(-0.5F, -0.5F, -0.5F);
200  glTexCoord2f(0.0F, 0.0F);
201  glVertex3f(-0.5F, 0.5F, -0.5F);
202  glTexCoord2f(1.0F, 0.0F);
203  glVertex3f(0.5F, 0.5F, -0.5F);
204  glTexCoord2f(1.0F, 1.0F);
205  glVertex3f(0.5F, -0.5F, -0.5F);
206 
207  glNormal3f(0.0F, 0.0F, 1.0F);
208  glTexCoord2f(1.0F, 1.0F);
209  glVertex3f(0.5F, 0.5F, 0.5F);
210  glTexCoord2f(0.0F, 1.0F);
211  glVertex3f(-0.5F, 0.5F, 0.5F);
212  glTexCoord2f(0.0F, 0.0F);
213  glVertex3f(-0.5F, -0.5F, 0.5F);
214  glTexCoord2f(1.0F, 0.0F);
215  glVertex3f(0.5F, -0.5F, 0.5F);
216  glEnd();
217  glEndList();
218 
219  // the cube
220  glNewList(SPHERE, GL_COMPILE);
221  glEndList();
222 
223  // the cube
224  glNewList(TORUS, GL_COMPILE);
225  glEndList();
226 
227 }
228 
229 void AboutGLDisplay::drawText(void) const
230 {
231 
232  unsigned int index, i;
233 
234  double xoffset = 0;
235  double yoffset;
236  int textIndex;
237 
238  yoffset = glyphMetrics[0].gmfBlackBoxY;
239 
240  textIndex = ((GetTickCount() - startup) / 2000) % (outText.size());
241 
242  std::string text = outText[textIndex];
243  for (i = 0; i < text.size(); i++)
244  {
245  // index into the glyph metrics to get the position info
246  index = (int) outText[textIndex].c_str()[i];
247  xoffset += glyphMetrics[index].gmfBlackBoxX;
248  }
249 
250  // notes re text : face sense gets screwed (maybe)
251 
252  glTranslatef(-xoffset / 2, -yoffset / 2, m_glOptions.textExtrusion / 2);
253  glListBase(GLF_START_LIST);
254  glCallLists( static_cast<int> ( text.size() ), GL_UNSIGNED_BYTE, reinterpret_cast<const void *> (text.c_str()) );
255  glListBase(0);
256  glTranslatef(xoffset / 2, yoffset / 2, -m_glOptions.textExtrusion / 2);
257 
258 }
259 ;
260 
261 void AboutGLDisplay::drawCube(void) const
262 {
263  glPushMatrix(); //push nice view
264  glScalef(1, 1, 1);
265  glListBase(0);
266  glCallList(CUBE);
267  glPopMatrix(); //pop nice view
268 }
269 
270 void AboutGLDisplay::drawTorus(void) const
271 {
272  struct vertex
273  {
274  GLfloat t[2];
275  GLfloat n[3];
276  GLfloat v[3];
277  };
278 
279  int numVerts = (objectNumMajor + 1) * (objectNumMinor + 1);
280  int numStrips =
281  m_glOptions.halfObject ? objectNumMajor / 2 : objectNumMajor;
282  int numPerStrip = 2 * (objectNumMinor + 1);
283  int numElements = (objectNumMajor + 1) * numPerStrip;
284 
285  static struct vertex *vertexArray, *v;
286  static GLuint *elementArray, *e;
287  static int numMajor;
288  static int numMinor;
289  int i, j;
290 
291  if (!vertexArray || numMajor != objectNumMajor
292  || numMinor != objectNumMinor)
293  {
294  float majorRadius = 0.6F;
295  float minorRadius = 0.2F;
296  double majorStep = 2.0F * M_PI / objectNumMajor;
297  double minorStep = 2.0F * M_PI / objectNumMinor;
298 
299  if (vertexArray)
300  free(vertexArray);
301  vertexArray = (struct vertex *) calloc(numVerts, sizeof(struct vertex));
302 
303  if (elementArray)
304  free(elementArray);
305  elementArray = (GLuint *) calloc(numElements, sizeof(GLuint));
306 
307  numMajor = objectNumMajor;
308  numMinor = objectNumMinor;
309 
310  v = vertexArray;
311  e = elementArray;
312  for (i = 0; i <= numMajor; ++i)
313  {
314  double a = i * majorStep;
315  GLfloat x = (GLfloat) cos(a);
316  GLfloat y = (GLfloat) sin(a);
317 
318  for (j = 0; j <= numMinor; ++j)
319  {
320  double b = j * minorStep;
321  GLfloat c = (GLfloat) cos(b);
322  GLfloat r = minorRadius * c + majorRadius;
323  GLfloat z = minorRadius * (GLfloat) sin(b);
324 
325  v->t[0] = i / (GLfloat) numMajor;
326  v->t[1] = j / (GLfloat) numMinor;
327 
328  v->n[0] = x * c;
329  v->n[1] = y * c;
330  v->n[2] = z / minorRadius;
331 
332  v->v[0] = x * r;
333  v->v[1] = y * r;
334  v->v[2] = z;
335 
336  v++;
337 
338  *e++ = i * (numMinor + 1) + j;
339  *e++ = (i + 1) * (numMinor + 1) + j;
340  }
341  }
342  }
343 
344  if (m_glOptions.useVertexArray)
345  {
346  glInterleavedArrays(GL_T2F_N3F_V3F, 0, vertexArray);
347 
348 #if defined(GL_SGI_compiled_vertex_array)
349  if (useVertexLocking && LockArrays) LockArrays(0, numVerts);
350 #endif
351 
352  for (i = 0, e = elementArray; i < numStrips; ++i, e += numPerStrip)
353  {
354  glDrawElements(GL_TRIANGLE_STRIP, numPerStrip, GL_UNSIGNED_INT, e);
355  }
356 
357 #if defined(GL_SGI_compiled_vertex_array)
358  if (useVertexLocking && UnlockArrays) UnlockArrays();
359 #endif
360  }
361  else
362  {
363  for (i = 0, e = elementArray; i < numStrips; ++i, e += numPerStrip)
364  {
365  glBegin(GL_TRIANGLE_STRIP);
366  for (j = 0; j < numPerStrip; ++j)
367  {
368  v = &vertexArray[e[j]];
369 
370  glTexCoord2fv(v->t);
371  glNormal3fv(v->n);
372  glVertex3fv(v->v);
373  }
374  glEnd();
375  }
376  }
377 }
378 
379 void AboutGLDisplay::drawSphere(void) const
380 {
381  struct vertex
382  {
383  GLfloat t[2];
384  GLfloat n[3];
385  GLfloat v[3];
386  };
387 
388  int numVerts = (objectNumMajor + 1) * (objectNumMinor + 1);
389  int numStrips =
390  m_glOptions.halfObject ? objectNumMajor / 2 : objectNumMajor;
391  int numPerStrip = 2 * (objectNumMinor + 1);
392  int numElements = (objectNumMajor + 1) * numPerStrip;
393 
394  static struct vertex *vertexArray, *v;
395  static GLuint *elementArray, *e;
396  static int numMajor;
397  static int numMinor;
398  int i, j;
399 
400  if (!vertexArray || numMajor != objectNumMajor
401  || numMinor != objectNumMinor)
402  {
403  float radius = 0.6F;
404  double majorStep = 2.0F * M_PI / objectNumMajor;
405  double minorStep = M_PI / objectNumMinor;
406 
407  if (vertexArray)
408  free(vertexArray);
409  vertexArray = (struct vertex *) calloc(numVerts, sizeof(struct vertex));
410 
411  if (elementArray)
412  free(elementArray);
413  elementArray = (GLuint *) calloc(numElements, sizeof(GLuint));
414 
415  numMajor = objectNumMajor;
416  numMinor = objectNumMinor;
417 
418  v = vertexArray;
419  e = elementArray;
420  for (i = 0; i <= numMajor; ++i)
421  {
422  double a = i * majorStep;
423  GLfloat x = (GLfloat) cos(a);
424  GLfloat y = (GLfloat) sin(a);
425 
426  for (j = 0; j <= numMinor; ++j)
427  {
428  double b = j * minorStep;
429  GLfloat c = (GLfloat) sin(b);
430  GLfloat r = c * radius;
431  GLfloat z = (GLfloat) cos(b);
432 
433  v->t[0] = i / (GLfloat) numMajor;
434  v->t[1] = j / (GLfloat) numMinor;
435 
436  v->n[0] = x * c;
437  v->n[1] = y * c;
438  v->n[2] = z;
439 
440  v->v[0] = x * r;
441  v->v[1] = y * r;
442  v->v[2] = z * radius;
443 
444  v++;
445 
446  *e++ = (i + 1) * (numMinor + 1) + j;
447  *e++ = i * (numMinor + 1) + j;
448  }
449  }
450  }
451 
452  if (m_glOptions.useVertexArray)
453  {
454  glInterleavedArrays(GL_T2F_N3F_V3F, 0, vertexArray);
455 
456 #if defined(GL_SGI_compiled_vertex_array)
457  if (useVertexLocking && LockArrays) LockArrays(0, numVerts);
458 #endif
459 
460  for (i = 0, e = elementArray; i < numStrips; ++i, e += numPerStrip)
461  {
462  glDrawElements(GL_TRIANGLE_STRIP, numPerStrip, GL_UNSIGNED_INT, e);
463  }
464 
465 #if defined(GL_SGI_compiled_vertex_array)
466  if (useVertexLocking && UnlockArrays) UnlockArrays();
467 #endif
468  }
469  else
470  {
471  for (i = 0, e = elementArray; i < numStrips; ++i, e += numPerStrip)
472  {
473  glBegin(GL_TRIANGLE_STRIP);
474  for (j = 0; j < numPerStrip; ++j)
475  {
476  v = &vertexArray[e[j]];
477 
478  glTexCoord2fv(v->t);
479  glNormal3fv(v->n);
480  glVertex3fv(v->v);
481  }
482  glEnd();
483  }
484  }
485 }
486 
487 void AboutGLDisplay::setCheckTexture(void) const
488 {
489  int texWidth = 256;
490  int texHeight = 256;
491  GLubyte *texPixels, *p;
492  int texSize;
493  int i, j;
494 
495  texSize = texWidth * texHeight * 4 * sizeof(GLubyte);
496  if (m_glOptions.textureReplace)
497  {
498  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
499  }
500  else
501  {
502  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
503  }
504 
505  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
506  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
507  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
508  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
509 
510  texPixels = (GLubyte *) malloc(texSize);
511  if (texPixels == NULL)
512  {
513  return;
514  }
515 
516  p = texPixels;
517  for (i = 0; i < texHeight; ++i)
518  {
519  for (j = 0; j < texWidth; ++j)
520  {
521  if ((i ^ j) & 32)
522  {
523  p[0] = 0xff;
524  p[1] = 0xff;
525  p[2] = 0xff;
526  p[3] = 0xff;
527  }
528  else
529  {
530  p[0] = 0x10;
531  p[1] = 0x10;
532  p[2] = 0x10;
533  p[3] = 0xff;
534  }
535  p += 4;
536  }
537  }
538 
539  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texWidth, texHeight, 0, GL_RGBA,
540  GL_UNSIGNED_BYTE, texPixels);
541 
542  free(texPixels);
543 }
544 
545 void matrixIdentity(GLfloat m[4][4])
546 {
547  m[0][0] = 1.0F;
548  m[0][1] = 0.0F;
549  m[0][2] = 0.0F;
550  m[0][3] = 0.0F;
551  m[1][0] = 0.0F;
552  m[1][1] = 1.0F;
553  m[1][2] = 0.0F;
554  m[1][3] = 0.0F;
555  m[2][0] = 0.0F;
556  m[2][1] = 0.0F;
557  m[2][2] = 1.0F;
558  m[2][3] = 0.0F;
559  m[3][0] = 0.0F;
560  m[3][1] = 0.0F;
561  m[3][2] = 0.0F;
562  m[3][3] = 1.0F;
563 }
564 
565 
567 {
568  GLfloat aspect = (GLfloat) clientWidth / (GLfloat) clientHeight;
569 
570  glMatrixMode(GL_PROJECTION);
571  glLoadIdentity();
572  gluPerspective(60.0, // Field-of-view angle
573  aspect, // Aspect ratio of viewing volume
574  0.1, // Distance to near clipping plane
575  100.0); // Distance to far clipping plane
576  glViewport(0, 0, clientWidth, clientHeight);
577 
578  glMatrixMode(GL_MODELVIEW);
579 }
580 
581 void AboutGLDisplay::setMaterial(void) const
582 {
583  GLfloat matAmb[4] =
584  { 0.01F, 0.01F, 0.01F, 1.00F };
585  GLfloat matDiff[4] =
586  { 0.45F, 0.05F, 0.65F, 0.60F };
587  GLfloat matSpec[4] =
588  { 0.50F, 0.50F, 0.50F, 1.00F };
589  GLfloat matShine = 20.00F;
590 
591  glMaterialfv(GL_FRONT, GL_AMBIENT, matAmb);
592  glMaterialfv(GL_FRONT, GL_DIFFUSE, matDiff);
593  glMaterialfv(GL_FRONT, GL_SPECULAR, matSpec);
594  glMaterialf(GL_FRONT, GL_SHININESS, matShine);
595 }
596 
597 void AboutGLDisplay::init(void)
598 {
599 
600  GLfloat light0Pos[4] =
601  { 0.70F, 0.70F, 1.25F, 0.00F };
602  GLfloat fogDensity = 1.35F * 0.180F;
603 
604  GLfloat fogColor[4] =
605  {
606  /*
607  0.4F, 0.4F, 0.5F, 1.0F,
608  */
609  0.0F, 0.0F, 0.0F, 1.0F,
610 
611  };
612 
613 #if defined(GL_SGI_cull_vertex)
614  CullParameterfv = (PFNGLCULLPARAMETERFVSGIPROC)
615  wglGetProcAddress("glCullParameterfvSGI");
616 #endif
617 
618 #if defined(GL_SGI_compiled_vertex_array)
619  LockArrays = (PFNGLLOCKARRAYSSGIPROC)
620  wglGetProcAddress("glLockArraysSGI");
621  UnlockArrays = (PFNGLUNLOCKARRAYSSGIPROC)
622  wglGetProcAddress("glUnlockArraysSGI");
623 #endif
624 
625  glFogi(GL_FOG_MODE, GL_EXP2);
626  glFogf(GL_FOG_DENSITY, fogDensity);
627  glFogfv(GL_FOG_COLOR, fogColor);
628 
629  setProjection();
630  glTranslatef(0.0F, 0.0F, -2.0F);
631 
632  setMaterial();
633 
634  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
635  glLightfv(GL_LIGHT0, GL_POSITION, light0Pos);
636  glEnable(GL_LIGHT0);
637 
638  setCheckTexture();
639 
640  matrixIdentity(objectXform);
641 
642  CreateFontList();
643  CreateDisplayLists();
644 }
645 
646 void AboutGLDisplay::resize(void) const
647 {
648  setProjection();
649  glViewport(0, 0, clientWidth, clientHeight);
650 }
651 
652 void AboutGLDisplay::redraw(void) const
653 {
654  try {
655 
656  glEnable(GL_DEPTH_TEST);
657  glEnable(GL_CULL_FACE);
658 
659  /* required for antialising */
660  // glEnable(GL_BLEND);
661 
662  /* "To antialias points or lines in Opengl,
663  you need to enable antialiasing by calling glEnable()
664  and passing in GL_POINT_SMOOTH or GL_LINE_SMOOTH,
665  as appropriate.
666  You can also provide a quality hint by calling glHint().
667  The hint parameter can be GL_FASTEST to indicate that
668  the most efficient option should be chosen,
669  GL_NICEST to indicate the highest quality option should be chosen,
670  or GL_DONT_CARE to indicate no preference.
671  */
672 
673  glEnable(GL_POINT_SMOOTH);
674  glEnable(GL_LINE_SMOOTH);
675 
676  glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
677  glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
678 
679  glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST);
680  glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST);
681 
682  //constant background
683  if (m_glOptions.useFog)
684  {
685  // glClearColor(0.4F, 0.4F, 0.5F, 1.0F);
686  glClearColor(0.0F, 0.0F, 0.0F, 1.0F);
687  glEnable(GL_FOG);
688  }
689  else
690  {
691  // glClearColor(0.2F, 0.2F, 0.1F, 1.0F);
692  glClearColor(0.0F, 0.0F, 0.0F, 1.0F);
693  glDisable(GL_FOG);
694  }
695 
696  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
697 
698  // update transformations
699  if (mode == MoveObject)
700  {
701  glPushMatrix();
702  glLoadIdentity();
703  glRotatef( angle , axis[0], axis[1], axis[2]); glMultMatrixf((GLfloat *) objectXform);
704  glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) objectXform);
705  glPopMatrix();
706  }
707 
708  if (m_glOptions.textureEnabled)
709  {
710  glEnable(GL_TEXTURE_2D);
711  }
712  if (m_glOptions.drawOutlines)
713  {
714  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
715  }
716  #if defined(GL_SGI_cull_vertex)
717  if (useVertexCull)
718  {
719  glEnable(GL_CULL_VERTEX_SGI);
720  }
721  #endif
722  if (m_glOptions.useFaceCull)
723  {
724  glEnable(GL_CULL_FACE);
725  }
726  if (m_glOptions.useLighting)
727  {
728  glEnable(GL_LIGHTING);
729  }
730  glEnable(GL_DEPTH_TEST);
731 
732  glPushMatrix();
733  glTranslatef(xOffset, yOffset, 0.0F);
734  glMultMatrixf((GLfloat *) objectXform);
735 
736  switch (objectIndex)
737  {
738  case 0:
739  glFrontFace(GL_CCW);
740  drawTorus();
741  break;
742  case 1:
743  glFrontFace(GL_CCW);
744  drawSphere();
745  break;
746  case 2:
747  glFrontFace(GL_CCW);
748  drawCube();
749  break;
750  case 3:
751  glFrontFace(GL_CW);
752  drawText();
753  break;
754  }
755 
756  glPopMatrix();
757 
758  glDisable(GL_TEXTURE_2D);
759  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
760  #if defined(GL_SGI_cull_vertex)
761  glDisable(GL_CULL_VERTEX_SGI);
762  #endif
763  glDisable(GL_CULL_FACE);
764  glDisable(GL_LIGHTING);
765  glDisable(GL_DEPTH_TEST);
766 
767  glFlush();
768  SwapBuffers(hDC);
769  }
770  catch ( ... )
771  {
772  // dunno
773  }
774 }
775 
776 void AboutGLDisplay::ptov(int x, int y, int width, int height, float v[3])
777 {
778  float d, a;
779 
780  // project x,y onto a hemi-sphere centered within width, height
781  v[0] = (2.0F * x - width) / width;
782  v[1] = (height - 2.0F * y) / height;
783  d = (float) sqrt(v[0] * v[0] + v[1] * v[1]);
784  v[2] = (float) cos((M_PI / 2.0F) * ((d < 1.0F) ? d : 1.0F));
785  a = 1.0F / (float) sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
786  v[0] *= a;
787  v[1] *= a;
788  v[2] *= a;
789 }
790 
791 void AboutGLDisplay::startMotion(DWORD /* time */, int button, int x, int y)
792 {
793  if (button == 1)
794  {
795  mode = MoveObject;
796  }
797  else
798  {
799  return;
800  }
801 
802  trackingMotion = TRUE;
803  startX = x;
804  startY = y;
805  ptov(x, y, clientWidth, clientHeight, lastPos);
806 }
807 
808 void AboutGLDisplay::stopMotion(DWORD /* time */, int button, int x, int y)
809 {
810  if (button == 1 && mode == MoveObject)
811  {
812  trackingMotion = FALSE;
813  }
814  else
815  {
816  return;
817  }
818 
819  if (startX != x || startY != y)
820  {
821  }
822  else
823  {
824  angle = 0.0F;
825  }
826 }
827 
828 void AboutGLDisplay::trackMotion(DWORD /* time */, int x, int y)
829 {
830  if (trackingMotion)
831  {
832  float curPos[3], dx, dy, dz;
833 
834  ptov(x, y, clientWidth, clientHeight, curPos);
835 
836  dx = curPos[0] - lastPos[0];
837  dy = curPos[1] - lastPos[1];
838  dz = curPos[2] - lastPos[2];
839  angle = 90.0F * (float) sqrt(dx * dx + dy * dy + dz * dz);
840 
841  axis[0] = lastPos[1] * curPos[2] - lastPos[2] * curPos[1];
842  axis[1] = lastPos[2] * curPos[0] - lastPos[0] * curPos[2];
843  axis[2] = lastPos[0] * curPos[1] - lastPos[1] * curPos[0];
844 
845  lastPos[0] = curPos[0];
846  lastPos[1] = curPos[1];
847  lastPos[2] = curPos[2];
848  }
849 }
850 
851 void AboutGLDisplay::setupPalette() const
852 {
853  PIXELFORMATDESCRIPTOR pfd;
854  LOGPALETTE* pPal;
855  int pixelFormat = GetPixelFormat(hDC);
856  int paletteSize;
857 
858  DescribePixelFormat(hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
859  if (!((pfd.dwFlags & PFD_NEED_PALETTE)
860  || (pfd.iPixelType == PFD_TYPE_COLORINDEX)))
861  {
862  return;
863  }
864 
865  paletteSize = 1 << pfd.cColorBits;
866  pPal = (LOGPALETTE*) malloc(
867  sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY));
868  pPal->palVersion = 0x300;
869  pPal->palNumEntries = (WORD) paletteSize;
870 
871  // start with a copy of the current system palette
872  (void) GetSystemPaletteEntries(hDC, 0, paletteSize, &pPal->palPalEntry[0]);
873 
874  {
875  // fill in an RGBA color palette
876  int redMask = (1 << pfd.cRedBits) - 1;
877  int greenMask = (1 << pfd.cGreenBits) - 1;
878  int blueMask = (1 << pfd.cBlueBits) - 1;
879  int i;
880 
881  for (i = 0; i < paletteSize; ++i)
882  {
883  pPal->palPalEntry[i].peRed = (GLbyte) ((((i >> pfd.cRedShift)
884  & redMask) * 255) / redMask);
885  pPal->palPalEntry[i].peGreen = (GLbyte) ((((i >> pfd.cGreenShift)
886  & greenMask) * 255) / greenMask);
887  pPal->palPalEntry[i].peBlue = (GLbyte) ((((i >> pfd.cBlueShift)
888  & blueMask) * 255) / blueMask);
889  pPal->palPalEntry[i].peFlags = 0;
890  }
891  }
892 
893  HPALETTE hPalette;
894  hPalette = CreatePalette(pPal);
895  free(pPal);
896 
897  if (hPalette)
898  {
899  SelectPalette(hDC, hPalette, FALSE);
900  RealizePalette(hDC);
901  }
902 }
903 
904 void AboutGLDisplay::setupPixelformat() const
905 {
906  PIXELFORMATDESCRIPTOR pfd =
907  { sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
908  1, // version num
909  PFD_DRAW_TO_WINDOW | // support window
910  PFD_SUPPORT_OPENGL, // support OpenGL
911  PFD_TYPE_RGBA, // color type
912  8, // 8-bit color depth
913  0, 0, 0, 0, 0, 0, // color bits (ignored)
914  0, // no alpha buffer
915  0, // alpha bits (ignored)
916  0, // no accumulation buffer
917  0, 0, 0, 0, // accum bits (ignored)
918  0, // depth buffer (filled below)
919  0, // no stencil buffer
920  0, // no auxiliary buffers
921  PFD_MAIN_PLANE, // main layer
922  0, // reserved
923  0, 0, 0, // no layer, visible, damage masks
924  };
925  int SelectedPixelFormat;
926  BOOL retVal;
927 
928  if (m_glOptions.doubleBuffered)
929  {
930  pfd.dwFlags |= PFD_DOUBLEBUFFER;
931  }
932 
933  if (m_glOptions.depthBuffered)
934  {
935  pfd.cDepthBits = 16;
936  }
937 
938  SelectedPixelFormat = ChoosePixelFormat(hDC, &pfd);
939  if (SelectedPixelFormat == 0)
940  {
941  throw "ChoosePixelFormat failed";
942  }
943 
944  retVal = SetPixelFormat(hDC, SelectedPixelFormat, &pfd);
945  if (retVal != TRUE)
946  {
947  MessageBox(WindowFromDC(hDC), "SetPixelFormat failed", "Error",
948  MB_ICONERROR | MB_OK);
949  exit(1);
950  }
951 }
952