Search in sources :

Example 1 with AnimInverval

use of com.jme3.scene.plugins.fbx.AnimationList.AnimInverval 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)

Aggregations

Animation (com.jme3.animation.Animation)1 BoneTrack (com.jme3.animation.BoneTrack)1 Track (com.jme3.animation.Track)1 Quaternion (com.jme3.math.Quaternion)1 Vector3f (com.jme3.math.Vector3f)1 AnimInverval (com.jme3.scene.plugins.fbx.AnimationList.AnimInverval)1 FbxAnimNode (com.jme3.scene.plugins.fbx.objects.FbxAnimNode)1 FbxNode (com.jme3.scene.plugins.fbx.objects.FbxNode)1 FbxObject (com.jme3.scene.plugins.fbx.objects.FbxObject)1 HashMap (java.util.HashMap)1 TreeSet (java.util.TreeSet)1