internal static LODData GetLODData(string assetPath)
        {
            var lodData = AssetDatabase.LoadAssetAtPath <LODData>(GetLODDataPath(assetPath));

            if (!lodData)
            {
                lodData = ScriptableObject.CreateInstance <LODData>();
            }

            var overrideDefaults = lodData.overrideDefaults;

            var importSettings = lodData.importSettings;

            if (importSettings == null)
            {
                importSettings         = new LODImportSettings();
                lodData.importSettings = importSettings;
            }

            if (!overrideDefaults)
            {
                importSettings.generateOnImport       = enabled;
                importSettings.meshSimplifier         = meshSimplifierType.AssemblyQualifiedName;
                importSettings.maxLODGenerated        = maxLOD;
                importSettings.initialLODMaxPolyCount = initialLODMaxPolyCount;
            }

            return(lodData);
        }
        void OnPostprocessModel(GameObject go)
        {
            if (enabled && !go.GetComponentInChildren <LODGroup>() && meshSimplifierType != null)
            {
                if (go.GetComponentsInChildren <SkinnedMeshRenderer>().Any())
                {
                    Debug.Log("Automatic LOD generation on does not currently support skinned meshes on import");
                    return;
                }

                var  originalMeshFilters = go.GetComponentsInChildren <MeshFilter>();
                uint polyCount           = 0;
                foreach (var mf in originalMeshFilters)
                {
                    var m = mf.sharedMesh;
                    for (int i = 0; i < m.subMeshCount; i++)
                    {
                        var topology   = m.GetTopology(i);
                        var indexCount = m.GetIndexCount(i);

                        switch (topology)
                        {
                        case MeshTopology.Quads:
                            indexCount /= 4;
                            break;

                        case MeshTopology.Triangles:
                            indexCount /= 3;
                            break;

                        case MeshTopology.Lines:
                        case MeshTopology.LineStrip:
                            indexCount /= 2;
                            break;
                        }

                        polyCount += indexCount;
                    }
                }

                var meshLODs         = new List <MeshLOD>();
                var preprocessMeshes = new HashSet <int>();

                var lodData = AssetDatabase.LoadAssetAtPath <LODData>(GetLODDataPath(assetPath));
                if (!lodData)
                {
                    lodData = ScriptableObject.CreateInstance <LODData>();
                }

                var overrideDefaults = lodData.overrideDefaults;

                var importSettings = lodData.importSettings;
                if (importSettings == null)
                {
                    importSettings         = new LODImportSettings();
                    lodData.importSettings = importSettings;
                }

                if (!overrideDefaults)
                {
                    importSettings.generateOnImport       = true;
                    importSettings.meshSimplifier         = meshSimplifierType.AssemblyQualifiedName;
                    importSettings.maxLODGenerated        = maxLOD;
                    importSettings.initialLODMaxPolyCount = initialLODMaxPolyCount;
                }

                if (importSettings.generateOnImport && importSettings.maxLODGenerated == 0 && polyCount <= importSettings.initialLODMaxPolyCount)
                {
                    return;
                }

                if (!overrideDefaults || importSettings.generateOnImport)
                {
                    if (polyCount > importSettings.initialLODMaxPolyCount)
                    {
                        foreach (var mf in originalMeshFilters)
                        {
                            var inputMesh = mf.sharedMesh;

                            var outputMesh = new Mesh();
                            outputMesh.name   = inputMesh.name;
                            outputMesh.bounds = inputMesh.bounds;
                            mf.sharedMesh     = outputMesh;

                            var meshLOD = new MeshLOD();
                            meshLOD.inputMesh  = inputMesh;
                            meshLOD.outputMesh = outputMesh;
                            meshLOD.quality    = (float)importSettings.initialLODMaxPolyCount / (float)polyCount;
                            meshLODs.Add(meshLOD);

                            preprocessMeshes.Add(outputMesh.GetInstanceID());
                        }
                    }

                    // Clear out previous LOD data in case the number of LODs has been reduced
                    for (int i = 0; i <= LODData.MaxLOD; i++)
                    {
                        lodData[i] = null;
                    }

                    lodData[0] = originalMeshFilters.Select(mf => mf.GetComponent <Renderer>()).ToArray();

                    for (int i = 1; i <= importSettings.maxLODGenerated; i++)
                    {
                        var lodMeshes = new List <Renderer>();

                        foreach (var mf in originalMeshFilters)
                        {
                            var inputMesh = mf.sharedMesh;

                            var lodTransform = EditorUtility.CreateGameObjectWithHideFlags(mf.name,
                                                                                           k_DefaultHideFlags, typeof(MeshFilter), typeof(MeshRenderer)).transform;
                            lodTransform.parent        = mf.transform;
                            lodTransform.localPosition = Vector3.zero;

                            var lodMF       = lodTransform.GetComponent <MeshFilter>();
                            var lodRenderer = lodTransform.GetComponent <MeshRenderer>();

                            AppendLODNameToRenderer(lodRenderer, i);

                            var outputMesh = new Mesh();
                            outputMesh.name   = string.Format("{0} LOD{1}", inputMesh.name, i);
                            outputMesh.bounds = inputMesh.bounds;
                            lodMF.sharedMesh  = outputMesh;

                            lodMeshes.Add(lodRenderer);

                            EditorUtility.CopySerialized(mf.GetComponent <MeshRenderer>(), lodRenderer);

                            var meshLOD = new MeshLOD();
                            meshLOD.inputMesh  = inputMesh;
                            meshLOD.outputMesh = outputMesh;
                            meshLOD.quality    = Mathf.Pow(0.5f, i);
                            meshLODs.Add(meshLOD);
                        }

                        lodData[i] = lodMeshes.ToArray();
                    }

                    // Change the name of the original renderers last, so the name change doesn't end up in the clones for other LODs
                    AppendLODNameToRenderers(go.transform, 0);

                    if (meshLODs.Count > 0)
                    {
                        if (string.IsNullOrEmpty(AssetDatabase.GetAssetPath(lodData)))
                        {
                            AssetDatabase.CreateAsset(lodData, GetLODDataPath(assetPath));
                        }
                        else
                        {
                            var objects = AssetDatabase.LoadAllAssetsAtPath(GetLODDataPath(assetPath));
                            foreach (var o in objects)
                            {
                                var mesh = o as Mesh;
                                if (mesh)
                                {
                                    UnityObject.DestroyImmediate(mesh, true);
                                }
                            }
                            EditorUtility.SetDirty(lodData);
                        }
                        meshLODs.ForEach(ml => AssetDatabase.AddObjectToAsset(ml.outputMesh, lodData));
                        AssetDatabase.SaveAssets();

                        foreach (var ml in meshLODs)
                        {
                            GenerateMeshLOD(ml, preprocessMeshes);
                        }
                    }
                }
                else
                {
                    // Don't allow overriding LOD0
                    lodData[0] = originalMeshFilters.Select(mf =>
                    {
                        var r = mf.GetComponent <Renderer>();
                        AppendLODNameToRenderer(r, 0);
                        return(r);
                    }).ToArray();

                    for (int i = 1; i <= LODData.MaxLOD; i++)
                    {
                        var renderers = lodData[i];
                        for (int j = 0; j < renderers.Length; j++)
                        {
                            var r = renderers[j];

                            var lodTransform = EditorUtility.CreateGameObjectWithHideFlags(r.name,
                                                                                           k_DefaultHideFlags, typeof(MeshFilter), typeof(MeshRenderer)).transform;
                            lodTransform.parent        = go.transform;
                            lodTransform.localPosition = Vector3.zero;

                            var lodMF       = lodTransform.GetComponent <MeshFilter>();
                            var lodRenderer = lodTransform.GetComponent <MeshRenderer>();

                            EditorUtility.CopySerialized(r.GetComponent <MeshFilter>(), lodMF);
                            EditorUtility.CopySerialized(r, lodRenderer);

                            AppendLODNameToRenderer(lodRenderer, i);

                            renderers[j] = lodRenderer;
                        }
                    }
                }

                List <LOD> lods        = new List <LOD>();
                var        maxLODFound = -1;
                for (int i = 0; i <= LODData.MaxLOD; i++)
                {
                    var renderers = lodData[i];
                    if (renderers == null || renderers.Length == 0)
                    {
                        break;
                    }

                    maxLODFound++;
                }

                for (int i = 0; i <= maxLODFound; i++)
                {
                    var lod = new LOD();
                    lod.renderers = lodData[i];
                    lod.screenRelativeTransitionHeight = i == maxLODFound ? 0.01f : Mathf.Pow(0.5f, i + 1);
                    lods.Add(lod);
                }

                var lodGroup = go.AddComponent <LODGroup>();
                lodGroup.SetLODs(lods.ToArray());
                lodGroup.RecalculateBounds();

                s_ModelAssetsProcessed.Add(assetPath);
            }
        }