示例#1
0
        /// <summary>
        /// Reads the model data for specified item and converts it into a .obj file
        /// </summary>
        /// <param name="itemID">The item ID</param>
        /// <param name="raceID">The currently selected races ID</param>
        /// <param name="part">items equipment slot</param>
        /// <param name="parentNode">Equipment slot name</param>
        /// <param name="childNode">Item Name</param>
        public Read3D(string itemID, string raceID, string part, string parentNode, string childNode)
        {
            string modelFolder, modelFile;

            modelFolder = "chara/equipment/e" + itemID + "/model";
            modelFile   = "c" + raceID + "e" + itemID + "_" + part + ".mdl";


            FindOffset fo     = new FindOffset(modelFile);
            string     offset = fo.getFileOffset();

            int loc = ((int.Parse(offset, NumberStyles.HexNumber) / 8) & 0x000f) / 2;

            using (BinaryReader br = new BinaryReader(File.OpenRead(Properties.Settings.Default.DefaultDir + "/040000.win32.dat" + loc)))
            {
                int initialOffset = int.Parse(offset, NumberStyles.HexNumber);

                if (loc == 1)
                {
                    initialOffset = initialOffset - 16;
                }
                else if (loc == 2)
                {
                    initialOffset = initialOffset - 32;
                }
                else if (loc == 3)
                {
                    initialOffset = initialOffset - 48;
                }


                List <byte> byteList = new List <byte>();

                br.BaseStream.Seek(initialOffset, SeekOrigin.Begin);

                int headerLength     = br.ReadInt32();
                int type             = br.ReadInt32();
                int decompressedSize = br.ReadInt32();
                br.ReadBytes(8);
                int parts = br.ReadInt16();

                int endOfHeader = initialOffset + headerLength;

                int partCount = 0;

                byteList.AddRange(new byte[68]);

                br.BaseStream.Seek(initialOffset + 24, SeekOrigin.Begin);

                int[] chunkUncompSizes = new int[11];
                int[] chunkLengths     = new int[11];
                int[] chunkOffsets     = new int[11];
                int[] chunkBlockStart  = new int[11];
                int[] chunkNumBlocks   = new int[11];



                for (int f = 0; f < 11; f++)
                {
                    chunkUncompSizes[f] = br.ReadInt32();
                }
                for (int f = 0; f < 11; f++)
                {
                    chunkLengths[f] = br.ReadInt32();
                }
                for (int f = 0; f < 11; f++)
                {
                    chunkOffsets[f] = br.ReadInt32();
                }
                for (int f = 0; f < 11; f++)
                {
                    chunkBlockStart[f] = br.ReadInt16();
                }
                int totalBlocks = 0;
                for (int f = 0; f < 11; f++)
                {
                    chunkNumBlocks[f] = br.ReadInt16();

                    totalBlocks += chunkNumBlocks[f];
                }

                meshCount     = br.ReadInt16();
                materialCount = br.ReadInt16();

                br.ReadBytes(4);

                int[] blockSizes = new int[totalBlocks];

                for (int f = 0; f < totalBlocks; f++)
                {
                    blockSizes[f] = br.ReadInt16();
                }


                br.BaseStream.Seek(initialOffset + headerLength + chunkOffsets[0], SeekOrigin.Begin);

                for (int i = 0; i < blockSizes.Length; i++)
                {
                    int lastPos = (int)br.BaseStream.Position;

                    br.ReadBytes(8);
                    int partCompressedSize   = br.ReadInt32();
                    int partDecompressedSize = br.ReadInt32();

                    if (partCompressedSize == 32000)
                    {
                        byte[] forlist = br.ReadBytes(partDecompressedSize);
                        byteList.AddRange(forlist);
                    }
                    else
                    {
                        byte[] forlist = br.ReadBytes(partCompressedSize);
                        byte[] partDecompressedBytes = new byte[partDecompressedSize];

                        using (MemoryStream ms = new MemoryStream(forlist))
                        {
                            using (DeflateStream ds = new DeflateStream(ms, CompressionMode.Decompress))
                            {
                                int count = ds.Read(partDecompressedBytes, 0x00, partDecompressedSize);
                            }
                        }
                        byteList.AddRange(partDecompressedBytes);
                    }

                    br.BaseStream.Seek(lastPos + blockSizes[i], SeekOrigin.Begin);
                }

                decompBytes = byteList.ToArray();
            }

            using (BinaryReader br = new BinaryReader(new MemoryStream(decompBytes)))
            {
                Model model = new Model(meshCount, materialCount);

                for (int x = 0; x < 3; x++)
                {
                    List <MeshInfo> mInfo = new List <MeshInfo>();

                    for (int i = 0; i < meshCount / 3; i++)
                    {
                        mInfo.Clear();
                        br.BaseStream.Seek((x * 136) + 68, SeekOrigin.Begin);
                        int dataArrayNum = br.ReadByte();

                        while (dataArrayNum != 255)
                        {
                            MeshInfo meshInfo = new MeshInfo(dataArrayNum, br.ReadByte(), br.ReadByte(), br.ReadByte());
                            mInfo.Add(meshInfo);
                            br.ReadBytes(4);
                            dataArrayNum = br.ReadByte();
                        }

                        model.Quality[x].meshInfoDict.Add(i, mInfo.ToArray());
                    }
                }

                br.BaseStream.Seek(136 * meshCount + 68, SeekOrigin.Begin);
                model.numStrings      = br.ReadInt32();
                model.stringBlockSize = br.ReadInt32();

                br.ReadBytes(model.stringBlockSize);
                br.ReadBytes(4);

                model.numTotalMeshes     = br.ReadInt16();
                model.numAtrStrings      = br.ReadInt16();
                model.numParts           = br.ReadInt16();
                model.numMaterialStrings = br.ReadInt16();
                model.numBoneStrings     = br.ReadInt16();
                model.numBoneLists       = br.ReadInt16();
                model.unk1 = br.ReadInt16();
                model.unk2 = br.ReadInt16();
                model.unk3 = br.ReadInt16();
                model.unk4 = br.ReadInt16();
                model.unk5 = br.ReadInt16();
                model.unk6 = br.ReadInt16();
                br.ReadBytes(10);
                model.unk7 = br.ReadInt16();
                br.ReadBytes(16);

                br.ReadBytes(32 * model.unk5);

                for (int i = 0; i < 3; i++)
                {
                    model.Quality[i].meshOffset = br.ReadInt16();
                    model.Quality[i].numMeshes  = br.ReadInt16();

                    br.ReadBytes(40);

                    model.Quality[i].vertDataSize  = br.ReadInt32();
                    model.Quality[i].indexDataSize = br.ReadInt32();
                    model.Quality[i].vertOffset    = br.ReadInt32();
                    model.Quality[i].indexOffset   = br.ReadInt32();
                }

                for (int x = 0; x < 3; x++)
                {
                    for (int i = 0; i < meshCount / 3; i++)
                    {
                        Mesh m = new Mesh();

                        m.numVerts        = br.ReadInt32();
                        m.numIndex        = br.ReadInt32();
                        m.materialNumber  = br.ReadInt16();
                        m.partTableOffset = br.ReadInt16();
                        m.partTableCount  = br.ReadInt16();
                        m.boneListIndex   = br.ReadInt16();
                        m.indexDataOffset = br.ReadInt32();
                        for (int j = 0; j < 3; j++)
                        {
                            m.vertexDataOffsets[j] = br.ReadInt32();
                        }
                        for (int k = 0; k < 3; k++)
                        {
                            m.vertexSizes[k] = br.ReadByte();
                        }
                        m.numBuffers = br.ReadByte();

                        model.Quality[x].mesh[i] = m;
                    }
                }

                br.ReadBytes(model.numAtrStrings * 4);
                br.ReadBytes(model.unk6 * 20);

                model.setMeshParts();

                for (int i = 0; i < model.numParts; i++)
                {
                    MeshPart mp = new MeshPart();
                    mp.indexOffset         = br.ReadInt32();
                    mp.indexCount          = br.ReadInt32();
                    mp.attributes          = br.ReadInt32();
                    mp.boneReferenceOffset = br.ReadInt16();
                    mp.boneReferenceCount  = br.ReadInt16();

                    model.meshPart[i] = mp;
                }

                //something with attribute masks

                br.ReadBytes(model.unk7 * 12);
                br.ReadBytes(model.numMaterialStrings * 4);
                br.ReadBytes(model.numBoneStrings * 4);

                model.setBoneList();

                for (int i = 0; i < model.numBoneLists; i++)
                {
                    BoneList bl = new BoneList();
                    for (int j = 0; j < 64; j++)
                    {
                        bl.boneList[j] = br.ReadInt16();
                    }
                    bl.boneCount = br.ReadInt32();

                    model.boneList[i] = bl;
                }

                br.ReadBytes(model.unk1 * 16);
                br.ReadBytes(model.unk2 * 12);
                br.ReadBytes(model.unk3 * 4);

                model.boneIndexSize = br.ReadInt32();

                model.setBoneIndicies();

                for (int i = 0; i < model.boneIndexSize / 2; i++)
                {
                    model.boneIndicies[i] = br.ReadInt16();
                }

                int padding = br.ReadByte();
                br.ReadBytes(padding);

                for (int i = 0; i < model.bb.Length; i++)
                {
                    BoundingBoxes bb = new BoundingBoxes();
                    for (int j = 0; j < 4; j++)
                    {
                        bb.pointA[j] = br.ReadSingle();
                    }
                    for (int k = 0; k < 4; k++)
                    {
                        bb.pointB[k] = br.ReadSingle();
                    }

                    model.bb[i] = bb;
                }

                for (int i = 0; i < 3; i++)
                {
                    for (int j = 0; j < model.Quality[i].numMeshes; j++)
                    {
                        Mesh m = model.Quality[i].mesh[j];

                        m.setMeshData();

                        for (int k = 0; k < m.numBuffers; k++)
                        {
                            br.BaseStream.Seek(model.Quality[i].vertOffset + m.vertexDataOffsets[k], SeekOrigin.Begin);

                            MeshData md = new MeshData();
                            md.meshData = br.ReadBytes(m.vertexSizes[k] * m.numVerts);

                            m.meshData[k] = md;
                        }

                        br.BaseStream.Seek(model.Quality[i].indexOffset + (m.indexDataOffset * 2), SeekOrigin.Begin);

                        m.indexData = br.ReadBytes(2 * m.numIndex);
                    }
                }

                List <string> objBytes = new List <string>();

                int vertexs = 0, coordinates = 0, normals = 0;

                for (int i = 0; i < model.Quality[0].numMeshes; i++)
                {
                    objBytes.Clear();
                    Mesh m = model.Quality[0].mesh[i];

                    MeshInfo[] mi = model.Quality[0].meshInfoDict[i];

                    int c = 0;
                    foreach (var a in mi)
                    {
                        if (a.useType == 0)
                        {
                            vertexs = c;
                        }
                        else if (a.useType == 3)
                        {
                            normals = c;
                        }
                        else if (a.useType == 4)
                        {
                            coordinates = c;
                        }
                        c++;
                    }

                    using (BinaryReader br1 = new BinaryReader(new MemoryStream(m.meshData[mi[vertexs].dataArrayNum].meshData)))
                    {
                        for (int j = 0; j < m.numVerts; j++)
                        {
                            int offset1 = j * m.vertexSizes[mi[vertexs].dataArrayNum] + mi[vertexs].offset;
                            br1.BaseStream.Seek(offset1, SeekOrigin.Begin);

                            if (mi[vertexs].dataType == 13 || mi[vertexs].dataType == 14)
                            {
                                float f1, f2, f3;

                                Half h1 = Half.ToHalf((ushort)br1.ReadInt16());
                                Half h2 = Half.ToHalf((ushort)br1.ReadInt16());
                                Half h3 = Half.ToHalf((ushort)br1.ReadInt16());


                                f1 = HalfHelper.HalfToSingle(h1);
                                f2 = HalfHelper.HalfToSingle(h2);
                                f3 = HalfHelper.HalfToSingle(h3);

                                objBytes.Add("v " + f1.ToString() + " " + f2.ToString() + " " + f3.ToString() + " ");
                            }
                            else if (mi[vertexs].dataType == 2)
                            {
                                float f1, f2, f3;

                                f1 = br1.ReadSingle();
                                f2 = br1.ReadSingle();
                                f3 = br1.ReadSingle();

                                objBytes.Add("v " + f1.ToString() + " " + f2.ToString() + " " + f3.ToString() + " ");
                            }
                        }
                    }

                    using (BinaryReader br1 = new BinaryReader(new MemoryStream(m.meshData[mi[coordinates].dataArrayNum].meshData)))
                    {
                        for (int j = 0; j < m.numVerts; j++)
                        {
                            int offset1 = j * m.vertexSizes[mi[coordinates].dataArrayNum] + mi[coordinates].offset;

                            br1.BaseStream.Seek(offset1, SeekOrigin.Begin);

                            Half a1 = Half.ToHalf((ushort)br1.ReadInt16());
                            Half b1 = Half.ToHalf((ushort)br1.ReadInt16());

                            float a = HalfHelper.HalfToSingle(a1);
                            float b = (HalfHelper.HalfToSingle(b1));

                            objBytes.Add("vt " + a.ToString() + " " + b.ToString() + " ");
                        }
                    }

                    using (BinaryReader br1 = new BinaryReader(new MemoryStream(m.meshData[mi[normals].dataArrayNum].meshData)))
                    {
                        for (int j = 0; j < m.numVerts; j++)
                        {
                            br1.BaseStream.Seek(j * m.vertexSizes[mi[normals].dataArrayNum] + mi[normals].offset, SeekOrigin.Begin);

                            Half h1 = Half.ToHalf((ushort)br1.ReadInt16());
                            Half h2 = Half.ToHalf((ushort)br1.ReadInt16());
                            Half h3 = Half.ToHalf((ushort)br1.ReadInt16());

                            objBytes.Add("vn " + HalfHelper.HalfToSingle(h1).ToString() + " " + HalfHelper.HalfToSingle(h2).ToString() + " " + HalfHelper.HalfToSingle(h3).ToString() + " ");
                        }
                    }

                    using (BinaryReader br1 = new BinaryReader(new MemoryStream(m.indexData)))
                    {
                        for (int j = 0; j < m.numIndex; j += 3)
                        {
                            int a1 = br1.ReadInt16() + 1;
                            int b1 = br1.ReadInt16() + 1;
                            int c1 = br1.ReadInt16() + 1;

                            objBytes.Add("f " + a1 + "/" + a1 + "/" + a1 + " " + b1 + "/" + b1 + "/" + b1 + " " + c1 + "/" + c1 + "/" + c1 + " ");
                        }
                    }

                    Directory.CreateDirectory(Properties.Settings.Default.SaveDir + "/" + parentNode + "/" + childNode);
                    File.WriteAllLines(Properties.Settings.Default.SaveDir + "/" + parentNode + "/" + childNode + "/Mesh_" + i + ".obj", objBytes.ToArray());
                }
            }
        }
示例#2
0
 /// <summary>
 /// Adds the texture names to dictionary
 /// </summary>
 /// <param name="name">full name of texture</param>
 /// <param name="sName">texture name substring</param>
 private void addTextures(string name, string sName)
 {
     if (name.Contains("_s.tex"))
     {
         fo = new FindOffset(sName);
         if (!fo.getFileOffset().Equals("0"))
         {
             textureOffsets.Add("Specular", fo.getFileOffset());
             textureNames.Add(sName);
         }
         else
         {
             fo = new FindOffset(sName.Substring(2));
             textureOffsets.Add("Specular", fo.getFileOffset());
             textureNames.Add(sName);
         }
     }
     else if (name.Contains("_d.tex"))
     {
         fo = new FindOffset(sName);
         if (!fo.getFileOffset().Equals("0"))
         {
             textureOffsets.Add("Diffuse", fo.getFileOffset());
             textureNames.Add(sName);
         }
         else
         {
             fo = new FindOffset(sName.Substring(2));
             textureOffsets.Add("Diffuse", fo.getFileOffset());
             textureNames.Add(sName);
         }
     }
     else if (name.Contains("_n.tex"))
     {
         fo = new FindOffset(sName);
         if (!fo.getFileOffset().Equals("0"))
         {
             textureOffsets.Add("Normal", fo.getFileOffset());
             textureNames.Add(sName);
         }
         else
         {
             fo = new FindOffset(sName.Substring(2));
             textureOffsets.Add("Normal", fo.getFileOffset());
             textureNames.Add(sName);
         }
     }
     else if (name.Contains("_m.tex"))
     {
         fo = new FindOffset(sName);
         if (!fo.getFileOffset().Equals("0"))
         {
             textureOffsets.Add("Mask", fo.getFileOffset());
             textureNames.Add(sName);
         }
         else
         {
             fo = new FindOffset(sName.Substring(2));
             textureOffsets.Add("Mask", fo.getFileOffset());
             textureNames.Add(sName);
         }
     }
 }