d6c8f25707c8d9114f478ac694de31cb72670bc8
[blender.git] / intern / ghost / test / gears / GHOST_Test.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /**
29  * Copyright (C) 2001 NaN Technologies B.V.
30  * Simple test file for the GHOST library.
31  * The OpenGL gear code is taken from the Qt sample code which,
32  * in turn, is probably taken from somewhere as well.
33  * \author      Maarten Gribnau
34  * \date        May 31, 2001
35  * Stereo code by Raymond de Vries, januari 2002
36  */
37
38 #include <iostream>
39 #include <math.h>
40
41 #if defined(WIN32) || defined(__APPLE__)
42 #  ifdef WIN32
43 #    include <windows.h>
44 #    include <atlbase.h>
45
46 #    include <GL/gl.h>
47 #  else // WIN32
48           // __APPLE__ is defined
49 #    include <AGL/gl.h>
50 #  endif // WIN32
51 #else // defined(WIN32) || defined(__APPLE__)
52 #  include <GL/gl.h>
53 #endif // defined(WIN32) || defined(__APPLE__)
54
55 #include "STR_String.h"
56 #include "GHOST_Rect.h"
57
58 #include "GHOST_ISystem.h"
59 #include "GHOST_IEvent.h"
60 #include "GHOST_IEventConsumer.h"
61
62
63 #define LEFT_EYE  0
64 #define RIGHT_EYE 1
65
66 static bool nVidiaWindows;  // very dirty but hey, it's for testing only
67
68 static void gearsTimerProc(GHOST_ITimerTask *task, GHOST_TUns64 time);
69
70 static class Application * fApp;
71 static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
72 static GLfloat fAngle = 0.0;
73 static GHOST_ISystem *fSystem = 0;
74
75
76 void StereoProjection(float left, float right, float bottom, float top, float nearplane, float farplane,
77                       float zero_plane, float dist,
78                       float eye);
79
80
81 static void testTimerProc(GHOST_ITimerTask * /*task*/, GHOST_TUns64 time)
82 {
83         std::cout << "timer1, time=" << (int)time << "\n";
84 }
85
86
87 static void gearGL(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, GLint teeth, GLfloat tooth_depth)
88 {
89         GLint i;
90         GLfloat r0, r1, r2;
91         GLfloat angle, da;
92         GLfloat u, v, len;
93
94         r0 = inner_radius;
95         r1 = outer_radius - tooth_depth / 2.0;
96         r2 = outer_radius + tooth_depth / 2.0;
97
98         const double pi = 3.14159264;
99         da = 2.0 * pi / teeth / 4.0;
100
101         glShadeModel(GL_FLAT);
102         glNormal3f(0.0, 0.0, 1.0);
103
104         /* draw front face */
105         glBegin(GL_QUAD_STRIP);
106         for (i = 0; i <= teeth; i++) {
107                 angle = i * 2.0 * pi / teeth;
108                 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
109                 glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
110                 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
111                 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
112         }
113         glEnd();
114
115         /* draw front sides of teeth */
116         glBegin(GL_QUADS);
117         da = 2.0 * pi / teeth / 4.0;
118         for (i = 0; i < teeth; i++) {
119                 angle = i * 2.0 * pi / teeth;
120                 glVertex3f(r1 * cos(angle),      r1 * sin(angle),      width * 0.5);
121                 glVertex3f(r2 * cos(angle + da),   r2 * sin(angle + da),   width * 0.5);
122                 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5);
123                 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
124         }
125         glEnd();
126
127         glNormal3f(0.0, 0.0, -1.0);
128
129         /* draw back face */
130         glBegin(GL_QUAD_STRIP);
131         for (i = 0; i <= teeth; i++) {
132                 angle = i * 2.0 * pi / teeth;
133                 glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
134                 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
135                 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
136                 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
137         }
138         glEnd();
139
140         /* draw back sides of teeth */
141         glBegin(GL_QUADS);
142         da = 2.0 * pi / teeth / 4.0;
143         for (i = 0; i < teeth; i++) {
144                 angle = i * 2.0 * pi / teeth;
145                 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
146                 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5);
147                 glVertex3f(r2 * cos(angle + da),   r2 * sin(angle + da),      -width * 0.5);
148                 glVertex3f(r1 * cos(angle),      r1 * sin(angle),     -width * 0.5);
149         }
150         glEnd();
151
152         /* draw outward faces of teeth */
153         glBegin(GL_QUAD_STRIP);
154         for (i = 0; i < teeth; i++) {
155                 angle = i * 2.0 * pi / teeth;
156                 glVertex3f(r1 * cos(angle),      r1 * sin(angle),      width * 0.5);
157                 glVertex3f(r1 * cos(angle),      r1 * sin(angle),     -width * 0.5);
158                 u = r2 * cos(angle + da) - r1 *cos(angle);
159                 v = r2 * sin(angle + da) - r1 *sin(angle);
160                 len = sqrt(u * u + v * v);
161                 u /= len;
162                 v /= len;
163                 glNormal3f(v, -u, 0.0);
164                 glVertex3f(r2 * cos(angle + da),   r2 * sin(angle + da),       width * 0.5);
165                 glVertex3f(r2 * cos(angle + da),   r2 * sin(angle + da),      -width * 0.5);
166                 glNormal3f(cos(angle), sin(angle), 0.0);
167                 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),  width * 0.5);
168                 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5);
169                 u = r1 * cos(angle + 3 * da) - r2 *cos(angle + 2 * da);
170                 v = r1 * sin(angle + 3 * da) - r2 *sin(angle + 2 * da);
171                 glNormal3f(v, -u, 0.0);
172                 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),  width * 0.5);
173                 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
174                 glNormal3f(cos(angle), sin(angle), 0.0);
175         }
176         glVertex3f(r1 * cos(0.0), r1 * sin(0.0), width * 0.5);
177         glVertex3f(r1 * cos(0.0), r1 * sin(0.0), -width * 0.5);
178         glEnd();
179
180         glShadeModel(GL_SMOOTH);
181
182         /* draw inside radius cylinder */
183         glBegin(GL_QUAD_STRIP);
184         for (i = 0; i <= teeth; i++) {
185                 angle = i * 2.0 * pi / teeth;
186                 glNormal3f(-cos(angle), -sin(angle), 0.0);
187                 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
188                 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
189         }
190         glEnd();
191 }
192
193
194
195 static void drawGearGL(int id)
196 {
197         static GLfloat pos[4] = { 5.0f, 5.0f, 10.0f, 1.0f };
198         static GLfloat ared[4] = { 0.8f, 0.1f, 0.0f, 1.0f };
199         static GLfloat agreen[4] = { 0.0f, 0.8f, 0.2f, 1.0f };
200         static GLfloat ablue[4] = { 0.2f, 0.2f, 1.0f, 1.0f };
201
202         glLightfv(GL_LIGHT0, GL_POSITION, pos);
203         glEnable(GL_CULL_FACE);
204         glEnable(GL_LIGHTING);
205         glEnable(GL_LIGHT0);
206         glEnable(GL_DEPTH_TEST);
207
208         switch (id)
209         {
210                 case 1:
211                         glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, ared);
212                         gearGL(1.0f, 4.0f, 1.0f, 20, 0.7f);
213                         break;
214                 case 2:
215                         glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, agreen);
216                         gearGL(0.5f, 2.0f, 2.0f, 10, 0.7f);
217                         break;
218                 case 3:
219                         glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, ablue);
220                         gearGL(1.3f, 2.0f, 0.5f, 10, 0.7f);
221                         break;
222                 default:
223                         break;
224         }
225         glEnable(GL_NORMALIZE);
226 }
227
228
229 void RenderCamera()
230 {
231         glRotatef(view_rotx, 1.0, 0.0, 0.0);
232         glRotatef(view_roty, 0.0, 1.0, 0.0);
233         glRotatef(view_rotz, 0.0, 0.0, 1.0);
234 }
235
236
237 void RenderScene()
238 {
239         glPushMatrix();
240         glTranslatef(-3.0, -2.0, 0.0);
241         glRotatef(fAngle, 0.0, 0.0, 1.0);
242         drawGearGL(1);
243         glPopMatrix();
244
245         glPushMatrix();
246         glTranslatef(3.1f, -2.0f, 0.0f);
247         glRotatef(-2.0 * fAngle - 9.0, 0.0, 0.0, 1.0);
248         drawGearGL(2);
249         glPopMatrix();
250
251         glPushMatrix();
252         glTranslatef(-3.1f, 2.2f, -1.8f);
253         glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
254         glRotatef(2.0 * fAngle - 2.0, 0.0, 0.0, 1.0);
255         drawGearGL(3);
256         glPopMatrix();
257 }
258
259
260 static void View(GHOST_IWindow *window, bool stereo, int eye = 0)
261 {
262         window->activateDrawingContext();
263         GHOST_Rect bnds;
264         int noOfScanlines = 0, lowerScanline = 0;
265         /* hard coded for testing purposes, display device dependent */
266         int verticalBlankingInterval = 32;
267         float left, right, bottom, top;
268         float nearplane, farplane, zeroPlane, distance;
269         float eyeSeparation = 0.62f;
270         window->getClientBounds(bnds);
271
272         // viewport
273         if (stereo)
274         {
275                 if (nVidiaWindows)
276                 { 
277                         // handled by nVidia driver so act as normal (explicitly put here since
278                         // it -is- stereo)
279                         glViewport(0, 0, bnds.getWidth(), bnds.getHeight());
280                 }
281                 else { // generic cross platform above-below stereo
282                         noOfScanlines = (bnds.getHeight() - verticalBlankingInterval) / 2;
283                         switch (eye)
284                         {
285                                 case LEFT_EYE:
286                                         // upper half of window
287                                         lowerScanline = bnds.getHeight() - noOfScanlines;
288                                         break;
289                                 case RIGHT_EYE:
290                                         // lower half of window
291                                         lowerScanline = 0;
292                                         break;
293                         }
294                 }
295         }
296         else {
297                 noOfScanlines = bnds.getHeight();
298                 lowerScanline = 0;
299         }
300
301         glViewport(0, lowerScanline, bnds.getWidth(), noOfScanlines);
302
303         // projection
304         left = -6.0;
305         right = 6.0;
306         bottom = -4.8f;
307         top = 4.8f;
308         nearplane = 5.0;
309         farplane = 60.0;
310
311         if (stereo)
312         {
313                 zeroPlane = 0.0;
314                 distance = 14.5;
315                 switch (eye)
316                 {
317                         case LEFT_EYE:
318                                 StereoProjection(left, right, bottom, top, nearplane, farplane, zeroPlane, distance, -eyeSeparation / 2.0);
319                                 break;
320                         case RIGHT_EYE:
321                                 StereoProjection(left, right, bottom, top, nearplane, farplane, zeroPlane, distance, eyeSeparation / 2.0);
322                                 break;
323                 }
324         }
325         else {
326 //              left = -w;
327 //              right = w;
328 //              bottom = -h;
329 //              top = h;
330                 glMatrixMode(GL_PROJECTION);
331                 glLoadIdentity();
332                 glFrustum(left, right, bottom, top, 5.0, 60.0);
333                 glMatrixMode(GL_MODELVIEW);
334                 glLoadIdentity();
335                 glTranslatef(0.0, 0.0, -40.0);
336
337         }
338
339         glClearColor(.2f, 0.0f, 0.0f, 0.0f);
340 }
341
342
343 void StereoProjection(float left, float right, float bottom, float top, float nearplane, float farplane,
344                 float zero_plane, float dist,
345                 float eye)
346 /* Perform the perspective projection for one eye's subfield.
347  * The projection is in the direction of the negative z axis.
348  *
349  * -6.0, 6.0, -4.8, 4.8,
350  * left, right, bottom, top = the coordinate range, in the plane of zero
351  * parallax setting, which will be displayed on the screen.  The
352  * ratio between (right-left) and (top-bottom) should equal the aspect
353  * ratio of the display.
354  *
355  * 6.0, -6.0,
356  * near, far = the z-coordinate values of the clipping planes.
357  *
358  * 0.0,
359  * zero_plane = the z-coordinate of the plane of zero parallax setting.
360  *
361  * 14.5,
362  * dist = the distance from the center of projection to the plane
363  * of zero parallax.
364  *
365  * -0.31
366  * eye = half the eye separation; positive for the right eye subfield,
367  * negative for the left eye subfield.
368  */
369 {
370         float xmid, ymid, clip_near, clip_far, topw, bottomw, leftw, rightw,
371               dx, dy, n_over_d;
372
373         dx = right - left;
374         dy = top - bottom;
375
376         xmid = (right + left) / 2.0;
377         ymid = (top + bottom) / 2.0;
378
379         clip_near = dist + zero_plane - nearplane;
380         clip_far  = dist + zero_plane - farplane;
381
382         n_over_d = clip_near / dist;
383
384         topw = n_over_d * dy / 2.0;
385         bottomw = -topw;
386         rightw = n_over_d * (dx / 2.0 - eye);
387         leftw  = n_over_d * (-dx / 2.0 - eye);
388
389         /* Need to be in projection mode for this. */
390         glLoadIdentity();
391         glFrustum(leftw,  rightw,  bottomw,  topw,  clip_near,  clip_far);
392
393         glTranslatef(-xmid - eye,  -ymid,  -zero_plane - dist);
394         return;
395 } /* stereoproj */
396
397
398 class Application : public GHOST_IEventConsumer {
399 public:
400         Application(GHOST_ISystem *system);
401         ~Application(void);
402         virtual bool processEvent(GHOST_IEvent *event);
403
404         GHOST_ISystem *m_system;
405         GHOST_IWindow *m_mainWindow;
406         GHOST_IWindow *m_secondaryWindow;
407         GHOST_IWindow *m_fullScreenWindow;
408         GHOST_ITimerTask *m_gearsTimer, *m_testTimer;
409         GHOST_TStandardCursor m_cursor;
410         bool m_exitRequested;
411
412         bool stereo;
413 };
414
415
416 Application::Application(GHOST_ISystem *system)
417         : m_system(system), m_mainWindow(0), m_secondaryWindow(0), m_fullScreenWindow(0),
418         m_gearsTimer(0), m_testTimer(0), m_cursor(GHOST_kStandardCursorFirstCursor),
419         m_exitRequested(false), stereo(false)
420 {
421         GHOST_GLSettings glSettings = {0};
422         fApp = this;
423
424         // Create the main window
425         STR_String title1("gears - main window");
426         m_mainWindow = system->createWindow(
427                 title1,
428                 10, 64, 320, 200,
429                 GHOST_kWindowStateNormal,
430                 GHOST_kDrawingContextTypeOpenGL,
431                 glSettings);
432
433         if (!m_mainWindow) {
434                 std::cout << "could not create main window\n";
435                 exit(-1);
436         }
437
438         // Create a secondary window
439         STR_String title2("gears - secondary window");
440         m_secondaryWindow = system->createWindow(
441                 title2,
442                 340, 64, 320, 200,
443                 GHOST_kWindowStateNormal,
444                 GHOST_kDrawingContextTypeOpenGL,
445                 glSettings);
446         if (!m_secondaryWindow) {
447                 std::cout << "could not create secondary window\n";
448                 exit(-1);
449         }
450
451         // Install a timer to have the gears running
452         m_gearsTimer = system->installTimer(0 /*delay*/, 20 /*interval*/, gearsTimerProc, m_mainWindow);
453 }
454
455
456 Application::~Application(void)
457 {
458         // Dispose windows
459         if (m_system->validWindow(m_mainWindow)) {
460                 m_system->disposeWindow(m_mainWindow);
461         }
462         if (m_system->validWindow(m_secondaryWindow)) {
463                 m_system->disposeWindow(m_secondaryWindow);
464         }
465 }
466
467
468 bool Application::processEvent(GHOST_IEvent *event)
469 {
470         GHOST_IWindow *window = event->getWindow();
471         bool handled = true;
472
473         switch (event->getType()) {
474 #if 0
475         case GHOST_kEventUnknown:
476                 break;
477         case GHOST_kEventCursorButton:
478                 std::cout << "GHOST_kEventCursorButton"; break;
479         case GHOST_kEventCursorMove:
480                 std::cout << "GHOST_kEventCursorMove"; break;
481 #endif
482                 case GHOST_kEventWheel:
483                 {
484                         GHOST_TEventWheelData *wheelData = (GHOST_TEventWheelData *) event->getData();
485                         if (wheelData->z > 0)
486                         {
487                                 view_rotz += 5.f;
488                         }
489                         else {
490                                 view_rotz -= 5.f;
491                         }
492                 }
493                 break;
494
495                 case GHOST_kEventKeyUp:
496                         break;
497
498                 case GHOST_kEventKeyDown:
499                 {
500                         GHOST_TEventKeyData *keyData = (GHOST_TEventKeyData *) event->getData();
501                         switch (keyData->key) {
502                                 case GHOST_kKeyC:
503                                 {
504                                         int cursor = m_cursor;
505                                         cursor++;
506                                         if (cursor >= GHOST_kStandardCursorNumCursors) {
507                                                 cursor = GHOST_kStandardCursorFirstCursor;
508                                         }
509                                         m_cursor = (GHOST_TStandardCursor)cursor;
510                                         window->setCursorShape(m_cursor);
511                                 }
512                                 break;
513
514                                 case GHOST_kKeyE:
515                                 {
516                                         int x = 200, y = 200;
517                                         m_system->setCursorPosition(x, y);
518                                         break;
519                                 }
520
521                                 case GHOST_kKeyF:
522                                         if (!m_system->getFullScreen()) {
523                                                 // Begin fullscreen mode
524                                                 GHOST_DisplaySetting setting;
525
526                                                 setting.bpp = 16;
527                                                 setting.frequency = 50;
528                                                 setting.xPixels = 640;
529                                                 setting.yPixels = 480;
530                                                 m_system->beginFullScreen(setting, &m_fullScreenWindow, false /* stereo flag */);
531                                         }
532                                         else {
533                                                 m_system->endFullScreen();
534                                                 m_fullScreenWindow = 0;
535                                         }
536                                         break;
537
538                                 case GHOST_kKeyH:
539                                         window->setCursorVisibility(!window->getCursorVisibility());
540                                         break;
541
542                                 case GHOST_kKeyM:
543                                 {
544                                         bool down = false;
545                                         m_system->getModifierKeyState(GHOST_kModifierKeyLeftShift, down);
546                                         if (down) {
547                                                 std::cout << "left shift down\n";
548                                         }
549                                         m_system->getModifierKeyState(GHOST_kModifierKeyRightShift, down);
550                                         if (down) {
551                                                 std::cout << "right shift down\n";
552                                         }
553                                         m_system->getModifierKeyState(GHOST_kModifierKeyLeftAlt, down);
554                                         if (down) {
555                                                 std::cout << "left Alt down\n";
556                                         }
557                                         m_system->getModifierKeyState(GHOST_kModifierKeyRightAlt, down);
558                                         if (down) {
559                                                 std::cout << "right Alt down\n";
560                                         }
561                                         m_system->getModifierKeyState(GHOST_kModifierKeyLeftControl, down);
562                                         if (down) {
563                                                 std::cout << "left control down\n";
564                                         }
565                                         m_system->getModifierKeyState(GHOST_kModifierKeyRightControl, down);
566                                         if (down) {
567                                                 std::cout << "right control down\n";
568                                         }
569                                 }
570                                 break;
571
572                                 case GHOST_kKeyQ:
573                                         if (m_system->getFullScreen())
574                                         {
575                                                 m_system->endFullScreen();
576                                                 m_fullScreenWindow = 0;
577                                         }
578                                         m_exitRequested = true;
579                                         break;
580
581                                 case GHOST_kKeyS: // toggle mono and stereo
582                                         if (stereo)
583                                                 stereo = false;
584                                         else
585                                                 stereo = true;
586                                         break;
587
588                                 case GHOST_kKeyT:
589                                         if (!m_testTimer) {
590                                                 m_testTimer = m_system->installTimer(0, 1000, testTimerProc);
591                                         }
592
593                                         else {
594                                                 m_system->removeTimer(m_testTimer);
595                                                 m_testTimer = 0;
596                                         }
597
598                                         break;
599
600                                 case GHOST_kKeyW:
601                                         if (m_mainWindow)
602                                         {
603                                                 STR_String title;
604                                                 m_mainWindow->getTitle(title);
605                                                 title += "-";
606                                                 m_mainWindow->setTitle(title);
607
608                                         }
609                                         break;
610
611                                 default:
612                                         break;
613                         }
614                 }
615                 break;
616
617                 case GHOST_kEventWindowClose:
618                 {
619                         GHOST_IWindow *window2 = event->getWindow();
620                         if (window2 == m_mainWindow) {
621                                 m_exitRequested = true;
622                         }
623                         else {
624                                 m_system->disposeWindow(window2);
625                         }
626                 }
627                 break;
628
629                 case GHOST_kEventWindowActivate:
630                         handled = false;
631                         break;
632
633                 case GHOST_kEventWindowDeactivate:
634                         handled = false;
635                         break;
636
637                 case GHOST_kEventWindowUpdate:
638                 {
639                         GHOST_IWindow *window2 = event->getWindow();
640                         if (!m_system->validWindow(window2))
641                                 break;
642
643                         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
644
645                         if (stereo)
646                         {
647                                 View(window2, stereo, LEFT_EYE);
648                                 glPushMatrix();
649                                 RenderCamera();
650                                 RenderScene();
651                                 glPopMatrix();
652
653                                 View(window2, stereo, RIGHT_EYE);
654                                 glPushMatrix();
655                                 RenderCamera();
656                                 RenderScene();
657                                 glPopMatrix();
658                         }
659                         else {
660                                 View(window2, stereo);
661                                 glPushMatrix();
662                                 RenderCamera();
663                                 RenderScene();
664                                 glPopMatrix();
665                         }
666                         window2->swapBuffers();
667                 }
668                 break;
669                 
670                 default:
671                         handled = false;
672                         break;
673         }
674         return handled;
675 }
676
677
678 int main(int /*argc*/, char ** /*argv*/)
679 {
680         nVidiaWindows = false;
681 //      nVidiaWindows = true;
682
683 #ifdef WIN32
684         /* Set a couple of settings in the registry for the nVidia detonator driver.
685          * So this is very specific...
686          */
687         if (nVidiaWindows)
688         {
689                 LONG lresult;
690                 HKEY hkey = 0;
691                 DWORD dwd = 0;
692                 //unsigned char buffer[128];
693
694                 CRegKey regkey;
695                 //DWORD keyValue;
696 //              lresult = regkey.Open(HKEY_LOCAL_MACHINE, "SOFTWARE\\NVIDIA Corporation\\Global\\Stereo3D\\StereoEnable");
697                 lresult = regkey.Open(HKEY_LOCAL_MACHINE, "SOFTWARE\\NVIDIA Corporation\\Global\\Stereo3D\\StereoEnable",
698                                       KEY_ALL_ACCESS);
699
700                 if (lresult == ERROR_SUCCESS)
701                         printf("Succesfully opened key\n");
702 #if 0
703                 lresult = regkey.QueryValue(&keyValue, "StereoEnable");
704                 if (lresult == ERROR_SUCCESS)
705                         printf("Succesfully queried key\n");
706 #endif
707                 lresult = regkey.SetValue(HKEY_LOCAL_MACHINE, "SOFTWARE\\NVIDIA Corporation\\Global\\Stereo3D\\StereoEnable",
708                                           "1");
709                 if (lresult == ERROR_SUCCESS)
710                         printf("Succesfully set value for key\n");
711                 regkey.Close();
712                 if (lresult == ERROR_SUCCESS)
713                         printf("Succesfully closed key\n");
714 //              regkey.Write("2");
715         }
716 #endif  // WIN32
717
718         // Create the system
719         GHOST_ISystem::createSystem();
720         fSystem = GHOST_ISystem::getSystem();
721
722         if (fSystem) {
723                 // Create an application object
724                 Application app(fSystem);
725
726                 // Add the application as event consumer
727                 fSystem->addEventConsumer(&app);
728
729                 // Enter main loop
730                 while (!app.m_exitRequested) {
731                         //printf("main: loop\n");
732                         fSystem->processEvents(true);
733                         fSystem->dispatchEvents();
734                 }
735
736                 // Remove so ghost doesn't do a double free
737                 fSystem->removeEventConsumer(&app);
738         }
739
740         // Dispose the system
741         GHOST_ISystem::disposeSystem();
742
743         return 0;
744 }
745
746
747 static void gearsTimerProc(GHOST_ITimerTask *task, GHOST_TUns64 /*time*/)
748 {
749         fAngle += 2.0;
750         view_roty += 1.0;
751         GHOST_IWindow *window = (GHOST_IWindow *)task->getUserData();
752         if (fApp->m_fullScreenWindow) {
753                 // Running full screen
754                 fApp->m_fullScreenWindow->invalidate();
755         }
756         else {
757                 if (fSystem->validWindow(window)) {
758                         window->invalidate();
759                 }
760         }
761 }