Exemplo n.º 1
0
        public static void ProcessMOD(string PathIn, string PathOut, CpsxTex[] psxTex, float scaleFactor, bool bDebug = false, bool bSplit = true)
        {
            string pathIn = PathIn.Substring(0, PathIn.LastIndexOf("\\"));
            string fileIn = PathIn.Replace(pathIn, "");

            if (!Directory.Exists(PathOut))
            {
                Directory.CreateDirectory(PathOut);
            }

            BinaryReader br = new BinaryReader(new FileStream(pathIn + fileIn, FileMode.Open));

            int iMagic = br.ReadInt32();

            if (bDebug)
            {
                Console.WriteLine("Magic number : " + iMagic);
            }

            if (iMagic == 21102604)
            {
                // Process map
                int iBlockCount = br.ReadInt32();
                int gX          = br.ReadInt32();
                int gZ          = br.ReadInt32();
                int h4          = br.ReadInt32();

                if (bDebug)
                {
                    Console.WriteLine("Block Count : " + iBlockCount + " :: Width : " + gX + " :: Length : " + gZ + " :: H4 : " + h4);
                }

                DAT dat = new DAT();

                if (bDebug)
                {
                    Console.WriteLine("Reading 256 4 byte chunks");
                }
                // Possibly some sort of vert colours?
                for (int i = 0; i < 256; i++)
                {
                    //Console.WriteLine(i + ")\t" + br.ReadInt32());
                    br.ReadInt32();
                }

                int iFirstBlockSize = br.ReadInt32();
                if (bDebug)
                {
                    Console.WriteLine("Reading header block");
                }
                int[] blockOffsets = new int[iBlockCount + 1];

                for (int i = 0; i < blockOffsets.Length; i++)
                {
                    blockOffsets[i] = br.ReadInt32();
                    if (bDebug)
                    {
                        Console.WriteLine("Block start at : " + blockOffsets[i]);
                    }
                }

                Console.WriteLine("Reading " + h4 + " records (" + (h4 * 8) + " bytes) of the header block at " + br.BaseStream.Position);

                // This is similar to the header block in the car files, I have no idea what it is for.
                for (int i = 0; i < h4; i++)
                {
                    //Console.WriteLine(i + "\t" + br.ReadInt16() + "\t" + br.ReadInt16() + "\t" + br.ReadInt16() + "\t" + br.ReadByte() + "\t" + br.ReadByte());
                    br.ReadBytes(8);
                }

                Console.WriteLine("Reading " + iFirstBlockSize + " records (" + (iFirstBlockSize * 8) + " bytes) of the first block at " + br.BaseStream.Position);

                // The first two values are always(?) the same and never repeat.
                // Material ID lookup
                int[] matIDs = new int[iFirstBlockSize];
                for (int i = 0; i < iFirstBlockSize; i++)
                {
                    matIDs[i] = br.ReadInt16();
                    //Console.WriteLine(i + ")\t" + br.ReadInt16() + "\t" + br.ReadUInt16() + "\t" + br.ReadUInt16());
                    br.ReadBytes(6);
                }

                Console.WriteLine("Began seeking at " + br.BaseStream.Position + " of " + br.BaseStream.Length);

                for (int i = 1; i < blockOffsets.Length; i++)
                {
                    int z = (i - 1) / gX;
                    int x = (i - 1) - (z * gX);

                    Console.WriteLine(x + ", " + z);

                    if (blockOffsets[i] > 0)
                    {
                        br.BaseStream.Seek(blockOffsets[i], SeekOrigin.Begin);

                        int     uAs, uAe, uC, uD, uE, uF;
                        short[] sX = new short[8];

                        if (bDebug)
                        {
                            Console.WriteLine();
                            Console.WriteLine("Processing footer for block " + (i - 1));
                        }

                        uAs = br.ReadInt32();
                        uAe = br.ReadInt32();
                        uC  = br.ReadInt32();
                        uD  = br.ReadInt32();
                        if (bDebug)
                        {
                            Console.WriteLine("Block A Start:\t" + uAs);
                            Console.WriteLine("Block A End  :\t" + uAe);
                            Console.WriteLine("Offset C     :\t" + uC);
                            Console.WriteLine("Offset D     :\t" + uD);
                        }
                        for (int j = 0; j < 8; j++)
                        {
                            sX[j] = br.ReadInt16();
                            if (bDebug)
                            {
                                Console.WriteLine(j + ")\t" + sX[j]);
                            }
                        }

                        uE = br.ReadInt32();
                        uF = br.ReadInt32();
                        if (bDebug)
                        {
                            Console.WriteLine("Offset E     :\t" + uE);
                            Console.WriteLine("Offset F     :\t" + uF);
                        }

                        bool bFlipU = false;

                        if (1 == 1)
                        {
                            C2Mesh m = new C2Mesh();

                            if (psxTex != null)
                            {
                                for (int j = 0; j < psxTex.Length; j++)
                                {
                                    m.AddListMaterial(psxTex[j].Name);
                                }
                            }

                            br.BaseStream.Seek(uAs, SeekOrigin.Begin);
                            Vector3[] verts = new Vector3[sX[0]];

                            if (bDebug)
                            {
                                Console.WriteLine("Reading " + sX[0] + " records (" + (sX[0] * 8) + " bytes) of block " + (i - 1) + " at " + br.BaseStream.Position);
                            }

                            for (int j = 0; j < sX[0]; j++)
                            {
                                //Single oX = x * -8192;
                                //Single oZ = z * 8192;

                                //verts[j] = new Vector3(-br.ReadInt16() + oX, -br.ReadInt16(), br.ReadInt16() + oZ);

                                //Single oX = x * 8192;
                                //Single oZ = z * 8192;

                                //verts[j] = new Vector3(br.ReadInt16() + oX, -br.ReadInt16(), br.ReadInt16() + oZ);

                                float oX = x * 8192;
                                float oZ = z * -8192;

                                verts[j] = new Vector3(br.ReadInt16() + oX, -br.ReadInt16(), -br.ReadInt16() + oZ);

                                // Note: Spare bytes are either 0 0 or 255 255
                                br.ReadBytes(2);
                            }

                            if (bDebug)
                            {
                                Console.WriteLine("Reading " + sX[2] + " records (" + (sX[2] * 24) + " bytes) of block " + (i - 1) + " at " + br.BaseStream.Position);
                            }

                            for (int j = 0; j < sX[2]; j++)
                            {
                                int v1 = br.ReadInt16();
                                int v2 = br.ReadInt16();
                                int v3 = br.ReadInt16();

                                int v4 = br.ReadInt16(); // This is very occasionally not 0!

                                float v1u = br.ReadByte();
                                float v1v = br.ReadByte();
                                float v2u = br.ReadByte();
                                float v2v = br.ReadByte();
                                float v3u = br.ReadByte();
                                float v3v = br.ReadByte();
                                float v4u = br.ReadByte(); // This is very occasionally not 0!
                                float v4v = br.ReadByte(); // This is very occasionally not 0!

                                br.ReadBytes(5);

                                int matID = matIDs[br.ReadByte()];

                                br.ReadBytes(2);

                                if (psxTex != null)
                                {
                                    if (!bFlipU)
                                    {
                                        v1u /= psxTex[matID].Width;
                                        v2u /= psxTex[matID].Width;
                                        v3u /= psxTex[matID].Width;
                                    }
                                    else
                                    {
                                        v1u = 1.0f - (v1u / psxTex[matID].Width);
                                        v2u = 1.0f - (v2u / psxTex[matID].Width);
                                        v3u = 1.0f - (v3u / psxTex[matID].Width);
                                    }
                                    v1v = 1.0f - (v1v / psxTex[matID].Height);
                                    v2v = 1.0f - (v2v / psxTex[matID].Height);
                                    v3v = 1.0f - (v3v / psxTex[matID].Height);
                                }

                                //Console.WriteLine("Vert #" + v1 + " has UV #" + m.AddUV(new Vector2(v1u, v1v)));
                                //Console.WriteLine("Vert #" + v2 + " has UV #" + m.AddUV(new Vector2(v2u, v2v)));
                                //Console.WriteLine("Vert #" + v3 + " has UV #" + m.AddUV(new Vector2(v3u, v3v)));

                                //m.AddFace(verts[v1], verts[v2], verts[v3], new Vector2(v1u, v1v), new Vector2(v2u, v2v), new Vector2(v3u, v3v), matID);
                                m.AddFace(verts[v3], verts[v2], verts[v1], new Vector2(v3u, v3v), new Vector2(v2u, v2v), new Vector2(v1u, v1v), matID);
                                //m.AddFace(v1, v2, v3, m.AddUV(new Vector2(v1u, v1v)), m.AddUV(new Vector2(v2u, v2v)), m.AddUV(new Vector2(v3u, v3v)), matID);

                                //Console.WriteLine(v1 + " : " + verts[v1].ToString() + " || " + v2 + " : " + verts[v2].ToString() + " || " + v3 + " : " + verts[v3].ToString());
                                //Console.WriteLine(j + ")\t" + br.ReadByte() + "\t" + br.ReadByte() + "\t" + br.ReadByte() + "\t" + br.ReadByte() + "\t" + br.ReadByte() + "\t" + br.ReadByte() + "\t" + br.ReadInt16());
                                //br.ReadBytes(10);
                            }

                            if (bDebug)
                            {
                                Console.WriteLine("Reading " + sX[3] + " records (" + (sX[3] * 24) + " bytes) of block " + (i - 1) + " at " + br.BaseStream.Position);
                            }

                            for (int j = 0; j < sX[3]; j++)
                            {
                                // Quads :|
                                int v1 = br.ReadInt16();
                                int v2 = br.ReadInt16();
                                int v3 = br.ReadInt16();
                                int v4 = br.ReadInt16();

                                float v1u = br.ReadByte();
                                float v1v = br.ReadByte();
                                float v2u = br.ReadByte();
                                float v2v = br.ReadByte();
                                float v3u = br.ReadByte();
                                float v3v = br.ReadByte();
                                float v4u = br.ReadByte();
                                float v4v = br.ReadByte();

                                br.ReadBytes(5);

                                int matID = matIDs[br.ReadByte()];

                                br.ReadBytes(2);

                                if (psxTex != null)
                                {
                                    if (!bFlipU)
                                    {
                                        v1u /= psxTex[matID].Width;
                                        v2u /= psxTex[matID].Width;
                                        v3u /= psxTex[matID].Width;
                                        v4u /= psxTex[matID].Width;
                                    }
                                    else
                                    {
                                        v1u = 1.0f - (v1u / psxTex[matID].Width);
                                        v2u = 1.0f - (v2u / psxTex[matID].Width);
                                        v3u = 1.0f - (v3u / psxTex[matID].Width);
                                        v4u = 1.0f - (v4u / psxTex[matID].Width);
                                    }
                                    v1v = 1.0f - (v1v / psxTex[matID].Height);
                                    v2v = 1.0f - (v2v / psxTex[matID].Height);
                                    v3v = 1.0f - (v3v / psxTex[matID].Height);
                                    v4v = 1.0f - (v4v / psxTex[matID].Height);
                                }

                                // correct apart from UVs
                                //m.AddFace(verts[v1], verts[v2], verts[v4], new Vector2(v1u, v1v), new Vector2(v2u, v2v), new Vector2(v4u, v4v), matID);
                                //m.AddFace(verts[v1], verts[v4], verts[v3], new Vector2(v1u, v1v), new Vector2(v4u, v4v), new Vector2(v3u, v3v), matID);

                                // correct apart from UVs
                                //m.AddFace(verts[v1], verts[v2], verts[v4], new Vector2(v1u, v1v), new Vector2(v2u, v2v), new Vector2(v4u, v4v), matID);
                                //m.AddFace(verts[v1], verts[v4], verts[v3], new Vector2(v1u, v1v), new Vector2(v4u, v4v), new Vector2(v3u, v3v), matID);

                                // this is inside out
                                m.AddFace(verts[v4], verts[v2], verts[v1], new Vector2(v4u, v4v), new Vector2(v2u, v2v), new Vector2(v1u, v1v), matID);
                                m.AddFace(verts[v3], verts[v4], verts[v1], new Vector2(v3u, v3v), new Vector2(v4u, v4v), new Vector2(v1u, v1v), matID);

                                //m.AddFace(v1, v2, v4, m.AddUV(new Vector2(v1u, v1v)), m.AddUV(new Vector2(v2u, v2v)), m.AddUV(new Vector2(v4u, v4v)), matID);
                                //m.AddFace(v1, v4, v3, m.AddUV(new Vector2(v1u, v1v)), m.AddUV(new Vector2(v4u, v4v)), m.AddUV(new Vector2(v3u, v3v)), matID);
                            }

                            if (bDebug)
                            {
                                Console.WriteLine("Finished processing section at " + br.BaseStream.Position + " of " + br.BaseStream.Length);
                            }

                            m.ProcessMesh();
                            if (bDebug)
                            {
                                Console.WriteLine("Adding mesh test" + i);
                                Console.WriteLine(m.Extents.ToString());
                            }

                            dat.AddMesh("test" + i, 0, m);
                        }
                    }
                }

                //dat.CentreOn(0f, 0f, 0f);
                dat.Scale(scaleFactor);
                dat.Save(PathOut + fileIn.Replace("MAP", "dat"));
            }
            else
            {
                // Process everything else
                int headLoop = br.ReadInt32();
                Console.WriteLine("# of offsets " + headLoop);
                Console.WriteLine("Unknown A " + br.ReadInt32());
                Console.WriteLine("Unknown B " + br.ReadInt32());

                int iCountA = br.ReadInt32();
                Console.WriteLine("There are " + iCountA + " global entries");

                for (int i = 0; i < headLoop - 1; i++)
                {
                    Console.WriteLine("Offset #" + i + " :: " + br.ReadInt32());
                }

                if (br.ReadInt32() != 0)
                {
                    Console.WriteLine("int not 0");
                }

                Console.WriteLine("Header read at " + br.BaseStream.Position + " of " + br.BaseStream.Length);

                Console.WriteLine("Reading " + iCountA + " (" + (8 * iCountA) + " bytes) global entries");
                for (int i = 0; i < iCountA; i++)
                {
                    //Console.WriteLine(i + ") " + faceNorms[i].X + " :: " + faceNorms[i].Y + " :: " + faceNorms[i].Z + " :: " + uvScale[i]);
                    br.ReadBytes(8);
                }

                DAT dat = new DAT();

                while (br.BaseStream.Position < br.BaseStream.Length)
                {
                    if (bSplit)
                    {
                        dat = new DAT();
                    }
                    C2Mesh m;

                    Console.WriteLine("Object discovered at " + br.BaseStream.Position + " of " + br.BaseStream.Length);

                    m = new C2Mesh();

                    if (psxTex != null)
                    {
                        for (int i = 0; i < psxTex.Length; i++)
                        {
                            m.AddListMaterial(psxTex[i].Name);
                        }
                    }

                    int iOffsetC = br.ReadInt32();
                    int iOffsetD = br.ReadInt32();
                    int iOffsetE = br.ReadInt32();
                    Console.WriteLine(iOffsetC + " :: " + iOffsetD + " :: " + iOffsetE);

                    int iCountB = br.ReadInt16();
                    int iCountC = br.ReadInt16();

                    Console.WriteLine("There are " + iCountB + " local x entries");
                    Console.WriteLine("There are " + iCountC + " local y entries");

                    for (int i = 0; i < 14; i++)
                    {
                        if (br.ReadInt32() != 0)
                        {
                            Console.WriteLine(i + " loop int not 0");
                        }
                    }

                    string name = ReadString(ref br, 32);
                    Console.WriteLine("Name block :: " + name);
                    Vector3[] verts = new Vector3[iCountB];

                    for (int i = 0; i < iCountB; i++)
                    {
                        verts[i] = new Vector3(-br.ReadInt16(), -br.ReadInt16(), br.ReadInt16());
                        //m.AddListVertex(verts[i] * scaleFactor);
                        br.ReadInt16();
                    }

                    int uvCount = 0;

                    for (int i = 0; i < iCountC; i++)
                    {
                        int   v3     = br.ReadInt16();
                        int   v2     = br.ReadInt16();
                        int   v1     = br.ReadInt16();
                        int   faceID = br.ReadInt16();
                        float v3u    = br.ReadByte();
                        float v3v    = br.ReadByte();
                        float v2u    = br.ReadByte();
                        float v2v    = br.ReadByte();
                        float v1u    = br.ReadByte();
                        float v1v    = br.ReadByte();
                        int   unkA   = br.ReadInt16();
                        int   unkB   = br.ReadInt16();
                        int   matID  = br.ReadInt16();

                        v1u /= psxTex[matID].Width;
                        v2u /= psxTex[matID].Width;
                        v3u /= psxTex[matID].Width;
                        v1v  = 1.0f - (v1v / psxTex[matID].Height);
                        v2v  = 1.0f - (v2v / psxTex[matID].Height);
                        v3v  = 1.0f - (v3v / psxTex[matID].Height);

                        int uv1 = uvCount;
                        m.AddListVertex(verts[v1] * scaleFactor);
                        m.AddListUV(new Vector2(v1u, v1v));
                        uvCount++;

                        int uv2 = uvCount;
                        m.AddListVertex(verts[v2] * scaleFactor);
                        m.AddListUV(new Vector2(v2u, v2v));
                        uvCount++;

                        int uv3 = uvCount;
                        m.AddListVertex(verts[v3] * scaleFactor);
                        m.AddListUV(new Vector2(v3u, v3v));
                        uvCount++;

                        //if (psxTex[matID].Width > psxTex[matID].Height)
                        //{
                        //    Console.WriteLine(i + ") " + v1 + " :: " + v2 + " :: " + v3 + " :: " + faceID + " :: " + v1u + ", " + v1v + " :: " + v2u + ", " + v2v + " :: " + v3u + ", " + v3v + " :: " + unkA + " :: " + unkB + " :: " + matID);
                        //    Console.WriteLine(psxTex[matID].Name + " :: " + psxTex[matID].Width + " :: " + psxTex[matID].Height);
                        //    Console.WriteLine(m.UVs[uv1].ToString() + " :: " + m.UVs[uv2].ToString() + " :: " + m.UVs[uv3].ToString());
                        //}

                        m.AddFace(uv1, uv2, uv3, uv1, uv2, uv3, matID);
                    }

                    m.ProcessMesh();
                    dat.AddMesh(name, 0, m);
                    if (bSplit)
                    {
                        dat.Save(PathOut + fileIn.Replace(".MOD", "_" + name + ".dat").Replace(".COL", ".dat"));
                    }
                    //    br.BaseStream.Position = br.BaseStream.Length;
                }

                if (!bSplit)
                {
                    dat.Save(PathOut + fileIn.Replace(".MOD", "_all.dat").Replace(".COL", ".dat"));
                }
            }

            Console.WriteLine(br.BaseStream.Position + " of " + br.BaseStream.Length);

            br.Close();
        }