generated from krampus/template-godot4
Constrained grid generation layer
This commit is contained in:
parent
3352e24771
commit
5272ebdc0a
@ -3,7 +3,29 @@ class_name GenerationFeature extends Node3D
|
||||
##
|
||||
## Layers contain features. Some features may contain layers.
|
||||
|
||||
@export var noise_scale := Vector3.ONE
|
||||
@export var noise_offset := Vector3.ZERO
|
||||
|
||||
@export var sub_layers: Array[GenerationLayer]
|
||||
|
||||
var _generated := false
|
||||
|
||||
|
||||
func probe() -> void:
|
||||
# TODO may want to make low-detail & high-detail probes distinct
|
||||
pass # Implemented in derived type.
|
||||
if not _generated:
|
||||
generate()
|
||||
_generated = true
|
||||
|
||||
for layer in sub_layers:
|
||||
layer.probe()
|
||||
|
||||
|
||||
## Generate elements of this feature. Called by default on the first call to `probe`
|
||||
func generate() -> void:
|
||||
pass # Implemented in derived type
|
||||
|
||||
|
||||
func sample_noise() -> float:
|
||||
var sample_point := global_position * noise_scale + noise_offset
|
||||
return WorldGenManager.noise.get_noise_3dv(sample_point)
|
||||
|
||||
117
src/world/generation/layer/grid_layer/grid_layer.gd
Normal file
117
src/world/generation/layer/grid_layer/grid_layer.gd
Normal file
@ -0,0 +1,117 @@
|
||||
@tool
|
||||
class_name GridLayer extends GenerationLayer
|
||||
## A layer that generates tiles in a locally-constrained grid.
|
||||
|
||||
## Bounding box for the grid on the local XZ plane.
|
||||
##
|
||||
## Note that only feature handles are checked to be within the bounding box.
|
||||
## The Y component of this AABB is not used.
|
||||
@export var bounding_box: AABB:
|
||||
set(value):
|
||||
bounding_box = value
|
||||
if _debug_box:
|
||||
_set_debug_box_shape(bounding_box)
|
||||
|
||||
## Size of a grid tile in the local XZ plane.
|
||||
@export var grid_size: Vector2
|
||||
|
||||
@export_group("Debug Draw")
|
||||
@export var draw_debug := true
|
||||
@export var debug_color := Color("#a486006b"):
|
||||
set(value):
|
||||
debug_color = value
|
||||
if _debug_box:
|
||||
_set_debug_box_color(debug_color)
|
||||
|
||||
var _debug_meshinstance: MeshInstance3D
|
||||
var _debug_box: BoxMesh
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
if Engine.is_editor_hint():
|
||||
_init_debug_draw()
|
||||
|
||||
|
||||
func probe() -> void:
|
||||
var world_pos := WorldGenManager.get_generation_point()
|
||||
probe_radius(world_pos, WorldGenManager.med_detail_radius)
|
||||
# TODO high-detail & low-detail probes
|
||||
|
||||
|
||||
func probe_radius(center: Vector3, radius: float) -> void:
|
||||
var rad_diff := Vector3(radius, 0, radius)
|
||||
|
||||
# Translate probe box limits to grid space
|
||||
var grid_low := world_to_local(center - rad_diff).floor()
|
||||
var grid_high := world_to_local(center + rad_diff).floor()
|
||||
var grid_max := _plane_size().floor()
|
||||
|
||||
# Constrain to bounding box
|
||||
var x_min := maxf(grid_low.x, 0)
|
||||
var x_max := minf(grid_high.x + 1, grid_max.x)
|
||||
var y_min := maxf(grid_low.y, 0)
|
||||
var y_max := minf(grid_high.y + 1, grid_max.y)
|
||||
|
||||
# Probe everything within radius
|
||||
for i in range(x_min, x_max):
|
||||
for j in range(y_min, y_max):
|
||||
probe_grid(Vector2(i, j))
|
||||
|
||||
|
||||
func probe_grid(_grid_pos: Vector2) -> void:
|
||||
pass # Implement in derived type
|
||||
|
||||
|
||||
func _plane_size() -> Vector2:
|
||||
return Vector2(bounding_box.size.x / grid_size.x, bounding_box.size.z / grid_size.y)
|
||||
|
||||
|
||||
func is_bounding_box_valid() -> bool:
|
||||
return bounding_box.size.length_squared() > 0
|
||||
|
||||
|
||||
func is_point_in_bounds(local_pos: Vector2) -> bool:
|
||||
local_pos = local_pos.floor()
|
||||
var grid_max := _plane_size()
|
||||
return (
|
||||
0 <= local_pos.x
|
||||
and local_pos.x < grid_max.x
|
||||
and 0 <= local_pos.y
|
||||
and local_pos.y < grid_max.y
|
||||
)
|
||||
|
||||
|
||||
func local_to_world(local_pos: Vector2) -> Vector3:
|
||||
var v3_pos := Vector3(local_pos.x * grid_size.x, 0, local_pos.y * grid_size.y)
|
||||
return global_transform * (bounding_box.position + v3_pos)
|
||||
|
||||
|
||||
func world_to_local(world_pos: Vector3) -> Vector2:
|
||||
var rel_pos := world_pos * global_transform - bounding_box.position
|
||||
return Vector2(rel_pos.x / grid_size.x, rel_pos.z / grid_size.y)
|
||||
|
||||
|
||||
#region debug draw
|
||||
func _init_debug_draw() -> void:
|
||||
_debug_box = BoxMesh.new()
|
||||
var mat := StandardMaterial3D.new()
|
||||
mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
|
||||
mat.cull_mode = BaseMaterial3D.CULL_DISABLED
|
||||
mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
|
||||
_debug_box.material = mat
|
||||
_debug_meshinstance = MeshInstance3D.new()
|
||||
_debug_meshinstance.mesh = _debug_box
|
||||
add_child(_debug_meshinstance)
|
||||
_set_debug_box_color(debug_color)
|
||||
_set_debug_box_shape(bounding_box)
|
||||
|
||||
|
||||
func _set_debug_box_color(color: Color) -> void:
|
||||
var mat := _debug_box.material as StandardMaterial3D
|
||||
mat.albedo_color = color
|
||||
|
||||
|
||||
func _set_debug_box_shape(aabb: AABB) -> void:
|
||||
_debug_meshinstance.position = aabb.position + aabb.size / 2
|
||||
_debug_box.size = aabb.size
|
||||
#endregion
|
||||
Loading…
x
Reference in New Issue
Block a user