2
* $Id: GHOST_Test.cpp 14444 2008-04-16 22:40:48Z hos $
3
* ***** BEGIN GPL LICENSE BLOCK *****
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.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software Foundation,
17
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20
* All rights reserved.
22
* The Original Code is: all of this file.
24
* Contributor(s): none yet.
26
* ***** END GPL LICENSE BLOCK *****
31
* $Id: GHOST_Test.cpp 14444 2008-04-16 22:40:48Z hos $
32
* Copyright (C) 2001 NaN Technologies B.V.
33
* Simple test file for the GHOST library.
34
* The OpenGL gear code is taken from the Qt sample code which,
35
* in turn, is probably taken from somewhere as well.
36
* @author Maarten Gribnau
38
* Stereo code by Raymond de Vries, januari 2002
48
#if defined(WIN32) || defined(__APPLE__)
55
// __APPLE__ is defined
58
#else // defined(WIN32) || defined(__APPLE__)
60
#endif // defined(WIN32) || defined(__APPLE__)
62
#include "STR_String.h"
63
#include "GHOST_Rect.h"
65
#include "GHOST_ISystem.h"
66
#include "GHOST_IEvent.h"
67
#include "GHOST_IEventConsumer.h"
73
static bool nVidiaWindows; // very dirty but hey, it's for testing only
75
static void gearsTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 time);
77
static class Application* fApp;
78
static GLfloat view_rotx=20.0, view_roty=30.0, view_rotz=0.0;
79
static GLfloat fAngle = 0.0;
80
static GHOST_ISystem* fSystem = 0;
83
void StereoProjection(float left, float right, float bottom, float top, float nearplane, float farplane,
84
float zero_plane, float dist,
88
static void testTimerProc(GHOST_ITimerTask* /*task*/, GHOST_TUns64 time)
90
std::cout << "timer1, time=" << (int)time << "\n";
94
static void gearGL(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, GLint teeth, GLfloat tooth_depth)
102
r1 = outer_radius - tooth_depth/2.0;
103
r2 = outer_radius + tooth_depth/2.0;
105
const double pi = 3.14159264;
106
da = 2.0*pi / teeth / 4.0;
108
glShadeModel(GL_FLAT);
109
glNormal3f(0.0, 0.0, 1.0);
111
/* draw front face */
112
glBegin(GL_QUAD_STRIP);
113
for (i=0;i<=teeth;i++) {
114
angle = i * 2.0*pi / teeth;
115
glVertex3f(r0*cos(angle), r0*sin(angle), width*0.5);
116
glVertex3f(r1*cos(angle), r1*sin(angle), width*0.5);
117
glVertex3f(r0*cos(angle), r0*sin(angle), width*0.5);
118
glVertex3f(r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5);
122
/* draw front sides of teeth */
124
da = 2.0*pi / teeth / 4.0;
125
for (i=0;i<teeth;i++) {
126
angle = i * 2.0*pi / teeth;
127
glVertex3f(r1*cos(angle), r1*sin(angle), width*0.5);
128
glVertex3f(r2*cos(angle+da), r2*sin(angle+da), width*0.5);
129
glVertex3f(r2*cos(angle+2*da), r2*sin(angle+2*da), width*0.5);
130
glVertex3f(r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5);
134
glNormal3f(0.0, 0.0, -1.0);
137
glBegin(GL_QUAD_STRIP);
138
for (i=0;i<=teeth;i++) {
139
angle = i * 2.0*pi / teeth;
140
glVertex3f(r1*cos(angle), r1*sin(angle), -width*0.5);
141
glVertex3f(r0*cos(angle), r0*sin(angle), -width*0.5);
142
glVertex3f(r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5);
143
glVertex3f(r0*cos(angle), r0*sin(angle), -width*0.5);
147
/* draw back sides of teeth */
149
da = 2.0*pi / teeth / 4.0;
150
for (i=0;i<teeth;i++) {
151
angle = i * 2.0*pi / teeth;
152
glVertex3f(r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5);
153
glVertex3f(r2*cos(angle+2*da), r2*sin(angle+2*da), -width*0.5);
154
glVertex3f(r2*cos(angle+da), r2*sin(angle+da), -width*0.5);
155
glVertex3f(r1*cos(angle), r1*sin(angle), -width*0.5);
159
/* draw outward faces of teeth */
160
glBegin(GL_QUAD_STRIP);
161
for (i=0;i<teeth;i++) {
162
angle = i * 2.0*pi / teeth;
163
glVertex3f(r1*cos(angle), r1*sin(angle), width*0.5);
164
glVertex3f(r1*cos(angle), r1*sin(angle), -width*0.5);
165
u = r2*cos(angle+da) - r1*cos(angle);
166
v = r2*sin(angle+da) - r1*sin(angle);
167
len = sqrt(u*u + v*v);
170
glNormal3f(v, -u, 0.0);
171
glVertex3f(r2*cos(angle+da), r2*sin(angle+da), width*0.5);
172
glVertex3f(r2*cos(angle+da), r2*sin(angle+da), -width*0.5);
173
glNormal3f(cos(angle), sin(angle), 0.0);
174
glVertex3f(r2*cos(angle+2*da), r2*sin(angle+2*da), width*0.5);
175
glVertex3f(r2*cos(angle+2*da), r2*sin(angle+2*da), -width*0.5);
176
u = r1*cos(angle+3*da) - r2*cos(angle+2*da);
177
v = r1*sin(angle+3*da) - r2*sin(angle+2*da);
178
glNormal3f(v, -u, 0.0);
179
glVertex3f(r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5);
180
glVertex3f(r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5);
181
glNormal3f(cos(angle), sin(angle), 0.0);
183
glVertex3f(r1*cos(0.0), r1*sin(0.0), width*0.5);
184
glVertex3f(r1*cos(0.0), r1*sin(0.0), -width*0.5);
187
glShadeModel(GL_SMOOTH);
189
/* draw inside radius cylinder */
190
glBegin(GL_QUAD_STRIP);
191
for (i=0;i<=teeth;i++) {
192
angle = i * 2.0*pi / teeth;
193
glNormal3f(-cos(angle), -sin(angle), 0.0);
194
glVertex3f(r0*cos(angle), r0*sin(angle), -width*0.5);
195
glVertex3f(r0*cos(angle), r0*sin(angle), width*0.5);
202
static void drawGearGL(int id)
204
static GLfloat pos[4] = { 5.0f, 5.0f, 10.0f, 1.0f };
205
static GLfloat ared[4] = { 0.8f, 0.1f, 0.0f, 1.0f };
206
static GLfloat agreen[4] = { 0.0f, 0.8f, 0.2f, 1.0f };
207
static GLfloat ablue[4] = { 0.2f, 0.2f, 1.0f, 1.0f };
209
glLightfv(GL_LIGHT0, GL_POSITION, pos);
210
glEnable(GL_CULL_FACE);
211
glEnable(GL_LIGHTING);
213
glEnable(GL_DEPTH_TEST);
218
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, ared);
219
gearGL(1.0f, 4.0f, 1.0f, 20, 0.7f);
222
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, agreen);
223
gearGL(0.5f, 2.0f, 2.0f, 10, 0.7f);
226
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, ablue);
227
gearGL(1.3f, 2.0f, 0.5f, 10, 0.7f);
232
glEnable(GL_NORMALIZE);
238
glRotatef(view_rotx, 1.0, 0.0, 0.0);
239
glRotatef(view_roty, 0.0, 1.0, 0.0);
240
glRotatef(view_rotz, 0.0, 0.0, 1.0);
247
glTranslatef(-3.0, -2.0, 0.0);
248
glRotatef(fAngle, 0.0, 0.0, 1.0);
253
glTranslatef(3.1f, -2.0f, 0.0f);
254
glRotatef(-2.0 * fAngle - 9.0, 0.0, 0.0, 1.0);
259
glTranslatef(-3.1f, 2.2f, -1.8f);
260
glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
261
glRotatef(2.0 * fAngle - 2.0, 0.0, 0.0, 1.0);
267
static void View(GHOST_IWindow* window, bool stereo, int eye = 0)
269
window->activateDrawingContext();
271
int noOfScanlines = 0, lowerScanline = 0;
272
int verticalBlankingInterval = 32; // hard coded for testing purposes, display device dependant
273
float left, right, bottom, top;
274
float nearplane, farplane, zeroPlane, distance;
275
float eyeSeparation = 0.62f;
276
window->getClientBounds(bnds);
283
// handled by nVidia driver so act as normal (explicitly put here since
285
glViewport(0, 0, bnds.getWidth(), bnds.getHeight());
288
{ // generic cross platform above-below stereo
289
noOfScanlines = (bnds.getHeight() - verticalBlankingInterval) / 2;
293
// upper half of window
294
lowerScanline = bnds.getHeight() - noOfScanlines;
297
// lower half of window
305
noOfScanlines = bnds.getHeight();
309
glViewport(0, lowerScanline, bnds.getWidth(), noOfScanlines);
326
StereoProjection(left, right, bottom, top, nearplane, farplane, zeroPlane, distance, -eyeSeparation / 2.0);
329
StereoProjection(left, right, bottom, top, nearplane, farplane, zeroPlane, distance, eyeSeparation / 2.0);
339
glMatrixMode(GL_PROJECTION);
341
glFrustum(left, right, bottom, top, 5.0, 60.0);
342
glMatrixMode(GL_MODELVIEW);
344
glTranslatef(0.0, 0.0, -40.0);
348
glClearColor(.2f,0.0f,0.0f,0.0f);
352
void StereoProjection(float left, float right, float bottom, float top, float nearplane, float farplane,
353
float zero_plane, float dist,
355
/* Perform the perspective projection for one eye's subfield.
356
The projection is in the direction of the negative z axis.
358
-6.0, 6.0, -4.8, 4.8,
359
left, right, bottom, top = the coordinate range, in the plane of zero
360
parallax setting, which will be displayed on the screen. The
361
ratio between (right-left) and (top-bottom) should equal the aspect
362
ratio of the display.
365
near, far = the z-coordinate values of the clipping planes.
368
zero_plane = the z-coordinate of the plane of zero parallax setting.
371
dist = the distance from the center of projection to the plane
375
eye = half the eye separation; positive for the right eye subfield,
376
negative for the left eye subfield.
379
float xmid, ymid, clip_near, clip_far, topw, bottomw, leftw, rightw,
385
xmid = (right + left) / 2.0;
386
ymid = (top + bottom) / 2.0;
388
clip_near = dist + zero_plane - nearplane;
389
clip_far = dist + zero_plane - farplane;
391
n_over_d = clip_near / dist;
393
topw = n_over_d * dy / 2.0;
395
rightw = n_over_d * (dx / 2.0 - eye);
396
leftw = n_over_d *(-dx / 2.0 - eye);
398
/* Need to be in projection mode for this. */
400
glFrustum(leftw, rightw, bottomw, topw, clip_near, clip_far);
402
glTranslatef(-xmid - eye, -ymid, -zero_plane - dist);
407
class Application : public GHOST_IEventConsumer {
409
Application(GHOST_ISystem* system);
411
virtual bool processEvent(GHOST_IEvent* event);
413
GHOST_ISystem* m_system;
414
GHOST_IWindow* m_mainWindow;
415
GHOST_IWindow* m_secondaryWindow;
416
GHOST_IWindow* m_fullScreenWindow;
417
GHOST_ITimerTask* m_gearsTimer, *m_testTimer;
418
GHOST_TStandardCursor m_cursor;
419
bool m_exitRequested;
425
Application::Application(GHOST_ISystem* system)
426
: m_system(system), m_mainWindow(0), m_secondaryWindow(0), m_fullScreenWindow(0),
427
m_gearsTimer(0), m_testTimer(0), m_cursor(GHOST_kStandardCursorFirstCursor),
428
m_exitRequested(false), stereo(false)
432
// Create the main window
433
STR_String title1 ("gears - main window");
434
m_mainWindow = system->createWindow(title1, 10, 64, 320, 200, GHOST_kWindowStateNormal,
435
GHOST_kDrawingContextTypeOpenGL, true /* stereo flag */);
438
std::cout << "could not create main window\n";
442
// Create a secondary window
443
STR_String title2 ("gears - secondary window");
444
m_secondaryWindow = system->createWindow(title2, 340, 64, 320, 200, GHOST_kWindowStateNormal,
445
GHOST_kDrawingContextTypeOpenGL, false /* stereo flag */);
446
if (!m_secondaryWindow) {
447
cout << "could not create secondary window\n";
451
// Install a timer to have the gears running
452
m_gearsTimer = system->installTimer(0 /*delay*/, 20/*interval*/, gearsTimerProc, m_mainWindow);
456
Application::~Application(void)
459
if (m_system->validWindow(m_mainWindow)) {
460
m_system->disposeWindow(m_mainWindow);
462
if (m_system->validWindow(m_secondaryWindow)) {
463
m_system->disposeWindow(m_secondaryWindow);
468
bool Application::processEvent(GHOST_IEvent* event)
470
GHOST_IWindow* window = event->getWindow();
473
switch (event->getType()) {
474
/* case GHOST_kEventUnknown:
476
case GHOST_kEventCursorButton:
477
std::cout << "GHOST_kEventCursorButton"; break;
478
case GHOST_kEventCursorMove:
479
std::cout << "GHOST_kEventCursorMove"; break;
481
case GHOST_kEventWheel:
483
GHOST_TEventWheelData* wheelData = (GHOST_TEventWheelData*) event->getData();
484
if (wheelData->z > 0)
495
case GHOST_kEventKeyUp:
498
case GHOST_kEventKeyDown:
500
GHOST_TEventKeyData* keyData = (GHOST_TEventKeyData*) event->getData();
501
switch (keyData->key) {
504
int cursor = m_cursor;
506
if (cursor >= GHOST_kStandardCursorNumCursors) {
507
cursor = GHOST_kStandardCursorFirstCursor;
509
m_cursor = (GHOST_TStandardCursor)cursor;
510
window->setCursorShape(m_cursor);
517
m_system->setCursorPosition(x,y);
522
if (!m_system->getFullScreen()) {
523
// Begin fullscreen mode
524
GHOST_DisplaySetting setting;
527
setting.frequency = 50;
528
setting.xPixels = 640;
529
setting.yPixels = 480;
530
m_system->beginFullScreen(setting, &m_fullScreenWindow, false /* stereo flag */);
533
m_system->endFullScreen();
534
m_fullScreenWindow = 0;
539
window->setCursorVisibility(!window->getCursorVisibility());
545
m_system->getModifierKeyState(GHOST_kModifierKeyLeftShift,down);
547
std::cout << "left shift down\n";
549
m_system->getModifierKeyState(GHOST_kModifierKeyRightShift,down);
551
std::cout << "right shift down\n"; }
552
m_system->getModifierKeyState(GHOST_kModifierKeyLeftAlt,down);
554
std::cout << "left Alt down\n";
556
m_system->getModifierKeyState(GHOST_kModifierKeyRightAlt,down);
558
std::cout << "right Alt down\n";
560
m_system->getModifierKeyState(GHOST_kModifierKeyLeftControl,down);
562
std::cout << "left control down\n";
564
m_system->getModifierKeyState(GHOST_kModifierKeyRightControl,down);
566
std::cout << "right control down\n";
572
if (m_system->getFullScreen())
574
m_system->endFullScreen();
575
m_fullScreenWindow = 0;
577
m_exitRequested = true;
580
case GHOST_kKeyS: // toggle mono and stereo
589
m_testTimer = m_system->installTimer(0, 1000, testTimerProc);
593
m_system->removeTimer(m_testTimer);
603
m_mainWindow->getTitle(title);
605
m_mainWindow->setTitle(title);
616
case GHOST_kEventWindowClose:
618
GHOST_IWindow* window2 = event->getWindow();
619
if (window2 == m_mainWindow) {
620
m_exitRequested = true;
623
m_system->disposeWindow(window2);
628
case GHOST_kEventWindowActivate:
632
case GHOST_kEventWindowDeactivate:
636
case GHOST_kEventWindowUpdate:
638
GHOST_IWindow* window2 = event->getWindow();
639
if(!m_system->validWindow(window2))
642
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
646
View(window2, stereo, LEFT_EYE);
652
View(window2, stereo, RIGHT_EYE);
660
View(window2, stereo);
666
window2->swapBuffers();
678
int main(int /*argc*/, char** /*argv*/)
680
nVidiaWindows = false;
681
// nVidiaWindows = true;
684
/* Set a couple of settings in the registry for the nVidia detonator driver.
685
* So this is very specific...
692
//unsigned char buffer[128];
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",
700
if(lresult == ERROR_SUCCESS)
701
printf("Succesfully opened key\n");
703
lresult = regkey.QueryValue(&keyValue, "StereoEnable");
704
if(lresult == ERROR_SUCCESS)
705
printf("Succesfully queried key\n");
707
lresult = regkey.SetValue(HKEY_LOCAL_MACHINE, "SOFTWARE\\NVIDIA Corporation\\Global\\Stereo3D\\StereoEnable",
709
if(lresult == ERROR_SUCCESS)
710
printf("Succesfully set value for key\n");
712
if(lresult == ERROR_SUCCESS)
713
printf("Succesfully closed key\n");
714
// regkey.Write("2");
719
GHOST_ISystem::createSystem();
720
fSystem = GHOST_ISystem::getSystem();
723
// Create an application object
724
Application app (fSystem);
726
// Add the application as event consumer
727
fSystem->addEventConsumer(&app);
730
while (!app.m_exitRequested) {
731
//printf("main: loop\n");
732
fSystem->processEvents(true);
733
fSystem->dispatchEvents();
737
// Dispose the system
738
GHOST_ISystem::disposeSystem();
744
static void gearsTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 /*time*/)
748
GHOST_IWindow* window = (GHOST_IWindow*)task->getUserData();
749
if (fApp->m_fullScreenWindow) {
750
// Running full screen
751
fApp->m_fullScreenWindow->invalidate();
754
if (fSystem->validWindow(window)) {
755
window->invalidate();