From: hgn Date: Tue, 25 Oct 2022 02:30:41 +0000 (+0100) Subject: well yeah i guess X-Git-Url: https://harrygodden.com/git/?a=commitdiff_plain;h=47941822dae18a018c985847b052e70214a3ccc6;hp=4f96bd0040e35ecb21d353ee2b895129682d22c1;p=carveJwlIkooP6JGAAIwe30JlM.git well yeah i guess --- diff --git a/audio.h b/audio.h index fd21286..34ebb3a 100644 --- a/audio.h +++ b/audio.h @@ -16,69 +16,68 @@ static int k_audio_debug_soundscape = 0; audio_clip audio_board[] = { - {.path="sound/skate.ogg", .source_mode=k_audio_source_compressed }, - {.path="sound/wheel.ogg", .source_mode=k_audio_source_compressed }, - {.path="sound/slide.ogg", .source_mode=k_audio_source_compressed }, - {.path="sound/reverb.ogg",.source_mode=k_audio_source_compressed } + { .path="sound/skate.ogg" }, + { .path="sound/wheel.ogg" }, + { .path="sound/slide.ogg" }, + { .path="sound/reverb.ogg" } }; audio_clip audio_splash = -{ .path = "sound/splash.ogg", .source_mode=k_audio_source_compressed }; +{ .path = "sound/splash.ogg" }; audio_clip audio_jumps[] = { - { .path = "sound/jump0.ogg", .source_mode=k_audio_source_compressed, }, - { .path = "sound/jump1.ogg", .source_mode=k_audio_source_compressed, }, + { .path = "sound/jump0.ogg" }, + { .path = "sound/jump1.ogg" }, }; audio_clip audio_footsteps[] = { - {.path = "sound/step_concrete0.ogg", .source_mode=k_audio_source_compressed,}, - {.path = "sound/step_concrete1.ogg", .source_mode=k_audio_source_compressed,}, - {.path = "sound/step_concrete2.ogg", .source_mode=k_audio_source_compressed,}, - {.path = "sound/step_concrete3.ogg", .source_mode=k_audio_source_compressed,} + {.path = "sound/step_concrete0.ogg" }, + {.path = "sound/step_concrete1.ogg" }, + {.path = "sound/step_concrete2.ogg" }, + {.path = "sound/step_concrete3.ogg" } }; audio_clip audio_lands[] = { - { .path = "sound/land0.ogg", .source_mode=k_audio_source_compressed }, - { .path = "sound/land1.ogg", .source_mode=k_audio_source_compressed }, - { .path = "sound/land2.ogg", .source_mode=k_audio_source_compressed }, - { .path = "sound/landsk0.ogg", .source_mode=k_audio_source_compressed }, - { .path = "sound/landsk1.ogg", .source_mode=k_audio_source_compressed }, - { .path = "sound/onto.ogg", .source_mode=k_audio_source_compressed }, - { .path = "sound/outo.ogg", .source_mode=k_audio_source_compressed }, + { .path = "sound/land0.ogg" }, + { .path = "sound/land1.ogg" }, + { .path = "sound/land2.ogg" }, + { .path = "sound/landsk0.ogg" }, + { .path = "sound/landsk1.ogg" }, + { .path = "sound/onto.ogg" }, + { .path = "sound/outo.ogg" }, }; audio_clip audio_water[] = { - { .path = "sound/wave0.ogg", .source_mode=k_audio_source_compressed }, - { .path = "sound/wave1.ogg", .source_mode=k_audio_source_compressed }, - { .path = "sound/wave2.ogg", .source_mode=k_audio_source_compressed }, - { .path = "sound/wave3.ogg", .source_mode=k_audio_source_compressed }, - { .path = "sound/wave4.ogg", .source_mode=k_audio_source_compressed }, - { .path = "sound/wave5.ogg", .source_mode=k_audio_source_compressed } + { .path = "sound/wave0.ogg" }, + { .path = "sound/wave1.ogg" }, + { .path = "sound/wave2.ogg" }, + { .path = "sound/wave3.ogg" }, + { .path = "sound/wave4.ogg" }, + { .path = "sound/wave5.ogg" } }; audio_clip audio_grass[] = { - { .path = "sound/grass0.ogg", .source_mode=k_audio_source_compressed }, - { .path = "sound/grass1.ogg", .source_mode=k_audio_source_compressed }, - { .path = "sound/grass2.ogg", .source_mode=k_audio_source_compressed }, - { .path = "sound/grass3.ogg", .source_mode=k_audio_source_compressed }, + { .path = "sound/grass0.ogg" }, + { .path = "sound/grass1.ogg" }, + { .path = "sound/grass2.ogg" }, + { .path = "sound/grass3.ogg" }, }; audio_clip audio_ambience[] = { - {.path="sound/town_generic.ogg", - .source_mode=k_audio_source_compressed } + { .path="sound/town_generic.ogg" } }; audio_clip audio_gate_pass = { - .path = "sound/gate_pass.ogg", .source_mode=k_audio_source_compressed + .path = "sound/gate_pass.ogg" }; audio_clip audio_gate_lap = { - .path = "sound/gate_lap.ogg", .source_mode=k_audio_source_compressed + .path = "sound/gate_lap.ogg" }; audio_clip audio_gate_ambient = { -.path = "sound/gate_ambient.ogg", .source_mode=k_audio_source_compressed +.path = "sound/gate_ambient.ogg" }; audio_player ambient_player = @@ -92,16 +91,16 @@ audio_player audio_rewind_player = }; audio_clip audio_rewind[] = { -{ .path = "sound/rewind_start.ogg", .source_mode=k_audio_source_compressed }, -{ .path = "sound/rewind_end_1.5.ogg", .source_mode=k_audio_source_compressed}, -{ .path = "sound/rewind_end_2.5.ogg", .source_mode=k_audio_source_compressed }, -{ .path = "sound/rewind_end_6.5.ogg", .source_mode=k_audio_source_compressed }, -{ .path = "sound/rewind_clack.ogg", .source_mode=k_audio_source_compressed }, +{ .path = "sound/rewind_start.ogg" }, +{ .path = "sound/rewind_end_1.5.ogg" }, +{ .path = "sound/rewind_end_2.5.ogg" }, +{ .path = "sound/rewind_end_6.5.ogg" }, +{ .path = "sound/rewind_clack.ogg" }, }; audio_clip audio_ui[] = { - { .path = "sound/ui_click.ogg", .source_mode=k_audio_source_compressed }, - { .path = "sound/ui_ding.ogg", .source_mode=k_audio_source_compressed }, + { .path = "sound/ui_click.ogg" }, + { .path = "sound/ui_ding.ogg" }, }; audio_player ambient_sprites[4] = @@ -322,13 +321,13 @@ static void audio_debug_soundscapes(void) char buf[64]; snprintf( buf, 31, "occlusion: %.5f", audio_occlusion_current ); - ui_global_ctx.cursor[0] = 450; - ui_global_ctx.cursor[1] = 10; - ui_global_ctx.cursor[2] = audio_occlusion_current * 200.0f; - ui_global_ctx.cursor[3] = 20; + vg_uictx.cursor[0] = 450; + vg_uictx.cursor[1] = 10; + vg_uictx.cursor[2] = audio_occlusion_current * 200.0f; + vg_uictx.cursor[3] = 20; - gui_fill_rect( ui_global_ctx.cursor, 0x55cccccc ); - gui_text( ui_global_ctx.cursor, buf, 1, 0 ); + ui_fill_rect( vg_uictx.cursor, 0x55cccccc ); + ui_text( vg_uictx.cursor, buf, 1, 0 ); } #endif /* AUDIO_H */ diff --git a/blender_export.py b/blender_export.py index c069d7f..2ed183a 100644 --- a/blender_export.py +++ b/blender_export.py @@ -47,6 +47,7 @@ class mdl_node(Structure): _fields_ = [("co",c_float*3), ( "q",c_float*4), ( "s",c_float*3), + ("sub_uid",c_uint32), # dont use ("submesh_start",c_uint32), ("submesh_count",c_uint32), ("classtype",c_uint32), @@ -59,6 +60,8 @@ class mdl_header(Structure): _fields_ = [("identifier",c_uint32), ("version",c_uint32), ("file_length",c_uint32), + ("pad0",c_uint32), + ("vertex_count",c_uint32), ("vertex_offset",c_uint32), @@ -76,11 +79,16 @@ class mdl_header(Structure): ("anim_count",c_uint32), ("anim_offset",c_uint32), - + + ("strings_length",c_uint32), ("strings_offset",c_uint32), + + ("entdata_length",c_uint32), ("entdata_offset",c_uint32), - ("animdata_offset",c_uint32) - ] + + ("keyframe_count",c_uint32), + ("keyframe_offset",c_uint32)] + class mdl_animation(Structure): _pack_ = 1 @@ -187,6 +195,10 @@ def write_model(collection_name): header.node_count = 0 header.material_count = 0 header.file_length = 0 + + header.strings_length = 0 + header.entdata_length = 0 + header.keyframe_count = 0 mesh_cache = {} string_cache = {} @@ -200,10 +212,8 @@ def write_model(collection_name): indice_buffer = [] node_buffer = [] entdata_buffer = [] - entdata_length = 0 anim_buffer = [] - animdata_length = 0 animdata_buffer = [] def emplace_string( s ): @@ -596,7 +606,7 @@ def write_model(collection_name): # Process entity data # ================================================================== - node.offset = entdata_length + node.offset = header.entdata_length if classtype != 'k_classtype_none': disptype = classtype @@ -629,7 +639,7 @@ def write_model(collection_name): node.classtype = 12 armature = armature_def['obj'] - entdata_length += sizeof( classtype_skin ) + header.entdata_length += sizeof( classtype_skin ) skin = classtype_skin() skin.skeleton = armature.cv_data.uid @@ -637,7 +647,7 @@ def write_model(collection_name): elif classtype == 'k_classtype_skeleton': node.classtype = 11 - entdata_length += sizeof( classtype_skeleton ) + header.entdata_length += sizeof( classtype_skeleton ) skeleton = classtype_skeleton() armature_def = graph_lookup[obj] @@ -669,7 +679,7 @@ def write_model(collection_name): anim = mdl_animation() anim.pstr_name = emplace_string( NLAStrip.action.name ) anim.rate = 30.0 - anim.offset = animdata_length + anim.offset = header.keyframe_count anim.length = anim_end-anim_start # Export the fucking keyframes @@ -723,7 +733,7 @@ def write_model(collection_name): kf.s[2] = sca[1] animdata_buffer += [kf] - animdata_length += sizeof(mdl_keyframe) + header.keyframe_count += 1 break anim_buffer += [anim] @@ -739,7 +749,7 @@ def write_model(collection_name): elif classtype == 'k_classtype_bone': node.classtype = 10 - entdata_length += sizeof( classtype_bone ) + header.entdata_length += sizeof( classtype_bone ) bone = classtype_bone() bone.deform = node_def['deform'] @@ -789,7 +799,7 @@ def write_model(collection_name): elif classtype == 'k_classtype_gate': node.classtype = 1 - entdata_length += sizeof( classtype_gate ) + header.entdata_length += sizeof( classtype_gate ) gate = classtype_gate() gate.target = 0 @@ -809,7 +819,7 @@ def write_model(collection_name): elif classtype == 'k_classtype_block': node.classtype = 2 - entdata_length += sizeof( classtype_block ) + header.entdata_length += sizeof( classtype_block ) source = obj.data.cv_data @@ -826,7 +836,7 @@ def write_model(collection_name): elif classtype == 'k_classtype_achievement_box': node.classtype = 13 - entdata_length += sizeof( classtype_achievement_box ) + header.entdata_length += sizeof( classtype_achievement_box ) ach = classtype_achievement_box() ach.pstr_name = emplace_string( obj.cv_data.strp ) ach.trigger = 0 @@ -839,7 +849,7 @@ def write_model(collection_name): elif classtype == 'k_classtype_audio': node.classtype = 14 - entdata_length += sizeof( classtype_audio ) + header.entdata_length += sizeof( classtype_audio ) aud = classtype_audio() aud.pstr_file = emplace_string( obj.cv_data.strp ) aud.flags = obj.cv_data.intp @@ -855,7 +865,7 @@ def write_model(collection_name): elif classtype == 'k_classtype_car_path': node.classtype = 5 - entdata_length += sizeof( classtype_car_path ) + header.entdata_length += sizeof( classtype_car_path ) pn = classtype_car_path() pn.target = 0 @@ -872,7 +882,7 @@ def write_model(collection_name): target = obj.instance_collection node.classtype = 6 - entdata_length += sizeof( classtype_instance ) + header.entdata_length += sizeof( classtype_instance ) inst = classtype_instance() inst.pstr_file = emplace_string( F"models/{target.name}.mdl" ) @@ -883,7 +893,7 @@ def write_model(collection_name): elif classtype == 'k_classtype_route_node': node.classtype = 8 - entdata_length += sizeof( classtype_route_node ) + header.entdata_length += sizeof( classtype_route_node ) rn = classtype_route_node() if obj.cv_data.target != None: @@ -895,7 +905,7 @@ def write_model(collection_name): elif classtype == 'k_classtype_route': node.classtype = 9 - entdata_length += sizeof( classtype_route ) + header.entdata_length += sizeof( classtype_route ) r = classtype_route() r.colour[0] = obj.cv_data.colour[0] r.colour[1] = obj.cv_data.colour[1] @@ -914,8 +924,7 @@ def write_model(collection_name): node_buffer += [node] # Write data arrays - # - header.anim_count = len(anim_buffer) + # TODO: 8 BYTE ALIGNMENT print( "Writing data" ) fpos = sizeof(header) @@ -932,13 +941,24 @@ def write_model(collection_name): header.material_offset = fpos fpos += sizeof(mdl_material)*header.material_count - print( F"Animation count: {header.anim_count}" ) + print( F"Animation count: {len(anim_buffer)}" ) + header.anim_count = len(anim_buffer) header.anim_offset = fpos fpos += sizeof(mdl_animation)*header.anim_count - print( F"Entdata length: {entdata_length}" ) + print( F"Entdata length: {header.entdata_length}" ) header.entdata_offset = fpos - fpos += entdata_length + fpos += header.entdata_length + + print( F"Strings length: {len(strings_buffer)}" ) + header.strings_offset = fpos + header.strings_length = len(strings_buffer) + fpos += header.strings_length + + # Optional array things + print( F"Keyframe count: {header.keyframe_count}" ) + header.keyframe_offset = fpos + fpos += sizeof(mdl_keyframe)*header.keyframe_count print( F"Vertex count: {header.vertex_count}" ) header.vertex_offset = fpos @@ -948,14 +968,6 @@ def write_model(collection_name): header.indice_offset = fpos fpos += sizeof(c_uint32)*header.indice_count - print( F"Keyframe count: {animdata_length}" ) - header.animdata_offset = fpos - fpos += animdata_length - - print( F"Strings length: {len(strings_buffer)}" ) - header.strings_offset = fpos - fpos += len(strings_buffer) - header.file_length = fpos path = F"/home/harry/Documents/carve/models_src/{collection_name}.mdl" @@ -973,14 +985,17 @@ def write_model(collection_name): fp.write( bytearray(a) ) for ed in entdata_buffer: fp.write( bytearray(ed) ) + + fp.write( strings_buffer ) + + for kf in animdata_buffer: + fp.write( bytearray(kf) ) + for v in vertex_buffer: fp.write( bytearray(v) ) for i in indice_buffer: fp.write( bytearray(i) ) - for kf in animdata_buffer: - fp.write( bytearray(kf) ) - fp.write( strings_buffer ) fp.close() print( F"Completed {collection_name}.mdl" ) diff --git a/build.sh b/build.sh index 8920806..fad6201 100755 --- a/build.sh +++ b/build.sh @@ -23,7 +23,7 @@ _windows_asan="" _windows_linksteam="vg/dep/steam/steam_api.dll" _windows_folder="bin/win32" -_options_debugmode="-O0 -ggdb3 -fno-omit-frame-pointer" +_options_debugmode="-O0 -ggdb3 -fno-omit-frame-pointer -rdynamic" _options_release="-O3 -DVG_RELEASE" # Compiler lines @@ -228,6 +228,11 @@ vg_command(){ test) run_game ;; + gdb) + cd $_linux_folder + gdb -tui ./skaterift + cd ./../ + ;; testserver) run_server ;; diff --git a/bvh.h b/bvh.h index c18bb30..9fdbe98 100644 --- a/bvh.h +++ b/bvh.h @@ -18,30 +18,30 @@ * system: the system we created above which will deal with the data * * call bh_create( bh_tree *bh, u32 item_count ) - * static int bh_ray( bh_tree *bh, u32 inode, v3f co, v3f dir, ray_hit *hit ) - * static int bh_select( bh_tree *bh, boxf box, u32 *buffer, int len ) + * VG_STATIC int bh_ray( bh_tree *bh, u32 inode, v3f co, v3f dir, ray_hit *hit ) + * VG_STATIC int bh_select( bh_tree *bh, boxf box, u32 *buffer, int len ) */ typedef struct bh_node bh_node; typedef struct bh_tree bh_tree; typedef struct bh_system bh_system; -struct bh_node -{ - boxf bbx; - - /* if il is 0, this is a leaf */ - u32 il, count; - union{ u32 ir, start; }; -}; - struct bh_tree { - bh_node *nodes; u32 node_count; bh_system *system; void *user; + + struct bh_node + { + boxf bbx; + + /* if il is 0, this is a leaf */ + u32 il, count; + union{ u32 ir, start; }; + } + nodes[]; }; struct bh_system @@ -61,7 +61,7 @@ struct bh_system int (*cast_ray)( void *user, u32 index, v3f co, v3f dir, ray_hit *hit ); }; -static void bh_update_bounds( bh_tree *bh, u32 inode ) +VG_STATIC void bh_update_bounds( bh_tree *bh, u32 inode ) { bh_node *node = &bh->nodes[ inode ]; @@ -73,7 +73,7 @@ static void bh_update_bounds( bh_tree *bh, u32 inode ) } } -static void bh_subdivide( bh_tree *bh, u32 inode ) +VG_STATIC void bh_subdivide( bh_tree *bh, u32 inode ) { bh_node *node = &bh->nodes[ inode ]; @@ -128,18 +128,19 @@ static void bh_subdivide( bh_tree *bh, u32 inode ) node->ir = ir; node->count = 0; - /* TODO: Implement max depth, or stack */ bh_update_bounds( bh, il ); bh_update_bounds( bh, ir ); bh_subdivide( bh, il ); bh_subdivide( bh, ir ); } -static void bh_create( bh_tree *bh, bh_system *sys, void *user, u32 item_count ) +VG_STATIC bh_tree *bh_create( void *lin_alloc, bh_system *system, + void *user, u32 item_count ) { - bh->system = sys; + u32 totsize = sizeof(bh_tree) + sizeof(bh_node)*(item_count*2-1); + bh_tree *bh = vg_linear_alloc( lin_alloc, totsize ); + bh->system = system; bh->user = user; - bh->nodes = vg_alloc( sizeof(bh_node) * (item_count*2-1) ); bh_node *root = &bh->nodes[0]; bh->node_count = 1; @@ -152,20 +153,14 @@ static void bh_create( bh_tree *bh, bh_system *sys, void *user, u32 item_count ) bh_update_bounds( bh, 0 ); bh_subdivide( bh, 0 ); - bh->nodes = vg_realloc( bh->nodes, sizeof(bh_node) * bh->node_count ); - vg_success( "BVH done, size: %u/%u\n", bh->node_count, (item_count*2-1) ); - -#if 0 - vg_fatal_exit_loop( "Test crash from loader" ); -#endif -} + totsize = sizeof(bh_tree) + sizeof(bh_node) * bh->node_count; + bh = vg_linear_resize( lin_alloc, bh, totsize ); -static void bh_free( bh_tree *bh ) -{ - vg_free( bh->nodes ); + vg_success( "BVH done, size: %u/%u\n", bh->node_count, (item_count*2-1) ); + return bh; } -static void bh_debug_node( bh_tree *bh, u32 inode, v3f pos, u32 colour ) +VG_STATIC void bh_debug_node( bh_tree *bh, u32 inode, v3f pos, u32 colour ) { bh_node *node = &bh->nodes[ inode ]; @@ -195,7 +190,7 @@ static void bh_debug_node( bh_tree *bh, u32 inode, v3f pos, u32 colour ) } } -static int bh_ray( bh_tree *bh, u32 inode, v3f co, v3f dir, ray_hit *hit ) +VG_STATIC int bh_ray( bh_tree *bh, v3f co, v3f dir, ray_hit *hit ) { int count = 0; u32 stack[100]; @@ -246,7 +241,7 @@ static int bh_ray( bh_tree *bh, u32 inode, v3f co, v3f dir, ray_hit *hit ) return count; } -static int bh_select( bh_tree *bh, boxf box, u32 *buffer, int len ) +VG_STATIC int bh_select( bh_tree *bh, boxf box, u32 *buffer, int len ) { int count = 0; u32 stack[100]; diff --git a/camera.h b/camera.h index 07205de..1c265a7 100644 --- a/camera.h +++ b/camera.h @@ -3,13 +3,13 @@ #include "common.h" -static v2f camera_angles; -static v3f camera_pos; +VG_STATIC v2f camera_angles; +VG_STATIC v3f camera_pos; -static m4x3f camera_mtx, - camera_mtx_inverse; +VG_STATIC m4x3f camera_mtx, + camera_mtx_inverse; -static void camera_update(void) +VG_STATIC void camera_update(void) { /* Update camera matrices */ v4f qyaw, qpitch, qcam; diff --git a/common.h b/common.h index 0890ac4..fa6df75 100644 --- a/common.h +++ b/common.h @@ -21,9 +21,9 @@ struct ray_hit v3f pos, normal; }; -static int network_scores_updated = 0; +VG_STATIC int network_scores_updated = 0; -static u32 utf8_byte0_byte_count( u8 char0 ) +VG_STATIC u32 utf8_byte0_byte_count( u8 char0 ) { for( u32 k=2; k<4; k++ ) { @@ -34,7 +34,7 @@ static u32 utf8_byte0_byte_count( u8 char0 ) return 0; } -static void str_utf8_collapse( const char *str, char *buf, u32 length ) +VG_STATIC void str_utf8_collapse( const char *str, char *buf, u32 length ) { u8 *ustr = (u8 *)str; u32 utf32_code = 0x00000000; diff --git a/highscores.h b/highscores.h index f19f93a..f2c5eab 100644 --- a/highscores.h +++ b/highscores.h @@ -80,7 +80,7 @@ struct highscore_database #pragma pack(pop) -static struct highscore_system +VG_STATIC struct highscore_system { highscore_database dbheader; aatree aainfo, @@ -91,19 +91,20 @@ static struct highscore_system aainfo_playerinfo_playerid, aainfo_playerinfo; - void *data, *playerinfo_data; + void *data, + *playerinfo_data; u32 pool_size, playerinfo_pool_size; } highscore_system; -static int highscore_cmp_points( void *a, void *b ) +VG_STATIC int highscore_cmp_points( void *a, void *b ) { highscore_record *pa = a, *pb = b; return (int)pa->points - (int)pb->points; } -static int highscore_cmp_datetime( void *a, void *b ) +VG_STATIC int highscore_cmp_datetime( void *a, void *b ) { highscore_record *pa = a, *pb = b; @@ -111,52 +112,27 @@ static int highscore_cmp_datetime( void *a, void *b ) return pa->datetime < pb->datetime? 1: -1; } -static int highscore_cmp_time( void *a, void *b ) +VG_STATIC int highscore_cmp_time( void *a, void *b ) { highscore_record *pa = a, *pb = b; return (int)pb->time - (int)pa->time; } -static int highscore_cmp_playerid( void *a, void *b ) +VG_STATIC int highscore_cmp_playerid( void *a, void *b ) { highscore_record *pa = a, *pb = b; if( pa->playerid == pb->playerid ) return 0; return pa->playerid < pb->playerid? -1: 1; } -static int highscore_cmp_playerinfo_playerid( void *a, void *b ) +VG_STATIC int highscore_cmp_playerinfo_playerid( void *a, void *b ) { highscore_playerinfo *pa = a, *pb = b; if( pa->playerid == pb->playerid ) return 0; return pa->playerid < pb->playerid? -1: 1; } -static void *highscore_malloc( u32 count, u32 size ) -{ - size_t requested_mem = size * count; - void *data = vg_alloc( requested_mem ); - - requested_mem /= 1024; - requested_mem /= 1024; - - if( !data ) - { - vg_error( "Could not allocated %dmb of memory\n", requested_mem ); - return NULL; - } - else - vg_success( "Allocated %dmb for %u records\n", requested_mem, count ); - - return data; -} - -static void highscores_free(void) -{ - vg_free( highscore_system.data ); - vg_free( highscore_system.playerinfo_data ); -} - -static void highscores_create_db(void) +VG_STATIC void highscores_create_db(void) { struct highscore_system *sys = &highscore_system; @@ -183,7 +159,7 @@ static void highscores_create_db(void) sys->dbheader.playerinfo_root = AATREE_PTR_NIL; } -static int highscores_read(void) +VG_STATIC int highscores_read(void) { struct highscore_system *sys = &highscore_system; @@ -200,7 +176,9 @@ static int highscores_read(void) return 0; } - count = fread( sys->data, sizeof(highscore_record), sys->pool_size, fp ); + count = fread( sys->data, sizeof(highscore_record), + sys->pool_size, fp ); + if( count != sys->pool_size ) { vg_error( "Unexpected EOF reading database contents;" @@ -229,13 +207,17 @@ static int highscores_read(void) } } -static void highscores_init( u32 pool_size, u32 playerinfo_pool_size ) +VG_STATIC void highscores_init( u32 pool_size, u32 playerinfo_pool_size ) { struct highscore_system *sys = &highscore_system; - sys->data = highscore_malloc( pool_size, sizeof(highscore_record) ); - sys->playerinfo_data = highscore_malloc( playerinfo_pool_size, - sizeof(highscore_playerinfo)); + sys->data = vg_linear_alloc( vg_mem.rtmemory, + pool_size*sizeof(highscore_record) ); + + sys->playerinfo_data = + vg_linear_alloc( vg_mem.rtmemory, + playerinfo_pool_size * sizeof(highscore_playerinfo) ); + /* This is ugly.. too bad! */ sys->aainfo.base = highscore_system.data; @@ -278,7 +260,7 @@ static void highscores_init( u32 pool_size, u32 playerinfo_pool_size ) sys->pool_size = pool_size; } -static int highscores_serialize_all(void) +VG_STATIC int highscores_serialize_all(void) { struct highscore_system *sys = &highscore_system; vg_info( "Serializing database\n" ); @@ -301,7 +283,7 @@ static int highscores_serialize_all(void) return 1; } -static highscore_record *highscore_find_user_record( u64 playerid, u32 trackid ) +VG_STATIC highscore_record *highscore_find_user_record( u64 playerid, u32 trackid ) { struct highscore_system *sys = &highscore_system; @@ -318,7 +300,7 @@ static highscore_record *highscore_find_user_record( u64 playerid, u32 trackid ) return aatree_get_data( &sys->aainfo_playerid, find ); } -static aatree_ptr highscores_push_record( highscore_record *record ) +VG_STATIC aatree_ptr highscores_push_record( highscore_record *record ) { struct highscore_system *sys = &highscore_system; @@ -389,7 +371,7 @@ static aatree_ptr highscores_push_record( highscore_record *record ) return index; } -static aatree_ptr highscore_set_user_nickname( u64 steamid, char nick[16] ) +VG_STATIC aatree_ptr highscore_set_user_nickname( u64 steamid, char nick[16] ) { char name[17]; for( int i=0; i<16; i++ ) @@ -429,8 +411,7 @@ static aatree_ptr highscore_set_user_nickname( u64 steamid, char nick[16] ) info->playerid = steamid; sys->dbheader.playerinfo_root = aatree_insert( &sys->aainfo_playerinfo_playerid, - sys->dbheader.playerinfo_root, - record ); + sys->dbheader.playerinfo_root, record ); } for( int i=0; i<16; i++ ) @@ -440,7 +421,7 @@ static aatree_ptr highscore_set_user_nickname( u64 steamid, char nick[16] ) } /* Get the length of a string, bounded by '\0' or len, whichever is first */ -static int highscore_strlen( const char *str, int len ) +VG_STATIC int highscore_strlen( const char *str, int len ) { int str_length; for( str_length=0; str_lengthenabled }; @@ -352,32 +354,104 @@ static void run_light_widget( struct light_widget *lw ) } #endif -static void run_debug_info(void) +VG_STATIC void run_debug_info(void) { char buf[40]; snprintf( buf, 40, "%.2fm/s", v3_length( player.phys.rb.v ) ); - gui_text( (ui_px [2]){ 0, 0 }, buf, 1, k_text_align_left ); + ui_text( (ui_px [2]){ 0, 0 }, buf, 1, k_text_align_left ); snprintf( buf, 40, "%.2f %.2f %.2f m/s", player.phys.a[0], player.phys.a[1], player.phys.a[2] ); - gui_text( (ui_px [2]){ 0, 20 }, buf, 1, k_text_align_left ); + ui_text( (ui_px [2]){ 0, 20 }, buf, 1, k_text_align_left ); snprintf( buf, 40, "pos %.2f %.2f %.2f", player.phys.rb.co[0], player.phys.rb.co[1], player.phys.rb.co[2] ); - gui_text( (ui_px [2]){ 0, 40 }, buf, 1, k_text_align_left ); + ui_text( (ui_px [2]){ 0, 40 }, buf, 1, k_text_align_left ); if( vg.gamepad_ready ) { for( int i=0; i<6; i++ ) { snprintf( buf, 40, "%.2f", vg.gamepad.axes[i] ); - gui_text( (ui_px [2]){ 0, (i+3)*20 }, buf, 1, k_text_align_left ); + ui_text( (ui_px [2]){ 0, (i+3)*20 }, buf, 1, k_text_align_left ); } } else { - gui_text( (ui_px [2]){ 0, 60 }, + ui_text( (ui_px [2]){ 0, 60 }, "Gamepad not ready", 1, k_text_align_left ); } } + +#else + +#define VG_TIMESTEP_FIXED (1.0/60.0) +#define VG_3D +#define VG_FRAMEBUFFER_RESIZE 1 +#include "vg/vg.h" + +int main( int argc, char *argv[] ) +{ + vg_prealloc_quota( 512*1024*1024 ); + vg_enter( argc, argv, "Voyager Game Engine" ); +} + +VG_STATIC void vg_preload(void) +{ +vg_info(" Copyright . . . -----, ,----- ,---. .---. \n" ); +vg_info(" 2021-2022 |\\ /| | / | | | | /| \n" ); +vg_info(" | \\ / | +-- / +----- +---' | / | \n" ); +vg_info(" | \\ / | | / | | \\ | / | \n" ); +vg_info(" | \\/ | | / | | \\ | / | \n" ); +vg_info(" ' ' '--' [] '----- '----- ' ' '---' " + "SOFTWARE\n" ); +} + +VG_STATIC void vg_load(void) +{ + vg_bake_shaders(); + vg_console_load_autos(); +} + +VG_STATIC void vg_start(void) +{ +} + +VG_STATIC void vg_update( int loaded ) +{ +} + +VG_STATIC void vg_update_fixed( int loaded ) +{ +} + +VG_STATIC void vg_update_post( int loaded ) +{ +} + +VG_STATIC void vg_framebuffer_resize( int w, int h ) +{ +} + +VG_STATIC void vg_render(void) +{ + glBindFramebuffer( GL_FRAMEBUFFER, 0 ); + glViewport( 0,0, vg.window_x, vg.window_y ); + glDisable( GL_DEPTH_TEST ); + + glClearColor( 0.11f, 0.35f, 0.37f, 1.0f ); + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT ); + + /* Other shite */ + glDisable(GL_BLEND); + glDisable( GL_DEPTH_TEST ); + vg_lines_drawall( (float *)vg.pv ); + glViewport( 0,0, vg.window_x, vg.window_y ); +} + +VG_STATIC void vg_ui(void) +{ +} + +#endif diff --git a/menu.h b/menu.h index 7d8bf76..02ab252 100644 --- a/menu.h +++ b/menu.h @@ -8,32 +8,31 @@ #include "shaders/menu.h" -static mdl_header *menu_model; -static glmesh menu_glmesh; -static m4x3f menu_mdl_mtx; -static float menu_opacity = 0.0f; -static float menu_input_cooldown = 0.0f; -static float menu_fov_target = 97.0f; -static v2f menu_extra_angles; - -static int menu_loc = 1, +VG_STATIC mdl_context menu_model; +VG_STATIC glmesh menu_glmesh; +VG_STATIC m4x3f menu_mdl_mtx; +VG_STATIC float menu_opacity = 0.0f; +VG_STATIC float menu_input_cooldown = 0.0f; +VG_STATIC float menu_fov_target = 97.0f; +VG_STATIC v2f menu_extra_angles; + +VG_STATIC int menu_loc = 1, menu_loc_last = 1; -static u32 menu_page = 0; +VG_STATIC u32 menu_page = 0; -static int cl_menu = 0, +VG_STATIC int cl_menu = 0, cl_menu_go_away = 0; -static int cl_playermdl_id = 0; -static const char *playermodels[] = { "ch_new", "ch_jordan", "ch_outlaw" }; +VG_STATIC const char *playermodels[] = { "ch_new", "ch_jordan", "ch_outlaw" }; -static void menu_btn_paused( int event ); -static void menu_btn_quit( int event ); -static void menu_btn_skater( int event ); -static void menu_btn_map( int event ); -static void menu_btn_map_a( int event ); -static void menu_btn_map_b( int event ); -static void menu_btn_map_c( int event ); -static void menu_btn_fuckoff( int event ); +VG_STATIC void menu_btn_paused( int event ); +VG_STATIC void menu_btn_quit( int event ); +VG_STATIC void menu_btn_skater( int event ); +VG_STATIC void menu_btn_map( int event ); +VG_STATIC void menu_btn_map_a( int event ); +VG_STATIC void menu_btn_map_b( int event ); +VG_STATIC void menu_btn_map_c( int event ); +VG_STATIC void menu_btn_fuckoff( int event ); struct menu_button { @@ -46,7 +45,7 @@ struct menu_button float falpha, fsize; } -static menu_buttons[] = +VG_STATIC menu_buttons[] = { /*0*/{"text_paused", 1, menu_btn_paused }, /*1*/{"text_quit", 9, menu_btn_quit, {3,-1,4,2}}, @@ -64,69 +63,63 @@ static menu_buttons[] = /*d*/{"text_yes", 8, menu_btn_fuckoff,{-1,-1,-1,-1} }, }; -static void menu_btn_map_a( int event ){} -static void menu_btn_map_b( int event ){} -static void menu_btn_map_c( int event ){} +VG_STATIC void menu_btn_map_a( int event ){} +VG_STATIC void menu_btn_map_b( int event ){} +VG_STATIC void menu_btn_map_c( int event ){} -static void menu_btn_paused( int event ) +VG_STATIC void menu_btn_paused( int event ) { } -static void menu_btn_fuckoff( int event ) +VG_STATIC void menu_btn_fuckoff( int event ) { glfwSetWindowShouldClose( vg.window, 1 ); } -static void menu_btn_quit( int event ) +VG_STATIC void menu_btn_quit( int event ) { menu_page = 0x8; menu_loc = 0xd; } -static void menu_btn_map( int event ) +VG_STATIC void menu_btn_map( int event ) { menu_page = 0x4; menu_loc = 7; } -static void menu_btn_skater( int event ) +VG_STATIC void menu_btn_skater( int event ) { menu_page = 0x2; } -static void menu_init(void) +VG_STATIC void menu_init(void) { - menu_model = mdl_load( "models/rs_menu.mdl" ); + vg_linear_clear( vg_mem.scratch ); - if( !menu_model ) - vg_fatal_exit_loop( "No menu model" ); + mdl_open( &menu_model, "models/rs_menu.mdl" ); + mdl_load_metadata( &menu_model, vg_mem.rtmemory ); + mdl_load_mesh_data( &menu_model, vg_mem.scratch ); + mdl_close( &menu_model ); + + vg_acquire_thread_sync(); + mdl_unpack_glmesh( &menu_model, &menu_glmesh ); + vg_release_thread_sync(); for( int i=0; ipnode = mdl_node_from_name( menu_model, btn->name ); + btn->pnode = mdl_node_from_name( &menu_model, btn->name ); if( !btn->pnode ) vg_fatal_exit_loop( "Menu programming error" ); } - vg_convar_push( (struct vg_convar){ - .name = "cl_playermdl_id", - .data = &cl_playermdl_id, - .data_type = k_convar_dtype_i32, - .opt_i32 = { .min=0, .max=2, .clamp=1 }, - .persistent = 1 - }); - - vg_acquire_thread_sync(); - mdl_unpack_glmesh( menu_model, &menu_glmesh ); - vg_release_thread_sync(); - shader_menu_register(); } -static void menu_run_directional(void) +VG_STATIC void menu_run_directional(void) { struct menu_button *btn = &menu_buttons[ menu_loc ]; @@ -174,18 +167,18 @@ static void menu_run_directional(void) } } -static int menu_page_should_backout(void) +VG_STATIC int menu_page_should_backout(void) { return vg_get_button_down( "break" ); } -static void menu_close(void) +VG_STATIC void menu_close(void) { cl_menu_go_away = 1; menu_page = 0; } -static void menu_page_main(void) +VG_STATIC void menu_page_main(void) { if( menu_page_should_backout() ) { @@ -197,7 +190,7 @@ static void menu_page_main(void) menu_run_directional(); } -static void menu_page_map(void) +VG_STATIC void menu_page_map(void) { if( menu_page_should_backout() ) { @@ -209,7 +202,7 @@ static void menu_page_map(void) menu_run_directional(); } -static void menu_page_quit(void) +VG_STATIC void menu_page_quit(void) { if( menu_page_should_backout() ) { @@ -221,7 +214,7 @@ static void menu_page_quit(void) menu_run_directional(); } -static void menu_page_skater(void) +VG_STATIC void menu_page_skater(void) { float h = vg_get_axis( "lookh" ); menu_fov_target = 97.0f; @@ -245,7 +238,6 @@ static void menu_page_skater(void) menu_buttons[5].falpha = 1.0f; menu_input_cooldown = 0.25f; - player_load_model( playermodels[ cl_playermdl_id ], 1 ); } else { @@ -257,12 +249,11 @@ static void menu_page_skater(void) menu_buttons[6].falpha = 1.0f; menu_input_cooldown = 0.25f; - player_load_model( playermodels[ cl_playermdl_id ], 1 ); } } } -static void menu_update(void) +VG_STATIC void menu_update(void) { if( vg_get_button_down( "menu" ) ) { @@ -376,7 +367,7 @@ float expSustainedImpulse( float x, float f, float k ) return fminf( x*x/(f*f), 1.0f+(2.0f/f)*s*expf(-k*s)); } -static void menu_render( m4x4f projection ) +VG_STATIC void menu_render( m4x4f projection ) { glEnable(GL_BLEND); glDisable(GL_DEPTH_TEST); @@ -431,7 +422,7 @@ static void menu_render( m4x4f projection ) for( int j=0; jpnode->submesh_count; j++ ) { mdl_submesh *sm = - mdl_submesh_from_id( menu_model, btn->pnode->submesh_start+j ); + &menu_model.submesh_buffer[ btn->pnode->submesh_start+j ]; mdl_draw_submesh( sm ); } } @@ -456,9 +447,4 @@ static void menu_render( m4x4f projection ) */ } -static void menu_free(void *_) -{ - mesh_free( &menu_glmesh ); -} - #endif /* MENU_H */ diff --git a/model.h b/model.h index faa9f5f..b3650f8 100644 --- a/model.h +++ b/model.h @@ -13,9 +13,10 @@ typedef struct mdl_vert mdl_vert; typedef struct mdl_submesh mdl_submesh; typedef struct mdl_material mdl_material; typedef struct mdl_node mdl_node; -typedef struct mdl_header mdl_header; +typedef struct mdl_file_header mdl_file_header; typedef struct mdl_animation mdl_animation; typedef struct mdl_keyframe mdl_keyframe; +typedef struct mdl_context mdl_context; #define MDL_SIZE_MAX 0x1000000 #define MDL_VERT_MAX 1000000 @@ -41,7 +42,8 @@ enum classtype k_classtype_skeleton = 11, k_classtype_skin = 12, k_classtype_achievement_box = 13, - k_classtype_audio = 14 + k_classtype_audio = 14, + k_classtype_trigger = 15 }; @@ -79,9 +81,8 @@ struct mdl_node v4f q; v3f s; - union{ u32 submesh_start, sub_uid; }; - - u32 + u32 sub_uid, /* allocated in-file... too bad. */ + submesh_start, submesh_count, classtype, offset, @@ -106,9 +107,9 @@ struct mdl_animation u32 offset; }; -struct mdl_header +struct mdl_file_header { - u32 identifier, version, file_length; + u32 identifier, version, file_length, pad0; u32 vertex_count, vertex_offset, indice_count, indice_offset, @@ -116,7 +117,9 @@ struct mdl_header material_count, material_offset, node_count, node_offset, anim_count, anim_offset, - strings_offset, entdata_offset, animdata_offset; + strings_length, strings_offset, + entdata_length, entdata_offset, + keyframe_count, keyframe_offset; }; /* @@ -212,6 +215,26 @@ struct classtype_audio #pragma pack(pop) + +struct mdl_context +{ + FILE *file; + mdl_file_header info; + + /* each buffer becomes availible after each _load function is called */ + mdl_node *node_buffer; /* mdl_load_metadata() */ + mdl_submesh *submesh_buffer; + mdl_material *material_buffer; + mdl_animation *anim_buffer; + void *entdata_buffer; + const char *string_buffer; + + mdl_keyframe *keyframe_buffer; /* mdl_load_anim_data() */ + + mdl_vert *vertex_buffer; /* mdl_load_mesh_data() */ + u32 *index_buffer; +}; + /* * Simple mesh interface for OpenGL */ @@ -223,7 +246,7 @@ struct glmesh u32 loaded; }; -static void mesh_upload( glmesh *mesh, +VG_STATIC void mesh_upload( glmesh *mesh, mdl_vert *verts, u32 vert_count, u32 *indices, u32 indice_count ) { @@ -279,23 +302,23 @@ static void mesh_upload( glmesh *mesh, mesh->loaded = 1; } -static void mesh_bind( glmesh *mesh ) +VG_STATIC void mesh_bind( glmesh *mesh ) { glBindVertexArray( mesh->vao ); } -static void mesh_drawn( u32 start, u32 count ) +VG_STATIC void mesh_drawn( u32 start, u32 count ) { glDrawElements( GL_TRIANGLES, count, GL_UNSIGNED_INT, (void *)(start*sizeof(u32)) ); } -static void mesh_draw( glmesh *mesh ) +VG_STATIC void mesh_draw( glmesh *mesh ) { mesh_drawn( 0, mesh->indice_count ); } -static void mesh_free( glmesh *mesh ) +VG_STATIC void mesh_free( glmesh *mesh ) { if( mesh->loaded ) { @@ -305,156 +328,177 @@ static void mesh_free( glmesh *mesh ) } } +VG_STATIC void mdl_load_fatal_corrupt( mdl_context *mdl ) +{ + fclose( mdl->file ); + vg_file_print_invalid( mdl->file ); + vg_fatal_exit_loop( "Corrupt model" ); +} /* * Model implementation + * + * TODO. + * + * you have two api options for loading a model, first, the easy way: + * mdl_load ... + * will put the entire model straight into the linear_alloc + * + * or, to target different allocators: + * + * mdl_open + * mdl_load_metadata + * mdl_load_vertex_data + * mdl_load_indice_data + * mdl_close + * + * these should ideally be called in quick succession to limit stalls. */ -static mdl_header *mdl_load( const char *path ) +/* + * if calling mdl_open, and the file does not exist, the game will fatal quit + */ +VG_STATIC void mdl_open( mdl_context *mdl, const char *path ) { - i64 size; - mdl_header *header = vg_asset_read_s( path, &size ); + memset( mdl, 0, sizeof( mdl_context ) ); + mdl->file = fopen( path, "rb" ); - /* - * Check file is valid - */ - if( !header ) + if( !mdl->file ) { - vg_error( "Could not open '%s'\n", path ); - return NULL; + vg_error( "mdl_open('%s'): %s\n", path, strerror(errno) ); + vg_fatal_exit_loop( "see above for details" ); } - if( size < sizeof(mdl_header) ) - { - vg_free( header ); - vg_error( "Invalid file '%s' (too small for header)\n", path ); - return NULL; - } + u64 l = fread( &mdl->info, sizeof(mdl_file_header), 1, mdl->file ); + if( l != 1 ) + mdl_load_fatal_corrupt( mdl ); +} - if( header->file_length != size ) - { - vg_error( "Invalid file '%s'" - "(wrong .file_length, %ub != real file size %ub)\n", - path, header->file_length, size ); - vg_free( header ); - return NULL; - } +/* + * Load all metadata (everything up until the large buffers). Probs at most 50k + */ +VG_STATIC void mdl_load_metadata( mdl_context *mdl, void *lin_alloc ) +{ + assert( mdl->file ); + + u64 lheader = sizeof(mdl_file_header), + ldata = mdl->info.keyframe_offset - lheader; - /* - * Validate offsets and memory sections, to ensure all arrays are in-bounds, - * and that they do not overlap. - */ + void *all_data = vg_linear_alloc( lin_alloc, ldata ); - struct memregion + fseek( mdl->file, lheader, SEEK_SET ); + u64 l = fread( all_data, ldata, 1, mdl->file ); + + if( l != 1 ) { - const char *desc; - u32 count, max_count, size, offset; + vg_file_print_invalid( mdl->file ); + vg_fatal_exit_loop( "Corrupt model" ); } - regions[] = { - { - "Vertices", - header->vertex_count, MDL_VERT_MAX, - sizeof(mdl_vert), header->vertex_offset - }, - { - "Indices", - header->indice_count, MDL_INDICE_MAX, - sizeof(u32), header->indice_offset - }, - { - "Submesh", - header->submesh_count, MDL_SUBMESH_MAX, - sizeof(mdl_submesh), header->submesh_offset - }, - { - "Materials", - header->material_count, MDL_MATERIAL_MAX, - sizeof(mdl_material), header->material_offset - }, - { - "Nodes", - header->node_count, MDL_NODE_MAX, - sizeof(mdl_node), header->node_count - } - }; - for( int i=0; inode_buffer = all_data + (mdl->info.node_offset - lheader); + mdl->submesh_buffer = all_data + (mdl->info.submesh_offset - lheader); + mdl->material_buffer = all_data + (mdl->info.material_offset - lheader); + mdl->anim_buffer = all_data + (mdl->info.anim_offset - lheader); + mdl->entdata_buffer = all_data + (mdl->info.entdata_offset - lheader); + mdl->string_buffer = all_data + (mdl->info.strings_offset - lheader); +} - if( ri->count == 0 ) - continue; +/* + * Load just the mesh data + */ +VG_STATIC void mdl_load_mesh_data( mdl_context *mdl, void *lin_alloc ) +{ + assert( mdl->file ); + + u64 size_verts = mdl->info.vertex_count * sizeof(mdl_vert), + size_index = mdl->info.indice_count * sizeof(u32); - if( ri->count > ri->max_count ) - { - vg_free( header ); - vg_error( "'%s': '%s' buffer exceeds the maximum (%u/%u)\n", - path, ri->desc, ri->count, ri->max_count ); - return NULL; - } + mdl->vertex_buffer = vg_linear_alloc( lin_alloc, size_verts ); + mdl->index_buffer = vg_linear_alloc( lin_alloc, size_index ); + + { + fseek( mdl->file, mdl->info.vertex_offset, SEEK_SET ); + u64 l = fread( mdl->vertex_buffer, size_verts, 1, mdl->file ); + if( l != 1 ) + mdl_load_fatal_corrupt( mdl ); + } + { + fseek( mdl->file, mdl->info.indice_offset, SEEK_SET ); + u64 l = fread( mdl->index_buffer, size_index, 1, mdl->file ); + if( l != 1 ) + mdl_load_fatal_corrupt( mdl ); + } +} - if( ri->offset >= header->file_length ) - { - vg_free( header ); - vg_error( "'%s': '%s' buffer offset is out of range\n", - path, ri->desc ); - return NULL; - } +/* + * Load animation data + */ +VG_STATIC void mdl_load_anim_data( mdl_context *mdl, void *lin_alloc ) +{ + assert( mdl->file ); - if( ri->offset + ri->size*ri->count > header->file_length ) - { - vg_free( header ); - vg_error( "'%s': '%s' buffer size is out of range\n", - path, ri->desc ); - return NULL; - } + if( mdl->info.keyframe_count == 0 ) + return; + + u64 size_kf = mdl->info.keyframe_count * sizeof(mdl_keyframe); + mdl->keyframe_buffer = vg_linear_alloc( lin_alloc, size_kf ); + + fseek( mdl->file, mdl->info.keyframe_offset, SEEK_SET ); + u64 l = fread( mdl->keyframe_buffer, size_kf, 1, mdl->file ); + if( l != 1 ) + mdl_load_fatal_corrupt( mdl ); +} - for( int j=0; jcount == 0 ) - continue; +/* + * close file handle + */ +VG_STATIC void mdl_close( mdl_context *mdl ) +{ + fclose( mdl->file ); + mdl->file = NULL; +} - if( ri->offset >= rj->offset && - (ri->offset+ri->size*ri->count < rj->offset+rj->size*rj->count)) - { - vg_free( header ); - vg_error( "'%s': '%s' buffer overlaps '%s'\n", - path, ri->desc, rj->desc ); - return NULL; - } - } - } +/* open a model */ +VG_STATIC mdl_context *mdl_load_full( void *lin_alloc, const char *path ) +{ + /* Inspect the header by opening it, give us the size needed */ + mdl_context temp_ctx; + mdl_open( &temp_ctx, path ); - /* - * Pointer validation TODO(workshop) - */ + /* create allocator */ + u32 tot_size = temp_ctx.info.file_length + sizeof( mdl_context ); + void *data = vg_create_linear_allocator( lin_alloc, tot_size ); - /* - * strings TODO(workshop) - */ + /* copy context and load all other data */ + mdl_context *ctx = vg_linear_alloc( data, sizeof(mdl_context) ); + memcpy( ctx, &temp_ctx, sizeof(mdl_context) ); - return header; -} + mdl_load_metadata( ctx, data ); + mdl_load_anim_data( ctx, data ); + mdl_load_mesh_data( ctx, data ); + mdl_close( ctx ); -static void *mdl_baseptr( mdl_header *mdl, u32 offset ) -{ - return (void *)mdl + offset; + return ctx; } -static const char *mdl_pstr( mdl_header *mdl, u32 pstr ) +/* + * Item getters + * ---------------------------------------------------------------------------- + * TODO: Clamp access and oob errors + */ +VG_STATIC const char *mdl_pstr( mdl_context *mdl, u32 pstr ) { - return (const char *)(mdl_baseptr( mdl, mdl->strings_offset )) + pstr; + return mdl->string_buffer + pstr; } -static mdl_node *mdl_node_from_id( mdl_header *mdl, u32 id ) +VG_STATIC mdl_node *mdl_node_from_id( mdl_context *mdl, u32 id ) { - return ((mdl_node *)mdl_baseptr( mdl, mdl->node_offset )) + id; + return &mdl->node_buffer[id]; } -static mdl_node *mdl_node_from_name( mdl_header *mdl, const char *name ) +VG_STATIC mdl_node *mdl_node_from_name( mdl_context *mdl, const char *name ) { - for( int i=0; inode_count; i++ ) + for( int i=0; i < mdl->info.node_count; i++ ) { mdl_node *pnode = mdl_node_from_id( mdl, i ); @@ -465,43 +509,23 @@ static mdl_node *mdl_node_from_name( mdl_header *mdl, const char *name ) return NULL; } -static mdl_submesh *mdl_submesh_from_id( mdl_header *mdl, u32 id ) -{ - if( id >= mdl->submesh_count ) - return NULL; - - return ((mdl_submesh *)mdl_baseptr( mdl, mdl->submesh_offset )) + id; -} - -static mdl_submesh *mdl_node_submesh( mdl_header *mdl, mdl_node *node, u32 i ) -{ - if( i >= node->submesh_count ) - return NULL; - - return mdl_submesh_from_id( mdl, node->submesh_start+i ); -} - -static u32 *mdl_submesh_indices( mdl_header *mdl, mdl_submesh *sm ) +VG_STATIC mdl_submesh *mdl_node_submesh( mdl_context *mdl, + mdl_node *node, u32 i ) { - return ((u32 *)mdl_baseptr( mdl, mdl->indice_offset )) + sm->indice_start; + return &mdl->submesh_buffer[ node->submesh_start+i ]; } -static mdl_vert *mdl_submesh_vertices( mdl_header *mdl, mdl_submesh *sm ) +VG_STATIC u32 *mdl_submesh_indices( mdl_context *mdl, mdl_submesh *sm ) { - return ((mdl_vert *)mdl_baseptr(mdl,mdl->vertex_offset)) + sm->vertex_start; + return &mdl->index_buffer[ sm->indice_start ]; } -static mdl_material *mdl_material_from_id( mdl_header *mdl, u32 id ) +VG_STATIC mdl_vert *mdl_submesh_vertices( mdl_context *mdl, mdl_submesh *sm ) { - return ((mdl_material *)mdl_baseptr(mdl,mdl->material_offset)) + id; + return &mdl->vertex_buffer[ sm->vertex_start ]; } -static mdl_animation *mdl_animation_from_id( mdl_header *mdl, u32 id ) -{ - return ((mdl_animation *)mdl_baseptr(mdl,mdl->anim_offset)) + id; -} - -static void mdl_node_transform( mdl_node *pnode, m4x3f transform ) +VG_STATIC void mdl_node_transform( mdl_node *pnode, m4x3f transform ) { q_m3x3( pnode->q, transform ); v3_muls( transform[0], pnode->s[0], transform[0] ); @@ -510,20 +534,23 @@ static void mdl_node_transform( mdl_node *pnode, m4x3f transform ) v3_copy( pnode->co, transform[3] ); } -static void mdl_unpack_submesh( mdl_header *mdl, glmesh *mesh, mdl_submesh *sm ) +/* upload a mesh based on file submesh */ +VG_STATIC void mdl_unpack_submesh( mdl_context *mdl, glmesh *mesh, + mdl_submesh *sm ) { mesh_upload( mesh, mdl_submesh_vertices( mdl, sm ), sm->vertex_count, mdl_submesh_indices( mdl, sm ), sm->indice_count ); } -static void mdl_unpack_glmesh( mdl_header *mdl, glmesh *mesh ) +/* upload entire mesh from model */ +VG_STATIC void mdl_unpack_glmesh( mdl_context *mdl, glmesh *mesh ) { - u32 offset = mdl_submesh_from_id( mdl, 0 )->vertex_count; + u32 offset = mdl->submesh_buffer[0].vertex_count; - for( int i=1; i< mdl->submesh_count; i++ ) + for( int i=1; i< mdl->info.submesh_count; i++ ) { - mdl_submesh *sm = mdl_submesh_from_id( mdl, i ); - u32 *indices = mdl_submesh_indices( mdl, sm ); + mdl_submesh *sm = &mdl->submesh_buffer[i]; + u32 *indices = mdl_submesh_indices( mdl, sm ); for( u32 j=0; jindice_count; j++ ) indices[j] += offset; @@ -531,42 +558,39 @@ static void mdl_unpack_glmesh( mdl_header *mdl, glmesh *mesh ) offset += sm->vertex_count; } - mdl_vert *vertex_base = mdl_baseptr( mdl, mdl->vertex_offset ); - u32 *indice_base = mdl_baseptr( mdl, mdl->indice_offset ); - - mesh_upload( mesh, vertex_base, mdl->vertex_count, - indice_base, mdl->indice_count ); + mesh_upload( mesh, mdl->vertex_buffer, mdl->info.vertex_count, + mdl->index_buffer, mdl->info.indice_count ); } -static void mdl_draw_submesh( mdl_submesh *sm ) +VG_STATIC void mdl_draw_submesh( mdl_submesh *sm ) { mesh_drawn( sm->indice_start, sm->indice_count ); } -static void *mdl_get_entdata( mdl_header *mdl, mdl_node *pnode ) +VG_STATIC void *mdl_get_entdata( mdl_context *mdl, mdl_node *pnode ) { - return mdl_baseptr( mdl, mdl->entdata_offset ) + pnode->offset; + return mdl->entdata_buffer + pnode->offset; } -static mdl_keyframe *mdl_get_animdata( mdl_header *mdl, mdl_animation *anim ) +VG_STATIC mdl_keyframe *mdl_get_animdata( mdl_context *mdl, mdl_animation *anim ) { - return mdl_baseptr( mdl, mdl->animdata_offset ) + anim->offset; + return mdl->keyframe_buffer + anim->offset; } -static void mdl_link_materials( mdl_header *root, mdl_header *child ) +VG_STATIC void mdl_link_materials( mdl_context *root, mdl_context *child ) { u32 lookup[MDL_MATERIAL_MAX]; - for( int i=0; imaterial_count; i++ ) + for( int i=0; iinfo.material_count; i++ ) { - mdl_material *mi = mdl_material_from_id( child, i ); + mdl_material *mi = &child->material_buffer[i]; const char *si = mdl_pstr( child, mi->pstr_name ); lookup[i] = 0; - for( int j=0; jmaterial_count; j++ ) + for( int j=0; jinfo.material_count; j++ ) { - mdl_material *mj = mdl_material_from_id( root, j ); + mdl_material *mj = &root->material_buffer[j]; const char *sj = mdl_pstr( root, mj->pstr_name ); if( !strcmp( si, sj ) ) @@ -583,10 +607,10 @@ static void mdl_link_materials( mdl_header *root, mdl_header *child ) } } - for( int i=0; isubmesh_count; i++ ) + for( int i=0; iinfo.submesh_count; i++ ) { - mdl_submesh *sm = mdl_submesh_from_id( child, i ); - sm->material_id = lookup[sm->material_id]; + mdl_submesh *sm = &child->submesh_buffer[i]; + sm->material_id = lookup[sm->material_id]; } } diff --git a/models_src/alter.mdl b/models_src/alter.mdl index b5b0798..502c98e 100644 Binary files a/models_src/alter.mdl and b/models_src/alter.mdl differ diff --git a/models_src/ch_default.mdl b/models_src/ch_default.mdl index 0d66961..7877bd2 100644 Binary files a/models_src/ch_default.mdl and b/models_src/ch_default.mdl differ diff --git a/models_src/ch_empty.mdl b/models_src/ch_empty.mdl index 6448b33..ce85ad9 100644 Binary files a/models_src/ch_empty.mdl and b/models_src/ch_empty.mdl differ diff --git a/models_src/ch_jordan.mdl b/models_src/ch_jordan.mdl index 80482dc..0f65fb2 100644 Binary files a/models_src/ch_jordan.mdl and b/models_src/ch_jordan.mdl differ diff --git a/models_src/ch_mike.mdl b/models_src/ch_mike.mdl index 6296030..44e128f 100644 Binary files a/models_src/ch_mike.mdl and b/models_src/ch_mike.mdl differ diff --git a/models_src/ch_new.mdl b/models_src/ch_new.mdl index df1e23c..71c7a3f 100644 Binary files a/models_src/ch_new.mdl and b/models_src/ch_new.mdl differ diff --git a/models_src/ch_outlaw.001.mdl b/models_src/ch_outlaw.001.mdl new file mode 100644 index 0000000..fa40549 Binary files /dev/null and b/models_src/ch_outlaw.001.mdl differ diff --git a/models_src/ch_outlaw.mdl b/models_src/ch_outlaw.mdl index 0fffc5c..ee1bbb8 100644 Binary files a/models_src/ch_outlaw.mdl and b/models_src/ch_outlaw.mdl differ diff --git a/models_src/epic_scene.mdl b/models_src/epic_scene.mdl index 858fe3d..faabb16 100644 Binary files a/models_src/epic_scene.mdl and b/models_src/epic_scene.mdl differ diff --git a/models_src/mp_dev.mdl b/models_src/mp_dev.mdl index 7a27b25..1f8a3db 100644 Binary files a/models_src/mp_dev.mdl and b/models_src/mp_dev.mdl differ diff --git a/models_src/mp_test.mdl b/models_src/mp_test.mdl new file mode 100644 index 0000000..28b0a8b Binary files /dev/null and b/models_src/mp_test.mdl differ diff --git a/models_src/rs_cars.mdl b/models_src/rs_cars.mdl index 6e75103..40ddec8 100644 Binary files a/models_src/rs_cars.mdl and b/models_src/rs_cars.mdl differ diff --git a/models_src/rs_chicken.mdl b/models_src/rs_chicken.mdl index 73c6686..5e72b53 100644 Binary files a/models_src/rs_chicken.mdl and b/models_src/rs_chicken.mdl differ diff --git a/models_src/rs_foliage.mdl b/models_src/rs_foliage.mdl index bac6866..adfdd5b 100644 Binary files a/models_src/rs_foliage.mdl and b/models_src/rs_foliage.mdl differ diff --git a/models_src/rs_gate.mdl b/models_src/rs_gate.mdl index 30c54bc..07e5ab2 100644 Binary files a/models_src/rs_gate.mdl and b/models_src/rs_gate.mdl differ diff --git a/models_src/rs_menu.mdl b/models_src/rs_menu.mdl index 160d37e..dcee13c 100644 Binary files a/models_src/rs_menu.mdl and b/models_src/rs_menu.mdl differ diff --git a/models_src/rs_scoretext.mdl b/models_src/rs_scoretext.mdl index 876dc58..637d198 100644 Binary files a/models_src/rs_scoretext.mdl and b/models_src/rs_scoretext.mdl differ diff --git a/models_src/rs_skydome.mdl b/models_src/rs_skydome.mdl index 9cc16f0..a3aea27 100644 Binary files a/models_src/rs_skydome.mdl and b/models_src/rs_skydome.mdl differ diff --git a/models_src/rs_vig.mdl b/models_src/rs_vig.mdl index 26cdd0d..2e27cf3 100644 Binary files a/models_src/rs_vig.mdl and b/models_src/rs_vig.mdl differ diff --git a/network.h b/network.h index e06027a..b47f518 100644 --- a/network.h +++ b/network.h @@ -17,19 +17,19 @@ //#define SR_USE_LOCALHOST /* Call it at start; Connects us to the gameserver */ -static void network_init(void); +VG_STATIC void network_init(void); /* Run this from main loop */ -static void network_update(void); +VG_STATIC void network_update(void); /* Call it at shutdown */ -static void network_end(void*_); +VG_STATIC void network_end(void*_); /* * Can buffer up a bunch of these by calling many times, they will be * sent at the next connection */ -static void network_submit_highscore( u32 trackid, u16 points, u16 time ); +VG_STATIC void network_submit_highscore( u32 trackid, u16 points, u16 time ); /* * Game endpoints are provided with the same names to allow running without a @@ -40,21 +40,21 @@ static void network_submit_highscore( u32 trackid, u16 points, u16 time ); /* * Runtime connection stuff */ -static u8 steam_app_ticket[ 1024 ]; -static u32 steam_app_ticket_length; -static int network_name_update = 1; +VG_STATIC u8 steam_app_ticket[ 1024 ]; +VG_STATIC u32 steam_app_ticket_length; +VG_STATIC int network_name_update = 1; -static HSteamNetConnection cremote; -static ESteamNetworkingConnectionState cremote_state = +VG_STATIC HSteamNetConnection cremote; +VG_STATIC ESteamNetworkingConnectionState cremote_state = k_ESteamNetworkingConnectionState_None; /* * Implementation */ -static void scores_update(void); +VG_STATIC void scores_update(void); -static void on_auth_ticket_recieved( void *result, void *context ) +VG_STATIC void on_auth_ticket_recieved( void *result, void *context ) { EncryptedAppTicketResponse_t *response = result; @@ -82,7 +82,7 @@ static void on_auth_ticket_recieved( void *result, void *context ) } } -static void request_auth_ticket(void) +VG_STATIC void request_auth_ticket(void) { /* * TODO Check for one thats cached on the disk and load it. @@ -97,7 +97,7 @@ static void request_auth_ticket(void) NULL, 0 ); } -static void send_auth_ticket(void) +VG_STATIC void send_auth_ticket(void) { u32 size = sizeof(netmsg_auth) + steam_app_ticket_length; netmsg_auth *auth = alloca(size); @@ -112,7 +112,7 @@ static void send_auth_ticket(void) k_nSteamNetworkingSend_Reliable, NULL ); } -static void send_score_request(void) +VG_STATIC void send_score_request(void) { vg_info( "Requesting scores\n" ); netmsg_scores_request req; @@ -123,7 +123,7 @@ static void send_score_request(void) k_nSteamNetworkingSend_Reliable, NULL ); } -static void send_score_update(void) +VG_STATIC void send_score_update(void) { vg_info( "Sending scores\n" ); u32 size = sizeof(netmsg_set_score) + @@ -166,7 +166,7 @@ static void send_score_update(void) k_nSteamNetworkingSend_Reliable, NULL ); } -static void send_nickname(void) +VG_STATIC void send_nickname(void) { netmsg_set_nickname nick; nick.inetmsg_id = k_inetmsg_set_nickname; @@ -181,7 +181,7 @@ static void send_nickname(void) network_name_update = 0; } -static void server_routine_update(void) +VG_STATIC void server_routine_update(void) { send_auth_ticket(); @@ -192,7 +192,7 @@ static void server_routine_update(void) send_score_request(); } -static void on_server_connect_status( CallbackMsg_t *msg ) +VG_STATIC void on_server_connect_status( CallbackMsg_t *msg ) { SteamNetConnectionStatusChangedCallback_t *info = (void *)msg->m_pubParam; vg_info( " Connection status changed for %lu\n", info->m_hConn ); @@ -216,7 +216,7 @@ static void on_server_connect_status( CallbackMsg_t *msg ) } } -static void network_connect_gc(void) +VG_STATIC void network_connect_gc(void) { /* Connect to server if not connected */ SteamNetworkingIPAddr remoteAddr; @@ -236,7 +236,7 @@ static void network_connect_gc(void) hSteamNetworkingSockets, &remoteAddr, 0, NULL ); } -static void on_inet_scoreboard( SteamNetworkingMessage_t *msg ) +VG_STATIC void on_inet_scoreboard( SteamNetworkingMessage_t *msg ) { netmsg_scoreboard *sb = msg->m_pData; @@ -272,7 +272,7 @@ static void on_inet_scoreboard( SteamNetworkingMessage_t *msg ) network_scores_updated = 1; } -static void poll_connection(void) +VG_STATIC void poll_connection(void) { SteamNetworkingMessage_t *messages[32]; int len; @@ -308,7 +308,7 @@ static void poll_connection(void) /* * Subroutine to be connected to main game loop, runs all routines on timers */ -static void network_update(void) +VG_STATIC void network_update(void) { if( steam_ready ) { @@ -339,7 +339,7 @@ static void network_update(void) } } -static void network_init(void) +VG_STATIC void network_init(void) { if( steam_ready ) { @@ -349,7 +349,7 @@ static void network_init(void) } } -static void network_end(void*_) +VG_STATIC void network_end(void*_) { /* TODO: Fire off any buffered highscores that need to be setn */ if( cremote_state == k_ESteamNetworkingConnectionState_Connected || @@ -362,9 +362,9 @@ static void network_end(void*_) #else /* SR_NETWORKED */ -static void network_init(void){} -static void network_update(void){} -static void network_end(void*_){} +VG_STATIC void network_init(void){} +VG_STATIC void network_update(void){} +VG_STATIC void network_end(void*_){} #endif /* SR_NETWORKED */ #endif /* NETWORK_H */ diff --git a/network_msg.h b/network_msg.h index 1e3e475..5f1bc41 100644 --- a/network_msg.h +++ b/network_msg.h @@ -73,7 +73,7 @@ struct netmsg_scoreboard } boards[ vg_list_size(track_infos) ]; } -static scoreboard_client_data = { +VG_STATIC scoreboard_client_data = { .inetmsg_id = k_inetmsg_scoreboard, .board_count = vg_list_size(track_infos) }; diff --git a/player.h b/player.h index a7831b7..5a21afe 100644 --- a/player.h +++ b/player.h @@ -13,7 +13,7 @@ #include "skeleton.h" #include "bvh.h" -static float +VG_STATIC float k_walkspeed = 20.0f, /* no longer used */ k_runspeed = 20.0f, k_board_radius = 0.3f, @@ -38,9 +38,10 @@ static float k_walk_accel = 150.0f, k_walk_friction = 8.0f; -static int freecam = 0; -static int walk_grid_iterations = 1; -static float fc_speed = 10.0f; +VG_STATIC int cl_playermdl_id = 0; +VG_STATIC int freecam = 0; +VG_STATIC int walk_grid_iterations = 1; +VG_STATIC float fc_speed = 10.0f; /* * ----------------------------------------------------------------------------- @@ -48,7 +49,7 @@ static float fc_speed = 10.0f; * ----------------------------------------------------------------------------- */ -static struct gplayer +VG_STATIC struct gplayer { /* Physics */ rigidbody collide_front, collide_back; @@ -127,7 +128,9 @@ static struct gplayer /* player model */ struct player_model { - glmesh mesh; + glmesh player_meshes[3]; + + mdl_context meta; struct skeleton sk; struct skeleton_anim *anim_stand, *anim_highg, @@ -159,7 +162,7 @@ static struct gplayer rigidbody rb; u32 parent; } - *ragdoll; + ragdoll[32]; u32 ragdoll_count; int shoes[2]; @@ -175,12 +178,12 @@ player = /* * API */ -static float *player_get_pos(void); -static void player_kill(void); -static float *player_cam_pos(void); -static void player_save_frame(void); -static void player_restore_frame(void); -static void player_save_rewind_frame(void); +VG_STATIC float *player_get_pos(void); +VG_STATIC void player_kill(void); +VG_STATIC float *player_cam_pos(void); +VG_STATIC void player_save_frame(void); +VG_STATIC void player_restore_frame(void); +VG_STATIC void player_save_rewind_frame(void); /* * Submodules @@ -197,12 +200,20 @@ static void player_save_rewind_frame(void); * ----------------------------------------------------------------------------- */ -static void player_init(void) /* 1 */ +VG_STATIC void player_init(void) /* 1 */ { rb_init( &player.phys.rb ); rb_init( &player.collide_front ); rb_init( &player.collide_back ); + vg_convar_push( (struct vg_convar){ + .name = "cl_playermdl_id", + .data = &cl_playermdl_id, + .data_type = k_convar_dtype_i32, + .opt_i32 = { .min=0, .max=2, .clamp=1 }, + .persistent = 1 + }); + vg_convar_push( (struct vg_convar){ .name = "walk_speed", .data = &k_walkspeed, @@ -249,14 +260,14 @@ static void player_init(void) /* 1 */ }); player.rewind_length = 0; - player.rewind_buffer = vg_alloc( sizeof(struct rewind_frame) - * PLAYER_REWIND_FRAMES ); + player.rewind_buffer = + vg_linear_alloc( vg_mem.rtmemory, + sizeof(struct rewind_frame) * PLAYER_REWIND_FRAMES ); - /* other systems */ - vg_loader_highwater( player_model_init, player_model_free, NULL ); + player_model_init(); } -static void player_save_rewind_frame(void) +VG_STATIC void player_save_rewind_frame(void) { if( player.rewind_length < PLAYER_REWIND_FRAMES ) { @@ -278,7 +289,7 @@ static void player_save_rewind_frame(void) } /* Deal with input etc */ -static void player_update_pre(void) +VG_STATIC void player_update_pre(void) { struct player_phys *phys = &player.phys; @@ -289,7 +300,7 @@ static void player_update_pre(void) if( vg_get_button_down( "reset" ) ) { - double delta = world_routes.time - world_routes.last_use; + double delta = world.time - world.last_use; if( delta <= RESET_MAX_TIME ) { @@ -353,7 +364,7 @@ static void player_update_pre(void) } } -static void player_update_fixed(void) /* 2 */ +VG_STATIC void player_update_fixed(void) /* 2 */ { if( player.rewinding ) return; @@ -380,7 +391,7 @@ static void player_update_fixed(void) /* 2 */ } } -static void player_update_post(void) +VG_STATIC void player_update_post(void) { for( int i=0; ijump = vg_clampf( phys->jump, 0.0f, 1.0f ); } -static void player_save_frame(void) +VG_STATIC void player_save_frame(void) { player.phys_gate_frame = player.phys; } -static void player_restore_frame(void) +VG_STATIC void player_restore_frame(void) { player.phys = player.phys_gate_frame; rb_update_transform( &player.phys.rb ); } -static void player_do_motion(void) +VG_STATIC void player_do_motion(void) { struct player_phys *phys = &player.phys; @@ -684,9 +684,9 @@ static void player_do_motion(void) /* * Gate intersection, by tracing a line over the gate planes */ - for( int i=0; igate; if( gate_intersect( gate, phys->rb.co, prevco ) ) @@ -732,9 +732,9 @@ static void player_do_motion(void) /* * Free camera movement */ -static void player_mouseview(void) +VG_STATIC void player_mouseview(void) { - if( gui_want_mouse() ) + if( ui_want_mouse() ) return; static v2f mouse_last, @@ -757,7 +757,7 @@ static void player_mouseview(void) player.angles[1] = vg_clampf( player.angles[1], -VG_PIf*0.5f, VG_PIf*0.5f ); } -static void player_freecam(void) +VG_STATIC void player_freecam(void) { player_mouseview(); @@ -782,7 +782,7 @@ static void player_freecam(void) v3_add( move_vel, player.camera_pos, player.camera_pos ); } -static int reset_player( int argc, char const *argv[] ) +VG_STATIC int reset_player( int argc, char const *argv[] ) { struct player_phys *phys = &player.phys; struct respawn_point *rp = NULL, *r; diff --git a/player_ragdoll.h b/player_ragdoll.h index 28776c3..6193bf7 100644 --- a/player_ragdoll.h +++ b/player_ragdoll.h @@ -3,15 +3,16 @@ #include "player.h" -static float k_ragdoll_floatyiness = 20.0f, +VG_STATIC float k_ragdoll_floatyiness = 20.0f, k_ragdoll_floatydrag = 1.0f; /* * Setup ragdoll colliders */ -static void player_init_ragdoll( mdl_header *src ) +VG_STATIC void player_init_ragdoll(void) { struct player_model *mdl = &player.mdl; + mdl_context *src = &mdl->meta; if( !mdl->sk.collider_count ) { @@ -19,7 +20,6 @@ static void player_init_ragdoll( mdl_header *src ) return; } - mdl->ragdoll = vg_alloc(sizeof(struct ragdoll_part)*mdl->sk.collider_count); mdl->ragdoll_count = 0; for( u32 i=0; isk.bone_count; i ++ ) @@ -28,6 +28,9 @@ static void player_init_ragdoll( mdl_header *src ) if( bone->collider ) { + if( mdl->ragdoll_count > vg_list_size(player.mdl.ragdoll) ) + vg_fatal_exit_loop( "Playermodel has too many colliders" ); + struct ragdoll_part *rp = &mdl->ragdoll[ mdl->ragdoll_count ++ ]; rp->bone_id = i; @@ -73,7 +76,7 @@ static void player_init_ragdoll( mdl_header *src ) /* * Make the player model copy the ragdoll */ -static void player_model_copy_ragdoll(void) +VG_STATIC void player_model_copy_ragdoll(void) { struct player_model *mdl = &player.mdl; @@ -92,7 +95,7 @@ static void player_model_copy_ragdoll(void) /* * Make the ragdoll copy the player model */ -static void player_ragdoll_copy_model( v3f v ) +VG_STATIC void player_ragdoll_copy_model( v3f v ) { struct player_model *mdl = &player.mdl; @@ -117,7 +120,7 @@ static void player_ragdoll_copy_model( v3f v ) /* * Draw rigidbody colliders for ragdoll */ -static void player_debug_ragdoll(void) +VG_STATIC void player_debug_ragdoll(void) { struct player_model *mdl = &player.mdl; @@ -128,7 +131,7 @@ static void player_debug_ragdoll(void) /* * Ragdoll physics step */ -static void player_ragdoll_iter(void) +VG_STATIC void player_ragdoll_iter(void) { struct player_model *mdl = &player.mdl; rb_solver_reset(); diff --git a/render.h b/render.h index 8122b2a..209bed6 100644 --- a/render.h +++ b/render.h @@ -9,11 +9,11 @@ #include "shaders/standard.h" #include "shaders/vblend.h" -static void render_water_texture( m4x3f camera ); -static void render_water_surface( m4x4f pv, m4x3f camera ); -static void render_world( m4x4f projection, m4x3f camera ); -static void shader_link_standard_ub( GLuint shader, int texture_id ); -static void render_world_depth( m4x4f projection, m4x3f camera ); +VG_STATIC void render_water_texture( m4x3f camera ); +VG_STATIC void render_water_surface( m4x4f pv, m4x3f camera ); +VG_STATIC void render_world( m4x4f projection, m4x3f camera ); +VG_STATIC void shader_link_standard_ub( GLuint shader, int texture_id ); +VG_STATIC void render_world_depth( m4x4f projection, m4x3f camera ); #ifndef RENDER_H #define RENDER_H @@ -27,7 +27,7 @@ struct framebuffer int allocated; }; -static struct pipeline +VG_STATIC struct pipeline { float fov; glmesh fsquad; @@ -103,7 +103,7 @@ gpipeline = /* * http://www.terathon.com/lengyel/Lengyel-Oblique.pdf */ -static void plane_clip_projection( m4x4f mat, v4f plane ) +VG_STATIC void plane_clip_projection( m4x4f mat, v4f plane ) { v4f c = { @@ -121,7 +121,7 @@ static void plane_clip_projection( m4x4f mat, v4f plane ) mat[3][2] = c[3]; } -static void pipeline_projection( m4x4f mat, float nearz, float farz ) +VG_STATIC void pipeline_projection( m4x4f mat, float nearz, float farz ) { m4x4_projection( mat, gpipeline.fov, @@ -132,7 +132,7 @@ static void pipeline_projection( m4x4f mat, float nearz, float farz ) /* * Shaders */ -static void shader_link_standard_ub( GLuint shader, int texture_id ) +VG_STATIC void shader_link_standard_ub( GLuint shader, int texture_id ) { GLuint idx = glGetUniformBlockIndex( shader, "ub_world_lighting" ); glUniformBlockBinding( shader, idx, 0 ); @@ -142,7 +142,7 @@ static void shader_link_standard_ub( GLuint shader, int texture_id ) glUniform1i( glGetUniformLocation( shader, "g_world_depth" ), texture_id ); } -static void render_update_lighting_ub(void) +VG_STATIC void render_update_lighting_ub(void) { struct ub_world_lighting *winf = &gpipeline.ub_world_lighting; int c = 0; @@ -178,7 +178,7 @@ static void render_update_lighting_ub(void) * Framebuffers */ -static void fb_use( struct framebuffer *fb ) +VG_STATIC void fb_use( struct framebuffer *fb ) { if( !fb ) { @@ -192,7 +192,7 @@ static void fb_use( struct framebuffer *fb ) } } -static void fb_init( struct framebuffer *fb ) +VG_STATIC void fb_init( struct framebuffer *fb ) { i32 ix = vg.window_x / fb->div, iy = vg.window_y / fb->div; @@ -222,19 +222,19 @@ static void fb_init( struct framebuffer *fb ) fb->allocated = 1; } -static void fb_free( struct framebuffer *fb ) +VG_STATIC void fb_free( struct framebuffer *fb ) { glDeleteTextures( 1, &fb->colour ); glDeleteFramebuffers( 1, &fb->fb ); } -static void fb_bindtex( struct framebuffer *fb, int texture ) +VG_STATIC void fb_bindtex( struct framebuffer *fb, int texture ) { glActiveTexture( GL_TEXTURE0 + texture ); glBindTexture( GL_TEXTURE_2D, fb->colour ); } -static void fb_resize( struct framebuffer *fb ) +VG_STATIC void fb_resize( struct framebuffer *fb ) { if( !fb->allocated ) return; @@ -250,7 +250,7 @@ static void fb_resize( struct framebuffer *fb ) glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, ix, iy ); } -static void render_fb_resize(void) +VG_STATIC void render_fb_resize(void) { if( gpipeline.ready ) { @@ -261,7 +261,7 @@ static void render_fb_resize(void) } /* used for drawing player onto */ -static void render_init_temp_buffer(void) +VG_STATIC void render_init_temp_buffer(void) { vg_info( "[render] Allocate temporary framebuffer\n" ); @@ -284,7 +284,7 @@ static void render_init_temp_buffer(void) /* used for drawing world depth from the top view, used in our water and * lighting calculations */ -static void render_init_depthmap_buffer(void) +VG_STATIC void render_init_depthmap_buffer(void) { vg_info( "[render] Allocate depth map buffer\n" ); @@ -306,7 +306,7 @@ static void render_init_depthmap_buffer(void) VG_CHECK_GL_ERR(); } -static void render_init_fs_quad(void) +VG_STATIC void render_init_fs_quad(void) { vg_info( "[render] Allocate quad\n" ); @@ -326,7 +326,7 @@ static void render_init_fs_quad(void) VG_CHECK_GL_ERR(); } -static void render_init_uniform_buffers(void) +VG_STATIC void render_init_uniform_buffers(void) { vg_info( "[render] Allocate uniform buffer\n" ); @@ -341,7 +341,7 @@ static void render_init_uniform_buffers(void) VG_CHECK_GL_ERR(); } -static void render_init(void) +VG_STATIC void render_init(void) { shader_blit_register(); shader_standard_register(); @@ -361,24 +361,10 @@ static void render_init(void) vg_release_thread_sync(); } -static void render_free(void *_) -{ - glDeleteBuffers( 1, &gpipeline.ubo_world_lighting ); - - glDeleteVertexArrays( 1, &gpipeline.fsquad.vao ); - glDeleteBuffers( 1, &gpipeline.fsquad.vbo ); - - glDeleteFramebuffers( 1, &gpipeline.fb_depthmap ); - glDeleteTextures( 1, &gpipeline.rgb_depthmap ); - - glDeleteFramebuffers( 1, &gpipeline.fb_background ); - glDeleteTextures( 1, &gpipeline.rgb_background ); -} - /* * Utility */ -static void render_fsquad(void) +VG_STATIC void render_fsquad(void) { glBindVertexArray( gpipeline.fsquad.vao ); glDrawArrays( GL_TRIANGLES, 0, 6 ); diff --git a/rigidbody.h b/rigidbody.h index b9b863a..94ad181 100644 --- a/rigidbody.h +++ b/rigidbody.h @@ -11,8 +11,8 @@ #include "bvh.h" #include "scene.h" -static void rb_tangent_basis( v3f n, v3f tx, v3f ty ); -static bh_system bh_system_rigidbodies; +VG_STATIC void rb_tangent_basis( v3f n, v3f tx, v3f ty ); +VG_STATIC bh_system bh_system_rigidbodies; #ifndef RIGIDBODY_H #define RIGIDBODY_H @@ -23,7 +23,7 @@ static bh_system bh_system_rigidbodies; * ----------------------------------------------------------------------------- */ -static const float +VG_STATIC const float k_rb_rate = (1.0/VG_TIMESTEP_FIXED), k_rb_delta = (1.0/k_rb_rate), k_friction = 0.6f, @@ -74,7 +74,7 @@ struct rigidbody struct rb_scene { - scene *pscene; + bh_tree *bh_scene; } scene; } @@ -94,7 +94,7 @@ struct rigidbody m4x3f to_world, to_local; }; -static struct contact +VG_STATIC struct contact { rigidbody *rba, *rbb; v3f co, n; @@ -105,7 +105,7 @@ static struct contact u32 element_id; } rb_contact_buffer[256]; -static int rb_contact_count = 0; +VG_STATIC int rb_contact_count = 0; /* * ----------------------------------------------------------------------------- @@ -113,13 +113,13 @@ static int rb_contact_count = 0; * ----------------------------------------------------------------------------- */ -static float sphere_volume( float radius ) +VG_STATIC float sphere_volume( float radius ) { float r3 = radius*radius*radius; return (4.0f/3.0f) * VG_PIf * r3; } -static void rb_tangent_basis( v3f n, v3f tx, v3f ty ) +VG_STATIC void rb_tangent_basis( v3f n, v3f tx, v3f ty ) { /* Compute tangent basis (box2d) */ if( fabsf( n[0] ) >= 0.57735027f ) @@ -145,7 +145,7 @@ static void rb_tangent_basis( v3f n, v3f tx, v3f ty ) * ----------------------------------------------------------------------------- */ -static void rb_debug_contact( rb_ct *ct ) +VG_STATIC void rb_debug_contact( rb_ct *ct ) { v3f p1; v3_muladds( ct->co, ct->n, 0.1f, p1 ); @@ -153,7 +153,7 @@ static void rb_debug_contact( rb_ct *ct ) vg_line( ct->co, p1, 0xffffffff ); } -static void debug_sphere( m4x3f m, float radius, u32 colour ) +VG_STATIC void debug_sphere( m4x3f m, float radius, u32 colour ) { v3f ly = { 0.0f, 0.0f, radius }, lx = { 0.0f, radius, 0.0f }, @@ -187,7 +187,7 @@ static void debug_sphere( m4x3f m, float radius, u32 colour ) } } -static void debug_capsule( m4x3f m, float radius, float h, u32 colour ) +VG_STATIC void debug_capsule( m4x3f m, float radius, float h, u32 colour ) { v3f ly = { 0.0f, 0.0f, radius }, lx = { 0.0f, radius, 0.0f }, @@ -269,7 +269,7 @@ static void debug_capsule( m4x3f m, float radius, float h, u32 colour ) } } -static void rb_debug( rigidbody *rb, u32 colour ) +VG_STATIC void rb_debug( rigidbody *rb, u32 colour ) { if( rb->type == k_rb_shape_box ) { @@ -303,7 +303,7 @@ static void rb_debug( rigidbody *rb, u32 colour ) /* * Update world space bounding box based on local one */ -static void rb_update_bounds( rigidbody *rb ) +VG_STATIC void rb_update_bounds( rigidbody *rb ) { box_copy( rb->bbx, rb->bbx_world ); m4x3_transform_aabb( rb->to_world, rb->bbx_world ); @@ -312,7 +312,7 @@ static void rb_update_bounds( rigidbody *rb ) /* * Commit transform to rigidbody. Updates matrices */ -static void rb_update_transform( rigidbody *rb ) +VG_STATIC void rb_update_transform( rigidbody *rb ) { q_normalize( rb->q ); q_m3x3( rb->q, rb->to_world ); @@ -334,7 +334,7 @@ static void rb_update_transform( rigidbody *rb ) * Extrapolate rigidbody into a transform based on vg accumulator. * Useful for rendering */ -static void rb_extrapolate_transform( rigidbody *rb, m4x3f transform ) +VG_STATIC void rb_extrapolate_transform( rigidbody *rb, m4x3f transform ) { float substep = vg_clampf( vg.accumulator / k_rb_delta, 0.0f, 1.0f ); @@ -367,7 +367,7 @@ static void rb_extrapolate_transform( rigidbody *rb, m4x3f transform ) /* * Initialize rigidbody and calculate masses, inertia */ -static void rb_init( rigidbody *rb ) +VG_STATIC void rb_init( rigidbody *rb ) { float volume = 1.0f; @@ -397,7 +397,7 @@ static void rb_init( rigidbody *rb ) else if( rb->type == k_rb_shape_scene ) { rb->is_world = 1; - box_copy( rb->inf.scene.pscene->bbx, rb->bbx ); + box_copy( rb->inf.scene.bh_scene->nodes[0].bbx, rb->bbx ); } if( rb->is_world ) @@ -438,7 +438,7 @@ static void rb_init( rigidbody *rb ) rb_update_transform( rb ); } -static void rb_iter( rigidbody *rb ) +VG_STATIC void rb_iter( rigidbody *rb ) { v3f gravity = { 0.0f, -9.8f, 0.0f }; v3_muladds( rb->v, gravity, k_rb_delta, rb->v ); @@ -475,7 +475,7 @@ static void rb_iter( rigidbody *rb ) * These closest point tests were learned from Real-Time Collision Detection by * Christer Ericson */ -static float closest_segment_segment( v3f p1, v3f q1, v3f p2, v3f q2, +VG_STATIC float closest_segment_segment( v3f p1, v3f q1, v3f p2, v3f q2, float *s, float *t, v3f c1, v3f c2) { v3f d1,d2,r; @@ -552,13 +552,13 @@ static float closest_segment_segment( v3f p1, v3f q1, v3f p2, v3f q2, return v3_length2( v0 ); } -static void closest_point_aabb( v3f p, boxf box, v3f dest ) +VG_STATIC void closest_point_aabb( v3f p, boxf box, v3f dest ) { v3_maxv( p, box[0], dest ); v3_minv( dest, box[1], dest ); } -static void closest_point_obb( v3f p, rigidbody *rb, v3f dest ) +VG_STATIC void closest_point_obb( v3f p, rigidbody *rb, v3f dest ) { v3f local; m4x3_mulv( rb->to_local, p, local ); @@ -566,7 +566,7 @@ static void closest_point_obb( v3f p, rigidbody *rb, v3f dest ) m4x3_mulv( rb->to_world, local, dest ); } -static float closest_point_segment( v3f a, v3f b, v3f point, v3f dest ) +VG_STATIC float closest_point_segment( v3f a, v3f b, v3f point, v3f dest ) { v3f v0, v1; v3_sub( b, a, v0 ); @@ -578,7 +578,7 @@ static float closest_point_segment( v3f a, v3f b, v3f point, v3f dest ) return t; } -static void closest_on_triangle( v3f p, v3f tri[3], v3f dest ) +VG_STATIC void closest_on_triangle( v3f p, v3f tri[3], v3f dest ) { v3f ab, ac, ap; float d1, d2; @@ -667,7 +667,7 @@ static void closest_on_triangle( v3f p, v3f tri[3], v3f dest ) v3_muladds( dest, ac, w, dest ); } -static void closest_on_triangle_1( v3f p, v3f tri[3], v3f dest ) +VG_STATIC void closest_on_triangle_1( v3f p, v3f tri[3], v3f dest ) { v3f ab, ac, ap; float d1, d2; @@ -759,7 +759,7 @@ static void closest_on_triangle_1( v3f p, v3f tri[3], v3f dest ) /* * Project AABB, and triangle interval onto axis to check if they overlap */ -static int rb_box_triangle_interval( v3f extent, v3f axis, v3f tri[3] ) +VG_STATIC int rb_box_triangle_interval( v3f extent, v3f axis, v3f tri[3] ) { float @@ -780,7 +780,7 @@ static int rb_box_triangle_interval( v3f extent, v3f axis, v3f tri[3] ) /* * Seperating axis test box vs triangle */ -static int rb_box_triangle_sat( rigidbody *rba, v3f tri_src[3] ) +VG_STATIC int rb_box_triangle_sat( rigidbody *rba, v3f tri_src[3] ) { v3f tri[3]; @@ -870,7 +870,7 @@ struct capsule_manifold * Expand a line manifold with a new pair. t value is the time along segment * on the oriented object which created this pair. */ -static void rb_capsule_manifold( v3f pa, v3f pb, float t, float r, +VG_STATIC void rb_capsule_manifold( v3f pa, v3f pb, float t, float r, capsule_manifold *manifold ) { v3f delta; @@ -894,13 +894,13 @@ static void rb_capsule_manifold( v3f pa, v3f pb, float t, float r, } } -static void rb_capsule_manifold_init( capsule_manifold *manifold ) +VG_STATIC void rb_capsule_manifold_init( capsule_manifold *manifold ) { manifold->t0 = INFINITY; manifold->t1 = -INFINITY; } -static int rb_capsule_manifold_done( rigidbody *rba, rigidbody *rbb, +VG_STATIC int rb_capsule_manifold_done( rigidbody *rba, rigidbody *rbb, capsule_manifold *manifold, rb_ct *buf ) { float h = rba->inf.capsule.height, @@ -959,7 +959,7 @@ static int rb_capsule_manifold_done( rigidbody *rba, rigidbody *rbb, return count; } -static int rb_capsule_sphere( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) +VG_STATIC int rb_capsule_sphere( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) { float h = rba->inf.capsule.height, ra = rba->inf.capsule.radius, @@ -999,7 +999,7 @@ static int rb_capsule_sphere( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) return 0; } -static int rb_capsule_capsule( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) +VG_STATIC int rb_capsule_capsule( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) { float ha = rba->inf.capsule.height, hb = rbb->inf.capsule.height, @@ -1037,7 +1037,7 @@ static int rb_capsule_capsule( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) /* * Generates up to two contacts; optimised for the most stable manifold */ -static int rb_capsule_box( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) +VG_STATIC int rb_capsule_box( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) { float h = rba->inf.capsule.height, r = rba->inf.capsule.radius; @@ -1161,7 +1161,7 @@ static int rb_capsule_box( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) return rb_capsule_manifold_done( rba, rbb, &manifold, buf ); } -static int rb_sphere_box( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) +VG_STATIC int rb_sphere_box( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) { v3f co, delta; @@ -1218,7 +1218,7 @@ static int rb_sphere_box( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) return 0; } -static int rb_sphere_sphere( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) +VG_STATIC int rb_sphere_sphere( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) { v3f delta; v3_sub( rba->co, rbb->co, delta ); @@ -1247,7 +1247,7 @@ static int rb_sphere_sphere( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) return 0; } -static int rb_sphere_triangle( rigidbody *rba, rigidbody *rbb, +VG_STATIC int rb_sphere_triangle( rigidbody *rba, rigidbody *rbb, v3f tri[3], rb_ct *buf ) { v3f delta, co; @@ -1284,22 +1284,22 @@ static int rb_sphere_triangle( rigidbody *rba, rigidbody *rbb, return 0; } -static int rb_sphere_scene( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) +VG_STATIC int rb_sphere_scene( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) { - scene *sc = rbb->inf.scene.pscene; + scene *sc = rbb->inf.scene.bh_scene->user; u32 geo[128]; v3f tri[3]; - int len = bh_select( &sc->bhtris, rba->bbx_world, geo, 128 ); + int len = bh_select( rbb->inf.scene.bh_scene, rba->bbx_world, geo, 128 ); int count = 0; for( int i=0; iindices[ geo[i]*3 ]; + u32 *ptri = &sc->arrindices[ geo[i]*3 ]; for( int j=0; j<3; j++ ) - v3_copy( sc->verts[ptri[j]].co, tri[j] ); + v3_copy( sc->arrvertices[ptri[j]].co, tri[j] ); vg_line(tri[0],tri[1],0xff00ff00 ); vg_line(tri[1],tri[2],0xff00ff00 ); @@ -1318,22 +1318,22 @@ static int rb_sphere_scene( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) return count; } -static int rb_box_scene( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) +VG_STATIC int rb_box_scene( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) { - scene *sc = rbb->inf.scene.pscene; + scene *sc = rbb->inf.scene.bh_scene->user; u32 geo[128]; v3f tri[3]; - int len = bh_select( &sc->bhtris, rba->bbx_world, geo, 128 ); + int len = bh_select( rbb->inf.scene.bh_scene, rba->bbx_world, geo, 128 ); int count = 0; for( int i=0; iindices[ geo[i]*3 ]; + u32 *ptri = &sc->arrindices[ geo[i]*3 ]; for( int j=0; j<3; j++ ) - v3_copy( sc->verts[ptri[j]].co, tri[j] ); + v3_copy( sc->arrvertices[ptri[j]].co, tri[j] ); if( rb_box_triangle_sat( rba, tri ) ) { @@ -1458,7 +1458,7 @@ static int rb_box_scene( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) return count; } -static int RB_MATRIX_ERROR( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) +VG_STATIC int RB_MATRIX_ERROR( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) { vg_error( "Collision type is unimplemented between types %d and %d\n", rba->type, rbb->type ); @@ -1466,27 +1466,27 @@ static int RB_MATRIX_ERROR( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) return 0; } -static int rb_sphere_capsule( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) +VG_STATIC int rb_sphere_capsule( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) { return rb_capsule_sphere( rbb, rba, buf ); } -static int rb_box_capsule( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) +VG_STATIC int rb_box_capsule( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) { return rb_capsule_box( rbb, rba, buf ); } -static int rb_box_sphere( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) +VG_STATIC int rb_box_sphere( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) { return rb_sphere_box( rbb, rba, buf ); } -static int rb_scene_box( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) +VG_STATIC int rb_scene_box( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) { return rb_box_scene( rbb, rba, buf ); } -static int (*rb_jump_table[4][4])( rigidbody *a, rigidbody *b, rb_ct *buf ) = +VG_STATIC int (*rb_jump_table[4][4])( rigidbody *a, rigidbody *b, rb_ct *buf ) = { /* box */ /* Sphere */ /* Capsule */ /* Mesh */ { RB_MATRIX_ERROR, rb_box_sphere, rb_box_capsule, rb_box_scene }, @@ -1495,7 +1495,7 @@ static int (*rb_jump_table[4][4])( rigidbody *a, rigidbody *b, rb_ct *buf ) = { rb_scene_box, RB_MATRIX_ERROR, RB_MATRIX_ERROR, RB_MATRIX_ERROR } }; -static int rb_collide( rigidbody *rba, rigidbody *rbb ) +VG_STATIC int rb_collide( rigidbody *rba, rigidbody *rbb ) { int (*collider_jump)(rigidbody *rba, rigidbody *rbb, rb_ct *buf ) = rb_jump_table[rba->type][rbb->type]; @@ -1530,12 +1530,12 @@ static int rb_collide( rigidbody *rba, rigidbody *rbb ) * ----------------------------------------------------------------------------- */ -static void rb_solver_reset(void) +VG_STATIC void rb_solver_reset(void) { rb_contact_count = 0; } -static rb_ct *rb_global_ct(void) +VG_STATIC rb_ct *rb_global_ct(void) { return rb_contact_buffer + rb_contact_count; } @@ -1543,7 +1543,7 @@ static rb_ct *rb_global_ct(void) /* * Initializing things like tangent vectors */ -static void rb_presolve_contacts( rb_ct *buffer, int len ) +VG_STATIC void rb_presolve_contacts( rb_ct *buffer, int len ) { for( int i=0; irba, *rbb = ct->rbb; @@ -1612,7 +1612,7 @@ static void rb_rcv( rb_ct *ct, v3f rv, v3f da, v3f db ) /* * Apply impulse to object */ -static void rb_linear_impulse( rigidbody *rb, v3f delta, v3f impulse ) +VG_STATIC void rb_linear_impulse( rigidbody *rb, v3f delta, v3f impulse ) { /* linear */ v3_muladds( rb->v, impulse, rb->inv_mass, rb->v ); @@ -1628,7 +1628,7 @@ static void rb_linear_impulse( rigidbody *rb, v3f delta, v3f impulse ) /* * One iteration to solve the contact constraint */ -static void rb_solve_contacts( rb_ct *buf, int len ) +VG_STATIC void rb_solve_contacts( rb_ct *buf, int len ) { for( int i=0; ibbx_world ); } -static float rb_bh_centroid( void *user, u32 item_index, int axis ) +VG_STATIC float rb_bh_centroid( void *user, u32 item_index, int axis ) { rigidbody *rb = &((rigidbody *)user)[ item_index ]; return (rb->bbx_world[axis][0] + rb->bbx_world[1][axis]) * 0.5f; } -static void rb_bh_swap( void *user, u32 ia, u32 ib ) +VG_STATIC void rb_bh_swap( void *user, u32 ia, u32 ib ) { rigidbody temp, *rba, *rbb; rba = &((rigidbody *)user)[ ia ]; @@ -1936,13 +1936,13 @@ static void rb_bh_swap( void *user, u32 ia, u32 ib ) *rbb = temp; } -static void rb_bh_debug( void *user, u32 item_index ) +VG_STATIC void rb_bh_debug( void *user, u32 item_index ) { rigidbody *rb = &((rigidbody *)user)[ item_index ]; rb_debug( rb, 0xff00ffff ); } -static bh_system bh_system_rigidbodies = +VG_STATIC bh_system bh_system_rigidbodies = { .expand_bound = rb_bh_expand_bound, .item_centroid = rb_bh_centroid, diff --git a/scene.h b/scene.h index a4f6bd1..51ce103 100644 --- a/scene.h +++ b/scene.h @@ -9,70 +9,89 @@ typedef struct scene scene; struct scene { - glmesh mesh; + mdl_vert *arrvertices; + u32 *arrindices; - mdl_vert *verts; - u32 *indices; - - bh_tree bhtris; - u32 vertex_count, - indice_count, - vertex_cap, - indice_cap; + u32 vertex_count, indice_count, + max_vertices, max_indices; boxf bbx; - - u32 shadower_count, - shadower_cap; - mdl_submesh submesh; }; -static void scene_init( scene *pscene ) +/* Initialize a scene description with bounded buffers */ +VG_STATIC scene *scene_init( void *lin_alloc, u32 max_verts, u32 max_indices ) { - pscene->verts = NULL; - pscene->indices = NULL; + u32 vertex_length = max_verts * sizeof(mdl_vert), + index_length = max_indices * sizeof(u32), + tot_size = sizeof(scene) + vertex_length + index_length; + + scene *pscene = vg_linear_alloc( lin_alloc, tot_size ); + + pscene->arrvertices = (mdl_vert *)(pscene+1); + pscene->arrindices = (u32 *)( pscene->arrvertices + max_verts ); + pscene->vertex_count = 0; pscene->indice_count = 0; - pscene->shadower_count = 0; - pscene->shadower_cap = 0; + pscene->max_vertices = max_verts; + pscene->max_indices = max_indices; + pscene->submesh.indice_start = 0; pscene->submesh.indice_count = 0; v3_fill( pscene->bbx[0], 999999.9f ); v3_fill( pscene->bbx[1], -999999.9f ); + + return pscene; } /* * Append a model into the scene with a given transform */ -static void scene_add_submesh( scene *pscene, mdl_header *mdl, - mdl_submesh *sm, m4x3f transform ) +VG_STATIC void scene_add_submesh( scene *pscene, mdl_context *mdl, + mdl_submesh *sm, m4x3f transform ) { - pscene->verts = buffer_reserve( pscene->verts, pscene->vertex_count, - &pscene->vertex_cap, sm->vertex_count, sizeof(mdl_vert) ); + if( pscene->vertex_count + sm->vertex_count > pscene->max_vertices ) + { + vg_error( "%u(current) + %u > %u\n", pscene->vertex_count, + sm->vertex_count, + pscene->max_vertices ); - pscene->indices = buffer_reserve( pscene->indices, pscene->indice_count, - &pscene->indice_cap, sm->indice_count, sizeof(u32) ); + vg_warn( "%p ... %p\n", pscene, sm ); + vg_fatal_exit_loop( "Scene vertex buffer overflow" ); + } - m3x3f normal_matrix; - m3x3_copy( transform, normal_matrix ); - v3_normalize( normal_matrix[0] ); - v3_normalize( normal_matrix[1] ); - v3_normalize( normal_matrix[2] ); + if( pscene->indice_count + sm->indice_count > pscene->max_indices ) + { + vg_error( "%u(current) + %u > %u\n", pscene->indice_count, + sm->indice_count, + pscene->max_indices ); + vg_warn( "%p ... %p\n", pscene, sm ); + + vg_fatal_exit_loop( "Scene index buffer overflow" ); + } + + mdl_vert *src_verts = mdl_submesh_vertices( mdl, sm ), + *dst_verts = &pscene->arrvertices[ pscene->vertex_count ]; + + u32 *src_indices = mdl_submesh_indices( mdl, sm ), + *dst_indices = &pscene->arrindices[ pscene->indice_count ]; /* Transform and place vertices */ - mdl_vert *src_verts = mdl_submesh_vertices( mdl, sm ); - u32 *src_indices = mdl_submesh_indices( mdl, sm ); - boxf bbxnew; box_copy( sm->bbx, bbxnew ); m4x3_transform_aabb( transform, bbxnew ); box_concat( pscene->bbx, bbxnew ); + + m3x3f normal_matrix; + m3x3_copy( transform, normal_matrix ); + v3_normalize( normal_matrix[0] ); + v3_normalize( normal_matrix[1] ); + v3_normalize( normal_matrix[2] ); for( u32 i=0; ivertex_count; i++ ) { - mdl_vert *pvert = &pscene->verts[ pscene->vertex_count+i ], + mdl_vert *pvert = &dst_verts[ i ], *src = &src_verts[ i ]; m4x3_mulv( transform, src->co, pvert->co ); @@ -87,23 +106,24 @@ static void scene_add_submesh( scene *pscene, mdl_header *mdl, for( u32 i=0; iindice_count; i++ ) { - u32 *pidx = &pscene->indices[ pscene->indice_count+i ]; - *pidx = src_indices[i] + pscene->vertex_count; + dst_indices[i] = src_indices[i] + pscene->vertex_count; } pscene->vertex_count += sm->vertex_count; pscene->indice_count += sm->indice_count; + } /* * One by one adders for simplified access (mostly procedural stuff) */ -static void scene_push_tri( scene *pscene, u32 tri[3] ) +VG_STATIC void scene_push_tri( scene *pscene, u32 tri[3] ) { - pscene->indices = buffer_reserve( pscene->indices, pscene->indice_count, - &pscene->indice_cap, 3, sizeof(u32) ); + if( pscene->indice_count + 3 > pscene->max_indices ) + vg_fatal_exit_loop( "Scene vertex buffer overflow" ); + + u32 *dst = &pscene->arrindices[ pscene->indice_count ]; - u32 *dst = &pscene->indices[pscene->indice_count]; dst[0] = tri[0]; dst[1] = tri[1]; dst[2] = tri[2]; @@ -111,14 +131,18 @@ static void scene_push_tri( scene *pscene, u32 tri[3] ) pscene->indice_count += 3; } -static void scene_push_vert( scene *pscene, mdl_vert *v ) +VG_STATIC void scene_push_vert( scene *pscene, mdl_vert *v ) { - pscene->verts = buffer_reserve( pscene->verts, pscene->vertex_count, - &pscene->vertex_cap, 1, sizeof(mdl_vert) ); - pscene->verts[pscene->vertex_count ++] = *v; + if( pscene->vertex_count + 1 > pscene->max_vertices ) + vg_fatal_exit_loop( "Scene vertex buffer overflow" ); + + mdl_vert *dst = &pscene->arrvertices[ pscene->vertex_count ]; + *dst = *v; + + pscene->vertex_count ++; } -static void scene_copy_slice( scene *pscene, mdl_submesh *sm ) +VG_STATIC void scene_copy_slice( scene *pscene, mdl_submesh *sm ) { sm->indice_start = pscene->submesh.indice_start; sm->indice_count = pscene->indice_count - sm->indice_start; @@ -130,79 +154,99 @@ static void scene_copy_slice( scene *pscene, mdl_submesh *sm ) pscene->submesh.vertex_start = pscene->vertex_count; } -static void scene_fix( scene *pscene ) +/* finalization: tightly pack data */ +__attribute__((warn_unused_result)) +VG_STATIC scene *scene_fix( void *lin_alloc, scene *pscene ) { - buffer_fix( pscene->verts, pscene->vertex_count, - &pscene->vertex_cap, sizeof( mdl_vert )); + u32 vertex_length = pscene->vertex_count * sizeof(mdl_vert), + index_length = pscene->indice_count * sizeof(u32), + tot_size = sizeof(scene) + vertex_length + index_length; - buffer_fix( pscene->indices, pscene->indice_count, - &pscene->indice_cap, sizeof( mdl_vert )); -} + scene *src_scene = pscene; + mdl_vert *src_verts = pscene->arrvertices; + u32 *src_indices = pscene->arrindices; -static void scene_upload( scene *pscene ) -{ - mesh_upload( &pscene->mesh, - pscene->verts, pscene->vertex_count, - pscene->indices, pscene->indice_count ); + scene *dst_scene = vg_linear_resize( lin_alloc, pscene, tot_size ); + memcpy( dst_scene, src_scene, sizeof(scene) ); - vg_info( "Scene upload\n" ); - vg_info( " indices:%u\n", pscene->indice_count ); - vg_info( " verts:%u\n", pscene->vertex_count ); -} + void *dst_verts = dst_scene+1, + *dst_indices = dst_verts + vertex_length; -static void scene_bind( scene *pscene ) -{ - mesh_bind( &pscene->mesh ); -} + memcpy( dst_verts, src_verts, vertex_length ); + memcpy( dst_indices, src_indices, index_length ); -static void scene_draw( scene *pscene ) -{ - mesh_drawn( 0, pscene->indice_count ); + dst_scene->arrvertices = dst_verts; + dst_scene->arrindices = dst_indices; + dst_scene->max_vertices = pscene->vertex_count; + dst_scene->max_indices = pscene->indice_count; + + return dst_scene; } -static void scene_free_offline_buffers( scene *pscene ) +#if 0 +/* finalization: delete any offline buffers and reduce size */ +__attribute__((warn_unused_result)) +VG_STATIC scene *scene_free_offline_buffers( void *lin_alloc, scene *pscene ) { - vg_free( pscene->verts ); - vg_free( pscene->indices ); + u32 tot_size = sizeof(scene); + + scene *src_scene = pscene; + mdl_vert *src_verts = pscene->arrvertices; + u32 *src_indices = pscene->arrindices; + + scene *dst_scene = vg_linear_resize( lin_alloc, pscene, tot_size ); + memcpy( dst_scene, src_scene, sizeof(scene) ); + + dst_scene->arrindices = NULL; + dst_scene->arrvertices = NULL; + + return dst_scene; } +#endif -static void scene_free( scene *pscene ) +VG_STATIC void scene_upload( scene *pscene, glmesh *mesh ) { - scene_free_offline_buffers( pscene ); + mesh_upload( mesh, + pscene->arrvertices, pscene->vertex_count, + pscene->arrindices, pscene->indice_count ); + + vg_info( "Scene upload\n" ); + vg_info( " indices:%u\n", pscene->indice_count ); + vg_info( " verts:%u\n", pscene->vertex_count ); } /* * BVH implementation */ -static void scene_bh_expand_bound( void *user, boxf bound, u32 item_index ) +VG_STATIC void scene_bh_expand_bound( void *user, boxf bound, u32 item_index ) { scene *s = user; - mdl_vert *pa = &s->verts[ s->indices[item_index*3+0] ], - *pb = &s->verts[ s->indices[item_index*3+1] ], - *pc = &s->verts[ s->indices[item_index*3+2] ]; + mdl_vert *pa = &s->arrvertices[ s->arrindices[item_index*3+0] ], + *pb = &s->arrvertices[ s->arrindices[item_index*3+1] ], + *pc = &s->arrvertices[ s->arrindices[item_index*3+2] ]; box_addpt( bound, pa->co ); box_addpt( bound, pb->co ); box_addpt( bound, pc->co ); } -static float scene_bh_centroid( void *user, u32 item_index, int axis ) +VG_STATIC float scene_bh_centroid( void *user, u32 item_index, int axis ) { scene *s = user; - mdl_vert *pa = &s->verts[ s->indices[item_index*3+0] ], - *pb = &s->verts[ s->indices[item_index*3+1] ], - *pc = &s->verts[ s->indices[item_index*3+2] ]; + mdl_vert *pa = &s->arrvertices[ s->arrindices[item_index*3+0] ], + *pb = &s->arrvertices[ s->arrindices[item_index*3+1] ], + *pc = &s->arrvertices[ s->arrindices[item_index*3+2] ]; return (pa->co[axis] + pb->co[axis] + pc->co[axis]) * (1.0f/3.0f); } -static void scene_bh_swap( void *user, u32 ia, u32 ib ) +VG_STATIC void scene_bh_swap( void *user, u32 ia, u32 ib ) { scene *s = user; - u32 *ti = &s->indices[ia*3]; - u32 *tj = &s->indices[ib*3]; + u32 *ti = &s->arrindices[ia*3]; + u32 *tj = &s->arrindices[ib*3]; u32 temp[3]; temp[0] = ti[0]; @@ -218,28 +262,29 @@ static void scene_bh_swap( void *user, u32 ia, u32 ib ) tj[2] = temp[2]; } -static void scene_bh_debug( void *user, u32 item_index ) +VG_STATIC void scene_bh_debug( void *user, u32 item_index ) { scene *s = user; u32 idx = item_index*3; - mdl_vert *pa = &s->verts[ s->indices[ idx+0 ] ], - *pb = &s->verts[ s->indices[ idx+1 ] ], - *pc = &s->verts[ s->indices[ idx+2 ] ]; + mdl_vert *pa = &s->arrvertices[ s->arrindices[ idx+0 ] ], + *pb = &s->arrvertices[ s->arrindices[ idx+1 ] ], + *pc = &s->arrvertices[ s->arrindices[ idx+2 ] ]; vg_line( pa->co, pb->co, 0xff0000ff ); vg_line( pb->co, pc->co, 0xff0000ff ); vg_line( pc->co, pa->co, 0xff0000ff ); } -static int scene_bh_ray( void *user, u32 index, v3f co, v3f dir, ray_hit *hit ) +VG_STATIC int scene_bh_ray( void *user, u32 index, v3f co, + v3f dir, ray_hit *hit ) { scene *s = user; v3f positions[3]; - u32 *tri = &s->indices[ index*3 ]; + u32 *tri = &s->arrindices[ index*3 ]; for( int i=0; i<3; i++ ) - v3_copy( s->verts[tri[i]].co, positions[i] ); + v3_copy( s->arrvertices[tri[i]].co, positions[i] ); float t; if(ray_tri( positions, co, dir, &t )) @@ -255,7 +300,7 @@ static int scene_bh_ray( void *user, u32 index, v3f co, v3f dir, ray_hit *hit ) return 0; } -static bh_system bh_system_scene = +VG_STATIC bh_system bh_system_scene = { .expand_bound = scene_bh_expand_bound, .item_centroid = scene_bh_centroid, @@ -267,17 +312,18 @@ static bh_system bh_system_scene = /* * An extra step is added onto the end to calculate the hit normal */ -static int scene_raycast( scene *s, v3f co, v3f dir, ray_hit *hit ) +VG_STATIC int scene_raycast( scene *s, bh_tree *bh, + v3f co, v3f dir, ray_hit *hit ) { - int count = bh_ray( &s->bhtris, 0, co, dir, hit ); + int count = bh_ray( bh, co, dir, hit ); if( count ) { v3f v0, v1; - float *pa = s->verts[hit->tri[0]].co, - *pb = s->verts[hit->tri[1]].co, - *pc = s->verts[hit->tri[2]].co; + float *pa = s->arrvertices[hit->tri[0]].co, + *pb = s->arrvertices[hit->tri[1]].co, + *pc = s->arrvertices[hit->tri[2]].co; v3_sub( pa, pb, v0 ); v3_sub( pc, pb, v1 ); @@ -289,10 +335,10 @@ static int scene_raycast( scene *s, v3f co, v3f dir, ray_hit *hit ) return count; } -static void scene_bh_create( scene *s ) +VG_STATIC bh_tree *scene_bh_create( void *lin_alloc, scene *s ) { u32 triangle_count = s->indice_count / 3; - bh_create( &s->bhtris, &bh_system_scene, s, triangle_count ); + return bh_create( lin_alloc, &bh_system_scene, s, triangle_count ); } #endif diff --git a/server.c b/server.c index d5d5d91..dfe8be8 100644 --- a/server.c +++ b/server.c @@ -36,6 +36,7 @@ static void *hSteamHTTP, static u8 steam_symetric_key[ k_nSteamEncryptedAppTicketSymmetricKeyLen ]; static HSteamNetPollGroup client_pollgroup; +#if 0 static void recieve_http( void *callresult, void *context ) { HTTPRequestCompleted_t *result = callresult; @@ -55,6 +56,7 @@ static void recieve_http( void *callresult, void *context ) vg_free( buffer ); SteamAPI_ISteamHTTP_ReleaseHTTPRequest( hSteamHTTP, result->m_hRequest ); } +#endif static u64_steamid get_connection_authsteamid( SteamNetworkingMessage_t *msg ) { @@ -335,7 +337,9 @@ int main( int argc, char *argv[] ) /* TODO: Options to override, ammend, remove etc */ + vg_prealloc_quota( 80*1024*1024 ); highscores_init( 250000, 10000 ); + if( !highscores_read() ) highscores_create_db(); @@ -424,7 +428,6 @@ int main( int argc, char *argv[] ) } highscores_serialize_all(); - highscores_free(); SteamAPI_ISteamNetworkingSockets_DestroyPollGroup( hSteamNetworkingSockets, client_pollgroup ); diff --git a/skeleton.h b/skeleton.h index 78a0b56..9f715ef 100644 --- a/skeleton.h +++ b/skeleton.h @@ -24,9 +24,22 @@ struct skeleton int collider; boxf hitbox; - char name[16]; + const char *name; } *bones; + u32 bone_count; + + struct skeleton_anim + { + const char *name; + u32 length; + + float rate; + mdl_keyframe *anim_data; + } + *anims; + u32 anim_count; + m4x3f *final_mtx; struct skeleton_ik @@ -35,28 +48,16 @@ struct skeleton m3x3f ia, ib; } *ik; + u32 ik_count; - struct skeleton_anim - { - float rate; - u32 length; - struct mdl_keyframe *anim_data; - char name[32]; - } - *anims; - - u32 bone_count, - ik_count, + u32 collider_count, - anim_count, - bindable_count; /* TODO: try to place IK last in the rig from export - so that we dont always upload transforms for - useless cpu IK bones. */ + bindable_count; }; -static u32 skeleton_bone_id( struct skeleton *skele, const char *name ) +VG_STATIC u32 skeleton_bone_id( struct skeleton *skele, const char *name ) { - for( u32 i=0; ibone_count; i++ ) + for( u32 i=1; ibone_count; i++ ) { if( !strcmp( skele->bones[i].name, name )) return i; @@ -65,7 +66,7 @@ static u32 skeleton_bone_id( struct skeleton *skele, const char *name ) return 0; } -static void keyframe_copy_pose( mdl_keyframe *kfa, mdl_keyframe *kfb, int num ) +VG_STATIC void keyframe_copy_pose( mdl_keyframe *kfa, mdl_keyframe *kfb, int num ) { for( int i=0; ibones[ id ], *sp = &skele->bones[ sb->parent ]; @@ -179,7 +180,7 @@ static int should_apply_bone( struct skeleton *skele, u32 id, anim_apply type ) /* * Apply block of keyframes to skeletons final pose */ -static void skeleton_apply_pose( struct skeleton *skele, mdl_keyframe *pose, +VG_STATIC void skeleton_apply_pose( struct skeleton *skele, mdl_keyframe *pose, anim_apply passtype ) { m4x3_identity( skele->final_mtx[0] ); @@ -217,7 +218,7 @@ static void skeleton_apply_pose( struct skeleton *skele, mdl_keyframe *pose, * creates the reference inverse matrix for an IK bone, as it has an initial * intrisic rotation based on the direction that the IK is setup.. */ -static void skeleton_inverse_for_ik( struct skeleton *skele, +VG_STATIC void skeleton_inverse_for_ik( struct skeleton *skele, v3f ivaxis, u32 id, m3x3f inverse ) { @@ -231,7 +232,7 @@ static void skeleton_inverse_for_ik( struct skeleton *skele, /* * Creates inverse rotation matrices which the IK system uses. */ -static void skeleton_create_inverses( struct skeleton *skele ) +VG_STATIC void skeleton_create_inverses( struct skeleton *skele ) { /* IK: inverse 'plane-bone space' axis '(^axis,^bone,...)[base] */ for( int i=0; iik_count; i++ ) @@ -241,7 +242,7 @@ static void skeleton_create_inverses( struct skeleton *skele ) m4x3f inverse; v3f iv0, iv1, ivaxis; v3_sub( skele->bones[ik->target].co, skele->bones[ik->lower].co, iv0 ); - v3_sub( skele->bones[ik->pole].co, skele->bones[ik->lower].co, iv1 ); + v3_sub( skele->bones[ik->pole].co, skele->bones[ik->lower].co, iv1 ); v3_cross( iv0, iv1, ivaxis ); v3_normalize( ivaxis ); @@ -253,7 +254,7 @@ static void skeleton_create_inverses( struct skeleton *skele ) /* * Apply a model matrix to all bones, should be done last */ -static void skeleton_apply_transform( struct skeleton *skele, m4x3f transform ) +VG_STATIC void skeleton_apply_transform( struct skeleton *skele, m4x3f transform ) { for( int i=0; ibone_count; i++ ) { @@ -266,7 +267,7 @@ static void skeleton_apply_transform( struct skeleton *skele, m4x3f transform ) * Apply an inverse matrix to all bones which maps vertices from bind space into * bone relative positions */ -static void skeleton_apply_inverses( struct skeleton *skele ) +VG_STATIC void skeleton_apply_inverses( struct skeleton *skele ) { for( int i=0; ibone_count; i++ ) { @@ -282,7 +283,7 @@ static void skeleton_apply_inverses( struct skeleton *skele ) /* * Apply all IK modifiers (2 bone ik reference from blender is supported) */ -static void skeleton_apply_ik_pass( struct skeleton *skele ) +VG_STATIC void skeleton_apply_ik_pass( struct skeleton *skele ) { for( int i=0; iik_count; i++ ) { @@ -362,7 +363,7 @@ static void skeleton_apply_ik_pass( struct skeleton *skele ) * Applies the typical operations that you want for an IK rig: * Pose, IK, Pose(deferred), Inverses, Transform */ -static void skeleton_apply_standard( struct skeleton *skele, mdl_keyframe *pose, +VG_STATIC void skeleton_apply_standard( struct skeleton *skele, mdl_keyframe *pose, m4x3f transform ) { skeleton_apply_pose( skele, pose, k_anim_apply_defer_ik ); @@ -375,7 +376,7 @@ static void skeleton_apply_standard( struct skeleton *skele, mdl_keyframe *pose, /* * Get an animation by name */ -static struct skeleton_anim *skeleton_get_anim( struct skeleton *skele, +VG_STATIC struct skeleton_anim *skeleton_get_anim( struct skeleton *skele, const char *name ) { for( int i=0; ianim_count; i++ ) @@ -389,8 +390,34 @@ static struct skeleton_anim *skeleton_get_anim( struct skeleton *skele, return NULL; } -/* Setup an animated skeleton from model */ -static int skeleton_setup( struct skeleton *skele, mdl_header *mdl ) +VG_STATIC void skeleton_alloc_from( struct skeleton *skele, + void *lin_alloc, + struct classtype_skeleton *inf ) +{ + skele->bone_count = inf->channels; + skele->ik_count = inf->ik_count; + skele->collider_count = inf->collider_count; + skele->anim_count = inf->anim_count; + + u32 bone_size = sizeof(struct skeleton_bone) * skele->bone_count, + ik_size = sizeof(struct skeleton_ik) * skele->ik_count, + mtx_size = sizeof(m4x3f) * skele->bone_count, + anim_size = sizeof(struct skeleton_anim) * skele->anim_count; + + skele->bones = vg_linear_alloc( lin_alloc, bone_size ); + skele->ik = vg_linear_alloc( lin_alloc, ik_size ); + skele->final_mtx = vg_linear_alloc( lin_alloc, mtx_size ); + skele->anims = vg_linear_alloc( lin_alloc, anim_size ); +} + +VG_STATIC void skeleton_fatal_err(void) +{ + vg_fatal_exit_loop( "Skeleton setup failed" ); +} + +/* Setup an animated skeleton from model. mdl's metadata should stick around */ +VG_STATIC void skeleton_setup( struct skeleton *skele, + void *lin_alloc, mdl_context *mdl ) { u32 bone_count = 1, skeleton_root = 0, ik_count = 0, collider_count = 0; skele->bone_count = 0; @@ -400,24 +427,14 @@ static int skeleton_setup( struct skeleton *skele, mdl_header *mdl ) struct classtype_skeleton *inf = NULL; - for( u32 i=0; inode_count; i++ ) + for( u32 i=0; iinfo.node_count; i++ ) { mdl_node *pnode = mdl_node_from_id( mdl, i ); if( pnode->classtype == k_classtype_skeleton ) { inf = mdl_get_entdata( mdl, pnode ); - if( skele->bone_count ) - { - vg_error( "Multiple skeletons in model file\n" ); - goto error_dealloc; - } - - skele->bone_count = inf->channels; - skele->ik_count = inf->ik_count; - skele->collider_count = inf->collider_count; - skele->bones =vg_alloc(sizeof(struct skeleton_bone)*skele->bone_count); - skele->ik = vg_alloc(sizeof(struct skeleton_ik)*skele->ik_count); + skeleton_alloc_from( skele, lin_alloc, inf ); skeleton_root = i; } else if( skele->bone_count ) @@ -432,7 +449,7 @@ static int skeleton_setup( struct skeleton *skele, mdl_header *mdl ) bone_count, skele->bone_count, mdl_pstr( mdl, pnode->pstr_name )); - goto error_dealloc; + skeleton_fatal_err(); } struct skeleton_bone *sb = &skele->bones[bone_count]; @@ -442,7 +459,7 @@ static int skeleton_setup( struct skeleton *skele, mdl_header *mdl ) v3_copy( pnode->co, sb->co ); v3_copy( pnode->s, sb->end ); sb->parent = pnode->parent-skeleton_root; - strncpy( sb->name, mdl_pstr(mdl,pnode->pstr_name), 15 ); + sb->name = mdl_pstr( mdl, pnode->pstr_name ); sb->deform = bone_inf->deform; if( is_ik ) @@ -453,7 +470,7 @@ static int skeleton_setup( struct skeleton *skele, mdl_header *mdl ) if( ik_count == skele->ik_count ) { vg_error( "Too many ik bones, corrupt model file\n" ); - goto error_dealloc; + skeleton_fatal_err(); } struct skeleton_ik *ik = &skele->ik[ ik_count ++ ]; @@ -476,7 +493,7 @@ static int skeleton_setup( struct skeleton *skele, mdl_header *mdl ) if( collider_count == skele->collider_count ) { vg_error( "Too many collider bones\n" ); - goto error_dealloc; + skeleton_fatal_err(); } collider_count ++; @@ -494,26 +511,27 @@ static int skeleton_setup( struct skeleton *skele, mdl_header *mdl ) if( !inf ) { vg_error( "No skeleton in model\n" ); - return 0; + skeleton_fatal_err(); } if( collider_count != skele->collider_count ) { vg_error( "Loaded %u colliders out of %u\n", collider_count, - skele->collider_count ); - goto error_dealloc; + skele->collider_count ); + skeleton_fatal_err(); } if( bone_count != skele->bone_count ) { vg_error( "Loaded %u bones out of %u\n", bone_count, skele->bone_count ); - goto error_dealloc; + vg_fatal_exit_loop( "Skeleton setup failed" ); + skeleton_fatal_err(); } if( ik_count != skele->ik_count ) { vg_error( "Loaded %u ik bones out of %u\n", ik_count, skele->ik_count ); - goto error_dealloc; + skeleton_fatal_err(); } /* fill in implicit root bone */ @@ -521,40 +539,29 @@ static int skeleton_setup( struct skeleton *skele, mdl_header *mdl ) v3_copy( (v3f){0.0f,1.0f,0.0f}, skele->bones[0].end ); skele->bones[0].parent = 0xffffffff; skele->bones[0].collider = 0; + skele->bones[0].name = "[root]"; - skele->final_mtx = vg_alloc( sizeof(m4x3f) * skele->bone_count ); - skele->anim_count = inf->anim_count; - skele->anims = vg_alloc( sizeof(struct skeleton_anim) * inf->anim_count); - - for( int i=0; ianim_count; i++ ) + /* process animation quick refs */ + for( int i=0; ianim_count; i++ ) { - mdl_animation *anim = - mdl_animation_from_id( mdl, inf->anim_start+i ); - - skele->anims[i].rate = anim->rate; - skele->anims[i].length = anim->length; - strncpy( skele->anims[i].name, mdl_pstr(mdl, anim->pstr_name), 31 ); + mdl_animation *anim = &mdl->anim_buffer[ inf->anim_start + i ]; - u32 total_keyframes = (skele->bone_count-1)*anim->length; - size_t block_size = sizeof(mdl_keyframe) * total_keyframes; - mdl_keyframe *dst = vg_alloc( block_size ); + skele->anims[i].rate = anim->rate; + skele->anims[i].length = anim->length; + skele->anims[i].name = mdl_pstr(mdl, anim->pstr_name); + skele->anims[i].anim_data = &mdl->keyframe_buffer[ anim->offset ]; - skele->anims[i].anim_data = dst; - memcpy( dst, mdl_get_animdata( mdl, anim ), block_size ); + vg_info( "animation[ %f, %u ] '%s'\n", anim->rate, + anim->length, + skele->anims[i].name ); } skeleton_create_inverses( skele ); vg_success( "Loaded skeleton with %u bones\n", skele->bone_count ); vg_success( " %u colliders\n", skele->collider_count ); - return 1; - -error_dealloc: - vg_free( skele->bones ); - vg_free( skele->ik ); - return 0; } -static void skeleton_debug( struct skeleton *skele ) +VG_STATIC void skeleton_debug( struct skeleton *skele ) { for( int i=0; ibone_count; i ++ ) { diff --git a/steam.h b/steam.h index a213222..a92c325 100644 --- a/steam.h +++ b/steam.h @@ -25,9 +25,9 @@ * nothing. */ -static char steam_username_at_startup[128]; +VG_STATIC char steam_username_at_startup[128]; -static void recv_steam_warning( int severity, const char *msg ) +VG_STATIC void recv_steam_warning( int severity, const char *msg ) { if( severity == 0 ) vg_low( "%s\n", msg ); @@ -35,23 +35,23 @@ static void recv_steam_warning( int severity, const char *msg ) vg_info( "%s\n", msg ); } -static int steam_ready = 0, +VG_STATIC int steam_ready = 0, steam_stats_ready = 0; -static void *hSteamNetworkingSockets, +VG_STATIC void *hSteamNetworkingSockets, *hSteamUser; -static ISteamUserStats *hSteamUserStats; -static HSteamPipe hSteamClientPipe; +VG_STATIC ISteamUserStats *hSteamUserStats; +VG_STATIC HSteamPipe hSteamClientPipe; -static const char *steam_achievement_names[] = +VG_STATIC const char *steam_achievement_names[] = { "ALBERT", "MARC", "ROUTE_MPY", "ROUTE_MPG", "ROUTE_MPB", "ROUTE_MPR", "ROUTE_TO", "ROUTE_TC" }; -static void steam_store_achievements(void) +VG_STATIC void steam_store_achievements(void) { if( steam_ready && steam_stats_ready ) { @@ -59,7 +59,7 @@ static void steam_store_achievements(void) } } -static void steam_set_achievement( const char *name ) +VG_STATIC void steam_set_achievement( const char *name ) { if( steam_ready && steam_stats_ready ) { @@ -78,7 +78,7 @@ static void steam_set_achievement( const char *name ) } } -static void steam_clear_achievement( const char *name ) +VG_STATIC void steam_clear_achievement( const char *name ) { if( steam_ready && steam_stats_ready ) { @@ -98,7 +98,7 @@ static void steam_clear_achievement( const char *name ) } -static int steam_list_achievements( int argc, char const *argv[] ) +VG_STATIC int steam_list_achievements( int argc, char const *argv[] ) { vg_info( "Achievements: \n" ); @@ -128,7 +128,7 @@ static int steam_list_achievements( int argc, char const *argv[] ) return 0; } -static int steam_clear_all_achievements( int argc, char const *argv[] ) +VG_STATIC int steam_clear_all_achievements( int argc, char const *argv[] ) { if( steam_ready && steam_stats_ready ) { @@ -147,7 +147,7 @@ static int steam_clear_all_achievements( int argc, char const *argv[] ) return 0; } -static int steam_set_achievemnt_test( int argc, char const *argv[] ) +VG_STATIC int steam_set_achievemnt_test( int argc, char const *argv[] ) { if( argc < 2 ) return 0; @@ -161,7 +161,7 @@ static int steam_set_achievemnt_test( int argc, char const *argv[] ) return 0; } -static void steam_on_recieve_current_stats( CallbackMsg_t *msg ) +VG_STATIC void steam_on_recieve_current_stats( CallbackMsg_t *msg ) { UserStatsReceived_t *rec = (UserStatsReceived_t *)msg->m_pubParam; @@ -177,7 +177,7 @@ static void steam_on_recieve_current_stats( CallbackMsg_t *msg ) } } -static int steam_init(void) +VG_STATIC int steam_init(void) { const char *username = NULL; @@ -249,13 +249,13 @@ static int steam_init(void) return 1; } -static void steam_update(void) +VG_STATIC void steam_update(void) { if( steam_ready ) steamworks_event_loop( hSteamClientPipe ); } -static void steam_end(void *nothing) +VG_STATIC void steam_end(void *nothing) { if( steam_ready ) { diff --git a/vg_config.h b/vg_config.h index b812ef2..8b1ea59 100644 --- a/vg_config.h +++ b/vg_config.h @@ -5,7 +5,7 @@ #define VG_CONFIG #include "vg/vg.h" -static struct button_binding vg_button_binds[] = +VG_STATIC struct button_binding vg_button_binds[] = { { .name = "primary", .bind = GLFW_MOUSE_BUTTON_LEFT }, { .name = "secondary", .bind = GLFW_MOUSE_BUTTON_RIGHT }, @@ -21,7 +21,7 @@ static struct button_binding vg_button_binds[] = { .name = "menu", .bind = GLFW_KEY_ESCAPE } }; -static struct button_binding vg_controller_binds[] = +VG_STATIC struct button_binding vg_controller_binds[] = { { "jump", GLFW_GAMEPAD_BUTTON_A }, { "break", GLFW_GAMEPAD_BUTTON_B }, @@ -30,7 +30,7 @@ static struct button_binding vg_controller_binds[] = { "menu", GLFW_GAMEPAD_BUTTON_BACK } }; -static struct axis_binding vg_axis_binds[] = +VG_STATIC struct axis_binding vg_axis_binds[] = { { .name = "lookh", .axis = GLFW_GAMEPAD_AXIS_LEFT_X }, { .name = "lookv", .axis = GLFW_GAMEPAD_AXIS_LEFT_Y }, @@ -40,6 +40,6 @@ static struct axis_binding vg_axis_binds[] = { .name = "grab", .axis = GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER }, }; -static struct vg_achievement vg_achievements[] = +VG_STATIC struct vg_achievement vg_achievements[] = { }; diff --git a/world.h b/world.h index 08fe437..8b1b1dc 100644 --- a/world.h +++ b/world.h @@ -4,7 +4,7 @@ #include "common.h" -static int ray_world( v3f pos, v3f dir, ray_hit *hit ); +VG_STATIC int ray_world( v3f pos, v3f dir, ray_hit *hit ); #ifndef WORLD_H #define WORLD_H @@ -19,8 +19,6 @@ static int ray_world( v3f pos, v3f dir, ray_hit *hit ); #include "bvh.h" #include "model.h" -#include "traffic.h" /*TODO: -> world_traffic.h */ - #include "shaders/terrain.h" #include "shaders/sky.h" #include "shaders/planeinf.h" @@ -30,28 +28,122 @@ static int ray_world( v3f pos, v3f dir, ray_hit *hit ); #include "shaders/fscolour.h" #include "shaders/alphatest.h" +typedef struct teleport_gate teleport_gate; + enum { k_max_ui_segments = 8 }; -enum { k_max_ui_splits_per_segment = 16 }; -enum { k_max_ui_elements = k_max_ui_segments*k_max_ui_splits_per_segment }; +enum { k_max_ui_elements = k_max_ui_segments }; enum { k_max_element_verts = 10 }; enum { k_max_element_indices = 20 }; enum { k_route_ui_max_verts = k_max_ui_elements*k_max_element_verts }; enum { k_route_ui_max_indices = k_max_ui_elements*k_max_element_indices }; -static struct gworld +enum logic_type +{ + k_logic_type_relay = 1, + k_logic_type_chance = 2, + k_logic_type_achievement = 3 +}; + +VG_STATIC struct gworld { - /* gameplay */ + /* + * Allocated as system memory + * -------------------------------------------------------------------------- + */ + + /* rendering */ + glmesh skydome; + mdl_submesh dome_upper, dome_lower; + + glmesh mesh_gate_surface; + + double sky_time, sky_rate, sky_target_rate; + + /* water rendering */ + struct + { + struct framebuffer fbreflect, fbdepth; + + boxf depthbounds; + int depth_computed; + + float height; + int enabled; + v4f plane; + } + water; + + /* split flap display */ + struct + { + mdl_submesh *sm_module, *sm_card; + glmesh mesh_base, mesh_display; + + u32 w, h; + float *buffer; + } + sfd; + + /* timing bars, fixed maximum amount */ + struct route_ui_bar + { + GLuint vao, vbo, ebo; + + u32 indices_head; + u32 vertex_head; + + float last_notch; + + struct route_ui_segment + { + float length; + u32 vertex_start, vertex_count, + index_start, index_count, notches; + } + segments[k_max_ui_segments]; + + u32 segment_start, segment_count, fade_start, fade_count; + double fade_timer_start; + float xpos; + } + ui_bars[16]; + + v3f render_gate_pos; + int active_route_board; + + /* + * Dynamically allocated when world_load is called. + * + * the following arrays index somewhere into this linear + * allocator + * + * (world_gen.h) + * -------------------------------------------------------------------------- + */ + void *dynamic_vgl; + + /* + * Main world .mdl + */ + mdl_context *meta; + + /* + * Named safe places to respawn + */ struct respawn_point { v3f co; v4f q; - char name[32]; + const char *name; } - spawns[32]; + * spawns; u32 spawn_count; + /* + * Audio player entities + */ struct world_audio_thing { v3f pos; @@ -62,98 +154,51 @@ static struct gworld audio_clip temp_embedded_clip; } * audio_things; - - u32 audio_things_count, - audio_things_cap; + u32 audio_things_count; - struct achievement_zone + /* + * Relays, random, etc + */ + struct logic_entity { - m4x3f transform, inv_transform; - char name[32]; - int triggered; + v3f pos; + enum logic_type logic_type; + int enabled; - union - { - mdl_node *ptarget_delegated; - struct world_audio_thing *ptarget; - }; + /* indexes the action array */ + u32 action_start, action_count; } - * achievement_zones; + * logic_entities; + u32 logic_entity_count; - u32 achievement_zones_count, - achievement_zones_cap; - - struct subworld_sfd + /* + * Action array + */ + struct logic_action { - scene mesh; - mdl_submesh *sm_module, *sm_card; - glmesh temp; + u32 event, /* on trigger, on enable, etc (TODO: Enum) */ + target_id; /* thing to target, 0: self */ - struct sfd_instance - { - float *buffer; - - u32 w,h; - } - tester; } - sfd; - - /* Paths */ - traffic_node traffic[128]; - u32 traffic_count; - -#if 0 - traffic_driver van_man[6]; -#endif - - double sky_time, sky_rate, sky_target_rate; - - /* Physics */ - - /* Rendering & geometry */ - scene geo, foliage; - rigidbody rb_geo; + * logic_actions; + u32 logic_action_count; - /* TODO Maybe make this less hardcoded */ - mdl_submesh sm_geo_std_oob, sm_geo_std, sm_geo_vb, - sm_foliage_main, sm_foliage_alphatest, - sm_graffiti, sm_subworld, sm_terrain; - - glmesh skybox, skydome; - mdl_submesh dome_upper, dome_lower; - - glmesh cars; - mdl_submesh car_holden; - - /* Load time */ - - struct instance_cache + /* + * Box trigger entities + */ + struct trigger_zone { - mdl_header *mdl; - u32 pstr_file; + m4x3f transform, inv_transform; + u32 trigger_entity; } - * instance_cache; - u32 instance_cache_count, - instance_cache_cap; + * triggers; + u32 trigger_count; - v3f render_gate_pos; - int active_route_board; -} -world ; - -typedef struct teleport_gate teleport_gate; -struct teleport_gate -{ - v3f co[2]; - v4f q[2]; - v2f dims; - m4x3f to_world, recv_to_world, transport; -}; - -struct subworld_routes -{ + /* + * Routes (world_routes.h) + * -------------------------------------------------------------------------- + */ struct route_node { v3f co, right, up, h; @@ -163,9 +208,7 @@ struct subworld_routes u32 route_ids[4]; /* Gates can be linked into up to four routes */ } *nodes; - - u32 node_count, - node_cap; + u32 node_count; struct route { @@ -180,41 +223,23 @@ struct subworld_routes double best_lap, latest_pass; /* Session */ - struct - { - GLuint vao, vbo, ebo; - - u32 indices_head; - u32 vertex_head; - - float last_notch; - - struct route_ui_segment - { - float length; - u32 vertex_start, vertex_count, - index_start, index_count, notches; - } - segments[k_max_ui_segments]; - - u32 segment_start, segment_count, fade_start, fade_count; - double fade_timer_start; - float xpos; - } - ui; - m4x3f scoreboard_transform; } *routes; - - double time, rewind_from, rewind_to, last_use; - - u32 route_count, - route_cap; + u32 route_count; struct route_gate { - teleport_gate gate; + struct teleport_gate + { + v3f co[2]; + v4f q[2]; + v2f dims; + + m4x3f to_world, recv_to_world, transport; + } + gate; + u32 node_id; struct route_timing @@ -225,34 +250,71 @@ struct subworld_routes timing; } *gates; + u32 gate_count; struct route_collector { struct route_timing timing; } *collectors; + u32 collector_count; + - u32 gate_count, - gate_cap, - collector_count, - collector_cap; + /* logic + * ---------------------------------------------------- + */ u32 active_gate, current_run_version; + double time, rewind_from, rewind_to, last_use; + + /* world geometry */ + scene *scene_geo, + *scene_no_collide, + *scene_lines; + + /* spacial mappings */ + bh_tree *audio_bh, + *trigger_bh, + *geo_bh; + + /* graphics */ + glmesh mesh_geo, + mesh_no_collide, + mesh_route_lines, + mesh_water; + + rigidbody rb_geo; + + /* TODO Maybe make this less hardcoded */ + mdl_submesh sm_geo_std_oob, sm_geo_std, sm_geo_vb, + sm_foliage_main, sm_foliage_alphatest, + sm_graffiti, sm_subworld, sm_terrain; - scene scene_lines; + /* + * Allocated AFTER all previous buffers are done + * -------------------------------------------------------------------------- + */ + + struct instance_cache + { + mdl_context *mdl; + u32 pstr_file; + } + instance_cache[32]; + u32 instance_cache_count; } -static world_routes; +world; /* * API */ -static int ray_hit_is_ramp( ray_hit *hit ); -static int ray_hit_is_terrain( ray_hit *hit ); -static void ray_world_get_tri( ray_hit *hit, v3f tri[3] ); -static int ray_world( v3f pos, v3f dir, ray_hit *hit ); +VG_STATIC int ray_hit_is_ramp( ray_hit *hit ); +VG_STATIC int ray_hit_is_terrain( ray_hit *hit ); +VG_STATIC void ray_world_get_tri( ray_hit *hit, v3f tri[3] ); +VG_STATIC int ray_world( v3f pos, v3f dir, ray_hit *hit ); /* * Submodules @@ -271,8 +333,16 @@ static int ray_world( v3f pos, v3f dir, ray_hit *hit ); * ----------------------------------------------------------------------------- */ -static void world_init(void) +VG_STATIC void world_init(void) { + vg_convar_push( (struct vg_convar){ + .name = "water_enable", + .data = &world.water.enabled, + .data_type = k_convar_dtype_i32, + .opt_i32 = { .min=0, .max=1, .clamp=1 }, + .persistent = 0 + }); + world.sky_rate = 1.0; world.sky_target_rate = 1.0; @@ -284,12 +354,9 @@ static void world_init(void) shader_alphatest_register(); vg_info( "Loading world resources\n" ); - - VG_REQUIRED_ASSET( mdl_header*, mcars, mdl_load, "models/rs_cars.mdl" ); - VG_REQUIRED_ASSET( mdl_header*, msky, mdl_load, "models/rs_skydome.mdl" ); - - mdl_node *nholden = mdl_node_from_name( mcars, "holden" ); - world.car_holden = *mdl_node_submesh( mcars, nholden, 0 ); + + vg_linear_clear( vg_mem.scratch ); + mdl_context *msky = mdl_load_full( vg_mem.scratch, "models/rs_skydome.mdl" ); mdl_node *nlower = mdl_node_from_name( msky, "dome_lower" ), *nupper = mdl_node_from_name( msky, "dome_upper" ); @@ -299,37 +366,25 @@ static void world_init(void) vg_acquire_thread_sync(); { - mdl_unpack_glmesh( mcars, &world.cars ); mdl_unpack_glmesh( msky, &world.skydome ); } vg_release_thread_sync(); - vg_free(mcars); - vg_free(msky); - /* Other systems */ vg_info( "Loading other world systems\n" ); - vg_loader_highwater( world_render_init, world_render_free, NULL ); - vg_loader_highwater( world_sfd_init, world_sfd_free, NULL ); - vg_loader_highwater( world_water_init, world_water_free, NULL ); - vg_loader_highwater( world_gates_init, world_gates_free, NULL ); - vg_loader_highwater( world_routes_init, world_routes_free, NULL ); -} - -static void world_free( void *_ ) -{ - mesh_free( &world.cars ); - mesh_free( &world.skydome ); - vg_free( world.achievement_zones ); + vg_loader_highwater( world_render_init, NULL, NULL ); + vg_loader_highwater( world_sfd_init, NULL, NULL ); + vg_loader_highwater( world_water_init, NULL, NULL ); + vg_loader_highwater( world_gates_init, NULL, NULL ); + vg_loader_highwater( world_routes_init, NULL, NULL ); - /* FIXME: This fucks with the audio player. Use-after-free */ -#if 0 - vg_free( world.audio_things ); -#endif + /* Allocate dynamic world memory arena */ + u32 max_size = 72*1024*1024; + world.dynamic_vgl = vg_create_linear_allocator( vg_mem.rtmemory, max_size ); } -static void world_update( v3f pos ) +VG_STATIC void world_update( v3f pos ) { world.sky_time += world.sky_rate * vg.time_delta; world.sky_rate = vg_lerp( world.sky_rate, world.sky_target_rate, @@ -343,9 +398,9 @@ static void world_update( v3f pos ) int closest = 0; float min_dist = INFINITY; - for( int i=0; itrack_id; @@ -370,12 +424,13 @@ static void world_update( v3f pos ) for( int i=0; i<13; i++ ) { - sfd_encode( &sfd->tester, i, &local_board->data[27*i] ); + sfd_encode( i, &local_board->data[27*i] ); } } } - static int in_zone = 0; +#if 0 + VG_STATIC int in_zone = 0; int in_zone_this_time = 0; @@ -415,8 +470,9 @@ static void world_update( v3f pos ) } in_zone = in_zone_this_time; +#endif - sfd_update( &world.sfd.tester ); + sfd_update(); } /* @@ -425,18 +481,18 @@ static void world_update( v3f pos ) * ----------------------------------------------------------------------------- */ -static void ray_world_get_tri( ray_hit *hit, v3f tri[3] ) +VG_STATIC void ray_world_get_tri( ray_hit *hit, v3f tri[3] ) { for( int i=0; i<3; i++ ) - v3_copy( world.geo.verts[ hit->tri[i] ].co, tri[i] ); + v3_copy( world.scene_geo->arrvertices[ hit->tri[i] ].co, tri[i] ); } -static int ray_world( v3f pos, v3f dir, ray_hit *hit ) +VG_STATIC int ray_world( v3f pos, v3f dir, ray_hit *hit ) { - return scene_raycast( &world.geo, pos, dir, hit ); + return scene_raycast( world.scene_geo, world.geo_bh, pos, dir, hit ); } -static int ray_hit_is_terrain( ray_hit *hit ) +VG_STATIC int ray_hit_is_terrain( ray_hit *hit ) { u32 valid_start = 0, valid_end = world.sm_terrain.vertex_count; @@ -445,7 +501,7 @@ static int ray_hit_is_terrain( ray_hit *hit ) (hit->tri[0] < valid_end); } -static int ray_hit_is_ramp( ray_hit *hit ) +VG_STATIC int ray_hit_is_ramp( ray_hit *hit ) { u32 valid_start = world.sm_geo_std.vertex_start, valid_end = world.sm_geo_vb.vertex_start; diff --git a/world_gate.h b/world_gate.h index 39a1e78..b57c799 100644 --- a/world_gate.h +++ b/world_gate.h @@ -5,35 +5,15 @@ #ifndef WORLD_GATE_H #define WORLD_GATE_H -#define GATE_RENDER_PERFORMANCE - #include "common.h" #include "model.h" #include "render.h" -#ifndef GATE_RENDER_PERFORMANCE - #include "shaders/gate.h" -#else - #include "shaders/gatelq.h" -#endif - +#include "shaders/gatelq.h" #include "world_water.h" -static struct -{ - struct framebuffer fb; - glmesh mdl; -} -grender = -{ - .fb = { - .format = GL_RGB, - .div = 1 - } -}; - -static void gate_transform_update( teleport_gate *gate ) +VG_STATIC void gate_transform_update( teleport_gate *gate ) { m4x3f to_local; @@ -47,37 +27,23 @@ static void gate_transform_update( teleport_gate *gate ) m4x3_mul( gate->recv_to_world, to_local, gate->transport ); } -static void world_gates_init(void) +VG_STATIC void world_gates_init(void) { vg_info( "world_gates_init\n" ); -#ifndef GATE_RENDER_PERFORMANCE - shader_gate_register(); -#else shader_gatelq_register(); -#endif - mdl_header *mgate = mdl_load( "models/rs_gate.mdl" ); + vg_linear_clear( vg_mem.scratch ); + mdl_context *mgate = mdl_load_full( vg_mem.scratch, "models/rs_gate.mdl" ); vg_acquire_thread_sync(); { - fb_init( &grender.fb ); - mdl_unpack_glmesh( mgate, &grender.mdl ); + mdl_unpack_glmesh( mgate, &world.mesh_gate_surface ); } vg_release_thread_sync(); } -static void world_gates_free(void*_) -{ - fb_free( &grender.fb ); -} - -static void gate_fb_resize(void) -{ - fb_resize( &grender.fb ); -} - -static int render_gate( teleport_gate *gate, v3f viewpos, m4x3f camera ) +VG_STATIC int render_gate( teleport_gate *gate, v3f viewpos, m4x3f camera ) { v3f viewdir, gatedir; m3x3_mulv( camera, (v3f){0.0f,0.0f,-1.0f}, viewdir ); @@ -135,11 +101,7 @@ static int render_gate( teleport_gate *gate, v3f viewpos, m4x3f camera ) m4x4_mul( projection, view, projection ); -#ifndef GATE_RENDER_PERFORMANCE - fb_use( &grender.fb ); - glClearColor( 0.11f, 0.35f, 0.37f, 1.0f ); - glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT ); -#else + { shader_gatelq_use(); shader_gatelq_uPv( vg.pv ); shader_gatelq_uMdl( gate_xform ); @@ -154,53 +116,17 @@ static int render_gate( teleport_gate *gate, v3f viewpos, m4x3f camera ) glStencilFunc( GL_ALWAYS, 1, 0xFF ); glStencilMask( 0xFF ); - mesh_bind( &grender.mdl ); - mesh_draw( &grender.mdl ); + mesh_bind( &world.mesh_gate_surface ); + mesh_draw( &world.mesh_gate_surface ); glClear( GL_DEPTH_BUFFER_BIT ); glStencilFunc( GL_EQUAL, 1, 0xFF ); glStencilMask( 0x00 ); -#endif + } render_world( projection, cam_new ); -#ifndef GATE_RENDER_PERFORMANCE - - /* - * NOTE: Need to find a way to draw a stencil buffer into the water - * rendering - */ - - render_water_texture( cam_new ); - fb_use( &grender.fb ); - - render_water_surface( projection, cam_new ); - fb_use( NULL ); - - shader_gate_use(); - - shader_gate_uPv( vg_pv ); - shader_gate_uMdl( gate_xform ); - - fb_bindtex( &grender.fb, 0 ); - - shader_gate_uCam( viewpos ); - shader_gate_uTexMain( 0 ); - shader_gate_uTexWater( 1 ); - shader_gate_uTime( vg_time*0.25f ); - shader_gate_uInvRes( (v2f){ - 1.0f / (float)vg_window_x, - 1.0f / (float)vg_window_y }); - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); - glBlendEquation(GL_FUNC_ADD); - - mesh_bind( &grender.mdl ); - mesh_draw( &grender.mdl ); - - glDisable(GL_BLEND); -#else + { glDisable( GL_STENCIL_TEST ); render_water_texture( cam_new ); @@ -212,12 +138,12 @@ static int render_gate( teleport_gate *gate, v3f viewpos, m4x3f camera ) glStencilMask( 0xFF ); glStencilFunc( GL_ALWAYS, 1, 0xFF ); glDisable( GL_STENCIL_TEST ); -#endif + } return 1; } -static int gate_intersect( teleport_gate *gate, v3f pos, v3f last ) +VG_STATIC int gate_intersect( teleport_gate *gate, v3f pos, v3f last ) { v4f surface; m3x3_mulv( gate->to_world, (v3f){0.0f,0.0f,-1.0f}, surface ); diff --git a/world_gen.h b/world_gen.h index 31722e5..ccd3eda 100644 --- a/world_gen.h +++ b/world_gen.h @@ -5,24 +5,23 @@ #ifndef WORLD_GEN_H #define WORLD_GEN_H -/* - * FUTURE: - * If we have multiple levels, write an unloader - */ - #include "world.h" -static void world_add_all_if_material( m4x3f transform, scene *pscene, - mdl_header *mdl, u32 id ) +/* load world TODO: Put back vg back in loading state while this happens */ +VG_STATIC void world_load( const char *mdl_file ); + + + +VG_STATIC void world_add_all_if_material( m4x3f transform, scene *pscene, + mdl_context *mdl, u32 id ) { - for( int i=0; inode_count; i++ ) + for( int i=0; iinfo.node_count; i++ ) { mdl_node *pnode = mdl_node_from_id( mdl, i ); for( int j=0; jsubmesh_count; j++ ) { mdl_submesh *sm = mdl_node_submesh( mdl, pnode, j ); - if( sm->material_id == id ) { m4x3f transform2; @@ -33,13 +32,14 @@ static void world_add_all_if_material( m4x3f transform, scene *pscene, } } +#if 0 if( pnode->classtype == k_classtype_instance ) { if( pnode->sub_uid ) { u32 instance_id = pnode->sub_uid -1; struct instance_cache *cache = &world.instance_cache[instance_id]; - mdl_header *mdl2 = cache->mdl; + mdl_context *mdl2 = cache->mdl; m4x3f transform2; mdl_node_transform( pnode, transform2 ); @@ -48,15 +48,20 @@ static void world_add_all_if_material( m4x3f transform, scene *pscene, world_add_all_if_material( transform2, pscene, mdl2, id ); } } +#endif } } -static void world_apply_procedural_foliage(void) +/* Sprinkle foliage models over the map on terrain material */ +VG_STATIC void world_apply_procedural_foliage(void) { - mdl_header *mfoliage = mdl_load("models/rs_foliage.mdl"); + vg_linear_clear( vg_mem.scratch ); + + mdl_context *mfoliage = + mdl_load_full( vg_mem.scratch, "models/rs_foliage.mdl"); v3f volume; - v3_sub( world.geo.bbx[1], world.geo.bbx[0], volume ); + v3_sub( world.scene_geo->bbx[1], world.scene_geo->bbx[0], volume ); volume[1] = 1.0f; m4x3f transform; @@ -68,7 +73,7 @@ static void world_apply_procedural_foliage(void) v3f pos; v3_mul( volume, (v3f){ vg_randf(), 1000.0f, vg_randf() }, pos ); pos[1] = 1000.0f; - v3_add( pos, world.geo.bbx[0], pos ); + v3_add( pos, world.scene_geo->bbx[0], pos ); ray_hit hit; hit.dist = INFINITY; @@ -90,124 +95,211 @@ static void world_apply_procedural_foliage(void) q_m3x3( qsurface, transform ); v3_copy( hit.pos, transform[3] ); - scene_add_submesh( &world.foliage, mfoliage, sm_blob, transform); + scene_add_submesh( world.scene_no_collide, mfoliage, + sm_blob, transform); } } } - - vg_free( mfoliage ); } -static void world_load(void) +VG_STATIC void world_ents_allocate(void) { - mdl_header *mworld = mdl_load( "models/mp_dev.mdl" ); - vg_info( "Loading world: models/mp_dev.mdl\n" ); + vg_info( "Allocating entities\n" ); - world.spawn_count = 0; - world.traffic_count = 0; - world.instance_cache = NULL; - - /* - * Process entities - */ - for( int i=0; inode_count; i++ ) + /* count entites to allocate buffers for them. + * maybe in the future we just store these numbers in the model file... + * + * TODO: use this in world_routes too */ + + struct countable { - mdl_node *pnode = mdl_node_from_id( mworld, i ); - - if( pnode->classtype == k_classtype_none ) - {} - else if( pnode->classtype == k_classtype_spawn ) + enum classtype ct; + void **to_allocate; + u32 item_size; + int count; + } + entity_counts[] = + { + { + k_classtype_spawn, + (void*)&world.spawns, + sizeof(struct respawn_point) + }, + { + k_classtype_audio, + (void*)&world.audio_things, + sizeof(struct world_audio_thing) + }, { - struct respawn_point *rp = &world.spawns[ world.spawn_count ++ ]; - - v3_copy( pnode->co, rp->co ); - v4_copy( pnode->q, rp->q ); - strcpy( rp->name, mdl_pstr( mworld, pnode->pstr_name ) ); + k_classtype_trigger, + (void*)&world.triggers, + sizeof(struct trigger_zone) } - else if( pnode->classtype == k_classtype_water ) + }; + + for( int i=0; iinfo.node_count; i++ ) + { + mdl_node *pnode = mdl_node_from_id( world.meta, i ); + + for( int j=0; jclasstype == entity_counts[j].ct ) { - vg_warn( "Multiple water surfaces in level! ('%s')\n", - mdl_pstr( mworld, pnode->pstr_name )); - continue; + entity_counts[j].count ++; + break; } + } + } - mdl_submesh *sm = mdl_node_submesh( mworld, pnode, 0 ); - - if( sm ) - { - vg_acquire_thread_sync(); - { - glmesh surf; - mdl_unpack_submesh( mworld, &surf, sm ); - water_set_surface( &surf, pnode->co[1] ); - } - vg_release_thread_sync(); - } + for( int i=0; iitem_size*counter->count; + *counter->to_allocate = vg_linear_alloc( world.dynamic_vgl, bufsize ); + } +} + +VG_STATIC void world_pct_spawn( mdl_node *pnode ) +{ + struct respawn_point *rp = &world.spawns[ world.spawn_count ++ ]; + + v3_copy( pnode->co, rp->co ); + v4_copy( pnode->q, rp->q ); + rp->name = mdl_pstr( world.meta, pnode->pstr_name ); +} + +VG_STATIC void world_pct_water( mdl_node *pnode ) +{ + if( world.water.enabled ) + { + vg_warn( "Multiple water surfaces in level! ('%s')\n", + mdl_pstr( world.meta, pnode->pstr_name )); + return; + } + + mdl_submesh *sm = mdl_node_submesh( world.meta, pnode, 0 ); + + if( sm ) + { + vg_acquire_thread_sync(); + { + mdl_unpack_submesh( world.meta, &world.mesh_water, sm ); + world.water.enabled = 1; + water_set_surface( pnode->co[1] ); + } + vg_release_thread_sync(); + } + else + { + vg_warn( "Water entity has no submeshes!\n" ); + } +} + +VG_STATIC void world_pct_instance( mdl_node *pnode ) +{ + struct classtype_instance *inst = mdl_get_entdata( world.meta, pnode ); + pnode->sub_uid = 0; + + int cache_entry = 0; + for( int i=0; ipstr_file == cache->pstr_file ) + { + cache_entry = 1; + pnode->sub_uid = i+1; + break; } - else if( pnode->classtype == k_classtype_car_path ) + } + + if( !cache_entry ) + { + if( world.instance_cache_count == vg_list_size(world.instance_cache) ) + vg_fatal_exit_loop( "Instance cache is full!" ); + + struct instance_cache *cache = + &world.instance_cache[world.instance_cache_count ++ ]; + + cache->pstr_file = inst->pstr_file; + +#if 0 + cache->mdl = mdl_load( filename ); + + if( cache->mdl ) { - struct classtype_car_path *p = mdl_get_entdata( mworld, pnode ); - traffic_node *tn = &world.traffic[ world.traffic_count ]; - tn->mn_next = NULL; - tn->mn_next1 = NULL; - - if( p->target ) tn->mn_next = mdl_node_from_id( mworld, p->target ); - if( p->target1 ) tn->mn_next1 = mdl_node_from_id( mworld, p->target1 ); - - m4x3f transform; - mdl_node_transform( pnode, transform ); - m3x3_mulv( transform, (v3f){1.0f,0.0f,0.0f}, tn->h ); - v3_copy( transform[3], tn->co ); - - pnode->sub_uid = world.traffic_count ++; + world.instance_cache_count ++; + pnode->sub_uid = world.instance_cache_count; + mdl_link_materials( mworld, cache->mdl ); + vg_success( "Cached %s\n", filename ); } - else if( pnode->classtype == k_classtype_instance ) + else { - struct classtype_instance *inst = mdl_get_entdata( mworld, pnode ); - pnode->sub_uid = 0; - - int cached = 0; - for( int i=0; ipstr_file == cache->pstr_file ) - { - cached = 1; - pnode->sub_uid = i+1; - break; - } - } + vg_warn( "Failed to cache %s\n", filename ); + } +#endif + } +} + +VG_STATIC void world_pct_audio( mdl_node *pnode ) +{ + struct world_audio_thing *thing = &world.audio_things[ + world.audio_things_count ]; + + memset( thing, 0, sizeof(struct world_audio_thing) ); + struct classtype_audio *aud = mdl_get_entdata( world.meta, pnode ); + + v3_copy( pnode->co, thing->pos ); + + if( aud->flags & AUDIO_FLAG_SPACIAL_3D ) + thing->volume = aud->volume * pnode->s[0]; + else + thing->volume = aud->volume; + + thing->flags = aud->flags; + thing->temp_embedded_clip.path = mdl_pstr( world.meta, aud->pstr_file ); + audio_clip_load( &thing->temp_embedded_clip ); + thing->player.name = mdl_pstr( world.meta, pnode->pstr_name ); + thing->player.enqued = 0; - if( !cached ) + pnode->sub_uid = world.audio_things_count; + world.audio_things_count ++; +} + +VG_STATIC void world_entities_process(void) +{ + struct entity_instruction + { + enum classtype ct; + void (*process)( mdl_node *pnode ); + } + entity_instructions[] = + { + { k_classtype_spawn, world_pct_spawn }, + { k_classtype_water, world_pct_water }, + { k_classtype_instance, world_pct_instance }, + { k_classtype_audio, world_pct_audio }, + }; + + for( int i=0; iinfo.node_count; i++ ) + { + mdl_node *pnode = mdl_node_from_id( world.meta, i ); + + for( int j=0; jclasstype == instr->ct ) { - world.instance_cache = buffer_reserve( - world.instance_cache, world.instance_cache_count, - &world.instance_cache_cap, 1, - sizeof(struct instance_cache) ); - - struct instance_cache *cache = - &world.instance_cache[world.instance_cache_count]; - - const char *filename = mdl_pstr(mworld, inst->pstr_file); - - cache->pstr_file = inst->pstr_file; - cache->mdl = mdl_load( filename ); - - if( cache->mdl ) - { - world.instance_cache_count ++; - pnode->sub_uid = world.instance_cache_count; - mdl_link_materials( mworld, cache->mdl ); - vg_success( "Cached %s\n", filename ); - } - else - { - vg_warn( "Failed to cache %s\n", filename ); - } + instr->process( pnode ); + break; } } + +#if 0 else if( pnode->classtype == k_classtype_achievement_box ) { world.achievement_zones = @@ -233,41 +325,10 @@ static void world_load(void) else zone->ptarget_delegated = NULL; } - else if( pnode->classtype == k_classtype_audio ) - { - world.audio_things = - buffer_reserve( world.audio_things, - world.audio_things_count, - &world.audio_things_cap, 1, - sizeof(struct world_audio_thing) ); - - struct world_audio_thing *thing = &world.audio_things[ - world.audio_things_count ]; - memset( thing, 0, sizeof(struct world_audio_thing) ); - struct classtype_audio *aud = mdl_get_entdata(mworld,pnode); - - v3_copy( pnode->co, thing->pos ); - - if( aud->flags & AUDIO_FLAG_SPACIAL_3D ) - thing->volume = aud->volume * pnode->s[0]; - else - thing->volume = aud->volume; - - thing->flags = aud->flags; - const char *fp = mdl_pstr( mworld, aud->pstr_file ); - char *path2 = vg_alloc( strlen(fp)+1 ); - strcpy( path2, fp ); - thing->temp_embedded_clip.path = path2; - thing->temp_embedded_clip.source_mode = k_audio_source_compressed; - audio_clip_load( &thing->temp_embedded_clip ); - thing->player.name = "[temp]"; - thing->player.enqued = 0; - - pnode->sub_uid = world.audio_things_count; - world.audio_things_count ++; - } +#endif } +#if 0 /* fixup links */ for( int i=0; iptarget = NULL; } +#endif +} - /* initialize audio if need be */ - audio_lock(); - for( int i=0; iplayer ); - audio_player_set_flags( &thingy->player, thingy->flags ); - audio_player_set_vol( &thingy->player, thingy->volume ); - audio_player_set_pan( &thingy->player, 0.0f ); - - if( thingy->flags & AUDIO_FLAG_SPACIAL_3D ) - audio_player_set_position( &thingy->player, thingy->pos ); - - if( thingy->flags & AUDIO_FLAG_AUTO_START ) - audio_player_playclip( &thingy->player, &thingy->temp_embedded_clip ); + const char *filename = mdl_pstr( world.meta, inst->pstr_file ); + inst->mdl = mdl_load_full( vg_mem.scratch, filename ); } - audio_unlock(); - - world.instance_cache = buffer_fix( world.instance_cache, - world.instance_cache_count, - &world.instance_cache_cap, - sizeof( struct instance_cache ) ); - -#if 0 - traffic_finalize( world.traffic, world.traffic_count ); - for( int i=0; imaterial_count; i++ ) + for( int i=1; iinfo.material_count; i++ ) { - mdl_material *mat = mdl_material_from_id( mworld, i ); - const char *mat_name = mdl_pstr( mworld, mat->pstr_name ); + mdl_material *mat = &world.meta->material_buffer[ i ]; + const char *mat_name = mdl_pstr( world.meta, mat->pstr_name ); if( !strcmp( "surf", mat_name )) mat_surf = i; @@ -346,50 +397,122 @@ static void world_load(void) m4x3f midentity; m4x3_identity( midentity ); + world_load_instance_cache(); + + /* + * Generate scene: collidable geometry + * ---------------------------------------------------------------- + */ + + vg_info( "Generating collidable geometry\n" ); + vg_info( "terrain...\n" ); + /* terrain */ if( mat_terrain ) - world_add_all_if_material( midentity, &world.geo, mworld, mat_terrain ); - scene_copy_slice( &world.geo, &world.sm_terrain ); + world_add_all_if_material( midentity, world.scene_geo, + world.meta, mat_terrain ); + scene_copy_slice( world.scene_geo, &world.sm_terrain ); + /* oob */ + vg_info( "oob...\n" ); if( mat_surf_oob ) - world_add_all_if_material( midentity, &world.geo, mworld, mat_surf_oob ); + world_add_all_if_material( midentity, world.scene_geo, + world.meta, mat_surf_oob ); else vg_warn( "No OOB surface\n" ); - scene_copy_slice( &world.geo, &world.sm_geo_std_oob ); + scene_copy_slice( world.scene_geo, &world.sm_geo_std_oob ); + + /* surface */ + vg_info( "surface...\n" ); if( mat_surf ) - world_add_all_if_material( midentity, &world.geo, mworld, mat_surf ); - scene_copy_slice( &world.geo, &world.sm_geo_std ); + world_add_all_if_material( midentity, world.scene_geo, + world.meta, mat_surf ); + scene_copy_slice( world.scene_geo, &world.sm_geo_std ); + /* vertex_blend */ + vg_info( "vertex blend...\n" ); if( mat_vertex_blend ) - world_add_all_if_material( midentity, &world.geo,mworld,mat_vertex_blend); - scene_copy_slice( &world.geo, &world.sm_geo_vb ); + world_add_all_if_material( midentity, world.scene_geo, + world.meta, mat_vertex_blend); + scene_copy_slice( world.scene_geo, &world.sm_geo_vb ); + + /* compress that bad boy */ + world.scene_geo = scene_fix( world.dynamic_vgl, world.scene_geo ); vg_acquire_thread_sync(); - scene_upload( &world.geo ); + { + scene_upload( world.scene_geo, &world.mesh_geo ); + } vg_release_thread_sync(); - scene_bh_create( &world.geo ); + /* setup spacial mapping and rigidbody */ + world.geo_bh = scene_bh_create( world.dynamic_vgl, world.scene_geo ); + v3_zero( world.rb_geo.co ); + q_identity( world.rb_geo.q ); - /* Foliage /nocollide layer. - * TODO: Probably should have material traits for this + world.rb_geo.type = k_rb_shape_scene; + world.rb_geo.inf.scene.bh_scene = world.geo_bh; + world.rb_geo.is_world = 1; + rb_init( &world.rb_geo ); + + /* + * Generate scene: non-collidable geometry + * ---------------------------------------------------------------- */ - scene_init( &world.foliage ); + vg_info( "Generating non-collidable geometry\n" ); + + world.scene_no_collide = scene_init( world.dynamic_vgl, 200000, 500000 ); + vg_info( "Applying foliage\n" ); world_apply_procedural_foliage(); - scene_copy_slice( &world.foliage, &world.sm_foliage_main ); + scene_copy_slice( world.scene_no_collide, &world.sm_foliage_main ); - world_add_all_if_material( midentity, &world.foliage, mworld, mat_alphatest); - scene_copy_slice( &world.foliage, &world.sm_foliage_alphatest ); + vg_info( "alphatest...\n" ); + world_add_all_if_material( midentity, world.scene_no_collide, + world.meta, mat_alphatest ); + scene_copy_slice( world.scene_no_collide, &world.sm_foliage_alphatest ); - world_add_all_if_material( midentity, &world.foliage, mworld, mat_graffiti ); - scene_copy_slice( &world.foliage, &world.sm_graffiti ); + vg_info( "graffiti...\n" ); + world_add_all_if_material( midentity, world.scene_no_collide, + world.meta, mat_graffiti ); + scene_copy_slice( world.scene_no_collide, &world.sm_graffiti ); + /* upload and free that */ vg_acquire_thread_sync(); { - scene_upload( &world.foliage ); + scene_upload( world.scene_no_collide, &world.mesh_no_collide ); + } + vg_release_thread_sync(); + + vg_linear_del( world.dynamic_vgl, world.scene_no_collide ); + world.scene_no_collide = NULL; +} +VG_STATIC void world_post_process(void) +{ + /* initialize audio if need be */ + audio_lock(); + for( int i=0; iplayer ); + audio_player_set_flags( &thingy->player, thingy->flags ); + audio_player_set_vol( &thingy->player, thingy->volume ); + audio_player_set_pan( &thingy->player, 0.0f ); + + if( thingy->flags & AUDIO_FLAG_SPACIAL_3D ) + audio_player_set_position( &thingy->player, thingy->pos ); + + if( thingy->flags & AUDIO_FLAG_AUTO_START ) + audio_player_playclip( &thingy->player, &thingy->temp_embedded_clip ); + } + audio_unlock(); + + vg_acquire_thread_sync(); + { /* * Rendering the depth map */ @@ -397,12 +520,12 @@ static void world_load(void) m4x3f camera; v3f extent; - v3_sub( world.geo.bbx[1], world.geo.bbx[0], extent ); + v3_sub( world.scene_geo->bbx[1], world.scene_geo->bbx[0], extent ); - float fl = world.geo.bbx[0][0], - fr = world.geo.bbx[1][0], - fb = world.geo.bbx[0][2], - ft = world.geo.bbx[1][2], + float fl = world.scene_geo->bbx[0][0], + fr = world.scene_geo->bbx[1][0], + fb = world.scene_geo->bbx[0][2], + ft = world.scene_geo->bbx[1][2], rl = 1.0f / (fr-fl), tb = 1.0f / (ft-fb); @@ -434,14 +557,18 @@ static void world_load(void) * TODO: World settings entity */ struct ub_world_lighting *winfo = &gpipeline.ub_world_lighting; - v4_copy( wrender.plane, winfo->g_water_plane ); - v4f bounds; - bounds[0] = world.geo.bbx[0][0]; - bounds[1] = world.geo.bbx[0][2]; - bounds[2] = 1.0f/ (world.geo.bbx[1][0]-world.geo.bbx[0][0]); - bounds[3] = 1.0f/ (world.geo.bbx[1][2]-world.geo.bbx[0][2]); - v4_copy( bounds, winfo->g_depth_bounds ); + if( world.water.enabled ) + v4_copy( world.water.plane, winfo->g_water_plane ); + + v4f info_vec; + v3f *bounds = world.scene_geo->bbx; + + info_vec[0] = bounds[0][0]; + info_vec[1] = bounds[0][2]; + info_vec[2] = 1.0f/ (bounds[1][0]-bounds[0][0]); + info_vec[3] = 1.0f/ (bounds[1][2]-bounds[0][2]); + v4_copy( info_vec, winfo->g_depth_bounds ); winfo->g_water_fog = 0.04f; render_update_lighting_ub(); @@ -449,25 +576,84 @@ static void world_load(void) vg_release_thread_sync(); - world_routes_loadfrom( mworld ); - - for( int i=0; igate.co[0], camera[3] ); if( dist < closest ) @@ -214,14 +191,14 @@ static void render_world_gates( m4x4f projection, v3f playerco, m4x3f camera ) } } - render_gate( &world_routes.gates[id].gate, playerco, camera ); + render_gate( &world.gates[id].gate, playerco, camera ); v3_lerp( world.render_gate_pos, - world_routes.gates[id].gate.co[0], + world.gates[id].gate.co[0], 1.0f, world.render_gate_pos ); } -static void render_world( m4x4f projection, m4x3f camera ) +VG_STATIC void render_world( m4x4f projection, m4x3f camera ) { render_sky( camera ); render_world_routes( projection, camera[3] ); @@ -232,9 +209,9 @@ static void render_world( m4x4f projection, m4x3f camera ) int closest = 0; float min_dist = INFINITY; - for( int i=0; inext[stack_i[si-1]]; stack_i[si-1] ++; @@ -107,37 +108,35 @@ static u32 world_routes_get_path( u32 starter, u32 stack[64] ) /* * Free a segment from the UI bar to be reused later */ -static void world_routes_ui_popfirst( u32 route ) +VG_STATIC void world_routes_ui_popfirst( struct route_ui_bar *pui ) { - struct route *pr = &world_routes.routes[route]; - - if( pr->ui.segment_count ) + if( pui->segment_count ) { - pr->ui.segment_start ++; + pui->segment_start ++; - if( pr->ui.segment_start == 32 ) - pr->ui.segment_start = 0; + if( pui->segment_start == 32 ) + pui->segment_start = 0; - pr->ui.segment_count --; + pui->segment_count --; } } /* * Reset ui bar completely */ -static void world_routes_ui_clear( u32 route ) +VG_STATIC void world_routes_ui_clear( struct route_ui_bar *pui ) { - struct route *pr = &world_routes.routes[route]; - pr->ui.segment_start = (pr->ui.segment_start + pr->ui.segment_count) % - k_max_ui_segments; - pr->ui.segment_count = 0; + pui->segment_start = (pui->segment_start + pui->segment_count) % + k_max_ui_segments; + pui->segment_count = 0; } /* * Break a index range into two pieces over the edge of the maximum it can * store. s1 is 0 always, so its a ring buffer. */ -static void world_routes_ui_split_indices( u32 s0, u32 count, u32 *c0, u32 *c1 ) +VG_STATIC void world_routes_ui_split_indices( u32 s0, u32 count, + u32 *c0, u32 *c1 ) { *c0 = (VG_MIN( s0+count, k_route_ui_max_indices )) - s0; *c1 = count-(*c0); @@ -147,41 +146,42 @@ static void world_routes_ui_split_indices( u32 s0, u32 count, u32 *c0, u32 *c1 ) * Place a set of indices into gpu array automatically splits * across bounds */ -static void world_routes_ui_set_indices( struct route *pr, - u16 *indices, u32 count ) +VG_STATIC void world_routes_ui_set_indices( struct route_ui_bar *pui, + u16 *indices, u32 count ) { u32 c0, c1; - world_routes_ui_split_indices( pr->ui.indices_head, count, &c0, &c1 ); + world_routes_ui_split_indices( pui->indices_head, count, &c0, &c1 ); - glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, pr->ui.ebo ); + glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, pui->ebo ); if( c0 ) { - glBufferSubData( GL_ELEMENT_ARRAY_BUFFER, pr->ui.indices_head*sizeof(u16), + glBufferSubData( GL_ELEMENT_ARRAY_BUFFER, pui->indices_head*sizeof(u16), c0*sizeof(u16), indices ); } if( c1 ) { glBufferSubData( GL_ELEMENT_ARRAY_BUFFER, 0, c1*sizeof(u16), indices+c0 ); - pr->ui.indices_head = c1; + pui->indices_head = c1; } else - pr->ui.indices_head += c0; + pui->indices_head += c0; } /* * Place a set of vertices into gpu array */ -static u32 world_routes_ui_set_verts( struct route *pr, v2f *verts, u32 count ) +VG_STATIC u32 world_routes_ui_set_verts( struct route_ui_bar *pui, + v2f *verts, u32 count ) { - if( pr->ui.vertex_head + count >= k_route_ui_max_verts ) - pr->ui.vertex_head = 0; + if( pui->vertex_head + count >= k_route_ui_max_verts ) + pui->vertex_head = 0; - u32 vert_start = pr->ui.vertex_head; - pr->ui.vertex_head += count; + u32 vert_start = pui->vertex_head; + pui->vertex_head += count; - glBindBuffer( GL_ARRAY_BUFFER, pr->ui.vbo ); + glBindBuffer( GL_ARRAY_BUFFER, pui->vbo ); glBufferSubData( GL_ARRAY_BUFFER, (GLintptr)(vert_start*sizeof(v2f)), sizeof(v2f)*count, verts ); @@ -192,12 +192,12 @@ static u32 world_routes_ui_set_verts( struct route *pr, v2f *verts, u32 count ) * Update the last (count) vertices positions, does not add any. * Data must already be written to, and not cross either array boundaries. */ -static u32 world_routes_ui_update_verts( struct route *pr, +VG_STATIC u32 world_routes_ui_update_verts( struct route_ui_bar *pui, v2f *verts, u32 count ) { - u32 vert_start = pr->ui.vertex_head-count; + u32 vert_start = pui->vertex_head-count; - glBindBuffer( GL_ARRAY_BUFFER, pr->ui.vbo ); + glBindBuffer( GL_ARRAY_BUFFER, pui->vbo ); glBufferSubData( GL_ARRAY_BUFFER, (GLintptr)(vert_start*sizeof(v2f)), sizeof(v2f)*count, verts ); @@ -207,28 +207,29 @@ static u32 world_routes_ui_update_verts( struct route *pr, /* * Current/active segment of this UI bar */ -static struct route_ui_segment *world_routes_ui_curseg( struct route *pr ) +VG_STATIC struct route_ui_segment *world_routes_ui_curseg( + struct route_ui_bar *pui ) { - u32 index = (pr->ui.segment_start+pr->ui.segment_count-1)%k_max_ui_segments; - return &pr->ui.segments[ index ]; + u32 index = (pui->segment_start+pui->segment_count-1)%k_max_ui_segments; + return &pui->segments[ index ]; } /* * Start a new segment in the UI bar, will create a split on the last one if * there is one active currently. (api) */ -static void world_routes_ui_newseg( u32 route ) +VG_STATIC void world_routes_ui_newseg( u32 route ) { - struct route *pr = &world_routes.routes[route]; + struct route_ui_bar *pui = &world.ui_bars[route]; - pr->ui.last_notch = 0.0; + pui->last_notch = 0.0; - glBindVertexArray( pr->ui.vao ); - if( pr->ui.segment_count ) + glBindVertexArray( pui->vao ); + if( pui->segment_count ) { float const k_gap_width = 1.0f; - struct route_ui_segment *cseg = world_routes_ui_curseg(pr); + struct route_ui_segment *cseg = world_routes_ui_curseg( pui ); v2f verts[2]; verts[0][0] = cseg->length-k_gap_width; @@ -236,11 +237,11 @@ static void world_routes_ui_newseg( u32 route ) verts[1][0] = cseg->length-k_gap_width; verts[1][1] = -0.5f; - world_routes_ui_update_verts( pr, verts, 2 ); + world_routes_ui_update_verts( pui, verts, 2 ); } - pr->ui.segment_count ++; - struct route_ui_segment *segment = world_routes_ui_curseg(pr); + pui->segment_count ++; + struct route_ui_segment *segment = world_routes_ui_curseg( pui ); v2f verts[4]; verts[0][0] = 0.0f; @@ -252,7 +253,7 @@ static void world_routes_ui_newseg( u32 route ) verts[3][0] = 0.0f; verts[3][1] = -0.5f; - u32 vert_start = world_routes_ui_set_verts( pr, verts, 4 ); + u32 vert_start = world_routes_ui_set_verts( pui, verts, 4 ); u16 indices[6]; indices[0] = vert_start + 0; @@ -264,19 +265,19 @@ static void world_routes_ui_newseg( u32 route ) segment->vertex_start = vert_start; segment->vertex_count = 4; - segment->index_start = pr->ui.indices_head; + segment->index_start = pui->indices_head; segment->index_count = 6; segment->notches = 0; - world_routes_ui_set_indices( pr, indices, 6 ); + world_routes_ui_set_indices( pui, indices, 6 ); } /* * Extend the end of the bar */ -static void world_routes_ui_updatetime( u32 route, float time ) +VG_STATIC void world_routes_ui_updatetime( u32 route, float time ) { - struct route *pr = &world_routes.routes[route]; + struct route_ui_bar *pui = &world.ui_bars[route]; v2f verts[2]; verts[0][0] = time; @@ -284,96 +285,16 @@ static void world_routes_ui_updatetime( u32 route, float time ) verts[1][0] = time; verts[1][1] = -0.5f; - u32 vert_start = pr->ui.vertex_head-2; + u32 vert_start = pui->vertex_head-2; - glBindVertexArray( pr->ui.vao ); - world_routes_ui_update_verts( pr, verts, 2 ); + glBindVertexArray( pui->vao ); + world_routes_ui_update_verts( pui, verts, 2 ); - struct route_ui_segment *cseg = world_routes_ui_curseg(pr); + struct route_ui_segment *cseg = world_routes_ui_curseg( pui ); cseg->length = time; } -/* - * Create a notch in the bar, used when a reset is triggered by the user - */ -static void world_routes_ui_notch( u32 route, float time ) -{ - return; /* FIXME: Temporarily disabled */ - - struct route *pr = &world_routes.routes[route]; - - if( (time - pr->ui.last_notch) > 1.0 ) - { - struct route_ui_segment *segment = world_routes_ui_curseg(pr); - if( segment->notches == k_max_ui_splits_per_segment ) - return; - - segment->notches ++; - - v2f verts[8]; - - float const k_notch_width = 1.0f; - - float xa = time-k_notch_width, - xb = time-k_notch_width * 0.5f, - xc = time; - - verts[0][0] = xa; - verts[0][1] = 0.5f; - verts[1][0] = xa; - verts[1][1] = -0.5f; - - verts[2][0] = xb; - verts[2][1] = 0.25f; - verts[3][0] = xb; - verts[3][1] = -0.25f; - - verts[4][0] = xc; - verts[4][1] = 0.5f; - verts[5][0] = xc; - verts[5][1] = -0.5f; - - verts[6][0] = xc; - verts[6][1] = 0.5f; - verts[7][0] = xc; - verts[7][1] = -0.5f; - - glBindVertexArray( pr->ui.vao ); - u32 vert_start_mod = world_routes_ui_update_verts( pr, verts, 2 ), - vert_start_new = world_routes_ui_set_verts( pr, verts+2, 6 ); - - u16 indices[18]; - indices[ 0] = vert_start_mod+1; - indices[ 1] = vert_start_new+0; - indices[ 2] = vert_start_mod+0; - indices[ 3] = vert_start_mod+1; - indices[ 4] = vert_start_new+1; - indices[ 5] = vert_start_new+0; - - indices[ 6] = vert_start_new+0; - indices[ 7] = vert_start_new+1; - indices[ 8] = vert_start_new+3; - indices[ 9] = vert_start_new+0; - indices[10] = vert_start_new+3; - indices[11] = vert_start_new+2; - - indices[12] = vert_start_new+3; - indices[13] = vert_start_new+4; - indices[14] = vert_start_new+2; - indices[15] = vert_start_new+3; - indices[16] = vert_start_new+5; - indices[17] = vert_start_new+4; - - world_routes_ui_set_indices( pr, indices, 18 ); - - pr->ui.last_notch = time; - - segment->vertex_count += 6; - segment->index_count += 18; - } -} - -static void world_routes_ui_draw_segment( struct route_ui_segment *segment ) +VG_STATIC void world_routes_ui_draw_segment( struct route_ui_segment *segment ) { u32 c0, c1; world_routes_ui_split_indices( segment->index_start, @@ -388,28 +309,29 @@ static void world_routes_ui_draw_segment( struct route_ui_segment *segment ) /* * Draws full bar at Y offset(offset). */ -static void world_routes_ui_draw( u32 route, v4f colour, float offset ) +VG_STATIC void world_routes_ui_draw( u32 route, v4f colour, float offset ) { float const k_bar_height = 0.05f, k_bar_scale_x = 0.005f; - struct route *pr = &world_routes.routes[route]; + struct route *pr = &world.routes[route]; + struct route_ui_bar *pui = &world.ui_bars[route]; - float cx = pr->ui.xpos; + float cx = pui->xpos; shader_routeui_use(); - glBindVertexArray( pr->ui.vao ); + glBindVertexArray( pui->vao ); - float fade_amt = world_routes.time - pr->ui.fade_timer_start; + float fade_amt = world.time - pui->fade_timer_start; fade_amt = vg_clampf( fade_amt / 1.0f, 0.0f, 1.0f ); float fade_block_size = 0.0f, main_block_size = 0.0f; - for( u32 i=0; iui.fade_count; i++ ) + for( u32 i=0; ifade_count; i++ ) { - u32 j = (pr->ui.fade_start + i) % k_max_ui_segments; - struct route_ui_segment *segment = &pr->ui.segments[j]; + u32 j = (pui->fade_start + i) % k_max_ui_segments; + struct route_ui_segment *segment = &pui->segments[j]; fade_block_size += segment->length; } @@ -421,7 +343,7 @@ static void world_routes_ui_draw( u32 route, v4f colour, float offset ) fade_colour[3] *= 1.0f-fade_amt; /* 1 minute timer */ - float timer_delta = (world_routes.time - world_routes.last_use) * (1.0/45.0), + float timer_delta = (world.time - world.last_use) * (1.0/45.0), timer_scale = 1.0f - vg_minf( timer_delta, 1.0f ); /* @@ -432,10 +354,10 @@ static void world_routes_ui_draw( u32 route, v4f colour, float offset ) base = -1.0f + (offset+0.5f)*k_bar_height * timer_scale; shader_routeui_uColour( fade_colour ); - for( u32 i=0; iui.fade_count; i++ ) + for( u32 i=0; ifade_count; i++ ) { - u32 j = (pr->ui.fade_start + i) % k_max_ui_segments; - struct route_ui_segment *segment = &pr->ui.segments[j]; + u32 j = (pui->fade_start + i) % k_max_ui_segments; + struct route_ui_segment *segment = &pui->segments[j]; shader_routeui_uOffset( (v4f){ cx*k_bar_scale_x, base, k_bar_scale_x, height } ); @@ -448,10 +370,10 @@ static void world_routes_ui_draw( u32 route, v4f colour, float offset ) * Draw main bar */ shader_routeui_uColour( colour ); - for( u32 i=0; iui.segment_count; i++ ) + for( u32 i=0; isegment_count; i++ ) { - u32 j = (pr->ui.segment_start + i) % k_max_ui_segments; - struct route_ui_segment *segment = &pr->ui.segments[j]; + u32 j = (pui->segment_start + i) % k_max_ui_segments; + struct route_ui_segment *segment = &pui->segments[j]; shader_routeui_uOffset( (v4f){ cx*k_bar_scale_x, base, k_bar_scale_x, height } ); @@ -462,14 +384,14 @@ static void world_routes_ui_draw( u32 route, v4f colour, float offset ) main_block_size += segment->length; } - pr->ui.xpos = vg_lerpf( pr->ui.xpos, -main_block_size * 0.5f, 0.03f ); + pui->xpos = vg_lerpf( pui->xpos, -main_block_size * 0.5f, 0.03f ); } -static void world_routes_local_set_record( u32 route, double lap_time ) +VG_STATIC void world_routes_local_set_record( u32 route, double lap_time ) { vg_success( " NEW LAP TIME: %f\n", lap_time ); - struct route *pr = &world_routes.routes[route]; + struct route *pr = &world.routes[route]; if( pr->track_id != 0xffffffff ) { @@ -507,12 +429,13 @@ static void world_routes_local_set_record( u32 route, double lap_time ) * 2: the time of each segment will be recorded into the data buffer * (not implemented: TODO) */ -static void world_routes_verify_run( u32 route ) +VG_STATIC void world_routes_verify_run( u32 route ) { - struct route *pr = &world_routes.routes[route]; + struct route *pr = &world.routes[route]; + struct route_ui_bar *pui = &world.ui_bars[route]; u32 stack[64]; - u32 si = world_routes_get_path( world_routes.routes[route].start, stack ); + u32 si = world_routes_get_path( world.routes[route].start, stack ); /* * we only care about gates that ref gates, so shuffle down the array @@ -521,15 +444,15 @@ static void world_routes_verify_run( u32 route ) u32 sj = 0, maxv = 0, begin = 0; for( u32 i=0; ispecial_type == k_route_special_type_collector ) { - timings[sj ++] = &world_routes.collectors[ inode->special_id ].timing; + timings[sj ++] = &world.collectors[ inode->special_id ].timing; } else if( inode->special_type == k_route_special_type_gate ) { - timings[sj ++] = &world_routes.gates[inode->special_id].timing; + timings[sj ++] = &world.gates[inode->special_id].timing; } } @@ -543,10 +466,10 @@ static void world_routes_verify_run( u32 route ) } vg_info( "== begin verification (%u) ==\n", route ); - vg_info( " current version: %u\n", world_routes.current_run_version ); + vg_info( " current version: %u\n", world.current_run_version ); int verified = 0; - if( timings[begin]->version == world_routes.current_run_version ) + if( timings[begin]->version == world.current_run_version ) verified = 1; int valid_segment_count = 0; @@ -576,24 +499,24 @@ static void world_routes_verify_run( u32 route ) if( verified ) vg_success( " [ %u %f ] %f\n", timings[j1]->time, - timings[j1]->version, diff ); + timings[j1]->version, diff ); else vg_warn( " [ %u %f ]\n", timings[j1]->time, timings[j1]->version ); } - pr->ui.fade_start = pr->ui.segment_start; - pr->ui.fade_count = 0; - pr->ui.fade_timer_start = world_routes.time; + pui->fade_start = pui->segment_start; + pui->fade_count = 0; + pui->fade_timer_start = world.time; - int orig_seg_count = pr->ui.segment_count; + int orig_seg_count = pui->segment_count; world_routes_ui_newseg( route ); if( verified ) { world_routes_local_set_record( route, lap_time ); - world_routes_ui_popfirst(route); - pr->ui.fade_count ++; + world_routes_ui_popfirst( pui ); + pui->fade_count ++; } else vg_info( " ctime: %f\n", lap_time ); @@ -602,32 +525,33 @@ static void world_routes_verify_run( u32 route ) int to_remove = orig_seg_count-valid_segment_count; for( int i=0; iui.fade_count ++; + world_routes_ui_popfirst( pui ); + pui->fade_count ++; } - world_routes.routes[route].latest_pass = world_routes.time; + world.routes[route].latest_pass = world.time; } /* * When going through a gate this is called for bookkeeping purposes */ -static void world_routes_activate_gate( u32 id ) +VG_STATIC void world_routes_activate_gate( u32 id ) { - struct route_gate *rg = &world_routes.gates[id]; - struct route_node *pnode = &world_routes.nodes[rg->node_id], - *pdest = &world_routes.nodes[pnode->next[0]]; + struct route_gate *rg = &world.gates[id]; + struct route_node *pnode = &world.nodes[rg->node_id], + *pdest = &world.nodes[pnode->next[0]]; + + world.last_use = world.time; - world_routes.last_use = world_routes.time; + struct route_collector *rc = &world.collectors[ pdest->special_id ]; - struct route_collector *rc = &world_routes.collectors[ pdest->special_id ]; + world.active_gate = id; + rg->timing.version = world.current_run_version; + rg->timing.time = world.time; - world_routes.active_gate = id; - rg->timing.version = world_routes.current_run_version; - rg->timing.time = world_routes.time; - for( u32 i=0; iactive; @@ -644,30 +568,31 @@ static void world_routes_activate_gate( u32 id ) if( was_active && !route->active ) { - route->ui.fade_start = route->ui.segment_start; - route->ui.fade_count = route->ui.segment_count; - route->ui.fade_timer_start = world_routes.time; - world_routes_ui_clear(i); - - vg_success( "CLEARING -> %u %u \n", route->ui.fade_start, - route->ui.fade_count ); + struct route_ui_bar *pui = &world.ui_bars[i]; + pui->fade_start = pui->segment_start; + pui->fade_count = pui->segment_count; + pui->fade_timer_start = world.time; + + world_routes_ui_clear( pui ); + vg_success( "CLEARING -> %u %u \n", pui->fade_start, + pui->fade_count ); } } - world_routes.current_run_version ++; + world.current_run_version ++; - rc->timing.version = world_routes.current_run_version; - rc->timing.time = world_routes.time; - world_routes.current_run_version ++; + rc->timing.version = world.current_run_version; + rc->timing.time = world.time; + world.current_run_version ++; } /* * Notify the UI system that we've reset the player */ -static void world_routes_notify_reset(void) +VG_STATIC void world_routes_notify_reset(void) { - world_routes.rewind_from = world_routes.time; - world_routes.rewind_to = world_routes.last_use; + world.rewind_from = world.time; + world.rewind_to = world.last_use; #if 0 for( int i=0; iroute_count; i++ ) @@ -681,25 +606,23 @@ static void world_routes_notify_reset(void) } /* Rewind between the saved points in time */ -static void world_routes_rollback_time( double t ) +VG_STATIC void world_routes_rollback_time( double t ) { - world_routes.time = - vg_lerp( world_routes.rewind_to, world_routes.rewind_from, t ); + world.time = vg_lerp( world.rewind_to, world.rewind_from, t ); } /* draw lines along the paths */ -static void world_routes_debug(void) +VG_STATIC void world_routes_debug(void) { - - for( int i=0; ico, 1.0f, rn->special_type? 0xffffff00: 0xff00b2ff ); } - for( int i=0; istart, stack ); @@ -713,39 +636,31 @@ static void world_routes_debug(void) { int sk = (sj+1)%si; - struct route_node *pj = &world_routes.nodes[stack[sj]], - *pk = &world_routes.nodes[stack[sk]]; + struct route_node *pj = &world.nodes[stack[sj]], + *pk = &world.nodes[stack[sk]]; debug_sbpath( pj, pk, cc, (float)i ); } } - for( int i=0; inext[j] != 0xffffffff ) { - rj = &world_routes.nodes[ri->next[j]]; + rj = &world.nodes[ri->next[j]]; vg_line( ri->co, rj->co, 0x20ffffff ); } } } } -static void world_id_fixup( u32 *uid, mdl_header *mdl ) +VG_STATIC void world_routes_create_mesh( u32 route_id ) { - if( *uid ) - *uid = mdl_node_from_id( mdl, *uid )->sub_uid; - else - *uid = 0xffffffff; -} - -static void world_routes_create_mesh( u32 route_id ) -{ - struct route *route = &world_routes.routes[ route_id ]; + struct route *route = &world.routes[ route_id ]; u32 stack[64]; u32 si = world_routes_get_path( route->start, stack ); @@ -756,8 +671,8 @@ static void world_routes_create_mesh( u32 route_id ) { int sk=(sj+1)%si; - struct route_node *rnj = &world_routes.nodes[ stack[sj] ], - *rnk = &world_routes.nodes[ stack[sk] ], + struct route_node *rnj = &world.nodes[ stack[sj] ], + *rnk = &world.nodes[ stack[sk] ], *rnl; if( rnj->special_type && rnk->special_type ) @@ -771,7 +686,7 @@ static void world_routes_create_mesh( u32 route_id ) if( rnk->special_type ) { - rnl = &world_routes.nodes[ rnk->next[0] ]; + rnl = &world.nodes[ rnk->next[0] ]; base_x1 = (float)rnl->ref_count*-0.5f + (float)rnl->current_refs; } @@ -830,19 +745,19 @@ static void world_routes_create_mesh( u32 route_id ) v2_zero( va.uv ); v2_zero( vb.uv ); - scene_push_vert( &world_routes.scene_lines, &va ); - scene_push_vert( &world_routes.scene_lines, &vb ); + scene_push_vert( world.scene_lines, &va ); + scene_push_vert( world.scene_lines, &vb ); if( last_valid ) { /* Connect them with triangles */ - scene_push_tri( &world_routes.scene_lines, (u32[3]){ + scene_push_tri( world.scene_lines, (u32[3]){ last_valid+0-2, last_valid+1-2, last_valid+2-2} ); - scene_push_tri( &world_routes.scene_lines, (u32[3]){ + scene_push_tri( world.scene_lines, (u32[3]){ last_valid+1-2, last_valid+3-2, last_valid+2-2} ); } - last_valid = world_routes.scene_lines.vertex_count; + last_valid = world.scene_lines->vertex_count; } else last_valid = 0; @@ -860,255 +775,286 @@ static void world_routes_create_mesh( u32 route_id ) rnj->current_refs ++; } - scene_copy_slice( &world_routes.scene_lines, &route->sm ); + scene_copy_slice( world.scene_lines, &route->sm ); } /* * Create the strips of colour that run through the world along course paths */ -static int world_routes_create_all_meshes(void) +VG_STATIC void world_routes_generate(void) { vg_info( "Generating route meshes\n" ); + world.scene_lines = scene_init( world.dynamic_vgl, 200000, 300000 ); - scene_init( &world_routes.scene_lines ); - - for( u32 i=0; iclasstype == k_classtype_gate ) + { + struct classtype_gate *inf = mdl_get_entdata( world.meta, pnode ); - /* UI buffers */ - for( int i=0; itarget ) { - /* OpenGL strips */ - struct route *route = &world_routes.routes[i]; + mdl_node *pother = mdl_node_from_id( world.meta, inf->target ); + + if( pother->classtype == k_classtype_gate ) + { + return k_route_special_type_gate; + } + } - glGenVertexArrays( 1, &route->ui.vao ); - glGenBuffers( 1, &route->ui.vbo ); - glGenBuffers( 1, &route->ui.ebo ); - glBindVertexArray( route->ui.vao ); + return k_route_special_type_collector; + } - size_t stride = sizeof(v2f); + return k_route_special_type_none; +} - glBindBuffer( GL_ARRAY_BUFFER, route->ui.vbo ); - glBufferData( GL_ARRAY_BUFFER, k_route_ui_max_verts*stride, - NULL, GL_DYNAMIC_DRAW ); +/* count entities and allocate correct amount of memory in advance */ +VG_STATIC void world_routes_allocate(void) +{ + vg_info( "Allocating routes\n" ); - glBindVertexArray( route->ui.vao ); - glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, route->ui.ebo ); - glBufferData( GL_ELEMENT_ARRAY_BUFFER, - k_route_ui_max_indices*sizeof(u16), NULL, - GL_DYNAMIC_DRAW ); + /* count */ + u32 node_count = 0, + route_count = 0, + gate_count = 0, + collector_count = 0; + + for( int i=0; iinfo.node_count; i++ ) + { + mdl_node *pnode = mdl_node_from_id( world.meta, i ); - glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, stride, (void *)0 ); - glEnableVertexAttribArray( 0 ); - VG_CHECK_GL_ERR(); + if( pnode->classtype == k_classtype_route_node || + pnode->classtype == k_classtype_gate ) + { + pnode->sub_uid = node_count; + + enum route_special_type type = world_route_node_type( pnode ); + + if( type == k_route_special_type_gate ) + gate_count ++; + else if( type == k_route_special_type_collector ) + collector_count ++; + + node_count ++; + } + else if( pnode->classtype == k_classtype_route ) + { + route_count ++; } } - vg_release_thread_sync(); - scene_free_offline_buffers( &world_routes.scene_lines ); - return 1; -} + /* allocate */ + u32 node_size = node_count * sizeof(struct route_node), + route_size = route_count * sizeof(struct route), + gate_size = gate_count * sizeof(struct route_gate), + collector_size = collector_count * sizeof(struct route_collector); + world.nodes = vg_linear_alloc( world.dynamic_vgl, node_size ); + world.routes = vg_linear_alloc( world.dynamic_vgl, route_size ); + world.gates = vg_linear_alloc( world.dynamic_vgl, gate_size ); + world.collectors = vg_linear_alloc( world.dynamic_vgl, collector_size ); +} -static void world_routes_loadfrom( mdl_header *mdl ) +/* create node from mdl node */ +VG_STATIC struct route_node *world_routes_create_node( mdl_node *pnode ) { - vg_info( "Initializing routes\n" ); + struct route_node *rn = &world.nodes[ world.node_count ++ ]; - world_routes.nodes = NULL; - world_routes.node_count = 0; - world_routes.node_cap = 0; - world_routes.routes = NULL; - world_routes.route_count = 0; - world_routes.route_cap = 0; - world_routes.gates = NULL; - world_routes.gate_count = 0; - world_routes.gate_cap = 0; - - /* TODO Break this up */ - for( int i=0; inode_count; i++ ) - { - mdl_node *pnode = mdl_node_from_id(mdl,i); - m4x3f transform; + m4x3f transform; + mdl_node_transform( pnode, transform ); - if( pnode->classtype == k_classtype_route_node || - pnode->classtype == k_classtype_gate ) - { - mdl_node_transform( pnode, transform ); - pnode->sub_uid = world_routes.node_count; - - world_routes.nodes = buffer_reserve( world_routes.nodes, - world_routes.node_count, - &world_routes.node_cap, 1, - sizeof( struct route_node ) ); - - struct route_node *rn = &world_routes.nodes[world_routes.node_count]; - - v3_copy( transform[0], rn->right ); - v3_normalize( rn->right ); - v3_copy( transform[1], rn->up ); - v3_normalize( rn->up ); - v3_muls( transform[2], -1.0f, rn->h ); - v3_copy( transform[3], rn->co ); - rn->ref_count = 0; - rn->current_refs = 0; - rn->special_type = 0; - rn->special_id = 0; + v3_copy( transform[3], rn->co ); + v3_copy( transform[0], rn->right ); + v3_copy( transform[1], rn->up ); + v3_muls( transform[2], -1.0f, rn->h ); + v3_normalize( rn->right ); + v3_normalize( rn->up ); - if( pnode->classtype == k_classtype_gate ) - { - struct classtype_gate *inf = mdl_get_entdata( mdl, pnode ); + rn->next[0] = 0xffffffff; + rn->next[1] = 0xffffffff; - /* H is later scaled based on link distance */ - v3_normalize( rn->h ); - rn->next[0] = inf->target; - rn->next[1] = 0; + rn->special_type = 0; + rn->special_id = 0; + rn->current_refs = 0; + rn->ref_count = 0; - /* TODO */ - if( inf->target ) - { - mdl_node *pother = mdl_node_from_id( mdl, inf->target ); - - if( pother->classtype == k_classtype_gate ) - { - world_routes.gates = buffer_reserve( world_routes.gates, - world_routes.gate_count, - &world_routes.gate_cap, - 1, sizeof( struct route_gate ) ); - - struct route_gate *rg = - &world_routes.gates[world_routes.gate_count]; - - rg->node_id = world_routes.node_count; - rg->timing.time = 0.0; - rg->timing.version = 0; - - v3_copy( pnode->co, rg->gate.co[0] ); - v3_copy( pother->co, rg->gate.co[1] ); - v4_copy( pnode->q, rg->gate.q[0] ); - v4_copy( pother->q, rg->gate.q[1] ); - v2_copy( inf->dims, rg->gate.dims ); - - gate_transform_update( &rg->gate ); - rn->special_type = k_route_special_type_gate; - rn->special_id = world_routes.gate_count; - - world_routes.gate_count ++; - } - } + return rn; +} - if( rn->special_type == 0 ) - { - world_routes.collectors = buffer_reserve( - world_routes.collectors, - world_routes.collector_count, - &world_routes.collector_cap, - 1, sizeof( struct route_collector )); +/* retrieve the correct node id from mdl subuid */ +VG_STATIC u32 world_routes_get_subuid( u32 target ) +{ + if( target == 0 ) + return 0xffffffff; + else + return mdl_node_from_id( world.meta, target )->sub_uid; +} + +#if 0 +VG_STATIC void world_id_fixup( u32 *uid, mdl_context *mdl ) +{ + if( *uid ) + *uid = mdl_node_from_id( mdl, *uid )->sub_uid; + else + *uid = 0xffffffff; +} +#endif - struct route_collector *rc = - &world_routes.collectors[world_routes.collector_count]; - rc->timing.time = 0.0; - rc->timing.version = 0; +/* process gate attachement onto node */ +VG_STATIC void world_routes_process_gate( struct route_node *rn, + mdl_node *pnode ) +{ + struct classtype_gate *inf = mdl_get_entdata( world.meta, pnode ); - rn->special_type = k_route_special_type_collector; - rn->special_id = world_routes.collector_count; + /* H is later scaled based on link distance */ + v3_normalize( rn->h ); - world_routes.collector_count ++; - } - } - else - { - struct classtype_route_node *inf = mdl_get_entdata( mdl, pnode ); - rn->next[0] = inf->target; - rn->next[1] = inf->target1; - } + rn->next[0] = world_routes_get_subuid( inf->target ); + rn->next[1] = 0xffffffff; + rn->special_type = world_route_node_type( pnode ); - world_routes.node_count ++; - } - else if( pnode->classtype == k_classtype_route ) - { - struct classtype_route *inf = mdl_get_entdata( mdl, pnode ); - world_routes.routes = buffer_reserve( world_routes.routes, - world_routes.route_count, - &world_routes.route_cap, - 1, sizeof( struct route ) ); + /* process gate type */ + if( rn->special_type == k_route_special_type_gate ) + { + mdl_node *pother = mdl_node_from_id( world.meta, inf->target ); + + struct route_gate *rg = &world.gates[ world.gate_count ]; - struct route *route = &world_routes.routes[world_routes.route_count]; - memset( route, 0, sizeof(struct route) ); + rg->node_id = world.node_count-1; + rg->timing.time = 0.0; + rg->timing.version = 0; - v3_copy( inf->colour, route->colour ); - route->colour[3] = 1.0f; + v3_copy( pnode->co, rg->gate.co[0] ); + v3_copy( pother->co, rg->gate.co[1] ); + v4_copy( pnode->q, rg->gate.q[0] ); + v4_copy( pother->q, rg->gate.q[1] ); + v2_copy( inf->dims, rg->gate.dims ); + gate_transform_update( &rg->gate ); + rn->special_id = world.gate_count; - route->track_id = 0xffffffff; - for( u32 j=0; jpstr_name), track_infos[j].name )) - { - route->track_id = j; - break; - } - } + world.gate_count ++; + } - route->start = inf->id_start; - route->active = 0; - route->factive = 0.0f; - mdl_node_transform( pnode, route->scoreboard_transform ); - - route->ui.indices_head = k_route_ui_max_indices - 9; - route->ui.vertex_head = k_route_ui_max_verts - 200; - route->ui.segment_start = 0; - route->ui.segment_count = 0; - route->ui.last_notch = 0.0; - route->ui.fade_start = 0; - route->ui.fade_count = 0; - route->ui.fade_timer_start = 0.0; - - world_routes.route_count ++; - } + /* process collector type */ + else if( rn->special_type == k_route_special_type_collector ) + { + struct route_collector *rc = + &world.collectors[ world.collector_count ]; + + rc->timing.time = 0.0; + rc->timing.version = 0; + + rn->special_id = world.collector_count; + world.collector_count ++; } + else + vg_fatal_exit_loop( "Invalid state" ); +} - /* - * Apply correct system-local ids - */ - for( int i=0; icolour, route->colour ); + route->colour[3] = 1.0f; + route->track_id = 0xffffffff; + + for( u32 j=0; jnext[j], mdl ); + if( !strcmp( mdl_pstr(mdl,pnode->pstr_name), track_infos[j].name )) + { + route->track_id = j; + break; + } } - for( int i=0; istart = world_routes_get_subuid( inf->id_start ); + route->active = 0; + route->factive = 0.0f; + mdl_node_transform( pnode, route->scoreboard_transform ); + + struct route_ui_bar *pui = &world.ui_bars[ world.route_count ]; + pui->indices_head = k_route_ui_max_indices - 9; + pui->vertex_head = k_route_ui_max_verts - 200; + pui->segment_start = 0; + pui->segment_count = 0; + pui->last_notch = 0.0; + pui->fade_start = 0; + pui->fade_count = 0; + pui->fade_timer_start = 0.0; + + world.route_count ++; +} + +/* load all routes from model header */ +VG_STATIC void world_routes_process(void) +{ + vg_info( "Initializing routes\n" ); + mdl_context *mdl = world.meta; + + for( int i=0; iinfo.node_count; i++ ) { - struct route *route = &world_routes.routes[i]; - world_id_fixup( &route->start, mdl ); + mdl_node *pnode = mdl_node_from_id(mdl,i); + + if( pnode->classtype == k_classtype_route_node || + pnode->classtype == k_classtype_gate ) + { + struct route_node *rn = world_routes_create_node( pnode ); + + if( pnode->classtype == k_classtype_gate ) + { + world_routes_process_gate( rn, pnode ); + } + else + { + struct classtype_route_node *inf = mdl_get_entdata( mdl, pnode ); + rn->next[0] = world_routes_get_subuid( inf->target ); + rn->next[1] = world_routes_get_subuid( inf->target1 ); + } + } + else if( pnode->classtype == k_classtype_route ) + { + world_routes_create_route( pnode ); + } } /* * Gather references */ - for( int i=0; istart, stack ); for( int sj=0; sjroute_ids[ rn->ref_count ++ ] = i; if( rn->ref_count > 4 ) vg_warn( "Too many references on route node %i\n", i ); } } - - world_routes_create_all_meshes(); } /* @@ -1117,42 +1063,67 @@ static void world_routes_loadfrom( mdl_header *mdl ) * ----------------------------------------------------------------------------- */ -static void world_routes_init(void) +VG_STATIC void world_routes_init(void) { - world_routes.current_run_version = 2; - world_routes.time = RESET_MAX_TIME*2.0; - world_routes.last_use = 0.0; + world.current_run_version = 2; + world.time = RESET_MAX_TIME*2.0; + world.last_use = 0.0; shader_route_register(); shader_routeui_register(); -} -static void world_routes_free(void*_) -{ - vg_free( world_routes.nodes ); - vg_free( world_routes.routes ); - vg_free( world_routes.gates ); + vg_acquire_thread_sync(); + { + /* UI buffers */ + for( int i=0; ivao ); + glGenBuffers( 1, &pui->vbo ); + glGenBuffers( 1, &pui->ebo ); + glBindVertexArray( pui->vao ); + + size_t stride = sizeof(v2f); + + glBindBuffer( GL_ARRAY_BUFFER, pui->vbo ); + glBufferData( GL_ARRAY_BUFFER, k_route_ui_max_verts*stride, + NULL, GL_DYNAMIC_DRAW ); + + glBindVertexArray( pui->vao ); + glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, pui->ebo ); + glBufferData( GL_ELEMENT_ARRAY_BUFFER, + k_route_ui_max_indices*sizeof(u16), NULL, + GL_DYNAMIC_DRAW ); + + glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, stride, (void *)0 ); + glEnableVertexAttribArray( 0 ); + VG_CHECK_GL_ERR(); + } + } + vg_release_thread_sync(); } -static void world_routes_update(void) +VG_STATIC void world_routes_update(void) { - world_routes.time += vg.time_delta; + world.time += vg.time_delta; - for( int i=0; ifactive = vg_lerpf( route->factive, route->active, 0.6f*vg.time_delta ); if( route->active ) { - world_routes_ui_updatetime(i, world_routes.time - route->latest_pass ); + world_routes_ui_updatetime(i, world.time - route->latest_pass ); } } } -static void bind_terrain_textures(void); -static void render_world_routes( m4x4f projection, v3f camera ) +VG_STATIC void bind_terrain_textures(void); +VG_STATIC void render_world_routes( m4x4f projection, v3f camera ) { m4x3f identity_matrix; m4x3_identity( identity_matrix ); @@ -1166,11 +1137,11 @@ static void render_world_routes( m4x4f projection, v3f camera ) shader_route_uMdl( identity_matrix ); shader_route_uCamera( camera ); - scene_bind( &world_routes.scene_lines ); + mesh_bind( &world.mesh_route_lines ); - for( int i=0; icolour, route->factive, colour ); @@ -1181,16 +1152,16 @@ static void render_world_routes( m4x4f projection, v3f camera ) } } -static void render_world_routes_ui(void) +VG_STATIC void render_world_routes_ui(void) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); float active_offset = 0.0f; - for( int i=0; icolour, active_offset ); active_offset += route->factive; } diff --git a/world_sfd.h b/world_sfd.h index 0f8e374..a83fe0a 100644 --- a/world_sfd.h +++ b/world_sfd.h @@ -53,43 +53,37 @@ float sfd_encode_glyph( char c ) return (float)value; } -static void sfd_encode( struct sfd_instance *display, u32 row, const char *str ) +VG_STATIC void sfd_encode( u32 row, const char *str ) { int end=0; - u32 row_h = display->h-1-row; + u32 row_h = world.sfd.h -1 -row; - for( int i=0; iw; i++ ) + for( int i=0; ibuffer[display->w*row_h + i] = 0.0f; + world.sfd.buffer[world.sfd.w*row_h + i] = 0.0f; } else { if( !str[i] ) end = 1; - display->buffer[display->w*row_h + i] = sfd_encode_glyph( str[i] ); + world.sfd.buffer[world.sfd.w*row_h + i] = sfd_encode_glyph( str[i] ); } } } -static void sfd_new( struct sfd_instance *display, u32 w, u32 h ) +VG_STATIC void sfd_init( u32 w, u32 h ) { - display->w = w; - display->h = h; - display->buffer = vg_alloc( w*h*sizeof(float)*2 ); - - for( int i=0; ibuffer[i] = 0.0f; } -static void sfd_update( struct sfd_instance *display ) +VG_STATIC void sfd_update(void) { - for( int i=0; iw*display->h; i++ ) + for( int i=0; ibuffer[i], - *cur = target+display->w*display->h; + float *target = &world.sfd.buffer[i*2+0], + *cur = &world.sfd.buffer[i*2+1]; float const rate = vg.time_delta * 15.2313131414f; float d1 = *target-*cur; @@ -105,11 +99,9 @@ static void sfd_update( struct sfd_instance *display ) } } -static void sfd_render( struct sfd_instance *display, - m4x4f projection, v3f camera, m4x3f transform ) +VG_STATIC void sfd_render( m4x4f projection, v3f camera, m4x3f transform ) { - struct subworld_sfd *sfd = &world.sfd; - scene_bind( &sfd->mesh ); + mesh_bind( &world.sfd.mesh_display ); shader_scoretext_use(); shader_scoretext_uTexGarbage(0); @@ -122,13 +114,13 @@ static void sfd_render( struct sfd_instance *display, shader_scoretext_uMdl( transform ); shader_scoretext_uCamera( camera ); - for( int y=0;yh; y++ ) + for( int y=0;yw; x++ ) + for( int x=0; xbuffer[display->h*display->w+y*display->w+x]; + float value = world.sfd.buffer[(y*world.sfd.w+x)*2+1]; shader_scoretext_uInfo( (v3f){ x,y, value } ); - scene_draw( &sfd->mesh ); + mesh_draw( &world.sfd.mesh_display ); } } @@ -142,54 +134,53 @@ static void sfd_render( struct sfd_instance *display, shader_vblend_uMdl( transform ); shader_vblend_uCamera( camera ); - mesh_bind( &sfd->temp ); - mesh_draw( &sfd->temp ); + mesh_bind( &world.sfd.mesh_base ); + mesh_draw( &world.sfd.mesh_base ); } -static int world_sfd_test( int argc, const char *argv[] ) +VG_STATIC int world_sfd_test( int argc, const char *argv[] ) { - struct subworld_sfd *sfd = &world.sfd; - if( argc == 2 ) { - int row = vg_min(vg_max(atoi(argv[0]),0),sfd->tester.h); - sfd_encode( &sfd->tester, row, argv[1] ); + int row = vg_min( vg_max(atoi(argv[0]),0), world.sfd.h); + sfd_encode( row, argv[1] ); } return 0; } -static void world_sfd_init(void) +VG_STATIC void world_sfd_init(void) { vg_info( "world_sfd_init\n" ); shader_scoretext_register(); - struct subworld_sfd *sfd = &world.sfd; - vg_function_push( (struct vg_cmd){ .name = "sfd", .function = world_sfd_test }); - mdl_header *mboard = mdl_load( "models/rs_scoretext.mdl" ); - scene_init( &sfd->mesh ); + vg_linear_clear( vg_mem.scratch ); + mdl_context *mboard = + mdl_load_full( vg_mem.scratch, "models/rs_scoretext.mdl" ); + + scene *sc = scene_init( vg_mem.scratch, 3000, 8000 ); mdl_node *pn_backer = mdl_node_from_name( mboard, "backer" ); - mdl_submesh *backer = mdl_submesh_from_id( mboard, pn_backer->submesh_start); + mdl_submesh *backer = &mboard->submesh_buffer[ pn_backer->submesh_start ]; mdl_node *pn_card = mdl_node_from_name( mboard, "score_card" ); - mdl_submesh *card = mdl_submesh_from_id( mboard, pn_card->submesh_start ); + mdl_submesh *card = &mboard->submesh_buffer[ pn_card->submesh_start ]; m4x3f identity; m4x3_identity( identity ); for( int i=4;i<6;i++ ) { - u32 vert_start = sfd->mesh.vertex_count; - scene_add_submesh( &sfd->mesh, mboard, card, identity ); + u32 vert_start = sc->vertex_count; + scene_add_submesh( sc, mboard, card, identity ); for( int j=0; jvertex_count; j++ ) { - mdl_vert *vert = &sfd->mesh.verts[ vert_start+j ]; + mdl_vert *vert = &sc->arrvertices[ vert_start+j ]; float const k_glyph_uvw = 1.0f/64.0f; vert->uv[0] -= k_glyph_uvw * (float)(i-4); @@ -200,23 +191,22 @@ static void world_sfd_init(void) vg_acquire_thread_sync(); { - vg_tex2d_init( (vg_tex2d *[]){ &tex_scoretext }, 1 ); + scene_upload( sc, &world.sfd.mesh_display ); + mdl_unpack_submesh( mboard, &world.sfd.mesh_base, backer ); - scene_upload( &sfd->mesh ); - mdl_unpack_submesh( mboard, &sfd->temp, backer ); + vg_tex2d_init( (vg_tex2d *[]){ &tex_scoretext }, 1 ); } vg_release_thread_sync(); - scene_free_offline_buffers( &sfd->mesh ); - sfd_new( &sfd->tester, 27, 13 ); - vg_free( mboard ); -} + int w = 27, + h = 13; + world.sfd.w = w; + world.sfd.h = h; + world.sfd.buffer = vg_linear_alloc( vg_mem.rtmemory, 2*w*h*sizeof(float) ); -static void world_sfd_free(void *_) -{ - mesh_free( &world.sfd.mesh.mesh ); - vg_tex2d_free( (vg_tex2d *[]){ &tex_scoretext }, 1 ); + for( int i=0; i