summaryrefslogtreecommitdiffstats
path: root/src/gleem/HandleBoxManip.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/gleem/HandleBoxManip.java')
-rw-r--r--src/gleem/HandleBoxManip.java948
1 files changed, 0 insertions, 948 deletions
diff --git a/src/gleem/HandleBoxManip.java b/src/gleem/HandleBoxManip.java
deleted file mode 100644
index e35ad40..0000000
--- a/src/gleem/HandleBoxManip.java
+++ /dev/null
@@ -1,948 +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.util.*;
-
-import gleem.linalg.*;
-import javax.media.opengl.*;
-
-/** Patterned after Inventor's HandleBoxManip (by Paul Isaacs and
- David Mott) and TransformerManip (by Paul Isaacs). Center box
- allows 3-D translation. Outer six handles allow rotation about the
- box's six axes. When a handle is clicked, the axis of rotation is
- immediately chosen as that which is most parallel to the viewing
- direction (note there are at most two possibilities for the axis
- of each handle's rotation). Eight corner handles allow aspect
- ratio-preserving scaling; shift-dragging these handles allows
- non-uniform scaling in one of two possible directions using a
- "snap-to-axis" paradigm. These two directions are chosen as the
- axes of the adjacent face to the handle whose normal most directly
- faces the viewing direction. */
-
-public class HandleBoxManip extends Manip {
- private ManipPart parts;
- private Vec3f translation;
- private Vec3f scale;
- private Vec3f geometryScale;
- private Rotf rotation;
- /** Cumulative transform of this object */
- private Mat4f xform;
-
- /** Dragging state */
- private static final int INACTIVE = 0;
- private static final int TRANSLATE = 1;
- private static final int ROTATE = 2;
- // Scaling based on all three axes, preserving current aspect ratio
- private static final int SCALE_XYZ = 3;
- // Scaling along one of two axes (shift key + drag scale handle)
- private static final int SCALE_SINGLE_AXIS = 4;
-
- private int dragState;
- private Plane dragPlane;
- private Vec3f dragOffset;
-
- /** Scale axes */
- private static final int SCALE_XY = 0;
- private static final int SCALE_YZ = 1;
- private static final int SCALE_ZX = 2;
-
- /** All of the line segments comprising the faces */
- private ManipPart[] lineSegs;
-
- static class FaceInfo {
- ManipPart[] lineSegs;
- /** The invisible square comprising this face's invisible, but
- pickable, geometry */
- ManipPart centerSquare;
- Vec3f origNormal;
- Vec3f normal;
- int scaleAxes;
-
- FaceInfo() {
- lineSegs = new ManipPart[4];
- origNormal = new Vec3f();
- normal = new Vec3f();
- }
- }
- /** List<FaceInfo> */
- private List faces;
- /** List<ManipPart> */
- private List highlightedGeometry;
- /** List<ManipPart> */
- private List draggedGeometry;
-
- /** Each rotation handle points off to two faces corresponding to
- the planes in which that handle can rotate. It also points to
- two circles which appear during dragging to indicate to the user
- in which plane the manipulator is being rotated. */
- static class RotateHandleInfo {
- ManipPart geometry;
- int faceIdx0;
- int faceIdx1;
- }
- /** List<RotateHandleInfo> */
- private List rotateHandles;
- private PlaneUV rotatePlane;
- private float startAngle;
- private Rotf startRot;
-
- private int scaleAxes;
- /** Each scale handle points off to its three adjacent faces. */
- static class ScaleHandleInfo {
- ManipPart geometry;
- /** The indices of the three adjacent faces */
- int[] faceIndices;
-
- ScaleHandleInfo() {
- faceIndices = new int[3];
- }
- }
- /** List<ScaleHandleInfo> */
- private List scaleHandles;
- // State variables for XYZ scaling
- /** This line's direction must point outward from the center of the
- cube. */
- private Line scaleXYZLine;
- private float origScaleLen;
- private Vec3f origScale;
- // State variables for single-axis scaling
- private PlaneUV scaleAxisPlane;
- private Vec3f scaleAxisOffset;
- private Vec2f scaleAxisOrigUV;
-
- /** Default HandleBoxManip has translation (0, 0, 0) and the
- identity orientation */
- public HandleBoxManip() {
- parts = new ManipPartTwoWayArrow();
- translation = new Vec3f(0, 0, 0);
- scale = new Vec3f(1, 1, 1);
- geometryScale = new Vec3f(1, 1, 1);
- // Rotf should have a makeIdent() or at least initialize
- // itself to the unit quaternion (see NOTES.txt)
- rotation = new Rotf();
- xform = new Mat4f();
-
- dragState = INACTIVE;
- dragPlane = new Plane();
- dragOffset = new Vec3f();
-
- lineSegs = new ManipPart[12];
-
- faces = new ArrayList();
- highlightedGeometry = new ArrayList();
- draggedGeometry = new ArrayList();
-
- rotateHandles = new ArrayList();
- rotatePlane = new PlaneUV();
- startRot = new Rotf();
-
- scaleHandles = new ArrayList();
- scaleXYZLine = new Line();
- origScale = new Vec3f();
- scaleAxisPlane = new PlaneUV();
- scaleAxisOffset = new Vec3f();
- scaleAxisOrigUV = new Vec2f();
-
- createGeometry();
- recalc();
- }
-
- /** Set the translation of this HandleBoxManip. This moves its
- on-screen representation. Manipulations cause the translation to
- be modified, not overwritten. */
- public void setTranslation(Vec3f translation) {
- this.translation.set(translation);
- recalc();
- }
-
- /** Get the translation of this Translate1Manip. This corresponds to
- the center of its body. */
- public Vec3f getTranslation() {
- return new Vec3f(translation);
- }
-
- /** Set the rotation of this HandleBoxManip. */
- public void setRotation(Rotf rotation) {
- this.rotation.set(rotation);
- recalc();
- }
-
- /** Get the rotation of this HandleBoxManip. */
- public Rotf getRotation() {
- return new Rotf(rotation);
- }
-
- /** Set the scale of the HandleBoxManip. This corresponds to the
- scaling the user has performed. */
- public void setScale(Vec3f scale) {
- this.scale.set(scale);
- recalc();
- }
-
- public Vec3f getScale() {
- return new Vec3f(scale);
- }
-
- /** Set the scale of the HandleBoxManip's geometry. This only
- affects its on-screen representation. It is probably a bad idea
- to use a non-uniform scale here, because it'd be very confusing
- to the user. None of the components of the geometryScale vector
- may be negative. */
- public void setGeometryScale(Vec3f geometryScale) {
- this.geometryScale.set(geometryScale);
- recalc();
- }
-
- public Vec3f getGeometryScale() {
- return new Vec3f(geometryScale);
- }
-
- /** Get the cumulative transformation matrix of this
- HandleBoxManip. */
- public Mat4f getTransform() {
- // Transform is Scale, Rotation, Translation applied to incoming
- // column vectors in that order (SRT, or TRS since column vectors
- // are right-multiplied)
- Mat4f dest = new Mat4f();
- getTransform(dest);
- return dest;
- }
-
- /** Get the cumulative transformation matrix of this HandleBoxManip
- into the passed matrix. */
- public void getTransform(Mat4f dest) {
- Mat4f tmp1 = new Mat4f();
- Mat4f tmp2 = new Mat4f();
- tmp1.makeIdent();
- tmp2.makeIdent();
- tmp1.setScale(scale);
- dest.makeIdent();
- dest.setRotation(rotation);
- tmp2.mul(dest, tmp1);
- tmp1.makeIdent();
- tmp1.setTranslation(translation);
- dest.mul(tmp1, tmp2);
- }
-
- public void render(GL gl) {
- int i;
- for (i = 0; i < 12; i++)
- lineSegs[i].render(gl);
- for (i = 0; i < rotateHandles.size(); i++)
- ((RotateHandleInfo) rotateHandles.get(i)).geometry.render(gl);
- for (i = 0; i < scaleHandles.size(); i++)
- ((ScaleHandleInfo) scaleHandles.get(i)).geometry.render(gl);
- }
-
- public void intersectRay(Vec3f rayStart,
- Vec3f rayDirection,
- List results) {
- for (Iterator iter = faces.iterator(); iter.hasNext(); ) {
- ((FaceInfo) iter.next()).centerSquare.intersectRay(rayStart, rayDirection,
- results, this);
- }
- for (Iterator iter = rotateHandles.iterator(); iter.hasNext(); ) {
- ((RotateHandleInfo) iter.next()).geometry.intersectRay(rayStart, rayDirection,
- results, this);
- }
- for (Iterator iter = scaleHandles.iterator(); iter.hasNext(); ) {
- ((ScaleHandleInfo) iter.next()).geometry.intersectRay(rayStart, rayDirection,
- results, this);
- }
- }
-
- public void highlight(HitPoint hit) {
- ManipPart part = hit.manipPart;
- // Search for this part in the FaceInfo array
- for (Iterator iter = faces.iterator(); iter.hasNext(); ) {
- FaceInfo info = (FaceInfo) iter.next();
- if (info.centerSquare == part) {
- for (int j = 0; j < 4; j++) {
- info.lineSegs[j].highlight();
- highlightedGeometry.add(info.lineSegs[j]);
- }
- return;
- }
- }
-
- // Otherwise, was a rotation or scale handle
- part.highlight();
- highlightedGeometry.add(part);
- }
-
- public void clearHighlight() {
- for (Iterator iter = highlightedGeometry.iterator(); iter.hasNext(); ) {
- ((ManipPart) iter.next()).clearHighlight();
- }
- highlightedGeometry.clear();
- }
-
- public void makeActive(HitPoint hit) {
- // Find which piece of geometry it is
- for (Iterator iter = faces.iterator(); iter.hasNext(); ) {
- FaceInfo face = (FaceInfo) iter.next();
- if (face.centerSquare == hit.manipPart) {
- dragState = TRANSLATE;
- dragPlane.setPoint(hit.intPt.getIntersectionPoint());
- dragPlane.setNormal(face.normal);
- dragOffset.sub(translation, hit.intPt.getIntersectionPoint());
- for (int j = 0; j < 4; j++) {
- face.lineSegs[j].highlight();
- draggedGeometry.add(face.lineSegs[j]);
- }
- return;
- }
- }
-
- for (Iterator iter = rotateHandles.iterator(); iter.hasNext(); ) {
- RotateHandleInfo rotInfo = (RotateHandleInfo) iter.next();
- if (rotInfo.geometry == hit.manipPart) {
- dragState = ROTATE;
- // Determine which direction we're rotating by taking dot
- // products of the ray direction with the rotating planes'
- // normals
- float dotp0 =
- Math.abs(hit.rayDirection.dot(((FaceInfo) faces.get(rotInfo.faceIdx0)).normal));
- float dotp1 =
- Math.abs(hit.rayDirection.dot(((FaceInfo) faces.get(rotInfo.faceIdx1)).normal));
- int faceIdx;
- if (dotp0 > dotp1)
- faceIdx = rotInfo.faceIdx0;
- else
- faceIdx = rotInfo.faceIdx1;
- FaceInfo face = (FaceInfo) faces.get(faceIdx);
- // Set up the rotation plane
- rotatePlane.setOrigin(translation);
- rotatePlane.setNormal(face.normal);
- Vec3f dummy = new Vec3f();
- Vec2f startUV = new Vec2f();
- rotatePlane.projectPoint(hit.intPt.getIntersectionPoint(), dummy, startUV);
- startAngle = (float) Math.atan2(startUV.y(), startUV.x());
- startRot.set(rotation);
- rotInfo.geometry.highlight();
- draggedGeometry.add(rotInfo.geometry);
- return;
- }
- }
-
- for (Iterator iter = scaleHandles.iterator(); iter.hasNext(); ) {
- ScaleHandleInfo info = (ScaleHandleInfo) iter.next();
- if (info.geometry == hit.manipPart) {
- if (hit.shiftDown) {
- dragState = SCALE_SINGLE_AXIS;
- // Figure out which are the two axes along which we're
- // going to allow scaling by taking dot products of the
- // ray direction with the normals of the adjacent faces
- // to the scale handle.
- float dotp = 0.0f;
- float tmpDotp;
- int faceIdx = 0;
- for (int i = 0; i < 3; i++) {
- FaceInfo faceInfo = (FaceInfo) faces.get(info.faceIndices[i]);
- tmpDotp = faceInfo.normal.dot(hit.rayDirection);
- if ((i == 0) || (tmpDotp < dotp)) {
- dotp = tmpDotp;
- faceIdx = info.faceIndices[i];
- }
- }
- scaleAxes = ((FaceInfo) faces.get(faceIdx)).scaleAxes;
- Vec3f uAxisOrig = new Vec3f();
- Vec3f vAxisOrig = new Vec3f();
- if (scaleAxes == SCALE_XY) {
- uAxisOrig.set(1, 0, 0);
- vAxisOrig.set(0, 1, 0);
- } else if (scaleAxes == SCALE_YZ) {
- uAxisOrig.set(0, 1, 0);
- vAxisOrig.set(0, 0, 1);
- } else {
- uAxisOrig.set(0, 0, 1);
- vAxisOrig.set(1, 0, 0);
- }
- Vec3f uAxis = new Vec3f();
- Vec3f vAxis = new Vec3f();
- Mat4f rotationTmpMat = new Mat4f();
- rotationTmpMat.makeIdent();
- rotationTmpMat.setRotation(rotation);
- rotationTmpMat.xformDir(uAxisOrig, uAxis);
- rotationTmpMat.xformDir(vAxisOrig, vAxis);
- Vec3f normal = new Vec3f();
- normal.cross(uAxis, vAxis);
- scaleAxisPlane.setNormalAndUV(normal, uAxis, vAxis);
- // We need to be able to constrain the scaling to be
- // nonnegative.
- Vec3f newOrigin = new Vec3f();
- Vec2f foo = new Vec2f();
- scaleAxisPlane.projectPoint(translation, newOrigin, foo);
- scaleAxisPlane.setOrigin(newOrigin);
- scaleAxisOffset.sub(hit.intPt.getIntersectionPoint(), newOrigin);
- // Now project intersection point onto plane
- Vec3f bar = new Vec3f();
- scaleAxisPlane.projectPoint(hit.intPt.getIntersectionPoint(),
- bar, scaleAxisOrigUV);
- // Put the plane back where it was
- scaleAxisPlane.setOrigin(hit.intPt.getIntersectionPoint());
- origScale.set(scale);
- } else {
- dragState = SCALE_XYZ;
- scaleXYZLine.setPoint(hit.intPt.getIntersectionPoint());
- Vec3f scaleDiffVec = new Vec3f();
- scaleDiffVec.sub(hit.intPt.getIntersectionPoint(), translation);
- scaleXYZLine.setDirection(scaleDiffVec);
- origScale.set(scale);
- origScaleLen = scaleDiffVec.length();
- }
- info.geometry.highlight();
- draggedGeometry.add(info.geometry);
- return;
- }
- }
-
- throw new RuntimeException("Couldn't find intersected piece of geometry");
- }
-
- public void drag(Vec3f rayStart,
- Vec3f rayDirection) {
- if (dragState == TRANSLATE) {
- // Algorithm: Find intersection of ray with dragPlane. Add
- // dragOffset to this point to get new translation.
- IntersectionPoint intPt = new IntersectionPoint();
- if (dragPlane.intersectRay(rayStart,
- rayDirection,
- intPt) == false) {
- // Ray is parallel to plane. Punt.
- return;
- }
- translation.add(intPt.getIntersectionPoint(), dragOffset);
- recalc();
- } else if (dragState == ROTATE) {
- IntersectionPoint intPt = new IntersectionPoint();
- Vec2f uvCoords = new Vec2f();
- if (rotatePlane.intersectRay(rayStart,
- rayDirection,
- intPt,
- uvCoords) == false) {
- // Ray is parallel to plane. Punt.
- return;
- }
- // Compute offset rotation angle
- Rotf offsetRot = new Rotf();
- offsetRot.set(rotatePlane.getNormal(),
- (float) Math.atan2(uvCoords.y(), uvCoords.x()) - startAngle);
- rotation.mul(offsetRot, startRot);
- recalc();
- } else if (dragState == SCALE_XYZ) {
- Vec3f closestPt = new Vec3f();
- boolean gotPt = scaleXYZLine.closestPointToRay(rayStart,
- rayDirection,
- closestPt);
- if (gotPt) {
- // How far have we moved?
- // Clamp scale to be positive.
- Vec3f newDiffVec = new Vec3f();
- newDiffVec.sub(closestPt, translation);
- if (newDiffVec.dot(scaleXYZLine.getDirection()) < 0) {
- scale.set(0, 0, 0);
- } else {
- float scaleChange = newDiffVec.length() / origScaleLen;
- scale.set(origScale);
- scale.scale(scaleChange);
- }
- recalc();
- }
- } else if (dragState == SCALE_SINGLE_AXIS) {
- IntersectionPoint intPt = new IntersectionPoint();
- Vec2f uvCoords = new Vec2f();
- if (scaleAxisPlane.intersectRay(rayStart, rayDirection, intPt, uvCoords)) {
- Vec2f faceCenteredUVCoords = new Vec2f();
- Vec3f foo = new Vec3f();
- Vec3f tmp = new Vec3f();
- tmp.set(intPt.getIntersectionPoint());
- tmp.add(scaleAxisOffset);
- scaleAxisPlane.projectPoint(tmp, foo, faceCenteredUVCoords);
- if ((MathUtil.sgn(faceCenteredUVCoords.x()) ==
- MathUtil.sgn(scaleAxisOrigUV.x())) &&
- (MathUtil.sgn(faceCenteredUVCoords.y()) ==
- MathUtil.sgn(scaleAxisOrigUV.y()))) {
- if (faceCenteredUVCoords.x() < 0)
- uvCoords.setX(uvCoords.x() * -1);
- if (faceCenteredUVCoords.y() < 0)
- uvCoords.setY(uvCoords.y() * -1);
- Vec3f scaleVec = new Vec3f();
- if (Math.abs(uvCoords.x()) > Math.abs(uvCoords.y())) {
- if (scaleAxes == SCALE_XY)
- scaleVec.setX(uvCoords.x());
- else if (scaleAxes == SCALE_YZ)
- scaleVec.setY(uvCoords.x());
- else
- scaleVec.setZ(uvCoords.x());
- } else {
- if (scaleAxes == SCALE_XY)
- scaleVec.setY(uvCoords.y());
- else if (scaleAxes == SCALE_YZ)
- scaleVec.setZ(uvCoords.y());
- else
- scaleVec.setX(uvCoords.y());
- }
- scaleVec.setX(scaleVec.x() / geometryScale.x());
- scaleVec.setY(scaleVec.y() / geometryScale.y());
- scaleVec.setZ(scaleVec.z() / geometryScale.z());
- scale.add(origScale, scaleVec);
- // This shouldn't be necessary anymore
- /*
- if (scale.x() < 0)
- scale.setX(0);
- if (scale.y() < 0)
- scale.setY(0);
- if (scale.z() < 0)
- scale.setZ(0);
- */
- } else {
- if (Math.abs(uvCoords.x()) > Math.abs(uvCoords.y())) {
- if (scaleAxes == SCALE_XY)
- scale.setX(0);
- else if (scaleAxes == SCALE_YZ)
- scale.setY(0);
- else
- scale.setZ(0);
- } else {
- if (scaleAxes == SCALE_XY)
- scale.setY(0);
- else if (scaleAxes == SCALE_YZ)
- scale.setZ(0);
- else
- scale.setX(0);
- }
- }
- recalc();
- }
- } else {
- throw new RuntimeException("HandleBoxManip::drag: ERROR: Unexpected drag state");
- }
- super.drag(rayStart, rayDirection);
- }
-
- public void makeInactive() {
- dragState = INACTIVE;
- for (Iterator iter = draggedGeometry.iterator(); iter.hasNext(); ) {
- ((ManipPart) iter.next()).clearHighlight();
- }
- draggedGeometry.clear();
- }
-
- //----------------------------------------------------------------------
- // Internals only below this point
- //
-
- private void createGeometry() {
- ManipPartGroup group = new ManipPartGroup();
-
- //
- // Lines
- //
-
- // Top face:
- // Front line
- lineSegs[0] = createLineSeg(new Vec3f(0, 1, 1),
- new Vec3f(1, 0, 0),
- new Vec3f(0, 1, 0));
- // Left line
- lineSegs[1] = createLineSeg(new Vec3f(-1, 1, 0),
- new Vec3f(0, 0, 1),
- new Vec3f(0, 1, 0));
- // Back line
- lineSegs[2] = createLineSeg(new Vec3f(0, 1, -1),
- new Vec3f(1, 0, 0),
- new Vec3f(0, 1, 0));
- // Right line
- lineSegs[3] = createLineSeg(new Vec3f(1, 1, 0),
- new Vec3f(0, 0, 1),
- new Vec3f(0, 1, 0));
- // Middle segments:
- // Front left
- lineSegs[4] = createLineSeg(new Vec3f(-1, 0, 1),
- new Vec3f(0, -1, 0),
- new Vec3f(1, 0, 0));
- // Back left
- lineSegs[5] = createLineSeg(new Vec3f(-1, 0, -1),
- new Vec3f(0, -1, 0),
- new Vec3f(1, 0, 0));
- // Back right
- lineSegs[6] = createLineSeg(new Vec3f(1, 0, -1),
- new Vec3f(0, -1, 0),
- new Vec3f(1, 0, 0));
- // Front right
- lineSegs[7] = createLineSeg(new Vec3f(1, 0, 1),
- new Vec3f(0, -1, 0),
- new Vec3f(1, 0, 0));
- // Bottom face:
- // Front line
- lineSegs[8] = createLineSeg(new Vec3f(0, -1, 1),
- new Vec3f(1, 0, 0),
- new Vec3f(0, 1, 0));
- // Left line
- lineSegs[9] = createLineSeg(new Vec3f(-1, -1, 0),
- new Vec3f(0, 0, 1),
- new Vec3f(0, 1, 0));
- // Back line
- lineSegs[10] = createLineSeg(new Vec3f(0, -1, -1),
- new Vec3f(1, 0, 0),
- new Vec3f(0, 1, 0));
- // Right line
- lineSegs[11] = createLineSeg(new Vec3f(1, -1, 0),
- new Vec3f(0, 0, 1),
- new Vec3f(0, 1, 0));
-
- for (int i = 0; i < 12; i++) {
- group.addChild(lineSegs[i]);
- }
-
- //
- // Faces
- //
-
- // Front face (index 0)
- FaceInfo info = new FaceInfo();
- info.origNormal.set(0, 0, 1);
- info.centerSquare =
- createFace(info.origNormal, info.origNormal, new Vec3f(0, 1, 0));
- info.lineSegs[0] = lineSegs[0];
- info.lineSegs[1] = lineSegs[4];
- info.lineSegs[2] = lineSegs[7];
- info.lineSegs[3] = lineSegs[8];
- info.scaleAxes = SCALE_XY;
- faces.add(info);
- // Right face (index 1)
- info = new FaceInfo();
- info.origNormal.set(1, 0, 0);
- info.centerSquare =
- createFace(info.origNormal, info.origNormal, new Vec3f(0, 1, 0));
- info.lineSegs[0] = lineSegs[3];
- info.lineSegs[1] = lineSegs[6];
- info.lineSegs[2] = lineSegs[7];
- info.lineSegs[3] = lineSegs[11];
- info.scaleAxes = SCALE_YZ;
- faces.add(info);
- // Back face (index 2)
- info = new FaceInfo();
- info.origNormal.set(0, 0, -1);
- info.centerSquare =
- createFace(info.origNormal, info.origNormal, new Vec3f(0, 1, 0));
- info.lineSegs[0] = lineSegs[2];
- info.lineSegs[1] = lineSegs[5];
- info.lineSegs[2] = lineSegs[6];
- info.lineSegs[3] = lineSegs[10];
- info.scaleAxes = SCALE_XY;
- faces.add(info);
- // Left face (index 3)
- info = new FaceInfo();
- info.origNormal.set(-1, 0, 0);
- info.centerSquare =
- createFace(info.origNormal, info.origNormal, new Vec3f(0, 1, 0));
- info.lineSegs[0] = lineSegs[1];
- info.lineSegs[1] = lineSegs[4];
- info.lineSegs[2] = lineSegs[5];
- info.lineSegs[3] = lineSegs[9];
- info.scaleAxes = SCALE_YZ;
- faces.add(info);
- // Top face (index 4)
- info = new FaceInfo();
- info.origNormal.set(0, 1, 0);
- info.centerSquare =
- createFace(info.origNormal, info.origNormal, new Vec3f(0, 0, -1));
- info.lineSegs[0] = lineSegs[0];
- info.lineSegs[1] = lineSegs[1];
- info.lineSegs[2] = lineSegs[2];
- info.lineSegs[3] = lineSegs[3];
- info.scaleAxes = SCALE_ZX;
- faces.add(info);
- // Bottom face (index 5)
- info = new FaceInfo();
- info.origNormal.set(0, -1, 0);
- info.centerSquare =
- createFace(info.origNormal, info.origNormal, new Vec3f(0, 0, 1));
- info.lineSegs[0] = lineSegs[8];
- info.lineSegs[1] = lineSegs[9];
- info.lineSegs[2] = lineSegs[10];
- info.lineSegs[3] = lineSegs[11];
- info.scaleAxes = SCALE_ZX;
- faces.add(info);
-
- for (Iterator iter = faces.iterator(); iter.hasNext(); ) {
- group.addChild(((FaceInfo) iter.next()).centerSquare);
- }
-
- //
- // Rotation handles
- //
-
- // Front handle. Rotates about top/bottom and left/right faces.
- // Maintain references to top and right faces.
- RotateHandleInfo rotInfo = new RotateHandleInfo();
- rotInfo.faceIdx0 = 4;
- rotInfo.faceIdx1 = 1;
- rotInfo.geometry = createRotateHandle(new Vec3f(0, 0, 1));
- rotateHandles.add(rotInfo);
- // Right handle. Rotates about top/bottom and front/back faces.
- // Maintain references to top and front faces.
- rotInfo = new RotateHandleInfo();
- rotInfo.faceIdx0 = 4;
- rotInfo.faceIdx1 = 0;
- rotInfo.geometry = createRotateHandle(new Vec3f(1, 0, 0));
- rotateHandles.add(rotInfo);
- // Back handle. Rotates about top/bottom and left/right faces.
- // Maintain references to top and right faces.
- rotInfo = new RotateHandleInfo();
- rotInfo.faceIdx0 = 4;
- rotInfo.faceIdx1 = 1;
- rotInfo.geometry = createRotateHandle(new Vec3f(0, 0, -1));
- rotateHandles.add(rotInfo);
- // Left handle. Rotates about top/bottom and front/back faces.
- // Maintain references to top and front faces.
- rotInfo = new RotateHandleInfo();
- rotInfo.faceIdx0 = 4;
- rotInfo.faceIdx1 = 0;
- rotInfo.geometry = createRotateHandle(new Vec3f(-1, 0, 0));
- rotateHandles.add(rotInfo);
- // Top handle. Rotates about front/back and left/right faces.
- // Maintain references to front and right faces.
- rotInfo = new RotateHandleInfo();
- rotInfo.faceIdx0 = 0;
- rotInfo.faceIdx1 = 1;
- rotInfo.geometry = createRotateHandle(new Vec3f(0, 1, 0));
- rotateHandles.add(rotInfo);
- // Bottom handle. Rotates about front/back and left/right faces.
- // Maintain references to front and right faces.
- rotInfo = new RotateHandleInfo();
- rotInfo.faceIdx0 = 0;
- rotInfo.faceIdx1 = 1;
- rotInfo.geometry = createRotateHandle(new Vec3f(0, -1, 0));
- rotateHandles.add(rotInfo);
-
- for (Iterator iter = rotateHandles.iterator(); iter.hasNext(); ) {
- group.addChild(((RotateHandleInfo) iter.next()).geometry);
- }
-
- // Scale handles
- // Top right front (order: front right top)
- ScaleHandleInfo scaleInfo = new ScaleHandleInfo();
- scaleInfo.geometry = createScaleHandle(new Vec3f(1, 1, 1));
- scaleInfo.faceIndices[0] = 0;
- scaleInfo.faceIndices[1] = 1;
- scaleInfo.faceIndices[2] = 4;
- scaleHandles.add(scaleInfo);
- // Top right back (order: right back top)
- scaleInfo = new ScaleHandleInfo();
- scaleInfo.geometry = createScaleHandle(new Vec3f(1, 1, -1));
- scaleInfo.faceIndices[0] = 1;
- scaleInfo.faceIndices[1] = 2;
- scaleInfo.faceIndices[2] = 4;
- scaleHandles.add(scaleInfo);
- // Bottom right front (order: front right bottom)
- scaleInfo = new ScaleHandleInfo();
- scaleInfo.geometry = createScaleHandle(new Vec3f(1, -1, 1));
- scaleInfo.faceIndices[0] = 0;
- scaleInfo.faceIndices[1] = 1;
- scaleInfo.faceIndices[2] = 5;
- scaleHandles.add(scaleInfo);
- // Bottom right back (order: right back bottom)
- scaleInfo = new ScaleHandleInfo();
- scaleInfo.geometry = createScaleHandle(new Vec3f(1, -1, -1));
- scaleInfo.faceIndices[0] = 1;
- scaleInfo.faceIndices[1] = 2;
- scaleInfo.faceIndices[2] = 5;
- scaleHandles.add(scaleInfo);
- // Top left front (order: front left top)
- scaleInfo = new ScaleHandleInfo();
- scaleInfo.geometry = createScaleHandle(new Vec3f(-1, 1, 1));
- scaleInfo.faceIndices[0] = 0;
- scaleInfo.faceIndices[1] = 3;
- scaleInfo.faceIndices[2] = 4;
- scaleHandles.add(scaleInfo);
- // Top left back (order: back left top)
- scaleInfo = new ScaleHandleInfo();
- scaleInfo.geometry = createScaleHandle(new Vec3f(-1, 1, -1));
- scaleInfo.faceIndices[0] = 2;
- scaleInfo.faceIndices[1] = 3;
- scaleInfo.faceIndices[2] = 4;
- scaleHandles.add(scaleInfo);
- // Bottom left front (order: front left bottom)
- scaleInfo = new ScaleHandleInfo();
- scaleInfo.geometry = createScaleHandle(new Vec3f(-1, -1, 1));
- scaleInfo.faceIndices[0] = 0;
- scaleInfo.faceIndices[1] = 3;
- scaleInfo.faceIndices[2] = 5;
- scaleHandles.add(scaleInfo);
- // Bottom left back (order: back left bottom)
- scaleInfo = new ScaleHandleInfo();
- scaleInfo.geometry = createScaleHandle(new Vec3f(-1, -1, -1));
- scaleInfo.faceIndices[0] = 2;
- scaleInfo.faceIndices[1] = 3;
- scaleInfo.faceIndices[2] = 5;
- scaleHandles.add(scaleInfo);
-
- for (Iterator iter = scaleHandles.iterator(); iter.hasNext(); ) {
- group.addChild(((ScaleHandleInfo) iter.next()).geometry);
- }
-
- parts = group;
- }
-
- private ManipPart createLineSeg(Vec3f translation,
- Vec3f xAxis,
- Vec3f yAxis) {
- ManipPartTransform xform = new ManipPartTransform();
- ManipPartLineSeg lineSeg = new ManipPartLineSeg();
- xform.addChild(lineSeg);
- Mat4f offset = new Mat4f();
- offset.makeIdent();
- Vec3f zAxis = new Vec3f();
- zAxis.cross(xAxis, yAxis);
- offset.set(0, 0, xAxis.x());
- offset.set(1, 0, xAxis.y());
- offset.set(2, 0, xAxis.z());
- offset.set(0, 1, yAxis.x());
- offset.set(1, 1, yAxis.y());
- offset.set(2, 1, yAxis.z());
- offset.set(0, 2, zAxis.x());
- offset.set(1, 2, zAxis.y());
- offset.set(2, 2, zAxis.z());
- offset.set(0, 3, translation.x());
- offset.set(1, 3, translation.y());
- offset.set(2, 3, translation.z());
- xform.setOffsetTransform(offset);
- return xform;
- }
-
- private ManipPart createFace(Vec3f translation,
- Vec3f normal,
- Vec3f up) {
- ManipPartTransform xform = new ManipPartTransform();
- ManipPartSquare square = new ManipPartSquare();
- square.setVisible(false);
- xform.addChild(square);
- Mat4f offset = new Mat4f();
- offset.makeIdent();
- Vec3f right = new Vec3f();
- right.cross(up, normal);
- offset.set(0, 0, right.x());
- offset.set(1, 0, right.y());
- offset.set(2, 0, right.z());
- offset.set(0, 1, up.x());
- offset.set(1, 1, up.y());
- offset.set(2, 1, up.z());
- offset.set(0, 2, normal.x());
- offset.set(1, 2, normal.y());
- offset.set(2, 2, normal.z());
- offset.set(0, 3, translation.x());
- offset.set(1, 3, translation.y());
- offset.set(2, 3, translation.z());
- xform.setOffsetTransform(offset);
- return xform;
- }
-
- private ManipPart createRotateHandle(Vec3f direction) {
- ManipPartCube handle = new ManipPartCube();
- Mat4f offset = new Mat4f();
- offset.makeIdent();
- offset.set(0, 0, 0.1f);
- offset.set(1, 1, 0.1f);
- offset.set(2, 2, 0.1f);
- Vec3f scaledDirection = new Vec3f(direction);
- scaledDirection.scale(2.0f);
- offset.setTranslation(scaledDirection);
- ManipPartTransform xform = new ManipPartTransform();
- xform.addChild(handle);
- xform.setOffsetTransform(offset);
- return xform;
- }
-
- private ManipPart createScaleHandle(Vec3f position) {
- ManipPartCube handle = new ManipPartCube();
- Mat4f offset = new Mat4f();
- offset.makeIdent();
- offset.set(0, 0, 0.1f);
- offset.set(1, 1, 0.1f);
- offset.set(2, 2, 0.1f);
- offset.setTranslation(position);
- ManipPartTransform xform = new ManipPartTransform();
- xform.addChild(handle);
- xform.setOffsetTransform(offset);
- return xform;
- }
-
- private void recalc() {
- // Construct local to world transform for geometry.
- // Scale, Rotation, Translation. Since we're right multiplying
- // column vectors, the actual matrix composed is TRS.
- Mat4f scaleMat = new Mat4f();
- Mat4f rotMat = new Mat4f();
- Mat4f xlateMat = new Mat4f();
- Mat4f tmpMat = new Mat4f();
- scaleMat.makeIdent();
- scaleMat.set(0, 0, scale.x() * geometryScale.x());
- scaleMat.set(1, 1, scale.y() * geometryScale.y());
- scaleMat.set(2, 2, scale.z() * geometryScale.z());
- rotMat.makeIdent();
- rotMat.setRotation(rotation);
- xlateMat.makeIdent();
- xlateMat.set(0, 3, translation.x());
- xlateMat.set(1, 3, translation.y());
- xlateMat.set(2, 3, translation.z());
- tmpMat.mul(xlateMat, rotMat);
- xform.mul(tmpMat, scaleMat);
- int i;
- for (i = 0; i < 12; i++) {
- lineSegs[i].setTransform(xform);
- }
- for (i = 0; i < faces.size(); i++) {
- FaceInfo face = (FaceInfo) faces.get(i);
- face.centerSquare.setTransform(xform);
- xform.xformDir(face.origNormal, face.normal);
- face.normal.normalize();
-
- RotateHandleInfo rotInfo = (RotateHandleInfo) rotateHandles.get(i);
- rotInfo.geometry.setTransform(xform);
- }
- for (i = 0; i < scaleHandles.size(); i++) {
- ((ScaleHandleInfo) scaleHandles.get(i)).geometry.setTransform(xform);
- }
- }
-}