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