function updated, had some float inaccuracies, issue still there though
[java]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;
float epsilon = 0.001f; // used to compare floats accurately
private float currentSpeed = 0;
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.currentSpeed = previous_speed;
}
@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 > epsilon)
{
System.out.println("Accelerated Speed: "+currentSpeed);
currentSpeed += tpf * accelerationFactor;
if( currentSpeed - maxSpeed > epsilon )
{
currentSpeed = maxSpeed;
}
}
// deceleration
else if(acceleration < epsilon)
{
System.out.println("reduced Speed: "+currentSpeed);
currentSpeed -= tpf * accelerationFactor;
if( currentSpeed < epsilon )
{
currentSpeed = 0;
}
}
if (spatial != null) {
Vector3f dir = endPosition.subtract( startPosition );
dir.normalize();
Vector3f velocity = dir.mult( currentSpeed * 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]
Sorry i thought i answered your question.
You use tpf to compute the acceleration on each frame. thatās what i did at first for every cinematicEvents.
For the seTime(float) to be possible I had to change every event to use the time variable of the AbstractCinematicEvent (the time elapsed since the play method was called).
What you should do is to choose an arbitrary amount of time your acceleration should occur per seconds (30 for example), and accelerate or decelerate like you were doing before but based on the time elapsed since the beginning.
This way you know exactly how many times the acceleration occur for a given time, (1 second 30 times, 2 second 60 times and so on)
So when the setTime is called you can easily recompute the parameters for a given time.
@nehon thereās something terribly wrong here right?
given the correct duration and speed, the spatial does not stop where itās supposed to stopā¦
it actually stops at Position: (13.288592, 13.455835, 0.0) instead of what I passed it: (13.268, 13.435, 0.0), although minor , iām curious whyā¦
@nehon, not sure I quite get it. I have 3 questions.
What you should do is to choose an arbitrary amount of time your acceleration should occur per seconds (30 for example), and accelerate or decelerate like you were doing before but based on the time elapsed since the beginning.
1- Can you give me an example? are you saying to replace the tpf in currentSpeed += tpf * accelerationFactor with time?
2- Also on another note, I am confusing the discussion of setTime with setSpeed(). Are they related as far as the fix? if I fix my event by adding time willl it fix setSpeed() as well?
3- can I call setSpeed DURING the animation to speed up then call it again to slow it down?
Thanks in advance
@garnaout said:
@nehon, not sure I quite get it. I have 3 questions.
1- Can you give me an example? are you saying to replace the tpf in currentSpeed += tpf * accelerationFactor with time?
Look at the RotationTrack code for example
@garnaout said:
@nehon, not sure I quite get it. I have 3 questions.
2- Also on another note, I am confusing the discussion of setTime with setSpeed(). Are they related as far as the fix? if I fix my event by adding time willl it fix setSpeed() as well?
Mhh sorry, i'm the one confusing things.I don't know why i though your issue was with setTime...not setSpeed.
Ok, so this should be easier you only have to multiply tpf by the speed variable in your update method and speed will be taken into account.
@garnaout said:
3- can I call setSpeed DURING the animation to speed up then call it again to slow it down?
I see no reason why you couldn't, it should work.
Actually itās both! haha Iāll give it a shot
btw is it fine to let onPause in all ofthe cinematic events empty?
I noticed that when I pause and then resume, the timings get messed up.
@garnaout said:
Actually it's both! haha I'll give it a shot
btw is it fine to let onPause in all ofthe cinematic events empty?
I noticed that when I pause and then resume, the timings get messed up.
Yeah, i also take care of that in AbstractCinematicEvent, it's one more good reason to use the time attribute instead of tpf, because the time spent during the pause is taken into account.
so solving one issue at a time for setSpeed to work efficiently I did update my AccelerateTrack to
currentSpeed -= tpf * accelerationFactor * myApp.getAnimationSpeed(); //in deceleration
currentSpeed += tpf * accelerationFactor * myApp.getAnimationSpeed(); // in acceleration
it is still funky when I accelerate the speedā¦
@garnaout said:
so solving one issue at a time for setSpeed to work efficiently I did update my AccelerateTrack to
currentSpeed -= tpf * accelerationFactor * myApp.getAnimationSpeed(); //in deceleration
currentSpeed += tpf * accelerationFactor * myApp.getAnimationSpeed(); // in acceleration
it is still funky when I accelerate the speed...
no...
you have a protected speed attribute in the AbstractCinematicEvent, that's the one you have to use.
I added : [java] value = Math.min(time / initialDuration, 1.0f);[/java]
for setSpeed issues:
in my AccelerateTrack and changed the speed variable to the protected speed variable you created. Animation looks fine now when I speed it up. However, when I pause, it still gets messed up. Should I add anything onPause()? I currently have it empty just like your cinematic events.
As for setTime(), I will work on it today and let you know. I still didnāt figure out the issue I am having in my Eclipse compiler not recognizing setTime() (although it is in the class).
Thanks @nehon
sorry was using Maven and I needed to do a clean and clean also my repository and now it worksā¦
@nehon I tried
cinematic.setTime(100);
however nothing happensā¦ it continues reading w/o skipping.
I did include the time as u suggested in AccelerateTrack
@nehon for this one u said as an example look at the rotationTrack.java (http://code.google.com/p/jmonkeyengine/source/browse/branches/jme3/src/core/com/jme3/cinematic/events/RotationTrack.java?r=6681)
however in that example you donāt use time, u use tpf
yeahā¦that was 3000 revisions beforeā¦
check the up to date code
http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/core/com/jme3/cinematic/events/RotationTrack.java
well then I thought of thta and added value = Math.min(time / initialDuration, 1.0f); inside the onUpdate()
and set the speed += time * acceleration; and the time doesnāt update if thereās no tpf involved
anyways I fixed my animation acceleration by simply passing to the spatial the direction as @pspeed suggested and it works perfectly now. IHowever, I am still using tpf.
I want setTime() to work, can you help me with that? when I call it, animation just freezes as if there are no events to be read.
edit: it actually jumps to a certain time (assuming itās 100) but animation gets messed up - nothing is synchronized.
@nehon, Can you at least explain to me how to implement it āyour wayā to get rid of tpf variable? I really donāt understand and your explanation is a little bit too summarized.
time != tpf
time is the time elapsed since the beginning of the animation
tpf is time spent on last frame.
so the idea is to compute what acceleration value you should have for time = n. n being a float between 0 and initalDuration
since for now you have currentSpeed += tpf * accelerationFactor;
thatās pretty simple this means that you just stack accelerationFactor over time so for time n, current acceleration is n * accelerationFactor.
Soā¦ your currentSpeed is computed like that : currentSpeed = time * accelerationFactor;
Well I already tried that but like I mentioned before:
the variable time does not update unless I have speed += tpf * acceleration; Thats why I wanted to know how ātimeā updatesā¦
In addition you mentioned using:
[java]value = Math.min(time / initialDuration, 1.0f);[/java]
how do I use value? I looked at PositionTrack and RotationTrack and itās used depending on the relative function. How would I use it in acceleration with:
[java] 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) );
}[/java]
and btw I am using speed and not currentSpeed as you suggested before