Rotation Anomalies?

Started by chrizo, April 22, 2008, 16:22:34

Previous topic - Next topic

chrizo

Hi, guys!

I've been trying to simulate "mouse look" for some time now and I noticed the i couldn't seem to get it correctly. I noticed that the axis switch places from time to time. I tried drawing the axis lines and I found something weird...  :'(

Here is my code so far... Can anybody help?
import org.lwjgl.input.Mouse;
import org.lwjgl.util.Timer;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.glu.GLU;

public class DisplayWindow 
{
	private Timer t;
	private DisplayMode chosenDisplayMode;
	private boolean displayRunning;	
	private float camZoom;
	private float camPanX;
	private float camPanY;

	private float camAngleX;
	private float camAngleY;
	private float chosenDisplayWidth;
	private float chosenDisplayHeight;
	
	public DisplayWindow (int displayWidth, int displayHeight)
	{
		try
		{
			DisplayMode displayMode[] = Display.getAvailableDisplayModes();
			for (int i=0; i < displayMode.length; i++)
			{
				if ((displayMode[i].getWidth() == displayWidth) && (displayMode[i].getHeight() == displayHeight) && (displayMode[i].getBitsPerPixel() == 32)) 
				chosenDisplayMode = displayMode[i];
			}
		}
		catch (LWJGLException e)
		{
			e.printStackTrace();
			System.exit(0);
		}
		
		t = new Timer();
		camZoom = 0.0f;
		chosenDisplayWidth = chosenDisplayMode.getWidth();
		chosenDisplayHeight = chosenDisplayMode.getHeight();
		camPanX = 0.0f;
		camPanY = 0.0f;
		camAngleX = 0.0f;
		camAngleY = 0.0f;
		displayRunning = true;
	}
	
	public void createWindow (int framesPerSecond)
	{
		try
		{
			Display.setDisplayMode(chosenDisplayMode);			
			Display.create();	
			Display.setFullscreen(false);		
			Mouse.create();
			Mouse.setGrabbed(true);			
		}
		catch (LWJGLException e)
		{
			e.printStackTrace();
			System.exit(0);
		}
		
		initGraphics();

		while (displayRunning)
		{
			inputKeyboard();
			Display.update();			
			Display.sync(framesPerSecond);
			Timer.tick();			
			GL11.glClear (GL11.GL_COLOR_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT);
			GL11.glLoadIdentity();
			updateCamera ();	
			GL11.glPushMatrix();
			showOrigin(1);								
			triangle();
			

			GL11.glPopMatrix();
		}		
		Display.destroy();
	}
	
	public void showOrigin(float length)
	{
		GL11.glPushMatrix();				
		GL11.glBegin(GL11.GL_LINES);				
		GL11.glColor3f(0, 0, 0);		GL11.glVertex3f(-length, 0, 0);
		GL11.glColor3f(1, 0, 0); 		GL11.glVertex3f(length, 0, 0);
		GL11.glColor3f(0, 0, 0); 	GL11.glVertex3f(0, -length, 0);
		GL11.glColor3f(1, 1, 0);		GL11.glVertex3f(0, length, 0);				
		GL11.glColor3f(0, 0, 0); 	GL11.glVertex3f(0, 0, -length);
		GL11.glColor3f(0, 0, 1);		GL11.glVertex3f(0, 0, length);				
		GL11.glEnd();
		GL11.glPopMatrix();	
	}
	
	public void triangle()
	{
		GL11.glPushMatrix();				
		GL11.glBegin(GL11.GL_TRIANGLES);	
			GL11.glColor3d(0, 0, 1);
			GL11.glVertex3f(-0.2f, -0.2f, 0.0f);
			GL11.glColor3d(0, 1, 0);
			GL11.glVertex3f(0.0f, 0.2f, 0.0f);
			GL11.glColor3d(1, 0, 0);
			GL11.glVertex3f(0.2f, -0.2f, 0.0f);
		GL11.glEnd();
		GL11.glPopMatrix();	
	}
	
	public void updateCamera ()
	{				
/*
		if (camAngleX <= 359.9999999f && camAngleX >= 0.0f) camAngleX += Mouse.getDX()* 0.1f;
		else if (camAngleX > 359.9999999f) camAngleX = Mouse.getDX()* 0.1f;
		else if (camAngleX < 0.0f) camAngleX = 359.9999999f + (Mouse.getDX()* 0.1f);
	
		if (camAngleY <= 359.9999999f && camAngleY >= 0.0f) camAngleY += Mouse.getDY()* 0.1f;
		else if (camAngleY > 359.9999999f) camAngleY = Mouse.getDY()* 0.1f;
		else if (camAngleY < 0.0f) camAngleY = 359.9999999f + (Mouse.getDY()* 0.1f);
*/		
		//camAngleX += Mouse.getDX()* 0.1f;
		//camAngleY += Mouse.getDY()* 0.1f;
		
		//GL11.glTranslated(0.0f, 0.0f, 5.0f); //try to do sine cosine on this translate
		//GL11.glRotatef(camAngleX, 0.0f, 1.0f, 0.0f);
		GL11.glTranslated(1.0f, 0.0f, -5.0f);
		GL11.glRotatef(camAngleY, 1.0f, 0.0f, 0.0f);
		//GL11.glRotatef(camAngleX, 0.0f, 1.0f, 0.0f);
		//GL11.glTranslated(0.0f, 0.0f, camZoom);		
		//GL11.glTranslate
		//GL11.glRotatef(camPanX, 0.0f, 1.0f, 0.0f);
		
		System.out.println(t.getTime()+"("+camAngleX+","+camAngleY+")" + camZoom);			
	}
	
	public void inputKeyboard ()
	{
		if (Display.isCloseRequested() || Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) displayRunning = false;
		if (Keyboard.isKeyDown(Keyboard.KEY_S))camAngleY -= .2f;
		if (Keyboard.isKeyDown(Keyboard.KEY_W)) camAngleY += .2f;
		//if (Keyboard.isKeyDown(Keyboard.KEY_D)) camPanX -= 0.2f;
		//if (Keyboard.isKeyDown(Keyboard.KEY_A)) camPanX += 0.2f;
	}
	
	public void initGraphics ()
	{
	    GL11.glShadeModel(GL11.GL_SMOOTH);
		GL11.glMatrixMode (GL11.GL_PROJECTION);
		GL11.glLoadIdentity();		
		GLU.gluPerspective(45.0f, (chosenDisplayWidth/chosenDisplayHeight), 0.0f, 50.0f);		
		GL11.glMatrixMode (GL11.GL_MODELVIEW);		
	}
	
	public static void main (String args[])
	{		
		DisplayWindow Window = new DisplayWindow(640, 480);
		Window.createWindow(60);		
	}	
}

I'm very new to OpenGL & Java so... sorry for the mess.  :P ::)

It took me a while to try to narrow the problem down, so please try to ignore the commented code.

If I run the code above, i notice that i get a different rotation as I hold down w or s. (+) z-axis tends to flip towards or away from me.

that is what I get when I increment or decrement camAngleY with a small number...

      if (Keyboard.isKeyDown(Keyboard.KEY_S)) camAngleY -= .2f;
      if (Keyboard.isKeyDown(Keyboard.KEY_W)) camAngleY += .2f;

but when I increment or decrement camAngleY with a bigger number... lets say

           if (Keyboard.isKeyDown(Keyboard.KEY_S)) camAngleY -= 1.0f;
      if (Keyboard.isKeyDown(Keyboard.KEY_W)) camAngleY += 1.0f;

the problem is gone!

What the hell happened?

My guess is when hits camAngleY exactly 0.0 degrees... its screws up?

Any thoughts guys?  :-\

wolf_m

I'm not going to read through your code. Not because I don't want to help you, but because I think you should get familiar with how OpenGL handles rotation, what the camera is and so on.

Therefore, I'll recommend to you Chapter 6 of the OpenGL® Programming Guide: The Official Guide to Learning OpenGL®, Version 2.1, 6th Edition, which, by chance, has recently been made available online on gamedev.net: Link

Furthermore, gamedev.net has a subsection located at nehe.gamedev.net, which introduces aspects of game programming in OpenGL. There's a camera tutorial as well: Link

Both resources are not perfect at all, but they should give you an overview of how to handle cameras in OpenGL.

More sophisticated camera code usually contains quaternion rotation, which eliminates some common problems with specific rotation methods. This goes far ahead, but I'll give you the link anyway which introduces such a camera class: Link

Good luck!

chrizo

Hey, wolf_m, sorry for sounding like a noob.

Normally i'd try to learn this all on my own. I've already seen all those links you posted.

Last night, I played with opengl rotation & perspective mode. I dunno, i guess i was too tired :) But this morning, I realized it might have been an optical illusion.  ::)  ;D Hehe.

But, there is still something weird about it. I guess i should run a few more tests.




middy

Hey

What kind of rotational methods are you using and what are you trying todo?

The different methods all have advantages/disadvantage and to know what you should use its important to know what you are attempting todo?
um

chrizo

Hi middy :)

I'm not in my computer right now. So I cant finalize what im saying here until I test it out again at home :)

Originally I was trying to simulate just panning and rotating around the object with the mouse. It worked fine. But i noticed something weird with the rotation. So commented the code to try find the source of the problem.

You can copy paste that simple program from my first post to test it out if you like.

I guess what i'm doing in the program now is basically this...

                //initialize to perspective mode using 640x480
           GL11.glShadeModel(GL11.GL_SMOOTH);
      GL11.glMatrixMode (GL11.GL_PROJECTION);
      GL11.glLoadIdentity();      
      GLU.gluPerspective(45.0f, (chosenDisplayWidth/chosenDisplayHeight), 0.0f, 50.0f);      
      GL11.glMatrixMode (GL11.GL_MODELVIEW);      

                //open loop
           GL11.glTranslated(1.0f, 0.0f, -5.0f);                // move object back and to the right
      GL11.glRotatef(camAngleY, 1.0f, 0.0f, 0.0f);    // rotate object on the y axis based on angle from keypress

      GL11.glPushMatrix();            // this object is actually xyz axis colored lines
      GL11.glBegin(GL11.GL_LINES);            
      GL11.glColor3f(0, 0, 0);      GL11.glVertex3f(-1, 0, 0);
      GL11.glColor3f(1, 0, 0);       GL11.glVertex3f(1, 0, 0);
      GL11.glColor3f(0, 0, 0);            GL11.glVertex3f(0, -1, 0);
      GL11.glColor3f(1, 1, 0);      GL11.glVertex3f(0, 1, 0);            
      GL11.glColor3f(0, 0, 0);            GL11.glVertex3f(0, 0, -1);
      GL11.glColor3f(0, 0, 1);      GL11.glVertex3f(0, 0, 1);            
      GL11.glEnd();
      GL11.glPopMatrix();   

                // camAngleY starts at 0.0f;

      if (Keyboard.isKeyDown(Keyboard.KEY_S)) camAngleY -= .2f;
      if (Keyboard.isKeyDown(Keyboard.KEY_W)) camAngleY += .2f;
                // close loop

I thought i was just rotating the object but looking at the blue axis, it's orientation seems to change the positive side suddenly points towards me as it crosses the quadrants

Do you notice something wrong with it? or in my code perhaps?

chrizo

My friends, I'm sorry for the false alarm.  :-[ It was just an optical illusion.

The blue z-axis is darker than the yellow and red so it looked as if it was farther away.


Ahh well, to keep this thread from being entirely fruitless, some words of wisdom to the aspiring opengl learners.

Do not skip meals... have enough sleep... ESPECIALLY when playing around with 3D....  ;D





Fool Running

QuoteDo not skip meals... have enough sleep... ESPECIALLY when playing around with 3D....   ;D
Very good advice ;)
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D