Beispiel #1
0
        void ParseJoint(Lexer parser, MD5Joint joint, JointQuat defaultPose)
        {
            // parse name
            parser.ReadToken(out var token); joint.name = token;

            // parse parent
            var num = parser.ParseInt();

            if (num < 0)
            {
                joint.parent = null;
            }
            else
            {
                if (num >= joints.Length - 1)
                {
                    parser.Error($"Invalid parent for joint '{joint.name}'");
                }
                joint.parent = joints[num];
            }

            // parse default pose
            parser.Parse1DMatrix(3, &defaultPose.t.x);
            parser.Parse1DMatrix(3, &defaultPose.q.x);
            defaultPose.q.w = defaultPose.q.CalcW();
        }
        private void refreshTreeView()
        {
            treeView1.Nodes.Clear();
            if (md5model == null)
            {
                return;
            }
            TreeNode root         = new TreeNode("MD5Model");
            TreeNode fileName     = new TreeNode("FileName");
            TreeNode fileNameText = new TreeNode(md5model.getName());

            fileName.Nodes.Add(fileNameText);
            root.Nodes.Add(fileName);
            TreeNode commandLine     = new TreeNode("commandLine");
            TreeNode commandLineText = new TreeNode(md5model.getCommandLine());

            commandLine.Nodes.Add(commandLineText);
            root.Nodes.Add(commandLine);
            TreeNode meshes = new TreeNode("meshes (" + md5model.getMeshCount() + ")");

            for (int i = 0; i < md5model.getMeshCount(); i++)
            {
                TreeNode mesh         = new TreeNode("mesh " + i);
                TreeNode materialName = new TreeNode("material");
                materialName.Nodes.Add(new TreeNode(md5model.getMeshMaterialName(i)));
                mesh.Nodes.Add(materialName);
                TreeNode vertices = new TreeNode("vertices (" + md5model.getMeshVertexCount(i) + ")");

                mesh.Nodes.Add(vertices);
                TreeNode triangles = new TreeNode("triangles (" + md5model.getMeshTriangleCount(i) + ")");

                mesh.Nodes.Add(triangles);
                meshes.Nodes.Add(mesh);
            }
            root.Nodes.Add(meshes);
            TreeNode joints = new TreeNode("joints (" + md5model.getJointCount() + ")");

            for (int i = 0; i < md5model.getJointCount(); i++)
            {
                MD5Joint j              = md5model.getJoint(i);
                TreeNode joint          = new TreeNode("joint " + i + " " + j.getName());
                TreeNode jointName      = new TreeNode("name");
                TreeNode jointNameValue = new TreeNode(j.getName());
                jointName.Nodes.Add(jointNameValue);
                joint.Nodes.Add(jointName);
                TreeNode jointOrigin      = new TreeNode("Ofs");
                TreeNode jointOriginValue = new TreeNode(j.getOfs().ToString());
                jointOrigin.Nodes.Add(jointOriginValue);
                joint.Nodes.Add(jointOrigin);
                TreeNode jointRot      = new TreeNode("Rot");
                TreeNode jointRotValue = new TreeNode(j.getRot().ToString());
                jointRot.Nodes.Add(jointRotValue);
                joint.Nodes.Add(jointRot);
                joints.Nodes.Add(joint);
            }
            root.Nodes.Add(joints);
            treeView1.Nodes.Add(root);
        }
Beispiel #3
0
        void ComputeFrameSkeletons(MD5Hierarchy[] hierarchy, MD5Frame[] baseFrames, MD5Frame[] frames)
        {
            int i, j;
            int numberOfJoints = hierarchy.Length;

            numberOfFrames = frames.Length;

            skeletons = new MD5FrameSkeleton[numberOfFrames];

            for (i = 0; i < numberOfFrames; i++)
            {
                skeletons[i]        = new MD5FrameSkeleton();
                skeletons[i].Joints = new MD5Joint[numberOfJoints];

                for (j = 0; j < numberOfJoints; j++)
                {
                    int      flags     = hierarchy[j].Flags;
                    int      dataIndex = hierarchy[j].StartIndex;
                    MD5Joint joint     = new MD5Joint();

                    joint.Name     = hierarchy[j].Name;
                    joint.Parent   = hierarchy[j].Parent;
                    joint.Position = new Vector3(baseFrames[j].Data[0], baseFrames[j].Data[2], baseFrames[j].Data[1]);
                    joint.Rotation = new Quaternion(baseFrames[j].Data[3], baseFrames[j].Data[5], baseFrames[j].Data[4], ComputeW(baseFrames[j].Data[3], baseFrames[j].Data[5], baseFrames[j].Data[4]));

                    #region Replace Joint components with data from the Frame
                    if ((flags & 1) == 1)
                    {
                        joint.Position.X = frames[i].Data[dataIndex];
                        dataIndex++;
                    }
                    if ((flags & 2) == 2)
                    {
                        joint.Position.Z = frames[i].Data[dataIndex];
                        dataIndex++;
                    }
                    if ((flags & 4) == 4)
                    {
                        joint.Position.Y = frames[i].Data[dataIndex];
                        dataIndex++;
                    }

                    if ((flags & 8) == 8)
                    {
                        joint.Rotation.X = frames[i].Data[dataIndex];
                        dataIndex++;
                    }
                    if ((flags & 16) == 16)
                    {
                        joint.Rotation.Z = frames[i].Data[dataIndex];
                        dataIndex++;
                    }
                    if ((flags & 32) == 32)
                    {
                        joint.Rotation.Y = frames[i].Data[dataIndex];
                        dataIndex++;
                    }

                    joint.Rotation = new Quaternion(joint.Rotation.X, joint.Rotation.Y, joint.Rotation.Z, ComputeW(joint.Rotation.X, joint.Rotation.Y, joint.Rotation.Z));

                    if (joint.Parent == -1)
                    {
                        Vector3 scale;

                        Matrix m = Matrix.CreateFromQuaternion(joint.Rotation) * Matrix.CreateTranslation(joint.Position);
                        m *= Matrix.CreateScale(-1, 1, 1);

                        m.Decompose(out scale, out joint.Rotation, out joint.Position);
                    }
                    #endregion

                    #region Tranform by the parent joint's data
                    if (hierarchy[j].Parent >= 0)
                    {
                        Vector3    rotatedPosition      = Vector3.Transform(joint.Position, skeletons[i].Joints[hierarchy[j].Parent].Rotation);
                        Quaternion concatenatedRotation = Quaternion.Concatenate(joint.Rotation, skeletons[i].Joints[hierarchy[j].Parent].Rotation);

                        joint.Position = skeletons[i].Joints[hierarchy[j].Parent].Position + rotatedPosition;
                        joint.Rotation = Quaternion.Normalize(concatenatedRotation);
                    }

                    // If this is the root bone, strip out the position data and store it to be used later
                    else
                    {
                        skeletons[i].RootPosition = joint.Position;
                        joint.Position            = Vector3.Zero;//new Vector3(baseFrames[0].Data[0], baseFrames[0].Data[2], baseFrames[0].Data[1]);
                    }
                    #endregion

                    skeletons[i].Joints[j] = joint;
                }
            }
        }
Beispiel #4
0
        public MD5MeshContent(string filename)
        {
            int    i, j;
            string line;

            string[] split;

            if (!File.Exists(filename))
            {
                throw new FileNotFoundException("File " + filename + " not found in directory " + Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + ".");
            }

            FileStream   fs     = new FileStream(filename, FileMode.Open);
            StreamReader reader = new StreamReader(fs);

            #region LINE 1 - MD5Version
            line = MD5MeshContent.ReadLine(reader);
            if (!line.StartsWith("MD5Version"))
            {
                throw new Exception("File " + filename + "is not a valid .md5mesh.");
            }
            int Version = int.Parse(line.Substring(10));
            #endregion

            #region LINE 2 - commandline (discard)
            line = MD5MeshContent.ReadLine(reader);
            #endregion

            #region LINE 3 - numJoints
            line = MD5MeshContent.LookForLine(reader, "numJoints ");
            int NumberOfJoints = int.Parse(line.Substring(10));
            #endregion

            #region LINE 4 - numMeshes
            line = MD5MeshContent.LookForLine(reader, "numMeshes ");
            int NumberOfMeshes = int.Parse(line.Substring(10));
            #endregion

            #region CHUNK - Joints
            line = MD5MeshContent.LookForLine(reader, "joints");
            MD5Joint[] joints = new MD5Joint[NumberOfJoints];
            for (i = 0; i < joints.Length; i++)
            {
                MD5Joint joint = new MD5Joint();
                line = MD5MeshContent.ReadLine(reader);

                if (line.StartsWith("}"))
                {
                    throw new Exception("MD5Mesh " + filename + " is invalid: Joints chuck has missing joints.");
                }

                //Line format: "name" parent ( x y z ) ( rX rY rZ )
                split = line.Split(new Char[] { '"', '"', '(', ')', '(', ')' });
                for (j = 0; j < split.Length; j++)
                {
                    split[j] = split[j].Trim();
                }

                if (split.Length != 7)
                {
                    throw new Exception("MD5Mesh " + filename + " is invalid: Joint " + i + " appears to be malformed. ");
                }

                joint.Name   = split[1];
                joint.Parent = int.Parse(split[2]);

                // Position
                string[] pos = split[3].Split(' ', ' ');
                if (pos.Length != 3)
                {
                    throw new Exception("MD5Mesh " + filename + " is invalid: Joint " + i + "'s position data appears to be malformed. ");
                }

                joint.Position = new Vector3(float.Parse(pos[0]), float.Parse(pos[2]), float.Parse(pos[1]));

                // Rotation
                string[] rot = split[5].Split(' ', ' ');
                if (rot.Length != 3)
                {
                    throw new Exception("MD5Mesh " + filename + " is invalid: Joint " + i + "'s rotation data appears to be malformed. ");
                }
                float x, y, z, w;
                x = float.Parse(rot[0]);
                y = float.Parse(rot[2]);
                z = float.Parse(rot[1]);
                w = MD5AnimationContent.ComputeW(x, y, z);

                joint.Rotation = new Quaternion(x, y, z, w);

                joints[i] = joint;
            }
            #endregion

            #region CHUNKS - Meshes
            MD5Submesh[] submeshes = new MD5Submesh[NumberOfMeshes];
            for (i = 0; i < NumberOfMeshes; i++)
            {
                #region Pull the Mesh Chunk Out
                string chunk = "";
                line = MD5MeshContent.LookForLine(reader, "mesh {");

                while (!line.Contains("}"))
                {
                    if (reader.EndOfStream)
                    {
                        throw new Exception("MD5Mesh " + filename + " is invalid: Mesh chunk " + i + " is malformed.");
                    }

                    line   = MD5MeshContent.ReadLine(reader);
                    chunk += line + '\n';
                }
                StringReader sr = new StringReader(chunk);
                #endregion

                MD5Submesh mesh = new MD5Submesh();

                #region mesh.Shader
                line = MD5MeshContent.LookForLine(sr, "shader");
                line = line.Substring(8);
                if (line.LastIndexOf('.') > 0)
                {
                    line = line.Substring(0, line.LastIndexOf('.'));
                }
                if (line.Length > 1 && line[0] == '/' && line[1] == '/')
                {
                    line = line.Substring(2);
                }
                if (line.Length > 1 && line[line.Length - 1] == '"')
                {
                    line = mesh.Shader.Substring(0, line.Length - 1);
                }

                mesh.Shader = line;
                #endregion

                line = MD5MeshContent.LookForLine(sr, "numverts");
                mesh.NumberOfVertices = int.Parse(line.Substring(9));
                mesh.Vertices         = new MD5Vertex[mesh.NumberOfVertices];

                #region mesh.Vertices[j]
                for (j = 0; j < mesh.NumberOfVertices; j++)
                {
                    MD5Vertex vert;

                    line  = MD5MeshContent.LookForLine(sr, "vert");
                    split = line.Split(new char[] { ' ', '(', ' ', ')', ' ' });

                    if (int.Parse(split[1]) != j)
                    {
                        throw new Exception("MD5Mesh " + filename + " is invalid: Vertex " + j + " in mesh chunk " + i + " is missing.");
                    }

                    vert.S               = float.Parse(split[4]);
                    vert.T               = float.Parse(split[5]);
                    vert.FirstWeight     = int.Parse(split[8]);
                    vert.NumberOfWeights = int.Parse(split[9]);

                    mesh.Vertices[j] = vert;
                }
                #endregion

                line = MD5MeshContent.LookForLine(sr, "numtris");
                mesh.NumberOfTriangles = int.Parse(line.Substring(8));
                mesh.Triangles         = new MD5Triangle[mesh.NumberOfTriangles];

                #region mesh.Triangles[j]
                for (j = 0; j < mesh.NumberOfTriangles; j++)
                {
                    MD5Triangle tri = new MD5Triangle();

                    line  = MD5MeshContent.LookForLine(sr, "tri");
                    split = line.Split(new char[] { ' ' });

                    if (int.Parse(split[1]) != j)
                    {
                        throw new Exception("MD5Mesh " + filename + " is invalid: Triangle " + j + " in mesh chunk " + i + " is missing.");
                    }

                    tri.Indices = new int[] { int.Parse(split[2]), int.Parse(split[3]), int.Parse(split[4]) };

                    mesh.Triangles[j] = tri;
                }
                #endregion

                line = MD5MeshContent.LookForLine(sr, "numweights");
                mesh.NumberOfWeights = int.Parse(line.Substring(10));
                mesh.Weights         = new MD5Weight[mesh.NumberOfWeights];

                #region mesh.Weights[j]
                for (j = 0; j < mesh.NumberOfWeights; j++)
                {
                    MD5Weight weight = new MD5Weight();

                    line  = MD5MeshContent.LookForLine(sr, "weight");
                    split = line.Split(new char[] { ' ', '(', ')' });

                    if (int.Parse(split[1]) != j)
                    {
                        throw new Exception("MD5Mesh " + filename + " is invalid: Weight " + j + " in mesh chunk " + i + " is missing.");
                    }

                    weight.Joint    = int.Parse(split[2]);
                    weight.Weight   = float.Parse(split[3]);
                    weight.Position = new Vector3(float.Parse(split[6]), float.Parse(split[8]), float.Parse(split[7]));

                    mesh.Weights[j] = weight;
                }
                #endregion

                submeshes[i] = mesh;
            }
            #endregion

            this.Filename  = filename.Substring(filename.LastIndexOf("Content") + 8);
            this.Joints    = joints;
            this.Submeshes = submeshes;
        }