package mocap.figure; import java.util.ArrayList; import java.util.List; import javax.media.j3d.BranchGroup; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.vecmath.Point3d; import javax.vecmath.Vector3d; import j3d.Util; import mocap.player.MocapPlayer; /** * Represents an autonomous graphical figure. Contains the skeleton and * its own player (= motor). * * @author Michael Kipp */ public class Figure { private String _name; private Bone _skeleton; // root bone of skeleton private MocapPlayer _player; // drives animation private Point3d _offset; private BranchGroup _branchGroup; // scenegraph root private TransformGroup _tg; // can be used to give a base orientation /** * Creates a new figure and initializes the skeleton. * * @param name * ID of the figure * @param skeleton * Root bone of the skeleton */ public Figure(String name, Bone skeleton) { _name = name; _skeleton = skeleton; _branchGroup = new BranchGroup(); _branchGroup.setCapability(BranchGroup.ALLOW_DETACH); _tg = new TransformGroup(); _tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); _tg.addChild(_skeleton.getBaseTG()); _branchGroup.addChild(_tg); _branchGroup.compile(); } public double getScale() { return _skeleton.getScale(); } /** * Measures the length of the skeleton by computing the max. distance between any two leaves in * the skeleton tree. Figure must be LIVE to allow this operation. */ public double measureLength() { List leaves = new ArrayList(); List all = new ArrayList(); _skeleton.collectBones(all); for (Bone b : all) { if (b.getChildren().length == 0) { leaves.add(b); } } double dist = 0; Point3d p1 = new Point3d(); Point3d p2 = new Point3d(); for (Bone b1 : leaves) { for (Bone b2 : leaves) { if (!b1.equals(b2)) { b1.getWorldPosition(p1); b2.getWorldPosition(p2); dist = Math.max(p1.distance(p2), dist); } } } System.out.println("### LENGTH IS " + dist); return dist; } /** * For motion data where the skeleton head point up the z-axis, use this transformation (reset * with resetRotation). */ // public void correctUpVector(Vector3d rotationAxis, double angle) // { // Transform3D t1 = new Transform3D(); // Transform3D t2 = new Transform3D(); // t1.rotX(-Math.PI / 2d); // t2.rotY(-Math.PI / 2d); // t2.mul(t1); // _tg.setTransform(t2); // } /** * For motion data where the skeleton head point up the z-axis, use this transformation (reset * with resetRotation). */ public void setZUpRotation() { Transform3D t2 = new Transform3D(); t2.rotX(-Math.PI / 2d); _tg.setTransform(t2); } /** * For motion data where the skeleton head point up the x-axis, use this transformation (reset * with resetRotation). */ public void setXUpRotation() { Transform3D t2 = new Transform3D(); t2.rotZ(Math.PI / 2d); _tg.setTransform(t2); } public void resetRotation() { _tg.setTransform(new Transform3D()); } public boolean hasAnimation() { return _player != null; } public String getName() { return _name; } public MocapPlayer getPlayer() { return _player; } public Bone getSkeleton() { return _skeleton; } public void setBG(BranchGroup bg) { _branchGroup = bg; } /** * Point in the scene graph where this skeleton is attached. */ public BranchGroup getBG() { return _branchGroup; } public void setAnimation(AnimData data) { _player = new MocapPlayer(_skeleton, data, _offset); _player.setPlaybackFps(data.getFps()); } public void setOffset(Point3d p) { _offset = p; } }