OSDN Git Service

aac807358e9b85b38cfd46a1bfbba4679403c08f
[mikumikustudio/MikuMikuStudio.git] / src / com / jme / curve / CurveController.java
1 /*
2  * Copyright (c) 2003-2009 jMonkeyEngine
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17  *   may be used to endorse or promote products derived from this software
18  *   without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 package com.jme.curve;
34
35 import java.io.IOException;
36
37 import com.jme.math.Vector3f;
38 import com.jme.scene.Controller;
39 import com.jme.scene.Spatial;
40 import com.jme.util.export.InputCapsule;
41 import com.jme.util.export.JMEExporter;
42 import com.jme.util.export.JMEImporter;
43 import com.jme.util.export.OutputCapsule;
44
45 /**
46  * <code>CurveController</code> defines a controller that moves a supplied
47  * <code>Spatial</code> object along a curve. Attributes of the curve are set
48  * such as the up vector (if not set, the spacial object will roll along the
49  * curve), the orientation precision defines how accurate the orientation of the
50  * spatial will be.
51  * @author Mark Powell
52  * @version $Id: CurveController.java,v 1.14 2007/02/04 14:37:56 sunsett Exp $
53  */
54 public class CurveController extends Controller {
55     private static final long serialVersionUID = 1L;
56         private Spatial mover;
57     private Curve curve;
58     private Vector3f up;
59     private float orientationPrecision = 0.1f;
60     private float currentTime = 0.0f;
61     private float deltaTime = 0.0f;
62
63     private boolean cycleForward = true;
64     private boolean autoRotation = false;
65
66     /**
67      * Constructor instantiates a new <code>CurveController</code> object.
68      * The curve object that the controller operates on and the spatial object
69      * that is moved is specified during construction.
70      * @param curve the curve to operate on.
71      * @param mover the spatial to move.
72      */
73     public CurveController(Curve curve, Spatial mover) {
74         this.curve = curve;
75         this.mover = mover;
76         setUpVector(new Vector3f(0,1,0));
77         setMinTime(0);
78         setMaxTime(Float.MAX_VALUE);
79         setRepeatType(Controller.RT_CLAMP);
80         setSpeed(1.0f);
81     }
82
83     /**
84      * Constructor instantiates a new <code>CurveController</code> object.
85      * The curve object that the controller operates on and the spatial object
86      * that is moved is specified during construction. The game time to
87      * start and the game time to finish is also supplied.
88      * @param curve the curve to operate on.
89      * @param mover the spatial to move.
90      * @param minTime the time to start the controller.
91      * @param maxTime the time to end the controller.
92      */
93     public CurveController(
94         Curve curve,
95         Spatial mover,
96         float minTime,
97         float maxTime) {
98         this.curve = curve;
99         this.mover = mover;
100         setMinTime(minTime);
101         setMaxTime(maxTime);
102         setRepeatType(Controller.RT_CLAMP);
103     }
104
105     /**
106      *
107      * <code>setUpVector</code> sets the locking vector for the spatials up
108      * vector. This prevents rolling along the curve and allows for a better
109      * tracking.
110      * @param up the vector to lock as the spatials up vector.
111      */
112     public void setUpVector(Vector3f up) {
113         this.up = up;
114     }
115
116     /**
117      *
118      * <code>setOrientationPrecision</code> sets a precision value for the
119      * spatials orientation. The smaller the number the higher the precision.
120      * By default 0.1 is used, and typically does not require changing.
121      * @param value the precision value of the spatial's orientation.
122      */
123     public void setOrientationPrecision(float value) {
124         orientationPrecision = value;
125     }
126
127     /**
128      *
129      * <code>setAutoRotation</code> determines if the object assigned to
130      * the controller will rotate with the curve or just following the
131      * curve.
132      * @param value true if the object is to rotate with the curve, false
133      *      otherwise.
134      */
135     public void setAutoRotation(boolean value) {
136         autoRotation = value;
137     }
138
139     /**
140      *
141      * <code>isAutoRotating</code> returns true if the object is rotating with
142      * the curve and false if it is not.
143      * @return true if the object is following the curve, false otherwise.
144      */
145     public boolean isAutoRotating() {
146         return autoRotation;
147     }
148
149     /**
150      * <code>update</code> moves a spatial along the given curve for along a
151      * time period.
152      * @see com.jme.scene.Controller#update(float)
153      */
154     public void update(float time) {
155         if(mover == null || curve == null || up == null) {
156             return;
157         }
158         currentTime += time * getSpeed();
159
160         if (currentTime >= getMinTime() && currentTime <= getMaxTime()) {
161
162             if (getRepeatType() == RT_CLAMP) {
163                 deltaTime = currentTime - getMinTime();
164                 mover.setLocalTranslation(curve.getPoint(deltaTime,mover.getLocalTranslation()));
165                 if(autoRotation) {
166                     mover.setLocalRotation(
167                         curve.getOrientation(
168                             deltaTime,
169                             orientationPrecision,
170                             up));
171                 }
172             } else if (getRepeatType() == RT_WRAP) {
173                 deltaTime = (currentTime - getMinTime()) % 1.0f;
174                 if (deltaTime > 1) {
175                     currentTime = 0;
176                     deltaTime = 0;
177                 }
178                 mover.setLocalTranslation(curve.getPoint(deltaTime,mover.getLocalTranslation()));
179                 if(autoRotation) {
180                     mover.setLocalRotation(
181                         curve.getOrientation(
182                             deltaTime,
183                             orientationPrecision,
184                             up));
185                 }
186             } else if (getRepeatType() == RT_CYCLE) {
187                 float prevTime = deltaTime;
188                 deltaTime = (currentTime - getMinTime()) % 1.0f;
189                 if (prevTime > deltaTime) {
190                     cycleForward = !cycleForward;
191                 }
192                 if (cycleForward) {
193
194                     mover.setLocalTranslation(curve.getPoint(deltaTime,mover.getLocalTranslation()));
195                     if(autoRotation) {
196                         mover.setLocalRotation(
197                             curve.getOrientation(
198                                 deltaTime,
199                                 orientationPrecision,
200                                 up));
201                     }
202                 } else {
203                     mover.setLocalTranslation(
204                         curve.getPoint(1.0f - deltaTime,mover.getLocalTranslation()));
205                     if(autoRotation) {
206                         mover.setLocalRotation(
207                             curve.getOrientation(
208                                 1.0f - deltaTime,
209                                 orientationPrecision,
210                                 up));
211                     }
212                 }
213             } else {
214                 return;
215             }
216         }
217     }
218     
219     public void reset() {
220         this.currentTime = 0;
221     }
222     
223     public void write(JMEExporter e) throws IOException {
224         super.write(e);
225         OutputCapsule capsule = e.getCapsule(this);
226         capsule.write(mover, "mover", null);
227         capsule.write(curve, "Curve", null);
228         capsule.write(up, "up", null);
229         capsule.write(orientationPrecision, "orientationPrecision", 0.1f);
230         capsule.write(cycleForward, "cycleForward", true);
231         capsule.write(autoRotation, "autoRotation", false);
232     }
233
234     public void read(JMEImporter e) throws IOException {
235         super.read(e);
236         InputCapsule capsule = e.getCapsule(this);
237         
238         mover = (Spatial)capsule.readSavable("mover", null);
239         curve = (Curve)capsule.readSavable("curve", null);
240         up = (Vector3f)capsule.readSavable("up", null);
241         orientationPrecision = capsule.readFloat("orientationPrecision", 0.1f);
242         cycleForward = capsule.readBoolean("cycleForward", true);
243         autoRotation = capsule.readBoolean("autoRotation", false);
244     }
245 }