fix river water direction2

This commit is contained in:
2026-05-10 18:44:43 +02:00
parent bcf854fd74
commit 8ceb6cb16b
2 changed files with 151 additions and 8 deletions

View File

@@ -8,6 +8,19 @@ const CHUNK_GENERATION_STEPS_PER_FRAME: int = 2
const CHUNK_CLEANUP_STEPS_PER_FRAME: int = 4
const LAMPPOST_WIRE_STEPS_PER_FRAME: int = 1
const RAILWAY_SCENE_DIRECTORY: String = "res://tgcc/chunk/railway/scene"
const RIVER_SIDE_ORDER: Array[String] = ["north", "est", "south", "west"]
const RIVER_DIRECTIONS: Dictionary = {
"north": Vector2(0.0, -1.0),
"est": Vector2(1.0, 0.0),
"south": Vector2(0.0, 1.0),
"west": Vector2(-1.0, 0.0),
}
const RIVER_NEIGHBOUR_OFFSETS: Dictionary = {
"north": Vector2i(0, -1),
"est": Vector2i(1, 0),
"south": Vector2i(0, 1),
"west": Vector2i(-1, 0),
}
@export_group("Rails")
@export var rail_path: Path3D
@@ -616,11 +629,15 @@ func _add_compatible_biome(grid_pos: Vector2i) -> void:
var have_lamppost = false
if info_new != null and "have_lamppost" in info_new:
have_lamppost = info_new.have_lamppost
var river_flow_direction = _calculate_river_flow_direction(grid_pos, choise.data["river_connections"])
_apply_river_flow_direction(new_chunk, river_flow_direction)
board[grid_pos] = {
"type": "bioma",
"exit": choise.data["connections"],
"river_exit": choise.data["river_connections"],
"river_flow_direction": river_flow_direction,
"heights": choise.data["heights"],
"node": new_chunk,
"info": info_new,
@@ -647,12 +664,109 @@ func _add_compatible_biome(grid_pos: Vector2i) -> void:
"type": "biome",
"exit": {"north":false, "est":false, "south":false, "west":false},
"river_exit": {"north":false, "est":false, "south":false, "west":false},
"river_flow_direction": Vector2.ZERO,
"heights": safe_heights,
"node": backup,
"info": info_backup,
"have_lamppost": false
}
func _calculate_river_flow_direction(grid_pos: Vector2i, river_connections: Dictionary) -> Vector2:
var connected_sides: Array[String] = []
for side in RIVER_SIDE_ORDER:
if river_connections.has(side) and river_connections[side]:
connected_sides.append(side)
if connected_sides.is_empty():
return Vector2.ZERO
var neighbour_flow = _get_connected_neighbour_river_flow(grid_pos, connected_sides)
if not neighbour_flow.is_zero_approx():
var continued_flow = _continue_river_flow_from_neighbour(grid_pos, connected_sides, neighbour_flow)
if not continued_flow.is_zero_approx():
return continued_flow.normalized()
var default_flow = _get_default_river_flow(connected_sides)
if default_flow.is_zero_approx():
return Vector2.ZERO
return default_flow.normalized()
func _get_connected_neighbour_river_flow(grid_pos: Vector2i, connected_sides: Array[String]) -> Vector2:
for side in connected_sides:
var neighbour_pos: Vector2i = grid_pos + RIVER_NEIGHBOUR_OFFSETS[side]
if not board.has(neighbour_pos):
continue
var neighbour = board[neighbour_pos]
if not neighbour.has("river_flow_direction"):
continue
var neighbour_flow: Vector2 = neighbour["river_flow_direction"]
if not neighbour_flow.is_zero_approx():
return neighbour_flow.normalized()
return Vector2.ZERO
func _continue_river_flow_from_neighbour(grid_pos: Vector2i, connected_sides: Array[String], neighbour_flow: Vector2) -> Vector2:
for side in connected_sides:
var neighbour_pos: Vector2i = grid_pos + RIVER_NEIGHBOUR_OFFSETS[side]
if not board.has(neighbour_pos):
continue
var neighbour = board[neighbour_pos]
if not neighbour.has("river_flow_direction"):
continue
var side_direction: Vector2 = RIVER_DIRECTIONS[side]
var neighbour_direction: Vector2 = neighbour["river_flow_direction"]
if neighbour_direction.is_zero_approx():
continue
neighbour_direction = neighbour_direction.normalized()
var other_sides = connected_sides.duplicate()
other_sides.erase(side)
if other_sides.is_empty():
return neighbour_direction
var other_direction = _get_average_river_side_direction(other_sides)
if neighbour_direction.dot(-side_direction) > 0.25:
return other_direction - side_direction
if neighbour_direction.dot(side_direction) > 0.25:
return side_direction - other_direction
var default_flow = _get_default_river_flow(connected_sides)
if default_flow.dot(neighbour_flow) < 0.0:
return -default_flow
return default_flow
func _get_default_river_flow(connected_sides: Array[String]) -> Vector2:
if connected_sides.size() == 1:
return RIVER_DIRECTIONS[connected_sides[0]]
if connected_sides.has("north") and connected_sides.has("south"):
return Vector2(0.0, 1.0)
if connected_sides.has("est") and connected_sides.has("west"):
return Vector2(1.0, 0.0)
var start_direction: Vector2 = RIVER_DIRECTIONS[connected_sides[0]]
var end_direction = _get_average_river_side_direction(connected_sides.slice(1))
return end_direction - start_direction
func _get_average_river_side_direction(sides: Array[String]) -> Vector2:
var direction := Vector2.ZERO
for side in sides:
direction += RIVER_DIRECTIONS[side]
if direction.is_zero_approx():
return Vector2.ZERO
return direction / float(sides.size())
func _apply_river_flow_direction(root: Node, flow_direction: Vector2) -> void:
if flow_direction.is_zero_approx():
return
_set_river_flow_direction_recursive(root, flow_direction.normalized())
func _set_river_flow_direction_recursive(node: Node, flow_direction: Vector2) -> void:
if node is MeshInstance3D and node.name.begins_with("Water_F"):
var mesh_instance := node as MeshInstance3D
mesh_instance.set_instance_shader_parameter("river_flow_direction", flow_direction)
for child in node.get_children():
_set_river_flow_direction_recursive(child, flow_direction)
func _needed_connection(near_pos: Vector2i, side_needed: String) -> int:
if not board.has(near_pos):
_register_cell_with_ray(near_pos)