// split VBE by stream public VertexElementDescriptor[][] SplitVBE(VertexElementDescriptor[] input) { VertexElementDescriptor[][] elements = new VertexElementDescriptor[2][]; // pass 1 byte[] sizes = new byte[2] { 0, 0 }; for (int i = 0; i < input.Length; ++i) { sizes[input[i].stream] += 1; } // pass 2 elements[0] = new VertexElementDescriptor[sizes[0]]; elements[1] = new VertexElementDescriptor[sizes[1]]; sizes = new byte[2] { 0, 0 }; for (int i = 0; i < input.Length; ++i) { byte stream = input[i].stream; elements[stream][sizes[stream]] = input[i]; sizes[stream] += 1; } return(elements); }
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 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 } }