extends Node3D class_name BuyancyProbe ## How much force is applied upward @export var float_strenght: float = 10.0 @export_category("Debug") @export var show_probe :bool = false var sphere_preview:MeshInstance3D @onready var debug_sphere:SphereMesh = SphereMesh.new() @export_category("Wave") # Wave parameters (should match the shader). # For a single wave, we used these parameters. @export var wave_amplitude: float = 1.0 @export var wave_length: float = 10.0 @export var wave_speed: float = 1.0 @export var wave_direction: Vector2 = Vector2(1.0, 0.0) @export var wave:Vector4 @onready var ocean_mat: ShaderMaterial = preload("uid://wes0mbjy8mno").surface_get_material(0) @onready var gravity: float = ProjectSettings.get_setting("physics/3d/default_gravity") @onready var OceanNode:Ocean = get_tree().get_first_node_in_group("Ocean") # For multiple waves, define an array of waves. @export var waves: Array[Vector4] = [ Vector4(1.0, 0.0, 0.5, 10.0), Vector4(0.0, 1.0, 0.25, 20.0), Vector4(1.0, 1.0, 0.15, 10.0) ] # Called when the node enters the scene tree for the first time. func _ready() -> void: if ocean_mat != null: wave = ocean_mat.get_shader_parameter("wave") wave_speed = ocean_mat.get_shader_parameter("wave_speed") if show_probe: sphere_preview = MeshInstance3D.new() sphere_preview.set_name("Sphere") add_child(sphere_preview) debug_sphere.radius = 0.1 debug_sphere.height = 0.2 sphere_preview.mesh = debug_sphere var Oceantime:float # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta: float) -> void: if OceanNode != null: Oceantime = OceanNode.time if show_probe && sphere_preview != null: sphere_preview.global_position.y = get_gerstner_wave(global_position,wave,Oceantime).y #print(get_gerstner_wave(global_position,wave,Oceantime).y) # Calculate the wave height using a sine function. func get_wave_height(position: Vector3, time: float) -> float: var frequency = (2.0 * PI) / wave_length var phase = frequency * (wave_direction.dot(Vector2(position.x, position.z))) + time * wave_speed return wave_amplitude * sin(phase) # Approximate the wave's normal based on the derivative of the wave function. func get_wave_normal(position: Vector3, time: float) -> Vector3: var frequency = (2.0 * PI) / wave_length var phase = frequency * (wave_direction.dot(Vector2(global_position.x, global_position.z))) + time * wave_speed var dHeight_dx = wave_amplitude * cos(phase) * frequency * wave_direction.x var dHeight_dz = wave_amplitude * cos(phase) * frequency * wave_direction.y var normal = Vector3(-dHeight_dx, 1.0, -dHeight_dz).normalized() return normal func get_gerstner_wave(p: Vector3, wave: Vector4, time: float) -> Vector3: var steepness = wave.z var wavelength = wave.w var k = 2 * PI / wavelength var c = sqrt(gravity / k) # Wave speed factor (gravity-based) var d = Vector2(wave.x, wave.y).normalized() var f = k * ( d.dot(Vector2(p.x, p.z)) - c * time * wave_speed ) var a = steepness / k # Return the displacement vector. return Vector3( d.x * (a * cos(f)), a * sin(f), d.y * (a * cos(f)) )