chiser98
06-14-2011, 05:00 PM
Hi guys,
I'm just starting to work with Quaternions, but I'm having some annoying difficulties getting a simple FPS camera to work properly using Quaternions.
Hopefully this is the right place to ask about this.
Basically, whenever I try to move the mouse, a triangle I draw on the screen goes crazy and moves off and on the screen faster than I can see. Also, the movement keys (wasd) are not at all working as expected..
Here's my Camera .h file:
/*
* CameraSceneNode.h
*
* Created on: 2011-05-08
* Author: jarrett
*/
#ifndef CAMERASCENENODE_H_
#define CAMERASCENENODE_H_
#include "ICameraSceneNode.h"
#include "Quaternion.h"
//#include "IInputListener.h"
namespace icee {
namespace engine {
class CameraSceneNode: public ICameraSceneNode {
public:
CameraSceneNode();
CameraSceneNode(vmath::Vector3f position, vmath::Vector3f lookAt, bool active = true);
virtual ~CameraSceneNode();
// inherited from ICameraSceneNode
virtual void render(); // don't really need this
// inherited from ICameraSceneNode
virtual const vmath::Vector3f& getLookAt();
virtual void setLookAt(const vmath::Vector3f& newLookAt);
virtual void move(MOVE_DIRECTION dir, bool enabled);
// up/down
virtual void rotateX(float32 degrees);
// left/right
virtual void rotateY(float32 degrees);
virtual void tick(float32 time);
protected:
vmath::Vector3f lookAt_;
Quaternion rotation_;
sint32 prevX_, prevY_;
char8 movement_[NUM_MOVE_DIRECTIONS];
float32 moveSpeed_, rotSpeed_;
void clearMovementBuffer();
float32 xRot_, yRot_;
void initialize();
};
}
}
#endif /* CAMERASCENENODE_H_ */
And here's my Camera .cpp file:
/*
* CameraSceneNode.cpp
*
* Created on: 2011-05-08
* Author: jarrett
*/
#include "CameraSceneNode.h"
#include "../common/math/Math.h"
#include <GL/gl.h>
#include <iostream>
namespace icee {
namespace engine {
CameraSceneNode::CameraSceneNode() {
setLookAt(vmath::Vector3f(1, 1, 1));
setPosition(vmath::Vector3f(0, 0, 0));
active_ = true;
initialize();
}
CameraSceneNode::CameraSceneNode(vmath::Vector3f position, vmath::Vector3f lookAt, bool active) {
setPosition(position);
setLookAt(lookAt);
active_ = active;
initialize();
}
CameraSceneNode::~CameraSceneNode() {
}
void CameraSceneNode::initialize() {
clearMovementBuffer();
xRot_ = 0;
yRot_ = 0;
moveSpeed_ = 0.25f;
rotSpeed_ = 0.01f;
rotation_ = Quaternion();//(1, 1, 1, 1);
rotation_.normalize();
}
void CameraSceneNode::render() {
if (isActive()) {
float32 matrix[16];
rotation_.fillMatrix(matrix);
glMultMatrixf(&matrix[0]);
glTranslatef(-pos_.x, -pos_.y, -pos_.z);
}
}
const vmath::Vector3f& CameraSceneNode::getLookAt() {
return lookAt_;
}
void CameraSceneNode::setLookAt(const vmath::Vector3f& newLookAt) {
lookAt_ = newLookAt;
}
/**
*
*/
void CameraSceneNode::clearMovementBuffer() {
for (uint32 i = 0; i < NUM_MOVE_DIRECTIONS; i++)
movement_[i] = 0;
}
/**
*
*/
void CameraSceneNode::move(MOVE_DIRECTION dir, bool enabled) {
movement_[dir] = (enabled ? 1 : 0);
}
// up/down
/**
*
*/
void CameraSceneNode::rotateX(float32 degrees) {
xRot_ = degrees;
}
// left/right
/**
*
*/
void CameraSceneNode::rotateY(float32 degrees) {
yRot_ = degrees;
}
/**
*
*/
void CameraSceneNode::tick(float32 time) {
// movement direction
if (movement_[MOVE_DIR_FORWARD] == 1)
pos_ += rotation_ * vmath::Vector3f(0, 0, -moveSpeed_ * time);
if (movement_[MOVE_DIR_BACKWARD] == 1)
pos_ += rotation_ * vmath::Vector3f(0, 0, moveSpeed_ * time);
if (movement_[MOVE_DIR_LEFT] == 1)
pos_ += rotation_ * vmath::Vector3f(-moveSpeed_ * time, 0, 0);
if (movement_[MOVE_DIR_RIGHT] == 1)
pos_ += rotation_ * vmath::Vector3f(moveSpeed_ * time, 0, 0);
// rotation
if (xRot_ != 0) {
Quaternion quatRotation = Quaternion();
quatRotation.buildFromAxisAngle(1, 0, 0, (xRot_ * time * rotSpeed_) * math::DEGTORAD);
quatRotation.normalize();
rotation_ = rotation_ * quatRotation;
xRot_ = 0;
rotation_.normalize();
}
if (yRot_ != 0) {
Quaternion quatRotation = Quaternion();
quatRotation.buildFromAxisAngle(0, 1, 0, (yRot_ * time * rotSpeed_) * math::DEGTORAD);
quatRotation.normalize();
rotation_ = quatRotation * rotation_;
yRot_ = 0;
rotation_.normalize();
}
}
}
}
For good measure, here is also my Quaternion implementation:
/*
* Quaternion.h
*
* Created on: 2011-05-12
* Author: jarrett
*/
#ifndef QUATERNION_H_
#define QUATERNION_H_
#include "../vmath/Vector3f.h"
#include "../common/math/Math.h"
#include <math.h>
namespace icee {
namespace engine {
using namespace compatibility;
class Quaternion {
private:
float32 real_;
vmath::Vector3f imaginary_;
public:
/**
* Constructor.
*/
Quaternion() {
real_ = 1;
imaginary_ = vmath::Vector3f(0, 0, 0);
}
/**
* Constructor.
*/
Quaternion(float32 x, float32 y, float32 z, float32 real) {
real_ = real;
imaginary_ = vmath::Vector3f(x, y, z);
}
/**
* Constructor.
*/
Quaternion(const vmath::Vector3f& imaginary, float32 real) {
real_ = real;
imaginary_ = imaginary;
}
/**
* Build this Quaternion from an axis angle. This is useful if you want to use the Quaternion
* to rotate through an angle about the axis (unit) vector. The equation for this is:
* q = cos(theta/2) + vector*sin(theta/2)
*
* @param x
* @param y
* @param z
* @param angle The angle, in radians
*/
void buildFromAxisAngle(float32 x, float32 y, float32 z, float32 angle) {
// convert from degrees to radians
//float32 angle = ((degrees / 180.0f) * math::PI);
float32 sinAngle;
angle *= 0.5f;
//vmath::Vector3f vector(vec);
//vector.normalize();
sinAngle = sin(angle);
imaginary_.x = (x * sinAngle);
imaginary_.y = (y * sinAngle);
imaginary_.z = (z * sinAngle);
real_ = cos(angle);
}
/*
// Convert from Euler Angles
Quaternion(float32 pitch, float32 yaw, float32 roll) {
// Basically we create 3 Quaternions, one for pitch, one for yaw, one for roll
// and multiply those together.
// the calculation below does the same, just shorter
float p = pitch * PIOVER180 / 2.0;
float y = yaw * PIOVER180 / 2.0;
float r = roll * PIOVER180 / 2.0;
float sinp = sin(p);
float siny = sin(y);
float sinr = sin(r);
float cosp = cos(p);
float cosy = cos(y);
float cosr = cos(r);
this->x = sinr * cosp * cosy - cosr * sinp * siny;
this->y = cosr * sinp * cosy + sinr * cosp * siny;
this->z = cosr * cosp * siny - sinr * sinp * cosy;
this->w = cosr * cosp * cosy + sinr * sinp * siny;
normalise();
}
*/
/**
* Copy constructor.
*/
Quaternion(const Quaternion &quat) {
real_ = quat.real_;
imaginary_ = quat.imaginary_;
}
/**
* Destructor.
*/
virtual ~Quaternion() {
}
const Quaternion& operator =(const Quaternion &quat) {
real_ = quat.real_;
imaginary_ = quat.imaginary_;
return *this;
}
const Quaternion operator +(const Quaternion &quat) const {
return Quaternion(imaginary_ + quat.imaginary_, real_ + quat.real_);
}
const Quaternion operator -(const Quaternion &quat) const {
return Quaternion(imaginary_ - quat.imaginary_, real_ - quat.real_);
}
const Quaternion operator *(const Quaternion &quat) const {
return Quaternion(
imaginary_.y * quat.imaginary_.z - imaginary_.z * quat.imaginary_.y + real_
* quat.imaginary_.x + imaginary_.x * quat.real_,
imaginary_.z * quat.imaginary_.x - imaginary_.x * quat.imaginary_.z + real_
* quat.imaginary_.y + imaginary_.y * quat.real_,
imaginary_.x * quat.imaginary_.y - imaginary_.y * quat.imaginary_.x + real_
* quat.imaginary_.z + imaginary_.z * quat.real_,
real_ * quat.real_ - imaginary_ * quat.imaginary_);
}
// Multiplying a quaternion q with a vector v applies the q-rotation to v
const vmath::Vector3f operator*(const vmath::Vector3f &vec) {
vmath::Vector3f vector(vec);
vector.normalize();
Quaternion vectorQuat, resultQuat;
vectorQuat.imaginary_.x = vector.x;
vectorQuat.imaginary_.y = vector.y;
vectorQuat.imaginary_.z = vector.z;
vectorQuat.real_ = 0.0f;
resultQuat = vectorQuat * getConjugate();
resultQuat = *this * resultQuat;
return (vmath::Vector3f(resultQuat.imaginary_.x, resultQuat.imaginary_.y,
resultQuat.imaginary_.z));
}
const Quaternion operator /(const Quaternion &quat) const {
Quaternion retQuat(quat);
retQuat.invert();
return *this * retQuat;
}
const Quaternion& operator /=(float32 scale) {
real_ /= scale;
imaginary_ /= scale;
return *this;
}
void invert() {
conjugate();
*this /= lengthSquared();
}
void conjugate() {
imaginary_ *= (-1.f);
}
Quaternion getConjugate() {
return Quaternion(-imaginary_.x, -imaginary_.y, -imaginary_.z, real_);
}
float32 length() const {
return (float32) (sqrt(real_ * real_ + imaginary_ * imaginary_));
}
/**
* Get the squared length of this quaternion.
*/
float32 lengthSquared() {
return (float32) (real_ * real_ + imaginary_ * imaginary_);
}
void normalize() {
*this /= length();
}
/**
*
* Fills in Column-Major order.
*/
void fillMatrix(float32 matrix[]) {
// First col
matrix[0] = 1.0f - 2.0f * (imaginary_.y * imaginary_.y + imaginary_.z * imaginary_.z);
matrix[1] = 2.0f * (imaginary_.x * imaginary_.y + imaginary_.z * real_);
matrix[2] = 2.0f * (imaginary_.x * imaginary_.z - imaginary_.y * real_);
matrix[3] = 0.0f;
// Second col
matrix[4] = 2.0f * (imaginary_.x * imaginary_.y - imaginary_.z * real_);
matrix[5] = 1.0f - 2.0f * (imaginary_.x * imaginary_.x + imaginary_.z * imaginary_.z);
matrix[6] = 2.0f * (imaginary_.z * imaginary_.y + imaginary_.x * real_);
matrix[7] = 0.0f;
// Third col
matrix[8] = 2.0f * (imaginary_.x * imaginary_.z + imaginary_.y * real_);
matrix[9] = 2.0f * (imaginary_.y * imaginary_.z - imaginary_.x * real_);
matrix[10] = 1.0f - 2.0f * (imaginary_.x * imaginary_.x + imaginary_.y * imaginary_.y);
matrix[11] = 0.0f;
// Fourth col
matrix[12] = 0;
matrix[13] = 0;
matrix[14] = 0;
matrix[15] = 1.0f;
}
/*
// Convert to Matrix
Matrix4 getMatrix() const {
float x2 = x * x;
float y2 = y * y;
float z2 = z * z;
float xy = x * y;
float xz = x * z;
float yz = y * z;
float wx = w * x;
float wy = w * y;
float wz = w * z;
// This calculation would be a lot more complicated for non-unit length quaternions
// Note: The constructor of Matrix4 expects the Matrix in column-major format like expected by
// OpenGL
return Matrix4( 1.0f - 2.0f * (y2 + z2), 2.0f * (xy - wz), 2.0f * (xz + wy), 0.0f,
2.0f * (xy + wz), 1.0f - 2.0f * (x2 + z2), 2.0f * (yz - wx), 0.0f,
2.0f * (xz - wy), 2.0f * (yz + wx), 1.0f - 2.0f * (x2 + y2), 0.0f,
0.0f, 0.0f, 0.0f, 1.0f)
}
*/
/*
// Convert to Axis/Angles
void getAxisAngle(Vector3* axis, float* angle) {
float scale = sqrt(x * x + y * y + z * z);
axis->x = x / scale;
axis->y = y / scale;
axis->z = z / scale;
*angle = acos(w) * 2.0f;
}
*/
};
}
}
#endif /* QUATERNION_H_ */
It is important to mention that before CameraSceneNode::render() gets called, the following bit of code is called first:
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
What happens in my game loop is that CameraSceneNode::tick(..) gets called, which updates the movement/rotation variables. Then after some other code, CameraSceneNode::render() is called.
I know that's a lot of code to look over, but I would really appreciate it if anyone could see any (hopefully!) glaring omissions or errors on my part. Also, if something isn't clear just ask!
Thanks all,
Jarrett
I'm just starting to work with Quaternions, but I'm having some annoying difficulties getting a simple FPS camera to work properly using Quaternions.
Hopefully this is the right place to ask about this.
Basically, whenever I try to move the mouse, a triangle I draw on the screen goes crazy and moves off and on the screen faster than I can see. Also, the movement keys (wasd) are not at all working as expected..
Here's my Camera .h file:
/*
* CameraSceneNode.h
*
* Created on: 2011-05-08
* Author: jarrett
*/
#ifndef CAMERASCENENODE_H_
#define CAMERASCENENODE_H_
#include "ICameraSceneNode.h"
#include "Quaternion.h"
//#include "IInputListener.h"
namespace icee {
namespace engine {
class CameraSceneNode: public ICameraSceneNode {
public:
CameraSceneNode();
CameraSceneNode(vmath::Vector3f position, vmath::Vector3f lookAt, bool active = true);
virtual ~CameraSceneNode();
// inherited from ICameraSceneNode
virtual void render(); // don't really need this
// inherited from ICameraSceneNode
virtual const vmath::Vector3f& getLookAt();
virtual void setLookAt(const vmath::Vector3f& newLookAt);
virtual void move(MOVE_DIRECTION dir, bool enabled);
// up/down
virtual void rotateX(float32 degrees);
// left/right
virtual void rotateY(float32 degrees);
virtual void tick(float32 time);
protected:
vmath::Vector3f lookAt_;
Quaternion rotation_;
sint32 prevX_, prevY_;
char8 movement_[NUM_MOVE_DIRECTIONS];
float32 moveSpeed_, rotSpeed_;
void clearMovementBuffer();
float32 xRot_, yRot_;
void initialize();
};
}
}
#endif /* CAMERASCENENODE_H_ */
And here's my Camera .cpp file:
/*
* CameraSceneNode.cpp
*
* Created on: 2011-05-08
* Author: jarrett
*/
#include "CameraSceneNode.h"
#include "../common/math/Math.h"
#include <GL/gl.h>
#include <iostream>
namespace icee {
namespace engine {
CameraSceneNode::CameraSceneNode() {
setLookAt(vmath::Vector3f(1, 1, 1));
setPosition(vmath::Vector3f(0, 0, 0));
active_ = true;
initialize();
}
CameraSceneNode::CameraSceneNode(vmath::Vector3f position, vmath::Vector3f lookAt, bool active) {
setPosition(position);
setLookAt(lookAt);
active_ = active;
initialize();
}
CameraSceneNode::~CameraSceneNode() {
}
void CameraSceneNode::initialize() {
clearMovementBuffer();
xRot_ = 0;
yRot_ = 0;
moveSpeed_ = 0.25f;
rotSpeed_ = 0.01f;
rotation_ = Quaternion();//(1, 1, 1, 1);
rotation_.normalize();
}
void CameraSceneNode::render() {
if (isActive()) {
float32 matrix[16];
rotation_.fillMatrix(matrix);
glMultMatrixf(&matrix[0]);
glTranslatef(-pos_.x, -pos_.y, -pos_.z);
}
}
const vmath::Vector3f& CameraSceneNode::getLookAt() {
return lookAt_;
}
void CameraSceneNode::setLookAt(const vmath::Vector3f& newLookAt) {
lookAt_ = newLookAt;
}
/**
*
*/
void CameraSceneNode::clearMovementBuffer() {
for (uint32 i = 0; i < NUM_MOVE_DIRECTIONS; i++)
movement_[i] = 0;
}
/**
*
*/
void CameraSceneNode::move(MOVE_DIRECTION dir, bool enabled) {
movement_[dir] = (enabled ? 1 : 0);
}
// up/down
/**
*
*/
void CameraSceneNode::rotateX(float32 degrees) {
xRot_ = degrees;
}
// left/right
/**
*
*/
void CameraSceneNode::rotateY(float32 degrees) {
yRot_ = degrees;
}
/**
*
*/
void CameraSceneNode::tick(float32 time) {
// movement direction
if (movement_[MOVE_DIR_FORWARD] == 1)
pos_ += rotation_ * vmath::Vector3f(0, 0, -moveSpeed_ * time);
if (movement_[MOVE_DIR_BACKWARD] == 1)
pos_ += rotation_ * vmath::Vector3f(0, 0, moveSpeed_ * time);
if (movement_[MOVE_DIR_LEFT] == 1)
pos_ += rotation_ * vmath::Vector3f(-moveSpeed_ * time, 0, 0);
if (movement_[MOVE_DIR_RIGHT] == 1)
pos_ += rotation_ * vmath::Vector3f(moveSpeed_ * time, 0, 0);
// rotation
if (xRot_ != 0) {
Quaternion quatRotation = Quaternion();
quatRotation.buildFromAxisAngle(1, 0, 0, (xRot_ * time * rotSpeed_) * math::DEGTORAD);
quatRotation.normalize();
rotation_ = rotation_ * quatRotation;
xRot_ = 0;
rotation_.normalize();
}
if (yRot_ != 0) {
Quaternion quatRotation = Quaternion();
quatRotation.buildFromAxisAngle(0, 1, 0, (yRot_ * time * rotSpeed_) * math::DEGTORAD);
quatRotation.normalize();
rotation_ = quatRotation * rotation_;
yRot_ = 0;
rotation_.normalize();
}
}
}
}
For good measure, here is also my Quaternion implementation:
/*
* Quaternion.h
*
* Created on: 2011-05-12
* Author: jarrett
*/
#ifndef QUATERNION_H_
#define QUATERNION_H_
#include "../vmath/Vector3f.h"
#include "../common/math/Math.h"
#include <math.h>
namespace icee {
namespace engine {
using namespace compatibility;
class Quaternion {
private:
float32 real_;
vmath::Vector3f imaginary_;
public:
/**
* Constructor.
*/
Quaternion() {
real_ = 1;
imaginary_ = vmath::Vector3f(0, 0, 0);
}
/**
* Constructor.
*/
Quaternion(float32 x, float32 y, float32 z, float32 real) {
real_ = real;
imaginary_ = vmath::Vector3f(x, y, z);
}
/**
* Constructor.
*/
Quaternion(const vmath::Vector3f& imaginary, float32 real) {
real_ = real;
imaginary_ = imaginary;
}
/**
* Build this Quaternion from an axis angle. This is useful if you want to use the Quaternion
* to rotate through an angle about the axis (unit) vector. The equation for this is:
* q = cos(theta/2) + vector*sin(theta/2)
*
* @param x
* @param y
* @param z
* @param angle The angle, in radians
*/
void buildFromAxisAngle(float32 x, float32 y, float32 z, float32 angle) {
// convert from degrees to radians
//float32 angle = ((degrees / 180.0f) * math::PI);
float32 sinAngle;
angle *= 0.5f;
//vmath::Vector3f vector(vec);
//vector.normalize();
sinAngle = sin(angle);
imaginary_.x = (x * sinAngle);
imaginary_.y = (y * sinAngle);
imaginary_.z = (z * sinAngle);
real_ = cos(angle);
}
/*
// Convert from Euler Angles
Quaternion(float32 pitch, float32 yaw, float32 roll) {
// Basically we create 3 Quaternions, one for pitch, one for yaw, one for roll
// and multiply those together.
// the calculation below does the same, just shorter
float p = pitch * PIOVER180 / 2.0;
float y = yaw * PIOVER180 / 2.0;
float r = roll * PIOVER180 / 2.0;
float sinp = sin(p);
float siny = sin(y);
float sinr = sin(r);
float cosp = cos(p);
float cosy = cos(y);
float cosr = cos(r);
this->x = sinr * cosp * cosy - cosr * sinp * siny;
this->y = cosr * sinp * cosy + sinr * cosp * siny;
this->z = cosr * cosp * siny - sinr * sinp * cosy;
this->w = cosr * cosp * cosy + sinr * sinp * siny;
normalise();
}
*/
/**
* Copy constructor.
*/
Quaternion(const Quaternion &quat) {
real_ = quat.real_;
imaginary_ = quat.imaginary_;
}
/**
* Destructor.
*/
virtual ~Quaternion() {
}
const Quaternion& operator =(const Quaternion &quat) {
real_ = quat.real_;
imaginary_ = quat.imaginary_;
return *this;
}
const Quaternion operator +(const Quaternion &quat) const {
return Quaternion(imaginary_ + quat.imaginary_, real_ + quat.real_);
}
const Quaternion operator -(const Quaternion &quat) const {
return Quaternion(imaginary_ - quat.imaginary_, real_ - quat.real_);
}
const Quaternion operator *(const Quaternion &quat) const {
return Quaternion(
imaginary_.y * quat.imaginary_.z - imaginary_.z * quat.imaginary_.y + real_
* quat.imaginary_.x + imaginary_.x * quat.real_,
imaginary_.z * quat.imaginary_.x - imaginary_.x * quat.imaginary_.z + real_
* quat.imaginary_.y + imaginary_.y * quat.real_,
imaginary_.x * quat.imaginary_.y - imaginary_.y * quat.imaginary_.x + real_
* quat.imaginary_.z + imaginary_.z * quat.real_,
real_ * quat.real_ - imaginary_ * quat.imaginary_);
}
// Multiplying a quaternion q with a vector v applies the q-rotation to v
const vmath::Vector3f operator*(const vmath::Vector3f &vec) {
vmath::Vector3f vector(vec);
vector.normalize();
Quaternion vectorQuat, resultQuat;
vectorQuat.imaginary_.x = vector.x;
vectorQuat.imaginary_.y = vector.y;
vectorQuat.imaginary_.z = vector.z;
vectorQuat.real_ = 0.0f;
resultQuat = vectorQuat * getConjugate();
resultQuat = *this * resultQuat;
return (vmath::Vector3f(resultQuat.imaginary_.x, resultQuat.imaginary_.y,
resultQuat.imaginary_.z));
}
const Quaternion operator /(const Quaternion &quat) const {
Quaternion retQuat(quat);
retQuat.invert();
return *this * retQuat;
}
const Quaternion& operator /=(float32 scale) {
real_ /= scale;
imaginary_ /= scale;
return *this;
}
void invert() {
conjugate();
*this /= lengthSquared();
}
void conjugate() {
imaginary_ *= (-1.f);
}
Quaternion getConjugate() {
return Quaternion(-imaginary_.x, -imaginary_.y, -imaginary_.z, real_);
}
float32 length() const {
return (float32) (sqrt(real_ * real_ + imaginary_ * imaginary_));
}
/**
* Get the squared length of this quaternion.
*/
float32 lengthSquared() {
return (float32) (real_ * real_ + imaginary_ * imaginary_);
}
void normalize() {
*this /= length();
}
/**
*
* Fills in Column-Major order.
*/
void fillMatrix(float32 matrix[]) {
// First col
matrix[0] = 1.0f - 2.0f * (imaginary_.y * imaginary_.y + imaginary_.z * imaginary_.z);
matrix[1] = 2.0f * (imaginary_.x * imaginary_.y + imaginary_.z * real_);
matrix[2] = 2.0f * (imaginary_.x * imaginary_.z - imaginary_.y * real_);
matrix[3] = 0.0f;
// Second col
matrix[4] = 2.0f * (imaginary_.x * imaginary_.y - imaginary_.z * real_);
matrix[5] = 1.0f - 2.0f * (imaginary_.x * imaginary_.x + imaginary_.z * imaginary_.z);
matrix[6] = 2.0f * (imaginary_.z * imaginary_.y + imaginary_.x * real_);
matrix[7] = 0.0f;
// Third col
matrix[8] = 2.0f * (imaginary_.x * imaginary_.z + imaginary_.y * real_);
matrix[9] = 2.0f * (imaginary_.y * imaginary_.z - imaginary_.x * real_);
matrix[10] = 1.0f - 2.0f * (imaginary_.x * imaginary_.x + imaginary_.y * imaginary_.y);
matrix[11] = 0.0f;
// Fourth col
matrix[12] = 0;
matrix[13] = 0;
matrix[14] = 0;
matrix[15] = 1.0f;
}
/*
// Convert to Matrix
Matrix4 getMatrix() const {
float x2 = x * x;
float y2 = y * y;
float z2 = z * z;
float xy = x * y;
float xz = x * z;
float yz = y * z;
float wx = w * x;
float wy = w * y;
float wz = w * z;
// This calculation would be a lot more complicated for non-unit length quaternions
// Note: The constructor of Matrix4 expects the Matrix in column-major format like expected by
// OpenGL
return Matrix4( 1.0f - 2.0f * (y2 + z2), 2.0f * (xy - wz), 2.0f * (xz + wy), 0.0f,
2.0f * (xy + wz), 1.0f - 2.0f * (x2 + z2), 2.0f * (yz - wx), 0.0f,
2.0f * (xz - wy), 2.0f * (yz + wx), 1.0f - 2.0f * (x2 + y2), 0.0f,
0.0f, 0.0f, 0.0f, 1.0f)
}
*/
/*
// Convert to Axis/Angles
void getAxisAngle(Vector3* axis, float* angle) {
float scale = sqrt(x * x + y * y + z * z);
axis->x = x / scale;
axis->y = y / scale;
axis->z = z / scale;
*angle = acos(w) * 2.0f;
}
*/
};
}
}
#endif /* QUATERNION_H_ */
It is important to mention that before CameraSceneNode::render() gets called, the following bit of code is called first:
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
What happens in my game loop is that CameraSceneNode::tick(..) gets called, which updates the movement/rotation variables. Then after some other code, CameraSceneNode::render() is called.
I know that's a lot of code to look over, but I would really appreciate it if anyone could see any (hopefully!) glaring omissions or errors on my part. Also, if something isn't clear just ask!
Thanks all,
Jarrett