@tool
extends Node3D
## A/B Terrain Comparison — toggle between DCTerrain and VoxelLodTerrain
## Press T to toggle terrain systems, V for debug visualization
## Add this node to any scene and configure in inspector
enum TerrainSystem { DC_TERRAIN, VOXEL_LOD }
@export var active_system: TerrainSystem = TerrainSystem.DC_TERRAIN:
set(val):
active_system = val
if is_inside_tree():
_apply_active_system()
@export_group("VoxelLod Settings")
@export var voxel_lod_count: int = 8
@export var voxel_lod_distance: float = 48.0
@export var voxel_view_distance: int = 512
@export var voxel_mesh_block_size: int = 16
var _dc_terrain: Node = null
var _voxel_terrain: Node = null
var _voxel_viewer: Node = null
var _debug_material: ShaderMaterial = null
func _ready() -> void:
if Engine.is_editor_hint():
return
# Find existing DCTerrain in the scene
_dc_terrain = _find_child_of_type("DCTerrain")
if _dc_terrain:
print("[A/B] Found DCTerrain: %s" % _dc_terrain.name)
# Create VoxelLodTerrain as alternative
_setup_voxel_terrain()
# Load LOD debug shader for both systems
var shader = load("res://lod_debug.gdshader")
if shader:
_debug_material = ShaderMaterial.new()
_debug_material.shader = shader
_apply_active_system()
func _setup_voxel_terrain() -> void:
_voxel_terrain = ClassDB.instantiate("VoxelLodTerrain")
if not _voxel_terrain:
push_error("[A/B] VoxelLodTerrain class not found — is godot-voxel addon installed?")
return
_voxel_terrain.name = "VoxelLodTerrain_AB"
_voxel_terrain.set("lod_count", voxel_lod_count)
_voxel_terrain.set("lod_distance", voxel_lod_distance)
_voxel_terrain.set("view_distance", voxel_view_distance)
_voxel_terrain.set("mesh_block_size", voxel_mesh_block_size)
# Create noise generator
var gen = ClassDB.instantiate("VoxelGeneratorNoise")
if gen:
var noise = FastNoiseLite.new()
noise.noise_type = FastNoiseLite.TYPE_SIMPLEX_SMOOTH
noise.frequency = 0.005
noise.fractal_octaves = 5
gen.set("noise", noise)
gen.set("channel", 1) # SDF channel
gen.set("height_start", -100.0)
gen.set("height_range", 200.0)
_voxel_terrain.set("generator", gen)
# Create Transvoxel mesher
var mesher = ClassDB.instantiate("VoxelMesherTransvoxel")
if mesher:
_voxel_terrain.set("mesher", mesher)
_voxel_terrain.visible = false
add_child(_voxel_terrain)
# Create VoxelViewer on the camera
var camera = get_viewport().get_camera_3d()
if camera:
_voxel_viewer = ClassDB.instantiate("VoxelViewer")
if _voxel_viewer:
_voxel_viewer.set("view_distance", voxel_view_distance)
_voxel_viewer.set("requires_visuals", true)
_voxel_viewer.set("requires_collisions", false)
camera.add_child(_voxel_viewer)
print("[A/B] VoxelViewer attached to camera: %s" % camera.name)
print("[A/B] VoxelLodTerrain created (LODs=%d, dist=%.0f)" % [voxel_lod_count, voxel_lod_distance])
func _apply_active_system() -> void:
if Engine.is_editor_hint():
return
match active_system:
TerrainSystem.DC_TERRAIN:
if _dc_terrain: _dc_terrain.visible = true
if _voxel_terrain: _voxel_terrain.visible = false
print("[A/B] Active: DCTerrain")
TerrainSystem.VOXEL_LOD:
if _dc_terrain: _dc_terrain.visible = false
if _voxel_terrain: _voxel_terrain.visible = true
print("[A/B] Active: VoxelLodTerrain")
func _input(event: InputEvent) -> void:
if Engine.is_editor_hint():
return
if event is InputEventKey and event.pressed and not event.echo:
match event.keycode:
KEY_T: # Toggle terrain system
if active_system == TerrainSystem.DC_TERRAIN:
active_system = TerrainSystem.VOXEL_LOD
else:
active_system = TerrainSystem.DC_TERRAIN
KEY_V: # Toggle debug visualization on active terrain
_toggle_debug_vis()
func _toggle_debug_vis() -> void:
match active_system:
TerrainSystem.DC_TERRAIN:
if _dc_terrain and _dc_terrain.has_method("set_debug_lod_colors"):
var current = _dc_terrain.debug_lod_colors
_dc_terrain.debug_lod_colors = !current
print("[A/B] DC debug LOD colors: %s" % (!current))
TerrainSystem.VOXEL_LOD:
if _voxel_terrain:
if _debug_material:
var current_mat = _voxel_terrain.get("material")
if current_mat:
_voxel_terrain.set("material", null)
print("[A/B] Voxel LOD colors: OFF")
else:
_voxel_terrain.set("material", _debug_material)
print("[A/B] Voxel LOD colors: ON")
func _find_child_of_type(type_name: String) -> Node:
for child in get_parent().get_children():
if child.get_class() == type_name:
return child
return null