/******************************************************************************* * Breakout Cave Survey Visualizer * * Copyright (C) 2014 James Edwards * * jedwards8 at fastmail dot fm * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) any later * version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *******************************************************************************/ package org.andork.jogl.awt.anim; import static java.lang.Math.atan2; import static java.lang.Math.cos; import static java.lang.Math.sin; import static org.andork.math3d.Vecmath.cross; import static org.andork.math3d.Vecmath.dot3; import static org.andork.math3d.Vecmath.invAffine; import static org.andork.math3d.Vecmath.mmulAffine; import static org.andork.math3d.Vecmath.mvmulAffine; import static org.andork.math3d.Vecmath.normalize3; import static org.andork.math3d.Vecmath.rotY; import static org.andork.math3d.Vecmath.setColumn3; import static org.andork.math3d.Vecmath.setIdentity; import static org.andork.math3d.Vecmath.setRotation; import org.andork.awt.anim.Animation; import org.andork.jogl.JoglViewSettings; import org.andork.math3d.Vecmath; import org.andork.util.AnimationUtils; import com.jogamp.opengl.GLAutoDrawable; public class SpringViewOrbitAnimation implements Animation { GLAutoDrawable drawable; JoglViewSettings viewSettings; final float[] right = new float[3]; final float[] forward = new float[3]; final float[] targetRight = new float[3]; final float[] targetForward = new float[3]; final float[] targetUp = new float[3]; final float[] center = new float[3]; float targetPan; float targetTilt; final float[] v = Vecmath.newMat4f(); final float[] m1 = Vecmath.newMat4f(); final float[] m2 = Vecmath.newMat4f(); int period; float factor; float extra; public SpringViewOrbitAnimation(GLAutoDrawable drawable, JoglViewSettings viewSettings, float[] center, float targetPan, float targetTilt, float factor, float extra, int period) { if (period <= 0) { throw new IllegalArgumentException("period must be > 0"); } this.drawable = drawable; this.viewSettings = viewSettings; Vecmath.setf(this.center, center); this.targetPan = targetPan; this.targetTilt = targetTilt; this.factor = factor; this.extra = extra; this.period = period; } @Override public long animate(long animTime) { viewSettings.getViewXform(v); invAffine(v, m1); mvmulAffine(m1, 0, 0, -1, forward); normalize3(forward); mvmulAffine(m1, 1, 0, 0, right); normalize3(right); targetForward[0] = right[2]; targetForward[1] = 0; targetForward[2] = -right[0]; setRotation(m2, right, targetTilt); mvmulAffine(m2, targetForward); cross(right, targetForward, targetUp); float dTilt = (float) atan2(dot3(forward, targetUp), dot3(forward, targetForward)); targetForward[0] = (float) -sin(targetPan); targetForward[1] = 0; targetForward[2] = (float) -cos(targetPan); targetRight[0] = -targetForward[2]; targetRight[1] = 0; targetRight[2] = targetForward[0]; float dPan = (float) atan2(dot3(right, targetForward), dot3(right, targetRight)); float ratio; if (dPan == 0 && dTilt == 0) { return 0; } else if (Math.abs(dPan) > Math.abs(dTilt)) { float nextPan = AnimationUtils.animate(dPan, 0, animTime, factor, extra, period); ratio = nextPan / dPan; } else { float nextTilt = AnimationUtils.animate(dTilt, 0, animTime, factor, extra, period); ratio = nextTilt / dTilt; } boolean done = ratio == 0; float nextPan = dPan * ratio; float nextTilt = dTilt * ratio; float panAmount = nextPan - dPan; float tiltAmount = nextTilt - dTilt; setIdentity(m1); setIdentity(m2); m2[12] = -center[0]; m2[13] = -center[1]; m2[14] = -center[2]; rotY(m1, -panAmount); mmulAffine(m1, m2, m2); setRotation(m1, right, -tiltAmount); mmulAffine(m1, m2, m2); setIdentity(m1); setColumn3(m1, 3, center); mmulAffine(m1, m2, m2); mmulAffine(v, m2, v); viewSettings.setViewXform(v); drawable.display(); return done ? 0 : period; } }