summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenneth Russel <[email protected]>2009-06-19 20:35:04 +0000
committerKenneth Russel <[email protected]>2009-06-19 20:35:04 +0000
commitd075bda489c425d7f1ccd45944db6a8696bb0fd2 (patch)
tree0d2c22bb410c0d116c60dfc0bb82888006653e72
parent3ac44007a441db45e5ed45b901806dc5b0c2a6b6 (diff)
Improved interaction in ExaminerViewer to match Maya's camera
controls. Added optional up vector. Simplified logic by using MouseEvent.getModifiersEx(). MouseButtonHelper is no longer necessary and has been removed. Updated demos. git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/../svn-server-sync/jogl-demos/trunk@357 3298f667-5e0e-4b4a-8ed4-a3559d26a5f4
-rwxr-xr-xsrc/demos/hdr/HDR.java4
-rw-r--r--src/demos/hwShadowmapsSimple/HWShadowmapsSimple.java4
-rw-r--r--src/demos/infiniteShadowVolumes/InfiniteShadowVolumes.java4
-rw-r--r--src/demos/proceduralTexturePhysics/ProceduralTexturePhysics.java4
-rw-r--r--src/demos/vertexProgRefract/VertexProgRefract.java4
-rw-r--r--src/demos/vertexProgWarp/VertexProgWarp.java4
-rw-r--r--src/gleem/ExaminerViewer.java136
-rw-r--r--src/gleem/MouseButtonHelper.java75
-rw-r--r--src/gleem/TestExaminerViewer.java3
-rw-r--r--src/gleem/TestMultiWin.java3
-rw-r--r--src/gleem/linalg/MathUtil.java9
11 files changed, 109 insertions, 141 deletions
diff --git a/src/demos/hdr/HDR.java b/src/demos/hdr/HDR.java
index 2f71c3c..bd3f7d6 100755
--- a/src/demos/hdr/HDR.java
+++ b/src/demos/hdr/HDR.java
@@ -13,7 +13,6 @@ import gleem.BSphereProvider;
import gleem.CameraParameters;
import gleem.ExaminerViewer;
import gleem.ManipManager;
-import gleem.MouseButtonHelper;
import gleem.linalg.Mat4f;
import gleem.linalg.Rotf;
import gleem.linalg.Vec3f;
@@ -365,7 +364,8 @@ public class HDR extends Demo {
manager.registerWindow((AWTGLAutoDrawable) drawable);
this.drawable = drawable;
- viewer = new ExaminerViewer(MouseButtonHelper.numMouseButtons());
+ viewer = new ExaminerViewer();
+ viewer.setUpVector(Vec3f.Y_AXIS);
viewer.setAutoRedrawMode(false);
viewer.setNoAltKeyMode(true);
viewer.attach((AWTGLAutoDrawable) drawable, new BSphereProvider() {
diff --git a/src/demos/hwShadowmapsSimple/HWShadowmapsSimple.java b/src/demos/hwShadowmapsSimple/HWShadowmapsSimple.java
index 1c7effe..3190778 100644
--- a/src/demos/hwShadowmapsSimple/HWShadowmapsSimple.java
+++ b/src/demos/hwShadowmapsSimple/HWShadowmapsSimple.java
@@ -44,7 +44,6 @@ import gleem.CameraParameters;
import gleem.ExaminerViewer;
import gleem.HandleBoxManip;
import gleem.ManipManager;
-import gleem.MouseButtonHelper;
import gleem.linalg.Mat4f;
import gleem.linalg.Rotf;
import gleem.linalg.Vec3f;
@@ -301,7 +300,8 @@ public class HWShadowmapsSimple extends Demo {
spotlight.setRotation(new Rotf(Vec3f.X_AXIS, (float) Math.toRadians(-30.0f)));
manager.showManipInWindow(spotlight, (AWTGLAutoDrawable) drawable);
- viewer = new ExaminerViewer(MouseButtonHelper.numMouseButtons());
+ viewer = new ExaminerViewer();
+ viewer.setUpVector(Vec3f.Y_AXIS);
viewer.attach((AWTGLAutoDrawable) drawable, new BSphereProvider() {
public BSphere getBoundingSphere() {
return new BSphere(object.getTranslation(), 2.0f);
diff --git a/src/demos/infiniteShadowVolumes/InfiniteShadowVolumes.java b/src/demos/infiniteShadowVolumes/InfiniteShadowVolumes.java
index dde5135..c0feeb1 100644
--- a/src/demos/infiniteShadowVolumes/InfiniteShadowVolumes.java
+++ b/src/demos/infiniteShadowVolumes/InfiniteShadowVolumes.java
@@ -43,7 +43,6 @@ import gleem.CameraParameters;
import gleem.ExaminerViewer;
import gleem.HandleBoxManip;
import gleem.ManipManager;
-import gleem.MouseButtonHelper;
import gleem.linalg.Mat4f;
import gleem.linalg.Rotf;
import gleem.linalg.Vec3f;
@@ -260,7 +259,8 @@ public class InfiniteShadowVolumes extends Demo {
lightManip.setTranslation(new Vec3f(0.5f, 0.5f, -1));
lightManip.setGeometryScale(new Vec3f(0.1f, 0.1f, 0.1f));
- viewer = new ExaminerViewer(MouseButtonHelper.numMouseButtons());
+ viewer = new ExaminerViewer();
+ viewer.setUpVector(Vec3f.Y_AXIS);
viewer.attach((AWTGLAutoDrawable) drawable, new BSphereProvider() {
public BSphere getBoundingSphere() {
return new BSphere(objectManip.getTranslation(), 1.0f);
diff --git a/src/demos/proceduralTexturePhysics/ProceduralTexturePhysics.java b/src/demos/proceduralTexturePhysics/ProceduralTexturePhysics.java
index 427d645..a813906 100644
--- a/src/demos/proceduralTexturePhysics/ProceduralTexturePhysics.java
+++ b/src/demos/proceduralTexturePhysics/ProceduralTexturePhysics.java
@@ -40,7 +40,6 @@ import gleem.BSphereProvider;
import gleem.CameraParameters;
import gleem.ExaminerViewer;
import gleem.ManipManager;
-import gleem.MouseButtonHelper;
import gleem.linalg.Vec3f;
import java.awt.BorderLayout;
import java.awt.Frame;
@@ -195,7 +194,8 @@ public class ProceduralTexturePhysics extends Demo {
manager.registerWindow((AWTGLAutoDrawable) drawable);
this.drawable = drawable;
- viewer = new ExaminerViewer(MouseButtonHelper.numMouseButtons());
+ viewer = new ExaminerViewer();
+ viewer.setUpVector(Vec3f.Y_AXIS);
viewer.setAutoRedrawMode(false);
viewer.attach((AWTGLAutoDrawable) drawable, new BSphereProvider() {
diff --git a/src/demos/vertexProgRefract/VertexProgRefract.java b/src/demos/vertexProgRefract/VertexProgRefract.java
index edbef87..fa71f0c 100644
--- a/src/demos/vertexProgRefract/VertexProgRefract.java
+++ b/src/demos/vertexProgRefract/VertexProgRefract.java
@@ -45,7 +45,6 @@ import gleem.BSphere;
import gleem.BSphereProvider;
import gleem.ExaminerViewer;
import gleem.ManipManager;
-import gleem.MouseButtonHelper;
import gleem.linalg.Rotf;
import gleem.linalg.Vec3f;
import java.awt.BorderLayout;
@@ -332,7 +331,8 @@ public class VertexProgRefract extends Demo {
manager.registerWindow((AWTGLAutoDrawable) drawable);
this.drawable = drawable;
- viewer = new ExaminerViewer(MouseButtonHelper.numMouseButtons());
+ viewer = new ExaminerViewer();
+ viewer.setUpVector(Vec3f.Y_AXIS);
viewer.setNoAltKeyMode(true);
viewer.setAutoRedrawMode(false);
viewer.attach((AWTGLAutoDrawable) drawable, new BSphereProvider() {
diff --git a/src/demos/vertexProgWarp/VertexProgWarp.java b/src/demos/vertexProgWarp/VertexProgWarp.java
index e6dbca7..8ab7166 100644
--- a/src/demos/vertexProgWarp/VertexProgWarp.java
+++ b/src/demos/vertexProgWarp/VertexProgWarp.java
@@ -43,7 +43,6 @@ import gleem.BSphere;
import gleem.BSphereProvider;
import gleem.ExaminerViewer;
import gleem.ManipManager;
-import gleem.MouseButtonHelper;
import gleem.linalg.Vec3f;
import java.awt.BorderLayout;
import java.awt.Frame;
@@ -231,7 +230,8 @@ public class VertexProgWarp extends Demo {
manager.registerWindow((AWTGLAutoDrawable) drawable);
this.drawable = drawable;
- viewer = new ExaminerViewer(MouseButtonHelper.numMouseButtons());
+ viewer = new ExaminerViewer();
+ viewer.setUpVector(Vec3f.Y_AXIS);
viewer.setNoAltKeyMode(true);
viewer.setAutoRedrawMode(false);
viewer.attach((AWTGLAutoDrawable) drawable, new BSphereProvider() {
diff --git a/src/gleem/ExaminerViewer.java b/src/gleem/ExaminerViewer.java
index d21579a..a99e555 100644
--- a/src/gleem/ExaminerViewer.java
+++ b/src/gleem/ExaminerViewer.java
@@ -84,8 +84,7 @@ public class ExaminerViewer {
/** Simple state machine for computing distance dragged */
private boolean button1Down;
private boolean button2Down;
- private int numMouseButtons;
- private int oldNumMouseButtons;
+ private boolean button3Down;
private int lastX;
private int lastY;
@@ -94,6 +93,7 @@ public class ExaminerViewer {
private Vec3f dolly = new Vec3f(0, 0, 10); // Amount we have "backed up" from focal point
private Vec3f center = new Vec3f(0, 0, 0); // Position of focal point in world coordinates
private Rotf orientation = new Rotf();
+ private Vec3f upVector = null;
private float rotateSpeed = 1.0f;
private float minRotateSpeed = 0.0001f;
private float dollySpeed = 2.0f;
@@ -112,17 +112,23 @@ public class ExaminerViewer {
}
public void mouseMoved(MouseEvent e) {
- passiveMotionMethod(e);
+ if (interactionUnderway && iOwnInteraction) {
+ // Hack for AWT behavior where Ctrl + Alt + Left mouse button is treated
+ // as motion instead of drag
+ motionMethod(e, e.getX(), e.getY());
+ } else {
+ passiveMotionMethod(e);
+ }
}
};
private MouseAdapter mouseListener = new MouseAdapter() {
public void mousePressed(MouseEvent e) {
- mouseMethod(e, e.getModifiers(), true, e.getX(), e.getY());
+ mouseMethod(e, e.getModifiersEx(), true, e.getX(), e.getY());
}
public void mouseReleased(MouseEvent e) {
- mouseMethod(e, e.getModifiers(), false, e.getX(), e.getY());
+ mouseMethod(e, e.getModifiersEx(), false, e.getX(), e.getY());
}
};
@@ -136,11 +142,7 @@ public class ExaminerViewer {
public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {}
};
- /** The constructor takes the number of mouse buttons on this system
- (couldn't figure out how to determine this internally) */
- public ExaminerViewer(int numMouseButtons) {
- this.numMouseButtons = numMouseButtons;
- oldNumMouseButtons = numMouseButtons;
+ public ExaminerViewer() {
}
/** <P> Attaches this ExaminerViewer to the given GLAutoDrawable. This
@@ -287,18 +289,20 @@ public class ExaminerViewer {
this.orientation.set(orientation);
}
- public void setNoAltKeyMode(boolean noAltKeyMode) {
- this.noAltKeyMode = noAltKeyMode;
- if (noAltKeyMode) {
- // FIXME: this is a hack to work around Windows' apparently
- // conflating the alt/meta key with one of the mouse buttons
- oldNumMouseButtons = numMouseButtons;
- numMouseButtons = 3;
+ /** Sets the preferred up vector of this ExaminerViewer. The default
+ is null. */
+ public void setUpVector(Vec3f up) {
+ if (up == null) {
+ upVector = null;
} else {
- numMouseButtons = oldNumMouseButtons;
+ upVector = up.copy();
}
}
+ public void setNoAltKeyMode(boolean noAltKeyMode) {
+ this.noAltKeyMode = noAltKeyMode;
+ }
+
public boolean getNoAltKeyMode() {
return noAltKeyMode;
}
@@ -354,17 +358,16 @@ public class ExaminerViewer {
private boolean modifiersMatch(MouseEvent e, int mods) {
if (noAltKeyMode) {
- if ((mods & MouseEvent.BUTTON1_MASK) != 0 &&
- (mods & MouseEvent.BUTTON2_MASK) == 0 &&
- (mods & MouseEvent.BUTTON3_MASK) == 0) {
+ if ((mods & MouseEvent.BUTTON1_DOWN_MASK) != 0 &&
+ (mods & MouseEvent.BUTTON2_DOWN_MASK) == 0 &&
+ (mods & MouseEvent.BUTTON3_DOWN_MASK) == 0) {
return (!e.isAltDown() && !e.isMetaDown() && !e.isControlDown() && !e.isShiftDown());
} else {
// At least on Windows, meta seems to be declared to be down on right button presses
return !e.isControlDown() && !e.isShiftDown();
}
} else {
- return ((e.isAltDown() || e.isMetaDown()) &&
- (!e.isControlDown() && !e.isShiftDown()));
+ return (e.isAltDown() || e.isMetaDown());
}
}
@@ -396,7 +399,30 @@ public class ExaminerViewer {
lastX = x;
lastY = y;
- if ((button1Down && (!button2Down))) {
+ // The intent is to match Maya's camera controls, which are the de facto standard:
+ // - Alt + Left = rotation
+ // - Alt + Right = zoom
+ // - Alt + Middle = translation
+ // With the hack that Ctrl + Alt + Right on a trackpad be the same as translation,
+ // so that gesture can be done without a 3-button mouse hooked up.
+
+ boolean doRotation =
+ (button1Down && !button2Down && !button3Down);
+ boolean doTranslation =
+ (button2Down && !button1Down && !button3Down);
+ boolean doZoom =
+ (button3Down && !button1Down && !button2Down);
+
+ // Hack to allow us to use Ctrl + Alt + LMB to translate so
+ // that we can do that gesture on the trackpad
+ if (e.isControlDown() && (doRotation || doZoom ||
+ (button1Down && button2Down))) {
+ doRotation = false;
+ doZoom = false;
+ doTranslation = true;
+ }
+
+ if (doRotation) {
// Rotation functionality
float xRads = (float) Math.PI * -1.0f * dy * rotateSpeed / 1000.0f;
@@ -406,7 +432,23 @@ public class ExaminerViewer {
Rotf newRot = yRot.times(xRot);
orientation = orientation.times(newRot);
- } else if (button2Down && (!button1Down)) {
+ if (upVector != null) {
+ // FIXME: has degenerate behavior when pointing parallel to up vector
+ Vec3f cameraUp = orientation.rotateVector(Vec3f.Y_AXIS);
+ float dotp = cameraUp.dot(upVector);
+ if (Math.abs(dotp) > MathUtil.ZERO_TOLERANCE) {
+ // Form orthonormal basis
+ Vec3f back = orientation.rotateVector(Vec3f.Z_AXIS);
+ Vec3f right = upVector.cross(back);
+ right.normalize();
+ cameraUp.cross(back, right);
+ Mat4f mat = new Mat4f();
+ mat.setRotation(right, cameraUp, back);
+ orientation.fromMatrix(mat);
+ }
+ }
+
+ } else if (doTranslation) {
// Translate functionality
// Compute the local coordinate system's difference vector
@@ -418,9 +460,10 @@ public class ExaminerViewer {
// Add on to center
center.add(worldDiff);
- } else if (button1Down && button2Down) {
+ } else if (doZoom) {
- float diff = dollySpeed * -1.0f * dy / 100.0f;
+ // FIXME: implement this in terms of mouse wheel
+ float diff = dollySpeed * (-1.0f * dy - dx) / 100.0f;
float newDolly = dolly.z() + diff;
if (newDolly < minFocalDist) {
newDolly = minFocalDist;
@@ -451,37 +494,26 @@ public class ExaminerViewer {
ManipManager.getManipManager().mouseReleased(e);
}
} else {
- if ((mods & MouseEvent.BUTTON1_MASK) != 0) {
- if (press) {
- button1Down = true;
- } else {
- button1Down = false;
- }
+ if ((mods & MouseEvent.BUTTON1_DOWN_MASK) != 0) {
+ button1Down = true;
} else {
- if (numMouseButtons != 3) {
- if ((mods & MouseEvent.BUTTON2_MASK) != 0) {
- if (press) {
- button2Down = true;
- } else {
- button2Down = false;
- }
- }
- } else {
- // FIXME: must test this on 3-button system
- if ((mods & MouseEvent.BUTTON3_MASK) != 0) {
- if (press) {
- button2Down = true;
- } else {
- button2Down = false;
- }
- }
- }
+ button1Down = false;
+ }
+ if ((mods & MouseEvent.BUTTON2_DOWN_MASK) != 0) {
+ button2Down = true;
+ } else {
+ button2Down = false;
+ }
+ if ((mods & MouseEvent.BUTTON3_DOWN_MASK) != 0) {
+ button3Down = true;
+ } else {
+ button3Down = false;
}
lastX = x;
lastY = y;
- if (button1Down || button2Down) {
+ if (button1Down || button2Down || button3Down) {
interactionUnderway = true;
iOwnInteraction = true;
} else {
diff --git a/src/gleem/MouseButtonHelper.java b/src/gleem/MouseButtonHelper.java
deleted file mode 100644
index f682c53..0000000
--- a/src/gleem/MouseButtonHelper.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * gleem -- OpenGL Extremely Easy-To-Use Manipulators.
- * Copyright (C) 1998-2003 Kenneth B. Russell ([email protected])
- *
- * Copying, distribution and use of this software in source and binary
- * forms, with or without modification, is permitted provided that the
- * following conditions are met:
- *
- * Distributions of source code must reproduce the copyright notice,
- * this list of conditions and the following disclaimer in the source
- * code header files; and Distributions of binary code must reproduce
- * the copyright notice, this list of conditions and the following
- * disclaimer in the documentation, Read me file, license file and/or
- * other materials provided with the software distribution.
- *
- * The names of Sun Microsystems, Inc. ("Sun") and/or the copyright
- * holder may not be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF ANY
- * KIND. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, NON-INTERFERENCE, ACCURACY OF
- * INFORMATIONAL CONTENT OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. THE
- * COPYRIGHT HOLDER, SUN AND SUN'S LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL THE
- * COPYRIGHT HOLDER, SUN OR SUN'S LICENSORS BE LIABLE FOR ANY LOST
- * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
- * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
- * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
- * INABILITY TO USE THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGES. YOU ACKNOWLEDGE THAT THIS SOFTWARE IS NOT
- * DESIGNED, LICENSED OR INTENDED FOR USE IN THE DESIGN, CONSTRUCTION,
- * OPERATION OR MAINTENANCE OF ANY NUCLEAR FACILITY. THE COPYRIGHT
- * HOLDER, SUN AND SUN'S LICENSORS DISCLAIM ANY EXPRESS OR IMPLIED
- * WARRANTY OF FITNESS FOR SUCH USES.
- */
-
-package gleem;
-
-import java.security.*;
-
-/** Helper class for figuring out how many mouse buttons are
- available. (Does not seem to be a way of figuring this out with
- the AWT.) */
-
-public class MouseButtonHelper {
- /** Returns the number of buttons on the mouse device. This is only
- a guess and the implementation may need to be extended to
- support other operating systems (in particular, Mac OS). */
- public static int numMouseButtons() {
- String osName = null;
- if (System.getSecurityManager() != null) {
- osName = (String)
- AccessController.doPrivileged(new PrivilegedAction() {
- public Object run() {
- return System.getProperty("os.name");
- }
- });
- } else {
- osName = System.getProperty("os.name");
- }
- return mouseButtonsForOS(osName);
- }
-
- private static int mouseButtonsForOS(String osName) {
- if (osName.startsWith("Windows")) {
- return 2;
- } else {
- // Assume X11 and a three-button mouse
- return 3;
- }
- }
-}
diff --git a/src/gleem/TestExaminerViewer.java b/src/gleem/TestExaminerViewer.java
index 03f4a00..aae755a 100644
--- a/src/gleem/TestExaminerViewer.java
+++ b/src/gleem/TestExaminerViewer.java
@@ -127,7 +127,8 @@ public class TestExaminerViewer {
manager.showManipInWindow(manip, (AWTGLAutoDrawable) drawable);
// Instantiate ExaminerViewer
- viewer = new ExaminerViewer(MouseButtonHelper.numMouseButtons());
+ viewer = new ExaminerViewer();
+ viewer.setUpVector(Vec3f.Y_AXIS);
viewer.attach((AWTGLAutoDrawable) drawable, new HandleBoxManipBSphereProvider(manip));
viewer.viewAll(gl);
}
diff --git a/src/gleem/TestMultiWin.java b/src/gleem/TestMultiWin.java
index ae78828..39fee6b 100644
--- a/src/gleem/TestMultiWin.java
+++ b/src/gleem/TestMultiWin.java
@@ -126,7 +126,8 @@ public class TestMultiWin {
manager.showManipInWindow(manip, (AWTGLAutoDrawable) drawable);
// Instantiate ExaminerViewer
- viewer = new ExaminerViewer(MouseButtonHelper.numMouseButtons());
+ viewer = new ExaminerViewer();
+ viewer.setUpVector(Vec3f.Y_AXIS);
viewer.attach((AWTGLAutoDrawable) drawable, new HandleBoxManipBSphereProvider(manip));
viewer.viewAll(gl);
}
diff --git a/src/gleem/linalg/MathUtil.java b/src/gleem/linalg/MathUtil.java
index 7415953..fa3db3e 100644
--- a/src/gleem/linalg/MathUtil.java
+++ b/src/gleem/linalg/MathUtil.java
@@ -42,6 +42,15 @@ package gleem.linalg;
/** Utility math routines. */
public class MathUtil {
+ /** A "close to zero" float epsilon value for use */
+ public static final float FLT_EPSILON = 1.19209290e-07f;
+
+ /** A "close to zero" double epsilon value for use */
+ public static final double EPSILON = 2.220446049250313E-16d;
+
+ /** A close, but not quite, zero float epsilon value for use */
+ public static final float ZERO_TOLERANCE = 0.0001f;
+
/** Makes an arbitrary vector perpendicular to <B>src</B> and
inserts it into <B>dest</B>. Returns false if the source vector
was equal to (0, 0, 0). */