/*******************************************************************************
* Copyright (c) 2007- VTT Technical Research Centre of Finland.
* 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.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VTT Technical Research Centre of Finland - initial API and implementation
*******************************************************************************/
package org.simantics.proconf.g3d.common;
import javax.vecmath.AxisAngle4d;
import javax.vecmath.Matrix3d;
import javax.vecmath.Vector3d;
import org.simantics.proconf.g3d.base.VecmathJmeTools;
import com.jme.renderer.Camera;
/**
* Orbital camera
*
* Modified version of fi.vtt.proconf.webmon.graphics3d.utils.OrbitalCamera
* Using floats instead of double
*
*
*
* @author Marko Luukkainen
*
*/
public class OrbitalCamera {
private Vector3d up = new Vector3d(0.0,1.0,0.0);
private static Vector3d up2 = new Vector3d(0.0,0.0,-1.0);
private static double minDistance = 0.5;
private Vector3d target = new Vector3d();
private Vector3d cameraPos = new Vector3d(10.0,0.0,0.0);
public void translate(Vector3d v) {
target.add(v);
cameraPos.add(v);
}
public void rotateAroundTarget(Vector3d axis, double angle) {
Vector3d temp = new Vector3d(cameraPos);
temp.sub(target);
Matrix3d rotation = new Matrix3d();
rotation.set(new AxisAngle4d(axis,angle));
rotation.transform(temp);
temp.add(target);
cameraPos.set(temp);
}
public Vector3d getUnNormalizedHeading() {
Vector3d heading = new Vector3d(target);
heading.sub(cameraPos);
return heading;
}
public Vector3d getUnNormalizedRight() {
Vector3d heading = getUnNormalizedHeading();
Vector3d right = new Vector3d();
right.cross(heading,up);
if (right.lengthSquared() < 0.01)
right.cross(heading,up2);
return right;
}
public double getDistanceToTarget() {
Vector3d t = new Vector3d(target);
t.sub(cameraPos);
return t.length();
}
public void moveToTarget(double distance) {
Vector3d heading = getUnNormalizedHeading();
double length = heading.length();
if (length + distance < minDistance) {
// cannot move closer
return;
}
heading.scale(distance / length); //normalizing and scaling by distance
cameraPos.add(heading);
}
public void moveScaledToTarget(double s) {
Vector3d heading = getUnNormalizedHeading();
double currentLength = heading.length();
double length = currentLength * (1.0 - s);// heading.length();
if (length < minDistance) {
s = -minDistance / currentLength + 1.0;
}
heading.scale(s);
//normalizing and scaling by distance
cameraPos.add(heading);
}
public void rotateUp(double angle) {
Vector3d right = getUnNormalizedRight();
double length = right.length();
// TODO : better handling of singular cases
if (length > 0.01)
right.scale(1.0/length);
else
right.set(-1.0,0.0,0.0);
rotateAroundTarget(right,angle);
}
public void rotateRight(double angle) {
rotateAroundTarget(up,angle);
}
public void moveRight(double length) {
Vector3d right = getUnNormalizedRight();
right.normalize();
right.scale(length);
translate(right);
}
public void moveUp(double length) {
Vector3d u = new Vector3d(up);
u.scale(length);
translate(u);
}
public void moveFront(double length) {
Vector3d right = getUnNormalizedRight();
Vector3d front = new Vector3d();
front.cross(up,right);
front.normalize();
front.scale(length);
translate(front);
}
public void updateCamera() {
Vector3d t = new Vector3d(cameraPos);
t.sub(target);
t.normalize();
cam.setLocation(VecmathJmeTools.get(cameraPos));
if (Math.abs(t.dot(up)) > 0.99) {
cam.lookAt(VecmathJmeTools.get(target), VecmathJmeTools.get(up2));
} else {
cam.lookAt(VecmathJmeTools.get(target), VecmathJmeTools.get(up));
}
cam.update();
cam.apply();
}
/**
* @return Returns the cameraPos.
*/
public Vector3d getCameraPos() {
return cameraPos;
}
/**
* @param cameraPos The cameraPos to set.
*/
public void setCameraPos(Vector3d cameraPos) {
this.cameraPos = cameraPos;
}
/**
* @return Returns the target.
*/
public Vector3d getTarget() {
return target;
}
/**
* @param target The target to set.
*/
public void setTarget(Vector3d target) {
this.target = target;
}
public void setCameraPosRelativeToTarget(Vector3d targetToCam) {
targetToCam.add(target);
setCameraPos(targetToCam);
}
public void setUp(Vector3d v) {
up.set(v);
}
public Vector3d getUp() {
return up;
}
public void setDefaultUp() {
up.set(0.0,1.0,0.0);
}
private Camera cam;
public void setCamera(Camera cam) {
this.cam = cam;
}
}