package br.com.lbbento.glapp;
import org.lwjgl.util.glu.*;
import br.com.lbbento.glapp.model.GL_Matrix;
import br.com.lbbento.glapp.model.GL_Vector;
/**
* Camera class by Philipp Crocoll at CodeColony (codecolony.de).
* Ported from C++ to Java by mark napier (potatoland.org).
*
* Can move camera position forward/back, pan left/right, shift up/down, and
* rotate around X, Y, Z axes.
*
* Uses gluLookat() to orient scene to camera position. See Camera.render().
*
* To use:
* renderScene() {
* GL11.glMatrixMode(GL11.GL_MODELVIEW);
* GL11.glLoadIdentity();
* camera.Render();
* // render scene ...
* }
*
* Requires GL_Vector to perform vector operations.
*
* jul13,2006: added move(x,y,z). added ctor(pos,dir,up).
*/
public class GLCamera {
static final float PIdiv180 = 0.0174532925f;
public GL_Vector ViewDir;
public GL_Vector RightVector;
public GL_Vector UpVector;
public GL_Vector Position;
public float RotatedX, RotatedY, RotatedZ;
public GLCamera() {
setCamera( 0f, 0f, 0f, // position at origin
0f, 0f, -1f, // looking down Z axis
0f, 1f, 0f ); // camera up axis is straight up Y axis
}
public GLCamera(float posx, float posy, float posz,
float dirx, float diry, float dirz,
float upx, float upy, float upz)
{
setCamera( posx,posy,posz, dirx,diry,dirz, upx,upy,upz );
}
/**
* Set the camera position, view direction and up vector. NOTE: direction
* is direction the camera is facing NOT a target position (as in gluLookAt()).
*
* @param posx Position of camera
* @param posy
* @param posz
* @param dirx Direction camera is facing
* @param diry
* @param dirz
* @param upx Up vector
* @param upy
* @param upz
*/
public void setCamera(float posx, float posy, float posz,
float dirx, float diry, float dirz,
float upx, float upy, float upz)
{
if (upx == 0 && upy == 0 && upz == 0) {
System.out.println("GLCamera.setCamera(): Up vector needs to be defined");
upx=0; upy=1; upz=0;
}
if (dirx == 0 && diry == 0 && dirz == 0) {
System.out.println("GLCamera.setCamera(): ViewDirection vector needs to be defined");
dirx=0; diry=0; dirz=-1;
}
Position = new GL_Vector(posx, posy, posz);
ViewDir = new GL_Vector(dirx, diry, dirz);
UpVector = new GL_Vector(upx, upy, upz);
RightVector = GL_Vector.crossProduct(ViewDir, UpVector);
RotatedX = RotatedY = RotatedZ = 0.0f; // TO DO: should set these to correct values
}
/**
* Set the camera to look at a target. Positions the camera on the same X and Y
* as the target, at the Z value specified by the distance param, looking down
* the Z axis.
*
* @param targetX camera will face this XYZ
* @param targetY
* @param targetZ
* @param distance distance from target
*/
public void setCamera(float targetX, float targetY, float targetZ, float distance)
{
Position = new GL_Vector(targetX, targetY, targetZ+distance);
ViewDir = new GL_Vector(0, 0, -1);
UpVector = new GL_Vector(0, 1, 0);
RightVector = GL_Vector.crossProduct(ViewDir, UpVector);
RotatedX = RotatedY = RotatedZ = 0.0f;
}
/**
* Move camera position in the given direction
*/
public void viewDir(GL_Vector direction) {
ViewDir = direction;
RightVector = GL_Vector.crossProduct(ViewDir, UpVector);
}
/**
* Move camera position in the given direction
*/
public void Move(GL_Vector Direction) {
Position = GL_Vector.add(Position, Direction);
}
/**
* Move camera position in the given direction
*/
public void Move(float x, float y, float z) {
GL_Vector Direction = new GL_Vector(x,y,z);
Position = GL_Vector.add(Position, Direction);
}
/**
* Move camera to the given xyz
*/
public void MoveTo(float x, float y, float z) {
Position = new GL_Vector(x, y, z);
}
public void RotateX(float Angle) {
RotatedX += Angle;
//Rotate viewdir around the right vector:
ViewDir = GL_Vector.normalize(
GL_Vector.add(
GL_Vector.multiply(ViewDir, (float) Math.cos(Angle * PIdiv180)),
GL_Vector.multiply(UpVector, (float) Math.sin(Angle * PIdiv180))
)
);
//now compute the new UpVector (by cross product)
UpVector = GL_Vector.multiply(GL_Vector.crossProduct(ViewDir, RightVector), -1);
}
public void RotateY(float Angle) {
RotatedY += Angle;
//Rotate viewdir around the up vector:
ViewDir = GL_Vector.normalize(
GL_Vector.sub(
GL_Vector.multiply(ViewDir, (float) Math.cos(Angle * PIdiv180)),
GL_Vector.multiply(RightVector, (float) Math.sin(Angle * PIdiv180))
));
//now compute the new RightVector (by cross product)
RightVector = GL_Vector.crossProduct(ViewDir, UpVector);
}
public void RotateZ(float Angle) {
RotatedZ += Angle;
//Rotate viewdir around the right vector:
RightVector = GL_Vector.normalize(
GL_Vector.add(
GL_Vector.multiply(RightVector, (float) Math.cos(Angle * PIdiv180)),
GL_Vector.multiply(UpVector, (float) Math.sin(Angle * PIdiv180))
));
//now compute the new UpVector (by cross product)
UpVector = GL_Vector.multiply(GL_Vector.crossProduct(ViewDir, RightVector), -1);
}
/**
* Rotate the camera around the absolute vertical axis (0,1,0), NOT around the cameras Y axis.
* This simulates a person looking up or down and rotating in place. You will rotate your
* body around the vertical axis, while your head remains tilted at the same angle.
* @param Angle the angle to rotate around the vertical axis in degrees
*/
public void RotateV(float Angle) {
// Make a matrix to rotate the given number of degrees around Y axis
GL_Matrix M = GL_Matrix.rotateMatrix(0,(float)Math.toRadians(Angle),0);
// rotate the view vector
GL_Vector vd = M.transform(ViewDir);
// the up vector is perpendicular to the old view and the new view
UpVector = (Angle > 0)? GL_Vector.crossProduct(ViewDir,vd) : GL_Vector.crossProduct(vd,ViewDir);
// the right vector is perpendicular to the new view and Up vectors
RightVector = GL_Vector.crossProduct(vd,UpVector);
// set the view direction
ViewDir = vd;
RotatedY += Angle;
}
public void MoveForward(float Distance) {
Position = GL_Vector.add(Position, GL_Vector.multiply(ViewDir, -Distance));
}
public void MoveUpward(float Distance) {
Position = GL_Vector.add(Position, GL_Vector.multiply(UpVector, Distance));
}
public void StrafeRight(float Distance) {
Position = GL_Vector.add(Position, GL_Vector.multiply(RightVector, Distance));
}
/**
* Call GLU.gluLookAt() to set view position, direction and orientation. Be
* sure that the modelview matrix is current before calling Render()
* (glMatrixMode(GL_MODEL_VIEW)).
*/
public void Render() {
//The point at which the camera looks:
GL_Vector ViewPoint = GL_Vector.add(Position, ViewDir);
//as we know the up vector, we can easily use gluLookAt:
GLU.gluLookAt(Position.x, Position.y, Position.z,
ViewPoint.x, ViewPoint.y, ViewPoint.z,
UpVector.x, UpVector.y, UpVector.z);
//System.out.println(Position.x + "," + Position.y + "," + Position.z + " " +
// ViewDir.x + "," + ViewDir.y + "," + ViewDir.z + " " +
// UpVector.x + "," + UpVector.y + "," + UpVector.z + " "
// );
}
/**
* Return the current camera view direction
*/
public GL_Vector getViewDir() {
return ViewDir;
}
}