public static void NewJoint(StreamWriter output, ModelJoint Joint, string parentName, string jointName) { output.Write(System.Environment.NewLine + System.Environment.NewLine + "createNode joint -n \"" + jointName + "\" -p \"Joints\";"); output.Write(System.Environment.NewLine + "addAttr -ci true -sn \"liw\" -ln \"lockInfluenceWeights\" -bt \"lock\" -min 0 -max 1 -at \"bool\";"); output.Write(System.Environment.NewLine + "setAttr \".uoc\" yes;"); output.Write(System.Environment.NewLine + "setAttr \".ove\" yes;"); output.Write(System.Environment.NewLine + "setAttr \".t\" -type \"double3\" " + Joint.LocalPosition.X + " " + Joint.LocalPosition.Y + " " + Joint.LocalPosition.Z + " ;"); output.Write(System.Environment.NewLine + "setAttr \".mnrl\" -type \"double3\" -360 -360 -360 ;"); output.Write(System.Environment.NewLine + "setAttr \".mxrl\" -type \"double3\" 360 360 360 ;"); output.Write(System.Environment.NewLine + "setAttr \".radi\" 0.50;"); output.Write(System.Environment.NewLine + "setAttr \".jo\" -type \"double3\" " + Joint.LocalDirection.X + " " + Joint.LocalDirection.Y + " " + Joint.LocalDirection.Z + ";"); //output.Write(System.Environment.NewLine + "setAttr \".jo\" -type \"double3\" 0 0 0;"); output.Write(System.Environment.NewLine + "setAttr \".scale\" -type \"double3\" 1.000000 1.000000 1.000000;"); output.Write(System.Environment.NewLine + "setAttr \".scale\" -type \"double3\" 1.000000 1.000000 1.000000;"); output.Write(System.Environment.NewLine + "parent " + jointName + " " + parentName + " ;"); }
/// <summary> /// Parse the .msh file /// </summary> public static void Decode(string fileName) { // Get the right names string OutputName = Path.GetDirectoryName(fileName) + "\\" + Path.GetFileNameWithoutExtension(fileName); string ModelName = Path.GetFileNameWithoutExtension(fileName).Replace("-", "_").Replace("#", ""); using (BinaryReader reader = new BinaryReader(new FileStream(fileName, FileMode.Open))) { // Check if the msh file is setup correctly string Magic = reader.ReadFixedString(4); if (Magic != "MESH") { Console.WriteLine(String.Format("File Magic \"{0}\" does not match IS's \"MESH\"", Magic)); return; } // Skip empty models if (reader.BaseStream.Length < 55) { Console.Write("Empty Model : Skipping"); return; } // Skip to the joint data reader.Seek(36, SeekOrigin.Begin); // Get joint count int JointCount = reader.ReadInt32(); // Make a list with all joints List <ModelJoint> ModelJoints = new List <ModelJoint>(); // Go through all joints for (int j = 0; j < JointCount; j++) { //Get the position for the next joint long StreamPos = reader.BaseStream.Position + 56; // Create a new model Joint ModelJoint Joint = new ModelJoint(); // Get basic joint data int JointHash = reader.ReadInt32(); int Unk = reader.ReadInt32(); Joint.Parent = reader.ReadInt32(); // Get the joint coordinates Joint.LocalPosition = new Vector3D( System.BitConverter.ToSingle(reader.ReadBytes(4), 0), System.BitConverter.ToSingle(reader.ReadBytes(4), 0), System.BitConverter.ToSingle(reader.ReadBytes(4), 0) * -1); // Switch X and Y Axis Joint.LocalPosition = new Vector3D(Joint.LocalPosition.X, Joint.LocalPosition.Z, Joint.LocalPosition.Y); // Get the joint direction Quaternion quat = new Quaternion( System.BitConverter.ToSingle(reader.ReadBytes(4), 0), System.BitConverter.ToSingle(reader.ReadBytes(4), 0), System.BitConverter.ToSingle(reader.ReadBytes(4), 0), System.BitConverter.ToSingle(reader.ReadBytes(4), 0)); // Change it from Quaternion to Vector3D + switch axis Joint.LocalDirection = QuaternionIS.setFromQuaternion(new Quaternion( quat.X, quat.Z, quat.Y, quat.W )); // Add the joint to the list ModelJoints.Add(Joint); // Go to the next joint reader.Seek(StreamPos, SeekOrigin.Begin); } // Add a base joint for static models if (JointCount == 0) { // Make a basic joint ModelJoint Joint = new ModelJoint(); Joint.Parent = -1; Joint.LocalPosition = new Vector3D(0, 0, 0); Joint.LocalDirection = new Vector3D(0, 0, 0); // Add the joint to the list ModelJoints.Add(Joint); } // Weird extra thing that i have no idea about what it does if (reader.ReadInt32() == 2) { reader.ReadBytes(12); } reader.ReadBytes(8); // Get mesh and material count int MeshCount = reader.ReadInt32(); int MaterialCount = reader.ReadInt32(); // Make a list with all meshes List <ModelMesh> ModelMeshes = new List <ModelMesh>(); // Go through all meshes for (int i = 0; i < MeshCount; i++) { // Make a new mesh ModelMesh Mesh = new ModelMesh(); // Skip first 8 bytes reader.ReadBytes(8); // Get mesh data int WShift = reader.ReadInt32(); int VSecSize = reader.ReadInt32(); // Get size of the arrays for vertexes, UV's and weights float[,] vertexCoorValues = new float[VSecSize / 32, 3]; float[,] UVValues = new float[VSecSize / 32, 2]; float[,] WeightValues = new float[VSecSize / 32, 8]; // Check verts for models without joints if (WShift == 2) { // Create new arrays with new values float[,] vertexCoorValues2 = new float[VSecSize / 28, 3]; float[,] UVValues2 = new float[VSecSize / 28, 2]; float[,] WeightValues2 = new float[VSecSize / 28, 8]; // Go through all vertexes etc for (int h = 0; h < (VSecSize / 28); h++) { // Get next vertex pos long StreamPos = reader.BaseStream.Position + 28; // Read values vertexCoorValues2[h, 0] = System.BitConverter.ToSingle(reader.ReadBytes(4), 0); vertexCoorValues2[h, 2] = System.BitConverter.ToSingle(reader.ReadBytes(4), 0); vertexCoorValues2[h, 1] = System.BitConverter.ToSingle(reader.ReadBytes(4), 0) * -1; UVValues2[h, 0] = reader.ReadInt16() / 1024.0f; UVValues2[h, 1] = 1 - reader.ReadInt16() / 1024.0f; // Set basic weights WeightValues2[h, 0] = 0; WeightValues2[h, 4] = 1; // Go to next vertex reader.Seek(StreamPos, SeekOrigin.Begin); } // Change the arrays vertexCoorValues = vertexCoorValues2; UVValues = UVValues2; WeightValues = WeightValues2; } else if (WShift == 3) { // Go through all vertexes etc for (int h = 0; h < VSecSize / 32; h++) { // Get next vertex pos long StreamPos = reader.BaseStream.Position + 32; // Read values vertexCoorValues[h, 0] = System.BitConverter.ToSingle(reader.ReadBytes(4), 0); vertexCoorValues[h, 2] = System.BitConverter.ToSingle(reader.ReadBytes(4), 0); vertexCoorValues[h, 1] = System.BitConverter.ToSingle(reader.ReadBytes(4), 0) * -1; UVValues[h, 0] = reader.ReadInt16() / 1024.0f; UVValues[h, 1] = 1 - reader.ReadInt16() / 1024.0f; // Skip 8 bytes reader.ReadBytes(8); // Get weight percentages float weight3 = (int)reader.ReadByte(); float weight2 = (int)reader.ReadByte(); float weight1 = (int)reader.ReadByte(); float weight4 = (int)reader.ReadByte(); // Get weight joints int Joint1 = (int)reader.ReadByte() / WShift; int Joint2 = (int)reader.ReadByte() / WShift; int Joint3 = (int)reader.ReadByte() / WShift; int Joint4 = (int)reader.ReadByte() / WShift; // Get the maxweight float maxweight = 0; if (weight1 != 0) { maxweight += weight1; } if (weight2 != 0) { maxweight += weight2; } if (weight3 != 0) { maxweight += weight3; } if (weight4 != 0) { maxweight += weight4; } if (maxweight != 0) { if (weight1 != 0) { WeightValues[h, 0] = Joint1; WeightValues[h, 4] = (weight1 / 255); } if (weight2 != 0) { WeightValues[h, 1] = Joint2; WeightValues[h, 5] = (weight2 / 255); } if (weight3 != 0) { WeightValues[h, 2] = Joint3; WeightValues[h, 6] = (weight3 / 255); } if (weight4 != 0) { WeightValues[h, 3] = Joint4; WeightValues[h, 7] = (weight4 / 255); } } // Go to next vertex reader.Seek(StreamPos, SeekOrigin.Begin); } } // Get faces count int FSecSize = reader.ReadInt32(); // Make faces array float[,] FacesValues = new float[FSecSize / 6, 3]; // Read all faces for (int h = 0; h < (FSecSize / 6); h++) { FacesValues[h, 0] = reader.ReadInt16() + 1; FacesValues[h, 1] = reader.ReadInt16() + 1; FacesValues[h, 2] = reader.ReadInt16() + 1; } // Add the data to the mesh Mesh.WeightValues = WeightValues; Mesh.VertexCoordinates = vertexCoorValues; Mesh.UVValues = UVValues; Mesh.FacesValues = FacesValues; // Add the mesh to the list ModelMeshes.Add(Mesh); } // Get the amount of mtrl's in the .msh file int MaterialsCount = reader.ReadInt32(); // Make a list for the materials List <Material> MaterialList = new List <Material>(); // Loop through mtrl's for (int j = 0; j < MaterialsCount; j++) { // Check if theres a material at this position if (reader.ReadFixedString(4) != "MTRL") { Console.WriteLine("Weird position isnt a material"); continue; } // Check if its a correct material int mtrlCheck = reader.ReadInt32(); Material Mtrl = new Material(); // Set the right position if (mtrlCheck == 9) { reader.Seek(76, SeekOrigin.Current); } else { reader.Seek(124, SeekOrigin.Current); } string[] MaterialTextures = new string[5]; // Loop through materials for (int i = 0; i < 5; i++) { // Get the length of the texture int TextureNameLenth = reader.ReadInt32(); string TextureName = ""; if (TextureNameLenth < 5) { TextureName = "unknown_image.dds"; } else { TextureName = Path.GetFileName(reader.ReadFixedString(TextureNameLenth)); } MaterialTextures[i] = TextureName; } // Skip to the next material reader.Seek(40, SeekOrigin.Current); if (mtrlCheck != 9) { reader.Seek(4, SeekOrigin.Current); } // Get the material name string MaterialName = ""; if (MaterialsCount == 1) { MaterialName = "mtl_" + ModelName; } else { MaterialName = "mtl_" + ModelName + "_" + j; } // Set the material data and add it to the list Mtrl.Name = MaterialName; Mtrl.ColorMap = MaterialTextures[0]; Mtrl.NormalMap = MaterialTextures[1]; MaterialList.Add(Mtrl); } // Export the model to .obj ObjUtil.ExportObjFile(OutputName, ModelMeshes, MaterialList); // Export the model to .ma MayaUtil.ExportMaFile(OutputName, ModelMeshes, MaterialList, ModelJoints); } // Add a line in the console Console.WriteLine("Converted model : " + ModelName); }