Fix a bunch of collision bugs
This commit is contained in:
parent
1c3810483a
commit
a4ed430efe
@ -1,19 +1,7 @@
|
|||||||
# Blender 4.4.1
|
# Blender 4.4.1
|
||||||
# www.blender.org
|
# www.blender.org
|
||||||
o Object_5
|
o Object_5
|
||||||
v -0.812577 0.172395 1.254792
|
|
||||||
v -0.646673 -0.190612 1.848713
|
|
||||||
v -0.666983 -0.006338 1.874366
|
|
||||||
v -0.635056 0.256211 1.783894
|
|
||||||
v -0.508939 0.803110 -0.009132
|
|
||||||
v -0.769510 0.352081 -1.291787
|
|
||||||
v -0.761933 0.013607 -1.722252
|
|
||||||
v 0.677186 -0.189706 1.840916
|
v 0.677186 -0.189706 1.840916
|
||||||
v -0.590011 0.087673 1.933771
|
|
||||||
v -0.669674 -0.180060 -1.336290
|
|
||||||
v -0.512564 0.833925 -0.989792
|
|
||||||
v -0.627160 0.507336 -2.050498
|
|
||||||
v -0.682347 0.022719 -2.244187
|
|
||||||
v 0.678533 0.090349 1.926879
|
v 0.678533 0.090349 1.926879
|
||||||
v 0.700321 -0.179143 -1.337300
|
v 0.700321 -0.179143 -1.337300
|
||||||
v 0.792520 0.013658 -1.722244
|
v 0.792520 0.013658 -1.722244
|
||||||
@ -24,32 +12,41 @@ v 0.543159 0.833925 -0.989791
|
|||||||
v 0.657754 0.507336 -2.050497
|
v 0.657754 0.507336 -2.050497
|
||||||
v 0.712870 0.023363 -2.243935
|
v 0.712870 0.023363 -2.243935
|
||||||
v 0.800105 0.352079 -1.291788
|
v 0.800105 0.352079 -1.291788
|
||||||
|
v -0.646592 -0.189706 1.840916
|
||||||
|
v -0.647939 0.090349 1.926879
|
||||||
|
v -0.669726 -0.179143 -1.337300
|
||||||
|
v -0.761926 0.013658 -1.722244
|
||||||
|
v -0.812613 0.172325 1.254793
|
||||||
|
v -0.635077 0.258142 1.777555
|
||||||
|
v -0.508940 0.803109 -0.009139
|
||||||
|
v -0.512565 0.833925 -0.989791
|
||||||
|
v -0.627160 0.507336 -2.050497
|
||||||
|
v -0.682276 0.023363 -2.243935
|
||||||
|
v -0.769511 0.352079 -1.291788
|
||||||
s 0
|
s 0
|
||||||
f 1 2 3
|
f 11 8 7 5
|
||||||
f 1 3 4
|
f 4 5 1 3
|
||||||
f 1 4 5
|
f 12 1 2 13
|
||||||
f 23 20 19 17
|
f 9 11 4 10
|
||||||
f 1 6 7
|
f 1 5 2
|
||||||
f 16 17 8 15
|
f 9 20 19 8
|
||||||
f 2 9 3
|
f 2 5 6
|
||||||
f 3 9 4
|
f 3 10 4
|
||||||
f 9 14 18 4
|
f 4 11 5
|
||||||
f 6 11 12
|
f 5 7 6
|
||||||
f 21 23 16 22
|
f 8 11 9
|
||||||
f 7 13 10
|
f 14 21 10 3
|
||||||
f 8 17 14
|
f 19 18 7 8
|
||||||
f 8 14 9 2
|
f 7 18 17 6
|
||||||
f 12 21 22 13
|
f 6 17 13 2
|
||||||
f 20 11 5 19
|
f 12 14 3 1
|
||||||
f 15 10 13 22
|
f 22 16 18 19
|
||||||
f 14 17 18
|
f 15 14 12 16
|
||||||
f 15 22 16
|
f 20 21 15 22
|
||||||
f 16 23 17
|
f 12 13 16
|
||||||
f 7 10 2 1
|
f 13 17 16
|
||||||
f 17 19 18
|
f 14 15 21
|
||||||
f 20 23 21
|
f 15 16 22
|
||||||
f 5 11 6 1
|
f 16 17 18
|
||||||
f 5 4 18 19
|
f 19 20 22
|
||||||
f 13 7 6 12
|
f 10 21 20 9
|
||||||
f 12 11 20 21
|
|
||||||
f 8 2 10 15
|
|
||||||
|
@ -16,6 +16,7 @@ out vec4 finalColor;
|
|||||||
|
|
||||||
uniform vec3 ambient;
|
uniform vec3 ambient;
|
||||||
uniform vec3 lightDir;
|
uniform vec3 lightDir;
|
||||||
|
uniform vec3 lightColor;
|
||||||
|
|
||||||
|
|
||||||
// NOTE: Add your custom variables here
|
// NOTE: Add your custom variables here
|
||||||
@ -30,8 +31,8 @@ void main()
|
|||||||
// times the fragment color (interpolated vertex color)
|
// times the fragment color (interpolated vertex color)
|
||||||
|
|
||||||
float NDotL = dot(lightDir, -worldNormal);
|
float NDotL = dot(lightDir, -worldNormal);
|
||||||
float toon = 0.5 * smoothstep(0.66, 0.67, NDotL) + 0.5;
|
float toon = 0.5 * smoothstep(0.5, 0.51, NDotL) + 0.5;
|
||||||
vec3 light = mix(vec3(0), vec3(1), toon);
|
vec3 light = mix(vec3(ambient), lightColor, toon);
|
||||||
|
|
||||||
finalColor = texelColor*colDiffuse*fragColor * vec4(light, 1);
|
finalColor = texelColor*colDiffuse*fragColor * vec4(light, 1);
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ esac
|
|||||||
|
|
||||||
# Build the game.
|
# Build the game.
|
||||||
echo "Building game$DLL_EXT"
|
echo "Building game$DLL_EXT"
|
||||||
odin build game -extra-linker-flags:"$EXTRA_LINKER_FLAGS" -define:RAYLIB_SHARED=true -define:PHYSFS_SHARED=true -define:TRACY_ENABLE=true -collection:libs=./libs -collection:common=./common -collection:game=./game -build-mode:dll -out:game_tmp$DLL_EXT -strict-style -vet -debug -o:speed
|
odin build game -extra-linker-flags:"$EXTRA_LINKER_FLAGS" -define:RAYLIB_SHARED=true -define:PHYSFS_SHARED=true -define:TRACY_ENABLE=true -collection:libs=./libs -collection:common=./common -collection:game=./game -build-mode:dll -out:game_tmp$DLL_EXT -strict-style -vet -debug
|
||||||
|
|
||||||
# Need to use a temp file on Linux because it first writes an empty `game.so`, which the game will load before it is actually fully written.
|
# Need to use a temp file on Linux because it first writes an empty `game.so`, which the game will load before it is actually fully written.
|
||||||
mv game_tmp$DLL_EXT game$DLL_EXT
|
mv game_tmp$DLL_EXT game$DLL_EXT
|
||||||
|
@ -78,13 +78,15 @@ Asset_Cache :: struct($E: typeid) {
|
|||||||
Shader_Location :: enum {
|
Shader_Location :: enum {
|
||||||
Ambient,
|
Ambient,
|
||||||
LightDir,
|
LightDir,
|
||||||
|
LightColor,
|
||||||
}
|
}
|
||||||
Shader_Location_Set :: bit_set[Shader_Location]
|
Shader_Location_Set :: bit_set[Shader_Location]
|
||||||
Shader_Location_Array :: [Shader_Location]i32
|
Shader_Location_Array :: [Shader_Location]i32
|
||||||
|
|
||||||
SHADER_LOCATION_NAMES := [Shader_Location]cstring {
|
SHADER_LOCATION_NAMES := [Shader_Location]cstring {
|
||||||
.Ambient = "ambient",
|
.Ambient = "ambient",
|
||||||
.LightDir = "lightDir",
|
.LightDir = "lightDir",
|
||||||
|
.LightColor = "lightColor",
|
||||||
}
|
}
|
||||||
|
|
||||||
Loaded_Shader :: struct {
|
Loaded_Shader :: struct {
|
||||||
|
@ -78,7 +78,7 @@ Car :: struct {
|
|||||||
SOLVER_CONFIG :: physics.Solver_Config {
|
SOLVER_CONFIG :: physics.Solver_Config {
|
||||||
timestep = 1.0 / 60,
|
timestep = 1.0 / 60,
|
||||||
gravity = rl.Vector3{0, -9.8, 0},
|
gravity = rl.Vector3{0, -9.8, 0},
|
||||||
substreps_minus_one = 8 - 1,
|
substreps_minus_one = 4 - 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
Game_Memory :: struct {
|
Game_Memory :: struct {
|
||||||
@ -433,11 +433,11 @@ update_runtime_world :: proc(runtime_world: ^Runtime_World, dt: f32) {
|
|||||||
&g_mem.assetman,
|
&g_mem.assetman,
|
||||||
"assets/ae86_rpm_torque.csv",
|
"assets/ae86_rpm_torque.csv",
|
||||||
),
|
),
|
||||||
lowest_rpm = 1100,
|
lowest_rpm = 1200,
|
||||||
rev_limit_rpm = 7800,
|
rev_limit_rpm = 7800,
|
||||||
rev_limit_interval = 0.025,
|
rev_limit_interval = 0.025,
|
||||||
inertia = 0.264 * 0.5,
|
inertia = 0.264 * 0.5,
|
||||||
internal_friction = 0.01,
|
internal_friction = 0.005,
|
||||||
gear_ratios = []f32{3.48, 3.587, 2.022, 1.384, 1, 0.861},
|
gear_ratios = []f32{3.48, 3.587, 2.022, 1.384, 1, 0.861},
|
||||||
axle = physics.Drive_Axle_Config {
|
axle = physics.Drive_Axle_Config {
|
||||||
wheels = {wheel_rl, wheel_rr},
|
wheels = {wheel_rl, wheel_rr},
|
||||||
@ -733,6 +733,7 @@ draw :: proc() {
|
|||||||
|
|
||||||
car_body := physics.get_body(sim_state, runtime_world.car_handle)
|
car_body := physics.get_body(sim_state, runtime_world.car_handle)
|
||||||
car_model := assets.get_model(&g_mem.assetman, "assets/toyota_corolla_ae86_trueno.glb")
|
car_model := assets.get_model(&g_mem.assetman, "assets/toyota_corolla_ae86_trueno.glb")
|
||||||
|
_ = car_model
|
||||||
|
|
||||||
mesh_col: bvh.Collision
|
mesh_col: bvh.Collision
|
||||||
hit_mesh_idx := -1
|
hit_mesh_idx := -1
|
||||||
@ -803,10 +804,11 @@ draw :: proc() {
|
|||||||
&g_mem.assetman,
|
&g_mem.assetman,
|
||||||
"assets/shaders/lit_vs.glsl",
|
"assets/shaders/lit_vs.glsl",
|
||||||
"assets/shaders/lit_ps.glsl",
|
"assets/shaders/lit_ps.glsl",
|
||||||
{.Ambient, .LightDir},
|
{.Ambient, .LightDir, .LightColor},
|
||||||
)
|
)
|
||||||
light_dir := linalg.normalize(rl.Vector3{1, -1, 0})
|
light_dir := linalg.normalize(rl.Vector3{1, -1, 0})
|
||||||
ambient := linalg.normalize(rl.Vector3{0.1, 0.1, 0.1})
|
ambient := rl.Vector3{0.1, 0.1, 0.1}
|
||||||
|
light_color := rl.Vector3{0.816, 0.855, 0.89}
|
||||||
rl.SetShaderValue(
|
rl.SetShaderValue(
|
||||||
basic_shader.shader,
|
basic_shader.shader,
|
||||||
basic_shader.locations[.LightDir],
|
basic_shader.locations[.LightDir],
|
||||||
@ -819,6 +821,12 @@ draw :: proc() {
|
|||||||
&ambient,
|
&ambient,
|
||||||
.VEC3,
|
.VEC3,
|
||||||
)
|
)
|
||||||
|
rl.SetShaderValue(
|
||||||
|
basic_shader.shader,
|
||||||
|
basic_shader.locations[.LightColor],
|
||||||
|
&light_color,
|
||||||
|
.VEC3,
|
||||||
|
)
|
||||||
|
|
||||||
render.draw_model(car_model, basic_shader.shader, car_matrix)
|
render.draw_model(car_model, basic_shader.shader, car_matrix)
|
||||||
|
|
||||||
@ -952,12 +960,13 @@ draw :: proc() {
|
|||||||
gear_ratios := physics.get_gear_ratios(sim_state, engine.gear_ratios)
|
gear_ratios := physics.get_gear_ratios(sim_state, engine.gear_ratios)
|
||||||
rl.DrawText(
|
rl.DrawText(
|
||||||
fmt.ctprintf(
|
fmt.ctprintf(
|
||||||
"p: %v\nv: %v\ngear: %v\nratio: %v\nrpm: %v\nspeed: %v km/h",
|
"p: %v\nv: %v\ngear: %v\nratio: %v\nrpm: %v\nclutch: %v\nspeed: %v km/h",
|
||||||
car.x,
|
car.x,
|
||||||
car.v,
|
car.v,
|
||||||
engine.gear,
|
engine.gear,
|
||||||
physics.lookup_gear_ratio(gear_ratios, engine.gear),
|
physics.lookup_gear_ratio(gear_ratios, engine.gear),
|
||||||
physics.angular_velocity_to_rpm(engine.w),
|
physics.angular_velocity_to_rpm(engine.w),
|
||||||
|
engine.clutch,
|
||||||
linalg.length(car.v) * 3.6,
|
linalg.length(car.v) * 3.6,
|
||||||
),
|
),
|
||||||
5,
|
5,
|
||||||
|
@ -3,13 +3,9 @@ package halfedge
|
|||||||
import rl "libs:raylib"
|
import rl "libs:raylib"
|
||||||
|
|
||||||
debug_draw_mesh_wires :: proc(mesh: Half_Edge_Mesh, color: rl.Color) {
|
debug_draw_mesh_wires :: proc(mesh: Half_Edge_Mesh, color: rl.Color) {
|
||||||
for _, f in mesh.faces {
|
for edge in mesh.edges {
|
||||||
it := iterator_face_edges(mesh, Face_Index(f))
|
a, b := get_edge_points(mesh, edge)
|
||||||
|
|
||||||
for edge in iterate_next_edge(&it) {
|
rl.DrawLine3D(a, b, color)
|
||||||
a, b := get_edge_points(mesh, edge)
|
|
||||||
|
|
||||||
rl.DrawLine3D(a, b, color)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,9 @@ import "core:log"
|
|||||||
import "core:math"
|
import "core:math"
|
||||||
import lg "core:math/linalg"
|
import lg "core:math/linalg"
|
||||||
import "game:halfedge"
|
import "game:halfedge"
|
||||||
import "libs:tracy"
|
|
||||||
import rl "libs:raylib"
|
import rl "libs:raylib"
|
||||||
import "libs:raylib/rlgl"
|
import "libs:raylib/rlgl"
|
||||||
|
import "libs:tracy"
|
||||||
|
|
||||||
_ :: math
|
_ :: math
|
||||||
_ :: rl
|
_ :: rl
|
||||||
@ -84,12 +84,9 @@ convex_vs_convex_sat :: proc(a, b: Convex) -> (manifold: Contact_Manifold, colli
|
|||||||
if edge_separation > 0 {
|
if edge_separation > 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
biased_face_a_separation := face_query_a.separation + 0.3
|
|
||||||
biased_face_b_separation := face_query_b.separation + 0.2
|
|
||||||
biased_edge_separation := edge_separation
|
|
||||||
|
|
||||||
is_face_a_contact := biased_face_a_separation >= biased_edge_separation
|
is_face_a_contact := face_query_a.separation > edge_separation
|
||||||
is_face_b_contact := biased_face_b_separation >= biased_edge_separation
|
is_face_b_contact := face_query_b.separation > edge_separation
|
||||||
|
|
||||||
if is_face_a_contact || is_face_b_contact {
|
if is_face_a_contact || is_face_b_contact {
|
||||||
manifold = create_face_contact_manifold(face_query_a, a, face_query_b, b)
|
manifold = create_face_contact_manifold(face_query_a, a, face_query_b, b)
|
||||||
@ -290,7 +287,7 @@ create_face_contact_manifold :: proc(
|
|||||||
) {
|
) {
|
||||||
tracy.Zone()
|
tracy.Zone()
|
||||||
|
|
||||||
is_ref_a := face_query_a.separation > face_query_b.separation
|
is_ref_a := (face_query_a.separation + 0.1) > face_query_b.separation
|
||||||
ref_face_query := is_ref_a ? face_query_a : face_query_b
|
ref_face_query := is_ref_a ? face_query_a : face_query_b
|
||||||
ref_convex := is_ref_a ? a : b
|
ref_convex := is_ref_a ? a : b
|
||||||
inc_convex := is_ref_a ? b : a
|
inc_convex := is_ref_a ? b : a
|
||||||
@ -303,13 +300,19 @@ create_face_contact_manifold :: proc(
|
|||||||
inc_face_idx: halfedge.Face_Index
|
inc_face_idx: halfedge.Face_Index
|
||||||
// Find the most anti parallel face
|
// Find the most anti parallel face
|
||||||
{
|
{
|
||||||
min_dot := f32(1.0)
|
_, support_idx, _ := find_support_point(inc_convex, -ref_face.normal)
|
||||||
for face, face_idx in inc_convex.faces {
|
|
||||||
|
it := halfedge.iterator_vertex_edges(inc_convex, support_idx)
|
||||||
|
|
||||||
|
min_dot := max(f32)
|
||||||
|
|
||||||
|
for edge in halfedge.iterate_next_vertex_edge(&it) {
|
||||||
|
face := inc_convex.faces[edge.face]
|
||||||
dot := lg.dot(ref_face.normal, face.normal)
|
dot := lg.dot(ref_face.normal, face.normal)
|
||||||
if dot < min_dot {
|
if dot < min_dot {
|
||||||
min_dot = dot
|
min_dot = dot
|
||||||
inc_face = face
|
inc_face = face
|
||||||
inc_face_idx = halfedge.Face_Index(face_idx)
|
inc_face_idx = halfedge.Face_Index(edge.face)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -336,6 +339,7 @@ create_face_contact_manifold :: proc(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
assert(len(inc_polygon) > 0)
|
assert(len(inc_polygon) > 0)
|
||||||
|
|
||||||
// Set up ping pong buffers
|
// Set up ping pong buffers
|
||||||
@ -352,6 +356,14 @@ create_face_contact_manifold :: proc(
|
|||||||
step := 0
|
step := 0
|
||||||
vert_count := original_vert_count
|
vert_count := original_vert_count
|
||||||
|
|
||||||
|
|
||||||
|
// {
|
||||||
|
// polygon := clip_bufs[get_other_clip_buf(clip_buf_idx)]
|
||||||
|
// for i in 2 ..< vert_count {
|
||||||
|
// rl.DrawTriangle3D(polygon[0], polygon[i - 1], polygon[i], rl.RED)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
EPS :: 1e-6
|
EPS :: 1e-6
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -5,15 +5,16 @@ import "core:log"
|
|||||||
import "core:math"
|
import "core:math"
|
||||||
import lg "core:math/linalg"
|
import lg "core:math/linalg"
|
||||||
import "game:debug"
|
import "game:debug"
|
||||||
import "game:halfedge"
|
import he "game:halfedge"
|
||||||
import "game:ui"
|
import "game:ui"
|
||||||
import "libs:tracy"
|
|
||||||
import rl "libs:raylib"
|
import rl "libs:raylib"
|
||||||
import "libs:raylib/rlgl"
|
import "libs:raylib/rlgl"
|
||||||
|
import "libs:tracy"
|
||||||
|
|
||||||
_ :: log
|
_ :: log
|
||||||
_ :: math
|
_ :: math
|
||||||
_ :: debug
|
_ :: debug
|
||||||
|
_ :: he
|
||||||
|
|
||||||
draw_debug_shape :: proc(
|
draw_debug_shape :: proc(
|
||||||
sim_state: ^Sim_State,
|
sim_state: ^Sim_State,
|
||||||
@ -35,7 +36,7 @@ draw_debug_shape :: proc(
|
|||||||
rl.DrawCubeV(0, s.size, color)
|
rl.DrawCubeV(0, s.size, color)
|
||||||
case Internal_Shape_Convex:
|
case Internal_Shape_Convex:
|
||||||
mesh := convex_container_get_mesh(&sim_state.convex_container, s.mesh)
|
mesh := convex_container_get_mesh(&sim_state.convex_container, s.mesh)
|
||||||
halfedge.debug_draw_mesh_wires(mesh, color)
|
he.debug_draw_mesh_wires(mesh, color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,6 +317,6 @@ debug_draw_manifold_points :: proc(
|
|||||||
contact.total_friction_impulse[point_idx].y * contact.manifold.bitangent
|
contact.total_friction_impulse[point_idx].y * contact.manifold.bitangent
|
||||||
rl.DrawLine3D(p, p + total_impulse * impulse_sign, color)
|
rl.DrawLine3D(p, p + total_impulse * impulse_sign, color)
|
||||||
|
|
||||||
// rl.DrawSphereWires(p, 0.1, 4, 4, color)
|
rl.DrawSphereWires(p, 0.1, 4, 4, color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,7 +119,7 @@ body_get_convex_shape_world :: proc(
|
|||||||
}
|
}
|
||||||
|
|
||||||
transform :=
|
transform :=
|
||||||
lg.matrix4_translate(body_get_shape_pos(body)) * lg.matrix4_from_quaternion(body.q)
|
lg.matrix4_translate_f32(body_get_shape_pos(body)) * lg.matrix4_from_quaternion_f32(body.q)
|
||||||
halfedge.transform_mesh(&mesh, transform)
|
halfedge.transform_mesh(&mesh, transform)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -254,6 +254,7 @@ Engine :: struct {
|
|||||||
|
|
||||||
// Controls
|
// Controls
|
||||||
throttle: f32,
|
throttle: f32,
|
||||||
|
clutch: f32,
|
||||||
|
|
||||||
// Free list
|
// Free list
|
||||||
next_plus_one: i32,
|
next_plus_one: i32,
|
||||||
|
@ -11,6 +11,9 @@ import lg "core:math/linalg"
|
|||||||
import "core:math/rand"
|
import "core:math/rand"
|
||||||
import "core:slice"
|
import "core:slice"
|
||||||
import "game:container/spanpool"
|
import "game:container/spanpool"
|
||||||
|
import "game:debug"
|
||||||
|
import he "game:halfedge"
|
||||||
|
import rl "libs:raylib"
|
||||||
import "libs:tracy"
|
import "libs:tracy"
|
||||||
|
|
||||||
_ :: log
|
_ :: log
|
||||||
@ -18,6 +21,8 @@ _ :: rand
|
|||||||
_ :: math
|
_ :: math
|
||||||
_ :: fmt
|
_ :: fmt
|
||||||
_ :: slice
|
_ :: slice
|
||||||
|
_ :: he
|
||||||
|
_ :: debug
|
||||||
|
|
||||||
Solver_Config :: struct {
|
Solver_Config :: struct {
|
||||||
// Will automatically do fixed timestep
|
// Will automatically do fixed timestep
|
||||||
@ -198,7 +203,7 @@ find_new_contacts :: proc(sim_state: ^Sim_State, tlas: ^TLAS) {
|
|||||||
|
|
||||||
pair := make_contact_pair(i32(body_idx), i32(other_body_idx))
|
pair := make_contact_pair(i32(body_idx), i32(other_body_idx))
|
||||||
if body_idx != other_body_idx &&
|
if body_idx != other_body_idx &&
|
||||||
bvh.test_aabb_vs_aabb(body_aabb, prim_aabb) &&
|
(true || bvh.test_aabb_vs_aabb(body_aabb, prim_aabb)) &&
|
||||||
!(pair in sim_state.contact_container.lookup) {
|
!(pair in sim_state.contact_container.lookup) {
|
||||||
|
|
||||||
new_contact_idx := len(sim_state.contact_container.contacts)
|
new_contact_idx := len(sim_state.contact_container.contacts)
|
||||||
@ -341,6 +346,11 @@ update_contacts :: proc(sim_state: ^Sim_State) {
|
|||||||
body_get_convex_shape_world(sim_state, body),
|
body_get_convex_shape_world(sim_state, body),
|
||||||
body_get_convex_shape_world(sim_state, body2)
|
body_get_convex_shape_world(sim_state, body2)
|
||||||
|
|
||||||
|
if contact_idx == 2 {
|
||||||
|
he.debug_draw_mesh_wires(m1, rl.RED)
|
||||||
|
he.debug_draw_mesh_wires(m2, rl.BLUE)
|
||||||
|
}
|
||||||
|
|
||||||
// Raw manifold has contact points in world space
|
// Raw manifold has contact points in world space
|
||||||
raw_manifold, collision := collision.convex_vs_convex_sat(m1, m2)
|
raw_manifold, collision := collision.convex_vs_convex_sat(m1, m2)
|
||||||
|
|
||||||
@ -440,24 +450,24 @@ pgs_solve_contacts :: proc(
|
|||||||
body_local_to_world(body2, manifold.points_b[point_idx])
|
body_local_to_world(body2, manifold.points_b[point_idx])
|
||||||
|
|
||||||
p_diff_normal := lg.dot(p2 - p1, manifold.normal)
|
p_diff_normal := lg.dot(p2 - p1, manifold.normal)
|
||||||
separation := min(p_diff_normal, 0)
|
separation := p_diff_normal
|
||||||
|
|
||||||
if separation < 0 {
|
w1 := get_body_inverse_mass(body1, manifold.normal, p1)
|
||||||
|
w2 := get_body_inverse_mass(body2, manifold.normal, p2)
|
||||||
|
|
||||||
|
w := w1 + w2
|
||||||
|
|
||||||
|
if w == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
inv_w := 1.0 / w
|
||||||
|
|
||||||
|
{
|
||||||
// r1, r2 := p1 - body1.x, p2 - body2.x
|
// r1, r2 := p1 - body1.x, p2 - body2.x
|
||||||
v1 := body_velocity_at_point(body1, p1)
|
v1 := body_velocity_at_point(body1, p1)
|
||||||
v2 := body_velocity_at_point(body2, p2)
|
v2 := body_velocity_at_point(body2, p2)
|
||||||
|
|
||||||
w1 := get_body_inverse_mass(body1, manifold.normal, p1)
|
|
||||||
w2 := get_body_inverse_mass(body2, manifold.normal, p2)
|
|
||||||
|
|
||||||
w := w1 + w2
|
|
||||||
|
|
||||||
if w == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
inv_w := 1.0 / w
|
|
||||||
|
|
||||||
delta_v := v2 - v1
|
delta_v := v2 - v1
|
||||||
{
|
{
|
||||||
delta_v_norm := lg.dot(delta_v, manifold.normal)
|
delta_v_norm := lg.dot(delta_v, manifold.normal)
|
||||||
@ -488,45 +498,51 @@ pgs_solve_contacts :: proc(
|
|||||||
apply_velocity_correction(body1, -applied_impulse_vec, p1)
|
apply_velocity_correction(body1, -applied_impulse_vec, p1)
|
||||||
apply_velocity_correction(body2, applied_impulse_vec, p2)
|
apply_velocity_correction(body2, applied_impulse_vec, p2)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
DYNAMIC_FRICTION :: 0.6
|
// r1, r2 := p1 - body1.x, p2 - body2.x
|
||||||
STATIC_FRICTION :: 0.8
|
v1 := body_velocity_at_point(body1, p1)
|
||||||
STATIC_FRICTION_VELOCITY_THRESHOLD :: 0.01
|
v2 := body_velocity_at_point(body2, p2)
|
||||||
|
|
||||||
delta_v_tang := Vec2 {
|
delta_v := v2 - v1
|
||||||
lg.dot(delta_v, manifold.tangent),
|
|
||||||
lg.dot(delta_v, manifold.bitangent),
|
|
||||||
}
|
|
||||||
|
|
||||||
use_static_friction :=
|
DYNAMIC_FRICTION :: 0.6
|
||||||
lg.dot(delta_v_tang, delta_v_tang) <
|
STATIC_FRICTION :: 0.8
|
||||||
STATIC_FRICTION_VELOCITY_THRESHOLD * STATIC_FRICTION_VELOCITY_THRESHOLD
|
STATIC_FRICTION_VELOCITY_THRESHOLD :: 0.01
|
||||||
friction: f32 = use_static_friction ? STATIC_FRICTION : DYNAMIC_FRICTION
|
|
||||||
friction_clamp := contact.total_normal_impulse[point_idx] * friction
|
|
||||||
|
|
||||||
incremental_impulse := -inv_w * delta_v_tang
|
delta_v_tang := Vec2 {
|
||||||
|
lg.dot(delta_v, manifold.tangent),
|
||||||
new_total_impulse: Vec2 = lg.clamp(
|
lg.dot(delta_v, manifold.bitangent),
|
||||||
contact.total_friction_impulse[point_idx] + incremental_impulse,
|
|
||||||
Vec2(-friction_clamp),
|
|
||||||
Vec2(friction_clamp),
|
|
||||||
)
|
|
||||||
|
|
||||||
applied_impulse :=
|
|
||||||
new_total_impulse - contact.total_friction_impulse[point_idx]
|
|
||||||
contact.total_friction_impulse[point_idx] = new_total_impulse
|
|
||||||
|
|
||||||
applied_impulse_vec :=
|
|
||||||
applied_impulse.x * manifold.tangent +
|
|
||||||
applied_impulse.y * manifold.bitangent
|
|
||||||
|
|
||||||
apply_velocity_correction(body1, -applied_impulse_vec, p1)
|
|
||||||
apply_velocity_correction(body2, applied_impulse_vec, p2)
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
contact.total_normal_impulse[point_idx] = 0
|
use_static_friction :=
|
||||||
contact.total_friction_impulse[point_idx] = 0
|
lg.dot(delta_v_tang, delta_v_tang) <
|
||||||
|
STATIC_FRICTION_VELOCITY_THRESHOLD * STATIC_FRICTION_VELOCITY_THRESHOLD
|
||||||
|
friction: f32 = use_static_friction ? STATIC_FRICTION : DYNAMIC_FRICTION
|
||||||
|
friction_clamp := contact.total_normal_impulse[point_idx] * friction
|
||||||
|
|
||||||
|
incremental_impulse := -inv_w * delta_v_tang
|
||||||
|
|
||||||
|
new_total_impulse: Vec2 = lg.clamp(
|
||||||
|
contact.total_friction_impulse[point_idx] + incremental_impulse,
|
||||||
|
Vec2(-friction_clamp),
|
||||||
|
Vec2(friction_clamp),
|
||||||
|
)
|
||||||
|
|
||||||
|
applied_impulse := new_total_impulse - contact.total_friction_impulse[point_idx]
|
||||||
|
contact.total_friction_impulse[point_idx] = new_total_impulse
|
||||||
|
|
||||||
|
applied_impulse_vec :=
|
||||||
|
applied_impulse.x * manifold.tangent + applied_impulse.y * manifold.bitangent
|
||||||
|
|
||||||
|
rl.DrawSphereWires(p1, 0.05, 8, 8, rl.RED)
|
||||||
|
rl.DrawLine3D(p1, p1 + v1, rl.RED)
|
||||||
|
rl.DrawSphereWires(p2, 0.05, 8, 8, rl.BLUE)
|
||||||
|
rl.DrawLine3D(p2, p2 + v2, rl.BLUE)
|
||||||
|
|
||||||
|
apply_velocity_correction(body1, -applied_impulse_vec, p1)
|
||||||
|
apply_velocity_correction(body2, applied_impulse_vec, p2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -555,24 +571,29 @@ pgs_solve_engines :: proc(sim_state: ^Sim_State, config: Solver_Config, dt: f32,
|
|||||||
rpm_torque_curve := get_engine_curve(sim_state, engine.rpm_torque_curve)
|
rpm_torque_curve := get_engine_curve(sim_state, engine.rpm_torque_curve)
|
||||||
gear_ratios := get_gear_ratios(sim_state, engine.gear_ratios)
|
gear_ratios := get_gear_ratios(sim_state, engine.gear_ratios)
|
||||||
|
|
||||||
// Unstall impulse
|
|
||||||
{
|
|
||||||
engine_lowest_velocity := rpm_to_angular_velocity(engine.lowest_rpm)
|
|
||||||
|
|
||||||
delta_omega := engine_lowest_velocity - engine.w
|
|
||||||
|
|
||||||
inv_w := engine.inertia
|
|
||||||
|
|
||||||
incremental_impulse := inv_w * delta_omega
|
|
||||||
new_total_impulse := max(engine.unstall_impulse + incremental_impulse, 0)
|
|
||||||
applied_impulse := new_total_impulse - engine.unstall_impulse
|
|
||||||
engine.unstall_impulse = new_total_impulse
|
|
||||||
|
|
||||||
engine.w += applied_impulse / engine.inertia
|
|
||||||
}
|
|
||||||
|
|
||||||
rpm := angular_velocity_to_rpm(engine.w)
|
rpm := angular_velocity_to_rpm(engine.w)
|
||||||
throttle := engine.throttle
|
throttle := engine.throttle
|
||||||
|
clutch := f32(0)
|
||||||
|
|
||||||
|
// Blending range in rpm of auto clutch activation
|
||||||
|
AUTO_CLUTCH_RPM_RANGE :: f32(100)
|
||||||
|
AUTO_BLIP_RPM_RANGE :: f32(100)
|
||||||
|
|
||||||
|
// Prevent stalling
|
||||||
|
{
|
||||||
|
if rpm < engine.lowest_rpm {
|
||||||
|
clutch =
|
||||||
|
min(engine.lowest_rpm - rpm, AUTO_CLUTCH_RPM_RANGE) / AUTO_CLUTCH_RPM_RANGE
|
||||||
|
|
||||||
|
throttle = max(
|
||||||
|
throttle,
|
||||||
|
min((engine.lowest_rpm - AUTO_BLIP_RPM_RANGE) - rpm, AUTO_BLIP_RPM_RANGE) /
|
||||||
|
AUTO_BLIP_RPM_RANGE,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
engine.clutch = clutch
|
||||||
|
|
||||||
if engine.rev_limit_time < 0.0 {
|
if engine.rev_limit_time < 0.0 {
|
||||||
engine.rev_limit_time += dt
|
engine.rev_limit_time += dt
|
||||||
@ -582,7 +603,6 @@ pgs_solve_engines :: proc(sim_state: ^Sim_State, config: Solver_Config, dt: f32,
|
|||||||
throttle = 0
|
throttle = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Throttle
|
// Throttle
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -670,6 +690,8 @@ pgs_solve_engines :: proc(sim_state: ^Sim_State, config: Solver_Config, dt: f32,
|
|||||||
incremental_impulse := -inv_w * delta_omega
|
incremental_impulse := -inv_w * delta_omega
|
||||||
engine.axle.engine_impulse += incremental_impulse
|
engine.axle.engine_impulse += incremental_impulse
|
||||||
|
|
||||||
|
incremental_impulse *= (1.0 - clutch)
|
||||||
|
|
||||||
engine.w += incremental_impulse * w1
|
engine.w += incremental_impulse * w1
|
||||||
wheel1.w += incremental_impulse * w2 * inv_ratio
|
wheel1.w += incremental_impulse * w2 * inv_ratio
|
||||||
wheel2.w += incremental_impulse * w3 * inv_ratio
|
wheel2.w += incremental_impulse * w3 * inv_ratio
|
||||||
@ -706,6 +728,21 @@ pgs_solve_engines :: proc(sim_state: ^Sim_State, config: Solver_Config, dt: f32,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
calculate_ground_vel :: proc(
|
||||||
|
body: Body_Ptr,
|
||||||
|
p: Vec3,
|
||||||
|
right, forward: Vec3,
|
||||||
|
) -> (
|
||||||
|
body_vel_at_contact_patch: Vec3,
|
||||||
|
ground_vel: Vec2,
|
||||||
|
) {
|
||||||
|
body_vel_at_contact_patch = body_velocity_at_point(body, p)
|
||||||
|
ground_vel.x = lg.dot(body_vel_at_contact_patch, right)
|
||||||
|
ground_vel.y = lg.dot(body_vel_at_contact_patch, forward)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
pgs_solve_suspension :: proc(
|
pgs_solve_suspension :: proc(
|
||||||
sim_state: ^Sim_State,
|
sim_state: ^Sim_State,
|
||||||
tlas: ^TLAS,
|
tlas: ^TLAS,
|
||||||
@ -735,8 +772,6 @@ pgs_solve_suspension :: proc(
|
|||||||
forward := wheel_get_forward_vec(body, v)
|
forward := wheel_get_forward_vec(body, v)
|
||||||
right := wheel_get_right_vec(body, v)
|
right := wheel_get_right_vec(body, v)
|
||||||
|
|
||||||
body_vel_at_contact_patch := body_velocity_at_point(body, v.hit_point)
|
|
||||||
|
|
||||||
w_normal := get_body_angular_inverse_mass(body, dir)
|
w_normal := get_body_angular_inverse_mass(body, dir)
|
||||||
inv_w_normal := 1.0 / w_normal
|
inv_w_normal := 1.0 / w_normal
|
||||||
|
|
||||||
@ -796,22 +831,25 @@ pgs_solve_suspension :: proc(
|
|||||||
|
|
||||||
// Positive means spinning forward
|
// Positive means spinning forward
|
||||||
wheel_spin_vel := -v.radius * v.w
|
wheel_spin_vel := -v.radius * v.w
|
||||||
ground_vel_x := lg.dot(body_vel_at_contact_patch, right)
|
|
||||||
ground_vel_y := lg.dot(body_vel_at_contact_patch, forward)
|
body_vel_at_contact_patch, ground_vel := calculate_ground_vel(
|
||||||
// contact_patch_linear_vel :=
|
body,
|
||||||
// body_vel_at_contact_patch + (v.radius * v.w * forward)
|
v.hit_point,
|
||||||
|
right,
|
||||||
|
forward,
|
||||||
|
)
|
||||||
|
|
||||||
slip_ratio :=
|
slip_ratio :=
|
||||||
ground_vel_y == 0 ? 0 : clamp(wheel_spin_vel / ground_vel_y - 1, -1, 1) * 100.0
|
ground_vel.y == 0 ? 0 : clamp(wheel_spin_vel / ground_vel.y - 1, -1, 1) * 100.0
|
||||||
|
|
||||||
slip_angle :=
|
slip_angle :=
|
||||||
-lg.angle_between(Vec2{0, 1}, Vec2{ground_vel_x, ground_vel_y}) *
|
-lg.angle_between(Vec2{0, 1}, Vec2{ground_vel.x, ground_vel.y}) *
|
||||||
math.DEG_PER_RAD
|
math.DEG_PER_RAD
|
||||||
|
|
||||||
v.slip_ratio = slip_ratio
|
v.slip_ratio = slip_ratio
|
||||||
v.slip_angle = slip_angle
|
v.slip_angle = slip_angle
|
||||||
|
|
||||||
MAX_SLIP_LEN :: f32(2.0)
|
MAX_SLIP_LEN :: f32(1.5)
|
||||||
|
|
||||||
slip_vec := Vec2 {
|
slip_vec := Vec2 {
|
||||||
slip_angle / PACEJKA94_LATERAL_PEAK_X / MAX_SLIP_LEN,
|
slip_angle / PACEJKA94_LATERAL_PEAK_X / MAX_SLIP_LEN,
|
||||||
@ -848,8 +886,15 @@ pgs_solve_suspension :: proc(
|
|||||||
|
|
||||||
// Longitudinal friction
|
// Longitudinal friction
|
||||||
if true {
|
if true {
|
||||||
|
body_vel_at_contact_patch, ground_vel = calculate_ground_vel(
|
||||||
|
body,
|
||||||
|
v.hit_point,
|
||||||
|
right,
|
||||||
|
forward,
|
||||||
|
)
|
||||||
|
|
||||||
// Wheel linear velocity relative to ground
|
// Wheel linear velocity relative to ground
|
||||||
relative_vel := ground_vel_y - wheel_spin_vel
|
relative_vel := ground_vel.y - wheel_spin_vel
|
||||||
|
|
||||||
friction_clamp := abs(v.spring_impulse) * long_friction
|
friction_clamp := abs(v.spring_impulse) * long_friction
|
||||||
|
|
||||||
@ -872,9 +917,13 @@ pgs_solve_suspension :: proc(
|
|||||||
}
|
}
|
||||||
// Lateral friction
|
// Lateral friction
|
||||||
if true {
|
if true {
|
||||||
vel_contact := body_vel_at_contact_patch
|
body_vel_at_contact_patch, ground_vel = calculate_ground_vel(
|
||||||
|
body,
|
||||||
lateral_vel := lg.dot(right, vel_contact)
|
v.hit_point,
|
||||||
|
right,
|
||||||
|
forward,
|
||||||
|
)
|
||||||
|
lateral_vel := ground_vel.x
|
||||||
friction_clamp := abs(v.spring_impulse) * lat_friction
|
friction_clamp := abs(v.spring_impulse) * lat_friction
|
||||||
|
|
||||||
incremental_impulse := -inv_w_normal * lateral_vel
|
incremental_impulse := -inv_w_normal * lateral_vel
|
||||||
@ -944,7 +993,7 @@ pgs_substep :: proc(
|
|||||||
|
|
||||||
if e.alive {
|
if e.alive {
|
||||||
gear_ratios := get_gear_ratios(sim_state, e.gear_ratios)
|
gear_ratios := get_gear_ratios(sim_state, e.gear_ratios)
|
||||||
e.w += e.unstall_impulse / e.inertia
|
// e.w += e.unstall_impulse / e.inertia
|
||||||
|
|
||||||
e.w += e.friction_impulse / e.inertia
|
e.w += e.friction_impulse / e.inertia
|
||||||
|
|
||||||
@ -966,9 +1015,9 @@ pgs_substep :: proc(
|
|||||||
w2 := wheel1.inv_inertia
|
w2 := wheel1.inv_inertia
|
||||||
w3 := wheel2.inv_inertia
|
w3 := wheel2.inv_inertia
|
||||||
|
|
||||||
e.w += e.axle.engine_impulse * w1
|
e.w += e.axle.engine_impulse * w1 * (1.0 - e.clutch)
|
||||||
wheel1.w += e.axle.engine_impulse * w2 * inv_ratio
|
wheel1.w += e.axle.engine_impulse * w2 * inv_ratio * (1.0 - e.clutch)
|
||||||
wheel2.w += e.axle.engine_impulse * w3 * inv_ratio
|
wheel2.w += e.axle.engine_impulse * w3 * inv_ratio * (1.0 - e.clutch)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warmp start diff impulse
|
// Warmp start diff impulse
|
||||||
@ -1058,9 +1107,11 @@ simulate_step :: proc(scene: ^Scene, sim_state: ^Sim_State, config: Solver_Confi
|
|||||||
|
|
||||||
substeps := config.substreps_minus_one + 1
|
substeps := config.substreps_minus_one + 1
|
||||||
|
|
||||||
dt := config.timestep / f32(substeps)
|
dt_64 := f64(config.timestep) / f64(substeps)
|
||||||
inv_dt := 1.0 / dt
|
inv_dt_64 := f64(1.0) / dt_64
|
||||||
|
|
||||||
|
dt := f32(dt_64)
|
||||||
|
inv_dt := f32(inv_dt_64)
|
||||||
|
|
||||||
tlas := build_tlas(sim_state, config)
|
tlas := build_tlas(sim_state, config)
|
||||||
|
|
||||||
@ -1073,7 +1124,7 @@ simulate_step :: proc(scene: ^Scene, sim_state: ^Sim_State, config: Solver_Confi
|
|||||||
aabb_a := tlas.body_aabbs[int(contact.a) - 1]
|
aabb_a := tlas.body_aabbs[int(contact.a) - 1]
|
||||||
aabb_b := tlas.body_aabbs[int(contact.b) - 1]
|
aabb_b := tlas.body_aabbs[int(contact.b) - 1]
|
||||||
|
|
||||||
if !bvh.test_aabb_vs_aabb(aabb_a, aabb_b) {
|
if false && !bvh.test_aabb_vs_aabb(aabb_a, aabb_b) {
|
||||||
removed_pair := make_contact_pair(i32(contact.a) - 1, i32(contact.b) - 1)
|
removed_pair := make_contact_pair(i32(contact.a) - 1, i32(contact.b) - 1)
|
||||||
delete_key(&sim_state.contact_container.lookup, removed_pair)
|
delete_key(&sim_state.contact_container.lookup, removed_pair)
|
||||||
|
|
||||||
|
BIN
src_assets/car_convex.blend
(Stored with Git LFS)
BIN
src_assets/car_convex.blend
(Stored with Git LFS)
Binary file not shown.
BIN
src_assets/car_convex.blend1
(Stored with Git LFS)
BIN
src_assets/car_convex.blend1
(Stored with Git LFS)
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user