/// <summary> /// Prepare mesh for rendering /// </summary> void PrepareMesh() { int i, j, k; meshes.Clear(); // Calculate the final Position ingame Position of all the model vertexes for (k = 0; k < numMesh; k++) { numOfFaces = model[k].numTris; vertices = new Vertex[numOfFaces * 3]; for (i = 0; i < model[k].numVert; i++) { Vector3 finalVertex = new Vector3(0, 0, 0); for (j = 0; j < model[k].verts[i].countw; j++) { MD5Weight wt = model[k].weights[model[k].verts[i].startw + j]; MD5Joint joint = skeleton[wt.joint]; Vector3 wv = MathExt.RotatePoint(ref joint.orient, ref wt.pos); finalVertex.X += (joint.pos.X + wv.X) * wt.bias; finalVertex.Y += (joint.pos.Y + wv.Y) * wt.bias; finalVertex.Z += (joint.pos.Z + wv.Z) * wt.bias; } finalVert[i] = finalVertex; } // aika laskea normaalit uudelleen? if (updateNormalsCount == FramesBetweenNormalsUpdate) { MathExt.CalcNormals(ref finalVert, ref model[k].faces, ref normals, false); updateNormalsCount = 0; } else { updateAnimCount++; } int count = 0; // Organize the final vertexes acording to the meshes triangles for (i = 0; i < model[k].numTris; i++) { vertices[count] = new Vertex(finalVert[(int)model[k].faces[i][0]], normals[(int)model[k].faces[i][0]], model[k].verts[(int)model[k].faces[i][0]].uv); vertices[count + 1] = new Vertex(finalVert[(int)model[k].faces[i][1]], normals[(int)model[k].faces[i][1]], model[k].verts[(int)model[k].faces[i][1]].uv); vertices[count + 2] = new Vertex(finalVert[(int)model[k].faces[i][2]], normals[(int)model[k].faces[i][2]], model[k].verts[(int)model[k].faces[i][2]].uv); count += 3; } meshes.Add(vertices); if (model[k].vbo != null) { model[k].vbo.Update(vertices); } } }
/// <summary> /// Prepare mesh for rendering /// </summary> void PrepareMesh() { int i, j, k; meshes.Clear(); // Calculate the final Position ingame Position of all the model vertexes for (k = 0; k < numMesh; k++) { numOfFaces = model[k].numTris; VertexBuffer = new Vertex[numOfFaces * 3]; for (i = 0; i < model[k].numVert; i++) { Vector3 finalVertex = new Vector3(0, 0, 0); for (j = 0; j < model[k].verts[i].countw; j++) { MD5Weight wt = model[k].weights[model[k].verts[i].startw + j]; MD5Joint joint = skeleton[wt.joint]; Vector3 wv = QuaternionExt.RotatePoint(joint.orient, wt.pos); finalVertex.X += (joint.pos.X + wv.X) * wt.bias; finalVertex.Y += (joint.pos.Y + wv.Y) * wt.bias; finalVertex.Z += (joint.pos.Z + wv.Z) * wt.bias; } finalVert[i] = finalVertex; } int count = 0; // Organize the final vertexes acording to the meshes triangles for (i = 0; i < model[k].numTris; i++) { VertexBuffer[count] = new Vertex(finalVert[(int)model[k].faces[i][0]], normals[(int)model[k].faces[i][0]], model[k].verts[(int)model[k].faces[i][0]].uv); VertexBuffer[count + 1] = new Vertex(finalVert[(int)model[k].faces[i][1]], normals[(int)model[k].faces[i][1]], model[k].verts[(int)model[k].faces[i][1]].uv); VertexBuffer[count + 2] = new Vertex(finalVert[(int)model[k].faces[i][2]], normals[(int)model[k].faces[i][2]], model[k].verts[(int)model[k].faces[i][2]].uv); count += 3; } meshes.Add(VertexBuffer); if (model[k].vbo != null) { model[k].vbo.Update(VertexBuffer); } } }
bool ReadWeights() { // weights Advance("numweights"); int weightNum = int.Parse(NextToken); weights = new MD5Weight[weightNum]; for (int j = 0; j < weightNum; j++) { Advance("weight"); //sanity check int currentWeightNum = int.Parse(NextToken); System.Diagnostics.Debug.Assert(j == currentWeightNum, "Invalid weight num!"); MD5Weight weight = new MD5Weight(); weight.BoneIndex = int.Parse(NextToken); weight.BiasFactor = NextFloat; weight.Vector = new Vector3(NextFloat, NextFloat, NextFloat); weights[j] = weight; } return(true); }
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; }
bool ReadMeshes() { Advance("nummeshes"); int meshNum = int.Parse(NextToken); mesh = new Mesh(); for (int i = 0; i < 1 /*meshNum*/; i++) { Advance("mesh"); // sanity check int num = int.Parse(NextToken); System.Diagnostics.Debug.Assert(num == i, "Invalid mesh num!"); // read mesh data - shader, verts Advance("shader"); string shaderPath = NextToken; FileInfo info = new FileInfo(shaderPath); string localPath = shaderPath.Insert(shaderPath.Length - info.Extension.Length, "_local"); string diffusePath = shaderPath.Insert(shaderPath.Length - info.Extension.Length, "_d"); Textures textures = new Textures(); ITexture texture = null; try { texture = TextureManager.Instance.Load(shaderPath); } catch { texture = TextureManager.Instance.Load(diffusePath); } ITexture normalMap = TextureManager.Instance.Load(localPath); textures["color"] = texture; textures["normal"] = normalMap; if (!ReadVertices()) { return(false); } if (!ReadTriangles()) { return(false); } if (!ReadWeights()) { return(false); } // let's test it VertexUnit vertexUnit = new VertexUnit(VertexFormat.PositionTexture2Tangent, vertices.Length); PositionStream positionStream = (PositionStream)vertexUnit[0]; TextureStream textureStream = (TextureStream)vertexUnit[1]; TextureStream normalStream = (TextureStream)vertexUnit[2]; for (int j = 0; j < vertices.Length; j++) { Vector3 pos = Vector3.Zero; MD5Vertex vertex = vertices[j]; for (int k = 0; k < vertex.WeightCount; k++) { MD5Weight weight = weights[vertex.WeightIndex + k]; MD5Bone bone = bones[weight.BoneIndex]; pos += weight.Vector * bone.Matrix * weight.BiasFactor; } positionStream[j] = pos; textureStream[j] = vertex.UV; normalStream[j] = vertex.UV; } // add tangent space stuff IGraphicsStream[] streams = Util.CalcTangentSpaceStreams(positionStream, textureStream, indexStream); Array.Copy(streams[0].Data, vertexUnit[3].Data, vertices.Length); Array.Copy(streams[1].Data, vertexUnit[4].Data, vertices.Length); Array.Copy(streams[2].Data, vertexUnit[5].Data, vertices.Length); //mesh.SubSets.Add( new SubSet(vertexUnit, indexStream, material)); } return(true); }