source: OniSplit/Physics/ObjectDaeImporter.cs

Last change on this file was 1114, checked in by iritscen, 5 years ago

Adding OniSplit source code (v0.9.99.0). Many thanks to Neo for all his work over the years.

File size: 8.5 KB
Line 
1using System;
2using System.Collections.Generic;
3using Oni.Akira;
4using Oni.Motoko;
5
6namespace Oni.Physics
7{
8 internal class ObjectDaeImporter
9 {
10 private readonly TextureImporter3 textureImporter;
11 private readonly Dictionary<string, AkiraDaeNodeProperties> properties;
12 private readonly List<ObjectNode> nodes = new List<ObjectNode>();
13
14 public ObjectDaeImporter(TextureImporter3 textureImporter, Dictionary<string, AkiraDaeNodeProperties> properties)
15 {
16 this.textureImporter = textureImporter;
17 this.properties = properties;
18 }
19
20 public List<ObjectNode> Nodes
21 {
22 get { return nodes; }
23 }
24
25 public void Import(Dae.Scene scene)
26 {
27 ImportNode(scene, null, GetNodeProperties(scene));
28 }
29
30 private void ImportNode(Dae.Node node, List<ObjectAnimationKey> parentAnimation, ObjectDaeNodeProperties parentNodeProperties)
31 {
32 Console.WriteLine("\t{0}", node.Id);
33
34 var animation = ImportNodeAnimation(node, parentAnimation);
35 var nodeProperties = GetNodeProperties(node);
36
37 if (nodeProperties == null && parentNodeProperties != null)
38 {
39 nodeProperties = new ObjectDaeNodeProperties
40 {
41 HasPhysics = parentNodeProperties.HasPhysics,
42 ScriptId = parentNodeProperties.ScriptId,
43 ObjectFlags = parentNodeProperties.ObjectFlags
44 };
45
46 //
47 // We can't use the same anim name when we inherit the properties of the parent,
48 // generate a name by appending "_anim" to the node name.
49 //
50
51 nodeProperties.Animations.AddRange(
52 from a in parentNodeProperties.Animations
53 select new ObjectAnimationClip
54 {
55 Name = node.Name + "_anim",
56 Start = a.Start,
57 Stop = a.Stop,
58 End = a.End,
59 Flags = a.Flags
60 });
61 }
62
63 if (nodeProperties != null && nodeProperties.HasPhysics)
64 {
65 var geometries = GeometryDaeReader.Read(node, textureImporter).ToList();
66
67 if (animation.Count > 0 || geometries.Count > 0)
68 {
69 nodes.Add(new ObjectNode(from g in geometries select new ObjectGeometry(g))
70 {
71 Name = node.Name,
72 FileName = node.FileName,
73 Animations = CreateAnimations(animation, nodeProperties),
74 ScriptId = nodeProperties.ScriptId,
75 Flags = nodeProperties.ObjectFlags
76 });
77 }
78 }
79
80 foreach (var child in node.Nodes)
81 {
82 ImportNode(child, animation, nodeProperties);
83 }
84 }
85
86 private List<ObjectAnimationKey> ImportNodeAnimation(Dae.Node node, List<ObjectAnimationKey> parentAnimation)
87 {
88 var scale = Vector3.One;
89 var scaleTransform = node.Transforms.OfType<Dae.TransformScale>().FirstOrDefault();
90
91 if (scaleTransform != null)
92 {
93 scale.X = scaleTransform.Values[0];
94 scale.Y = scaleTransform.Values[1];
95 scale.Z = scaleTransform.Values[2];
96 }
97
98 if (parentAnimation != null && parentAnimation.Count > 0)
99 {
100 scale *= parentAnimation[0].Scale;
101 }
102
103 var rotateTransforms = new List<Dae.TransformRotate>();
104 var angles = new List<float[]>();
105
106 foreach (var rotate in node.Transforms.OfType<Dae.TransformRotate>())
107 {
108 rotateTransforms.Add(rotate);
109
110 var angleAnimation = rotate.AngleAnimation;
111
112 if (angleAnimation != null)
113 angles.Add(angleAnimation.Sample());
114 else
115 angles.Add(new[] { rotate.Angle });
116 }
117
118 var translateTransforms = node.Transforms.OfType<Dae.TransformTranslate>().FirstOrDefault();
119 var positions = new List<float[]>();
120
121 if (translateTransforms != null)
122 {
123 for (int i = 0; i < 3; i++)
124 {
125 var positionAnimation = translateTransforms.Animations[i];
126
127 if (positionAnimation != null)
128 positions.Add(positionAnimation.Sample());
129 else
130 positions.Add(new[] { translateTransforms.Translation[i] });
131 }
132 }
133
134 var frames = new List<ObjectAnimationKey>();
135 int frameCount = Math.Max(angles.Max(a => a.Length), positions.Max(a => a.Length));
136
137 for (int time = 0; time < frameCount; time++)
138 {
139 var rotation = Quaternion.Identity;
140
141 for (int i = 0; i < rotateTransforms.Count; i++)
142 {
143 float angle;
144
145 float[] values = angles[i];
146
147 if (time >= values.Length)
148 angle = values.Last();
149 else
150 angle = values[time];
151
152 rotation *= Quaternion.CreateFromAxisAngle(rotateTransforms[i].Axis, MathHelper.ToRadians(angle));
153 }
154
155 var translation = Vector3.Zero;
156
157 if (translateTransforms != null)
158 {
159 translation.X = positions[0][MathHelper.Clamp(time, 0, positions[0].Length - 1)];
160 translation.Y = positions[1][MathHelper.Clamp(time, 0, positions[1].Length - 1)];
161 translation.Z = positions[2][MathHelper.Clamp(time, 0, positions[2].Length - 1)];
162 }
163
164 if (parentAnimation != null)
165 {
166 var parentFrame = time < parentAnimation.Count ? parentAnimation[time] : parentAnimation.LastOrDefault();
167
168 if (parentFrame != null)
169 {
170 rotation = parentFrame.Rotation * rotation;
171 translation = parentFrame.Translation + Vector3.Transform(translation * parentFrame.Scale, parentFrame.Rotation);
172 }
173 }
174
175 frames.Add(new ObjectAnimationKey
176 {
177 Time = time,
178 Scale = scale,
179 Rotation = rotation,
180 Translation = translation
181 });
182 }
183
184 return frames;
185 }
186
187 private ObjectAnimation[] CreateAnimations(List<ObjectAnimationKey> allFrames, ObjectDaeNodeProperties props)
188 {
189 var anims = new List<ObjectAnimation>();
190
191 foreach (var clip in props.Animations)
192 {
193 int start = clip.Start;
194 int end = clip.End != int.MaxValue ? clip.End : allFrames.Last().Time;
195
196 var clipFrames = (from f in allFrames
197 where start <= f.Time && f.Time <= end
198 select new ObjectAnimationKey
199 {
200 Time = f.Time - start,
201 Scale = f.Scale,
202 Rotation = f.Rotation,
203 Translation = f.Translation
204 }).ToArray();
205
206 if (clipFrames.Length == 0)
207 continue;
208
209 anims.Add(new ObjectAnimation
210 {
211 Name = clip.Name,
212 Flags = clip.Flags,
213 Stop = clip.Stop,
214 Length = end - start + 1,
215 Keys = clipFrames
216 });
217 }
218
219 return anims.ToArray();
220 }
221
222 private ObjectDaeNodeProperties GetNodeProperties(Dae.Node node)
223 {
224 AkiraDaeNodeProperties nodeProperties;
225
226 if (properties == null || !properties.TryGetValue(node.Id, out nodeProperties))
227 return null;
228
229 return nodeProperties as ObjectDaeNodeProperties;
230 }
231 }
232}
Note: See TracBrowser for help on using the repository browser.