private void ExportCollada_NodeSub(XmlWriter xml, IReadOnlyList <string> boneNames, Kn5Node node) { xml.WriteStartElement("node"); xml.WriteAttributeStringSafe("id", node.Name); xml.WriteAttributeStringSafe("sid", node.Name); xml.WriteAttributeStringSafe("name", node.Name); xml.WriteAttributeString("layer", node.Active ? "Visible" : "Hidden"); xml.WriteAttributeString("type", node.NodeClass == Kn5NodeClass.Base && boneNames.Contains(node.Name) ? "JOINT" : "NODE"); if (node.Children?.FirstOrDefault()?.NodeClass != Kn5NodeClass.SkinnedMesh) { xml.WriteElement("matrix", "sid", "transform", node.NodeClass == Kn5NodeClass.Base ? XmlWriterExtension.MatrixToCollada(node.Transform) : "1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0"); } if (IsMultiMaterial(node) && node.Children != null) { xml.WriteStartElement("instance_geometry"); xml.WriteAttributeStringSafe("url", $"#{node.Name}-mesh"); ExportCollada_NodeSub_BindMaterial(xml, node.Children.Select(x => x.MaterialId).ToArray()); xml.WriteEndElement(); } else { ExportCollada_NodeSub_Inner(xml, boneNames, node); } xml.WriteEndElement(); // node }
private void ExportCollada_Skinned(XmlWriter xml, Kn5Node node) { switch (node.NodeClass) { case Kn5NodeClass.Base: foreach (var child in node.Children) { ExportCollada_Skinned(xml, child); } break; case Kn5NodeClass.Mesh: return; case Kn5NodeClass.SkinnedMesh: xml.WriteStartElement("controller"); xml.WriteAttributeStringSafe("id", $"{node.Name}Controller"); xml.WriteStartElement("skin"); xml.WriteAttributeStringSafe("source", $"#{node.Name}-mesh"); // xml.WriteElementString("bind_shape_matrix", "1 0 0 0 0 0 1 0 0 -1 0 0 0 0 0 1"); xml.WriteElementString("bind_shape_matrix", "1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1"); // Joints xml.WriteStartElement("source"); xml.WriteAttributeStringSafe("id", $"{node.Name}Controller-Joints"); xml.WriteStartElement("Name_array"); xml.WriteAttributeStringSafe("id", $"{node.Name}Controller-Joints-array"); xml.WriteAttributeString("count", node.Bones.Length); xml.WriteString(node.Bones.Select(x => x.Name).JoinToString(" ")); xml.WriteEndElement(); // Name_array xml.WriteStartElement("technique_common"); xml.WriteStartElement("accessor"); xml.WriteAttributeStringSafe("source", $"#{node.Name}Controller-Joints-array"); xml.WriteAttributeString("count", node.Bones.Length); xml.WriteAttributeString("stride", 1); xml.WriteStartElement("param"); xml.WriteAttributeString("name", "JOINT"); xml.WriteAttributeString("type", "name"); xml.WriteEndElement(); // param xml.WriteEndElement(); // accessor xml.WriteEndElement(); // technique_common xml.WriteEndElement(); // source (Joints) // Matrices xml.WriteStartElement("source"); xml.WriteAttributeStringSafe("id", $"{node.Name}Controller-Matrices"); xml.WriteStartElement("float_array"); xml.WriteAttributeStringSafe("id", $"{node.Name}Controller-Matrices-array"); xml.WriteAttributeString("count", node.Bones.Length * 16); xml.WriteString(node.Bones.Select(x => XmlWriterExtension.MatrixToCollada(x.Transform)) .JoinToString(" ")); xml.WriteEndElement(); // float_array xml.WriteStartElement("technique_common"); xml.WriteStartElement("accessor"); xml.WriteAttributeStringSafe("source", $"#{node.Name}Controller-Matrices-array"); xml.WriteAttributeString("count", node.Bones.Length); xml.WriteAttributeString("stride", 16); xml.WriteStartElement("param"); xml.WriteAttributeString("name", "TRANSFORM"); xml.WriteAttributeString("type", "float4x4"); xml.WriteEndElement(); // param xml.WriteEndElement(); // accessor xml.WriteEndElement(); // technique_common xml.WriteEndElement(); // source (Matrices) // Weights xml.WriteStartElement("source"); xml.WriteAttributeStringSafe("id", $"{node.Name}Controller-Weights"); xml.WriteStartElement("float_array"); xml.WriteAttributeStringSafe("id", $"{node.Name}Controller-Weights-array"); var weights = node.VerticeWeights.SelectMany(x => x.Weights.Where((y, i) => !Equals(x.Indices[i], -1f))).ToList(); xml.WriteAttributeString("count", weights.Count); xml.WriteString(weights.JoinToString(" ")); xml.WriteEndElement(); // float_array xml.WriteStartElement("technique_common"); xml.WriteStartElement("accessor"); xml.WriteAttributeStringSafe("source", $"#{node.Name}Controller-Weights-array"); xml.WriteAttributeString("count", weights.Count); xml.WriteAttributeString("stride", 1); xml.WriteStartElement("param"); xml.WriteAttributeString("name", "WEIGHT"); xml.WriteAttributeString("type", "float"); xml.WriteEndElement(); // param xml.WriteEndElement(); // accessor xml.WriteEndElement(); // technique_common xml.WriteEndElement(); // source (Matrices) xml.WriteStartElement("joints"); xml.WriteStartElement("input"); xml.WriteAttributeString("semantic", "JOINT"); xml.WriteAttributeStringSafe("source", $"#{node.Name}Controller-Joints"); xml.WriteEndElement(); // input xml.WriteStartElement("input"); xml.WriteAttributeString("semantic", "INV_BIND_MATRIX"); xml.WriteAttributeStringSafe("source", $"#{node.Name}Controller-Matrices"); xml.WriteEndElement(); // input xml.WriteEndElement(); // joints xml.WriteStartElement("vertex_weights"); xml.WriteAttributeString("count", node.Vertices.Length); xml.WriteStartElement("input"); xml.WriteAttributeString("semantic", "JOINT"); xml.WriteAttributeString("offset", 0); xml.WriteAttributeStringSafe("source", $"#{node.Name}Controller-Joints"); xml.WriteEndElement(); // input xml.WriteStartElement("input"); xml.WriteAttributeString("semantic", "WEIGHT"); xml.WriteAttributeString("offset", 1); xml.WriteAttributeStringSafe("source", $"#{node.Name}Controller-Weights"); xml.WriteEndElement(); // input xml.WriteElementString("vcount", node.VerticeWeights.Select(x => x.Weights.Where(y => !Equals(y, 0f)).Count()).JoinToString(" ")); var k = 0; xml.WriteElementString("v", node.VerticeWeights.SelectMany(x => x.Indices.Where(y => !Equals(y, -1f)).SelectMany((y, i) => new[] { y, k++ })).JoinToString(" ")); xml.WriteEndElement(); // vertex_weights xml.WriteEndElement(); // skin xml.WriteEndElement(); // controller break; } }