diff options
Diffstat (limited to 'src/gleem/HandleBoxManip.java')
-rw-r--r-- | src/gleem/HandleBoxManip.java | 948 |
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); - } - } -} |