public ImmutableMesh(Mdlx.DmaChain dmaChain) { DmaChain = dmaChain; VpuPackets = dmaChain.DmaVifs .Select(dmaVif => { var unpacker = new VifUnpacker(dmaVif.VifPacket); unpacker.Run(); using (var stream = new MemoryStream(unpacker.Memory)) return(VpuPacket.Read(stream)); }) .ToList(); }
private ExportedMesh PreProcessVerticesAndBuildModel() { var exportedMesh = new ExportedMesh(); exportedMesh.vertexAssignments = new List <VertexIndexWeighted[][]>(); exportedMesh.vertices = new List <Vector4[]>(); int vertexBaseIndex = 0; int uvBaseIndex = 0; VertexRef[] ringBuffer = new VertexRef[4]; int ringIndex = 0; int[] triangleOrder = new int[] { 1, 3, 2 }; foreach (ImmutableMesh meshRoot in immultableMeshList) { for (int i = 0; i < meshRoot.VpuPackets.Count; i++) { VpuPacket mesh = meshRoot.VpuPackets[i]; var part = new ExportedMesh.Part { TextureIndex = meshRoot.TextureIndex, IsOpaque = meshRoot.IsOpaque, }; for (int x = 0; x < mesh.Indices.Length; x++) { var indexAssign = mesh.Indices[x]; VertexRef vertexRef = new VertexRef( vertexBaseIndex + indexAssign.Index, uvBaseIndex + x ); ringBuffer[ringIndex] = vertexRef; ringIndex = (ringIndex + 1) & 3; var flag = indexAssign.Function; if (flag == VpuPacket.VertexFunction.DrawTriangle || flag == VpuPacket.VertexFunction.DrawTriangleDoubleSided) { var triRef = new TriangleRef( ringBuffer[(ringIndex - triangleOrder[0]) & 3], ringBuffer[(ringIndex - triangleOrder[1]) & 3], ringBuffer[(ringIndex - triangleOrder[2]) & 3] ); part.triangleRefList.Add(triRef); } if (flag == VpuPacket.VertexFunction.DrawTriangleInverse || flag == VpuPacket.VertexFunction.DrawTriangleDoubleSided) { var triRef = new TriangleRef( ringBuffer[(ringIndex - triangleOrder[0]) & 3], ringBuffer[(ringIndex - triangleOrder[2]) & 3], ringBuffer[(ringIndex - triangleOrder[1]) & 3] ); part.triangleRefList.Add(triRef); } } var vertices = mesh.Vertices .Select(vertex => new Vector4(vertex.X, vertex.Y, vertex.Z, vertex.W)) .ToArray(); exportedMesh.vertices.Add(vertices); var matrixIndexList = meshRoot.DmaChain.DmaVifs[i].Alaxi; var vertexAssignmentsList = mesh.GetWeightedVertices(mesh.GetFromMatrixIndices(matrixIndexList)); exportedMesh.vertexAssignments.Add(vertexAssignmentsList); exportedMesh.uvList.AddRange( mesh.Indices.Select(x => new Vector2(x.U / 16 / 256.0f, x.V / 16 / 256.0f)) ); exportedMesh.partList.Add(part); vertexBaseIndex += vertexAssignmentsList.Length; uvBaseIndex += mesh.Indices.Length; } } return(exportedMesh); }
private static MeshDescriptor Parse(Mdlx.VifPacketDescriptor vifPacketDescriptor) { var vertices = new List <CustomVertex.PositionColoredTextured>(); var indices = new List <int>(); var unpacker = new VifUnpacker(vifPacketDescriptor.VifPacket); var indexBuffer = new int[4]; var recentIndex = 0; while (unpacker.Run() != VifUnpacker.State.End) { var vpu = new MemoryStream(unpacker.Memory, false) .Using(stream => VpuPacket.Read(stream)); var baseVertexIndex = vertices.Count; for (var i = 0; i < vpu.Indices.Length; i++) { var vertexIndex = vpu.Indices[i]; var position = new Vector3( vpu.Vertices[vertexIndex.Index].X, vpu.Vertices[vertexIndex.Index].Y, vpu.Vertices[vertexIndex.Index].Z); int colorR, colorG, colorB, colorA; if (vpu.Colors.Length != 0) { colorR = vpu.Colors[i].R; colorG = vpu.Colors[i].G; colorB = vpu.Colors[i].B; colorA = vpu.Colors[i].A; } else { colorR = 0x80; colorG = 0x80; colorB = 0x80; colorA = 0x80; } var color = Math.Min(byte.MaxValue, colorB * 2) | (Math.Min(byte.MaxValue, colorG * 2) << 8) | (Math.Min(byte.MaxValue, colorR * 2) << 16) | (Math.Min(byte.MaxValue, colorA * 2) << 24); vertices.Add(new CustomVertex.PositionColoredTextured( position, color, (short)(ushort)vertexIndex.U / 4096.0f, (short)(ushort)vertexIndex.V / 4096.0f)); indexBuffer[(recentIndex++) & 3] = baseVertexIndex + i; switch (vertexIndex.Function) { case VpuPacket.VertexFunction.DrawTriangleDoubleSided: indices.Add(indexBuffer[(recentIndex - 1) & 3]); indices.Add(indexBuffer[(recentIndex - 3) & 3]); indices.Add(indexBuffer[(recentIndex - 2) & 3]); indices.Add(indexBuffer[(recentIndex - 1) & 3]); indices.Add(indexBuffer[(recentIndex - 2) & 3]); indices.Add(indexBuffer[(recentIndex - 3) & 3]); break; case VpuPacket.VertexFunction.Stock: break; case VpuPacket.VertexFunction.DrawTriangle: indices.Add(indexBuffer[(recentIndex - 1) & 3]); indices.Add(indexBuffer[(recentIndex - 3) & 3]); indices.Add(indexBuffer[(recentIndex - 2) & 3]); break; case VpuPacket.VertexFunction.DrawTriangleInverse: indices.Add(indexBuffer[(recentIndex - 1) & 3]); indices.Add(indexBuffer[(recentIndex - 2) & 3]); indices.Add(indexBuffer[(recentIndex - 3) & 3]); break; } } } return(new MeshDescriptor { Vertices = vertices.ToArray(), Indices = indices.ToArray(), TextureIndex = vifPacketDescriptor.TextureId, IsOpaque = vifPacketDescriptor.IsTransparentFlag == 0, }); }
private void Parse(List <Mdlx.VifPacketDescriptor> packetDescriptors) { var textureIndex = 0; var indexBuffer = new int[4]; var recenti = 0; var model = new Model(); for (var pdIndex = 0; pdIndex < packetDescriptors.Count; pdIndex++) { var vifPacketDescriptor = packetDescriptors[pdIndex]; var unpacker = new VifUnpacker(vifPacketDescriptor.VifPacket); VifUnpacker.State state; do { var indices = new List <int>(); state = unpacker.Run(); var vpu = new MemoryStream(unpacker.Memory, false) .Using(stream => VpuPacket.Read(stream)); var baseVertexIndex = Vertices.Count; for (var i = 0; i < vpu.Indices.Length; i++) { var vertexIndex = vpu.Indices[i]; Vector3 position; position.X = -vpu.Vertices[vertexIndex.Index].X; position.Y = vpu.Vertices[vertexIndex.Index].Y; position.Z = vpu.Vertices[vertexIndex.Index].Z; int colorR, colorG, colorB, colorA; if (vpu.Colors.Length != 0) { colorR = vpu.Colors[i].R; colorG = vpu.Colors[i].G; colorB = vpu.Colors[i].B; colorA = vpu.Colors[i].A; } else { colorR = 0x80; colorG = 0x80; colorB = 0x80; colorA = 0x80; } var color = Math.Min(byte.MaxValue, colorB * 2) | (Math.Min(byte.MaxValue, colorG * 2) << 8) | (Math.Min(byte.MaxValue, colorR * 2) << 16) | (Math.Min(byte.MaxValue, colorA * 2) << 24); Vertices.Add(new CustomVertex.PositionColoredTextured( position, color, vertexIndex.U / 4096.0f, vertexIndex.V / 4096.0f)); indexBuffer[(recenti++) & 3] = baseVertexIndex + i; switch (vertexIndex.Function) { case VpuPacket.VertexFunction.None: break; case VpuPacket.VertexFunction.Stock: break; case VpuPacket.VertexFunction.DrawTriangle: indices.Add(indexBuffer[(recenti - 1) & 3]); indices.Add(indexBuffer[(recenti - 2) & 3]); indices.Add(indexBuffer[(recenti - 3) & 3]); break; case VpuPacket.VertexFunction.DrawTriangleInverse: indices.Add(indexBuffer[(recenti - 1) & 3]); indices.Add(indexBuffer[(recenti - 3) & 3]); indices.Add(indexBuffer[(recenti - 2) & 3]); break; } } MeshDescriptors.Add(new MeshDescriptor { Indices = indices.ToArray(), TextureIndex = textureIndex + vifPacketDescriptor.TextureId, SegmentIndex = pdIndex }); } while (state == VifUnpacker.State.Microprogram); } }