/*
|
* 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.*;
|
|
/**
|
* <p>Bones define a skeleton that is linked to a SmoothMesh. By repositioning the
|
* bone joins, one can deform it's associated mesh.</p>
|
*
|
* <p>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.</p>
|
*
|
* <p>A single bone transforms points from the local bind coordinate system (static mesh)
|
* to the local target coordinated system (animated mesh). Given:</p>
|
* <ul>
|
* <li/>ltp - local target point
|
* <li/>lbp - local bind point
|
* <li/>B - bind matrix
|
* <li/>A - current joint orientation matrix
|
* </ul>
|
*
|
* <p>then <code>ltp = A B^-1 lbp</code></p>
|
*
|
*
|
* <p>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</p>
|
*
|
* <code>M = A(0) B^-1(0) ... A(n - 1) B^-1(n - 1) A(n) B^-1(n)</code>
|
*
|
* <p>The position of the final animated mesh is a weighted sum over all bones.</p>
|
*
|
* <code>
|
* tp = 0 <br/>
|
* foreach (joint j) <br/>
|
* { <br/>
|
* tp += w(bp, j) * M(j) * bp <br/>
|
* } <br/>
|
* </code>
|
*
|
* <p>where
|
* <ul>
|
* <li/>bp - bind point
|
* <li/>M(j) - transform of bone j
|
* <li/>w(bp, j) - weight for point bp on bone j
|
* </ul>
|
* </p>
|
*
|
* @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<Bone> children = new Vector<Bone>();
|
|
/** 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;
|
}
|
*/
|
}
|