コード例 #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 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);

#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
        public void Simplify(WorkingMesh inputMesh, WorkingMesh outputMesh, float quality)
        {
            var isMainThread = MonoBehaviourHelper.IsMainThread();

            Renderer renderer = null;

            UnityCloudJob job     = null;
            string        jobName = null;

            var assembly     = typeof(SharedData).Assembly;
            var cloudJobType = assembly.GetType("Simplygon.Cloud.Yoda.IntegrationClient.CloudJob");
            var jobNameField = cloudJobType.GetField("name", BindingFlags.NonPublic | BindingFlags.Instance);

            lock (executionLock)
            {
                const int kSimultaneousJobs = 4;
                //var processSubscriptionRestrictionsType = assembly.GetType("Simplygon.Cloud.Yoda.Client.ProcessSubscriptionRestrictions23");
                //var simultaneousJobsProperty = processSubscriptionRestrictionsType.GetProperty("SimultaneousJobs");
                //var accountType = assembly.GetType("Simplygon.Cloud.Yoda.Client.User23");
                //var processSubscriptionsRestrictionsProperty = accountType.GetProperty("ProcessSubscriptionRestrictions");
                //var processSubscriptionRestrictions = processSubscriptionsRestrictionsProperty.GetValue(SharedData.Instance.Account, null);
                //var simultaneousJobs = (int)simultaneousJobsProperty.GetValue(processSubscriptionRestrictions, null);

                while (SharedData.Instance.GeneralManager.JobManager.ProcessingJobCount >= kSimultaneousJobs)
                {
                    if (!isMainThread)
                    {
                        Thread.Sleep(1000);
                    }
                }

                MonoBehaviourHelper.ExecuteOnMainThread(() =>
                {
                    var go   = EditorUtility.CreateGameObjectWithHideFlags("Temp", HideFlags.HideAndDontSave, typeof(MeshRenderer), typeof(MeshFilter));
                    var mf   = go.GetComponent <MeshFilter>();
                    var mesh = new Mesh();
                    inputMesh.ApplyToMesh(mesh);
                    mf.sharedMesh       = mesh;
                    renderer            = go.GetComponent <MeshRenderer>();
                    var material        = new Material(Shader.Find("Standard"));
                    var sharedMaterials = new Material[mesh.subMeshCount];
                    for (int i = 0; i < mesh.subMeshCount; i++)
                    {
                        sharedMaterials[i] = material;
                    }
                    renderer.sharedMaterials = sharedMaterials;
                    renderer.enabled         = false;

                    EditorWindow.GetWindow <Window>(); // Must be visible for background processing

                    SharedData.Instance.Settings.SetDownloadAssetsAutomatically(true);

                    var lodChainProperty = typeof(SharedData).GetProperty("LODChain");
                    var lodChainList     = lodChainProperty.GetValue(SharedData.Instance, null) as IList;
                    var lodChain         = lodChainList[0];

                    var processNodeType   = assembly.GetType("Simplygon.SPL.v80.Node.ProcessNode");
                    var processorProperty = processNodeType.GetProperty("Processor");
                    var processor         = processorProperty.GetValue(lodChain, null);

                    var reductionProcessorType    = assembly.GetType("Simplygon.SPL.v80.Processor.ReductionProcessor");
                    var reductionSettingsProperty = reductionProcessorType.GetProperty("ReductionSettings");
                    var reductionSettingsType     = assembly.GetType("Simplygon.SPL.v80.Settings.ReductionSettings");
                    var reductionSettings         = reductionSettingsProperty.GetValue(processor, null);

                    var triangleRatioProperty = reductionSettingsType.GetProperty("TriangleRatio");
                    triangleRatioProperty.SetValue(reductionSettings, quality, null);

                    jobName        = Path.GetRandomFileName().Replace(".", string.Empty);
                    var prefabList = PrefabUtilityEx.GetPrefabsForSelection(new List <GameObject>()
                    {
                        go
                    });
                    var generalManager = SharedData.Instance.GeneralManager;
                    generalManager.CreateJob(jobName, "myPriority", prefabList, () =>
                    {
                        foreach (var j in generalManager.JobManager.Jobs)
                        {
                            var name = (string)jobNameField.GetValue(j.CloudJob);
                            if (name == jobName)
                            {
                                job = j;
                            }
                        }
                    });
                });

                while (job == null)
                {
                    if (!isMainThread)
                    {
                        Thread.Sleep(100);
                    }
                }
            }

            while (string.IsNullOrEmpty(job.AssetDirectory))
            {
                if (!isMainThread)
                {
                    Thread.Sleep(100);
                }
            }

            MonoBehaviourHelper.ExecuteOnMainThread(() =>
            {
                var customDataType            = assembly.GetType("Simplygon.Cloud.Yoda.IntegrationClient.CloudJob+CustomData");
                var pendingFolderNameProperty = customDataType.GetProperty("UnityPendingLODFolderName");
                var jobCustomDataProperty     = cloudJobType.GetProperty("JobCustomData");
                var jobCustomData             = jobCustomDataProperty.GetValue(job.CloudJob, null);
                var jobFolderName             = pendingFolderNameProperty.GetValue(jobCustomData, null) as string;

                var lodAssetDir = "Assets/LODs/" + job.AssetDirectory;
                var mesh        = AssetDatabase.LoadAssetAtPath <Mesh>(string.Format("{0}/{1}_LOD1.prefab", lodAssetDir, jobName));
                mesh.ApplyToWorkingMesh(outputMesh);

                //job.CloudJob.StateHandler.RequestJobDeletion();
                AssetDatabaseEx.DeletePendingLODFolder(jobFolderName);
                AssetDatabase.DeleteAsset(lodAssetDir);

                UnityObject.DestroyImmediate(renderer.gameObject);
            });
        }
コード例 #3
0
        static void GenerateMeshLOD(MeshLOD meshLOD, HashSet <int> preprocessMeshes)
        {
            // A NOP to make sure we have an instance before launching into threads that may need to execute on the main thread
            MonoBehaviourHelper.ExecuteOnMainThread(() => { });

            WorkingMesh inputMesh   = null;
            var         inputMeshID = meshLOD.inputMesh.GetInstanceID();

            if (!preprocessMeshes.Contains(inputMeshID))
            {
                inputMesh = meshLOD.inputMesh.ToWorkingMesh();
            }

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

#if !SINGLE_THREADED
            var worker = new BackgroundWorker();
            worker.DoWork += (sender, args) =>
            {
                // If this mesh is dependent on another mesh, then let it complete first
                if (inputMesh == null)
                {
                    while (preprocessMeshes.Contains(inputMeshID))
                    {
                        Thread.Sleep(100);
                    }

                    MonoBehaviourHelper.ExecuteOnMainThread(() => inputMesh = meshLOD.inputMesh.ToWorkingMesh());
                }
#endif

            var outputMesh = new WorkingMesh();
#if UNITY_2017_3_OR_NEWER
            outputMesh.indexFormat = inputMesh.indexFormat;
#endif
            meshSimplifier.Simplify(inputMesh, outputMesh, meshLOD.quality);
#if !SINGLE_THREADED
            args.Result = outputMesh;
        };
#endif

#if !SINGLE_THREADED
            worker.RunWorkerCompleted += (sender, args) =>
#endif
            {
                var outMesh = meshLOD.outputMesh;
                Debug.Log("Completed LOD " + outMesh.name);
#if !SINGLE_THREADED
                var resultMesh = (WorkingMesh)args.Result;
#else
                var resultMesh = outputMesh;
#endif
                resultMesh.name = outMesh.name;
                resultMesh.ApplyToMesh(outMesh);
                outMesh.RecalculateBounds();

                var outputMeshID = outMesh.GetInstanceID();
                if (preprocessMeshes.Remove(outputMeshID))
                {
                    Debug.Log("Pre-process mesh complete: " + outputMeshID);
                }
            };

#if !SINGLE_THREADED
            worker.RunWorkerAsync();
#endif
        }
コード例 #4
0
        public void Simplify(WorkingMesh inputMesh, WorkingMesh outputMesh, float quality)
        {
            Renderer renderer = null;

            MonoBehaviourHelper.ExecuteOnMainThread(() =>
            {
                var go   = EditorUtility.CreateGameObjectWithHideFlags("Temp", HideFlags.HideAndDontSave, typeof(MeshRenderer), typeof(MeshFilter));
                var mf   = go.GetComponent <MeshFilter>();
                var mesh = new Mesh();
                inputMesh.ApplyToMesh(mesh);
                mf.sharedMesh       = mesh;
                renderer            = go.GetComponent <MeshRenderer>();
                var material        = new Material(Shader.Find("Standard"));
                var sharedMaterials = new Material[mesh.subMeshCount];
                for (int i = 0; i < mesh.subMeshCount; i++)
                {
                    sharedMaterials[i] = material;
                }
                renderer.sharedMaterials = sharedMaterials;
                renderer.enabled         = false;
            });

            var settings = new InstaLODOptimizeSettings(quality);

            settings.PercentTriangles = quality;
            var nativeMeshSettings = new InstaLODNativeMeshOperationSettings(true);

            nativeMeshSettings.hideSourceGameObjects = false;

            lock (executionLock)
            {
                if (!MonoBehaviourHelper.IsMainThread())
                {
                    while (InstaLODNative.currentMeshOperationState != null)
                    {
                        Thread.Sleep(100);
                    }
                }

                MonoBehaviourHelper.ExecuteOnMainThread(() =>
                {
                    EditorWindow.GetWindow <InstaLODToolkitWindow>(); // Necessary for background processing
                    InstaLODNative.Optimize(new List <Renderer>()
                    {
                        renderer
                    }, settings, nativeMeshSettings);
                    Selection.activeGameObject = null; // Necessary to avoid errors from InstaLOD trying to add settings component to imported model
                });
            }

            while (InstaLODNative.currentMeshOperationState != null)
            {
                if (MonoBehaviourHelper.IsMainThread())
                {
                    InstaLODMainThreadAction.RunMainThreadActions();
                }
                else
                {
                    Thread.Sleep(100);
                }
            }

            MonoBehaviourHelper.ExecuteOnMainThread(() =>
            {
                var mf = renderer.GetComponent <MeshFilter>();
                mf.sharedMesh.ApplyToWorkingMesh(outputMesh);
                UnityObject.DestroyImmediate(mf.gameObject);
            });
        }