예제 #1
0
        public void NEW_ShouldGetImmutableMeshHighDef()
        {
            var alaxi = new int[]
            {
                0x43, 0x8c, 0xdb, 0xd9, 0x89, 0x42, 0x41, 0x02, 0xd7, 0xd3
            };

            var data             = File.ReadAllBytes("res/obj_vif_unpack_alt.bin");
            var vpu              = VpuPacket.Read(new MemoryStream(data));
            var immutableMesh    = vpu.GetWeightedVertices(vpu.GetFromMatrixIndices(alaxi));
            var weightedVertices = immutableMesh
                                   .Select(x => x.Select(y => new
            {
                y.MatrixIndex,
                Vertex = vpu.Vertices[y.VertexIndex]
            }).ToArray())
                                   .ToArray();

            Assert.NotNull(immutableMesh);
            Assert.Equal(0x4a, immutableMesh.Length);
            Assert.Equal(0x4f, vpu.Indices.Length);

            Assert.Equal(0x89, weightedVertices[0][0].MatrixIndex);
            AssertEqual(weightedVertices[0][0].Vertex,
                        6.9705353f, 0.5387306f, -4.146785f, 1f);

            Assert.Equal(0x89, weightedVertices[1][0].MatrixIndex);
            AssertEqual(weightedVertices[1][0].Vertex,
                        6.1054993f, 1.1867695f, -3.7489133f, 1f);

            Assert.Equal(0x8c, weightedVertices[73][0].MatrixIndex);
            AssertEqual(weightedVertices[73][0].Vertex,
                        9.300911f, -0.66315675f, -5.8931007f, 0.5f);

            Assert.Equal(0xd3, weightedVertices[73][1].MatrixIndex);
            AssertEqual(weightedVertices[73][1].Vertex,
                        3.4593887f, -1.39147f, -1.8666306f, 0.5f);
        }
예제 #2
0
        public void NEW_ShouldGetImmutableMesh()
        {
            var alaxi = new int[]
            {
                0x35, 0x2, 0x18, 0x29, 0x0c, 0x31, 0x3f, 0x14, 0x22, 0x16
            };

            var data             = File.ReadAllBytes("res/obj_vif_unpack.bin");
            var vpu              = VpuPacket.Read(new MemoryStream(data));
            var immutableMesh    = vpu.GetWeightedVertices(vpu.GetFromMatrixIndices(alaxi));
            var weightedVertices = immutableMesh
                                   .Select(x => x.Select(y => new
            {
                y.MatrixIndex,
                Vertex = vpu.Vertices[y.VertexIndex]
            }).ToArray())
                                   .ToArray();

            Assert.NotNull(immutableMesh);
            Assert.Equal(0x4c, immutableMesh.Length);
            Assert.Equal(0x4f, vpu.Indices.Length);

            Assert.Equal(0x35, weightedVertices[0][0].MatrixIndex);
            AssertEqual(weightedVertices[0][0].Vertex,
                        11.55658f, -10.695402f, -1.8525791f, 0);

            Assert.Equal(0x35, weightedVertices[1][0].MatrixIndex);
            AssertEqual(weightedVertices[1][0].Vertex,
                        12.341873f, -6.8589644f, -6.79047f, 0);

            Assert.Equal(0x16, weightedVertices[75][0].MatrixIndex);
            AssertEqual(weightedVertices[75][0].Vertex,
                        -0.29302156f, -0.004016876f, 13.689127f, 0);

            AssertEqual(vpu.Indices[0], 0x10, 0x27, 0f, 0.26171875f);
            AssertEqual(vpu.Indices[1], 0x10, 0x28, 0.02734375f, 0.24609375f);
            AssertEqual(vpu.Indices[78], 0x30, 0x36, 0.5234375f, 0.49609375f);
        }
예제 #3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="matrixIndexList">The limited count of matrices are transferred to VU1 due to memory limitation.</param>
        /// <returns></returns>
        public static ImmutableMesh Run(byte[] vu1mem, int tops, int top2, int textureIndex, int[] matrixIndexList)
        {
            MemoryStream si = new MemoryStream(vu1mem, true);
            BinaryReader br = new BinaryReader(si);

            si.Position = 16 * (tops);

            var vpu = VpuPacket.Header(si);

            if (vpu.Type != 1 && vpu.Type != 2)
            {
                throw new ProtInvalidTypeException();
            }

            // Type1 example:

            // 0004   unpack V4-32 c 4 a 000 usn 0 flg 1 m 0
            //     00000001 00000000 00000000 00000000
            //     0000004f 00000004 0000009e 000000a1
            //     00000000 00000000 00000000 00000000 // this 16 bytes: seen in only for Type1
            //     0000004b 00000053 00000000 0000000b

            //  int type = 1;
            //  int unk1 = 0;
            //  int unk2 = 0;
            //  int unk3 = 0;

            //  int cntBox2 = 0x4f;
            //  int offBox2 = 0x4;
            //  int offVertexCountPerMatrix = 0x9e;
            //  int offMatrices = 0xa1;

            //  int cntVertsColor = 0x0; // only for Type1
            //  int offVertsColor = 0x0; // only for Type1
            //  int cntSpec = 0x0; // only for Type1
            //  int offSpec = 0x0; // only for Type1

            //  int cntVerts = 0x4b;
            //  int offVerts = 0x53;
            //  int unka = 0;
            //  int cntVertexCountPerMatrix = 0xb;

            // box1 → VertexCountPerMatrix

            int v04         = vpu.Unknown04;
            int v08         = vpu.Unknown08;
            int v0c         = vpu.Unknown1cLocation;
            int offMatrices = vpu.Unknown1cLocation; // off matrices

            // Shady logic here???? It MIGHT cause problems:
            // If vpu.Type != 1, those 0x10 bytes will be skipped. Therefore,
            // stuff that it's at 0x40, will be at 0x30 instead.
            int cntvertscolor  = (vpu.Type == 1) ? vpu.ColorCount : 0;    // cntvertscolor
            int offvertscolor  = (vpu.Type == 1) ? vpu.ColorLocation : 0; // offvertscolor
            int cntVertexMixer = (vpu.Type == 1) ? vpu.Unknown28 : 0;     // cnt spec
            int offVertexMixer = (vpu.Type == 1) ? vpu.Unknown2c : 0;     // off spec

            int v38 = vpu.Unknown38;                                      //

            si.Position = 16 * (tops + vpu.UnkBoxLocation);
            int[] vertexCountPerMatrix = new int[vpu.UnkBoxCount];
            for (int x = 0; x < vertexCountPerMatrix.Length; x++)
            {
                vertexCountPerMatrix[x] = br.ReadInt32();
            }

            ImmutableMesh mesh = new ImmutableMesh();

            mesh.textureIndex          = textureIndex;
            mesh.vertexAssignmentsList = new VertexAssignment[vpu.VertexCount][];

            VertexAssignment[] vertexAssignmentList = new VertexAssignment[vpu.VertexCount];

            int vertexIndex = 0;

            si.Position = 16 * (tops + vpu.VertexLocation);
            for (int indexToMatrixIndex = 0; indexToMatrixIndex < vertexCountPerMatrix.Length; indexToMatrixIndex++)
            {
                int cntVertices = vertexCountPerMatrix[indexToMatrixIndex];
                for (int t = 0; t < cntVertices; t++)
                {
                    float   xPos   = br.ReadSingle();
                    float   yPos   = br.ReadSingle();
                    float   zPos   = br.ReadSingle();
                    float   weight = br.ReadSingle();
                    Vector4 v4     = new Vector4(xPos, yPos, zPos, weight);
                    mesh.vertexAssignmentsList[vertexIndex] = new VertexAssignment[] {
                        vertexAssignmentList[vertexIndex] = new VertexAssignment {
                            matrixIndex = matrixIndexList[indexToMatrixIndex],
                            weight      = weight,
                            rawPos      = v4,
                        }
                    };

                    vertexIndex++;
                }
            }

            mesh.indexAssignmentList = new IndexAssignment[vpu.IndexCount];

            si.Position = 16 * (tops + vpu.IndexLocation);
            for (int x = 0; x < vpu.IndexCount; x++)
            {
                int texU = br.ReadUInt16() / 16;
                br.ReadUInt16(); // skip
                int texV = br.ReadUInt16() / 16;
                br.ReadUInt16(); // skip

                var localVertexIndex = br.ReadUInt16();
                br.ReadUInt16(); // skip
                var vertexFlag = br.ReadUInt16();
                br.ReadUInt16(); // skip

                mesh.indexAssignmentList[x] = new IndexAssignment(
                    new Vector2(texU / 256.0f, texV / 256.0f),
                    localVertexIndex,
                    vertexFlag
                    );
            }

            if (cntVertexMixer != 0)
            {
                si.Position = 16 * (tops + offVertexMixer);
                int cntSkip = br.ReadInt32();
                int cntVerticesMix2ToOne = br.ReadInt32();
                int cntVerticesMix3ToOne = br.ReadInt32();
                int cntVerticesMix4ToOne = br.ReadInt32();
                int cntVerticesMix5ToOne = 0;
                int cntVerticesMix6ToOne = 0;
                int cntVerticesMix7ToOne = 0;
                int cntVerticesMix8ToOne = 0;

                if (cntVertexMixer >= 5)
                {
                    cntVerticesMix5ToOne = br.ReadInt32();
                    cntVerticesMix6ToOne = br.ReadInt32();
                    cntVerticesMix7ToOne = br.ReadInt32();
                    cntVerticesMix8ToOne = br.ReadInt32(); // unused in asset models.
                }

                var vertexAssignmentCount = cntSkip
                                            + cntVerticesMix2ToOne
                                            + cntVerticesMix3ToOne
                                            + cntVerticesMix4ToOne
                                            + cntVerticesMix5ToOne
                                            + cntVerticesMix6ToOne
                                            + cntVerticesMix7ToOne
                                            + cntVerticesMix8ToOne
                ;

                VertexAssignment[][] newVertexAssignList = new VertexAssignment[vertexAssignmentCount][];
                int inputVertexIndex = 0;
                for (; inputVertexIndex < cntSkip; inputVertexIndex++)
                {
                    int index = br.ReadInt32();
                    newVertexAssignList[inputVertexIndex] = (new VertexAssignment[] {
                        vertexAssignmentList[index]
                    });
                }
                if (cntVertexMixer >= 2)
                {
                    //Debug.Fail("v28: " + v28);

                    si.Position = (si.Position + 15) & (~15); // 16 bytes alignment

                    for (int x = 0; x < cntVerticesMix2ToOne; x++, inputVertexIndex++)
                    {
                        int vertex1 = br.ReadInt32();
                        int vertex2 = br.ReadInt32();
                        newVertexAssignList[inputVertexIndex] = (new VertexAssignment[] {
                            vertexAssignmentList[vertex1],
                            vertexAssignmentList[vertex2]
                        });
                    }
                }
                if (cntVertexMixer >= 3)
                {
                    //Debug.Fail("v28: " + v28);

                    si.Position = (si.Position + 15) & (~15); // 16 bytes alignment

                    for (int x = 0; x < cntVerticesMix3ToOne; x++, inputVertexIndex++)
                    {
                        int vertex1 = br.ReadInt32();
                        int vertex2 = br.ReadInt32();
                        int vertex3 = br.ReadInt32();
                        newVertexAssignList[inputVertexIndex] = (new VertexAssignment[] {
                            vertexAssignmentList[vertex1],
                            vertexAssignmentList[vertex2],
                            vertexAssignmentList[vertex3]
                        });
                    }
                }
                if (cntVertexMixer >= 4)
                {
                    //Debug.Fail("v28: " + v28);

                    si.Position = (si.Position + 15) & (~15); // 16 bytes alignment

                    for (int x = 0; x < cntVerticesMix4ToOne; x++, inputVertexIndex++)
                    {
                        int vertex1 = br.ReadInt32();
                        int vertex2 = br.ReadInt32();
                        int vertex3 = br.ReadInt32();
                        int vertex4 = br.ReadInt32();
                        newVertexAssignList[inputVertexIndex] = (new VertexAssignment[] {
                            vertexAssignmentList[vertex1],
                            vertexAssignmentList[vertex2],
                            vertexAssignmentList[vertex3],
                            vertexAssignmentList[vertex4]
                        });
                    }
                }
                if (cntVertexMixer >= 5)
                {
                    si.Position = (si.Position + 15) & (~15);  // 16 bytes alignment

                    for (int x = 0; x < cntVerticesMix5ToOne; x++, inputVertexIndex++)
                    {
                        int vertex1 = br.ReadInt32();
                        int vertex2 = br.ReadInt32();
                        int vertex3 = br.ReadInt32();
                        int vertex4 = br.ReadInt32();
                        int vertex5 = br.ReadInt32();
                        newVertexAssignList[inputVertexIndex] = (new VertexAssignment[] {
                            vertexAssignmentList[vertex1],
                            vertexAssignmentList[vertex2],
                            vertexAssignmentList[vertex3],
                            vertexAssignmentList[vertex4],
                            vertexAssignmentList[vertex5]
                        });
                    }
                }
                if (cntVertexMixer >= 6)
                {
                    si.Position = (si.Position + 15) & (~15);  // 16 bytes alignment

                    for (int x = 0; x < cntVerticesMix6ToOne; x++, inputVertexIndex++)
                    {
                        int vertex1 = br.ReadInt32();
                        int vertex2 = br.ReadInt32();
                        int vertex3 = br.ReadInt32();
                        int vertex4 = br.ReadInt32();
                        int vertex5 = br.ReadInt32();
                        int vertex6 = br.ReadInt32();
                        newVertexAssignList[inputVertexIndex] = (new VertexAssignment[] {
                            vertexAssignmentList[vertex1],
                            vertexAssignmentList[vertex2],
                            vertexAssignmentList[vertex3],
                            vertexAssignmentList[vertex4],
                            vertexAssignmentList[vertex5],
                            vertexAssignmentList[vertex6]
                        });
                    }
                }
                if (cntVertexMixer >= 7)
                {
                    si.Position = (si.Position + 15) & (~15);  // 16 bytes alignment

                    for (int x = 0; x < cntVerticesMix7ToOne; x++, inputVertexIndex++)
                    {
                        int vertex1 = br.ReadInt32();
                        int vertex2 = br.ReadInt32();
                        int vertex3 = br.ReadInt32();
                        int vertex4 = br.ReadInt32();
                        int vertex5 = br.ReadInt32();
                        int vertex6 = br.ReadInt32();
                        int vertex7 = br.ReadInt32();
                        newVertexAssignList[inputVertexIndex] = (new VertexAssignment[] {
                            vertexAssignmentList[vertex1],
                            vertexAssignmentList[vertex2],
                            vertexAssignmentList[vertex3],
                            vertexAssignmentList[vertex4],
                            vertexAssignmentList[vertex5],
                            vertexAssignmentList[vertex6],
                            vertexAssignmentList[vertex7]
                        });
                    }
                }
                if (cntVertexMixer >= 8)
                {
                    si.Position = (si.Position + 15) & (~15);  // 16 bytes alignment

                    for (int x = 0; x < cntVerticesMix8ToOne; x++, inputVertexIndex++)
                    {
                        int vertex1 = br.ReadInt32();
                        int vertex2 = br.ReadInt32();
                        int vertex3 = br.ReadInt32();
                        int vertex4 = br.ReadInt32();
                        int vertex5 = br.ReadInt32();
                        int vertex6 = br.ReadInt32();
                        int vertex7 = br.ReadInt32();
                        int vertex8 = br.ReadInt32();
                        newVertexAssignList[inputVertexIndex] = (new VertexAssignment[] {
                            vertexAssignmentList[vertex1],
                            vertexAssignmentList[vertex2],
                            vertexAssignmentList[vertex3],
                            vertexAssignmentList[vertex4],
                            vertexAssignmentList[vertex5],
                            vertexAssignmentList[vertex6],
                            vertexAssignmentList[vertex7],
                            vertexAssignmentList[vertex8]
                        });
                    }
                }
                // if cntVertexMixer >= 1, replace current vertexAssignmentList with regrouped list.
                mesh.vertexAssignmentsList = newVertexAssignList;
            }

            return(mesh);
        }