package gdl; import processing.core.PGraphics; import toxi.geom.Vec3D; public class MinimalCamera extends Vec3D { public Vec3D target, up; public float fov, aspect, nearClip, farClip; public float mag; public boolean autoClip = false; public float autoClip_nearMul = 0.1f; public float autoClip_farMul = 10; public Vec3D pos = new Vec3D(), ppos = new Vec3D(), vel = new Vec3D(); public MinimalCamera() { this( 0.0f, 0.0f, whOffsetZ(2.0f, 2.0f), 0.0f, 0.0f, 0.0f, 2.0f, 2.0f ); } public MinimalCamera(float width, float height) { this( width / 2.0f, height / 2.0f, whOffsetZ(width, height), width / 2.0f, height / 2.0f, 0.0f, width, height ); } public MinimalCamera(float x, float y, float width, float height) { this( x, y, whOffsetZ(width, height), x, y, 0.0f, width, height ); } public MinimalCamera(float x, float y, float z, float aimx, float aimy, float aimz, float width, float height) { this( x, y, z, aimx, aimy, aimz, 0, -1, 0, (float)(Math.PI / 3.0), width / height, 0, 0 ); autoClip = true; updateClip(); } public MinimalCamera(float x, float y, float z, float aimx, float aimy, float aimz, float upx, float upy, float upz, float _fov, float _aspect, float _nearClip, float _farClip) { super(); pos = new Vec3D(x, y, z); target = new Vec3D(aimx, aimy, aimz); vel = new Vec3D(); up = new Vec3D(upx, upy, upz); fov = _fov; aspect = _aspect; nearClip = _nearClip; farClip = _farClip; updateMag(); } public void setPos(float x, float y, float z) { pos.set(x,y,z); updateMag(); } public void setPos(Vec3D _pos) { pos.set(_pos); updateMag(); } public void setTarget(float x, float y, float z) { target.set(x,y,z); updateMag(); } public void setUp(float x, float y, float z) { up.set(x,y,z); } public void setOrbit(float rx, float ry, float distance) { pos.set(0,0,-distance); pos.rotateX(rx); pos.rotateY(ry); up.set(0,-1,0); up.rotateY(-ry); up.rotateX(-rx); updateMag(); } public void translate(float x, float y, float z) { pos.add(x,y,z); target.add(x,y,z); updateMag(); } // /** Move the camera and target simultaneously along the camera's X axis */ // public void truck(float anAmount) // { // // Calculate the camera's X axis in world space // Vector3 direction = new Vector3( // theDeltaY * up.z - theDeltaZ * up.y, // theDeltaX * up.z - theDeltaZ * up.x, // theDeltaX * up.y - theDeltaY * up.x // ); // direction.normalize(); // // // Perform the truck, if any // translate( // pos.x -anAmount * direction.x, // pos.y -anAmount * direction.y, // pos.z -anAmount * direction.z // ); // } // // /** Move the camera and target simultaneously along the camera's Y axis */ // public void boom(float anAmount) // { // // Perform the boom, if any // pos.x += anAmount * up.x; // pos.y += anAmount * up.y; // pos.z += anAmount * up.z; // target.x += anAmount * up.x; // target.y += anAmount * up.y; // target.z += anAmount * up.z; // } // // /** Move the camera and target along the view vector */ // public void dolly(float anAmount) // { // // Normalize the view vector // float directionX = theDeltaX / mag; // float directionY = theDeltaY / mag; // float directionZ = theDeltaZ / mag; // // // Perform the dolly, if any // pos.x += anAmount * directionX; // pos.y += anAmount * directionY; // pos.z += anAmount * directionZ; // target.x += anAmount * directionX; // target.y += anAmount * directionY; // target.z += anAmount * directionZ; // // // } public void update() { ppos.set(pos); setPos( pos.x + vel.x, pos.y + vel.y, pos.z + vel.z ); } public void apply(PGraphics g) { g.perspective(fov, aspect, nearClip, farClip); g.camera(pos.x,pos.y,pos.z, target.x,target.y,target.z, up.x,-up.y,up.z); } public void updateMag() { mag = pos.distanceTo(target); if(autoClip) updateClip(); } public void updateClip() { nearClip = mag * autoClip_nearMul; farClip = mag * autoClip_farMul; } public static float whOffsetZ(float width, float height) { return (height / 2.0f) / (float) Math.tan(Math.PI * 60.0 / 360.0); } }