Restrict generated clam spots to visible sand
This commit is contained in:
parent
4dc87235ec
commit
966968e54d
2 changed files with 74 additions and 1 deletions
|
|
@ -11,6 +11,15 @@ const Gatherables: GatherableCatalog = preload(
|
||||||
"res://gathering/catalog/gatherable_catalog.tres"
|
"res://gathering/catalog/gatherable_catalog.tres"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
class PrimaryTerrainProvider:
|
||||||
|
extends Node3D
|
||||||
|
|
||||||
|
var primary_mesh: MeshInstance3D
|
||||||
|
|
||||||
|
|
||||||
|
func get_primary_terrain_meshes() -> Array[MeshInstance3D]:
|
||||||
|
return [primary_mesh] if primary_mesh != null else []
|
||||||
|
|
||||||
|
|
||||||
func _initialize() -> void:
|
func _initialize() -> void:
|
||||||
call_deferred("_run")
|
call_deferred("_run")
|
||||||
|
|
@ -20,6 +29,7 @@ func _run() -> void:
|
||||||
_validate_catalog_content()
|
_validate_catalog_content()
|
||||||
_validate_flat_shovel()
|
_validate_flat_shovel()
|
||||||
await _validate_beach_authoring()
|
await _validate_beach_authoring()
|
||||||
|
_validate_primary_terrain_provider()
|
||||||
print("Digging prototype validation: PASS")
|
print("Digging prototype validation: PASS")
|
||||||
quit()
|
quit()
|
||||||
|
|
||||||
|
|
@ -81,6 +91,52 @@ func _validate_beach_authoring() -> void:
|
||||||
region.queue_free()
|
region.queue_free()
|
||||||
|
|
||||||
|
|
||||||
|
func _validate_primary_terrain_provider() -> void:
|
||||||
|
var fixture := Node3D.new()
|
||||||
|
fixture.name = "PrimaryTerrainFixture"
|
||||||
|
root.add_child(fixture)
|
||||||
|
var provider := PrimaryTerrainProvider.new()
|
||||||
|
provider.name = "Provider"
|
||||||
|
fixture.add_child(provider)
|
||||||
|
provider.primary_mesh = _flat_sand_triangle(0.0)
|
||||||
|
provider.add_child(provider.primary_mesh)
|
||||||
|
var buried_base := _flat_sand_triangle(10.0)
|
||||||
|
buried_base.name = "BuriedSandBase"
|
||||||
|
provider.add_child(buried_base)
|
||||||
|
var area := DiggableArea3D.new()
|
||||||
|
area.name = "DiggableArea"
|
||||||
|
area.area_id = &"provider_test"
|
||||||
|
area.terrain_source = NodePath("../Provider")
|
||||||
|
area.surface_materials = [&"sand"]
|
||||||
|
area.generation_bounds = Rect2(-20.0, -20.0, 40.0, 40.0)
|
||||||
|
fixture.add_child(area)
|
||||||
|
var triangles := area.get_surface_triangles()
|
||||||
|
assert(triangles.size() == 1)
|
||||||
|
var center := (triangles[0][0] + triangles[0][1] + triangles[0][2]) / 3.0
|
||||||
|
assert(center.x < 2.0)
|
||||||
|
fixture.free()
|
||||||
|
|
||||||
|
|
||||||
|
func _flat_sand_triangle(x_offset: float) -> MeshInstance3D:
|
||||||
|
var arrays: Array = []
|
||||||
|
arrays.resize(Mesh.ARRAY_MAX)
|
||||||
|
arrays[Mesh.ARRAY_VERTEX] = PackedVector3Array([
|
||||||
|
Vector3(x_offset, 0.0, 0.0),
|
||||||
|
Vector3(x_offset, 0.0, 1.0),
|
||||||
|
Vector3(x_offset + 1.0, 0.0, 0.0),
|
||||||
|
])
|
||||||
|
arrays[Mesh.ARRAY_INDEX] = PackedInt32Array([0, 1, 2])
|
||||||
|
var mesh := ArrayMesh.new()
|
||||||
|
mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, arrays)
|
||||||
|
var material := StandardMaterial3D.new()
|
||||||
|
material.resource_name = "sand"
|
||||||
|
mesh.surface_set_material(0, material)
|
||||||
|
var mesh_instance := MeshInstance3D.new()
|
||||||
|
mesh_instance.name = "PrimarySand"
|
||||||
|
mesh_instance.mesh = mesh
|
||||||
|
return mesh_instance
|
||||||
|
|
||||||
|
|
||||||
func _collect_meshes(
|
func _collect_meshes(
|
||||||
root_node: Node,
|
root_node: Node,
|
||||||
result: Array[MeshInstance3D],
|
result: Array[MeshInstance3D],
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ func get_surface_triangles() -> Array[PackedVector3Array]:
|
||||||
var terrain_root: Node = get_node_or_null(terrain_source)
|
var terrain_root: Node = get_node_or_null(terrain_source)
|
||||||
if terrain_root == null:
|
if terrain_root == null:
|
||||||
return triangles
|
return triangles
|
||||||
for mesh_instance: MeshInstance3D in _collect_mesh_instances(terrain_root):
|
for mesh_instance: MeshInstance3D in _terrain_mesh_instances(terrain_root):
|
||||||
var mesh: Mesh = mesh_instance.mesh
|
var mesh: Mesh = mesh_instance.mesh
|
||||||
if mesh == null:
|
if mesh == null:
|
||||||
continue
|
continue
|
||||||
|
|
@ -92,6 +92,23 @@ func _append_triangle(
|
||||||
result.append(PackedVector3Array([a, b, c]))
|
result.append(PackedVector3Array([a, b, c]))
|
||||||
|
|
||||||
|
|
||||||
|
func _terrain_mesh_instances(terrain_root: Node) -> Array[MeshInstance3D]:
|
||||||
|
# Generated terrain can contain authored base layers beneath raised visual
|
||||||
|
# overlays. Those meshes are useful for closing terrain seams, but they are
|
||||||
|
# not necessarily the visible surface and must not produce buried dig spots.
|
||||||
|
# A terrain provider may therefore expose its authoritative primary meshes.
|
||||||
|
if terrain_root.has_method(&"get_primary_terrain_meshes"):
|
||||||
|
var provided: Variant = terrain_root.call(&"get_primary_terrain_meshes")
|
||||||
|
var meshes: Array[MeshInstance3D] = []
|
||||||
|
if provided is Array:
|
||||||
|
for value: Variant in provided:
|
||||||
|
var mesh_instance := value as MeshInstance3D
|
||||||
|
if mesh_instance != null:
|
||||||
|
meshes.append(mesh_instance)
|
||||||
|
return meshes
|
||||||
|
return _collect_mesh_instances(terrain_root)
|
||||||
|
|
||||||
|
|
||||||
func _collect_mesh_instances(root: Node) -> Array[MeshInstance3D]:
|
func _collect_mesh_instances(root: Node) -> Array[MeshInstance3D]:
|
||||||
var meshes: Array[MeshInstance3D] = []
|
var meshes: Array[MeshInstance3D] = []
|
||||||
if root is MeshInstance3D:
|
if root is MeshInstance3D:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue