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); }
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; } } }
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; }