Improve generated river terrain
This commit is contained in:
parent
8456093f8c
commit
e6f46dcad9
21 changed files with 586 additions and 18 deletions
|
|
@ -247,6 +247,7 @@ func _validate_generated_region(
|
|||
assert(_placement_count(placements, "chunk_0034") == 1)
|
||||
assert(_placement_count(placements, "chunk_0035") == 1)
|
||||
assert(_placement_count(placements, "chunk_0036") == 1)
|
||||
assert(_placement_count(placements, "chunk_0038") == 2)
|
||||
assert(
|
||||
_placement_count(placements, "chunk_0014")
|
||||
== (2 if has_secondary_elevation else 0)
|
||||
|
|
@ -285,10 +286,31 @@ func _validate_generated_region(
|
|||
var river_edge_count := (
|
||||
_placement_count(placements, "chunk_0024")
|
||||
+ _placement_count(placements, "chunk_0025")
|
||||
+ _placement_count(placements, "chunk_0038")
|
||||
)
|
||||
assert(river_coordinate_count >= 12)
|
||||
assert(generator._river_feature_placements.size() == river_coordinate_count)
|
||||
assert(river_edge_count == river_coordinate_count - 8)
|
||||
var stone_bridge_specs: Array[Dictionary] = []
|
||||
for spec: Dictionary in generator._river_feature_placements:
|
||||
if spec.get("id", &"") == &"chunk_0038":
|
||||
stone_bridge_specs.append(spec)
|
||||
assert(stone_bridge_specs.size() == 2)
|
||||
var first_bridge_coordinate := stone_bridge_specs[0].get(
|
||||
"coordinate",
|
||||
Vector2i(-1, -1),
|
||||
) as Vector2i
|
||||
var second_bridge_coordinate := stone_bridge_specs[1].get(
|
||||
"coordinate",
|
||||
Vector2i(-1, -1),
|
||||
) as Vector2i
|
||||
var bridge_delta := second_bridge_coordinate - first_bridge_coordinate
|
||||
assert(absi(bridge_delta.x) + absi(bridge_delta.y) == 1)
|
||||
assert(posmod(
|
||||
int(stone_bridge_specs[1].get("turns", -1))
|
||||
- int(stone_bridge_specs[0].get("turns", -1)),
|
||||
4,
|
||||
) == 2)
|
||||
var river_source_coordinates := generator._river_source_coordinates(
|
||||
generator._river_feature_origin,
|
||||
generator._river_feature_footprint_size,
|
||||
|
|
@ -446,6 +468,20 @@ func _validate_generated_region(
|
|||
assert(fresh.surface_size.x <= 10.0 and fresh.surface_size.y <= 10.0)
|
||||
assert(not fresh.visual_surface_enabled)
|
||||
assert(not (fresh.get_node("VisualWater") as MeshInstance3D).visible)
|
||||
var generated_bed := fresh.get_node_or_null(
|
||||
"GeneratedBed",
|
||||
) as MeshInstance3D
|
||||
assert(generated_bed != null and generated_bed.mesh != null)
|
||||
assert(
|
||||
is_equal_approx(
|
||||
generated_bed.global_position.y,
|
||||
GeneratedWorldRegion.GENERATED_FRESH_WATER_BED_HEIGHT,
|
||||
)
|
||||
)
|
||||
assert(
|
||||
generated_bed.material_override != null
|
||||
and generated_bed.material_override.resource_name == "dirt"
|
||||
)
|
||||
var fresh_recovery := (
|
||||
fresh.get_node("RecoveryRegion") as PlayerWaterTrigger
|
||||
)
|
||||
|
|
@ -486,6 +522,16 @@ func _validate_generated_region(
|
|||
)
|
||||
|
||||
var decorations := region.get_node("Decorations") as Node3D
|
||||
var grass_prop_surface_triangles := region.get_spawn_surface_triangles(
|
||||
[&"grass_lite"],
|
||||
-INF,
|
||||
0.35,
|
||||
)
|
||||
var sand_prop_surface_triangles := region.get_spawn_surface_triangles(
|
||||
[&"sand"],
|
||||
-INF,
|
||||
0.35,
|
||||
)
|
||||
var anchors := region.get_node(
|
||||
"GatherableAnchors/ReachableTreeTrunks"
|
||||
) as GatherableAnchorSet3D
|
||||
|
|
@ -540,6 +586,8 @@ func _validate_generated_region(
|
|||
region,
|
||||
child as Node3D,
|
||||
definition,
|
||||
grass_prop_surface_triangles,
|
||||
sand_prop_surface_triangles,
|
||||
)
|
||||
if prop_id == &"prop_palm":
|
||||
var cluster_id := int(
|
||||
|
|
@ -1063,6 +1111,8 @@ func _validate_decoration_transform(
|
|||
region: GeneratedWorldRegion,
|
||||
prop: Node3D,
|
||||
definition: TerrainPropDefinition,
|
||||
grass_surface_triangles: Array[PackedVector3Array],
|
||||
sand_surface_triangles: Array[PackedVector3Array],
|
||||
) -> void:
|
||||
assert(prop != null)
|
||||
assert(prop.scale.is_equal_approx(Vector3.ONE))
|
||||
|
|
@ -1142,6 +1192,43 @@ func _validate_decoration_transform(
|
|||
],
|
||||
],
|
||||
)
|
||||
var required_surface_triangles: Array[PackedVector3Array] = (
|
||||
sand_surface_triangles
|
||||
if definition.procedural_group == &"sand_tree"
|
||||
else grass_surface_triangles
|
||||
)
|
||||
var required_surface_height := _triangle_surface_height_at(
|
||||
prop.global_position,
|
||||
required_surface_triangles,
|
||||
)
|
||||
assert(
|
||||
required_surface_height > -INF
|
||||
and absf(required_surface_height - prop.global_position.y) <= 0.01,
|
||||
"%s (%s) is not rooted on its required terrain material at %s."
|
||||
% [prop.name, definition.stable_id, prop.global_position],
|
||||
)
|
||||
|
||||
|
||||
func _triangle_surface_height_at(
|
||||
position: Vector3,
|
||||
triangles: Array[PackedVector3Array],
|
||||
) -> float:
|
||||
var highest := -INF
|
||||
var segment_start := position + Vector3.UP * 100.0
|
||||
var segment_end := position + Vector3.DOWN * 100.0
|
||||
for triangle: PackedVector3Array in triangles:
|
||||
if triangle.size() != 3:
|
||||
continue
|
||||
var hit: Variant = Geometry3D.segment_intersects_triangle(
|
||||
segment_start,
|
||||
segment_end,
|
||||
triangle[0],
|
||||
triangle[1],
|
||||
triangle[2],
|
||||
)
|
||||
if hit is Vector3:
|
||||
highest = maxf(highest, (hit as Vector3).y)
|
||||
return highest
|
||||
|
||||
|
||||
func _validate_tree_gatherable_anchors(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue