use of com.jme3.scene.plugins.fbx.anim.FbxLimbNode in project jmonkeyengine by jMonkeyEngine.
the class FbxLoader method constructAnimations.
private void constructAnimations() {
// In FBX, animation are not attached to any root.
// They are implicitly global.
// So, we need to use hueristics to find which node(s)
// an animation is associated with, so we can create the AnimControl
// in the appropriate location in the scene.
Map<FbxToJmeTrack, FbxToJmeTrack> pairs = new HashMap<FbxToJmeTrack, FbxToJmeTrack>();
for (FbxAnimStack stack : animStacks) {
for (FbxAnimLayer layer : stack.getLayers()) {
for (FbxAnimCurveNode curveNode : layer.getAnimationCurveNodes()) {
for (Map.Entry<FbxNode, String> nodePropertyEntry : curveNode.getInfluencedNodeProperties().entrySet()) {
FbxToJmeTrack lookupPair = new FbxToJmeTrack();
lookupPair.animStack = stack;
lookupPair.animLayer = layer;
lookupPair.node = nodePropertyEntry.getKey();
// Find if this pair is already stored
FbxToJmeTrack storedPair = pairs.get(lookupPair);
if (storedPair == null) {
// If not, store it.
storedPair = lookupPair;
pairs.put(storedPair, storedPair);
}
String property = nodePropertyEntry.getValue();
storedPair.animCurves.put(property, curveNode);
}
}
}
}
// At this point we can construct the animation for all pairs ...
for (FbxToJmeTrack pair : pairs.values()) {
String animName = pair.animStack.getName();
float duration = pair.animStack.getDuration();
System.out.println("ANIMATION: " + animName + ", duration = " + duration);
System.out.println("NODE: " + pair.node.getName());
duration = pair.getDuration();
if (pair.node instanceof FbxLimbNode) {
// Find the spatial that has the skeleton for this limb.
FbxLimbNode limbNode = (FbxLimbNode) pair.node;
Bone bone = limbNode.getJmeBone();
Spatial jmeSpatial = limbNode.getSkeletonHolder().getJmeObject();
Skeleton skeleton = limbNode.getSkeletonHolder().getJmeSkeleton();
// Get the animation control (create if missing).
AnimControl animControl = jmeSpatial.getControl(AnimControl.class);
if (animControl.getSkeleton() != skeleton) {
throw new UnsupportedOperationException();
}
// Get the animation (create if missing).
Animation anim = animControl.getAnim(animName);
if (anim == null) {
anim = new Animation(animName, duration);
animControl.addAnim(anim);
}
// Find the bone index from the spatial's skeleton.
int boneIndex = skeleton.getBoneIndex(bone);
// Generate the bone track.
BoneTrack bt = pair.toJmeBoneTrack(boneIndex, bone.getBindInverseTransform());
// Add the bone track to the animation.
anim.addTrack(bt);
} else {
// Create the spatial animation
Animation anim = new Animation(animName, duration);
anim.setTracks(new Track[] { pair.toJmeSpatialTrack() });
// Get the animation control (create if missing).
Spatial jmeSpatial = pair.node.getJmeObject();
AnimControl animControl = jmeSpatial.getControl(AnimControl.class);
if (animControl == null) {
animControl = new AnimControl(null);
jmeSpatial.addControl(animControl);
}
// Add the spatial animation
animControl.addAnim(anim);
}
}
}
use of com.jme3.scene.plugins.fbx.anim.FbxLimbNode in project jmonkeyengine by jMonkeyEngine.
the class FbxMesh method applyCluster.
public void applyCluster(FbxCluster cluster) {
if (boneIndices == null) {
boneIndices = new ArrayList[positions.length];
boneWeights = new ArrayList[positions.length];
}
FbxLimbNode limb = cluster.getLimb();
Bone bone = limb.getJmeBone();
Skeleton skeleton = limb.getSkeletonHolder().getJmeSkeleton();
int boneIndex = skeleton.getBoneIndex(bone);
int[] positionIndices = cluster.getVertexIndices();
double[] weights = cluster.getWeights();
for (int i = 0; i < positionIndices.length; i++) {
int positionIndex = positionIndices[i];
float boneWeight = (float) weights[i];
ArrayList<Integer> boneIndicesForVertex = boneIndices[positionIndex];
ArrayList<Float> boneWeightsForVertex = boneWeights[positionIndex];
if (boneIndicesForVertex == null) {
boneIndicesForVertex = new ArrayList<Integer>();
boneWeightsForVertex = new ArrayList<Float>();
boneIndices[positionIndex] = boneIndicesForVertex;
boneWeights[positionIndex] = boneWeightsForVertex;
}
boneIndicesForVertex.add(boneIndex);
boneWeightsForVertex.add(boneWeight);
}
}
use of com.jme3.scene.plugins.fbx.anim.FbxLimbNode in project jmonkeyengine by jMonkeyEngine.
the class FbxNode method createScene.
public static Spatial createScene(FbxNode fbxNode) {
Spatial jmeSpatial = fbxNode.getJmeObject();
if (jmeSpatial instanceof Node) {
// Attach children to Node
Node jmeNode = (Node) jmeSpatial;
for (FbxNode fbxChild : fbxNode.children) {
if (!(fbxChild instanceof FbxLimbNode)) {
createScene(fbxChild);
FbxNode preferredParent = fbxChild.getPreferredParent();
Spatial jmeChild = fbxChild.getJmeObject();
if (preferredParent != null) {
System.out.println("Preferred parent for " + fbxChild + " is " + preferredParent);
Node jmePreferredParent = (Node) preferredParent.getJmeObject();
relocateSpatial(jmeChild, fbxChild.jmeWorldNodeTransform, preferredParent.jmeWorldNodeTransform);
jmePreferredParent.attachChild(jmeChild);
} else {
jmeNode.attachChild(jmeChild);
}
}
}
}
if (fbxNode.skeleton != null) {
jmeSpatial.addControl(new AnimControl(fbxNode.skeleton));
jmeSpatial.addControl(new SkeletonControl(fbxNode.skeleton));
SkeletonDebugger sd = new SkeletonDebugger("debug", fbxNode.skeleton);
Material mat = new Material(fbxNode.assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.getAdditionalRenderState().setWireframe(true);
mat.getAdditionalRenderState().setDepthTest(false);
mat.setColor("Color", ColorRGBA.Green);
sd.setMaterial(mat);
((Node) jmeSpatial).attachChild(sd);
}
return jmeSpatial;
}
use of com.jme3.scene.plugins.fbx.anim.FbxLimbNode in project jmonkeyengine by jMonkeyEngine.
the class FbxNode method getPreferredParent.
/**
* If this geometry node is deformed by a skeleton, this
* returns the node containing the skeleton.
*
* In jME3, a mesh can be deformed by a skeleton only if it is
* a child of the node containing the skeleton. However, this
* is not a requirement in FBX, so we have to modify the scene graph
* of the loaded model to adjust for this.
* This happens automatically in
* {@link #createScene(com.jme3.scene.plugins.fbx.node.FbxNode)}.
*
* @return The model this node would like to be a child of, or null
* if no preferred parent.
*/
public FbxNode getPreferredParent() {
if (!(nodeAttribute instanceof FbxMesh)) {
return null;
}
FbxMesh fbxMesh = (FbxMesh) nodeAttribute;
FbxSkinDeformer deformer = fbxMesh.getSkinDeformer();
FbxNode preferredParent = null;
if (deformer != null) {
for (FbxCluster cluster : deformer.getJmeObject()) {
FbxLimbNode limb = cluster.getLimb();
if (preferredParent == null) {
preferredParent = limb.getSkeletonHolder();
} else if (preferredParent != limb.getSkeletonHolder()) {
logger.log(Level.WARNING, "A mesh is being deformed by multiple skeletons. " + "Only one skeleton will work, ignoring other skeletons.");
}
}
}
return preferredParent;
}
use of com.jme3.scene.plugins.fbx.anim.FbxLimbNode in project jmonkeyengine by jMonkeyEngine.
the class FbxLimbNode method createBones.
private static void createBones(FbxNode skeletonHolderNode, FbxLimbNode limb, List<Bone> bones) {
limb.skeletonHolder = skeletonHolderNode;
Bone parentBone = limb.getJmeBone();
bones.add(parentBone);
for (FbxNode child : limb.children) {
if (child instanceof FbxLimbNode) {
FbxLimbNode childLimb = (FbxLimbNode) child;
createBones(skeletonHolderNode, childLimb, bones);
parentBone.addChild(childLimb.getJmeBone());
}
}
}
Aggregations