package mocap.figure; import javax.media.j3d.Appearance; import javax.media.j3d.LineArray; import javax.media.j3d.Shape3D; import javax.media.j3d.Switch; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.vecmath.AxisAngle4d; import javax.vecmath.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Vector3d; import com.sun.j3d.utils.geometry.Box; import com.sun.j3d.utils.geometry.Cylinder; import com.sun.j3d.utils.geometry.Sphere; /** * Actual geometry of the bone (various options). * * @author Michael Kipp */ public class BoneGeom implements java.io.Serializable { public static final int NONE = -1, LINE = 0, CYLINDER = 1, QUAD = 2; public static double CYLINDER_RADIUS = .1; private Switch _switch; //private Box _quad; private double _length; public BoneGeom(TransformGroup parent, Vector3d direction) { _length = direction.length(); TransformGroup tgRot = new TransformGroup(); tgRot.setTransform(computeRotation(direction)); _switch = new Switch(); _switch.setCapability(Switch.ALLOW_SWITCH_WRITE); // _switch.addChild(createLineLimb(_length)); TransformGroup cyl = createCylinder(CYLINDER_RADIUS, _length); // _switch.addChild(createQuad(_length)); _switch.setWhichChild(CYLINDER); parent.addChild(tgRot); // tgRot.addChild(_switch); tgRot.addChild(cyl); // _switch.addChild(cyl); } // public void detach() { // ((TransformGroup)_switch.getParent().getParent()).removeChild(_switch.getParent()); // } public double getLength() { return _length; } public void select(int style) { _switch.setWhichChild(style == NONE ? Switch.CHILD_NONE : style); } private TransformGroup createCylinder(double radius, double length) { Sphere c = new Sphere(1); //Cylinder c = new Cylinder((float) radius, (float) length); TransformGroup tg = new TransformGroup(); Transform3D tf = new Transform3D(); tf.setTranslation(new Vector3d(0, length / 2, 0)); tf.setScale(new Vector3d(radius*length, length/2, radius*length)); tg.setTransform(tf); tg.addChild(c); return tg; } // private TransformGroup createQuad(double length) // { // Box c = new Box(.2f, (float) length / 2, .2f, new Appearance()); // TransformGroup tg = new TransformGroup(); // Transform3D tf = new Transform3D(); // tf.setTranslation(new Vector3d(0, length / 2, 0)); // tg.setTransform(tf); // tg.addChild(c); // _quad = c; // _quad.setCapability(Box.ENABLE_APPEARANCE_MODIFY); // for (int i = 0; i < 6; i++) // { // _quad.getShape(i).setCapability(Shape3D.ALLOW_APPEARANCE_WRITE); // } // return tg; // } private Shape3D createLineLimb(double length) { LineArray line = new LineArray(2, LineArray.COORDINATES | LineArray.COLOR_3); line.setCoordinate(0, new Point3d(0, 0, 0)); line.setCoordinate(1, new Point3d(0, length, 0)); line.setColor(0, new Color3f(0, 0, 1)); line.setColor(1, new Color3f(0, 0, 1)); return new Shape3D(line); } protected void setSelected(boolean val) { // if (val) // { // _quad.setAppearance(JointAppearance.getSelectedInstance()); // } else // { // _quad.setAppearance(JointAppearance.getInstance()); // } } /** * Given a direction, computes the necessary rotation to let the y-axis * point in that direction. */ private Transform3D computeRotation(Vector3d direction) { Transform3D tf = new Transform3D(); double x2 = direction.x * direction.x; double z2 = direction.z * direction.z; if (x2 < .00001 && z2 < .00001) { if (direction.y < 0) { tf.rotX(Math.PI); } } else { Vector3d vec = new Vector3d(); vec.cross(new Vector3d(0d, 1d, 0d), new Vector3d(direction)); double angle = Math.asin(Math.sqrt(x2 + z2) / direction.length()); if (direction.y < 0) { angle = Math.PI - angle; } tf.setRotation(new AxisAngle4d(vec, angle)); } return tf; } }