using System; using System.Collections.Generic; using System.IO; namespace Oni.Totoro { internal class BodyDaeReader { private Body body; private float shellOffset = 0.07f; private bool generateNormals; private bool flatNormals; private BodyDaeReader() { } public static Body Read(Dae.Scene scene) { var reader = new BodyDaeReader { body = new Body() }; reader.ReadBodyParts(scene); return reader.body; } public static Body Read(Dae.Scene scene, bool generateNormals, bool flatNormals, float shellOffset) { var reader = new BodyDaeReader { body = new Body(), flatNormals = flatNormals, generateNormals = generateNormals, shellOffset = shellOffset }; reader.ReadBodyParts(scene); return reader.body; } private void ReadBodyParts(Dae.Scene scene) { var rootBodyNode = FindRootNode(scene); if (rootBodyNode == null) throw new InvalidDataException("The scene does not contain any geometry nodes."); // // Make sure the pelvis is not translated from origin. // rootBodyNode.Translation = Vector3.Zero; if (body.Nodes.Count != 19) Console.Error.WriteLine("Non standard bone count: {0}", body.Nodes.Count); } private BodyNode FindRootNode(Dae.Node daeNode) { if (daeNode.GeometryInstances.Any()) return ReadNode(daeNode, null); foreach (var childDaeNode in daeNode.Nodes) { var bodyNode = FindRootNode(childDaeNode); if (bodyNode != null) return bodyNode; } return null; } private BodyNode ReadNode(Dae.Node daeNode, BodyNode parentNode) { var bodyNode = new BodyNode { DaeNode = daeNode, Parent = parentNode, Index = body.Nodes.Count }; body.Nodes.Add(bodyNode); // // Find and read the geometry for this node // foreach (var geometryInstance in daeNode.GeometryInstances.Where(n => n.Target != null)) { var daeGeometry = geometryInstance.Target; if (bodyNode.Geometry != null) Console.Error.WriteLine("The node {0} contains more than one geometry. Only the first geometry will be used.", daeGeometry.Name); bodyNode.Geometry = Motoko.GeometryDaeReader.Read(daeGeometry, generateNormals, flatNormals, shellOffset); } // // Extract the translation part of this node's transform // bodyNode.Translation = daeNode.Transforms.ToMatrix().Translation; // // Read child nodes // foreach (var daeChildNode in daeNode.Nodes) bodyNode.Nodes.Add(ReadNode(daeChildNode, parentNode)); return bodyNode; } } }