Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
MeshAnimationUpdater.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Collections.Generic;
5 using SiliconStudio.Core;
6 using SiliconStudio.Core.Extensions;
7 using SiliconStudio.Paradox.DataModel;
10 
11 namespace SiliconStudio.Paradox.Effects
12 {
13  /// <summary>
14  /// Applies animation from a <see cref="AnimationClip"/> to a <see cref="ModelViewHierarchyUpdater"/>.
15  /// </summary>
16  public class MeshAnimationUpdater
17  {
18  // Keep track of source channel (if changed, we should regenerate updateChannels)
19  private List<AnimationBlender.Channel> currentSourceChannels;
20  private int currentSourceChannelCount;
21  private UpdateChannel[] updateChannels;
22 
23  public unsafe void Update(ModelViewHierarchyUpdater hierarchy, AnimationClipResult result)
24  {
25  // Check if we need to regenerate "update channels" (i.e. how to copy data from result to hierarchy)
26  if (updateChannels == null // First time?...
27  || currentSourceChannels != result.Channels // ... or changed?
28  || currentSourceChannels.Count != currentSourceChannelCount) // .. or modified? (could only append channel)
29  {
30  RegenerateUpdateChannels(hierarchy, result.Channels);
31  currentSourceChannels = result.Channels;
32  currentSourceChannelCount = currentSourceChannels.Count;
33  }
34 
35  // Copy results to node hierarchy
36  fixed (byte* structures = result.Data)
37  {
38  foreach (var updateChannel in updateChannels)
39  {
40  var structureData = (float*)(structures + updateChannel.Offset);
41  var factor = *structureData++;
42  if (factor == 0.0f)
43  continue;
44 
45  switch (updateChannel.Type)
46  {
47  case ChannelType.Translation:
48  Utilities.Read((IntPtr)structureData, ref hierarchy.NodeTransformations[updateChannel.Index].Transform.Translation);
49  break;
50  case ChannelType.Rotation:
51  Utilities.Read((IntPtr)structureData, ref hierarchy.NodeTransformations[updateChannel.Index].Transform.Rotation);
52  break;
53  case ChannelType.Scaling:
54  Utilities.Read((IntPtr)structureData, ref hierarchy.NodeTransformations[updateChannel.Index].Transform.Scaling);
55  break;
56  default:
57  throw new ArgumentOutOfRangeException();
58  }
59  }
60  }
61  }
62 
63  private static bool NodeNameMatch(string name1, string name2)
64  {
65  // Try exact match
66  if (name1 == name2)
67  return true;
68 
69  // Try to match only after : so that patterns like "Model::j_rarm03" and "Model::mc00_rig:protomodel:j_rarm03" matches (happens with FBX references and Maya)
70  // TODO: Maybe this should be done at FBX export time? (need to find the FBX naming pattern w/ references -- and check it with every DCC tool)
71  name1 = name1.Substring(name1.LastIndexOf(':') + 1);
72  name2 = name2.Substring(name2.LastIndexOf(':') + 1);
73 
74  return name1 == name2;
75  }
76 
77  private void RegenerateUpdateChannels(ModelViewHierarchyUpdater hierarchy, List<AnimationBlender.Channel> channels)
78  {
79  var newUpdateChannels = new List<UpdateChannel>();
80 
81  // TODO: Temporary implementation due to lack of time before first release.
82  foreach (var channel in channels)
83  {
84  string nodeName = channel.NodeName;
85  if (nodeName == null)
86  continue;
87 
88  var updateChannel = new UpdateChannel();
89  updateChannel.Index = -1;
90 
91  var hierarchyNodes = hierarchy.Nodes;
92  for (int i = 0; i < hierarchyNodes.Length; ++i)
93  {
94  var node = hierarchyNodes[i];
95  if (node.Name == nodeName)
96  {
97  updateChannel.Index = i;
98  break;
99  }
100  }
101 
102  if (updateChannel.Index == -1)
103  {
104  // TODO: Warning?
105  //throw new InvalidOperationException(string.Format("Could not find matching node in animation for {0}", nodeName));
106  continue;
107  }
108 
109  updateChannel.Offset = channel.Offset;
110  updateChannel.Type = channel.Type;
111 
112  newUpdateChannels.Add(updateChannel);
113  }
114 
115  updateChannels = newUpdateChannels.ToArray();
116  }
117 
118  internal static ChannelType GetType(string propertyName)
119  {
120  if (propertyName.StartsWith("Transformation.Translation["))
121  {
122  return ChannelType.Translation;
123  }
124  if (propertyName.StartsWith("Transformation.Rotation["))
125  {
126  return ChannelType.Rotation;
127  }
128  if (propertyName.StartsWith("Transformation.Scaling["))
129  {
130  return ChannelType.Scaling;
131  }
132 
133  return ChannelType.Unknown;
134  }
135 
136  internal static string GetNodeName(string propertyName)
137  {
138  int nodeNameFirstChar = propertyName.IndexOf('[');
139  if (nodeNameFirstChar == -1)
140  return null;
141 
142  int nodeNameLastChar = propertyName.IndexOf(']', nodeNameFirstChar);
143 
144  return propertyName.Substring(nodeNameFirstChar + 1, nodeNameLastChar - nodeNameFirstChar - 1);
145  }
146 
147  [DataContract]
148  public enum ChannelType
149  {
150  Unknown,
151  Translation,
152  Rotation,
153  Scaling,
154  }
155 
156  /// <summary>
157  /// Describes how to update data from <see cref="AnimationClipResult"/> to <see cref="ModelViewHierarchyUpdater"/>.
158  /// </summary>
159  private struct UpdateChannel
160  {
161  public ChannelType Type;
162  public int Index;
163  public int Offset;
164  }
165  }
166 }
Vector3 Translation
The translation.
Definition: TransformTRS.cs:22
Applies animation from a AnimationClip to a ModelViewHierarchyUpdater.
SiliconStudio.Core.Mathematics.Vector3 Vector3
List< AnimationBlender.Channel > Channels
Gets or sets the animation channel descriptions.
unsafe void Update(ModelViewHierarchyUpdater hierarchy, AnimationClipResult result)
SiliconStudio.Core.Mathematics.Quaternion Quaternion
SiliconStudio.Core.Mathematics.Quaternion Quaternion
Performs hierarchical updates for a given Model.
SiliconStudio.Core.Mathematics.Vector3 Vector3