Basic lelel import working, collisions for level geo broken
This commit is contained in:
parent
a81e81c52c
commit
7da986970e
BIN
assets/blender/test_level_blend/Plane.glb
(Stored with Git LFS)
BIN
assets/blender/test_level_blend/Plane.glb
(Stored with Git LFS)
Binary file not shown.
@ -1,41 +1,41 @@
|
|||||||
(inst
|
(inst
|
||||||
:model "assets/blender/testblend_blend/Bakery.glb"
|
:model "assets/blender/testblend_blend/Bakery.glb"
|
||||||
:pos (0.000000 12.000000 0.000000)
|
:pos (0.000000 0.000000 12.000000)
|
||||||
:rot (0.000000 0.000000 0.000000 1.000000)
|
:rot (0.000000 0.000000 0.000000 1.000000)
|
||||||
:scale (1.000000 1.000000 1.000000))
|
:scale (1.000000 1.000000 1.000000))
|
||||||
(inst
|
(inst
|
||||||
:model "assets/blender/test_level_blend/Plane.glb"
|
:model "assets/blender/test_level_blend/Plane.glb"
|
||||||
:pos (0.000000 0.000000 0.000000)
|
:pos (0.000000 -1.000000 0.000000)
|
||||||
:rot (0.000000 0.000000 0.000000 1.000000)
|
:rot (0.000000 0.000000 0.000000 1.000000)
|
||||||
:scale (22.469545 22.469545 22.469545))
|
:scale (22.469545 22.469545 22.469545))
|
||||||
(inst
|
(inst
|
||||||
:model "assets/blender/testblend_blend/Fire_Station.glb"
|
:model "assets/blender/testblend_blend/Fire_Station.glb"
|
||||||
:pos (9.000000 13.000000 0.000000)
|
:pos (9.000000 0.000000 13.000000)
|
||||||
:rot (0.000000 0.000000 0.000000 1.000000)
|
:rot (0.000000 0.000000 0.000000 1.000000)
|
||||||
:scale (1.000000 1.000000 1.000000))
|
:scale (1.000000 1.000000 1.000000))
|
||||||
(inst
|
(inst
|
||||||
:model "assets/blender/testblend_blend/Gas_Station_Shop.glb"
|
:model "assets/blender/testblend_blend/Gas_Station_Shop.glb"
|
||||||
:pos (-8.000000 11.000000 0.000000)
|
:pos (-8.000000 0.000000 11.000000)
|
||||||
:rot (0.000000 0.000000 0.000000 1.000000)
|
:rot (0.000000 0.000000 0.000000 1.000000)
|
||||||
:scale (1.000000 1.000000 1.000000))
|
:scale (1.000000 1.000000 1.000000))
|
||||||
(inst
|
(inst
|
||||||
:model "assets/blender/testblend_blend/Gas_Station_Shop.glb"
|
:model "assets/blender/testblend_blend/Gas_Station_Shop.glb"
|
||||||
:pos (-16.000000 11.000000 0.000000)
|
:pos (-16.000000 0.000000 11.000000)
|
||||||
:rot (0.000000 0.000000 0.000000 1.000000)
|
:rot (0.000000 0.000000 0.000000 1.000000)
|
||||||
:scale (1.000000 1.000000 1.000000))
|
:scale (1.000000 1.000000 1.000000))
|
||||||
(inst
|
(inst
|
||||||
:model "assets/blender/testblend_blend/Gas_Station_Shop.glb"
|
:model "assets/blender/testblend_blend/Gas_Station_Shop.glb"
|
||||||
:pos (-15.559284 0.259853 1.609015)
|
:pos (-15.559284 1.609015 0.259853)
|
||||||
:rot (0.000000 0.000000 0.000000 1.000000)
|
:rot (0.000000 0.000000 0.000000 1.000000)
|
||||||
:scale (1.000000 1.000000 1.000000))
|
:scale (1.000000 1.000000 1.000000))
|
||||||
(inst
|
(inst
|
||||||
:model "assets/blender/testblend_blend/Green_House.glb"
|
:model "assets/blender/testblend_blend/Green_House.glb"
|
||||||
:pos (14.000000 -7.000000 0.000000)
|
:pos (14.000000 0.000000 -7.000000)
|
||||||
:rot (0.000000 0.000000 0.000000 1.000000)
|
:rot (0.000000 0.000000 0.000000 1.000000)
|
||||||
:scale (1.000000 1.000000 1.000000))
|
:scale (1.000000 1.000000 1.000000))
|
||||||
(inst
|
(inst
|
||||||
:model "assets/blender/testblend_blend/Hotel.glb"
|
:model "assets/blender/testblend_blend/Hotel.glb"
|
||||||
:pos (8.000000 -18.000000 0.000000)
|
:pos (8.000000 0.000000 -18.000000)
|
||||||
:rot (0.000000 0.000000 0.000000 1.000000)
|
:rot (0.000000 0.000000 0.000000 1.000000)
|
||||||
:scale (1.000000 1.000000 1.000000))
|
:scale (1.000000 1.000000 1.000000))
|
||||||
(inst
|
(inst
|
||||||
@ -43,8 +43,3 @@
|
|||||||
:pos (0.000000 0.000000 0.000000)
|
:pos (0.000000 0.000000 0.000000)
|
||||||
:rot (0.000000 0.000000 0.000000 1.000000)
|
:rot (0.000000 0.000000 0.000000 1.000000)
|
||||||
:scale (1.000000 1.000000 1.000000))
|
:scale (1.000000 1.000000 1.000000))
|
||||||
(inst
|
|
||||||
:model "assets/blender/ice_cream_truck_blend/Split.glb"
|
|
||||||
:pos (-1.000000 3.000000 0.000000)
|
|
||||||
:rot (0.000000 0.000000 0.000000 1.000000)
|
|
||||||
:scale (1.000000 1.000000 1.000000))
|
|
||||||
|
@ -70,7 +70,7 @@ for obj in visible_objects:
|
|||||||
instance_sexpr = (
|
instance_sexpr = (
|
||||||
'(inst'
|
'(inst'
|
||||||
f'\n\t:model "assets/{model_path}"'
|
f'\n\t:model "assets/{model_path}"'
|
||||||
f'\n\t:pos ({loc.x:.6f} {loc.y:.6f} {loc.z:.6f}) '
|
f'\n\t:pos ({loc.x:.6f} {loc.z:.6f} {loc.y:.6f})'
|
||||||
f'\n\t:rot ({rot.x:.6f} {rot.y:.6f} {rot.z:.6f} {rot.w:.6f})'
|
f'\n\t:rot ({rot.x:.6f} {rot.y:.6f} {rot.z:.6f} {rot.w:.6f})'
|
||||||
f'\n\t:scale ({scale.x:.6f} {scale.y:.6f} {scale.z:.6f}))'
|
f'\n\t:scale ({scale.x:.6f} {scale.y:.6f} {scale.z:.6f}))'
|
||||||
)
|
)
|
||||||
|
@ -4,6 +4,7 @@ import "common:name"
|
|||||||
import "core:container/intrusive/list"
|
import "core:container/intrusive/list"
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "core:io"
|
import "core:io"
|
||||||
|
import "core:strconv"
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
import "core:testing"
|
import "core:testing"
|
||||||
import "core:unicode"
|
import "core:unicode"
|
||||||
@ -151,7 +152,13 @@ parse_atom :: proc(ctx: ^SEXP_Parser) -> (atom: Atom, error: Error) {
|
|||||||
result := ctx.data[start:ctx.pos]
|
result := ctx.data[start:ctx.pos]
|
||||||
ctx.pos = next
|
ctx.pos = next
|
||||||
return result, nil
|
return result, nil
|
||||||
|
case '0' ..= '9', '-', '+':
|
||||||
|
value, n, ok := strconv.parse_f64_prefix(ctx.data[ctx.pos:])
|
||||||
|
if !ok {
|
||||||
|
return nil, make_error(ctx, "failed to parse number")
|
||||||
|
}
|
||||||
|
ctx.pos += n
|
||||||
|
return value, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, make_error(ctx, fmt.tprintf("unknown atom {}", c))
|
return nil, make_error(ctx, fmt.tprintf("unknown atom {}", c))
|
||||||
@ -233,6 +240,43 @@ iterator_next_checked :: proc(it: ^List_Iterator) -> Sexp {
|
|||||||
return node.expr
|
return node.expr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iterator_has_more :: proc(it: List_Iterator) -> bool {
|
||||||
|
return it.curr != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator_expect_list :: proc(it: ^List_Iterator) -> (Sexp_List, bool) {
|
||||||
|
next, ok := iterator_next(it)
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return {}, false
|
||||||
|
}
|
||||||
|
|
||||||
|
list_expr: Sexp_List
|
||||||
|
list_expr, ok = next.expr.(Sexp_List)
|
||||||
|
|
||||||
|
return list_expr, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator_expect_atom :: proc(it: ^List_Iterator, $T: typeid) -> (T, bool) {
|
||||||
|
next, ok := iterator_next(it)
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return {}, false
|
||||||
|
}
|
||||||
|
|
||||||
|
atom_expr: Atom
|
||||||
|
atom_expr, ok = next.expr.(Atom)
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return {}, false
|
||||||
|
}
|
||||||
|
|
||||||
|
result: T
|
||||||
|
result, ok = atom_expr.(T)
|
||||||
|
|
||||||
|
return result, ok
|
||||||
|
}
|
||||||
|
|
||||||
print_list :: proc(it: List_Iterator, w: io.Writer) -> io.Error {
|
print_list :: proc(it: List_Iterator, w: io.Writer) -> io.Error {
|
||||||
it := it
|
it := it
|
||||||
io.write_byte(w, '(') or_return
|
io.write_byte(w, '(') or_return
|
||||||
@ -402,6 +446,16 @@ print_pretty_error :: proc(w: io.Writer, data: string, error: Error) -> io.Error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prints pretty error to temp string
|
||||||
|
temp_pretty_error :: proc(data: string, error: Error) -> string {
|
||||||
|
builder: strings.Builder
|
||||||
|
strings.builder_init(&builder, context.temp_allocator)
|
||||||
|
|
||||||
|
writer := strings.to_writer(&builder)
|
||||||
|
print_pretty_error(writer, data, error)
|
||||||
|
return strings.to_string(builder)
|
||||||
|
}
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
test_parse :: proc(t: ^testing.T) {
|
test_parse :: proc(t: ^testing.T) {
|
||||||
ctx: SEXP_Parser
|
ctx: SEXP_Parser
|
||||||
|
@ -81,3 +81,7 @@ to_string :: proc(name: Name) -> string {
|
|||||||
sync.atomic_rw_mutex_shared_guard(&global_container.lock)
|
sync.atomic_rw_mutex_shared_guard(&global_container.lock)
|
||||||
return global_container.names_array[name]
|
return global_container.names_array[name]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
to_cstring :: proc(name: Name) -> cstring {
|
||||||
|
return strings.unsafe_string_to_cstring(to_string(name))
|
||||||
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package assets
|
package assets
|
||||||
|
|
||||||
|
import "common:encoding/sexp"
|
||||||
|
import "common:name"
|
||||||
import "core:log"
|
import "core:log"
|
||||||
import "core:math"
|
import "core:math"
|
||||||
import lg "core:math/linalg"
|
import lg "core:math/linalg"
|
||||||
@ -57,6 +59,18 @@ destroy_loaded_bvh :: proc(loaded_bvh: ^Loaded_BVH) {
|
|||||||
|
|
||||||
Curve_2D :: [][2]f32
|
Curve_2D :: [][2]f32
|
||||||
|
|
||||||
|
Scene_Instance :: struct {
|
||||||
|
model: name.Name,
|
||||||
|
// TODO: common format definitions
|
||||||
|
pos: rl.Vector3,
|
||||||
|
rot: rl.Quaternion,
|
||||||
|
scale: rl.Vector3,
|
||||||
|
}
|
||||||
|
|
||||||
|
Scene_Desc :: struct {
|
||||||
|
instances: []Scene_Instance,
|
||||||
|
}
|
||||||
|
|
||||||
Asset_Manager :: struct {
|
Asset_Manager :: struct {
|
||||||
textures: Asset_Cache(rl.Texture2D),
|
textures: Asset_Cache(rl.Texture2D),
|
||||||
models: Asset_Cache(rl.Model),
|
models: Asset_Cache(rl.Model),
|
||||||
@ -65,6 +79,7 @@ Asset_Manager :: struct {
|
|||||||
music: Asset_Cache(rl.Music),
|
music: Asset_Cache(rl.Music),
|
||||||
curves_1d: Asset_Cache([]f32),
|
curves_1d: Asset_Cache([]f32),
|
||||||
curves_2d: Asset_Cache(Curve_2D),
|
curves_2d: Asset_Cache(Curve_2D),
|
||||||
|
scenes: Asset_Cache(Scene_Desc),
|
||||||
bvhs: map[cstring]Loaded_BVH,
|
bvhs: map[cstring]Loaded_BVH,
|
||||||
curves: map[cstring]Loaded_Curve_2D,
|
curves: map[cstring]Loaded_Curve_2D,
|
||||||
}
|
}
|
||||||
@ -203,6 +218,104 @@ CURVE_2D_CSV_LOADER :: Asset_Cache_Loader(Curve_2D) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SCENE_DESC_LOADER :: Asset_Cache_Loader(Scene_Desc) {
|
||||||
|
load = proc(path: cstring, payload: Asset_Cache_Loader_Payload) -> (Scene_Desc, bool) {
|
||||||
|
data, err := physfs.read_entire_file(string(path), context.temp_allocator)
|
||||||
|
if err != nil {
|
||||||
|
log.errorf("Failed to read curve: %s, %v", path, err)
|
||||||
|
return {}, false
|
||||||
|
}
|
||||||
|
|
||||||
|
parser: sexp.SEXP_Parser
|
||||||
|
parser.data = string(data)
|
||||||
|
parsed, err2 := sexp.parse(&parser, context.temp_allocator)
|
||||||
|
|
||||||
|
if err2 != nil {
|
||||||
|
log.errorf(
|
||||||
|
"Failed to parse curve: %s\n%s",
|
||||||
|
path,
|
||||||
|
sexp.temp_pretty_error(parser.data, err2),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
inst_identifier := sexp.Ident(name.from_string("inst"))
|
||||||
|
|
||||||
|
num_instances: int
|
||||||
|
|
||||||
|
top_it := sexp.iterator_list(parsed)
|
||||||
|
for top_level_expr in sexp.iterator_next(&top_it) {
|
||||||
|
list_expr := top_level_expr.expr.(sexp.Sexp_List) or_continue
|
||||||
|
|
||||||
|
it := sexp.iterator_list(list_expr)
|
||||||
|
ident := sexp.iterator_expect_atom(&it, sexp.Ident) or_continue
|
||||||
|
|
||||||
|
if ident != inst_identifier {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
num_instances += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
instances := make([]Scene_Instance, num_instances)
|
||||||
|
num_instances = 0
|
||||||
|
|
||||||
|
top_it = sexp.iterator_list(parsed)
|
||||||
|
for top_level_expr in sexp.iterator_next(&top_it) {
|
||||||
|
list_expr := top_level_expr.expr.(sexp.Sexp_List) or_continue
|
||||||
|
|
||||||
|
it := sexp.iterator_list(list_expr)
|
||||||
|
ident := sexp.iterator_expect_atom(&it, sexp.Ident) or_continue
|
||||||
|
|
||||||
|
if ident != inst_identifier {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
inst: Scene_Instance
|
||||||
|
|
||||||
|
for sexp.iterator_has_more(it) {
|
||||||
|
key := sexp.iterator_expect_atom(&it, sexp.Tag) or_continue
|
||||||
|
|
||||||
|
switch name.Name(key) {
|
||||||
|
case name.from_string("model"):
|
||||||
|
model_path := sexp.iterator_expect_atom(&it, string) or_continue
|
||||||
|
inst.model = name.from_string(model_path)
|
||||||
|
case name.from_string("pos"):
|
||||||
|
pos_list := sexp.iterator_expect_list(&it) or_continue
|
||||||
|
pos_it := sexp.iterator_list(pos_list)
|
||||||
|
x := sexp.iterator_expect_atom(&pos_it, f64) or_continue
|
||||||
|
y := sexp.iterator_expect_atom(&pos_it, f64) or_continue
|
||||||
|
z := sexp.iterator_expect_atom(&pos_it, f64) or_continue
|
||||||
|
|
||||||
|
inst.pos = {f32(x), f32(y), f32(z)}
|
||||||
|
case name.from_string("rot"):
|
||||||
|
rot_list := sexp.iterator_expect_list(&it) or_continue
|
||||||
|
rot_it := sexp.iterator_list(rot_list)
|
||||||
|
inst.rot.x = f32(sexp.iterator_expect_atom(&rot_it, f64) or_continue)
|
||||||
|
inst.rot.y = f32(sexp.iterator_expect_atom(&rot_it, f64) or_continue)
|
||||||
|
inst.rot.z = f32(sexp.iterator_expect_atom(&rot_it, f64) or_continue)
|
||||||
|
inst.rot.w = f32(sexp.iterator_expect_atom(&rot_it, f64) or_continue)
|
||||||
|
case name.from_string("scale"):
|
||||||
|
scale_list := sexp.iterator_expect_list(&it) or_continue
|
||||||
|
scale_it := sexp.iterator_list(scale_list)
|
||||||
|
x := sexp.iterator_expect_atom(&scale_it, f64) or_continue
|
||||||
|
y := sexp.iterator_expect_atom(&scale_it, f64) or_continue
|
||||||
|
z := sexp.iterator_expect_atom(&scale_it, f64) or_continue
|
||||||
|
|
||||||
|
inst.scale = {f32(x), f32(y), f32(z)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
instances[num_instances] = inst
|
||||||
|
num_instances += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return Scene_Desc{instances = instances[:num_instances]}, true
|
||||||
|
},
|
||||||
|
unload = proc(scene_desc: Scene_Desc) {
|
||||||
|
delete(scene_desc.instances)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
assetman_init :: proc(assetman: ^Asset_Manager) {
|
assetman_init :: proc(assetman: ^Asset_Manager) {
|
||||||
assetman.models = {
|
assetman.models = {
|
||||||
loader = MODEL_LOADER,
|
loader = MODEL_LOADER,
|
||||||
@ -225,6 +338,9 @@ assetman_init :: proc(assetman: ^Asset_Manager) {
|
|||||||
assetman.curves_2d = {
|
assetman.curves_2d = {
|
||||||
loader = CURVE_2D_CSV_LOADER,
|
loader = CURVE_2D_CSV_LOADER,
|
||||||
}
|
}
|
||||||
|
assetman.scenes = {
|
||||||
|
loader = SCENE_DESC_LOADER,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Asset_Cache_Result :: enum {
|
Asset_Cache_Result :: enum {
|
||||||
@ -238,6 +354,7 @@ assetcache_fetch_or_load :: proc(
|
|||||||
ac: ^$T/Asset_Cache($E),
|
ac: ^$T/Asset_Cache($E),
|
||||||
path: cstring,
|
path: cstring,
|
||||||
payload: Asset_Cache_Loader_Payload = nil,
|
payload: Asset_Cache_Loader_Payload = nil,
|
||||||
|
force_no_reload := false,
|
||||||
) -> (
|
) -> (
|
||||||
value: E,
|
value: E,
|
||||||
modtime: physfs.sint64,
|
modtime: physfs.sint64,
|
||||||
@ -250,7 +367,7 @@ assetcache_fetch_or_load :: proc(
|
|||||||
if has_existing {
|
if has_existing {
|
||||||
new_modtime := physfs.getLastModTime(path)
|
new_modtime := physfs.getLastModTime(path)
|
||||||
|
|
||||||
if existing.modtime == new_modtime {
|
if force_no_reload || existing.modtime == new_modtime {
|
||||||
result = .Cached
|
result = .Cached
|
||||||
return existing.value, new_modtime, result
|
return existing.value, new_modtime, result
|
||||||
} else {
|
} else {
|
||||||
@ -408,7 +525,9 @@ get_bvh :: proc(assetman: ^Asset_Manager, path: cstring) -> (Loaded_BVH, bool) {
|
|||||||
copy(vertices[vert_count:], mesh_vertices)
|
copy(vertices[vert_count:], mesh_vertices)
|
||||||
|
|
||||||
for j in 0 ..< len(mesh_indices) {
|
for j in 0 ..< len(mesh_indices) {
|
||||||
indices[indices_count + j] = u16(vert_count) + mesh_indices[j]
|
index := vert_count + int(mesh_indices[j])
|
||||||
|
assert(index <= int(max(u16)))
|
||||||
|
indices[indices_count + j] = u16(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
vert_count += len(mesh_vertices)
|
vert_count += len(mesh_vertices)
|
||||||
@ -446,6 +565,20 @@ get_curve_2d :: proc(assetman: ^Asset_Manager, path: cstring) -> (curve: Curve_2
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reads a two column comma separated csv file as a curve
|
||||||
|
get_scene_desc :: proc(
|
||||||
|
assetman: ^Asset_Manager,
|
||||||
|
path: name.Name,
|
||||||
|
force_no_reload := false,
|
||||||
|
) -> (
|
||||||
|
scene: Scene_Desc,
|
||||||
|
reloaded: bool,
|
||||||
|
) {
|
||||||
|
res: Asset_Cache_Result
|
||||||
|
scene, _, res = assetcache_fetch_or_load(&assetman.scenes, name.to_cstring(path))
|
||||||
|
return scene, (res == .Loaded || res == .Reloaded)
|
||||||
|
}
|
||||||
|
|
||||||
get_convex :: proc(assetman: ^Asset_Manager, path: cstring) -> (result: Loaded_Convex) {
|
get_convex :: proc(assetman: ^Asset_Manager, path: cstring) -> (result: Loaded_Convex) {
|
||||||
bytes, err := physfs.read_entire_file(string(path), context.temp_allocator)
|
bytes, err := physfs.read_entire_file(string(path), context.temp_allocator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -852,6 +985,7 @@ shutdown :: proc(assetman: ^Asset_Manager) {
|
|||||||
assetcache_destroy(&assetman.music)
|
assetcache_destroy(&assetman.music)
|
||||||
assetcache_destroy(&assetman.curves_1d)
|
assetcache_destroy(&assetman.curves_1d)
|
||||||
assetcache_destroy(&assetman.curves_2d)
|
assetcache_destroy(&assetman.curves_2d)
|
||||||
|
assetcache_destroy(&assetman.scenes)
|
||||||
|
|
||||||
for _, &loaded_bvh in assetman.bvhs {
|
for _, &loaded_bvh in assetman.bvhs {
|
||||||
destroy_loaded_bvh(&loaded_bvh)
|
destroy_loaded_bvh(&loaded_bvh)
|
||||||
|
107
game/game.odin
107
game/game.odin
@ -17,7 +17,6 @@ package game
|
|||||||
import "assets"
|
import "assets"
|
||||||
import "common:name"
|
import "common:name"
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "core:hash"
|
|
||||||
import "core:log"
|
import "core:log"
|
||||||
import "core:math"
|
import "core:math"
|
||||||
import "core:math/linalg"
|
import "core:math/linalg"
|
||||||
@ -48,6 +47,65 @@ Debug_Draw_State :: struct {
|
|||||||
draw_physics_scene: bool,
|
draw_physics_scene: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Scene :: struct {
|
||||||
|
scene_desc_path: name.Name,
|
||||||
|
level_geoms: []physics.Level_Geom_Handle,
|
||||||
|
}
|
||||||
|
|
||||||
|
scene_destroy :: proc(world: ^World, scene: ^Scene) {
|
||||||
|
scene.scene_desc_path = name.NONE
|
||||||
|
sim_state := physics.get_sim_state(&world.physics_scene)
|
||||||
|
for handle in scene.level_geoms {
|
||||||
|
physics.remove_level_geom(sim_state, handle)
|
||||||
|
}
|
||||||
|
delete(scene.level_geoms)
|
||||||
|
scene.level_geoms = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
immediate_scene :: proc(world: ^World, scene: ^Scene, path: cstring) {
|
||||||
|
path_name := name.from_string(string(path))
|
||||||
|
|
||||||
|
desc, reloaded := assets.get_scene_desc(&g_mem.assetman, path_name)
|
||||||
|
|
||||||
|
if reloaded || scene.scene_desc_path != path_name {
|
||||||
|
scene_destroy(world, scene)
|
||||||
|
|
||||||
|
scene.scene_desc_path = path_name
|
||||||
|
|
||||||
|
sim_state := physics.get_sim_state(&world.physics_scene)
|
||||||
|
for inst in desc.instances {
|
||||||
|
physics.add_level_geom(
|
||||||
|
sim_state,
|
||||||
|
physics.Level_Geom_Config {
|
||||||
|
position = inst.pos,
|
||||||
|
rotation = inst.rot,
|
||||||
|
source = physics.Level_Geometry_Asset(name.to_string(inst.model)),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scene_copy :: proc(dst, src: ^Scene) {
|
||||||
|
dst.scene_desc_path = src.scene_desc_path
|
||||||
|
if len(dst.level_geoms) != len(src.level_geoms) {
|
||||||
|
delete(dst.level_geoms)
|
||||||
|
dst.level_geoms = make([]physics.Level_Geom_Handle, len(src.level_geoms))
|
||||||
|
}
|
||||||
|
copy(dst.level_geoms, src.level_geoms)
|
||||||
|
}
|
||||||
|
|
||||||
|
scene_draw :: proc(scene: ^Scene) {
|
||||||
|
desc, _ := assets.get_scene_desc(&g_mem.assetman, scene.scene_desc_path, true)
|
||||||
|
for geo in desc.instances {
|
||||||
|
render.draw_model(
|
||||||
|
assets.get_model(&g_mem.assetman, name.to_cstring(geo.model)),
|
||||||
|
{},
|
||||||
|
auto_cast linalg.matrix4_from_trs(geo.pos, geo.rot, geo.scale),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
World :: struct {
|
World :: struct {
|
||||||
player_pos: rl.Vector3,
|
player_pos: rl.Vector3,
|
||||||
track: Track,
|
track: Track,
|
||||||
@ -57,6 +115,7 @@ World :: struct {
|
|||||||
car_handle: physics.Body_Handle,
|
car_handle: physics.Body_Handle,
|
||||||
engine_handle: physics.Engine_Handle,
|
engine_handle: physics.Engine_Handle,
|
||||||
debug_state: Debug_Draw_State,
|
debug_state: Debug_Draw_State,
|
||||||
|
main_scene: Scene,
|
||||||
}
|
}
|
||||||
world_init :: proc(world: ^World) {
|
world_init :: proc(world: ^World) {
|
||||||
physics.scene_init(&world.physics_scene, &g_mem.assetman)
|
physics.scene_init(&world.physics_scene, &g_mem.assetman)
|
||||||
@ -64,6 +123,7 @@ world_init :: proc(world: ^World) {
|
|||||||
copy_world :: proc(dst, src: ^World) {
|
copy_world :: proc(dst, src: ^World) {
|
||||||
copy_track(&dst.track, &src.track)
|
copy_track(&dst.track, &src.track)
|
||||||
physics.copy_physics_scene(&dst.physics_scene, &src.physics_scene)
|
physics.copy_physics_scene(&dst.physics_scene, &src.physics_scene)
|
||||||
|
scene_copy(&dst.main_scene, &src.main_scene)
|
||||||
dst.player_pos = src.player_pos
|
dst.player_pos = src.player_pos
|
||||||
dst.pause = src.pause
|
dst.pause = src.pause
|
||||||
dst.car_com = src.car_com
|
dst.car_com = src.car_com
|
||||||
@ -73,6 +133,7 @@ copy_world :: proc(dst, src: ^World) {
|
|||||||
}
|
}
|
||||||
destroy_world :: proc(world: ^World) {
|
destroy_world :: proc(world: ^World) {
|
||||||
destroy_track(&world.track)
|
destroy_track(&world.track)
|
||||||
|
scene_destroy(world, &world.main_scene)
|
||||||
physics.scene_destroy(&world.physics_scene)
|
physics.scene_destroy(&world.physics_scene)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -699,46 +760,7 @@ update_world :: proc(world: ^World, dt: f32, config: World_Update_Config) {
|
|||||||
wheel.turn_angle = TURN_ANGLE * turn_vel_correction * turn_input
|
wheel.turn_angle = TURN_ANGLE * turn_vel_correction * turn_input
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
immediate_scene(world, &world.main_scene, "assets/blender/test_level_blend/Scene.scn")
|
||||||
physics.immediate_level_geom(
|
|
||||||
&world.physics_scene,
|
|
||||||
u32(name.from_string("level_geom_from_asset")),
|
|
||||||
{
|
|
||||||
position = physics.Vec3{5, 0, 0},
|
|
||||||
rotation = linalg.QUATERNIONF32_IDENTITY,
|
|
||||||
source = physics.Level_Geometry_Asset(
|
|
||||||
"assets/blender/test_level_blend/NurbsPath.glb",
|
|
||||||
),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
level_model := assets.get_model(&g_mem.assetman, "assets/testblend.glb")
|
|
||||||
|
|
||||||
for i in 0 ..< level_model.meshCount {
|
|
||||||
mesh := &level_model.meshes[i]
|
|
||||||
|
|
||||||
if mesh.triangleCount > 0 {
|
|
||||||
assert(mesh.vertexCount <= i32(max(u16)))
|
|
||||||
m := level_model.transform
|
|
||||||
pos := physics.Vec3{m[3][0], m[3][1], m[3][2]}
|
|
||||||
rotation := linalg.quaternion_from_matrix4_f32(auto_cast level_model.transform)
|
|
||||||
physics.immediate_level_geom(
|
|
||||||
&world.physics_scene,
|
|
||||||
hash.fnv32a(transmute([]byte)(fmt.tprintf("level mesh {}", i))),
|
|
||||||
{
|
|
||||||
position = pos,
|
|
||||||
rotation = rotation,
|
|
||||||
source = physics.Level_Geometry_Mesh {
|
|
||||||
vertices = (cast([^]rl.Vector3)mesh.vertices)[:mesh.vertexCount],
|
|
||||||
indices = mesh.indices[:mesh.triangleCount * 3],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(world.track.points) > 1 {
|
if len(world.track.points) > 1 {
|
||||||
interpolated_points := calculate_spline_interpolated_points(
|
interpolated_points := calculate_spline_interpolated_points(
|
||||||
@ -1094,7 +1116,6 @@ draw_world :: proc(world: ^World) {
|
|||||||
|
|
||||||
sim_state := physics.get_sim_state(&world.physics_scene)
|
sim_state := physics.get_sim_state(&world.physics_scene)
|
||||||
|
|
||||||
level_model := assets.get_model(&g_mem.assetman, "assets/testblend.glb")
|
|
||||||
car_model := assets.get_model(&g_mem.assetman, "assets/ice_cream_truck.glb")
|
car_model := assets.get_model(&g_mem.assetman, "assets/ice_cream_truck.glb")
|
||||||
|
|
||||||
phys_debug_state: physics.Debug_State
|
phys_debug_state: physics.Debug_State
|
||||||
@ -1183,7 +1204,7 @@ draw_world :: proc(world: ^World) {
|
|||||||
// .VEC3,
|
// .VEC3,
|
||||||
// )
|
// )
|
||||||
|
|
||||||
render.draw_model(level_model, {}, 1)
|
scene_draw(&world.main_scene)
|
||||||
|
|
||||||
render.draw_model(car_model, {}, car_matrix)
|
render.draw_model(car_model, {}, car_matrix)
|
||||||
|
|
||||||
|
@ -967,6 +967,7 @@ get_level_geom_data :: proc(
|
|||||||
)
|
)
|
||||||
if reloaded {
|
if reloaded {
|
||||||
level_geom.aabb = bvh_aabb_to_phys_aabb(loaded_bvh.aabb)
|
level_geom.aabb = bvh_aabb_to_phys_aabb(loaded_bvh.aabb)
|
||||||
|
level_geom.aabb = aabb_transform(level_geom.aabb, level_geom.x, level_geom.q)
|
||||||
}
|
}
|
||||||
vertices = loaded_bvh.vertices
|
vertices = loaded_bvh.vertices
|
||||||
indices = loaded_bvh.indices
|
indices = loaded_bvh.indices
|
||||||
@ -989,6 +990,7 @@ get_level_geom_blas :: proc(sim_state: ^Sim_State, handle: Level_Geom_Handle) ->
|
|||||||
)
|
)
|
||||||
if reloaded {
|
if reloaded {
|
||||||
level_geom.aabb = bvh_aabb_to_phys_aabb(loaded_bvh.aabb)
|
level_geom.aabb = bvh_aabb_to_phys_aabb(loaded_bvh.aabb)
|
||||||
|
level_geom.aabb = aabb_transform(level_geom.aabb, level_geom.x, level_geom.q)
|
||||||
}
|
}
|
||||||
|
|
||||||
bvh = loaded_bvh.bvh
|
bvh = loaded_bvh.bvh
|
||||||
@ -1074,6 +1076,8 @@ add_level_geom :: proc(sim_state: ^Sim_State, config: Level_Geom_Config) -> Leve
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
level_geom.aabb = aabb_transform(level_geom.aabb, level_geom.x, level_geom.q)
|
||||||
|
|
||||||
if sim_state.first_free_level_geom_plus_one > 0 {
|
if sim_state.first_free_level_geom_plus_one > 0 {
|
||||||
index := sim_state.first_free_level_geom_plus_one
|
index := sim_state.first_free_level_geom_plus_one
|
||||||
new_level_geom := get_level_geom(sim_state, Level_Geom_Handle(index))
|
new_level_geom := get_level_geom(sim_state, Level_Geom_Handle(index))
|
||||||
|
@ -200,6 +200,7 @@ raycasts_level :: proc(
|
|||||||
level_geom_handle := index_to_level_geom(
|
level_geom_handle := index_to_level_geom(
|
||||||
int(tlas.bvh_tree.primitives[leaf_node.child_or_prim_start + j]),
|
int(tlas.bvh_tree.primitives[leaf_node.child_or_prim_start + j]),
|
||||||
)
|
)
|
||||||
|
level_geom := get_level_geom(sim_state, level_geom_handle)
|
||||||
blas := get_level_geom_blas(sim_state, level_geom_handle)
|
blas := get_level_geom_blas(sim_state, level_geom_handle)
|
||||||
vertices, indices := get_level_geom_data(sim_state, level_geom_handle)
|
vertices, indices := get_level_geom_data(sim_state, level_geom_handle)
|
||||||
|
|
||||||
@ -210,7 +211,13 @@ raycasts_level :: proc(
|
|||||||
for k in 0 ..< blas_leaf_node.prim_len {
|
for k in 0 ..< blas_leaf_node.prim_len {
|
||||||
tri_idx := int(blas.primitives[blas_leaf_node.child_or_prim_start + k])
|
tri_idx := int(blas.primitives[blas_leaf_node.child_or_prim_start + k])
|
||||||
|
|
||||||
tri := get_triangle(vertices, indices, tri_idx)
|
tri := get_transformed_triangle(
|
||||||
|
vertices,
|
||||||
|
indices,
|
||||||
|
tri_idx,
|
||||||
|
level_geom.x,
|
||||||
|
level_geom.q,
|
||||||
|
)
|
||||||
|
|
||||||
hit_t, tmp_normal, _, ok := collision.intersect_ray_triangle(
|
hit_t, tmp_normal, _, ok := collision.intersect_ray_triangle(
|
||||||
{origin, origin + dir},
|
{origin, origin + dir},
|
||||||
@ -392,7 +399,13 @@ remove_invalid_contacts :: proc(
|
|||||||
|
|
||||||
if !should_remove {
|
if !should_remove {
|
||||||
aabb_a := dyn_tlas.body_aabbs[body_handle_to_index(contact.a)]
|
aabb_a := dyn_tlas.body_aabbs[body_handle_to_index(contact.a)]
|
||||||
tri := get_triangle(vertices, indices, tri_idx)
|
tri := get_transformed_triangle(
|
||||||
|
vertices,
|
||||||
|
indices,
|
||||||
|
tri_idx,
|
||||||
|
level_geom.x,
|
||||||
|
level_geom.q,
|
||||||
|
)
|
||||||
aabb_b := get_triangle_aabb(tri)
|
aabb_b := get_triangle_aabb(tri)
|
||||||
|
|
||||||
should_remove |= !bvh.test_aabb_vs_aabb(aabb_a, aabb_b)
|
should_remove |= !bvh.test_aabb_vs_aabb(aabb_a, aabb_b)
|
||||||
@ -555,7 +568,13 @@ find_new_contacts :: proc(
|
|||||||
tri_idx := int(
|
tri_idx := int(
|
||||||
blas.primitives[blas_leaf_node.child_or_prim_start + k],
|
blas.primitives[blas_leaf_node.child_or_prim_start + k],
|
||||||
)
|
)
|
||||||
tri := get_triangle(vertices, indices, tri_idx)
|
tri := get_transformed_triangle(
|
||||||
|
vertices,
|
||||||
|
indices,
|
||||||
|
tri_idx,
|
||||||
|
level_geom.x,
|
||||||
|
level_geom.q,
|
||||||
|
)
|
||||||
prim_aabb := get_triangle_aabb(tri)
|
prim_aabb := get_triangle_aabb(tri)
|
||||||
|
|
||||||
if bvh.test_aabb_vs_aabb(body_aabb, prim_aabb) {
|
if bvh.test_aabb_vs_aabb(body_aabb, prim_aabb) {
|
||||||
@ -804,8 +823,15 @@ update_contacts :: proc(sim_state: ^Sim_State, static_tlas: ^Static_TLAS) {
|
|||||||
)
|
)
|
||||||
case .Body_vs_Level:
|
case .Body_vs_Level:
|
||||||
level_geom_handle := Level_Geom_Handle(contact.b)
|
level_geom_handle := Level_Geom_Handle(contact.b)
|
||||||
|
level_geom := get_level_geom(sim_state, level_geom_handle)
|
||||||
vertices, indices := get_level_geom_data(sim_state, level_geom_handle)
|
vertices, indices := get_level_geom_data(sim_state, level_geom_handle)
|
||||||
tri := get_triangle(vertices, indices, int(contact.local_tri_idx))
|
tri := get_transformed_triangle(
|
||||||
|
vertices,
|
||||||
|
indices,
|
||||||
|
int(contact.local_tri_idx),
|
||||||
|
level_geom.x,
|
||||||
|
level_geom.q,
|
||||||
|
)
|
||||||
|
|
||||||
m2 = collision.double_sided_triangle_to_convex(tri, context.temp_allocator)
|
m2 = collision.double_sided_triangle_to_convex(tri, context.temp_allocator)
|
||||||
}
|
}
|
||||||
|
BIN
src_assets/test_level.blend
(Stored with Git LFS)
BIN
src_assets/test_level.blend
(Stored with Git LFS)
Binary file not shown.
BIN
src_assets/test_level.blend1
(Stored with Git LFS)
BIN
src_assets/test_level.blend1
(Stored with Git LFS)
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user