Exemple #1
0
        private static MyLODDescriptor[] ReadLODs(BinaryReader reader, int version)
        {
            var length = reader.ReadInt32();
            var myLodDescriptorArray = new MyLODDescriptor[length];
            var num = 0;

            while (length-- > 0)
            {
                var myLodDescriptor = new MyLODDescriptor();
                myLodDescriptorArray[num++] = myLodDescriptor;
                myLodDescriptor.Read(reader);
            }

            return(myLodDescriptorArray);
        }
Exemple #2
0
        private static MyLODDescriptor[] ReadMyLodDescriptorArray(BinaryReader reader)
        {
            var nCount = reader.ReadInt32();
            var myLodDescriptorArray = new MyLODDescriptor[nCount];

            for (var i = 0; i < nCount; i++)
            {
                var distance      = reader.ReadSingle();
                var model         = reader.ReadString();
                var renderQuality = reader.ReadString();
                myLodDescriptorArray[i] = new MyLODDescriptor {
                    Distance = distance, Model = model, RenderQuality = renderQuality
                };
            }

            return(myLodDescriptorArray);
        }
Exemple #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();
        }
Exemple #4
0
        MyRenderMeshInfo LoadMesh(string assetName, out MyLODDescriptor[] LodDescriptors)
        {
            //Debug.Assert(assetName.EndsWith(".mwm"));
            #region Temporary for mwm endings
            if (!assetName.EndsWith(".mwm"))
            {
                assetName += ".mwm";
            }
            #endregion

            var meshVertexInput = MyVertexInputLayout.Empty;
            LodDescriptors = null;
            MyRenderMeshInfo result = new MyRenderMeshInfo();

            var importer = new MyModelImporter();
            var fsPath = Path.IsPathRooted(assetName) ? assetName : Path.Combine(MyFileSystem.ContentPath, assetName);

            if (!MyFileSystem.FileExists(fsPath))
            {
                System.Diagnostics.Debug.Fail("Model " + assetName + " does not exists!");

                return MyAssetsLoader.GetDebugMesh().LODs[0].m_meshInfo;
            }


            string contentPath = null;
            if (Path.IsPathRooted(assetName) && assetName.ToLower().Contains("models"))
                contentPath = assetName.Substring(0, assetName.ToLower().IndexOf("models"));

            try
            {

                importer.ImportData(fsPath, new string[]
                    {
                        MyImporterConstants.TAG_VERTICES,
                        MyImporterConstants.TAG_BLENDINDICES,
                        MyImporterConstants.TAG_BLENDWEIGHTS,
                        MyImporterConstants.TAG_NORMALS,
                        MyImporterConstants.TAG_TEXCOORDS0,
                        MyImporterConstants.TAG_TANGENTS,
                        MyImporterConstants.TAG_BINORMALS,
                        MyImporterConstants.TAG_BONES,
                        MyImporterConstants.TAG_MESH_PARTS,
                        MyImporterConstants.TAG_BOUNDING_BOX,
                        MyImporterConstants.TAG_BOUNDING_SPHERE,
                        MyImporterConstants.TAG_LODS,
                    });
                Dictionary<string, object> tagData = importer.GetTagData();

                // extract data
                var positions = (HalfVector4[])tagData[MyImporterConstants.TAG_VERTICES];
                System.Diagnostics.Debug.Assert(positions.Length > 0);
                var verticesNum = positions.Length;
                var boneIndices = (Vector4I[])tagData[MyImporterConstants.TAG_BLENDINDICES];
                var boneWeights = (Vector4[])tagData[MyImporterConstants.TAG_BLENDWEIGHTS];
                var normals = (Byte4[])tagData[MyImporterConstants.TAG_NORMALS];
                var texcoords = (HalfVector2[])tagData[MyImporterConstants.TAG_TEXCOORDS0];
                var tangents = (Byte4[])tagData[MyImporterConstants.TAG_TANGENTS];
                var bintangents = (Byte4[])tagData[MyImporterConstants.TAG_BINORMALS];
                var tangentBitanSgn = new Byte4[verticesNum];
                for (int i = 0; i < verticesNum; i++)
                {
                    var N = VF_Packer.UnpackNormal(normals[i].PackedValue);
                    var T = VF_Packer.UnpackNormal(tangents[i].PackedValue);
                    var B = VF_Packer.UnpackNormal(bintangents[i].PackedValue);

                    var tanW = new Vector4(T.X, T.Y, T.Z, 0);

                    tanW.W = T.Cross(N).Dot(B) < 0 ? -1 : 1;
                    tangentBitanSgn[i] = VF_Packer.PackTangentSignB4(ref tanW);
                }
                
                bool hasBonesInfo = boneIndices.Length > 0 && boneWeights.Length > 0;
                var bones = (MyModelBone[])tagData[MyImporterConstants.TAG_BONES];

                //
                var vertexBuffers = new List<IVertexBuffer>();
                IIndexBuffer indexBuffer = null;
                var submeshes = new Dictionary<MyMeshDrawTechnique, List<MyDrawSubmesh>>();
                var submeshes2 = new Dictionary<MyMeshDrawTechnique, List<MySubmeshInfo>>();
                var submeshesMeta = new List<MySubmeshInfo>();

                int indicesNum = 0;
                bool missingMaterial = false;
                if (tagData.ContainsKey(MyImporterConstants.TAG_MESH_PARTS))
                {
                    var indices = new List<uint>(positions.Length);
                    uint maxIndex = 0;

                    var meshParts = tagData[MyImporterConstants.TAG_MESH_PARTS] as List<MyMeshPartInfo>;
                    foreach (MyMeshPartInfo meshPart in meshParts)
                    {
                        # region Bones indirection
                        int[] bonesRemapping = null;
                        if (boneIndices.Length > 0 && bones.Length > MyRender11Constants.SHADER_MAX_BONES)
                        {
                            Dictionary<int, int> vertexChanged = new Dictionary<int, int>();

                            Dictionary<int, int> bonesUsed = new Dictionary<int, int>();

                            int trianglesNum = meshPart.m_indices.Count / 3;
                            for (int i = 0; i < trianglesNum; i++)
                            {
                                for (int j = 0; j < 3; j++)
                                {
                                    int index = meshPart.m_indices[i * 3 + j];
                                    if (boneWeights[index].X > 0)
                                        bonesUsed[boneIndices[index].X] = 1;
                                    if (boneWeights[index].Y > 0)
                                        bonesUsed[boneIndices[index].Y] = 1;
                                    if (boneWeights[index].Z > 0)
                                        bonesUsed[boneIndices[index].Z] = 1;
                                    if (boneWeights[index].W > 0)
                                        bonesUsed[boneIndices[index].W] = 1;
                                }
                            }

                            if (bonesUsed.Count > MyRender11Constants.SHADER_MAX_BONES)
                            {
                                Debug.Assert(bonesUsed.Count <= MyRender11Constants.SHADER_MAX_BONES, "Model \"" + assetName + "\"'s part uses more than 60 bones, please split model on more parts");
                            }

                            var partBones = new List<int>(bonesUsed.Keys);
                            partBones.Sort();
                            if (partBones.Count > 0 && partBones[partBones.Count - 1] >= MyRender11Constants.SHADER_MAX_BONES)
                            {
                                for (int i = 0; i < partBones.Count; i++)
                                {
                                    bonesUsed[partBones[i]] = i;
                                }

                                Dictionary<int, int> vertexTouched = new Dictionary<int, int>();

                                for (int i = 0; i < trianglesNum; i++)
                                {
                                    for (int j = 0; j < 3; j++)
                                    {
                                        int index = meshPart.m_indices[i * 3 + j];
                                        if (!vertexTouched.ContainsKey(index))
                                        {
                                            if (boneWeights[index].X > 0)
                                                boneIndices[index].X = bonesUsed[boneIndices[index].X];
                                            if (boneWeights[index].Y > 0)
                                                boneIndices[index].Y = bonesUsed[boneIndices[index].Y];
                                            if (boneWeights[index].Z > 0)
                                                boneIndices[index].Z = bonesUsed[boneIndices[index].Z];
                                            if (boneWeights[index].W > 0)
                                                boneIndices[index].W = bonesUsed[boneIndices[index].W];

                                            vertexTouched[index] = 1;

                                            int changes = 0;
                                            vertexChanged.TryGetValue(index, out changes);
                                            vertexChanged[index] = changes + 1;
                                        }
                                    }
                                }

                                bonesRemapping = partBones.ToArray();
                            }

                            if (vertexChanged.Values.Count > 0)
                                Debug.Assert(vertexChanged.Values.Max() < 2, "Vertex shared between model parts, will likely result in wrong skinning");
                        }

                        #endregion

                        int startIndex = indices.Count;
                        int indexCount = meshPart.m_indices.Count;

                        uint minIndex = (uint)meshPart.m_indices[0];
                        foreach (var i in meshPart.m_indices)
                        {
                            indices.Add((uint)i);
                            minIndex = Math.Min(minIndex, (uint)i);
                        }

                        uint baseVertex = minIndex;

                        for (int i = startIndex; i < startIndex + indexCount; i++)
                        {
                            indices[i] -= minIndex;
                            maxIndex = Math.Max(maxIndex, indices[i]);
                        }

                        #region Material
                        var materialDesc = meshPart.m_MaterialDesc;

                        var matId = MyMeshMaterials1.GetMaterialId(materialDesc, contentPath);
                        var partKey = MyMeshMaterials1.Table[matId.Index].Technique;
                        var materialName = MyMeshMaterials1.Table[matId.Index].Name;

                        var list = submeshes.SetDefault(partKey, new List<MyDrawSubmesh>());
                        list.Add(new MyDrawSubmesh(indexCount, startIndex, (int)baseVertex, MyMeshMaterials1.GetProxyId(matId), bonesRemapping));

                        submeshesMeta.Add(new MySubmeshInfo
                        {
                            IndexCount = indexCount,
                            StartIndex = startIndex,
                            BaseVertex = (int)baseVertex,
                            BonesMapping = bonesRemapping,
                            Material = materialName.ToString(),
                            Technique = partKey
                        });

                        var list2 = submeshes2.SetDefault(partKey, new List<MySubmeshInfo>());
                        list2.Add(submeshesMeta[submeshesMeta.Count - 1]);

                        #endregion

                    }
                    indicesNum = indices.Count;

                    #region Fill gpu buffes
                    unsafe
                    {
                        if (maxIndex <= ushort.MaxValue)
                        {
                            // create 16 bit indices
                            var indices16 = new ushort[indices.Count];
                            for (int i = 0; i < indices.Count; i++)
                            {
                                indices16[i] = (ushort)indices[i];
                            }

                            result.Indices = indices16;

                            fixed (ushort* I = indices16)
                            {
                                indexBuffer = MyManagers.Buffers.CreateIndexBuffer(assetName + " index buffer", indices16.Length, new IntPtr(I), MyIndexBufferFormat.UShort, ResourceUsage.Immutable);
                            }
                        }
                        else
                        {
                            var indicesArray = indices.ToArray();
                            fixed (uint* I = indicesArray)
                            {
                                indexBuffer = MyManagers.Buffers.CreateIndexBuffer(assetName + " index buffer", indices.Count, new IntPtr(I), MyIndexBufferFormat.UInt, ResourceUsage.Immutable);
                            }
                        }
                    }
                    unsafe
                    {
                        if (!hasBonesInfo)
                        {
                            var vertices = new MyVertexFormatPositionH4[verticesNum];

                            for (int i = 0; i < verticesNum; i++)
                            {
                                vertices[i] = new MyVertexFormatPositionH4(positions[i]);
                            }
                            meshVertexInput = meshVertexInput.Append(MyVertexInputComponentType.POSITION_PACKED);

                            result.VertexPositions = vertices;

                            fixed (MyVertexFormatPositionH4* V = vertices)
                            {
                                vertexBuffers.Add(
                                    MyManagers.Buffers.CreateVertexBuffer(
                                        assetName + " vertex buffer " + vertexBuffers.Count, verticesNum,
                                        sizeof(MyVertexFormatPositionH4), new IntPtr(V), ResourceUsage.Immutable));
                            }
                        }
                        else
                        {
                            var vertices = new MyVertexFormatPositionSkinning[verticesNum];
                            for (int i = 0; i < verticesNum; i++)
                            {
                                vertices[i] = new MyVertexFormatPositionSkinning(
                                    positions[i],
                                    new Byte4(boneIndices[i].X, boneIndices[i].Y, boneIndices[i].Z, boneIndices[i].W),
                                    boneWeights[i]);
                            }
                            meshVertexInput = meshVertexInput.Append(MyVertexInputComponentType.POSITION_PACKED)
                                .Append(MyVertexInputComponentType.BLEND_WEIGHTS)
                                .Append(MyVertexInputComponentType.BLEND_INDICES);

                            fixed (MyVertexFormatPositionSkinning* V = vertices)
                            {
                                vertexBuffers.Add(MyManagers.Buffers.CreateVertexBuffer(
                                    assetName + " vertex buffer " + vertexBuffers.Count, verticesNum,
                                    sizeof(MyVertexFormatPositionSkinning), new IntPtr(V), ResourceUsage.Immutable));
                            }
                        }
                        // add second stream
                        {
                            var vertices = new MyVertexFormatTexcoordNormalTangent[verticesNum];
                            for (int i = 0; i < verticesNum; i++)
                            {
                                vertices[i] = new MyVertexFormatTexcoordNormalTangent(texcoords[i], normals[i], tangentBitanSgn[i]);
                            }

                            fixed (MyVertexFormatTexcoordNormalTangent* V = vertices)
                            {
                                vertexBuffers.Add(MyManagers.Buffers.CreateVertexBuffer(
                                    assetName + " vertex buffer " + vertexBuffers.Count, verticesNum,
                                    sizeof(MyVertexFormatTexcoordNormalTangent), new IntPtr(V), ResourceUsage.Immutable));
                            }

                            result.VertexExtendedData = vertices;

                            meshVertexInput = meshVertexInput
                                .Append(MyVertexInputComponentType.NORMAL, 1)
                                .Append(MyVertexInputComponentType.TANGENT_SIGN_OF_BITANGENT, 1)
                                .Append(MyVertexInputComponentType.TEXCOORD0_H, 1);
                        }
                    }
                    #endregion
                }
                #region Extract lods
                if (tagData.ContainsKey(MyImporterConstants.TAG_LODS))
                {
                    var tagLODs = tagData[MyImporterConstants.TAG_LODS];
                    if (((MyLODDescriptor[])tagLODs).Length > 0)
                    {
                    }
                    LodDescriptors = (MyLODDescriptor[])((MyLODDescriptor[])tagLODs).Clone();
                }
                #endregion

                if (missingMaterial)
                {
                    Debug.WriteLine(String.Format("Mesh {0} has missing material", assetName));
                }

                //indexBuffer.SetDebugName(assetName + " index buffer");
                int c = 0;
                //vertexBuffers.ForEach(x => x.SetDebugName(assetName + " vertex buffer " + c++));

                //
                result.BoundingBox = (BoundingBox)tagData[MyImporterConstants.TAG_BOUNDING_BOX];
                result.BoundingSphere = (BoundingSphere)tagData[MyImporterConstants.TAG_BOUNDING_SPHERE];
                result.VerticesNum = verticesNum;
                result.IndicesNum = indicesNum;
                result.VertexLayout = meshVertexInput;
                result.IB = indexBuffer;
                result.VB = vertexBuffers.ToArray();
                result.IsAnimated = hasBonesInfo;
                result.Parts = submeshes.ToDictionary(x => x.Key, x => x.Value.ToArray());
                result.PartsMetadata = submeshes2.ToDictionary(x => x.Key, x => x.Value.ToArray());
                result.m_submeshes = submeshesMeta;

                IsAnimated |= result.IsAnimated;

                importer.Clear();
                return result;
            }
        public bool ExportData(string tagName, MyLODDescriptor[] lodDescriptions)
        {
            WriteTag(tagName);

            m_writer.Write(lodDescriptions.Length);
            foreach (var desc in lodDescriptions)
            {
                desc.Write(m_writer);
            }

            return true;
        }
Exemple #6
0
        private static bool ExportData(this BinaryWriter writer, string tagName, MyLODDescriptor[] lodArray)
        {
            WriteTag(writer, tagName);
            writer.Write(lodArray.Length);

            foreach (var lodVal in lodArray)
            {
                lodVal.Write(writer);
            }

            return true;
        }
Exemple #7
0
        private static MyLODDescriptor[] ReadMyLodDescriptorArray(BinaryReader reader)
        {
            var nCount = reader.ReadInt32();
            var myLodDescriptorArray = new MyLODDescriptor[nCount];

            for (var i = 0; i < nCount; i++)
            {
                var distance = reader.ReadSingle();
                var model = reader.ReadString();
                var renderQuality = reader.ReadString();
                myLodDescriptorArray[i] = new MyLODDescriptor { Distance = distance, Model = model, RenderQuality = renderQuality };
            }

            return myLodDescriptorArray;
        }
Exemple #8
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();
        }