Example #1
0
        private MyModelProcessor CreateProcessor(MyModelConfiguration configuration)
        {
            MyModelProcessor myModelProcessor = new MyModelProcessor();

            foreach (MyModelParameter parameter in configuration.Parameters)
            {
                Action <MyModelProcessor, object> action;
                if (this.m_setters.TryGetValue(parameter.Name, out action))
                {
                    action(myModelProcessor, (object)parameter.Value);
                }
            }
            return(myModelProcessor);
        }
Example #2
0
        public static void ExportXml(string xmlFile, MyModelConfiguration configuration)
        {
            XmlSerializer           xmlSerializer = new XmlSerializer(typeof(MyModelConfiguration));
            XmlSerializerNamespaces namespaces    = new XmlSerializerNamespaces();

            namespaces.Add(string.Empty, string.Empty);
            using (MemoryStream memoryStream = new MemoryStream())
            {
                using (FileStream fileStream = File.Open(xmlFile, FileMode.OpenOrCreate))
                {
                    xmlSerializer.Serialize((Stream)memoryStream, (object)configuration, namespaces);
                    memoryStream.Position = 0L;
                    fileStream.Position   = 0L;
                    if (memoryStream.Length == fileStream.Length && ProgramContext.StreamEquals((Stream)memoryStream, (Stream)fileStream))
                    {
                        return;
                    }
                    fileStream.SetLength(0L);
                    fileStream.Position   = 0L;
                    memoryStream.Position = 0L;
                    memoryStream.WriteTo((Stream)fileStream);
                }
            }
        }
Example #3
0
        public void Build(
            string filename,
            string intermediateDir,
            string outputDir,
            MyModelConfiguration configuration,
            byte[] havokCollisionShapes,
            bool checkOpenBoundaries,
            float[] lodDistances,
            bool overrideLods,
            Func <string, MyMaterialConfiguration> getMaterialByRef,
            IMyBuildLogger logger)
        {
            string withoutExtension = Path.GetFileNameWithoutExtension(filename);
            string directoryName    = Path.GetDirectoryName(filename);
            string str1             = "content";
            int    num1             = directoryName.ToLower().LastIndexOf(str1) + str1.Length + 1;
            string path1            = directoryName.Substring(num1, directoryName.Length - num1);

            directoryName.Substring(0, num1);
            Path.Combine(path1, withoutExtension + ".FBX");
            AssimpContext assimpContext = new AssimpContext();

            assimpContext.SetConfig((PropertyConfig) new NormalSmoothingAngleConfig(66f));
            assimpContext.SetConfig((PropertyConfig) new FBXPreservePivotsConfig(false));
            Scene  input      = assimpContext.ImportFile(filename, PostProcessSteps.CalculateTangentSpace | PostProcessSteps.JoinIdenticalVertices | PostProcessSteps.Triangulate | PostProcessSteps.GenerateSmoothNormals | PostProcessSteps.SplitLargeMeshes | PostProcessSteps.LimitBoneWeights | PostProcessSteps.SortByPrimitiveType | PostProcessSteps.FindInvalidData | PostProcessSteps.GenerateUVCoords | PostProcessSteps.FlipWindingOrder);
            string outputDir1 = outputDir;

            if (input.MeshCount == 0 && input.AnimationCount == 0)
            {
                throw new Exception("Number of meshes is 0 and no animation present!");
            }
            if (input.MaterialCount > 0)
            {
                List <MyMaterialConfiguration> materialConfigurationList = new List <MyMaterialConfiguration>();
                for (int index = 0; index < input.MaterialCount; ++index)
                {
                    MyMaterialConfiguration materialConfiguration = getMaterialByRef(input.Materials[index].Name);
                    if (materialConfiguration != null)
                    {
                        materialConfigurationList.Add(materialConfiguration);
                    }
                }
                if (materialConfigurationList.Count > 0)
                {
                    configuration.Materials = configuration.Materials != null ? ((IEnumerable <MyMaterialConfiguration>)configuration.Materials).Union <MyMaterialConfiguration>((IEnumerable <MyMaterialConfiguration>)materialConfigurationList.ToArray()).ToArray <MyMaterialConfiguration>() : materialConfigurationList.ToArray();
                }
            }
            MyModelProcessor processor = this.CreateProcessor(configuration);

            if (configuration.Materials != null)
            {
                foreach (MyMaterialConfiguration material in configuration.Materials)
                {
                    try
                    {
                        Dictionary <string, object> dictionary = new Dictionary <string, object>();
                        if (processor.MaterialProperties.Keys.Contains <string>(material.Name))
                        {
                            logger.LogMessage(MessageType.Error, "Material: " + material.Name + " is already defined in the processor. Not adding it again..", filename);
                        }
                        else
                        {
                            processor.MaterialProperties.Add(material.Name, dictionary);
                            foreach (MyModelParameter parameter in material.Parameters)
                            {
                                dictionary.Add(parameter.Name, (object)parameter.Value);
                            }
                        }
                    }
                    catch (ArgumentException ex)
                    {
                        logger.LogMessage(MessageType.Error, "Problem when procesing materials: " + ex.Message, filename);
                    }
                }
            }
            int num2 = 999;
            List <MyLODDescriptor> myLodDescriptorList = new List <MyLODDescriptor>();

            for (int index = 0; index < num2; ++index)
            {
                string path = Path.Combine(directoryName, withoutExtension + "_LOD" + (object)(index + 1)) + ".fbx";
                string str2 = Path.Combine(path1, withoutExtension + "_LOD" + (object)(index + 1));
                if (File.Exists(path))
                {
                    if (overrideLods && lodDistances != null && (index < lodDistances.Length && (double)lodDistances[index] > 0.0))
                    {
                        MyLODDescriptor myLodDescriptor = new MyLODDescriptor()
                        {
                            Distance = lodDistances[index],
                            Model    = str2
                        };
                        myLodDescriptorList.Add(myLodDescriptor);
                    }
                    else if (configuration.LODs != null && index < configuration.LODs.Length)
                    {
                        MyLODConfiguration loD             = configuration.LODs[index];
                        MyLODDescriptor    myLodDescriptor = new MyLODDescriptor()
                        {
                            Distance      = loD.Distance,
                            Model         = configuration.LODs[index].Model, //str2,   <-- FIx for LODS. Take defined path in the config.
                            RenderQuality = loD.RenderQuality
                        };
                        if (str2.ToLower() != loD.Model.ToLower())
                        {
                            logger.LogMessage(MessageType.Error, "LOD" + (object)(index + 1) + " name differs " + str2 + " and " + loD.Model, filename);
                        }
                        myLodDescriptorList.Add(myLodDescriptor);
                    }
                    else
                    {
                        logger.LogMessage(MessageType.Error, "LOD" + (object)(index + 1) + " model exists but configuration is missing", filename);
                    }
                }
                else if (configuration.LODs != null && index < configuration.LODs.Length)
                {
                    logger.LogMessage(MessageType.Error, "LOD model " + configuration.LODs[index].Model + " is missing", filename);
                }
                else
                {
                    break;
                }
            }
            processor.LODs                 = myLodDescriptorList.ToArray();
            processor.BoneGridMapping      = configuration.BoneGridSize;
            processor.BoneMapping          = configuration.BoneMapping != null ? ((IEnumerable <MyModelVector>)configuration.BoneMapping).Select <MyModelVector, Vector3>((Func <MyModelVector, Vector3>)(s => new Vector3((float)s.X, (float)s.Y, (float)s.Z))).ToArray <Vector3>() : (Vector3[])null;
            processor.HavokCollisionShapes = havokCollisionShapes;
            processor.Process(input, filename, outputDir1, checkOpenBoundaries, logger);
            if (configuration.BoneGridSize.HasValue)
            {
                configuration.BoneMapping = ((IEnumerable <Vector3>)processor.BoneMapping).Select <Vector3, MyModelVector>((Func <Vector3, MyModelVector>)(s => (MyModelVector)s)).ToArray <MyModelVector>();
            }
            List <MyMaterialConfiguration> materialConfigurationList1 = new List <MyMaterialConfiguration>();

            foreach (KeyValuePair <string, Dictionary <string, object> > materialProperty in processor.MaterialProperties)
            {
                materialConfigurationList1.Add(new MyMaterialConfiguration()
                {
                    Name       = materialProperty.Key,
                    Parameters = MyModelBuilder.GetParameters(materialProperty)
                });
            }
            configuration.Materials = materialConfigurationList1.Count <= 0 ? (MyMaterialConfiguration[])null : materialConfigurationList1.ToArray();
            if (processor.LODs == null)
            {
                return;
            }
            List <MyLODConfiguration> lodConfigurationList = new List <MyLODConfiguration>();

            foreach (MyLODDescriptor loD in processor.LODs)
            {
                lodConfigurationList.Add(new MyLODConfiguration()
                {
                    Distance      = loD.Distance,
                    Model         = loD.Model,
                    RenderQuality = loD.RenderQuality
                });
            }
            configuration.LODs = lodConfigurationList.ToArray();
        }
Example #4
0
        private bool ProcessFile(
            string file,
            string outputDir,
            Dictionary <string, object> defaultVars,
            bool exportXml,
            bool forceBuild,
            bool checkOpenBoundaries,
            string lodDistances,
            bool overrideLods)
        {
            DateTime             sourceDateTime = File.GetLastWriteTimeUtc(file);
            string               str1           = Path.ChangeExtension(file, "xml");
            bool                 flag           = false;
            MyModelConfiguration configuration  = (MyModelConfiguration)null;

            if (File.Exists(str1))
            {
                DateTime lastWriteTimeUtc = File.GetLastWriteTimeUtc(str1);
                if (lastWriteTimeUtc > sourceDateTime)
                {
                    sourceDateTime = lastWriteTimeUtc;
                }
                configuration = ProgramContext.ImportXml(str1);
            }
            else
            {
                flag = exportXml;
            }
            if (configuration == null)
            {
                configuration = new MyModelConfiguration()
                {
                    Name       = "Default",
                    Parameters = defaultVars.Select <KeyValuePair <string, object>, MyModelParameter>((Func <KeyValuePair <string, object>, MyModelParameter>)(s => new MyModelParameter()
                    {
                        Name  = s.Key,
                        Value = s.Value.ToString()
                    })).ToArray <MyModelParameter>()
                }
            }
            ;
            if (configuration.MaterialRefs != null)
            {
                foreach (MyModelParameter materialRef in configuration.MaterialRefs)
                {
                    ProgramContext.LoadMaterialByRef(materialRef.Name);
                }
            }
            byte[] havokCollisionShapes = this.ReadExternalFile("hkt", file, ref sourceDateTime);
            if (this.appLastChangeDateTime.HasValue && this.appLastChangeDateTime.Value > sourceDateTime)
            {
                sourceDateTime = this.appLastChangeDateTime.Value;
            }
            FileInfo fileInfo = new FileInfo(MyModelProcessor.GetOutputPath(file, outputDir));

            if (fileInfo.Exists && fileInfo.LastWriteTimeUtc > sourceDateTime && !forceBuild)
            {
                if (flag)
                {
                    ProgramContext.ExportXml(str1, configuration);
                }
                return(false);
            }
            ProgramContext.ItemInfo itemInfo = new ProgramContext.ItemInfo()
            {
                Index         = 0,
                Path          = file,
                Name          = Path.GetFileNameWithoutExtension(file),
                Configuration = configuration
            };
            float[] numArray;
            if (lodDistances == null)
            {
                numArray = new float[0];
            }
            else
            {
                numArray = Array.ConvertAll <string, float>(lodDistances.Trim().Split(' '), new Converter <string, float>(float.Parse));
            }
            float[] lodDistances1 = numArray;
            this.ProcessItem(itemInfo, outputDir, havokCollisionShapes, checkOpenBoundaries, lodDistances1, overrideLods);
            if (exportXml)
            {
                List <string> materialsToRef = new List <string>();
                foreach (MyMaterialConfiguration material in configuration.Materials)
                {
                    if (ProgramContext.GetMaterialByRef(material.Name) != null)
                    {
                        materialsToRef.Add(material.Name);
                    }
                }
                if (materialsToRef.Count > 0)
                {
                    configuration.Materials = ((IEnumerable <MyMaterialConfiguration>)configuration.Materials).Where <MyMaterialConfiguration>((Func <MyMaterialConfiguration, bool>)(x => !materialsToRef.Contains(x.Name))).ToArray <MyMaterialConfiguration>();
                    if (configuration.MaterialRefs == null)
                    {
                        configuration.MaterialRefs = materialsToRef.ConvertAll <MyModelParameter>((Converter <string, MyModelParameter>)(x => new MyModelParameter()
                        {
                            Name = x
                        })).ToArray();
                    }
                    else
                    {
                        List <MyModelParameter> myModelParameterList = new List <MyModelParameter>();
                        foreach (string str2 in materialsToRef)
                        {
                            string mat = str2;
                            if (!((IEnumerable <MyModelParameter>)configuration.MaterialRefs).Any <MyModelParameter>((Func <MyModelParameter, bool>)(x => x.Name == mat)))
                            {
                                myModelParameterList.Add(new MyModelParameter()
                                {
                                    Name = mat
                                });
                            }
                        }
                        configuration.MaterialRefs = ((IEnumerable <MyModelParameter>)configuration.MaterialRefs).Union <MyModelParameter>((IEnumerable <MyModelParameter>)myModelParameterList).ToArray <MyModelParameter>();
                    }
                }
                ProgramContext.ExportXml(str1, configuration);
            }
            return(true);
        }
Example #5
0
        public void Build(
            string filename,
            string intermediateDir,
            string outputDir,
            MyModelConfiguration configuration,
            byte[] havokCollisionShapes,
            bool checkOpenBoundaries,
            float[] lodDistances,
            bool overrideLods,
            Func <string, MyMaterialConfiguration> getMaterialByRef,
            IMyBuildLogger logger)
        {
            logger.LogMessage(MessageType.Info, "**FileName: " + filename);

            string withoutExtension = Path.GetFileNameWithoutExtension(filename);

            logger.LogMessage(MessageType.Info, "**Filename (without extension): " + withoutExtension);

            string directoryName = Path.GetDirectoryName(filename);

            logger.LogMessage(MessageType.Info, "**Directory Name: " + directoryName);

            //string contentDirectoryString = "content";
            // int numberOfPathCharactersToCull = directoryName.ToLower().LastIndexOf(contentDirectoryString) + contentDirectoryString.Length + 1;

            var numberOfPathCharactersToCull = filename.LastIndexOf("models\\", StringComparison.OrdinalIgnoreCase);

            if (numberOfPathCharactersToCull == -1)
            {
                throw new Exception("Couldn't find 'models\\' in path provided: " + filename);
            }

            logger.LogMessage(MessageType.Info, "**Number of characters to cull: " + numberOfPathCharactersToCull);
            string culledPath = directoryName.Substring(numberOfPathCharactersToCull, directoryName.Length - numberOfPathCharactersToCull); // Used to cull 'content' from path name to create relative pathing.

            logger.LogMessage(MessageType.Info, "**Culled Path: " + culledPath);

            directoryName.Substring(0, numberOfPathCharactersToCull);
            Path.Combine(directoryName, withoutExtension + ".FBX");
            AssimpContext assimpContext = new AssimpContext();

            assimpContext.SetConfig((PropertyConfig) new NormalSmoothingAngleConfig(66f));
            assimpContext.SetConfig((PropertyConfig) new FBXPreservePivotsConfig(false));
            Scene scene = assimpContext.ImportFile(filename,
                                                   PostProcessSteps.CalculateTangentSpace |
                                                   PostProcessSteps.JoinIdenticalVertices |
                                                   PostProcessSteps.Triangulate |
                                                   PostProcessSteps.GenerateSmoothNormals |
                                                   PostProcessSteps.SplitLargeMeshes |
                                                   PostProcessSteps.LimitBoneWeights |
                                                   PostProcessSteps.SortByPrimitiveType |
                                                   PostProcessSteps.FindInvalidData |
                                                   PostProcessSteps.GenerateUVCoords |
                                                   PostProcessSteps.FlipWindingOrder);

            string outputDir1 = outputDir;

            if (scene.MeshCount == 0 && scene.AnimationCount == 0)
            {
                throw new Exception("Number of meshes is 0 and no animation present!");
            }
            else
            {
                logger.LogMessage(MessageType.Info, "Found " + scene.MeshCount + " meshe(s).", "Meshes");
                logger.LogMessage(MessageType.Info, "Found " + scene.AnimationCount + " animation(s).", "Animations");
            }

            #region check UV for 0-sized faces
            if (scene.MeshCount > 0)
            {
                void LogUVError(Assimp.Mesh mesh, string message)
                {
                    //logger.LogMessage(MessageType.Error, $"Mesh '{mesh.Name}' {message}");
                    throw new Exception($"Mesh '{mesh.Name}' {message}");
                }

                for (int meshIdx = 0; meshIdx < scene.MeshCount; meshIdx++)
                {
                    Assimp.Mesh mesh = scene.Meshes[meshIdx];

                    if (mesh.TextureCoordinateChannels == null || mesh.TextureCoordinateChannels.Length == 0)
                    {
                        LogUVError(mesh, "has no UV map/channel!");
                        continue;
                    }

                    int channels = 1; // don't care about other channels; if you want to, replace with: mesh.TextureCoordinateChannels.Length;
                    for (int chIdx = 0; chIdx < channels; chIdx++)
                    {
                        if (!mesh.HasTextureCoords(0))
                        {
                            LogUVError(mesh, "has no UV map/channel!");
                            continue;
                        }

                        List <Assimp.Vector3D> vectors = mesh.TextureCoordinateChannels[chIdx];
                        if (vectors == null || vectors.Count == 0)
                        {
                            LogUVError(mesh, "has no UV vectors in first map/channel!");
                            continue;
                        }

                        //Console.WriteLine($"  channel={chIdx}");
                        //for (int v = 0; v < vectors.Count; v++)
                        //{
                        //    Console.WriteLine($"  {v} == {vectors[v]}");
                        //}

                        Assimp.Vector3D?lastVec       = null;
                        int             sameVecInARow = 1;

                        // these can be triangles, quads and prob more... so not safe to assume they're in pairs of 3.
                        for (int v = 0; v < vectors.Count; v++)
                        {
                            Assimp.Vector3D vec = vectors[v];

                            if (!lastVec.HasValue)
                            {
                                lastVec = vec;
                            }
                            else
                            {
                                if (lastVec.Value == vec)
                                {
                                    sameVecInARow++;

                                    if (sameVecInARow >= 3)
                                    {
                                        // Changed this to a warning instead of a LogUVError
                                        logger.LogMessage(MessageType.Warning, mesh.ToString() + "has UV with 3 identical vectors in a row, this likely means you have a face with an UV is 0-size which will cause SE to make the entire model shaderless.");
                                        break;
                                    }
                                }
                                else
                                {
                                    lastVec       = vec;
                                    sameVecInARow = 1;
                                }
                            }
                        }
                    }
                }
            }
            #endregion

            if (scene.MaterialCount > 0)
            {
                List <MyMaterialConfiguration> materialConfigurationList = new List <MyMaterialConfiguration>();
                for (int index = 0; index < scene.MaterialCount; ++index)
                {
                    MyMaterialConfiguration materialConfiguration = getMaterialByRef(scene.Materials[index].Name);
                    if (materialConfiguration != null)
                    {
                        materialConfigurationList.Add(materialConfiguration);
                    }
                }
                if (materialConfigurationList.Count > 0)
                {
                    configuration.Materials = configuration.Materials != null ? ((IEnumerable <MyMaterialConfiguration>)configuration.Materials).Union <MyMaterialConfiguration>((IEnumerable <MyMaterialConfiguration>)materialConfigurationList.ToArray()).ToArray <MyMaterialConfiguration>() : materialConfigurationList.ToArray();
                }
            }

            MyModelProcessor processor = this.CreateProcessor(configuration);
            if (configuration.Materials != null)
            {
                foreach (MyMaterialConfiguration material in configuration.Materials)
                {
                    try
                    {
                        Dictionary <string, object> dictionary = new Dictionary <string, object>();
                        if (processor.MaterialProperties.Keys.Contains <string>(material.Name))
                        {
                            logger.LogMessage(MessageType.Warning, "Material: " + material.Name + " is already defined in the processor. Not adding it again..", filename);
                        }
                        else
                        {
                            processor.MaterialProperties.Add(material.Name, dictionary);
                            foreach (MyModelParameter parameter in material.Parameters)
                            {
                                dictionary.Add(parameter.Name, (object)parameter.Value);
                            }
                        }
                    }
                    catch (ArgumentException ex)
                    {
                        logger.LogMessage(MessageType.Warning, "Problem when processing materials: " + ex.Message, filename);
                    }
                }
            }
            int num2 = 999;
            List <MyLODDescriptor> myLodDescriptorList = new List <MyLODDescriptor>();
            for (int index = 0; index < num2; ++index)
            {
                string path = Path.Combine(directoryName, withoutExtension + "_LOD" + (object)(index + 1)) + ".fbx";
                string str2 = Path.Combine(culledPath, withoutExtension + "_LOD" + (object)(index + 1));

                if (File.Exists(path))
                {
                    if (overrideLods && lodDistances != null && (index < lodDistances.Length && (double)lodDistances[index] > 0.0))
                    {
                        MyLODDescriptor myLodDescriptor = new MyLODDescriptor()
                        {
                            Distance = lodDistances[index],
                            Model    = str2
                        };
                        myLodDescriptorList.Add(myLodDescriptor);
                    }
                    else if (configuration.LODs != null && index < configuration.LODs.Length)
                    {
                        MyLODConfiguration loD             = configuration.LODs[index];
                        MyLODDescriptor    myLodDescriptor = new MyLODDescriptor()
                        {
                            Distance      = loD.Distance,
                            Model         = str2,
                            RenderQuality = loD.RenderQuality
                        };


                        if (str2.ToLower() != loD.Model.ToLower())
                        {
                            logger.LogMessage(MessageType.Warning, "LOD" + (object)(index + 1) + " name differs " + str2 + " and " + loD.Model, filename);
                        }
                        myLodDescriptorList.Add(myLodDescriptor);
                    }
                    else
                    {
                        logger.LogMessage(MessageType.Warning, "LOD" + (object)(index + 1) + " model exists but configuration is missing", filename);
                    }
                }
                else if (configuration.LODs != null && index < configuration.LODs.Length)
                {
                    logger.LogMessage(MessageType.Warning, "LOD model " + configuration.LODs[index].Model + " is missing", filename);
                }
                else
                {
                    break;
                }
            }
            processor.LODs                 = myLodDescriptorList.ToArray();
            processor.BoneGridMapping      = configuration.BoneGridSize;
            processor.BoneMapping          = configuration.BoneMapping != null ? ((IEnumerable <MyModelVector>)configuration.BoneMapping).Select <MyModelVector, Vector3>((Func <MyModelVector, Vector3>)(s => new Vector3((float)s.X, (float)s.Y, (float)s.Z))).ToArray <Vector3>() : (Vector3[])null;
            processor.HavokCollisionShapes = havokCollisionShapes;
            processor.Process(scene, filename, outputDir1, checkOpenBoundaries, logger);
            if (configuration.BoneGridSize.HasValue)
            {
                configuration.BoneMapping = ((IEnumerable <Vector3>)processor.BoneMapping).Select <Vector3, MyModelVector>((Func <Vector3, MyModelVector>)(s => (MyModelVector)s)).ToArray <MyModelVector>();
            }
            List <MyMaterialConfiguration> materialConfigurationList1 = new List <MyMaterialConfiguration>();
            foreach (KeyValuePair <string, Dictionary <string, object> > materialProperty in processor.MaterialProperties)
            {
                materialConfigurationList1.Add(new MyMaterialConfiguration()
                {
                    Name       = materialProperty.Key,
                    Parameters = MyModelBuilder.GetParameters(materialProperty)
                });
            }
            configuration.Materials = materialConfigurationList1.Count <= 0 ? (MyMaterialConfiguration[])null : materialConfigurationList1.ToArray();
            if (processor.LODs == null)
            {
                return;
            }
            List <MyLODConfiguration> lodConfigurationList = new List <MyLODConfiguration>();
            foreach (MyLODDescriptor loD in processor.LODs)
            {
                lodConfigurationList.Add(new MyLODConfiguration()
                {
                    Distance      = loD.Distance,
                    Model         = loD.Model,
                    RenderQuality = loD.RenderQuality
                });
            }
            configuration.LODs = lodConfigurationList.ToArray();
        }