Terrain physics uses surface drag model

This commit is contained in:
Rob Kelly 2025-01-07 15:50:59 -07:00
parent 2f4801dbaa
commit 9bef191bda
6 changed files with 50 additions and 69 deletions

View File

@ -1,6 +1,6 @@
extends GameBall
const INFO_FMT := "speed: {0} m/s\nlin.damp: {1}\nang.spd: {2}\nang.damp: {3}\ntime: {4} s\nsurface decay: {5}"
const INFO_FMT := "speed: {0} m/s\nang.spd: {1}\nsurface: {2}\ntime: {3} s"
@onready var debug_info: Label3D = %DebugInfo
@ -11,10 +11,8 @@ func _physics_process(delta: float) -> void:
debug_info.text = INFO_FMT.format(
[
linear_velocity.length(),
linear_damp,
angular_velocity.length(),
angular_damp,
_shot_time_s,
terrain_physics.get_decay_factor(_surface_time_s)
Terrain.Type.keys()[_surface_terrain],
_shot_time_s
]
)

View File

@ -19,6 +19,7 @@ size = Vector2(0.05, 0.05)
[sub_resource type="SystemFont" id="SystemFont_td87w"]
font_names = PackedStringArray("Monospace")
subpixel_positioning = 0
[node name="DebugBall" instance=ExtResource("1_gcsxs")]
script = ExtResource("2_edye5")

View File

@ -14,18 +14,12 @@ enum Type {
POWER,
}
const TERRAIN_DAMPING_EPSILON := 1e-6
const MAGNUS_EPSILON := 1e-3
const VELOCITY_SQ_EPSILON := 1e-4
const MAGNUS_SQ_EPSILON := 1e-3
## If enabled, ball ability cooldown is only reset at end of shot.
@export var once_per_shot_ability := false
## Linear damping while in the air.
@export var aerial_linear_damping := 0.0
## Angular damping while in the air.
@export var aerial_angular_damping := 0.0
## Material physics configuration for this ball.
@export var terrain_physics: TerrainPhysics
@ -64,6 +58,7 @@ var _ability_triggered := false
var _zones: Array[BallZone] = []
var _shot_time_s := 0.0
var _surface_time_s := 0.0
var _surface_terrain: Terrain.Type
@onready var ability_cooldown: Timer = %AbilityCooldown
@onready var manual_sleep_timer: Timer = %ManualSleepTimer
@ -74,9 +69,6 @@ var _surface_time_s := 0.0
"res://src/equipment/balls/physics_ball/normal_physics.tres"
)
@onready var default_surface_linear_damping := linear_damp
@onready var default_surface_angular_damping := angular_damp
## Should this ball stick to surfaces, rather than bounce?
func is_sticky() -> bool:
@ -131,43 +123,45 @@ func _integrate_forces(state: PhysicsDirectBodyState3D) -> void:
# We want the contact normal which minimizes the angle to the up vector
var min_dot := -1.0
var primary_body: Node
for i: int in range(state.get_contact_count()):
var norm := state.get_contact_local_normal(i)
var dot := norm.dot(Vector3.UP)
if dot > min_dot:
min_dot = dot
_last_contact_normal = norm
primary_body = state.get_contact_collider_object(i)
# Use first contact to determine terrain properties
var primary_body: Node = state.get_contact_collider_object(0)
var terrain := Terrain.from_collision(global_position, primary_body)
var params := terrain_physics.get_params(terrain)
if params:
linear_damp = params.linear_damping
angular_damp = params.angular_damping
else:
linear_damp = default_surface_linear_damping
angular_damp = default_surface_angular_damping
var decay := 1.0 + terrain_physics.get_decay_factor(_surface_time_s)
#linear_damp *= decay
#angular_damp *= decay
_surface_terrain = Terrain.from_collision(global_position, primary_body)
_surface_time_s += state.step
else:
# Ball is in the air
linear_damp = aerial_linear_damping
angular_damp = aerial_angular_damping
_surface_terrain = Terrain.Type.NONE
_surface_time_s = 0.0
func _physics_process(delta: float) -> void:
# Simulate magnus effect
var magnus := _magnus_force()
if magnus.length_squared() > MAGNUS_EPSILON:
if magnus.length_squared() > MAGNUS_SQ_EPSILON:
apply_central_force(magnus)
# Apply drag
var params := terrain_physics.get_params(_surface_terrain)
if linear_velocity.length() > params.linear_drag:
linear_velocity -= params.linear_drag * linear_velocity.normalized()
else:
linear_velocity = Vector3.ZERO
if angular_velocity.length() > params.angular_drag:
angular_velocity -= params.angular_drag * angular_velocity.normalized()
else:
angular_velocity = Vector3.ZERO
if linear_velocity.length_squared() < VELOCITY_SQ_EPSILON:
linear_velocity = Vector3.ZERO
if angular_velocity.length_squared() < VELOCITY_SQ_EPSILON:
angular_velocity = Vector3.ZERO
# Keep shot time
_shot_time_s += delta

View File

@ -19,58 +19,56 @@
[sub_resource type="Resource" id="Resource_casfi"]
script = ExtResource("4_onl6o")
linear_damping = 0.0
angular_damping = 0.5
linear_drag = 0.0
angular_drag = 1.0
[sub_resource type="Resource" id="Resource_3k63c"]
script = ExtResource("4_onl6o")
linear_damping = 0.0
angular_damping = 8.0
linear_drag = 0.0
angular_drag = 0.0
[sub_resource type="Resource" id="Resource_xf73q"]
script = ExtResource("4_onl6o")
linear_damping = 0.0
angular_damping = 2.0
linear_drag = 0.0
angular_drag = 1.0
[sub_resource type="Resource" id="Resource_nhn3l"]
script = ExtResource("4_onl6o")
linear_damping = 0.0
angular_damping = 0.1
linear_drag = 0.0
angular_drag = 1.0
[sub_resource type="Resource" id="Resource_m3wjo"]
script = ExtResource("4_onl6o")
linear_damping = 0.0
angular_damping = 1.0
linear_drag = 0.0
angular_drag = 1.0
[sub_resource type="Resource" id="Resource_h4rld"]
script = ExtResource("4_onl6o")
linear_damping = 0.0
angular_damping = 0.1
linear_drag = 0.0
angular_drag = 1.0
[sub_resource type="Resource" id="Resource_j6lib"]
script = ExtResource("4_onl6o")
linear_damping = 0.0
angular_damping = 2.0
linear_drag = 0.0
angular_drag = 1.0
[sub_resource type="Resource" id="Resource_7f7ql"]
script = ExtResource("4_onl6o")
linear_damping = 0.0
angular_damping = 8.0
linear_drag = 0.0
angular_drag = 3.0
[sub_resource type="Resource" id="Resource_pusmf"]
script = ExtResource("4_onl6o")
linear_damping = 1.0
angular_damping = 24.0
linear_drag = 1.0
angular_drag = 10.0
[sub_resource type="Resource" id="Resource_edkxb"]
script = ExtResource("4_onl6o")
linear_damping = 0.0
angular_damping = 1.0
linear_drag = 0.0
angular_drag = 1.0
[sub_resource type="Resource" id="Resource_3ngau"]
script = ExtResource("3_52hui")
damping_decay_curve = 12.0
damping_decay_scale = 8.0
default = SubResource("Resource_3k63c")
rough = SubResource("Resource_7f7ql")
fairway = SubResource("Resource_xf73q")

View File

@ -1,5 +1,5 @@
class_name TerrainParameters extends Resource
## Physical parameters for an individual terrain type.
@export var linear_damping := 0.0
@export var angular_damping := 0.0
@export var linear_drag := 0.0
@export var angular_drag := 0.0

View File

@ -1,9 +1,6 @@
class_name TerrainPhysics extends Resource
## Container for ball behavior parameters when in contact with different terrain types
@export_exp_easing() var damping_decay_curve := 1.0
@export var damping_decay_scale := 8.0
@export var default: TerrainParameters
@export var rough: TerrainParameters
@ -41,10 +38,3 @@ func get_params(type: Terrain.Type) -> TerrainParameters:
return glass
_:
return default
func get_decay_factor(time: float) -> float:
var x := time / damping_decay_scale
if damping_decay_curve < 1.0:
return 1.0 - pow(1.0 - x, 1.0 / damping_decay_curve)
return pow(x, damping_decay_curve)