Esempio n. 1
0
        public CryEngine(String fileName, String dataDir)
        {
            this.InputFile = fileName;

            FileInfo        inputFile  = new FileInfo(fileName);
            List <FileInfo> inputFiles = new List <FileInfo> {
                inputFile
            };

            // Validate file extension - handles .cgam / skinm
            if (!CryEngine._validExtensions.Contains(inputFile.Extension))
            {
                Utils.Log(LogLevelEnum.Debug, "Warning: Unsupported file extension - please use a cga, cgf, chr or skin file");
                throw new FileLoadException("Warning: Unsupported file extension - please use a cga, cgf, chr or skin file", fileName);
            }

            #region m-File Auto-Detection

            FileInfo mFile = new FileInfo(Path.ChangeExtension(fileName, String.Format("{0}m", inputFile.Extension)));

            if (mFile.Exists)
            {
                Utils.Log(LogLevelEnum.Debug, "Found mFile file {0}", mFile.Name);

                // Add to list of files to process
                inputFiles.Add(mFile);
            }

            #endregion

            this.Models = new List <CryEngine_Core.Model> {
            };

            foreach (var file in inputFiles)
            {
                CryEngine_Core.Model model = CryEngine_Core.Model.FromFile(file.FullName);
                this.RootNode = this.RootNode ?? model.RootNode;
                this.Models.Add(model);
            }

            foreach (CryEngine_Core.ChunkMtlName mtlChunk in this.Models.SelectMany(a => a.ChunkMap.Values).Where(c => c.ChunkType == ChunkTypeEnum.MtlName))
            {
                // Don't process child materials for now
                if (mtlChunk.MatType == MtlNameTypeEnum.Child)
                {
                    continue;
                }

                String cleanName = mtlChunk.Name;

                FileInfo materialFile;

                if (mtlChunk.Name.Contains(@"/") || mtlChunk.Name.Contains(@"\"))
                {
                    // The mtlname has a path.  Most likely starts at the Objects directory.
                    //
                    string[] stringSeparators = new string[] { @"\", @"/" };
                    string[] result;
                    // if objectdir is provided, check objectdir + mtlchunk.name
                    if (dataDir != null)
                    {
                        materialFile = new FileInfo(Path.Combine(dataDir, mtlChunk.Name));
                    }
                    else
                    {
                        // object dir not provided, but we have a path.  Just grab the last part of the name and check the dir of the cga file
                        result       = mtlChunk.Name.Split(stringSeparators, StringSplitOptions.None);
                        materialFile = new FileInfo(result[result.Length - 1]);
                    }
                }
                else
                {
                    var charsToClean = cleanName.ToCharArray().Intersect(Path.GetInvalidFileNameChars()).ToArray();
                    if (charsToClean.Length > 0)
                    {
                        foreach (Char character in charsToClean)
                        {
                            cleanName = cleanName.Replace(character.ToString(), "");
                        }
                    }
                    materialFile = new FileInfo(Path.Combine(Path.GetDirectoryName(fileName), cleanName));
                }
                // First try relative to file being processed
                if (materialFile.Extension != "mtl")
                {
                    materialFile = new FileInfo(Path.ChangeExtension(materialFile.FullName, "mtl"));
                }

                // Then try just the last part of the chunk, relative to the file being processed
                if (!materialFile.Exists)
                {
                    materialFile = new FileInfo(Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileName(cleanName)));
                }
                if (materialFile.Extension != "mtl")
                {
                    materialFile = new FileInfo(Path.ChangeExtension(materialFile.FullName, "mtl"));
                }

                // Then try relative to the ObjectDir
                if (!materialFile.Exists && dataDir != null)
                {
                    materialFile = new FileInfo(Path.Combine(dataDir, cleanName));
                }
                if (materialFile.Extension != "mtl")
                {
                    materialFile = new FileInfo(Path.ChangeExtension(materialFile.FullName, "mtl"));
                }

                // Then try just the fileName.mtl
                if (!materialFile.Exists)
                {
                    materialFile = new FileInfo(fileName);
                }
                if (materialFile.Extension != "mtl")
                {
                    materialFile = new FileInfo(Path.ChangeExtension(materialFile.FullName, "mtl"));
                }

                // TODO: Try more paths

                CryEngine_Core.Material material = CryEngine_Core.Material.FromFile(materialFile);

                if (material != null)
                {
                    // Utils.Log(LogLevelEnum.Debug, "Located material file {0}", materialFile.Name);

                    //this.Materials = CryEngine.FlattenMaterials(material).Skip(1).ToArray();
                    this.Materials = CryEngine.FlattenMaterials(material).Where(m => m.Textures != null).ToArray();
                    Console.WriteLine("Flattened material {0}", material.Name);

                    // Early return - we have the material map
                    return;
                }
                else
                {
                    // Utils.Log(LogLevelEnum.Debug, "Unable to locate material file {0}.mtl", mtlChunk.Name);
                }
            }

            // Utils.Log(LogLevelEnum.Debug, "Unable to locate any material file");

            this.Materials = new CryEngine_Core.Material[] { };
        }
        public CryEngine(String fileName, String dataDir)
        {
            this.InputFile = fileName;

            FileInfo        inputFile  = new FileInfo(fileName);
            List <FileInfo> inputFiles = new List <FileInfo> {
                inputFile
            };

            // Validate file extension - handles .cgam / skinm
            if (!CryEngine._validExtensions.Contains(inputFile.Extension))
            {
                Utils.Log(LogLevelEnum.Debug, "Warning: Unsupported file extension - please use a cga, cgf, chr or skin file");
                throw new FileLoadException("Warning: Unsupported file extension - please use a cga, cgf, chr or skin file", fileName);
            }

            #region m-File Auto-Detection

            FileInfo mFile = new FileInfo(Path.ChangeExtension(fileName, String.Format("{0}m", inputFile.Extension)));

            if (mFile.Exists)
            {
                Utils.Log(LogLevelEnum.Debug, "Found geometry file {0}", mFile.Name);

                // Add to list of files to process
                inputFiles.Add(mFile);
            }

            #endregion

            this.Models = new List <CryEngine_Core.Model> {
            };

            foreach (var file in inputFiles)
            {
                // Each file (.cga and .cgam if applicable) will have its own RootNode.  This can cause problems.  .cga files with a .cgam files won't have geometry for the one root node.
                CryEngine_Core.Model model = CryEngine_Core.Model.FromFile(file.FullName);
                if (this.RootNode == null)
                {
                    RootNode = model.RootNode;  // This makes the assumption that we read the .cga file before the .cgam file.
                }
                //this.RootNode = this.RootNode ?? model.RootNode;
                this.Bones = this.Bones ?? model.Bones;
                this.Models.Add(model);
            }
            SkinningInfo = ConsolidateSkinningInfo();
            // For eanch node with geometry info, populate that node's Mesh Chunk GeometryInfo with the geometry data.
            ConsolidateGeometryInfo();

            #region Get material file name
            // Get the material file name
            foreach (CryEngine_Core.ChunkMtlName mtlChunk in this.Models.SelectMany(a => a.ChunkMap.Values).Where(c => c.ChunkType == ChunkTypeEnum.MtlName))
            {
                // Don't process child or collision materials for now
                if (mtlChunk.MatType == MtlNameTypeEnum.Child || mtlChunk.MatType == MtlNameTypeEnum.Unknown1)
                {
                    continue;
                }

                // The Replace part is for SC files that point to a _core material file that doesn't exist.
                String cleanName = mtlChunk.Name.Replace("_core", "");

                FileInfo materialFile;

                if (mtlChunk.Name.Contains("default_body"))
                {
                    // New MWO models for some crazy reason don't put the actual mtl file name in the mtlchunk.  They just have /objects/mechs/default_body
                    // have to assume that it's /objects/mechs/<mechname>/body/<mechname>_body.mtl.  There is also a <mechname>.mtl that contains mtl
                    // info for hitboxes, but not needed.
                    // TODO:  This isn't right.  Fix it.
                    var charsToClean = cleanName.ToCharArray().Intersect(Path.GetInvalidFileNameChars()).ToArray();
                    if (charsToClean.Length > 0)
                    {
                        foreach (Char character in charsToClean)
                        {
                            cleanName = cleanName.Replace(character.ToString(), "");
                        }
                    }
                    materialFile = new FileInfo(Path.Combine(Path.GetDirectoryName(fileName), cleanName));
                }
                else if (mtlChunk.Name.Contains(@"/") || mtlChunk.Name.Contains(@"\"))
                {
                    // The mtlname has a path.  Most likely starts at the Objects directory.
                    //
                    string[] stringSeparators = new string[] { @"\", @"/" };
                    string[] result;
                    // if objectdir is provided, check objectdir + mtlchunk.name
                    if (dataDir != null)
                    {
                        materialFile = new FileInfo(Path.Combine(dataDir, mtlChunk.Name));
                    }
                    else
                    {
                        // object dir not provided, but we have a path.  Just grab the last part of the name and check the dir of the cga file
                        result       = mtlChunk.Name.Split(stringSeparators, StringSplitOptions.None);
                        materialFile = new FileInfo(result[result.Length - 1]);
                    }
                }
                else
                {
                    var charsToClean = cleanName.ToCharArray().Intersect(Path.GetInvalidFileNameChars()).ToArray();
                    if (charsToClean.Length > 0)
                    {
                        foreach (Char character in charsToClean)
                        {
                            cleanName = cleanName.Replace(character.ToString(), "");
                        }
                    }
                    materialFile = new FileInfo(Path.Combine(Path.GetDirectoryName(fileName), cleanName));
                }

                // First try relative to file being processed
                if (materialFile.Extension != ".mtl")
                {
                    materialFile = new FileInfo(Path.ChangeExtension(materialFile.FullName, "mtl"));
                }

                // Then try just the last part of the chunk, relative to the file being processed
                if (!materialFile.Exists)
                {
                    materialFile = new FileInfo(Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileName(cleanName)));
                }
                if (materialFile.Extension != ".mtl")
                {
                    materialFile = new FileInfo(Path.ChangeExtension(materialFile.FullName, "mtl"));
                }

                // Then try relative to the ObjectDir
                if (!materialFile.Exists && dataDir != null)
                {
                    materialFile = new FileInfo(Path.Combine(dataDir, cleanName));
                }
                if (materialFile.Extension != ".mtl")
                {
                    materialFile = new FileInfo(Path.ChangeExtension(materialFile.FullName, "mtl"));
                }

                // Then try just the fileName.mtl
                if (!materialFile.Exists)
                {
                    materialFile = new FileInfo(fileName);
                }
                if (materialFile.Extension != ".mtl")
                {
                    materialFile = new FileInfo(Path.ChangeExtension(materialFile.FullName, "mtl"));
                }

                // TODO: Try more paths

                // Populate CryEngine_Core.Material
                CryEngine_Core.Material material = CryEngine_Core.Material.FromFile(materialFile);

                if (material != null)
                {
                    Utils.Log(LogLevelEnum.Debug, "Located material file {0}", materialFile.Name);

                    this.Materials = CryEngine.FlattenMaterials(material).Where(m => m.Textures != null).ToArray();

                    if (this.Materials.Length == 1)
                    {
                        // only one material, so it's a material file with no submaterials.  Check and set the name
                        //Console.WriteLine("Single material found.  setting name...");
                        this.Materials[0].Name = this.RootNode.Name;
                    }

                    // Early return - we have the material map
                    return;
                }
                else
                {
                    Utils.Log(LogLevelEnum.Debug, "Unable to locate material file {0}.mtl", mtlChunk.Name);
                }
            }
            #endregion

            Utils.Log(LogLevelEnum.Debug, "Unable to locate any material file");
            this.Materials = new CryEngine_Core.Material[] { };
        }