Jump to content
  • Advertisement
Sign in to follow this  
vidjogamer

OpenGL Rotation problem.

This topic is 3073 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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!

Share this post


Link to post
Share on other sites
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).

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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 plane
public:
//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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!