/*******************************************************************************
* 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.math3d;
import static java.lang.Math.atan2;
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;
/**
* Applies orbit transforms to view transforms.
*/
public class Orbiter {
final float[] center = { 0, 0, 0 };
final float[] right = new float[3];
final float[] forward = new float[3];
final float[] levelForward = new float[3];
final float[] up = new float[3];
final float[] m1 = Vecmath.newMat4f();
final float[] m2 = Vecmath.newMat4f();
public void getCenter(float[] out) {
Vecmath.setf(out, center);
}
public float getPan(float[] v) {
invAffine(v, m1);
mvmulAffine(m1, 1, 0, 0, right);
return (float) atan2(-right[2], right[0]);
}
public float getTilt(float[] v) {
invAffine(v, m1);
mvmulAffine(m1, 1, 0, 0, right);
levelForward[0] = right[2];
levelForward[1] = 0;
levelForward[2] = -right[0];
cross(right, levelForward, up);
mvmulAffine(m1, 0, 0, -1, forward);
return (float) atan2(dot3(forward, up), dot3(forward, levelForward));
}
public void orbit(float[] v, float pan, float tilt, float[] out) {
invAffine(v, m1);
mvmulAffine(m1, 1, 0, 0, right);
normalize3(right);
setIdentity(m1);
setIdentity(m2);
m2[12] = -center[0];
m2[13] = -center[1];
m2[14] = -center[2];
rotY(m1, -pan);
mmulAffine(m1, m2, m2);
setRotation(m1, right, -tilt);
mmulAffine(m1, m2, m2);
setIdentity(m1);
setColumn3(m1, 3, center);
mmulAffine(m1, m2, m2);
mmulAffine(v, m2, out);
}
public void setCenter(float[] center) {
if (Vecmath.hasNaNsOrInfinites(center)) {
throw new IllegalArgumentException("center must not contain NaNs or infinites");
}
Vecmath.setf(this.center, center);
}
}