/* * Bone.java * * * The Salamander Project - 2D and 3D graphics libraries in Java * Copyright (C) 2004 Mark McKay * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Mark McKay can be contacted at mark@kitfox.com. Salamander and other * projects can be found at http://www.kitfox.com * * Created on March 10, 2004, 8:54 AM */ import javax.media.j3d.*; //import javax.vecmath.*; import java.util.*; /** *

Bones define a skeleton that is linked to a SmoothMesh. By repositioning the * bone joins, one can deform it's associated mesh.

* *

A bone coordinate system can be thought of as similar to a regular TransformGroup * hierarchy within the scene graph, with the exception that mesh verticies are * transformed instead of instanced geometry and that a vertex can be influenced * by more than one bone. To transform a mesh from it's bind pose (starting position) * to it's animated pose, you need to perform a weighted sum of the effects that * each bone contributes to the point.

* *

A single bone transforms points from the local bind coordinate system (static mesh) * to the local target coordinated system (animated mesh). Given:

* * *

then ltp = A B^-1 lbp

* * *

To determine the true transformation a bone contributes to a point, one must * take into account the transformations of it's parents too. So if this bone * is at level n and n - p indicates it's pth parent, then the true * transformation matrix is

* * M = A(0) B^-1(0) ... A(n - 1) B^-1(n - 1) A(n) B^-1(n) * *

The position of the final animated mesh is a weighted sum over all bones.

* * * tp = 0
* foreach (joint j)
* {
* tp += w(bp, j) * M(j) * bp
* }
*
* *

where *

*

* * @author kitfox */ public class Bone extends TransformGroup { /** Bind transfrom of this bone */ final Transform3D bindXform = new Transform3D(); /** Inverse bind transfrom of this bone */ final Transform3D bindInvXform = new Transform3D(); /** Current local pose position of this bone */ final Transform3D animXform = new Transform3D(); final Vector children = new Vector(); /** Creates a new instance of Bone */ public Bone(Transform3D bind) { super(bind); bindXform.set(bind); bindInvXform.invert(bind); animXform.set(bind); setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); } /** * Adds a child bone to this one. * @return - index of added child */ public int addChildBone(Bone child) { if (children.contains(child)) return children.indexOf(child); super.addChild(child); children.add(child); return children.size() - 1; } public void addChild(Node child) { if (child instanceof Bone) { addChildBone((Bone)child); } else super.addChild(child); } public int getNumChildBones() { return children.size(); } public Bone getChildBone(int idx) { return (Bone)children.get(idx); } /** * Returns cached bone xform. Do not write to this matrix! Instead, call * setTransform to update this bone's orientation */ public void getTransform(Transform3D xform) { xform.set(animXform); } public void getBindTransform(Transform3D xform) { xform.set(bindXform); } /** * Updates the animated local transformation of this bone */ public void setTransform(Transform3D xform) { super.setTransform(xform); animXform.set(xform); // sceneXformDirty = true; } public void setToBindTransform() { super.setTransform(bindXform); animXform.set(bindXform); // sceneXformDirty = true; } public Node cloneNode(boolean forceDuplicate) { Bone bone = new Bone(bindXform); bone.duplicateNode(this, forceDuplicate); return bone; } /* public void duplicateNode(Node originalNode, boolean forceDuplicate) { Bone src = (Bone)originalNode; } */ }