Search in sources :

Example 1 with SpatialTrack

use of com.jme3.animation.SpatialTrack in project jmonkeyengine by jMonkeyEngine.

the class FbxToJmeTrack method toJmeTrackInternal.

private Track toJmeTrackInternal(int boneIndex, Transform inverseBindPose) {
    float duration = animStack.getDuration();
    FbxAnimCurveNode translationCurve = animCurves.get("Lcl Translation");
    FbxAnimCurveNode rotationCurve = animCurves.get("Lcl Rotation");
    FbxAnimCurveNode scalingCurve = animCurves.get("Lcl Scaling");
    long[] fbxTimes = getKeyTimes();
    float[] times = new float[fbxTimes.length];
    // Translations / Rotations must be set on all tracks.
    // (Required for jME3)
    Vector3f[] translations = new Vector3f[fbxTimes.length];
    Quaternion[] rotations = new Quaternion[fbxTimes.length];
    Vector3f[] scales = null;
    if (scalingCurve != null) {
        scales = new Vector3f[fbxTimes.length];
    }
    for (int i = 0; i < fbxTimes.length; i++) {
        long fbxTime = fbxTimes[i];
        float time = (float) (fbxTime * FbxAnimUtil.SECONDS_PER_UNIT);
        if (time > duration) {
            // Expand animation duration to fit the curve.
            duration = time;
            System.out.println("actual duration: " + duration);
        }
        times[i] = time;
        if (translationCurve != null) {
            translations[i] = translationCurve.getVector3Value(fbxTime);
        } else {
            translations[i] = new Vector3f();
        }
        if (rotationCurve != null) {
            rotations[i] = rotationCurve.getQuaternionValue(fbxTime);
            if (i > 0) {
                if (rotations[i - 1].dot(rotations[i]) < 0) {
                    System.out.println("rotation will go the long way, oh noes");
                    rotations[i - 1].negate();
                }
            }
        } else {
            rotations[i] = new Quaternion();
        }
        if (scalingCurve != null) {
            scales[i] = scalingCurve.getVector3Value(fbxTime);
        }
        if (inverseBindPose != null) {
            applyInverse(translations[i], rotations[i], scales != null ? scales[i] : null, inverseBindPose);
        }
    }
    if (boneIndex == -1) {
        return new SpatialTrack(times, translations, rotations, scales);
    } else {
        if (scales != null) {
            return new BoneTrack(boneIndex, times, translations, rotations, scales);
        } else {
            return new BoneTrack(boneIndex, times, translations, rotations);
        }
    }
}
Also used : SpatialTrack(com.jme3.animation.SpatialTrack) BoneTrack(com.jme3.animation.BoneTrack) Quaternion(com.jme3.math.Quaternion) Vector3f(com.jme3.math.Vector3f)

Example 2 with SpatialTrack

use of com.jme3.animation.SpatialTrack in project jmonkeyengine by jMonkeyEngine.

the class AnimationHelper method applyAnimations.

/**
     * The method applies animations to the given node. The names of the animations should be the same as actions names in the blender file.
     * @param node
     *            the node to whom the animations will be applied
     * @param animationMatchMethod
     *            the way animation should be matched with node
     */
public void applyAnimations(Node node, AnimationMatchMethod animationMatchMethod) {
    List<BlenderAction> actions = this.getActions(node, animationMatchMethod);
    if (actions.size() > 0) {
        List<Animation> animations = new ArrayList<Animation>();
        for (BlenderAction action : actions) {
            SpatialTrack[] tracks = action.toTracks(node, blenderContext);
            if (tracks != null && tracks.length > 0) {
                Animation spatialAnimation = new Animation(action.getName(), action.getAnimationTime());
                spatialAnimation.setTracks(tracks);
                animations.add(spatialAnimation);
                blenderContext.addAnimation((Long) node.getUserData(ObjectHelper.OMA_MARKER), spatialAnimation);
            }
        }
        if (animations.size() > 0) {
            AnimControl control = new AnimControl();
            HashMap<String, Animation> anims = new HashMap<String, Animation>(animations.size());
            for (int i = 0; i < animations.size(); ++i) {
                Animation animation = animations.get(i);
                anims.put(animation.getName(), animation);
            }
            control.setAnimations(anims);
            node.addControl(control);
        }
    }
}
Also used : SpatialTrack(com.jme3.animation.SpatialTrack) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Animation(com.jme3.animation.Animation) AnimControl(com.jme3.animation.AnimControl)

Example 3 with SpatialTrack

use of com.jme3.animation.SpatialTrack in project jmonkeyengine by jMonkeyEngine.

the class SimulationNode method simulateSpatial.

/**
     * Simulates the spatial node.
     */
private void simulateSpatial() {
    List<Constraint> constraints = blenderContext.getConstraints(featureOMA);
    if (constraints != null && constraints.size() > 0) {
        LOGGER.fine("Simulating spatial.");
        boolean applyStaticConstraints = true;
        if (animations != null) {
            for (Animation animation : animations) {
                float[] animationTimeBoundaries = this.computeAnimationTimeBoundaries(animation);
                int maxFrame = (int) animationTimeBoundaries[0];
                float maxTime = animationTimeBoundaries[1];
                VirtualTrack vTrack = new VirtualTrack(spatial.getName(), maxFrame, maxTime);
                for (Track track : animation.getTracks()) {
                    for (int frame = 0; frame < maxFrame; ++frame) {
                        spatial.setLocalTranslation(((SpatialTrack) track).getTranslations()[frame]);
                        spatial.setLocalRotation(((SpatialTrack) track).getRotations()[frame]);
                        spatial.setLocalScale(((SpatialTrack) track).getScales()[frame]);
                        for (Constraint constraint : constraints) {
                            constraint.apply(frame);
                            vTrack.setTransform(frame, spatial.getLocalTransform());
                        }
                    }
                    Track newTrack = vTrack.getAsSpatialTrack();
                    if (newTrack != null) {
                        animation.removeTrack(track);
                        animation.addTrack(newTrack);
                    }
                    applyStaticConstraints = false;
                }
            }
        }
        // object's transformation
        if (applyStaticConstraints) {
            for (Constraint constraint : constraints) {
                constraint.apply(0);
            }
        }
    }
    for (SimulationNode child : children) {
        child.simulate();
    }
}
Also used : SpatialTrack(com.jme3.animation.SpatialTrack) Animation(com.jme3.animation.Animation) SpatialTrack(com.jme3.animation.SpatialTrack) BoneTrack(com.jme3.animation.BoneTrack) Track(com.jme3.animation.Track)

Example 4 with SpatialTrack

use of com.jme3.animation.SpatialTrack in project jmonkeyengine by jMonkeyEngine.

the class SimulationNode method computeAnimationTimeBoundaries.

/**
     * Computes the maximum frame and time for the animation. Different tracks
     * can have different lengths so here the maximum one is being found.
     * 
     * @param animation
     *            the animation
     * @return maximum frame and time of the animation
     */
private float[] computeAnimationTimeBoundaries(Animation animation) {
    int maxFrame = Integer.MIN_VALUE;
    float maxTime = -Float.MAX_VALUE;
    for (Track track : animation.getTracks()) {
        if (track instanceof BoneTrack) {
            maxFrame = Math.max(maxFrame, ((BoneTrack) track).getTranslations().length);
            maxTime = Math.max(maxTime, ((BoneTrack) track).getTimes()[((BoneTrack) track).getTimes().length - 1]);
        } else if (track instanceof SpatialTrack) {
            maxFrame = Math.max(maxFrame, ((SpatialTrack) track).getTranslations().length);
            maxTime = Math.max(maxTime, ((SpatialTrack) track).getTimes()[((SpatialTrack) track).getTimes().length - 1]);
        } else {
            throw new IllegalStateException("Unsupported track type for simuation: " + track);
        }
    }
    return new float[] { maxFrame, maxTime };
}
Also used : SpatialTrack(com.jme3.animation.SpatialTrack) BoneTrack(com.jme3.animation.BoneTrack) SpatialTrack(com.jme3.animation.SpatialTrack) BoneTrack(com.jme3.animation.BoneTrack) Track(com.jme3.animation.Track)

Example 5 with SpatialTrack

use of com.jme3.animation.SpatialTrack in project jmonkeyengine by jMonkeyEngine.

the class Ipo method calculateTrack.

/**
     * This method calculates the value of the curves as a bone track between
     * the specified frames.
     * 
     * @param targetIndex
     *            the index of the target for which the method calculates the
     *            tracks IMPORTANT! Aet to -1 (or any negative number) if you
     *            want to load spatial animation.
     * @param localTranslation
     *            the local translation of the object/bone that will be animated by
     *            the track
     * @param localRotation
     *            the local rotation of the object/bone that will be animated by
     *            the track
     * @param localScale
     *            the local scale of the object/bone that will be animated by
     *            the track
     * @param startFrame
     *            the first frame of tracks (inclusive)
     * @param stopFrame
     *            the last frame of the tracks (inclusive)
     * @param fps
     *            frame rate (frames per second)
     * @param spatialTrack
     *            this flag indicates if the track belongs to a spatial or to a
     *            bone; the difference is important because it appears that bones
     *            in blender have the same type of coordinate system (Y as UP)
     *            as jme while other features have different one (Z is UP)
     * @return bone track for the specified bone
     */
public Track calculateTrack(int targetIndex, BoneContext boneContext, Vector3f localTranslation, Quaternion localRotation, Vector3f localScale, int startFrame, int stopFrame, int fps, boolean spatialTrack) {
    if (calculatedTrack == null) {
        // preparing data for track
        int framesAmount = stopFrame - startFrame;
        float timeBetweenFrames = 1.0f / fps;
        float[] times = new float[framesAmount + 1];
        Vector3f[] translations = new Vector3f[framesAmount + 1];
        float[] translation = new float[3];
        Quaternion[] rotations = new Quaternion[framesAmount + 1];
        float[] quaternionRotation = new float[] { localRotation.getX(), localRotation.getY(), localRotation.getZ(), localRotation.getW() };
        float[] eulerRotation = localRotation.toAngles(null);
        Vector3f[] scales = new Vector3f[framesAmount + 1];
        float[] scale = new float[] { localScale.x, localScale.y, localScale.z };
        float degreeToRadiansFactor = 1;
        if (blenderVersion < 250) {
            // in blender earlier than 2.50 the values are stored in degrees
            // the values in blender are divided by 10, so we need to mult it here
            degreeToRadiansFactor *= FastMath.DEG_TO_RAD * 10;
        }
        int yIndex = 1, zIndex = 2;
        boolean swapAxes = spatialTrack && fixUpAxis;
        if (swapAxes) {
            yIndex = 2;
            zIndex = 1;
        }
        boolean eulerRotationUsed = false, queternionRotationUsed = false;
        // calculating track data
        for (int frame = startFrame; frame <= stopFrame; ++frame) {
            boolean translationSet = false;
            translation[0] = translation[1] = translation[2] = 0;
            int index = frame - startFrame;
            // start + (frame - 1) * timeBetweenFrames;
            times[index] = index * timeBetweenFrames;
            for (int j = 0; j < bezierCurves.length; ++j) {
                double value = bezierCurves[j].evaluate(frame, BezierCurve.Y_VALUE);
                switch(bezierCurves[j].getType()) {
                    // LOCATION
                    case AC_LOC_X:
                        translation[0] = (float) value;
                        translationSet = true;
                        break;
                    case AC_LOC_Y:
                        if (swapAxes && value != 0) {
                            value = -value;
                        }
                        translation[yIndex] = (float) value;
                        translationSet = true;
                        break;
                    case AC_LOC_Z:
                        translation[zIndex] = (float) value;
                        translationSet = true;
                        break;
                    // EULER ROTATION
                    case OB_ROT_X:
                        eulerRotationUsed = true;
                        eulerRotation[0] = (float) value * degreeToRadiansFactor;
                        break;
                    case OB_ROT_Y:
                        eulerRotationUsed = true;
                        if (swapAxes && value != 0) {
                            value = -value;
                        }
                        eulerRotation[yIndex] = (float) value * degreeToRadiansFactor;
                        break;
                    case OB_ROT_Z:
                        eulerRotationUsed = true;
                        eulerRotation[zIndex] = (float) value * degreeToRadiansFactor;
                        break;
                    // SIZE
                    case AC_SIZE_X:
                        scale[0] = (float) value;
                        break;
                    case AC_SIZE_Y:
                        scale[yIndex] = (float) value;
                        break;
                    case AC_SIZE_Z:
                        scale[zIndex] = (float) value;
                        break;
                    // QUATERNION ROTATION (used with bone animation)
                    case AC_QUAT_W:
                        queternionRotationUsed = true;
                        quaternionRotation[3] = (float) value;
                        break;
                    case AC_QUAT_X:
                        queternionRotationUsed = true;
                        quaternionRotation[0] = (float) value;
                        break;
                    case AC_QUAT_Y:
                        queternionRotationUsed = true;
                        if (swapAxes && value != 0) {
                            value = -value;
                        }
                        quaternionRotation[yIndex] = (float) value;
                        break;
                    case AC_QUAT_Z:
                        quaternionRotation[zIndex] = (float) value;
                        break;
                    default:
                        LOGGER.log(Level.WARNING, "Unknown ipo curve type: {0}.", bezierCurves[j].getType());
                }
            }
            if (translationSet) {
                translations[index] = localRotation.multLocal(new Vector3f(translation[0], translation[1], translation[2]));
            } else {
                translations[index] = new Vector3f();
            }
            if (boneContext != null) {
                if (boneContext.getBone().getParent() == null && boneContext.is(BoneContext.NO_LOCAL_LOCATION)) {
                    float temp = translations[index].z;
                    translations[index].z = -translations[index].y;
                    translations[index].y = temp;
                }
            }
            if (queternionRotationUsed) {
                rotations[index] = new Quaternion(quaternionRotation[0], quaternionRotation[1], quaternionRotation[2], quaternionRotation[3]);
            } else {
                rotations[index] = new Quaternion().fromAngles(eulerRotation);
            }
            scales[index] = new Vector3f(scale[0], scale[1], scale[2]);
        }
        if (spatialTrack) {
            calculatedTrack = new SpatialTrack(times, translations, rotations, scales);
        } else {
            calculatedTrack = new BoneTrack(targetIndex, times, translations, rotations, scales);
        }
        if (queternionRotationUsed && eulerRotationUsed) {
            LOGGER.warning("Animation uses both euler and quaternion tracks for rotations. Quaternion rotation is applied. Make sure that this is what you wanted!");
        }
    }
    return calculatedTrack;
}
Also used : SpatialTrack(com.jme3.animation.SpatialTrack) BoneTrack(com.jme3.animation.BoneTrack) Quaternion(com.jme3.math.Quaternion) Vector3f(com.jme3.math.Vector3f)

Aggregations

SpatialTrack (com.jme3.animation.SpatialTrack)6 BoneTrack (com.jme3.animation.BoneTrack)4 Animation (com.jme3.animation.Animation)3 Quaternion (com.jme3.math.Quaternion)3 Vector3f (com.jme3.math.Vector3f)3 AnimControl (com.jme3.animation.AnimControl)2 Track (com.jme3.animation.Track)2 HashMap (java.util.HashMap)2 AmbientLight (com.jme3.light.AmbientLight)1 DirectionalLight (com.jme3.light.DirectionalLight)1 Geometry (com.jme3.scene.Geometry)1 Node (com.jme3.scene.Node)1 Box (com.jme3.scene.shape.Box)1 ArrayList (java.util.ArrayList)1