示例#1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="model"></param>
        public void WriteFMDLData(XmlWriter writer, ResU.Model model)
        {
            writer.WriteStartElement("FMDL");
            writer.WriteAttributeString("Name", model.Name);

            // TODO Wrap these functions in if exists conditions, so that the xml only contains relevant data
            JPSkeleton jpSkeleton = new JPSkeleton();

            jpSkeleton.ReadSkeleton(model.Skeleton);
            FSKL.WriteSkeleton(writer, model.Skeleton);

            writer.WriteStartElement("Materials");
            writer.WriteAttributeString("FMATCount", model.Materials.Count.ToString());
            foreach (Material mat in model.Materials.Values)
            {
                FMAT.ReadMaterial(writer, mat);
            }
            writer.WriteEndElement();

            writer.WriteStartElement("Shapes");

            writer.WriteAttributeString("FSHPCount", model.Shapes.Count.ToString());
            writer.WriteAttributeString("FVTXCount", model.VertexBuffers.Count.ToString());
            writer.WriteAttributeString("TotalVertices", model.TotalVertexCount.ToString());
            foreach (Shape shp in model.Shapes.Values)
            {
                writer.WriteStartElement("FSHP");
                VertexBuffer vertexBuffer = model.VertexBuffers[shp.VertexBufferIndex];
                Material     material     = model.Materials[shp.MaterialIndex];
                WriteShapesVertices(writer, shp, vertexBuffer, model, jpSkeleton);
                writer.WriteEndElement();
            }
            writer.WriteEndElement();

            writer.WriteEndElement();
            writer.Flush();
        }
示例#2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="shp"></param>
        /// <param name="vertexBuffer"></param>
        /// <param name="model"></param>
        public static void WriteShapesVertices(XmlWriter writer, Shape shp, VertexBuffer vertexBuffer, ResU.Model model, JPSkeleton jpSkeleton)
        {
            writer.WriteAttributeString("Name", shp.Name);
            writer.WriteAttributeString("Flags", shp.Flags.ToString());
            writer.WriteAttributeString("MaterialIndex", shp.MaterialIndex.ToString());
            Program.AssertAndLog(Program.ErrorType.eBoneIndexSet, shp.BoneIndex == 0, $"{shp.Name}: Bone index is set. Why?");
            writer.WriteAttributeString("BoneIndex", shp.BoneIndex.ToString());
            writer.WriteAttributeString("VertexBufferIndex", shp.VertexBufferIndex.ToString());

            // Write Bounding Radius
            string tempRadiusArray = "";

            foreach (float rad in shp.RadiusArray)
            {
                tempRadiusArray += (rad.ToString() + ',');
            }
            tempRadiusArray = tempRadiusArray.Trim(',');

            writer.WriteAttributeString("RadiusArray", tempRadiusArray);
            writer.WriteAttributeString("VertexSkinCount", shp.VertexSkinCount.ToString());
            Program.AssertAndLog(Program.ErrorType.eShapeTargetAttributeCountGreaterThanZero, shp.TargetAttribCount == 0, $"{shp.Name}: target attribute count of greater than 0. Unsure of this meaning.");
            writer.WriteAttributeString("TargetAttributeCount", shp.TargetAttribCount.ToString());

            // Write Skin Bone Indices
            if (shp.SkinBoneIndices != null)
            {
                string tempSkinBoneIndices = "";
                foreach (ushort bn in shp.SkinBoneIndices)
                {
                    tempSkinBoneIndices += (bn + ",");
                }
                tempSkinBoneIndices = tempSkinBoneIndices.Trim(',');
                writer.WriteAttributeString("SkinBoneIndices", tempSkinBoneIndices);
            }

            // Write Key Shapes
            Program.AssertAndLog(Program.ErrorType.eKeyShapes, shp.KeyShapes.Count == 0, "If you hit this assert, write KeyShapes you lazy f**k.");

            // Write Bounding Boxes
            //
            // Summary:
            //     Represents a spatial bounding box.
            writer.WriteStartElement("SubMeshBoundings");
            writer.WriteAttributeString("SubMeshBoundingsCount", shp.SubMeshBoundings.Count.ToString());
            foreach (Bounding bnd in shp.SubMeshBoundings)
            {
                writer.WriteStartElement("SubMeshBounding");
                writer.WriteAttributeString("Center", Program.Vector3FToString(bnd.Center));
                writer.WriteAttributeString("Extent", Program.Vector3FToString(bnd.Extent));
                writer.WriteEndElement();
            }
            writer.WriteEndElement();

            //
            // Summary:
            //     Represents a node in a Syroot.NintenTools.Bfres.SubMesh bounding tree to determine
            //     when to show which sub mesh of a Syroot.NintenTools.Bfres.Mesh.
            writer.WriteStartElement("SubMeshBoundingNodes");
            writer.WriteAttributeString("SubMeshBoundingNodesCount", shp.SubMeshBoundingNodes.Count.ToString());
            foreach (BoundingNode node in shp.SubMeshBoundingNodes)
            {
                writer.WriteStartElement("SubMeshBoundingNode");

                writer.WriteAttributeString("LeftChildIndex", node.LeftChildIndex.ToString());
                writer.WriteAttributeString("NextSibling", node.NextSibling.ToString());
                writer.WriteAttributeString("RightChildIndex", node.RightChildIndex.ToString());
                writer.WriteAttributeString("Unknown", node.Unknown.ToString());
                writer.WriteAttributeString("SubMeshIndex", node.SubMeshIndex.ToString());
                writer.WriteAttributeString("SubMeshCount", node.SubMeshCount.ToString());

                writer.WriteEndElement();
            }
            writer.WriteEndElement();

            // Write SubMesh Bounding Indices
            writer.WriteStartElement("SubMeshBoundingIndices");
            writer.WriteAttributeString("SubMeshBoundingIndicesCount", shp.SubMeshBoundingIndices.Count.ToString());
            if (shp.SubMeshBoundingIndices != null)
            {
                string tempSubMeshBoundingIndices = "";
                foreach (ushort smbi in shp.SubMeshBoundingIndices)
                {
                    tempSubMeshBoundingIndices += (smbi + ",");
                }
                tempSubMeshBoundingIndices = tempSubMeshBoundingIndices.Trim(',');
                writer.WriteAttributeString("SubMeshBoundingIndices", tempSubMeshBoundingIndices);
            }
            writer.WriteEndElement();

            WriteMeshes(writer, shp);
            WriteVertexBuffer(writer, shp, vertexBuffer, model, jpSkeleton);
        }
示例#3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="shp"></param>
        /// <param name="vtx"></param>
        /// <param name="model"></param>
        private static void WriteVertexBuffer(XmlWriter writer, Shape shp, VertexBuffer vtx, ResU.Model model, JPSkeleton jPSkeleton)
        {
            //Create a buffer instance which stores all the buffer data
            VertexBufferHelper helper = new VertexBufferHelper(vtx, Syroot.BinaryData.ByteOrder.BigEndian); // TODO if this supports Switch files, you will need to re-look at this

            //Set each array first from the lib if exist. Then add the data all in one loop
            Syroot.Maths.Vector4F[] vec4Positions = new Syroot.Maths.Vector4F[0];
            Syroot.Maths.Vector4F[] vec4Normals   = new Syroot.Maths.Vector4F[0];
            Syroot.Maths.Vector4F[] vec4uv0       = new Syroot.Maths.Vector4F[0];
            Syroot.Maths.Vector4F[] vec4uv1       = new Syroot.Maths.Vector4F[0];
            Syroot.Maths.Vector4F[] vec4uv2       = new Syroot.Maths.Vector4F[0];
            Syroot.Maths.Vector4F[] vec4c0        = new Syroot.Maths.Vector4F[0];
            Syroot.Maths.Vector4F[] vec4c1        = new Syroot.Maths.Vector4F[0];
            Syroot.Maths.Vector4F[] vec4t0        = new Syroot.Maths.Vector4F[0];
            Syroot.Maths.Vector4F[] vec4b0        = new Syroot.Maths.Vector4F[0];
            Syroot.Maths.Vector4F[] vec4w0        = new Syroot.Maths.Vector4F[0];
            Syroot.Maths.Vector4F[] vec4i0        = new Syroot.Maths.Vector4F[0];

            //For shape morphing
            Syroot.Maths.Vector4F[] vec4Positions1 = new Syroot.Maths.Vector4F[0];
            Syroot.Maths.Vector4F[] vec4Positions2 = new Syroot.Maths.Vector4F[0];

            List <VertexAttrib> SortedList = vtx.Attributes.Values.OrderBy(o => o.BufferIndex).ToList();

            foreach (VertexAttrib att in vtx.Attributes.Values)
            {
                if (att.Name == "_p0")
                {
                    vec4Positions = AttributeData(att, helper, "_p0");
                }
                else if (att.Name == "_n0")
                {
                    vec4Normals = AttributeData(att, helper, "_n0");
                }
                else if (att.Name == "_u0")
                {
                    vec4uv0 = AttributeData(att, helper, "_u0");
                }
                else if (att.Name == "_u1")
                {
                    vec4uv1 = AttributeData(att, helper, "_u1");
                }
                else if (att.Name == "_u2")
                {
                    vec4uv2 = AttributeData(att, helper, "_u2");
                }
                else if (att.Name == "_c0")
                {
                    vec4c0 = AttributeData(att, helper, "_c0");
                }
                else if (att.Name == "_c1")
                {
                    vec4c1 = AttributeData(att, helper, "_c1");
                }
                else if (att.Name == "_t0")
                {
                    vec4t0 = AttributeData(att, helper, "_t0");
                }
                else if (att.Name == "_b0")
                {
                    vec4b0 = AttributeData(att, helper, "_b0");
                }
                else if (att.Name == "_w0")
                {
                    vec4w0 = AttributeData(att, helper, "_w0");
                }
                else if (att.Name == "_i0")
                {
                    vec4i0 = AttributeData(att, helper, "_i0");
                }

                else if (att.Name == "_p1")
                {
                    vec4Positions1 = AttributeData(att, helper, "_p1");
                }
                else if (att.Name == "_p2")
                {
                    vec4Positions2 = AttributeData(att, helper, "_p2");
                }
                else
                {
                    Program.AssertAndLog(Program.ErrorType.eUnhandledVertexAttrType, false, $"Vertex Attribute type {att.Name} not handled.");
                }
            }
            List <Vertex> vertices = new List <Vertex>();

            for (int i = 0; i < vec4Positions.Length; i++)
            {
                Vertex v = new Vertex();
                if (vec4Positions.Length > 0)
                {
                    v.pos = new OpenTK.Vector3(vec4Positions[i].X, vec4Positions[i].Y, vec4Positions[i].Z);
                }
                if (vec4Positions1.Length > 0)
                {
                    v.pos1 = new OpenTK.Vector3(vec4Positions1[i].X, vec4Positions1[i].Y, vec4Positions1[i].Z);
                }
                if (vec4Positions2.Length > 0)
                {
                    v.pos2 = new OpenTK.Vector3(vec4Positions2[i].X, vec4Positions2[i].Y, vec4Positions2[i].Z);
                }
                if (vec4Normals.Length > 0)
                {
                    v.nrm = new OpenTK.Vector3(vec4Normals[i].X, vec4Normals[i].Y, vec4Normals[i].Z);
                }
                if (vec4uv0.Length > 0)
                {
                    v.uv0 = new OpenTK.Vector2(vec4uv0[i].X, vec4uv0[i].Y);
                }
                if (vec4uv1.Length > 0)
                {
                    v.uv1 = new OpenTK.Vector2(vec4uv1[i].X, vec4uv1[i].Y);
                }
                if (vec4uv2.Length > 0)
                {
                    v.uv2 = new OpenTK.Vector2(vec4uv2[i].X, vec4uv2[i].Y);
                }
                if (vec4w0.Length > 0)
                {
                    v.boneWeights.Add(vec4w0[i].X);
                    v.boneWeights.Add(vec4w0[i].Y);
                    v.boneWeights.Add(vec4w0[i].Z);
                    v.boneWeights.Add(vec4w0[i].W);
                }
                if (vec4i0.Length > 0)
                {
                    v.boneIds.Add((int)vec4i0[i].X);
                    v.boneIds.Add((int)vec4i0[i].Y);
                    v.boneIds.Add((int)vec4i0[i].Z);
                    v.boneIds.Add((int)vec4i0[i].W);
                }

                if (vec4t0.Length > 0)
                {
                    v.tan = new OpenTK.Vector4(vec4t0[i].X, vec4t0[i].Y, vec4t0[i].Z, vec4t0[i].W);
                }
                if (vec4b0.Length > 0)
                {
                    v.bitan = new OpenTK.Vector4(vec4b0[i].X, vec4b0[i].Y, vec4b0[i].Z, vec4b0[i].W);
                }
                if (vec4c0.Length > 0)
                {
                    v.col = new OpenTK.Vector4(vec4c0[i].X, vec4c0[i].Y, vec4c0[i].Z, vec4c0[i].W);
                }
                if (vec4c1.Length > 0)
                {
                    v.col2 = new OpenTK.Vector4(vec4c1[i].X, vec4c1[i].Y, vec4c1[i].Z, vec4c1[i].W);
                }


                int[] boneList = new int[model.Skeleton.MatrixToBoneList.Count];
                int   uiBone   = 0;
                foreach (ushort node in model.Skeleton.MatrixToBoneList)
                {
                    boneList[uiBone] = node;
                    uiBone++;
                }
                if (shp.VertexSkinCount == 1)
                {
                    int boneIndex = shp.BoneIndex;
                    if (v.boneIds.Count > 0)
                    {
                        boneIndex = boneList[v.boneIds[0]];
                    }

                    //Check if the bones are a rigid type
                    //In game it seems to not transform if they are not rigid
                    if (model.Skeleton.Bones[boneIndex].RigidMatrixIndex != -1)
                    {
                        OpenTK.Matrix4 absTransform = jPSkeleton.bones[boneIndex].Transform;

                        v.pos = OpenTK.Vector3.TransformPosition(v.pos, absTransform);
                        v.nrm = OpenTK.Vector3.TransformNormal(v.nrm, absTransform);
                    }
                }
                if (shp.VertexSkinCount == 0)
                {
                    try
                    {
                        if (model.Skeleton.Bones.Count > 0)
                        {
                            int boneIndex = shp.BoneIndex;


                            // Create the Transform Matrix4
                            OpenTK.Vector3 mPos = new OpenTK.Vector3(
                                model.Skeleton.Bones[boneIndex].Position.X,
                                model.Skeleton.Bones[boneIndex].Position.Y,
                                model.Skeleton.Bones[boneIndex].Position.Z);

                            OpenTK.Quaternion mRot;
                            OpenTK.Vector3    v3 = new OpenTK.Vector3(
                                model.Skeleton.Bones[boneIndex].Rotation.X,
                                model.Skeleton.Bones[boneIndex].Rotation.Y,
                                model.Skeleton.Bones[boneIndex].Rotation.Z
                                );
                            if (model.Skeleton.Bones[boneIndex].FlagsRotation == BoneFlagsRotation.Quaternion)
                            {
                                mRot = new OpenTK.Quaternion(v3, model.Skeleton.Bones[boneIndex].Rotation.W);
                            }
                            else if (model.Skeleton.Bones[boneIndex].FlagsRotation == BoneFlagsRotation.EulerXYZ)
                            {
                                mRot = new OpenTK.Quaternion(v3);
                            }
                            else
                            {
                                mRot = new OpenTK.Quaternion();
                            }
                            OpenTK.Vector3 mSca = new OpenTK.Vector3(
                                model.Skeleton.Bones[boneIndex].Scale.X,
                                model.Skeleton.Bones[boneIndex].Scale.Y,
                                model.Skeleton.Bones[boneIndex].Scale.Z);

                            OpenTK.Matrix4 NoBindFix = OpenTK.Matrix4.CreateScale(mSca) * OpenTK.Matrix4.CreateFromQuaternion(mRot) * OpenTK.Matrix4.CreateTranslation(mPos);
                            v.pos = OpenTK.Vector3.TransformPosition(v.pos, NoBindFix);
                            v.nrm = OpenTK.Vector3.TransformNormal(v.nrm, NoBindFix);
                        }
                    }
                    catch //Matrix failed. Print the coordinate data of the bone
                    {
                        //Console.WriteLine(model.Skeleton.bones[fshp.BoneIndex].Text);
                        //Console.WriteLine(model.Skeleton.bones[fshp.BoneIndex].GetPosition());
                        //Console.WriteLine(model.Skeleton.bones[fshp.BoneIndex].GetRotation());
                        //Console.WriteLine(model.Skeleton.bones[fshp.BoneIndex].GetScale());
                    }
                }

                vertices.Add(v);
            }

            // Write Vertex Data
            writer.WriteStartElement("Vertices");
            writer.WriteAttributeString("VertexCount", vtx.VertexCount.ToString());
            for (int i = 0; i < vertices.Count; i++)
            {
                writer.WriteStartElement("Vertex");

                writer.WriteAttributeString("Index", i.ToString());
                writer.WriteAttributeString("Position0", Program.Vector3ToString(vertices[i].pos));
                writer.WriteAttributeString("Position1", Program.Vector3ToString(vertices[i].pos1)); Program.AssertAndLog(Program.ErrorType.eVertexPosSet, vertices[i].pos1 == OpenTK.Vector3.Zero, $"Vertex index {i} pos1 is set to {vertices[i].pos1} and not 0");     // Add C++ support
                writer.WriteAttributeString("Position2", Program.Vector3ToString(vertices[i].pos2)); Program.AssertAndLog(Program.ErrorType.eVertexPosSet, vertices[i].pos2 == OpenTK.Vector3.Zero, $"Vertex index {i} pos2 is set to {vertices[i].pos2} and not 0");     // Add C++ support
                writer.WriteAttributeString("Normal", Program.Vector3ToString(vertices[i].nrm));
                writer.WriteAttributeString("UV0", Program.Vector2ToString(vertices[i].uv0));
                writer.WriteAttributeString("UV1", Program.Vector2ToString(vertices[i].uv1));
                writer.WriteAttributeString("UV2", Program.Vector2ToString(vertices[i].uv2));
                writer.WriteAttributeString("Color0", Program.Vector4ToString(vertices[i].col));
                writer.WriteAttributeString("Color1", Program.Vector4ToString(vertices[i].col2)); Program.AssertAndLog(Program.ErrorType.eVertexPosSet, vertices[i].col2 == OpenTK.Vector4.One, $"Vertex index {i} col2 is set to {vertices[i].col2} and not One");        // Add C++ support. Unknown use of col2
                writer.WriteAttributeString("Tangent", Program.Vector4ToString(vertices[i].tan));
                writer.WriteAttributeString("Binormal", Program.Vector4ToString(vertices[i].bitan));

                string tempBoneWeights = "";
                foreach (var w in vertices[i].boneWeights)
                {
                    tempBoneWeights += (w.ToString() + ',');
                }
                tempBoneWeights = tempBoneWeights.Trim(',');
                writer.WriteAttributeString("BlendWeights", tempBoneWeights);

                string tempBoneIds = "";
                foreach (var w in vertices[i].boneIds)
                {
                    tempBoneIds += (w.ToString() + ',');
                }
                tempBoneIds = tempBoneIds.Trim(',');
                writer.WriteAttributeString("BlendIndex", tempBoneIds);
                writer.WriteEndElement();
            }
            writer.WriteEndElement();
        }
示例#4
0
 public JPBone(JPSkeleton jpSkeleton, short boneIndex)
 {
     skeletonParent = jpSkeleton;
     index          = boneIndex;
 }