예제 #1
0
        static void GenerateLODs(GameObject go)
        {
            // A NOP to make sure we have an instance before launching into threads that may need to execute on the main thread
            MonoBehaviourHelper.ExecuteOnMainThread(() => {});

            var meshFilters = go.GetComponentsInChildren <MeshFilter>();

            if (meshFilters.Length > 0)
            {
                var lodGroup = go.GetComponent <LODGroup>();
                if (!lodGroup)
                {
                    lodGroup = go.AddComponent <LODGroup>();
                }

                var lods = new LOD[maxLOD + 1];
                var lod0 = lods[0];
                lod0.renderers = go.GetComponentsInChildren <MeshRenderer>();
                lod0.screenRelativeTransitionHeight = 0.5f;
                lods[0] = lod0;

                var meshes = new List <Mesh>();

                for (int l = 1; l <= maxLOD; l++)
                {
                    var lodRenderers = new List <MeshRenderer>();
                    foreach (var mf in meshFilters)
                    {
                        var sharedMesh = mf.sharedMesh;

                        if (!sharedMesh)
                        {
                            Debug.LogWarning("AutoLOD: Missing mesh " + mf.name, mf);
                            continue;
                        }

                        var lodTransform = EditorUtility.CreateGameObjectWithHideFlags(string.Format("{0} LOD{1}", sharedMesh.name, l),
                                                                                       k_DefaultHideFlags, typeof(MeshFilter), typeof(MeshRenderer)).transform;
                        lodTransform.SetParent(mf.transform, false);

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

                        lodRenderers.Add(lodRenderer);

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

                        var simplifiedMesh = new Mesh();
                        simplifiedMesh.name = sharedMesh.name + string.Format(" LOD{0}", l);
                        lodMF.sharedMesh    = simplifiedMesh;
                        meshes.Add(simplifiedMesh);

                        var meshLOD = MeshLOD.GetGenericInstance(meshSimplifierType);
                        meshLOD.InputMesh  = sharedMesh;
                        meshLOD.OutputMesh = simplifiedMesh;
                        meshLOD.Quality    = Mathf.Pow(0.5f, l);
                        meshLOD.Generate();
                    }

                    var lod = lods[l];
                    lod.renderers = lodRenderers.ToArray();
                    lod.screenRelativeTransitionHeight = l == maxLOD ? 0.01f : Mathf.Pow(0.5f, l + 1);
                    lods[l] = lod;
                }

                lodGroup.ForceLOD(0);
                lodGroup.SetLODs(lods.ToArray());
                lodGroup.RecalculateBounds();
                lodGroup.ForceLOD(-1);

#if UNITY_2018_2_OR_NEWER
                var prefab = PrefabUtility.GetCorrespondingObjectFromSource(go);
#else
                var prefab = PrefabUtility.GetPrefabParent(go);
#endif
                if (prefab)
                {
                    var lodsAssetPath = GetLODAssetPath(prefab);
                    if (File.Exists(lodsAssetPath))
                    {
                        meshes.ForEach(m => AssetDatabase.AddObjectToAsset(m, lodsAssetPath));
                    }
                    else
                    {
                        ObjectUtils.CreateAssetFromObjects(meshes.ToArray(), lodsAssetPath);
                    }
                }
            }
        }
예제 #2
0
    void GenerateLODs(Action completedCallback)
    {
        int maxLOD = 1;
        var go     = gameObject;

        var hlodLayer = LayerMask.NameToLayer(HLODLayer);

        var lodGroup = go.GetComponent <LODGroup>();

        if (lodGroup)
        {
            var lods = new LOD[maxLOD + 1];
            var lod0 = lodGroup.GetLODs()[0];
            lod0.screenRelativeTransitionHeight = 0.5f;
            lods[0] = lod0;

            var meshes = new List <Mesh>();

            var totalMeshCount   = maxLOD * lod0.renderers.Length;
            var runningMeshCount = 0;
            for (int l = 1; l <= maxLOD; l++)
            {
                var lodRenderers = new List <MeshRenderer>();
                foreach (var mr in lod0.renderers)
                {
                    var mf         = mr.GetComponent <MeshFilter>();
                    var sharedMesh = mf.sharedMesh;

                    var lodTransform = UnityEditor.EditorUtility.CreateGameObjectWithHideFlags(string.Format("{0} LOD{1}", sharedMesh.name, l),
                                                                                               k_DefaultHideFlags, typeof(MeshFilter), typeof(MeshRenderer)).transform;
                    lodTransform.gameObject.layer = hlodLayer;
                    lodTransform.SetPositionAndRotation(mf.transform.position, mf.transform.rotation);
                    lodTransform.localScale = mf.transform.lossyScale;
                    lodTransform.SetParent(mf.transform, true);

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

                    lodRenderers.Add(lodRenderer);

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

                    var simplifiedMesh = new Mesh();
                    simplifiedMesh.name = sharedMesh.name + string.Format(" LOD{0}", l);
                    lodMF.sharedMesh    = simplifiedMesh;
                    meshes.Add(simplifiedMesh);

                    var index      = l;
                    var inputMesh  = sharedMesh.ToWorkingMesh();
                    var outputMesh = simplifiedMesh.ToWorkingMesh();

                    var meshSimplifier = (IMeshSimplifier)Activator.CreateInstance(meshSimplifierType);



                    meshSimplifier.Simplify(inputMesh, outputMesh, Mathf.Pow(meshSimplificationRatio, l), () =>
                    {
                        Debug.Log("Completed LOD " + index);
                        outputMesh.ApplyToMesh(simplifiedMesh);
                        simplifiedMesh.RecalculateBounds();

                        runningMeshCount++;
                        Debug.Log(runningMeshCount + " vs " + totalMeshCount);
                        if (runningMeshCount == totalMeshCount && completedCallback != null)
                        {
                            completedCallback();
                        }
                    });
                }

                var lod = lods[l];
                lod.renderers = lodRenderers.ToArray();
                lod.screenRelativeTransitionHeight = l == maxLOD ? 0.01f : Mathf.Pow(meshSimplificationRatio, l + 1);
                lods[l] = lod;
            }

            lodGroup.ForceLOD(0);
            lodGroup.SetLODs(lods.ToArray());
            lodGroup.RecalculateBounds();
            lodGroup.ForceLOD(-1);

#if UNITY_2018_2_OR_NEWER
            var prefab = UnityEditor.PrefabUtility.GetCorrespondingObjectFromSource(go);
#else
            var prefab = UnityEditor.PrefabUtility.GetPrefabParent(go);
#endif
            if (prefab)
            {
                var assetPath     = UnityEditor.AssetDatabase.GetAssetPath(prefab);
                var pathPrefix    = Path.GetDirectoryName(assetPath) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(assetPath);
                var lodsAssetPath = pathPrefix + "_lods.asset";
                ObjectUtils.CreateAssetFromObjects(meshes.ToArray(), lodsAssetPath);
            }
        }
    }
예제 #3
0
        static void GenerateLODs(GameObject go)
        {
            // A NOP to make sure we have an instance before launching into threads that may need to execute on the main thread
            MonoBehaviourHelper.ExecuteOnMainThread(() => {});

            var meshFilters = go.GetComponentsInChildren <MeshFilter>();

            if (meshFilters.Length > 0)
            {
                var lodGroup = go.GetComponent <LODGroup>();
                if (!lodGroup)
                {
                    lodGroup = go.AddComponent <LODGroup>();
                }

                var lods = new LOD[maxLOD + 1];
                var lod0 = lods[0];
                lod0.renderers = go.GetComponentsInChildren <MeshRenderer>();
                lod0.screenRelativeTransitionHeight = 0.5f;
                lods[0] = lod0;

                var meshes = new List <Mesh>();

                for (int l = 1; l <= maxLOD; l++)
                {
                    var lodRenderers = new List <MeshRenderer>();
                    foreach (var mf in meshFilters)
                    {
                        var sharedMesh = mf.sharedMesh;

                        if (!sharedMesh)
                        {
                            Debug.LogWarning("AutoLOD: Missing mesh " + mf.name, mf);
                            continue;
                        }

                        var lodTransform = EditorUtility.CreateGameObjectWithHideFlags(string.Format("{0} LOD{1}", sharedMesh.name, l),
                                                                                       k_DefaultHideFlags, typeof(MeshFilter), typeof(MeshRenderer)).transform;
                        lodTransform.SetParent(mf.transform, false);

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

                        lodRenderers.Add(lodRenderer);

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

                        var simplifiedMesh = new Mesh();
                        simplifiedMesh.name = sharedMesh.name + string.Format(" LOD{0}", l);
                        lodMF.sharedMesh    = simplifiedMesh;
                        meshes.Add(simplifiedMesh);

                        var worker = new BackgroundWorker();

                        var index      = l;
                        var inputMesh  = sharedMesh.ToWorkingMesh();
                        var outputMesh = simplifiedMesh.ToWorkingMesh();

                        var meshSimplifier = (IMeshSimplifier)Activator.CreateInstance(meshSimplifierType);
                        worker.DoWork += (sender, args) =>
                        {
                            meshSimplifier.Simplify(inputMesh, outputMesh, Mathf.Pow(0.5f, index));
                            args.Result = outputMesh;
                        };

                        worker.RunWorkerCompleted += (sender, args) =>
                        {
                            var resultMesh = (WorkingMesh)args.Result;
                            resultMesh.ApplyToMesh(simplifiedMesh);
                            simplifiedMesh.RecalculateBounds();
                        };

                        worker.RunWorkerAsync();
                    }

                    var lod = lods[l];
                    lod.renderers = lodRenderers.ToArray();
                    lod.screenRelativeTransitionHeight = l == maxLOD ? 0.01f : Mathf.Pow(0.5f, l + 1);
                    lods[l] = lod;
                }

                lodGroup.ForceLOD(0);
                lodGroup.SetLODs(lods.ToArray());
                lodGroup.RecalculateBounds();
                lodGroup.ForceLOD(-1);

                var prefab = PrefabUtility.GetPrefabParent(go);
                if (prefab)
                {
                    var lodsAssetPath = GetLODAssetPath(prefab);
                    if (File.Exists(lodsAssetPath))
                    {
                        meshes.ForEach(m => AssetDatabase.AddObjectToAsset(m, lodsAssetPath));
                    }
                    else
                    {
                        ObjectUtils.CreateAssetFromObjects(meshes.ToArray(), lodsAssetPath);
                    }
                }
            }
        }
예제 #4
0
    void GenerateLODs()
    {
        int maxLOD = 1;
        var go     = gameObject;

        var hlodLayer = LayerMask.NameToLayer(HLODLayer);

        var lodGroup = go.GetComponent <LODGroup>();

        if (lodGroup)
        {
            var lods = new LOD[maxLOD + 1];
            var lod0 = lodGroup.GetLODs()[0];
            lod0.screenRelativeTransitionHeight = 0.5f;
            lods[0] = lod0;

            var meshes = new List <Mesh>();

            var totalMeshCount = maxLOD * lod0.renderers.Length;
            for (int l = 1; l <= maxLOD; l++)
            {
                var lodRenderers = new List <MeshRenderer>();
                foreach (var mr in lod0.renderers)
                {
                    var mf         = mr.GetComponent <MeshFilter>();
                    var sharedMesh = mf.sharedMesh;

                    var lodTransform = EditorUtility.CreateGameObjectWithHideFlags(string.Format("{0} LOD{1}", sharedMesh.name, l),
                                                                                   k_DefaultHideFlags, typeof(MeshFilter), typeof(MeshRenderer)).transform;
                    lodTransform.gameObject.layer = hlodLayer;
                    lodTransform.SetPositionAndRotation(mf.transform.position, mf.transform.rotation);
                    lodTransform.localScale = mf.transform.lossyScale;
                    lodTransform.SetParent(mf.transform, true);

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

                    lodRenderers.Add(lodRenderer);

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

                    var simplifiedMesh = new Mesh();
                    simplifiedMesh.name = sharedMesh.name + string.Format(" LOD{0}", l);
                    lodMF.sharedMesh    = simplifiedMesh;
                    meshes.Add(simplifiedMesh);

                    var meshLOD = new MeshLOD();
                    meshLOD.inputMesh          = sharedMesh;
                    meshLOD.outputMesh         = simplifiedMesh;
                    meshLOD.quality            = Mathf.Pow(0.5f, l);
                    meshLOD.meshSimplifierType = meshSimplifierType;
                }

                var lod = lods[l];
                lod.renderers = lodRenderers.ToArray();
                lod.screenRelativeTransitionHeight = l == maxLOD ? 0.01f : Mathf.Pow(0.5f, l + 1);
                lods[l] = lod;
            }

            lodGroup.ForceLOD(0);
            lodGroup.SetLODs(lods.ToArray());
            lodGroup.RecalculateBounds();
            lodGroup.ForceLOD(-1);

#if UNITY_2018_2_OR_NEWER
            var prefab = PrefabUtility.GetCorrespondingObjectFromSource(go);
#else
            var prefab = PrefabUtility.GetPrefabParent(go);
#endif
            if (prefab)
            {
                var assetPath     = AssetDatabase.GetAssetPath(prefab);
                var pathPrefix    = Path.GetDirectoryName(assetPath) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(assetPath);
                var lodsAssetPath = pathPrefix + "_lods.asset";
                ObjectUtils.CreateAssetFromObjects(meshes.ToArray(), lodsAssetPath);
            }
        }
    }