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