Third person rotation

Started by
9 comments, last by BreathOfLife 15 years, 10 months ago
Hi all, I was trying to do a third person view for days now, but could get nothing to work properly. According to the gamedev tutorial http://www.gamedev.net/reference/articles/article1591.asp I was able to get this thing running quite good. But... I can only rotate around the y axis. So, if I want to rotate around the x axis I tried to add this: float cameray = cameradist * Math.sin((xrot * Math.PI / 180.0) + ypos); Works fine but the rotation gets inversed wehen i get too low or too high. What to do about that?
Advertisement
That's called Gimbal lock, and is a problem inherent in trying to represent rotations with Euler angles, which is probably what you are doing.

To remedy this, you need a different representation of rotations. The most straightforward is probably to use a rotation matrix. I recommend using a ready-made math library (such as CML) for usable matrix and vector data types.
-------------Please rate this post if it was useful.
ahh okay... got that. Heard of the Gimbal Lock before, but never experienced. Am kind a new to 3D programming. Can you tell me where to find good tutorials on matrices? I really want to understand the whole thing instead of (before) using pre-coded classes an functions.
Uhm... do you know any good Java Math Libs, beside VecMath?

Thanks for your answer so far!
There's a sample chapter here that gives some great explanations for how to understand matrices geometrically, though it would be best if you already understand vectors before reading it. If you don't, there's a long sample chapter here that covers them.
Quote:Original post by Hnefi
That's called Gimbal lock, and is a problem inherent in trying to represent rotations with Euler angles, which is probably what you are doing.
Umm, no. This has nothing whatsoever to do with gimbal lock - nor does gimbal lock have much to do with the particular representation.

Quote:Original post by hasta84
Works fine but the rotation gets inversed wehen i get too low or too high.
At what point does the inversion happen, and which axis becomes inverted? I assume the y axis, but does it flip before the vertical (since obviously, it will flip if you go past vertical).

Also, why is + ypos inside the Math.sin() cal in your code snippet there?

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Quote:Original post by swiftcoder
Quote:Original post by Hnefi
That's called Gimbal lock, and is a problem inherent in trying to represent rotations with Euler angles, which is probably what you are doing.
Umm, no. This has nothing whatsoever to do with gimbal lock

Oops. You are right. I used the wrong terminology. I'm unable to find any terminology to describe this phenomenon. What's it called?
Quote:- nor does gimbal lock have much to do with the particular representation.

Actually, it does. Quaternions, for example, does not suffer from gimbal lock.

-------------Please rate this post if it was useful.
Hi,

I spent the last days now almost only for studying matrices and quaternions and I think I now know what those are and what you can do. But... I just can't understand how to describe my desired rotation with one of them. That just won't go in my head. I read many tutorials on quaternions and matrices to do rotations... I now almost think I'm an idiot because I can't do a rotation...
I work with Java and lwjgl by the way...

There are so many questions...
Some tutorials work with the "right-vector", what's that?
One says the Up Vector can be ignored, the other that it's important?
What's true?
All tutorials I found were on opengl and C or C# or C++, isn't there any tutorial on Java so I can understand how it works in code?

Thanks for all your help!

Greetings, hasta
Hey, I tried to solve it with gluLookAt, but how to combine the rotX and rotY?


import java.util.logging.Level;
import java.util.logging.Logger;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.*;
import org.lwjgl.util.glu.GLU;
import org.lwjgl.util.vector.Vector3f;

public class test {

static Vector3f camPos = new Vector3f();
static float distance = 4.0f;
static float angleY = 0.0f;
static float angleX = 0.0f;

public static void main(String[] args){
try {
DisplayMode displayMode = null;

Display.setFullscreen(false);
DisplayMode[] d = Display.getAvailableDisplayModes();
for (int i = 0; i < d.length; i++) {
if (d.getWidth() == 640 && d.getHeight() == 480 && d.getBitsPerPixel() == 32) {
displayMode = d;
break;
}
}
Display.setDisplayMode(displayMode);
Display.setTitle("test");
Display.create();

GL11.glShadeModel(GL11.GL_SMOOTH);
GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GL11.glClearDepth(1.0f);
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glDepthFunc(GL11.GL_LEQUAL);

GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();

GLU.gluPerspective(45.0f, (float) displayMode.getWidth() / (float) displayMode.getWidth(),0.1f,100.0f);
GL11.glMatrixMode(GL11.GL_MODELVIEW);

GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);

boolean running = true;

Mouse.create();

while(running){

if(Mouse.isButtonDown(0)){
angleY += Mouse.getDX() * 0.5f;
angleX += Mouse.getDY() * 0.5f;
}
if(Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) { // Exit if Escape is pressed
running = false;
}
if(Display.isCloseRequested()) { // Exit if window is closed
running = false;
}

GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glMatrixMode(GL11.GL_MODELVIEW);

GL11.glLoadIdentity();

float camX = (float) (distance * Math.sin(angleY * Math.PI / 180.0));
float camZ = (float) (distance * Math.cos(angleY * Math.PI / 180.0));
Vector3f rotY = new Vector3f(camX, camPos.y, camZ);

float camY = (float) (distance * Math.sin(angleX * Math.PI / 180.0));
camZ = (float) (distance * Math.cos(angleX * Math.PI / 180.0));
Vector3f rotX = new Vector3f(camPos.x, camY, camZ);

//Take the Y rotation
camPos.x = rotY.x;
camPos.z = rotY.z;

//Take the X rotation
//camPos.y = rotX.y;
//camPos.z = rotX.z;

GLU.gluLookAt(camPos.x, camPos.y, camPos.z, 0, 0, 0, 0, 1, 0);

GL11.glBegin(GL11.GL_TRIANGLES);
GL11.glColor3f(1.0f,0.0f,0.0f);
GL11.glVertex3f( 0.0f, 1.0f, 0.0f);
GL11.glColor3f(0.0f,1.0f,0.0f);
GL11.glVertex3f(-1.0f,-1.0f, 1.0f);
GL11.glColor3f(0.0f,0.0f,1.0f);
GL11.glVertex3f( 1.0f,-1.0f, 1.0f);
GL11.glColor3f(1.0f,0.0f,0.0f);
GL11.glVertex3f( 0.0f, 1.0f, 0.0f);
GL11.glColor3f(0.0f,0.0f,1.0f);
GL11.glVertex3f( 1.0f,-1.0f, 1.0f);
GL11.glColor3f(0.0f,1.0f,0.0f);
GL11.glVertex3f( 1.0f,-1.0f, -1.0f);
GL11.glColor3f(1.0f,0.0f,0.0f);
GL11.glVertex3f( 0.0f, 1.0f, 0.0f);
GL11.glColor3f(0.0f,1.0f,0.0f);
GL11.glVertex3f( 1.0f,-1.0f, -1.0f);
GL11.glColor3f(0.0f,0.0f,1.0f);
GL11.glVertex3f(-1.0f,-1.0f, -1.0f);
GL11.glColor3f(1.0f,0.0f,0.0f);
GL11.glVertex3f( 0.0f, 1.0f, 0.0f);
GL11.glColor3f(0.0f,0.0f,1.0f);
GL11.glVertex3f(-1.0f,-1.0f,-1.0f);
GL11.glColor3f(0.0f,1.0f,0.0f);
GL11.glVertex3f(-1.0f,-1.0f, 1.0f);
GL11.glEnd();

Display.update();
}

Display.destroy();

} catch (LWJGLException ex) {
Logger.getLogger(test.class.getName()).log(Level.SEVERE, null, ex);
System.exit(0);
}

}
}


This is what i have so far to test...
Quote:Original post by Hnefi
Quote:Original post by swiftcoder
- nor does gimbal lock have much to do with the particular representation.

Actually, it does. Quaternions, for example, does not suffer from gimbal lock.

swiftcoder has it right - you can run into gimbal lock while using quaternions, and you can also avoid them if you use vectors and matrices appropriately. See the third post, followed quickly by the second, here for a full discussion.
Okay, but that doesn't help me with my problem...

How do I combine the two rotations into one?

This topic is closed to new replies.

Advertisement