1
+ /*
2
+ * Copyright (c) 2009-2022 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
+ */
1
32
package com .jme3 .anim .tween .action ;
2
33
3
34
import com .jme3 .anim .util .HasLocalTransform ;
35
+ import com .jme3 .math .FastMath ;
4
36
import com .jme3 .math .Transform ;
5
37
38
+ import java .util .Arrays ;
6
39
import java .util .Collection ;
7
40
import java .util .HashMap ;
8
41
import java .util .Map ;
@@ -14,6 +47,7 @@ public class BlendAction extends BlendableAction {
14
47
final private BlendSpace blendSpace ;
15
48
private float blendWeight ;
16
49
final private double [] timeFactor ;
50
+ private double [] speedFactors ;
17
51
final private Map <HasLocalTransform , Transform > targetMap = new HashMap <>();
18
52
19
53
public BlendAction (BlendSpace blendSpace , BlendableAction ... actions ) {
@@ -47,6 +81,10 @@ public BlendAction(BlendSpace blendSpace, BlendableAction... actions) {
47
81
}
48
82
}
49
83
}
84
+
85
+ // Calculate default factors that dynamically adjust speed to resolve
86
+ // slow motion effect on stretched actions.
87
+ applyDefaultSpeedFactors ();
50
88
}
51
89
52
90
@ Override
@@ -85,6 +123,58 @@ public BlendSpace getBlendSpace() {
85
123
return blendSpace ;
86
124
}
87
125
126
+ @ Override
127
+ public double getSpeed () {
128
+ if (speedFactors != null ) {
129
+ return super .getSpeed () * FastMath .interpolateLinear (blendWeight ,
130
+ (float ) speedFactors [firstActiveIndex ],
131
+ (float ) speedFactors [secondActiveIndex ]);
132
+ }
133
+
134
+ return super .getSpeed ();
135
+ }
136
+
137
+ /**
138
+ * @return The speed factor or null if there is none
139
+ */
140
+ public double [] getSpeedFactors () {
141
+ return speedFactors ;
142
+ }
143
+
144
+ /**
145
+ * Used to resolve the slow motion side effect caused by stretching actions that
146
+ * doesn't have the same length.
147
+ *
148
+ * @param speedFactors The speed factors for each child action. BlendAction will
149
+ * interpolate factor for current frame based on blend weight
150
+ * and will multiply it to speed.
151
+ */
152
+ public void setSpeedFactors (double ... speedFactors ) {
153
+ if (speedFactors .length != actions .length ) {
154
+ throw new IllegalArgumentException ("Array length must be " + actions .length );
155
+ }
156
+
157
+ this .speedFactors = speedFactors ;
158
+ }
159
+
160
+ public void clearSpeedFactors () {
161
+ this .speedFactors = null ;
162
+ }
163
+
164
+ /**
165
+ * BlendAction will stretch it's child actions if they don't have the same length.
166
+ * This might cause stretched animations to run slowly. This method generates factors
167
+ * based on how much actions are stretched. Multiplying this factor to base speed will
168
+ * resolve the slow-motion side effect caused by stretching. BlendAction will use the
169
+ * blend weight taken from BlendSpace to interpolate the speed factor for current frame.
170
+ */
171
+ public void applyDefaultSpeedFactors () {
172
+ double [] factors = Arrays .stream (getActions ())
173
+ .mapToDouble (action -> getLength () / action .getLength ())
174
+ .toArray ();
175
+ setSpeedFactors (factors );
176
+ }
177
+
88
178
protected void setFirstActiveIndex (int index ) {
89
179
this .firstActiveIndex = index ;
90
180
}
0 commit comments