| 1 | using System; | 
 
 
 
 
 | 2 | using System.Collections.Generic; | 
 
 
 
 
 | 3 | using System.IO; | 
 
 
 
 
 | 4 |  | 
 
 
 
 
 | 5 | namespace Oni.Totoro | 
 
 
 
 
 | 6 | { | 
 
 
 
 
 | 7 | internal class BodyDaeReader | 
 
 
 
 
 | 8 | { | 
 
 
 
 
 | 9 | private Body body; | 
 
 
 
 
 | 10 | private float shellOffset = 0.07f; | 
 
 
 
 
 | 11 | private bool generateNormals; | 
 
 
 
 
 | 12 | private bool flatNormals; | 
 
 
 
 
 | 13 |  | 
 
 
 
 
 | 14 | private BodyDaeReader() | 
 
 
 
 
 | 15 | { | 
 
 
 
 
 | 16 | } | 
 
 
 
 
 | 17 |  | 
 
 
 
 
 | 18 | public static Body Read(Dae.Scene scene) | 
 
 
 
 
 | 19 | { | 
 
 
 
 
 | 20 | var reader = new BodyDaeReader | 
 
 
 
 
 | 21 | { | 
 
 
 
 
 | 22 | body = new Body() | 
 
 
 
 
 | 23 | }; | 
 
 
 
 
 | 24 |  | 
 
 
 
 
 | 25 | reader.ReadBodyParts(scene); | 
 
 
 
 
 | 26 | return reader.body; | 
 
 
 
 
 | 27 | } | 
 
 
 
 
 | 28 |  | 
 
 
 
 
 | 29 | public static Body Read(Dae.Scene scene, bool generateNormals, bool flatNormals, float shellOffset) | 
 
 
 
 
 | 30 | { | 
 
 
 
 
 | 31 | var reader = new BodyDaeReader | 
 
 
 
 
 | 32 | { | 
 
 
 
 
 | 33 | body = new Body(), | 
 
 
 
 
 | 34 | flatNormals = flatNormals, | 
 
 
 
 
 | 35 | generateNormals = generateNormals, | 
 
 
 
 
 | 36 | shellOffset = shellOffset | 
 
 
 
 
 | 37 | }; | 
 
 
 
 
 | 38 |  | 
 
 
 
 
 | 39 | reader.ReadBodyParts(scene); | 
 
 
 
 
 | 40 | return reader.body; | 
 
 
 
 
 | 41 | } | 
 
 
 
 
 | 42 |  | 
 
 
 
 
 | 43 | private void ReadBodyParts(Dae.Scene scene) | 
 
 
 
 
 | 44 | { | 
 
 
 
 
 | 45 | var rootBodyNode = FindRootNode(scene); | 
 
 
 
 
 | 46 |  | 
 
 
 
 
 | 47 | if (rootBodyNode == null) | 
 
 
 
 
 | 48 | throw new InvalidDataException("The scene does not contain any geometry nodes."); | 
 
 
 
 
 | 49 |  | 
 
 
 
 
 | 50 | // | 
 
 
 
 
 | 51 | // Make sure the pelvis is not translated from origin. | 
 
 
 
 
 | 52 | // | 
 
 
 
 
 | 53 |  | 
 
 
 
 
 | 54 | rootBodyNode.Translation = Vector3.Zero; | 
 
 
 
 
 | 55 |  | 
 
 
 
 
 | 56 | if (body.Nodes.Count != 19) | 
 
 
 
 
 | 57 | Console.Error.WriteLine("Non standard bone count: {0}", body.Nodes.Count); | 
 
 
 
 
 | 58 | } | 
 
 
 
 
 | 59 |  | 
 
 
 
 
 | 60 | private BodyNode FindRootNode(Dae.Node daeNode) | 
 
 
 
 
 | 61 | { | 
 
 
 
 
 | 62 | if (daeNode.GeometryInstances.Any()) | 
 
 
 
 
 | 63 | return ReadNode(daeNode, null); | 
 
 
 
 
 | 64 |  | 
 
 
 
 
 | 65 | foreach (var childDaeNode in daeNode.Nodes) | 
 
 
 
 
 | 66 | { | 
 
 
 
 
 | 67 | var bodyNode = FindRootNode(childDaeNode); | 
 
 
 
 
 | 68 |  | 
 
 
 
 
 | 69 | if (bodyNode != null) | 
 
 
 
 
 | 70 | return bodyNode; | 
 
 
 
 
 | 71 | } | 
 
 
 
 
 | 72 |  | 
 
 
 
 
 | 73 | return null; | 
 
 
 
 
 | 74 | } | 
 
 
 
 
 | 75 |  | 
 
 
 
 
 | 76 | private BodyNode ReadNode(Dae.Node daeNode, BodyNode parentNode) | 
 
 
 
 
 | 77 | { | 
 
 
 
 
 | 78 | var bodyNode = new BodyNode | 
 
 
 
 
 | 79 | { | 
 
 
 
 
 | 80 | DaeNode = daeNode, | 
 
 
 
 
 | 81 | Parent = parentNode, | 
 
 
 
 
 | 82 | Index = body.Nodes.Count | 
 
 
 
 
 | 83 | }; | 
 
 
 
 
 | 84 |  | 
 
 
 
 
 | 85 | body.Nodes.Add(bodyNode); | 
 
 
 
 
 | 86 |  | 
 
 
 
 
 | 87 | // | 
 
 
 
 
 | 88 | // Find and read the geometry for this node | 
 
 
 
 
 | 89 | // | 
 
 
 
 
 | 90 |  | 
 
 
 
 
 | 91 | foreach (var geometryInstance in daeNode.GeometryInstances.Where(n => n.Target != null)) | 
 
 
 
 
 | 92 | { | 
 
 
 
 
 | 93 | var daeGeometry = geometryInstance.Target; | 
 
 
 
 
 | 94 |  | 
 
 
 
 
 | 95 | if (bodyNode.Geometry != null) | 
 
 
 
 
 | 96 | Console.Error.WriteLine("The node {0} contains more than one geometry. Only the first geometry will be used.", daeGeometry.Name); | 
 
 
 
 
 | 97 |  | 
 
 
 
 
 | 98 | bodyNode.Geometry = Motoko.GeometryDaeReader.Read(daeGeometry, generateNormals, flatNormals, shellOffset); | 
 
 
 
 
 | 99 | } | 
 
 
 
 
 | 100 |  | 
 
 
 
 
 | 101 | // | 
 
 
 
 
 | 102 | // Extract the translation part of this node's transform | 
 
 
 
 
 | 103 | // | 
 
 
 
 
 | 104 |  | 
 
 
 
 
 | 105 | bodyNode.Translation = daeNode.Transforms.ToMatrix().Translation; | 
 
 
 
 
 | 106 |  | 
 
 
 
 
 | 107 | // | 
 
 
 
 
 | 108 | // Read child nodes | 
 
 
 
 
 | 109 | // | 
 
 
 
 
 | 110 |  | 
 
 
 
 
 | 111 | foreach (var daeChildNode in daeNode.Nodes) | 
 
 
 
 
 | 112 | bodyNode.Nodes.Add(ReadNode(daeChildNode, parentNode)); | 
 
 
 
 
 | 113 |  | 
 
 
 
 
 | 114 | return bodyNode; | 
 
 
 
 
 | 115 | } | 
 
 
 
 
 | 116 | } | 
 
 
 
 
 | 117 | } |