// buffer -> stream -> vertex -> element public void ParseStride(BinaryReader reader) { for (int i = 0; i < VertexBuffers.Length; ++i) { VertexBufferDescriptor vbo = VertexBuffers[i]; Stride[i] = new object[2][][]; long[] offset = new long[2] { vbo.dataStream1Pointer, vbo.dataStream2Pointer }; byte[] sizes = new byte[2] { vbo.strideStream1, vbo.strideStream2 }; VertexElementDescriptor[][] elements = SplitVBE(VertexElements[i]); for (int j = 0; j < offset.Length; ++j) { Stride[i][j] = new object[vbo.vertexCount][]; reader.BaseStream.Position = offset[j]; for (int k = 0; k < vbo.vertexCount; ++k) { Stride[i][j][k] = new object[elements[j].Length]; long next = reader.BaseStream.Position + sizes[j]; long current = reader.BaseStream.Position; for (int l = 0; l < elements[j].Length; ++l) { reader.BaseStream.Position = current + elements[j][l].offset; Stride[i][j][k][l] = ReadElement(elements[j][l].format, reader); } reader.BaseStream.Position = next; } } } }
public VertexElementDescriptor[] ParseVBE(BinaryReader reader, VertexBufferDescriptor descriptor) { reader.BaseStream.Position = descriptor.vertexElementDescriptorPointer; VertexElementDescriptor[] elements = new VertexElementDescriptor[descriptor.vertexElementDescriptorCount]; for (int i = 0; i < descriptor.vertexElementDescriptorCount; ++i) { elements[i] = reader.Read <VertexElementDescriptor>(); } return(elements); }
public void ParseVBO(BinaryReader reader) { reader.BaseStream.Position = Mesh.vertexBufferDesciptorPointer; for (int i = 0; i < Mesh.vertexBufferDescriptorCount; ++i) { VertexBufferDescriptor descriptor = reader.Read <VertexBufferDescriptor>(); VertexBuffers[i] = descriptor; } for (int i = 0; i < Mesh.vertexBufferDescriptorCount; ++i) { VertexElements[i] = ParseVBE(reader, VertexBuffers[i]); } }
public void GenerateMeshes(BinaryReader reader) { // TODO for (int i = 0; i < Submeshes.Length; ++i) { SubmeshDescriptor submesh = Submeshes[i]; VertexBufferDescriptor vbo = VertexBuffers[submesh.vertexBuffer]; IndexBufferDescriptor ibo = IndexBuffers[submesh.indexBuffer]; byte uvCount = GetMaxIndex(VertexElements[submesh.vertexBuffer], SemanticType.UV); #region IBO ModelIndice[] indices = new ModelIndice[submesh.indicesToDraw / 3]; reader.BaseStream.Position = ibo.dataStreamPointer + submesh.indexStart * 2; List <ushort> indexTracker = new List <ushort>(submesh.verticesToDraw); for (int j = 0; j < submesh.indicesToDraw / 3; ++j) { ModelIndice index = reader.Read <ModelIndice>(); int v1 = indexTracker.IndexOf(index.v1); if (v1 == -1) { v1 = indexTracker.Count; indexTracker.Add(index.v1); } int v2 = indexTracker.IndexOf(index.v2); if (v2 == -1) { v2 = indexTracker.Count; indexTracker.Add(index.v2); } int v3 = indexTracker.IndexOf(index.v3); if (v3 == -1) { v3 = indexTracker.Count; indexTracker.Add(index.v3); } indices[j] = new ModelIndice { v1 = (ushort)v1, v2 = (ushort)v2, v3 = (ushort)v3 }; } Indices[i] = indices; #endregion #region UV Pre. ModelUV[][] uv = new ModelUV[uvCount][]; for (int j = 0; j < uvCount; ++j) { uv[j] = new ModelUV[submesh.verticesToDraw]; } #endregion #region VBO ModelVertex[] vertex = new ModelVertex[submesh.verticesToDraw]; ModelBoneData[] bone = new ModelBoneData[submesh.verticesToDraw]; ModelVertex[] normal = new ModelVertex[submesh.verticesToDraw]; VertexElementDescriptor[][] elements = SplitVBE(VertexElements[submesh.vertexBuffer]); for (int j = 0; j < Stride[submesh.vertexBuffer].Length; ++j) { for (int k = 0; k < submesh.verticesToDraw; ++k) { long offset = submesh.vertexStart + indexTracker[k]; for (int l = 0; l < elements[j].Length; ++l) { VertexElementDescriptor element = elements[j][l]; if (element.format == SemanticFormat.NONE) { break; } object value = Stride[submesh.vertexBuffer][j][offset][l]; switch (element.type) { case SemanticType.POSITION: if (element.index == 0) { float[] t = (float[])value; vertex[k] = new ModelVertex { x = t[0], y = t[1], z = t[2] }; } else { if (unhandledSemanticTypes.Add(element.type) && System.Diagnostics.Debugger.IsAttached) { System.Diagnostics.Debugger.Log(2, "CHUNK_LDOMMNRM", $"Unhandled vertex layer {element.index:X} for type {Util.GetEnumName(typeof(SemanticType), element.type)}!\n"); } } break; case SemanticType.NORMAL: if (element.index == 0) { float[] t = (float[])value; normal[k] = new ModelVertex { x = t[0], y = t[1], z = t[2] }; } else { if (unhandledSemanticTypes.Add(element.type) && System.Diagnostics.Debugger.IsAttached) { System.Diagnostics.Debugger.Log(2, "CHUNK_LDOMMNRM", $"Unhandled vertex layer {element.index:X} for type {Util.GetEnumName(typeof(SemanticType), element.type)}!\n"); } } break; case SemanticType.UV: { ushort[] t = (ushort[])value; uv[element.index][k] = new ModelUV { u = Half.ToHalf(t[0]), v = Half.ToHalf(t[1]) }; } break; case SemanticType.BONE_INDEX: if (element.index == 0) { byte[] t = (byte[])value; bone[k].boneIndex = new ushort[t.Length]; for (int m = 0; m < t.Length; ++m) { bone[k].boneIndex[m] = (ushort)(t[m] + submesh.boneIdOffset); } } else { if (unhandledSemanticTypes.Add(element.type) && System.Diagnostics.Debugger.IsAttached) { System.Diagnostics.Debugger.Log(2, "CHUNK_LDOMMNRM", $"Unhandled vertex layer {element.index:X} for type {Util.GetEnumName(typeof(SemanticType), element.type)}!\n"); } } break; case SemanticType.BONE_WEIGHT: if (element.index == 0) { bone[k].boneWeight = (float[])value; } else { if (unhandledSemanticTypes.Add(element.type) && System.Diagnostics.Debugger.IsAttached) { System.Diagnostics.Debugger.Log(2, "CHUNK_LDOMMNRM", $"Unhandled vertex layer {element.index:X} for type {Util.GetEnumName(typeof(SemanticType), element.type)}!\n"); } } break; default: if (unhandledSemanticTypes.Add(element.type) && System.Diagnostics.Debugger.IsAttached) { System.Diagnostics.Debugger.Log(2, "CHUNK_LDOMMNRM", $"Unhandled vertex type {Util.GetEnumName(typeof(SemanticType), element.type)}!\n"); } break; } } } } indexTracker.Clear(); TextureCoordinates[i] = uv; Vertices[i] = vertex; Bones[i] = bone; Normals[i] = normal; #endregion } }