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