/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package automenta.spacenet.space.control.camera; import automenta.spacenet.space.Repeat; import automenta.spacenet.space.Spacetime; import automenta.spacenet.space.control.Tangible; import automenta.spacenet.space.control.Zoomable; import automenta.spacenet.var.scalar.DoubleVar; import automenta.spacenet.var.vector.V3; import com.ardor3d.bounding.OrientedBoundingBox; import com.ardor3d.math.Vector3; import com.ardor3d.math.type.ReadOnlyVector3; import com.ardor3d.renderer.Camera; import com.ardor3d.scenegraph.Mesh; import com.ardor3d.scenegraph.Spatial; /** * * @author seh */ public class ArdorCamera extends Repeat { private final Spacetime spacetime; private Camera cam; private V3 targetPosition = new V3(); private V3 targetTarget = new V3(); private V3 targetUp = new V3(); private final V3 currentPosition; private final V3 currentTarget; private final V3 currentUp; private Vector3 currentDir = new Vector3(); private Vector3 currentLeft = new Vector3(); private Zoomable currentZoomed; private DoubleVar viewAngle = new DoubleVar(45.0 * 2 * Math.PI / 360.0); double zoomBoundsFactor = 1.2; double positionSpeed = 4.0; //in units per second private final DoubleVar near, far; private Vector3 targetDir = new Vector3(); private Vector3 targetLeft = new Vector3(); // double targetSpeed = 2.0; public ArdorCamera(Spacetime spacetime, V3 currentPosition, V3 currentTarget, V3 currentUp) { super(); this.near = new DoubleVar(1); this.far = new DoubleVar(1000); this.spacetime = spacetime; //this.cam = spacetime.getVideo().getCanvasRenderer().getCamera(); this.currentPosition = currentPosition; this.currentTarget = currentTarget; this.currentUp = currentUp; targetUp.set(currentUp); targetPosition.set(currentPosition); targetTarget.set(currentTarget); } @Override protected void update(double t, double dt, Spatial s) { currentPosition.interpolate(targetPosition, dt * getPositionSpeed()); currentTarget.interpolate(targetTarget, dt * getPositionSpeed()); currentUp.interpolate(targetUp, dt * getPositionSpeed()); currentUp.normalizeLocal(); if (this.cam == null) this.cam = spacetime.getVideo().getCanvasRenderer().getCamera(); // cam.setDepthRangeFar(getFar().d()); // cam.setDepthRangeNear(getNear().d()); cam.setFrustumNear(getNear().d()); cam.setFrustumFar(getFar().d()); cam.setLocation(currentPosition); cam.lookAt(currentTarget, currentUp); cam.normalize(); cam.update(); } public DoubleVar getNear() { return near; } public DoubleVar getFar() { return far; } // public double getTargetSpeed() { // return targetSpeed; // } public double getPositionSpeed() { return positionSpeed; } public void zoomTo(Zoomable z, Tangible touched, Mesh pickedMesh) { if (currentZoomed != z) { if (currentZoomed != null) { currentZoomed.onZoomStop(); currentZoomed = null; } } if ((z != null) && (touched != null)) { Spatial s = pickedMesh; double tx = s.getWorldBound().getCenter().getX(); double ty = s.getWorldBound().getCenter().getY(); double tz = s.getWorldBound().getCenter().getZ(); Vector3 up = new Vector3(0, 1, 0); //Vector3 normal = s.getWorldRotation(); if (s.getWorldBound() instanceof OrientedBoundingBox) { OrientedBoundingBox ob = ((OrientedBoundingBox) s.getWorldBound()); ReadOnlyVector3 normal = ob.getZAxis(); double r = ob.getExtent().length(); double va = getViewAngle().d(); double viewDist = 2 * r * zoomBoundsFactor * Math.sin(Math.PI / 4 - va / 2) / Math.sin(va / 2); //limit zooming to no closer than the near clipping plane times a certain factor (ex: 2.0) viewDist = Math.max(viewDist, getNear().d() * 2.0); double px = tx + normal.getX() * viewDist; double py = ty + normal.getY() * viewDist; double pz = tz + normal.getZ() * viewDist; ReadOnlyVector3 tup = ob.getYAxis(); targetPosition.set(px, py, pz); targetUp.set(tup); } else { } targetTarget.set(tx, ty, tz); currentZoomed = z; z.onZoomStart(); } } // public void zoomTo(Spacetime spaceTime, Space spatial, double zoomBoundsFactor) { // if (spatial instanceof HasPosition3) { // double x = ((HasPosition3)spatial).getAbsolutePosition().x(); // double y = ((HasPosition3)spatial).getAbsolutePosition().y(); // double z = ((HasPosition3)spatial).getAbsolutePosition().z(); // // double r; // if ((spatial instanceof HasSize3)) { // double w = ((HasSize3)spatial).getAbsoluteSize().x(); // double h = ((HasSize3)spatial).getAbsoluteSize().y(); // double d = ((HasSize3)spatial).getAbsoluteSize().z(); // // //r = Math.max(w, Math.max(h, d)); // r = Math.max(w, h); // } // else if (spatial instanceof HasSize2) { // double w = ((HasSize2)spatial).getAbsoluteSize().x(); // double h = ((HasSize2)spatial).getAbsoluteSize().y(); // // r = Math.max(w, h); // } // else { // r = 1; // } // // if (spatial instanceof HasOrientation) { // HasOrientation ho = (HasOrientation) spatial; // double tilt = ho.getAbsoluteOrientation().z(); // // // q.fromAngles(ho.getAbsoluteOrientation().x(), ho.getAbsoluteOrientation().y(), ho.getAbsoluteOrientation().z()); // if (qRot[0] == null) { // qRot[0] = new fVector3(); // qRot[1] = new fVector3(); // qRot[2] = new fVector3(); // } // q.toAxes(qRot); // // spaceTime.video().getUp().set(qRot[1].getX(), qRot[1].getY(), qRot[1].getZ()); // } // // double viewAngle = Math.toRadians(spaceTime.video().getFocusAngle().get()); // // double viewingDistance = 2 * r * zoomBoundsFactor * Math.sin(Math.PI/4 - viewAngle/2) / Math.sin(viewAngle/2); // //// logger.info("Zoom to focused: " + spatial + " pos=" + x + "," + y + ", " + z); //// logger.info(" r=" + r); //// logger.info(" dist=" + viewingDistance); // // //nextSightPosition.set(x, y, z + viewingDistance); // // ((HasPosition3)spatial).getAbsoluteNormal(vNormal); // vNormal.multiply(viewingDistance); // // Vector3 p = new Vector3(x + vNormal.x(), y + vNormal.y(), z + vNormal.z()); // Vector3 t = new Vector3(x,y,z); // // // spaceTime.video().getPosition().set(p); // spaceTime.video().getTarget().set(t); // // } // // } public V3 getTargetPosition() { return targetPosition; } public V3 getCurrentPosition() { return currentPosition; } public V3 getCurrentUp() { return currentUp; } public Vector3 getCurrentDirection() { currentDir.set(currentTarget); currentDir.subtractLocal(currentPosition); currentDir.normalizeLocal(); return currentDir; } public Vector3 getTargetDirection() { targetDir.set(targetTarget); targetDir.subtractLocal(targetPosition); targetDir.normalizeLocal(); return targetDir; } public Vector3 getCurrentLeft() { Vector3 direction = getCurrentDirection(); Vector3 up = getCurrentUp(); currentLeft.set(up); currentLeft.crossLocal(direction); currentLeft.normalizeLocal(); return currentLeft; } public Vector3 getTargetLeft() { Vector3 direction = getTargetDirection(); Vector3 up = getTargetUp(); targetLeft.set(up); targetLeft.crossLocal(direction); targetLeft.normalizeLocal(); return targetLeft; } public Vector3 getTargetTarget() { return targetTarget; } public Vector3 getTargetUp() { return targetUp; } public DoubleVar getViewAngle() { return viewAngle; } public void zoomForward(double l) { Vector3 d = getCurrentDirection().clone(); d.multiplyLocal(l); getTargetPosition().addLocal(d); } public void setTargetToCurrent() { getCurrentUp().set(getTargetUp()); getCurrentPosition().set(getTargetPosition()); getCurrentTarget().set(getTargetTarget()); } public V3 getCurrentTarget() { return currentTarget; } }