private XmlVertexData GetXmlVertexData(VertexData vertexData) { XmlVertexData xmlVertexData = new XmlVertexData(vertexData.vertexCount); xmlVertexData.positionData = null; xmlVertexData.normalData = null; xmlVertexData.diffuseData = null; xmlVertexData.specularData = null; // Normals are transformed by the transpose of the inverse of the spatial transform. // Exclude the scale though, since I don't want to mess that up. float scale = GetScale(exportTransform); Matrix4 tmpTransform = ScaleMatrix(exportTransform, 1 / scale); Matrix4 invTrans = tmpTransform.Inverse().Transpose(); // I'm going to write all the texture buffers to one vertex // buffer, so I can leave textureOffset at zero. int textureOffset = 0; for (short bindIdx = 0; bindIdx < vertexData.vertexDeclaration.ElementCount; ++bindIdx) { VertexElement element = vertexData.vertexDeclaration.GetElement(bindIdx); HardwareVertexBuffer vBuffer = vertexData.vertexBufferBinding.GetBuffer(element.Source); int vertexOffset = element.Offset; int vertexStride = vBuffer.VertexSize; switch (element.Semantic) { case VertexElementSemantic.Position: xmlVertexData.positionData = new float[xmlVertexData.vertexCount, 3]; ReadBuffer(vBuffer, vertexOffset, vertexStride, xmlVertexData.vertexCount, element.Size, xmlVertexData.positionData, exportTransform); break; case VertexElementSemantic.Normal: xmlVertexData.normalData = new float[xmlVertexData.vertexCount, 3]; ReadBuffer(vBuffer, vertexOffset, vertexStride, xmlVertexData.vertexCount, element.Size, xmlVertexData.normalData, invTrans); break; case VertexElementSemantic.Diffuse: xmlVertexData.diffuseData = new uint[xmlVertexData.vertexCount]; ReadBuffer(vBuffer, vertexOffset, vertexStride, xmlVertexData.vertexCount, element.Size, xmlVertexData.diffuseData); break; case VertexElementSemantic.Specular: xmlVertexData.specularData = new uint[xmlVertexData.vertexCount]; ReadBuffer(vBuffer, vertexOffset, vertexStride, xmlVertexData.vertexCount, element.Size, xmlVertexData.specularData); break; case VertexElementSemantic.TexCoords: { int dim = VertexElement.GetTypeSize(element.Type) / VertexElement.GetTypeSize(VertexElementType.Float1); float[,] data = new float[xmlVertexData.vertexCount, dim]; ReadBuffer(vBuffer, vertexOffset, vertexStride, xmlVertexData.vertexCount, element.Size, data); // pad out the list while (textureOffset + element.Index >= xmlVertexData.multiTexData.Count) xmlVertexData.multiTexData.Add(null); // set this element xmlVertexData.multiTexData[textureOffset + element.Index] = data; textureOffset++; } break; case VertexElementSemantic.Tangent: case VertexElementSemantic.Binormal: { int dim = VertexElement.GetTypeSize(element.Type) / VertexElement.GetTypeSize(VertexElementType.Float1); float[,] data = new float[xmlVertexData.vertexCount, dim]; ReadBuffer(vBuffer, vertexOffset, vertexStride, xmlVertexData.vertexCount, element.Size, data); // pad out the list while (textureOffset + element.Index >= xmlVertexData.multiTexData.Count) xmlVertexData.multiTexData.Add(null); // set this element xmlVertexData.multiTexData[textureOffset + element.Index] = data; textureOffset++; } break; default: log.WarnFormat("Unknown vertex buffer semantic: {0}", element.Semantic); break; } } return xmlVertexData; }
protected XmlElement WriteVertex(XmlVertexData xmlVertData, int vertIndex) { XmlElement node = document.CreateElement("vertex"); if (xmlVertData.positionData != null) { XmlElement childNode = document.CreateElement("position"); WriteVector(childNode, ref xmlVertData.positionData, vertIndex); node.AppendChild(childNode); } if (xmlVertData.normalData != null) { XmlElement childNode = document.CreateElement("normal"); WriteVector(childNode, ref xmlVertData.normalData, vertIndex); node.AppendChild(childNode); } if (xmlVertData.diffuseData != null) { XmlElement childNode = document.CreateElement("colour_diffuse"); WriteColour(childNode, xmlVertData.diffuseData[vertIndex]); node.AppendChild(childNode); } if (xmlVertData.specularData != null) { XmlElement childNode = document.CreateElement("colour_specular"); WriteColour(childNode, xmlVertData.specularData[vertIndex]); node.AppendChild(childNode); } if (xmlVertData.multiTexData != null) { for (int texIndex = 0; texIndex < xmlVertData.multiTexData.Count; ++texIndex) { XmlElement childNode = document.CreateElement("texcoord"); WriteTexCoord(childNode, xmlVertData.multiTexData[texIndex], vertIndex); node.AppendChild(childNode); } } return node; }
protected XmlElement WriteVertexBuffer(XmlVertexData xmlVertData) { XmlElement node = document.CreateElement("vertexbuffer"); XmlAttribute attr; if (xmlVertData.positionData != null) { attr = document.CreateAttribute("positions"); attr.Value = "true"; node.Attributes.Append(attr); } if (xmlVertData.normalData != null) { attr = document.CreateAttribute("normals"); attr.Value = "true"; node.Attributes.Append(attr); } if (xmlVertData.diffuseData != null) { attr = document.CreateAttribute("colours_diffuse"); attr.Value = "true"; node.Attributes.Append(attr); } if (xmlVertData.specularData != null) { attr = document.CreateAttribute("colours_specular"); attr.Value = "true"; node.Attributes.Append(attr); } if (xmlVertData.multiTexData != null) { attr = document.CreateAttribute("texture_coords"); attr.Value = xmlVertData.multiTexData.Count.ToString(); node.Attributes.Append(attr); for (int i = 0; i < xmlVertData.multiTexData.Count; ++i) { attr = document.CreateAttribute("texture_coord_dimensions_" + i); attr.Value = xmlVertData.multiTexData[i].GetLength(1).ToString(); node.Attributes.Append(attr); } } // now write the vertex entries; for (int i = 0; i < xmlVertData.vertexCount; ++i) { XmlElement childNode = WriteVertex(xmlVertData, i); node.AppendChild(childNode); } return node; }
protected XmlNode WriteMesh() { XmlElement node = document.CreateElement("mesh"); XmlNode childNode; // Build the dictionary of vertex data for the submeshes. for (int i = 0; i < mesh.SubMeshCount; ++i) { SubMesh subMesh = mesh.GetSubMesh(i); if (subMesh.vertexData == null) continue; XmlVertexData vertexData = GetXmlVertexData(subMesh.vertexData); xmlVertexDataDict[subMesh] = vertexData; } // TODO: Write the shared xml vertex data if (mesh.SharedVertexData != null) sharedXmlVertexData = GetXmlVertexData(mesh.SharedVertexData); // Write the submesh components childNode = WriteSubmeshes(); node.AppendChild(childNode); // Next write skeletonlink if (mesh.HasSkeleton) { childNode = WriteSkeletonLink(); node.AppendChild(childNode); } if (mesh.SharedVertexData != null) { childNode = WriteGeometry(mesh); node.AppendChild(childNode); } if (mesh.BoneAssignmentList.Count > 0) { childNode = WriteBoneAssignments(mesh); node.AppendChild(childNode); } // TODO: // childNode = WriteLevelOfDetail(); // node.AppendChild(childNode); // Next write submesh names childNode = WriteSubmeshNames(); node.AppendChild(childNode); // Finally write the bounds info childNode = WriteBoundsInfo(); node.AppendChild(childNode); return node; }
protected XmlElement WriteGeometry(XmlVertexData xmlVertData, XmlElement node) { // Break up the vertex data into the portions used for geometry, and the // portions used for color and textures. XmlElement childNode; if (xmlVertData.positionData != null || xmlVertData.normalData != null) { XmlVertexData xmlGeomVertData = new XmlVertexData(xmlVertData.vertexCount); xmlGeomVertData.positionData = xmlVertData.positionData; xmlGeomVertData.normalData = xmlVertData.normalData; xmlGeomVertData.diffuseData = null; xmlGeomVertData.specularData = null; xmlGeomVertData.multiTexData = null; childNode = WriteVertexBuffer(xmlGeomVertData); node.AppendChild(childNode); } if (xmlVertData.diffuseData != null || xmlVertData.specularData != null || xmlVertData.multiTexData.Count > 0) { XmlVertexData xmlMatVertData = new XmlVertexData(xmlVertData.vertexCount); xmlMatVertData.positionData = null; xmlMatVertData.normalData = null; xmlMatVertData.diffuseData = xmlVertData.diffuseData; xmlMatVertData.specularData = xmlVertData.specularData; xmlMatVertData.multiTexData = xmlVertData.multiTexData; childNode = WriteVertexBuffer(xmlMatVertData); node.AppendChild(childNode); } return node; }
protected void ReadVertexBuffer(XmlNode node, VertexData vertexData, XmlVertexData xmlVertexData) { bool positions = false; bool normals = false; bool colours_diffuse = false; bool colours_specular = false; int texture_coords = 0; foreach (XmlAttribute attr in node.Attributes) { switch (attr.Name) { case "positions": if (attr.Value == "true") { positions = true; xmlVertexData.positionData = new float[xmlVertexData.vertexCount, 3]; } break; case "normals": if (attr.Value == "true") { normals = true; xmlVertexData.normalData = new float[xmlVertexData.vertexCount, 3]; } break; case "colours_diffuse": if (attr.Value == "true") { colours_diffuse = true; xmlVertexData.diffuseData = new uint[xmlVertexData.vertexCount]; } break; case "colours_specular": if (attr.Value == "true") { colours_specular = true; xmlVertexData.specularData = new uint[xmlVertexData.vertexCount]; } break; case "texture_coords": texture_coords = int.Parse(attr.Value); break; case "texture_coord_dimensions_0": case "texture_coord_dimensions_1": case "texture_coord_dimensions_2": case "texture_coord_dimensions_3": case "texture_coord_dimensions_4": case "texture_coord_dimensions_5": case "texture_coord_dimensions_6": case "texture_coord_dimensions_7": break; default: DebugMessage(node, attr); break; } } for (int i = 0; i < texture_coords; ++i) { string key = string.Format("texture_coord_dimensions_{0}", i); XmlNode attrNode = node.Attributes.GetNamedItem(key); if (attrNode != null) xmlVertexData.AddTexture(int.Parse(attrNode.Value)); else xmlVertexData.AddTexture(2); } int vertexIndex = 0; foreach (XmlNode childNode in node.ChildNodes) { switch (childNode.Name) { case "vertex": ReadVertex(childNode, xmlVertexData, vertexIndex++); break; default: DebugMessage(childNode); break; } } if (positions) AllocateBuffer(vertexData, VertexElementType.Float3, VertexElementSemantic.Position, xmlVertexData.bindIdx++, 0, xmlVertexData.positionData); if (normals) AllocateBuffer(vertexData, VertexElementType.Float3, VertexElementSemantic.Normal, xmlVertexData.bindIdx++, 0, xmlVertexData.normalData); if (colours_diffuse) AllocateBuffer(vertexData, VertexElementType.Color, VertexElementSemantic.Diffuse, xmlVertexData.bindIdx++, 0, xmlVertexData.diffuseData); if (colours_specular) AllocateBuffer(vertexData, VertexElementType.Color, VertexElementSemantic.Specular, xmlVertexData.bindIdx++, 0, xmlVertexData.specularData); for (int i = 0; i < texture_coords; ++i) { int dim = xmlVertexData.GetTextureData(i).GetLength(1); AllocateBuffer(vertexData, VertexElement.MultiplyTypeCount(VertexElementType.Float1, dim), VertexElementSemantic.TexCoords, xmlVertexData.bindIdx++, i, xmlVertexData.GetTextureData(i)); } // We have read the textures for this vertex buffer node. xmlVertexData.textureOffset += texture_coords; }
protected void ReadVertex(XmlNode node, XmlVertexData vertexData, int vertexIndex) { int textureIndex = 0; foreach (XmlNode childNode in node.ChildNodes) { switch (childNode.Name) { case "position": ReadVector(childNode, vertexData.positionData, vertexIndex); break; case "normal": ReadVector(childNode, vertexData.normalData, vertexIndex); break; case "colour_diffuse": ReadColour(childNode, vertexData.diffuseData, vertexIndex); break; case "colour_specular": ReadColour(childNode, vertexData.specularData, vertexIndex); break; case "texcoord": ReadTexCoord(childNode, vertexData.GetTextureData(textureIndex), vertexIndex); textureIndex++; break; default: DebugMessage(childNode); break; } } }
protected void ReadGeometry(XmlNode node, SubMesh subMesh) { if (subMesh.useSharedVertices) throw new Exception("I don't support shared vertices"); VertexData vertexData = new VertexData(); subMesh.vertexData = vertexData; vertexData.vertexStart = 0; vertexData.vertexCount = int.Parse(node.Attributes["vertexcount"].Value); XmlVertexData xmlVertexData = new XmlVertexData(vertexData.vertexCount); // Read in the various vertex buffers for this geometry, and // consolidate them into one vertex buffer. foreach (XmlNode childNode in node.ChildNodes) { switch (childNode.Name) { case "vertexbuffer": ReadVertexBuffer(childNode, subMesh.vertexData, xmlVertexData); break; default: DebugMessage(childNode); break; } } xmlVertexDataDict[subMesh] = xmlVertexData; }