protected bool ExtractSkeletonData(Entity entity, out int boneCount, out int weightCount) { bool isValidData = false; boneCount = 0; weightCount = 0; //Check if we have pose animation which the HS sub render state does not //know how to handle bool hasVertexAnim = entity.Mesh.HasVertexAnimation; //gather data on the skeleton if (!hasVertexAnim && entity.HasSkeleton) { //get weights count Mesh mesh = entity.Mesh; // nb: OGRE source gets ..blendIndexToBoneIndexMap.Count, is this accurate? boneCount = mesh.BoneAssignmentList.Count; int totalMeshes = mesh.SubMeshCount; for (int i = 0; i < totalMeshes; i++) { var ro = new RenderOperation(); SubMesh subMesh = mesh.GetSubMesh(i); subMesh.GetRenderOperation(ro, 0); //get the largest bone assignment if (boneCount > subMesh.BoneAssignmentList.Count) { } else { boneCount = subMesh.BoneAssignmentList.Count; } //go over vertex decleration //check that they have blend indices and blend weights VertexElement declWeights = ro.vertexData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.BlendWeights, 0); VertexElement declIndexes = ro.vertexData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.BlendIndices, 0); if ((declWeights != null) && (declIndexes != null)) { isValidData = true; switch (declWeights.Type) { case VertexElementType.Float1: weightCount = Axiom.Math.Utility.Clamp(weightCount, weightCount, 1); break; case VertexElementType.Float2: weightCount = Axiom.Math.Utility.Clamp(weightCount, weightCount, 2); break; case VertexElementType.Float3: weightCount = Axiom.Math.Utility.Clamp(weightCount, weightCount, 3); break; case VertexElementType.Float4: weightCount = Axiom.Math.Utility.Clamp(weightCount, weightCount, 4); break; default: isValidData = false; break; } if (isValidData == false) { break; } } } } return(isValidData); }
protected XmlElement WriteSubmesh(SubMesh subMesh) { XmlElement node = document.CreateElement("submesh"); XmlAttribute attr; attr = document.CreateAttribute("material"); attr.Value = subMesh.MaterialName; node.Attributes.Append(attr); attr = document.CreateAttribute("usesharedvertices"); attr.Value = (subMesh.useSharedVertices) ? "true" : "false"; node.Attributes.Append(attr); VertexData vertexData = (subMesh.useSharedVertices) ? mesh.SharedVertexData : subMesh.vertexData; IndexType indexType = IndexType.Size16; if (vertexData.vertexCount > short.MaxValue) { indexType = IndexType.Size32; } attr = document.CreateAttribute("use32bitindexes"); attr.Value = (indexType == IndexType.Size32) ? "true" : "false"; node.Attributes.Append(attr); bool isTriList = true; // TODO: Support things other than triangle lists attr = document.CreateAttribute("operationtype"); RenderOperation op = new RenderOperation(); subMesh.GetRenderOperation(op); switch (op.operationType) { case OperationType.TriangleList: attr.Value = "triangle_list"; break; case OperationType.TriangleStrip: attr.Value = "triangle_strip"; isTriList = false; break; case OperationType.TriangleFan: attr.Value = "triangle_fan"; isTriList = false; break; default: throw new AxiomException("Export of non triangle lists is not supported"); } node.Attributes.Append(attr); XmlElement childNode; childNode = WriteFaces(subMesh, indexType, isTriList); node.AppendChild(childNode); if (!subMesh.useSharedVertices) { childNode = WriteGeometry(subMesh); node.AppendChild(childNode); } if (subMesh.BoneAssignmentList.Count > 0) { childNode = WriteBoneAssignments(subMesh); node.AppendChild(childNode); } return(node); }