show snow on grass

This commit is contained in:
2026-07-07 18:00:12 +02:00
parent 6da7021a58
commit 8ff14f3455
5 changed files with 58 additions and 18 deletions

View File

@@ -10,6 +10,7 @@ const TRACK_ZERO_SPACING_TARGET_RATIO: float = 0.97
const TRACK_ZERO_SPACING_MIN_DISTANCE: float = 1.0
enum TrainStartMode { RANDOM_POSITION, SPECIFIED_STATION, SPECIFIED_POSITION }
enum TrainFacingDirection { KEEP_PATH_DIRECTION, LOCOMOTIVE_LEFT, LOCOMOTIVE_RIGHT }
@export_group("Train")
##train speed
@@ -46,6 +47,7 @@ enum TrainStartMode { RANDOM_POSITION, SPECIFIED_STATION, SPECIFIED_POSITION }
@export var train_start_delay_seconds: float = 0.0
@export var train_start_after_delay: bool = true
@export var train_start_acceleration_seconds: float = 4.0
@export_enum("keep_path_direction", "locomotive_left", "locomotive_right") var train_facing_direction: int = TrainFacingDirection.KEEP_PATH_DIRECTION
@export_group("Rails Bulding")
##distance between sleepers of the rails
@@ -103,6 +105,7 @@ var wagon_instances: Array[Node3D] = []
var wagon_progress_offsets: Array[float] = []
var _initial_is_inmotion: bool = true
var _is_photo_mode_active: bool = false
var _train_direction_sign: float = 1.0
func _ready() -> void:
randomize()
@@ -144,8 +147,32 @@ func _apply_initial_train_start() -> void:
train_progress = wrapf(train_start_position, 0.0, total_length)
_update_next_stop_index_from_progress()
_apply_train_facing_direction(total_length)
_update_next_stop_index_from_progress()
_snap_train_to_progress()
func _apply_train_facing_direction(total_length: float) -> void:
_train_direction_sign = 1.0
if train_facing_direction == TrainFacingDirection.KEEP_PATH_DIRECTION or curve == null:
return
if total_length <= 0.0:
return
var center_progress: float = wrapf(train_progress, 0.0, total_length)
var center_position: Vector3 = to_global(curve.sample_baked(center_progress, true))
var forward_progress: float = wrapf(center_progress + 2.0, 0.0, total_length)
var forward_position: Vector3 = to_global(curve.sample_baked(forward_progress, true))
var forward_direction: Vector3 = forward_position - center_position
if forward_direction.length_squared() <= 0.0001 or is_zero_approx(forward_direction.x):
return
var desired_x_sign: float = -1.0 if train_facing_direction == TrainFacingDirection.LOCOMOTIVE_LEFT else 1.0
if forward_direction.x * desired_x_sign < 0.0:
_train_direction_sign = -1.0
if not is_zero_approx(train_speed):
train_speed = absf(train_speed) * _train_direction_sign
func _apply_train_start_delay() -> void:
if not _initial_is_inmotion:
return
@@ -207,13 +234,9 @@ func _snap_train_to_progress() -> void:
train_progress = wrapf(train_progress, 0.0, total_length)
var center_position: Vector3 = to_global(curve.sample_baked(train_progress, true))
var prog_forward: float = wrapf(train_progress + 2.0, 0.0, total_length)
var forward_position: Vector3 = to_global(curve.sample_baked(prog_forward, true))
train_instance.global_position = center_position
if center_position.distance_to(forward_position) > 0.01:
train_instance.look_at(forward_position, Vector3.UP)
train_instance.rotate_y(PI)
_orient_vehicle_to_track(train_instance, train_progress, total_length)
if cameras:
cameras.global_position = center_position
@@ -452,8 +475,7 @@ func train_move(delta: float) -> void:
if center_position.distance_to(forward_position) > 0.01:
train_instance.global_position = center_position
train_instance.look_at(forward_position, Vector3.UP)
train_instance.rotate_y(PI)
_orient_vehicle_to_track(train_instance, train_progress, total_length)
if cameras:
cameras.global_position = center_position
@@ -658,7 +680,7 @@ func _snap_wagons_to_progress(total_length: float = 0.0) -> void:
if i < wagon_progress_offsets.size():
wagon_offset = wagon_progress_offsets[i]
var wagon_progress: float = train_progress - wagon_offset
var wagon_progress: float = train_progress - wagon_offset * _train_direction_sign
var segment_spacing: float = maxf(wagon_offset - previous_wagon_offset, 0.1)
var vehicle_progress: float = wrapf(wagon_progress, 0.0, total_length)
@@ -670,18 +692,27 @@ func _snap_wagons_to_progress(total_length: float = 0.0) -> void:
vehicle_progress = _lerp_progress_on_track(vehicle_progress, corrected_progress, zero_spacing_fix_weight, total_length)
center_position = to_global(curve.sample_baked(vehicle_progress, true))
var prog_forward: float = wrapf(vehicle_progress + 2.0, 0.0, total_length)
var forward_position: Vector3 = to_global(curve.sample_baked(prog_forward, true))
wagon.global_position = center_position
if center_position.distance_to(forward_position) > 0.01:
wagon.look_at(forward_position, Vector3.UP)
wagon.rotate_y(PI)
_orient_vehicle_to_track(wagon, vehicle_progress, total_length)
previous_progress = vehicle_progress
previous_position = center_position
previous_wagon_offset = wagon_offset
func _orient_vehicle_to_track(vehicle: Node3D, progress: float, total_length: float) -> void:
if vehicle == null or curve == null or total_length <= 0.0:
return
var center_progress: float = wrapf(progress, 0.0, total_length)
var center_position: Vector3 = to_global(curve.sample_baked(center_progress, true))
var forward_progress: float = wrapf(center_progress + 2.0 * _train_direction_sign, 0.0, total_length)
var forward_position: Vector3 = to_global(curve.sample_baked(forward_progress, true))
if center_position.distance_to(forward_position) <= 0.01:
return
vehicle.look_at(forward_position, Vector3.UP)
vehicle.rotate_y(PI)
func _get_zero_spacing_fix_weight(previous_progress: float, vehicle_progress: float, total_length: float) -> float:
var distance_to_zero: float = minf(
_get_progress_distance_to_zero(previous_progress, total_length),
@@ -699,13 +730,13 @@ func _get_zero_spacing_target_distance(segment_spacing: float) -> float:
func _find_zero_spacing_progress(previous_progress: float, previous_position: Vector3, segment_spacing: float, minimum_distance: float, total_length: float) -> float:
var start_distance: float = minf(minimum_distance, segment_spacing)
var best_progress: float = wrapf(previous_progress - start_distance, 0.0, total_length)
var best_progress: float = wrapf(previous_progress - start_distance * _train_direction_sign, 0.0, total_length)
var search_limit: float = minf(maxf(segment_spacing, minimum_distance) + TRACK_ZERO_SPACING_SEARCH_EXTRA, total_length)
var search_distance: float = start_distance
var previous_search_distance: float = start_distance
while search_distance <= search_limit:
var candidate_progress: float = wrapf(previous_progress - search_distance, 0.0, total_length)
var candidate_progress: float = wrapf(previous_progress - search_distance * _train_direction_sign, 0.0, total_length)
var candidate_position: Vector3 = to_global(curve.sample_baked(candidate_progress, true))
best_progress = candidate_progress
if previous_position.distance_to(candidate_position) >= minimum_distance: