2002-10-12 11:37:38 +00:00
|
|
|
/**
|
2008-04-16 22:40:48 +00:00
|
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
2002-10-12 11:37:38 +00:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
2008-04-16 22:40:48 +00:00
|
|
|
* of the License, or (at your option) any later version.
|
2002-10-12 11:37:38 +00:00
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
2010-02-12 13:34:04 +00:00
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2002-10-12 11:37:38 +00:00
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* The Original Code is: all of this file.
|
|
|
|
*
|
|
|
|
* Contributor(s): none yet.
|
|
|
|
*
|
2008-04-16 22:40:48 +00:00
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
2002-10-12 11:37:38 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Copyright (C) 2001 NaN Technologies B.V.
|
|
|
|
* Simple test file for the GHOST library.
|
|
|
|
* The OpenGL gear code is taken from the Qt sample code which,
|
|
|
|
* in turn, is probably taken from somewhere as well.
|
|
|
|
* @author Maarten Gribnau
|
|
|
|
* @date May 31, 2001
|
|
|
|
* Stereo code by Raymond de Vries, januari 2002
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
#if defined(WIN32) || defined(__APPLE__)
|
2012-05-24 13:18:53 +00:00
|
|
|
# ifdef WIN32
|
|
|
|
# include <windows.h>
|
|
|
|
# include <atlbase.h>
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-24 13:18:53 +00:00
|
|
|
# include <GL/gl.h>
|
|
|
|
# else // WIN32
|
2012-05-19 09:57:55 +00:00
|
|
|
// __APPLE__ is defined
|
2012-05-24 13:18:53 +00:00
|
|
|
# include <AGL/gl.h>
|
|
|
|
# endif // WIN32
|
2002-10-12 11:37:38 +00:00
|
|
|
#else // defined(WIN32) || defined(__APPLE__)
|
2012-05-24 13:18:53 +00:00
|
|
|
# include <GL/gl.h>
|
2002-10-12 11:37:38 +00:00
|
|
|
#endif // defined(WIN32) || defined(__APPLE__)
|
|
|
|
|
|
|
|
#include "STR_String.h"
|
|
|
|
#include "GHOST_Rect.h"
|
|
|
|
|
|
|
|
#include "GHOST_ISystem.h"
|
|
|
|
#include "GHOST_IEvent.h"
|
|
|
|
#include "GHOST_IEventConsumer.h"
|
|
|
|
|
|
|
|
|
|
|
|
#define LEFT_EYE 0
|
|
|
|
#define RIGHT_EYE 1
|
|
|
|
|
|
|
|
static bool nVidiaWindows; // very dirty but hey, it's for testing only
|
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
static void gearsTimerProc(GHOST_ITimerTask *task, GHOST_TUns64 time);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
static class Application * fApp;
|
|
|
|
static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
|
2002-10-12 11:37:38 +00:00
|
|
|
static GLfloat fAngle = 0.0;
|
2012-05-19 09:57:55 +00:00
|
|
|
static GHOST_ISystem *fSystem = 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
void StereoProjection(float left, float right, float bottom, float top, float nearplane, float farplane,
|
2012-05-19 09:57:55 +00:00
|
|
|
float zero_plane, float dist,
|
|
|
|
float eye);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
static void testTimerProc(GHOST_ITimerTask * /*task*/, GHOST_TUns64 time)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
std::cout << "timer1, time=" << (int)time << "\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void gearGL(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, GLint teeth, GLfloat tooth_depth)
|
|
|
|
{
|
|
|
|
GLint i;
|
|
|
|
GLfloat r0, r1, r2;
|
|
|
|
GLfloat angle, da;
|
|
|
|
GLfloat u, v, len;
|
|
|
|
|
|
|
|
r0 = inner_radius;
|
2012-05-19 09:57:55 +00:00
|
|
|
r1 = outer_radius - tooth_depth / 2.0;
|
|
|
|
r2 = outer_radius + tooth_depth / 2.0;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
const double pi = 3.14159264;
|
2012-05-19 09:57:55 +00:00
|
|
|
da = 2.0 * pi / teeth / 4.0;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
glShadeModel(GL_FLAT);
|
|
|
|
glNormal3f(0.0, 0.0, 1.0);
|
|
|
|
|
|
|
|
/* draw front face */
|
|
|
|
glBegin(GL_QUAD_STRIP);
|
2012-05-19 09:57:55 +00:00
|
|
|
for (i = 0; i <= teeth; i++) {
|
|
|
|
angle = i * 2.0 * pi / teeth;
|
|
|
|
glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
|
|
|
|
glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
|
|
|
|
glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
|
|
|
|
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
glEnd();
|
|
|
|
|
|
|
|
/* draw front sides of teeth */
|
|
|
|
glBegin(GL_QUADS);
|
2012-05-19 09:57:55 +00:00
|
|
|
da = 2.0 * pi / teeth / 4.0;
|
|
|
|
for (i = 0; i < teeth; i++) {
|
|
|
|
angle = i * 2.0 * pi / teeth;
|
|
|
|
glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
|
|
|
|
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
|
|
|
|
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5);
|
|
|
|
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
glEnd();
|
|
|
|
|
|
|
|
glNormal3f(0.0, 0.0, -1.0);
|
|
|
|
|
|
|
|
/* draw back face */
|
|
|
|
glBegin(GL_QUAD_STRIP);
|
2012-05-19 09:57:55 +00:00
|
|
|
for (i = 0; i <= teeth; i++) {
|
|
|
|
angle = i * 2.0 * pi / teeth;
|
|
|
|
glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
|
|
|
|
glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
|
|
|
|
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
|
|
|
|
glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
glEnd();
|
|
|
|
|
|
|
|
/* draw back sides of teeth */
|
|
|
|
glBegin(GL_QUADS);
|
2012-05-19 09:57:55 +00:00
|
|
|
da = 2.0 * pi / teeth / 4.0;
|
|
|
|
for (i = 0; i < teeth; i++) {
|
|
|
|
angle = i * 2.0 * pi / teeth;
|
|
|
|
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
|
|
|
|
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5);
|
|
|
|
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
|
|
|
|
glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
glEnd();
|
|
|
|
|
|
|
|
/* draw outward faces of teeth */
|
|
|
|
glBegin(GL_QUAD_STRIP);
|
2012-05-19 09:57:55 +00:00
|
|
|
for (i = 0; i < teeth; i++) {
|
|
|
|
angle = i * 2.0 * pi / teeth;
|
|
|
|
glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
|
|
|
|
glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
|
|
|
|
u = r2 * cos(angle + da) - r1 *cos(angle);
|
|
|
|
v = r2 * sin(angle + da) - r1 *sin(angle);
|
|
|
|
len = sqrt(u * u + v * v);
|
2002-10-12 11:37:38 +00:00
|
|
|
u /= len;
|
|
|
|
v /= len;
|
|
|
|
glNormal3f(v, -u, 0.0);
|
2012-05-19 09:57:55 +00:00
|
|
|
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
|
|
|
|
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
|
2002-10-12 11:37:38 +00:00
|
|
|
glNormal3f(cos(angle), sin(angle), 0.0);
|
2012-05-19 09:57:55 +00:00
|
|
|
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5);
|
|
|
|
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5);
|
|
|
|
u = r1 * cos(angle + 3 * da) - r2 *cos(angle + 2 * da);
|
|
|
|
v = r1 * sin(angle + 3 * da) - r2 *sin(angle + 2 * da);
|
2002-10-12 11:37:38 +00:00
|
|
|
glNormal3f(v, -u, 0.0);
|
2012-05-19 09:57:55 +00:00
|
|
|
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
|
|
|
|
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
|
2002-10-12 11:37:38 +00:00
|
|
|
glNormal3f(cos(angle), sin(angle), 0.0);
|
2012-05-19 09:57:55 +00:00
|
|
|
}
|
|
|
|
glVertex3f(r1 * cos(0.0), r1 * sin(0.0), width * 0.5);
|
|
|
|
glVertex3f(r1 * cos(0.0), r1 * sin(0.0), -width * 0.5);
|
2002-10-12 11:37:38 +00:00
|
|
|
glEnd();
|
|
|
|
|
|
|
|
glShadeModel(GL_SMOOTH);
|
|
|
|
|
|
|
|
/* draw inside radius cylinder */
|
|
|
|
glBegin(GL_QUAD_STRIP);
|
2012-05-19 09:57:55 +00:00
|
|
|
for (i = 0; i <= teeth; i++) {
|
|
|
|
angle = i * 2.0 * pi / teeth;
|
2002-10-12 11:37:38 +00:00
|
|
|
glNormal3f(-cos(angle), -sin(angle), 0.0);
|
2012-05-19 09:57:55 +00:00
|
|
|
glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
|
|
|
|
glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
glEnd();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void drawGearGL(int id)
|
|
|
|
{
|
|
|
|
static GLfloat pos[4] = { 5.0f, 5.0f, 10.0f, 1.0f };
|
|
|
|
static GLfloat ared[4] = { 0.8f, 0.1f, 0.0f, 1.0f };
|
|
|
|
static GLfloat agreen[4] = { 0.0f, 0.8f, 0.2f, 1.0f };
|
|
|
|
static GLfloat ablue[4] = { 0.2f, 0.2f, 1.0f, 1.0f };
|
|
|
|
|
|
|
|
glLightfv(GL_LIGHT0, GL_POSITION, pos);
|
|
|
|
glEnable(GL_CULL_FACE);
|
|
|
|
glEnable(GL_LIGHTING);
|
|
|
|
glEnable(GL_LIGHT0);
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
|
|
|
|
switch (id)
|
|
|
|
{
|
2012-05-19 09:57:55 +00:00
|
|
|
case 1:
|
|
|
|
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, ared);
|
|
|
|
gearGL(1.0f, 4.0f, 1.0f, 20, 0.7f);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, agreen);
|
|
|
|
gearGL(0.5f, 2.0f, 2.0f, 10, 0.7f);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, ablue);
|
|
|
|
gearGL(1.3f, 2.0f, 0.5f, 10, 0.7f);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
glEnable(GL_NORMALIZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void RenderCamera()
|
|
|
|
{
|
2012-05-19 09:57:55 +00:00
|
|
|
glRotatef(view_rotx, 1.0, 0.0, 0.0);
|
|
|
|
glRotatef(view_roty, 0.0, 1.0, 0.0);
|
|
|
|
glRotatef(view_rotz, 0.0, 0.0, 1.0);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void RenderScene()
|
|
|
|
{
|
|
|
|
glPushMatrix();
|
|
|
|
glTranslatef(-3.0, -2.0, 0.0);
|
|
|
|
glRotatef(fAngle, 0.0, 0.0, 1.0);
|
|
|
|
drawGearGL(1);
|
|
|
|
glPopMatrix();
|
|
|
|
|
|
|
|
glPushMatrix();
|
|
|
|
glTranslatef(3.1f, -2.0f, 0.0f);
|
|
|
|
glRotatef(-2.0 * fAngle - 9.0, 0.0, 0.0, 1.0);
|
|
|
|
drawGearGL(2);
|
|
|
|
glPopMatrix();
|
|
|
|
|
|
|
|
glPushMatrix();
|
|
|
|
glTranslatef(-3.1f, 2.2f, -1.8f);
|
|
|
|
glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
|
|
|
|
glRotatef(2.0 * fAngle - 2.0, 0.0, 0.0, 1.0);
|
|
|
|
drawGearGL(3);
|
|
|
|
glPopMatrix();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
static void View(GHOST_IWindow *window, bool stereo, int eye = 0)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
window->activateDrawingContext();
|
|
|
|
GHOST_Rect bnds;
|
2003-01-24 05:52:25 +00:00
|
|
|
int noOfScanlines = 0, lowerScanline = 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
int verticalBlankingInterval = 32; // hard coded for testing purposes, display device dependant
|
|
|
|
float left, right, bottom, top;
|
|
|
|
float nearplane, farplane, zeroPlane, distance;
|
2003-01-27 21:35:26 +00:00
|
|
|
float eyeSeparation = 0.62f;
|
2002-10-12 11:37:38 +00:00
|
|
|
window->getClientBounds(bnds);
|
|
|
|
|
|
|
|
// viewport
|
2012-05-19 09:57:55 +00:00
|
|
|
if (stereo)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2012-05-19 09:57:55 +00:00
|
|
|
if (nVidiaWindows)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
// handled by nVidia driver so act as normal (explicitly put here since
|
|
|
|
// it -is- stereo)
|
|
|
|
glViewport(0, 0, bnds.getWidth(), bnds.getHeight());
|
|
|
|
}
|
2012-05-19 09:57:55 +00:00
|
|
|
else { // generic cross platform above-below stereo
|
2002-10-12 11:37:38 +00:00
|
|
|
noOfScanlines = (bnds.getHeight() - verticalBlankingInterval) / 2;
|
2012-05-19 09:57:55 +00:00
|
|
|
switch (eye)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
case LEFT_EYE:
|
|
|
|
// upper half of window
|
|
|
|
lowerScanline = bnds.getHeight() - noOfScanlines;
|
|
|
|
break;
|
|
|
|
case RIGHT_EYE:
|
|
|
|
// lower half of window
|
|
|
|
lowerScanline = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-05-19 09:57:55 +00:00
|
|
|
else {
|
2002-10-12 11:37:38 +00:00
|
|
|
noOfScanlines = bnds.getHeight();
|
|
|
|
lowerScanline = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
glViewport(0, lowerScanline, bnds.getWidth(), noOfScanlines);
|
|
|
|
|
|
|
|
// projection
|
|
|
|
left = -6.0;
|
|
|
|
right = 6.0;
|
2003-01-27 21:35:26 +00:00
|
|
|
bottom = -4.8f;
|
|
|
|
top = 4.8f;
|
2002-10-12 11:37:38 +00:00
|
|
|
nearplane = 5.0;
|
|
|
|
farplane = 60.0;
|
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
if (stereo)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
zeroPlane = 0.0;
|
|
|
|
distance = 14.5;
|
2012-05-19 09:57:55 +00:00
|
|
|
switch (eye)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
case LEFT_EYE:
|
|
|
|
StereoProjection(left, right, bottom, top, nearplane, farplane, zeroPlane, distance, -eyeSeparation / 2.0);
|
|
|
|
break;
|
|
|
|
case RIGHT_EYE:
|
|
|
|
StereoProjection(left, right, bottom, top, nearplane, farplane, zeroPlane, distance, eyeSeparation / 2.0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-05-19 09:57:55 +00:00
|
|
|
else {
|
2002-10-12 11:37:38 +00:00
|
|
|
// left = -w;
|
|
|
|
// right = w;
|
|
|
|
// bottom = -h;
|
|
|
|
// top = h;
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
|
|
|
glFrustum(left, right, bottom, top, 5.0, 60.0);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
|
|
|
glTranslatef(0.0, 0.0, -40.0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
glClearColor(.2f, 0.0f, 0.0f, 0.0f);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void StereoProjection(float left, float right, float bottom, float top, float nearplane, float farplane,
|
|
|
|
float zero_plane, float dist,
|
|
|
|
float eye)
|
|
|
|
/* Perform the perspective projection for one eye's subfield.
|
2012-05-19 09:57:55 +00:00
|
|
|
The projection is in the direction of the negative z axis.
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
-6.0, 6.0, -4.8, 4.8,
|
|
|
|
left, right, bottom, top = the coordinate range, in the plane of zero
|
|
|
|
parallax setting, which will be displayed on the screen. The
|
|
|
|
ratio between (right-left) and (top-bottom) should equal the aspect
|
|
|
|
ratio of the display.
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
6.0, -6.0,
|
|
|
|
near, far = the z-coordinate values of the clipping planes.
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
0.0,
|
|
|
|
zero_plane = the z-coordinate of the plane of zero parallax setting.
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
14.5,
|
|
|
|
dist = the distance from the center of projection to the plane
|
|
|
|
of zero parallax.
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
-0.31
|
|
|
|
eye = half the eye separation; positive for the right eye subfield,
|
|
|
|
negative for the left eye subfield.
|
|
|
|
*/
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
float xmid, ymid, clip_near, clip_far, topw, bottomw, leftw, rightw,
|
2012-05-19 09:57:55 +00:00
|
|
|
dx, dy, n_over_d;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
dx = right - left;
|
|
|
|
dy = top - bottom;
|
|
|
|
|
|
|
|
xmid = (right + left) / 2.0;
|
|
|
|
ymid = (top + bottom) / 2.0;
|
|
|
|
|
|
|
|
clip_near = dist + zero_plane - nearplane;
|
|
|
|
clip_far = dist + zero_plane - farplane;
|
|
|
|
|
|
|
|
n_over_d = clip_near / dist;
|
|
|
|
|
|
|
|
topw = n_over_d * dy / 2.0;
|
|
|
|
bottomw = -topw;
|
|
|
|
rightw = n_over_d * (dx / 2.0 - eye);
|
2012-05-19 09:57:55 +00:00
|
|
|
leftw = n_over_d * (-dx / 2.0 - eye);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
/* Need to be in projection mode for this. */
|
|
|
|
glLoadIdentity();
|
|
|
|
glFrustum(leftw, rightw, bottomw, topw, clip_near, clip_far);
|
|
|
|
|
|
|
|
glTranslatef(-xmid - eye, -ymid, -zero_plane - dist);
|
|
|
|
return;
|
|
|
|
} /* stereoproj */
|
|
|
|
|
|
|
|
|
|
|
|
class Application : public GHOST_IEventConsumer {
|
|
|
|
public:
|
2012-05-19 09:57:55 +00:00
|
|
|
Application(GHOST_ISystem *system);
|
2002-10-12 11:37:38 +00:00
|
|
|
~Application(void);
|
2012-05-19 09:57:55 +00:00
|
|
|
virtual bool processEvent(GHOST_IEvent *event);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
GHOST_ISystem *m_system;
|
|
|
|
GHOST_IWindow *m_mainWindow;
|
|
|
|
GHOST_IWindow *m_secondaryWindow;
|
|
|
|
GHOST_IWindow *m_fullScreenWindow;
|
|
|
|
GHOST_ITimerTask *m_gearsTimer, *m_testTimer;
|
2002-10-12 11:37:38 +00:00
|
|
|
GHOST_TStandardCursor m_cursor;
|
|
|
|
bool m_exitRequested;
|
|
|
|
|
|
|
|
bool stereo;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
Application::Application(GHOST_ISystem *system)
|
2002-10-12 11:37:38 +00:00
|
|
|
: m_system(system), m_mainWindow(0), m_secondaryWindow(0), m_fullScreenWindow(0),
|
2012-05-19 09:57:55 +00:00
|
|
|
m_gearsTimer(0), m_testTimer(0), m_cursor(GHOST_kStandardCursorFirstCursor),
|
|
|
|
m_exitRequested(false), stereo(false)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
fApp = this;
|
|
|
|
|
|
|
|
// Create the main window
|
2012-05-19 09:57:55 +00:00
|
|
|
STR_String title1("gears - main window");
|
2002-10-12 11:37:38 +00:00
|
|
|
m_mainWindow = system->createWindow(title1, 10, 64, 320, 200, GHOST_kWindowStateNormal,
|
2012-05-19 09:57:55 +00:00
|
|
|
GHOST_kDrawingContextTypeOpenGL, false, false);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
if (!m_mainWindow) {
|
2002-10-12 11:37:38 +00:00
|
|
|
std::cout << "could not create main window\n";
|
|
|
|
exit(-1);
|
2012-05-19 09:57:55 +00:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
// Create a secondary window
|
2012-05-19 09:57:55 +00:00
|
|
|
STR_String title2("gears - secondary window");
|
2002-10-12 11:37:38 +00:00
|
|
|
m_secondaryWindow = system->createWindow(title2, 340, 64, 320, 200, GHOST_kWindowStateNormal,
|
2012-05-19 09:57:55 +00:00
|
|
|
GHOST_kDrawingContextTypeOpenGL, false, false);
|
2002-10-12 11:37:38 +00:00
|
|
|
if (!m_secondaryWindow) {
|
|
|
|
cout << "could not create secondary window\n";
|
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Install a timer to have the gears running
|
2012-05-19 09:57:55 +00:00
|
|
|
m_gearsTimer = system->installTimer(0 /*delay*/, 20 /*interval*/, gearsTimerProc, m_mainWindow);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Application::~Application(void)
|
|
|
|
{
|
|
|
|
// Dispose windows
|
|
|
|
if (m_system->validWindow(m_mainWindow)) {
|
|
|
|
m_system->disposeWindow(m_mainWindow);
|
|
|
|
}
|
|
|
|
if (m_system->validWindow(m_secondaryWindow)) {
|
|
|
|
m_system->disposeWindow(m_secondaryWindow);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
bool Application::processEvent(GHOST_IEvent *event)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2012-05-19 09:57:55 +00:00
|
|
|
GHOST_IWindow *window = event->getWindow();
|
2002-10-12 11:37:38 +00:00
|
|
|
bool handled = true;
|
|
|
|
|
|
|
|
switch (event->getType()) {
|
|
|
|
/* case GHOST_kEventUnknown:
|
2012-05-19 09:57:55 +00:00
|
|
|
break;
|
|
|
|
case GHOST_kEventCursorButton:
|
|
|
|
std::cout << "GHOST_kEventCursorButton"; break;
|
|
|
|
case GHOST_kEventCursorMove:
|
|
|
|
std::cout << "GHOST_kEventCursorMove"; break;
|
|
|
|
*/
|
|
|
|
case GHOST_kEventWheel:
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2012-05-19 09:57:55 +00:00
|
|
|
GHOST_TEventWheelData *wheelData = (GHOST_TEventWheelData *) event->getData();
|
|
|
|
if (wheelData->z > 0)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2012-05-19 09:57:55 +00:00
|
|
|
view_rotz += 5.f;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-05-19 09:57:55 +00:00
|
|
|
view_rotz -= 5.f;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2012-05-19 09:57:55 +00:00
|
|
|
}
|
|
|
|
break;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
case GHOST_kEventKeyUp:
|
2002-10-12 11:37:38 +00:00
|
|
|
break;
|
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
case GHOST_kEventKeyDown:
|
|
|
|
{
|
|
|
|
GHOST_TEventKeyData *keyData = (GHOST_TEventKeyData *) event->getData();
|
|
|
|
switch (keyData->key) {
|
|
|
|
case GHOST_kKeyC:
|
|
|
|
{
|
|
|
|
int cursor = m_cursor;
|
|
|
|
cursor++;
|
|
|
|
if (cursor >= GHOST_kStandardCursorNumCursors) {
|
|
|
|
cursor = GHOST_kStandardCursorFirstCursor;
|
|
|
|
}
|
|
|
|
m_cursor = (GHOST_TStandardCursor)cursor;
|
|
|
|
window->setCursorShape(m_cursor);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2012-05-19 09:57:55 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GHOST_kKeyE:
|
|
|
|
{
|
|
|
|
int x = 200, y = 200;
|
|
|
|
m_system->setCursorPosition(x, y);
|
|
|
|
break;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2012-05-19 09:57:55 +00:00
|
|
|
|
|
|
|
case GHOST_kKeyF:
|
|
|
|
if (!m_system->getFullScreen()) {
|
|
|
|
// Begin fullscreen mode
|
|
|
|
GHOST_DisplaySetting setting;
|
|
|
|
|
|
|
|
setting.bpp = 16;
|
|
|
|
setting.frequency = 50;
|
|
|
|
setting.xPixels = 640;
|
|
|
|
setting.yPixels = 480;
|
|
|
|
m_system->beginFullScreen(setting, &m_fullScreenWindow, false /* stereo flag */);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
m_system->endFullScreen();
|
|
|
|
m_fullScreenWindow = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GHOST_kKeyH:
|
|
|
|
window->setCursorVisibility(!window->getCursorVisibility());
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GHOST_kKeyM:
|
|
|
|
{
|
|
|
|
bool down = false;
|
|
|
|
m_system->getModifierKeyState(GHOST_kModifierKeyLeftShift, down);
|
|
|
|
if (down) {
|
|
|
|
std::cout << "left shift down\n";
|
|
|
|
}
|
|
|
|
m_system->getModifierKeyState(GHOST_kModifierKeyRightShift, down);
|
|
|
|
if (down) {
|
|
|
|
std::cout << "right shift down\n";
|
|
|
|
}
|
|
|
|
m_system->getModifierKeyState(GHOST_kModifierKeyLeftAlt, down);
|
|
|
|
if (down) {
|
|
|
|
std::cout << "left Alt down\n";
|
|
|
|
}
|
|
|
|
m_system->getModifierKeyState(GHOST_kModifierKeyRightAlt, down);
|
|
|
|
if (down) {
|
|
|
|
std::cout << "right Alt down\n";
|
|
|
|
}
|
|
|
|
m_system->getModifierKeyState(GHOST_kModifierKeyLeftControl, down);
|
|
|
|
if (down) {
|
|
|
|
std::cout << "left control down\n";
|
|
|
|
}
|
|
|
|
m_system->getModifierKeyState(GHOST_kModifierKeyRightControl, down);
|
|
|
|
if (down) {
|
|
|
|
std::cout << "right control down\n";
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2012-05-19 09:57:55 +00:00
|
|
|
break;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
case GHOST_kKeyQ:
|
|
|
|
if (m_system->getFullScreen())
|
|
|
|
{
|
|
|
|
m_system->endFullScreen();
|
|
|
|
m_fullScreenWindow = 0;
|
|
|
|
}
|
|
|
|
m_exitRequested = true;
|
|
|
|
break;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
case GHOST_kKeyS: // toggle mono and stereo
|
|
|
|
if (stereo)
|
|
|
|
stereo = false;
|
|
|
|
else
|
|
|
|
stereo = true;
|
|
|
|
break;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
case GHOST_kKeyT:
|
|
|
|
if (!m_testTimer) {
|
|
|
|
m_testTimer = m_system->installTimer(0, 1000, testTimerProc);
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
else {
|
|
|
|
m_system->removeTimer(m_testTimer);
|
|
|
|
m_testTimer = 0;
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
break;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
case GHOST_kKeyW:
|
|
|
|
if (m_mainWindow)
|
|
|
|
{
|
|
|
|
STR_String title;
|
|
|
|
m_mainWindow->getTitle(title);
|
|
|
|
title += "-";
|
|
|
|
m_mainWindow->setTitle(title);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
}
|
|
|
|
break;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
case GHOST_kEventWindowClose:
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2012-05-19 09:57:55 +00:00
|
|
|
GHOST_IWindow *window2 = event->getWindow();
|
|
|
|
if (window2 == m_mainWindow) {
|
|
|
|
m_exitRequested = true;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
m_system->disposeWindow(window2);
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
case GHOST_kEventWindowActivate:
|
|
|
|
handled = false;
|
|
|
|
break;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
case GHOST_kEventWindowDeactivate:
|
|
|
|
handled = false;
|
|
|
|
break;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
case GHOST_kEventWindowUpdate:
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2012-05-19 09:57:55 +00:00
|
|
|
GHOST_IWindow *window2 = event->getWindow();
|
|
|
|
if (!m_system->validWindow(window2))
|
2002-10-12 11:37:38 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
if (stereo)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2002-12-16 10:57:08 +00:00
|
|
|
View(window2, stereo, LEFT_EYE);
|
2002-10-12 11:37:38 +00:00
|
|
|
glPushMatrix();
|
|
|
|
RenderCamera();
|
|
|
|
RenderScene();
|
|
|
|
glPopMatrix();
|
|
|
|
|
2002-12-16 10:57:08 +00:00
|
|
|
View(window2, stereo, RIGHT_EYE);
|
2002-10-12 11:37:38 +00:00
|
|
|
glPushMatrix();
|
|
|
|
RenderCamera();
|
|
|
|
RenderScene();
|
|
|
|
glPopMatrix();
|
|
|
|
}
|
2012-05-19 09:57:55 +00:00
|
|
|
else {
|
2002-12-16 10:57:08 +00:00
|
|
|
View(window2, stereo);
|
2002-10-12 11:37:38 +00:00
|
|
|
glPushMatrix();
|
|
|
|
RenderCamera();
|
|
|
|
RenderScene();
|
|
|
|
glPopMatrix();
|
|
|
|
}
|
2002-12-16 10:57:08 +00:00
|
|
|
window2->swapBuffers();
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
default:
|
|
|
|
handled = false;
|
|
|
|
break;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
return handled;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
int main(int /*argc*/, char ** /*argv*/)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
nVidiaWindows = false;
|
|
|
|
// nVidiaWindows = true;
|
|
|
|
|
|
|
|
#ifdef WIN32
|
|
|
|
/* Set a couple of settings in the registry for the nVidia detonator driver.
|
|
|
|
* So this is very specific...
|
|
|
|
*/
|
2012-05-19 09:57:55 +00:00
|
|
|
if (nVidiaWindows)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
LONG lresult;
|
|
|
|
HKEY hkey = 0;
|
|
|
|
DWORD dwd = 0;
|
2003-01-27 21:35:26 +00:00
|
|
|
//unsigned char buffer[128];
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
CRegKey regkey;
|
2003-01-27 21:35:26 +00:00
|
|
|
//DWORD keyValue;
|
2002-10-12 11:37:38 +00:00
|
|
|
// lresult = regkey.Open(HKEY_LOCAL_MACHINE, "SOFTWARE\\NVIDIA Corporation\\Global\\Stereo3D\\StereoEnable");
|
|
|
|
lresult = regkey.Open(HKEY_LOCAL_MACHINE, "SOFTWARE\\NVIDIA Corporation\\Global\\Stereo3D\\StereoEnable",
|
2011-11-11 13:09:14 +00:00
|
|
|
KEY_ALL_ACCESS);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
if (lresult == ERROR_SUCCESS)
|
2002-10-12 11:37:38 +00:00
|
|
|
printf("Succesfully opened key\n");
|
|
|
|
#if 0
|
|
|
|
lresult = regkey.QueryValue(&keyValue, "StereoEnable");
|
2012-05-19 09:57:55 +00:00
|
|
|
if (lresult == ERROR_SUCCESS)
|
2002-10-12 11:37:38 +00:00
|
|
|
printf("Succesfully queried key\n");
|
|
|
|
#endif
|
|
|
|
lresult = regkey.SetValue(HKEY_LOCAL_MACHINE, "SOFTWARE\\NVIDIA Corporation\\Global\\Stereo3D\\StereoEnable",
|
2012-05-19 09:57:55 +00:00
|
|
|
"1");
|
|
|
|
if (lresult == ERROR_SUCCESS)
|
2002-10-12 11:37:38 +00:00
|
|
|
printf("Succesfully set value for key\n");
|
|
|
|
regkey.Close();
|
2012-05-19 09:57:55 +00:00
|
|
|
if (lresult == ERROR_SUCCESS)
|
2002-10-12 11:37:38 +00:00
|
|
|
printf("Succesfully closed key\n");
|
|
|
|
// regkey.Write("2");
|
|
|
|
}
|
|
|
|
#endif // WIN32
|
|
|
|
|
|
|
|
// Create the system
|
|
|
|
GHOST_ISystem::createSystem();
|
|
|
|
fSystem = GHOST_ISystem::getSystem();
|
|
|
|
|
|
|
|
if (fSystem) {
|
|
|
|
// Create an application object
|
2012-05-19 09:57:55 +00:00
|
|
|
Application app(fSystem);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
// Add the application as event consumer
|
|
|
|
fSystem->addEventConsumer(&app);
|
|
|
|
|
|
|
|
// Enter main loop
|
|
|
|
while (!app.m_exitRequested) {
|
2012-05-19 09:57:55 +00:00
|
|
|
//printf("main: loop\n");
|
2002-10-12 11:37:38 +00:00
|
|
|
fSystem->processEvents(true);
|
|
|
|
fSystem->dispatchEvents();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Dispose the system
|
|
|
|
GHOST_ISystem::disposeSystem();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-05-19 09:57:55 +00:00
|
|
|
static void gearsTimerProc(GHOST_ITimerTask *task, GHOST_TUns64 /*time*/)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2012-05-19 09:57:55 +00:00
|
|
|
fAngle += 2.0;
|
|
|
|
view_roty += 1.0;
|
|
|
|
GHOST_IWindow *window = (GHOST_IWindow *)task->getUserData();
|
2002-10-12 11:37:38 +00:00
|
|
|
if (fApp->m_fullScreenWindow) {
|
|
|
|
// Running full screen
|
|
|
|
fApp->m_fullScreenWindow->invalidate();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (fSystem->validWindow(window)) {
|
|
|
|
window->invalidate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|