Draw road mesh, refactor
This commit is contained in:
parent
e404a33c6f
commit
64dbe0c5e4
254
game/game.odin
254
game/game.odin
@ -25,12 +25,16 @@ PIXEL_WINDOW_HEIGHT :: 360
|
|||||||
Track :: struct {
|
Track :: struct {
|
||||||
points: [dynamic]rl.Vector3,
|
points: [dynamic]rl.Vector3,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
World :: struct {
|
||||||
|
track: Track,
|
||||||
|
}
|
||||||
|
|
||||||
Game_Memory :: struct {
|
Game_Memory :: struct {
|
||||||
assetman: assets.Asset_Manager,
|
assetman: assets.Asset_Manager,
|
||||||
player_pos: rl.Vector3,
|
player_pos: rl.Vector3,
|
||||||
camera_yaw_pitch: rl.Vector2,
|
camera_yaw_pitch: rl.Vector2,
|
||||||
camera_speed: f32,
|
camera_speed: f32,
|
||||||
track: Track,
|
|
||||||
es: Editor_State,
|
es: Editor_State,
|
||||||
editor: bool,
|
editor: bool,
|
||||||
}
|
}
|
||||||
@ -53,15 +57,20 @@ Move_Axis :: enum {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Editor_State :: struct {
|
Editor_State :: struct {
|
||||||
mouse_captured: bool,
|
world: World,
|
||||||
selected_track_point: int,
|
mouse_captured: bool,
|
||||||
track_edit_state: Track_Edit_State,
|
point_selection: map[int]bool,
|
||||||
move_axis: Move_Axis,
|
track_edit_state: Track_Edit_State,
|
||||||
initial_point_pos: rl.Vector3,
|
move_axis: Move_Axis,
|
||||||
|
initial_point_pos: rl.Vector3,
|
||||||
}
|
}
|
||||||
|
|
||||||
g_mem: ^Game_Memory
|
g_mem: ^Game_Memory
|
||||||
|
|
||||||
|
world :: proc() -> ^World {
|
||||||
|
return &g_mem.es.world
|
||||||
|
}
|
||||||
|
|
||||||
game_camera :: proc() -> rl.Camera2D {
|
game_camera :: proc() -> rl.Camera2D {
|
||||||
w := f32(rl.GetScreenWidth())
|
w := f32(rl.GetScreenWidth())
|
||||||
h := f32(rl.GetScreenHeight())
|
h := f32(rl.GetScreenHeight())
|
||||||
@ -135,11 +144,20 @@ update_free_look_camera :: proc() {
|
|||||||
g_mem.player_pos += (input.x * right + input.y * forward) * g_mem.camera_speed
|
g_mem.player_pos += (input.x * right + input.y * forward) * g_mem.camera_speed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
select_track_point :: proc(index: int) {
|
||||||
|
clear(&g_mem.es.point_selection)
|
||||||
|
g_mem.es.point_selection[index] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
is_point_selected :: proc() -> bool {
|
||||||
|
return len(g_mem.es.point_selection) > 0
|
||||||
|
}
|
||||||
|
|
||||||
add_track_spline_point :: proc() {
|
add_track_spline_point :: proc() {
|
||||||
forward := camera_rotation_matrix()[2]
|
forward := camera_rotation_matrix()[2]
|
||||||
|
|
||||||
append(&g_mem.track.points, g_mem.player_pos + forward)
|
append(&world().track.points, g_mem.player_pos + forward)
|
||||||
g_mem.es.selected_track_point = len(g_mem.track.points) - 1
|
select_track_point(len(&world().track.points) - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
get_movement_axes :: proc(
|
get_movement_axes :: proc(
|
||||||
@ -198,17 +216,27 @@ update_editor :: proc() {
|
|||||||
add_track_spline_point()
|
add_track_spline_point()
|
||||||
}
|
}
|
||||||
|
|
||||||
if rl.IsKeyPressed(.G) && es.selected_track_point >= 0 {
|
if is_point_selected() {
|
||||||
es.track_edit_state = .Move
|
if rl.IsKeyPressed(.X) {
|
||||||
es.move_axis = .None
|
for k, v in es.point_selection {
|
||||||
es.initial_point_pos = g_mem.track.points[es.selected_track_point]
|
assert(v)
|
||||||
|
ordered_remove(&world().track.points, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
clear(&es.point_selection)
|
||||||
|
}
|
||||||
|
if rl.IsKeyPressed(.G) {
|
||||||
|
es.track_edit_state = .Move
|
||||||
|
es.move_axis = .None
|
||||||
|
// es.initial_point_pos = g_mem.track.points[es.selected_track_point]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case .Move:
|
case .Move:
|
||||||
{
|
{
|
||||||
if rl.IsKeyPressed(.ESCAPE) {
|
if rl.IsKeyPressed(.ESCAPE) {
|
||||||
es.track_edit_state = .Select
|
es.track_edit_state = .Select
|
||||||
g_mem.track.points[es.selected_track_point] = es.initial_point_pos
|
// g_mem.track.points[es.selected_track_point] = es.initial_point_pos
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,7 +293,9 @@ update_editor :: proc() {
|
|||||||
(rl.Vector4{movement_screen.x, movement_screen.y, 0, 1} * rl.MatrixInvert(view_proj)).xyz
|
(rl.Vector4{movement_screen.x, movement_screen.y, 0, 1} * rl.MatrixInvert(view_proj)).xyz
|
||||||
}
|
}
|
||||||
|
|
||||||
g_mem.track.points[es.selected_track_point] += movement_world
|
for k in es.point_selection {
|
||||||
|
world().track.points[k] += movement_world
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -336,8 +366,7 @@ draw :: proc() {
|
|||||||
rl.WHITE,
|
rl.WHITE,
|
||||||
)
|
)
|
||||||
|
|
||||||
points := &g_mem.track.points
|
points := &world().track.points
|
||||||
points_len := len(points)
|
|
||||||
|
|
||||||
// road: rl.Mesh
|
// road: rl.Mesh
|
||||||
// defer rl.UnloadMesh(road)
|
// defer rl.UnloadMesh(road)
|
||||||
@ -350,15 +379,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
|
||||||
|
|
||||||
// spline_segment_count := max(len(g_mem.track.points) - 4, 0)
|
|
||||||
|
|
||||||
|
|
||||||
SPLINE_SUBDIVS_U :: 4
|
|
||||||
SPLINE_SUBDIVS_V :: 16
|
|
||||||
ROAD_WIDTH :: 2.0
|
|
||||||
CATMULL_ROM_ALPHA :: 1.0
|
|
||||||
CATMULL_ROM_TENSION :: 0.0
|
|
||||||
|
|
||||||
{
|
{
|
||||||
// Debug draw spline road
|
// Debug draw spline road
|
||||||
{
|
{
|
||||||
@ -367,168 +387,13 @@ draw :: proc() {
|
|||||||
|
|
||||||
rlgl.Color3f(1, 0, 0)
|
rlgl.Color3f(1, 0, 0)
|
||||||
|
|
||||||
|
interpolated_points := calculate_spline_interpolated_points(
|
||||||
Frame :: struct {
|
points[:],
|
||||||
tangent, normal: rl.Vector3,
|
|
||||||
rotation: linalg.Quaternionf32,
|
|
||||||
}
|
|
||||||
|
|
||||||
ctrl_frames := make_soa(#soa[]Frame, points_len, context.temp_allocator)
|
|
||||||
|
|
||||||
// Normals for control points
|
|
||||||
for i in 0 ..< points_len - 1 {
|
|
||||||
pos := points[i]
|
|
||||||
tangent := linalg.normalize0(points[i + 1] - pos)
|
|
||||||
bitangent := linalg.normalize0(linalg.cross(tangent, rl.Vector3{0, 1, 0}))
|
|
||||||
normal := linalg.normalize0(linalg.cross(bitangent, tangent))
|
|
||||||
rotation_matrix: linalg.Matrix3f32
|
|
||||||
rotation_matrix[0], rotation_matrix[1], rotation_matrix[2] =
|
|
||||||
bitangent, normal, -tangent
|
|
||||||
ctrl_frames[i].tangent = tangent
|
|
||||||
ctrl_frames[i].normal = normal
|
|
||||||
ctrl_frames[i].rotation = linalg.quaternion_from_matrix3(rotation_matrix)
|
|
||||||
}
|
|
||||||
ctrl_frames[points_len - 1] = ctrl_frames[points_len - 2]
|
|
||||||
|
|
||||||
interpolated_points := make(
|
|
||||||
[]rl.Vector3,
|
|
||||||
(points_len - 1) * SPLINE_SUBDIVS_V + 1,
|
|
||||||
context.temp_allocator,
|
context.temp_allocator,
|
||||||
)
|
)
|
||||||
|
|
||||||
if points_len >= 2 {
|
debug_draw_spline(interpolated_points)
|
||||||
extended_start := points[0] + (points[0] - points[1])
|
debug_draw_spline_mesh(interpolated_points)
|
||||||
extended_end :=
|
|
||||||
points[points_len - 1] + points[points_len - 1] - points[points_len - 2]
|
|
||||||
extended_end2 := extended_end + points[points_len - 1] - points[points_len - 2]
|
|
||||||
|
|
||||||
for i in 0 ..< points_len - 1 {
|
|
||||||
prev := i > 0 ? points[i - 1] : extended_start
|
|
||||||
current := points[i]
|
|
||||||
next := i < points_len - 1 ? points[i + 1] : extended_end
|
|
||||||
next2 := i < points_len - 2 ? points[i + 2] : extended_end2
|
|
||||||
|
|
||||||
a, b, c, d := catmull_rom_coefs(
|
|
||||||
prev,
|
|
||||||
current,
|
|
||||||
next,
|
|
||||||
next2,
|
|
||||||
CATMULL_ROM_ALPHA,
|
|
||||||
CATMULL_ROM_TENSION,
|
|
||||||
)
|
|
||||||
|
|
||||||
v_dt := 1.0 / f32(SPLINE_SUBDIVS_V)
|
|
||||||
for v_index in 0 ..< SPLINE_SUBDIVS_V {
|
|
||||||
v_t := f32(v_index) * v_dt
|
|
||||||
|
|
||||||
interpolated_pos := catmull_rom(a, b, c, d, v_t)
|
|
||||||
interpolated_points[i * SPLINE_SUBDIVS_V + v_index] = interpolated_pos
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interpolated_points[len(interpolated_points) - 1] = points[points_len - 1]
|
|
||||||
|
|
||||||
frames := make_soa(
|
|
||||||
#soa[]Frame,
|
|
||||||
len(interpolated_points),
|
|
||||||
context.temp_allocator,
|
|
||||||
)
|
|
||||||
|
|
||||||
{
|
|
||||||
for i in 0 ..< len(frames) - 1 {
|
|
||||||
ctrl_index := i / SPLINE_SUBDIVS_V
|
|
||||||
v_t := f32(i % SPLINE_SUBDIVS_V) / (SPLINE_SUBDIVS_V)
|
|
||||||
|
|
||||||
pos := interpolated_points[i]
|
|
||||||
cur_frame := ctrl_frames[ctrl_index]
|
|
||||||
next_frame := ctrl_frames[ctrl_index + 1]
|
|
||||||
|
|
||||||
frames[i].rotation = linalg.quaternion_slerp(
|
|
||||||
cur_frame.rotation,
|
|
||||||
next_frame.rotation,
|
|
||||||
v_t,
|
|
||||||
)
|
|
||||||
normal := linalg.matrix3_from_quaternion(frames[i].rotation)[1]
|
|
||||||
tangent := linalg.normalize0(interpolated_points[i + 1] - pos)
|
|
||||||
|
|
||||||
frames[i].tangent = tangent
|
|
||||||
frames[i].normal = normal
|
|
||||||
}
|
|
||||||
|
|
||||||
frames[len(frames) - 1] = frames[len(frames) - 2]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parallel frame algorithm (doesn't work because it rotates the road too much, but looks pretty)
|
|
||||||
if false {
|
|
||||||
// Calculate reference normal
|
|
||||||
{
|
|
||||||
tangent := linalg.normalize0(
|
|
||||||
interpolated_points[1] - interpolated_points[0],
|
|
||||||
)
|
|
||||||
frames[0].tangent = tangent
|
|
||||||
bitangent := linalg.normalize0(
|
|
||||||
linalg.cross(tangent, rl.Vector3{0, 1, 0}),
|
|
||||||
)
|
|
||||||
frames[0].normal = linalg.normalize0(linalg.cross(bitangent, tangent))
|
|
||||||
}
|
|
||||||
|
|
||||||
for i in 1 ..< len(frames) {
|
|
||||||
cur, next := interpolated_points[i], interpolated_points[i + 1]
|
|
||||||
|
|
||||||
tangent := linalg.normalize0(next - cur)
|
|
||||||
bitangent := linalg.cross(frames[i - 1].tangent, tangent)
|
|
||||||
bitangent_len := linalg.length(bitangent)
|
|
||||||
normal: rl.Vector3
|
|
||||||
if bitangent_len < math.F32_EPSILON {
|
|
||||||
normal = frames[i - 1].normal
|
|
||||||
} else {
|
|
||||||
bitangent /= bitangent_len
|
|
||||||
angle := math.acos(linalg.dot(frames[i - 1].tangent, tangent))
|
|
||||||
normal =
|
|
||||||
linalg.matrix3_rotate(angle, bitangent) * frames[i - 1].normal
|
|
||||||
}
|
|
||||||
|
|
||||||
frames[i].tangent = tangent
|
|
||||||
frames[i].normal = normal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
rlgl.Begin(rlgl.LINES)
|
|
||||||
defer rlgl.End()
|
|
||||||
|
|
||||||
for i in 0 ..< len(interpolated_points) - 1 {
|
|
||||||
cur, next := interpolated_points[i], interpolated_points[i + 1]
|
|
||||||
|
|
||||||
// rotation := linalg.matrix3_look_at(cur, next, rl.Vector3{0, 1, 0})
|
|
||||||
tangent := frames[i].tangent
|
|
||||||
normal := frames[i].normal
|
|
||||||
bitangent := linalg.cross(tangent, normal)
|
|
||||||
|
|
||||||
rlgl.Color4ub(255, 255, 255, 255)
|
|
||||||
rlgl.Vertex3f(cur.x, cur.y, cur.z)
|
|
||||||
rlgl.Vertex3f(next.x, next.y, next.z)
|
|
||||||
|
|
||||||
rlgl.Color4ub(255, 0, 0, 255)
|
|
||||||
rlgl.Vertex3f(cur.x, cur.y, cur.z)
|
|
||||||
rlgl.Vertex3f(cur.x + tangent.x, cur.y + tangent.y, cur.z + tangent.z)
|
|
||||||
|
|
||||||
rlgl.Color4ub(0, 255, 0, 255)
|
|
||||||
rlgl.Vertex3f(cur.x, cur.y, cur.z)
|
|
||||||
rlgl.Vertex3f(
|
|
||||||
cur.x + bitangent.x,
|
|
||||||
cur.y + bitangent.y,
|
|
||||||
cur.z + bitangent.z,
|
|
||||||
)
|
|
||||||
|
|
||||||
rlgl.Color4ub(0, 0, 255, 255)
|
|
||||||
rlgl.Vertex3f(cur.x, cur.y, cur.z)
|
|
||||||
rlgl.Vertex3f(cur.x + normal.x, cur.y + normal.y, cur.z + normal.z)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if g_mem.editor {
|
if g_mem.editor {
|
||||||
@ -572,14 +437,24 @@ draw :: proc() {
|
|||||||
if g_mem.editor {
|
if g_mem.editor {
|
||||||
es := &g_mem.es
|
es := &g_mem.es
|
||||||
|
|
||||||
points := &g_mem.track.points
|
points := &world().track.points
|
||||||
points_len := len(points)
|
points_len := len(points)
|
||||||
|
|
||||||
|
selected_point := false
|
||||||
for i in 0 ..< points_len {
|
for i in 0 ..< points_len {
|
||||||
if spline_handle(g_mem.track.points[i], camera, es.selected_track_point == i) {
|
if spline_handle(world().track.points[i], camera, es.point_selection[i]) {
|
||||||
g_mem.es.selected_track_point = i
|
if !rl.IsKeyDown(.LEFT_CONTROL) {
|
||||||
|
clear(&g_mem.es.point_selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
g_mem.es.point_selection[i] = true
|
||||||
|
selected_point = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if rl.IsMouseButtonPressed(.LEFT) && !selected_point {
|
||||||
|
clear(&g_mem.es.point_selection)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// axis lines
|
// axis lines
|
||||||
@ -654,15 +529,14 @@ game_init :: proc() {
|
|||||||
|
|
||||||
g_mem^ = Game_Memory{}
|
g_mem^ = Game_Memory{}
|
||||||
|
|
||||||
g_mem.es.selected_track_point = -1
|
|
||||||
|
|
||||||
game_hot_reloaded(g_mem)
|
game_hot_reloaded(g_mem)
|
||||||
}
|
}
|
||||||
|
|
||||||
@(export)
|
@(export)
|
||||||
game_shutdown :: proc() {
|
game_shutdown :: proc() {
|
||||||
assets.shutdown(&g_mem.assetman)
|
assets.shutdown(&g_mem.assetman)
|
||||||
delete(g_mem.track.points)
|
delete(world().track.points)
|
||||||
|
delete(g_mem.es.point_selection)
|
||||||
free(g_mem)
|
free(g_mem)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,52 +1,12 @@
|
|||||||
package game
|
package game
|
||||||
|
|
||||||
import "base:runtime"
|
|
||||||
import "core:c/libc"
|
|
||||||
import "core:log"
|
|
||||||
import "core:mem"
|
|
||||||
import rl "vendor:raylib"
|
import rl "vendor:raylib"
|
||||||
|
import "vendor:raylib/rlgl"
|
||||||
|
|
||||||
logger: log.Logger = {
|
rlgl_color3v :: proc(v: rl.Vector3) {
|
||||||
lowest_level = .Debug,
|
rlgl.Color3f(v.r, v.g, v.b)
|
||||||
}
|
}
|
||||||
rl_log_buf: []byte
|
|
||||||
rl_log :: proc "c" (logLevel: rl.TraceLogLevel, text: cstring, args: ^libc.va_list) {
|
|
||||||
context = runtime.default_context()
|
|
||||||
context.logger = logger
|
|
||||||
|
|
||||||
level: log.Level
|
rlgl_vertex3v :: proc(v: rl.Vector3) {
|
||||||
switch logLevel {
|
rlgl.Vertex3f(v.x, v.y, v.z)
|
||||||
case .TRACE, .DEBUG:
|
|
||||||
level = .Debug
|
|
||||||
case .ALL, .NONE, .INFO:
|
|
||||||
level = .Info
|
|
||||||
case .WARNING:
|
|
||||||
level = .Warning
|
|
||||||
case .ERROR:
|
|
||||||
level = .Error
|
|
||||||
case .FATAL:
|
|
||||||
level = .Fatal
|
|
||||||
}
|
|
||||||
|
|
||||||
if level < logger.lowest_level {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if rl_log_buf == nil {
|
|
||||||
rl_log_buf = make([]byte, 1024)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer mem.zero_slice(rl_log_buf)
|
|
||||||
|
|
||||||
n: int
|
|
||||||
for {
|
|
||||||
va := args
|
|
||||||
n = int(libc.vsnprintf(raw_data(rl_log_buf), len(rl_log_buf), text, va))
|
|
||||||
if n < len(rl_log_buf) do break
|
|
||||||
log.infof("Resizing raylib log buffer from %m to %m", len(rl_log_buf), len(rl_log_buf) * 2)
|
|
||||||
rl_log_buf, _ = mem.resize_bytes(rl_log_buf, len(rl_log_buf) * 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
formatted := string(rl_log_buf[:n])
|
|
||||||
log.log(level, formatted)
|
|
||||||
}
|
}
|
||||||
|
178
game/track.odin
Normal file
178
game/track.odin
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
package game
|
||||||
|
|
||||||
|
import lg "core:math/linalg"
|
||||||
|
import rl "vendor:raylib"
|
||||||
|
import "vendor:raylib/rlgl"
|
||||||
|
|
||||||
|
SPLINE_SUBDIVS_U :: 1
|
||||||
|
SPLINE_SUBDIVS_V :: 16
|
||||||
|
ROAD_WIDTH :: 8.0
|
||||||
|
CATMULL_ROM_ALPHA :: 1.0
|
||||||
|
CATMULL_ROM_TENSION :: 0.0
|
||||||
|
|
||||||
|
calculate_spline_ctrl_rotations :: proc(
|
||||||
|
points: []rl.Vector3,
|
||||||
|
allocator := context.allocator,
|
||||||
|
) -> []lg.Quaternionf32 {
|
||||||
|
points_len := len(points)
|
||||||
|
ctrl_rotations := make([]lg.Quaternionf32, points_len, allocator)
|
||||||
|
|
||||||
|
// Normals for control points
|
||||||
|
for i in 0 ..< points_len - 1 {
|
||||||
|
pos := points[i]
|
||||||
|
tangent := lg.normalize0(points[i + 1] - pos)
|
||||||
|
bitangent := lg.normalize0(lg.cross(tangent, rl.Vector3{0, 1, 0}))
|
||||||
|
normal := lg.normalize0(lg.cross(bitangent, tangent))
|
||||||
|
rotation_matrix: lg.Matrix3f32
|
||||||
|
rotation_matrix[0], rotation_matrix[1], rotation_matrix[2] = bitangent, normal, -tangent
|
||||||
|
ctrl_rotations[i] = lg.quaternion_from_matrix3(rotation_matrix)
|
||||||
|
|
||||||
|
if points_len >= 2 {
|
||||||
|
ctrl_rotations[points_len - 1] = ctrl_rotations[points_len - 2]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ctrl_rotations
|
||||||
|
}
|
||||||
|
|
||||||
|
Interpolated_Point :: struct {
|
||||||
|
pos: rl.Vector3,
|
||||||
|
normal: rl.Vector3,
|
||||||
|
}
|
||||||
|
|
||||||
|
calculate_spline_interpolated_points :: proc(
|
||||||
|
points: []rl.Vector3,
|
||||||
|
allocator := context.allocator,
|
||||||
|
) -> []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,
|
||||||
|
(points_len - 1) * SPLINE_SUBDIVS_V + 1,
|
||||||
|
allocator,
|
||||||
|
)
|
||||||
|
|
||||||
|
extended_start := points[0] + (points[0] - points[1])
|
||||||
|
extended_end := points[points_len - 1] + points[points_len - 1] - points[points_len - 2]
|
||||||
|
extended_end2 := extended_end + points[points_len - 1] - points[points_len - 2]
|
||||||
|
|
||||||
|
for i in 0 ..< points_len - 1 {
|
||||||
|
prev := i > 0 ? points[i - 1] : extended_start
|
||||||
|
current := points[i]
|
||||||
|
next := i < points_len - 1 ? points[i + 1] : extended_end
|
||||||
|
next2 := i < points_len - 2 ? points[i + 2] : extended_end2
|
||||||
|
|
||||||
|
cur_frame := ctrl_rotations[i]
|
||||||
|
next_frame := ctrl_rotations[i + 1]
|
||||||
|
|
||||||
|
a, b, c, d := catmull_rom_coefs(
|
||||||
|
prev,
|
||||||
|
current,
|
||||||
|
next,
|
||||||
|
next2,
|
||||||
|
CATMULL_ROM_ALPHA,
|
||||||
|
CATMULL_ROM_TENSION,
|
||||||
|
)
|
||||||
|
|
||||||
|
v_dt := 1.0 / f32(SPLINE_SUBDIVS_V)
|
||||||
|
for v_index in 0 ..< SPLINE_SUBDIVS_V {
|
||||||
|
v_t := f32(v_index) * v_dt
|
||||||
|
out_point := &interpolated_points[i * SPLINE_SUBDIVS_V + v_index]
|
||||||
|
|
||||||
|
rotation := lg.quaternion_slerp(cur_frame, next_frame, v_t)
|
||||||
|
normal := lg.matrix3_from_quaternion(rotation)[1]
|
||||||
|
out_point.pos = catmull_rom(a, b, c, d, v_t)
|
||||||
|
out_point.normal = normal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interpolated_points[len(interpolated_points) - 1] =
|
||||||
|
interpolated_points[len(interpolated_points) - 2]
|
||||||
|
|
||||||
|
return interpolated_points
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_draw_spline :: proc(interpolated_points: []Interpolated_Point) {
|
||||||
|
rlgl.Begin(rlgl.LINES)
|
||||||
|
defer rlgl.End()
|
||||||
|
for i in 0 ..< len(interpolated_points) - 1 {
|
||||||
|
cur, next := interpolated_points[i], interpolated_points[i + 1]
|
||||||
|
|
||||||
|
tangent := lg.normalize0(next.pos - cur.pos)
|
||||||
|
normal := interpolated_points[i].normal
|
||||||
|
bitangent := lg.cross(tangent, normal)
|
||||||
|
|
||||||
|
rlgl.Color4ub(255, 255, 255, 255)
|
||||||
|
rlgl_vertex3v(cur.pos)
|
||||||
|
rlgl_vertex3v(next.pos)
|
||||||
|
|
||||||
|
rlgl.Color4ub(255, 0, 0, 255)
|
||||||
|
rlgl_vertex3v(cur.pos)
|
||||||
|
rlgl_vertex3v(cur.pos + tangent)
|
||||||
|
|
||||||
|
rlgl.Color4ub(0, 255, 0, 255)
|
||||||
|
rlgl_vertex3v(cur.pos)
|
||||||
|
rlgl_vertex3v(cur.pos + bitangent * ROAD_WIDTH)
|
||||||
|
|
||||||
|
rlgl.Color4ub(0, 0, 255, 255)
|
||||||
|
rlgl_vertex3v(cur.pos)
|
||||||
|
rlgl_vertex3v(cur.pos + normal)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug_draw_spline_mesh :: proc(interpolated_points: []Interpolated_Point) {
|
||||||
|
rlgl.Begin(rlgl.TRIANGLES)
|
||||||
|
defer rlgl.End()
|
||||||
|
|
||||||
|
for i in 0 ..< len(interpolated_points) - 1 {
|
||||||
|
cur, next := interpolated_points[i], interpolated_points[i + 1]
|
||||||
|
|
||||||
|
tangent := lg.normalize0(next.pos - cur.pos)
|
||||||
|
normal := interpolated_points[i].normal
|
||||||
|
bitangent := lg.normalize0(lg.cross(tangent, normal))
|
||||||
|
|
||||||
|
next_tangent: rl.Vector3
|
||||||
|
if i < len(interpolated_points) - 2 {
|
||||||
|
next2 := interpolated_points[i + 2]
|
||||||
|
next_tangent = next2.pos - next.pos
|
||||||
|
} else {
|
||||||
|
next_tangent = tangent
|
||||||
|
}
|
||||||
|
|
||||||
|
next_normal := interpolated_points[i + 1].normal
|
||||||
|
next_bitangent := lg.normalize0(lg.cross(next_tangent, next_normal))
|
||||||
|
|
||||||
|
u_dt := 1.0 / f32(SPLINE_SUBDIVS_U)
|
||||||
|
for u in 0 ..< SPLINE_SUBDIVS_U {
|
||||||
|
u_t := u_dt * f32(u)
|
||||||
|
u_t2 := u_t + u_dt
|
||||||
|
|
||||||
|
// [-1, 1]
|
||||||
|
u_t = u_t * 2 - 1
|
||||||
|
u_t2 = u_t2 * 2 - 1
|
||||||
|
u_t *= ROAD_WIDTH
|
||||||
|
u_t2 *= ROAD_WIDTH
|
||||||
|
|
||||||
|
p1 := cur.pos + bitangent * u_t
|
||||||
|
p2 := cur.pos + bitangent * u_t2
|
||||||
|
p3 := next.pos + next_bitangent * u_t
|
||||||
|
p4 := next.pos + next_bitangent * u_t2
|
||||||
|
|
||||||
|
rlgl_color3v(normal * 0.5 + 0.5)
|
||||||
|
rlgl_vertex3v(p1)
|
||||||
|
rlgl_vertex3v(p2)
|
||||||
|
rlgl_vertex3v(p3)
|
||||||
|
|
||||||
|
rlgl_color3v(next_normal * 0.5 + 0.5)
|
||||||
|
rlgl_vertex3v(p2)
|
||||||
|
rlgl_vertex3v(p4)
|
||||||
|
rlgl_vertex3v(p3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
3
ols.json
3
ols.json
@ -1,7 +1,8 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://raw.githubusercontent.com/DanielGavin/ols/master/misc/ols.schema.json",
|
"$schema": "https://raw.githubusercontent.com/DanielGavin/ols/master/misc/ols.schema.json",
|
||||||
"collections": [
|
"collections": [
|
||||||
{ "name": "common", "path": "./common" }
|
{ "name": "common", "path": "./common" },
|
||||||
|
{ "name": "game", "path": "./game" },
|
||||||
],
|
],
|
||||||
"enable_semantic_tokens": false,
|
"enable_semantic_tokens": false,
|
||||||
"enable_document_symbols": true,
|
"enable_document_symbols": true,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user