Rotation problem.

Started by
6 comments, last by Zakwayda 13 years, 12 months ago
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!
Advertisement
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).
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?
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.
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.

#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.
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