using Godot; using System.Collections; using System.Collections.Generic; using Godot.Collections; namespace Rokojori { [Tool] [GlobalClass] public partial class LODParent:Node3D { [Export] public float cullDistance = 4000; [Export] public Curve distribution = MathX.Curve( 0, 1 ); [Export] public Node3D[] lods; [Export] public float updateDistance = 10; float lastSquaredDistance = -1; int lastSelectedIndex = -1; [Export] public int changeBlock = 0; [Export] public int blocker = 0; public override void _Process( double delta ) { if ( blocker > 0 ) { blocker --; return; } if ( lods == null || lods.Length == 0 ) { return; } var camera = GetViewport().GetCamera3D(); #if TOOLS if ( Engine.IsEditorHint() ) { camera = EditorInterface.Singleton.GetEditorViewport3D().GetCamera3D(); } #endif var squaredDistance = GlobalPosition.DistanceSquaredTo( camera.GlobalPosition ); if ( Mathf.Abs( lastSquaredDistance - squaredDistance ) < updateDistance * updateDistance ) { return; } lastSquaredDistance = squaredDistance; var realDistance = Mathf.Sqrt( lastSquaredDistance ); var normalizedDistance = MathX.NormalizeClamped( realDistance, 0, cullDistance ); var active = distribution.Sample( normalizedDistance ) * lods.Length; var selectedIndex = Mathf.Min( lods.Length - 1, Mathf.RoundToInt( active ) ); if ( lastSelectedIndex == selectedIndex ) { return; } // RJLog.Log( // "realDistance:", realDistance, // "normalizedDistance:", normalizedDistance, // "active:", active, // "selectedIndex:", selectedIndex // ); var selectedLOD = lods[ selectedIndex ]; lastSelectedIndex = selectedIndex; Arrays.ForEach( lods, l => NodeState.Set( l, selectedLOD == l ) ); blocker = changeBlock; } } }