[SOLVED] Jme3 Cinematics: Speeding up the animation

how can I speed up and slow down the animation in cinematics? say I want to use 10x speed of the animation instead of real time speed.

Dude…there is a cinematic.setSpeed(10); method, with javadoc in case it’s not explicit enough.

1 Like

Thanks I’ll make sure to check there next time before asking.



Using cinematic.setspeed(1) runs the animation at real speed I assume works fine, however increasing that number messes up all my animation. For example setspeed(2) will mess up all the events and I won’t have any synchronization.

@nehon I’ve been trying to implement it for the last 2 days, do you know how it would be possible to set the speed for the whole animation w/o messing up the timing of the events? As I mentioned before, the trace file I have is:

[java]

time 0

create spatial duration = 0 // calls an abstract cinematic track

time 1.0

rotate spatial duration = 4 // calls rotationTrack

time 2.43

accelerate spatial duration = 10

time 3.45

deceleration spatial duration = 10

[/java]





cinematic.setSpeed(10); will only affect the duration of the cinematic however, it messes up the timing…





NOTE:



Description of the function:

Sets the speed of the animation. At speed = 1, the animation will last initialDuration seconds, At speed = 2 the animation will last initialDuraiton/2.



I don’t have one animation, but a series of events (to be animated) that are being read by a separate thread and being animated by cinematics on the fly. In other words I need to put all of them under one duration and control that with setSpeed(). Is that possible?

there are indeed issues with the timing when speeding up the cinematic.

I’ll look into it

ok you can update to last SVN it’s been fixed.

1 Like

Perfect Thanks Nehon. One more question, what if I want to jump to a specific time? How can I do so?

@garnaout said:
Perfect Thanks Nehon. One more question, what if I want to jump to a specific time? How can I do so?

I wish I knew

@nehon could there still be issues in the animation speeding in Cinematics? There’s something quite odd happening with me whenever I use setspeed > 1



It works fine for me for rotate, forward, accelerate, etc whenever the separating distance b/w these events is not very small. In other words a successful example of a pseudo trace:

  • accelerate/move for 10 secs
  • rotate for 2 secs
  • accelerate for 5 secs





    However, it acts very funky when I run a pseudo trace example like:
  • accelerate/move for 0.21 secs
  • rotate for 0.33 secs
  • accelerate for 0.4 secs



    it gets messy and kinda combines all three of them as if out of synch. Any ideas? code works perfectly if speed set to 1 which made me doubt the setSpeed ()code.



    thanks

Please note that in my previous version (and it worked) a typical cinematic event was something like:



[java] // PositionTrack is a pre-existing Cinematic event that moves drive at a constant speed.

cinematic.addCinematicEvent(trigger_time, new PositionTrack(spatialToMove, new Vector3f(x, y, z),

duration / (animation_speed), LoopMode.DontLoop ) );

[/java]



so I was dividing the duration of every cinematic event by the animation_speed ALTHOUGH I also set cinematic.setSpeed(animation_speed) which I think it defies the purpose of that function - however that did it for me - of course didn’t work for close events.



thanks

I wish I had a specific test case I could refer to, I would have tried to implement a hack in my app or suggested a fix but it’s a bit more complicated than that. The thing is, the same trace (and it’s more complicated than what it looks) does what it’s supposed to do correctly at speed 1x and does it inaccurately at speed say 3X.



Check these two videos to see what I mean: http://www.theforeigners.org/jme3/



what these cars are doing is trying to reach the green point by first going straight to an intersection point (calculated using an intersection function) then rotating 45 degrees and going straight again to that point. I already did some unit tests on my side of the code and it looks fine.

Do you have Vsync enabled? if not could you try?

I don’t understand your issue, setSpeed works in my tests, so you could you please give me a test case demonstrating the issue?

Is it set true by adding: setting.setVSync(true); in my settings? if so, that didn’t solve it.

ok well honestly I tested in TestCinematic, if i setSpeed(3), all times (cinematic and individual events) are divided by 3.



I’d really need a test case for this, i can’t help if i don’t witness the issue.

I don’t say the issue is in your code, but maybe the way you use it could lead to unexpected behavior in the cinematic code.

ok I’m gonna try to wrap up a test case showing the problem.



btw out of curiosity, what is the maximum speed the engine could handle in setSpeed() ?

Also should it be done this way?

example:

[java]

cinematic.addCinematicEvent(trigger_time, new PositionTrack(spatialToMove, new Vector3f(x, y, z),

duration / (animation_speed), LoopMode.DontLoop ) );[/java]



Am I supposed to manually divide every duration by the animation_speed variable that I have?



[java]animation_speed = cinematic.setSpeed();[/java]



Also, I have developed an AccelerateTrack and a CreateTrack not sure if I should share them or not and whether they’re useful. Do you want to take a look at them first?

@garnaout said:
btw out of curiosity, what is the maximum speed the engine could handle in setSpeed() ?

there is no maximum... I guess the float upper limit...which is huge..but that would make no sense

@garnaout said:
Also, I have developed an AccelerateTrack and a CreateTrack not sure if I should share them or not and whether they're useful. Do you want to take a look at them first?

Ho right!, there might be some specificity and you may have to implement your own set speed method for those tracks.
yes please post the code.

my own setSpeed()? that doesn’t sound good :S



AcceleraTrack:

[java]

import com.jme3.animation.LoopMode;

import com.jme3.app.Application;

import com.jme3.cinematic.Cinematic;

import com.jme3.cinematic.events.AbstractCinematicEvent;

import com.jme3.export.InputCapsule;

import com.jme3.export.JmeExporter;

import com.jme3.export.JmeImporter;

import com.jme3.export.OutputCapsule;

import com.jme3.math.FastMath;

import com.jme3.math.Vector3f;

import com.jme3.scene.Spatial;

import java.io.IOException;

import java.util.logging.Level;

import java.util.logging.Logger;



/**

*

    • AccelerateTrack -

      *
  • This class is responsible of accelerating spatials using a Cinematic event.

    *
  • @author garnaout
  • @modified Friday, September 23rd 2011

    */



    public class AccelerateTrack extends AbstractCinematicEvent {



    private static final Logger log = Logger.getLogger(AccelerateTrack.class.getName());

    private Vector3f startPosition;

    private Vector3f endPosition;

    private Spatial spatial;

    private String spatialName = "";

    private float value = 0;

    private float accelerationFactor;

    private float maxSpeed;

    private float acceleration;

    private float previous_speed;







    public AccelerateTrack(Spatial spatial, Vector3f endPosition) {

    this.endPosition = endPosition;

    this.spatial = spatial;

    spatialName = spatial.getName();

    }







    public AccelerateTrack(Spatial spatial, Vector3f endPosition, float initialDuration,

    float accelerationFactor, float acceleration, float previous_speed, float maxSpeed,

    LoopMode loopMode)

    {

    super(initialDuration, loopMode);

    this.endPosition = endPosition;

    this.spatial = spatial;

    this.accelerationFactor = accelerationFactor;

    this.acceleration = acceleration;

    this.maxSpeed = maxSpeed;

    this.previous_speed = previous_speed;

    //this.initialDuration = initialDuration;

    this.spatialName = spatial.getName();

    }





    @Override

    public void initEvent(Application app, Cinematic cinematic) {

    super.initEvent(app, cinematic);

    if (spatial == null) {



    spatial = cinematic.getScene().getChild(spatialName);

    if (spatial == null) {

    } else {

    log.log(Level.WARNING, "spatial {0} not found in the scene", spatialName);

    }

    }

    }





    @Override

    public void onPause() {

    // do nothing



    }



    @Override

    public void onPlay() {

    if (playState != playState.Paused) {

    startPosition = spatial.getWorldTranslation().clone();

    }

    if (initialDuration == 0 && spatial != null) {



    spatial.setLocalTranslation(endPosition);

    }



    }



    @Override

    public void onStop() {

    value = 0;



    }



    @Override

    public void onUpdate(float tpf) {



    // acceleration

    if(acceleration > 0)

    {

    //System.out.println("Accelerated Speed: "+speed);

    speed += tpf * accelerationFactor;



    if( speed > (acceleration + previous_speed))

    {

    speed = acceleration + previous_speed;

    }



    if( speed > maxSpeed )

    {

    speed = maxSpeed;

    }

    }



    // deceleration

    else if(acceleration < 0)

    {

    speed -= tpf * accelerationFactor;

    //System.out.println("reduced Speed: "+speed);



    if( speed < (acceleration + previous_speed))

    {

    speed = acceleration + previous_speed;

    }



    if( speed < 0 )

    {

    speed = 0;

    }

    }







    if (spatial != null) {

    Vector3f dir = endPosition.subtract( startPosition );

    dir.normalize();

    Vector3f velocity = dir.mult( speed * tpf );

    Vector3f pos = spatial.getLocalTranslation();

    spatial.setLocalTranslation( pos.add(velocity) );

    }

    }



    @Override

    public void write(JmeExporter ex) throws IOException {

    super.write(ex);

    OutputCapsule oc = ex.getCapsule(this);

    oc.write(spatialName, "spatialName", "");

    oc.write(endPosition, "endPosition", null);

    }



    @Override

    public void read(JmeImporter im) throws IOException {

    super.read(im);

    InputCapsule ic = im.getCapsule(this);

    spatialName = ic.readString("spatialName", "");

    endPosition = (Vector3f) ic.readSavable("endPosition", null);

    }











    }

    [/java]



    and CreateTrack

    [java] * @author garnaout
  • @modified Saturday, October 8th 2011

    */





    public class CreateTrack extends AbstractCinematicEvent {



    private static final Logger log = Logger.getLogger(CreateTrack.class.getName());

    private Spatial spatial;

    private float x;

    private float y;

    private float z;

    private float trigger_time = 0;

    private String type;

    private String id;

    private String spatialName = "";

    private Vector3f endPosition;

    private Vector3f startPosition;



    // create an instance of the Simpleapplication inside Jme3Cinematics

    private Jme3Cinematics myApp = Jme3Cinematics.getApp();

    // reads the asset manager initialized in Jme3Cinematics

    //private AssetManager assetManager = myApp.getAssetManager();



    //Constructor and initializer

    public CreateTrack(float trigger_time, String id, String type, Vector3f endPosition, LoopMode loopMode) {

    this.endPosition = endPosition;

    this.trigger_time = trigger_time;

    //this.spatial = spatial;

    this.id = id;

    this.type = type;

    this.x = endPosition.getX();

    this.y = endPosition.getY();

    this.z = endPosition.getZ();



    // Hack necessary to have spatials created before the animation plays

    if(trigger_time < 1)

    {

    // create the one that are initialized at time 0.00

    myApp.create3dModel(trigger_time, id, type, x, y, z);

    }

    }





    @Override

    public void onPause() {

    // do nothing just create

    }



    @Override

    public void onPlay() {



    // only for spatials that are created after time 0

    if(trigger_time > 0)

    {

    // call the animator to create spatials after the animation starts

    myApp.create3dModel(trigger_time, id, type, x, y, z);

    }

    }



    @Override

    public void onStop() {

    // do nothing just create

    }



    @Override

    public void onUpdate(float arg0) {

    // do nothing just create



    }

    }[/java]
@garnaout said:
my own setSpeed()? that doesn't sound good :S

lol don't worry that's not as complicated as it sounds.

there is a default setTime in AbstractCinematicEvent but it uses the time attribute, the problem here is that you use tpf for your AccelerationTrack.

I'll look into it tonight and i'll give you some directions.
1 Like