public FileInfo MtlFile; // The obj .mtl file that we write. Should be RootNode.Name + "_mtl.mtl". public void GetMtlFileName(CgfData cgfData) // Get FileInfo Mtlfile name from the MtlName chunks and read it. Assume pwd if no objectdir. { Datafile = cgfData; DirectoryInfo currentDir = new DirectoryInfo(Directory.GetCurrentDirectory()); String[] stringSeparators = new string[] { @"\", @"/" }; // to split up the paths String[] result; // carries the results of the split //Console.WriteLine("***** In MaterialFile.cs *****"); MtlFile = new FileInfo(Datafile.RootNode.Name + "_mtl.mtl"); // Console.WriteLine("Current dir is {0}", currentDir.FullName); // Find the number of material chunks. if 1, then name is the mtl file name. If many, find type 0x01. foreach (CgfData.ChunkMtlName mtlChunk in Datafile.CgfChunks.Where(a => a.chunkType == ChunkType.MtlName)) { // mtlChunk.WriteChunk(); if (mtlChunk.version == 0x800) { // this is a parent material. Should be only one. Don't care about the rest. if (mtlChunk.MatType == 0x01 || mtlChunk.MatType == 0x10) { // parent material. This is the one we want. //Console.WriteLine("Mat type 0x01 found."); if (mtlChunk.Name.Contains(@"\") || mtlChunk.Name.Contains(@"/")) { // I'm a qualified path, but don't know if objectdir exists. Need to get name+.mtl without the path info. result = mtlChunk.Name.Split(stringSeparators, StringSplitOptions.None); MtlFileName = result[result.Length - 1]; // Last element in mtlChunk.Name //Console.WriteLine("MtlFileName (has slash) is {0}", MtlFileName); if (Datafile.Args.ObjectDir != null) // Check to see if objectdir was set. if not, just check local dir { if (MtlFileName.EndsWith(".mtl")) { XmlMtlFile = new FileInfo(Datafile.Args.ObjectDir + @"\" + mtlChunk.Name); } else { XmlMtlFile = new FileInfo(Datafile.Args.ObjectDir + @"\" + mtlChunk.Name + ".mtl"); } } else { // No objectdir provided. Only check current directory. if (MtlFileName.EndsWith(".mtl")) { XmlMtlFile = new FileInfo(currentDir + @"\" + MtlFileName); } else { XmlMtlFile = new FileInfo(currentDir + @"\" + MtlFileName + ".mtl"); } } } else { MtlFileName = mtlChunk.Name; // will add .mtl later. //Console.WriteLine("MtlFileName (no slash) is {0}", MtlFileName); XmlMtlFile = new FileInfo(currentDir + @"\" + MtlFileName + ".mtl"); } //Console.WriteLine("MtlFile.Fullname is {0}", XmlMtlFile.FullName); if (XmlMtlFile.Exists) { //Console.WriteLine("*** Found material file {0}.", XmlMtlFile.FullName); ReadMtlFile(XmlMtlFile); } else { Console.WriteLine("*** 0x800 Unable to find material file {0}. I'm probably going to not work well.", XmlMtlFile.FullName); // Set up a dummy material and return. MtlFormat material = new MtlFormat(); material.MaterialName = Datafile.RootNode.Name; // since there is no Name, use the node name. material.Diffuse.Red = 1; material.Diffuse.Green = 0; material.Diffuse.Blue = 1; Materials.Add(material); MaterialNameArray = new MtlFormat[Materials.Count]; MaterialNameArray = Materials.ToArray(); } } // Not a material type 0x01 or 0x10. Will be a child material. Continue to next mtlname chunk } else // version 0x802 file. There will be just one, so return after it is found and read { // Process version 0x802 files //Console.WriteLine("In 0x802 section"); if (mtlChunk.Name.Contains(@"\") || mtlChunk.Name.Contains(@"/")) { // I'm a qualified path, but don't know if objectdir exists. Need to get name+.mtl without the path info. // Several cases here. Sometimes it has the .mtl ending, sometimes it doesn't. GRRR result = mtlChunk.Name.Split(stringSeparators, StringSplitOptions.None); MtlFileName = result[result.Length - 1]; // Last element in mtlChunk.Name //Console.WriteLine("MtlFileName is {0}", MtlFileName); if (Datafile.Args.ObjectDir != null) { if (MtlFileName.EndsWith(".mtl")) { XmlMtlFile = new FileInfo(Datafile.Args.ObjectDir + @"\" + mtlChunk.Name); } else { XmlMtlFile = new FileInfo(Datafile.Args.ObjectDir + @"\" + mtlChunk.Name + ".mtl"); } } else { // No objectdir provided. Only check current directory. if (MtlFileName.EndsWith(".mtl")) { XmlMtlFile = new FileInfo(currentDir + @"\" + MtlFileName); } else { XmlMtlFile = new FileInfo(currentDir + @"\" + MtlFileName + ".mtl"); } } } else { // It's just a file name. Search only in current directory. MtlFileName = mtlChunk.Name; XmlMtlFile = new FileInfo(currentDir + @"\" + MtlFileName + ".mtl"); //Console.WriteLine("MtlFileName (short version) is {0}", MtlFileName); } //Console.WriteLine("MtlFile.Fullname is {0}", XmlMtlFile.FullName); if (XmlMtlFile.Exists) { Console.WriteLine("*** 0x802 Found material file {0}.", XmlMtlFile.FullName); ReadMtlFile(XmlMtlFile); } else { Console.WriteLine(); Console.WriteLine("*** 0x802 Unable to find material file {0}. I'm probably going to not work well.", XmlMtlFile.FullName); Console.WriteLine(); // Set up a dummy material and return. // Console.WriteLine("Unable to find material file {0}. Using group names.", Materialfile.FullName); MtlFormat material = new MtlFormat(); material.MaterialName = Datafile.RootNode.Name; // since there is no Name, use the node name. material.Diffuse.Red = 1; material.Diffuse.Green = 0; material.Diffuse.Blue = 1; Materials.Add(material); MaterialNameArray = new MtlFormat[Materials.Count]; MaterialNameArray = Materials.ToArray(); } return; } } return; }
public void ReadMtlFile(FileInfo Materialfile) // reads the mtl file, so we can populate the MaterialNames array and assign those material names to the meshes { // MtlFile should be an object to the Material File for the CgfData. We need to populate the MaterialNameArray array with the objects. // If I was smart I'd actually get Blender to add this to /scripts/addons/io_scene_obj/import_obj.py // Console.WriteLine("Mtl File name is {0}", Materialfile.FullName); XElement materialmap = XElement.Load(Materialfile.FullName); if (materialmap.Attribute("MtlFlags").Value == "524288") { // Short mtl file with just one material. No name, so set it to the object name. //Console.WriteLine("Found material with 524288"); MtlFormat material = new MtlFormat(); //Console.WriteLine("Attribute: {0}", Datafile.RootNode.Name); material.MaterialName = Datafile.RootNode.Name; // since there is no Name, use the node name. material.Flags = materialmap.Attribute("MtlFlags").Value; material.Shader = materialmap.Attribute("Shader").Value; material.GenMask = materialmap.Attribute("GenMask").Value; material.StringGenMask = materialmap.Attribute("StringGenMask").Value; material.SurfaceType = materialmap.Attribute("SurfaceType").Value; material.MatTemplate = materialmap.Attribute("MatTemplate").Value; String tmpDiffuse = materialmap.Attribute("Diffuse").Value; string[] parse = tmpDiffuse.Split(','); material.Diffuse.Red = float.Parse(parse[0]); material.Diffuse.Green = float.Parse(parse[1]); material.Diffuse.Blue = float.Parse(parse[2]); String tmpSpec = materialmap.Attribute("Specular").Value; string[] parsespec = tmpSpec.Split(','); material.Specular.Red = float.Parse(parsespec[0]); material.Specular.Blue = float.Parse(parsespec[1]); material.Specular.Green = float.Parse(parsespec[2]); String tmpEmissive = materialmap.Attribute("Emissive").Value; string[] parseemissive = tmpEmissive.Split(','); material.Emissive.Red = float.Parse(parseemissive[0]); material.Emissive.Blue = float.Parse(parseemissive[1]); material.Emissive.Green = float.Parse(parseemissive[2]); material.Shininess = float.Parse(materialmap.Attribute("Shininess").Value); material.Opacity = float.Parse(materialmap.Attribute("Opacity").Value); // now loop for all the textures int i = 0; foreach (XElement tex in materialmap.Descendants("Texture")) { Texture temptex = new Texture(); temptex.Map = tex.Attribute("Map").Value; temptex.File = tex.Attribute("File").Value; material.Textures.Add(temptex); //Console.WriteLine("Texture File found: {0}", material.Textures[i].File); i++; } Materials.Add(material); } else // more complicated material file, with Submaterials attribute { foreach (XElement mat in materialmap.Descendants("SubMaterials")) { //var matElement = mat.Element("Material"); //Console.WriteLine("SubMat {0}", mat); foreach (XElement submat in mat.Descendants("Material")) { MtlFormat material = new MtlFormat(); //Console.WriteLine("Attribute: {0}", submat.Attribute("Name")); material.MaterialName = submat.Attribute("Name").Value; material.Flags = submat.Attribute("MtlFlags").Value; material.Shader = submat.Attribute("Shader").Value; material.GenMask = submat.Attribute("GenMask").Value; material.StringGenMask = submat.Attribute("StringGenMask").Value; material.SurfaceType = submat.Attribute("SurfaceType").Value; material.MatTemplate = submat.Attribute("MatTemplate").Value; String tmpDiffuse = submat.Attribute("Diffuse").Value; string[] parse = tmpDiffuse.Split(','); material.Diffuse.Red = float.Parse(parse[0]); material.Diffuse.Green = float.Parse(parse[1]); material.Diffuse.Blue = float.Parse(parse[2]); String tmpSpec = submat.Attribute("Specular").Value; string[] parsespec = tmpSpec.Split(','); material.Specular.Red = float.Parse(parsespec[0]); material.Specular.Blue = float.Parse(parsespec[1]); material.Specular.Green = float.Parse(parsespec[2]); String tmpEmissive = submat.Attribute("Emissive").Value; string[] parseemissive = tmpEmissive.Split(','); material.Emissive.Red = float.Parse(parseemissive[0]); material.Emissive.Blue = float.Parse(parseemissive[1]); material.Emissive.Green = float.Parse(parseemissive[2]); if (submat.Attribute("Shininess") != null) // default set to 255. { material.Shininess = float.Parse(submat.Attribute("Shininess").Value); } //Console.WriteLine("Submat: {0}", submat.Attribute("Opacity")); if (submat.Attribute("Opacity") != null) // Default is set to 1, but if it exists grab the value. { material.Opacity = float.Parse(submat.Attribute("Opacity").Value); } // now loop for all the textures int i = 0; foreach (XElement tex in submat.Descendants("Texture")) { Texture temptex = new Texture(); temptex.Map = tex.Attribute("Map").Value; temptex.File = tex.Attribute("File").Value; material.Textures.Add(temptex); //Console.WriteLine("Texture File found: {0}", material.Textures[i].File); i++; } Materials.Add(material); } } } int length = Materials.Count; //Console.WriteLine("{0} Materials found in the material file.", length); //foreach (MtlFormat mats in Materials) //{ // Console.WriteLine("Material name is {0}", mats.MaterialName); //} MaterialNameArray = new MtlFormat[Materials.Count]; MaterialNameArray = Materials.ToArray(); }