/****************************************************************************** * Copyright (c) 2008 Marco Della Vedova, Matteo Foppiano * and Pimods contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.pixelinstrument.net/license/cpl-v10.html ******************************************************************************/ package net.sf.robocode.bv3d.camera; import javax.media.opengl.glu.GLU; import net.sf.robocode.bv3d.math.Vertex3f; /** * @author Marco Della Vedova - pixelinstrument.net * @author Matteo Foppiano - pixelinstrument.net * */ public class Camera { private Vertex3f eye; private Vertex3f view; private Vertex3f up; public Camera(Vertex3f eye, Vertex3f view, Vertex3f up) { this.eye = eye; this.view = view; this.up = up; } public Camera() { eye = new Vertex3f(0, 0, 0); view = new Vertex3f(0, 0, 1); up = new Vertex3f(0, 1, 0); } public void setEye(Vertex3f eye) { if (eye != null) { this.eye = eye; } } public void setView(Vertex3f view) { if (view != null) { this.view = view; } } public void setUp(Vertex3f up) { if (up != null) { this.up = up; } } public Vertex3f getEye() { return((Vertex3f) eye.clone()); } public Vertex3f getView() { return((Vertex3f) view.clone()); } public Vertex3f getUp() { return((Vertex3f) up.clone()); } public void move(float x, float y, float z) { // Yes, view*up is correct for moving along the x direction Vertex3f perpendicolar = view.getVectorProduct(up); this.eye.x += perpendicolar.x * x + this.up.x * y + this.view.x * z; this.eye.y += perpendicolar.y * x + this.up.y * y + this.view.y * z; this.eye.z += perpendicolar.z * x + this.up.z * y + this.view.z * z; } public void rotateX(float angle) { float pitchAngle = this.getPitch(this.view) + angle; float yawAngle = this.getYaw(this.view); pitchAngle = pitchAngle > 90 ? 90 : pitchAngle; pitchAngle = pitchAngle < -90 ? -90 : pitchAngle; Vertex3f newSys[] = { new Vertex3f(0, 0, 1), new Vertex3f(0, 1, 0) }; newSys = rotateSystemX(pitchAngle, newSys[0], newSys[1]); newSys = rotateSystemY(yawAngle, newSys[0], newSys[1]); this.view = newSys[0]; this.up = newSys[1]; } public void rotateY(float angle) { float pitchAngle = this.getPitch(this.view); float yawAngle = (this.getYaw(this.view) + angle) % 360; Vertex3f newSys[] = { new Vertex3f(0, 0, 1), new Vertex3f(0, 1, 0) }; newSys = rotateSystemX(pitchAngle, newSys[0], newSys[1]); newSys = rotateSystemY(yawAngle, newSys[0], newSys[1]); this.view = newSys[0]; this.up = newSys[1]; } public void rotateZ(float angle) {/* not used */} public void refresh(GLU glu) { glu.gluLookAt(eye.x, eye.y, eye.z, eye.x + view.x, eye.y + view.y, eye.z + view.z, up.x, up.y, up.z); } private Vertex3f[] rotateSystemX(float angle, Vertex3f v, Vertex3f u) { Vertex3f newV = new Vertex3f(); Vertex3f newU = new Vertex3f(); double rad = (double) angle * Math.PI / 180.0; double cos = Math.cos(rad); double sin = Math.sin(rad); float y = (float) (v.y * cos - v.z * sin); float z = (float) (v.y * sin + v.z * cos); newV.x = v.x; newV.y = y; newV.z = z; y = (float) (u.y * cos - u.z * sin); z = (float) (u.y * sin + u.z * cos); newU.x = u.x; newU.y = y; newU.z = z; return(new Vertex3f[] { newV, newU }); } private Vertex3f[] rotateSystemY(float angle, Vertex3f v, Vertex3f u) { Vertex3f newV = new Vertex3f(); Vertex3f newU = new Vertex3f(); double rad = (double) angle * Math.PI / 180.0; double cos = Math.cos(rad); double sin = Math.sin(rad); float x = (float) (v.x * cos + v.z * sin); float z = (float) (-v.x * sin + v.z * cos); newV.x = x; newV.y = v.y; newV.z = z; x = (float) (u.x * cos + u.z * sin); z = (float) (u.x * sin + u.z * cos); newU.x = x; newU.y = u.y; newU.z = z; return(new Vertex3f[] { newV, newU }); } private Vertex3f[] rotateSystemZ(float angle, Vertex3f v, Vertex3f u) { Vertex3f newV = new Vertex3f(); Vertex3f newU = new Vertex3f(); double rad = (double) angle * Math.PI / 180.0; double cos = Math.cos(rad); double sin = Math.sin(rad); float x = (float) (v.x * cos - v.y * sin); float y = (float) (v.x * sin + v.y * cos); newV.x = x; newV.y = y; newV.z = v.z; x = (float) (u.x * cos - u.y * sin); y = (float) (u.x * sin + u.y * cos); newU.x = x; newU.y = y; newU.z = u.z; return(new Vertex3f[] { newV, newU }); } private float getYaw(Vertex3f v) { return((float) ((Math.atan2(-v.x, -v.z)) * 180.0f / Math.PI)); } private float getPitch(Vertex3f v) { return((float) (Math.asin(v.y / v.getLength()) * 180.0f / Math.PI)); } private float getRoll(Vertex3f v) { /* not used */ return(0); } }