OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-tps / scenes / test / terrain_ab_test.gd

142 lines · gd ref:
@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