Bläddra i källkod

Cinematic changes :
- more consistency in the way to handle time
- Complete refactoring of MotionPath interpolation (simpler and way faster)
- Time seeking should now work correctly.

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9168 75d07b2b-3a1a-0410-a2c5-0572b91ccdca

rem..om 13 år sedan
förälder
incheckning
9836918a07

+ 60 - 75
engine/src/core/com/jme3/cinematic/Cinematic.java

@@ -35,6 +35,7 @@ import com.jme3.animation.LoopMode;
 import com.jme3.app.Application;
 import com.jme3.app.state.AppState;
 import com.jme3.app.state.AppStateManager;
+import com.jme3.asset.TextureKey;
 import com.jme3.cinematic.events.AbstractCinematicEvent;
 import com.jme3.cinematic.events.CinematicEvent;
 import com.jme3.cinematic.events.CinematicEventListener;
@@ -58,7 +59,7 @@ import java.util.logging.Logger;
  * @author Nehon
  */
 public class Cinematic extends AbstractCinematicEvent implements AppState {
-
+    
     private static final Logger logger = Logger.getLogger(Application.class.getName());
     private Node scene;
     protected TimeLine timeLine = new TimeLine();
@@ -67,36 +68,33 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
     private Map<String, CameraNode> cameras = new HashMap<String, CameraNode>();
     private CameraNode currentCam;
     private boolean initialized = false;
-    private Map<String, Map<String, Object>> eventsData;
-    private int scheduledPause = -1;
-
+    private Map<String, Map<String, Object>> eventsData;    
+    
     public Cinematic() {
     }
-
+    
     public Cinematic(Node scene) {
         this.scene = scene;
     }
-
+    
     public Cinematic(Node scene, float initialDuration) {
         super(initialDuration);
         this.scene = scene;
     }
-
+    
     public Cinematic(Node scene, LoopMode loopMode) {
         super(loopMode);
         this.scene = scene;
     }
-
+    
     public Cinematic(Node scene, float initialDuration, LoopMode loopMode) {
         super(initialDuration, loopMode);
         this.scene = scene;
     }
-
+    
     @Override
     public void onPlay() {
         if (isInitialized()) {
-            scheduledPause = -1;
-            //enableCurrentCam(true);
             if (playState == PlayState.Paused) {
                 for (int i = 0; i < cinematicEvents.size(); i++) {
                     CinematicEvent ce = cinematicEvents.get(i);
@@ -107,7 +105,7 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
             }
         }
     }
-
+    
     @Override
     public void onStop() {
         time = 0;
@@ -118,7 +116,7 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
         }
         enableCurrentCam(false);
     }
-
+    
     @Override
     public void onPause() {
         for (int i = 0; i < cinematicEvents.size(); i++) {
@@ -128,28 +126,28 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
             }
         }
     }
-
+    
     @Override
     public void write(JmeExporter ex) throws IOException {
         super.write(ex);
         OutputCapsule oc = ex.getCapsule(this);
-
+        
         oc.writeSavableArrayList((ArrayList) cinematicEvents, "cinematicEvents", null);
         oc.writeStringSavableMap(cameras, "cameras", null);
         oc.write(timeLine, "timeLine", null);
-
+        
     }
-
+    
     @Override
     public void read(JmeImporter im) throws IOException {
         super.read(im);
         InputCapsule ic = im.getCapsule(this);
-
+        
         cinematicEvents = ic.readSavableArrayList("cinematicEvents", null);
         cameras = (Map<String, CameraNode>) ic.readStringSavableMap("cameras", null);
         timeLine = (TimeLine) ic.readSavable("timeLine", null);
     }
-
+    
     @Override
     public void setSpeed(float speed) {
         super.setSpeed(speed);
@@ -157,67 +155,53 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
             CinematicEvent ce = cinematicEvents.get(i);
             ce.setSpeed(speed);
         }
-
-
+        
+        
     }
-
+    
     public void initialize(AppStateManager stateManager, Application app) {
         initEvent(app, this);
         for (CinematicEvent cinematicEvent : cinematicEvents) {
             cinematicEvent.initEvent(app, this);
         }
-
+        
         initialized = true;
     }
-
+    
     public boolean isInitialized() {
         return initialized;
     }
-
+    
     public void setEnabled(boolean enabled) {
         if (enabled) {
             play();
         }
     }
-
+    
     public boolean isEnabled() {
         return playState == PlayState.Playing;
     }
-
+    
     public void stateAttached(AppStateManager stateManager) {
     }
-
+    
     public void stateDetached(AppStateManager stateManager) {
         stop();
     }
-
+    
     public void update(float tpf) {
         if (isInitialized()) {
             internalUpdate(tpf);
         }
     }
-
-    private void step() {
-        if (playState != PlayState.Playing) {
-            play();
-            scheduledPause = 2;
-        }
-    }
-
+    
     @Override
-    public void onUpdate(float tpf) {
-        if (scheduledPause >= 0) {
-            if (scheduledPause == 0) {
-                pause();
-            }
-            scheduledPause--;
-        }
-
+    public void onUpdate(float tpf) {        
         for (int i = 0; i < cinematicEvents.size(); i++) {
             CinematicEvent ce = cinematicEvents.get(i);
             ce.internalUpdate(tpf);
         }
-
+        
         int keyFrameIndex = timeLine.getKeyFrameIndexFromTime(time);
 
         //iterate to make sure every key frame is triggered
@@ -227,13 +211,13 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
                 keyFrame.trigger();
             }
         }
-
+        
         lastFetchedKeyFrame = keyFrameIndex;
     }
-
+    
     @Override
     public void setTime(float time) {
-        super.setTime(time);     
+        super.setTime(time);        
         int keyFrameIndex = timeLine.getKeyFrameIndexFromTime(time);
 
         //triggering all the event from start to "time" 
@@ -242,17 +226,18 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
             KeyFrame keyFrame = timeLine.get(i);
             if (keyFrame != null) {
                 for (CinematicEvent ce : keyFrame.getCinematicEvents()) {
-                    if (playState == PlayState.Playing) {
-                        ce.play();
-                    }
+                    ce.play();                    
                     ce.setTime(time - timeLine.getKeyFrameTime(keyFrame));
                 }
             }
         }
+        if (playState != PlayState.Playing) {
+            pause();
+        }
 
-        step();
+        //  step();
     }
-
+    
     public KeyFrame addCinematicEvent(float timeStamp, CinematicEvent cinematicEvent) {
         KeyFrame keyFrame = timeLine.getKeyFrameAtTime(timeStamp);
         if (keyFrame == null) {
@@ -263,13 +248,13 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
         cinematicEvents.add(cinematicEvent);
         return keyFrame;
     }
-
+    
     public void render(RenderManager rm) {
     }
-
+    
     public void postRender() {
     }
-
+    
     public void cleanup() {
     }
 
@@ -285,10 +270,10 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
                 d = (ce.getDuration() * ce.getSpeed());
             }
         }
-
+        
         initialDuration = d;
     }
-
+    
     public CameraNode bindCamera(String cameraName, Camera cam) {
         CameraNode node = new CameraNode(cameraName, cam);
         node.setControlDir(ControlDirection.SpatialToCamera);
@@ -297,17 +282,17 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
         scene.attachChild(node);
         return node;
     }
-
+    
     public CameraNode getCamera(String cameraName) {
         return cameras.get(cameraName);
     }
-
+    
     private void enableCurrentCam(boolean enabled) {
         if (currentCam != null) {
             currentCam.getControl(CameraControl.class).setEnabled(enabled);
         }
     }
-
+    
     public void setActiveCamera(String cameraName) {
         enableCurrentCam(false);
         currentCam = cameras.get(cameraName);
@@ -316,51 +301,51 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
         }
         enableCurrentCam(true);
     }
-
+    
     public void activateCamera(final float timeStamp, final String cameraName) {
         addCinematicEvent(timeStamp, new AbstractCinematicEvent() {
-
+            
             @Override
             public void play() {
                 super.play();
                 stop();
             }
-
+            
             @Override
             public void onPlay() {
                 setActiveCamera(cameraName);
             }
-
+            
             @Override
             public void onUpdate(float tpf) {
             }
-
+            
             @Override
             public void onStop() {
             }
-
+            
             @Override
             public void onPause() {
             }
-
+            
             @Override
             public void setTime(float time) {
                 play();
             }
         });
     }
-
+    
     public void setScene(Node scene) {
         this.scene = scene;
     }
-
+    
     private Map<String, Map<String, Object>> getEventsData() {
         if (eventsData == null) {
             eventsData = new HashMap<String, Map<String, Object>>();
         }
         return eventsData;
     }
-
+    
     public void putEventData(String type, String name, Object object) {
         Map<String, Map<String, Object>> data = getEventsData();
         Map<String, Object> row = data.get(type);
@@ -369,7 +354,7 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
         }
         row.put(name, object);
     }
-
+    
     public Object getEventData(String type, String name) {
         if (eventsData != null) {
             Map<String, Object> row = eventsData.get(type);
@@ -379,7 +364,7 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
         }
         return null;
     }
-
+    
     public Savable removeEventData(String type, String name) {
         if (eventsData != null) {
             Map<String, Object> row = eventsData.get(type);
@@ -389,7 +374,7 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
         }
         return null;
     }
-
+    
     public Node getScene() {
         return scene;
     }

+ 16 - 49
engine/src/core/com/jme3/cinematic/MotionPath.java

@@ -81,56 +81,23 @@ public class MotionPath implements Savable {
         TempVars vars = TempVars.get();
         Vector3f temp = vars.vect1;
         Vector3f tmpVector = vars.vect2;
-        switch (spline.getType()) {
-            case CatmullRom:
-
-                //this iterative process is done to keep the spatial travel at a constant speed on the path even if 
-                //waypoints are not equally spread over the path
-
-                // we compute the theorical distance that the spatial should travel on this frame
-                val = (time * (spline.getTotalLength() / control.getDuration())) - control.getTraveledDistance();
-                //adding and epsilon value to the control currents value
-                control.setCurrentValue(control.getCurrentValue() + eps);
-                //computing the new position at current value
-                spline.interpolate(control.getCurrentValue(), control.getCurrentWayPoint(), temp);
-                //computing traveled distance at current value
-                float dist = getDist(control, temp, tmpVector);
-
-                //While the distance traveled this frame is below the theorical distance we iterate the obove computation
-                while (dist < val) {
-                    //storing the distance traveled this frame
-                    traveledDistance = dist;
-                    control.setCurrentValue(control.getCurrentValue() + eps);
-                    spline.interpolate(control.getCurrentValue(), control.getCurrentWayPoint(), temp);
-                    dist = getDist(control, temp, tmpVector);
-                }
-                //compute the direction of the spline
-                if (control.needsDirection()) {
-                    tmpVector.set(temp);
-                    control.setDirection(tmpVector.subtractLocal(control.getSpatial().getLocalTranslation()).normalizeLocal());
-                }
-                //updating traveled distance to the total distance traveled by the spatial since the start
-                traveledDistance += control.getTraveledDistance();
-                break;
-            case Linear:
-                //distance traveled this frame
-                val = (time * (spline.getTotalLength() / control.getDuration())) - control.getTraveledDistance();
-                // computing total traveled distance
-                traveledDistance = control.getTraveledDistance() + val;
-                //computing interpolation ratio for this frame
-                val = val / spline.getSegmentsLength().get(control.getCurrentWayPoint());
-                control.setCurrentValue(Math.min(control.getCurrentValue() + val, 1.0f));
-                //interpolationg position
-                spline.interpolate(control.getCurrentValue(), control.getCurrentWayPoint(), temp);
-                //computing line direction
-                if (control.needsDirection()) {
-                    tmpVector.set(spline.getControlPoints().get(control.getCurrentWayPoint() + 1));
-                    control.setDirection(tmpVector.subtractLocal(spline.getControlPoints().get(control.getCurrentWayPoint())).normalizeLocal());
-                }
-                break;
-            default:
-                break;
+        //computing traveled distance according to new time
+        traveledDistance = time * (getLength() / control.getInitialDuration());
+
+        //getting waypoint index and current value from new traveled distance
+        Vector2f v = getWayPointIndexForDistance(traveledDistance);
+
+        //setting values
+        control.setCurrentWayPoint((int) v.x);
+        control.setCurrentValue(v.y);
+        
+        //interpolating new position
+        getSpline().interpolate(control.getCurrentValue(), control.getCurrentWayPoint(), temp);
+        if (control.needsDirection()) {
+            tmpVector.set(temp);
+            control.setDirection(tmpVector.subtractLocal(control.getSpatial().getLocalTranslation()).normalizeLocal());
         }
+
         control.getSpatial().setLocalTranslation(temp);
         vars.release();
         return traveledDistance;

+ 4 - 23
engine/src/core/com/jme3/cinematic/events/AbstractCinematicEvent.java

@@ -39,8 +39,6 @@ import com.jme3.export.InputCapsule;
 import com.jme3.export.JmeExporter;
 import com.jme3.export.JmeImporter;
 import com.jme3.export.OutputCapsule;
-import com.jme3.system.NanoTimer;
-import com.jme3.system.Timer;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
@@ -59,12 +57,8 @@ public abstract class AbstractCinematicEvent implements CinematicEvent {
     protected float initialDuration = 10;
     protected LoopMode loopMode = LoopMode.DontLoop;
     protected float time = 0;
-    protected Timer timer;
-    protected float start = 0;
-    /**
-     * the last time the event was paused
-     */
-    protected float elapsedTimePause = 0;
+    protected boolean resuming = false;
+    
     /**
      * the list of listeners
      */
@@ -108,12 +102,6 @@ public abstract class AbstractCinematicEvent implements CinematicEvent {
     public void play() {
         onPlay();
         playState = PlayState.Playing;
-        if (timer == null) {
-            //only when used as a control
-            timer = new NanoTimer();
-        }
-        start = timer.getTimeInSeconds();
-        //timer.reset();
         if (listeners != null) {
             for (int i = 0; i < listeners.size(); i++) {
                 CinematicEventListener cel = listeners.get(i);
@@ -133,7 +121,7 @@ public abstract class AbstractCinematicEvent implements CinematicEvent {
      */
     public void internalUpdate(float tpf) {
         if (playState == PlayState.Playing) {
-            time = time+ (tpf * speed);
+            time = time + (tpf * speed);
             //time = elapsedTimePause + (timer.getTimeInSeconds() - start) * speed;
 
             onUpdate(tpf);
@@ -157,7 +145,6 @@ 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);
@@ -177,7 +164,6 @@ public abstract class AbstractCinematicEvent implements CinematicEvent {
     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);
@@ -291,8 +277,6 @@ public abstract class AbstractCinematicEvent implements CinematicEvent {
      * @param cinematic 
      */
     public void initEvent(Application app, Cinematic cinematic) {
-        timer = app.getContext().getTimer();
-        //timer = new NanoTimer();
     }
 
     /**
@@ -327,10 +311,7 @@ public abstract class AbstractCinematicEvent implements CinematicEvent {
      * @param time the time to fast forward to
      */
     public void setTime(float time) {
-        elapsedTimePause = time / speed;
-        if (playState == PlayState.Playing) {
-            start = timer.getTimeInSeconds();
-        }
+        this.time = time / speed;
     }
 
     public float getTime() {

+ 1 - 0
engine/src/core/com/jme3/cinematic/events/AnimationTrack.java

@@ -122,6 +122,7 @@ public class AnimationTrack extends AbstractCinematicEvent {
             
         }
         channel.setTime(t);
+        channel.getControl().update(0);
     }
 
     @Override

+ 2 - 2
engine/src/core/com/jme3/cinematic/events/CinematicEvent.java

@@ -131,8 +131,8 @@ public interface CinematicEvent extends Savable {
      * When this method is invoked, the event should fast forward to the given time according tim 0 is the start of the event.
      * @param time the time to fast forward to
      */
-    public void setTime(float time);
-    
+    public void setTime(float time);    
+   
     /**
      * returns the current time of the cinematic event
      * @return the time

+ 10 - 33
engine/src/core/com/jme3/cinematic/events/MotionTrack.java

@@ -165,10 +165,12 @@ public class MotionTrack extends AbstractCinematicEvent implements Control {
         if (isControl) {
 
             if (playState == PlayState.Playing) {
-                time = (elapsedTimePause + timer.getTimeInSeconds() - start) * speed;
-                onUpdate(tpf);
+                time = time + (tpf * speed);
+
                 if (time >= initialDuration && loopMode == loopMode.DontLoop) {
                     stop();
+                } else {
+                    onUpdate(tpf);
                 }
             }
         }
@@ -183,40 +185,12 @@ public class MotionTrack extends AbstractCinematicEvent implements Control {
     @Override
     public void setTime(float time) {
         super.setTime(time);
-
-        //computing traveled distance according to new time
-        traveledDistance = time * (path.getLength() / initialDuration);
-
-        TempVars vars = TempVars.get();
-        Vector3f temp = vars.vect1;
-        //getting waypoint index and current value from new traveled distance
-        Vector2f v = path.getWayPointIndexForDistance(traveledDistance);
-        //setting values
-        currentWayPoint = (int) v.x;
-        setCurrentValue(v.y);
-        //interpolating new position
-        path.getSpline().interpolate(getCurrentValue(), getCurrentWayPoint(), temp);
-        //setting new position to the spatial
-        spatial.setLocalTranslation(temp);
-        vars.release();
+        onUpdate(0);
     }
 
-    public void onUpdate(float tpf) {       
+    public void onUpdate(float tpf) {
         traveledDistance = path.interpolatePath(time, this);
         computeTargetDirection();
-
-        if (currentValue >= 1.0f) {
-            currentValue = 0;
-            currentWayPoint++;
-            path.triggerWayPointReach(currentWayPoint, this);
-        }
-        if (currentWayPoint == path.getNbWayPoints() - 1) {
-            if (loopMode == LoopMode.Loop) {
-                currentWayPoint = 0;
-            } else {
-                stop();
-            }
-        }
     }
 
     @Override
@@ -346,7 +320,10 @@ public class MotionTrack extends AbstractCinematicEvent implements Control {
      *
      */
     public void setCurrentWayPoint(int currentWayPoint) {
-        this.currentWayPoint = currentWayPoint;
+        if (this.currentWayPoint != currentWayPoint) {
+            this.currentWayPoint = currentWayPoint;
+            path.triggerWayPointReach(currentWayPoint, this);
+        }
     }
 
     /**

+ 14 - 10
engine/src/core/com/jme3/cinematic/events/SoundTrack.java

@@ -48,7 +48,7 @@ import java.io.IOException;
 public class SoundTrack extends AbstractCinematicEvent {
 
     protected String path;
-    protected AudioNode audioNode;    
+    protected AudioNode audioNode;
     protected boolean stream = false;
 
     /**
@@ -82,7 +82,7 @@ public class SoundTrack extends AbstractCinematicEvent {
     }
 
     public SoundTrack(String path, boolean stream, float initialDuration, LoopMode loopMode) {
-        super(initialDuration, loopMode);        
+        super(initialDuration, loopMode);
         this.path = path;
         this.stream = stream;
     }
@@ -93,12 +93,12 @@ public class SoundTrack extends AbstractCinematicEvent {
     }
 
     public SoundTrack(String path, LoopMode loopMode) {
-        super(loopMode);        
+        super(loopMode);
         this.path = path;
     }
 
     public SoundTrack(String path, float initialDuration, LoopMode loopMode) {
-        super(initialDuration, loopMode);        
+        super(initialDuration, loopMode);
         this.path = path;
     }
 
@@ -106,7 +106,7 @@ 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);
@@ -115,23 +115,27 @@ public class SoundTrack extends AbstractCinematicEvent {
     @Override
     public void setTime(float time) {
         super.setTime(time);
-        //TODO has to be implemented in the audioRenderer
+        //can occur on rewind
+        if (time < 0) {            
+            stop();
+        }
+        audioNode.setTimeOffset(time);
     }
 
     @Override
     public void onPlay() {
-        audioNode.play();        
+        audioNode.play();
     }
 
     @Override
     public void onStop() {
         audioNode.stop();
-        
+
     }
 
     @Override
     public void onPause() {
-        audioNode.pause();        
+        audioNode.pause();
     }
 
     @Override
@@ -152,7 +156,7 @@ public class SoundTrack extends AbstractCinematicEvent {
     @Override
     public void setLoopMode(LoopMode loopMode) {
         super.setLoopMode(loopMode);
-        
+
         if (loopMode != LoopMode.DontLoop) {
             audioNode.setLooping(true);
         } else {