- fixed bad time calculation on cinematics

- Used a nano timer for precision
- javadoc'ed a bit

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8443 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
rem..om 13 years ago
parent 4c71cbc818
commit be6259e5ba
  1. 9
      engine/src/core/com/jme3/cinematic/Cinematic.java
  2. 107
      engine/src/core/com/jme3/cinematic/events/AbstractCinematicEvent.java
  3. 3
      engine/src/core/com/jme3/cinematic/events/AnimationTrack.java
  4. 3
      engine/src/core/com/jme3/cinematic/events/GuiTrack.java
  5. 20
      engine/src/core/com/jme3/cinematic/events/MotionTrack.java
  6. 4
      engine/src/core/com/jme3/cinematic/events/PositionTrack.java
  7. 4
      engine/src/core/com/jme3/cinematic/events/RotationTrack.java
  8. 4
      engine/src/core/com/jme3/cinematic/events/ScaleTrack.java
  9. 3
      engine/src/core/com/jme3/cinematic/events/SoundTrack.java
  10. 3
      engine/src/test/jme3test/animation/SubtitleTrack.java
  11. 18
      engine/src/test/jme3test/animation/TestCinematic.java

@ -166,7 +166,6 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
@Override
public void setSpeed(float speed) {
super.setSpeed(speed);
duration = initialDuration / speed;
for (int i = 0; i < cinematicEvents.size(); i++) {
CinematicEvent ce = cinematicEvents.get(i);
ce.setSpeed(speed);
@ -185,6 +184,7 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
nifty.fromXmlWithoutStartScreen(niftyXmlPath);
app.getGuiViewPort().addProcessor(niftyDisplay);
}
initEvent(app, this);
for (CinematicEvent cinematicEvent : cinematicEvents) {
cinematicEvent.initEvent(app, this);
}
@ -203,12 +203,11 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
play();
}
}
public boolean isEnabled() {
return playState == PlayState.Playing;
}
public void stateAttached(AppStateManager stateManager) {
}
@ -303,8 +302,8 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
enableCurrentCam(true);
}
public void activateCamera(float time, final String cameraName) {
addCinematicEvent(time, new AbstractCinematicEvent() {
public void activateCamera(float timeStamp, final String cameraName) {
addCinematicEvent(timeStamp, new AbstractCinematicEvent() {
@Override
public void onPlay() {

@ -39,13 +39,16 @@ import com.jme3.export.InputCapsule;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.export.OutputCapsule;
import com.jme3.export.Savable;
import com.jme3.system.NanoTimer;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
*
* This calls contains basic behavior of a cinematic event
* every cinematic event must extend this class
*
* A cinematic event must be given an inital duration in seconds (duration of the event at speed = 1) (default is 10)
* @author Nehon
*/
public abstract class AbstractCinematicEvent implements CinematicEvent {
@ -53,32 +56,61 @@ public abstract class AbstractCinematicEvent implements CinematicEvent {
protected PlayState playState = PlayState.Stopped;
protected float speed = 1;
protected float initialDuration = 10;
protected float duration = initialDuration / speed;
protected LoopMode loopMode = LoopMode.DontLoop;
protected float time = 0;
//nano timer for precisely computing the elapsed time
protected NanoTimer timer;
/**
* the last time the event was paused
*/
protected float elapsedTimePause = 0;
/**
* the list of listeners
*/
protected List<CinematicEventListener> listeners;
/**
* contruct a cinematic event
*/
public AbstractCinematicEvent() {
}
/**
* contruct a cinematic event wwith the given initial duration
* @param initialDuration
*/
public AbstractCinematicEvent(float initialDuration) {
this.initialDuration = initialDuration;
duration = initialDuration / speed;
}
/**
* contruct a cinematic event with the given loopMode
* @param loopMode
*/
public AbstractCinematicEvent(LoopMode loopMode) {
this.loopMode = loopMode;
}
/**
* contruct a cinematic event with the given loopMode and the given initialDuration
* @param initialDuration the duration of the event at speed = 1
* @param loopMode the loop mode of the event
*/
public AbstractCinematicEvent(float initialDuration, LoopMode loopMode) {
this.initialDuration = initialDuration;
this.loopMode = loopMode;
duration = initialDuration / speed;
}
/**
* Play this event
*/
public void play() {
onPlay();
playState = PlayState.Playing;
if (timer == null) {
timer = new NanoTimer();
}
timer.reset();
if (listeners != null) {
for (int i = 0; i < listeners.size(); i++) {
CinematicEventListener cel = listeners.get(i);
@ -87,21 +119,32 @@ public abstract class AbstractCinematicEvent implements CinematicEvent {
}
}
public abstract void onPlay();
/**
* Place here the code you want to execute when the event is started
*/
protected abstract void onPlay();
/**
* should be used internally only
* @param tpf time per frame
*/
public void internalUpdate(float tpf) {
if (playState == PlayState.Playing) {
time += tpf * speed;
time = (elapsedTimePause + timer.getTimeInSeconds()) * speed;
onUpdate(tpf);
if (time >= duration && loopMode == loopMode.DontLoop) {
if (time >= initialDuration && loopMode == loopMode.DontLoop) {
stop();
}
}
}
public abstract void onUpdate(float tpf);
/**
* Place here the code you want to execute on update (only called when the event is playing)
* @param tpf time per frame
*/
protected abstract void onUpdate(float tpf);
/**
* stops the animation, next time play() is called the animation will start from the begining.
@ -110,6 +153,7 @@ public abstract class AbstractCinematicEvent implements CinematicEvent {
onStop();
time = 0;
playState = PlayState.Stopped;
elapsedTimePause = 0;
if (listeners != null) {
for (int i = 0; i < listeners.size(); i++) {
CinematicEventListener cel = listeners.get(i);
@ -118,11 +162,18 @@ public abstract class AbstractCinematicEvent implements CinematicEvent {
}
}
public abstract void onStop();
/**
* Place here the code you want to execute when the event is stoped.
*/
protected abstract void onStop();
/**
* pause this event
*/
public void pause() {
onPause();
playState = PlayState.Paused;
elapsedTimePause = time;
if (listeners != null) {
for (int i = 0; i < listeners.size(); i++) {
CinematicEventListener cel = listeners.get(i);
@ -131,6 +182,9 @@ public abstract class AbstractCinematicEvent implements CinematicEvent {
}
}
/**
* place here the code you want to execute when the event is paused
*/
public abstract void onPause();
/**
@ -138,7 +192,7 @@ public abstract class AbstractCinematicEvent implements CinematicEvent {
* @return
*/
public float getDuration() {
return duration;
return initialDuration / speed;
}
/**
@ -149,7 +203,6 @@ public abstract class AbstractCinematicEvent implements CinematicEvent {
*/
public void setSpeed(float speed) {
this.speed = speed;
duration = initialDuration / speed;
}
/**
@ -182,7 +235,6 @@ public abstract class AbstractCinematicEvent implements CinematicEvent {
*/
public void setInitialDuration(float initialDuration) {
this.initialDuration = initialDuration;
duration = initialDuration / speed;
}
/**
@ -203,6 +255,11 @@ public abstract class AbstractCinematicEvent implements CinematicEvent {
this.loopMode = loopMode;
}
/**
* for serialization only
* @param ex exporter
* @throws IOException
*/
public void write(JmeExporter ex) throws IOException {
OutputCapsule oc = ex.getCapsule(this);
oc.write(playState, "playState", PlayState.Stopped);
@ -211,18 +268,32 @@ public abstract class AbstractCinematicEvent implements CinematicEvent {
oc.write(loopMode, "loopMode", LoopMode.DontLoop);
}
/**
* for serialization only
* @param im importer
* @throws IOException
*/
public void read(JmeImporter im) throws IOException {
InputCapsule ic = im.getCapsule(this);
playState = ic.readEnum("playState", PlayState.class, PlayState.Stopped);
speed = ic.readFloat("speed", 1);
initialDuration = ic.readFloat("initalDuration", 10);
duration = initialDuration / speed;
loopMode = ic.readEnum("loopMode", LoopMode.class, LoopMode.DontLoop);
}
/**
* initialize this event (should be called internally only)
* @param app
* @param cinematic
*/
public void initEvent(Application app, Cinematic cinematic) {
timer = new NanoTimer();
}
/**
* return a list of CinematicEventListener added on this event
* @return
*/
private List<CinematicEventListener> getListeners() {
if (listeners == null) {
listeners = new ArrayList<CinematicEventListener>();
@ -230,10 +301,18 @@ public abstract class AbstractCinematicEvent implements CinematicEvent {
return listeners;
}
/**
* Add a CinematicEventListener to this event
* @param listener CinematicEventListener
*/
public void addListener(CinematicEventListener listener) {
getListeners().add(listener);
}
/**
* remove a CinematicEventListener from this event
* @param listener CinematicEventListener
*/
public void removeListener(CinematicEventListener listener) {
getListeners().remove(listener);
}

@ -85,6 +85,7 @@ public class AnimationTrack extends AbstractCinematicEvent {
@Override
public void initEvent(Application app, Cinematic cinematic) {
super.initEvent(app, cinematic);
if (channel == null) {
Object s = cinematic.getEventData("modelChannels", modelName);
if (s != null && s instanceof AnimChannel) {
@ -107,6 +108,7 @@ public class AnimationTrack extends AbstractCinematicEvent {
channel.getControl().setEnabled(true);
if (playState == PlayState.Stopped) {
channel.setAnim(animationName);
channel.setSpeed(speed);
}
}
@ -117,6 +119,7 @@ public class AnimationTrack extends AbstractCinematicEvent {
@Override
public void onStop() {
channel.getControl().setEnabled(false);
channel.setTime(0);
}
@Override

@ -75,12 +75,13 @@ public class GuiTrack extends AbstractCinematicEvent {
@Override
public void initEvent(Application app, Cinematic cinematic) {
super.initEvent(app, cinematic);
nifty = cinematic.getNifty();
}
@Override
public void onPlay() {
nifty.gotoScreen(screen);
nifty.gotoScreen(screen);
}
@Override

@ -46,6 +46,7 @@ import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.Control;
import com.jme3.system.NanoTimer;
import java.io.IOException;
/**
@ -66,7 +67,7 @@ public class MotionTrack extends AbstractCinematicEvent implements Control {
protected Quaternion rotation;
protected Direction directionType = Direction.None;
protected MotionPath path;
private boolean isControl=true;
private boolean isControl = true;
/**
@ -157,11 +158,12 @@ public class MotionTrack extends AbstractCinematicEvent implements Control {
}
public void update(float tpf) {
if(isControl){
if (isControl) {
if (playState == PlayState.Playing) {
time += tpf * speed;
time = (elapsedTimePause + timer.getTimeInSeconds()) * speed;
onUpdate(tpf);
if (time >= duration && loopMode == loopMode.DontLoop) {
if (time >= initialDuration && loopMode == loopMode.DontLoop) {
stop();
}
}
@ -171,13 +173,13 @@ public class MotionTrack extends AbstractCinematicEvent implements Control {
@Override
public void initEvent(Application app, Cinematic cinematic) {
isControl=false;
super.initEvent(app, cinematic);
isControl = false;
timer = null;
}
public void onUpdate(float tpf) {
spatial.setLocalTranslation(path.interpolatePath(tpf, this));
spatial.setLocalTranslation(path.interpolatePath(tpf * speed, this));
computeTargetDirection();
if (currentValue >= 1.0f) {
@ -270,10 +272,8 @@ public class MotionTrack extends AbstractCinematicEvent implements Control {
control.lookAt = lookAt.clone();
control.upVector = upVector.clone();
control.rotation = rotation.clone();
control.duration = duration;
control.initialDuration = initialDuration;
control.speed = speed;
control.duration = duration;
control.loopMode = loopMode;
control.directionType = directionType;

@ -78,7 +78,7 @@ public class PositionTrack extends AbstractCinematicEvent {
if (playState != playState.Paused) {
startPosition = spatial.getWorldTranslation().clone();
}
if (duration == 0 && spatial != null) {
if (initialDuration == 0 && spatial != null) {
spatial.setLocalTranslation(endPosition);
}
@ -87,7 +87,7 @@ public class PositionTrack extends AbstractCinematicEvent {
@Override
public void onUpdate(float tpf) {
if (spatial != null) {
value += Math.min(tpf * speed / duration, 1.0f);
value = Math.min(time / initialDuration, 1.0f);
Vector3f pos = FastMath.interpolateLinear(value, startPosition, endPosition);
spatial.setLocalTranslation(pos);
}

@ -78,7 +78,7 @@ public class RotationTrack extends AbstractCinematicEvent {
if (playState != playState.Paused) {
startRotation.set(spatial.getWorldRotation());
}
if (duration == 0 && spatial != null) {
if (initialDuration == 0 && spatial != null) {
spatial.setLocalRotation(endRotation);
stop();
}
@ -87,7 +87,7 @@ public class RotationTrack extends AbstractCinematicEvent {
@Override
public void onUpdate(float tpf) {
if (spatial != null) {
value += Math.min(tpf * speed / duration, 1.0f);
value = Math.min(time / initialDuration, 1.0f);
TempVars vars = TempVars.get();
Quaternion q = vars.quat1;
q.set(startRotation).slerp(endRotation, value);

@ -78,7 +78,7 @@ public class ScaleTrack extends AbstractCinematicEvent {
if (playState != playState.Paused) {
startScale = spatial.getWorldScale().clone();
}
if (duration == 0 && spatial != null) {
if (initialDuration == 0 && spatial != null) {
spatial.setLocalScale(endScale);
stop();
}
@ -87,7 +87,7 @@ public class ScaleTrack extends AbstractCinematicEvent {
@Override
public void onUpdate(float tpf) {
if (spatial != null) {
value += Math.min(tpf * speed / duration, 1.0f);
value = Math.min(time / initialDuration, 1.0f);
spatial.setLocalScale(FastMath.interpolateLinear(value, startScale, endScale));
}
}

@ -107,7 +107,8 @@ public class SoundTrack extends AbstractCinematicEvent {
}
@Override
public void initEvent(Application app, Cinematic cinematic) {
public void initEvent(Application app, Cinematic cinematic) {
super.initEvent(app, cinematic);
audioNode = new AudioNode(app.getAssetManager(), path, stream);
setLoopMode(loopMode);

@ -23,8 +23,7 @@ public class SubtitleTrack extends GuiTrack{
@Override
public void onPlay() {
super.onPlay();
//REMY FIX THIS
//nifty.getScreen(screen).findElementByName("text").getRenderer(TextRenderer.class).changeText(text);
nifty.getScreen(screen).findElementByName("text").getRenderer(TextRenderer.class).setText(text);
}

@ -64,6 +64,8 @@ import com.jme3.scene.Geometry;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;
import com.jme3.shadow.PssmShadowRenderer;
import com.jme3.system.NanoTimer;
import com.jme3.system.lwjgl.LwjglTimer;
public class TestCinematic extends SimpleApplication {
@ -79,6 +81,8 @@ public class TestCinematic extends SimpleApplication {
public static void main(String[] args) {
TestCinematic app = new TestCinematic();
app.start();
}
@ -106,6 +110,7 @@ public class TestCinematic extends SimpleApplication {
@Override
public void onPlay() {
fade.setDuration(1f/cinematic.getSpeed());
fade.setValue(0);
fade.fadeIn();
}
@ -148,6 +153,7 @@ public class TestCinematic extends SimpleApplication {
@Override
public void onPlay() {
fade.setDuration(1f/cinematic.getSpeed());
fade.fadeOut();
}
@ -164,10 +170,13 @@ public class TestCinematic extends SimpleApplication {
}
});
final NanoTimer myTimer = new NanoTimer();
cinematic.addListener(new CinematicEventListener() {
public void onPlay(CinematicEvent cinematic) {
chaseCam.setEnabled(false);
myTimer.reset();
System.out.println("play");
}
@ -180,9 +189,13 @@ public class TestCinematic extends SimpleApplication {
chaseCam.setEnabled(true);
fade.setValue(1);
System.out.println("stop");
System.out.println((float)myTimer.getTime()/(float)myTimer.getResolution());
}
});
cinematic.setSpeed(2);
flyCam.setEnabled(false);
chaseCam = new ChaseCamera(cam, model, inputManager);
initInputs();
@ -270,4 +283,9 @@ public class TestCinematic extends SimpleApplication {
};
inputManager.addListener(acl, "togglePause");
}
}

Loading…
Cancel
Save