I thought this might be helpful for some. Derive from WASDDemoApplication instead of PlatformDemoApplication and WASD keys/arrow keys will allow you to fly through a scene.
WASDDemoApplication.h:
Code: Select all
#ifndef WASD_DEMO_APPLICATION
#define WASD_DEMO_APPLICATION
#ifdef _WINDOWS
#include "Win32DemoApplication.h"
#define PlatformDemoApplication Win32DemoApplication
#else
#include "GlutDemoApplication.h"
#define PlatformDemoApplication GlutDemoApplication
#endif
ATTRIBUTE_ALIGNED16(class) WASDDemoApplication : public PlatformDemoApplication {
private:
static const float STEPSIZE = .1;
protected:
float m_ele;
float m_azi;
btVector3 m_cameraFwd;
btVector3 m_cameraUp;
void bCreateLookAt(const btVector3& eye, const btVector3& center, const btVector3& up, GLfloat result[16]);
public:
WASDDemoApplication();
void keyboardCallback(unsigned char key, int x, int y);
void specialKeyboard(int key, int x, int y);
void strafeLeft();
void strafeRight();
void stepFront();
void stepBack();
void rotateUp();
void rotateDown();
void rotateLeft();
void rotateRight();
virtual void updateCamera();
};
#endif /* WASD_DEMO_APPLICATION */
Code: Select all
#include "WASDDemoApplication.h"
void WASDDemoApplication::bCreateLookAt(const btVector3& eye, const btVector3& center, const btVector3& up, GLfloat result[16]) {
btVector3 f = (center - eye).normalized();
btVector3 u = up.normalized();
btVector3 s = (f.cross(u)).normalized();
u = s.cross(f);
result[0*4+0] = s.x();
result[1*4+0] = s.y();
result[2*4+0] = s.z();
result[0*4+1] = u.x();
result[1*4+1] = u.y();
result[2*4+1] = u.z();
result[0*4+2] =-f.x();
result[1*4+2] =-f.y();
result[2*4+2] =-f.z();
result[0*4+3] = 0.f;
result[1*4+3] = 0.f;
result[2*4+3] = 0.f;
result[3*4+0] = -s.dot(eye);
result[3*4+1] = -u.dot(eye);
result[3*4+2] = f.dot(eye);
result[3*4+3] = 1.f;
}
void WASDDemoApplication::stepBack() {
btVector3 rayForward = (getCameraTargetPosition() - getCameraPosition());
rayForward.normalize();
m_cameraPosition -= m_zoomStepSize * rayForward;
m_cameraTargetPosition -= m_zoomStepSize * rayForward;
}
void WASDDemoApplication::stepFront() {
btVector3 rayForward = (getCameraTargetPosition()-getCameraPosition());
rayForward.normalize();
m_cameraPosition += m_zoomStepSize * rayForward;
m_cameraTargetPosition += m_zoomStepSize * rayForward;
}
void WASDDemoApplication::strafeLeft() {
btVector3 hor = getRayTo(0,0)-getRayTo(1,0);
btVector3 vert = getRayTo(0,0)-getRayTo(0,1);
btScalar multiplierX = btScalar(m_zoomStepSize/10.);
btScalar multiplierY = btScalar(m_zoomStepSize/10.);
if (m_ortho) {
multiplierX = 1;
multiplierY = 1;
}
m_cameraTargetPosition += hor * multiplierX;
m_cameraPosition += hor * multiplierX;
}
void WASDDemoApplication::strafeRight() {
btVector3 hor = -getRayTo(0,0)+getRayTo(1,0);
btVector3 vert = getRayTo(0,0)-getRayTo(0,1);
btScalar multiplierX = btScalar(m_zoomStepSize/10.);
btScalar multiplierY = btScalar(m_zoomStepSize/10.);
if (m_ortho) {
multiplierX = 1;
multiplierY = 1;
}
m_cameraTargetPosition += hor * multiplierX;
m_cameraPosition += hor * multiplierX;
}
void WASDDemoApplication::rotateLeft() {
m_ele += STEPSIZE; if (m_ele >= SIMD_PI) m_ele -= 2.*SIMD_PI; updateCamera();
}
void WASDDemoApplication::rotateRight() {
m_ele -= STEPSIZE; if (m_ele < -SIMD_PI) m_ele += 2.*SIMD_PI; updateCamera();
}
void WASDDemoApplication::rotateUp() {
m_azi -= STEPSIZE; if (m_azi < -SIMD_PI) m_azi += 2.*SIMD_PI; updateCamera();
}
void WASDDemoApplication::rotateDown() {
m_azi += STEPSIZE; if (m_azi >= SIMD_PI) m_azi -= 2.*SIMD_PI; updateCamera();
}
void WASDDemoApplication::keyboardCallback(unsigned char key, int x, int y) {
switch (key) {
case 'a' : strafeLeft(); break;
case 'd' : strafeRight(); break;
case 'w' : stepFront(); break;
case 's' : stepBack(); break;
default:
DemoApplication::keyboardCallback(key, x, y);
break;
}
}
void WASDDemoApplication::specialKeyboard(int key, int x, int y) {
switch (key) {
#ifdef _WINDOWS
case VK_LEFT : rotateLeft(); break;
case VK_RIGHT : rotateRight(); break;
case VK_UP : rotateUp(); break;
case VK_DOWN : rotateDown(); break;
#else
case GLUT_KEY_LEFT : rotateLeft(); break;
case GLUT_KEY_RIGHT : rotateRight(); break;
case GLUT_KEY_UP : rotateUp(); break;
case GLUT_KEY_DOWN : rotateDown(); break;
#endif
default:
DemoApplication::keyboardCallback(key, x, y);
break;
}
}
void WASDDemoApplication::updateCamera() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
btQuaternion camQuat(m_ele, m_azi, 0.);
m_cameraTargetPosition = btMatrix3x3(camQuat) * m_cameraFwd;
m_cameraTargetPosition += m_cameraPosition;
if (m_glutScreenWidth == 0 && m_glutScreenHeight == 0)
return;
btScalar aspect;
btVector3 extents;
aspect = m_glutScreenWidth / (btScalar)m_glutScreenHeight;
extents.setValue(aspect * 1.0f, 1.0f,0);
if (m_ortho)
{
// reset matrix
glLoadIdentity();
extents *= m_cameraDistance;
btVector3 lower = m_cameraTargetPosition - extents;
btVector3 upper = m_cameraTargetPosition + extents;
//gluOrtho2D(lower.x, upper.x, lower.y, upper.y);
glOrtho(lower.getX(), upper.getX(), lower.getY(), upper.getY(),-1000,1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//glTranslatef(100,210,0);
}
else {
//glFrustum (-aspect, aspect, -1.0, 1.0, 1.0, 10000.0);
glFrustum (-aspect * m_frustumZNear, aspect * m_frustumZNear, -m_frustumZNear, m_frustumZNear, m_frustumZNear, m_frustumZFar);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
GLfloat resultMat[16];
bCreateLookAt(m_cameraPosition,m_cameraTargetPosition, m_cameraUp, resultMat);
glMultMatrixf(resultMat);
}
}
WASDDemoApplication::WASDDemoApplication() :
m_cameraUp(0, 1, 0), // up vector for the camera without rotation
m_cameraFwd(0, 0, 1) // direction the camera points to without rotation
{
this->m_frustumZNear = 1E-2;
this->m_frustumZFar = 1E5;
}