Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

778 lines
19 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: glwindow.c
  3. *
  4. * OpenGL window maintenance.
  5. *
  6. * Created: 09-Mar-1995 15:10:10
  7. * Author: Gilman Wong [gilmanw]
  8. *
  9. * Copyright (c) 1995 Microsoft Corporation
  10. *
  11. \**************************************************************************/
  12. #include <windows.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <ctype.h>
  16. #include "global.h"
  17. #include "glwindow.h"
  18. #include "nff.h"
  19. #include "trackbal.h"
  20. // Move global stuff into SCENE struct.
  21. HGLRC ghrc = (HGLRC) 0;
  22. HPALETTE ghpalOld, ghPalette = (HPALETTE) 0;
  23. BOOL bUseStatic = FALSE;
  24. UINT uiSysPalUse = SYSPAL_STATIC;
  25. extern void DoGlStuff(HWND, HDC);
  26. extern HGLRC hrcInitGL(HWND, HDC);
  27. extern void stateInit(HWND, HDC);
  28. extern void vCleanupGL(HGLRC, HDC);
  29. extern BOOL bSetupPixelFormat(HDC);
  30. extern void CreateRGBPalette(HDC);
  31. extern VOID vSetSize(HWND);
  32. extern void ForceRedraw(HWND);
  33. extern SCENE *OpenScene(LPSTR lpstrFile);
  34. CHAR lpstrFile[256];
  35. // Global ambient lights.
  36. static GLfloat lightAmbient[4] = {0.4f, 0.4f, 0.4f, 1.0f};
  37. static GLfloat lightAmbientLow[4] = {0.2f, 0.2f, 0.2f, 1.0f};
  38. //!!!move to SCENE structure
  39. // Trackball stuff
  40. POINT gptWindow;
  41. SIZE gszWindow; // already in SCENE
  42. float curquat[4], lastquat[4];
  43. LONG glMouseDownX, glMouseDownY;
  44. BOOL gbLeftMouse = FALSE;
  45. BOOL gbSpinning = FALSE;
  46. float zoom = 1.0f;
  47. //!!!move to SCENE structure
  48. typedef enum enumPOLYDRAW {
  49. POLYDRAW_FILLED = 0,
  50. POLYDRAW_LINES = 1,
  51. POLYDRAW_POINTS = 2
  52. } POLYDRAW;
  53. typedef enum enumSHADE {
  54. SHADE_SMOOTH = 0,
  55. SHADE_FLAT = 1
  56. } SHADE;
  57. typedef enum enumLIGHT {
  58. LIGHT_OFF = 0,
  59. LIGHT_INFINITE = 1,
  60. LIGHT_LOCAL = 2
  61. } LIGHT;
  62. SHADE gShadeMode = SHADE_SMOOTH;
  63. POLYDRAW gPolyDrawMode = POLYDRAW_FILLED;
  64. LIGHT gLightMode = LIGHT_INFINITE;
  65. /******************************Public*Routine******************************\
  66. * MyCreateGLWindow
  67. *
  68. * Setup the windows.
  69. *
  70. * History:
  71. * 15-Dec-1994 -by- Gilman Wong [gilmanw]
  72. * Wrote it.
  73. \**************************************************************************/
  74. HWND MyCreateGLWindow(HINSTANCE hInstance, LPTSTR lpstr)
  75. {
  76. WNDCLASS wc;
  77. RECT rcl;
  78. HWND hwnd;
  79. lstrcpy(lpstrFile, lpstr);
  80. // Create the OpenGL window.
  81. wc.style = CS_OWNDC;
  82. wc.lpfnWndProc = GLWndProc;
  83. wc.cbClsExtra = 0;
  84. wc.cbWndExtra = 0;
  85. wc.hInstance = hInstance;
  86. wc.hIcon = NULL;
  87. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  88. wc.hbrBackground = GetStockObject(WHITE_BRUSH);
  89. wc.lpszMenuName = NULL;
  90. wc.lpszClassName = "GLWClass";
  91. RegisterClass(&wc);
  92. hwnd = CreateWindow(
  93. "GLWClass",
  94. "OpenGL stuff",
  95. WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
  96. //CW_USEDEFAULT,
  97. //CW_USEDEFAULT,
  98. 300,
  99. 0,
  100. 100,
  101. 100,
  102. NULL,
  103. NULL,
  104. hInstance,
  105. NULL
  106. );
  107. //!!!hack -- not really the right coordinates
  108. gptWindow.x = 0;
  109. gptWindow.y = 300;
  110. gszWindow.cx = 100;
  111. gszWindow.cy = 100;
  112. if (hwnd)
  113. {
  114. ShowWindow(hwnd, SW_NORMAL);
  115. UpdateWindow(hwnd);
  116. }
  117. SetTimer(hwnd, 1, 1, NULL);
  118. return hwnd;
  119. }
  120. /******************************Public*Routine******************************\
  121. * GLWndProc
  122. *
  123. * WndProc for the OpenGL window.
  124. *
  125. * History:
  126. * 15-Dec-1994 -by- Gilman Wong [gilmanw]
  127. * Wrote it.
  128. \**************************************************************************/
  129. long FAR PASCAL GLWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  130. {
  131. long lRet = 0;
  132. RECT rcl;
  133. HDC hdc;
  134. PAINTSTRUCT ps;
  135. SCENE *scene;
  136. if (message != WM_CREATE)
  137. scene = (SCENE *) GetWindowLong(hwnd, GWL_USERDATA);
  138. // Process window message.
  139. switch (message)
  140. {
  141. case WM_CREATE:
  142. //LBprintf("WM_CREATE");
  143. if(hdc = GetDC(hwnd))
  144. {
  145. if (ghrc == (HGLRC) 0)
  146. ghrc = hrcInitGL(hwnd, hdc);
  147. scene = OpenScene(lpstrFile);
  148. if (scene)
  149. {
  150. SetWindowLong(hwnd, GWL_USERDATA, (LONG) scene);
  151. rcl.left = 0;
  152. rcl.top = 0;
  153. rcl.right = scene->szWindow.cx;
  154. rcl.bottom = scene->szWindow.cy;
  155. AdjustWindowRect(&rcl, WS_OVERLAPPEDWINDOW, 0);
  156. SetWindowPos(hwnd, NULL, 0, 0,
  157. rcl.right, rcl.bottom,
  158. SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOCOPYBITS);
  159. stateInit(hwnd, hdc);
  160. }
  161. else
  162. lRet = -1;
  163. ReleaseDC(hwnd,hdc);
  164. }
  165. break;
  166. case WM_MOVE:
  167. gptWindow.x = (int) LOWORD(lParam);
  168. gptWindow.y = (int) HIWORD(lParam);
  169. break;
  170. case WM_SIZE:
  171. gszWindow.cx = LOWORD(lParam);
  172. gszWindow.cy = HIWORD(lParam);
  173. scene->szWindow.cx = LOWORD(lParam);
  174. scene->szWindow.cy = HIWORD(lParam);
  175. vSetSize(hwnd);
  176. ForceRedraw(hwnd);
  177. break;
  178. case WM_PAINT:
  179. //LBprintf("WM_PAINT");
  180. hdc = BeginPaint( hwnd, &ps );
  181. DoGlStuff( hwnd, hdc );
  182. EndPaint( hwnd, &ps );
  183. break;
  184. case WM_PALETTECHANGED:
  185. //LBprintf("WM_PALETTECHANGED");
  186. if (hwnd != (HWND) wParam)
  187. {
  188. if (hdc = GetDC(hwnd))
  189. {
  190. UnrealizeObject(ghPalette);
  191. SelectPalette(hdc, ghPalette, TRUE);
  192. if (RealizePalette(hdc) != GDI_ERROR)
  193. lRet = 1;
  194. }
  195. }
  196. break;
  197. case WM_QUERYNEWPALETTE:
  198. //LBprintf("WM_QUERYNEWPALETTE");
  199. if (hdc = GetDC(hwnd))
  200. {
  201. UnrealizeObject(ghPalette);
  202. SelectPalette(hdc, ghPalette, FALSE);
  203. if (RealizePalette(hdc) != GDI_ERROR)
  204. lRet = 1;
  205. }
  206. break;
  207. case WM_KEYDOWN:
  208. switch (wParam)
  209. {
  210. case VK_ESCAPE: // <ESC> is quick exit
  211. PostMessage(hwnd, WM_DESTROY, 0, 0);
  212. break;
  213. case VK_UP:
  214. zoom *= .8f;
  215. if (zoom < 1.0f && zoom > .8f)
  216. zoom = 1.0f;
  217. LBprintf("Zoom = %f", zoom);
  218. vSetSize(hwnd);
  219. break;
  220. case VK_DOWN:
  221. zoom *= 1.25f;
  222. if (zoom > 1.0f && zoom < 1.25f)
  223. zoom = 1.0f;
  224. LBprintf("Zoom = %f", zoom);
  225. vSetSize(hwnd);
  226. break;
  227. default:
  228. break;
  229. }
  230. break;
  231. case WM_CHAR:
  232. switch(wParam)
  233. {
  234. case 's':
  235. case 'S':
  236. gShadeMode = (gShadeMode + 1) % 2;
  237. glShadeModel( gShadeMode == SHADE_FLAT ? GL_FLAT : GL_SMOOTH );
  238. LBprintf("glShadeModel(%s)", gShadeMode == SHADE_FLAT ? "GL_FLAT" :
  239. "GL_SMOOTH");
  240. break;
  241. case 'p':
  242. case 'P':
  243. gPolyDrawMode = (gPolyDrawMode + 1) % 3;
  244. switch (gPolyDrawMode)
  245. {
  246. case POLYDRAW_POINTS:
  247. glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
  248. break;
  249. case POLYDRAW_LINES:
  250. glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  251. break;
  252. case POLYDRAW_FILLED:
  253. default:
  254. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  255. break;
  256. }
  257. LBprintf("glPolygonMode(%s)", gPolyDrawMode == POLYDRAW_POINTS ? "GL_POINT" :
  258. gPolyDrawMode == POLYDRAW_LINES ? "GL_LINE" :
  259. "GL_FILL");
  260. break;
  261. case 'l':
  262. case 'L':
  263. gLightMode = (gLightMode + 1) % 3;
  264. if ( gLightMode != LIGHT_OFF )
  265. {
  266. int i;
  267. glEnable(GL_NORMALIZE);
  268. glEnable(GL_LIGHTING);
  269. glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
  270. glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,
  271. gLightMode == LIGHT_LOCAL ? GL_TRUE : GL_FALSE);
  272. for (i = 0; i < scene->Lights.count; i++)
  273. {
  274. glCallList(scene->Lights.listBase + i);
  275. glEnable(GL_LIGHT0 + i);
  276. }
  277. /* If no other lights, turn on ambient on higher */
  278. if (!scene->Lights.count)
  279. glLightModelfv(GL_LIGHT_MODEL_AMBIENT, &lightAmbient);
  280. else
  281. glLightModelfv(GL_LIGHT_MODEL_AMBIENT, &lightAmbientLow);
  282. }
  283. else
  284. {
  285. glDisable(GL_NORMALIZE);
  286. glDisable(GL_LIGHTING);
  287. }
  288. LBprintf("Light = %s", gLightMode == LIGHT_OFF ? "disabled" :
  289. gLightMode == LIGHT_INFINITE ? "infinite" :
  290. "local");
  291. break;
  292. default:
  293. break;
  294. }
  295. ForceRedraw(hwnd);
  296. break;
  297. case WM_LBUTTONDOWN:
  298. SetCapture(hwnd);
  299. glMouseDownX = LOWORD(lParam);
  300. glMouseDownY = HIWORD(lParam);
  301. gbLeftMouse = TRUE;
  302. ForceRedraw(hwnd);
  303. break;
  304. case WM_LBUTTONUP:
  305. ReleaseCapture();
  306. gbLeftMouse = FALSE;
  307. ForceRedraw(hwnd);
  308. break;
  309. case WM_TIMER:
  310. hdc = GetDC(hwnd);
  311. DoGlStuff( hwnd, hdc );
  312. ReleaseDC(hwnd, hdc);
  313. break;
  314. case WM_DESTROY:
  315. KillTimer(hwnd, 1);
  316. hdc = GetDC(hwnd);
  317. vCleanupGL(ghrc, hdc);
  318. ReleaseDC(hwnd, hdc);
  319. PostQuitMessage( 0 );
  320. break;
  321. default:
  322. lRet = DefWindowProc(hwnd, message, wParam, lParam);
  323. break;
  324. }
  325. return lRet;
  326. }
  327. unsigned char threeto8[8] = {
  328. 0, 0111>>1, 0222>>1, 0333>>1, 0444>>1, 0555>>1, 0666>>1, 0377
  329. };
  330. unsigned char twoto8[4] = {
  331. 0, 0x55, 0xaa, 0xff
  332. };
  333. unsigned char oneto8[2] = {
  334. 0, 255
  335. };
  336. unsigned char
  337. ComponentFromIndex(i, nbits, shift)
  338. {
  339. unsigned char val;
  340. val = i >> shift;
  341. switch (nbits) {
  342. case 1:
  343. val &= 0x1;
  344. return oneto8[val];
  345. case 2:
  346. val &= 0x3;
  347. return twoto8[val];
  348. case 3:
  349. val &= 0x7;
  350. return threeto8[val];
  351. default:
  352. return 0;
  353. }
  354. }
  355. void
  356. CreateRGBPalette(HDC hdc)
  357. {
  358. PIXELFORMATDESCRIPTOR pfd, *ppfd;
  359. LOGPALETTE *pPal;
  360. int n, i;
  361. ppfd = &pfd;
  362. n = GetPixelFormat(hdc);
  363. DescribePixelFormat(hdc, n, sizeof(PIXELFORMATDESCRIPTOR), ppfd);
  364. if (ppfd->dwFlags & PFD_NEED_PALETTE) {
  365. n = 1 << ppfd->cColorBits;
  366. pPal = (PLOGPALETTE)LocalAlloc(LMEM_FIXED, sizeof(LOGPALETTE) +
  367. n * sizeof(PALETTEENTRY));
  368. pPal->palVersion = 0x300;
  369. pPal->palNumEntries = n;
  370. for (i=0; i<n; i++) {
  371. pPal->palPalEntry[i].peRed =
  372. ComponentFromIndex(i, ppfd->cRedBits, ppfd->cRedShift);
  373. pPal->palPalEntry[i].peGreen =
  374. ComponentFromIndex(i, ppfd->cGreenBits, ppfd->cGreenShift);
  375. pPal->palPalEntry[i].peBlue =
  376. ComponentFromIndex(i, ppfd->cBlueBits, ppfd->cBlueShift);
  377. pPal->palPalEntry[i].peFlags = (i == 0 || i == 255) ? 0 : PC_NOCOLLAPSE;
  378. }
  379. ghPalette = CreatePalette(pPal);
  380. LocalFree(pPal);
  381. if (ppfd->dwFlags & PFD_NEED_SYSTEM_PALETTE)
  382. {
  383. uiSysPalUse = SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC);
  384. bUseStatic = TRUE;
  385. }
  386. ghpalOld = SelectPalette(hdc, ghPalette, FALSE);
  387. n = RealizePalette(hdc);
  388. UnrealizeObject(ghPalette);
  389. n = RealizePalette(hdc);
  390. }
  391. }
  392. BOOL bSetupPixelFormat(HDC hdc)
  393. {
  394. PIXELFORMATDESCRIPTOR pfd, *ppfd;
  395. int pixelformat;
  396. ppfd = &pfd;
  397. memset(ppfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
  398. ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
  399. ppfd->nVersion = 1;
  400. ppfd->dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
  401. ppfd->dwLayerMask = PFD_MAIN_PLANE;
  402. ppfd->iPixelType = PFD_TYPE_RGBA;
  403. ppfd->cColorBits = 24;
  404. ppfd->cDepthBits = 16;
  405. ppfd->cAccumBits = 0;
  406. ppfd->cStencilBits = 0;
  407. pixelformat = ChoosePixelFormat(hdc, ppfd);
  408. if ( (pixelformat = ChoosePixelFormat(hdc, ppfd)) == 0 )
  409. {
  410. MessageBox(NULL, "ChoosePixelFormat failed", "Error", MB_OK);
  411. return FALSE;
  412. }
  413. if (SetPixelFormat(hdc, pixelformat, ppfd) == FALSE)
  414. {
  415. MessageBox(NULL, "SetPixelFormat failed", "Error", MB_OK);
  416. return FALSE;
  417. }
  418. CreateRGBPalette(hdc);
  419. return TRUE;
  420. }
  421. HGLRC hrcInitGL(HWND hwnd, HDC hdc)
  422. {
  423. HGLRC hrc;
  424. /* Create a Rendering Context */
  425. bSetupPixelFormat( hdc );
  426. hrc = wglCreateContext( hdc );
  427. /* Make it Current */
  428. wglMakeCurrent( hdc, hrc );
  429. return hrc;
  430. }
  431. void stateInit(HWND hwnd, HDC hdc)
  432. {
  433. GLint i;
  434. SCENE *scene = (SCENE *) GetWindowLong(hwnd, GWL_USERDATA); //!!! pass instead
  435. glDrawBuffer(GL_BACK);
  436. /* Set the clear color */
  437. glClearColor( scene->rgbaClear.r, scene->rgbaClear.g,
  438. scene->rgbaClear.b, scene->rgbaClear.a );
  439. /* Turn on z-buffer */
  440. glEnable(GL_DEPTH_TEST);
  441. /* Turn on backface culling */
  442. glFrontFace(GL_CCW);
  443. //glEnable(GL_CULL_FACE);
  444. /* Shading */
  445. glShadeModel( gShadeMode == SHADE_FLAT ? GL_FLAT : GL_SMOOTH );
  446. /* Polygon draw mode */
  447. switch (gPolyDrawMode)
  448. {
  449. case POLYDRAW_POINTS:
  450. glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
  451. break;
  452. case POLYDRAW_LINES:
  453. glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  454. break;
  455. case POLYDRAW_FILLED:
  456. default:
  457. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  458. break;
  459. }
  460. /* Turn on the lights */
  461. if ( gLightMode != LIGHT_OFF )
  462. {
  463. glEnable(GL_NORMALIZE);
  464. glEnable(GL_LIGHTING);
  465. glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
  466. glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,
  467. gLightMode == LIGHT_LOCAL ? GL_TRUE : GL_FALSE);
  468. for (i = 0; i < scene->Lights.count; i++)
  469. {
  470. glCallList(scene->Lights.listBase + i);
  471. glEnable(GL_LIGHT0 + i);
  472. }
  473. /* If no other lights, turn on ambient on higher */
  474. if (!scene->Lights.count)
  475. glLightModelfv(GL_LIGHT_MODEL_AMBIENT, &lightAmbient);
  476. else
  477. glLightModelfv(GL_LIGHT_MODEL_AMBIENT, &lightAmbientLow);
  478. }
  479. else
  480. {
  481. glDisable(GL_NORMALIZE);
  482. glDisable(GL_LIGHTING);
  483. }
  484. /* Setup viewport */
  485. vSetSize(hwnd);
  486. /* Initialize trackball */
  487. trackball(curquat, 0.0, 0.0, 0.0, 0.0);
  488. }
  489. VOID vSetSize(HWND hwnd)
  490. {
  491. SCENE *scene = (SCENE *) GetWindowLong(hwnd, GWL_USERDATA); //!!! pass instead
  492. MyXYZ xyzZoomFrom;
  493. GLfloat localPerspective = scene->AspectRatio;
  494. /* Adjust aspect ratio to window size */
  495. localPerspective *= ((GLfloat) scene->szWindow.cx / (GLfloat) scene->szWindow.cy);
  496. /* Compute the vector from xyzAt to xyzFrom */
  497. xyzZoomFrom.x = scene->xyzFrom.x - scene->xyzAt.x;
  498. xyzZoomFrom.y = scene->xyzFrom.y - scene->xyzAt.y;
  499. xyzZoomFrom.z = scene->xyzFrom.z - scene->xyzAt.z;
  500. /* Scale by the zoom factor */
  501. xyzZoomFrom.x *= zoom;
  502. xyzZoomFrom.y *= zoom;
  503. xyzZoomFrom.z *= zoom;
  504. /* Compute new xyzFrom */
  505. xyzZoomFrom.x += scene->xyzAt.x;
  506. xyzZoomFrom.y += scene->xyzAt.y;
  507. xyzZoomFrom.z += scene->xyzAt.x;
  508. /* Set up viewport extents */
  509. glViewport(0, 0, scene->szWindow.cx, scene->szWindow.cy);
  510. /* Set up the projection matrix */
  511. glMatrixMode(GL_PROJECTION);
  512. glLoadIdentity();
  513. //gluPerspective(scene->ViewAngle, scene->AspectRatio,
  514. // scene->Hither, scene->Yon);
  515. gluPerspective(scene->ViewAngle, localPerspective,
  516. scene->Hither, scene->Yon * zoom);
  517. /* Set up the model matrix */
  518. glMatrixMode(GL_MODELVIEW);
  519. glLoadIdentity();
  520. //gluLookAt(scene->xyzFrom.x,scene->xyzFrom.y,scene->xyzFrom.z,
  521. // scene->xyzAt.x,scene->xyzAt.y,scene->xyzAt.z,
  522. // scene->xyzUp.x,scene->xyzUp.y,scene->xyzUp.z);
  523. gluLookAt(xyzZoomFrom.x,xyzZoomFrom.y,xyzZoomFrom.z,
  524. scene->xyzAt.x,scene->xyzAt.y,scene->xyzAt.z,
  525. scene->xyzUp.x,scene->xyzUp.y,scene->xyzUp.z);
  526. }
  527. void
  528. vCleanupGL(HGLRC hrc, HDC hdc)
  529. {
  530. //if (ghPalette)
  531. // DeleteObject(SelectObject(ghdcMem, ghpalOld));
  532. /* Destroy our context */
  533. wglDeleteContext( hrc );
  534. if (bUseStatic)
  535. SetSystemPaletteUse(hdc, uiSysPalUse);
  536. }
  537. void
  538. ForceRedraw(HWND hwnd)
  539. {
  540. MSG msg;
  541. if (!PeekMessage(&msg, hwnd, WM_PAINT, WM_PAINT, PM_NOREMOVE) )
  542. {
  543. InvalidateRect(hwnd, NULL, FALSE);
  544. }
  545. }
  546. void
  547. DoGlStuff( HWND hwnd, HDC hdc )
  548. {
  549. SCENE *scene = (SCENE *) GetWindowLong(hwnd, GWL_USERDATA); //!!! pass instead
  550. USHORT usMouseCurX, usMouseCurY;
  551. POINT pt;
  552. float matRot[4][4];
  553. if (gbLeftMouse)
  554. {
  555. if (GetCursorPos(&pt))
  556. {
  557. // Subtract current window origin to convert to window coordinates.
  558. pt.x -= gptWindow.x;
  559. pt.y -= gptWindow.y;
  560. // If mouse has moved since button was pressed, change quaternion.
  561. if (pt.x != glMouseDownX || pt.y != glMouseDownY)
  562. {
  563. //trackball(lastquat,
  564. // 2.0*(gszWindow.cx-glMouseDownX)/gszWindow.cx-1.0,
  565. // 2.0*glMouseDownY/gszWindow.cy-1.0,
  566. // 2.0*(gszWindow.cx-pt.x)/gszWindow.cx-1.0,
  567. // 2.0*pt.y/gszWindow.cy-1.0);
  568. trackball(lastquat,
  569. 2.0*(glMouseDownX)/gszWindow.cx-1.0,
  570. 2.0*(gszWindow.cy-glMouseDownY)/gszWindow.cy-1.0,
  571. 2.0*(pt.x)/gszWindow.cx-1.0,
  572. 2.0*(gszWindow.cy-pt.y)/gszWindow.cy-1.0);
  573. gbSpinning = TRUE;
  574. }
  575. else
  576. gbSpinning = FALSE;
  577. glMouseDownX = pt.x;
  578. glMouseDownY = pt.y;
  579. }
  580. }
  581. glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  582. glPushMatrix();
  583. if (gbSpinning)
  584. add_quats(lastquat, curquat, curquat);
  585. build_rotmatrix(matRot, curquat);
  586. glMultMatrixf(&(matRot[0][0]));
  587. if (scene->Objects.count)
  588. {
  589. //LBprintf("call display list");
  590. glCallList(scene->Objects.listBase);
  591. }
  592. glPopMatrix();
  593. SwapBuffers(hdc);
  594. }
  595. SCENE *OpenScene(LPSTR lpstrFile)
  596. {
  597. SCENE *scene = (SCENE *) NULL;
  598. CHAR *pchExt;
  599. // Find the extension.
  600. pchExt = lpstrFile;
  601. while ((*pchExt != '.') && (*pchExt != '\0'))
  602. pchExt++;
  603. if (*pchExt == '.')
  604. {
  605. // Use extension as the key to call appropriate parser.
  606. if (!lstrcmpi(pchExt, ".nff"))
  607. scene = NffOpenScene(lpstrFile);
  608. else if (!lstrcmpi(pchExt, ".obj"))
  609. scene = ObjOpenScene(lpstrFile);
  610. else
  611. LBprintf("Unknown extension: %s", pchExt);
  612. }
  613. return scene;
  614. }