void EditorUpdate() { if ((m_CoroutineQueue.Count > 0 || m_SceneDirty || (m_RootVolume && m_RootVolume.dirty)) && m_ServiceCoroutineQueue == null) { m_ServiceCoroutineQueue = MonoBehaviourHelper.StartCoroutine(ServiceCoroutineQueue()); } }
public JobHandle Generate(NativeArray <JobHandle>?jobDependencies = null) { // 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 job = new GenerateMeshLODJob(); job.inputMesh = inputMesh.ToWorkingMesh(Allocator.TempJob); job.quality = quality; var typeNameBytes = Encoding.UTF8.GetBytes(meshSimplifierType.AssemblyQualifiedName); job.meshSimplifierTypeName = new NativeArray <byte>(typeNameBytes, Allocator.TempJob); job.outputMesh = new WorkingMesh(Allocator.Persistent, inputMesh.vertexCount, inputMesh.GetTriangleCount(), inputMesh.subMeshCount, inputMesh.blendShapeCount); JobHandle jobHandle; if (jobDependencies.HasValue) { jobHandle = job.Schedule(JobHandle.CombineDependencies(jobDependencies.Value)); } else { jobHandle = job.Schedule(); } MonoBehaviourHelper.StartCoroutine(UpdateMesh(jobHandle, job)); return(jobHandle); }
public JobHandle Generate(NativeArray <JobHandle>?jobDependencies = null) { // 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 job = default(T); var inputMesh = InputMesh; job.InputMesh = inputMesh.ToWorkingMesh(Allocator.Persistent); job.Quality = Quality; job.OutputMesh = new WorkingMesh(Allocator.Persistent, inputMesh.vertexCount, inputMesh.GetTriangleCount(), inputMesh.subMeshCount, inputMesh.blendShapeCount); JobHandle jobHandle; if (jobDependencies.HasValue) { jobHandle = job.Schedule(JobHandle.CombineDependencies(jobDependencies.Value)); } else { jobHandle = job.Schedule(); } MonoBehaviourHelper.StartCoroutine(UpdateMesh(jobHandle, job)); return(jobHandle); }
IEnumerator 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; while (InstaLODNative.currentMeshOperationState != null) { yield return(null); } 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) { yield return(null); } MonoBehaviourHelper.ExecuteOnMainThread(() => { var mf = renderer.GetComponent <MeshFilter>(); mf.sharedMesh.ApplyToWorkingMesh(outputMesh); UnityObject.DestroyImmediate(mf.gameObject); }); }
public void Destroy() { MonoBehaviourHelper.StartCoroutine(ObjectUtils.FindGameObject("HLODs", root => { DestroyImmediate(root); })); Utilities.FileUtils.DeleteDirectory(Application.dataPath + Path.DirectorySeparatorChar + SceneLOD.GetSceneLODPath()); AssetDatabase.Refresh(); }
void EditorUpdate() { if (m_Updater == null) { MonoBehaviourHelper.StartCoroutine(SetLODUpdater()); } if (SceneLODCreator.instance.IsCreating() == true) { s_HLODEnabled = false; } }
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(meshLOD.meshSimplifierType); 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()); } var outputMesh = new WorkingMesh(); #if UNITY_2017_3_OR_NEWER outputMesh.indexFormat = inputMesh.indexFormat; #endif meshSimplifier.Simplify(inputMesh, outputMesh, meshLOD.quality, () => { var outMesh = meshLOD.outputMesh; Debug.Log("Completed LOD " + outMesh.name); outputMesh.name = outMesh.name; outputMesh.ApplyToMesh(outMesh); outMesh.RecalculateBounds(); var outputMeshID = outMesh.GetInstanceID(); if (preprocessMeshes.Remove(outputMeshID)) { Debug.Log("Pre-process mesh complete: " + outputMeshID); } });; }; worker.RunWorkerAsync(); }
static void UpdateDependencies() { #if HAS_MINIMUM_REQUIRED_VERSION if (meshSimplifierType == null) { MonoBehaviourHelper.StartCoroutine(GetDefaultSimplifier()); ModelImporterLODGenerator.enabled = false; return; } MonoBehaviourHelper.maxSharedExecutionTimeMS = maxExecutionTime == 0 ? Mathf.Infinity : maxExecutionTime; LODDataEditor.meshSimplifier = meshSimplifierType.AssemblyQualifiedName; LODDataEditor.batcher = batcherType.AssemblyQualifiedName; LODDataEditor.maxLODGenerated = maxLOD; LODDataEditor.initialLODMaxPolyCount = initialLODMaxPolyCount; LODVolume.meshSimplifierType = meshSimplifierType; LODVolume.batcherType = batcherType; LODVolume.drawBounds = sceneLODEnabled && showVolumeBounds; ModelImporterLODGenerator.saveAssets = saveAssets; ModelImporterLODGenerator.meshSimplifierType = meshSimplifierType; ModelImporterLODGenerator.maxLOD = maxLOD; ModelImporterLODGenerator.enabled = generateOnImport; ModelImporterLODGenerator.initialLODMaxPolyCount = initialLODMaxPolyCount; if (sceneLODEnabled && !SceneLOD.activated) { if (!SceneLOD.instance) { Debug.LogError("SceneLOD failed to start"); } } else if (!sceneLODEnabled && SceneLOD.activated) { UnityObject.DestroyImmediate(SceneLOD.instance); } #else ModelImporterLODGenerator.enabled = false; #endif }
IEnumerator ServiceCoroutineQueue() { m_ServiceCoroutineExecutionTime.Start(); if (m_SceneDirty) { m_CoroutineQueue.Enqueue(UpdateOctree()); m_SceneDirty = false; } if (m_RootVolume && m_RootVolume.dirty) { m_CoroutineQueue.Enqueue(m_RootVolume.UpdateHLODs()); } while (m_CoroutineQueue.Count > 0) { yield return(MonoBehaviourHelper.StartCoroutine(m_CoroutineQueue.Dequeue())); } ResetServiceCoroutineQueue(); }
public JobHandle Generate() { // 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 job = default(T); var inputMesh = InputMesh; job.InputMesh = inputMesh.ToWorkingMesh(Allocator.Persistent); job.Quality = Quality; // Allocate a persistent working mesh for output, so that we can apply it after the job completes (i.e. memory // allocated in a job is freed when the job completes) var workingMesh = new WorkingMesh(Allocator.Persistent, inputMesh.vertexCount, inputMesh.GetTriangleCount(), inputMesh.subMeshCount, inputMesh.blendShapeCount); workingMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; job.OutputMesh = workingMesh; var jobHandle = job.Schedule(); MonoBehaviourHelper.StartCoroutine(UpdateMesh(jobHandle, job)); return(jobHandle); }
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(ref outputMesh); //job.CloudJob.StateHandler.RequestJobDeletion(); AssetDatabaseEx.DeletePendingLODFolder(jobFolderName); AssetDatabase.DeleteAsset(lodAssetDir); UnityObject.DestroyImmediate(renderer.gameObject); }); }
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); } } } }
static void GenerateLODs(MenuCommand menuCommand) { MonoBehaviourHelper.StartCoroutine(GenerateLODsCoroutine(menuCommand)); }
void OnPostprocessModel(GameObject go) { if (!go.GetComponentInChildren <LODGroup>() && meshSimplifierType != null && IsEditable(assetPath)) { if (go.GetComponentsInChildren <SkinnedMeshRenderer>().Any()) { Debug.LogWarning("Automatic LOD generation on skinned meshes is not currently supported"); 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 <IMeshLOD>(); var preprocessMeshes = new HashSet <int>(); var lodData = GetLODData(assetPath); var overrideDefaults = lodData.overrideDefaults; var importSettings = lodData.importSettings; // It's possible to override defaults to either generate on import or to not generate and use specified // LODs in the override, but in the case where we are not overriding and globally we are not generating // on import, then there should be no further processing. if (!overrideDefaults && !enabled) { return; } if (importSettings.generateOnImport) { if (importSettings.maxLODGenerated == 0 && polyCount <= importSettings.initialLODMaxPolyCount) { return; } var simplifierType = Type.GetType(importSettings.meshSimplifier) ?? meshSimplifierType; if (polyCount > importSettings.initialLODMaxPolyCount) { foreach (var mf in originalMeshFilters) { var inputMesh = mf.sharedMesh; var outputMesh = new Mesh(); outputMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; outputMesh.name = inputMesh.name; outputMesh.bounds = inputMesh.bounds; mf.sharedMesh = outputMesh; var meshLOD = MeshLOD.GetGenericInstance(meshSimplifierType); 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; lodTransform.localRotation = Quaternion.identity; lodTransform.localScale = new Vector3(1, 1, 1); var lodMF = lodTransform.GetComponent <MeshFilter>(); var lodRenderer = lodTransform.GetComponent <MeshRenderer>(); AppendLODNameToRenderer(lodRenderer, i); var outputMesh = new Mesh(); outputMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; 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 = MeshLOD.GetGenericInstance(meshSimplifierType); 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)); if (saveAssets) { AssetDatabase.SaveAssets(); } if (preprocessMeshes.Count > 0) { // Process dependencies first var jobDependencies = new List <JobHandle>(); meshLODs.RemoveAll(ml => { if (preprocessMeshes.Contains(ml.OutputMesh.GetInstanceID())) { jobDependencies.Add(ml.Generate()); return(true); } return(false); }); // Process remaining meshes foreach (var ml in meshLODs) { MonoBehaviourHelper.StartCoroutine(ml.GenerateAfterDependencies(jobDependencies)); } } else { foreach (var ml in meshLODs) { ml.Generate(); } } } } 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++; } var importerRef = new SerializedObject(assetImporter); var importerLODLevels = importerRef.FindProperty("m_LODScreenPercentages"); for (int i = 0; i <= maxLODFound; i++) { var lod = new LOD(); lod.renderers = lodData[i]; var screenPercentage = i == maxLODFound ? 0.01f : Mathf.Pow(0.5f, i + 1); // Use the model importer percentages if they exist if (i < importerLODLevels.arraySize && maxLODFound == importerLODLevels.arraySize) { var element = importerLODLevels.GetArrayElementAtIndex(i); screenPercentage = element.floatValue; } lod.screenRelativeTransitionHeight = screenPercentage; lods.Add(lod); } if (importerLODLevels.arraySize != 0 && maxLODFound != importerLODLevels.arraySize - 1) { Debug.LogWarning("The model has an existing lod group, but it's settings will not be used because " + "the specified lod count in the AutoLOD settings is different."); } var lodGroup = go.AddComponent <LODGroup>(); lodGroup.SetLODs(lods.ToArray()); lodGroup.RecalculateBounds(); // Keep model importer in sync importerLODLevels.ClearArray(); for (int i = 0; i < lods.Count; i++) { var lod = lods[i]; importerLODLevels.InsertArrayElementAtIndex(i); var element = importerLODLevels.GetArrayElementAtIndex(i); element.floatValue = lod.screenRelativeTransitionHeight; } importerRef.ApplyModifiedPropertiesWithoutUndo(); s_ModelAssetsProcessed.Add(assetPath); } }
IEnumerator Simplify(WorkingMesh inputMesh, WorkingMesh outputMesh, float quality) { 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); 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 sharedMaterials = new Material[mesh.subMeshCount]; if (Directory.Exists(materialPath) == false) { Directory.CreateDirectory(materialPath); } //For submesh, we should create material asset. //otherwise, simplygon will be combine uv of submesh. for (int i = 0; i < mesh.subMeshCount; i++) { var material = new Material(Shader.Find("Standard")); material.name = "Material " + i.ToString(); AssetDatabase.CreateAsset(material, materialPath + "/" + material.name); 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) { yield return(null); } while (string.IsNullOrEmpty(job.AssetDirectory)) { yield return(null); } 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 = lodPath + 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); AssetDatabase.DeleteAsset(materialPath); UnityObject.DestroyImmediate(renderer.gameObject); }); }