Kansei dorifto (no idea why car rotates like that lol)
This commit is contained in:
parent
aa0f945b0c
commit
ad2d175b10
@ -370,18 +370,35 @@ draw :: proc() {
|
||||
|
||||
camera := game_camera_3d()
|
||||
|
||||
points := &get_world().track.points
|
||||
|
||||
interpolated_points := calculate_spline_interpolated_points(points[:], context.temp_allocator)
|
||||
|
||||
collision, segment_idx := raycast_spline_tube(
|
||||
interpolated_points,
|
||||
rl.GetScreenToWorldRay(rl.GetMousePosition(), camera),
|
||||
)
|
||||
|
||||
{
|
||||
rl.BeginMode3D(camera)
|
||||
defer rl.EndMode3D()
|
||||
|
||||
rl.DrawModel(
|
||||
assets.get_model(&g_mem.assetman, "assets/toyota_corolla_ae86_trueno.glb"),
|
||||
rl.Vector3{0, 0, 0},
|
||||
1,
|
||||
rl.WHITE,
|
||||
)
|
||||
if collision.hit {
|
||||
tangent, bitangent := get_point_frame(interpolated_points, segment_idx)
|
||||
|
||||
points := &get_world().track.points
|
||||
rot_matrix: linalg.Matrix3f32
|
||||
rot_matrix[0] = bitangent
|
||||
rot_matrix[1] = interpolated_points[segment_idx].normal
|
||||
rot_matrix[2] = -tangent
|
||||
|
||||
angle, axis := linalg.angle_axis_from_quaternion(
|
||||
linalg.quaternion_from_matrix3(rot_matrix),
|
||||
)
|
||||
car_model := assets.get_model(&g_mem.assetman, "assets/toyota_corolla_ae86_trueno.glb")
|
||||
car_model.transform = rl.MatrixRotate(axis, angle)
|
||||
|
||||
rl.DrawModel(car_model, collision.point, 1, rl.WHITE)
|
||||
}
|
||||
|
||||
// road: rl.Mesh
|
||||
// defer rl.UnloadMesh(road)
|
||||
@ -394,11 +411,6 @@ draw :: proc() {
|
||||
// road_uvs.allocator = context.temp_allocator
|
||||
// road_indices.allocator = context.temp_allocator
|
||||
|
||||
interpolated_points := calculate_spline_interpolated_points(
|
||||
points[:],
|
||||
context.temp_allocator,
|
||||
)
|
||||
|
||||
|
||||
{
|
||||
// Debug draw spline road
|
||||
@ -439,6 +451,10 @@ draw :: proc() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if collision.hit {
|
||||
rl.DrawSphereWires(collision.point, 1, 8, 8, rl.RED)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
@ -448,6 +464,10 @@ draw :: proc() {
|
||||
if g_mem.editor {
|
||||
rl.DrawText("Editor", 5, 5, 8, rl.ORANGE)
|
||||
|
||||
if collision.hit {
|
||||
rl.DrawText(fmt.ctprintf("Segment: %v", segment_idx), 5, 32, 8, rl.ORANGE)
|
||||
}
|
||||
|
||||
switch g_mem.es.track_edit_state {
|
||||
case .Select:
|
||||
case .Move:
|
||||
@ -465,7 +485,6 @@ draw :: proc() {
|
||||
if g_mem.editor {
|
||||
es := &g_mem.es
|
||||
|
||||
points := &get_world().track.points
|
||||
points_len := len(points)
|
||||
|
||||
if points_len > 0 {
|
||||
|
135
game/track.odin
135
game/track.odin
@ -74,17 +74,142 @@ sample_spline :: proc(points: []rl.Vector3, t: f32) -> rl.Vector3 {
|
||||
return {}
|
||||
}
|
||||
|
||||
get_point_frame :: #force_inline proc(
|
||||
ps: #soa[]Interpolated_Point,
|
||||
i: int,
|
||||
) -> (
|
||||
tangent: rl.Vector3,
|
||||
bitangent: rl.Vector3,
|
||||
) {
|
||||
if len(ps) >= 2 {
|
||||
tangent =
|
||||
ps[i + 1].pos - ps[i].pos if (i < len(ps) - 1) else ps[len(ps) - 1].pos - ps[len(ps) - 2].pos
|
||||
normal := ps[i].normal
|
||||
bitangent = lg.normalize0(lg.cross(tangent, normal))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
point_to_quad_sdf :: proc(p, a, b, c, d: rl.Vector3) -> f32 {
|
||||
ba := b - a
|
||||
pa := p - a
|
||||
cb := c - b
|
||||
pb := p - b
|
||||
dc := d - c
|
||||
pc := p - c
|
||||
ad := a - d
|
||||
pd := p - d
|
||||
nor := lg.cross(ba, ad)
|
||||
|
||||
sqrt :: math.sqrt
|
||||
dot :: lg.dot
|
||||
cross :: lg.cross
|
||||
length2 :: lg.length2
|
||||
min :: math.min
|
||||
sign :: math.sign
|
||||
clamp :: math.clamp
|
||||
|
||||
return sqrt(
|
||||
(sign(dot(cross(ba, nor), pa)) + sign(dot(cross(cb, nor), pb)) + sign(dot(cross(dc, nor), pc)) + sign(dot(cross(ad, nor), pd)) < 3.0) ? (min(min(min(length2(ba * clamp(dot(ba, pa) / length2(ba), 0.0, 1.0) - pa), length2(cb * clamp(dot(cb, pb) / length2(cb), 0.0, 1.0) - pb)), length2(dc * clamp(dot(dc, pc) / length2(dc), 0.0, 1.0) - pc)), length2(ad * clamp(dot(ad, pd) / length2(ad), 0.0, 1.0) - pd))) : (dot(nor, pa) * dot(nor, pa) / length2(nor)),
|
||||
)
|
||||
}
|
||||
|
||||
// point_to_segmented_line_distance :: proc(
|
||||
// ps: #soa[]Interpolated_Point,
|
||||
// p: rl.Vector3,
|
||||
// ) -> (
|
||||
// min_distance: f32,
|
||||
// segment_idx: int,
|
||||
// ok: bool, // is point within spline
|
||||
// ) {
|
||||
// min_distance = math.F32_MAX
|
||||
// segment_idx = -1
|
||||
// for i in 0 ..< len(ps) - 1 {
|
||||
// cur, next := ps[i].pos, ps[i + 1].pos
|
||||
//
|
||||
// tangent, bitangent := get_point_frame(ps, i)
|
||||
// next_tangent, next_bitangent := get_point_frame(ps, i + 1)
|
||||
// normal, next_normal := ps[i].normal, ps[i + 1].normal
|
||||
//
|
||||
// tangent_len := lg.length(tangent)
|
||||
// tangent_norm := tangent / tangent_len if tangent_len > 0 else 0
|
||||
//
|
||||
// translated_p := p - cur
|
||||
//
|
||||
// // point_to_quad_sdf(p, cur - bitangent * -ROAD_WIDTH, cur)
|
||||
//
|
||||
// dot_v := lg.dot(tangent_norm, translated_p)
|
||||
// // dot_u := lg.dot(bitangent)
|
||||
//
|
||||
// distance: f32
|
||||
// if dot_v < 0 {
|
||||
// distance = lg.length(translated_p)
|
||||
// ok = false
|
||||
// } else if dot_v > tangent_len {
|
||||
// distance = lg.distance(tangent, translated_p)
|
||||
// ok = false
|
||||
// } else {
|
||||
// projected_p := tangent_norm * dot_v
|
||||
// distance = lg.distance(projected_p, translated_p)
|
||||
// ok = true
|
||||
// }
|
||||
//
|
||||
// if distance < min_distance {
|
||||
// segment_idx = i
|
||||
// min_distance = distance
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return min_distance, segment_idx, ok
|
||||
// }
|
||||
|
||||
/// Find collision with the closest
|
||||
raycast_spline_tube :: proc(
|
||||
ps: #soa[]Interpolated_Point,
|
||||
ray: rl.Ray,
|
||||
) -> (
|
||||
collision: rl.RayCollision,
|
||||
segment_idx: int,
|
||||
) {
|
||||
for i in 0 ..< len(ps) - 1 {
|
||||
cur, next := ps[i].pos, ps[i + 1].pos
|
||||
|
||||
_, bitangent := get_point_frame(ps, i)
|
||||
_, next_bitangent := get_point_frame(ps, i + 1)
|
||||
// normal, next_normal := ps[i].normal, ps[i + 1].normal
|
||||
|
||||
p1 := cur + bitangent * -ROAD_WIDTH
|
||||
p2 := cur + bitangent * ROAD_WIDTH
|
||||
p3 := next + next_bitangent * -ROAD_WIDTH
|
||||
p4 := next + next_bitangent * ROAD_WIDTH
|
||||
|
||||
segment_idx = i
|
||||
|
||||
collision = rl.GetRayCollisionTriangle(ray, p1, p2, p3)
|
||||
if collision.hit {
|
||||
break
|
||||
}
|
||||
collision = rl.GetRayCollisionTriangle(ray, p2, p4, p3)
|
||||
if collision.hit {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
calculate_spline_interpolated_points :: proc(
|
||||
points: []rl.Vector3,
|
||||
allocator := context.allocator,
|
||||
) -> []Interpolated_Point {
|
||||
) -> #soa[]Interpolated_Point {
|
||||
points_len := len(points)
|
||||
|
||||
ctrl_rotations := calculate_spline_ctrl_rotations(points, context.temp_allocator)
|
||||
|
||||
if points_len >= 2 {
|
||||
interpolated_points := make(
|
||||
[]Interpolated_Point,
|
||||
interpolated_points := make_soa(
|
||||
#soa[]Interpolated_Point,
|
||||
(points_len - 1) * SPLINE_SUBDIVS_V + 1,
|
||||
allocator,
|
||||
)
|
||||
@ -132,7 +257,7 @@ calculate_spline_interpolated_points :: proc(
|
||||
return nil
|
||||
}
|
||||
|
||||
debug_draw_spline :: proc(interpolated_points: []Interpolated_Point) {
|
||||
debug_draw_spline :: proc(interpolated_points: #soa[]Interpolated_Point) {
|
||||
rlgl.Begin(rlgl.LINES)
|
||||
defer rlgl.End()
|
||||
for i in 0 ..< len(interpolated_points) - 1 {
|
||||
@ -160,7 +285,7 @@ debug_draw_spline :: proc(interpolated_points: []Interpolated_Point) {
|
||||
|
||||
}
|
||||
}
|
||||
debug_draw_spline_mesh :: proc(interpolated_points: []Interpolated_Point) {
|
||||
debug_draw_spline_mesh :: proc(interpolated_points: #soa[]Interpolated_Point) {
|
||||
rlgl.Begin(rlgl.TRIANGLES)
|
||||
defer rlgl.End()
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user