com.jme.animation
Class SkinNode

java.lang.Object
  extended by com.jme.scene.Spatial
      extended by com.jme.scene.Node
          extended by com.jme.animation.SkinNode
All Implemented Interfaces:
BoneChangeListener, Savable, java.io.Serializable
Direct Known Subclasses:
SkinTransferNode

public class SkinNode
extends Node
implements Savable, BoneChangeListener

SkinNode defines a scene node that contains skinned mesh data. A skinned mesh is defined by a Geometry object representing the "skin" that is attached to a skeleton (or a tree of Bones). The orientation, translation of these bones define the position of the skin vertices. These bones can then be driven by an animation system to provide the animation of the skin. SkinNode defines for each vertex of the skin the bone that affects it and the weight (BoneInfluence) of that affect. This allows multiple bones to share a single vertex (although the total weight must add up to 1).

One of the removeSkinGeometry methods should be used to remove skins. Simply detaching a skin from the scene may result in a memory leak, since the bone influences for that skin will be retained.

The 'skins' Node of a SkinNode should only parent Geometries. Do not parent it to anything else.

Author:
Joshua Slack, Mark Powell
See Also:
Serialized Form

Nested Class Summary
 
Nested classes/interfaces inherited from class com.jme.scene.Spatial
Spatial.CullHint, Spatial.LightCombineMode, Spatial.NormalsMode, Spatial.TextureCombineMode
 
Field Summary
protected  Matrix4f bindMatrix
           
protected  java.util.ArrayList<BoneInfluence>[][] cache
           
protected  java.util.ArrayList<ConnectionPoint> connectionPoints
           
protected  StringStringMap geometryRegions
          We use a String key so that this structure won't delay garbage collection.
protected  boolean needsRefresh
           
protected  boolean newSkeletonAssigned
           
protected  Vector3f normal
           
protected  Bone skeleton
           
protected  Node skins
           
protected  Vector3f vertex
           
 
Fields inherited from class com.jme.scene.Node
children
 
Fields inherited from class com.jme.scene.Spatial
collisionBits, cullHint, frustrumIntersects, geometricalControllers, lightCombineMode, localRotation, localScale, localTranslation, LOCKED_BOUNDS, LOCKED_BRANCH, LOCKED_MESH_DATA, LOCKED_NONE, LOCKED_SHADOWS, LOCKED_TRANSFORMS, lockedMode, name, normalsMode, parent, queueDistance, renderQueueMode, renderStateList, textureCombineMode, worldBound, worldRotation, worldScale, worldTranslation, zOrder
 
Constructor Summary
SkinNode()
          Empty Constructor to be used internally only.
SkinNode(java.lang.String name)
          Constructor creates a new SkinNode object with the supplied name.
 
Method Summary
 void addBoneInfluence(int geomIndex, int vert, Bone bone, float weight)
          addBoneInfluence defines how a vertex will be affected by a bone.
 void addBoneInfluence(int geomIndex, int vert, java.lang.String boneId, float weight)
           
 ConnectionPoint addConnectionPoint(java.lang.String name, Bone b)
           
 void addSkin(Geometry skin)
          addSkins sets the skin that the SkinNode will affect.
 void assignSkeletonBoneInfluences()
          Assigns Bone instance references to BoneInfluences, by looking up the boneId names.
 void assignSkeletonBoneInfluences(Geometry skinGeo)
          Assigns Bone instance references for one specific skin Geometry.
protected  void assignSkeletonBoneInfluences(int i)
           
protected  void assimilate(Geometry newSkinGeo, java.util.ArrayList<BoneInfluence>[] newInfluences, java.lang.String skinRegion)
           
 void assimilate(SkinNode otherSkinNode)
          Assimilate all skin Geometries from the specified 'otherSkinNode', leaving this other SkinNode castrated.
 void assimilate(SkinNode otherSkinNode, java.lang.String geoNameRegex)
          Assimilates the specified skin mesh Geometries from the specified 'otherSkinNode' into this one, removing them from 'otherSkinNode'.
 void boneChanged(BoneChangeEvent e)
          Invoked when the target of the listener has changed bone status.
 void childChange(Geometry geometry, int index1, int index2)
           
protected  void cullRegionMappings()
          We can't control how skin Geometries are removed, so we must cull unused region mappings before we use it.
 int deassimilate(java.lang.String skinRegion)
          Remove specified skin Geometries, including associated BoneInfluences.
 java.lang.String getAnimationString()
           
 java.util.ArrayList<BoneInfluence>[][] getCache()
           
 java.util.ArrayList<ConnectionPoint> getConnectionPoints()
           
 int getInfluenceCount(int geomIndex)
           
 Bone getSkeleton()
           
 Geometry getSkin(int i)
          Returns a typed skin Geometry.
 Node getSkins()
          getSkin returns the skins (Geometry objects) that the SkinNode is currently controlling.
 boolean hasSkinGeometry(java.lang.String geoName, java.lang.String skinRegion)
           
 boolean isExternalControl()
           
 void normalizeWeights()
          normalizeWeights insures that all vertex BoneInfluences equal 1.
 void normalizeWeights(int geomIndex)
           
 void pose(int frameNum)
          Stops the current animation and poses the skins to the static pose of the specified and frame.
 void pose(java.lang.String frameName)
          Stops the current animation and poses the skins to the static pose of the specified and frame.
 void pose(java.lang.String animationName, int frameNum)
          Stops any running animation and poses the skins to the static pose of the specified animation and frame.
 void pose(java.lang.String animationName, java.lang.String frameName)
          Stops any running animation and poses the skins to the static pose of the specified animation and frame.
 void read(JMEImporter e)
           
 void recreateCache()
          recreateCache initializes the cache of BoneInfluences for use by the skin node.
 void regenInfluenceOffsets()
          regenInfluenceOffsets calculate the offset of a particular vertex from a bone.
 void regenInfluenceOffsets(Geometry skinGeo)
          Regenerates the offsets for one specific skin Geometry.
protected  void regenInfluenceOffsets(int index)
           
 void remapInfluences(VertMap[] mappings)
           
 void remapInfluences(VertMap mappings, int geomIndex)
           
 void removeGeometry(int geomIndex)
          This method DOES NOT REMOVE THE Geometry.
 int removeSkinGeometries()
          Remove all skin Geometries, including associated BoneInfluences.
 Geometry removeSkinGeometry(int i)
          Detaches a skin mesh from the SkinNode, removing the associated BoneInfluences along with it.
 Geometry removeSkinGeometry(java.lang.String geoName)
          Detaches the named skin mesh from the SkinNode, removing the associated BoneInfluences along with it.
 void revertToBind()
           
 void setAnimation(BoneAnimation anim)
           
 void setAnimation(int index)
           
 void setAnimation(java.lang.String name)
           
 void setBindMatrix(Matrix4f mat)
           
 void setCache(java.util.ArrayList<BoneInfluence>[][] cache)
           
 void setExternalControl(boolean externalControl)
           
 void setSkeleton(Bone b)
           
 void setSkinRegion(Geometry skinGeometry, java.lang.String skinRegion)
          Use this to assign a skin region for a specific skin geometry.
 void setSkins(Node skins)
          setSkin sets the skin that the SkinNode will affect.
 void updateGeometricState(float time, boolean initiator)
          updateGeometricState overrides Spatials updateGeometric state to update the assigned skeleton bone influences, if changed.
 void updateSkin()
          updateSkin positions the vertices of the skin based on the bones and the BoneInfluences those bones have on the vertices.
protected  void validateSkins()
          Validates that the 'skins' node is either null or contains only Geometry children.
 void write(JMEExporter e)
           
 
Methods inherited from class com.jme.scene.Node
applyRenderState, attachChild, attachChildAt, descendantMatches, descendantMatches, descendantMatches, detachAllChildren, detachChild, detachChildAt, detachChildNamed, draw, findCollisions, findPick, getChild, getChild, getChildIndex, getChildren, getQuantity, getTriangleCount, getVertexCount, hasChild, hasCollision, lockBounds, lockMeshes, lockShadows, lockTransforms, setModelBound, sortLights, swapChildren, unlockBounds, unlockMeshes, unlockShadows, unlockTransforms, updateModelBound, updateWorldBound, updateWorldData, updateWorldVectors
 
Methods inherited from class com.jme.scene.Spatial
addController, calculateCollisions, calculateCollisions, calculatePick, calculatePick, clearControllers, clearRenderState, clearRenderState, findCollisions, findPick, getClassTag, getCollisionMask, getController, getControllerCount, getControllers, getCullHint, getLastFrustumIntersection, getLightCombineMode, getLocalCullHint, getLocalLightCombineMode, getLocalNormalsMode, getLocalRenderQueueMode, getLocalRotation, getLocalScale, getLocalTextureCombineMode, getLocalToWorldMatrix, getLocalTranslation, getLocks, getName, getNormalsMode, getParent, getRenderQueueMode, getRenderState, getRenderState, getTextureCombineMode, getUserData, getWorldBound, getWorldRotation, getWorldScale, getWorldTranslation, getZOrder, hasAncestor, hasCollision, isCollidable, isCollidable, localToWorld, lock, lock, lockBranch, lockMeshes, lookAt, matches, matches, onDraw, propagateBoundToRoot, propagateStatesFromRoot, removeController, removeController, removeFromParent, removeUserData, rotateUpTo, setCollisionMask, setCullHint, setIsCollidable, setLastFrustumIntersection, setLightCombineMode, setLocalRotation, setLocalRotation, setLocalScale, setLocalScale, setLocalTranslation, setLocalTranslation, setLocks, setLocks, setName, setNormalsMode, setParent, setRenderQueueMode, setRenderState, setTextureCombineMode, setUserData, setZOrder, setZOrder, toString, unlock, unlock, unlockBranch, unlockMeshes, updateRenderState, updateRenderState, updateWorldRotation, updateWorldScale, updateWorldTranslation, updateWorldVectors, worldToLocal
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 
Methods inherited from interface com.jme.util.export.Savable
getClassTag
 

Field Detail

vertex

protected Vector3f vertex

normal

protected Vector3f normal

needsRefresh

protected boolean needsRefresh

skins

protected Node skins

skeleton

protected Bone skeleton

cache

protected java.util.ArrayList<BoneInfluence>[][] cache

connectionPoints

protected java.util.ArrayList<ConnectionPoint> connectionPoints

newSkeletonAssigned

protected transient boolean newSkeletonAssigned

bindMatrix

protected transient Matrix4f bindMatrix

geometryRegions

protected StringStringMap geometryRegions
We use a String key so that this structure won't delay garbage collection. Do not make this map public, since we update it lazily (only before we need to use it). See cullRegionMappings() about that.

Constructor Detail

SkinNode

public SkinNode()
Empty Constructor to be used internally only.


SkinNode

public SkinNode(java.lang.String name)
Constructor creates a new SkinNode object with the supplied name.

Parameters:
name - the name of this SkinNode
Method Detail

getSkins

public Node getSkins()
getSkin returns the skins (Geometry objects) that the SkinNode is currently controlling.

Returns:
the skins contained in this SkinNode

getSkin

public Geometry getSkin(int i)
Returns a typed skin Geometry.

Throws:
java.lang.RuntimeException - or Error subclass if 'skins' is null, if child not present, or is not a Geometry.

setSkins

public void setSkins(Node skins)
setSkin sets the skin that the SkinNode will affect.

Parameters:
skins - the skins that this SkinNode will affect.

validateSkins

protected void validateSkins()
Validates that the 'skins' node is either null or contains only Geometry children.

Throws:
java.lang.IllegalStateException - if 'skins' contains a non-Geometry child.

addSkin

public void addSkin(Geometry skin)
addSkins sets the skin that the SkinNode will affect.

Parameters:
skin - an additional skin that this SkinNode will affect.

addBoneInfluence

public void addBoneInfluence(int geomIndex,
                             int vert,
                             Bone bone,
                             float weight)
addBoneInfluence defines how a vertex will be affected by a bone. This is given with four values, the geometry child the vertex is found, the index to the vertex in the geometry, the index of the bone that has been or will be set via setBones or addBone and the weight that this indexed bone affects the vertex.

Parameters:
geomIndex - the geometry child that contains the vertex to be affected.
vert - the index to the vertex.
bone - the bone that affects the vertex.
weight - the weight that the bone will affect the vertex.

setAnimation

public void setAnimation(BoneAnimation anim)

setAnimation

public void setAnimation(int index)

setAnimation

public void setAnimation(java.lang.String name)

getAnimationString

public java.lang.String getAnimationString()

addBoneInfluence

public void addBoneInfluence(int geomIndex,
                             int vert,
                             java.lang.String boneId,
                             float weight)

addConnectionPoint

public ConnectionPoint addConnectionPoint(java.lang.String name,
                                          Bone b)

getConnectionPoints

public java.util.ArrayList<ConnectionPoint> getConnectionPoints()

recreateCache

public void recreateCache()
recreateCache initializes the cache of BoneInfluences for use by the skin node.


updateGeometricState

public void updateGeometricState(float time,
                                 boolean initiator)
updateGeometricState overrides Spatials updateGeometric state to update the assigned skeleton bone influences, if changed.

Overrides:
updateGeometricState in class Spatial
Parameters:
time - the time that has passed between calls.
initiator - true if this is the top level being called.

normalizeWeights

public void normalizeWeights()
normalizeWeights insures that all vertex BoneInfluences equal 1. The total BoneInfluence on a single vertex should be 1 otherwise the position of the vertex will be multiplied.


getInfluenceCount

public int getInfluenceCount(int geomIndex)

normalizeWeights

public void normalizeWeights(int geomIndex)

setSkeleton

public void setSkeleton(Bone b)

getSkeleton

public Bone getSkeleton()

assignSkeletonBoneInfluences

public void assignSkeletonBoneInfluences()
Assigns Bone instance references to BoneInfluences, by looking up the boneId names.


assignSkeletonBoneInfluences

public void assignSkeletonBoneInfluences(Geometry skinGeo)
Assigns Bone instance references for one specific skin Geometry.

See Also:
assignSkeletonBoneInfluences()

assignSkeletonBoneInfluences

protected void assignSkeletonBoneInfluences(int i)

regenInfluenceOffsets

public void regenInfluenceOffsets()
regenInfluenceOffsets calculate the offset of a particular vertex from a bone. This allows the bone's rotation to position the vertex in world space. This nees to be called only be called a single time during initialization (or when a Geometry's local vertex locations change).


regenInfluenceOffsets

public void regenInfluenceOffsets(Geometry skinGeo)
Regenerates the offsets for one specific skin Geometry.

See Also:
regenInfluenceOffsets()

regenInfluenceOffsets

protected void regenInfluenceOffsets(int index)

updateSkin

public void updateSkin()
updateSkin positions the vertices of the skin based on the bones and the BoneInfluences those bones have on the vertices. Each vertex is placed into world space for rendering.


getCache

public java.util.ArrayList<BoneInfluence>[][] getCache()

setCache

public void setCache(java.util.ArrayList<BoneInfluence>[][] cache)

setBindMatrix

public void setBindMatrix(Matrix4f mat)

childChange

public void childChange(Geometry geometry,
                        int index1,
                        int index2)
Overrides:
childChange in class Node

write

public void write(JMEExporter e)
           throws java.io.IOException
Specified by:
write in interface Savable
Overrides:
write in class Node
Throws:
java.io.IOException

read

public void read(JMEImporter e)
          throws java.io.IOException
Specified by:
read in interface Savable
Overrides:
read in class Node
Throws:
java.io.IOException

revertToBind

public void revertToBind()

boneChanged

public void boneChanged(BoneChangeEvent e)
Description copied from interface: BoneChangeListener
Invoked when the target of the listener has changed bone status.

Specified by:
boneChanged in interface BoneChangeListener
Parameters:
e - a ChangeEvent object

remapInfluences

public void remapInfluences(VertMap[] mappings)

remapInfluences

public void remapInfluences(VertMap mappings,
                            int geomIndex)

removeGeometry

public void removeGeometry(int geomIndex)
This method DOES NOT REMOVE THE Geometry. It just removes the Influences of the indicated Geometry.


setExternalControl

public void setExternalControl(boolean externalControl)

isExternalControl

public boolean isExternalControl()

assimilate

public void assimilate(SkinNode otherSkinNode)
Assimilate all skin Geometries from the specified 'otherSkinNode', leaving this other SkinNode castrated. Convenience wrapper for ALL skin geos. After running this method, you should remove 'otherSkinNode' from any scene graph it's attached to, unless you plan to add Geometry skin nodes to it again.

See Also:
assimilate(SkinNode, String)

assimilate

public void assimilate(SkinNode otherSkinNode,
                       java.lang.String geoNameRegex)
Assimilates the specified skin mesh Geometries from the specified 'otherSkinNode' into this one, removing them from 'otherSkinNode'. If otherSkinNode is a non-null-skinRegion SkinTransferNode and no narrowing regex is supplied, we will REPLACE all current Geometries with that same skinRegion.

For this first implementation, we have some rather stringent requirements. If use cases justify accommodating other states, these requirements can be relaxed with further development work.

This method will not succeed if the rest animation and rest pose frame have not been set in the AnimationController (unless no AnimationController has been assigned for this SkinNode yet).

IMPORTANT: The calling signature is tentative. It's likely that checked exceptions will be added, so expect to need to update your exception-handling until this method has stabilized.

Parameters:
otherSkinNode - Node from which the Geometries and BoneInfluences will be taken.
geoNameRegex - To specify which Geometries to assimilate. Null to assimilate all skin Geometries from 'otherSkinNode'.
Throws:
java.lang.RuntimeException - for various state validation failures. This is easier to use, but not as robust. This is likely to change soon.

assimilate

protected void assimilate(Geometry newSkinGeo,
                          java.util.ArrayList<BoneInfluence>[] newInfluences,
                          java.lang.String skinRegion)

removeSkinGeometry

public Geometry removeSkinGeometry(java.lang.String geoName)
Detaches the named skin mesh from the SkinNode, removing the associated BoneInfluences along with it. Returns null if there is no such named skin Geometry attached.

See Also:
removeSkinGeometry(int)

hasSkinGeometry

public boolean hasSkinGeometry(java.lang.String geoName,
                               java.lang.String skinRegion)
Parameters:
skinRegion - null means match any (including no) skin region

removeSkinGeometry

public Geometry removeSkinGeometry(int i)
Detaches a skin mesh from the SkinNode, removing the associated BoneInfluences along with it. Unlike the removeGeometry method, this one really does remove the specified Geometry.

See Also:
removeGeometry(int)

removeSkinGeometries

public int removeSkinGeometries()
Remove all skin Geometries, including associated BoneInfluences.

Returns:
Number of Geometries removed. May be zero.

deassimilate

public int deassimilate(java.lang.String skinRegion)
Remove specified skin Geometries, including associated BoneInfluences.

Parameters:
skinRegion - All skin Geometries associated with this skinRegion name will be removed. IMPORTANT: null means to remove all skin Geometries, not just those with null skinRegion, nor just those added by assimilation. There is no method to remove just null skinRegion skins, since null means they should be managed obliviously to skinRegions.
Returns:
Number of Geometries removed. May be zero.

cullRegionMappings

protected void cullRegionMappings()
We can't control how skin Geometries are removed, so we must cull unused region mappings before we use it. Note that we never cull an entry unless the named Geometry is missing. We will not cull because the skin region has not been loaded, or if the indicated Geometry is not a SkinTransferNode Geometry (in both cases, we have no way of knowing).


setSkinRegion

public void setSkinRegion(Geometry skinGeometry,
                          java.lang.String skinRegion)
Use this to assign a skin region for a specific skin geometry. This is very useful both to change skin regions of geometries loaded from SkinTransferNodes, and also to assign skin regions to non-SkinTransferNode skin geometries (so that traditionally loaded Geometries can be automatically replaced by assimilations).

If the skinRegion for skinGeometry is already set to skin region, no harm done.

Parameters:
skinGeometry - Should already be a skin geometry of this SkinNode. If it isn't, it will have no effect and no indication will be given. (The entry will get lazily culled in the future).

pose

public void pose(int frameNum)
Stops the current animation and poses the skins to the static pose of the specified and frame.


pose

public void pose(java.lang.String frameName)
Stops the current animation and poses the skins to the static pose of the specified and frame.


pose

public void pose(java.lang.String animationName,
                 int frameNum)
Stops any running animation and poses the skins to the static pose of the specified animation and frame.


pose

public void pose(java.lang.String animationName,
                 java.lang.String frameName)
Stops any running animation and poses the skins to the static pose of the specified animation and frame.



Copyright 2003-2009 jMonkeyEngine