174 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C#
		
	
	
	
			
		
		
	
	
			174 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C#
		
	
	
	
using Godot;
 | 
						|
using System.Collections;
 | 
						|
using System.Collections.Generic;
 | 
						|
using Godot.Collections;
 | 
						|
 | 
						|
namespace Rokojori
 | 
						|
{
 | 
						|
  [Tool]
 | 
						|
  [GlobalClass]
 | 
						|
  public partial class LODParent:Node3D
 | 
						|
  {
 | 
						|
    public enum DistanceMode
 | 
						|
    {
 | 
						|
      Via_Array,
 | 
						|
      Via_Curve
 | 
						|
    }
 | 
						|
 | 
						|
    [Export]
 | 
						|
    public DistanceMode mode;
 | 
						|
 | 
						|
    [ExportGroup("Array Mode")]
 | 
						|
    [Export]
 | 
						|
    public bool arrayCulling = true;
 | 
						|
    [Export]
 | 
						|
    public float[] arrayTresholds;
 | 
						|
 | 
						|
    [ExportGroup("Curve Mode")]
 | 
						|
    [Export]
 | 
						|
    public bool curveCulling = true;
 | 
						|
 | 
						|
    [Export]
 | 
						|
    public float curveCullDistance = 4000;
 | 
						|
 | 
						|
    [Export]
 | 
						|
    public Curve curveDistribution = MathX.Curve( 0, 1 );
 | 
						|
 | 
						|
    [ExportGroup("LODs")]
 | 
						|
    [Export]
 | 
						|
    public Node3D[] lods;
 | 
						|
 | 
						|
    [Export]
 | 
						|
    public float updateDistance = 10;
 | 
						|
 | 
						|
    [ExportGroup("Testing")]
 | 
						|
    [Export]
 | 
						|
    public float X_processingCameraDistance = 0;
 | 
						|
    
 | 
						|
    [Export]
 | 
						|
    public float X_realCameraDistance = 0;
 | 
						|
 | 
						|
    [Export]
 | 
						|
    public float X_selectedIndex = 0;
 | 
						|
 | 
						|
    [Export]
 | 
						|
    public bool testMode = false;
 | 
						|
 | 
						|
    [Export]
 | 
						|
    public float testDistance = 0;
 | 
						|
 | 
						|
    [Export]
 | 
						|
    public bool processOnlyWhenVisible = true;
 | 
						|
 | 
						|
    float lastSquaredDistance = -1;
 | 
						|
    int lastSelectedIndex = -1;
 | 
						|
 | 
						|
    public int changeBlock = 0;
 | 
						|
 | 
						|
    public int blocker = 0;
 | 
						|
 | 
						|
    public override void _Process( double delta )
 | 
						|
    {
 | 
						|
      if ( processOnlyWhenVisible && ! Visible )
 | 
						|
      {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
      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 );
 | 
						|
      X_realCameraDistance = Mathf.Sqrt( squaredDistance );
 | 
						|
 | 
						|
 | 
						|
      if ( testMode )
 | 
						|
      {
 | 
						|
        squaredDistance = testDistance * testDistance;
 | 
						|
      }
 | 
						|
 | 
						|
      if ( Mathf.Abs( lastSquaredDistance - squaredDistance ) < updateDistance * updateDistance )
 | 
						|
      {        
 | 
						|
        return;
 | 
						|
      } 
 | 
						|
 | 
						|
      
 | 
						|
 | 
						|
      lastSquaredDistance = squaredDistance;
 | 
						|
 | 
						|
      var realDistance = Mathf.Sqrt( lastSquaredDistance );
 | 
						|
 | 
						|
      X_processingCameraDistance = realDistance;
 | 
						|
 | 
						|
      var selectedIndex = GetLODIndex( realDistance );
 | 
						|
 | 
						|
      X_selectedIndex = selectedIndex;
 | 
						|
 | 
						|
      if ( lastSelectedIndex == selectedIndex )
 | 
						|
      {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
      lastSelectedIndex = selectedIndex;
 | 
						|
      blocker = changeBlock;
 | 
						|
 | 
						|
      if ( selectedIndex >= lods.Length )
 | 
						|
      {
 | 
						|
        Arrays.ForEach( lods, l => NodeState.Set( l, false ) );
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        var selectedLOD = lods[ selectedIndex ];
 | 
						|
        Arrays.ForEach( lods, l => NodeState.Set( l, selectedLOD == l ) );
 | 
						|
      } 
 | 
						|
    } 
 | 
						|
 | 
						|
    int GetLODIndex( float realDistance )
 | 
						|
    {
 | 
						|
      if ( DistanceMode.Via_Array == mode )
 | 
						|
      {        
 | 
						|
        for ( int i = 0; i < arrayTresholds.Length; i++ )
 | 
						|
        {
 | 
						|
          if ( realDistance <= arrayTresholds[ i ] )
 | 
						|
          {
 | 
						|
            return i;
 | 
						|
          }          
 | 
						|
        }
 | 
						|
 | 
						|
        return arrayCulling ? lods.Length : ( lods.Length - 1 );
 | 
						|
      }
 | 
						|
      else if ( DistanceMode.Via_Curve == mode )
 | 
						|
      {
 | 
						|
        if ( curveCulling && realDistance >= curveCullDistance )
 | 
						|
        {
 | 
						|
          return lods.Length;
 | 
						|
        }
 | 
						|
 | 
						|
        var normalizedDistance = MathX.NormalizeClamped( realDistance, 0, curveCullDistance );
 | 
						|
        var active = curveDistribution.Sample( normalizedDistance ) * lods.Length;
 | 
						|
        return Mathf.Min( lods.Length - 1, Mathf.RoundToInt( active ) ); 
 | 
						|
      }
 | 
						|
      
 | 
						|
      return -1;
 | 
						|
    }
 | 
						|
 | 
						|
  }
 | 
						|
} |