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 | }
|
---|