4 using System.Collections.Generic;
6 using SiliconStudio.Core;
7 using SiliconStudio.Core.Collections;
8 using SiliconStudio.Core.Mathematics;
9 using SiliconStudio.Paradox.Effects;
10 using SiliconStudio.Paradox.Engine;
12 namespace SiliconStudio.Paradox.DataModel
20 private static Stack<AnimationClipEvaluator> evaluatorPool =
new Stack<AnimationClipEvaluator>();
23 private static Stack<AnimationClipResult> availableResultsPool =
new Stack<AnimationClipResult>();
25 private Stack<AnimationClipResult> animationStack =
new Stack<AnimationClipResult>();
27 private HashSet<AnimationClipEvaluator> evaluators =
new HashSet<AnimationClipEvaluator>();
28 private HashSet<AnimationClip> clips =
new HashSet<AnimationClip>();
29 private Dictionary<string, Channel> channelsByName =
new Dictionary<string, Channel>();
30 private List<Channel> channels =
new List<Channel>();
31 private int structureSize;
42 if (channelsByName.TryGetValue(curve.Key, out channel))
51 var blendType = BlendType.None;
52 var elementType = curve.Value.ElementType;
58 else if (elementType == typeof(
float))
60 blendType = BlendType.Float1;
62 else if (elementType == typeof(
Vector2))
64 blendType = BlendType.Float2;
66 else if (elementType == typeof(
Vector3))
68 blendType = BlendType.Float3;
70 else if (elementType == typeof(
Vector4))
72 blendType = BlendType.Float4;
76 channel.BlendType = blendType;
77 channel.Offset = structureSize;
78 channel.PropertyName = curve.Key;
81 channel.NodeName = curve.Value.NodeName;
82 channel.Type = curve.Value.Type;
84 channel.Size = curve.Value.ElementSize;
87 channelsByName.Add(channel.PropertyName, channel);
88 channels.Add(channel);
92 structureSize +=
sizeof(float) + channel.Size;
96 foreach (var currentEvaluator in evaluators)
98 currentEvaluator.AddChannel(ref channel);
105 lock (availableResultsPool)
107 foreach (var result
in availableResultsPool)
109 if (result.DataSize < structureSize)
111 result.DataSize = structureSize;
112 result.Data =
new byte[structureSize];
121 if (evaluatorPool.Count > 0)
123 evaluator = evaluatorPool.Pop();
131 evaluator.Initialize(clip, channels);
132 evaluators.Add(evaluator);
141 evaluators.Remove(evaluator);
143 evaluatorPool.Push(evaluator);
149 fixed (byte* sourceLeftDataStart = sourceLeft.Data)
150 fixed (byte* sourceRightDataStart = sourceRight.Data)
151 fixed (byte* resultDataStart = result.Data)
153 foreach (var channel
in sourceLeft.
Channels)
155 int offset = channel.Offset;
156 var sourceLeftData = (
float*)(sourceLeftDataStart + offset);
157 var sourceRightData = (
float*)(sourceRightDataStart + offset);
158 var resultData = (
float*)(resultDataStart + offset);
160 float factorLeft = *sourceLeftData++;
161 float factorRight = *sourceRightData++;
164 if (factorLeft == 0.0f && factorRight == 0.0f)
166 *resultData++ = 0.0f;
171 if (factorLeft > 0.0f && factorRight == 0.0f)
173 *resultData++ = 1.0f;
174 Utilities.CopyMemory((IntPtr)resultData, (IntPtr)sourceLeftData, channel.Size);
179 if (factorRight > 0.0f && factorLeft == 0.0f)
181 *resultData++ = 1.0f;
182 Utilities.CopyMemory((IntPtr)resultData, (IntPtr)sourceRightData, channel.Size);
187 *resultData++ = 1.0f;
189 switch (blendOperation)
191 case AnimationBlendOperation.LinearBlend:
194 switch (channel.BlendType)
197 Utilities.CopyMemory((IntPtr)resultData, (IntPtr)sourceLeftData, channel.Size);
199 case BlendType.Float2:
200 Vector2.Lerp(ref *(
Vector2*)sourceLeftData, ref *(
Vector2*)sourceRightData, blendFactor, out *(
Vector2*)resultData);
202 case BlendType.Float3:
203 Vector3.Lerp(ref *(
Vector3*)sourceLeftData, ref *(
Vector3*)sourceRightData, blendFactor, out *(
Vector3*)resultData);
205 case BlendType.Quaternion:
209 throw new ArgumentOutOfRangeException();
212 case AnimationBlendOperation.Add:
215 switch (channel.BlendType)
218 Utilities.CopyMemory((IntPtr)resultData, (IntPtr)sourceLeftData, channel.Size);
220 case BlendType.Float2:
222 Vector2.Add(ref *(
Vector2*)sourceLeftData, ref *(
Vector2*)sourceRightData, out rightValue2);
223 Vector2.Lerp(ref *(
Vector2*)sourceLeftData, ref rightValue2, blendFactor, out *(
Vector2*)resultData);
225 case BlendType.Float3:
227 Vector3.Add(ref *(
Vector3*)sourceLeftData, ref *(
Vector3*)sourceRightData, out rightValue3);
228 Vector3.Lerp(ref *(
Vector3*)sourceLeftData, ref rightValue3, blendFactor, out *(
Vector3*)resultData);
230 case BlendType.Quaternion:
232 Quaternion.Multiply(ref *(
Quaternion*)sourceLeftData, ref *(
Quaternion*)sourceRightData, out rightValueQ);
233 Quaternion.Normalize(ref rightValueQ, out rightValueQ);
234 Quaternion.Slerp(ref *(
Quaternion*)sourceLeftData, ref rightValueQ, blendFactor, out *(
Quaternion*)resultData);
237 throw new ArgumentOutOfRangeException();
240 case AnimationBlendOperation.Subtract:
243 switch (channel.BlendType)
246 Utilities.CopyMemory((IntPtr)resultData, (IntPtr)sourceLeftData, channel.Size);
248 case BlendType.Float2:
250 Vector2.Subtract(ref *(
Vector2*)sourceLeftData, ref *(
Vector2*)sourceRightData, out rightValue2);
251 Vector2.Lerp(ref *(
Vector2*)sourceLeftData, ref rightValue2, blendFactor, out *(
Vector2*)resultData);
253 case BlendType.Float3:
255 Vector3.Subtract(ref *(
Vector3*)sourceLeftData, ref *(
Vector3*)sourceRightData, out rightValue3);
256 Vector3.Lerp(ref *(
Vector3*)sourceLeftData, ref rightValue3, blendFactor, out *(
Vector3*)resultData);
258 case BlendType.Quaternion:
261 Quaternion.Invert(ref *(
Quaternion*)sourceRightData, out rightValueQ);
262 Quaternion.Multiply(ref rightValueQ, ref *(
Quaternion*)sourceLeftData, out rightValueQ);
263 Quaternion.Normalize(ref rightValueQ, out rightValueQ);
265 Quaternion.Slerp(ref *(
Quaternion*)sourceLeftData, ref rightValueQ, blendFactor, out *(
Quaternion*)resultData);
268 throw new ArgumentOutOfRangeException();
272 throw new ArgumentOutOfRangeException(
"blendOperation");
286 animationStack.Clear();
289 var animationOperation0 = animationOperations.Items[0];
292 throw new InvalidOperationException(
"First operation should be a push");
295 var hasResult = result != null;
300 if (result.DataSize < structureSize)
302 result.DataSize = structureSize;
303 result.Data =
new byte[structureSize];
306 result.Channels = channels;
310 result = AllocateIntermediateResult();
313 animationOperation0.Evaluator.Compute((
CompressedTimeSpan)animationOperation0.Time, result);
315 animationStack.Push(result);
317 for (
int index = 1; index < animationOperations.Count; index++)
319 var animationOperation = animationOperations.Items[index];
321 ApplyAnimationOperation(ref animationOperation);
324 if (hasResult && (animationStack.Count != 1 || animationStack.Pop() != result))
326 throw new InvalidOperationException(
"Stack should end up with result.");
332 switch (animationOperation.Type)
334 case AnimationOperationType.Blend:
337 var op2 = animationStack.Pop();
338 var op1 = animationStack.Peek();
339 Blend(animationOperation.BlendOperation, animationOperation.BlendFactor, op1, op2, op1);
340 FreeIntermediateResult(op2);
343 case AnimationOperationType.Push:
345 var op = AllocateIntermediateResult();
346 animationOperation.Evaluator.Compute((CompressedTimeSpan)animationOperation.Time, op);
347 animationStack.Push(op);
350 case AnimationOperationType.Pop:
352 var op = animationStack.Pop();
353 animationOperation.Evaluator.AddCurveValues((CompressedTimeSpan)animationOperation.Time, op);
359 private AnimationClipResult AllocateIntermediateResult()
361 lock (availableResultsPool)
363 if (availableResultsPool.Count > 0)
365 var result = availableResultsPool.Pop();
367 if (result.DataSize < structureSize)
369 result.DataSize = structureSize;
370 result.Data =
new byte[structureSize];
373 result.Channels = channels;
380 return new AnimationClipResult
382 DataSize = structureSize,
383 Data =
new byte[structureSize],
388 internal void FreeIntermediateResult(AnimationClipResult result)
391 lock (availableResultsPool)
393 result.Channels = null;
394 availableResultsPool.Push(result);
AnimationClipEvaluator CreateEvaluator(AnimationClip clip)
Dictionary< string, Channel > Channels
Gets the channels of this clip.
Represents a two dimensional mathematical vector.
static unsafe void Blend(AnimationBlendOperation blendOperation, float blendFactor, AnimationClipResult sourceLeft, AnimationClipResult sourceRight, AnimationClipResult result)
MeshAnimationUpdater.ChannelType Type
void Compute(FastList< AnimationOperation > animationOperations, ref AnimationClipResult result)
Computes the specified animation operations.
AnimationBlendOperation
Describes the type of animation blend operation.
Represents a three dimensional mathematical vector.
A single animation operation (push or blend).
void ReleaseEvaluator(AnimationClipEvaluator evaluator)
An aggregation of AnimationCurve with their channel names.
List< AnimationBlender.Channel > Channels
Gets or sets the animation channel descriptions.
Represents a four dimensional mathematical vector.
Represents a four dimensional mathematical quaternion.
SiliconStudio.Core.Mathematics.Quaternion Quaternion
Performs animation blending. For now, all AnimationClip must target the same skeleton.
Blend
Blend option. A blend option identifies the data source and an optional pre-blend operation...
Evaluates AnimationClip to a AnimationClipResult at a given time.
override string ToString()