/*******************************************************************************
* 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;
import static org.andork.math3d.Vecmath.dot3;
import static org.andork.math3d.Vecmath.interp3;
import static org.andork.math3d.Vecmath.invAffine;
import static org.andork.math3d.Vecmath.mpmulAffine;
import static org.andork.math3d.Vecmath.scaleAdd3;
import static org.andork.math3d.Vecmath.sub3;
import static org.andork.math3d.Vecmath.subDot3;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import org.andork.jogl.AutoClipOrthoProjection;
import org.andork.jogl.JoglViewSettings;
import org.andork.jogl.JoglViewState;
import org.andork.math3d.Vecmath;
import com.jogamp.opengl.GLAutoDrawable;
public class JoglOrthoNavigator extends MouseAdapter {
final GLAutoDrawable drawable;
final JoglViewState viewState;
final JoglViewSettings viewSettings;
MouseEvent lastEvent = null;
MouseEvent pressEvent = null;
final float[] vi = Vecmath.newMat4f();
final float[] v = Vecmath.newMat4f();
boolean active = true;
boolean callDisplay = true;
float moveFactor = 0.05f;
float panFactor = (float) Math.PI;
float tiltFactor = (float) Math.PI;
float wheelFactor = 1f;
float sensitivity = 1f;
final float[] p0 = new float[3];
final float[] p1 = new float[3];
final float[] p2 = new float[3];
public JoglOrthoNavigator(GLAutoDrawable drawable, JoglViewState viewState, JoglViewSettings viewSettings) {
super();
this.drawable = drawable;
this.viewState = viewState;
this.viewSettings = viewSettings;
}
private void calcZoom(MouseEvent e, float factor) {
viewState.pickXform().xform(-1, -1, -1, p0);
viewState.pickXform().xform(1, 1, -1, p1);
viewState.pickXform().xform(e, -1, p2);
sub3(p0, p2, p0);
sub3(p1, p2, p1);
scaleAdd3(factor, p0, p2, p0);
scaleAdd3(factor, p1, p2, p1);
AutoClipOrthoProjection orthoCalc = (AutoClipOrthoProjection) viewSettings.getProjection();
orthoCalc.hSpan = Math.abs(dot3(p0, 0, vi, 0) - dot3(p1, 0, vi, 0));
orthoCalc.vSpan = Math.abs(dot3(p0, 0, vi, 4) - dot3(p1, 0, vi, 4));
interp3(p0, p1, 0.5f, p2);
float dx = subDot3(p2, 0, vi, 12, vi, 0);
float dy = subDot3(p2, 0, vi, 12, vi, 4);
vi[12] += vi[0] * dx + vi[4] * dy;
vi[13] += vi[1] * dx + vi[5] * dy;
vi[14] += vi[2] * dx + vi[6] * dy;
invAffine(vi, v);
viewSettings.setViewXform(v);
}
public float getMoveFactor() {
return moveFactor;
}
public float getPanFactor() {
return panFactor;
}
public float getSensitivity() {
return sensitivity;
}
public float getTiltFactor() {
return tiltFactor;
}
public float getWheelFactor() {
return wheelFactor;
}
public boolean isActive() {
return active;
}
public boolean isCallDisplay() {
return callDisplay;
}
@Override
public void mouseDragged(MouseEvent e) {
if (!active || pressEvent == null) {
return;
}
viewState.pickXform().xform(lastEvent, -1, p0);
viewState.pickXform().xform(e, -1, p1);
mpmulAffine(viewState.viewXform(), p0);
mpmulAffine(viewState.viewXform(), p1);
float dx = p1[0] - p0[0];
float dy = p1[1] - p0[1];
if (e.isControlDown()) {
dx /= 10f;
dy /= 10f;
}
lastEvent = e;
viewSettings.getViewXform(v);
Vecmath.invAffine(v, vi);
// float scaledMoveFactor = moveFactor * sensitivity;
// if( pressEvent.getButton( ) == MouseEvent.BUTTON1 )
// {
// if( pressEvent.isShiftDown( ) )
// {
// float dpan = ( float ) ( dx * panFactor * sensitivity /
// canvas.getWidth( ) );
// float dtilt = ( float ) ( dy * tiltFactor * sensitivity /
// canvas.getHeight( ) );
//
// Vecmath.rotY( temp , dpan );
// Vecmath.mmulRotational( temp , cam , cam );
//
// Vecmath.mvmulAffine( cam , 1 , 0 , 0 , v );
// Vecmath.setRotation( temp , v , dtilt );
// Vecmath.mmulRotational( temp , cam , cam );
//
// Vecmath.invAffine( cam );
// viewSettings.setViewXform( cam );
// }
// }
if (pressEvent.getButton() == MouseEvent.BUTTON2) {
if (e.isShiftDown()) {
vi[12] += vi[8] * dy;
vi[13] += vi[9] * dy;
vi[14] += vi[10] * dy;
Vecmath.invAffine(vi, v);
viewSettings.setViewXform(v);
} else {
calcZoom(e, (float) Math.pow(1.1f, dy));
}
} else {
vi[12] += vi[0] * -dx - vi[4] * dy;
vi[13] += vi[1] * -dx - vi[5] * dy;
vi[14] += vi[2] * -dx - vi[6] * dy;
Vecmath.invAffine(vi, v);
viewSettings.setViewXform(v);
}
if (callDisplay) {
drawable.display();
}
}
@Override
public void mousePressed(MouseEvent e) {
if (pressEvent == null) {
pressEvent = e;
lastEvent = e;
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (pressEvent != null && e.getButton() == pressEvent.getButton()) {
pressEvent = null;
}
}
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
if (!active) {
return;
}
viewSettings.getViewXform(v);
Vecmath.invAffine(v, vi);
float distance = e.getWheelRotation() * wheelFactor * sensitivity;
if (e.isControlDown()) {
distance /= 10;
}
if (e.isShiftDown()) {
vi[12] += vi[8] * distance;
vi[13] += vi[9] * distance;
vi[14] += vi[10] * distance;
Vecmath.invAffine(vi, v);
viewSettings.setViewXform(v);
} else {
calcZoom(e, (float) Math.pow(1.1f, distance));
}
if (callDisplay) {
drawable.display();
}
}
public void setActive(boolean active) {
this.active = active;
}
public void setCallDisplay(boolean callDisplay) {
this.callDisplay = callDisplay;
}
public void setMoveFactor(float moveFactor) {
this.moveFactor = moveFactor;
}
public void setPanFactor(float panFactor) {
this.panFactor = panFactor;
}
public void setSensitivity(float sensitivity) {
this.sensitivity = sensitivity;
}
public void setTiltFactor(float tiltFactor) {
this.tiltFactor = tiltFactor;
}
public void setWheelFactor(float wheelFactor) {
this.wheelFactor = wheelFactor;
}
}