Search in sources :

Example 1 with FbxLimbNode

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);
        }
    }
}
Also used : BoneTrack(com.jme3.animation.BoneTrack) HashMap(java.util.HashMap) FbxAnimCurveNode(com.jme3.scene.plugins.fbx.anim.FbxAnimCurveNode) AnimControl(com.jme3.animation.AnimControl) FbxNode(com.jme3.scene.plugins.fbx.node.FbxNode) Spatial(com.jme3.scene.Spatial) Animation(com.jme3.animation.Animation) FbxToJmeTrack(com.jme3.scene.plugins.fbx.anim.FbxToJmeTrack) Skeleton(com.jme3.animation.Skeleton) Bone(com.jme3.animation.Bone) FbxLimbNode(com.jme3.scene.plugins.fbx.anim.FbxLimbNode) FbxAnimLayer(com.jme3.scene.plugins.fbx.anim.FbxAnimLayer) HashMap(java.util.HashMap) Map(java.util.Map) FbxAnimStack(com.jme3.scene.plugins.fbx.anim.FbxAnimStack)

Example 2 with FbxLimbNode

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);
    }
}
Also used : Skeleton(com.jme3.animation.Skeleton) Bone(com.jme3.animation.Bone) FbxLimbNode(com.jme3.scene.plugins.fbx.anim.FbxLimbNode)

Example 3 with FbxLimbNode

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;
}
Also used : SkeletonDebugger(com.jme3.scene.debug.SkeletonDebugger) Spatial(com.jme3.scene.Spatial) FbxLimbNode(com.jme3.scene.plugins.fbx.anim.FbxLimbNode) Node(com.jme3.scene.Node) FbxAnimCurveNode(com.jme3.scene.plugins.fbx.anim.FbxAnimCurveNode) SkeletonControl(com.jme3.animation.SkeletonControl) Material(com.jme3.material.Material) FbxMaterial(com.jme3.scene.plugins.fbx.material.FbxMaterial) FbxLimbNode(com.jme3.scene.plugins.fbx.anim.FbxLimbNode) AnimControl(com.jme3.animation.AnimControl)

Example 4 with FbxLimbNode

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;
}
Also used : FbxCluster(com.jme3.scene.plugins.fbx.anim.FbxCluster) FbxMesh(com.jme3.scene.plugins.fbx.mesh.FbxMesh) FbxSkinDeformer(com.jme3.scene.plugins.fbx.anim.FbxSkinDeformer) FbxLimbNode(com.jme3.scene.plugins.fbx.anim.FbxLimbNode)

Example 5 with FbxLimbNode

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());
        }
    }
}
Also used : FbxNode(com.jme3.scene.plugins.fbx.node.FbxNode) Bone(com.jme3.animation.Bone)

Aggregations

FbxLimbNode (com.jme3.scene.plugins.fbx.anim.FbxLimbNode)4 Bone (com.jme3.animation.Bone)3 AnimControl (com.jme3.animation.AnimControl)2 Skeleton (com.jme3.animation.Skeleton)2 Spatial (com.jme3.scene.Spatial)2 FbxAnimCurveNode (com.jme3.scene.plugins.fbx.anim.FbxAnimCurveNode)2 FbxNode (com.jme3.scene.plugins.fbx.node.FbxNode)2 Animation (com.jme3.animation.Animation)1 BoneTrack (com.jme3.animation.BoneTrack)1 SkeletonControl (com.jme3.animation.SkeletonControl)1 Material (com.jme3.material.Material)1 Node (com.jme3.scene.Node)1 SkeletonDebugger (com.jme3.scene.debug.SkeletonDebugger)1 FbxAnimLayer (com.jme3.scene.plugins.fbx.anim.FbxAnimLayer)1 FbxAnimStack (com.jme3.scene.plugins.fbx.anim.FbxAnimStack)1 FbxCluster (com.jme3.scene.plugins.fbx.anim.FbxCluster)1 FbxSkinDeformer (com.jme3.scene.plugins.fbx.anim.FbxSkinDeformer)1 FbxToJmeTrack (com.jme3.scene.plugins.fbx.anim.FbxToJmeTrack)1 FbxMaterial (com.jme3.scene.plugins.fbx.material.FbxMaterial)1 FbxMesh (com.jme3.scene.plugins.fbx.mesh.FbxMesh)1