Search in sources :

Example 6 with FbxNode

use of com.jme3.scene.plugins.fbx.objects.FbxNode in project jmonkeyengine by jMonkeyEngine.

the class FbxNode method updateWorldTransforms.

public void updateWorldTransforms(Transform jmeParentNodeTransform, Transform parentBindPose) {
    Transform fbxLocalTransform = computeFbxLocalTransform();
    jmeLocalNodeTransform.set(fbxLocalTransform);
    if (jmeParentNodeTransform != null) {
        jmeParentNodeTransform = jmeParentNodeTransform.clone();
        switch(inheritMode) {
            case NoParentScale:
            case ScaleAfterChildRotation:
            case ScaleBeforeChildRotation:
                jmeWorldNodeTransform.set(jmeLocalNodeTransform);
                jmeWorldNodeTransform.combineWithParent(jmeParentNodeTransform);
                break;
        }
    } else {
        jmeWorldNodeTransform.set(jmeLocalNodeTransform);
    }
    if (jmeWorldBindPose != null) {
        jmeLocalBindPose = new Transform();
        // Need to derive local bind pose from world bind pose
        // (this is to be expected for FBX limbs)
        jmeLocalBindPose.set(jmeWorldBindPose);
        jmeLocalBindPose.combineWithParent(parentBindPose.invert());
        // Its somewhat odd for the transforms to differ ...
        System.out.println("Bind Pose for: " + getName());
        if (!jmeLocalBindPose.equals(jmeLocalNodeTransform)) {
            System.out.println("Local Bind: " + jmeLocalBindPose);
            System.out.println("Local Trans: " + jmeLocalNodeTransform);
        }
        if (!jmeWorldBindPose.equals(jmeWorldNodeTransform)) {
            System.out.println("World Bind: " + jmeWorldBindPose);
            System.out.println("World Trans: " + jmeWorldNodeTransform);
        }
    } else {
        // World pose derived from local transforms
        // (this is to be expected for FBX nodes)
        jmeLocalBindPose = new Transform();
        jmeWorldBindPose = new Transform();
        jmeLocalBindPose.set(jmeLocalNodeTransform);
        if (parentBindPose != null) {
            jmeWorldBindPose.set(jmeLocalNodeTransform);
            jmeWorldBindPose.combineWithParent(parentBindPose);
        } else {
            jmeWorldBindPose.set(jmeWorldNodeTransform);
        }
    }
    for (FbxNode child : children) {
        child.updateWorldTransforms(jmeWorldNodeTransform, jmeWorldBindPose);
    }
}
Also used : Transform(com.jme3.math.Transform)

Example 7 with FbxNode

use of com.jme3.scene.plugins.fbx.objects.FbxNode in project jmonkeyengine by jMonkeyEngine.

the class FbxLoader method constructSceneGraph.

private Spatial constructSceneGraph() {
    // Acquire the implicit root object.
    FbxNode fbxRoot = (FbxNode) objectMap.get(FbxId.ROOT);
    // Convert it into a jME3 scene
    Node jmeRoot = (Node) FbxNode.createScene(fbxRoot);
    // Fix the name (will probably be set to something like "-node")
    jmeRoot.setName(sceneName + "-scene");
    return jmeRoot;
}
Also used : FbxNode(com.jme3.scene.plugins.fbx.node.FbxNode) FbxLimbNode(com.jme3.scene.plugins.fbx.anim.FbxLimbNode) FbxNode(com.jme3.scene.plugins.fbx.node.FbxNode) Node(com.jme3.scene.Node) FbxAnimCurveNode(com.jme3.scene.plugins.fbx.anim.FbxAnimCurveNode) FbxRootNode(com.jme3.scene.plugins.fbx.node.FbxRootNode)

Example 8 with FbxNode

use of com.jme3.scene.plugins.fbx.objects.FbxNode in project jmonkeyengine by jMonkeyEngine.

the class FbxLoader method applyBindPoses.

/**
     * Copies the bind poses from FBX BindPose objects to FBX nodes.
     * Must be called prior to {@link #updateWorldTransforms()}.
     */
private void applyBindPoses() {
    for (FbxBindPose bindPose : bindPoses) {
        Map<FbxId, Matrix4f> bindPoseData = bindPose.getJmeObject();
        logger.log(Level.INFO, "Applying {0} bind poses", bindPoseData.size());
        for (Map.Entry<FbxId, Matrix4f> entry : bindPoseData.entrySet()) {
            FbxObject obj = objectMap.get(entry.getKey());
            if (obj instanceof FbxNode) {
                FbxNode node = (FbxNode) obj;
                node.setWorldBindPose(entry.getValue());
            } else {
                logger.log(Level.WARNING, "Bind pose can only be applied to FBX nodes. Ignoring.");
            }
        }
    }
}
Also used : FbxObject(com.jme3.scene.plugins.fbx.obj.FbxObject) FbxNode(com.jme3.scene.plugins.fbx.node.FbxNode) Matrix4f(com.jme3.math.Matrix4f) FbxBindPose(com.jme3.scene.plugins.fbx.anim.FbxBindPose) HashMap(java.util.HashMap) Map(java.util.Map) FbxId(com.jme3.scene.plugins.fbx.file.FbxId)

Example 9 with FbxNode

use of com.jme3.scene.plugins.fbx.objects.FbxNode in project jmonkeyengine by jMonkeyEngine.

the class SceneLoader method buildAnimations.

private void buildAnimations() {
    if (skeleton == null)
        return;
    if (animList == null || animList.list.size() == 0) {
        animList = new AnimationList();
        for (long layerId : alayerMap.keySet()) {
            FbxObject layer = alayerMap.get(layerId);
            animList.add(layer.name, layer.name, 0, -1);
        }
    }
    // Extract aminations
    HashMap<String, Animation> anims = new HashMap<String, Animation>();
    for (AnimInverval animInfo : animList.list) {
        float realLength = 0;
        float length = (animInfo.lastFrame - animInfo.firstFrame) / this.animFrameRate;
        float animStart = animInfo.firstFrame / this.animFrameRate;
        float animStop = animInfo.lastFrame / this.animFrameRate;
        Animation anim = new Animation(animInfo.name, length);
        // Search source layer for animation nodes
        long sourceLayerId = 0L;
        for (long layerId : alayerMap.keySet()) {
            FbxObject layer = alayerMap.get(layerId);
            if (layer.name.equals(animInfo.layerName)) {
                sourceLayerId = layerId;
                break;
            }
        }
        // Build bone tracks
        for (FbxNode limb : limbMap.values()) {
            // Animation channels may have different keyframes (non-baked animation).
            //   So we have to restore intermediate values for all channels cause of JME requires
            //   a bone track as a single channel with collective transformation for each keyframe
            // Sorted unique timestamps
            Set<Long> stamps = new TreeSet<Long>();
            FbxAnimNode animTranslation = limb.animTranslation(sourceLayerId);
            FbxAnimNode animRotation = limb.animRotation(sourceLayerId);
            FbxAnimNode animScale = limb.animScale(sourceLayerId);
            boolean haveTranslation = haveAnyChannel(animTranslation);
            boolean haveRotation = haveAnyChannel(animRotation);
            boolean haveScale = haveAnyChannel(animScale);
            // Collect keyframes stamps
            if (haveTranslation)
                animTranslation.exportTimes(stamps);
            if (haveRotation)
                animRotation.exportTimes(stamps);
            if (haveScale)
                animScale.exportTimes(stamps);
            if (stamps.isEmpty())
                continue;
            long[] keyTimes = new long[stamps.size()];
            int cnt = 0;
            for (long t : stamps) keyTimes[cnt++] = t;
            // Calculate keys interval by animation time interval
            int firstKeyIndex = 0;
            int lastKeyIndex = keyTimes.length - 1;
            for (int i = 0; i < keyTimes.length; ++i) {
                // Translate into seconds
                float time = (float) (((double) keyTimes[i]) * secondsPerUnit);
                if (time <= animStart)
                    firstKeyIndex = i;
                if (time >= animStop && animStop >= 0) {
                    lastKeyIndex = i;
                    break;
                }
            }
            int keysCount = lastKeyIndex - firstKeyIndex + 1;
            if (keysCount <= 0)
                continue;
            float[] times = new float[keysCount];
            Vector3f[] translations = new Vector3f[keysCount];
            Quaternion[] rotations = new Quaternion[keysCount];
            Vector3f[] scales = null;
            // Calculate keyframes times
            for (int i = 0; i < keysCount; ++i) {
                int keyIndex = firstKeyIndex + i;
                // Translate into seconds
                float time = (float) (((double) keyTimes[keyIndex]) * secondsPerUnit);
                times[i] = time - animStart;
                realLength = Math.max(realLength, times[i]);
            }
            // Load keyframes from animation curves
            if (haveTranslation) {
                for (int i = 0; i < keysCount; ++i) {
                    int keyIndex = firstKeyIndex + i;
                    FbxAnimNode n = animTranslation;
                    // Why do it here but not in other places? FBX magic?
                    Vector3f tvec = n.getValue(keyTimes[keyIndex], n.value).subtractLocal(n.value);
                    translations[i] = tvec.divideLocal(unitSize);
                }
            } else {
                for (int i = 0; i < keysCount; ++i) translations[i] = Vector3f.ZERO;
            }
            RotationOrder ro = RotationOrder.EULER_XYZ;
            if (haveRotation) {
                for (int i = 0; i < keysCount; ++i) {
                    int keyIndex = firstKeyIndex + i;
                    FbxAnimNode n = animRotation;
                    Vector3f tvec = n.getValue(keyTimes[keyIndex], n.value);
                    rotations[i] = ro.rotate(tvec);
                }
            } else {
                for (int i = 0; i < keysCount; ++i) rotations[i] = Quaternion.IDENTITY;
            }
            if (haveScale) {
                scales = new Vector3f[keysCount];
                for (int i = 0; i < keysCount; ++i) {
                    int keyIndex = firstKeyIndex + i;
                    FbxAnimNode n = animScale;
                    Vector3f tvec = n.getValue(keyTimes[keyIndex], n.value);
                    scales[i] = tvec;
                }
            }
            BoneTrack track = null;
            if (haveScale)
                track = new BoneTrack(limb.boneIndex, times, translations, rotations, scales);
            else
                track = new BoneTrack(limb.boneIndex, times, translations, rotations);
            anim.addTrack(track);
        }
        if (realLength != length && animInfo.lastFrame == -1) {
            Track[] tracks = anim.getTracks();
            if (tracks == null || tracks.length == 0)
                continue;
            anim = new Animation(animInfo.name, realLength);
            for (Track track : tracks) anim.addTrack(track);
        }
        anims.put(anim.getName(), anim);
    }
    animControl.setAnimations(anims);
}
Also used : FbxObject(com.jme3.scene.plugins.fbx.objects.FbxObject) HashMap(java.util.HashMap) Quaternion(com.jme3.math.Quaternion) FbxAnimNode(com.jme3.scene.plugins.fbx.objects.FbxAnimNode) FbxNode(com.jme3.scene.plugins.fbx.objects.FbxNode) TreeSet(java.util.TreeSet) BoneTrack(com.jme3.animation.BoneTrack) AnimInverval(com.jme3.scene.plugins.fbx.AnimationList.AnimInverval) Vector3f(com.jme3.math.Vector3f) Animation(com.jme3.animation.Animation) BoneTrack(com.jme3.animation.BoneTrack) Track(com.jme3.animation.Track)

Example 10 with FbxNode

use of com.jme3.scene.plugins.fbx.objects.FbxNode in project jmonkeyengine by jMonkeyEngine.

the class SceneLoader method linkScene.

private void linkScene() {
    logger.log(Level.FINE, "Linking scene objects");
    long startTime = System.currentTimeMillis();
    applySkinning();
    buildAnimations();
    for (FbxMesh mesh : geomMap.values()) mesh.clearMaterials();
    // Remove bones from node structures : JME creates attach node by itself
    for (FbxNode limb : limbMap.values()) limb.node.removeFromParent();
    long estimatedTime = System.currentTimeMillis() - startTime;
    logger.log(Level.FINE, "Linking done in {0} ms", estimatedTime);
}
Also used : FbxNode(com.jme3.scene.plugins.fbx.objects.FbxNode) FbxMesh(com.jme3.scene.plugins.fbx.objects.FbxMesh)

Aggregations

FbxNode (com.jme3.scene.plugins.fbx.node.FbxNode)6 Bone (com.jme3.animation.Bone)4 FbxLimbNode (com.jme3.scene.plugins.fbx.anim.FbxLimbNode)4 FbxNode (com.jme3.scene.plugins.fbx.objects.FbxNode)4 AnimControl (com.jme3.animation.AnimControl)3 FbxAnimCurveNode (com.jme3.scene.plugins.fbx.anim.FbxAnimCurveNode)3 HashMap (java.util.HashMap)3 Animation (com.jme3.animation.Animation)2 BoneTrack (com.jme3.animation.BoneTrack)2 Skeleton (com.jme3.animation.Skeleton)2 SkeletonControl (com.jme3.animation.SkeletonControl)2 Material (com.jme3.material.Material)2 Node (com.jme3.scene.Node)2 Spatial (com.jme3.scene.Spatial)2 FbxAnimNode (com.jme3.scene.plugins.fbx.objects.FbxAnimNode)2 FbxBindPose (com.jme3.scene.plugins.fbx.objects.FbxBindPose)2 FbxMesh (com.jme3.scene.plugins.fbx.objects.FbxMesh)2 FbxObject (com.jme3.scene.plugins.fbx.objects.FbxObject)2 Map (java.util.Map)2 Track (com.jme3.animation.Track)1