public static IEnumerable <GeometryMesh> GetMeshes(Module module, ModuleItem item, IList <SectionBlock> sections, int lod, Func <SectionBlock, short?> boundsIndex, Func <int, int, int> mapNode = null) { VertexBufferInfo[] vertexBufferInfo; IndexBufferInfo[] indexBufferInfo; var resourceIndex = module.Resources[item.ResourceIndex]; var resource = module.Items[resourceIndex]; //this will be the [mesh resource!*] tag if (resource.ResourceCount > 0) { System.Diagnostics.Debugger.Break(); } using (var blockReader = resource.CreateReader()) { var header = new MetadataHeader(blockReader); using (var reader = blockReader.CreateVirtualReader(header.GetSectionOffset(1))) { //DataBlock 0: ? //DataBlock 1: vertex buffer infos //DataBlock 2: index buffer infos //DataBlock 3+: additional vertex data block for each buffer //DataBlock n+: additional index data block for each buffer var bufferCount = (header.DataBlocks.Count - 3) / 2; var block = header.DataBlocks[1]; reader.Seek(block.Offset, SeekOrigin.Begin); vertexBufferInfo = reader.ReadEnumerable <VertexBufferInfo>(bufferCount).ToArray(); block = header.DataBlocks[2]; reader.Seek(block.Offset, SeekOrigin.Begin); indexBufferInfo = reader.ReadEnumerable <IndexBufferInfo>(bufferCount).ToArray(); } using (var reader = blockReader.CreateVirtualReader(header.GetSectionOffset(2))) { var doc = new XmlDocument(); doc.LoadXml(Resources.Halo5VertexBuffer); var lookup = doc.DocumentElement.ChildNodes.Cast <XmlNode>() .ToDictionary(n => Convert.ToInt32(n.Attributes[XmlVertexField.Type].Value, 16)); var sectionIndex = -1; foreach (var section in sections) { sectionIndex++; var lodData = section.SectionLods[Math.Min(lod, section.SectionLods.Count - 1)]; if (lodData.VertexBufferIndex < 0 || lodData.IndexBufferIndex < 0 || !lookup.ContainsKey(section.VertexFormat)) { yield return(new GeometryMesh()); continue; } var node = lookup[section.VertexFormat]; var vInfo = vertexBufferInfo[lodData.VertexBufferIndex]; var iInfo = indexBufferInfo[lodData.IndexBufferIndex]; var mesh = new GeometryMesh { IndexFormat = section.IndexFormat, Vertices = new IVertex[vInfo.VertexCount], VertexWeights = VertexWeights.None, NodeIndex = section.NodeIndex == byte.MaxValue ? (byte?)null : section.NodeIndex, BoundsIndex = 0 }; try { mesh.Submeshes.AddRange( lodData.Submeshes.Select(s => new GeometrySubmesh { MaterialIndex = s.ShaderIndex, IndexStart = s.IndexStart, IndexLength = s.IndexLength }) ); var block = header.DataBlocks[3 + lodData.VertexBufferIndex]; reader.Seek(block.Offset, SeekOrigin.Begin); for (int i = 0; i < vInfo.VertexCount; i++) { var vert = new XmlVertex(reader, node); mesh.Vertices[i] = vert; } block = header.DataBlocks[3 + vertexBufferInfo.Length + lodData.IndexBufferIndex]; reader.Seek(block.Offset, SeekOrigin.Begin); if (vInfo.VertexCount > ushort.MaxValue) { mesh.Indicies = reader.ReadEnumerable <int>(iInfo.IndexCount).ToArray(); } else { mesh.Indicies = reader.ReadEnumerable <ushort>(iInfo.IndexCount).Select(i => (int)i).ToArray(); } } catch { System.Diagnostics.Debugger.Break(); } yield return(mesh); } } } }