private static MESH_DATA SerializeMeshGeometry(MESH_FILE file, ShaderDataHelper shaderData, MeshGeometry meshGeometry) { var meshData = MESH_DATA.Create(meshGeometry.VertexCount, meshGeometry.IndexCount, file.IsTextured, file.IsFlexible); var vertIndexer = new ListIndexer <Vertex>(meshGeometry.Vertices); bool isTextured = meshGeometry.IsTextured; for (int i = 0; i < meshGeometry.Vertices.Count; i++) { var vert = meshGeometry.Vertices[i]; meshData.Positions[i] = vert.Position; meshData.Normals[i] = vert.Normal; if (file.IsTextured) { meshData.UVs[i] = isTextured ? vert.TexCoord : new Vector2(0f); } if (file.IsFlexible && vert.BoneWeights.Any()) { var boneWeights = vert.BoneWeights.Select(x => new MESH_BONE_WEIGHT { BoneID = x.BoneID, Weight = x.Weight }); meshData.Bones[i] = new MESH_BONE_MAPPING(boneWeights); } } for (int i = 0; i < meshGeometry.Indices.Count; i++) { var idx = meshGeometry.Indices[i]; meshData.Indices[i].VertexIndex = vertIndexer.IndexOf(idx.Vertex); meshData.Indices[i].AverageNormalIndex = shaderData.AvgNormals.IndexOf(idx.AverageNormal); int reIdx = shaderData.RoundEdgeData.IndexOf(idx.RoundEdgeData); int reOffset = reIdx * 12 + ((int)Math.Floor(reIdx / 21d) * 4); meshData.Indices[i].REShaderOffset = reOffset; } return(meshData); }
private static MESH_DATA ReadAlternateMesh(BinaryReaderEx br, MESH_FILE mesh, long boneMappingPosition, long meshDataSize) { long startPosition = br.Position; int vertexCount = br.ReadInt32(); int indexCount = br.ReadInt32(); var geom = MESH_DATA.Create(vertexCount, indexCount, mesh.IsTextured, mesh.IsFlexible); for (int i = 0; i < vertexCount; i++) { geom.Positions[i] = new Vector3(br.ReadSingles(3)); } for (int i = 0; i < vertexCount; i++) { geom.Normals[i] = new Vector3(br.ReadSingles(3)); } if (mesh.IsTextured) { for (int i = 0; i < vertexCount; i++) { geom.UVs[i] = new Vector2(br.ReadSingles(2)); } } for (int i = 0; i < indexCount; i++) { geom.Indices[i] = new MESH_INDEX() { VertexIndex = br.ReadInt32() } } ; for (int i = 0; i < indexCount; i++) { geom.Indices[i].AverageNormalIndex = br.ReadInt32(); } for (int i = 0; i < indexCount; i++) { geom.Indices[i].REShaderOffset = br.ReadInt32(); } if (mesh.IsFlexible) { Trace.WriteLine("WARNING Flexible alternate mesh encountered!"); if (br.Position < startPosition + meshDataSize) { var dataOffsets = new List <int>(); for (int i = 0; i < vertexCount; i++) { dataOffsets.Add(br.ReadInt32()); } long dataEndPosition = br.Position; for (int i = 0; i < vertexCount; i++) { geom.Bones[i] = ReadBoneMapping(br, boneMappingPosition, dataOffsets[i]); } br.Position = dataEndPosition; } else { Trace.WriteLine("Flexible alternate mesh does not seem to be supported!"); geom.Bones = new MESH_BONE_MAPPING[0]; } } return(geom); }
public static MESH_FILE ReadMeshFile(Stream stream) { stream.Position = 0; var meshFile = new MESH_FILE(); using (var br = new BinaryReaderEx(stream, Encoding.UTF8, true)) { var fileHeader = br.ReadStruct <MESH_HEADER>(); if (fileHeader.Header != "10GB") { throw new IOException("The file is not a LDD mesh file (*.g)"); } meshFile.Header = fileHeader; meshFile.Geometry = MESH_DATA.Create(fileHeader); // Vertices & triangles { for (int i = 0; i < fileHeader.VertexCount; i++) { meshFile.Geometry.Positions[i] = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); } for (int i = 0; i < fileHeader.VertexCount; i++) { meshFile.Geometry.Normals[i] = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); } if (fileHeader.MeshType == (int)MeshType.StandardTextured || fileHeader.MeshType == (int)MeshType.FlexibleTextured) { for (int i = 0; i < fileHeader.VertexCount; i++) { meshFile.Geometry.UVs[i] = new Vector2(br.ReadSingle(), br.ReadSingle()); } } for (int i = 0; i < fileHeader.IndexCount; i++) { meshFile.Geometry.Indices[i] = new MESH_INDEX { VertexIndex = br.ReadInt32() } } ; } // Edge shader data (brick outlines) { int shaderDataLength = br.ReadInt32(); int valueCounter = 0; var shaderData = new List <ROUNDEDGE_SHADER_DATA>(); while (valueCounter < shaderDataLength) { bool endOfRow = 256 - ((valueCounter + 12) % 256) < 12; int valueCount = endOfRow ? 16 : 12; int remainingData = shaderDataLength - valueCounter; if (valueCount > remainingData) { if (endOfRow && 12 <= remainingData) { valueCount = 12; } else { Trace.WriteLine("Shader data length error!!!"); stream.Skip(remainingData * 4); break; } } shaderData.Add(new ROUNDEDGE_SHADER_DATA(br.ReadSingles(valueCount))); valueCounter += valueCount; } meshFile.RoundEdgeShaderData = shaderData.ToArray(); for (int i = 0; i < fileHeader.IndexCount; i++) { meshFile.Geometry.Indices[i].REShaderOffset = br.ReadInt32(); } } // Average Normals { int averageNormalsCount = br.ReadInt32(); //we skip the first item because it looks like an header and the maximum referenced value seems always one less the specified length var dataHeader = new Vector3(br.ReadSingles(3)); if (dataHeader.X != 83 || dataHeader.Y != 0 || dataHeader.Z != 0) { Trace.WriteLine($"Unexpected average normal header: {dataHeader}"); } meshFile.AverageNormals = new Vector3[averageNormalsCount - 1]; for (int i = 0; i < averageNormalsCount - 1; i++) { meshFile.AverageNormals[i] = new Vector3(br.ReadSingles(3)); } for (int i = 0; i < fileHeader.IndexCount; i++) { meshFile.Geometry.Indices[i].AverageNormalIndex = br.ReadInt32(); } } long boneMappingPosition = 0; // Flex data if (fileHeader.MeshType == (int)MeshType.Flexible || fileHeader.MeshType == (int)MeshType.FlexibleTextured) { int dataSize = br.ReadInt32(); boneMappingPosition = stream.Position; stream.Seek(dataSize, SeekOrigin.Current); //skip over the data var dataOffsets = new List <int>(); for (int i = 0; i < fileHeader.VertexCount; i++) { dataOffsets.Add(br.ReadInt32()); } long dataEndPosition = stream.Position; for (int i = 0; i < fileHeader.VertexCount; i++) { meshFile.Geometry.Bones[i] = ReadBoneMapping(br, boneMappingPosition, dataOffsets[i]); } stream.Position = dataEndPosition; } int cullingInfoCount = br.ReadInt32(); int cullingInfoSize = br.ReadInt32(); meshFile.Cullings = new MESH_CULLING[cullingInfoCount]; for (int i = 0; i < cullingInfoCount; i++) { meshFile.Cullings[i] = ReadCullingInfo(br, meshFile, boneMappingPosition); } } return(meshFile); }