rj-action-library/Runtime/LOD/LODBuilder.cs

104 lines
2.1 KiB
C#

using Godot;
using System.Collections;
using System.Collections.Generic;
namespace Rokojori
{
public class LODCameraDistanceLevel
{
public Mesh mesh;
public Material material;
public float distance;
}
public class LODBuilder
{
public enum Mode
{
CameraDistance
}
Mode mode = Mode.CameraDistance;
public static LODBuilder ByCameraDistance()
{
var builder = new LODBuilder();
builder.mode = Mode.CameraDistance;
return builder;
}
List<LODCameraDistanceLevel> levels = new List<LODCameraDistanceLevel>();
Material material;
public LODBuilder SetMaterial( Material material )
{
this.material = material;
return this;
}
public LODBuilder Add( float distance, Mesh mesh, Material material = null )
{
var level = new LODCameraDistanceLevel
{
mesh = mesh,
distance = distance,
material = material
};
levels.Add( level );
return this;
}
public LODNode Create( Node parent, string name = "LOD" )
{
var lodNode = parent.CreateChild<LODNode>( name );
var arrangement = new LODArrangement();
levels.Sort( ( a, b ) => Mathf.Sign( a.distance - b.distance ) );
var maxMap = new Dictionary<LODCameraDistanceLevel, float>();
for ( int i = 0; i < levels.Count; i++ )
{
if ( ( i + 1 ) < levels.Count )
{
maxMap[ levels[ i ] ] = levels[ i + 1 ].distance;
}
else
{
maxMap[ levels[ i ] ] = 10000f;
}
}
levels[ 0 ].distance = 0;
levels.ForEach(
( l )=>
{
var level = new LODLevel();
var distanceRule = new LODCameraDistanceRule();
distanceRule.minDistance = l.distance;
distanceRule.maxDistance = maxMap[ l ];
level.visibilityRules = [ distanceRule ];
level.mesh = l.mesh;
level.material = l.material != null ? l.material : material;
arrangement.levels = arrangement.levels.Add( level );
}
);
lodNode.arrangement = arrangement;
return lodNode;
}
}
}