@@ -10,6 +10,12 @@ namespace FbxExporters.UnitTests
10
10
{
11
11
using CustomExtensions ;
12
12
13
+ public enum RotationInterpolation {
14
+ kEuler = 3 ,
15
+ kMixed = ( 3 + 4 ) ,
16
+ kQuaternion = 4
17
+ } ;
18
+
13
19
public class AnimationTestDataClass
14
20
{
15
21
// TODO: remove items that become supported by exporter
@@ -71,9 +77,11 @@ public static IEnumerable TestCases4 {
71
77
// specify continuous rotations
72
78
public static IEnumerable TestCases5 {
73
79
get {
74
- yield return new TestCaseData ( false /*use quaternion values*/ , m_keytimes5 , m_keyRotValues5 . Concat ( m_keyPosValues5 ) . ToArray ( ) ) . Returns ( 3 ) ;
75
- // Uni-35616 continuous rotations doesn't work with quaternions
76
- // yield return new TestCaseData (true /*use quaternion values*/, m_keytimes5, m_keyRotValues5.Concat(m_keyPosValues5).ToArray()).Returns (3);
80
+ yield return new TestCaseData ( RotationInterpolation . kEuler /*use quaternion values*/ , m_keytimes5 , m_keyPosValues5 , m_keyRotValues5 ) . Returns ( 3 ) ;
81
+ // Uni-35616 can't programmatically define a Euler (Quaternion) mix.
82
+ // yield return new TestCaseData (RotationInterpolation.kMixed /*use euler&quaternion values*/, m_keytimes5, m_keyPosValues5, m_keyRotValues5).Returns (3);
83
+ // Uni-35616 doesn't work with quaternions; rotations don't exceed 180
84
+ // yield return new TestCaseData (RotationInterpolation.kQuaternion /*use quaternion values*/, m_keytimes5, m_keyPosValues5, m_keyRotValues5).Returns (3);
77
85
}
78
86
}
79
87
}
@@ -134,11 +142,11 @@ public class KeyData
134
142
public GameObject targetObject ;
135
143
136
144
public virtual int NumKeys { get { return 0 ; } }
137
- public virtual int NumComponents { get { return 0 ; } }
145
+ public virtual int NumProperties { get { return 0 ; } }
138
146
public virtual float [ ] GetKeyValues ( int id ) { return null ; }
139
147
public virtual float [ ] GetAltKeyValues ( int id ) { return GetKeyValues ( id ) ; }
140
- public virtual string GetComponentName ( int id ) { return null ; }
141
- public virtual int FindComponent ( string name ) { return - 1 ; }
148
+ public virtual string GetPropertyName ( int id ) { return null ; }
149
+ public virtual int GetIndexOf ( string name ) { return - 1 ; }
142
150
143
151
}
144
152
@@ -148,10 +156,10 @@ public class ComponentKeyData : KeyData
148
156
public float [ ] keyFloatValues ;
149
157
150
158
public override int NumKeys { get { return Mathf . Min ( keyTimesInSeconds . Length , keyFloatValues . Length ) ; } }
151
- public override int NumComponents { get { return 1 ; } }
159
+ public override int NumProperties { get { return 1 ; } }
152
160
public override float [ ] GetKeyValues ( int id ) { return keyFloatValues ; }
153
- public override string GetComponentName ( int id ) { return propertyName ; }
154
- public override int FindComponent ( string name ) { return ( name == propertyName ) ? 0 : - 1 ; }
161
+ public override string GetPropertyName ( int id ) { return propertyName ; }
162
+ public override int GetIndexOf ( string name ) { return ( name == propertyName ) ? 0 : - 1 ; }
155
163
}
156
164
157
165
public class SingleKeyData : KeyData
@@ -160,10 +168,10 @@ public class SingleKeyData : KeyData
160
168
public System . Single [ ] keyFloatValues ;
161
169
162
170
public override int NumKeys { get { return Mathf . Min ( keyTimesInSeconds . Length , keyFloatValues . Length ) ; } }
163
- public override int NumComponents { get { return propertyNames . Length ; } }
171
+ public override int NumProperties { get { return propertyNames . Length ; } }
164
172
public override float [ ] GetKeyValues ( int id ) { return keyFloatValues ; }
165
- public override string GetComponentName ( int id ) { return propertyNames [ id ] ; }
166
- public override int FindComponent ( string name ) { return System . Array . IndexOf ( propertyNames , name ) ; }
173
+ public override string GetPropertyName ( int id ) { return propertyNames [ id ] ; }
174
+ public override int GetIndexOf ( string name ) { return System . Array . IndexOf ( propertyNames , name ) ; }
167
175
}
168
176
169
177
public class QuaternionKeyData : KeyData
@@ -172,7 +180,7 @@ public class QuaternionKeyData : KeyData
172
180
public Vector3 [ ] keyEulerValues ;
173
181
174
182
public override int NumKeys { get { return Mathf . Min ( keyTimesInSeconds . Length , keyEulerValues . Length ) ; } }
175
- public override int NumComponents { get { return propertyNames . Length ; } }
183
+ public override int NumProperties { get { return propertyNames . Length ; } }
176
184
public override float [ ] GetKeyValues ( int id )
177
185
{
178
186
return ( from e in keyEulerValues select Quaternion . Euler ( e ) [ id ] ) . ToArray ( ) ;
@@ -182,60 +190,69 @@ public override float [] GetAltKeyValues (int id)
182
190
return ( from e in keyEulerValues select e [ id ] ) . ToArray ( ) ;
183
191
}
184
192
185
- public override string GetComponentName ( int id ) { return propertyNames [ id ] ; }
186
- public override int FindComponent ( string name )
193
+ public override string GetPropertyName ( int id ) { return propertyNames [ id ] ; }
194
+ public override int GetIndexOf ( string name )
187
195
{
188
196
return System . Array . IndexOf ( propertyNames , name ) ;
189
197
}
190
198
}
191
199
192
200
public class TransformKeyData : KeyData
193
201
{
194
- public const int kNumQuatRotFields = 4 ;
195
- public const int kNumEulerRotFields = 3 ;
196
- public bool useQuaternionValues = false ;
197
-
198
- public int NumRotationFields { get { return ( ( useQuaternionValues ) ? kNumQuatRotFields : kNumEulerRotFields ) ; } }
202
+ public RotationInterpolation RotationType = RotationInterpolation . kEuler ;
199
203
200
204
public string [ ] propertyNames ;
201
- public Vector3 [ ] keyValues ; // NOTE: first half is Euler Rotation and second half is Translation
205
+ public Vector3 [ ] keyPosValues ;
206
+ public Vector3 [ ] keyEulerValues ;
202
207
private Quaternion [ ] keyQuatValues ;
203
208
204
- public bool IsRotation ( int id ) { return id < NumRotationFields ; }
209
+ public bool IsRotation ( int id ) { return id < ( int ) RotationType ; }
205
210
206
- public override int NumKeys { get { return Mathf . Min ( keyTimesInSeconds . Length , keyValues . Length / 2 ) ; } }
207
- public override int NumComponents { get { return propertyNames . Length ; } }
211
+ public override int NumKeys { get { return keyTimesInSeconds . Length ; } }
212
+ public override int NumProperties { get { return propertyNames . Length ; } }
208
213
public override float [ ] GetKeyValues ( int id )
209
214
{
210
- if ( ! useQuaternionValues ) return GetAltKeyValues ( id ) ;
215
+ if ( RotationType == RotationInterpolation . kEuler )
216
+ return GetAltKeyValues ( id ) ;
211
217
212
218
// compute continous rotations
213
219
if ( keyQuatValues == null )
214
220
{
215
221
keyQuatValues = new Quaternion [ NumKeys ] ;
216
- Quaternion currQuat = new Quaternion ( ) ;
217
222
218
223
for ( int idx = 0 ; idx < NumKeys ; idx ++ )
219
224
{
220
- if ( idx == 0 )
221
- {
222
- keyQuatValues [ idx ] = Quaternion . Euler ( keyValues [ idx ] ) ;
223
- currQuat = keyQuatValues [ idx ] ;
224
- }
225
- else
226
- {
227
- Vector3 deltaRot = keyValues [ idx ] - keyValues [ idx - 1 ] ;
228
- currQuat *= Quaternion . Euler ( deltaRot ) ;
229
- keyQuatValues [ idx ] = currQuat ;
230
- }
225
+ keyQuatValues [ idx ] = Quaternion . Euler ( keyEulerValues [ idx ] ) ;
231
226
}
232
227
}
233
228
234
229
float [ ] result = new float [ NumKeys ] ;
235
230
236
231
for ( int idx = 0 ; idx < NumKeys ; idx ++ )
237
232
{
238
- result [ idx ] = IsRotation ( id ) ? keyQuatValues [ idx ] [ id ] : keyValues [ NumKeys + idx ] [ id - NumRotationFields ] ;
233
+ if ( IsRotation ( id ) )
234
+ {
235
+ switch ( RotationType )
236
+ {
237
+ case ( RotationInterpolation . kEuler ) :
238
+ result [ idx ] = keyEulerValues [ idx ] [ id ] ;
239
+ break ;
240
+ case ( RotationInterpolation . kMixed ) :
241
+ int NumEulerFields = ( int ) RotationInterpolation . kEuler ;
242
+
243
+ result [ idx ] = ( id < NumEulerFields )
244
+ ? keyEulerValues [ idx ] [ id ] : keyQuatValues [ idx ] [ id - NumEulerFields ] ;
245
+
246
+ break ;
247
+ case ( RotationInterpolation . kQuaternion ) :
248
+ result [ idx ] = keyQuatValues [ idx ] [ id ] ;
249
+ break ;
250
+ }
251
+ }
252
+ else
253
+ {
254
+ result [ idx ] = keyPosValues [ idx ] [ id - ( int ) RotationType ] ;
255
+ }
239
256
}
240
257
241
258
return result ;
@@ -246,14 +263,32 @@ public override float [] GetAltKeyValues (int id)
246
263
247
264
for ( int idx = 0 ; idx < NumKeys ; idx ++ )
248
265
{
249
- result [ idx ] = IsRotation ( id ) ? keyValues [ idx ] [ id ] : keyValues [ NumKeys + idx ] [ id - NumRotationFields ] ;
266
+ // kMixed
267
+ // 0..2 euler XYZ
268
+ // 3..6 quaternion XYZ
269
+ // 7..9 position XYZ
270
+ // kQuaternion
271
+ // 0..3 quarternion XYZW
272
+ // 4..6 position XYZ
273
+ // kEuler
274
+ // 0..2 euler XYZ
275
+ // 3..5 position XYZ
276
+
277
+ if ( IsRotation ( id ) )
278
+ {
279
+ result [ idx ] = keyEulerValues [ idx ] [ id ] ;
280
+ }
281
+ else
282
+ {
283
+ result [ idx ] = keyPosValues [ idx ] [ id - ( int ) RotationType ] ;
284
+ }
250
285
}
251
286
252
287
return result ;
253
288
}
254
289
255
- public override string GetComponentName ( int id ) { return propertyNames [ id ] ; }
256
- public override int FindComponent ( string name )
290
+ public override string GetPropertyName ( int id ) { return propertyNames [ id ] ; }
291
+ public override int GetIndexOf ( string name )
257
292
{
258
293
return System . Array . IndexOf ( propertyNames , name ) ;
259
294
}
@@ -286,7 +321,7 @@ public int AnimTest (KeyData keyData, string testName)
286
321
animClipOriginal . legacy = true ;
287
322
animClipOriginal . name = "anim_" + testName ;
288
323
289
- for ( int id = 0 ; id < keyData . NumComponents ; id ++ ) {
324
+ for ( int id = 0 ; id < keyData . NumProperties ; id ++ ) {
290
325
// initialize keys
291
326
Keyframe [ ] keys = new Keyframe [ keyData . NumKeys ] ;
292
327
@@ -296,7 +331,7 @@ public int AnimTest (KeyData keyData, string testName)
296
331
}
297
332
AnimationCurve animCurveOriginal = new AnimationCurve ( keys ) ;
298
333
299
- animClipOriginal . SetCurve ( "" , keyData . componentType , keyData . GetComponentName ( id ) , animCurveOriginal ) ;
334
+ animClipOriginal . SetCurve ( "" , keyData . componentType , keyData . GetPropertyName ( id ) , animCurveOriginal ) ;
300
335
}
301
336
302
337
animOrig . AddClip ( animClipOriginal , animClipOriginal . name ) ;
@@ -356,7 +391,7 @@ public int AnimTest (KeyData keyData, string testName)
356
391
if ( ! hasAltPropertyName )
357
392
altPropertyName = curveBinding . propertyName ;
358
393
359
- int id = keyData . FindComponent ( altPropertyName ) ;
394
+ int id = keyData . GetIndexOf ( altPropertyName ) ;
360
395
361
396
if ( id != - 1 ) {
362
397
AnimCurveTest ( keyData . keyTimesInSeconds , hasAltPropertyName ? keyData . GetAltKeyValues ( id ) : keyData . GetKeyValues ( id ) , animCurveImported , curveBinding . propertyName ) ;
@@ -394,15 +429,26 @@ public int GimbalConditionsAnimTest (float [] keyTimesInSeconds, Vector3 [] keyV
394
429
395
430
[ Description ( "Uni-35616 continuous rotations" ) ]
396
431
[ Test , TestCaseSource ( typeof ( AnimationTestDataClass ) , "TestCases5" ) ]
397
- public int ContinuousRotationAnimTest ( bool useQuaternionValues , float [ ] keyTimesInSeconds , Vector3 [ ] keyValues )
432
+ public int ContinuousRotationAnimTest ( RotationInterpolation rotInterp , float [ ] keyTimesInSeconds , Vector3 [ ] keyPosValues , Vector3 [ ] keyEulerValues )
398
433
{
399
434
System . Type componentType = typeof ( Transform ) ;
400
435
401
- string [ ] propertyNames = useQuaternionValues ?
402
- AnimationTestDataClass . m_quaternionRotationNames . Concat ( AnimationTestDataClass . m_translationNames ) . ToArray ( ) :
403
- AnimationTestDataClass . m_eulerRotationNames . Concat ( AnimationTestDataClass . m_translationNames ) . ToArray ( ) ;
436
+ string [ ] propertyNames = null ;
437
+
438
+ switch ( rotInterp )
439
+ {
440
+ case RotationInterpolation . kEuler :
441
+ propertyNames = AnimationTestDataClass . m_eulerRotationNames . Concat ( AnimationTestDataClass . m_translationNames ) . ToArray ( ) ;
442
+ break ;
443
+ case RotationInterpolation . kQuaternion :
444
+ propertyNames = AnimationTestDataClass . m_quaternionRotationNames . Concat ( AnimationTestDataClass . m_translationNames ) . ToArray ( ) ;
445
+ break ;
446
+ case RotationInterpolation . kMixed :
447
+ propertyNames = AnimationTestDataClass . m_eulerRotationNames . Concat ( AnimationTestDataClass . m_quaternionRotationNames ) . Concat ( AnimationTestDataClass . m_translationNames ) . ToArray ( ) ;
448
+ break ;
449
+ }
404
450
405
- KeyData keyData = new TransformKeyData { useQuaternionValues = useQuaternionValues , propertyNames = propertyNames , componentType = componentType , keyTimesInSeconds = keyTimesInSeconds , keyValues = keyValues } ;
451
+ KeyData keyData = new TransformKeyData { RotationType = rotInterp , propertyNames = propertyNames , componentType = componentType , keyTimesInSeconds = keyTimesInSeconds , keyPosValues = keyPosValues , keyEulerValues = keyEulerValues } ;
406
452
407
453
return AnimTest ( keyData , componentType . ToString ( ) + "_ContinuousRotations" ) ;
408
454
}
0 commit comments