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()
|
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)
|
rl.BeginMode3D(camera)
|
||||||
defer rl.EndMode3D()
|
defer rl.EndMode3D()
|
||||||
|
|
||||||
rl.DrawModel(
|
if collision.hit {
|
||||||
assets.get_model(&g_mem.assetman, "assets/toyota_corolla_ae86_trueno.glb"),
|
tangent, bitangent := get_point_frame(interpolated_points, segment_idx)
|
||||||
rl.Vector3{0, 0, 0},
|
|
||||||
1,
|
|
||||||
rl.WHITE,
|
|
||||||
)
|
|
||||||
|
|
||||||
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
|
// road: rl.Mesh
|
||||||
// defer rl.UnloadMesh(road)
|
// defer rl.UnloadMesh(road)
|
||||||
@ -394,11 +411,6 @@ draw :: proc() {
|
|||||||
// road_uvs.allocator = context.temp_allocator
|
// road_uvs.allocator = context.temp_allocator
|
||||||
// road_indices.allocator = context.temp_allocator
|
// road_indices.allocator = context.temp_allocator
|
||||||
|
|
||||||
interpolated_points := calculate_spline_interpolated_points(
|
|
||||||
points[:],
|
|
||||||
context.temp_allocator,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
// Debug draw spline road
|
// 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 {
|
if g_mem.editor {
|
||||||
rl.DrawText("Editor", 5, 5, 8, rl.ORANGE)
|
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 {
|
switch g_mem.es.track_edit_state {
|
||||||
case .Select:
|
case .Select:
|
||||||
case .Move:
|
case .Move:
|
||||||
@ -465,7 +485,6 @@ draw :: proc() {
|
|||||||
if g_mem.editor {
|
if g_mem.editor {
|
||||||
es := &g_mem.es
|
es := &g_mem.es
|
||||||
|
|
||||||
points := &get_world().track.points
|
|
||||||
points_len := len(points)
|
points_len := len(points)
|
||||||
|
|
||||||
if points_len > 0 {
|
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 {}
|
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(
|
calculate_spline_interpolated_points :: proc(
|
||||||
points: []rl.Vector3,
|
points: []rl.Vector3,
|
||||||
allocator := context.allocator,
|
allocator := context.allocator,
|
||||||
) -> []Interpolated_Point {
|
) -> #soa[]Interpolated_Point {
|
||||||
points_len := len(points)
|
points_len := len(points)
|
||||||
|
|
||||||
ctrl_rotations := calculate_spline_ctrl_rotations(points, context.temp_allocator)
|
ctrl_rotations := calculate_spline_ctrl_rotations(points, context.temp_allocator)
|
||||||
|
|
||||||
if points_len >= 2 {
|
if points_len >= 2 {
|
||||||
interpolated_points := make(
|
interpolated_points := make_soa(
|
||||||
[]Interpolated_Point,
|
#soa[]Interpolated_Point,
|
||||||
(points_len - 1) * SPLINE_SUBDIVS_V + 1,
|
(points_len - 1) * SPLINE_SUBDIVS_V + 1,
|
||||||
allocator,
|
allocator,
|
||||||
)
|
)
|
||||||
@ -132,7 +257,7 @@ calculate_spline_interpolated_points :: proc(
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_draw_spline :: proc(interpolated_points: []Interpolated_Point) {
|
debug_draw_spline :: proc(interpolated_points: #soa[]Interpolated_Point) {
|
||||||
rlgl.Begin(rlgl.LINES)
|
rlgl.Begin(rlgl.LINES)
|
||||||
defer rlgl.End()
|
defer rlgl.End()
|
||||||
for i in 0 ..< len(interpolated_points) - 1 {
|
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)
|
rlgl.Begin(rlgl.TRIANGLES)
|
||||||
defer rlgl.End()
|
defer rlgl.End()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user