Rotation problem.
Hi, I'm somewhat new to OpenGL and I was hoping someone here could help me out. Basically I need to create a simple model display with interactive rotation controls. My only problem is that as the object rotates, the axes get out of wack.
Basically I allow the user to make a swipe and the object is supposed to rotate in the direction of the swipe. I am currently extracting the x and y components of the swipe to figure out how much to rotate on each axis.
I am storing a rotational velocity for the x, y and z components and updating based on this velocity each update.
My problem is when the object is upside down, a swipe to the right rotates it left, and vice versa.
Currently I am using glRotatef() to rotate and I am doing this 3 times-- once for each axis. I have a hunch that this is the problem.
Any insight anyone can provide would be much appreciated. Thanks!
Forget about glRotate*() and Euler angles. Based on what you've described, it sounds like you'll need to track and update the orientation yourself, and then upload it directly to OpenGL via glLoad/MultMatrix*(), or as a shader parameter.
As for storing the orientation, the obvious choices would probably be a matrix or a quaternion; for simplicity's sake, I'd recommend going with a matrix (at least for now).
When the user drags the mouse, I imagine you'd need to do a little math and convert the motion into an axis-angle pair (the angle would depend on how far the mouse moved, and the axis would be determined by the direction of motion and the relative configuration of the camera and the object). You would then update the orientation matrix using this axis-angle rotation (after which you should probably orthogonalize the matrix to prevent drift).
As for storing the orientation, the obvious choices would probably be a matrix or a quaternion; for simplicity's sake, I'd recommend going with a matrix (at least for now).
When the user drags the mouse, I imagine you'd need to do a little math and convert the motion into an axis-angle pair (the angle would depend on how far the mouse moved, and the axis would be determined by the direction of motion and the relative configuration of the camera and the object). You would then update the orientation matrix using this axis-angle rotation (after which you should probably orthogonalize the matrix to prevent drift).
Thank you very much jyk.
Do you have any tips regarding how I go about determining the correct axis to rotate.
Also, does anyone recommend any resources for transformation matrices?
Do you have any tips regarding how I go about determining the correct axis to rotate.
Also, does anyone recommend any resources for transformation matrices?
The way i do it in my simple application is i find out the up vector(its what you decide based on previous input). Then you can calculate a 2D plane which you can then rotate or tilt on. It makes it easy to find out your axis of rotation.
Btw i higly suggest using quaternions they arent to hard really once you learn em. And you dont have to understand em fully just to use em.
Btw i wasnt aware you could pass your own rotation matrices bypassing glRotate i will have to read up on this. Im using glRotate and it forces me to make a really stupid calculation to convert my quaternion back to euler angles :(
So thank you for that bit of info :)
Ive done my OpenGL in C++ and im using the vmath library for the vectors and quaternions i think those or the ones from Assimp model import library. Both works the same anyway so just decide on which one you go with.
Assimp is a really great library btw.
Btw i higly suggest using quaternions they arent to hard really once you learn em. And you dont have to understand em fully just to use em.
Btw i wasnt aware you could pass your own rotation matrices bypassing glRotate i will have to read up on this. Im using glRotate and it forces me to make a really stupid calculation to convert my quaternion back to euler angles :(
So thank you for that bit of info :)
Ive done my OpenGL in C++ and im using the vmath library for the vectors and quaternions i think those or the ones from Assimp model import library. Both works the same anyway so just decide on which one you go with.
Assimp is a really great library btw.
Please no laughing at this its my first attempt at a camera and ive done very little 3d programming.
But if it can help you out that would be cool.
Doh just realized i have the upvector hardcoded in that code. But anyway it shouldnt be to hard to manipulate it. Just have to add a another rotation depending on the upvector affecting the rotation axis.
Problem is the glRotate will still induce gimbal lock though by changing the upvector. ah lol silly me it was hardcoded also in the rendering loop.
Changed it now so it should work properly
camera.h file.
camera.cpp file
Utility method to convert quaternion back to angles i can use in glRotate
How i use the above code in my rendering loop
[Edited by - Lio on April 19, 2010 4:37:35 PM]
But if it can help you out that would be cool.
Doh just realized i have the upvector hardcoded in that code. But anyway it shouldnt be to hard to manipulate it. Just have to add a another rotation depending on the upvector affecting the rotation axis.
Problem is the glRotate will still induce gimbal lock though by changing the upvector. ah lol silly me it was hardcoded also in the rendering loop.
Changed it now so it should work properly
camera.h file.
#ifndef CAMERA_H#define CAMERA_H#include"vmath.h"#include"globals.h"typedef int CAMERA_MODE;const CAMERA_MODE CAMERA_MODE_THIRDPERSON = 0;const CAMERA_MODE CAMERA_MODE_FIRSTPERSON = 1;class Camera{private: int CAMERA_MODE; Vector3f cameraVector; //descripes the vector from position to lookAt point Vector3f position; //cameras position Vector3f lookAt; //point camera is looking at Vector3f upVector; //describes tilt and pitch of camera Vector3f projection; //projection on the plane that have the upVector as a normal vector Vector3f rotationAxis; //axis of rotation on xz planepublic: //constructors Camera(); Camera(Vector3f positon, Vector3f lookAt); ~Camera(); //public methods void SetPosition(float x, float y, float z); void SetLookAt(float x, float y, float z); void SetDirection(float x, float y); void MouseInput(float x, float y); void Move(float x, float y, float z); void UpdatePostion(); void UpdateCamera(); //get methods Vector3f GetPosition(); Vector3f GetLookAt(); Vector3f GetUpVector();};#endif
camera.cpp file
#include"camera.h"#include<iostream>using namespace std;Camera::Camera(){ this->CAMERA_MODE = CAMERA_MODE_THIRDPERSON; upVector.x = 0; upVector.y = 1; upVector.z = 0; }Camera::Camera(Vector3f position, Vector3f lookAt){ this->position = position; this->lookAt = lookAt;}Camera::~Camera(){}void Camera::SetPosition(float x, float y, float z){ position.x = x; position.y = y; position.z = z; }void Camera::SetLookAt(float x, float y, float z){ lookAt.x = x; lookAt.y = y; lookAt.z = z;}void Camera::SetDirection(float x, float y){}void Camera::MouseInput(float x, float y){ if(CAMERA_MODE == CAMERA_MODE_THIRDPERSON) { float dx = (x*M_PI)/180; float dy = (y*M_PI)/180; //creates a quaternion that can be used to rotate around our arbitary axis defined by rotationAxis vector; Quaternion<float> rotation = Quaternion<float>::fromAxisRot(rotationAxis,dy*10); //apply rotation to the delta vector cameraVector = rotation.rotMatrix() * cameraVector; //normalize upvector just to make sure its lenght 1 upVector.Normalize(); //perform rotation around the y/upVector axis rotation = Quaternion<float>::fromAxisRot(upVector,dx*10); cameraVector = rotation.rotMatrix() * cameraVector; //translate the delta vector back into is position position = cameraVector + lookAt; }}void Camera::Move(float x, float y, float z){}void Camera::UpdateCamera(){ //translate the vector to the origin point cameraVector = position - lookAt; //creates a projection of the vector on the xz plane projection = upVector.crossProduct(cameraVector.crossProduct(upVector)); //creates a perpendicular vector from the projection vector on the xz plane to rotate around rotationAxis = projection.crossProduct(upVector); //normalize the vector to allow for use by quaternion rotationAxis.normalize();}void Camera::UpdatePostion(){ Vector3f delta = cameraVector; delta.normalize(); delta = delta / 5; if(move_forward && cameraVector.length() > 5){ position -= delta; }if(move_backward){ position += delta; }}Vector3f Camera::GetPosition(){ return this->position;}Vector3f Camera::GetLookAt(){ return this->lookAt;}Vector3f Camera::GetUpVector(){ return this->upVector;}
Utility method to convert quaternion back to angles i can use in glRotate
#include"utility.h"/*Converts a quaternion to rotation axis and a scalar. Scalar is in pi's.Quaternion will be noramlized.*/void QuaternionToEulerAngles(aiQuaternion &q, aiVector3D &axis, float &scale){ if (q.w > 1) q.Normalize(); float angle = 2 * acosf(q.w); float s = sqrtf(1-q.w*q.w); if (s < 0.00001) { // test to avoid divide by zero, s is always positive due to sqrt // if s close to zero then direction of axis not important axis.x = q.x; // if it is important that axis is normalised then replace with x=1; y=z=0 axis.y = q.y; axis.z = q.z; } else { axis.x = q.x / s; // normalise axis axis.y = q.y / s; axis.z = q.z / s; } scale = s;}
How i use the above code in my rendering loop
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glClear(GL_LIGHTING_BIT); glMatrixMode( GL_MODELVIEW ); glLoadIdentity( ); camera.UpdateCamera(); camera.UpdatePostion(); Vector3f pos = camera.GetPosition(); Vector3f look = camera.GetLookAt(); Vector3f up = camera.GetUpVector(); //updates view position gluLookAt(pos.x,pos.y,pos.z,look.x,look.y,look.z,up.x,up.y,up.z); //push camera matrix glPushMatrix();
[Edited by - Lio on April 19, 2010 4:37:35 PM]
I apologize, my math skills are poor. Lio, how do I calculate a 2D plane on which to rotate? I essentially want all my rotation on the plane perpendicular the the vector from the object to the camera.
I rather not attempt to go into a lenghty description since its been along time since ive had linear algebra and i dont use math in my daily work. I just end up giving you wrong info.
But basicly just refer to a standard math formula book and look up vectors in spaces.
Its not hard. Using the Quaternions function to rotate around a vector defined axis makes the quaternion easy to work with and you get the benefit of no gimbal lock.
But basicly just refer to a standard math formula book and look up vectors in spaces.
Its not hard. Using the Quaternions function to rotate around a vector defined axis makes the quaternion easy to work with and you get the benefit of no gimbal lock.
Quote:Using the Quaternions function to rotate around a vector defined axis makes the quaternion easy to work with and you get the benefit of no gimbal lock.My usual comment: using quaternions does not protect you from gimbal lock.
Whether you use quaternions (as opposed to matrices) and whether you encounter gimbal lock are orthogonal issues; one has nothing to do with the other.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement