예제 #1
0
        public void LoadFrom_p3s_c4b_t2s(DataStream_p3s_c4b_t2s p3s_c4b_t2sList)
        {
            mesh = new Mesh(nCount);
            foreach (DataStream_p3s_c4b_t2s_Elem p3s_c4b_t2s in p3s_c4b_t2sList.p3s_c4b_t2sElem)
            {
                DataStream_Positions_Elem position = new DataStream_Positions_Elem();
                for (int i = 0; i < 3; i++)
                {
                    Half halfEl = new Half();
                    halfEl.value    = p3s_c4b_t2s.pos[i];
                    position.pos[i] = HalfHelper.HalfToSingle(halfEl);
                }
                mesh.positions.position.Add(position);

                DataStream_Colors_Elem color = new DataStream_Colors_Elem();
                for (int i = 0; i < 4; i++)
                {
                    color.rgba[i] = p3s_c4b_t2s.bgra[i];
                }
                mesh.colors.color.Add(color);

                DataStream_Texcoords_Elem texoord = new DataStream_Texcoords_Elem();
                for (int i = 0; i < 2; i++)
                {
                    Half halfEl = new Half();
                    halfEl.value  = p3s_c4b_t2s.uv[i];
                    texoord.uv[i] = HalfHelper.HalfToSingle(halfEl);
                }
                mesh.texcoords.texcoord.Add(texoord);
            }
        }
예제 #2
0
        public ONNXTensor(TensorProto onnxTensor)
        {
            // read shape
            var onnxShape = onnxTensor.Dims.ToArray();
            var shape     = ONNXLayout.ConvertShapeToBarracuda(onnxShape, onnxLayout: "?");

            // read data
            float[] data;
            if ((onnxTensor.RawData != null) && (!onnxTensor.RawData.IsEmpty))
            {
                var byteArray = new byte[onnxTensor.RawData.Length];
                onnxTensor.RawData.CopyTo(byteArray, 0);

                // Float32
                if (onnxTensor.DataType == (int)TensorProto.Types.DataType.Float)
                {
                    data = new float[shape.length];
                    Debug.Assert((sizeof(float) * shape.length) == onnxTensor.RawData.Length);
                    Buffer.BlockCopy(byteArray, 0, data, 0, byteArray.Length);
                }
                // Float16
                else if (onnxTensor.DataType == (int)TensorProto.Types.DataType.Float16)
                {
                    var typedData = new UInt16[shape.length];
                    Debug.Assert((sizeof(UInt16) * shape.length) == onnxTensor.RawData.Length);
                    Buffer.BlockCopy(byteArray, 0, typedData, 0, byteArray.Length);
                    data = typedData.Select(x => HalfHelper.HalfToSingle(x)).ToArray();
                }
                // Int32
                else if (onnxTensor.DataType == (int)TensorProto.Types.DataType.Int32)
                {
                    var typedData = new int[shape.length];
                    Debug.Assert((sizeof(int) * shape.length) == onnxTensor.RawData.Length);
                    Buffer.BlockCopy(byteArray, 0, typedData, 0, byteArray.Length);
                    data = typedData.Select(x => (float)x).ToArray();
                }
                // Int64
                else if (onnxTensor.DataType == (int)TensorProto.Types.DataType.Int64)
                {
                    var typedData = new long[shape.length];
                    Debug.Assert((sizeof(long) * shape.length) == onnxTensor.RawData.Length);
                    Buffer.BlockCopy(byteArray, 0, typedData, 0, byteArray.Length);
                    data = typedData.Select(x => (float)x).ToArray();
                }
                else
                {
                    throw new OnnxLayerImportException($"Tensor data type {(TensorProto.Types.DataType)onnxTensor.DataType} is not supported.");
                }
            }
            // Float32
            else if ((onnxTensor.FloatData != null) && (onnxTensor.FloatData.Count != 0))
            {
                Debug.Assert(shape.length == onnxTensor.FloatData.Count);
                data = new float[shape.length];
                onnxTensor.FloatData.CopyTo(data, 0);
            }
            // Int32
            else if ((onnxTensor.Int32Data != null) && (onnxTensor.Int32Data.Count != 0))
            {
                Debug.Assert(shape.length == onnxTensor.Int32Data.Count);
                data = onnxTensor.Int32Data.Select(x => (float)x).ToArray();
            }
            // Int64
            else if ((onnxTensor.Int64Data != null) && (onnxTensor.Int64Data.Count != 0))
            {
                Debug.Assert(shape.length == onnxTensor.Int64Data.Count);
                data = onnxTensor.Int64Data.Select(x => (float)x).ToArray();
            }
            else
            {
                throw new OnnxLayerImportException("Could not read tensor data for constant tensor.");
            }

            m_Data  = new Tensor(shape, new SharedArrayTensorData(data));
            m_Shape = onnxShape;
        }
예제 #3
0
        /// <summary>
        /// Parses the MDL file to obtain model information
        /// </summary>
        /// <param name="selectedItem">The currently selected item</param>
        /// <param name="selectedRace">The currently selected race</param>
        /// <param name="selectedBody">The currently selected body</param>
        /// <param name="selectedPart">The currently selected part</param>
        /// <param name="selectedCategory">The items category </param>
        public MDL(ItemData selectedItem, string selectedCategory, string selectedRace, string selectedBody, string selectedPart)
        {
            string itemType  = Helper.GetCategoryType(selectedCategory);
            string MDLFolder = "";

            if (itemType.Equals("weapon") || itemType.Equals("food"))
            {
                if (selectedPart.Equals("Secondary"))
                {
                    MDLFolder = string.Format(Strings.WeapMDLFolder, selectedItem.SecondaryModelID, selectedItem.SecondaryModelBody);
                    MDLFile   = string.Format(Strings.WeapMDLFile, selectedItem.SecondaryModelID, selectedItem.SecondaryModelBody);
                }
                else
                {
                    MDLFolder = string.Format(Strings.WeapMDLFolder, selectedItem.PrimaryModelID, selectedItem.PrimaryModelBody);
                    MDLFile   = string.Format(Strings.WeapMDLFile, selectedItem.PrimaryModelID, selectedItem.PrimaryModelBody);
                }
            }
            else if (itemType.Equals("accessory"))
            {
                MDLFolder = string.Format(Strings.AccMDLFolder, selectedItem.PrimaryModelID);
                MDLFile   = string.Format(Strings.AccMDLFile, selectedRace, selectedItem.PrimaryModelID, Info.slotAbr[selectedCategory]);
            }
            else if (itemType.Equals("character"))
            {
                if (selectedItem.ItemName.Equals(Strings.Body))
                {
                    MDLFolder = string.Format(Strings.BodyMDLFolder, selectedRace, selectedBody.PadLeft(4, '0'));
                    MDLFile   = string.Format(Strings.BodyMDLFile, selectedRace, selectedBody.PadLeft(4, '0'), selectedPart);
                }
                else if (selectedItem.ItemName.Equals(Strings.Face))
                {
                    MDLFolder = string.Format(Strings.FaceMDLFolder, selectedRace, selectedBody.PadLeft(4, '0'));
                    MDLFile   = string.Format(Strings.FaceMDLFile, selectedRace, selectedBody.PadLeft(4, '0'), selectedPart);
                }
                else if (selectedItem.ItemName.Equals(Strings.Hair))
                {
                    MDLFolder = string.Format(Strings.HairMDLFolder, selectedRace, selectedBody.PadLeft(4, '0'));
                    MDLFile   = string.Format(Strings.HairMDLFile, selectedRace, selectedBody.PadLeft(4, '0'), selectedPart);
                }
                else if (selectedItem.ItemName.Equals(Strings.Tail))
                {
                    MDLFolder = string.Format(Strings.TailMDLFolder, selectedRace, selectedBody.PadLeft(4, '0'));
                    MDLFile   = string.Format(Strings.TailMDLFile, selectedRace, selectedBody.PadLeft(4, '0'), selectedPart);
                }
            }
            else if (itemType.Equals("monster"))
            {
                bool isDemiHuman = false;
                if (selectedItem.PrimaryMTRLFolder != null)
                {
                    isDemiHuman = selectedItem.PrimaryMTRLFolder.Contains("demihuman");
                }

                string ID   = "";
                string body = "";

                if (selectedCategory.Equals(Strings.Pets))
                {
                    int part = 1;

                    if (selectedItem.ItemName.Equals(Strings.Selene) || selectedItem.ItemName.Equals(Strings.Bishop_Autoturret))
                    {
                        part = 2;
                    }

                    ID   = Info.petID[selectedItem.ItemName];
                    body = part.ToString().PadLeft(4, '0');
                }
                else
                {
                    ID   = selectedItem.PrimaryModelID.PadLeft(4, '0');
                    body = selectedItem.PrimaryModelBody;
                }

                if (isDemiHuman)
                {
                    MDLFolder = string.Format(Strings.DemiMDLFolder, ID, body);
                    MDLFile   = string.Format(Strings.DemiMDLFile, ID, body, selectedPart);
                }
                else
                {
                    MDLFolder = string.Format(Strings.MonsterMDLFolder, ID, body);
                    MDLFile   = string.Format(Strings.MonsterMDLFile, ID, body);
                }
            }
            else
            {
                MDLFolder = string.Format(Strings.EquipMDLFolder, selectedItem.PrimaryModelID);

                if (selectedPart.Equals("-"))
                {
                    MDLFile = string.Format(Strings.EquipMDLFile, selectedRace, selectedItem.PrimaryModelID, Info.slotAbr[selectedCategory]);
                }
                else
                {
                    MDLFile = string.Format(Strings.EquipMDLFile, selectedRace, selectedItem.PrimaryModelID, selectedPart);
                }
            }

            fullPath = MDLFolder + "/" + MDLFile;
            int offset = Helper.GetDataOffset(FFCRC.GetHash(MDLFolder), FFCRC.GetHash(MDLFile), Strings.ItemsDat);

            if (offset == 0)
            {
                if (itemType.Equals("weapon"))
                {
                    if (selectedPart.Equals("Secondary"))
                    {
                        MDLFolder = string.Format(Strings.EquipMDLFolder, selectedItem.SecondaryModelID);
                        MDLFile   = string.Format(Strings.EquipMDLFile, "0101", selectedItem.SecondaryModelID, Info.slotAbr[Strings.Hands]);

                        offset = Helper.GetDataOffset(FFCRC.GetHash(MDLFolder), FFCRC.GetHash(MDLFile), Strings.ItemsDat);
                    }
                }
            }

            int datNum = ((offset / 8) & 0x000f) / 2;

            var MDLDatData = Helper.GetType3DecompressedData(offset, datNum, Strings.ItemsDat);

            using (BinaryReader br = new BinaryReader(new MemoryStream(MDLDatData.Item1)))
            {
                // The size of the header + (size of the mesh information block (136 bytes) * the number of meshes) + padding
                br.BaseStream.Seek(64 + 136 * MDLDatData.Item2 + 4, SeekOrigin.Begin);

                var modelStringCount = br.ReadInt32();
                var stringBlockSize  = br.ReadInt32();
                var stringBlock      = br.ReadBytes(stringBlockSize);

                var unknown = br.ReadBytes(4);

                var totalMeshCount       = br.ReadInt16();
                var attributeStringCount = br.ReadInt16();
                var meshPartsCount       = br.ReadInt16();
                var materialStringCount  = br.ReadInt16();
                var boneStringCount      = br.ReadInt16();
                var boneListCount        = br.ReadInt16();

                var unknown1 = br.ReadInt16();
                var unknown2 = br.ReadInt16();
                var unknown3 = br.ReadInt16();
                var unknown4 = br.ReadInt16();
                var unknown5 = br.ReadInt16();
                var unknown6 = br.ReadInt16();

                br.ReadBytes(10);

                var unknown7 = br.ReadInt16();

                br.ReadBytes(16);

                using (BinaryReader br1 = new BinaryReader(new MemoryStream(stringBlock)))
                {
                    br1.BaseStream.Seek(0, SeekOrigin.Begin);

                    for (int i = 0; i < attributeStringCount; i++)
                    {
                        while (br1.ReadByte() != 0)
                        {
                            //extract each atribute string here
                        }
                    }

                    for (int i = 0; i < boneStringCount; i++)
                    {
                        byte        b;
                        List <byte> boneName = new List <byte>();
                        while ((b = br1.ReadByte()) != 0)
                        {
                            boneName.Add(b);
                        }
                        string bone = Encoding.ASCII.GetString(boneName.ToArray());
                        bone = bone.Replace("\0", "");

                        boneStrings.Add(bone);
                    }

                    for (int i = 0; i < materialStringCount; i++)
                    {
                        byte        b;
                        List <byte> name = new List <byte>();
                        while ((b = br1.ReadByte()) != 0)
                        {
                            name.Add(b);
                        }
                        string material = Encoding.ASCII.GetString(name.ToArray());
                        material = material.Replace("\0", "");

                        materialStrings.Add(material);
                    }
                }

                br.ReadBytes(32 * unknown5);

                for (int i = 0; i < 3; i++)
                {
                    LevelOfDetail LoD = new LevelOfDetail();
                    LoD.MeshOffset = br.ReadInt16();
                    LoD.MeshCount  = br.ReadInt16();

                    br.ReadBytes(40);

                    LoD.VertexDataSize = br.ReadInt32();
                    LoD.IndexDataSize  = br.ReadInt32();
                    LoD.VertexOffset   = br.ReadInt32();
                    LoD.IndexOffset    = br.ReadInt32();

                    modelData.LoD.Add(LoD);
                }

                var savePos = br.BaseStream.Position;

                for (int i = 0; i < modelData.LoD.Count; i++)
                {
                    List <MeshDataInfo> meshInfoList = new List <MeshDataInfo>();

                    for (int j = 0; j < modelData.LoD[i].MeshCount; j++)
                    {
                        modelData.LoD[i].MeshList.Add(new Mesh());
                        meshInfoList.Clear();

                        br.BaseStream.Seek((i * 136) + 68, SeekOrigin.Begin);
                        var dataBlockNum = br.ReadByte();

                        while (dataBlockNum != 255)
                        {
                            MeshDataInfo meshInfo = new MeshDataInfo()
                            {
                                VertexDataBlock = dataBlockNum,
                                Offset          = br.ReadByte(),
                                DataType        = br.ReadByte(),
                                UseType         = br.ReadByte()
                            };

                            meshInfoList.Add(meshInfo);

                            br.ReadBytes(4);

                            dataBlockNum = br.ReadByte();
                        }

                        modelData.LoD[i].MeshList[j].MeshDataInfoList = meshInfoList.ToArray();
                    }
                }

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

                for (int x = 0; x < modelData.LoD.Count; x++)
                {
                    for (int i = 0; i < modelData.LoD[x].MeshCount; i++)
                    {
                        MeshInfo meshInfo = new MeshInfo()
                        {
                            VertexCount     = br.ReadInt32(),
                            IndexCount      = br.ReadInt32(),
                            MaterialNum     = br.ReadInt16(),
                            MeshPartOffset  = br.ReadInt16(),
                            MeshPartCount   = br.ReadInt16(),
                            BoneListIndex   = br.ReadInt16(),
                            IndexDataOffset = br.ReadInt32()
                        };

                        for (int j = 0; j < 3; j++)
                        {
                            meshInfo.VertexDataOffsets.Add(br.ReadInt32());
                        }

                        for (int k = 0; k < 3; k++)
                        {
                            meshInfo.VertexSizes.Add(br.ReadByte());
                        }

                        meshInfo.VertexDataBlockCount = br.ReadByte();

                        modelData.LoD[x].MeshList[i].MeshInfo = meshInfo;
                    }
                }

                br.ReadBytes(attributeStringCount * 4);
                br.ReadBytes(unknown6 * 20);

                for (int i = 0; i < modelData.LoD.Count; i++)
                {
                    foreach (var mesh in modelData.LoD[i].MeshList)
                    {
                        for (int j = 0; j < mesh.MeshInfo.MeshPartCount; j++)
                        {
                            MeshPart meshPart = new MeshPart()
                            {
                                IndexOffset = br.ReadInt32(),
                                IndexCount  = br.ReadInt32(),
                                Attributes  = br.ReadInt32(),
                                BoneOffset  = br.ReadInt16(),
                                BoneCount   = br.ReadInt16()
                            };

                            mesh.MeshPartList.Add(meshPart);
                        }
                    }
                }

                br.ReadBytes(unknown7 * 12);
                br.ReadBytes(materialStringCount * 4);
                br.ReadBytes(boneStringCount * 4);

                for (int i = 0; i < boneListCount; i++)
                {
                    Bones bones = new Bones();

                    for (int j = 0; j < 64; j++)
                    {
                        bones.BoneData.Add(br.ReadInt16());
                    }

                    bones.BoneCount = br.ReadInt32();

                    modelData.BoneSet.Add(bones);
                }

                //br.ReadBytes(unknown1 * 16);

                Dictionary <int, int>         indexMin     = new Dictionary <int, int>();
                Dictionary <int, List <int> > extraIndices = new Dictionary <int, List <int> >();
                List <ExtraIndex>             indexCounts  = new List <ExtraIndex>();

                var pCount  = 0;
                var pCount1 = 0;
                var pCount2 = 0;

                if (unknown1 > 0)
                {
                    for (int i = 0; i < unknown1; i++)
                    {
                        //not sure
                        br.ReadBytes(4);

                        //LoD[0] Extra Data Index
                        var p1 = br.ReadUInt16();

                        //LoD[1] Extra Data Index
                        var p2 = br.ReadUInt16();

                        //LoD[2] Extra Data Index
                        var p3 = br.ReadUInt16();


                        //LoD[0] Extra Data Part Count
                        var p1n = br.ReadUInt16();
                        pCount += p1n;

                        //LoD[1] Extra Data Part Count
                        var p2n = br.ReadUInt16();
                        pCount1 += p2n;

                        //LoD[2] Extra Data Part Count
                        var p3n = br.ReadUInt16();
                        pCount2 += p3n;
                    }
                }

                Dictionary <int, int> indexLoc = new Dictionary <int, int>();

                if (unknown1 > 0)
                {
                    for (int i = 0; i < modelData.LoD[0].MeshCount; i++)
                    {
                        var ido = modelData.LoD[0].MeshList[i].MeshInfo.IndexDataOffset;
                        indexLoc.Add(ido, i);
                    }
                }


                List <int>            maskCounts       = new List <int>();
                Dictionary <int, int> totalExtraCounts = new Dictionary <int, int>();
                if (unknown2 > 0)
                {
                    for (int i = 0; i < pCount; i++)
                    {
                        //Index Offset Start
                        var m1   = br.ReadInt32();
                        var iLoc = 0;
                        if (indexLoc.ContainsKey(m1))
                        {
                            iLoc = indexLoc[m1];
                        }

                        //index count
                        var mCount = br.ReadInt32();

                        //index offset in unk3
                        var mOffset = br.ReadInt32();

                        indexCounts.Add(new ExtraIndex()
                        {
                            IndexLocation = iLoc, IndexCount = mCount
                        });
                        maskCounts.Add(mCount);
                    }

                    br.ReadBytes((pCount1 + pCount2) * 12);
                }

                int totalLoD0MaskCount = 0;

                if (unknown2 > 0)
                {
                    for (int i = 0; i < pCount; i++)
                    {
                        totalLoD0MaskCount += maskCounts[i];
                    }
                }

                if (unknown3 > 0)
                {
                    var unk3Remainder = (unknown3 * 4) - (totalLoD0MaskCount * 4);

                    foreach (var ic in indexCounts)
                    {
                        HashSet <int> mIndexList = new HashSet <int>();

                        for (int i = 0; i < ic.IndexCount; i++)
                        {
                            //index its replacing? attatched to?
                            br.ReadBytes(2);
                            //extra index following last equipment index
                            var mIndex = br.ReadInt16();
                            mIndexList.Add(mIndex);

                            if (extraIndices.ContainsKey(ic.IndexLocation))
                            {
                                extraIndices[ic.IndexLocation].Add(mIndex);
                            }
                            else
                            {
                                extraIndices.Add(ic.IndexLocation, new List <int>()
                                {
                                    mIndex
                                });
                            }
                        }

                        if (totalExtraCounts.ContainsKey(ic.IndexLocation))
                        {
                            totalExtraCounts[ic.IndexLocation] += mIndexList.Count;
                        }
                        else
                        {
                            totalExtraCounts.Add(ic.IndexLocation, mIndexList.Count);
                        }
                    }
                    //the rest of unk3
                    br.ReadBytes(unk3Remainder);
                }



                if (unknown3 > 0)
                {
                    foreach (var ei in extraIndices)
                    {
                        indexMin.Add(ei.Key, ei.Value.Min());
                    }

                    extraIndexData.indexCounts      = indexCounts;
                    extraIndexData.indexMin         = indexMin;
                    extraIndexData.totalExtraCounts = totalExtraCounts;
                    extraIndexData.extraIndices     = extraIndices;

                    modelData.ExtraData = extraIndexData;
                }

                //br.ReadBytes(unknown3 * 4);

                var boneIndexSize = br.ReadInt32();

                for (int i = 0; i < boneIndexSize / 2; i++)
                {
                    modelData.BoneIndicies.Add(br.ReadInt16());
                }

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

                for (int i = 0; i < 4; i++)
                {
                    ModelMaterial.BoundingBox boundingBox = new ModelMaterial.BoundingBox();
                    for (int j = 0; j < 4; j++)
                    {
                        boundingBox.PointA.Add(br.ReadSingle());
                    }
                    for (int k = 0; k < 4; k++)
                    {
                        boundingBox.PointB.Add(br.ReadSingle());
                    }

                    modelData.BoundingBoxes.Add(boundingBox);
                }

                //float4x4
                for (int i = 0; i < boneStringCount; i++)
                {
                    boneTransforms.Add(br.ReadSingle());
                    boneTransforms.Add(br.ReadSingle());
                    boneTransforms.Add(br.ReadSingle());
                    boneTransforms.Add(br.ReadSingle());

                    boneTransforms.Add(br.ReadSingle());
                    boneTransforms.Add(br.ReadSingle());
                    boneTransforms.Add(br.ReadSingle());
                    boneTransforms.Add(br.ReadSingle());
                }

                for (int i = 0; i < 3; i++)
                {
                    for (int j = 0; j < modelData.LoD[i].MeshCount; j++)
                    {
                        Mesh mesh = modelData.LoD[i].MeshList[j];

                        for (int k = 0; k < mesh.MeshInfo.VertexDataBlockCount; k++)
                        {
                            br.BaseStream.Seek(modelData.LoD[i].VertexOffset + mesh.MeshInfo.VertexDataOffsets[k], SeekOrigin.Begin);

                            mesh.MeshVertexData.Add(br.ReadBytes(mesh.MeshInfo.VertexSizes[k] * mesh.MeshInfo.VertexCount));
                        }

                        br.BaseStream.Seek(modelData.LoD[i].IndexOffset + (mesh.MeshInfo.IndexDataOffset * 2), SeekOrigin.Begin);

                        mesh.IndexData = br.ReadBytes(2 * mesh.MeshInfo.IndexCount);
                    }
                }

                int vertex = 0, coordinates = 0, normals = 0, tangents = 0, colors = 0, blendWeights = 0, blendIndices = 0;

                for (int i = 0; i < modelData.LoD[0].MeshCount; i++)
                {
                    objBytes.Clear();

                    var vertexList        = new Vector3Collection();
                    var texCoordList      = new Vector2Collection();
                    var texCoordList2     = new Vector2Collection();
                    var normalList        = new Vector3Collection();
                    var tangentList       = new Vector3Collection();
                    var colorsList        = new Color4Collection();
                    var indexList         = new IntCollection();
                    var blendWeightList   = new List <float>();
                    var blendWeightList2  = new List <float[]>();
                    var blendIndicesList  = new List <int>();
                    var blendIndicesList2 = new List <int[]>();
                    var weightCounts      = new List <int>();


                    Mesh mesh = modelData.LoD[0].MeshList[i];

                    MeshDataInfo[] meshDataInfoList = mesh.MeshDataInfoList;

                    int c = 0;
                    foreach (var meshDataInfo in meshDataInfoList)
                    {
                        if (meshDataInfo.UseType == 0)
                        {
                            vertex = c;
                        }
                        else if (meshDataInfo.UseType == 1)
                        {
                            blendWeights = c;
                        }
                        else if (meshDataInfo.UseType == 2)
                        {
                            blendIndices = c;
                        }
                        else if (meshDataInfo.UseType == 3)
                        {
                            normals = c;
                        }
                        else if (meshDataInfo.UseType == 4)
                        {
                            coordinates = c;
                        }
                        else if (meshDataInfo.UseType == 6)
                        {
                            tangents = c;
                        }
                        else if (meshDataInfo.UseType == 7)
                        {
                            colors = c;
                        }

                        c++;
                    }

                    /*
                     * -----------------
                     * Vertex
                     * -----------------
                     */
                    using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[vertex].VertexDataBlock])))
                    {
                        for (int j = 0; j < mesh.MeshInfo.VertexCount; j++)
                        {
                            br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[vertex].VertexDataBlock] + meshDataInfoList[vertex].Offset, SeekOrigin.Begin);

                            Vector3 vVector = new Vector3();
                            if (meshDataInfoList[vertex].DataType == 13 || meshDataInfoList[vertex].DataType == 14)
                            {
                                System.Half h1 = System.Half.ToHalf((ushort)br1.ReadInt16());
                                System.Half h2 = System.Half.ToHalf((ushort)br1.ReadInt16());
                                System.Half h3 = System.Half.ToHalf((ushort)br1.ReadInt16());

                                float x = HalfHelper.HalfToSingle(h1);
                                float y = HalfHelper.HalfToSingle(h2);
                                float z = HalfHelper.HalfToSingle(h3);

                                vVector = new Vector3(x, y, z);
                                objBytes.Add("v " + x.ToString("N5") + " " + y.ToString("N5") + " " + z.ToString("N5") + " ");
                            }
                            else if (meshDataInfoList[vertex].DataType == 2)
                            {
                                var x = BitConverter.ToSingle(br1.ReadBytes(4), 0);
                                var y = BitConverter.ToSingle(br1.ReadBytes(4), 0);
                                var z = BitConverter.ToSingle(br1.ReadBytes(4), 0);

                                vVector = new Vector3(x, y, z);
                                objBytes.Add("v " + x.ToString("N5") + " " + y.ToString("N5") + " " + z.ToString("N5") + " ");
                            }

                            vertexList.Add(vVector);
                        }
                    }


                    /*
                     * -----------------
                     * Blend Weight
                     * -----------------
                     */
                    using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[blendWeights].VertexDataBlock])))
                    {
                        for (int j = 0; j < mesh.MeshInfo.VertexCount; j++)
                        {
                            br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[blendWeights].VertexDataBlock] + meshDataInfoList[blendWeights].Offset, SeekOrigin.Begin);

                            float x = br1.ReadByte() / 255.0f;
                            float y = br1.ReadByte() / 255.0f;
                            float z = br1.ReadByte() / 255.0f;
                            float w = br1.ReadByte() / 255.0f;

                            int count = 0;
                            if (x != 0)
                            {
                                blendWeightList.Add(x);
                                count++;

                                if (y != 0)
                                {
                                    blendWeightList.Add(y);
                                    count++;

                                    if (z != 0)
                                    {
                                        blendWeightList.Add(z);
                                        count++;

                                        if (w != 0)
                                        {
                                            blendWeightList.Add(w);
                                            count++;
                                        }
                                    }
                                }
                            }

                            if (count == 1)
                            {
                                blendWeightList2.Add(new float[] { x });
                            }
                            else if (count == 2)
                            {
                                blendWeightList2.Add(new float[] { x, y });
                            }
                            else if (count == 3)
                            {
                                blendWeightList2.Add(new float[] { x, y, z });
                            }
                            else if (count == 4)
                            {
                                blendWeightList2.Add(new float[] { x, y, z, w });
                            }

                            weightCounts.Add(count);
                        }
                    }


                    /*
                     * -----------------
                     * Blend Index
                     * -----------------
                     */
                    using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[blendIndices].VertexDataBlock])))
                    {
                        for (int j = 0; j < mesh.MeshInfo.VertexCount; j++)
                        {
                            br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[blendIndices].VertexDataBlock] + meshDataInfoList[blendIndices].Offset, SeekOrigin.Begin);

                            int x = br1.ReadByte();
                            int y = br1.ReadByte();
                            int z = br1.ReadByte();
                            int w = br1.ReadByte();

                            if (weightCounts[j] == 1)
                            {
                                blendIndicesList.Add(x);
                                blendIndicesList2.Add(new int[] { x });
                            }
                            else if (weightCounts[j] == 2)
                            {
                                blendIndicesList.Add(x);
                                blendIndicesList.Add(y);
                                blendIndicesList2.Add(new int[] { x, y });
                            }
                            else if (weightCounts[j] == 3)
                            {
                                blendIndicesList.Add(x);
                                blendIndicesList.Add(y);
                                blendIndicesList.Add(z);
                                blendIndicesList2.Add(new int[] { x, y, z });
                            }
                            else if (weightCounts[j] == 4)
                            {
                                blendIndicesList.Add(x);
                                blendIndicesList.Add(y);
                                blendIndicesList.Add(z);
                                blendIndicesList.Add(w);
                                blendIndicesList2.Add(new int[] { x, y, z, w });
                            }
                        }
                    }


                    /*
                     * -----------------
                     * Texture Coordinates
                     * -----------------
                     */
                    using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[coordinates].VertexDataBlock])))
                    {
                        for (int j = 0; j < mesh.MeshInfo.VertexCount; j++)
                        {
                            br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[coordinates].VertexDataBlock] + meshDataInfoList[coordinates].Offset, SeekOrigin.Begin);

                            float x = 0;
                            float y = 0;
                            float z = 0;
                            float w = 0;
                            if (meshDataInfoList[coordinates].DataType == 13 || meshDataInfoList[coordinates].DataType == 14)
                            {
                                var sx = (ushort)br1.ReadInt16();
                                var sy = (ushort)br1.ReadInt16();
                                var sz = (ushort)br1.ReadInt16();
                                var sw = (ushort)br1.ReadInt16();

                                var h1 = new SharpDX.Half(sx);
                                var h2 = new SharpDX.Half(sy);
                                var h3 = new SharpDX.Half(sz);
                                var h4 = new SharpDX.Half(sw);

                                x = h1;
                                y = h2;
                                z = h3;
                                w = h4;
                            }
                            else if (meshDataInfoList[coordinates].DataType == 1)
                            {
                                x = br1.ReadSingle();
                                y = br1.ReadSingle();
                            }
                            else
                            {
                                x = br1.ReadSingle();
                                y = br1.ReadSingle();
                                z = br1.ReadSingle();
                                w = br1.ReadSingle();
                            }


                            var ox = x - Math.Truncate(x);
                            var oy = y - Math.Truncate(y);

                            objBytes.Add("vt " + ox.ToString("N5") + " " + (1 - y).ToString("N5") + " ");
                            texCoordList.Add(new Vector2(x, y));
                            texCoordList2.Add(new Vector2(z, w));
                        }
                    }



                    /*
                     * -----------------
                     * Normals
                     * -----------------
                     */
                    using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[normals].VertexDataBlock])))
                    {
                        for (int j = 0; j < mesh.MeshInfo.VertexCount; j++)
                        {
                            br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[normals].VertexDataBlock] + meshDataInfoList[normals].Offset, SeekOrigin.Begin);

                            float x = 0;
                            float y = 0;
                            float z = 0;
                            float w = 0;

                            if (meshDataInfoList[normals].DataType == 13 || meshDataInfoList[normals].DataType == 14)
                            {
                                System.Half h1 = System.Half.ToHalf((ushort)br1.ReadInt16());
                                System.Half h2 = System.Half.ToHalf((ushort)br1.ReadInt16());
                                System.Half h3 = System.Half.ToHalf((ushort)br1.ReadInt16());
                                System.Half h4 = System.Half.ToHalf((ushort)br1.ReadInt16());

                                x = HalfHelper.HalfToSingle(h1);
                                y = HalfHelper.HalfToSingle(h2);
                                z = HalfHelper.HalfToSingle(h3);
                                w = HalfHelper.HalfToSingle(h4);
                            }
                            else
                            {
                                x = br1.ReadSingle();
                                y = br1.ReadSingle();
                                z = br1.ReadSingle();
                            }

                            var nv = new Vector3(x, y, z);

                            objBytes.Add("vn " + x.ToString("N5") + " " + y.ToString("N5") + " " + z.ToString("N5") + " ");
                            normalList.Add(nv);
                        }
                    }


                    /*
                     * -----------------
                     * Tangents
                     * -----------------
                     */
                    using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[tangents].VertexDataBlock])))
                    {
                        for (int j = 0; j < mesh.MeshInfo.VertexCount; j++)
                        {
                            br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[tangents].VertexDataBlock] + meshDataInfoList[tangents].Offset, SeekOrigin.Begin);

                            int x = br1.ReadByte();
                            int y = br1.ReadByte();
                            int z = br1.ReadByte();
                            int w = br1.ReadByte();

                            var x1 = x * 2 / 255f - 1f;
                            var y1 = y * 2 / 255f - 1f;
                            var z1 = z * 2 / 255f - 1f;
                            var w1 = w * 2 / 255f - 1f;


                            var nv = new Vector3(x1, y1, z1);

                            tangentList.Add(nv);
                        }
                    }


                    /*
                     * -----------------
                     * Vertex Color
                     * -----------------
                     */
                    using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[colors].VertexDataBlock])))
                    {
                        for (int j = 0; j < mesh.MeshInfo.VertexCount; j++)
                        {
                            br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[colors].VertexDataBlock] + meshDataInfoList[colors].Offset, SeekOrigin.Begin);

                            int a = br1.ReadByte();
                            int r = br1.ReadByte();
                            int g = br1.ReadByte();
                            int b = br1.ReadByte();

                            colorsList.Add(new Color4(r, g, b, a));
                        }
                    }


                    /*
                     * -----------------
                     * Index
                     * -----------------
                     */
                    using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.IndexData)))
                    {
                        for (int j = 0; j < mesh.MeshInfo.IndexCount; j += 3)
                        {
                            int i1 = br1.ReadInt16();
                            int i2 = br1.ReadInt16();
                            int i3 = br1.ReadInt16();

                            objBytes.Add("f " + (i1 + 1) + "/" + (i1 + 1) + "/" + (i1 + 1) + " " + (i2 + 1) + "/" + (i2 + 1) + "/" + (i2 + 1) + " " + (i3 + 1) + "/" + (i3 + 1) + "/" + (i3 + 1) + " ");

                            indexList.Add(i1);
                            indexList.Add(i2);
                            indexList.Add(i3);
                        }
                    }

                    ModelMeshData modelMeshData = new ModelMeshData()
                    {
                        Vertices              = vertexList,
                        Normals               = normalList,
                        TextureCoordinates    = texCoordList,
                        TextureCoordinates2   = texCoordList2,
                        BiTangents            = tangentList,
                        Indices               = indexList,
                        VertexColors          = colorsList,
                        OBJFileData           = objBytes.ToArray(),
                        BoneStrings           = boneStrings,
                        BoneIndices           = modelData.BoneIndicies,
                        BoneTransforms        = boneTransforms,
                        BlendWeights          = blendWeightList,
                        BlendIndices          = blendIndicesList,
                        WeightCounts          = weightCounts,
                        MeshPartList          = mesh.MeshPartList,
                        BlendIndicesArrayList = blendIndicesList2,
                        BlendWeightsArrayList = blendWeightList2,
                        MaterialNum           = mesh.MeshInfo.MaterialNum,
                        MeshPartCount         = mesh.MeshInfo.MeshPartCount,
                        MeshPartOffset        = mesh.MeshInfo.MeshPartOffset
                    };

                    meshList.Add(modelMeshData);
                }
            }
        }
예제 #4
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());
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Parses the MDL file to obtain model information
        /// </summary>
        /// <param name="selectedItem">The currently selected item</param>
        /// <param name="selectedRace">The currently selected race</param>
        /// <param name="selectedBody">The currently selected body</param>
        /// <param name="selectedPart">The currently selected part</param>
        /// <param name="selectedCategory">The items category </param>
        public MDL(ItemData selectedItem, string selectedCategory, string selectedRace, string selectedBody, string selectedPart)
        {
            string itemType  = Helper.GetCategoryType(selectedCategory);
            string MDLFolder = "";

            if (itemType.Equals("weapon") || itemType.Equals("food"))
            {
                if (selectedPart.Equals("Secondary"))
                {
                    MDLFolder = string.Format(Strings.WeapMDLFolder, selectedItem.SecondaryModelID, selectedItem.SecondaryModelBody);
                    MDLFile   = string.Format(Strings.WeapMDLFile, selectedItem.SecondaryModelID, selectedItem.SecondaryModelBody);
                }
                else
                {
                    MDLFolder = string.Format(Strings.WeapMDLFolder, selectedItem.PrimaryModelID, selectedItem.PrimaryModelBody);
                    MDLFile   = string.Format(Strings.WeapMDLFile, selectedItem.PrimaryModelID, selectedItem.PrimaryModelBody);
                }
            }
            else if (itemType.Equals("accessory"))
            {
                MDLFolder = string.Format(Strings.AccMDLFolder, selectedItem.PrimaryModelID);
                MDLFile   = string.Format(Strings.AccMDLFile, selectedRace, selectedItem.PrimaryModelID, Info.slotAbr[selectedCategory]);
            }
            else if (itemType.Equals("character"))
            {
                if (selectedItem.ItemName.Equals(Strings.Body))
                {
                    MDLFolder = string.Format(Strings.BodyMDLFolder, selectedRace, selectedBody.PadLeft(4, '0'));
                    MDLFile   = string.Format(Strings.BodyMDLFile, selectedRace, selectedBody.PadLeft(4, '0'), selectedPart);
                }
                else if (selectedItem.ItemName.Equals(Strings.Face))
                {
                    MDLFolder = string.Format(Strings.FaceMDLFolder, selectedRace, selectedBody.PadLeft(4, '0'));
                    MDLFile   = string.Format(Strings.FaceMDLFile, selectedRace, selectedBody.PadLeft(4, '0'), selectedPart);
                }
                else if (selectedItem.ItemName.Equals(Strings.Hair))
                {
                    MDLFolder = string.Format(Strings.HairMDLFolder, selectedRace, selectedBody.PadLeft(4, '0'));
                    MDLFile   = string.Format(Strings.HairMDLFile, selectedRace, selectedBody.PadLeft(4, '0'), selectedPart);
                }
                else if (selectedItem.ItemName.Equals(Strings.Tail))
                {
                    MDLFolder = string.Format(Strings.TailMDLFolder, selectedRace, selectedBody.PadLeft(4, '0'));
                    MDLFile   = string.Format(Strings.TailMDLFile, selectedRace, selectedBody.PadLeft(4, '0'), selectedPart);
                }
            }
            else if (itemType.Equals("monster"))
            {
                bool isDemiHuman = false;
                if (selectedItem.PrimaryMTRLFolder != null)
                {
                    isDemiHuman = selectedItem.PrimaryMTRLFolder.Contains("demihuman");
                }

                if (isDemiHuman)
                {
                    MDLFolder = string.Format(Strings.DemiMDLFolder, selectedItem.PrimaryModelID.PadLeft(4, '0'), selectedItem.PrimaryModelBody.PadLeft(4, '0'));
                    MDLFile   = string.Format(Strings.DemiMDLFile, selectedItem.PrimaryModelID.PadLeft(4, '0'), selectedItem.PrimaryModelBody, selectedPart);
                }
                else
                {
                    MDLFolder = string.Format(Strings.MonsterMDLFolder, selectedItem.PrimaryModelID.PadLeft(4, '0'), selectedItem.PrimaryModelBody.PadLeft(4, '0'));
                    MDLFile   = string.Format(Strings.MonsterMDLFile, selectedItem.PrimaryModelID.PadLeft(4, '0'), selectedItem.PrimaryModelBody.PadLeft(4, '0'));
                }
            }
            else
            {
                MDLFolder = string.Format(Strings.EquipMDLFolder, selectedItem.PrimaryModelID);

                if (selectedPart.Equals("-"))
                {
                    MDLFile = string.Format(Strings.EquipMDLFile, selectedRace, selectedItem.PrimaryModelID, Info.slotAbr[selectedCategory]);
                }
                else
                {
                    MDLFile = string.Format(Strings.EquipMDLFile, selectedRace, selectedItem.PrimaryModelID, selectedPart);
                }
            }

            fullPath = MDLFolder + "/" + MDLFile;
            int offset = Helper.GetDataOffset(FFCRC.GetHash(MDLFolder), FFCRC.GetHash(MDLFile), Strings.ItemsDat);

            if (offset == 0)
            {
                if (itemType.Equals("weapon"))
                {
                    if (selectedPart.Equals("Secondary"))
                    {
                        MDLFolder = string.Format(Strings.EquipMDLFolder, selectedItem.SecondaryModelID);
                        MDLFile   = string.Format(Strings.EquipMDLFile, "0101", selectedItem.SecondaryModelID, Info.slotAbr[Strings.Hands]);

                        offset = Helper.GetDataOffset(FFCRC.GetHash(MDLFolder), FFCRC.GetHash(MDLFile), Strings.ItemsDat);
                    }
                }
            }

            int datNum = ((offset / 8) & 0x000f) / 2;

            var MDLDatData = Helper.GetType3DecompressedData(offset, datNum, Strings.ItemsDat);

            using (BinaryReader br = new BinaryReader(new MemoryStream(MDLDatData.Item1)))
            {
                // The size of the header + (size of the mesh information block (136 bytes) * the meshes) + padding
                br.BaseStream.Seek(64 + 136 * MDLDatData.Item2 + 4, SeekOrigin.Begin);

                var modelStringCount = br.ReadInt32();
                var stringBlockSize  = br.ReadInt32();
                var stringBlock      = br.ReadBytes(stringBlockSize);

                var unknown = br.ReadBytes(4);

                var totalMeshCount       = br.ReadInt16();
                var attributeStringCount = br.ReadInt16();
                var meshPartsCount       = br.ReadInt16();
                var materialStringCount  = br.ReadInt16();
                var boneStringCount      = br.ReadInt16();
                var boneListCount        = br.ReadInt16();


                //Has something to do with amount of extra vertex data.
                var unknown1 = br.ReadInt16();

                //Has something to do with amount of extra vertex data.
                var unknown2 = br.ReadInt16();


                var unknown3 = br.ReadInt16();

                // Seems to always be 1027
                var unknown4 = br.ReadInt16();


                var unknown5 = br.ReadInt16();
                var unknown6 = br.ReadInt16();

                br.ReadBytes(10);

                var unknown7 = br.ReadInt16();

                br.ReadBytes(16);

                using (BinaryReader br1 = new BinaryReader(new MemoryStream(stringBlock)))
                {
                    br1.BaseStream.Seek(0, SeekOrigin.Begin);

                    for (int i = 0; i < attributeStringCount; i++)
                    {
                        byte        a;
                        List <byte> atrName = new List <byte>();
                        while ((a = br1.ReadByte()) != 0)
                        {
                            atrName.Add(a);
                        }
                        string atr = Encoding.ASCII.GetString(atrName.ToArray());
                        atr = atr.Replace("\0", "");

                        modelData.Attributes.Add(atr);
                        atrStrings.Add(atr);
                    }

                    for (int i = 0; i < boneStringCount; i++)
                    {
                        byte        b;
                        List <byte> boneName = new List <byte>();
                        while ((b = br1.ReadByte()) != 0)
                        {
                            boneName.Add(b);
                        }
                        string bone = Encoding.ASCII.GetString(boneName.ToArray());
                        bone = bone.Replace("\0", "");

                        modelData.Bones.Add(bone);
                        boneStrings.Add(bone);
                    }

                    for (int i = 0; i < materialStringCount; i++)
                    {
                        byte        b;
                        List <byte> name = new List <byte>();
                        while ((b = br1.ReadByte()) != 0)
                        {
                            name.Add(b);
                        }
                        string material = Encoding.ASCII.GetString(name.ToArray());
                        material = material.Replace("\0", "");

                        modelData.Materials.Add(material);
                        materialStrings.Add(material);
                    }
                }

                byte[] unknown5Bytes = br.ReadBytes(32 * unknown5);

                for (int i = 0; i < 3; i++)
                {
                    LevelOfDetail LoD = new LevelOfDetail();
                    LoD.MeshOffset = br.ReadInt16();
                    LoD.MeshCount  = br.ReadInt16();

                    br.ReadBytes(40);

                    LoD.VertexDataSize = br.ReadInt32();
                    LoD.IndexDataSize  = br.ReadInt32();
                    LoD.VertexOffset   = br.ReadInt32();
                    LoD.IndexOffset    = br.ReadInt32();

                    modelData.LoD.Add(LoD);
                }

                var savePos      = br.BaseStream.Position;
                var lodStructPos = 68;

                for (int i = 0; i < modelData.LoD.Count; i++)
                {
                    List <MeshDataInfo> meshInfoList = new List <MeshDataInfo>();

                    for (int j = 0; j < modelData.LoD[i].MeshCount; j++)
                    {
                        modelData.LoD[i].MeshList.Add(new Mesh());
                        meshInfoList.Clear();

                        br.BaseStream.Seek((j * 136) + lodStructPos, SeekOrigin.Begin);
                        var dataBlockNum = br.ReadByte();

                        while (dataBlockNum != 255)
                        {
                            MeshDataInfo meshInfo = new MeshDataInfo()
                            {
                                VertexDataBlock = dataBlockNum,
                                Offset          = br.ReadByte(),
                                DataType        = br.ReadByte(),
                                UseType         = br.ReadByte()
                            };

                            meshInfoList.Add(meshInfo);

                            br.ReadBytes(4);

                            dataBlockNum = br.ReadByte();
                        }

                        modelData.LoD[i].MeshList[j].MeshDataInfoList = meshInfoList.ToArray();
                    }
                    lodStructPos += 136 * modelData.LoD[i].MeshCount;
                }

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

                for (int x = 0; x < modelData.LoD.Count; x++)
                {
                    for (int i = 0; i < modelData.LoD[x].MeshCount; i++)
                    {
                        MeshInfo meshInfo = new MeshInfo()
                        {
                            VertexCount     = br.ReadInt32(),
                            IndexCount      = br.ReadInt32(),
                            MaterialNum     = br.ReadInt16(),
                            MeshPartOffset  = br.ReadInt16(),
                            MeshPartCount   = br.ReadInt16(),
                            BoneListIndex   = br.ReadInt16(),
                            IndexDataOffset = br.ReadInt32()
                        };

                        modelData.LoD[x].MeshList[i].MaterialId = meshInfo.MaterialNum;
                        var typeChar = materialStrings[meshInfo.MaterialNum][4].ToString() + materialStrings[meshInfo.MaterialNum][9].ToString();

                        modelData.LoD[x].MeshList[i].BoneListIndex = meshInfo.BoneListIndex;
                        if (typeChar.Equals("cb"))
                        {
                            modelData.LoD[x].MeshList[i].IsBody = true;
                        }

                        for (int j = 0; j < 3; j++)
                        {
                            meshInfo.VertexDataOffsets.Add(br.ReadInt32());
                        }

                        for (int k = 0; k < 3; k++)
                        {
                            meshInfo.VertexSizes.Add(br.ReadByte());
                        }

                        meshInfo.VertexDataBlockCount = br.ReadByte();

                        modelData.LoD[x].MeshList[i].MeshInfo = meshInfo;
                    }
                }

                byte[] attributeOffsetBytes = br.ReadBytes(attributeStringCount * 4);
                br.ReadBytes(unknown6 * 20);

                for (int i = 0; i < modelData.LoD.Count; i++)
                {
                    foreach (var mesh in modelData.LoD[i].MeshList)
                    {
                        for (int j = 0; j < mesh.MeshInfo.MeshPartCount; j++)
                        {
                            MeshPart meshPart = new MeshPart()
                            {
                                IndexOffset = br.ReadInt32(),
                                IndexCount  = br.ReadInt32(),
                                Attributes  = br.ReadInt32(),
                                BoneOffset  = br.ReadInt16(),
                                BoneCount   = br.ReadInt16()
                            };

                            mesh.MeshPartList.Add(meshPart);
                        }
                    }
                }

                br.ReadBytes(unknown7 * 12);
                br.ReadBytes(materialStringCount * 4);

                List <int> boneIncrements = new List <int>();

                // Loop through the increments and save their data.
                for (int i = 0; i < boneStringCount; i++)
                {
                    int increment = br.ReadInt32();
                    boneIncrements.Add(increment);
                }


                for (int i = 0; i < boneListCount; i++)
                {
                    Bones bones = new Bones();

                    for (int j = 0; j < 64; j++)
                    {
                        bones.BoneData.Add(br.ReadInt16());
                    }

                    bones.BoneCount = br.ReadInt32();

                    modelData.BoneSet.Add(bones);
                }

                //br.ReadBytes(unknown1 * 16);

                Dictionary <int, int>         indexMin      = new Dictionary <int, int>();
                Dictionary <int, List <int> > extraIndices  = new Dictionary <int, List <int> >();
                Dictionary <int, List <int> > extraIndices2 = new Dictionary <int, List <int> >();
                var indexCounts = new List <List <ExtraIndex> >();

                // One for each LoD level.
                indexCounts.Add(new List <ExtraIndex>());
                indexCounts.Add(new List <ExtraIndex>());
                indexCounts.Add(new List <ExtraIndex>());

                var pCounts = new int[3];

                if (unknown1 > 0)
                {
                    for (int i = 0; i < unknown1; i++)
                    {
                        //not sure
                        br.ReadBytes(4);

                        //LoD[0] Extra Data Index
                        var p1 = br.ReadUInt16();

                        //LoD[1] Extra Data Index
                        var p2 = br.ReadUInt16();

                        //LoD[2] Extra Data Index
                        var p3 = br.ReadUInt16();


                        //LoD[0] Extra Data Part Count
                        var p1n = br.ReadUInt16();
                        pCounts[0] += p1n;

                        //LoD[1] Extra Data Part Count
                        var p2n = br.ReadUInt16();
                        pCounts[1] += p2n;

                        //LoD[2] Extra Data Part Count
                        var p3n = br.ReadUInt16();
                        pCounts[2] += p3n;
                    }
                }

                Dictionary <int, int> indexLoc = new Dictionary <int, int>();

                if (unknown1 > 0)
                {
                    for (int i = 0; i < modelData.LoD[LoDViewLevel].MeshCount; i++)
                    {
                        var ido = modelData.LoD[LoDViewLevel].MeshList[i].MeshInfo.IndexDataOffset;

                        if (!indexLoc.ContainsKey(ido))
                        {
                            indexLoc.Add(ido, i);
                        }
                    }
                }


                var totalMaskCounts = new int[3];
                Dictionary <int, int> totalExtraCounts = new Dictionary <int, int>();
                if (unknown2 > 0)
                {
                    for (int x = 0; x < pCounts.Length; x++)
                    {
                        for (int i = 0; i < pCounts[x]; i++)
                        {
                            //Index Offset Start
                            var m1 = br.ReadInt32();

                            //index count
                            var mCount = br.ReadInt32();

                            //index offset in unk3
                            var mOffset = br.ReadInt32();

                            var iLoc = 0;
                            if (indexLoc.ContainsKey(m1))
                            {
                                iLoc = indexLoc[m1];
                            }

                            indexCounts[x].Add(new ExtraIndex()
                            {
                                IndexLocation = iLoc, IndexCount = mCount
                            });
                            totalMaskCounts[x] += mCount;
                        }
                    }
                }


                if (unknown3 > 0)
                {
                    //var unk3Remainder = (unknown3 * 4) - (totalLoD0MaskCount * 4);
                    var c = 0;
                    for (int l = 0; l < indexCounts.Count; l++)
                    {
                        foreach (var ic in indexCounts[l])
                        {
                            HashSet <int> mIndexList = new HashSet <int>();

                            for (int i = 0; i < ic.IndexCount; i++)
                            {
                                //index its replacing? attatched to?
                                var oIndex = br.ReadUInt16();

                                //extra index following last equipment index
                                var mIndex = br.ReadUInt16();

                                if (l == LoDViewLevel)
                                {
                                    mIndexList.Add(mIndex);

                                    if (extraIndices.ContainsKey(ic.IndexLocation))
                                    {
                                        extraIndices[ic.IndexLocation].Add(mIndex);
                                        extraIndices2[ic.IndexLocation].Add(oIndex);
                                    }
                                    else
                                    {
                                        extraIndices.Add(ic.IndexLocation, new List <int>()
                                        {
                                            mIndex
                                        });
                                        extraIndices2.Add(ic.IndexLocation, new List <int>()
                                        {
                                            oIndex
                                        });
                                    }
                                }
                            }

                            if (l == LoDViewLevel)
                            {
                                if (totalExtraCounts.ContainsKey(ic.IndexLocation))
                                {
                                    totalExtraCounts[ic.IndexLocation] += mIndexList.Count;
                                }
                                else
                                {
                                    totalExtraCounts.Add(ic.IndexLocation, mIndexList.Count);
                                }
                            }
                            c++;
                        }
                    }

                    //the rest of unk3
                    //br.ReadBytes(unk3Remainder);

                    foreach (var ei in extraIndices)
                    {
                        indexMin.Add(ei.Key, ei.Value.Min());
                    }

                    extraIndexData.indexCounts      = indexCounts[LoDViewLevel];
                    extraIndexData.indexMin         = indexMin;
                    extraIndexData.totalExtraCounts = totalExtraCounts;
                    extraIndexData.extraIndices     = extraIndices;
                    extraIndexData.extraIndices2    = extraIndices2;

                    modelData.ExtraData = extraIndexData;
                }

                //br.ReadBytes(unknown3 * 4);

                var boneIndexSize = br.ReadInt32();

                for (int i = 0; i < boneIndexSize / 2; i++)
                {
                    modelData.BoneIndicies.Add(br.ReadUInt16());
                }

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

                for (int i = 0; i < 4; i++)
                {
                    ModelMaterial.BoundingBox boundingBox = new ModelMaterial.BoundingBox();
                    for (int j = 0; j < 4; j++)
                    {
                        boundingBox.PointA.Add(br.ReadSingle());
                    }
                    for (int k = 0; k < 4; k++)
                    {
                        boundingBox.PointB.Add(br.ReadSingle());
                    }

                    modelData.BoundingBoxes.Add(boundingBox);
                }

                //float4x4
                for (int i = 0; i < boneStringCount; i++)
                {
                    string boneName = boneStrings[i];

                    Vector4 transform1 = new Vector4();
                    Vector4 transform2 = new Vector4();

                    transform1.X = br.ReadSingle();
                    transform1.Y = br.ReadSingle();
                    transform1.Z = br.ReadSingle();
                    transform1.W = br.ReadSingle();

                    transform2.X = br.ReadSingle();
                    transform2.Y = br.ReadSingle();
                    transform2.Z = br.ReadSingle();
                    transform2.W = br.ReadSingle();

                    boneTransforms.Add(transform1.X);
                    boneTransforms.Add(transform1.Y);
                    boneTransforms.Add(transform1.Z);
                    boneTransforms.Add(transform1.W);

                    boneTransforms.Add(transform2.X);
                    boneTransforms.Add(transform2.Y);
                    boneTransforms.Add(transform2.Z);
                    boneTransforms.Add(transform2.W);
                }

                for (int i = 0; i < 3; i++)
                {
                    for (int j = 0; j < modelData.LoD[i].MeshCount; j++)
                    {
                        Mesh mesh = modelData.LoD[i].MeshList[j];

                        for (int k = 0; k < mesh.MeshInfo.VertexDataBlockCount; k++)
                        {
                            br.BaseStream.Seek(modelData.LoD[i].VertexOffset + mesh.MeshInfo.VertexDataOffsets[k], SeekOrigin.Begin);

                            mesh.MeshVertexData.Add(br.ReadBytes(mesh.MeshInfo.VertexSizes[k] * mesh.MeshInfo.VertexCount));
                        }

                        br.BaseStream.Seek(modelData.LoD[i].IndexOffset + (mesh.MeshInfo.IndexDataOffset * 2), SeekOrigin.Begin);

                        mesh.IndexData = br.ReadBytes(2 * mesh.MeshInfo.IndexCount);
                    }
                }



                int vertex = 0, coordinates = 0, normals = 0, tangents = 0, colors = 0, blendWeights = 0, blendIndices = 0;

                for (int i = 0; i < modelData.LoD[LoDViewLevel].MeshCount; i++)
                {
                    objBytes.Clear();

                    var vertexList        = new Vector3Collection();
                    var texCoordList      = new Vector2Collection();
                    var texCoordList2     = new Vector2Collection();
                    var normalList        = new Vector3Collection();
                    var tangentList       = new Vector3Collection();
                    var colorsList        = new Color4Collection();
                    var indexList         = new IntCollection();
                    var blendWeightList   = new List <float>();
                    var blendWeightList2  = new List <float[]>();
                    var blendIndicesList  = new List <int>();
                    var blendIndicesList2 = new List <int[]>();
                    var weightCounts      = new List <int>();
                    var extraVerts        = new HashSet <Vector3>();
                    Dictionary <int, Vector3> extraVertDict = new Dictionary <int, Vector3>();


                    Mesh mesh = modelData.LoD[LoDViewLevel].MeshList[i];

                    MeshDataInfo[] meshDataInfoList = mesh.MeshDataInfoList;

                    int c = 0;
                    foreach (var meshDataInfo in meshDataInfoList)
                    {
                        if (meshDataInfo.UseType == 0)
                        {
                            vertex = c;
                        }
                        else if (meshDataInfo.UseType == 1)
                        {
                            blendWeights = c;
                        }
                        else if (meshDataInfo.UseType == 2)
                        {
                            blendIndices = c;
                        }
                        else if (meshDataInfo.UseType == 3)
                        {
                            normals = c;
                        }
                        else if (meshDataInfo.UseType == 4)
                        {
                            coordinates = c;
                        }
                        else if (meshDataInfo.UseType == 6)
                        {
                            tangents = c;
                        }
                        else if (meshDataInfo.UseType == 7)
                        {
                            colors = c;
                        }

                        c++;
                    }

                    /*
                     * -----------------
                     * Vertex
                     * -----------------
                     */

                    // Only actually read the buffers if they have data in them.
                    if (mesh.MeshVertexData.Count > 0)
                    {
                        using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[vertex].VertexDataBlock])))
                        {
                            for (int j = 0; j < mesh.MeshInfo.VertexCount; j++)
                            {
                                br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[vertex].VertexDataBlock] + meshDataInfoList[vertex].Offset, SeekOrigin.Begin);

                                Vector3 vVector = new Vector3();
                                if (meshDataInfoList[vertex].DataType == 13 || meshDataInfoList[vertex].DataType == 14)
                                {
                                    System.Half h1 = System.Half.ToHalf(br1.ReadUInt16());
                                    System.Half h2 = System.Half.ToHalf(br1.ReadUInt16());
                                    System.Half h3 = System.Half.ToHalf(br1.ReadUInt16());

                                    float x = HalfHelper.HalfToSingle(h1);
                                    float y = HalfHelper.HalfToSingle(h2);
                                    float z = HalfHelper.HalfToSingle(h3);

                                    vVector = new Vector3(x, y, z);
                                    objBytes.Add("v " + x.ToString("N5") + " " + y.ToString("N5") + " " + z.ToString("N5") + " ");
                                }
                                else if (meshDataInfoList[vertex].DataType == 2)
                                {
                                    var x = BitConverter.ToSingle(br1.ReadBytes(4), 0);
                                    var y = BitConverter.ToSingle(br1.ReadBytes(4), 0);
                                    var z = BitConverter.ToSingle(br1.ReadBytes(4), 0);

                                    vVector = new Vector3(x, y, z);
                                    objBytes.Add("v " + x.ToString("N5") + " " + y.ToString("N5") + " " + z.ToString("N5") + " ");
                                }

                                vertexList.Add(vVector);
                            }
                        }


                        /*
                         * -----------------
                         * Blend Weight
                         * -----------------
                         */
                        using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[blendWeights].VertexDataBlock])))
                        {
                            for (int j = 0; j < mesh.MeshInfo.VertexCount; j++)
                            {
                                br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[blendWeights].VertexDataBlock] + meshDataInfoList[blendWeights].Offset, SeekOrigin.Begin);

                                float x = br1.ReadByte() / 255.0f;
                                float y = br1.ReadByte() / 255.0f;
                                float z = br1.ReadByte() / 255.0f;
                                float w = br1.ReadByte() / 255.0f;

                                int count = 0;
                                if (x != 0)
                                {
                                    blendWeightList.Add(x);
                                    count++;

                                    if (y != 0)
                                    {
                                        blendWeightList.Add(y);
                                        count++;

                                        if (z != 0)
                                        {
                                            blendWeightList.Add(z);
                                            count++;

                                            if (w != 0)
                                            {
                                                blendWeightList.Add(w);
                                                count++;
                                            }
                                        }
                                    }
                                }

                                if (count == 1)
                                {
                                    blendWeightList2.Add(new float[] { x });
                                }
                                else if (count == 2)
                                {
                                    blendWeightList2.Add(new float[] { x, y });
                                }
                                else if (count == 3)
                                {
                                    blendWeightList2.Add(new float[] { x, y, z });
                                }
                                else if (count == 4)
                                {
                                    blendWeightList2.Add(new float[] { x, y, z, w });
                                }

                                weightCounts.Add(count);
                            }
                        }


                        /*
                         * -----------------
                         * Blend Index
                         * -----------------
                         */
                        using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[blendIndices].VertexDataBlock])))
                        {
                            for (int j = 0; j < mesh.MeshInfo.VertexCount; j++)
                            {
                                br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[blendIndices].VertexDataBlock] + meshDataInfoList[blendIndices].Offset, SeekOrigin.Begin);

                                int x = br1.ReadByte();
                                int y = br1.ReadByte();
                                int z = br1.ReadByte();
                                int w = br1.ReadByte();

                                if (weightCounts[j] == 1)
                                {
                                    blendIndicesList.Add(x);
                                    blendIndicesList2.Add(new int[] { x });
                                }
                                else if (weightCounts[j] == 2)
                                {
                                    blendIndicesList.Add(x);
                                    blendIndicesList.Add(y);
                                    blendIndicesList2.Add(new int[] { x, y });
                                }
                                else if (weightCounts[j] == 3)
                                {
                                    blendIndicesList.Add(x);
                                    blendIndicesList.Add(y);
                                    blendIndicesList.Add(z);
                                    blendIndicesList2.Add(new int[] { x, y, z });
                                }
                                else if (weightCounts[j] == 4)
                                {
                                    blendIndicesList.Add(x);
                                    blendIndicesList.Add(y);
                                    blendIndicesList.Add(z);
                                    blendIndicesList.Add(w);
                                    blendIndicesList2.Add(new int[] { x, y, z, w });
                                }
                            }
                        }

                        /*
                         * -----------------
                         * Texture Coordinates
                         * -----------------
                         */
                        using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[coordinates].VertexDataBlock])))
                        {
                            for (int j = 0; j < mesh.MeshInfo.VertexCount; j++)
                            {
                                br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[coordinates].VertexDataBlock] + meshDataInfoList[coordinates].Offset, SeekOrigin.Begin);

                                float x = 0;
                                float y = 0;
                                float z = 0;
                                float w = 0;
                                if (meshDataInfoList[coordinates].DataType == 13 || meshDataInfoList[coordinates].DataType == 14)
                                {
                                    var sx = br1.ReadUInt16();
                                    var sy = br1.ReadUInt16();
                                    var sz = br1.ReadUInt16();
                                    var sw = br1.ReadUInt16();

                                    var h1 = new SharpDX.Half(sx);
                                    var h2 = new SharpDX.Half(sy);
                                    var h3 = new SharpDX.Half(sz);
                                    var h4 = new SharpDX.Half(sw);

                                    x = h1;
                                    y = h2;
                                    z = h3;
                                    w = h4;
                                }
                                else if (meshDataInfoList[coordinates].DataType == 1)
                                {
                                    x = br1.ReadSingle();
                                    y = br1.ReadSingle();
                                }
                                else
                                {
                                    x = br1.ReadSingle();
                                    y = br1.ReadSingle();
                                    z = br1.ReadSingle();
                                    w = br1.ReadSingle();
                                }


                                var ox = x - Math.Truncate(x);
                                var oy = y - Math.Truncate(y);

                                objBytes.Add("vt " + ox.ToString("N5") + " " + (1 - y).ToString("N5") + " ");
                                texCoordList.Add(new Vector2(x, y));
                                texCoordList2.Add(new Vector2(z, w));
                            }
                        }



                        /*
                         * -----------------
                         * Normals
                         * -----------------
                         */
                        using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[normals].VertexDataBlock])))
                        {
                            for (int j = 0; j < mesh.MeshInfo.VertexCount; j++)
                            {
                                br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[normals].VertexDataBlock] + meshDataInfoList[normals].Offset, SeekOrigin.Begin);

                                float x = 0;
                                float y = 0;
                                float z = 0;
                                float w = 0;

                                if (meshDataInfoList[normals].DataType == 13 || meshDataInfoList[normals].DataType == 14)
                                {
                                    System.Half h1 = System.Half.ToHalf(br1.ReadUInt16());
                                    System.Half h2 = System.Half.ToHalf(br1.ReadUInt16());
                                    System.Half h3 = System.Half.ToHalf(br1.ReadUInt16());
                                    System.Half h4 = System.Half.ToHalf(br1.ReadUInt16());

                                    x = HalfHelper.HalfToSingle(h1);
                                    y = HalfHelper.HalfToSingle(h2);
                                    z = HalfHelper.HalfToSingle(h3);
                                    w = HalfHelper.HalfToSingle(h4);
                                }
                                else
                                {
                                    x = br1.ReadSingle();
                                    y = br1.ReadSingle();
                                    z = br1.ReadSingle();
                                }

                                var nv = new Vector3(x, y, z);

                                objBytes.Add("vn " + x.ToString("N5") + " " + y.ToString("N5") + " " + z.ToString("N5") + " ");
                                normalList.Add(nv);
                            }
                        }


                        /*
                         * -----------------
                         * Tangents
                         * -----------------
                         */
                        using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[tangents].VertexDataBlock])))
                        {
                            for (int j = 0; j < mesh.MeshInfo.VertexCount; j++)
                            {
                                br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[tangents].VertexDataBlock] + meshDataInfoList[tangents].Offset, SeekOrigin.Begin);

                                int x = br1.ReadByte();
                                int y = br1.ReadByte();
                                int z = br1.ReadByte();
                                int w = br1.ReadByte();

                                var x1 = x * 2 / 255f - 1f;
                                var y1 = y * 2 / 255f - 1f;
                                var z1 = z * 2 / 255f - 1f;
                                var w1 = w * 2 / 255f - 1f;


                                var nv = new Vector3(x1, y1, z1);

                                tangentList.Add(nv);
                            }
                        }


                        /*
                         * -----------------
                         * Vertex Color
                         * -----------------
                         */
                        using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[colors].VertexDataBlock])))
                        {
                            for (int j = 0; j < mesh.MeshInfo.VertexCount; j++)
                            {
                                br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[colors].VertexDataBlock] + meshDataInfoList[colors].Offset, SeekOrigin.Begin);

                                int a = br1.ReadByte();
                                int r = br1.ReadByte();
                                int g = br1.ReadByte();
                                int b = br1.ReadByte();

                                colorsList.Add(new Color4(r, g, b, a));
                            }
                        }
                    }


                    /*
                     * -----------------
                     * Index
                     * -----------------
                     */
                    using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.IndexData)))
                    {
                        for (int j = 0; j < mesh.MeshInfo.IndexCount; j += 3)
                        {
                            int i1 = br1.ReadUInt16();
                            int i2 = br1.ReadUInt16();
                            int i3 = br1.ReadUInt16();

                            objBytes.Add("f " + (i1 + 1) + "/" + (i1 + 1) + "/" + (i1 + 1) + " " + (i2 + 1) + "/" + (i2 + 1) + "/" + (i2 + 1) + " " + (i3 + 1) + "/" + (i3 + 1) + "/" + (i3 + 1) + " ");

                            indexList.Add(i1);
                            indexList.Add(i2);
                            indexList.Add(i3);
                        }
                    }

                    ModelMeshData modelMeshData = new ModelMeshData()
                    {
                        Vertices              = vertexList,
                        Normals               = normalList,
                        TextureCoordinates    = texCoordList,
                        TextureCoordinates2   = texCoordList2,
                        BiTangents            = tangentList,
                        Indices               = indexList,
                        VertexColors          = colorsList,
                        OBJFileData           = objBytes.ToArray(),
                        BoneStrings           = boneStrings,
                        AttributeStrings      = atrStrings,
                        BoneIndices           = modelData.BoneIndicies,
                        BoneTransforms        = boneTransforms,
                        BlendWeights          = blendWeightList,
                        BlendIndices          = blendIndicesList,
                        WeightCounts          = weightCounts,
                        MeshPartList          = mesh.MeshPartList,
                        BlendIndicesArrayList = blendIndicesList2,
                        BlendWeightsArrayList = blendWeightList2,
                        MaterialNum           = mesh.MeshInfo.MaterialNum,
                        MeshPartCount         = mesh.MeshInfo.MeshPartCount,
                        MeshPartOffset        = mesh.MeshInfo.MeshPartOffset
                    };

                    if (extraIndices2.ContainsKey(i))
                    {
                        foreach (var id in extraIndices2[i])
                        {
                            if (!extraVertDict.ContainsKey(id))
                            {
                                if (modelMeshData.Indices.Count >= id)
                                {
                                    var v = 0;
                                    try
                                    {
                                        v = modelMeshData.Indices[id];
                                    }
                                    catch
                                    {
                                        v = 0;
                                    }

                                    extraVertDict.Add(id, modelMeshData.Vertices[v]);
                                }
                                else
                                {
                                    //new Thread(() => MessageBox.Show("There was an error reading the models extra data.\n\n" +
                                    //    "Mesh " + i + " Index " + id + "\n\n" +
                                    //    "This is likely caused by parts of a mesh being deleted and may cause crashes in-game.\n\n" +
                                    //    "Consider using Advanced Import to Fix or Disable Hiding for the above mesh.",
                                    //    "Extra Data Warning" + Info.appVersion, MessageBoxButtons.OK, MessageBoxIcon.Warning)).Start();
                                    new Thread(() => MessageBox.Show(string.Format(Dialogs.MDLExtraDataWarning, i, id),
                                                                     Dialogs.ExtraDataWarning + Info.appVersion, MessageBoxButtons.OK, MessageBoxIcon.Warning)).Start();

                                    break;
                                }
                            }
                        }
                    }


                    mesh.extraVertDict = extraVertDict;

                    meshList.Add(modelMeshData);
                }
            }
        }
        private static float HalfToFloat(BinaryReaderEx src)
        {
            ushort val = src.ReadUInt16(Endianness.BigEndian);

            return(HalfHelper.HalfToSingle(val));
        }
예제 #7
0
 /// <summary>
 /// Write UVVector2 as floats.
 /// </summary>
 public void WriteToFile(BinaryWriter writer)
 {
     writer.Write(HalfHelper.HalfToSingle(X));
     writer.Write(HalfHelper.HalfToSingle(Y));
     // writer.Write((Half)1f-Y);
 }
예제 #8
0
        /// <summary>
        /// Parses the MDL file to obtain model information
        /// </summary>
        /// <param name="selectedItem">The currently selected item</param>
        /// <param name="selectedRace">The currently selected race</param>
        /// <param name="selectedBody">The currently selected body</param>
        /// <param name="selectedPart">The currently selected part</param>
        /// <param name="selectedCategory">The items category </param>
        public MDL(ItemData selectedItem, string selectedCategory, string selectedRace, string selectedBody, string selectedPart)
        {
            string itemType  = Helper.GetCategoryType(selectedCategory);
            string MDLFolder = "";

            if (itemType.Equals("weapon") || itemType.Equals("food"))
            {
                if (selectedPart.Equals("Secondary"))
                {
                    MDLFolder = string.Format(Strings.WeapMDLFolder, selectedItem.SecondaryModelID, selectedItem.SecondaryModelBody);
                    MDLFile   = string.Format(Strings.WeapMDLFile, selectedItem.SecondaryModelID, selectedItem.SecondaryModelBody);
                }
                else
                {
                    MDLFolder = string.Format(Strings.WeapMDLFolder, selectedItem.PrimaryModelID, selectedItem.PrimaryModelBody);
                    MDLFile   = string.Format(Strings.WeapMDLFile, selectedItem.PrimaryModelID, selectedItem.PrimaryModelBody);
                }
            }
            else if (itemType.Equals("accessory"))
            {
                MDLFolder = string.Format(Strings.AccMDLFolder, selectedItem.PrimaryModelID);
                MDLFile   = string.Format(Strings.AccMDLFile, selectedRace, selectedItem.PrimaryModelID, Info.slotAbr[selectedCategory]);
            }
            else if (itemType.Equals("character"))
            {
                if (selectedItem.ItemName.Equals(Strings.Body))
                {
                    MDLFolder = string.Format(Strings.BodyMDLFolder, selectedRace, selectedBody.PadLeft(4, '0'));
                    MDLFile   = string.Format(Strings.BodyMDLFile, selectedRace, selectedBody.PadLeft(4, '0'), selectedPart);
                }
                else if (selectedItem.ItemName.Equals(Strings.Face))
                {
                    MDLFolder = string.Format(Strings.FaceMDLFolder, selectedRace, selectedBody.PadLeft(4, '0'));
                    MDLFile   = string.Format(Strings.FaceMDLFile, selectedRace, selectedBody.PadLeft(4, '0'), selectedPart);
                }
                else if (selectedItem.ItemName.Equals(Strings.Hair))
                {
                    MDLFolder = string.Format(Strings.HairMDLFolder, selectedRace, selectedBody.PadLeft(4, '0'));
                    MDLFile   = string.Format(Strings.HairMDLFile, selectedRace, selectedBody.PadLeft(4, '0'), selectedPart);
                }
                else if (selectedItem.ItemName.Equals(Strings.Tail))
                {
                    MDLFolder = string.Format(Strings.TailMDLFolder, selectedRace, selectedBody.PadLeft(4, '0'));
                    MDLFile   = string.Format(Strings.TailMDLFile, selectedRace, selectedBody.PadLeft(4, '0'), selectedPart);
                }
            }
            else if (itemType.Equals("monster"))
            {
                bool isDemiHuman = false;
                if (selectedItem.PrimaryMTRLFolder != null)
                {
                    isDemiHuman = selectedItem.PrimaryMTRLFolder.Contains("demihuman");
                }

                string ID   = "";
                string body = "";

                if (selectedCategory.Equals(Strings.Pets))
                {
                    ID   = Info.petID[selectedItem.ItemName];
                    body = "0001";
                }
                else
                {
                    ID   = selectedItem.PrimaryModelID.PadLeft(4, '0');
                    body = selectedItem.PrimaryModelBody;
                }

                if (isDemiHuman)
                {
                    MDLFolder = string.Format(Strings.DemiMDLFolder, ID, body);
                    MDLFile   = string.Format(Strings.DemiMDLFile, ID, body, selectedPart);
                }
                else
                {
                    MDLFolder = string.Format(Strings.MonsterMDLFolder, ID, body);
                    MDLFile   = string.Format(Strings.MonsterMDLFile, ID, body);
                }
            }
            else
            {
                MDLFolder = string.Format(Strings.EquipMDLFolder, selectedItem.PrimaryModelID);
                MDLFile   = string.Format(Strings.EquipMDLFile, selectedRace, selectedItem.PrimaryModelID, Info.slotAbr[selectedCategory]);
            }

            int offset = Helper.GetItemOffset(FFCRC.GetHash(MDLFolder), FFCRC.GetHash(MDLFile));

            int datNum = ((offset / 8) & 0x000f) / 2;

            offset = Helper.OffsetCorrection(datNum, offset);

            var MDLDatData = Helper.GetType3DecompressedData(offset, datNum);

            using (BinaryReader br = new BinaryReader(new MemoryStream(MDLDatData.Item1)))
            {
                ModelData modelData = new ModelData();

                // The size of the header + (size of the mesh information block (136 bytes) * the number of meshes) + padding
                br.BaseStream.Seek(64 + 136 * MDLDatData.Item2 + 4, SeekOrigin.Begin);

                var modelStringCount = br.ReadInt32();
                var stringBlockSize  = br.ReadInt32();
                var stringBlock      = br.ReadBytes(stringBlockSize);

                var unknown = br.ReadBytes(4);

                var totalMeshCount       = br.ReadInt16();
                var attributeStringCount = br.ReadInt16();
                var meshPartsCount       = br.ReadInt16();
                var materialStringCount  = br.ReadInt16();
                var boneStringCount      = br.ReadInt16();
                var boneListCount        = br.ReadInt16();

                var unknown1 = br.ReadInt16();
                var unknown2 = br.ReadInt16();
                var unknown3 = br.ReadInt16();
                var unknown4 = br.ReadInt16();
                var unknown5 = br.ReadInt16();
                var unknown6 = br.ReadInt16();

                br.ReadBytes(10);

                var unknown7 = br.ReadInt16();

                br.ReadBytes(16);

                using (BinaryReader br1 = new BinaryReader(new MemoryStream(stringBlock)))
                {
                    br1.BaseStream.Seek(0, SeekOrigin.Begin);

                    for (int i = 0; i < attributeStringCount; i++)
                    {
                        while (br1.ReadByte() != 0)
                        {
                            //extract each atribute string here
                        }
                    }

                    for (int i = 0; i < boneStringCount; i++)
                    {
                        while (br1.ReadByte() != 0)
                        {
                            //extact each bone string here
                        }
                    }

                    for (int i = 0; i < materialStringCount; i++)
                    {
                        byte        b;
                        List <byte> name = new List <byte>();
                        while ((b = br1.ReadByte()) != 0)
                        {
                            name.Add(b);
                        }
                        string material = Encoding.ASCII.GetString(name.ToArray());
                        material = material.Replace("\0", "");

                        materialStrings.Add(material);
                    }
                }

                br.ReadBytes(32 * unknown5);

                for (int i = 0; i < 3; i++)
                {
                    LevelOfDetail LoD = new LevelOfDetail();
                    LoD.MeshOffset = br.ReadInt16();
                    LoD.MeshCount  = br.ReadInt16();

                    br.ReadBytes(40);

                    LoD.VertexDataSize = br.ReadInt32();
                    LoD.IndexDataSize  = br.ReadInt32();
                    LoD.VertexOffset   = br.ReadInt32();
                    LoD.IndexOffset    = br.ReadInt32();

                    modelData.LoD.Add(LoD);
                }

                var savePos = br.BaseStream.Position;

                for (int i = 0; i < modelData.LoD.Count; i++)
                {
                    List <MeshDataInfo> meshInfoList = new List <MeshDataInfo>();

                    for (int j = 0; j < modelData.LoD[i].MeshCount; j++)
                    {
                        modelData.LoD[i].MeshList.Add(new Mesh());
                        meshInfoList.Clear();

                        br.BaseStream.Seek((i * 136) + 68, SeekOrigin.Begin);
                        var dataBlockNum = br.ReadByte();

                        while (dataBlockNum != 255)
                        {
                            MeshDataInfo meshInfo = new MeshDataInfo()
                            {
                                VertexDataBlock = dataBlockNum,
                                Offset          = br.ReadByte(),
                                DataType        = br.ReadByte(),
                                UseType         = br.ReadByte()
                            };

                            meshInfoList.Add(meshInfo);

                            br.ReadBytes(4);

                            dataBlockNum = br.ReadByte();
                        }

                        modelData.LoD[i].MeshList[j].MeshDataInfoList = meshInfoList.ToArray();
                    }
                }

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

                for (int x = 0; x < modelData.LoD.Count; x++)
                {
                    for (int i = 0; i < modelData.LoD[x].MeshCount; i++)
                    {
                        MeshInfo meshInfo = new MeshInfo()
                        {
                            VertexCount     = br.ReadInt32(),
                            IndexCount      = br.ReadInt32(),
                            MaterialNum     = br.ReadInt16(),
                            MeshPartOffset  = br.ReadInt16(),
                            MeshPartCount   = br.ReadInt16(),
                            BoneListIndex   = br.ReadInt16(),
                            IndexDataOffset = br.ReadInt32()
                        };

                        for (int j = 0; j < 3; j++)
                        {
                            meshInfo.VertexDataOffsets.Add(br.ReadInt32());
                        }

                        for (int k = 0; k < 3; k++)
                        {
                            meshInfo.VertexSizes.Add(br.ReadByte());
                        }

                        meshInfo.VertexDataBlockCount = br.ReadByte();

                        modelData.LoD[x].MeshList[i].MeshInfo = meshInfo;
                    }
                }

                br.ReadBytes(attributeStringCount * 4);
                br.ReadBytes(unknown6 * 20);

                for (int i = 0; i < modelData.LoD.Count; i++)
                {
                    foreach (var mesh in modelData.LoD[i].MeshList)
                    {
                        for (int j = 0; j < mesh.MeshInfo.MeshPartCount; j++)
                        {
                            MeshPart meshPart = new MeshPart()
                            {
                                IndexOffset = br.ReadInt32(),
                                IndexCount  = br.ReadInt32(),
                                Attributes  = br.ReadInt32(),
                                BoneOffset  = br.ReadInt16(),
                                BoneCount   = br.ReadInt16()
                            };

                            mesh.MeshPartList.Add(meshPart);
                        }
                    }
                }

                br.ReadBytes(unknown7 * 12);
                br.ReadBytes(materialStringCount * 4);
                br.ReadBytes(boneStringCount * 4);

                for (int i = 0; i < boneListCount; i++)
                {
                    Bones bones = new Bones();

                    for (int j = 0; j < 64; j++)
                    {
                        bones.BoneData.Add(br.ReadInt16());
                    }

                    bones.BoneCount = br.ReadInt32();

                    modelData.BoneSet.Add(bones);
                }

                br.ReadBytes(unknown1 * 16);
                br.ReadBytes(unknown2 * 12);
                br.ReadBytes(unknown3 * 4);

                var boneIndexSize = br.ReadInt32();

                for (int i = 0; i < boneIndexSize / 2; i++)
                {
                    modelData.BoneIndicies.Add(br.ReadInt16());
                }

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

                for (int i = 0; i < 4; i++)
                {
                    ModelMaterial.BoundingBox boundingBox = new ModelMaterial.BoundingBox();
                    for (int j = 0; j < 4; j++)
                    {
                        boundingBox.PointA.Add(br.ReadSingle());
                    }
                    for (int k = 0; k < 4; k++)
                    {
                        boundingBox.PointB.Add(br.ReadSingle());
                    }

                    modelData.BoundingBoxes.Add(boundingBox);
                }

                for (int i = 0; i < 3; i++)
                {
                    for (int j = 0; j < modelData.LoD[i].MeshCount; j++)
                    {
                        Mesh mesh = modelData.LoD[i].MeshList[j];

                        for (int k = 0; k < mesh.MeshInfo.VertexDataBlockCount; k++)
                        {
                            br.BaseStream.Seek(modelData.LoD[i].VertexOffset + mesh.MeshInfo.VertexDataOffsets[k], SeekOrigin.Begin);

                            mesh.MeshVertexData.Add(br.ReadBytes(mesh.MeshInfo.VertexSizes[k] * mesh.MeshInfo.VertexCount));
                        }

                        br.BaseStream.Seek(modelData.LoD[i].IndexOffset + (mesh.MeshInfo.IndexDataOffset * 2), SeekOrigin.Begin);

                        mesh.IndexData = br.ReadBytes(2 * mesh.MeshInfo.IndexCount);
                    }
                }

                int vertex = 0, coordinates = 0, normals = 0, tangents = 0, colors = 0;

                for (int i = 0; i < modelData.LoD[0].MeshCount; i++)
                {
                    objBytes.Clear();

                    var vertexList   = new Vector3Collection();
                    var texCoordList = new Vector2Collection();
                    var normalList   = new Vector3Collection();
                    var tangentList  = new Vector3Collection();
                    var colorsList   = new Color4Collection();
                    var indexList    = new IntCollection();

                    Mesh mesh = modelData.LoD[0].MeshList[i];

                    MeshDataInfo[] meshDataInfoList = mesh.MeshDataInfoList;

                    int c = 0;
                    foreach (var meshDataInfo in meshDataInfoList)
                    {
                        if (meshDataInfo.UseType == 0)
                        {
                            vertex = c;
                        }
                        else if (meshDataInfo.UseType == 3)
                        {
                            normals = c;
                        }
                        else if (meshDataInfo.UseType == 4)
                        {
                            coordinates = c;
                        }
                        else if (meshDataInfo.UseType == 6)
                        {
                            tangents = c;
                        }
                        else if (meshDataInfo.UseType == 7)
                        {
                            colors = c;
                        }

                        c++;
                    }

                    using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[vertex].VertexDataBlock])))
                    {
                        for (int j = 0; j < mesh.MeshInfo.VertexCount; j++)
                        {
                            br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[vertex].VertexDataBlock] + meshDataInfoList[vertex].Offset, SeekOrigin.Begin);

                            if (meshDataInfoList[vertex].DataType == 13 || meshDataInfoList[vertex].DataType == 14)
                            {
                                System.Half h1 = System.Half.ToHalf((ushort)br1.ReadInt16());
                                System.Half h2 = System.Half.ToHalf((ushort)br1.ReadInt16());
                                System.Half h3 = System.Half.ToHalf((ushort)br1.ReadInt16());

                                float x = HalfHelper.HalfToSingle(h1);
                                float y = HalfHelper.HalfToSingle(h2);
                                float z = HalfHelper.HalfToSingle(h3);

                                objBytes.Add("v " + x.ToString() + " " + y.ToString() + " " + z.ToString() + " ");
                                vertexList.Add(new Vector3(x, y, z));
                            }
                            else if (meshDataInfoList[vertex].DataType == 2)
                            {
                                float x = br1.ReadSingle();
                                float y = br1.ReadSingle();
                                float z = br1.ReadSingle();

                                objBytes.Add("v " + x.ToString() + " " + y.ToString() + " " + z.ToString() + " ");
                                vertexList.Add(new Vector3(x, y, z));
                            }
                        }
                    }

                    using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[coordinates].VertexDataBlock])))
                    {
                        for (int j = 0; j < mesh.MeshInfo.VertexCount; j++)
                        {
                            br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[coordinates].VertexDataBlock] + meshDataInfoList[coordinates].Offset, SeekOrigin.Begin);

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

                            float x = HalfHelper.HalfToSingle(h1);
                            float y = HalfHelper.HalfToSingle(h2);

                            objBytes.Add("vt " + x.ToString() + " " + (y * -1f).ToString() + " ");
                            texCoordList.Add(new Vector2(x, y));
                        }
                    }

                    using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[normals].VertexDataBlock])))
                    {
                        for (int j = 0; j < mesh.MeshInfo.VertexCount; j++)
                        {
                            br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[normals].VertexDataBlock] + meshDataInfoList[normals].Offset, SeekOrigin.Begin);

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

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

                    using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[tangents].VertexDataBlock])))
                    {
                        for (int j = 0; j < mesh.MeshInfo.VertexCount; j++)
                        {
                            br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[tangents].VertexDataBlock] + meshDataInfoList[tangents].Offset, SeekOrigin.Begin);

                            float x = br1.ReadByte() / 255f;
                            float y = br1.ReadByte() / 255f;
                            float z = br1.ReadByte() / 255f;

                            tangentList.Add(new Vector3(x, y, z));
                        }
                    }

                    using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[colors].VertexDataBlock])))
                    {
                        for (int j = 0; j < mesh.MeshInfo.VertexCount; j++)
                        {
                            br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[colors].VertexDataBlock] + meshDataInfoList[colors].Offset, SeekOrigin.Begin);

                            int a = br1.ReadByte();
                            int r = br1.ReadByte();
                            int g = br1.ReadByte();
                            int b = br1.ReadByte();

                            colorsList.Add(new Color4(r, g, b, a));
                        }
                    }

                    using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.IndexData)))
                    {
                        for (int j = 0; j < mesh.MeshInfo.IndexCount; j += 3)
                        {
                            int i1 = br1.ReadInt16();
                            int i2 = br1.ReadInt16();
                            int i3 = br1.ReadInt16();

                            objBytes.Add("f " + (i1 + 1) + "/" + (i1 + 1) + "/" + (i1 + 1) + " " + (i2 + 1) + "/" + (i2 + 1) + "/" + (i2 + 1) + " " + (i3 + 1) + "/" + (i3 + 1) + "/" + (i3 + 1) + " ");

                            indexList.Add(i1);
                            indexList.Add(i2);
                            indexList.Add(i3);
                        }
                    }

                    ModelMeshData modelMeshData = new ModelMeshData()
                    {
                        Vertices           = vertexList,
                        Normals            = normalList,
                        TextureCoordinates = texCoordList,
                        Tangents           = tangentList,
                        Indices            = indexList,
                        VertexColors       = colorsList,
                        OBJFileData        = objBytes.ToArray()
                    };

                    meshList.Add(modelMeshData);
                }
            }
        }