Library/VoxelVolume/VoxelVolume.cs
namespace Boxfish.Library;
/// <summary>
/// Example voxel volume component.
/// <para>If you want more freedom, see <see cref="BaseVoxelVolume{T, U}"/> instead.</para>
/// </summary>
[Icon( "view_in_ar" ), Category( "Boxfish" )]
public partial class VoxelVolume
: BaseVoxelVolume<Voxel, VoxelVertex>
{
/// <summary>
/// The reference to our atlas.
/// </summary>
[Property, Category( "Appearance" )]
public AtlasResource Atlas
{
get => _atlas;
set
{
if ( _atlas == value )
return;
_atlas = value;
UpdateObjects();
}
}
private AtlasResource _atlas = ResourceLibrary.Get<AtlasResource>( "resources/base.voxatlas" );
/// <summary>
/// The scale of our voxels in inches.
/// <para>Defaulted to 1 meter.</para>
/// </summary>
[Property, Range( 0.1f, 50f ), Category( "Appearance" )]
public float VoxelScale { get; set; } = VoxelUtils.METER;
#region Abstract class implementation
private Material _material = Material.FromShader( "shaders/base_voxel.shader" );
public override Material Material => _material;
public override float Scale => VoxelScale;
public override bool Collisions => true;
public override VertexAttribute[] Layout => VoxelVertex.Layout;
public override VoxelVertex CreateVertex( Vector3Int position, int vertexIndex, int face, int ao, Voxel voxel )
=> new VoxelVertex( (byte)position.x, (byte)position.y, (byte)position.z, (byte)vertexIndex, (byte)face, (byte)ao, voxel );
public override bool IsValidVoxel( Voxel voxel ) => voxel.Valid;
public override bool IsOpaqueVoxel( Voxel voxel )
{
if ( Atlas == null ) return false;
if ( Atlas.TryGet( voxel.Texture, out var item ) )
return item.Opaque;
return false;
}
#endregion
public override void SetAttributes( RenderAttributes attributes )
{
base.SetAttributes( attributes );
// Set some render attributes.
if ( Atlas is null )
{
Logger.Warning( $"Atlas is null, please assign an AtlasResource to {GameObject}!" );
return;
}
attributes.Set( "VoxelScale", VoxelScale );
attributes.Set( "VoxelAtlas", Atlas?.Texture );
attributes.Set( "TransformMatrix", TransformMatrix );
}
/// <summary>
/// Call this to update all attributes and transforms on ChunkObjects.
/// </summary>
protected void UpdateObjects()
{
foreach ( var (_, obj) in Objects )
{
var sceneObject = obj.SceneObject;
if ( sceneObject.IsValid() )
SetAttributes( sceneObject.Attributes );
var body = obj.Body;
if ( body.IsValid() )
body.Transform = WorldTransform;
}
}
protected override void OnStart()
{
base.OnStart();
Atlas?.Build();
}
protected override void OnEnabled()
{
base.OnEnabled();
GameObject.Transform.OnTransformChanged += UpdateObjects;
}
protected override void OnDisabled()
{
base.OnDisabled();
GameObject.Transform.OnTransformChanged -= UpdateObjects;
}
}