Beispiel #1
0
        /// <summary>
        /// Create a Mesh, with found props
        /// </summary>
        /// <param name="positions"></param>
        /// <param name="textureCoordinates"></param>
        /// <param name="triangleIndices"></param>
        /// <param name="normals"></param>
        /// <param name="tangents"></param>
        /// <param name="bitangents"></param>
        /// <param name="material"></param>
        /// <param name="transforms"></param>
        private void CreateMesh(Vector3Collection positions, Vector2Collection textureCoordinates, IntCollection triangleIndices, List <Matrix> transforms,
                                out Vector3Collection normals, out Vector3Collection tangents, out Vector3Collection bitangents, MaterialCore material)
        {
            ComputeNormals(positions, triangleIndices, out normals);
            if (textureCoordinates == null)
            {
                textureCoordinates = new Vector2Collection();
                foreach (var pos in positions)
                {
                    textureCoordinates.Add(Vector2.One);
                }
            }
            MeshBuilder.ComputeTangents(positions, normals, textureCoordinates, triangleIndices, out tangents, out bitangents);
            MeshGeometry3D mesh = new MeshGeometry3D()
            {
                Positions          = positions,
                Normals            = normals,
                TextureCoordinates = textureCoordinates,
                Indices            = triangleIndices,
                Tangents           = tangents,
                BiTangents         = bitangents
            };
            Object3D ob3d = new Object3D();

            ob3d.Geometry  = mesh;
            ob3d.Material  = material;
            ob3d.Transform = transforms;
            ob3d.Name      = "Default";
            this.obGroup.Add(ob3d);
        }
Beispiel #2
0
        private static List <MeshGeometryModel3D> GenerateMeshGeometryModels(MGEOFile mgeo)
        {
            List <MeshGeometryModel3D> models = new List <MeshGeometryModel3D>(mgeo.Objects.Count);

            foreach (MGEOObject mgeoModel in mgeo.Objects)
            {
                IntCollection     indices  = new IntCollection(mgeoModel.Indices.Select(x => (int)x).AsEnumerable());
                Vector3Collection vertices = new Vector3Collection(mgeoModel.Vertices.Count);
                Vector2Collection uvs      = new Vector2Collection(mgeoModel.Vertices.Count);
                foreach (MGEOVertex vertex in mgeoModel.Vertices)
                {
                    vertices.Add(new dxVector3(vertex.Position.X, vertex.Position.Y, vertex.Position.Z));
                    uvs.Add(new dxVector2(vertex.DiffuseUV.X, vertex.DiffuseUV.Y));
                }

                MeshGeometry3D meshGeometry = new MeshGeometry3D()
                {
                    Indices            = indices,
                    Positions          = vertices,
                    TextureCoordinates = uvs
                };

                MeshGeometryModel3D model = new MeshGeometryModel3D()
                {
                    Geometry = meshGeometry,
                    Material = DiffuseMaterials.Pearl,
                    Name     = mgeoModel.Name
                };

                models.Add(model);
            }

            return(models);
        }
Beispiel #3
0
        public static MeshGeometry3D GetRect(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
        {
            var positions       = new Vector3Collection();
            var triangleIndices = new HelixToolkit.Wpf.SharpDX.Core.IntCollection();

            var normals = new Vector3Collection();
            //private Vector3Collection tangents;
            //private Vector3Collection bitangents;
            var textureCoordinates = new Vector2Collection();

            var widthOrientation  = new Vector3(0, 0, 1);
            var heightOrientation = new Vector3(0, 1, 0);

            positions.Add(p0);
            positions.Add(p1);
            positions.Add(p2);
            positions.Add(p3);

            normals.Add(new Vector3(1, 0, 0));
            normals.Add(new Vector3(1, 0, 0));
            normals.Add(new Vector3(1, 0, 0));
            normals.Add(new Vector3(1, 0, 0));


            textureCoordinates.Add(new Vector2(0, 0));
            textureCoordinates.Add(new Vector2(1, 0));
            textureCoordinates.Add(new Vector2(1, 1));
            textureCoordinates.Add(new Vector2(0, 1));

            triangleIndices.Add(2);
            triangleIndices.Add(1);
            triangleIndices.Add(0);

            triangleIndices.Add(0);
            triangleIndices.Add(3);
            triangleIndices.Add(2);

            return(new MeshGeometry3D()
            {
                Positions = positions,
                Indices = triangleIndices,
                Normals = normals,
                TextureCoordinates = textureCoordinates
            });
        }
Beispiel #4
0
        public static MeshGeometry3D GetRect(Vector3 center, float width, float height, Vector3 widthOrientation, Vector3 heightOrientation)
        {
            var positions       = new Vector3Collection();
            var triangleIndices = new HelixToolkit.Wpf.SharpDX.Core.IntCollection();

            var normals = new Vector3Collection();
            //private Vector3Collection tangents;
            //private Vector3Collection bitangents;
            var textureCoordinates = new Vector2Collection();

            positions.Add(center - widthOrientation * width / 2 - heightOrientation * height / 2);
            positions.Add(center + widthOrientation * width / 2 - heightOrientation * height / 2);
            positions.Add(center + widthOrientation * width / 2 + heightOrientation * height / 2);
            positions.Add(center - widthOrientation * width / 2 + heightOrientation * height / 2);

            normals.Add(new Vector3(1, 0, 0));
            normals.Add(new Vector3(1, 0, 0));
            normals.Add(new Vector3(1, 0, 0));
            normals.Add(new Vector3(1, 0, 0));

            textureCoordinates.Add(new Vector2(1, 1));
            textureCoordinates.Add(new Vector2(0, 1));
            textureCoordinates.Add(new Vector2(0, 0));
            textureCoordinates.Add(new Vector2(1, 0));

            triangleIndices.Add(2);
            triangleIndices.Add(1);
            triangleIndices.Add(0);

            triangleIndices.Add(0);
            triangleIndices.Add(3);
            triangleIndices.Add(2);

            return(new MeshGeometry3D()
            {
                Positions = positions,
                Indices = triangleIndices,
                Normals = normals,
                TextureCoordinates = textureCoordinates
            });
        }
Beispiel #5
0
        private Vector2Collection ReadTexCoords(BinaryReader reader)
        {
            int size = reader.ReadUInt16();
            var pts  = new Vector2Collection();

            for (int i = 0; i < size; i++)
            {
                float x = reader.ReadSingle();
                float y = reader.ReadSingle();
                pts.Add(new Vector2(x, 1 - y));
            }
            return(pts);
        }
        private void CreatePerlinNoise()
        {
            float[] noise;
            MathHelper.GenerateNoiseMap(Width, Height, 8, out noise);
            Vector2Collection collection = new Vector2Collection(Width * Height);

            for (int i = 0; i < Width; ++i)
            {
                for (int j = 0; j < Height; ++j)
                {
                    collection.Add(new Vector2(Math.Abs(noise[Width * i + j]), 0));
                }
            }
            Model.TextureCoordinates = collection;
        }
Beispiel #7
0
        public static IEnumerable <GroupNode> LoadMapMGEO(MGEOFile mgeo, MapData mapData, string mapPath)
        {
            foreach (MGEOObject mgeoModel in mgeo.Objects)
            {
                IntCollection     indices  = new IntCollection(mgeoModel.Indices.Select(x => (int)x).AsEnumerable());
                Vector3Collection vertices = new Vector3Collection(mgeoModel.Vertices.Count);
                Vector2Collection uvs      = new Vector2Collection(mgeoModel.Vertices.Count);
                foreach (MGEOVertex vertex in mgeoModel.Vertices)
                {
                    vertices.Add(new dxVector3(vertex.Position.X, vertex.Position.Y, vertex.Position.Z));
                    uvs.Add(new dxVector2(vertex.DiffuseUV.X, vertex.DiffuseUV.Y));
                }

                foreach (MGEOSubmesh submesh in mgeoModel.Submeshes)
                {
                    GroupNode groupNode = new GroupNode()
                    {
                        Name = mgeoModel.Name
                    };

                    MeshGeometry3D submeshGeometry3D = new MeshGeometry3D()
                    {
                        Indices            = indices.GetRange((int)submesh.StartIndex, (int)submesh.IndexCount) as IntCollection,
                        Positions          = vertices,
                        TextureCoordinates = uvs
                    };

                    DiffuseMaterial diffuseMaterial = new DiffuseMaterial()
                    {
                        Name        = submesh.Material,
                        DiffuseMap  = CreateMaterial(submesh.Material, mapData, mapPath),
                        EnableUnLit = true
                    };

                    groupNode.AddChildNode(new MeshNode()
                    {
                        Name     = mgeoModel.Name + "|" + submesh.Material,
                        Geometry = submeshGeometry3D,
                        Material = diffuseMaterial
                    });

                    yield return(groupNode);
                }
            }
        }
        public static Vector2Collection Parse(string source)
        {
            IFormatProvider formatProvider = CultureInfo.InvariantCulture;

            var th       = new TokenizerHelper(source, formatProvider);
            var resource = new Vector2Collection();

            Vector2 value;

            while (th.NextToken())
            {
                value = new Vector2(
                    Convert.ToSingle(th.GetCurrentToken(), formatProvider),
                    Convert.ToSingle(th.NextTokenRequired(), formatProvider));

                resource.Add(value);
            }

            return(resource);
        }
Beispiel #9
0
        public static MeshGeometry3D GetCube(Vector3 minimum, Vector3 maximum)
        {
            var positions       = new Vector3Collection();
            var triangleIndices = new HelixToolkit.Wpf.SharpDX.Core.IntCollection();

            var normals            = new Vector3Collection();
            var textureCoordinates = new Vector2Collection();

            positions.Add(new Vector3(minimum.X, minimum.Y, minimum.Z)); //0
            positions.Add(new Vector3(maximum.X, minimum.Y, minimum.Z)); //1
            positions.Add(new Vector3(minimum.X, maximum.Y, minimum.Z)); //2
            positions.Add(new Vector3(minimum.X, minimum.Y, maximum.Z)); //3
            positions.Add(new Vector3(maximum.X, maximum.Y, minimum.Z)); //4
            positions.Add(new Vector3(maximum.X, minimum.Y, maximum.Z)); //5
            positions.Add(new Vector3(minimum.X, maximum.Y, maximum.Z)); //6
            positions.Add(new Vector3(maximum.X, maximum.Y, maximum.Z)); //7

            triangleIndices.AddRange(new[] { 0, 5, 3, 0, 1, 5 });
            triangleIndices.AddRange(new[] { 1, 7, 5, 1, 4, 7 });
            triangleIndices.AddRange(new[] { 4, 7, 2, 7, 6, 2 });
            triangleIndices.AddRange(new[] { 6, 3, 0, 6, 0, 2 });
            triangleIndices.AddRange(new[] { 6, 3, 5, 5, 7, 6 });
            triangleIndices.AddRange(new[] { 0, 1, 2, 2, 1, 4 });

            for (int i = 0; i < positions.Count; i++)
            {
                normals.Add(new Vector3(1, 0, 0));
                textureCoordinates.Add(new Vector2(0, 0));
            }


            return(new MeshGeometry3D()
            {
                Positions = positions,
                Indices = triangleIndices,
                Normals = normals,
                TextureCoordinates = textureCoordinates
            });
        }
        /////////////////////////////////////////////////////////////////////////////////////////////
        //// below all functions taken from "Helix 3D Toolkit" MeshBuilder 
        /////////////////////////////////////////////////////////////////////////////////////////////


        /// <summary>
        /// Gets a circle section (cached).
        /// </summary>
        /// <param name="thetaDiv">
        /// The number of division.
        /// </param>
        /// <returns>
        /// A circle.
        /// </returns>
        public static IList<Vector2> GetCircle(int thetaDiv)
        {
            IList<Vector2> circle;
            if (!CircleCache.TryGetValue(thetaDiv, out circle))
            {
                circle = new Vector2Collection();
                CircleCache.Add(thetaDiv, circle);
                for (int i = 0; i < thetaDiv; i++)
                {
                    double theta = Math.PI * 2 * ((double)i / (thetaDiv - 1));
                    circle.Add(new Vector2((float)Math.Cos(theta), -(float)Math.Sin(theta)));
                }
            }

            return circle;
        }
        private static void AppendSphere(Vector3 center, double radius, int thetaSteps, int phiSteps,
            out Vector3Collection positions, out Vector3Collection normals, out Vector2Collection textureCoordinates, out IntCollection triangleIndices)
        {
            positions = new Vector3Collection();
            normals = new Vector3Collection();
            textureCoordinates = new Vector2Collection();
            triangleIndices = new IntCollection();

            double dt = DegToRad(360.0) / thetaSteps;
            double dp = DegToRad(180.0) / phiSteps;

            for (int pi = 0; pi <= phiSteps; pi++)
            {
                double phi = pi * dp;
                for (int ti = 0; ti <= thetaSteps; ti++)
                {
                    // we want to start the mesh on the x axis
                    double theta = ti * dt;

                    positions.Add(GetPosition(theta, phi, radius) + center);
                    normals.Add(GetNormal(theta, phi));
                    textureCoordinates.Add(GetTextureCoordinate(theta, phi));
                }
            }

            for (int pi = 0; pi < phiSteps; pi++)
            {
                for (int ti = 0; ti < thetaSteps; ti++)
                {
                    int x0 = ti;
                    int x1 = ti + 1;
                    int y0 = pi * (thetaSteps + 1);
                    int y1 = (pi + 1) * (thetaSteps + 1);

                    triangleIndices.Add(x0 + y0);
                    triangleIndices.Add(x0 + y1);
                    triangleIndices.Add(x1 + y0);

                    triangleIndices.Add(x1 + y0);
                    triangleIndices.Add(x0 + y1);
                    triangleIndices.Add(x1 + y1);
                }
            }
        }
        /// <summary>
        /// Adds a (possibly hollow) pipe.
        /// </summary>
        /// <param name="point1">
        /// The start point.
        /// </param>
        /// <param name="point2">
        /// The end point.
        /// </param>
        /// <param name="innerDiameter">
        /// The inner diameter.
        /// </param>
        /// <param name="diameter">
        /// The outer diameter.
        /// </param>
        /// <param name="thetaDiv">
        /// The number of divisions around the pipe.
        /// </param>
        public void AddPipe(Vector3 point1, Vector3 point2, double innerDiameter, double diameter, int thetaDiv)
        {
            var dir = point2 - point1;

            double height = dir.Length();
            dir.Normalize();

            var pc = new Vector2Collection
                {
                    new Vector2(0, (float)innerDiameter / 2),
                    new Vector2(0, (float)diameter / 2),
                    new Vector2((float)height, (float)diameter / 2),
                    new Vector2((float)height, (float)innerDiameter / 2)
                };

            if (innerDiameter > 0)
            {
                // Add the inner surface
                pc.Add(new Vector2(0, (float)innerDiameter / 2));
            }

            this.AddRevolvedGeometry(pc, point1, dir, thetaDiv);
        }
        /// <summary>
        /// Adds a (possibly truncated) cone.
        /// </summary>
        /// <param name="origin">
        /// The origin.
        /// </param>
        /// <param name="direction">
        /// The direction (normalization not required).
        /// </param>
        /// <param name="baseRadius">
        /// The base radius.
        /// </param>
        /// <param name="topRadius">
        /// The top radius.
        /// </param>
        /// <param name="height">
        /// The height.
        /// </param>
        /// <param name="baseCap">
        /// Include a base cap if set to <c>true</c> .
        /// </param>
        /// <param name="topCap">
        /// Include the top cap if set to <c>true</c> .
        /// </param>
        /// <param name="thetaDiv">
        /// The number of divisions around the cone.
        /// </param>
        /// <remarks>
        /// See http://en.wikipedia.org/wiki/Cone_(geometry).
        /// </remarks>
        public void AddCone(
            Vector3 origin,
            Vector3 direction,
            double baseRadius,
            double topRadius,
            double height,
            bool baseCap,
            bool topCap,
            int thetaDiv)
        {
            var pc = new Vector2Collection();
            if (baseCap)
            {
                pc.Add(new Vector2(0, 0));
            }

            pc.Add(new Vector2(0, (float)baseRadius));
            pc.Add(new Vector2((float)height, (float)topRadius));
            if (topCap)
            {
                pc.Add(new Vector2((float)height, 0));
            }

            this.AddRevolvedGeometry(pc, origin, direction, thetaDiv);
        }
        /// <summary>
        /// Gets a circle segment section.
        /// </summary>
        /// <param name="thetaDiv">The number of division.</param>
        /// <param name="totalAngle">The angle of the circle segment.</param>
        /// <param name="angleOffset">The angle-offset to use.</param>
        /// <returns>
        /// A circle segment.
        /// </returns>
        public static IList<Vector2> GetCircleSegment(int thetaDiv, float totalAngle = 2 * (float)Math.PI, float angleOffset = 0)
        {
            IList <Vector2> circleSegment;
            circleSegment = new Vector2Collection();
            for (int i = 0; i < thetaDiv; i++)
            {
                double theta = totalAngle * ((double)i / (thetaDiv - 1)) + angleOffset;
                circleSegment.Add(new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta)));
            }

            return circleSegment;
        }
Beispiel #15
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  Vector2Collection ReadTexCoords(BinaryReader reader)
 {
   int size = reader.ReadUInt16();
   var pts = new Vector2Collection();
   for(int i=0;i< size; i++)
   {
     float x = reader.ReadSingle();
     float y = reader.ReadSingle();
     pts.Add(new Vector2(x, y));
   }
   return pts;
 }
Beispiel #17
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);
                }
            }
        }
Beispiel #18
0
        public static Dictionary <string, object> PlaneMesh(
            [DefaultArgument("CoordinateSystem.ByOriginVectors(Point.Origin(), Vector.XAxis(), Vector.YAxis())")] CoordinateSystem cs,
            [DefaultArgument("20.0")] double lengthX,
            [DefaultArgument("20.0")] double lengthY,
            [DefaultArgument("20")] int divX,
            [DefaultArgument("20")] int divY,
            [DefaultArgument("true")] bool alternatingDiagons)
        {
            if (divX < 1 || divY < 0)
            {
                throw new Exception("divX and divY must be larger than 0");
            }

            List <Point>      vertices           = new List <Point>((divX + 1) * (divY + 1));
            Vector2Collection textureCoordinates = new Vector2Collection();

            for (int j = 0; j <= divY; j++)
            {
                for (int i = 0; i <= divX; i++)
                {
                    vertices.Add(
                        Point.ByCartesianCoordinates(
                            cs,
                            ((double)i / divX - 0.5f) * lengthX,
                            ((double)j / divY - 0.5f) * lengthY));

                    textureCoordinates.Add(new Vector2((float)i / (float)(divX), 1f - (float)j / (float)(divY)));
                }
            }

            List <int>         indices = new List <int>();
            List <List <int> > quadFaceVertexIndices = new List <List <int> >();

            for (int j = 0; j < divY; j++)
            {
                for (int i = 0; i < divX; i++)
                {
                    int a = i + j * (divX + 1);
                    int b = i + 1 + j * (divX + 1);
                    int c = i + 1 + (j + 1) * (divX + 1);
                    int d = i + (j + 1) * (divX + 1);

                    quadFaceVertexIndices.Add(new List <int> {
                        a, b, c, d
                    });

                    if (alternatingDiagons)
                    {
                        if ((i + j) % 2 == 0)
                        {
                            indices.Add(a);
                            indices.Add(b);
                            indices.Add(c);
                            indices.Add(a);
                            indices.Add(c);
                            indices.Add(d);
                        }
                        else
                        {
                            indices.Add(a);
                            indices.Add(b);
                            indices.Add(d);
                            indices.Add(b);
                            indices.Add(c);
                            indices.Add(d);
                        }
                    }
                    else
                    {
                        indices.Add(a);
                        indices.Add(b);
                        indices.Add(c);
                        indices.Add(a);
                        indices.Add(c);
                        indices.Add(d);
                    }
                }
            }

            return(new Dictionary <string, object>()
            {
                { "mesh", Mesh.ByVerticesAndIndices(vertices, indices) },
                { "quadFaceVertexIndices", quadFaceVertexIndices },
                { "textureCoordinates", new TextureCoordinateSet(textureCoordinates) },
            });
        }
        /////////////////////////////////////////////////////////////////////////////////////////////
        //// below all functions taken from "Helix 3D Toolkit" MeshBuilder 
        /////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Gets a circle section (cached).
        /// </summary>
        /// <param name="thetaDiv">
        /// The number of division.
        /// </param>
        /// <param name="closed">
        /// Is the circle closed?
        /// If true, the last point will not be at the same position than the first one.
        /// </param>
        /// <returns>
        /// A circle.
        /// </returns>
        public static IList<Vector2> GetCircle(int thetaDiv, bool closed = false)
        {
            IList<Vector2> circle = null;
            // If the circle can't be found in one of the two caches
            if ((!closed && !CircleCache.TryGetValue(thetaDiv, out circle)) ||
                (closed && !ClosedCircleCache.TryGetValue(thetaDiv, out circle)))
            {
                circle = new Vector2Collection();
                // Add to the cache
                if (!closed)
                {
                    CircleCache.TryAdd(thetaDiv, circle);
                }
                else
                {
                    ClosedCircleCache.TryAdd(thetaDiv, circle);
                }
                // Determine the angle steps
                var num = closed ? thetaDiv : thetaDiv - 1;
                for (int i = 0; i < thetaDiv; i++)
                {
                    double theta = Math.PI * 2 * ((double)i / num);
                    circle.Add(new Vector2((float)Math.Cos(theta), (float)-Math.Sin(theta)));
                }
            }

            // Since Vector2Collection is not Freezable,
            // return new IList<Vector> to avoid manipulation of the Cached Values
            IList<Vector2> result = new List<Vector2>();
            foreach (var point in circle)
            {
                result.Add(new Vector2(point.X, point.Y));
            }
            return result;
        }
Beispiel #20
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);
                }
            }
        }
Beispiel #21
-32
    /// <summary>
    /// Create a Mesh, with found props
    /// </summary>
    /// <param name="positions"></param>
    /// <param name="textureCoordinates"></param>
    /// <param name="triangleIndices"></param>
    /// <param name="normals"></param>
    /// <param name="tangents"></param>
    /// <param name="bitangents"></param>
    /// <param name="material"></param>
    private void CreateMesh(Vector3Collection positions, Vector2Collection textureCoordinates, IntCollection triangleIndices, out Vector3Collection normals, out Vector3Collection tangents, out Vector3Collection bitangents,Material material)
    {
      ComputeNormals(positions, triangleIndices, out normals);
      if (textureCoordinates == null)
      {
        textureCoordinates = new Vector2Collection();
        foreach(var pos in positions)
        {
          textureCoordinates.Add(Vector2.One);
        }
      } 
      MeshBuilder.ComputeTangents(positions, normals, textureCoordinates, triangleIndices, out tangents, out bitangents);
      MeshGeometry3D mesh = new MeshGeometry3D()
      {
        Positions = positions,
        Normals = normals,
        TextureCoordinates = textureCoordinates,
        Indices = triangleIndices,
        Tangents = tangents,
        BiTangents = bitangents

      };
      Object3D ob3d = new Object3D();
      ob3d.Geometry = mesh;
      ob3d.Material = material;
      ob3d.Transform = Matrix.Identity;
      ob3d.Name = "Default";
      this.obGroup.Add(ob3d);
    }