Example #1
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 #2
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();
        }