LWJGL Forum

Programming => Lightweight Java Gaming Library => Topic started by: jjones7947 on July 05, 2005, 23:36:12

Title: Camera Code
Post by: jjones7947 on July 05, 2005, 23:36:12
Have tried a dozen different ways to impliment "camera" code in a separate class.  All results to this point were bizarre. This one comes the closest, but the frame alternately flips when mouse input is supplied. I want to eliminate the rotation about the z axis, which is why I'm using the flatRotate method on rotation about the Y. Can anyone spot my problem?
Using vecmath package.

package core;


/*
* Created on Jun 7, 2005
*
* GameCamera
*/
/**
* @author Jim Jones
*
* Sharp Productions
*/
import java.nio.FloatBuffer;

import javax.vecmath.AxisAngle4f;
import javax.vecmath.Matrix4f;
import javax.vecmath.Vector3f;

import org.lwjgl.BufferUtils;

import utils.TestUtil;



public class GameCamera {
boolean gMousing = true;
float gMoveSpeed = 0.1f;
float gElapseTime;
double gCurTime;
double gLastTime = 0.0f;
Vector3f gEye;
Vector3f gLook;
Vector3f tmpLook = new Vector3f();
Vector3f gUp;
final Vector3f stdUp = new Vector3f(0.0f, 1.0f, 0.0f);
Vector3f gRight;
Vector3f tmpRight = new Vector3f();
final int FORWARD = 0;
final int BACKWARD = 1;
final int RIGHT = 3;
final int LEFT = 4;
Matrix4f view;
FloatBuffer transform;
Matrix4f matrix = new Matrix4f();
Matrix4f tMatrix = new Matrix4f();
float[] matArray = new float[16];

public GameCamera(Vector3f pos) {
gEye = pos;
gLook = new Vector3f(0.0f, 0.0f, 1.0f);
gUp = new Vector3f(0.0f, 1.0f, 0.0f);
gRight = new Vector3f(1.0f, 0.0f, 0.0f);
transform = BufferUtils.createFloatBuffer(16);
updateMatrix();
}
/**
public void handleInput() {
   if (Keyboard.isKeyDown(Keyboard.KEY_UP)) {
translateCamera(FORWARD, gElapseTime);
}  
if (Keyboard.isKeyDown(Keyboard.KEY_DOWN)) {
translateCamera(BACKWARD, gElapseTime);
}
if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) {
translateCamera(RIGHT, gElapseTime);
}
if (Keyboard.isKeyDown(Keyboard.KEY_LEFT)) {
translateCamera(LEFT, gElapseTime);
}
float xMove = (float)Mouse.getDX();
float yMove = (float)Mouse.getDY();
//System.out.println("Mouse X"+ xMove);
//System.out.println("Mouse Y"+ yMove );
//if((xMove != 0)||(yMove != 0)) {
// float xAngle = ((xMove/(float)halfWidth) * halfViewHorz);
// float yAngle = ((yMove/(float)halfHeight) * halfViewVert);
// mouseRotate(xAngle, yAngle);
//}
}
*/
public void translateCamera(int flag, float gElapseTime) {
tmpLook.set(gLook);
tmpRight.set(gRight);
if(flag == FORWARD) {
tmpLook.scale(-gMoveSpeed);
//System.out.println("Scale 1 "+ tmpLook.toString());
tmpLook.scale(gElapseTime);
//System.out.println("Scale 2 "+ tmpLook.toString());
gEye.sub(tmpLook);
//System.out.println("gEye "+ gEye.toString());
} else if(flag == BACKWARD) {
tmpLook.scale(-gMoveSpeed);
tmpLook.scale(gElapseTime);
gEye.add(tmpLook);
} else if(flag == LEFT) {
tmpRight.scale(gMoveSpeed);
tmpRight.scale(gElapseTime);
gEye.sub(tmpRight);
} else if(flag == RIGHT) {
tmpRight.scale(gMoveSpeed);
tmpRight.scale(gElapseTime);
gEye.add(tmpRight);
}
}

public void mouseRotate(float xAngle, float yAngle) {
System.out.println("mouseRot X "+xAngle+" Y "+yAngle);
if(gMousing == false) {
return;
}
if(yAngle != 0) {
float rad = (float)Math.toRadians(yAngle);
matrix.set(new AxisAngle4f(gRight, rad));
matrix.transform(gLook);
matrix.transform(gRight);
gUp.cross(gLook, gRight);
}
if(xAngle != 0) {
float rad = (float)Math.toRadians(yAngle);
matrix.set(new AxisAngle4f(stdUp, rad));
gLook = flatRotate(gLook);
//gLook.normalize();
gRight = flatRotate(gRight);
gRight.normalize();
gUp.cross(gLook, gRight);
}
}

public Vector3f flatRotate(Vector3f v) {
Vector3f tmp = new Vector3f(v.x, 0.0f, v.z);
matrix.transform(tmp);
return(new Vector3f(tmp.x, v.y, tmp.z));
}

public void updateMatrix() {
gLook.normalize();
TestUtil.printVector("gLook", gLook);
gRight.cross(gLook, gUp);
TestUtil.printVector("gRight", gRight);
gRight.normalize();
gUp.cross(gRight, gLook);
TestUtil.printVector("gUp", gUp);
gUp.normalize();
matArray[0] = gRight.x;
matArray[1] = gUp.x;
matArray[2] = -gLook.x;
matArray[3] = 0.0f;
matArray[4] = gRight.y;
matArray[5] = gUp.y;
matArray[6] = -gLook.y;
matArray[7] = 0.0f;
matArray[8] = gRight.z;
matArray[9] = gUp.z;
matArray[10] = -gLook.z;
matArray[11] = 0.0f;
matArray[12] = -gRight.dot(gEye);
matArray[13] = -gUp.dot(gEye);
matArray[14] = gLook.dot(gEye);
matArray[15] = 1.0f;
}

public FloatBuffer getMatrix() {
transform.put(matArray);
return((FloatBuffer)transform.rewind());
}
}


Thanks,
Jim
Title: Camera Code
Post by: Funkapotamus on July 06, 2005, 18:16:04
Sorry for the size guys!  (is there any way to make the code fit in it's own textbox?)

move(float speed) - Move the camera where it's looking.
strafe(float speed) - Strafe left/right and maintain the camera's current look.

You can get some nifty things by messing with strafe();
For example, if you remove the part where it updates the target vector you'll get automatic circlestrafing around a point.

And if you mess with "currentXRot -= angleZ;" that in getMouseAngle() you can give the camera the option of flipping upsidedown- useful for flight sim games.

All the math functions should be self explanitory.  The exception is "crappyNormalize()"- which you should just assume a plain normalize.  I was messing with some equations and ended up with two normalize methods.  One was crappier than the other so hence "crappyNormalize" :)  I used it because it was faster though.  This code is old- I havn't gotten around to updating things.


import org.jon.crs.util.FunkMath;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.glu.GLU;

public final class Camera3D
{
public static final float FOV = 80.0f;

private Vector3D origin = new Vector3D();
private Vector3D target = new Vector3D();
private Vector3D upVector = new Vector3D();
private Vector3D strafe = new Vector3D();

private boolean inverted = false;
private float sensitivity = 750.0f;

private float currentXRot = 0.0f;

public Camera3D()
{}

public void setOrigin(Vector3D origin, Vector3D target, Vector3D upVector)
{
// I'm copying things here just because it's safer.  It's also easier to send vectors rather than points.
this.origin.copy(origin);
this.target.copy(target);
this.upVector.copy(upVector);
}

public void update()
{
// Normalize the strafe vector.
strafe = FunkMath.crossProduct(FunkMath.subtract(target, origin), upVector);
strafe.crappyNormalize();

// Update view based on mouse.
getMouseAngle();
}

public void look()
{
// Camera Position, Direction the Camera's looking, "Up"
GLU.gluLookAt(origin.x, origin.y, origin.z, target.x, target.y, target.z, upVector.x, upVector.y, upVector.z);
}

public void move(float speed)
{
origin.x += (target.x - origin.x) * speed;
origin.y += (target.y - origin.y) * speed;
origin.z += (target.z - origin.z) * speed;

target.x += (target.x - origin.x) * speed;
target.y += (target.y - origin.y) * speed;
target.z += (target.z - origin.z) * speed;
}

public void strafe(float speed)
{
// Add strafe vector to origin & target.
origin.x += strafe.x * speed;
origin.z += strafe.z * speed;

target.x += strafe.x * speed;
target.z += strafe.z * speed;
}

public void setInverted(boolean inverted)
{
this.inverted = inverted;
}

public void setSensitivity(float sensitivity)
{
this.sensitivity = sensitivity;
}

public Vector3D getOrigin()
{
return origin;
}

public Vector3D getTarget()
{
return target;
}

private void getMouseAngle()
{
float angleY = 0.0f;
float angleZ = 0.0f;
final Vector3D axis;

// Get the direction the mouse moved in, and bring it down to a reasonable amount.
angleY = -(float)(Mouse.getDX()) / sensitivity;
angleZ = (float)(Mouse.getDY()) / sensitivity;

// If mouse is inverted, invert rotation on Z axis.
if(inverted)
angleZ = -angleZ;

// Keep track of the current X Rotation so the camera can't do a full loop.
// TODO Mess with this so looping is possible (fly like an old lerk in NS).
currentXRot -= angleZ;

// Cap the X Rotation within 1 radian (+/- 90 degrees)
if(currentXRot > 1.0f)
currentXRot = 1.0f;
else if(currentXRot < -1.0f)
currentXRot = -1.0f;
else
{
axis = FunkMath.crossProduct(FunkMath.subtract(target, origin), upVector);
axis.crappyNormalize();

// Rotate Z and Y axis.
rotate(angleZ, axis.x, axis.y, axis.z);
rotate(angleY, 0, 1, 0);
}
}

private void rotate(float angle, float x, float y, float z)
{
Vector3D newTarget = new Vector3D();
Vector3D currentTarget = new Vector3D();

// Get the current facing direction
currentTarget.x = target.x - origin.x;
currentTarget.y = target.y - origin.y;
currentTarget.z = target.z - origin.z;

// Store Sin/Cos
float cosTheta = (float)Math.cos(angle);
float sinTheta = (float)Math.sin(angle);

newTarget.x  = (cosTheta + (1 - cosTheta) * x * x) * currentTarget.x;
newTarget.x += ((1 - cosTheta) * x * y - z * sinTheta) * currentTarget.y;
newTarget.x += ((1 - cosTheta) * x * z + y * sinTheta) * currentTarget.z;

newTarget.y  = ((1 - cosTheta) * x * y + z * sinTheta) * currentTarget.x;
newTarget.y += (cosTheta + (1 - cosTheta) * y * y) * currentTarget.y;
newTarget.y += ((1 - cosTheta) * y * z - x * sinTheta) * currentTarget.z;

newTarget.z  = ((1 - cosTheta) * x * z - y * sinTheta) * currentTarget.x;
newTarget.z += ((1 - cosTheta) * y * z + x * sinTheta) * currentTarget.y;
newTarget.z += (cosTheta + (1 - cosTheta) * z * z) * currentTarget.z;

target.x = origin.x + newTarget.x;
target.y = origin.y + newTarget.y;
target.z = origin.z + newTarget.z;
}
}
Title: Camera Code
Post by: jjones7947 on July 06, 2005, 20:57:51
Thanks,
I'll run some compares and see if I can figure out the diffs.
Jim