| 1 | using System; | 
 
 
 
 
 | 2 | using System.Collections.Generic; | 
 
 
 
 
 | 3 | using System.IO; | 
 
 
 
 
 | 4 |  | 
 
 
 
 
 | 5 | namespace Oni | 
 
 
 
 
 | 6 | { | 
 
 
 
 
 | 7 | internal class DaeExporter : Exporter | 
 
 
 
 
 | 8 | { | 
 
 
 
 
 | 9 | private readonly bool noAnimation; | 
 
 
 
 
 | 10 | private readonly List<string> animationNames = new List<string>(); | 
 
 
 
 
 | 11 | private readonly string geometryName; | 
 
 
 
 
 | 12 | private readonly string fileType; | 
 
 
 
 
 | 13 |  | 
 
 
 
 
 | 14 | public DaeExporter(string[] args, InstanceFileManager fileManager, string outputDirPath, string fileType) | 
 
 
 
 
 | 15 | : base(fileManager, outputDirPath) | 
 
 
 
 
 | 16 | { | 
 
 
 
 
 | 17 | foreach (string arg in args) | 
 
 
 
 
 | 18 | { | 
 
 
 
 
 | 19 | if (arg == "-noanim") | 
 
 
 
 
 | 20 | noAnimation = true; | 
 
 
 
 
 | 21 | else if (arg.StartsWith("-anim:", StringComparison.Ordinal)) | 
 
 
 
 
 | 22 | animationNames.Add(arg.Substring(6)); | 
 
 
 
 
 | 23 | else if (arg.StartsWith("-geom:", StringComparison.Ordinal)) | 
 
 
 
 
 | 24 | geometryName = arg.Substring(6); | 
 
 
 
 
 | 25 | } | 
 
 
 
 
 | 26 |  | 
 
 
 
 
 | 27 | this.fileType = fileType; | 
 
 
 
 
 | 28 | } | 
 
 
 
 
 | 29 |  | 
 
 
 
 
 | 30 | protected override void ExportFile(string sourceFilePath) | 
 
 
 
 
 | 31 | { | 
 
 
 
 
 | 32 | string extension = Path.GetExtension(sourceFilePath); | 
 
 
 
 
 | 33 |  | 
 
 
 
 
 | 34 | if (string.Equals(extension, ".xml", StringComparison.OrdinalIgnoreCase)) | 
 
 
 
 
 | 35 | { | 
 
 
 
 
 | 36 | var sceneExporter = new SceneExporter(InstanceFileManager, OutputDirPath); | 
 
 
 
 
 | 37 | sceneExporter.ExportScene(sourceFilePath); | 
 
 
 
 
 | 38 | return; | 
 
 
 
 
 | 39 | } | 
 
 
 
 
 | 40 |  | 
 
 
 
 
 | 41 | base.ExportFile(sourceFilePath); | 
 
 
 
 
 | 42 | } | 
 
 
 
 
 | 43 |  | 
 
 
 
 
 | 44 | protected override List<InstanceDescriptor> GetSupportedDescriptors(InstanceFile file) | 
 
 
 
 
 | 45 | { | 
 
 
 
 
 | 46 | var descriptors = new List<InstanceDescriptor>(); | 
 
 
 
 
 | 47 | descriptors.AddRange(file.GetNamedDescriptors(TemplateTag.ONCC)); | 
 
 
 
 
 | 48 | descriptors.AddRange(file.GetNamedDescriptors(TemplateTag.TRBS)); | 
 
 
 
 
 | 49 | descriptors.AddRange(file.GetNamedDescriptors(TemplateTag.M3GM)); | 
 
 
 
 
 | 50 | descriptors.AddRange(file.GetNamedDescriptors(TemplateTag.AKEV)); | 
 
 
 
 
 | 51 | descriptors.AddRange(file.GetNamedDescriptors(TemplateTag.OBAN)); | 
 
 
 
 
 | 52 | descriptors.AddRange(file.GetNamedDescriptors(TemplateTag.OFGA)); | 
 
 
 
 
 | 53 | descriptors.AddRange(file.GetNamedDescriptors(TemplateTag.ONWC)); | 
 
 
 
 
 | 54 | return descriptors; | 
 
 
 
 
 | 55 | } | 
 
 
 
 
 | 56 |  | 
 
 
 
 
 | 57 | protected override void ExportInstance(InstanceDescriptor descriptor) | 
 
 
 
 
 | 58 | { | 
 
 
 
 
 | 59 | var tag = descriptor.Template.Tag; | 
 
 
 
 
 | 60 |  | 
 
 
 
 
 | 61 | if (tag == TemplateTag.AKEV) | 
 
 
 
 
 | 62 | { | 
 
 
 
 
 | 63 | var mesh = Akira.AkiraDatReader.Read(descriptor); | 
 
 
 
 
 | 64 | Akira.AkiraDaeWriter.Write(mesh, descriptor.Name, OutputDirPath, fileType); | 
 
 
 
 
 | 65 | return; | 
 
 
 
 
 | 66 | } | 
 
 
 
 
 | 67 |  | 
 
 
 
 
 | 68 | var scene = new Dae.Scene(); | 
 
 
 
 
 | 69 | scene.Name = descriptor.Name; | 
 
 
 
 
 | 70 |  | 
 
 
 
 
 | 71 | var textureWriter = new Motoko.TextureDaeWriter(OutputDirPath); | 
 
 
 
 
 | 72 | var geometryWriter = new Motoko.GeometryDaeWriter(textureWriter); | 
 
 
 
 
 | 73 | var bodyWriter = new Totoro.BodyDaeWriter(geometryWriter); | 
 
 
 
 
 | 74 |  | 
 
 
 
 
 | 75 | if (tag == TemplateTag.OFGA) | 
 
 
 
 
 | 76 | ExportObjectGeometry(descriptor, scene, geometryWriter); | 
 
 
 
 
 | 77 | else if (tag == TemplateTag.OBAN) | 
 
 
 
 
 | 78 | ExportObjectAnimation(descriptor, scene, geometryWriter); | 
 
 
 
 
 | 79 | else if (tag == TemplateTag.ONCC) | 
 
 
 
 
 | 80 | ExportCharacterBody(descriptor, scene, bodyWriter); | 
 
 
 
 
 | 81 | else if (tag == TemplateTag.TRBS) | 
 
 
 
 
 | 82 | ExportCharacterBodySet(descriptor, scene, bodyWriter); | 
 
 
 
 
 | 83 | else if (tag == TemplateTag.M3GM) | 
 
 
 
 
 | 84 | ExportGeometry(descriptor, scene, geometryWriter); | 
 
 
 
 
 | 85 | else if (tag == TemplateTag.ONWC) | 
 
 
 
 
 | 86 | ExportWeaponGeometry(descriptor, scene, geometryWriter); | 
 
 
 
 
 | 87 |  | 
 
 
 
 
 | 88 | if (scene.Nodes.Count > 0) | 
 
 
 
 
 | 89 | { | 
 
 
 
 
 | 90 | string filePath = Path.Combine(OutputDirPath, descriptor.Name + "." + fileType); | 
 
 
 
 
 | 91 |  | 
 
 
 
 
 | 92 | Dae.Writer.WriteFile(filePath, scene); | 
 
 
 
 
 | 93 | } | 
 
 
 
 
 | 94 | } | 
 
 
 
 
 | 95 |  | 
 
 
 
 
 | 96 | private void ExportObjectGeometry(InstanceDescriptor descriptor, Dae.Scene scene, Motoko.GeometryDaeWriter geometryWriter) | 
 
 
 
 
 | 97 | { | 
 
 
 
 
 | 98 | var geometry = Physics.ObjectDatReader.ReadObjectGeometry(descriptor); | 
 
 
 
 
 | 99 | var root = new Dae.Node(); | 
 
 
 
 
 | 100 |  | 
 
 
 
 
 | 101 | foreach (var objNode in geometry.Geometries) | 
 
 
 
 
 | 102 | root.Nodes.Add(geometryWriter.WriteNode(objNode.Geometry, objNode.Geometry.Name)); | 
 
 
 
 
 | 103 |  | 
 
 
 
 
 | 104 | scene.Nodes.Add(root); | 
 
 
 
 
 | 105 | } | 
 
 
 
 
 | 106 |  | 
 
 
 
 
 | 107 | private void ExportObjectAnimation(InstanceDescriptor descriptor, Dae.Scene scene, Motoko.GeometryDaeWriter geometryWriter) | 
 
 
 
 
 | 108 | { | 
 
 
 
 
 | 109 | var animation = Physics.ObjectDatReader.ReadAnimation(descriptor); | 
 
 
 
 
 | 110 | Dae.Node node; | 
 
 
 
 
 | 111 |  | 
 
 
 
 
 | 112 | if (geometryName == "camera") | 
 
 
 
 
 | 113 | { | 
 
 
 
 
 | 114 | node = new Dae.Node | 
 
 
 
 
 | 115 | { | 
 
 
 
 
 | 116 | Name = descriptor.Name + "_camera", | 
 
 
 
 
 | 117 | Instances = { | 
 
 
 
 
 | 118 | new Dae.CameraInstance { | 
 
 
 
 
 | 119 | Target = new Dae.Camera { | 
 
 
 
 
 | 120 | XFov = 45.0f, | 
 
 
 
 
 | 121 | AspectRatio = 4.0f / 3.0f, | 
 
 
 
 
 | 122 | ZNear = 1.0f, | 
 
 
 
 
 | 123 | ZFar = 10000.0f | 
 
 
 
 
 | 124 | } | 
 
 
 
 
 | 125 | }} | 
 
 
 
 
 | 126 | }; | 
 
 
 
 
 | 127 | } | 
 
 
 
 
 | 128 | else if (geometryName != null) | 
 
 
 
 
 | 129 | { | 
 
 
 
 
 | 130 | var file = InstanceFileManager.OpenFile(geometryName); | 
 
 
 
 
 | 131 |  | 
 
 
 
 
 | 132 | if (file == null) | 
 
 
 
 
 | 133 | { | 
 
 
 
 
 | 134 | Console.Error.WriteLine("Cannot fine file {0}", geometryName); | 
 
 
 
 
 | 135 | node = new Dae.Node(); | 
 
 
 
 
 | 136 | } | 
 
 
 
 
 | 137 | else | 
 
 
 
 
 | 138 | { | 
 
 
 
 
 | 139 | var geom = Motoko.GeometryDatReader.Read(file.Descriptors[0]); | 
 
 
 
 
 | 140 | node = geometryWriter.WriteNode(geom, geom.Name); | 
 
 
 
 
 | 141 | } | 
 
 
 
 
 | 142 | } | 
 
 
 
 
 | 143 | else | 
 
 
 
 
 | 144 | { | 
 
 
 
 
 | 145 | node = new Dae.Node(); | 
 
 
 
 
 | 146 | } | 
 
 
 
 
 | 147 |  | 
 
 
 
 
 | 148 | scene.Nodes.Add(node); | 
 
 
 
 
 | 149 |  | 
 
 
 
 
 | 150 | ExportAnimation(node, new List<Physics.ObjectAnimationKey>(animation.Keys)); | 
 
 
 
 
 | 151 | } | 
 
 
 
 
 | 152 |  | 
 
 
 
 
 | 153 | private void ExportGeometry(InstanceDescriptor descriptor, Dae.Scene scene, Motoko.GeometryDaeWriter geometryWriter) | 
 
 
 
 
 | 154 | { | 
 
 
 
 
 | 155 | var animations = new List<Physics.ObjectAnimation>(animationNames.Count); | 
 
 
 
 
 | 156 |  | 
 
 
 
 
 | 157 | foreach (string animationFilePath in animationNames) | 
 
 
 
 
 | 158 | { | 
 
 
 
 
 | 159 | var file = InstanceFileManager.OpenFile(animationFilePath); | 
 
 
 
 
 | 160 |  | 
 
 
 
 
 | 161 | if (file == null) | 
 
 
 
 
 | 162 | { | 
 
 
 
 
 | 163 | Console.Error.WriteLine("Cannot find animation {0}", animationFilePath); | 
 
 
 
 
 | 164 | continue; | 
 
 
 
 
 | 165 | } | 
 
 
 
 
 | 166 |  | 
 
 
 
 
 | 167 | animations.Add(Physics.ObjectDatReader.ReadAnimation(file.Descriptors[0])); | 
 
 
 
 
 | 168 | } | 
 
 
 
 
 | 169 |  | 
 
 
 
 
 | 170 | ExportGeometry(scene, geometryWriter, descriptor, animations); | 
 
 
 
 
 | 171 | } | 
 
 
 
 
 | 172 |  | 
 
 
 
 
 | 173 | private void ExportCharacterBodySet(InstanceDescriptor descriptor, Dae.Scene scene, Totoro.BodyDaeWriter bodyWriter) | 
 
 
 
 
 | 174 | { | 
 
 
 
 
 | 175 | var body = Totoro.BodyDatReader.Read(descriptor); | 
 
 
 
 
 | 176 | var node = bodyWriter.Write(body, noAnimation, null); | 
 
 
 
 
 | 177 |  | 
 
 
 
 
 | 178 | scene.Nodes.Add(node); | 
 
 
 
 
 | 179 | } | 
 
 
 
 
 | 180 |  | 
 
 
 
 
 | 181 | private void ExportCharacterBody(InstanceDescriptor descriptor, Dae.Scene scene, Totoro.BodyDaeWriter bodyWriter) | 
 
 
 
 
 | 182 | { | 
 
 
 
 
 | 183 | var animationName = animationNames.Count > 0 ? animationNames[0] : null; | 
 
 
 
 
 | 184 | var characterClass = Game.CharacterClass.Read(descriptor, animationName); | 
 
 
 
 
 | 185 |  | 
 
 
 
 
 | 186 | var body = Totoro.BodyDatReader.Read(characterClass.Body); | 
 
 
 
 
 | 187 | var textures = characterClass.Textures; | 
 
 
 
 
 | 188 | var pelvis = bodyWriter.Write(body, noAnimation, textures); | 
 
 
 
 
 | 189 |  | 
 
 
 
 
 | 190 | scene.Nodes.Add(pelvis); | 
 
 
 
 
 | 191 |  | 
 
 
 
 
 | 192 | var animation = noAnimation ? null : characterClass.Animation; | 
 
 
 
 
 | 193 |  | 
 
 
 
 
 | 194 | if (animation != null) | 
 
 
 
 
 | 195 | { | 
 
 
 
 
 | 196 | var anim = Totoro.AnimationDatReader.Read(animation); | 
 
 
 
 
 | 197 |  | 
 
 
 
 
 | 198 | Totoro.AnimationDaeWriter.Write(pelvis, anim); | 
 
 
 
 
 | 199 | } | 
 
 
 
 
 | 200 | } | 
 
 
 
 
 | 201 |  | 
 
 
 
 
 | 202 | private void ExportWeaponGeometry(InstanceDescriptor descriptor, Dae.Scene scene, Motoko.GeometryDaeWriter geometryWriter) | 
 
 
 
 
 | 203 | { | 
 
 
 
 
 | 204 | var weaponClass = Game.WeaponClass.Read(descriptor); | 
 
 
 
 
 | 205 |  | 
 
 
 
 
 | 206 | if (weaponClass.Geometry != null) | 
 
 
 
 
 | 207 | ExportGeometry(weaponClass.Geometry, scene, geometryWriter); | 
 
 
 
 
 | 208 | } | 
 
 
 
 
 | 209 |  | 
 
 
 
 
 | 210 | private static void ExportGeometry(Dae.Scene scene, Motoko.GeometryDaeWriter geometryWriter, InstanceDescriptor m3gm, List<Physics.ObjectAnimation> animations) | 
 
 
 
 
 | 211 | { | 
 
 
 
 
 | 212 | var geometry = Motoko.GeometryDatReader.Read(m3gm); | 
 
 
 
 
 | 213 |  | 
 
 
 
 
 | 214 | if (animations != null && animations.Count > 0) | 
 
 
 
 
 | 215 | { | 
 
 
 
 
 | 216 | geometry.HasTransform = true; | 
 
 
 
 
 | 217 | geometry.Transform = Matrix.CreateScale(animations[0].Keys[0].Scale); | 
 
 
 
 
 | 218 | } | 
 
 
 
 
 | 219 |  | 
 
 
 
 
 | 220 | var node = geometryWriter.WriteNode(geometry, m3gm.Name); | 
 
 
 
 
 | 221 | scene.Nodes.Add(node); | 
 
 
 
 
 | 222 |  | 
 
 
 
 
 | 223 | if (animations != null && animations.Count > 0) | 
 
 
 
 
 | 224 | { | 
 
 
 
 
 | 225 | var frames = new List<Physics.ObjectAnimationKey>(); | 
 
 
 
 
 | 226 | int offset = 0; | 
 
 
 
 
 | 227 |  | 
 
 
 
 
 | 228 | foreach (var animation in animations) | 
 
 
 
 
 | 229 | { | 
 
 
 
 
 | 230 | foreach (var key in animation.Keys) | 
 
 
 
 
 | 231 | { | 
 
 
 
 
 | 232 | frames.Add(new Physics.ObjectAnimationKey | 
 
 
 
 
 | 233 | { | 
 
 
 
 
 | 234 | Translation = key.Translation, | 
 
 
 
 
 | 235 | Rotation = key.Rotation, | 
 
 
 
 
 | 236 | Time = key.Time + offset | 
 
 
 
 
 | 237 | }); | 
 
 
 
 
 | 238 | } | 
 
 
 
 
 | 239 |  | 
 
 
 
 
 | 240 | offset += animation.Length; | 
 
 
 
 
 | 241 | } | 
 
 
 
 
 | 242 |  | 
 
 
 
 
 | 243 | ExportAnimation(node, frames); | 
 
 
 
 
 | 244 | } | 
 
 
 
 
 | 245 | } | 
 
 
 
 
 | 246 |  | 
 
 
 
 
 | 247 | private static void ExportAnimation(Dae.Node node, List<Physics.ObjectAnimationKey> frames) | 
 
 
 
 
 | 248 | { | 
 
 
 
 
 | 249 | var times = new float[frames.Count]; | 
 
 
 
 
 | 250 | var interpolations = new string[times.Length]; | 
 
 
 
 
 | 251 | var positions = new Vector3[frames.Count]; | 
 
 
 
 
 | 252 | var angles = new Vector3[frames.Count]; | 
 
 
 
 
 | 253 |  | 
 
 
 
 
 | 254 | for (int i = 0; i < times.Length; ++i) | 
 
 
 
 
 | 255 | times[i] = frames[i].Time / 60.0f; | 
 
 
 
 
 | 256 |  | 
 
 
 
 
 | 257 | for (int i = 0; i < interpolations.Length; i++) | 
 
 
 
 
 | 258 | interpolations[i] = "LINEAR"; | 
 
 
 
 
 | 259 |  | 
 
 
 
 
 | 260 | for (int i = 0; i < frames.Count; i++) | 
 
 
 
 
 | 261 | positions[i] = frames[i].Translation; | 
 
 
 
 
 | 262 |  | 
 
 
 
 
 | 263 | for (int i = 0; i < frames.Count; i++) | 
 
 
 
 
 | 264 | angles[i] = frames[i].Rotation.ToEulerXYZ(); | 
 
 
 
 
 | 265 |  | 
 
 
 
 
 | 266 | var translate = node.Transforms.Translate("translate", positions[0]); | 
 
 
 
 
 | 267 | var rotateX = node.Transforms.Rotate("rotX", Vector3.UnitX, angles[0].X); | 
 
 
 
 
 | 268 | var rotateY = node.Transforms.Rotate("rotY", Vector3.UnitY, angles[0].Y); | 
 
 
 
 
 | 269 | var rotateZ = node.Transforms.Rotate("rotZ", Vector3.UnitZ, angles[0].Z); | 
 
 
 
 
 | 270 |  | 
 
 
 
 
 | 271 | WriteSampler(times, interpolations, i => positions[i].X, translate, "X"); | 
 
 
 
 
 | 272 | WriteSampler(times, interpolations, i => positions[i].Y, translate, "Y"); | 
 
 
 
 
 | 273 | WriteSampler(times, interpolations, i => positions[i].Z, translate, "Z"); | 
 
 
 
 
 | 274 | WriteSampler(times, interpolations, i => angles[i].X, rotateX, "ANGLE"); | 
 
 
 
 
 | 275 | WriteSampler(times, interpolations, i => angles[i].Y, rotateY, "ANGLE"); | 
 
 
 
 
 | 276 | WriteSampler(times, interpolations, i => angles[i].Z, rotateZ, "ANGLE"); | 
 
 
 
 
 | 277 | } | 
 
 
 
 
 | 278 |  | 
 
 
 
 
 | 279 | private static void WriteSampler(float[] times, string[] interpolations, Func<int, float> getValue, Dae.Transform transform, string targetName) | 
 
 
 
 
 | 280 | { | 
 
 
 
 
 | 281 | var values = new float[times.Length]; | 
 
 
 
 
 | 282 |  | 
 
 
 
 
 | 283 | for (int i = 0; i < values.Length; ++i) | 
 
 
 
 
 | 284 | values[i] = getValue(i); | 
 
 
 
 
 | 285 |  | 
 
 
 
 
 | 286 | transform.BindAnimation(targetName, new Dae.Sampler | 
 
 
 
 
 | 287 | { | 
 
 
 
 
 | 288 | Inputs = { | 
 
 
 
 
 | 289 | new Dae.Input(Dae.Semantic.Input, new Dae.Source(times, 1)), | 
 
 
 
 
 | 290 | new Dae.Input(Dae.Semantic.Output, new Dae.Source(values, 1)), | 
 
 
 
 
 | 291 | new Dae.Input(Dae.Semantic.Interpolation, new Dae.Source(interpolations, 1)) | 
 
 
 
 
 | 292 | } | 
 
 
 
 
 | 293 | }); | 
 
 
 
 
 | 294 | } | 
 
 
 
 
 | 295 | } | 
 
 
 
 
 | 296 | } |