Main Menu

Mouse questions

Started by jagdfalke, December 12, 2006, 17:14:34

Previous topic - Next topic

jagdfalke

Hi,
I have several questions about mouse events in lwjgl:

1. I found out Mouse provides a method to grab the mouse, but how can I still show the cursor inside the open gl window?
2. I want to write a "Counter Stike" - like mouse navigation: means the cameras lookAt point moves as the user moves the mouse. How can I center the mouse on the open gl window after reading the mouse movement from the Mouse class?
3. Is there an already implemented way to provide this "CS"-like navigation?

jagdfalke

Fool Running

1. You have to do it yourself (i.e. get the mouse (x,y) position and draw a cursor there)
2. The best way to do that is to not use the gluLookAt() method. Its more for like 3rd person games where you want the camera to always look at the player, but have the camera move around the player. Do something more like this where you used to do the gluLookAt():
            glRotatef(angle.x, 1.0f, 0.0f, 0.0f);
            glRotatef(angle.y, 0.0f, 1.0f, 0.0f);
            glRotatef(angle.z, 0.0f, 0.0f, 1.0f);
            glTranslatef(-location.x, -location.y, -location.z);

When the mouse moves in the x direction, just increment/decrement angle.y and the same for the y direction (angle.x).
3. The code above should work (worked for me at least :D )
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

jagdfalke

Ahhh ok. Sounds like a good idea moving the whole scene but there's still the problem of recentering the mouse, right? As the mouse reaches e.g the right border of the frame the camera stops turning.

Fool Running

Just use Mouse.getDX() and Mouse.getDY(). They tell how much the mouse moved versus the real (x,y) position. This allows you to do: angleY += Mouse.getDX(). This also fixes the problem of needing to center the mouse.
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

jagdfalke

But imagine the Camera is at 5/5/5 looking down to 0/0/0. You move the mouse up so you wand the camera to look up. Which axis do want to rotate arround now? It would be an axis going thru 5/5/5 and being parallel to the xz plain and orthographic to the looking direction. Moving backwards as well depends on the looking direction ...
So I don't really know to which axis to apply the rotation when the mouse moves and to which coordinates of the vector to apply the move to. Are you sure there's no way to center the mouse?

One more thing: Do I have to call Mouse.poll() first? Do I have to use Mouse.next() and add the dx and dy values to get the real movement?

jagdfalke

Hmm, seem like I dont really need to center the mouse after moving it. getDX() and getDY() even return the correct values if the cursor has gone past the frame's borders. But there seems to be a mistake in my calculations.  I have a Camera class that uses the GLU#gluLookAt() when the loop calls Camera#setCamera(). The idea is to have a sphere arround the camera with a radius of 1. The camera stores position and direction. In Camera#setCamera() the point to look at is calculated by adding the direction vector (length = 1) to the position coordinates. But there seems to be something wrong calculating the new direction as the mouse moves:

package lwjgltestings.utils;

import org.lwjgl.opengl.glu.GLU;

public class Camera {
	
	private float[] position, lookAt, orientation, direction;
	
	public Camera(float[] pos, float[] dir, float[] or) {
		position 	= pos;
		direction 	= dir;
		orientation = or;
	}

	public void setCamera() {
		lookAt 		= addVectors(position, normalize(direction));
        GLU.gluLookAt(	position[0], 	position[1], 	position[2], 
			   			lookAt[0], 		lookAt[1], 		lookAt[2], 
			   			orientation[0], orientation[1], orientation[2]);  
	}
	
	public void changeDirectionHorizontally(int amount) {
		float dx3 = -(float)Math.tan((double)amount);
		float dx1 = (1 - (float)Math.cos((double)amount));
		direction[0] += dx1;
		direction[2] += dx3;
	}
	
	public void changeDirectionVertically(int amount) {
	
	}

	public void moveForward() {
		position = addVectors(position, cutToLength(direction, 0.1f));
	}
	public void moveBackward() {
		position = addVectors(position, reverse(cutToLength(direction, 0.1f)));
	}
	
	
	public void moveLeft() {
		float[] leftDir = cutToLength(crossProduct(direction, new float[] {0,-1,0}), 0.05f);
		position = addVectors(position, leftDir);		
	}
	public void moveRight() {
		float[] rightDir = cutToLength(crossProduct(direction, new float[] {0,1,0}), 0.05f);
		position = addVectors(position, rightDir);		
	}
	
	
	
	
	
	
	
	private float[] crossProduct(float[] vec1, float[] vec2) {
		float[] cross = new float[3];
		cross[0] = vec1[1]*vec2[2]-vec1[2]*vec2[1];
		cross[1] = vec1[2]*vec2[0]-vec1[0]*vec2[2];
		cross[2] = vec1[0]*vec2[1]-vec1[1]*vec2[0];
		return cross;
	}
	private float[] reverse(float[] vec) {
		float[] v = new float[3];
		v[0] = vec[0] * -1;
		v[1] = vec[1] * -1;
		v[2] = vec[2] * -1;
		return v;
	}
	private float[] cutToLength(float[] v, float length) {
		float[] cut = normalize(v);
		cut[0] /= (1/length);
		cut[1] /= (1/length);
		cut[2] /= (1/length);
		return cut;
	}
	private float[] normalize(float[] vec) {
		float[] v = new float[3];
		float length = vectorLength(vec);
		v[0] = vec[0] / length;
		v[1] = vec[1] / length;
		v[2] = vec[2] / length;
		return v;
	}
	private float vectorLength(float[] vec) {
		return (float)Math.sqrt(Math.pow(vec[0], 2)+Math.pow(vec[1], 2)+Math.pow(vec[2], 2));
	}
	private float[] addVectors(float[] vec1, float[] vec2) {
		float[] v = new float[3];
		v[0] = vec1[0] + vec2[0];
		v[1] = vec1[1] + vec2[1];
		v[2] = vec1[2] + vec2[2];
		return v;
	}
}


You might see strange naming conventions in my code. This is because I'm german trying to translate german words into english ;)

Fool Running

Am I correct assuming that direction is a Vector? If so, then this
public void changeDirectionHorizontally(int amount) {
		float dx3 = -(float)Math.tan((double)amount);
		float dx1 = (1 - (float)Math.cos((double)amount));
		direction[0] += dx1;
		direction[2] += dx3;
	}

looks wrong. You shouldn't have to use Math.tan() in that calculation, just sin and cos. Maybe something as simple as:
public void changeDirectionHorizontally(int amountInDegrees) {
                double amountInRadians = Math.toRadians(amountInDegrees);
		float zChange = (float)Math.cos(amountInRadians);
		float xChange = (float)Math.sin(amountInRadians);
		direction[0] += xChange;
		direction[2] += zChange;
	}

Also, is the direction vector initially {0,0,0}? It should be initialized to something other than all zeros.

Hope that helps :D

QuoteYou might see strange naming conventions in my code. This is because I'm german trying to translate german words into english
Looks fine to me ;D
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

jagdfalke

Hi,
are you sure I don't have to use tan in this case? Here's a picture of the my drawings:

- d is the direction of the camera
- c the the change of direction which I'm trying to figure out
- the strippled line is the change on x3
- the strippled line devides d at a point. the part from this point to the end of d is the change on x1

To calculate the change on x3 I need tan I think.
tan(a) = change_on_x3 / 1  (as the length of d is 1)
=>change_on_x3 = tan(a)

Is that wrong?

Fool Running

Hmmmmmmmm, you're right ;D
Is there a reason you are using gluLookAt() instead of the easier (in my opinion) code I posted above? It's much less confusing ;)

I'll try play with it a little more later...
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

jagdfalke

the reason why I'm not using the rotation and translation method is that I dont know on which axis to translate if the user presses left and the camera is looking e.g. vec(-0.3, 0f, 0.6f). the movement has to be relative to the viewing direction.

Fool Running

Sorry if if the code wasn't really understandable. angle is not a vector, just an easy way to hold 3 separate angles. (rotation around the x-axis, y-axis, and z-axis). If the user presses left (or moves the mouse left) just rotate around the x-axis (subtract from angle.x).
It would be easer to just add an amount to that value than trying to do all the calculations you are trying to do, is all I was trying to say :-\

The code basically rotates the entire world around the origin (0,0,0) and then moves the entire world in the opposite direction that the camera "moved."

Glad I'm not a teacher, I would probably have been fired already :D
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

jagdfalke

hmm,
I can't really imagine how this is supposed to work. So the mouse would determine the direction and the arrow key would determine the camera's position? I still dont see how the camera moves orthographic to the direction ... Can you just give a short code example.

mfg
jagdfalke

jagdfalke

Well, I tried your code now. After thinking about it a few days I figured it out ;) The problem with this code is that you can't take your "eyes" off (0/0/0).

import org.lwjgl.opengl.*;

public class Camera1 {
		
	
	private float[] position = {0f, 0f, 0f};
	
	private float rotX = 0f;
	private float rotZ = 0f;

	public void setCamera() {
		GL11.glRotatef(rotX, 1f, 0f, 0f);
		GL11.glRotatef(rotZ, 0f, 0f, 1f);
		GL11.glTranslatef(position[0], position[1], position[2]);
	}
	
	public void changeDirectionHorizontally(int amount) {
		rotZ += amount;
	}
	
	public void changeDirectionVertically(int amount) {
		rotX += amount;
	}

	
	public void moveForward() {
//		not implemented yet
	}
	public void moveBackward() {
//		not implemented yet
	}
	
	
	
	public void moveLeft() {
//		not implemented yet
	}
	public void moveRight() {
//		not implemented yet
	}