1 |
using System; |
2 |
using System.Collections.Generic; |
3 |
|
4 |
namespace Oni.Totoro |
5 |
{ |
6 |
internal class AnimationDaeReader |
7 |
{ |
8 |
private Animation animation; |
9 |
private Dae.Scene scene; |
10 |
private int startFrame; |
11 |
private int endFrame; |
12 |
private Body body; |
13 |
private int frameCount; |
14 |
|
15 |
public void Read(Animation targetAnimation) |
16 |
{ |
17 |
animation = targetAnimation; |
18 |
|
19 |
body = BodyDaeReader.Read(scene); |
20 |
|
21 |
ComputeFrameCount(); |
22 |
ImportTranslation(); |
23 |
ImportRotations(); |
24 |
animation.ComputeExtents(body); |
25 |
} |
26 |
|
27 |
public Dae.Scene Scene |
28 |
{ |
29 |
get { return scene; } |
30 |
set { scene = value; } |
31 |
} |
32 |
|
33 |
public int StartFrame |
34 |
{ |
35 |
get { return startFrame; } |
36 |
set { startFrame = value; } |
37 |
} |
38 |
|
39 |
public int EndFrame |
40 |
{ |
41 |
get { return endFrame; } |
42 |
set { endFrame = value; } |
43 |
} |
44 |
|
45 |
private void ComputeFrameCount() |
46 |
{ |
47 |
float maxTime = float.MinValue; |
48 |
|
49 |
var inputs = body.Nodes |
50 |
.SelectMany(n => n.DaeNode.Transforms).Where(t => t.HasAnimations) |
51 |
.SelectMany(t => t.Animations).Where(a => a != null) |
52 |
.SelectMany(a => a.Inputs).Where(i => i.Semantic == Dae.Semantic.Input); |
53 |
|
54 |
foreach (var input in inputs) |
55 |
maxTime = Math.Max(maxTime, input.Source.FloatData.Max()); |
56 |
|
57 |
float maxFrameF = maxTime * 60.0f; |
58 |
int maxFrame; |
59 |
|
60 |
if (maxFrameF - Math.Round(maxFrameF) < 0.0005) |
61 |
maxFrame = FMath.RoundToInt32(maxFrameF); |
62 |
else |
63 |
maxFrame = FMath.TruncateToInt32(maxFrameF); |
64 |
|
65 |
//Console.Error.WriteLine("Info: The last keyframe time is {0}s. The animation length is {1} (at 60fps).", |
66 |
// maxTime, maxFrame + 1); |
67 |
|
68 |
if (endFrame == 0) |
69 |
{ |
70 |
endFrame = maxFrame; |
71 |
} |
72 |
else if (endFrame > maxFrame) |
73 |
{ |
74 |
Console.Error.WriteLine("Warning: the specified animation end frame ({0}) is beyond the last key frame ({1}), using the last frame instead", endFrame, maxFrame); |
75 |
endFrame = maxFrame; |
76 |
} |
77 |
|
78 |
if (startFrame >= maxFrame) |
79 |
{ |
80 |
Console.Error.WriteLine("Warning: the specified animation start frame ({0}) is beyond the last key frame ({1}), using 0 instead", startFrame, maxFrame); |
81 |
startFrame = 0; |
82 |
} |
83 |
|
84 |
frameCount = endFrame - startFrame; |
85 |
} |
86 |
|
87 |
private void ImportTranslation() |
88 |
{ |
89 |
var rootNode = body.Nodes[0].DaeNode; |
90 |
var translate = rootNode.Transforms[0] as Dae.TransformTranslate; |
91 |
|
92 |
if (translate == null) |
93 |
{ |
94 |
animation.Heights.AddRange(Enumerable.Repeat(0.0f, frameCount)); |
95 |
animation.Velocities.AddRange(Enumerable.Repeat(Vector2.Zero, frameCount)); |
96 |
} |
97 |
else |
98 |
{ |
99 |
animation.Heights.AddRange(Sample(translate, 1, endFrame - 1)); |
100 |
|
101 |
var x = Sample(translate, 0, endFrame); |
102 |
var z = Sample(translate, 2, endFrame); |
103 |
|
104 |
for (int i = 1; i < x.Length; i++) |
105 |
animation.Velocities.Add(new Vector2(x[i] - x[i - 1], z[i] - z[i - 1])); |
106 |
} |
107 |
} |
108 |
|
109 |
private void ImportRotations() |
110 |
{ |
111 |
animation.FrameSize = 16; |
112 |
|
113 |
foreach (var node in body.Nodes.Select(n => n.DaeNode)) |
114 |
{ |
115 |
var keys = new List<KeyFrame>(); |
116 |
animation.Rotations.Add(keys); |
117 |
|
118 |
var rotations = new List<Dae.TransformRotate>(); |
119 |
var angles = new List<float[]>(); |
120 |
|
121 |
foreach (var transform in node.Transforms) |
122 |
{ |
123 |
var rotate = transform as Dae.TransformRotate; |
124 |
|
125 |
if (rotate != null) |
126 |
{ |
127 |
rotations.Add(rotate); |
128 |
angles.Add(Sample(rotate, 3, endFrame - 1)); |
129 |
} |
130 |
} |
131 |
|
132 |
for (int i = 0; i < frameCount; i++) |
133 |
{ |
134 |
var q = Quaternion.Identity; |
135 |
|
136 |
for (int j = 0; j < rotations.Count; j++) |
137 |
q *= Quaternion.CreateFromAxisAngle(rotations[j].Axis, MathHelper.ToRadians(angles[j][i])); |
138 |
|
139 |
keys.Add(new KeyFrame { |
140 |
Duration = 1, |
141 |
Rotation = q.ToVector4() |
142 |
}); |
143 |
} |
144 |
} |
145 |
} |
146 |
|
147 |
private float[] Sample(Dae.Transform transform, int index, int endFrame) |
148 |
{ |
149 |
Dae.Sampler sampler = null; |
150 |
|
151 |
if (transform.HasAnimations) |
152 |
sampler = transform.Animations[index]; |
153 |
|
154 |
if (sampler == null) |
155 |
{ |
156 |
var value = transform.Values[index]; |
157 |
var values = new float[endFrame - startFrame + 1]; |
158 |
|
159 |
for (int i = 0; i < values.Length; i++) |
160 |
values[i] = value; |
161 |
|
162 |
return values; |
163 |
} |
164 |
|
165 |
return sampler.Sample(startFrame, endFrame); |
166 |
} |
167 |
} |
168 |
} |