// -------------------------------------------------------------------------------------------------------------------- // // Copyright (c) VRMADA, All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- using UnityEngine; namespace UltimateXR.Extensions.Unity.Render { /// /// extensions. /// Most functionality has been copied from: /// https://github.com/JulienHeijmans/EditorScripts/blob/master/Scripts/Utility/Editor/LODExtendedUtility.cs, which /// in turn copied functionality from: /// https://github.com/Unity-Technologies/AutoLOD/blob/master/Scripts/Extensions/LODGroupExtensions.cs /// public static class LODGroupExt { #region Public Methods /// /// Gets the LOD level index that should be enabled from a specific view. /// /// Component to check /// Camera to use as point of view /// LOD level index that should be enabled public static int GetVisibleLevel(this LODGroup lodGroup, Camera camera) { if (camera == null) { return lodGroup.lodCount - 1; } var lods = lodGroup.GetLODs(); var relativeHeight = GetRelativeHeight(lodGroup, camera); int lodIndex = lodGroup.lodCount - 1; for (int i = 0; i < lods.Length; i++) { var lod = lods[i]; if (relativeHeight >= lod.screenRelativeTransitionHeight) { lodIndex = i; break; } } return lodIndex; } /// /// Manually enables all renderers belonging to a LOD level. /// /// Component to process /// Level whose renderers to enable public static void EnableLevelRenderers(this LODGroup lodGroup, int level) { var lods = lodGroup.GetLODs(); for (int i = 0; i < lods.Length; i++) { foreach (Renderer renderer in lods[i].renderers) { if (renderer != null) { renderer.enabled = i == level; } } } } /// /// Manually enables the renderers from all LOD levels. /// /// Component to process public static void EnableAllLevelRenderers(this LODGroup lodGroup) { var lods = lodGroup.GetLODs(); for (int i = 0; i < lods.Length; i++) { foreach (Renderer renderer in lods[i].renderers) { if (renderer != null) { renderer.enabled = true; } } } } #endregion #region Private Methods /// /// Computes the relative height in the camera view. /// /// Component to check /// Camera to use as point of view /// Relative height private static float GetRelativeHeight(LODGroup lodGroup, Camera camera) { var distance = (lodGroup.transform.TransformPoint(lodGroup.localReferencePoint) - camera.transform.position).magnitude; return DistanceToRelativeHeight(camera, distance / QualitySettings.lodBias, GetWorldSpaceSize(lodGroup)); } /// /// Computes the relative height in the camera view. /// /// Camera to use as point of view /// Distance to the camera /// Largest axis in world-space /// Relative height private static float DistanceToRelativeHeight(Camera camera, float distance, float size) { if (camera.orthographic) { return size * 0.5F / camera.orthographicSize; } var halfAngle = Mathf.Tan(Mathf.Deg2Rad * camera.fieldOfView * 0.5F); var relativeHeight = size * 0.5F / (distance * halfAngle); return relativeHeight; } /// /// Computes the largest axis of the in world-space. /// /// Component to process /// World space size private static float GetWorldSpaceSize(LODGroup lodGroup) { return GetWorldSpaceScale(lodGroup.transform) * lodGroup.size; } /// /// Computes the largest scale axis. /// /// Transform to get the largest scale of /// Largest scale axis private static float GetWorldSpaceScale(Transform transform) { var scale = transform.lossyScale; float largestAxis = Mathf.Abs(scale.x); largestAxis = Mathf.Max(largestAxis, Mathf.Abs(scale.y)); largestAxis = Mathf.Max(largestAxis, Mathf.Abs(scale.z)); return largestAxis; } #endregion } }