models_src/boards/workshop
ccflags/png
icons/png
+src.generated/
# auto generated code
shaders/*.h
-#include "vg/vg_tool.h"
-#include "vg/vg_platform.h"
-#include "vg/vg_log.h"
-#include "vg/vg_opt.h"
-#include "vg/vg_build.h"
-#include "vg/vg_mem_pool.h"
-#include "vg/vg_build_utils_shader.h"
-#include "vg/vg_msg.h"
-#include "src/addon_types.h"
+#define VG_BUILD_TOOLS
+#define VG_MATH
+#define VG_MSG_TO_KVS
+#include "vg/vg.hconf"
-#include "vg/vg_m.h"
-#include "src/model.h"
-#include "src/model.c"
-#include "src/array_file.c"
+#define VG_IMPLEMENTATION
+#include "vg/vg.hconf"
+#undef VG_IMPLEMENTATION
+#define VG_THIRDPARTY
+#include "vg/vg.hconf"
+#undef VG_THIRDPARTY
-/*
- * Addon metadata utilities
- * -------------------------------------------------------------------------- */
-
-void write_msg( vg_msg *msg, const char *path ){
- FILE *fp = fopen( path, "wb" );
- if( !fp ){
- vg_error( "Cannot open %s for writing.\n", path );
- exit(0);
- }
+#define SR_MODEL
+#include "src/skaterift.hconf"
- fwrite( msg->buf, msg->cur.co, 1, fp );
- fclose( fp );
- vg_success( "Written %s (%ub)\n", path, msg->cur );
-}
+#define SR_IMPLEMENTATION
+#include "src/skaterift.hconf"
+#undef SR_IMPLEMENTATION
-void write_generic_addon_inf( u32 type, const char *title,
- const char *content, const char *dest, u32 flags )
+void build_shaders(void)
{
- u8 descriptor_buf[ 512 ];
- vg_msg descriptor = {0};
- descriptor.buf = descriptor_buf;
- descriptor.max = sizeof(descriptor_buf);
- vg_msg_frame( &descriptor, "workshop" );
- vg_msg_wkvstr( &descriptor, "title", title );
- vg_msg_wkvstr( &descriptor, "author", "Skaterift" );
- vg_msg_wkvnum( &descriptor, "type", k_vg_msg_u32, 1, &type );
- vg_msg_end_frame( &descriptor );
- vg_msg_wkvstr( &descriptor, "content", content );
- if( flags )
- vg_msg_wkvnum( &descriptor, "flags", k_vg_msg_u32, 1, &flags );
- write_msg( &descriptor, dest );
-}
-
-/*
- * Compilation specifications
- * -------------------------------------------------------------------------- */
+ vg_info( "Compiling shader headers\n" );
+ vg_shader_set_include_dir( "shaders" );
-/* operates in the local files, not in the bin folders */
-void build_game_metadata(void)
-{
- vg_info( "Building game metadata\n" );
- write_generic_addon_inf( k_addon_type_board,
- "Longboard", "board.mdl",
- "content_skaterift/boards/skaterift_long/addon.inf", 0 );
- write_generic_addon_inf( k_addon_type_board,
- "Fractal", "board.mdl",
- "content_skaterift/boards/skaterift_fract/addon.inf", 0 );
- write_generic_addon_inf( k_addon_type_board,
- "Striped", "board.mdl",
- "content_skaterift/boards/skaterift_striped/addon.inf", 0 );
- write_generic_addon_inf( k_addon_type_board,
- "Licco", "board.mdl",
- "content_skaterift/boards/skaterift_licco/addon.inf", 0 );
- write_generic_addon_inf( k_addon_type_board,
- "Hypno", "board.mdl",
- "content_skaterift/boards/skaterift_spiral/addon.inf", 0 );
- write_generic_addon_inf( k_addon_type_board,
- "Shark", "board.mdl",
- "content_skaterift/boards/skaterift_shark/addon.inf", 0 );
-
- write_generic_addon_inf( k_addon_type_player,
- "De'folde", "ch_new.mdl",
- "content_skaterift/playermodels/skaterift_new/addon.inf", 0 );
- write_generic_addon_inf( k_addon_type_player,
- "Jordan", "ch_jordan.mdl",
- "content_skaterift/playermodels/skaterift_jordan/addon.inf", 0 );
- write_generic_addon_inf( k_addon_type_player,
- "Outlaw", "ch_outlaw.mdl",
- "content_skaterift/playermodels/skaterift_outlaw/addon.inf", 0 );
- write_generic_addon_inf( k_addon_type_player,
- "Chip", "ch_chip.mdl",
- "content_skaterift/playermodels/skaterift_chip/addon.inf", ADDON_REG_HIDDEN );
- write_generic_addon_inf( k_addon_type_player,
- "Aaron", "ch_aaron.mdl",
- "content_skaterift/playermodels/skaterift_aaron/addon.inf", 0 );
- write_generic_addon_inf( k_addon_type_player,
- "JC", "ch_john.mdl",
- "content_skaterift/playermodels/skaterift_john/addon.inf", ADDON_REG_HIDDEN );
- write_generic_addon_inf( k_addon_type_player,
- "Ela", "ch_ela.mdl",
- "content_skaterift/playermodels/skaterift_ela/addon.inf", 0 );
- write_generic_addon_inf( k_addon_type_player,
- "Custom", "ch_sr2t.mdl",
- "content_skaterift/playermodels/sr2t/addon.inf", 0 );
- write_generic_addon_inf( k_addon_type_player,
- "Pro", "ch_pro.mdl",
- "content_skaterift/playermodels/skaterift_pro/addon.inf", 0 );
- write_generic_addon_inf( k_addon_type_player,
- "Amin", "ch_amin.mdl",
- "content_skaterift/playermodels/skaterift_amin/addon.inf", 0 );
-
- write_generic_addon_inf( k_addon_type_player,
- "Jesus", "ch_jesus.mdl",
- "content_skaterift/playermodels/skaterift_jesus/addon.inf", ADDON_REG_HIDDEN );
- write_generic_addon_inf( k_addon_type_player,
- "FBI", "ch_fbi.mdl",
- "content_skaterift/playermodels/skaterift_fbi/addon.inf", ADDON_REG_HIDDEN );
- write_generic_addon_inf( k_addon_type_player,
- "FBI2", "ch_fbi2.mdl",
- "content_skaterift/playermodels/skaterift_fbi2/addon.inf", ADDON_REG_HIDDEN );
- write_generic_addon_inf( k_addon_type_player,
- "President", "ch_president.mdl",
- "content_skaterift/playermodels/skaterift_president/addon.inf", ADDON_REG_HIDDEN );
-
- struct
+ struct { c8 *name, *vs, *fs; } shaders[] =
{
- const char *title, *location, *file;
- u32 flags;
- }
- maps[] =
- {
- { "Mt.Zero Island", "Australia", "content_skaterift/maps/mp_mtzero/addon.inf", ADDON_REG_CAMPAIGN | ADDON_REG_MTZERO | ADDON_REG_PREMIUM },
- { "Flat World", "...", "content_skaterift/maps/dev_flatworld/addon.inf", ADDON_REG_CAMPAIGN | ADDON_REG_HIDDEN },
- { "Heaven", "...", "content_skaterift/maps/dev_heaven/addon.inf", ADDON_REG_CAMPAIGN | ADDON_REG_HIDDEN },
- { "Valley", "Cambodia", "content_skaterift/maps/mp_line1/addon.inf", ADDON_REG_CAMPAIGN | ADDON_REG_VALLEY | ADDON_REG_PREMIUM },
- { "Training Island", "Australia", "content_skaterift/maps/dev_tutorial/addon.inf", ADDON_REG_CAMPAIGN | ADDON_REG_VOLC },
- { "Center Island", "Australia", "content_skaterift/maps/dev_hub/addon.inf", ADDON_REG_CAMPAIGN | ADDON_REG_HUB },
- { "Downtown", "USA, Georgia", "content_skaterift/maps/mp_spawn/addon.inf", ADDON_REG_CAMPAIGN | ADDON_REG_CITY | ADDON_REG_PREMIUM },
- { "Moon", "Venus", "content_skaterift/maps/vm/addon.inf", ADDON_REG_VENUS | ADDON_REG_PREMIUM },
+ /* TODO: We need to move this into a vg header */
+ { "debug_lines", "vg/shaders/debug_lines.vs", "vg/shaders/debug_lines.fs" },
+ { "debug_rigidbody", "vg/shaders/rigidbody_view.vs", "vg/shaders/rigidbody_view.fs" },
+ { "vgui", "vg/shaders/ui.vs", "vg/shaders/ui.fs" },
+ { "vgui_image", "vg/shaders/ui_image.vs", "vg/shaders/ui_image.fs" },
+ { "vgui_image_grad", "vg/shaders/ui_image.vs", "vg/shaders/ui_image_grad.fs" },
+ { "vgui_image_hsv", "vg/shaders/ui_image.vs", "vg/shaders/ui_image_hsv.fs" },
+ { "vgloader", "vg/shaders/blit.vs", "vg/shaders/loader.fs" },
+
+ /* Scene */
+ { "scene_standard", "shaders/scene.vs", "shaders/scene_standard.fs" },
+ { "scene_standard_alphatest", "shaders/scene.vs", "shaders/scene_standard_alphatest.fs" },
+ { "scene_foliage", "shaders/scene_foliage.vs", "shaders/scene_foliage.fs" },
+ { "scene_override", "shaders/scene_override.vs", "shaders/scene_override.fs" },
+ { "scene_preview", "shaders/scene_override.vs", "shaders/scene_preview.fs" },
+ { "scene_fxglow", "shaders/scene_fxglow.vs", "shaders/scene_fxglow.fs" },
+ { "scene_vertex_blend", "shaders/scene.vs", "shaders/scene_vertex_blend.fs" },
+ { "scene_terrain", "shaders/scene.vs", "shaders/scene_terrain.fs" },
+ { "scene_route", "shaders/scene_override.vs", "shaders/scene_route.fs" },
+ { "scene_depth", "shaders/scene.vs", "shaders/scene_depth.fs" },
+ { "scene_position", "shaders/scene.vs", "shaders/scene_position.fs" },
+ { "scene_cubemapped", "shaders/scene.vs", "shaders/scene_cubemapped.fs" },
+ { "scene_water", "shaders/scene.vs", "shaders/scene_water.fs" },
+ { "scene_water_fast", "shaders/scene.vs", "shaders/scene_water_fast.fs" },
+ { "scene_scoretext", "shaders/scene_sfd.vs", "shaders/scene_standard.fs" },
+ { "scene_font", "shaders/model_font.vs", "shaders/scene_font.fs" },
+
+ /* Models */
+ { "model_sky", "shaders/model.vs", "shaders/model_sky.fs" },
+ { "model_sky_space", "shaders/model.vs", "shaders/model_sky_space.fs" },
+ { "model_sky_cubemap", "shaders/model_sky.vs", "shaders/model_sky_cubemap.fs" },
+ { "model_menu", "shaders/model.vs", "shaders/model_menu.fs" },
+ { "model_character_view", "shaders/model_skinned.vs", "shaders/model_character_view.fs" },
+ { "model_board_view", "shaders/model.vs", "shaders/model_character_view.fs" },
+ { "model_entity", "shaders/model.vs", "shaders/model_entity.fs" },
+ { "model_gate", "shaders/model.vs", "shaders/model_gate_lq.fs" },
+ { "model_superworld", "shaders/model.vs", "shaders/model_superworld.fs" },
+ { "model_gate_unlinked", "shaders/model.vs", "shaders/model_gate_unlinked.fs" },
+ { "model_font", "shaders/model_font.vs", "shaders/model_font.fs" },
+
+ { "particle", "shaders/particle.vs", "shaders/particle.fs" },
+ { "trail", "shaders/trail.vs", "shaders/trail.fs" },
+
+ /* 2D */
+ { "workshop_compositor", "shaders/workshop_compositor.vs", "shaders/workshop_compositor.fs" },
+ { "blit", "vg/shaders/blit.vs", "vg/shaders/blit_tex.fs" },
+ { "blitblur", "vg/shaders/blit.vs", "vg/shaders/blit_blur.fs" },
+ { "blitcolour", "vg/shaders/blit.vs", "vg/shaders/blit_colour.fs" },
+ { "blit_transition", "vg/shaders/blit.vs", "shaders/blit_transition.fs" },
+ { "compass", "shaders/compass.vs", "shaders/compass.fs" },
+ { "routeui", "shaders/routeui.vs", "shaders/routeui.fs" },
};
- for( u32 i=0; i<VG_ARRAY_LEN(maps); i ++ )
- {
- u8 descriptor_buf[ 512 ];
- vg_msg descriptor = {0};
- descriptor.buf = descriptor_buf;
- descriptor.max = sizeof(descriptor_buf);
- vg_msg_frame( &descriptor, "workshop" );
- {
- vg_msg_wkvstr( &descriptor, "title", maps[i].title );
- vg_msg_wkvstr( &descriptor, "author", "Skaterift" );
- u32 type = k_addon_type_world;
- vg_msg_wkvnum( &descriptor, "type", k_vg_msg_u32, 1, &type );
- }
- vg_msg_end_frame( &descriptor );
- vg_msg_wkvstr( &descriptor, "content", "main.mdl" );
- if( maps[i].flags )
- vg_msg_wkvnum( &descriptor, "flags", k_vg_msg_u32, 1, &maps[i].flags );
- write_msg( &descriptor, maps[i].file );
- }
-}
+ bool errors = 0;
-#define _S( NAME, VS, FS ) \
- vg_build_shader( "shaders/" VS, "shaders/" FS, NULL, "shaders", NAME )
+ for( u32 i=0; i<VG_ARRAY_LEN(shaders); i ++ )
+ if( !vg_build_shader( shaders[i].vs, shaders[i].fs, NULL, shaders[i].name ) )
+ errors = 1;
-void build_shaders(void){
- vg_info( "Compiling shader headers\n" );
- vg_shader_set_include_dir( "shaders" );
+ if( errors )
+ exit(0);
- /* Scene */
- _S( "scene_standard", "scene.vs", "scene_standard.fs" );
- _S( "scene_standard_alphatest", "scene.vs", "scene_standard_alphatest.fs" );
- _S( "scene_foliage", "scene_foliage.vs", "scene_foliage.fs" );
- _S( "scene_override", "scene_override.vs", "scene_override.fs" );
- _S( "scene_preview", "scene_override.vs", "scene_preview.fs" );
- _S( "scene_fxglow", "scene_fxglow.vs", "scene_fxglow.fs" );
- _S( "scene_vertex_blend", "scene.vs", "scene_vertex_blend.fs" );
- _S( "scene_terrain", "scene.vs", "scene_terrain.fs" );
- _S( "scene_route", "scene_override.vs", "scene_route.fs" );
- _S( "scene_depth", "scene.vs", "scene_depth.fs" );
- _S( "scene_position", "scene.vs", "scene_position.fs" );
- _S( "scene_cubemapped", "scene.vs", "scene_cubemapped.fs" );
- _S( "scene_water", "scene.vs", "scene_water.fs" );
- _S( "scene_water_fast", "scene.vs", "scene_water_fast.fs" );
- _S( "scene_scoretext", "scene_sfd.vs", "scene_standard.fs" );
- _S( "scene_font", "model_font.vs","scene_font.fs" );
-
- /* Models */
- _S( "model_sky", "model.vs", "model_sky.fs" );
- _S( "model_sky_space", "model.vs", "model_sky_space.fs" );
- _S( "model_sky_cubemap", "model_sky.vs", "model_sky_cubemap.fs" );
- _S( "model_menu", "model.vs", "model_menu.fs" );
- _S( "model_character_view", "model_skinned.vs", "model_character_view.fs" );
- _S( "model_board_view", "model.vs", "model_character_view.fs" );
- _S( "model_entity", "model.vs", "model_entity.fs" );
- _S( "model_gate", "model.vs", "model_gate_lq.fs" );
- _S( "model_superworld", "model.vs", "model_superworld.fs" );
- _S( "model_gate_unlinked", "model.vs", "model_gate_unlinked.fs" );
- _S( "model_font", "model_font.vs", "model_font.fs" );
-
- _S( "particle", "particle.vs", "particle.fs" );
- _S( "trail", "trail.vs", "trail.fs" );
-
- /* 2D */
- //_S( "blit", "blit.vs", "blit.fs" );
- _S( "workshop_compositor", "workshop_compositor.vs", "workshop_compositor.fs" );
- _S( "blitblur", "blit.vs", "blitblur.fs" );
- _S( "blitcolour","blit.vs", "colour.fs" );
- _S( "compass","compass.vs", "compass.fs" );
- _S( "blit_transition", "blit.vs", "blit_transition.fs" );
- _S( "routeui", "routeui.vs", "routeui.fs" );
-
- vg_build_shader_impl( "shaders/impl.c" );
+ vg_build_shader_impl();
}
-void build_game_content( struct vg_project *proj )
+void build_control_overlay(void)
{
- vg_symlink( proj, "content_skaterift/textures", "textures" );
- vg_symlink( proj, "content_skaterift/models", "models" );
- vg_symlink( proj, "content_skaterift/boards", "boards" );
- vg_symlink( proj, "content_skaterift/maps", "maps" );
- vg_symlink( proj, "content_skaterift/sound", "sound" );
- vg_symlink( proj, "content_skaterift/playermodels", "playermodels" );
- vg_symlink( proj, "content_skaterift/metascenes", "metascenes" );
- vg_syscall( "mkdir -p bin/%s/cfg", proj->uid.buffer );
- vg_syscall( "mkdir -p bin/%s/savedata", proj->uid.buffer );
- vg_syscall( "mkdir -p bin/%s/tools", proj->uid.buffer );
- vg_syscall( "cp bin/skaterift_blender.zip bin/%s/tools/", proj->uid.buffer );
+ FILE *hdr = fopen( "src.generated/control_overlay.h", "w" );
+ VG_ASSERT( hdr );
+
+ vg_stack_allocator stack;
+ vg_stack_init( &stack, NULL, VG_MB(8), "Model buffer" );
+
+ vg_model model;
+ VG_ASSERT( vg_model_load( &model, VG_MODEL_CPU_METADATA, "content_skaterift/models/rs_overlay.mdl", &stack ) );
+
+ for( u32 i=0; i<model.mesh_count; i ++ )
+ {
+ mdl_mesh *mesh = &model.meshes[ i ];
+ fprintf( hdr, " %s = %u,\n", af_str( model.packed_strings, mesh->pstr_name ), mesh->submesh_start );
+ }
+ vg_stack_free( &stack );
+ fclose( hdr );
}
-
-#include "src/build_control_overlay.c"
void build_game_bin( struct vg_project *proj, struct vg_compiler_env *env )
{
{
meta = 1;
build_shaders();
- build_game_metadata();
+ build_control_overlay();
vg_low( "\n\n" );
}
- build_control_overlay();
-
struct vg_compiler_conf conf = {0};
if( env->platform == k_platform_windows )
.steam_api = 1,
.use_3d = 1,
.custom_game_settings = 0,
- .custom_shaders = 1,
.multiplayer = 1
},
- env, &conf, "src/client.c", "skaterift" );
+ env, &conf, "src/unit_skaterift.c", "skaterift" );
vg_add_controller_database( proj );
+ vg_add_blob( proj, "steam_appid.txt", "" );
}
+void build_game_content( struct vg_project *proj )
+{
+ vg_symlink( proj, "content_skaterift/textures", "textures" );
+ vg_symlink( proj, "content_skaterift/models", "models" );
+ vg_symlink( proj, "content_skaterift/boards", "boards" );
+ vg_symlink( proj, "content_skaterift/maps", "maps" );
+ vg_symlink( proj, "content_skaterift/sound", "sound" );
+ vg_symlink( proj, "content_skaterift/playermodels", "playermodels" );
+ vg_symlink( proj, "content_skaterift/metascenes", "metascenes" );
+ vg_syscall( "mkdir -p bin/%s/cfg", proj->uid.buffer );
+ vg_syscall( "mkdir -p bin/%s/savedata", proj->uid.buffer );
+ vg_syscall( "mkdir -p bin/%s/tools", proj->uid.buffer );
+ vg_syscall( "cp bin/skaterift_blender.zip bin/%s/tools/", proj->uid.buffer );
+}
+
+void vg_build_scripts(void)
+{
+ if( vg_long_opt( "skaterift", "Make skaterift" ) )
+ {
+ struct vg_project proj;
+ vg_project_init( &proj, "bin", "skaterift", NULL, 0 );
+
+ build_game_bin( &proj, &_vg_common_env );
+ build_game_content( &proj );
+ vg_add_blob( &proj, "steam_appid.txt", "" );
+ }
+}
+
+#if 0
+#include "vg/vg_tool.h"
+#include "vg/vg_platform.h"
+#include "vg/vg_log.h"
+#include "vg/vg_opt.h"
+#include "vg/vg_build.h"
+#include "vg/vg_mem_pool.h"
+#include "vg/vg_build_utils_shader.h"
+#include "vg/vg_msg.h"
+#include "src/addon_types.h"
+
+#include "vg/vg_m.h"
+#include "src/model.h"
+#include "src/model.c"
+#include "src/array_file.c"
+
+
+/*
+ * Addon metadata utilities
+ * -------------------------------------------------------------------------- */
+
void build_crash_reporter( struct vg_project *proj, struct vg_compiler_env *env )
{
struct vg_compiler_conf conf = {0};
.log_source_info = 1,
.use_3d = 0,
.custom_game_settings = 0,
- .custom_shaders = 0,
.multiplayer = 0
},
env, &conf, "src/utest.c", "utest" );
int main( int argc, const char *argv[] )
{
- vg_log_init();
+ _vg_log_pre_init();
_vg_opt_init( argc, argv );
-
const char *arg;
if( (arg = vg_long_opt_arg( "glsl-dir", "Specify output directory for preprocessed GLSL" )) )
vg_success( "All scripts completed\n" );
}
+#endif
-clang -fsanitize=address -O0 -I. -I./vg build.c vg/vg_tool.c -o /tmp/tmpsr && /tmp/tmpsr $@
+zig cc -lasan -fsanitize=address -O0 -I. build.c -o /tmp/build_sr && /tmp/build_sr $@
--- /dev/null
+workshop
+{
+ title Fractal
+ author "Skate Rift"
+}
+
+content board.mdl
--- /dev/null
+workshop
+{
+ title Licco
+ author "Skate Rift"
+}
+
+content board.mdl
--- /dev/null
+workshop
+{
+ title Longboard
+ author "Skate Rift"
+}
+
+content board.mdl
--- /dev/null
+workshop
+{
+ title Shark
+ author "Skate Rift"
+}
+
+content board.mdl
--- /dev/null
+workshop
+{
+ title Hypno
+ author "Skate Rift"
+}
+
+content board.mdl
--- /dev/null
+workshop
+{
+ title Striped
+ author "Skate Rift"
+}
+
+content board.mdl
--- /dev/null
+workshop
+{
+ title "Flat World"
+ author "Skate Rift"
+}
+
+content main.mdl
+flags CAMPAIGN|HIDDEN
+
+location Nowhere
--- /dev/null
+workshop
+{
+ title "Heaven"
+ author "Skate Rift"
+}
+
+content main.mdl
+flags CAMPAIGN|HIDDEN
+
+location Nowhere
--- /dev/null
+workshop
+{
+ title "Center Island"
+ author "Skate Rift"
+}
+
+content main.mdl
+flags CAMPAIGN|HUB
+
+location Australia
--- /dev/null
+workshop
+{
+ title "Training Island"
+ author "Skate Rift"
+}
+
+content main.mdl
+flags CAMPAIGN|VOLC
+
+location Australia
--- /dev/null
+workshop
+{
+ title "Valley"
+ author "Skate Rift"
+}
+
+content main.mdl
+flags CAMPAIGN|VALLEY|PREMIUM
+
+location Cambodia
--- /dev/null
+workshop
+{
+ title "Mt.Zero Island"
+ author "Skate Rift"
+}
+
+content main.mdl
+flags CAMPAIGN|MTZERO|PREMIUM
+
+location Australia
--- /dev/null
+workshop
+{
+ title "Downtown"
+ author "Skate Rift"
+}
+
+content main.mdl
+flags CAMPAIGN|CITY|PREMIUM
+
+location USA
--- /dev/null
+workshop
+{
+ title "Moon"
+ author "Skate Rift"
+}
+
+content main.mdl
+flags VENUS|PREMIUM
+
+location Venus
--- /dev/null
+workshop
+{
+ title "Aaron"
+ author "Skate Rift"
+}
+
+content ch_aaron.mdl
--- /dev/null
+workshop
+{
+ title "Amin"
+ author "Skate Rift"
+}
+
+content ch_amin.mdl
--- /dev/null
+workshop
+{
+ title "Chip"
+ author "Skate Rift"
+}
+
+content ch_chip.mdl
+flags HIDDEN
--- /dev/null
+workshop
+{
+ title "Ela"
+ author "Skate Rift"
+}
+
+content ch_ela.mdl
--- /dev/null
+workshop
+{
+ title "FBI"
+ author "Skate Rift"
+}
+
+content ch_fbi.mdl
+flags HIDDEN
--- /dev/null
+workshop
+{
+ title "FBI2"
+ author "Skate Rift"
+}
+
+content ch_fbi2.mdl
+flags HIDDEN
--- /dev/null
+workshop
+{
+ title "Jesus"
+ author "Skate Rift"
+}
+
+content ch_jesus.mdl
+flags HIDDEN
--- /dev/null
+workshop
+{
+ title "JC"
+ author "Skate Rift"
+}
+
+content ch_john.mdl
+flags HIDDEN
--- /dev/null
+workshop
+{
+ title "Jordan"
+ author "Skate Rift"
+}
+
+content ch_jordan.mdl
--- /dev/null
+workshop
+{
+ title "De'folde"
+ author "Skate Rift"
+}
+
+content ch_new.mdl
--- /dev/null
+workshop
+{
+ title "Outlaw"
+ author "Skate Rift"
+}
+
+content ch_outlaw.mdl
--- /dev/null
+workshop
+{
+ title "President"
+ author "Skate Rift"
+}
+
+content ch_president.mdl
+flags HIDDEN
--- /dev/null
+workshop
+{
+ title "Pro"
+ author "Skate Rift"
+}
+
+content ch_pro.mdl
--- /dev/null
+workshop
+{
+ title "Custom"
+ author "Skate Rift"
+}
+
+content ch_sr2t.mdl
+++ /dev/null
- ov_carve_l = 0,
- ov_y = 1,
- ov_a = 2,
- ov_b = 3,
- ov_x = 4,
- ov_ls = 5,
- ov_key = 6,
- ov_key_down = 7,
- ov_shift = 8,
- ov_shift_down = 9,
- ov_space = 10,
- ov_space_down = 11,
- ov_text_jump = 12,
- ov_jump_ind = 13,
- ov_text_carve = 14,
- ov_text_crouch = 15,
- ov_stored_ind = 16,
- ov_text_stored = 17,
- ov_text_push = 18,
- ov_text_left = 19,
- ov_text_right = 20,
- ov_text_manual = 21,
- ov_text_front_flip = 22,
- ov_text_back_flip = 23,
- ov_text_w = 24,
- ov_text_s = 25,
- ov_text_shift = 26,
- ov_text_grab = 27,
- ov_key_fill = 28,
- ov_shift_fill = 29,
- ov_space_fill = 30,
- ov_lmb = 31,
- ov_rmb = 32,
- ov_mouse = 33,
- ov_text_shuvit = 34,
- ov_text_kickflip = 35,
- ov_text_treflip = 36,
- ov_rmb_down = 37,
- ov_lmb_down = 38,
- ov_mouse_grabs = 39,
- ov_text_walk = 40,
- ov_text_back = 41,
- ov_text_skate = 42,
- ov_text_forward = 43,
- ov_text_e = 44,
- ov_text_glide = 45,
- ov_text_walk_lwr = 46,
- ov_text_camera = 47,
- ov_text_run = 48,
- ov_text_look = 49,
- ov_text_rewind = 50,
- ov_text_respawn = 51,
- ov_ls_circ_walk = 52,
- ov_rs_circ_look = 53,
- ov_rs = 54,
- ov_ls_circ_skate = 55,
- ov_ls_circ_manual = 56,
- ov_ls_circ_frontflip = 57,
- ov_ls_circ_backflip = 58,
- ov_rs_circ_grab = 59,
- ov_lt = 60,
- ov_lb = 61,
- ov_carve_r = 62,
- ov_lb_down = 63,
- ov_rb = 64,
- ov_rb_down = 65,
- ov_lt_act = 66,
- ov_rt = 67,
- ov_rt_act = 68,
- ov_lt_run = 69,
- ov_rt_grab = 70,
- ov_rt_crouch = 71,
- ov_dpad = 72,
- ov_text_dw_rewind = 73,
- ov_text_a_shuvit = 74,
- ov_text_b_kickflip = 75,
- ov_text_x_treflip = 76,
- ov_text_y_walk = 77,
- ov_text_y_glide = 78,
- ov_text_y_walk_lwr = 79,
- ov_text_de_camera = 80,
- ov_y_down = 81,
- ov_a_down = 82,
- ov_b_down = 83,
- ov_x_down = 84,
- ov_text_a_jump = 85,
- ov_text_a_jump_mid = 86,
- ov_text_b_push = 87,
- ov_text_y_skate = 88,
- ov_dpad_w = 89,
- ov_dpad_n = 90,
- ov_dpad_e = 91,
- ov_dpad_s = 92,
- ov_text_dn_respawn = 93,
- ov_text_met_menu = 94,
- ov_met_r = 95,
- ov_met = 96,
- ov_met_r_down = 97,
- ov_met_l = 98,
- ov_met_l_down = 99,
- ov_text_menu = 100,
- ov_key_menu = 101,
- ov_key_menu_down = 102,
- ov_y_ps = 103,
- ov_a_ps = 104,
- ov_b_ps = 105,
- ov_x_ps = 106,
- ov_y_down_ps = 107,
- ov_a_down_ps = 108,
- ov_b_down_ps = 109,
- ov_x_down_ps = 110,
float compute_board_shadow()
{
// player shadow
- float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,
- g_board_1.xyz )-0.1 );
+ float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz, g_board_1.xyz )-0.1 );
float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );
player_shadow *= player_shadow*player_shadow*player_shadow;
-#include "vg/vg_engine.h"
-#include "vg/vg_io.h"
-#include "vg/vg_loader.h"
-#include "addon.h"
-#include "addon_types.h"
-#include "vg/vg_msg.h"
-#include "vg/vg_steam2.h"
-#include "workshop.h"
-#include <string.h>
-
struct _addon _addon;
/*
addon_reg *reg = addon_details(id);
addon_alias *alias = ®->alias;
- if( alias->steam_workshop_id )
- snprintf( buf, ADDON_UID_MAX, "sr%03d-steam-"PRINTF_U64"%s%s", alias->type, alias->steam_workshop_id,
- cpart? ":": "", cpart? cpart: "" );
- else
- snprintf( buf, ADDON_UID_MAX, "sr%03d-local-%s%s%s", alias->type, alias->folder,
- cpart? ":": "", cpart? cpart: "" );
+ vg_str str_alias;
+ vg_strnull( &str_alias, buf, ADDON_UID_MAX );
+ vg_strcat( &str_alias, "sr" );
+ vg_strcati64r( &str_alias, alias->type, 10, 3, '0' );
+
+ if( alias->steam_workshop_id )
+ {
+ vg_strcat( &str_alias, "-steam-" );
+ vg_strcatu64( &str_alias, alias->steam_workshop_id, 10 );
+ }
+ else
+ {
+ vg_strcat( &str_alias, "-local-" );
+ vg_strcat( &str_alias, alias->folder );
+ }
+
+ if( cpart )
+ {
+ vg_strcat( &str_alias, ":" );
+ vg_strcat( &str_alias, cpart );
+ }
+
+ VG_ASSERT( vg_strgood( &str_alias ) );
}
else
buf[0] = '\0';
return 1;
}
-void addon_system_init( void )
+VG_API void _addon_system_init(void)
{
- THREAD_1;
-
u32 reg_size = sizeof(addon_reg)*ADDON_MOUNTED_MAX;
- _addon.registry = vg_stack_allocate( &vg.rtmem, reg_size, 8, "Addon Registry" );
+ _addon.registry = vg_stack_allocate( NULL, reg_size, 8, "Addon Registry" );
for( u32 type=0; type<k_addon_type_max; type++ )
{
{
/* create the allocations pool */
u32 alloc_size = sizeof(struct addon_cache_entry)*inf->cache_count;
- cache->entries = vg_stack_allocate( &vg.rtmem, alloc_size, 8, "Cache entries" );
- memset( cache->entries, 0, alloc_size );
- vg_pool_init( &cache->pool, &cache->pool_unreferenced, inf->cache_count, &vg.rtmem );
+ cache->entries = vg_stack_allocate( NULL, alloc_size, 8, "Cache entries" );
+ vg_zero_mem( cache->entries, alloc_size );
+ vg_pool_init( &cache->pool, &cache->pool_unreferenced, inf->cache_count, NULL );
/* create the real memory */
u32 cache_size = inf->cache_stride*inf->cache_count;
- cache->items = vg_stack_allocate( &vg.rtmem, cache_size, 8, "Cache data" );
+ cache->items = vg_stack_allocate( NULL, cache_size, 8, "Cache data" );
cache->stride = inf->cache_stride;
- memset( cache->items, 0, cache_size );
+ vg_zero_mem( cache->items, cache_size );
for( i32 j=0; j<inf->cache_count; j++ )
{
entry->addon_id = 0;
if( inf->item_arena_size )
- entry->item_arena = vg_stack_make_substack( &vg.rtmem, inf->item_arena_size, "Addon item arena" );
- else
- entry->item_arena = NULL;
+ vg_stack_init( &entry->item_arena, NULL, inf->item_arena_size, "Addon item arena" );
}
}
}
static bool addon_try_load_metadata( addon_reg *reg, const char *folder_path )
{
- THREAD_1;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
VG_ASSERT( reg );
char path_buf[ 4096 ];
vg_str meta_path;
vg_strnull( &meta_path, path_buf, sizeof(path_buf) );
vg_strcat( &meta_path, folder_path );
- vg_strcat( &meta_path, "/addon.inf" );
-
+ vg_strcat( &meta_path, "/addon.kv" );
if( !vg_strgood( &meta_path ) )
{
vg_error( "The metadata path is too long\n" );
return 0;
}
- FILE *fp = fopen( meta_path.buffer, "rb" );
- if( !fp )
- {
- vg_error( "Could not open the '%s'\n", meta_path.buffer );
- return 0;
- }
+ vg_kv_parser parser;
+ vg_kv_parser_init( &parser, ®->metadata, 0 );
- reg->metadata_len = fread( reg->metadata, 1, 512, fp );
- if( !feof(fp) )
+ vg_stream file;
+ if( vg_file_stream_open( &file, path_buf, VG_STREAM_READ ) )
{
- fclose(fp);
- vg_error( "Metadata too big\n" );
- return 0;
+ vg_kv_parse_stream( &parser, &file );
+ vg_file_stream_close( &file );
+ return 1;
}
- fclose(fp);
+ else
+ {
+ u32 size;
+ void *legacy_msg_buf = vg_file_read( NULL, path_buf, &size, 0 );
- return 1;
+ if( legacy_msg_buf )
+ {
+ vg_kvs_append_from_legacy_msg2( ®->metadata, 0, legacy_msg_buf, size );
+ vg_free( legacy_msg_buf );
+ return 1;
+ }
+ else return 0;
+ }
}
static addon_id addon_alloc_reg( PublishedFileId_t workshop_id, enum addon_type type )
addon_reg *reg = &_addon.registry[ id-1 ];
reg->flags = 0;
- reg->metadata_len = 0;
reg->cache_id = 0;
memset( ®->alias, 0, sizeof(addon_alias) );
reg->alias.steam_workshop_id = workshop_id;
reg->alias.type = type;
+ vg_stack_init( ®->metadata_stack, NULL, VG_KB(8), "Addon metadata KV\n" );
+ vg_kvs_init( ®->metadata, ®->metadata_stack );
+
if( workshop_id )
{
#if 0
*/
addon_id _addon_mount_from_folder_path( const char *folder_path, enum addon_type type, const char *content_ext )
{
- THREAD_1;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
u32 folder_name_length = 0;
const char *folder_name = folder_path;
bool loaded_metadata = addon_try_load_metadata( reg, folder_path );
if( loaded_metadata )
{
- vg_msg msg;
- vg_msg_init( &msg, reg->metadata, reg->metadata_len );
-
u32 flags = 0x00;
- vg_msg_getkvintg( &msg, "flags", k_vg_msg_u32, &flags, NULL );
+ vg_kv_read_vu32( ®->metadata, 0, "flags", NULL, &flags, 1 );
reg->flags |= ADDON_REG_MOUNTED | flags;
addon_complete_allocation();
return id;
}
/* create our own content commands */
- vg_msg msg;
- vg_msg_init( &msg, reg->metadata, sizeof(reg->metadata) );
- vg_msg_frame( &msg, "workshop" );
- {
- vg_msg_wkvstr( &msg, "title", reg->alias.folder );
- vg_msg_wkvstr( &msg, "author", "Custom Mod" );
- }
- vg_msg_end_frame( &msg );
+ u32 workshop_block = vg_kv_append( ®->metadata, 0, "workshop", NULL );
+ vg_kv_append( ®->metadata, workshop_block, "title", reg->alias.folder );
+ vg_kv_append( ®->metadata, workshop_block, "author", "Custom Mod" );
u32 content_count = 0;
while( vg_dir_next_entry(&subdir) )
continue;
if( strcmp( ext, content_ext ) )
continue;
- vg_msg_wkvstr( &msg, "content", fname );
+
+ vg_kv_append( ®->metadata, 0, "content", fname );
content_count ++;
}
}
return 0;
}
- if( msg.error == k_vg_msg_error_OK )
- {
- reg->metadata_len = msg.cur.co;
- reg->flags |= ADDON_REG_MOUNTED;
- addon_complete_allocation();
- return id;
- }
- else
- {
- vg_error( "Error creating metadata: %d\n", msg.error );
- addon_fail_allocation();
- return 0;
- }
+ reg->flags |= ADDON_REG_MOUNTED;
+ addon_complete_allocation();
+ return id;
}
}
void _addon_mount_content_folder( enum addon_type type, const char *base_folder, const char *content_ext )
{
- THREAD_1;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
vg_info( "Mounting addons(type:%d) matching skaterift/%s/*/*%s\n", type, base_folder, content_ext );
struct workshop_mount_info
{
u64 workshop_id;
- char path[];
+ c8 path[4096];
};
-static void workshop_mount_task( vg_async_task *task )
+static void workshop_mount_task( struct workshop_mount_info *in_args )
{
- THREAD_1;
- struct workshop_mount_info *info = (void *)task->data;
-
- addon_id id = addon_alloc_reg( info->workshop_id, k_addon_type_none );
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+ addon_id id = addon_alloc_reg( in_args->workshop_id, k_addon_type_none );
if( !id )
return;
addon_reg *reg = &_addon.registry[ id-1 ];
- bool loaded_metadata = addon_try_load_metadata( reg, info->path );
+ bool loaded_metadata = addon_try_load_metadata( reg, in_args->path );
if( !loaded_metadata )
{
return;
}
- enum addon_type type = k_addon_type_none;
- vg_msg msg;
- vg_msg_init( &msg, reg->metadata, reg->metadata_len );
+ u32 type = k_addon_type_none;
- if( vg_msg_seekframe( &msg, "workshop" ))
- vg_msg_getkvintg( &msg, "type", k_vg_msg_u32, &type, NULL );
+ u32 workshop_block = vg_kv_find( ®->metadata, 0, "workshop" );
+ if( workshop_block )
+ vg_kv_read_vu32( ®->metadata, workshop_block, "type", NULL, &type, 1 );
if( type == k_addon_type_none )
{
addon_complete_allocation();
}
-struct workshop_scan_info
-{
- enum workshop_scan_state
- {
- k_workshop_scan_state_filter_mounted,
- k_workshop_scan_state_mount
- }
- state;
-
- u32 count;
- PublishedFileId_t workshop_ids[ ADDON_MOUNTED_MAX ];
-};
-static void workshop_scan_t1( vg_async_task *co_task )
-{
- THREAD_1;
- struct workshop_scan_info *co_info = (void *)co_task->data;
-
- if( co_info->state == k_workshop_scan_state_filter_mounted )
- {
- vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, sizeof(struct workshop_scan_info), 1 );
- struct workshop_scan_info *info = (void *)task->data;
- info->state = k_workshop_scan_state_mount;
-
- u32 send_count = 0;
- for( u32 i=0; i<co_info->count; i ++ )
- {
- for( u32 j=0; j<_addon.registry_count; j ++ )
- {
- if( _addon.registry[j].alias.steam_workshop_id == co_info->workshop_ids[i] )
- goto s1;
- }
-
- info->workshop_ids[ send_count ++ ] = co_info->workshop_ids[i];
-s1:;
- }
-
- info->count = send_count;
- vg_async_task_dispatch( task, _mount_workshop_addons );
- }
-}
-
-void _mount_workshop_addons( vg_async_task *co_task )
+VG_API void _mount_workshop_addons(void)
{
- THREAD_0;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
- if( g_client.demo_mode )
+ if( _is_running_demo() )
{
vg_info( "Won't load workshop items in demo mode\n" );
return;
if( _steam_api.disabled )
return;
- if( !co_task )
- {
- vg_async_task *task = vg_allocate_async_task( &vg.loader_tasks, sizeof(struct workshop_scan_info), 1 );
- struct workshop_scan_info *info = (void *)task->data;
- info->state = k_workshop_scan_state_filter_mounted;
- u32 count = SteamAPI_ISteamUGC_GetSubscribedItems( _steam_api.pSteamUGC, info->workshop_ids, ADDON_MOUNTED_MAX, 0 );
- vg_info( "Found %u subscribed items\n", count );
+ PublishedFileId_t workshop_ids[ ADDON_MOUNTED_MAX ];
+ u32 count = SteamAPI_ISteamUGC_GetSubscribedItems( _steam_api.pSteamUGC, workshop_ids, ADDON_MOUNTED_MAX, 0 );
+ vg_info( "Found %u subscribed items\n", count );
- u32 send_count = 0;
+ for( u32 i=0; i<count; i++ )
+ {
+ u32 state = SteamAPI_ISteamUGC_GetItemState( _steam_api.pSteamUGC, workshop_ids[i] );
+ if( !(state & k_EItemStateInstalled) )
+ continue;
- for( u32 i=0; i<count; i++ )
+ /* check if already installed, TODO: hash this?.. O(N^2) */
+ bool mounted = 0;
+ for( u32 j=0; j<_addon.registry_count; j ++ )
{
- u32 state = SteamAPI_ISteamUGC_GetItemState( _steam_api.pSteamUGC, info->workshop_ids[i] );
- if( !(state & k_EItemStateInstalled) )
- continue;
-
- info->workshop_ids[ send_count ++ ] = info->workshop_ids[i];
+ if( _addon.registry[j].alias.steam_workshop_id == workshop_ids[i] )
+ {
+ mounted = 1;
+ break;
+ }
}
-
- info->count = send_count;
- vg_async_task_dispatch( task, workshop_scan_t1 );
- }
- else
- {
- struct workshop_scan_info *co_info = (void *)co_task->data;
- for( u32 i=0; i<co_info->count; i ++ )
+
+ if( !mounted )
{
- char path[ 4096 ];
-
+ struct workshop_mount_info *out_args = _vg_async_alloc(VG_THREAD_ASYNC_ID, sizeof(struct workshop_mount_info));
+ out_args->workshop_id = workshop_ids[i];
u64 _size;
u32 _ts;
- if( !SteamAPI_ISteamUGC_GetItemInstallInfo( _steam_api.pSteamUGC, co_info->workshop_ids[i],
- &_size, path, sizeof(path), &_ts ))
+ if( !SteamAPI_ISteamUGC_GetItemInstallInfo( _steam_api.pSteamUGC, workshop_ids[i],
+ &_size, out_args->path, sizeof(out_args->path), &_ts ))
{
- vg_error( "GetItemInstallInfo failed for addon %lu\n", co_info->workshop_ids[i] );
+ vg_error( "GetItemInstallInfo failed for addon %lu\n", workshop_ids[i] );
continue;
}
-
- u32 len = strlen( path );
- vg_async_task *task = vg_allocate_async_task( &vg.loader_tasks, sizeof(struct workshop_mount_info)+len+1, 1 );
- struct workshop_mount_info *info = (void *)task->data;
- strcpy( info->path, path );
- info->workshop_id = co_info->workshop_ids[i];
- vg_async_task_dispatch( task, workshop_mount_task );
+ _vg_async_send( out_args, (vg_async_fn)workshop_mount_task );
}
}
}
bool addon_get_content_folder( addon_id addon_id, vg_str *folder )
{
- THREAD_0;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
VG_ASSERT( addon_id );
addon_reg *reg = addon_details( addon_id );
return 0;
}
- folder->i = strlen( folder->buffer );
+ folder->i = vg_strlen( folder->buffer );
return 1;
}
else
addon_cache_id cache_id;
enum addon_cache_state result_state;
};
-static void cache_load_complete( vg_async_task *task )
+static void cache_load_complete( struct cache_complete_info *in_args )
{
- THREAD_0;
- struct cache_complete_info *info = (void *)task->data;
- struct addon_cache *cache = &_addon.cache[info->type];
- cache->entries[ vg_pool_index( &cache->pool, info->cache_id ) ].state = info->result_state;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ struct addon_cache *cache = &_addon.cache[in_args->type];
+ cache->entries[ vg_pool_index( &cache->pool, in_args->cache_id ) ].state = in_args->result_state;
}
struct cache_load_info
{
enum addon_type type;
addon_cache_id cache_id;
-
- char path[];
+ char path[4096];
};
-static void cache_load_task( vg_async_task *task )
+static void cache_load_task( struct cache_load_info *in_args )
{
- THREAD_1;
- struct cache_load_info *info = (void *)task->data;
- addon_cache_entry *cache_entry = get_addon_cache_entry( info->type, info->cache_id );
- vg_info( "process cache load request (%u#%u): %s\n", info->type, info->cache_id, info->path );
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+ addon_cache_entry *cache_entry = get_addon_cache_entry( in_args->type, in_args->cache_id );
+ vg_info( "process cache load request (%u#%u): %s\n", in_args->type, in_args->cache_id, in_args->path );
+
+ enum addon_cache_state result_state = k_addon_cache_state_errored;
/* load content files
* --------------------------------- */
char path_buf[4096];
vg_str content_path;
vg_strnull( &content_path, path_buf, sizeof(path_buf) );
- vg_strcat( &content_path, info->path );
+ vg_strcat( &content_path, in_args->path );
addon_reg *reg = addon_details( cache_entry->addon_id );
- vg_msg msg;
- vg_msg_init( &msg, reg->metadata, reg->metadata_len );
- enum addon_cache_state result_state = k_addon_cache_state_errored;
-
- const char *kv_content = vg_msg_getkvstr( &msg, "content" );
+ const c8 *kv_content = vg_kv_value( ®->metadata, vg_kv_find( ®->metadata, 0, "content" ), NULL );
if( kv_content )
{
vg_strcat( &content_path, "/" );
vg_error( " Metadata path too long\n" );
goto e0;
}
-
- vg_stack_allocator *arena = cache_entry->item_arena;
- if( info->type == k_addon_type_board )
+
+ vg_stack_allocator *arena = &cache_entry->item_arena;
+ if( in_args->type == k_addon_type_board )
{
- struct player_board *board = addon_cache_item_data( info->type, info->cache_id, 0 );
+ struct player_board *board = addon_cache_item_data( in_args->type, in_args->cache_id, 0 );
vg_stack_clear( arena );
player_board_load( board, content_path.buffer, arena );
result_state = k_addon_cache_state_loaded;
}
- else if( info->type == k_addon_type_player )
+ else if( in_args->type == k_addon_type_player )
{
- struct player_model *model = addon_cache_item_data( info->type, info->cache_id, 0 );
+ struct player_model *model = addon_cache_item_data( in_args->type, in_args->cache_id, 0 );
vg_stack_clear( arena );
player_model_load( model, content_path.buffer, arena );
result_state = k_addon_cache_state_loaded;
}
e0:;
- vg_async_task *res_task = vg_allocate_async_task( &vg.main_tasks, sizeof(struct cache_complete_info), 1 );
- struct cache_complete_info *complete_info = (void *)res_task->data;
- complete_info->type = info->type;
- complete_info->cache_id = info->cache_id;
- complete_info->result_state = result_state;
- vg_async_task_dispatch( res_task, cache_load_complete );
+ struct cache_complete_info *out_args = _vg_async_alloc( VG_THREAD_MAIN_ID, sizeof(struct cache_complete_info) );
+ out_args->type = in_args->type;
+ out_args->cache_id = in_args->cache_id;
+ out_args->result_state = result_state;
+ _vg_async_send( out_args, (vg_async_fn)cache_load_complete );
}
/*
addon_cache_entry *entry = &cache->entries[ vg_pool_index( &cache->pool, id ) ];
if( entry->state == k_addon_cache_state_load_request )
{
- char path_buf[4096];
+ struct cache_load_info *out_args = _vg_async_alloc( VG_THREAD_ASYNC_ID, sizeof(struct cache_load_info) );
vg_str folder;
- vg_strnull( &folder, path_buf, 4096 );
+ vg_strnull( &folder, out_args->path, sizeof(out_args->path) );
+
if( !addon_get_content_folder( entry->addon_id, &folder ) )
{
+ _vg_async_send( out_args, NULL );
entry->state = k_addon_cache_state_errored;
continue;
}
- u32 len = strlen( path_buf ) + 1;
- vg_async_task *task = vg_allocate_async_task( &vg.loader_tasks, sizeof(struct cache_load_info) + len, 1 );
- struct cache_load_info *info = (void *)task->data;
-
- info->type = type;
- info->cache_id = id;
- strcpy( info->path, path_buf );
-
+ out_args->type = type;
+ out_args->cache_id = id;
entry->state = k_addon_cache_state_loading;
- vg_async_task_dispatch( task, cache_load_task );
+ _vg_async_send( out_args, (vg_async_fn)cache_load_task );
+
}
id = vg_pool_next( &cache->pool, id, 0 );
}
addon_cache_id addon_cache_create_viewer( enum addon_type type, addon_id addon_id )
{
- THREAD_0;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
if( !addon_id )
return 0;
addon_cache_id addon_cache_create_viewer_from_uid( enum addon_type type, const char uid[ADDON_UID_MAX] )
{
- THREAD_0;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
addon_id id = addon_get_from_uid( type, uid );
if( id )
void addon_cache_watch( enum addon_type type, addon_cache_id cache_id )
{
- THREAD_0;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
if( !cache_id )
return;
void addon_cache_unwatch( enum addon_type type, addon_cache_id cache_id )
{
- THREAD_0;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
if( !cache_id )
return;
-#pragma once
-#include "vg/vg_steam2.h"
-#include "vg/vg_mem_pool.h"
-#include "vg/vg_string.h"
-#include "addon_types.h"
-#include "vg/vg_mutex.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/addon.c"
+#else
typedef struct addon_reg addon_reg;
typedef struct addon_cache_entry addon_cache_entry;
addon_alias alias;
u32 alias_hash;
- u8 metadata[512]; /* vg_msg buffer */
- u32 metadata_len;
+ vg_stack_allocator metadata_stack;
+ vg_kvs metadata;
+
u32 flags;
addon_cache_id cache_id;
}
state;
char local_cpart[ ADDON_CPART_MAX ];
- vg_stack_allocator *item_arena;
+ vg_stack_allocator item_arena;
}
*entries;
vg_pool pool;
}
extern _addon;
-void addon_system_init( void );
+VG_API void _addon_system_init(void);
addon_reg *addon_details( addon_id id );
u32 _addon_filtered_count( enum addon_type type, u32 whitelist, u32 blacklist );
addon_id _addon_mount_from_folder_path( const char *folder, enum addon_type type, const char *content_ext );
void _addon_mount_content_folder( enum addon_type type, const char *base_folder, const char *content_ext );
-void _mount_workshop_addons( vg_async_task *co_task );
+VG_API void _mount_workshop_addons(void);
void _addon_system_pre_update(void);
addon_id addon_get_from_uid( enum addon_type type, const char uid[ADDON_UID_MAX] );
void addon_cache_unwatch( enum addon_type type, addon_cache_id cache_id );
void *addon_cache_item_data( enum addon_type type, addon_cache_id cache_id, bool only_if_loaded );
addon_cache_entry *get_addon_cache_entry( enum addon_type type, u16 cache_id );
+
+#endif
-#include "player.h"
-#include "player_render.h"
-#include "player_api.h"
-
struct addon_type_info addon_type_infos[] =
{
[k_addon_type_board] = {
-#pragma once
+#if defined( SR_IMPLEMENTATION )
+# include "src/addon_types.c"
+#else
enum addon_type{
k_addon_type_none = 0,
extern addon_type_infos[];
#endif
+#endif
-#include "array_file.h"
-#include <errno.h>
-
-u32 af_str_hash( array_file_context *af, u32 pstr )
+VG_TIER_0 u32 af_str_hash( const void *packed_strings, u32 pstr )
{
if( pstr & 0x3 )
vg_fatal_error( "ALIGNMENT ERROR (%u)\n", pstr );
-
- return *((u32 *)(af->strings + pstr));
+ return *((u32 *)(packed_strings + pstr));
}
-const char *af_str( array_file_context *af, u32 pstr )
+VG_TIER_0 const c8 *af_str( const void *packed_strings, u32 pstr )
{
- return af->strings + pstr + 4;
+ return packed_strings + pstr + 4;
}
-bool af_str_eq( array_file_context *af, u32 pstr, const char *str, u32 str_hash )
+VG_TIER_0 bool af_str_eq( const void *packed_strings, u32 pstr, const c8 *str, u32 str_hash )
{
- if( af_str_hash( af, pstr ) == str_hash )
- if( !strcmp( str, af_str( af, pstr )))
+ if( af_str_hash( packed_strings, pstr ) == str_hash )
+ if( !strcmp( str, af_str( packed_strings, pstr )))
return 1;
return 0;
}
-static void af_load_array_file_buffer( array_file_context *ctx, array_file_meta *arr, void *buffer, u32 stride )
+VG_TIER_0 void af_load_array_file_buffer( array_file_context *ctx, array_file_meta *arr, void *buffer, u32 stride )
{
if( arr->item_count )
{
- fseek( ctx->fp, arr->file_offset, SEEK_SET );
-
- if( stride == arr->item_size )
- {
- u64 l = fread( buffer, arr->item_size*arr->item_count, 1, ctx->fp );
- if( l != 1 )
- {
- vg_file_error_info( ctx->fp );
- fclose( ctx->fp );
- vg_fatal_error( "AF file buffer error\n" );
- }
- }
- else
+ vg_zero_mem( buffer, stride*arr->item_count );
+ u32 read_size = VG_MIN( stride, arr->item_size );
+ for( u32 i=0; i<arr->item_count; i++ )
{
- vg_warn( "Applying alignment fixup to array '%s' [%u -> %u] x %u\n",
- arr->name, arr->item_size, stride, arr->item_count );
-
- if( stride > arr->item_size )
- memset( buffer, 0, stride*arr->item_count );
-
- u32 read_size = VG_MIN( stride, arr->item_size );
-
- for( u32 i=0; i<arr->item_count; i++ )
- {
- u64 l = fread( buffer+i*stride, read_size, 1, ctx->fp );
- if( stride < arr->item_size )
- fseek( ctx->fp, arr->item_size - stride, SEEK_CUR );
-
- if( l != 1 )
- {
- vg_file_error_info( ctx->fp );
- fclose( ctx->fp );
- vg_fatal_error( "AF read arror\n" );
- }
- }
+ vg_stream_seek( ctx->stream, arr->file_offset + i*arr->item_size );
+ vg_stream_read( ctx->stream, buffer+i*stride, read_size );
}
}
}
-void af_load_array_file( array_file_context *ctx, array_file_ptr *out_ptr,
- array_file_meta *arr, vg_stack_allocator *stack, u32 stride )
+VG_TIER_1 void af_load_array_file( array_file_context *ctx, array_file_ptr *out_ptr,
+ array_file_meta *arr, vg_stack_allocator *stack, u32 stride )
{
if( arr->item_count )
{
u32 size = stride*arr->item_count;
- out_ptr->data = stack? vg_stack_allocate( stack, size, 8, NULL ): malloc( size );
+ out_ptr->data = vg_stack_allocate( stack, size, 8, NULL );
af_load_array_file_buffer( ctx, arr, out_ptr->data, stride );
}
else
- {
out_ptr->data = NULL;
- }
out_ptr->stride = stride;
out_ptr->count = arr->item_count;
}
-void *af_arritm( array_file_ptr *arr, u32 index )
+VG_TIER_0 void *af_arritm( array_file_ptr *arr, u32 index )
{
if( index >= arr->count )
vg_fatal_error( "Index out of range (%u >= %u)\n", index, arr->count );
return ((u8 *)arr->data) + index*arr->stride;
}
-u32 af_arrcount( array_file_ptr *arr )
+VG_TIER_0 u32 af_arrcount( array_file_ptr *arr )
{
return arr->count;
}
-array_file_meta *af_find_array( array_file_context *ctx, const char *name )
+VG_TIER_0 array_file_meta *af_find_array( array_file_context *ctx, const c8 *name )
{
for( u32 i=0; i<af_arrcount(&ctx->index); i++ )
{
return NULL;
}
-int af_load_array( array_file_context *ctx, array_file_ptr *ptr, const char *name, vg_stack_allocator *stack, u32 stride )
+VG_TIER_1 bool af_load_array( array_file_context *ctx, array_file_ptr *ptr, const c8 *name,
+ vg_stack_allocator *stack, u32 stride )
{
array_file_meta *arr = af_find_array( ctx, name );
}
}
-void af_open( array_file_context *ctx, const char *path, u32 min_version, u32 max_version, vg_stack_allocator *stack )
+VG_TIER_1 bool af_open_stream( array_file_context *afc, vg_stream *stream, u32 min_version, u32 max_version,
+ vg_stack_allocator *stack )
{
- ctx->fp = fopen( path, "rb" );
- if( !ctx->fp )
- vg_fatal_error( "open('%s'): %s\n", path, strerror(errno) );
-
- u64 l = fread( &ctx->header, sizeof(array_file_header), 1, ctx->fp );
- if( l != 1 )
+ afc->stream = stream;
+ if( vg_stream_read( stream, &afc->header, sizeof(array_file_header)) != sizeof(array_file_header) )
{
- fclose( ctx->fp );
- vg_fatal_error( "Array file corrupt\n" );
+ vg_error( "Array file not large enough to contain header.\n" );
+ return 0;
}
- if( ctx->header.version < min_version || ctx->header.version > max_version )
+ if( (afc->header.version < min_version) || (afc->header.version > max_version) )
{
- vg_info( "Legacy model version incompatable" );
- vg_info( "For model: %s\n", path );
- vg_info( " version: %u (min: %u, max: %u)\n",
- ctx->header.version, min_version, max_version );
- fclose( ctx->fp );
- vg_fatal_error( "Legacy\n" );
+ vg_error( "Array file version out of range\n" );
+ vg_error( " version: %u (min: %u, max: %u)\n", afc->header.version, min_version, max_version );
+ return 0;
}
- af_load_array_file( ctx, &ctx->index, &ctx->header.index, stack, sizeof(array_file_meta) );
-
- array_file_ptr strings;
- af_load_array( ctx, &strings, "strings", stack, 1 );
- ctx->strings = strings.data;
-}
-
-void af_close( array_file_context *ctx )
-{
- fclose( ctx->fp );
- ctx->fp = NULL;
+ af_load_array_file( afc, &afc->index, &afc->header.index, stack, sizeof(array_file_meta) );
+ return 1;
}
/* compiler
* ---------------------------------------------------------------------- */
-
+#if defined( VG_ENGINE )
struct af_compiler_iter
{
u32 i, j;
af_compiler_item *af_compiler_allocate_items( af_compiler *compiler, af_compiler_index *index, u32 count )
{
- af_compiler_item *entry = VG_STACK_ALLOCATE_STRUCT( compiler->stack, af_compiler_item );
+ af_compiler_item *entry = vg_stack_allocate( compiler->stack, sizeof(af_compiler_item), 1, "Compiler item" );
entry->next = NULL;
u32 data_size = count * index->element_size;
{
if( data )
{
- fwrite( data, data_len, 1, compiler->fp );
+ vg_stream_write( &compiler->stream, data, data_len );
compiler->file_offset += data_len;
}
while( compiler->file_offset % padding )
{
const u8 pad_byte = 0xac;
- fwrite( &pad_byte, 1, 1, compiler->fp );
+ vg_stream_write( &compiler->stream, &pad_byte, 1 );
compiler->file_offset ++;
}
}
u32 header_size = vg_align8( sizeof( array_file_header ) );
u32 index_size = vg_align8( sizeof( array_file_meta ) * indices_to_write );
-
- compiler->fp = fopen( path, "wb" );
- if( !compiler->fp )
+
+ if( !vg_file_stream_open( &compiler->stream, path, VG_STREAM_WRITE ) )
return 0;
compiler->file_offset = 0;
}
}
- fclose( compiler->fp );
+ vg_file_stream_close( &compiler->stream );
return 1;
}
+#endif
-#pragma once
-#include "vg_mem.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/array_file.c"
+#else
typedef struct array_file_ptr array_file_ptr;
typedef struct array_file_meta array_file_meta;
struct array_file_context
{
- FILE *fp;
+ vg_stream *stream;
array_file_header header;
array_file_ptr index;
- const void *strings;
};
-void af_open( array_file_context *ctx, const char *path, u32 min_version, u32 max_version, vg_stack_allocator *stack );
-void af_close( array_file_context *ctx );
-
/* array loading */
-array_file_meta *af_find_array( array_file_context *ctx, const char *name );
-void af_load_array_file( array_file_context *ctx, array_file_ptr *out_ptr,
- array_file_meta *arr, vg_stack_allocator *stack, u32 stride );
-int af_load_array( array_file_context *ctx, array_file_ptr *ptr, const char *name, vg_stack_allocator *stack, u32 stride );
+VG_TIER_0 array_file_meta *af_find_array( array_file_context *ctx, const c8 *name );
+
+
+VG_TIER_1 void af_load_array_file( array_file_context *ctx, array_file_ptr *out_ptr,
+ array_file_meta *arr, vg_stack_allocator *stack, u32 stride );
+VG_TIER_1 bool af_load_array( array_file_context *ctx, array_file_ptr *ptr, const char *name, vg_stack_allocator *stack, u32 stride );
+VG_TIER_0 void af_load_array_file_buffer( array_file_context *ctx, array_file_meta *arr, void *buffer, u32 stride );
#define AF_LOAD_ARRAY_STRUCT( CTX, PTR, STRUCT, STACK ) \
af_load_array( CTX, PTR, #STRUCT, STACK, sizeof(STRUCT) )
u32 af_arrcount( array_file_ptr *arr );
/* packed string buffer access (with djb2 hash prefix) */
-const char *af_str( array_file_context *af, u32 pstr );
-u32 af_str_hash( array_file_context *af, u32 pstr );
-bool af_str_eq( array_file_context *af, u32 pstr, const char *str, u32 str_hash );
+VG_TIER_0 const c8 *af_str( const void *packed_strings, u32 pstr );
+VG_TIER_0 u32 af_str_hash( const void *packed_strings, u32 pstr );
+VG_TIER_0 bool af_str_eq( const void *packed_strings, u32 pstr, const char *str, u32 str_hash );
#define AF_STR_EQ( CTX, PSTR, CONSTR ) \
af_str_eq( CTX, PSTR, CONSTR, vg_strdjb2( CONSTR ) )
/* COmpiler
* ------------------------------------ */
-
+#if defined( VG_ENGINE )
typedef struct af_compiler af_compiler;
typedef struct af_compiler_item af_compiler_item;
typedef struct af_compiler_index af_compiler_index;
af_compiler_item *most_recent_item;
- FILE *fp;
+ vg_stream stream;
u32 file_offset;
};
bool af_write( af_compiler *compiler, const char *path, u32 version );
af_compiler_index *af_get_or_make_index( af_compiler *compiler, const char *alias, u32 element_size );
u32 af_compile_string( af_compiler *compiler, const char *string );
+#endif
+#endif
-#include "world.h"
-#include "audio.h"
-#include "vg/vg_audio_dsp.h"
-
audio_clip audio_board[] =
{
{ .path="sound/skate_hpf.ogg" },
.any_data = &air_audio_data
};
-void audio_init(void)
+static void _audio_load_content_async( void *_, vg_async_info *async )
+{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+
+ vg_audio_clip_loadn( audio_board, VG_ARRAY_LEN(audio_board), NULL );
+ vg_audio_clip_loadn( audio_taps, VG_ARRAY_LEN(audio_taps), NULL );
+ vg_audio_clip_loadn( audio_flips, VG_ARRAY_LEN(audio_flips), NULL );
+ vg_audio_clip_loadn( audio_hits, VG_ARRAY_LEN(audio_hits), NULL );
+ vg_audio_clip_loadn( &audio_splash, 1, NULL );
+ vg_audio_clip_loadn( &audio_gate_pass, 1, NULL );
+ vg_audio_clip_loadn( &audio_gate_lap, 1, NULL );
+ vg_audio_clip_loadn( &audio_gate_ambient, 1, NULL );
+ vg_audio_clip_loadn( &audio_wood_break, 1, NULL );
+ vg_audio_clip_loadn( audio_jumps, VG_ARRAY_LEN(audio_jumps), NULL );
+ vg_audio_clip_loadn( audio_lands, VG_ARRAY_LEN(audio_lands), NULL );
+ vg_audio_clip_loadn( audio_water, VG_ARRAY_LEN(audio_water), NULL );
+ vg_audio_clip_loadn( audio_grass, VG_ARRAY_LEN(audio_grass), NULL );
+ vg_audio_clip_loadn( audio_footsteps, VG_ARRAY_LEN(audio_footsteps), NULL );
+ vg_audio_clip_loadn( audio_footsteps_grass, VG_ARRAY_LEN(audio_footsteps_grass), NULL );
+ vg_audio_clip_loadn( audio_footsteps_wood, VG_ARRAY_LEN(audio_footsteps_wood), NULL );
+ vg_audio_clip_loadn( audio_rewind, VG_ARRAY_LEN(audio_rewind), NULL );
+ vg_audio_clip_loadn( audio_ui, VG_ARRAY_LEN(audio_ui), NULL );
+ vg_audio_clip_loadn( audio_challenge, VG_ARRAY_LEN(audio_challenge), NULL );
+ vg_audio_clip_loadn( audio_gino, VG_ARRAY_LEN(audio_gino), NULL );
+}
+
+VG_API void _audio_init(void)
{
- audio_clip_loadn( audio_board, VG_ARRAY_LEN(audio_board), NULL );
- audio_clip_loadn( audio_taps, VG_ARRAY_LEN(audio_taps), NULL );
- audio_clip_loadn( audio_flips, VG_ARRAY_LEN(audio_flips), NULL );
- audio_clip_loadn( audio_hits, VG_ARRAY_LEN(audio_hits), NULL );
- audio_clip_loadn( &audio_splash, 1, NULL );
- audio_clip_loadn( &audio_gate_pass, 1, NULL );
- audio_clip_loadn( &audio_gate_lap, 1, NULL );
- audio_clip_loadn( &audio_gate_ambient, 1, NULL );
- audio_clip_loadn( &audio_wood_break, 1, NULL );
-
- audio_clip_loadn( audio_jumps, VG_ARRAY_LEN(audio_jumps), NULL );
- audio_clip_loadn( audio_lands, VG_ARRAY_LEN(audio_lands), NULL );
- audio_clip_loadn( audio_water, VG_ARRAY_LEN(audio_water), NULL );
- audio_clip_loadn( audio_grass, VG_ARRAY_LEN(audio_grass), NULL );
- audio_clip_loadn( audio_footsteps, VG_ARRAY_LEN(audio_footsteps), NULL );
- audio_clip_loadn( audio_footsteps_grass, VG_ARRAY_LEN(audio_footsteps_grass), NULL );
- audio_clip_loadn( audio_footsteps_wood, VG_ARRAY_LEN(audio_footsteps_wood), NULL );
- audio_clip_loadn( audio_rewind, VG_ARRAY_LEN(audio_rewind), NULL );
- audio_clip_loadn( audio_ui, VG_ARRAY_LEN(audio_ui), NULL );
- audio_clip_loadn( audio_challenge, VG_ARRAY_LEN(audio_challenge), NULL );
- audio_clip_loadn( audio_gino, VG_ARRAY_LEN(audio_gino), NULL );
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_audio_load_content_async );
vg_audio_lock();
air_audio_data.channel_id = vg_audio_get_first_idle_channel();
}
vg_audio_unlock();
}
-
-enum audio_sprite_type world_audio_sample_sprite_random(v3f origin, v3f output);
-void audio_ambient_sprites_update( world_instance *world, v3f co )
-{
- static float accum = 0.0f;
- accum += vg.time_delta;
-
- if( accum > 0.1f )
- accum -= 0.1f;
- else return;
-
- v3f sprite_pos;
- enum audio_sprite_type sprite_type =
- world_audio_sample_sprite_random( co, sprite_pos );
-
- if( sprite_type != k_audio_sprite_type_none ){
- if( sprite_type == k_audio_sprite_type_grass ){
- audio_ambient_sprite_play( sprite_pos,
- &audio_grass[vg_randu32(&vg.rand)%4] );
- }
- else if( sprite_type == k_audio_sprite_type_water ){
- if( world->water.enabled ){
- audio_ambient_sprite_play( sprite_pos,
- &audio_water[vg_randu32(&vg.rand)%6] );
- }
- }
- }
-}
-/*
- * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#pragma once
-
-#include "vg/vg_engine.h"
-#include "vg/vg_audio.h"
-#include "vg/vg_audio_dsp.h"
-#include "world.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/audio.c"
+#else
struct air_synth_data {
f32 speed;
}
extern air_audio_data;
-void audio_init(void);
+VG_API void _audio_init(void);
void audio_ambient_sprite_play( v3f co, audio_clip *clip );
-void audio_ambient_sprites_update( world_instance *world, v3f co );
/* TODO(ASSETS):
* Have these as asignable ID's and not a bunch of different arrays.
+ * TODO: Just marking here again because this still isn't fucking fixed
*/
extern audio_clip audio_board[];
extern audio_clip audio_taps[];
k_audio_sprite_type_grass,
k_audio_sprite_type_water
};
+
+#endif
-#include "board_maker.h"
-#include "shaders/workshop_compositor.h"
-#include "vg/vg_ui/filebrowser.h"
-
struct _board_maker _board_maker =
{
- .compositor_fb =
- {
- .display_name = "Workshop Compositor texture",
- .resolution_div = 0,
- .fixed_w = 512, .fixed_h = 512,
- .attachments = (vg_framebuffer_attachment[])
- {
- {
- .display_name = "RGBA",
- .purpose = k_framebuffer_attachment_type_texture,
- .quality = k_framebuffer_quality_all,
- .internalformat = GL_RGBA,
- .format = GL_RGBA,
- .type = GL_UNSIGNED_BYTE,
- .attachment = GL_COLOR_ATTACHMENT0
- }
- },
- .attachment_count = 1
- }
};
/* image loader thread
i32 w, h;
};
-static void _async_board_maker_image_finish( vg_async_task *task )
+static void _async_board_maker_image_finish( struct board_maker_image_info *in_args, vg_async_info *async )
{
- struct board_maker_image_info *inf = (void *)task->data;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_OWNS_OPENGL ) );
struct board_maker_decal *decal = &_board_maker.decals[ _board_maker.ui_target_part ];
if( decal->loaded )
glGenTextures( 1, &decal->texture );
glBindTexture( GL_TEXTURE_2D, decal->texture );
- glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, inf->w, inf->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, inf->data );
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, in_args->w, in_args->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, in_args->data );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glGenerateMipmap( GL_TEXTURE_2D );
-
- stbi_image_free( inf->data );
+ stbi_image_free( in_args->data );
_board_maker.state = k_board_maker_state_none;
_board_maker.compositor_state = k_board_maker_compositor_dirty;
static void _board_maker_image_t1( void *userdata )
{
- THREAD_1;
- vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, sizeof(struct board_maker_image_info), 1 );
- struct board_maker_image_info *info = (void *)task->data;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+ struct board_maker_image_info *out_args = _vg_async_alloc( VG_THREAD_MAIN_ID, sizeof(struct board_maker_image_info));
i32 nc;
stbi_set_flip_vertically_on_load(1);
- info->data = stbi_load( _board_maker.browser->current_path, &info->w, &info->h, &nc, 4 );
- vg_async_task_dispatch( task, _async_board_maker_image_finish );
+ out_args->data = stbi_load( _board_maker.browser->current_path, &out_args->w, &out_args->h, &nc, 4 );
+ _vg_async_send( out_args, (vg_async_fn)_async_board_maker_image_finish );
}
/* model loader thread
* ----------------------------------------- */
-static void _async_board_maker_load_finish( void *userdata )
+static void _async_board_maker_load_finish( void *nothing, vg_async_info *async )
{
_board_maker.state = k_board_maker_state_none;
_board_maker.template_loaded = _board_maker.template_selection;
_board_maker.base_shader = NULL;
- mdl_context *mdl = &_board_maker.template_mdl;
+ vg_model *mdl = &_board_maker.template_mdl;
if( mdl->version <= 105 )
return;
if( mat0->shader != k_shader_workshop )
return;
- _board_maker.base_shader = mat0->props.compiled;
+ _board_maker.base_shader = &mdl->shader_props[0];
}
struct ui_enum_opt _board_maker_template_opts[] =
[2] = "models/workshop/longboard.mdl"
};
-static void _board_maker_load_template( void *_ )
+static void _board_maker_load_template( void *_, vg_async_info *async )
{
- THREAD_1;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
vg_stack_clear( &_board_maker.template_stack );
- mdl_context *mdl = &_board_maker.template_mdl;
- mdl_open( mdl, _board_maker_template_paths[_board_maker.template_selection], &_board_maker.template_stack );
- mdl_load_metadata_block( mdl, &_board_maker.template_stack );
+ vg_model_stream_context ctx;
+ VG_ASSERT( vg_model_stream_open( &ctx, &_board_maker.template_mdl,
+ _board_maker_template_paths[_board_maker.template_selection] ) );
+ vg_model_stream_metadata( &ctx, &_board_maker.template_stack );
/* we need this for compiling it back down */
- mdl_load_mesh_block( mdl, &_board_maker.template_stack );
- AF_LOAD_ARRAY_STRUCT( &mdl->af, &_board_maker.template_mdl_markers, ent_marker, &_board_maker.template_stack );
+ vg_model_stream_meshes_cpu( &ctx, &_board_maker.template_stack );
+ vg_model_stream_meshes_gpu( &ctx, NULL );
+ vg_model_stream_textures_gpu( &ctx );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &_board_maker.template_mdl_markers, ent_marker, &_board_maker.template_stack );
+ vg_model_stream_close( &ctx );
- mdl_async_full_load_std( mdl, NULL );
- mdl_close( mdl );
- vg_async_call( &vg.main_tasks, _async_board_maker_load_finish, NULL );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)_async_board_maker_load_finish );
}
/* system init thread
* ----------------------------------------------------- */
-static void _async_board_maker_init_finish( void *userdata )
+static void _board_maker_init_late(void)
{
- THREAD_0;
- _board_maker.state = k_board_maker_state_none;
-}
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+
+ _board_maker.compositor_fb = _vg_framebuffer_alloc( VG_STACK_USE_HEAP, 1, 0 );
+ _board_maker.compositor_fb->display_name = "Workshop Compositor texture";
+ _board_maker.compositor_fb->resolution_div = 0;
+ _board_maker.compositor_fb->fixed_w = 512;
+ _board_maker.compositor_fb->fixed_h = 512;
+ _board_maker.compositor_fb->attachments[0] = (vg_framebuffer_attachment)
+ {
+ .display_name = "RGBA",
+ .purpose = k_framebuffer_attachment_type_texture,
+ .quality = k_framebuffer_quality_all,
+ .internalformat = GL_RGBA,
+ .format = GL_RGBA,
+ .type = GL_UNSIGNED_BYTE,
+ .attachment = GL_COLOR_ATTACHMENT0
+ };
+ vg_framebuffer_init( _board_maker.compositor_fb );
-static void _board_maker_init_t1( void *userdata )
-{
- THREAD_1;
- vg_framebuffer_create( &_board_maker.compositor_fb );
- vg_async_call( &vg.main_tasks, _async_board_maker_init_finish, NULL );
+ _board_maker.state = k_board_maker_state_none;
}
static void _board_maker_export(void)
.channels = 3,
.colorspace = QOI_SRGB
};
-
- void *raw_data = malloc( 512*512*3 ),
- *qoi_data = malloc( vg_query_qoi_storage_size( &desc ) );
-
- vg_framebuffer_bind( &_board_maker.compositor_fb, 1.0f );
- glReadBuffer( GL_COLOR_ATTACHMENT0 );
- glReadPixels( 0,0, 512,512, GL_RGB, GL_UNSIGNED_BYTE, raw_data );
-
- i32 qoi_len;
- if( !vg_encode_qoi2( raw_data, &desc, qoi_data, &qoi_len ) )
+
+ u32 onetex;
+ u32 temp_frame = _vg_start_temp_frame();
{
- free( raw_data );
- free( qoi_data );
-
- _board_maker.export_success = 0;
- _board_maker.export_message = "Texture failed to compress";
- _board_maker.ui_state = k_board_maker_ui_state_export_signal_done;
- return;
- }
+ void *raw_data = vg_stack_allocate( _vg_temp_stack(), 512*512*3, 8, "Raw data" ),
+ *qoi_data = vg_stack_allocate( _vg_temp_stack(), vg_query_qoi_max_compressed_size( &desc ), 8, "QOI" );
- u32 onetex = mdl_compiler_compile_texture_qoi( &compiler, "Maker Tex", qoi_data, qoi_len );
+ vg_framebuffer_bind( _board_maker.compositor_fb, 1.0f );
+ glReadBuffer( GL_COLOR_ATTACHMENT0 );
+ glReadPixels( 0,0, 512,512, GL_RGB, GL_UNSIGNED_BYTE, raw_data );
- free( raw_data );
- free( qoi_data );
+ vg_stream qoi_stream;
+ vg_buffer_stream_open( &qoi_stream, qoi_data, vg_query_qoi_max_compressed_size( &desc ), VG_STREAM_WRITE );
- u8 shader_buf[ 512 ];
- vg_msg shader_kvs;
- vg_msg_init( &shader_kvs, shader_buf, sizeof(shader_buf) );
- vg_msg_wkvnum( &shader_kvs, "tex_diffuse", k_vg_msg_u32, 1, &onetex );
+ i32 qoi_len = vg_qoi_stream_encode( &desc, raw_data, &qoi_stream, 0 );
+ if( qoi_len == 0 )
+ {
+ _board_maker.export_success = 0;
+ _board_maker.export_message = "Texture failed to compress";
+ _board_maker.ui_state = k_board_maker_ui_state_export_signal_done;
+ _vg_end_temp_frame( temp_frame );
+ return;
+ }
+ onetex = mdl_compiler_compile_texture_qoi( &compiler, "Maker Tex", qoi_data, qoi_len );
+ }
+ _vg_end_temp_frame( temp_frame );
- u32 onemat = mdl_compiler_start_material( &compiler, "Maker Mat" );
- mdl_compiler_push_shaderdata( &compiler, k_shader_standard, &shader_kvs );
+ u32 onemat;
+ temp_frame = _vg_start_temp_frame();
+ {
+ vg_kvs shader_kvs;
+ vg_kvs_init( &shader_kvs, _vg_temp_stack() );
+ vg_kv_append_vu32( &shader_kvs, 0, "tex_diffuse", &onetex, 1 );
+ onemat = mdl_compiler_start_material( &compiler, "Maker Mat" );
+ mdl_compiler_push_shaderdata( &compiler, k_shader_standard, &shader_kvs );
+ }
+ _vg_end_temp_frame( temp_frame );
for( u32 i=0; i<_board_maker.template_mdl.mesh_count; i ++ )
{
u32 ref_marker_index = mdl_entity_id_id( ref_mesh->entity_id );
ent_marker *ref_marker = af_arritm( &_board_maker.template_mdl_markers, ref_marker_index );
- const char *ref_marker_alias = af_str( &_board_maker.template_mdl.af, ref_marker->pstr_alias );
+ const c8 *ref_marker_alias = af_str( _board_maker.template_mdl.packed_strings, ref_marker->pstr_alias );
ent_marker copy_marker = *ref_marker;
copy_marker.pstr_alias = af_compile_string( &compiler.af, ref_marker_alias );
ref_submesh->indice_count );
}
- af_write( &compiler.af, _board_maker.export_path, MDL_VERSION_NR );
+ af_write( &compiler.af, _board_maker.export_path, VG_MODEL_VERSION_NR );
mdl_compiler_free( &compiler );
_board_maker.export_success = 1;
{
if( _board_maker.compositor_state == k_board_maker_compositor_dirty )
{
- vg_framebuffer_bind( &_board_maker.compositor_fb, 1.0f );
+ vg_framebuffer_bind( _board_maker.compositor_fb, 1.0f );
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT );
{
for( u32 i=0; i<k_workshop_shader_part_max; i ++ )
{
- u32 tex_id = _board_maker.base_shader->tex_all[i];
+ u32 tex_id = _board_maker.base_shader->workshop.tex_all[i];
if( tex_id )
{
- mdl_texture *tex = &_board_maker.template_mdl.textures[ tex_id-1 ];
+ mdl_texture *mdl_tex = &_board_maker.template_mdl.textures[ tex_id-1 ];
- glActiveTexture( GL_TEXTURE0 );
- glBindTexture( GL_TEXTURE_2D, tex->glname );
+ vg_tex_bind( GL_TEXTURE_2D, &mdl_tex->tex, 0 );
shader_workshop_compositor_uColour( _board_maker.colours[i] );
struct board_maker_decal *decal = &_board_maker.decals[ i ];
{
if( _board_maker.template_loaded != -1 )
{
- mdl_sync_std_unload( &_board_maker.template_mdl );
+ vg_model_unload_gpu( &_board_maker.template_mdl );
_board_maker.template_loaded = -1;
}
_board_maker.state = k_board_maker_state_loading_template;
- vg_async_call( &vg.loader_tasks, _board_maker_load_template, NULL );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_board_maker_load_template );
}
}
else
if( _board_maker.state == k_board_maker_state_not_ready )
{
_board_maker.state = k_board_maker_state_initializing;
- vg_async_call( &vg.loader_tasks, _board_maker_init_t1, NULL );
+ _board_maker_init_late();
}
else if( _board_maker.state == k_board_maker_state_load_image )
{
_board_maker.state = k_board_maker_state_loading_image;
- vg_async_call( &vg.loader_tasks, _board_maker_image_t1, NULL );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_board_maker_image_t1 );
}
else if( _board_maker.state == k_board_maker_state_export )
{
if( _board_maker.template_loaded >= 0 )
{
- vg_framebuffer_bind_texture( &_board_maker.compositor_fb, 0, 0 );
-
+ vg_framebuffer_bind_texture( _board_maker.compositor_fb, 0, 0 );
shader_model_entity_use();
shader_model_entity_uTexMain( 0 );
shader_model_entity_uCamera( cam->transform[3] );
shader_model_entity_uPv( cam->mtx.pv );
-
- WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, model_entity );
+ WORLD_LINK_LIGHTING( world, model_entity );
m4x3f root_mmdl;
m4x3_identity( root_mmdl );
q_m3x3( _board_maker.q, root_mmdl );
v3_copy( _board_maker.origin, root_mmdl[3] );
- mdl_context *mdl = &_board_maker.template_mdl;
- mesh_bind( &mdl->mesh );
+ vg_model *mdl = &_board_maker.template_mdl;
+ vg_model_bind_mesh( mdl );
for( u32 i=0; i<mdl->mesh_count; i ++ )
{
for( u32 j=0; j<mesh->submesh_count; j ++ )
{
mdl_submesh *sm = &mdl->submeshes[ mesh->submesh_start + j ];
- mdl_draw_submesh( sm );
+ vg_model_draw_submesh( sm );
}
}
}
if( _board_maker.ui_state == k_board_maker_ui_state_export )
{
ui_rect export_rect = { 0,0, 400, 300 };
- ui_rect_center( (ui_rect){0,0,vg.window_x,vg.window_y}, export_rect );
+ ui_rect_center( (ui_rect){0,0,_vg_window.w,_vg_window.h}, export_rect );
ui_panel( ctx, export_rect, export_rect );
/* title */
}
}
- ui_rect box = { vg.window_x-(400+8),8, 400,400 };
- ui_image( ctx, box, &_board_maker.compositor_fb.attachments[0].id, 0 );
+ ui_rect box = { _vg_window.w-(400+8),8, 400,400 };
+ ui_image( ctx, box, &_board_maker.compositor_fb->attachments[0].tex, 0 );
ui_outline( ctx, box, 1, ui_colour( ctx, k_ui_fg ), 0 );
if( quit_me )
_board_maker.template_loaded = -1;
_board_maker.template_selection = 0;
- vg_stack_init( &_board_maker.static_stack, NULL, VG_MB(8), "Board Maker: Static Stack" );
- vg_stack_init( &_board_maker.template_stack, NULL, VG_MB(16), "Board Maker: Template Stack" );
+ vg_stack_init( &_board_maker.static_stack, VG_STACK_USE_HEAP, VG_MB(8), "Board Maker: Static Stack" );
+ vg_stack_init( &_board_maker.template_stack, VG_STACK_USE_HEAP, VG_MB(16), "Board Maker: Template Stack" );
for( u32 i=0; i<k_workshop_shader_part_max; i ++ )
{
void _board_maker_close(void)
{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+
for( u32 i=0; i<k_workshop_shader_part_max; i ++ )
{
struct board_maker_decal *decal = &_board_maker.decals[i];
clear_decal( decal );
}
- vg_framebuffer_free( &_board_maker.compositor_fb );
+ vg_framebuffer_free( _board_maker.compositor_fb );
vg_filebrowser_free_entries( _board_maker.browser );
free( _board_maker.browser );
_board_maker.browser = NULL;
- mdl_sync_std_unload( &_board_maker.template_mdl );
+ vg_model_unload_gpu( &_board_maker.template_mdl );
_board_maker.template_loaded = -1;
vg_stack_free( &_board_maker.static_stack );
-#pragma once
-#include "vg/vg_framebuffer.h"
-#include "shader_props.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/board_maker.c"
+#else
v4f _board_maker_default_colours[] =
{
i32 template_selection,
template_loaded;
- mdl_context template_mdl;
+ vg_model template_mdl;
array_file_ptr template_mdl_markers;
enum board_maker_state
}
compositor_state;
- vg_framebuffer compositor_fb;
+ vg_framebuffer *compositor_fb;
v4f colours[ k_workshop_shader_part_max ];
- struct shader_props_workshop *base_shader;
+ union shader_props *base_shader;
struct board_maker_decal
{
void _board_maker_ui( ui_context *ctx );
void _board_maker_open(void);
void _board_maker_close(void);
+
+#endif
+++ /dev/null
-/*
- * Script to load the overlay model and generate an enum referencing each
- * submesh by its name.
- */
-void build_control_overlay(void)
-{
- FILE *hdr = fopen( "src/control_overlay.h.generated", "w" );
-
- vg_stack_allocator stack;
- vg_stack_init( &stack, NULL, VG_MB(8), "Model buffer" );
-
- mdl_context ctx;
- mdl_open( &ctx, "content_skaterift/models/rs_overlay.mdl", &stack );
- mdl_load_metadata_block( &ctx, &stack );
- mdl_close( &ctx );
-
- for( u32 i=0; i<ctx.mesh_count; i ++ )
- {
- mdl_mesh *mesh = &ctx.meshes[ i ];
- fprintf( hdr, " %s = %u,\n", af_str( &ctx.af, mesh->pstr_name ), mesh->submesh_start );
- }
-
- vg_stack_free( &stack );
- fclose( hdr );
-}
-#include "vg/vg_opt.h"
-#include "vg/vg_loader.h"
-#include "vg/vg_io.h"
-#include "vg/vg_audio.h"
-
-#include "client.h"
-#include "render.h"
-#include "network.h"
-#include "player_remote.h"
-#include "menu.h"
-
const char* __asan_default_options() { return "detect_leaks=0"; }
-struct game_client g_client =
+struct game_client _client =
{
- .demo_mode = 1,
};
-#include "skaterift.c"
+struct skaterift_globals skaterift =
+{
+ .time_rate = 1.0f,
+};
+
+static void _skaterift_mount_addons_async( void *_, vg_async_info *async )
+{
+ _world.default_hub_addon = _addon_mount_from_folder_path( "maps/dev_hub", k_addon_type_world, ".mdl" );
+ VG_ASSERT( _world.default_hub_addon );
+ _addon_mount_content_folder( k_addon_type_player, "playermodels", ".mdl" );
+ _addon_mount_content_folder( k_addon_type_board, "boards", ".mdl" );
+ _addon_mount_content_folder( k_addon_type_world, "maps", ".mdl" );
+}
+
+int skaterift_quit_command( int argc, const char *argv[] )
+{
+ if( argc >= 1 )
+ if( !strcmp( argv[0], "1" ) )
+ skaterift.no_save_location = 1;
+
+ _vg_terminate();
+ return 1;
+}
+
+/*
+ * UPDATE LOOP
+ * ---------------------------------------------------------------------------*/
+
+static void draw_origin_axis(void)
+{
+ vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 1.0f, 0.0f, 0.0f }, 0xffff0000 );
+ vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 0.0f, 1.0f, 0.0f }, 0xff00ff00 );
+ vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 0.0f, 0.0f, 1.0f }, 0xff0000ff );
+}
+
+void client_event_handler( vg_event_info *info )
+{
+ if( info->type == k_vg_event_opts )
+ {
+ const char *arg;
+ if( vg_long_opt( "noauth", "Disable server authentication" ) )
+ network_client.auth_mode = eServerModeNoAuthentication;
+
+ if( (arg = vg_long_opt_arg( "server", "Specify server address" )) )
+ network_set_host( arg, NULL );
+
+ if( (arg = vg_long_opt_arg( "world", "Specify path to world to load" )) )
+ skaterift.override_load_world = arg;
+
+ _demo_check_opts();
+ }
+ else if( info->type == k_vg_event_register )
+ {
+ vg_console_reg_cmd( "quit", skaterift_quit_command, NULL );
+ vg_console_reg_cmd( "load_world", skaterift_load_world_command, NULL );
+ vg_console_reg_var( "immobile", &localplayer.immobile, k_var_dtype_i32, 0 );
+ vg_console_reg_var( "allow_resume", &skaterift.allow_replay_resume, k_var_dtype_i32, VG_VAR_CHEAT );
+ vg_console_reg_var( "boost_scale", &skaterift.boost_scale, k_var_dtype_f32, VG_VAR_CHEAT );
+
+ _render_register();
+ _remote_players_register();
+ _network_register();
+ _menu_register();
+ _control_overlay_register();
+ _world_render_register();
+ _gui_register();
+ _compass_register();
+ _player_register();
+ _player_ragdoll_register();
+ _cutscene_register();
+ _workshop_register();
+ _ent_tornado_register();
+ _replay2_register();
+ _ent_atom_register();
+ _ent_challenge_register();
+
+ _steam_api.cb_connection_changed = cb_skaterift_connection_changed;
+ _steam_api.cb_persona_changed = cb_skaterift_persona_changed;
+
+ network_set_host( "skaterift.com", NULL );
+ }
+ else if( info->type == k_vg_event_init )
+ {
+ _vg_loader_set_user_information( "Initializing subsystems" );
+
+ _vg_async_context_push_groups( SKATERIFT_LOAD_GROUP );
+ _demo_check_init();
+ _render_init();
+ _remote_players_init();
+ _network_init();
+ _menu_init();
+ _user_profile_init();
+ _particles_init();
+ _addon_system_init();
+
+ _player_init();
+ _player_render_init();
+
+ _control_overlay_init();
+ _world_init();
+ _gui_init();
+ _compass_init();
+ _skateshop_init();
+ _world_map_init();
+ _replay2_init();
+ _ent_npc_init();
+ _audio_init();
+ _ent_atom_init();
+
+ _mount_workshop_addons();
+ _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_skaterift_mount_addons_async );
+
+ if( network_client.auto_connect )
+ network_client.user_intent = k_server_intent_online;
+ menu_at_begin();
+ _vg_async_context_pop_groups();
+ }
+ else if( info->type == k_vg_event_pre_update )
+ {
+
+#if 0
+ if( co_step( co, 1 ) )
+ {
+ /* initializing / loading world. */
+ vg_loader_set_user_information( "Loading savedata" );
+ skaterift_load_mainsave();
+
+ if( skaterift.override_load_world )
+ _world.load_addon = _addon_mount_from_folder_path( skaterift.override_load_world, k_addon_type_world, ".mdl" );
+
+ _world.loader_instance = &_world.main;
+ _world.loader_preview_mode = 0;
+ _world.loader_stack = _world.stack;
+
+ if( !_world.load_addon )
+ {
+ vg_warn( "Falling back to default hub world...\n" );
+ _world.load_addon = _world.default_hub_addon;
+ }
+
+ _world_loader_set_addon( _world.load_addon );
+ }
+#endif
+
+
+ skaterift_preupdate_inputs();
+ world_switcher_update();
+
+ if( !skaterift.ready_to_show_game )
+ return;
+
+ //draw_origin_axis();
+ //_skaterift_script_update();
+ _addon_system_pre_update();
+ _network_update();
+
+ /* time rate */
+ f32 target = 1;
+ if( skaterift.activity & k_skaterift_replay )
+ target = 0;
+
+ if( skaterift.activity == k_skaterift_spectate )
+ {
+ if( button_down( k_srbind_mback ) )
+ {
+ vg_audio_lock();
+ vg_audio_oneshot( &audio_ui[3], 1.0f, 0.0f, 0, 0 );
+ vg_audio_unlock();
+ menu_close(); /* sets tate to default*/
+ menu_open( k_menu_page_quick );
+ _gui_helper_reset( k_gui_helper_mode_clear );
+ localplayer.immobile = 0;
+ }
+ }
+
+ world_update( &_world.main, localplayer.rb.co );
+ _board_maker_pre_update();
+
+ cutscene_update( vg.time_rate * vg.time_frame_delta );
+
+ if( !((skaterift.activity == k_skaterift_menu) && (menu.page != k_menu_page_quick)) )
+ player__pre_update();
+
+ _replay2_pre_update();
+ remote_sfx_pre_update();
+
+ v3f listen_co;
+ v3_copy( localplayer.rb.co, listen_co );
+ if( skaterift.activity & k_skaterift_menu )
+ {
+ if( menu.page != k_menu_page_quick )
+ {
+ if( menu.bg_cam )
+ v3_copy( menu.bg_cam->co, listen_co );
+ else target = 0;
+ }
+ }
+
+ vg_slewf( &skaterift.time_rate, target, vg.time_frame_delta * (1.0f/0.3f) );
+ vg.time_rate = vg_smoothstepf( skaterift.time_rate );
+ }
+ else if( info->type == k_vg_event_fixed_update )
+ {
+ if( !skaterift.ready_to_show_game )
+ return;
+
+ world_routes_fixedupdate( &_world.main );
+ player__update();
+ }
+ else if( info->type == k_vg_event_post_update )
+ {
+ if( !skaterift.ready_to_show_game )
+ return;
+
+ player__post_update();
+
+ float dist;
+ int sample_index;
+ world_audio_sample_distances( localplayer.rb.co, &sample_index, &dist );
+
+ vg_audio_lock();
+ vg_dsp.echo_distances[sample_index] = dist;
+
+ v3f ears = { 1.0f,0.0f,0.0f };
+ m3x3_mulv( g_render.cam.transform, ears, ears );
+ v3_copy( ears, _vg_audio.controls.listener_right_ear_direction );
+ v3_copy( g_render.cam.transform[3], _vg_audio.controls.listener_position );
+
+ if( localplayer.gate_waiting )
+ {
+ m4x3_mulv( localplayer.gate_waiting->transport, _vg_audio.controls.listener_position,
+ _vg_audio.controls.listener_position );
+ }
+
+ v3_copy( localplayer.rb.v, _vg_audio.controls.listener_velocity );
+ vg_audio_unlock();
+
+ _skaterift_autosave_post_update();
+ localplayer.immunity = 0;
+ }
+ else if( info->type == k_vg_event_render )
+ {
+ if( !skaterift.ready_to_show_game )
+ return;
+
+ glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+
+ glViewport( 0,0, _vg_window.w, _vg_window.h );
+ glDisable( GL_DEPTH_TEST );
+ glDisable( GL_BLEND );
+
+ glClearColor( 1.0f, 0.0f, 0.0f, 0.0f );
+ glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
+
+ /* RENDER main game
+ * ------------------------------------------------------------------------------------------------------------ */
+ {
+ if( (_cutscene.state >= k_cutscene_state_ready) && _cutscene.player_binding )
+ {
+ struct cs_instance *inst = _cutscene.player_binding;
+ ms_skeleton *sk = &localplayer.skeleton;
+ for( u32 i=0; i<sk->bone_count; i ++ )
+ m4x3_copy( inst->skinning_data[i], localplayer.final_mtx[i] );
+ }
+ else if( skaterift.activity == k_skaterift_replay ){}
+ else
+ {
+ player__animate();
+ _replay2_record_local_frame();
+ }
+
+ animate_remote_players();
+ player__pre_render();
+
+
+ /* world entity driven camera
+ * ------------------------------------------------------------------------------ */
+ if( _world.entity_set_camera )
+ {
+ _world.entity_set_camera = 0;
+ _world.entity_camera_modulate = vg_minf( 1.0f, _world.entity_camera_modulate+vg.time_frame_delta );
+ }
+ else
+ {
+ _world.entity_camera_modulate = vg_maxf( 0.0f, _world.entity_camera_modulate-vg.time_frame_delta );
+ }
+
+ vg_camera_lerp( &localplayer.cam, &_world.entity_driven_camera,
+ vg_smoothstepf(_world.entity_camera_modulate), &g_render.cam );
+
+ /* replay camera
+ * ------------------------------------------------------------------ */
+ if( skaterift.activity == k_skaterift_replay )
+ {
+ _replay2_get_camera( &g_render.cam );
+ }
+
+ if( skaterift.activity == k_skaterift_spectate )
+ {
+ _network_get_spectate_cam( &g_render.cam );
+ }
+
+ g_render.cam.nearz = 0.1f;
+ g_render.cam.farz = 2100.0f;
+
+ /* menu override camera
+ * -------------------------------------------------------------------- */
+ if( (skaterift.activity == k_skaterift_menu) && menu.bg_cam )
+ {
+ ent_camera_unpack( menu.bg_cam, &g_render.cam );
+ }
+
+ /* cutscene camera TODO: Fix the action camera
+ * ---------------------------------------------------------------- */
+ ent_camera *cs_cam = _cutscene_active_camera();
+ if( cs_cam )
+ ent_camera_unpack( cs_cam, &g_render.cam );
+
+ world_map_get_transition_cam( &g_render.cam );
+
+ vg_camera_update_transform( &g_render.cam );
+
+ vg_camera_update_view( &g_render.cam );
+ vg_camera_update_projection( &g_render.cam, _vg_window.w, _vg_window.h );
+ vg_camera_finalize( &g_render.cam );
+
+
+
+
+
+
+
+ bool render_actual_game = !menu_viewing_map();
+ bool render_stenciled = 0;
+
+ if( render_actual_game )
+ {
+ world_instance *world = &_world.main;
+ render_world_cubemaps( world );
+ }
+
+ /* variable res target */
+ vg_framebuffer_bind( _vg_render.fb_main, _vg_render.scale );
+ glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
+ glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT );
+
+ if( !render_actual_game )
+ {
+ render_world_map();
+
+ if( world_map_get_transition_cam(NULL) )
+ {
+ glEnable( GL_STENCIL_TEST );
+ glDisable( GL_DEPTH_TEST );
+ glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
+ glStencilFunc( GL_ALWAYS, 1, 0xFF );
+ glStencilMask( 0xFF );
+
+ shader_blit_transition_use();
+ shader_blit_transition_uInverseRatio( (v2f){1.0f,1.0f} );
+ shader_blit_transition_uT( -(sqrtf(2)+0.5f) * world_map.spawn_timer );
+ render_fsquad();
+ render_stenciled = 1;
+ render_actual_game = 1;
+ }
+ }
+
+ if( render_actual_game )
+ {
+ /* Draw world */
+ glEnable( GL_DEPTH_TEST );
+ world_prerender( &_world.main );
+
+ render_world( &_world.main, &g_render.cam, render_stenciled, 0, 1, 1, _vg_render.fb_main );
+
+ particle_system_update( &particles_grind, vg.time_delta );
+ //particle_system_debug( &particles_grind );
+ particle_system_prerender( &particles_grind );
+ particle_system_render( &particles_grind, &g_render.cam );
+
+ ent_tornado_pre_update();
+ particle_system_update( &particles_env, vg.time_delta );
+ particle_system_prerender( &particles_env );
+ particle_system_render( &particles_env, &g_render.cam );
+
+ player_glide_render_effects( &g_render.cam );
+ }
+
+ glEnable( GL_DEPTH_TEST );
+
+ /* full res target */
+ glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+ glViewport( 0,0, _vg_window.w, _vg_window.h );
+
+ if( render_actual_game && !render_stenciled )
+ {
+ bool render_player_transparent = 1;
+
+ if( (skaterift.activity == k_skaterift_menu) &&
+ (menu.page == k_menu_page_main) &&
+ (menu.main_index == k_menu_main_guide) )
+ {
+ render_player_transparent = 0;
+ }
+
+ if( skaterift.activity == k_skaterift_replay )
+ render_player_transparent = 0;
+
+ if( render_player_transparent )
+ {
+ static vg_camera small_cam; /* DOES NOT NEED TO BE STATIC BUT MINGW
+ SAIS OTHERWISE */
+
+ m4x3_copy( g_render.cam.transform, small_cam.transform );
+
+ small_cam.fov = g_render.cam.fov;
+ small_cam.nearz = 0.05f;
+ small_cam.farz = 60.0f;
+
+ vg_camera_update_view( &small_cam );
+ vg_camera_update_projection( &small_cam, _vg_window.w, _vg_window.h );
+ vg_camera_finalize( &small_cam );
+
+ /* Draw player to window buffer and blend background ontop */
+ player__render( &small_cam );
+ }
+
+ /* continue with variable rate */
+ vg_framebuffer_bind( _vg_render.fb_main, _vg_render.scale );
+ render_world_gates( &_world.main, &g_render.cam, _vg_render.fb_main );
+ }
+
+ /* composite */
+ if( (skaterift.activity == k_skaterift_menu) && menu.bg_blur )
+ v2_muls( (v2f){ 0.04f, 0.001f }, 1.0f-skaterift.time_rate, g_render.blur_override );
+ else
+ v2_zero( g_render.blur_override );
+
+ vg_postprocess_to_screen( _vg_render.fb_main );
+ _cutscene_render_fadeout();
+
+ if( !_gui_helpers_active() )
+ control_overlay_render();
+ }
+
+
+ m4x4_copy( g_render.cam.mtx.pv, vg.pv );
+
+ glDisable(GL_BLEND);
+ glDisable(GL_DEPTH_TEST);
+ glViewport( 0,0, _vg_window.w, _vg_window.h );
+
+ _gui_render_icons();
+ compass_render_texture();
+ }
+ else if( info->type == k_vg_event_gui )
+ {
+ if( !skaterift.ready_to_show_game )
+ return;
+
+ glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+ glViewport( 0,0, _vg_window.w, _vg_window.h );
+
+ _gui_draw( info->gui.ctx );
+ _compass_render_imgui( info->gui.ctx );
+
+ if( k_light_editor )
+ imgui_world_light_edit( info->gui.ctx, &_world.main );
+
+ vg_ui.tex_bg = &_vg_render.fb_main->attachments[0].tex;
+ vg_framebuffer_inverse_ratio( _vg_render.fb_main, vg_ui.bg_inverse_ratio );
+
+ _cutscene_gui( info->gui.ctx );
+ _board_maker_ui( info->gui.ctx );
+ menu_gui( info->gui.ctx );
+ player__im_gui( info->gui.ctx );
+ world_instance *world = &_world.main;
+
+ if( skaterift.activity != k_skaterift_replay )
+ {
+ world_routes_imgui( info->gui.ctx, world );
+ _ent_route_imgui( info->gui.ctx );
+ }
+ _replay2_imgui( info->gui.ctx );
+ workshop_form_gui( info->gui.ctx );
+ world_gui( info->gui.ctx, world );
+
+ if( menu_viewing_map() )
+ {
+ remote_players_imgui_world( info->gui.ctx, &_world.main, vg.pv, 2000.0f, 0 );
+ //remote_players_imgui_lobby( ctx );
+ }
+ else
+ {
+ remote_players_chat_imgui( info->gui.ctx ); /* TODO: conditional */
+ remote_players_imgui_world( info->gui.ctx, &_world.main, vg.pv, 100.0f, 1 );
+ }
+ }
+}
+
+int main( int argc, const char *argv[] )
+{
+ vg_run( argc, argv, client_event_handler );
+ return 0;
+}
-#pragma once
-#include "vg/vg_platform.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/client.c"
+#else
-/*
- * client - entry point. window, common things like render init.. etc
- * vg - backend code
- * game - top layer: game content, state
- */
+#define SKATERIFT_APPID 2103940
+#define SKATERIFT_WORLD_READY 0x10000
+#define SKATERIFT_LOAD_GROUP VG_ASYNC_GROUP_CLIENT3
struct game_client
{
- bool demo_mode;
+ u32 async_init_count;
}
-extern g_client;
+extern _client;
/* game defined */
void game_launch_opt( void );
+
+enum skaterift_rt
+{
+ k_skaterift_rt_workshop_preview,
+ k_skaterift_rt_server_status,
+ k_skaterift_rt_max
+};
+
+struct skaterift_globals
+{
+ f32 time_rate;
+
+ enum skaterift_activity {
+ k_skaterift_default = 0x00, /* regular playing */
+ k_skaterift_replay = 0x01,
+ k_skaterift_spectate = 0x02,
+ k_skaterift_menu = 0x04,
+ k_skaterift_activity_max = 0x8
+ }
+ activity;
+
+ vg_tex *rt_textures[k_skaterift_rt_max];
+
+ u32 achievements;
+ i32 allow_replay_resume;
+
+ const char *override_load_world;
+
+ f32 boost_scale;
+ bool no_save_location;
+
+ bool ready_to_show_game;
+}
+extern skaterift;
+
+#endif
+++ /dev/null
-/*
- * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#ifndef COMMON_H
-#define COMMON_H
-
-#endif /* COMMON_H */
-#include "compass.h"
-#include "shaders/compass.h"
-#include "world.h"
-
struct _compass _compass = { .alpha = 1 };
-void compass_register(void)
+VG_API void _compass_register(void)
{
vg_console_reg_var( "compass_alpha", &_compass.alpha, k_var_dtype_f32, VG_VAR_PERSISTENT );
}
-void compass_init(void)
+static void _compass_load_content_async( void *_, vg_async_info *async )
+{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+ vg_model_load( &_compass.model, VG_MODEL_ENGINE_STANDARD, "models/rs_compass.mdl", NULL );
+ _compass.sm_comp = vg_model_get_submesh_index( &_compass.model, "comp" );
+ _compass.sm_comp_bar = vg_model_get_submesh_index( &_compass.model, "comp_bar" );
+ _compass.sm_comp_dot = vg_model_get_submesh_index( &_compass.model, "comp_dot" );
+ _compass.sm_comp_e = vg_model_get_submesh_index( &_compass.model, "comp_e" );
+ _compass.sm_comp_fade = vg_model_get_submesh_index( &_compass.model, "comp_fade" );
+ _compass.sm_comp_friend = vg_model_get_submesh_index( &_compass.model, "comp_friend" );
+ _compass.sm_comp_gate = vg_model_get_submesh_index( &_compass.model, "comp_gate" );
+ _compass.sm_comp_n = vg_model_get_submesh_index( &_compass.model, "comp_n" );
+ _compass.sm_comp_notify = vg_model_get_submesh_index( &_compass.model, "comp_notify" );
+ _compass.sm_comp_person = vg_model_get_submesh_index( &_compass.model, "comp_person" );
+ _compass.sm_comp_s = vg_model_get_submesh_index( &_compass.model, "comp_s" );
+ _compass.sm_comp_w = vg_model_get_submesh_index( &_compass.model, "comp_w" );
+ _compass.sm_comp_objective = vg_model_get_submesh_index( &_compass.model, "comp_objective" );
+}
+
+VG_API void _compass_init(void)
{
- mdl_context *mdl = &_compass.mdl;
-
- mdl_open( mdl, "models/rs_compass.mdl", &vg.rtmem );
- mdl_load_metadata_block( mdl, &vg.rtmem );
- mdl_async_full_load_std( mdl, NULL );
- _compass.sm_comp = mdl_get_submesh_index( mdl, "comp" );
- _compass.sm_comp_bar = mdl_get_submesh_index( mdl, "comp_bar" );
- _compass.sm_comp_dot = mdl_get_submesh_index( mdl, "comp_dot" );
- _compass.sm_comp_e = mdl_get_submesh_index( mdl, "comp_e" );
- _compass.sm_comp_fade = mdl_get_submesh_index( mdl, "comp_fade" );
- _compass.sm_comp_friend = mdl_get_submesh_index( mdl, "comp_friend" );
- _compass.sm_comp_gate = mdl_get_submesh_index( mdl, "comp_gate" );
- _compass.sm_comp_n = mdl_get_submesh_index( mdl, "comp_n" );
- _compass.sm_comp_notify = mdl_get_submesh_index( mdl, "comp_notify" );
- _compass.sm_comp_person = mdl_get_submesh_index( mdl, "comp_person" );
- _compass.sm_comp_s = mdl_get_submesh_index( mdl, "comp_s" );
- _compass.sm_comp_w = mdl_get_submesh_index( mdl, "comp_w" );
- _compass.sm_comp_objective = mdl_get_submesh_index( mdl, "comp_objective" );
- mdl_close( mdl );
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_compass_load_content_async );
}
static void compass_project( m3x3f base_projection, f32 x, f32 height )
projection[0][0] = 512.0f/400.0f;
projection[1][1] = 512.0f/50.0f;
- mdl_context *mdl = &_compass.mdl;
- mesh_bind( &mdl->mesh );
+ vg_model *mdl = &_compass.model;
+ vg_model_bind_mesh( mdl );
shader_compass_use();
shader_compass_uTexMain( 0 );
- glActiveTexture( GL_TEXTURE0 );
- glBindTexture( GL_TEXTURE_2D, mdl->textures[0].glname );
+ vg_tex_bind( GL_TEXTURE_2D, &mdl->textures[0].tex, 0 );
/* base */
shader_compass_uColour( (v4f){ 1,1,1,0.4 } );
compass_project( projection, 0,0 );
- mdl_draw_submesh( &mdl->submeshes[ _compass.sm_comp_bar ] );
+ vg_model_draw_submesh( &mdl->submeshes[ _compass.sm_comp_bar ] );
if( compass_a( projection, 0.0f, 0 ) )
- mdl_draw_submesh( &mdl->submeshes[ _compass.sm_comp_n ] );
+ vg_model_draw_submesh( &mdl->submeshes[ _compass.sm_comp_n ] );
if( compass_a( projection, VG_PIf/2.0f, 0 ) )
- mdl_draw_submesh( &mdl->submeshes[ _compass.sm_comp_e ] );
+ vg_model_draw_submesh( &mdl->submeshes[ _compass.sm_comp_e ] );
if( compass_a( projection, VG_PIf, 0 ) )
- mdl_draw_submesh( &mdl->submeshes[ _compass.sm_comp_s ] );
+ vg_model_draw_submesh( &mdl->submeshes[ _compass.sm_comp_s ] );
if( compass_a( projection, -VG_PIf/2.0f, 0 ) )
- mdl_draw_submesh( &mdl->submeshes[ _compass.sm_comp_w ] );
+ vg_model_draw_submesh( &mdl->submeshes[ _compass.sm_comp_w ] );
for( u32 i=0; i<4; i ++ )
{
f32 a = VG_PIf/4.0f + (f32)i * (VG_PIf/2.0f);
if( compass_a( projection, a, 0 ) )
{
- mdl_draw_submesh( &mdl->submeshes[ _compass.sm_comp_dot ] );
+ vg_model_draw_submesh( &mdl->submeshes[ _compass.sm_comp_dot ] );
}
}
struct network_player *player = &netplayers.list[i];
if( player->active && player->same_world )
{
- struct skeleton *sk = &localplayer.skeleton;
+ ms_skeleton *sk = &localplayer.skeleton;
m4x3f *final_mtx = &netplayers.final_mtx[ sk->bone_count*i ];
if( compass_co( projection, final_mtx[0][3], 0.0f ) )
- mdl_draw_submesh( &mdl->submeshes[ player->isfriend? _compass.sm_comp_friend: _compass.sm_comp_person ] );
+ vg_model_draw_submesh( &mdl->submeshes[ player->isfriend? _compass.sm_comp_friend: _compass.sm_comp_person ] );
}
}
}
if( marker->flags & k_ent_marker_flag_gui_icon )
{
if( compass_co( projection, marker->transform.co, 0.0f ) )
- mdl_draw_submesh( &mdl->submeshes[ _compass.sm_comp_notify ] );
+ vg_model_draw_submesh( &mdl->submeshes[ _compass.sm_comp_notify ] );
}
}
for( u32 i=0; i<af_arrcount(&world->ent_challenge); i++ )
if( !challenge->status )
{
if( compass_co( projection, challenge->transform.co, 0.0f ) )
- mdl_draw_submesh( &mdl->submeshes[ _compass.sm_comp_objective ] );
+ vg_model_draw_submesh( &mdl->submeshes[ _compass.sm_comp_objective ] );
}
}
ent_gate *gate = af_arritm( &world->ent_gate, cp->gate_index );
if( compass_co( projection, gate->co[0], 0.0f ) )
- mdl_draw_submesh( &mdl->submeshes[ _compass.sm_comp_gate ] );
+ vg_model_draw_submesh( &mdl->submeshes[ _compass.sm_comp_gate ] );
}
}
}
if( !(route->flags & (k_ent_route_flag_achieve_gold|k_ent_route_flag_achieve_silver)) )
{
if( compass_co( projection, route->board_transform[3], 0.0f ) )
- mdl_draw_submesh( &mdl->submeshes[ _compass.sm_comp_objective ] );
+ vg_model_draw_submesh( &mdl->submeshes[ _compass.sm_comp_objective ] );
}
}
}
}
-void compass_render_imgui( ui_context *ctx )
+VG_API void _compass_render_imgui( ui_context *ctx )
{
if( skaterift.activity == k_skaterift_replay )
return;
ui_rect rect = { 0,0, 800, 100 };
- ui_rect_center( (ui_rect){0,0,vg.window_x,100}, rect );
+ ui_rect_center( (ui_rect){0,0,_vg_window.w,100}, rect );
ui_flush( ctx, k_ui_shader_colour, NULL );
vg_ui.colour[3] = _compass.alpha;
- ui_image( ctx, rect, &g_render.fb_compass->attachments[0].id, 0 );
+ ui_image( ctx, rect, &g_render.fb_compass->attachments[0].tex, 0 );
vg_ui.colour[3] = 1.0f;
}
-#pragma once
-#include "vg/vg_framebuffer.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/compass.c"
+#else
struct _compass
{
- mdl_context mdl;
+ vg_model model;
i32 sm_comp,
sm_comp_bar,
}
extern _compass;
-void compass_init(void);
-void compass_register(void);
+VG_API void _compass_register(void);
+VG_API void _compass_init(void);
void compass_render_texture(void);
-void compass_render_imgui( ui_context *ctx );
+VG_API void _compass_render_imgui( ui_context *ctx );
+
+#endif
-#include "control_overlay.h"
-#include "model.h"
-#include "input.h"
-#include "player.h"
-#include "player_skate.h"
-#include "player_walk.h"
-#include "shaders/model_menu.h"
-#include "vg/vg_engine.h"
-#include "vg/vg_mem.h"
-#include "vg/vg_m.h"
-
-struct control_overlay control_overlay = { .enabled = 1 };
+struct control_overlay _control_overlay = { .enabled = 1 };
static void render_overlay_mesh( enum control_overlay_mesh index )
{
- mdl_draw_submesh( &control_overlay.mdl.submeshes[ index ] );
+ vg_model_draw_submesh( &_control_overlay.model.submeshes[ index ] );
}
-static void control_overlay_init_finish( void *userdata )
+VG_API void _control_overlay_register(void)
{
- mdl_context *mdl = &control_overlay.mdl;
- if( mdl->texture_count )
- {
- mdl_texture *tex = &mdl->textures[ 0 ];
- control_overlay.tex = tex->glname;
- }
- else
- {
- control_overlay.tex = vg.tex_missing;
- vg_error( "No texture in control overlay\n" );
- }
+ vg_console_reg_var( "control_overlay", &_control_overlay.enabled, k_var_dtype_i32, VG_VAR_PERSISTENT );
}
-void control_overlay_register(void)
+static void _control_overlay_load_content_async( void *_, vg_async_info *async )
{
- vg_console_reg_var( "control_overlay", &control_overlay.enabled, k_var_dtype_i32, VG_VAR_PERSISTENT );
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+ vg_model_load( &_control_overlay.model, VG_MODEL_ENGINE_STANDARD, "models/rs_overlay.mdl", NULL );
+ VG_ASSERT( _control_overlay.model.texture_count );
}
-void control_overlay_init(void)
+VG_API void _control_overlay_init(void)
{
- mdl_context *mdl = &control_overlay.mdl;
-
- mdl_open( mdl, "models/rs_overlay.mdl", &vg.rtmem );
- mdl_load_metadata_block( mdl, &vg.rtmem );
- mdl_async_full_load_std( mdl, NULL );
- mdl_close( mdl );
- vg_async_call( &vg.main_tasks, control_overlay_init_finish, NULL );
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_control_overlay_load_content_async );
}
static void draw_key( bool press, bool wide )
void control_overlay_render(void)
{
- if( !control_overlay.enabled ) return;
+ if( !_control_overlay.enabled ) return;
if( skaterift.activity != k_skaterift_default ) return;
if( _cutscene.state != k_cutscene_state_none ) return;
if( localplayer.subsystem == k_player_subsystem_dead ) return;
glBlendEquation(GL_FUNC_ADD);
m4x4f ortho;
- f32 r = (f32)vg.window_x / (f32)vg.window_y,
+ f32 r = (f32)_vg_window.w / (f32)_vg_window.h,
fl = -r,
fr = r,
fb = 1.0f,
shader_model_menu_uPv( ortho );
shader_model_menu_uColour( cnorm );
- mdl_context *mdl = &control_overlay.mdl;
- mesh_bind( &mdl->mesh );
- glActiveTexture( GL_TEXTURE1 );
- glBindTexture( GL_TEXTURE_2D, control_overlay.tex );
+ vg_model_bind_mesh( &_control_overlay.model );
+ vg_tex_bind( GL_TEXTURE_2D, &_control_overlay.model.textures[0].tex, 1 );
enum player_subsystem subsytem = localplayer.subsystem;
-#pragma once
+#if defined( SR_IMPLEMENTATION )
+# include "src/control_overlay.c"
+#else
enum control_overlay_mesh
{
- #include "control_overlay.h.generated"
+ #include "src.generated/control_overlay.h"
};
struct control_overlay
{
- mdl_context mdl;
- GLuint tex;
+ vg_model model;
i32 enabled;
}
-extern control_overlay;
+extern _control_overlay;
+
+VG_API void _control_overlay_register(void);
+VG_API void _control_overlay_init(void);
void control_overlay_render(void);
-void control_overlay_init(void);
-void control_overlay_register(void);
+
+#endif
--- /dev/null
+struct _cutscene _cutscene;
+
+struct cs_instance *_cutscene_get_first_model_instance( const c8 *mdl_name )
+{
+ for( u32 i=0; i<_cutscene.instance_count; i ++ )
+ {
+ struct cs_instance *inst = &_cutscene.instances[i];
+ struct model_ref *mref = &_cutscene.refs[ inst->ref_id ];
+
+ if( vg_str_eq( mdl_name, mref->name ) )
+ return inst;
+ }
+
+ return NULL;
+}
+
+void _cutscene_unload(void)
+{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ vg_info( "Unloading cutscene\n" );
+ vg_audio_lock();
+ vg_audio_set_flagged_pause( AUDIO_FLAG_CUTSCENE, 0 );
+ vg_audio_fadeout_flagged_audio( AUDIO_FLAG_CUTSCENE, 1.0f );
+ vg_audio_unlock();
+
+ for( u32 i=0; i<_cutscene.unique_refs; i ++ )
+ vg_model_unload_gpu( &_cutscene.refs[i].model );
+
+ _cutscene.unique_refs = 0;
+ _cutscene.active_camera = NULL;
+ _cutscene.strip = 0;
+ _cutscene.time = 0.0f;
+ _cutscene.active_samplers = 0;
+ _cutscene.state = k_cutscene_state_unloading;
+ _cutscene.player_binding = NULL;
+ _cutscene.subtitle = NULL;
+ _cutscene.raiser_entity = 0;
+ _cutscene.fadeout = 0;
+ _cutscene.skipped = 0;
+ _cutscene.fadeout_start = 0.0f;
+}
+
+/*
+ * Find associated entity data. We should also probably do this on the world
+ * thingy
+ */
+struct cs_asoc
+{
+ vg_model *orig_data;
+ u16 entity_type,
+ entity_index;
+ ms_override *override;
+};
+
+static void _cutscene_override_asoc( u32 instance_id, u32 override_index, struct cs_asoc *out_asoc )
+{
+ struct cs_instance *instance = &_cutscene.instances[ instance_id ];
+ vg_model *model = &_cutscene.refs[ instance->ref_id ].model;
+
+ ms_instance *oins = af_arritm( &_cutscene.meta.instances, instance_id );
+ ms_override *override = af_arritm( &_cutscene.meta.overrides, oins->override_start + override_index );
+
+ out_asoc->orig_data = model;
+ out_asoc->entity_type = override->entity_type;
+ out_asoc->override = override;
+ const char *name = af_str( _cutscene.meta.packed_strings, override->pstr_name );
+ u32 name_hash = af_str_hash( _cutscene.meta.packed_strings, override->pstr_name );
+
+ if( out_asoc->entity_type != 28 )
+ goto NOT_IMPLEMENTED;
+
+ for( u32 j=0; j<model->armature_count; j ++ )
+ {
+ mdl_armature *armature = &model->armatures[ j ];
+ if( af_str_eq( model->packed_strings, armature->pstr_name, name, name_hash ) )
+ {
+ out_asoc->entity_index = j;
+ return;
+ }
+ }
+
+NOT_IMPLEMENTED:
+
+ vg_fatal_error( "The data association was not found.\n"
+ " Entity Type: %u\n"
+ " Entity name: %s\n", override->entity_type, name );
+}
+
+static void _cutscene_get_strip_asoc( ms_strip *strip, struct cs_asoc *out_asoc )
+{
+ VG_ASSERT( strip->mode & k_ms_strip_mode_animation );
+ if( strip->strip.instance_id == 0xffffffff )
+ {
+ out_asoc->orig_data = NULL;// &_cutscene.meta;
+ out_asoc->entity_type = mdl_entity_id_type( strip->strip.object_id );
+ out_asoc->entity_index = mdl_entity_id_id( strip->strip.object_id );
+ out_asoc->override = NULL;
+ }
+ else
+ _cutscene_override_asoc( strip->strip.instance_id, strip->strip.object_id, out_asoc );
+}
+
+static void sync_cutscene_loaded( void *nothing, vg_async_info *async )
+{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ vg_info( "Cutscene loaded\n" );
+ _cutscene.state = k_cutscene_state_ready;
+}
+
+struct cutscene_load_info
+{
+ u32 nothing;
+ char path[];
+};
+static void cutscene_load_thread( struct cutscene_load_info *in_args, vg_async_info *info )
+{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+
+ vg_info( "Loading cutscene: %s\n", in_args->path );
+ vg_stack_init( &_cutscene.stack, NULL, VG_MB(20), "Cutscene Stack" );
+ metascene_load( &_cutscene.meta, in_args->path, &_cutscene.stack );
+ _cutscene.instance_count = af_arrcount( &_cutscene.meta.instances );
+ _cutscene.instances = vg_stack_allocate( &_cutscene.stack, sizeof(struct cs_instance) * _cutscene.instance_count,
+ 8, "Instances" );
+
+ _cutscene.refs = vg_stack_allocate( &_cutscene.stack, 0, 8, "References" );
+ _cutscene.unique_refs = 0;
+ for( u32 i=0; i < _cutscene.instance_count; i ++ )
+ {
+ ms_instance *instance = af_arritm( &_cutscene.meta.instances, i );
+ const char *name = af_str( _cutscene.meta.packed_strings, instance->pstr_name );
+ u32 name_hash = af_str_hash( _cutscene.meta.packed_strings, instance->pstr_name );
+
+ struct model_ref *ref = NULL;
+ u32 ref_id = 0;
+
+ for( u32 j=0; j<_cutscene.unique_refs; j ++ )
+ {
+ struct model_ref *ref_j = &_cutscene.refs[ j ];
+
+ if( af_str_eq( _cutscene.meta.packed_strings, instance->pstr_name, ref_j->name, ref_j->name_hash ) )
+ {
+ ref = ref_j;
+ ref_id = j;
+ break;
+ }
+ }
+
+ if( !ref )
+ {
+ vg_stack_extend_last( &_cutscene.stack, sizeof(struct model_ref) );
+ ref_id = _cutscene.unique_refs;
+ ref = &_cutscene.refs[ ref_id ];
+ ref->name = name;
+ ref->name_hash = name_hash;
+ ref->reference_count = 0;
+ vg_info( "Indexed reference '%s'\n", name );
+ _cutscene.unique_refs ++;
+ }
+
+ ref->reference_count ++;
+ _cutscene.instances[ i ].ref_id = ref_id;
+ _cutscene.instances[ i ].skinning_data = NULL;
+ _cutscene.instances[ i ].disable_render = 0;
+ }
+
+ /* load model data */
+ for( u32 i=0; i<_cutscene.unique_refs; i ++ )
+ {
+ struct model_ref *ref = &_cutscene.refs[ i ];
+ char mdl_path_buf[ 512 ];
+ vg_str mdl_path;
+ vg_strnull( &mdl_path, mdl_path_buf, sizeof(mdl_path_buf) );
+ vg_strcat( &mdl_path, ref->name );
+ vg_strcat( &mdl_path, ".mdl" );
+
+ vg_info( "Loading instance model: %s\n", mdl_path.buffer );
+ vg_model_load( &ref->model, VG_MODEL_ENGINE_STANDARD, mdl_path.buffer, &_cutscene.stack );
+
+ u32 skeleton_count = ref->model.armature_count;
+ if( skeleton_count )
+ {
+ ref->skeletons = vg_stack_allocate( &_cutscene.stack, sizeof(struct cs_skeleton) * skeleton_count, 8, "Skeletons" );
+ ref->total_skinning_bones = 0;
+ for( u32 j=0; j<skeleton_count; j ++ )
+ {
+ struct cs_skeleton *skele = &ref->skeletons[ j ];
+ skeleton_setup( &skele->sk, &ref->model, j, &_cutscene.stack );
+ skele->skinning_offset = ref->total_skinning_bones;
+ ref->total_skinning_bones += skele->sk.bone_count;
+ }
+ }
+ else
+ {
+ ref->skeletons = NULL;
+ ref->total_skinning_bones = 0;
+ }
+ }
+
+ /* allocate skinning memory per-instance */
+ for( u32 i=0; i<_cutscene.instance_count; i ++ )
+ {
+ struct cs_instance *ins = &_cutscene.instances[ i ];
+ struct model_ref *ref = &_cutscene.refs[ ins->ref_id ];
+
+ ins->skinning_data = vg_stack_allocate( &_cutscene.stack, sizeof(m4x3f) * ref->total_skinning_bones,
+ 8, "Skinning Data" );
+ for( u32 j=0; j<ref->total_skinning_bones; j ++ )
+ m4x3_identity( ins->skinning_data[ j ] );
+
+ /* load overrides */
+ ms_instance *oins = af_arritm( &_cutscene.meta.instances, i );
+ for( u32 j=0; j<oins->override_count; j ++ )
+ {
+ ms_override *override = af_arritm( &_cutscene.meta.overrides, oins->override_start + j );
+
+ struct cs_asoc asoc;
+ _cutscene_override_asoc( i, j, &asoc );
+
+ VG_ASSERT( asoc.entity_type == 28 );
+
+ struct cs_skeleton *skele = &ref->skeletons[ asoc.entity_index ];
+ m4x3f mmdl;
+ mdl_transform_m4x3( &override->transform, mmdl );
+
+ for( u32 l=0; l<skele->sk.bone_count; l ++ )
+ m4x3_copy( mmdl, ins->skinning_data[skele->skinning_offset+l] );
+ }
+ }
+
+ /* audio packs */
+ for( u32 j=0; j<af_arrcount( &_cutscene.meta.audios ); j++ )
+ {
+ ent_audio *audio = af_arritm( &_cutscene.meta.audios, j );
+
+ for( u32 k=0; k<audio->clip_count; k++ )
+ {
+ ent_audio_clip *clip = af_arritm( &_cutscene.meta.audio_clips, audio->clip_start+k );
+ if( clip->_.file.pack_size )
+ vg_error( "Currently not support packed audio in metascene..." );
+ else
+ {
+ clip->_.clip.path = af_str( _cutscene.meta.packed_strings, clip->_.file.pstr_path );
+ clip->_.clip.flags = audio->flags;
+ clip->_.clip.any_data = NULL;
+ clip->_.clip.size = 0;
+ }
+ vg_audio_clip_load( &clip->_.clip, &_cutscene.stack );
+ }
+ }
+
+ _vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)sync_cutscene_loaded );
+}
+
+bool _cutscene_load_and_play( const char *path, bool freeze_player, u32 raiser_entity )
+{
+ if( _cutscene.state != k_cutscene_state_none )
+ {
+ vg_error( "Tried to play cutscene '%s' while already playing one.\n", path );
+ return 0;
+ }
+
+ _cutscene.raiser_entity = raiser_entity;
+
+ for( u32 i=0; i<k_npc_max; i ++ )
+ _ent_npc_set_in_cutscene( i, 0 );
+
+ _cutscene.state = k_cutscene_state_loading;
+ _cutscene.time = 0.0f;
+ _cutscene.strip = 0;
+ _cutscene.active_samplers = 0;
+ _cutscene.freeze_player = freeze_player;
+
+ u32 len = strlen( path ) +1;
+ struct cutscene_load_info *out_args = _vg_async_alloc( VG_THREAD_ASYNC_ID, sizeof(struct cutscene_load_info) + len );
+ strcpy( out_args->path, path );
+ _vg_async_send( out_args, (vg_async_fn)cutscene_load_thread );
+ return 1;
+}
+
+/*
+ * Currently draws everything as skinned meshes.
+ */
+static void cutscene_render_instance( struct cs_instance *ins, vg_camera *cam )
+{
+ if( ins->disable_render )
+ return;
+
+ struct model_ref *ref = &_cutscene.refs[ ins->ref_id ];
+ vg_model *mdl = &ref->model;
+ vg_model_bind_mesh( mdl );
+
+ shader_model_character_view_use();
+ shader_model_character_view_uCamera( cam->transform[3] );
+ shader_model_character_view_uPv( cam->mtx.pv );
+ shader_model_character_view_uDepthMode( 0 );
+ shader_model_character_view_uShadeless( 0 );
+ shader_model_character_view_uUvOffset( (v2f){0,0} );
+
+ WORLD_LINK_LIGHTING( &_world.main, model_character_view );
+ shader_model_character_view_uTexMain( 0 );
+
+ u32 armature_id = 0x00;
+ u32 material_id = 0x00;
+ bool using_additive = 0;
+
+ for( u32 i=0; i<mdl->mesh_count; i ++ )
+ {
+ mdl_mesh *mesh = &mdl->meshes[ i ];
+ VG_ASSERT( mesh->armature_id );
+
+ if( mesh->armature_id != armature_id )
+ {
+ armature_id = mesh->armature_id;
+ u32 sk_index = mdl_entity_id_id( armature_id );
+
+ struct cs_skeleton *skele = &ref->skeletons[ sk_index ];
+ m4x3f *skinning_data = ins->skinning_data + skele->skinning_offset;
+ shader_model_character_view_uTransforms( skinning_data, skele->sk.bone_count );
+ }
+
+ for( u32 j=0; j<mesh->submesh_count; j ++ )
+ {
+ mdl_submesh *sm = &mdl->submeshes[ mesh->submesh_start+j ];
+ VG_ASSERT( sm->material_id );
+
+ if( sm->material_id != material_id )
+ {
+ mdl_material *m = &mdl->materials[ sm->material_id-1 ];
+ VG_ASSERT( m->shader == k_shader_standard );
+
+ union shader_props *props = &mdl->shader_props[ sm->material_id-1 ];
+ VG_ASSERT( props->standard.tex_diffuse );
+ vg_tex_bind( GL_TEXTURE_2D, &mdl->textures[ props->standard.tex_diffuse-1 ].tex, 0 );
+
+ if( props->standard.render_flags & k_material_render_additive )
+ {
+ using_additive = 1;
+ glDepthMask(GL_FALSE);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE);
+ glBlendEquation(GL_FUNC_ADD);
+ glDisable( GL_CULL_FACE );
+ shader_model_character_view_uShadeless( 1 );
+ }
+ else
+ {
+ if( using_additive )
+ {
+ using_additive = 0;
+ glDepthMask(GL_TRUE);
+ glDisable(GL_BLEND);
+ glEnable( GL_CULL_FACE );
+ shader_model_character_view_uShadeless( 0 );
+ }
+ }
+ }
+
+ vg_model_draw_submesh( sm );
+ }
+ }
+
+ if( using_additive )
+ {
+ shader_model_character_view_uShadeless( 0 );
+ glDepthMask(GL_TRUE);
+ glDisable(GL_BLEND);
+ }
+}
+
+#define CS_LOCATION 0
+#define CS_ANGLES 4
+#define CS_FOV 8
+
+struct cs_link_info
+{
+ f32 *target;
+ u32 semantic_type;
+};
+
+static bool link_internal_datapath( struct cs_asoc *asoc, const char *datapath, struct cs_link_info *out_link )
+{
+ if( asoc->entity_type != k_ent_camera )
+ {
+ vg_warn( "Failed link %d#%d:'%s'\n", asoc->entity_type, asoc->entity_index, datapath );
+ VG_ASSERT( 0 );
+ }
+ ent_camera *cam = af_arritm( &_cutscene.meta.cameras, asoc->entity_index );
+
+ struct
+ {
+ const char *prefix;
+ f32 *arr;
+ u32 semantic;
+ }
+ reference[] =
+ {
+ { "location:", cam->co, CS_LOCATION },
+ { "rotation_euler:", cam->r, CS_ANGLES },
+ { "lens:", &cam->fov, CS_FOV }
+ };
+
+ for( u32 i=0; i<VG_ARRAY_LEN(reference); i ++ )
+ {
+ u32 len = strlen( reference[i].prefix );
+ if( !strncmp( reference[i].prefix, datapath, len ) )
+ {
+ i32 offset = atoi( datapath + len );
+ out_link->target = reference[i].arr + offset;
+ out_link->semantic_type = reference[i].semantic + offset;
+
+ vg_info( "Linked %d#%d:'%s'\n", asoc->entity_type, asoc->entity_index, datapath );
+ return 1;
+ }
+ }
+
+ vg_warn( "Failed link %d#%d:'%s'\n", asoc->entity_type, asoc->entity_index, datapath );
+ return 0;
+}
+
+ent_camera *_cutscene_active_camera(void)
+{
+ return _cutscene.active_camera;
+}
+
+void cutscene_update( f32 delta )
+{
+ if( _cutscene.state == k_cutscene_state_unloading )
+ {
+ // NOTE: This somestimes still fails!
+ if( !vg_audio_flagged_stopped( AUDIO_FLAG_CUTSCENE ) )
+ {
+ static u32 ticker = 0;
+ ticker ++;
+ if( ticker > 50 )
+ {
+ vg_low( "waiting for audio to stop...\n" );
+ ticker = 0;
+ }
+ return;
+ }
+
+ vg_stack_free( &_cutscene.stack );
+ _cutscene.state = k_cutscene_state_none;
+ _cutscene.marker_this_frame = NULL;
+ _cutscene.subtitle = NULL;
+ _cutscene.raiser_entity = 0;
+ vg_info( "Finished unloading cutscene\n" );
+ return;
+ }
+
+ if( _cutscene.state == k_cutscene_state_ready )
+ {
+ _cutscene.player_binding = _cutscene_get_first_model_instance( "models/ch_none" );
+ if( _cutscene.player_binding )
+ _cutscene.player_binding->disable_render = 1;
+
+ /* start playing */
+ if( _cutscene.freeze_player )
+ localplayer.immobile = 1;
+
+ vg_audio_lock();
+ for( u32 j=0; j<af_arrcount( &_cutscene.meta.audios ); j++ )
+ {
+ ent_audio *audio = af_arritm( &_cutscene.meta.audios, j );
+ ent_audio_clip *clip = af_arritm( &_cutscene.meta.audio_clips, audio->clip_start );
+
+ if( audio->flags & AUDIO_FLAG_AUTO_START )
+ {
+ const u16 group = 0xfff1;
+ const u32 flags = AUDIO_FLAG_CUTSCENE;
+
+ if( audio->flags & AUDIO_FLAG_SPACIAL_3D )
+ vg_audio_oneshot_3d( &clip->_.clip, audio->transform.co, audio->transform.s[0], audio->volume, group,flags);
+ else
+ vg_audio_oneshot( &clip->_.clip, 1.0f, 0.0f, group, flags );
+ }
+ }
+ vg_audio_unlock();
+
+ _cutscene.state = k_cutscene_state_playing;
+ _world_raise_event( _cutscene.raiser_entity, "start" );
+ }
+
+ if( _cutscene.state != k_cutscene_state_playing )
+ return;
+
+ _cutscene.marker_this_frame = NULL;
+ _cutscene.time += delta;
+ i32 frame = _cutscene.time * _cutscene.meta.info.framerate;
+
+ /* clear out finished samplers */
+ bool move = 0;
+ u32 j = 0;
+ for( u32 i=0; i<_cutscene.active_samplers; i ++ )
+ {
+ struct cs_sampler *si = &_cutscene.samplers[i];
+
+ if( frame > (si->strip->offset + (i32)si->strip->strip.length) )
+ move = 1;
+ else
+ {
+ if( move )
+ {
+ struct cs_sampler *sj = &_cutscene.samplers[j];
+ *sj = *si;
+ }
+
+ j ++;
+ }
+ }
+ _cutscene.active_samplers = j;
+
+ /* add new samplers as we get to them */
+ for( u32 i=_cutscene.strip; i<af_arrcount(&_cutscene.meta.strips); i ++ )
+ {
+ ms_strip *strip = af_arritm(&_cutscene.meta.strips, i);
+
+ if( frame < strip->offset )
+ break;
+
+ if( strip->mode & k_ms_strip_mode_animation )
+ {
+ if( frame > strip->offset + (i32)strip->strip.length )
+ {
+ vg_warn( "Skipping?\n" );
+ _cutscene.strip ++;
+ continue;
+ }
+
+ if( _cutscene.skipped == 2 )
+ {
+ _cutscene.strip ++;
+ continue;
+ }
+
+ if( strip->strip.instance_id == 0xffffffff )
+ {
+ const char *strip_name = af_str( _cutscene.meta.packed_strings, strip->strip.pstr_name );
+ vg_info( "+ Strip: '%s' entity: %u\n", strip_name, strip->strip.object_id );
+
+ /* internal link */
+ struct cs_asoc asoc;
+ _cutscene_get_strip_asoc( strip, &asoc );
+
+ if( strip->mode == k_ms_strip_mode_curves )
+ {
+ for( u32 j=0; j<strip->strip.count; j ++ )
+ {
+ ms_track *track = af_arritm( &_cutscene.meta.tracks, strip->strip.start + j );
+ const char *datapath = af_str( _cutscene.meta.packed_strings, track->pstr_datapath );
+
+ struct cs_link_info link;
+ if( !link_internal_datapath( &asoc, datapath, &link ) )
+ continue;
+
+ VG_ASSERT( _cutscene.active_samplers < VG_ARRAY_LEN(_cutscene.samplers) );
+ struct cs_sampler *samp = &_cutscene.samplers[ _cutscene.active_samplers ++ ];
+ samp->strip = strip;
+ samp->curves.track = track;
+
+ samp->curves.target = link.target;
+ samp->curves.semantic = link.semantic_type;
+ samp->curves.keyframe = 0;
+ samp->override = asoc.override;
+ VG_ASSERT( samp->curves.target );
+ }
+ }
+ else VG_ASSERT(0);
+ }
+ else
+ {
+ /* external link */
+ struct cs_instance *ins = &_cutscene.instances[ strip->strip.instance_id ];
+ struct cs_asoc asoc;
+ _cutscene_get_strip_asoc( strip, &asoc );
+ VG_ASSERT( asoc.entity_type == 28 );
+
+ if( strip->mode == k_ms_strip_mode_keyframes )
+ {
+ VG_ASSERT( _cutscene.active_samplers < VG_ARRAY_LEN(_cutscene.samplers) );
+
+ struct cs_sampler *samp = &_cutscene.samplers[ _cutscene.active_samplers ++ ];
+ struct model_ref *ref = &_cutscene.refs[ ins->ref_id ];
+ struct cs_skeleton *skele = &ref->skeletons[ asoc.entity_index ];
+
+ samp->strip = strip;
+ samp->skeleton.skinning_data = &ins->skinning_data[ skele->skinning_offset ];
+ samp->skeleton.ref_sk = &skele->sk;
+ samp->override = asoc.override;
+ }
+ else
+ {
+ VG_ASSERT(0);
+ }
+ }
+ }
+ else
+ {
+ if( strip->mode == k_ms_strip_mode_camera )
+ {
+ u32 type = mdl_entity_id_type( strip->camera.entity_id ),
+ index = mdl_entity_id_id( strip->camera.entity_id );
+ VG_ASSERT( type == k_ent_camera );
+ ent_camera *cam = af_arritm( &_cutscene.meta.cameras, index );
+ _cutscene.active_camera = cam;
+ }
+
+ if( strip->mode == k_ms_strip_mode_fadeout )
+ {
+ _cutscene.fadeout = 1;
+ _cutscene.fadeout_start = _cutscene.time;
+ }
+
+ if( strip->mode == k_ms_strip_mode_subtitle )
+ {
+ // FIXME: COLOURS
+ _cutscene.subtitle = af_str( _cutscene.meta.packed_strings, strip->subtitle.pstr_en );
+ }
+
+ if( strip->mode == k_ms_strip_mode_event )
+ {
+ const char *str = af_str( _cutscene.meta.packed_strings, strip->event.pstr_string );
+ vg_info( "cutscene event: %s\n", str );
+ _world_raise_event( _cutscene.raiser_entity, str );
+ }
+ }
+
+ _cutscene.strip ++;
+ }
+
+ /* sample da samplers */
+ for( u32 i=0; i<_cutscene.active_samplers && (_cutscene.skipped != 2); i ++ )
+ {
+ struct cs_sampler *samp = &_cutscene.samplers[ i ];
+
+ if( samp->strip->mode == k_ms_strip_mode_keyframes )
+ {
+ ms_skeletal_animation temp_anim =
+ {
+ .strip = samp->strip,
+ .framerate = _cutscene.meta.info.framerate,
+ .keyframes_base = af_arritm( &_cutscene.meta.keyframes, samp->strip->strip.start )
+ };
+
+ f32 t = _cutscene.time;
+ t -= (f32)samp->strip->offset / _cutscene.meta.info.framerate;
+
+ ms_skeleton *ref_sk = samp->skeleton.ref_sk;
+ m4x3f *final_mtx = samp->skeleton.skinning_data;
+
+ ms_keyframe pose[32];
+ skeleton_sample_anim_clamped( ref_sk, &temp_anim, t, pose );
+
+ skeleton_apply_pose( ref_sk, pose, k_anim_apply_defer_ik, final_mtx );
+ skeleton_apply_ik_pass( ref_sk, final_mtx );
+ skeleton_apply_pose( ref_sk, pose, k_anim_apply_deffered_only, final_mtx );
+ skeleton_apply_inverses( ref_sk, final_mtx );
+
+ if( samp->override )
+ {
+ m4x3f mmdl;
+ mdl_transform_m4x3( &samp->override->transform, mmdl );
+ skeleton_apply_transform( ref_sk, mmdl, final_mtx );
+ }
+
+ skeleton_debug( ref_sk, final_mtx );
+ }
+ else
+ {
+ f32 scene_t = _cutscene.time * _cutscene.meta.info.framerate,
+ t = (f32)(scene_t - samp->strip->offset) + samp->strip->strip.timing_offset;
+
+ ms_curve_keyframe *kl = af_arritm( &_cutscene.meta.curves,
+ samp->curves.track->keyframe_start + samp->curves.keyframe ),
+ *kr = NULL;
+
+ if( t > kl->co[0] )
+ {
+ if( samp->curves.track->keyframe_count > 1 )
+ {
+ for( u32 j=samp->curves.keyframe+1; j<samp->curves.track->keyframe_count; j ++ )
+ {
+ kr = af_arritm( &_cutscene.meta.curves, samp->curves.track->keyframe_start + j );
+ if( kr->co[0] <= t )
+ {
+ kl = kr;
+ kr = NULL;
+ samp->curves.keyframe = j;
+ }
+ else break;
+ }
+ }
+ }
+
+ if( kl && kr )
+ *samp->curves.target = explicit_bezier( kl->co, kl->r, kr->l, kr->co, t );
+ else
+ *samp->curves.target = kl->co[1];
+
+ if( samp->curves.semantic == CS_FOV )
+ {
+ f32 mm = *samp->curves.target,
+ fov = 2.0f * 57.2957795f * atanf( (36.0f*0.5f) / mm );
+ *samp->curves.target = fov;
+ }
+ }
+ }
+
+ for( u32 i=0; i<af_arrcount( &_cutscene.meta.cameras ); i ++ )
+ {
+ ent_camera *cam = af_arritm( &_cutscene.meta.cameras, i );
+ vg_line_cross( cam->co, VG__RED, 0.2f );
+ }
+
+ f32 scene_t = _cutscene.time * _cutscene.meta.info.framerate,
+ end_t = _cutscene.meta.info.end_frame;
+
+ if( scene_t >= end_t )
+ {
+ if( _cutscene.strip != af_arrcount(&_cutscene.meta.strips) )
+ {
+ _cutscene.time = 9999999.9f;
+ _cutscene.skipped = 2; /* signal we can ignore animation strips, just want events for correctness */
+ return;
+ }
+ _world_raise_event( _cutscene.raiser_entity, "end" );
+
+ if( _cutscene.freeze_player )
+ localplayer.immobile = 0;
+
+ _cutscene_unload();
+ }
+}
+
+void _cutscene_render_fadeout(void)
+{
+ bool render = 0;
+ f32 render_alpha = 0.0f;
+
+ if( _cutscene.state >= k_cutscene_state_ready )
+ {
+ if( _cutscene.fadeout )
+ {
+ f32 l = ((f32)_cutscene.meta.info.end_frame/(f32)_cutscene.meta.info.framerate) - _cutscene.fadeout_start,
+ t = (_cutscene.time - _cutscene.fadeout_start) / l;
+ render = 1;
+ render_alpha = t;
+ _cutscene.fadeout_cooldown = 1.0f;
+ }
+ }
+ else
+ {
+ if( _cutscene.fadeout_cooldown > 0.0f )
+ {
+ render = 1;
+ render_alpha = _cutscene.fadeout_cooldown;
+ _cutscene.fadeout_cooldown -= vg.time_delta;
+ }
+ }
+
+ if( render )
+ {
+ glEnable(GL_BLEND);
+ glDisable(GL_DEPTH_TEST);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendEquation(GL_FUNC_ADD);
+
+ shader_blitcolour_use();
+ shader_blitcolour_uColour( (v4f){ 0.04f, 0.02f, 0.03f, vg_clampf( render_alpha, 0.0f, 1.0f ) } );
+ render_fsquad();
+ }
+}
+
+void _cutscene_render( vg_camera *cam )
+{
+ if( _cutscene.state >= k_cutscene_state_ready )
+ {
+ for( u32 i=0; i<_cutscene.instance_count; i ++ )
+ cutscene_render_instance( &_cutscene.instances[i], cam );
+ }
+}
+
+void _cutscene_gui( ui_context *ctx )
+{
+ if( _cutscene.subtitle )
+ {
+ ctx->font = &vgf_default_small;
+ ctx->kern[1] = 16;
+ ui_px scale = 2;
+ ui_rect box = { 0,0, 1000, 80*2 };
+ ui_rect_center( (ui_rect){0,0,_vg_window.w,_vg_window.h}, box );
+ box[1] = _vg_window.h - (box[3] + 8);
+
+ i32 lines = 1;
+
+ const char *_c = _cutscene.subtitle;
+ u8 c;
+
+ i32 length = 0;
+ ui_px y = box[1];
+
+ while(1)
+ {
+ c = *(_c ++);
+
+ /* TODO: This is pasted straight from vg_ui, maybe create a vg_ui_text_iter() ...? */
+ if( c == '\x1B' )
+ {
+ while( (c = *(_c ++)) )
+ {
+ if( c == 'm' )
+ break;
+ }
+
+ if( c == 0 )
+ break;
+ else
+ continue;
+ }
+
+ if( c >= 32 )
+ length ++;
+ else if( c == '\n' || c == '\0' )
+ {
+ ui_px w = length * ctx->font->sx*scale + 16;
+ ui_rect background_rect = { _vg_window.w/2 - w/2, y-8, w, ctx->font->sy*scale+16 };
+
+ ui_fill( ctx, background_rect, ui_opacity( GUI_COL_DARK, 0.75f ) );
+ y += (ctx->font->sy)*scale + 16;
+ length = 0;
+ lines ++;
+ }
+
+ if( c == '\0' )
+ break;
+ }
+
+ ui_text( ctx, box, _cutscene.subtitle, scale, k_ui_align_center, 0 );
+ ctx->font = &vgf_default_small;
+ ctx->kern[1] = 0;
+ }
+}
+
+/* cutscene magi
+ * ----------------------------------------------------------------------------
+ */
+
+static void cb_cutscene_view( ui_context *ctx, ui_rect rect, struct vg_magi_panel *magi )
+{
+ if( _cutscene.state == k_cutscene_state_none )
+ {
+ ui_text( ctx, rect, "No cutscene loaded.", 1, k_ui_align_middle_center, 0 );
+ return;
+ }
+
+ if( _cutscene.state == k_cutscene_state_loading )
+ {
+ ui_text( ctx, rect, "Cutscene loading..", 1, k_ui_align_middle_center, 0 );
+ return;
+ }
+
+ if( _cutscene.state == k_cutscene_state_unloading )
+ {
+ ui_text( ctx, rect, "Cutscene UN-loading..", 1, k_ui_align_middle_center, 0 );
+ return;
+ }
+
+ ms_strip *usage[8];
+ for( u32 i=0; i<VG_ARRAY_LEN(usage); i ++ ) usage[i] = NULL;
+
+ ui_rect panel_l, panel_r;
+ ui_split( rect, k_ui_axis_v, 400, 4, panel_l, panel_r );
+
+ if( ui_clip( rect, panel_l, panel_l ) )
+ {
+ ui_px root[2] = { panel_l[0]+8, panel_l[1]+8 };
+ ui_rect box = { root[0], root[1], panel_l[2]-16, 16 };
+
+ for( u32 i=0; i<_cutscene.unique_refs; i ++ )
+ {
+ struct model_ref *mref = &_cutscene.refs[i];
+
+ char inf[128];
+ snprintf( inf, sizeof(inf), "%s (%u references)", mref->name, mref->reference_count );
+ ui_text( ctx, box, inf, 1, k_ui_align_middle_left, 0 );
+ box[1] += 16;
+ }
+ }
+
+ if( ui_clip( rect, panel_r, panel_r ) )
+ {
+ ui_px root[2] = { panel_r[0]+8, panel_r[1]+8 };
+
+ for( u32 i=0; i<af_arrcount(&_cutscene.meta.strips); i ++ )
+ {
+ ms_strip *strip = af_arritm(&_cutscene.meta.strips, i );
+
+ if( !(strip->mode & k_ms_strip_mode_animation) )
+ {
+ ui_rect box = { root[0]+strip->offset, root[1], 1, panel_r[3]-16 };
+ ui_fill( ctx, box, 0xff00ff00 );
+
+ box[1] += box[3] -16;
+ box[2] = 200;
+ box[3] = 16;
+
+ if( ui_clip( panel_r, box, box ) )
+ {
+ if( strip->mode == k_ms_strip_mode_camera )
+ ui_text( ctx, box, "Camera", 1, k_ui_align_middle_left, 0 );
+ if( strip->mode == k_ms_strip_mode_subtitle )
+ ui_text( ctx, box, "\"", 1, k_ui_align_middle_left, 0 );
+ if( strip->mode == k_ms_strip_mode_fadeout )
+ ui_text( ctx, box, "\\", 1, k_ui_align_middle_left, 0 );
+ }
+ continue;
+ }
+
+ u32 layer = 0;
+ for( u32 k=0; k<VG_ARRAY_LEN(usage); k ++ )
+ {
+ if( usage[k] )
+ if( usage[k]->offset + (i32)usage[k]->strip.length < strip->offset )
+ usage[k] = NULL;
+
+ if( !usage[k] )
+ {
+ usage[k] = strip;
+ layer = k;
+ break;
+ }
+ }
+
+ ui_rect box = { strip->offset, layer*32, (i32)strip->strip.length, 30 };
+ box[0] += root[0];
+ box[1] += root[1];
+
+ if( ui_clip( panel_r, box, box ) )
+ {
+ u32 colour = af_str_hash( _cutscene.meta.packed_strings, strip->strip.pstr_name );
+ ui_fill( ctx, box, colour | 0xff000000 );
+ ui_text( ctx, box, af_str( _cutscene.meta.packed_strings, strip->strip.pstr_name ),
+ 1, k_ui_align_middle_center, 0 );
+ }
+ }
+
+ ui_rect cursor = { (f32)_cutscene.time*_cutscene.meta.info.framerate, 0, 1, VG_ARRAY_LEN(usage)*32 };
+ cursor[0] += root[0];
+ cursor[1] += root[1];
+ if( ui_clip( panel_r, cursor, cursor ) )
+ ui_fill( ctx, cursor, 0xffffffff );
+ }
+}
+
+static int cmd_cutscene_play( int argc, const char *argv[] )
+{
+ if( argc == 1 )
+ _cutscene_load_and_play( argv[0], 0, 0 );
+ return 1;
+}
+
+static int cmd_cutscene_inspector( int argc, const char *argv[] )
+{
+ ui_px w = 800, h = 400;
+ struct vg_magi_panel *magi = _vg_magi_open( w, h, VG_MAGI_ALL );
+ magi->title = "Cutscene Inpsector";
+ magi->data = NULL;
+ magi->ui_cb = cb_cutscene_view;
+ magi->close_cb = NULL;
+ return 1;
+}
+
+VG_API void _cutscene_register(void)
+{
+ vg_console_reg_cmd( "cutscene_play", cmd_cutscene_play, NULL );
+ vg_console_reg_cmd( "cutscene_inspector", cmd_cutscene_inspector, NULL );
+}
--- /dev/null
+#if defined( SR_IMPLEMENTATION )
+# include "src/cutscene.c"
+#else
+
+struct cs_instance
+{
+ bool disable_render;
+ u32 ref_id;
+ m4x3f *skinning_data;
+};
+
+struct cs_subtitle
+{
+ const char *key, *value;
+};
+
+struct _cutscene
+{
+ metascene meta;
+ vg_stack_allocator stack;
+
+ enum cutscene_state
+ {
+ k_cutscene_state_none,
+ k_cutscene_state_loading,
+ k_cutscene_state_unloading,
+ k_cutscene_state_ready,
+ k_cutscene_state_playing,
+ k_cutscene_state_done,
+ }
+ state;
+
+ struct model_ref
+ {
+ const char *name;
+ u32 name_hash;
+ u32 reference_count;
+
+ vg_model model;
+ struct cs_skeleton
+ {
+ ms_skeleton sk;
+ u32 skinning_offset;
+ }
+ *skeletons;
+ u32 total_skinning_bones;
+ }
+ * refs;
+ u32 unique_refs;
+
+ struct cs_instance *instances;
+ u32 instance_count;
+
+ struct cs_sampler
+ {
+ ms_strip *strip;
+ ms_override *override;
+ union
+ {
+ struct
+ {
+ ms_track *track;
+ f32 *target;
+ u32 keyframe;
+ u32 semantic;
+ }
+ curves;
+
+ struct
+ {
+ ms_skeleton *ref_sk;
+ m4x3f *skinning_data;
+ }
+ skeleton;
+ };
+ }
+ samplers[32];
+ u32 active_samplers;
+
+ ent_camera *active_camera;
+ struct cs_instance *player_binding;
+
+ u32 strip;
+ f32 time;
+
+ bool fadeout;
+ u8 skipped;
+ f32 fadeout_start, fadeout_cooldown;
+
+ const char *marker_this_frame;
+ const char *subtitle;
+ bool subtitle_length_warning;
+
+ bool freeze_player;
+
+ u32 raiser_entity;
+}
+extern _cutscene;
+
+VG_API void _cutscene_register(void);
+void _cutscene_render( vg_camera *cam );
+void _cutscene_render_fadeout(void);
+bool _cutscene_load_and_play( const char *path, bool freeze_player, u32 raiser_entity );
+void _cutscene_unload(void);
+void cutscene_update( f32 delta );
+ent_camera *_cutscene_active_camera(void);
+void _cutscene_gui( ui_context *ctx );
+
+struct cs_instance *_cutscene_get_first_model_instance( const c8 *mdl_name );
+
+#endif
--- /dev/null
+struct _demo_check _demo_check;
+
+static void demo_check_not_demo( void *_, vg_async_info *async )
+{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ _demo_check.mode = 0;
+ _steam_api.demo_mode = 0;
+}
+
+static void demo_check_task( void *_, vg_async_info *async )
+{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+
+ c8 drm[ 32 ];
+ vg_stream drm_file;
+ if( vg_file_stream_open( &drm_file, "DRM", VG_STREAM_READ ) )
+ {
+ vg_stream_read( &drm_file, drm, sizeof(drm) );
+ vg_file_stream_close( &drm_file );
+ if( !strncmp( drm, "blibby!", sizeof(drm) ) )
+ _vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)demo_check_not_demo );
+ }
+}
+
+VG_API void _demo_check_init(void)
+{
+ if( _demo_check.mode == 0 )
+ {
+ _demo_check.mode = 1;
+ _steam_api.demo_mode = 1;
+ _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)demo_check_task );
+ }
+}
+
+VG_API void _demo_check_opts(void)
+{
+ if( vg_long_opt( "demo", "Turn demo mode on" ) )
+ {
+ _demo_check.mode = 2;
+ _steam_api.demo_mode = 1;
+ }
+}
+
+VG_API bool _is_running_demo(void)
+{
+ return _demo_check.mode > 0;
+}
--- /dev/null
+#if defined( SR_IMPLEMENTATION )
+# include "src/demo_check.c"
+#else
+
+struct _demo_check
+{
+ i32 mode;
+}
+extern _demo_check;
+
+VG_API void _demo_check_opts(void);
+VG_API void _demo_check_init(void);
+VG_API bool _is_running_demo(void);
+
+#endif
-#pragma once
-#include "vg/vg_m.h"
-#include "vg/vg_framebuffer.h"
-#include "vg/vg_render.h"
-#include "skaterift.h"
-#include "render.h"
+#if defined( SR_IMPLEMENTATION )
+//# include "src/depth_compare.c"
+#else
static inline void depth_compare_bind(
void (*uTexSceneDepth)(int),
inverse[2] = cam->farz-cam->nearz;
uInverseRatioMain( inverse );
}
+
+#endif
-#include "ent_atom.h"
-
struct _atom
{
struct atom_list
if( atom->flags & k_ent_atom_scrap )
return "<anonymous>";
else
- return af_str( &world->meta.af, atom->pstr_alias );
+ return af_str( world->meta.packed_strings, atom->pstr_alias );
}
i32 _ent_atom_get( u32 atom_entity_id )
return atom->scrap_value;
else
{
- const char *alias = af_str( &world->meta.af, atom->pstr_alias );
+ const char *alias = af_str( world->meta.packed_strings, atom->pstr_alias );
return _atom_get( (atom->flags & k_ent_atom_global)? k_atom_list_global: k_atom_list_world, alias );
}
}
else
{
enum e_atom_list list = (atom->flags & k_ent_atom_global)? k_atom_list_global: k_atom_list_world;
- const char *alias = af_str( &world->meta.af, atom->pstr_alias );
+ const char *alias = af_str( world->meta.packed_strings, atom->pstr_alias );
_atom_set( list, alias, value );
_atom_notify( list, alias );
}
world_instance *world = &_world.main;
bool pass = 0, fail = 0;
- if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "pass_equal" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "pass_equal" ) )
{
if( event->flags & k_ent_event_data_const_i32 )
{
}
else return k_entity_event_result_invalid;
}
- else if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "pass_greater" ) )
+ else if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "pass_greater" ) )
{
if( event->flags & k_ent_event_data_const_i32 )
{
}
else return k_entity_event_result_invalid;
}
- else if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "set" ) )
+ else if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "set" ) )
{
if( event->flags & k_ent_event_data_const_i32 )
{
}
else return k_entity_event_result_invalid;
}
- else if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "set_or" ) )
+ else if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "set_or" ) )
{
if( event->flags & k_ent_event_data_const_i32 )
{
}
else return k_entity_event_result_invalid;
}
- else if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "set_and" ) )
+ else if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "set_and" ) )
{
if( event->flags & k_ent_event_data_const_i32 )
{
return k_entity_event_result_OK;
}
-void serialize_atoms( enum e_atom_list list, vg_msg *msg )
+void serialize_atoms( enum e_atom_list list, vg_kvs *savedata, u32 root )
{
+ // FIXME
+#if 0
for( u32 i=0; i<_atom.lists[list].count; i ++ )
{
atom *a = &_atom.lists[list].atoms[i];
- vg_msg_wkvnum( msg, a->alias, k_vg_msg_i32, 1, &a->status );
+ vg_kv_append_vu32( savedata, root, a->alias, &a->status, 1 );
}
+#endif
}
static atom *_atom_internal( enum e_atom_list list, const char *alias )
if( atom->flags & k_ent_atom_scrap )
continue;
- if( af_str_eq( &world->meta.af, atom->pstr_alias, alias, vg_strdjb2(alias)) )
+ if( af_str_eq( world->meta.packed_strings, atom->pstr_alias, alias, vg_strdjb2(alias)) )
{
_world_raise_event( mdl_entity_id( k_ent_atom, i ), "changed" );
_world_raise_event( mdl_entity_id( k_ent_atom, i ), value? "true": "false" );
void _ent_atom_init(void)
{
- THREAD_0;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
if( _steam_api.disabled )
return;
-#pragma once
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_atom.c"
+#else
enum e_atom_list
{
i32 status;
};
-void serialize_atoms( enum e_atom_list list, vg_msg *msg );
+void serialize_atoms( enum e_atom_list list, vg_kvs *savedata, u32 root );
void _atom_list_clear( enum e_atom_list list );
i32 _atom_get( enum e_atom_list list, const char *alias );
entity_event_result _ent_atom_event( ent_event *event );
void _ent_atom_register(void);
void _ent_atom_init(void);
+
+#endif
-#include "entity.h"
-
void ent_camera_unpack( ent_camera *ent, vg_camera *cam )
{
v3_copy( ent->co, cam->pos ); /* wow */
-#include "entity.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_camera.c"
+#else
void ent_camera_unpack( ent_camera *ent, vg_camera *cam );
+
+#endif
-#include "vg/vg_engine.h"
-#include "entity.h"
-#include "input.h"
-#include "gui.h"
-#include "audio.h"
-#include "ent_region.h"
-
void _ent_challenge_clear( ent_challenge *challenge )
{
world_instance *world = &_world.main;
if( !challenge->status )
{
- gui_notify( "\xb3 Challenge complete!", 5.0f, k_ui_fg );
+ _gui_notify( "\xb3 Challenge complete!", 5.0f, k_ui_fg );
}
_ent_challenge_clear( challenge );
{
world_instance *world = &_world.main;
ent_challenge *challenge = af_arritm( &world->ent_challenge, mdl_entity_id_id( event->recieve_entity_id ) );
- if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "view" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "view" ) )
{
if( world_set_event( k_world_event_challenge ) )
{
srinput.state = k_input_state_resume;
- gui_helper_reset( k_gui_helper_mode_clear );
+ _gui_helper_reset( k_gui_helper_mode_clear );
vg_str text;
- if( gui_new_helper( input_button_list[k_srbind_maccept], &text ))
+ if( _gui_new_helper( input_button_list[k_srbind_maccept], &text ))
vg_strcat( &text, "Start" );
- if( gui_new_helper( input_button_list[k_srbind_mback], &text ))
+ if( _gui_new_helper( input_button_list[k_srbind_mback], &text ))
vg_strcat( &text, "Exit" );
localplayer.immobile = 1;
_world_raise_event( _world.active_challenge_id, "activate" );
}
-void ent_challenge_update(void)
+void _ent_challenge_update(void)
{
world_instance *world = &_world.main;
if( button_down( k_srbind_maccept ) )
{
menu_close();
- gui_helper_reset( k_gui_helper_mode_clear );
+ _gui_helper_reset( k_gui_helper_mode_clear );
_world.challenge_state = k_challenge_state_running;
localplayer.immobile = 0; /* TODO: Unify this probably after eating some potats */
menu.disable_open = 0;
_world.active_challenge_id = 0;
_world.challenge_target = NULL;
_world.challenge_timer = 0.0f;
- gui_helper_reset( k_gui_helper_mode_clear );
+ _gui_helper_reset( k_gui_helper_mode_clear );
_world.challenge_state = k_challenge_state_none;
localplayer.immobile = 0; /* TODO: Unify this probably after eating some potats */
menu.disable_open = 0;
vg_audio_oneshot_3d( &audio_challenge[6], localplayer.rb.co, 30.0f, 1.0f, 0, 0 );
vg_audio_unlock();
vg_info( "Challenge expired due to player being out of range.\n" );
- gui_helper_reset( k_gui_helper_mode_clear );
+ _gui_helper_reset( k_gui_helper_mode_clear );
}
}
}
srinput.state = k_input_state_resume;
_restart_active_challenge();
_world.challenge_reset_timer = 0.0f;
- gui_helper_reset( k_gui_helper_mode_clear );
+ _gui_helper_reset( k_gui_helper_mode_clear );
}
}
else
ent_challenge *challenge = af_arritm( &world->ent_challenge, challenge_index );
ui_px w = 340;
- ui_rect description_box = { vg.window_x - (w + 8), 8, w, 32 };
+ ui_rect description_box = { _vg_window.w - (w + 8), 8, w, 32 };
ctx->font = &vgf_default_large;
if( !(_world.challenge_state >= k_challenge_state_running) )
ui_fill( ctx, description_box, ui_opacity( GUI_COL_DARK, 0.36f ) );
ui_outline( ctx, description_box, 1, colour, 0 );
- const char *description = af_str( &world->meta.af, objective->pstr_description_ui );
+ const char *description = af_str( world->meta.packed_strings, objective->pstr_description_ui );
ui_text( ctx, description_box, description, 1, k_ui_align_middle_center, colour );
description_box[1] += description_box[3] + 4;
if( _world.challenge_reset_timer > 0.0f )
{
- ui_rect box = { vg.window_x/2 - 200, vg.window_y - 200, 400, 100 };
+ ui_rect box = { _vg_window.w/2 - 200, _vg_window.h - 200, 400, 100 };
ui_fill( ctx, box, ui_opacity( GUI_COL_DARK, 0.35f ) );
ui_outline( ctx, box, 1, GUI_COL_NORM, 0 );
for( u32 i=0; i<af_arrcount( &world->ent_challenge ); i ++ )
{
ent_challenge *challenge = af_arritm( &world->ent_challenge, i );
- const char *alias = af_str( &world->meta.af, challenge->pstr_alias );
+ const char *alias = af_str( world->meta.packed_strings, challenge->pstr_alias );
if( all || (atoi( argv[0] ) == index) )
{
for( u32 i=0; i<af_arrcount( &world->ent_route ); i ++ )
{
ent_route *route = af_arritm( &world->ent_route, i );
- const char *alias = af_str( &world->meta.af, route->pstr_name );
+ const c8 *alias = af_str( world->meta.packed_strings, route->pstr_name );
if( all || (atoi( argv[0] ) == index) )
{
-#pragma once
-#include "entity.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_challenge.c"
+#else
entity_event_result ent_challenge_event( ent_event *event );
void _ent_challenge_ui( ui_context *ctx );
void _restart_active_challenge(void);
void _ent_challenge_complete( ent_challenge *challenge );
void _ent_challenge_win(void);
+void _ent_challenge_clear( ent_challenge *challenge );
void _ent_challenge_register(void);
+void _ent_challenge_update(void);
+
+#endif
-#include "ent_cutscene.h"
-
entity_event_result _ent_cutscene_event( ent_event *event )
{
world_instance *world = &_world.main;
ent_cutscene *cs = af_arritm( &world->ent_cutscene, mdl_entity_id_id( event->recieve_entity_id ) );
- if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "play" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "play" ) )
{
- const char *path = af_str( &world->meta.af, cs->pstr_path );
+ const char *path = af_str( world->meta.packed_strings, cs->pstr_path );
_cutscene_load_and_play( path, (cs->flags & k_ent_cutscene_freeze_player), event->recieve_entity_id );
return k_entity_event_result_OK;
-#pragma once
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_cutscene.c"
+#else
entity_event_result _ent_cutscene_event( ent_event *event );
+
+#endif
-#pragma once
-#include "entity.h"
-#include "player_glide.h"
-
entity_event_result ent_glider_event( ent_event *event )
{
world_instance *world = &_world.main;
ent_glider *glider = af_arritm( &world->ent_glider, mdl_entity_id_id( event->recieve_entity_id ) );
- if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "lock" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "lock" ) )
{
// TODO: Make this dynamiclly fetched from a handler for the entity itself. (or not, fuck you)
if( event->flags == k_ent_event_data_const_i32 )
else
return k_entity_event_result_invalid;
}
- else if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "equip" ) )
+ else if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "equip" ) )
{
if( !(glider->flags & k_ent_glider_flag_locked) )
player_glide_equip_glider();
-#pragma once
-#include "entity.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_glider.c"
+#else
entity_event_result ent_glider_call( ent_event *event );
+entity_event_result ent_glider_event( ent_event *event );
+
+#endif
-#include "ent_list.h"
-
ent_list *_ent_list_get_aliased( const char *alias )
{
world_instance *world = &_world.main;
{
ent_list *list = af_arritm( &world->ent_list, i );
if( list->alias_type == k_list_alias_string )
- if( af_str_eq( &world->meta.af, list->pstr_alias, alias, hash ) )
+ if( af_str_eq( world->meta.packed_strings, list->pstr_alias, alias, hash ) )
return list;
}
return NULL;
world_instance *world = &_world.main;
ent_list *list = af_arritm( &world->ent_list, mdl_entity_id_id( event->recieve_entity_id ) );
- if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "visible" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "visible" ) )
{
// TODO: Make this dynamiclly fetched from a handler for the entity itself. (or not, fuck you)
if( event->flags == k_ent_event_data_const_i32 )
-#pragma once
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_list.c"
+#else
struct ent_list_iter
{
entity_event_result _ent_list_world_event( ent_event *event );
bool _ent_list_check_completed( ent_list *list );
void _ent_list_set_as_targets( ent_list *list, bool yes );
+
+#endif
-#include "ent_npc.h"
-
struct
{
struct
}
state;
- mdl_context mdl;
+ vg_model mdl;
i32 sm_main, sm_hat, sm_glow;
v3f co, p0, p1;
f64 command_t;
}
humans[4];
- struct skeleton_anim anim_idle, anim_stand, anim_sit;
+ ms_skeletal_animation anim_idle, anim_stand, anim_sit;
enum npc_sub_state
{
},
};
-void _ent_npc_init(void)
+static void _ent_npc_load_content( void *_, vg_async_info *async )
+{
+ vg_model_load( &_npc.gino.mdl, VG_MODEL_ENGINE_STANDARD, "models/gino.mdl", VG_STACK_USE_HEAP );
+ _npc.gino.sm_main = vg_model_get_submesh_index( &_npc.gino.mdl, "gino" );
+ _npc.gino.sm_hat = vg_model_get_submesh_index( &_npc.gino.mdl, "gino.hat" );
+ _npc.gino.sm_glow = vg_model_get_submesh_index( &_npc.gino.mdl, "gino.spt" );
+
+ ms_skeleton *sk = &localplayer.skeleton;
+ u32 mtx_size = sizeof(m4x3f)*sk->bone_count;
+ for( u32 i=0; i<4; i ++ )
+ {
+ struct human_npc *human = &_npc.humans[i];
+ human->final_mtx = vg_stack_allocate( VG_STACK_USE_HEAP, mtx_size, 8, "Final MTX" );
+ }
+ player_get_anim( &_npc.anim_idle, "idle_lean+y" );
+ player_get_anim( &_npc.anim_stand, "idle_cycle+y" );
+ player_get_anim( &_npc.anim_sit, "sit" );
+}
+
+VG_API void _ent_npc_init(void)
{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_ent_npc_load_content );
+
for( u32 i=0; i<k_npc_max; i ++ )
{
struct sub_context *contexts = _sub_contexts[ i ];
struct sub_context *context = &contexts[i];
if( context->alias == NULL )
break;
-
context->alias_hash = vg_strdjb2( context->alias );
}
}
-
- mdl_context *mdl = &_npc.gino.mdl;
- mdl_open( mdl, "models/gino.mdl", &vg.rtmem );
- mdl_load_metadata_block( mdl, &vg.rtmem );
- mdl_async_full_load_std( mdl, NULL );
- _npc.gino.sm_main = mdl_get_submesh_index( mdl, "gino" );
- _npc.gino.sm_hat = mdl_get_submesh_index( mdl, "gino.hat" );
- _npc.gino.sm_glow = mdl_get_submesh_index( mdl, "gino.spt" );
- mdl_close( mdl );
-
- struct skeleton *sk = &localplayer.skeleton;
- u32 mtx_size = sizeof(m4x3f)*sk->bone_count;
- for( u32 i=0; i<4; i ++ )
- {
- struct human_npc *human = &_npc.humans[i];
- human->final_mtx = vg_stack_allocate( &vg.rtmem, mtx_size, 8, "Final MTX" );
- }
- player_get_anim( &_npc.anim_idle, "idle_lean+y" );
- player_get_anim( &_npc.anim_stand, "idle_cycle+y" );
- player_get_anim( &_npc.anim_sit, "sit" );
}
void _ent_npc_reset(void)
_npc.sub_state = k_npc_sub_reading;
_cutscene.subtitle = sub->value;
- gui_helper_reset( k_gui_helper_mode_black_bars );
+ _gui_helper_reset( k_gui_helper_mode_black_bars );
vg_str text;
- if( gui_new_helper( input_button_list[k_srbind_maccept], &text ))
+ if( _gui_new_helper( input_button_list[k_srbind_maccept], &text ))
vg_strcat( &text, "Next" );
v3_copy( localplayer.rb.co, _npc.sub_position );
}
_npc.sub_state = k_npc_sub_off;
_npc.subtitles = NULL;
_cutscene.subtitle = NULL;
- gui_helper_reset( k_gui_helper_mode_clear );
+ _gui_helper_reset( k_gui_helper_mode_clear );
}
}
{
_npc.sub_state = k_npc_sub_off;
_cutscene.subtitle = NULL;
- gui_helper_reset( k_gui_helper_mode_clear );
+ _gui_helper_reset( k_gui_helper_mode_clear );
}
}
if( human->alive && (v3_dist2( localplayer.rb.co, human->co ) < 40.0f*40.0f) )
{
ms_keyframe apose[32], bpose[32];
- struct skeleton *sk = &localplayer.skeleton;
+ ms_skeleton *sk = &localplayer.skeleton;
player_pose *pose = &human->pose;
pose->type = k_player_pose_type_ik;
pose->board.lean = 0.0f;
if( !((_cutscene.state == k_cutscene_state_playing) && human->in_cutscene) )
{
m4x3f *final_mtx = human->final_mtx;
- struct skeleton *sk = &localplayer.skeleton;
+ ms_skeleton *sk = &localplayer.skeleton;
render_playermodel( cam, world, 0, &human->playermodel, sk, final_mtx );
}
}
shader_model_entity_uTexMain( 0 );
shader_model_entity_uCamera( cam->transform[3] );
shader_model_entity_uPv( cam->mtx.pv );
- WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, model_entity );
+ WORLD_LINK_LIGHTING( world, model_entity );
- mesh_bind( &_npc.gino.mdl.mesh );
- glActiveTexture( GL_TEXTURE0 );
+ vg_model_bind_mesh( &_npc.gino.mdl );
glDepthMask(GL_FALSE);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
glBlendEquation(GL_FUNC_ADD);
- glBindTexture( GL_TEXTURE_2D, _npc.gino.mdl.textures[1].glname );
+ vg_tex_bind( GL_TEXTURE_2D, &_npc.gino.mdl.textures[1].tex, 0 );
m4x3f mmdl;
m3x3_copy( cam->transform, mmdl );
v3_copy( _npc.gino.co, mmdl[3] );
shader_model_entity_uMdl( mmdl );
glDrawBuffers( 1, (GLenum[]){ GL_COLOR_ATTACHMENT0 } );
- mdl_draw_submesh( &_npc.gino.mdl.submeshes[ _npc.gino.sm_glow ] );
+ vg_model_draw_submesh( &_npc.gino.mdl.submeshes[ _npc.gino.sm_glow ] );
glDrawBuffers( 2, (GLenum[]){ GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 } );
glDepthMask(GL_TRUE);
glDisable(GL_BLEND);
- glBindTexture( GL_TEXTURE_2D, _npc.gino.mdl.textures[0].glname );
+ vg_tex_bind( GL_TEXTURE_2D, &_npc.gino.mdl.textures[0].tex, 0 );
v3f v0 = { localplayer.rb.co[0] - _npc.gino.co[0], 0.0f, localplayer.rb.co[2] - _npc.gino.co[2] };
v3_normalize( v0 );
m4x4_mul( cam->mtx_prev.pv, m4mmdl, m4mmdl );
shader_model_entity_uMdl( mmdl );
shader_model_entity_uPvmPrev( m4mmdl );
- mdl_draw_submesh( &_npc.gino.mdl.submeshes[ _npc.gino.sm_main ] );
+ vg_model_draw_submesh( &_npc.gino.mdl.submeshes[ _npc.gino.sm_main ] );
m3x3f mspin;
v4f qspin;
m4x4_mul( cam->mtx_prev.pv, m4mmdl, m4mmdl );
shader_model_entity_uMdl( mmdl );
shader_model_entity_uPvmPrev( m4mmdl );
- mdl_draw_submesh( &_npc.gino.mdl.submeshes[ _npc.gino.sm_hat ] );
+ vg_model_draw_submesh( &_npc.gino.mdl.submeshes[ _npc.gino.sm_hat ] );
}
entity_event_result ent_npc_event( ent_event *event )
{
if( npc_aliases[i] )
{
- if( AF_STR_EQ( &world->meta.af, npc->pstr_id, npc_aliases[i] ) )
+ if( AF_STR_EQ( world->meta.packed_strings, npc->pstr_id, npc_aliases[i] ) )
{
npc_id = i;
break;
if( npc_id == k_npc_none )
{
- vg_warn( "No npc with alias: %s\n", af_str( &world->meta.af, npc->pstr_id ) );
+ vg_warn( "No npc with alias: %s\n", af_str( world->meta.packed_strings, npc->pstr_id ) );
return k_entity_event_result_invalid;
}
if( npc_id == k_npc_gino )
{
- if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "interact" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "interact" ) )
{
vg_audio_lock();
vg_audio_oneshot( &audio_ui[1], 1.0f, 0.0f, 0, 0 );
vg_audio_unlock();
- _ent_npc_speech( npc_id, af_str( &world->meta.af, npc->pstr_context_id ) );
+ _ent_npc_speech( npc_id, af_str( world->meta.packed_strings, npc->pstr_context_id ) );
return k_entity_event_result_OK;
}
- else if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "proximity" ) )
+ else if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "proximity" ) )
{
if( _npc.gino.current_entity_id != event->source_entity_id )
{
struct human_npc *human = human_npc( npc_id );
VG_ASSERT( human );
- if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "interact" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "interact" ) )
{
vg_audio_lock();
vg_audio_oneshot( &audio_ui[1], 1.0f, 0.0f, 0, 0 );
vg_audio_unlock();
- _ent_npc_speech( npc_id, af_str( &world->meta.af, npc->pstr_context_id ) );
+ _ent_npc_speech( npc_id, af_str( world->meta.packed_strings, npc->pstr_context_id ) );
return k_entity_event_result_OK;
}
- else if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "proximity" ) )
+ else if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "proximity" ) )
{
human->anim = 0;
- if( AF_STR_EQ( &world->meta.af, npc->pstr_anim, "sit" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, npc->pstr_anim, "sit" ) )
human->anim = k_npc_sit;
- else if( AF_STR_EQ( &world->meta.af, npc->pstr_anim, "stand" ) )
+ else if( AF_STR_EQ( world->meta.packed_strings, npc->pstr_anim, "stand" ) )
human->anim = k_npc_stand;
if( human->alive == 0 )
-#pragma once
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_npc.c"
+#else
#define KCOL_JOHN KNRM
#define KCOL_MIKE KBLU
k_npc_max
};
-void _ent_npc_init(void);
+VG_API void _ent_npc_init(void);
+
void _ent_npc_render( vg_camera *cam );
void _ent_npc_goto( v3f pos, i32 uid );
void _ent_npc_preupdate(void);
void _ent_npc_reset(void);
void _ent_npc_set_in_cutscene( enum npc npc_id, bool yes );
entity_event_result ent_npc_event( ent_event *event );
+
+#endif
-#include "world.h"
-#include "world_load.h"
-#include "entity.h"
-#include "audio.h"
-#include "vg/vg_steam2.h"
-#include "ent_region.h"
-#include "player.h"
-#include "player_skate.h"
-
static void ent_objective_pass( world_instance *world, ent_objective *objective )
{
objective->flags |= k_ent_objective_passed;
world_instance *world = &_world.main;
ent_objective *objective = af_arritm( &world->ent_objective, mdl_entity_id_id( event->recieve_entity_id ) );
- if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "trigger" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "trigger" ) )
{
if( (_world.event == k_world_event_challenge) && (_world.challenge_state == k_challenge_state_running) )
{
objective->flags |= k_ent_objective_failed;
_world.challenge_state = k_challenge_state_fail;
- gui_helper_reset( k_gui_helper_mode_black_bars );
+ _gui_helper_reset( k_gui_helper_mode_black_bars );
vg_str str;
struct gui_helper *helper;
- if( (helper = gui_new_helper(input_button_list[k_srbind_reset], &str)) )
+ if( (helper = _gui_new_helper(input_button_list[k_srbind_reset], &str)) )
vg_strcat( &str, "Retry" );
}
}
return k_entity_event_result_OK;
}
- else if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "hide" ) )
+ else if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "hide" ) )
{
// TODO: Make this dynamiclly fetched from a handler for the entity itself. (or not, fuck you)
if( event->flags == k_ent_event_data_const_i32 )
-#pragma once
-#include "entity.h"
-#include "world.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_objective.c"
+#else
+
entity_event_result ent_objective_event( ent_event *event );
+
+#endif
-#include "ent_prop.h"
-
void ent_prop_update( world_instance *world )
{
for( u32 i=0; i<af_arrcount( &world->ent_prop ); i ++ )
-#pragma once
-#include "world.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_prop.c"
+#else
+
void ent_prop_update( world_instance *world );
+
+#endif
-#include "ent_region.h"
-#include "gui.h"
-#include "network_common.h"
-#include "network.h"
-
struct global_ent_region global_ent_region;
u32 region_spark_colour( u32 flags )
if( region->v109.id_list != 0 )
challenge_list = af_arritm( &world->ent_list, mdl_entity_id_id( region->v109.id_list ) );
- if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "set_active" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "set_active" ) )
{
- gui_location_print_ccmd( 1, (const char *[]){af_str( &world->meta.af, region->pstr_title)} );
- vg_strncpy( af_str( &world->meta.af, region->pstr_title ),
+ gui_location_print_ccmd( 1, (const char *[]){af_str( world->meta.packed_strings, region->pstr_title)} );
+ vg_strncpy( af_str( world->meta.packed_strings, region->pstr_title ),
global_ent_region.location, NETWORK_REGION_MAX,
k_strncpy_always_add_null );
global_ent_region.flags = region->flags;
if( !(original_flags & (k_ent_route_flag_achieve_silver|k_ent_route_flag_achieve_gold)) &&
region->flags & (k_ent_route_flag_achieve_silver|k_ent_route_flag_achieve_gold) )
{
- gui_notify( "\xb3 Region completed!", 6.0f, k_ui_fg );
+ _gui_notify( "\xb3 Region completed!", 6.0f, k_ui_fg );
}
}
}
-#pragma once
-#include "world_entity.h"
-#include "network_common.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_region.c"
+#else
struct global_ent_region
{
u32 region_spark_colour( u32 flags );
void ent_region_re_eval( world_instance *world, bool init );
entity_event_result ent_region_event( ent_event *event );
+
+#endif
-#pragma once
-#include "entity.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_relay.c"
+#else
+#endif
-#include "ent_route.h"
-#include "input.h"
-#include "gui.h"
-#include "network_requests.h"
-#include "user_profile.h"
-
struct _ent_route _ent_route;
entity_event_result ent_route_event( ent_event *event )
world_instance *world = &_world.main;
ent_route *route = af_arritm( &world->ent_route, mdl_entity_id_id( event->recieve_entity_id ) );
- if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "view" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "view" ) )
{
if( world_set_event( k_world_event_route_leaderboard ) )
{
menu_close();
- gui_helper_reset( k_gui_helper_mode_clear );
+ _gui_helper_reset( k_gui_helper_mode_clear );
vg_str text;
- if( gui_new_helper( input_button_list[k_srbind_mback], &text ) )
+ if( _gui_new_helper( input_button_list[k_srbind_mback], &text ) )
vg_strcat( &text, "Exit" );
_ent_route.viewing_route_id = event->recieve_entity_id;
localplayer.immobile = 1;
{
srinput.state = k_input_state_resume;
localplayer.immobile = 0;
- gui_helper_reset( k_gui_helper_mode_clear );
+ _gui_helper_reset( k_gui_helper_mode_clear );
return;
}
}
u32 index = mdl_entity_id_id( _ent_route.viewing_route_id );
- ui_fill( ctx, (ui_rect){0,0,vg.window_x,vg.window_y}, 0x01ffffff );
+ ui_fill( ctx, (ui_rect){0,0,_vg_window.w,_vg_window.h}, 0x01ffffff );
ui_px w = 500;
- ent_route_leaderboard_ui( ctx, (ui_rect){ vg.window_x/2 - w/2, 64, w, 0 }, index );
+ ent_route_leaderboard_ui( ctx, (ui_rect){ _vg_window.w/2 - w/2, 64, w, 0 }, index );
}
void ent_route_leaderboard_ui( ui_context *ctx, ui_rect ref_box, u32 route_index )
char mod_uid[ ADDON_UID_MAX ];
addon_make_uid( _world.main.addon_id, mod_uid );
- network_request_scoreboard( mod_uid, af_str( &world->meta.af, route->pstr_name ),
+ network_request_scoreboard( mod_uid, af_str( world->meta.packed_strings, route->pstr_name ),
NETWORK_LEADERBOARD_ALLTIME_AND_CURRENT_WEEK, route_index );
}
return;
}
+ ui_fill( ctx, leaderboard_box, ui_opacity( GUI_COL_DARK, 0.36f ) );
+ ui_text( ctx, leaderboard_box, "FIXME FIXME!!!!!", 1, k_ui_align_middle_center, 0 );
+
+ //FIXME////FIXME
+#if 0
vg_msg body;
vg_msg_init( &body, board->data, board->data_len );
u64 steamid;
vg_msg_getkvintg( &body, "steamid", k_vg_msg_u64, &steamid, NULL );
ui_px y = bl[1];
- if( (y + 200+8) > vg.window_y )
- y = vg.window_y - (200+8);
+ if( (y + 200+8) > _vg_window.h )
+ y = _vg_window.h - (200+8);
_user_profile_ui( ctx, (ui_rect){ bl[0]-(360+8),y, 360,200 }, steamid );
}
{
skaterift.activity = k_skaterift_default;
- u32 last_minute = (u32)( lastsec / 60 );
-
- // TODO: put this in a header
- u32 minutes_span = (centiseconds+(200*60)) / (100*60);
- vg_queue_clear( &_remote_replay.buffer );
- _remote_replay.min_frame_t = 0.0;
- _remote_replay.total_chunks = minutes_span;
- _remote_replay.chunks_downloaded = 0;
+ // FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////
+#if 0
u64 steamid;
vg_msg_getkvintg( &body, "steamid", k_vg_msg_u64, &steamid, NULL );
- _remote_replay.steamid = steamid;
- _remote_replay.state = k_remote_replay_state_init;
- _remote_replay.last_second = lastsec;
-
- for( u32 i=0; i<minutes_span; i ++ )
- {
- struct remote_replay_chunk *chunk = &_remote_replay.chunks[i];
- chunk->minute = last_minute - minutes_span + 1 + i;
- chunk->state = k_chunk_state_none;
- }
+#endif
+ u64 steamid = 0;
+ _remote_replay_reset( centiseconds, lastsec, steamid );
world_clear_event( k_world_event_route_leaderboard );
srinput.state = k_input_state_resume;
- gui_helper_reset( k_gui_helper_mode_clear );
+ _gui_helper_reset( k_gui_helper_mode_clear );
_replay2_open_player( k_replay_type_network, 0 );
}
}
_ent_route.entries_max = count;
vg_ui.frosting = 0.015f;
ui_flush( ctx, k_ui_shader_colour, NULL );
+#endif
vg_ui.frosting = 0.0f;
ctx->font = &vgf_default_small;
}
-#pragma once
-#include "entity.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_route.c"
+#else
struct _ent_route
{
void ent_route_preupdate(void);
void ent_route_leaderboard_ui( ui_context *ctx, ui_rect ref_box, u32 route_index );
void _ent_route_imgui( ui_context *ctx );
+
+#endif
-#include "ent_script.h"
-
struct
{
void **userdata_array;
for( u32 i=0; i<af_arrcount( &world->ent_script ); i ++ )
{
ent_script *script = af_arritm( &world->ent_script, i );
- const char *script_name = af_str( &world->meta.af, script->pstr_script_name );
+ const char *script_name = af_str( world->meta.packed_strings, script->pstr_script_name );
for( u32 j=0; 1; j ++ )
{
-#pragma once
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_script.c"
+#else
struct script_event_allocate
{
void ent_script_update( world_instance *world );
void ent_script_alloc( world_instance *world, vg_stack_allocator *stack );
entity_event_result _ent_script_world_event( ent_event *event );
+
+#endif
-#include "vg/vg_steam2.h"
-#include "vg/vg_msg.h"
-#include "vg/vg_tex.h"
-#include "vg/vg_image.h"
-#include "vg/vg_loader.h"
-#include "ent_skateshop.h"
-#include "world.h"
-#include "player.h"
-#include "gui.h"
-#include "menu.h"
-#include "addon.h"
-#include "save.h"
-#include "network.h"
-
struct global_skateshop _skateshop;
static void skateshop_update_viewpage(void)
}
}
-static void skateshop_init_async( void *userdata )
-{
- THREAD_0;
-
- skaterift.rt_textures[ k_skaterift_rt_workshop_preview ] = vg.tex_missing;
- skaterift.rt_textures[ k_skaterift_rt_server_status ] = vg.tex_missing;
- render_server_status_gui();
-}
-
/*
* VG event init
*/
-void skateshop_init(void)
+VG_API void _skateshop_init(void)
{
- THREAD_1;
- vg_async_call( &vg.main_tasks, skateshop_init_async, NULL );
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
}
static addon_cache_id skateshop_selected_board_cache_id(void)
vg_str text;
vg_strnull( &text, _skateshop.helper_toggle->text, sizeof(_skateshop.helper_toggle->text) );
- if( g_client.demo_mode )
+ if( _is_running_demo() )
{
vg_strcat( &text, "Not availible in demo" );
}
{
enum addon_type type;
};
-static void skateshop_addon_scan_task( vg_async_task *task )
+static void skateshop_addon_scan_task( struct skateshop_scan_info *in_args, vg_async_info *async )
{
- THREAD_1;
- struct skateshop_scan_info *info = (void *)task->data;
- if( info->type == k_addon_type_board )
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+ if( in_args->type == k_addon_type_board )
_addon_mount_content_folder( k_addon_type_board, "boards", ".mdl" );
- else if( info->type == k_addon_type_player )
+ else if( in_args->type == k_addon_type_player )
_addon_mount_content_folder( k_addon_type_world, "playermodels", ".mdl" );
- else if( info->type == k_addon_type_world )
+ else if( in_args->type == k_addon_type_world )
_addon_mount_content_folder( k_addon_type_world, "maps", ".mdl" );
}
static void skateshop_scan( enum addon_type specific_type )
{
- THREAD_0;
- _mount_workshop_addons( NULL );
- vg_async_task *task = vg_allocate_async_task( &vg.loader_tasks, sizeof(struct skateshop_scan_info), 1 );
- struct skateshop_scan_info *info = (void *)task->data;
- info->type = specific_type;
- vg_async_task_dispatch( task, skateshop_addon_scan_task );
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ _mount_workshop_addons();
+ struct skateshop_scan_info *out_args = _vg_async_alloc( VG_THREAD_ASYNC_ID, sizeof(struct skateshop_scan_info) );
+ out_args->type = specific_type;
+ _vg_async_send( out_args, (vg_async_fn)skateshop_addon_scan_task );
}
static void ent_skateshop_helpers_pickable( const char *acceptance )
{
vg_str text;
- if( gui_new_helper( input_button_list[k_srbind_mback], &text ))
+ if( _gui_new_helper( input_button_list[k_srbind_mback], &text ))
vg_strcat( &text, "Exit" );
- if( (_skateshop.helper_pick = gui_new_helper( input_button_list[k_srbind_maccept], &text)))
+ if( (_skateshop.helper_pick = _gui_new_helper( input_button_list[k_srbind_maccept], &text)))
vg_strcat( &text, acceptance );
- if( (_skateshop.helper_browse = gui_new_helper( input_axis_list[k_sraxis_mbrowse_h], &text )))
+ if( (_skateshop.helper_browse = _gui_new_helper( input_axis_list[k_sraxis_mbrowse_h], &text )))
vg_strcat( &text, "Browse" );
}
addon_cache_watch( k_addon_type_board, cache_id );
localplayer.board_view_slot = cache_id;
network_send_item( k_netmsg_playeritem_board );
- gui_helper_reset( k_gui_helper_mode_clear );
+ _gui_helper_reset( k_gui_helper_mode_clear );
skateshop_playermod( 0 );
_skateshop.open = 0;
}
void charshop_quitsave(void)
{
_skateshop.open = 0;
- gui_helper_reset( k_gui_helper_mode_clear );
+ _gui_helper_reset( k_gui_helper_mode_clear );
skateshop_playermod( 0 );
srinput.state = k_input_state_resume;
if( model->flags & PLAYER_MODEL_FLAG_CUSTOMIZABLE )
{
+ // FIXME////FIXME/FIXME write cpart
+#if 0
addon_cache_entry *cache_entry = get_addon_cache_entry( k_addon_type_player, slot );
memcpy( cache_entry->local_cpart, localplayer.playermodel.cpart, ADDON_CPART_MAX );
savedata_file file;
init_savefile( &file, "" );
- addon_make_savedata_path( cache_entry->addon_id, file.path );
- vg_msg_wkvstr( &file.msg, "cpart", localplayer.playermodel.cpart );
- write_savefile( &file, 1 );
+ //addon_make_savedata_path( cache_entry->addon_id, file.path );
+
+ //vg_msg_wkvstr( &file.msg, "cpart", localplayer.playermodel.cpart );
+ //write_savefile( &file, 1 );
+#endif
}
network_send_item( k_netmsg_playeritem_player );
else
{
_skateshop.open = 0;
- gui_helper_reset( k_gui_helper_mode_clear );
+ _gui_helper_reset( k_gui_helper_mode_clear );
skateshop_playermod( 0 );
srinput.state = k_input_state_resume;
}
{
f64 delta = vg.time_real - network_client.last_intent_change;
- if( (delta > 5.0) && (!g_client.demo_mode) )
+ if( (delta > 5.0) && !_is_running_demo() )
{
_skateshop.helper_pick->greyed = 0;
if( button_down( k_srbind_maccept ) )
float scale = 0.2f,
thickness = 0.03f;
- font3d_bind( &gui.font, k_font_shader_default, 0, world, cam );
+ font3d_bind( &gui.font, k_font_shader_default, 0, cam );
shader_model_font_uColour( (v4f){1.0f,1.0f,1.0f,1.0f} );
/* Selection counter
char buf[16];
vg_str str;
vg_strnull( &str, buf, sizeof(buf) );
- vg_strcati32( &str, _skateshop.selected_board_index+1 );
+ vg_strcati64( &str, _skateshop.selected_board_index+1, 10 );
vg_strcatch( &str, '/' );
- vg_strcati32( &str, valid_count );
+ vg_strcati64( &str, valid_count, 10 );
font3d_simple_draw( 0, buf, cam, mmdl );
}
else
{
_skateshop.render.item_title = "";
_skateshop.render.item_desc = "";
- vg_msg msg;
- vg_msg_init( &msg, reg->metadata, reg->metadata_len );
- if( vg_msg_seekframe( &msg, "workshop" ) )
+ u32 workshop_block = vg_kv_find( ®->metadata, 0, "workshop" );
+ if( workshop_block )
{
- const char *title = vg_msg_getkvstr( &msg, "title" );
- if( title ) _skateshop.render.item_title = title;
+ const c8 *title = vg_kv_value( ®->metadata, vg_kv_find( ®->metadata, workshop_block, "title" ), NULL );
+ if( title )
+ _skateshop.render.item_title = title;
- const char *dsc = vg_msg_getkvstr( &msg, "author" );
- if( dsc ) _skateshop.render.item_desc = dsc;
- vg_msg_skip_frame( &msg );
+ const c8 *dsc = vg_kv_value( ®->metadata, vg_kv_find( ®->metadata, workshop_block, "author" ), NULL );
+ if( dsc )
+ _skateshop.render.item_desc = dsc;
}
_skateshop.render.addon_id = entry->addon_id;
world_instance *world = &_world.main;
ent_skateshop *shop = af_arritm( &world->ent_skateshop, mdl_entity_id_id( event->recieve_entity_id ) );
- if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "open" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "open" ) )
{
if( world_set_event( k_world_event_shop ) )
{
skateshop_scan( k_addon_type_board );
}
- gui_helper_reset( k_gui_helper_mode_clear );
+ _gui_helper_reset( k_gui_helper_mode_clear );
if( shop->type == k_skateshop_type_charshop )
{
i32 R = menu_nav( &_skateshop.charshop_row, mv, _skateshop.charshop_row_max );
- ui_rect panel = { 8, 8, 350, vg.window_y };
+ ui_rect panel = { 8, 8, 350, _vg_window.h };
ui_fill( ctx, panel, ui_opacity( GUI_COL_DARK, 0.35f ) );
ui_outline( ctx, panel, 1, GUI_COL_NORM, 0 );
ui_rect_pad( panel, (ui_px[]){8,8} );
player__use_model( id );
addon_reg *reg = addon_details( id );
- vg_msg msg;
- vg_msg_init( &msg, reg->metadata, reg->metadata_len );
-
- if( vg_msg_seekframe( &msg, "workshop" ) )
+ u32 workshop_block = vg_kv_find( ®->metadata, 0, "workshop" );
+ if( workshop_block )
{
- const char *title = vg_msg_getkvstr( &msg, "title" );
- if( title ) _skateshop.render.item_title = title;
- vg_msg_skip_frame( &msg );
+ const c8 *title = vg_kv_value( ®->metadata, vg_kv_find( ®->metadata, workshop_block, "title" ), NULL );
+ if( title )
+ _skateshop.render.item_title = title;
}
}
for( u32 i=0; i<prop_count; i ++ )
{
editer_property *prop = af_arritm( &model->editer_property, i );
- const char *alias = af_str( &model->mdl.af, prop->pstr_alias );
+ const char *alias = af_str( &model->model.packed_strings, prop->pstr_alias );
if( prop->ui_type == k_editer_type_toggle )
{
}
else if( prop->ui_type == k_editer_type_selecter )
{
- const char *options = af_str( &model->mdl.af, prop->max.pstr_options );
+ const char *options = af_str( model->model.packed_strings, prop->max.pstr_options );
if( menu_options( ctx, panel, R == i+1, &_skateshop.charshop_col, alias, options,
&view->property_values[i]._u32, mh, enter ) )
edited = 1;
ctx->font = &vgf_default_small;
}
-void ent_skateshop_gui( ui_context *ctx )
+void _ent_skateshop_gui( ui_context *ctx )
{
if( _world.event == k_world_event_shop )
{
v2_divs( handles[i], handles[i][3], handles[i] );
v2_muladds( (v2f){0.5f,0.5f}, handles[i], 0.5f, handles[i] );
handles[i][1] = 1.0f - handles[i][1];
- v2_mul( (v2f){ vg.window_x, vg.window_y }, handles[i], handles[i] );
+ v2_mul( (v2f){ _vg_window.w, _vg_window.h }, handles[i], handles[i] );
}
ui_px r = 24;
-#pragma once
-#include "world.h"
-#include "world_load.h"
-#include "player.h"
-#include "vg/vg_steam2.h"
-#include "workshop.h"
-#include "addon.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_skateshop.c"
+#else
#define SKATESHOP_VIEW_SLOT_MAX 5
}
extern _skateshop;
-void skateshop_init(void);
+VG_API void _skateshop_init(void);
void ent_skateshop_update(void);
void ent_skateshop_render( vg_camera *cam );
void skateshop_world_preupdate(void);
entity_event_result ent_skateshop_event( ent_event *event );
void skateshop_world_preview_preupdate(void);
+void _ent_skateshop_gui( ui_context *ctx );
+
+#endif
-#include "world.h"
-#include "particle.h"
-
static f32 k_tornado_strength = 0.0f,
k_tornado_ratio = 0.5f,
k_tornado_range = 10.f;
-void ent_tornado_register(void)
+VG_API void _ent_tornado_register(void)
{
vg_console_reg_var( "k_tonado_strength", &k_tornado_strength,
k_var_dtype_f32, VG_VAR_PERSISTENT|VG_VAR_CHEAT );
for( u32 i=0; i<af_arrcount(&world->ent_marker); i ++ )
{
ent_marker *marker = af_arritm( &world->ent_marker, i );
-
- if( AF_STR_EQ( &world->meta.af, marker->pstr_alias, "tornado" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, marker->pstr_alias, "tornado" ) )
{
v3f p1;
v3_add( marker->transform.co, (v3f){0,20,0}, p1 );
for( u32 i=0; i<af_arrcount(&world->ent_marker); i ++ )
{
ent_marker *marker = af_arritm( &world->ent_marker, i );
-
- if( AF_STR_EQ( &world->meta.af, marker->pstr_alias, "tornado" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, marker->pstr_alias, "tornado" ) )
{
v3f d, dir;
v3_sub( co, marker->transform.co, d );
for( u32 i=0; i<af_arrcount(&world->ent_marker); i ++ )
{
ent_marker *marker = af_arritm( &world->ent_marker, i );
-
- if( AF_STR_EQ( &world->meta.af, marker->pstr_alias, "tornado" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, marker->pstr_alias, "tornado" ) )
{
v3f co;
vg_rand_sphere( &vg.rand, co );
-#pragma once
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_tornado.c"
+#else
-void ent_tornado_register(void);
+VG_API void _ent_tornado_register(void);
void ent_tornado_debug(void);
void ent_tornado_forces( v3f co, v3f cv, v3f out_a );
void ent_tornado_pre_update(void);
+
+#endif
-#include "world.h"
-
void ent_traffic_update( world_instance *world, v3f pos )
{
for( u32 i=0; i<af_arrcount( &world->ent_traffic ); i++ ){
-#pragma once
-#include "world.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_traffic.c"
+#else
void ent_traffic_update( world_instance *world, v3f pos );
+#endif
-#include "world.h"
-#include "entity.h"
-#include "world_entity.h"
-
-#include "ent_objective.h"
-#include "ent_skateshop.h"
-#include "ent_relay.h"
-#include "ent_challenge.h"
-#include "ent_route.h"
-#include "ent_region.h"
-#include "ent_glider.h"
-#include "ent_prop.h"
-#include "world_water.h"
-
-#include <string.h>
-
-#pragma once
-
-#include "vg/vg_audio.h"
-#include "vg/vg_ui/imgui.h"
-#include "model.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/entity.c"
+#else
typedef struct ent_spawn ent_spawn;
typedef struct ent_light ent_light;
}
data;
};
+
+#endif
--- /dev/null
+VG_TIER_2 void font3d_load( font3d *font, const c8 *mdl_path, vg_stack_allocator *stack )
+{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+ vg_model_stream_context ctx;
+ VG_ASSERT( vg_model_stream_open( &ctx, &font->model, mdl_path ) );
+ vg_model_stream_metadata( &ctx, stack );
+ vg_model_stream_meshes_gpu( &ctx, NULL );
+ vg_model_stream_textures_gpu( &ctx );
+
+ u32 temp_frame = _vg_start_temp_frame();
+ {
+ array_file_ptr fonts;
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &fonts, ent_font, _vg_temp_stack() );
+ VG_ASSERT( af_arrcount(&fonts) );
+ font->info = *((ent_font *)af_arritm(&fonts,0));
+ }
+ _vg_end_temp_frame( temp_frame );
+
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &font->font_variants, ent_font_variant, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &font->glyphs, ent_glyph, stack );
+ vg_model_stream_close( &ctx );
+}
+
+VG_TIER_0 u32 font3d_find_variant( font3d *font, const c8 *name )
+{
+ for( u32 i=0; i<af_arrcount( &font->font_variants ); i ++ )
+ {
+ ent_font_variant *variant = af_arritm( &font->font_variants, i );
+ if( !strcmp( af_str( font->model.packed_strings, variant->name ), name ) )
+ return i;
+ }
+
+ return 0;
+}
+
+struct _font3d_render
+{
+ v4f offset;
+ font3d *font;
+ u32 variant_id;
+
+ enum font_shader shader;
+}
+static gui_font3d;
+
+/*
+ * world can be null if not using world shader
+ */
+VG_TIER_0 void font3d_bind( font3d *font, enum font_shader shader, i32 depth_compare, vg_camera *cam )
+{
+ gui_font3d.shader = shader;
+ gui_font3d.font = font;
+ vg_tex_bind( GL_TEXTURE_2D, &font->model.textures[0].tex, 1 );
+
+ if( shader == k_font_shader_default )
+ {
+ shader_model_font_use();
+ shader_model_font_uColour( (v4f){1.0f,1.0f,1.0f,1.0f} );
+ shader_model_font_uTexMain( 1 );
+ shader_model_font_uDepthMode( depth_compare );
+ if( depth_compare )
+ {
+ depth_compare_bind( shader_model_font_uTexSceneDepth,
+ shader_model_font_uInverseRatioDepth,
+ shader_model_font_uInverseRatioMain, cam );
+ }
+ shader_model_font_uPv( cam->mtx.pv );
+ }
+ else if( shader == k_font_shader_world )
+ {
+ shader_scene_font_use();
+ shader_scene_font_uTexGarbage(0);
+ shader_scene_font_uTexMain(1);
+
+ shader_scene_font_uPv( g_render.cam.mtx.pv );
+ shader_scene_font_uTime( vg.time );
+
+ WORLD_LINK_TERRAIN_NOISE( &_world.main, scene_font );
+ WORLD_LINK_LIGHTING( &_world.main, scene_font );
+ shader_scene_font_uCamera( g_render.cam.transform[3] );
+ }
+
+ vg_model_bind_mesh( &font->model );
+}
+
+VG_TIER_0 ent_glyph *font3d_glyph( font3d *font, u32 variant_id, u32 utf32 )
+{
+ if( utf32 < font->info.glyph_utf32_base ) return NULL;
+ if( utf32 >= font->info.glyph_utf32_base+font->info.glyph_count) return NULL;
+
+ u32 index = utf32 - font->info.glyph_utf32_base;
+ index += font->info.glyph_start;
+ index += font->info.glyph_count * variant_id;
+ return af_arritm( &font->glyphs, index );
+}
+
+VG_API void font3d_set_transform( const c8 *text, vg_camera *cam, m4x3f transform )
+{
+ v4_copy( (v4f){0.0f,0.0f,0.0f,1.0f}, gui_font3d.offset );
+
+ m4x4f prev_mtx;
+ m4x3_expand( transform, prev_mtx );
+ m4x4_mul( cam->mtx_prev.pv, prev_mtx, prev_mtx );
+
+ if( gui_font3d.shader == k_font_shader_default )
+ {
+ shader_model_font_uPvmPrev( prev_mtx );
+ shader_model_font_uMdl( transform );
+ }
+ else if( gui_font3d.shader == k_font_shader_world )
+ {
+ shader_scene_font_uPvmPrev( prev_mtx );
+ shader_scene_font_uMdl( transform );
+ }
+}
+
+VG_API void font3d_setoffset( v4f offset )
+{
+ if( gui_font3d.shader == k_font_shader_default )
+ shader_model_font_uOffset( offset );
+ else if( gui_font3d.shader == k_font_shader_world )
+ shader_scene_font_uOffset( offset );
+}
+
+VG_API void font3d_setcolour( v4f colour )
+{
+ if( gui_font3d.shader == k_font_shader_default )
+ shader_model_font_uColour( colour );
+#if 0
+ else if( gui_font3d.shader == k_font_shader_world )
+ shader_scene_font_uColour( colour );
+#endif
+}
+
+VG_API void font3d_draw( const c8 *text )
+{
+ u8 *u8pch = (u8*)text;
+
+ u32 max_chars = 512;
+ while( u8pch && max_chars )
+ {
+ max_chars --;
+
+ u32 c0 = *u8pch, c1;
+ u8pch ++;
+
+ if( !c0 )
+ break;
+ ent_glyph *glyph0 = font3d_glyph( gui_font3d.font, gui_font3d.variant_id, c0 ),
+ *glyph1 = NULL;
+ /* multibyte characters */
+ if( c0 >= 1 && c0 < k_SRglyph_ascii_min )
+ {
+ c1 = *u8pch;
+ if( !c1 ) break;
+ glyph1 = font3d_glyph( gui_font3d.font, gui_font3d.variant_id, c1 );
+ }
+
+ if( c0 == k_SRglyph_ctrl_variant )
+ {
+ gui_font3d.variant_id = c1;
+ u8pch ++;
+ continue;
+ }
+ else if( c0 == k_SRglyph_ctrl_size )
+ {
+ gui_font3d.offset[3] = (float)c1 * (1.0f/255.0f);
+ u8pch ++;
+ continue;
+ }
+ else if( c0 == k_SRglyph_ctrl_baseline )
+ {
+ gui_font3d.offset[1] = 0.0f;
+ continue;
+ }
+ else if( c0 == k_SRglyph_ctrl_center )
+ {
+ if( glyph1 )
+ {
+ float diff = glyph1->size[1] - glyph1->size[1]*gui_font3d.offset[3];
+ gui_font3d.offset[1] = diff * 0.5f;
+ }
+ continue;
+ }
+ else if( c0 == k_SRglyph_ctrl_top )
+ {
+ if( glyph1 )
+ {
+ float diff = glyph1->size[1] - glyph1->size[1]*gui_font3d.offset[3];
+ gui_font3d.offset[1] = diff;
+ }
+ continue;
+ }
+
+ if( !glyph0 )
+ continue;
+
+ if( glyph1 && (c0 == k_SRglyph_mod_square || c0 == k_SRglyph_mod_circle))
+ {
+ v4f v0;
+ v2_sub( glyph0->size, glyph1->size, v0 );
+ v2_muladds( gui_font3d.offset, v0, -0.5f, v0 );
+ v0[2] = gui_font3d.offset[2];
+ v0[3] = gui_font3d.offset[3];
+
+ font3d_setoffset( v0 );
+ vg_model_draw_elements( glyph0->indice_start, glyph0->indice_count );
+ continue;
+ }
+ else
+ {
+ font3d_setoffset( gui_font3d.offset );
+ vg_model_draw_elements( glyph0->indice_start, glyph0->indice_count );
+ }
+
+ gui_font3d.offset[0] += glyph0->size[0]*gui_font3d.offset[3];
+ }
+}
+
+VG_API f32 font3d_simple_draw( u32 variant_id, const c8 *text, vg_camera *cam, m4x3f transform )
+{
+ if( !text )
+ return 0.0f;
+
+ gui_font3d.variant_id = variant_id;
+ font3d_set_transform( text, cam, transform );
+ font3d_draw( text );
+ return gui_font3d.offset[0];
+}
+
+VG_TIER_0 f32 font3d_string_width( u32 variant_id, const c8 *text )
+{
+ if( !text )
+ return 0.0f;
+ f32 width = 0.0f;
+
+ const u8 *buf = (const u8 *)text;
+ for( u32 i=0;; i++ )
+ {
+ u32 c = buf[i];
+ if( !c )
+ break;
+
+ ent_glyph *glyph = font3d_glyph( gui_font3d.font, variant_id, c );
+ if( !glyph )
+ continue;
+
+ width += glyph->size[0];
+ }
+
+ return width;
+}
-#pragma once
-#include "model.h"
-#include "entity.h"
-#include "vg/vg_camera.h"
-#include "shaders/model_font.h"
-#include "shaders/scene_font.h"
-#include "world_render.h"
-#include "depth_compare.h"
-#include "vg/vg_tex.h"
-#include <string.h>
+#if defined( SR_IMPLEMENTATION )
+# include "src/font.c"
+#else
enum efont_SRglyph{
k_SRglyph_end = 0x00, /* control characters */
};
typedef struct font3d font3d;
-struct font3d{
- mdl_context mdl;
- GLuint texture;
- glmesh mesh;
-
+struct font3d
+{
+ vg_model model;
ent_font info;
- array_file_ptr font_variants,
- glyphs;
+ array_file_ptr font_variants, glyphs;
};
-static void font3d_load( font3d *font, const char *mdl_path, void *alloc )
-{
- THREAD_1;
- mdl_context *mdl = &font->mdl;
- mdl_open( mdl, mdl_path, alloc );
- mdl_load_metadata_block( mdl, alloc );
-
- vg_stack_clear( &vg.scratch );
- array_file_ptr fonts;
- AF_LOAD_ARRAY_STRUCT( &mdl->af, &fonts, ent_font, &vg.scratch );
- font->info = *((ent_font *)af_arritm(&fonts,0));
-
- AF_LOAD_ARRAY_STRUCT( &mdl->af, &font->font_variants, ent_font_variant, alloc );
- AF_LOAD_ARRAY_STRUCT( &mdl->af, &font->glyphs, ent_glyph, alloc );
- vg_stack_clear( &vg.scratch );
-
- if( !font->mdl.texture_count )
- vg_fatal_error( "No texture in font file" );
-
- mdl_texture *tex0 = &mdl->textures[ 0 ];
- void *data = vg_stack_allocate( &vg.scratch, tex0->file.pack_size, 8, "Pack data" );
- mdl_fread_pack_file( mdl, &tex0->file, data );
-
- mdl_async_load_glmesh( mdl, &font->mesh, NULL );
- vg_tex2d_load_qoi_async( data, tex0->file.pack_size, VG_TEX2D_LINEAR|VG_TEX2D_CLAMP, &font->texture );
-
- mdl_close( mdl );
-}
-
-static u32 font3d_find_variant( font3d *font, const char *name )
-{
- for( u32 i=0; i<af_arrcount( &font->font_variants ); i ++ )
- {
- ent_font_variant *variant = af_arritm( &font->font_variants, i );
-
- if( !strcmp( af_str( &font->mdl.af, variant->name ), name ) )
- return i;
- }
-
- return 0;
-}
-
-struct _font3d_render{
- v4f offset;
- font3d *font;
- u32 variant_id;
-
- enum font_shader {
- k_font_shader_default,
- k_font_shader_world
- }
- shader;
-}
-static gui_font3d;
-
-/*
- * world can be null if not using world shader
- */
-static void font3d_bind( font3d *font, enum font_shader shader, int depth_compare, world_instance *world,vg_camera *cam )
+enum font_shader
{
- gui_font3d.shader = shader;
- gui_font3d.font = font;
- glActiveTexture( GL_TEXTURE1 );
- glBindTexture( GL_TEXTURE_2D, font->texture );
-
- if( shader == k_font_shader_default )
- {
- shader_model_font_use();
- shader_model_font_uColour( (v4f){1.0f,1.0f,1.0f,1.0f} );
- shader_model_font_uTexMain( 1 );
- shader_model_font_uDepthMode( depth_compare );
-
- if( depth_compare )
- {
- depth_compare_bind(
- shader_model_font_uTexSceneDepth,
- shader_model_font_uInverseRatioDepth,
- shader_model_font_uInverseRatioMain, cam );
- }
-
- shader_model_font_uPv( cam->mtx.pv );
- }
- else if( shader == k_font_shader_world )
- {
- shader_scene_font_use();
- shader_scene_font_uTexGarbage(0);
- shader_scene_font_uTexMain(1);
-
- shader_scene_font_uPv( g_render.cam.mtx.pv );
- shader_scene_font_uTime( vg.time );
-
- WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_font );
-
- bind_terrain_noise();
- shader_scene_font_uCamera( g_render.cam.transform[3] );
- }
- mesh_bind( &font->mesh );
-}
-
-static ent_glyph *font3d_glyph( font3d *font, u32 variant_id, u32 utf32 ){
- if( utf32 < font->info.glyph_utf32_base ) return NULL;
- if( utf32 >= font->info.glyph_utf32_base+font->info.glyph_count) return NULL;
-
- u32 index = utf32 - font->info.glyph_utf32_base;
- index += font->info.glyph_start;
- index += font->info.glyph_count * variant_id;
- return af_arritm( &font->glyphs, index );
-}
-
-static void font3d_set_transform( const char *text,
- vg_camera *cam, m4x3f transform ){
- v4_copy( (v4f){0.0f,0.0f,0.0f,1.0f}, gui_font3d.offset );
-
- m4x4f prev_mtx;
- m4x3_expand( transform, prev_mtx );
- m4x4_mul( cam->mtx_prev.pv, prev_mtx, prev_mtx );
-
- if( gui_font3d.shader == k_font_shader_default ){
- shader_model_font_uPvmPrev( prev_mtx );
- shader_model_font_uMdl( transform );
- }
- else if( gui_font3d.shader == k_font_shader_world ){
- shader_scene_font_uPvmPrev( prev_mtx );
- shader_scene_font_uMdl( transform );
- }
-}
+ k_font_shader_default,
+ k_font_shader_world
+};
-static void font3d_setoffset( v4f offset ){
- if( gui_font3d.shader == k_font_shader_default )
- shader_model_font_uOffset( offset );
- else if( gui_font3d.shader == k_font_shader_world )
- shader_scene_font_uOffset( offset );
-}
+VG_TIER_2 void font3d_load( font3d *font, const c8 *mdl_path, vg_stack_allocator *stack );
+VG_TIER_0 u32 font3d_find_variant( font3d *font, const c8 *name );
+VG_TIER_0 void font3d_bind( font3d *font, enum font_shader shader, i32 depth_compare, vg_camera *cam );
+VG_TIER_0 ent_glyph *font3d_glyph( font3d *font, u32 variant_id, u32 utf32 );
+VG_API void font3d_set_transform( const c8 *text, vg_camera *cam, m4x3f transform );
+VG_API void font3d_setoffset( v4f offset );
+VG_API void font3d_setcolour( v4f colour );
+VG_API void font3d_draw( const c8 *text );
+VG_API f32 font3d_simple_draw( u32 variant_id, const c8 *text, vg_camera *cam, m4x3f transform );
+VG_TIER_0 f32 font3d_string_width( u32 variant_id, const c8 *text );
-static void font3d_setcolour( v4f colour ){
- if( gui_font3d.shader == k_font_shader_default )
- shader_model_font_uColour( colour );
-#if 0
- else if( gui_font3d.shader == k_font_shader_world )
- shader_scene_font_uColour( colour );
#endif
-}
-
-static void font3d_draw( const char *text ){
- u8 *u8pch = (u8*)text;
-
- u32 max_chars = 512;
- while( u8pch && max_chars ){
- max_chars --;
-
- u32 c0 = *u8pch, c1;
- u8pch ++;
-
- if( !c0 ) break;
-
- ent_glyph *glyph0 = font3d_glyph( gui_font3d.font,
- gui_font3d.variant_id, c0 ),
- *glyph1 = NULL;
-
- /* multibyte characters */
- if( c0 >= 1 && c0 < k_SRglyph_ascii_min ){
- c1 = *u8pch;
- if( !c1 ) break;
- glyph1 = font3d_glyph( gui_font3d.font, gui_font3d.variant_id, c1 );
- }
-
- if( c0 == k_SRglyph_ctrl_variant ){
- gui_font3d.variant_id = c1;
- u8pch ++;
- continue;
- }
- else if( c0 == k_SRglyph_ctrl_size ){
- gui_font3d.offset[3] = (float)c1 * (1.0f/255.0f);
- u8pch ++;
- continue;
- }
- else if( c0 == k_SRglyph_ctrl_baseline ){
- gui_font3d.offset[1] = 0.0f;
- continue;
- }
- else if( c0 == k_SRglyph_ctrl_center ){
- if( glyph1 ){
- float diff = glyph1->size[1] - glyph1->size[1]*gui_font3d.offset[3];
- gui_font3d.offset[1] = diff * 0.5f;
- }
- continue;
- }
- else if( c0 == k_SRglyph_ctrl_top ){
- if( glyph1 ){
- float diff = glyph1->size[1] - glyph1->size[1]*gui_font3d.offset[3];
- gui_font3d.offset[1] = diff;
- }
- continue;
- }
-
- if( !glyph0 ) continue;
-
- if( glyph1 && (c0 == k_SRglyph_mod_square || c0 == k_SRglyph_mod_circle)){
- v4f v0;
- v2_sub( glyph0->size, glyph1->size, v0 );
- v2_muladds( gui_font3d.offset, v0, -0.5f, v0 );
- v0[2] = gui_font3d.offset[2];
- v0[3] = gui_font3d.offset[3];
-
- font3d_setoffset( v0 );
- mesh_drawn( glyph0->indice_start, glyph0->indice_count );
- continue;
- }
- else{
- font3d_setoffset( gui_font3d.offset );
- mesh_drawn( glyph0->indice_start, glyph0->indice_count );
- }
-
- gui_font3d.offset[0] += glyph0->size[0]*gui_font3d.offset[3];
- }
-}
-
-static f32 font3d_simple_draw( u32 variant_id, const char *text,
- vg_camera *cam, m4x3f transform ){
- if( !text ) return 0.0f;
-
- gui_font3d.variant_id = variant_id;
- font3d_set_transform( text, cam, transform );
- font3d_draw( text );
- return gui_font3d.offset[0];
-}
-
-static f32 font3d_string_width( u32 variant_id, const char *text ){
- if( !text ) return 0.0f;
- float width = 0.0f;
-
- const u8 *buf = (const u8 *)text;
- for( int i=0;; i++ ){
- u32 c = buf[i];
- if(!c) break;
-
- ent_glyph *glyph = font3d_glyph( gui_font3d.font, variant_id, c );
- if( !glyph ) continue;
-
- width += glyph->size[0];
- }
-
- return width;
-}
+++ /dev/null
-#include "skaterift.h"
-#include "player.h"
-#include "player_render.h"
-#include "replay2.h"
-#include "input.h"
-
-void freecam_preupdate(void)
-{
- vg_camera *cam = &_replay2.replay_freecam;
- v3f angles;
- v3_copy( cam->angles, angles );
- player_look( angles, 1.0f );
-
- f32 decay = vg_maxf(0.0f,1.0f-vg.time_frame_delta*10.0f);
-
- v3f d;
- v3_sub( angles, cam->angles, d );
- v3_muladds( _replay2.freecam_w, d, 20.0f, _replay2.freecam_w );
- v3_muls( _replay2.freecam_w, decay, _replay2.freecam_w );
- v3_muladds( cam->angles, _replay2.freecam_w, vg.time_frame_delta, cam->angles );
- cam->angles[1] = vg_clampf( cam->angles[1], -VG_PIf*0.5f,VG_PIf*0.5f);
-
- vg_camera_update_transform( cam );
-
- v3f lookdir = { 0.0f, 0.0f, -1.0f },
- sidedir = { 1.0f, 0.0f, 0.0f };
-
- m3x3_mulv( cam->transform, lookdir, lookdir );
- m3x3_mulv( cam->transform, sidedir, sidedir );
-
- v2f input;
- joystick_state( k_srjoystick_steer, input );
- v2_muls( input, vg.time_frame_delta*6.0f*20.0f, input );
-
- v3_muladds( _replay2.freecam_v, lookdir, -input[1], _replay2.freecam_v );
- v3_muladds( _replay2.freecam_v, sidedir, input[0], _replay2.freecam_v );
-
- v3_muls( _replay2.freecam_v, decay, _replay2.freecam_v );
- v3_muladds( cam->pos,_replay2.freecam_v, vg.time_frame_delta, cam->pos );
-}
+++ /dev/null
-#pragma once
-void freecam_preupdate(void);
-int freecam_cmd( int argc, const char *argv[] );
static void setlap_task( vg_async_task *task )
{
- THREAD_1;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
struct task_writeusertime *info = (void *)task->data;
db_writeusertime( info->uid, info->steamid, info->centiseconds, info->last_second, info->only_if_faster );
}
-#pragma once
-
-#include "vg/vg_platform.h"
-#include "vg/vg_steam2.h"
-#include "vg/vg_async2.h"
-#include "network_msg.h"
-#include "network_common.h"
+#include "vg/vg.h"
#include <sys/socket.h>
+#include "gameserver_database.h"
+#include "gameserver_db.h"
+#include "gameserver_monitor.h"
+#include "gameserver_replay.h"
+#include "gameserver_requests.h"
+
+
#define CLIENT_KNOWLEDGE_SAME_WORLD0 0x1
#define CLIENT_KNOWLEDGE_SAME_WORLD1 0x2
#define CLIENT_KNOWLEDGE_FRIENDS 0x4 /* unused */
bool db_writeusertime( char uid[DB_TABLE_UID_MAX], u64 steamid, u32 centiseconds, u64 last_second, bool only_if_faster )
{
- THREAD_1;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
u64 leaderboard_addr = db_leaderboard_address( uid ),
table = leaderboard_addr + offsetof(struct skaterift_leaderboard,entries);
bool db_get_username( u64 steamid, char *out_username, u32 username_max )
{
- THREAD_1;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
u64 user_address = vg_db_translate( &_gs_db.db, _gs_db.users_tree, steamid );
if( user_address )
void _db_edit_profile( struct profile_edits *info )
{
- THREAD_1;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
if( info->steamid == k_steamid_max )
return;
static void task_edit_profile( vg_async_task *task )
{
- THREAD_1;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
_db_edit_profile( (void *)task->data );
}
void db_action_edit_profile( struct profile_edits *edits )
{
- THREAD_0;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
vg_async_task *task = vg_allocate_async_task( &_gs_db.tasks, sizeof(struct profile_edits), 1 );
memcpy( (void *)task->data, edits, sizeof(struct profile_edits) );
vg_async_task_dispatch( task, task_edit_profile );
enum request_status gameserver_read_highscore_table( vg_msg *msg, char uid[ DB_TABLE_UID_MAX ] )
{
- THREAD_1;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
u64 leaderboard_address = db_leaderboard_address( uid );
u64 table_address = leaderboard_address + offsetof(struct skaterift_leaderboard,entries);
enum request_status _gs_db_get_profile( vg_msg *msg, u64 steamid )
{
- THREAD_1;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
u16 top3_count = 0,
top10_count = 0;
void _gs_db_dump_task( vg_async_task *task )
{
- THREAD_1;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
struct task_db_dump *info = (void *)task->data;
FILE *fp = fopen( info->output_path, "w" );
void db_action_dump( const char *path, bool kv_mode )
{
- THREAD_0;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
vg_async_task *task = vg_allocate_async_task( &_gs_db.tasks, sizeof(struct task_db_dump) + strlen(path)+1, 1 );
struct task_db_dump *info = (void *)task->data;
info->mode = kv_mode? k_dump_mode_kv: k_dump_mode_commands;
void _monitor_write_task( vg_async_task *task )
{
- THREAD_1;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
struct task_monitor_write *info = (void *)task->data;
FILE *fp = fopen( _gs_monitor.html_path, "w" );
void _monitor_journal_task( vg_async_task *task )
{
- THREAD_1;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
struct task_journal *info = (void *)task->data;
fputs( info->buf, _gs_monitor.journal_fp );
}
if( thread1 )
{
- THREAD_1;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
}
else
{
- THREAD_0;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
}
va_list args;
static void task_write_replay( vg_async_task *task )
{
- THREAD_1;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
struct serialized_replay *info = (void *)task->data;
vg_make_directory( "replaydata" );
{
if( async )
{
- THREAD_1;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
vg_async_task *task = vg_allocate_async_task( &_gameserver.tasks, sizeof(struct request_save_info), 1 );
struct request_save_info *info = (void *)task->data;
info->client_id = client_id;
return;
}
- THREAD_0;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
struct gameserver_client *client = &_gameserver.clients[ client_id ];
if( client->steamid != steamid )
static void log_request_status( u16 request_id )
{
- THREAD_0;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
gs_request *req = _get_request( request_id );
const char *associated_username = "none";
static void _gs_release_request( u16 client_id, u16 request_id )
{
- THREAD_0;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
VG_ASSERT( request_id );
gs_request *req = _get_request( request_id );
void _gs_requests_client_disconnect( u32 client_id )
{
- THREAD_0;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
gs_request_client *rc = &_gs_requests.clients[ client_id ];
u16 request_id = rc->active_chain.tail;
while( request_id )
void _gs_requests_tick(void)
{
- THREAD_0;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
for( u32 i=0; i<NETWORK_MAX_PLAYERS; i ++ )
{
static void task_request_processing_complete( vg_async_task *task )
{
- THREAD_0;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
struct task_request_run_info *info = (void *)task->data;
gs_request *req = _get_request( info->pool_id );
static void task_request_run( vg_async_task *task )
{
- THREAD_1;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
struct task_request_run_info *info = (void *)task->data;
gs_request *req = _get_request( info->pool_id );
void _gs_handle_request_message( u32 client_id, SteamNetworkingMessage_t *msg )
{
- THREAD_0;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
if( !packet_minsize( msg, sizeof(netmsg_request)+1 ))
{
--- /dev/null
+struct
+{
+ struct gui_helper
+ {
+ vg_input_op *binding;
+ c8 text[32];
+ int greyed;
+ }
+ helpers[4];
+ u32 helper_count;
+
+ enum gui_helper_mode helper_mode;
+
+ struct gui_notifier
+ {
+ const char *string;
+ f32 duration, time_left; /* seconds */
+ u32 colour;
+ }
+ notifiers[ 4 ];
+
+ struct icon_call
+ {
+ enum gui_icon icon;
+ v4f location;
+ v4f colour;
+ int colour_changed;
+ }
+ icon_draw_buffer[64];
+ u32 icon_draw_count;
+ v4f cur_icon_colour;
+ int colour_changed;
+
+ char location[64];
+ f64 location_time;
+
+ f32 factive;
+ font3d font;
+
+ v3f trick_co;
+ vg_model model_icons;
+
+ i32 icon_submeshes[ k_gui_icon_count ];
+}
+static gui = {.cur_icon_colour = {1.0f,1.0f,1.0f,1.0f},.colour_changed=1};
+
+VG_API void _gui_notify( const char *string, f32 duration, u32 colour )
+{
+ struct gui_notifier *notifier = NULL;
+ for( u32 i=0; i<VG_ARRAY_LEN(gui.notifiers); i ++ )
+ {
+ notifier = &gui.notifiers[i];
+ if( notifier->time_left > 0.0f )
+ {
+ notifier = NULL;
+ continue;
+ }
+ else break;
+ }
+
+ if( !notifier )
+ return;
+
+ notifier->string = string;
+ notifier->duration = duration;
+ notifier->time_left = duration;
+ notifier->colour = colour;
+}
+
+VG_API void _gui_helper_reset( enum gui_helper_mode mode )
+{
+ gui.helper_count = 0;
+ gui.helper_mode = mode;
+}
+
+VG_API struct gui_helper *_gui_new_helper( vg_input_op *bind, vg_str *out_text )
+{
+ if( gui.helper_count >= VG_ARRAY_LEN(gui.helpers) )
+ {
+ vg_error( "Too many helpers\n" );
+ return NULL;
+ }
+
+ struct gui_helper *helper = &gui.helpers[ gui.helper_count ++ ];
+ helper->greyed = 0;
+ helper->binding = bind;
+ vg_strnull( out_text, helper->text, sizeof(helper->text) );
+ return helper;
+}
+
+VG_API void _gui_render_icons(void)
+{
+ vg_camera ortho;
+
+ float fl = 0.0f,
+ fr = _vg_window.w,
+ fb = 0.0f,
+ ft = _vg_window.h,
+ rl = 1.0f / (fr-fl),
+ tb = 1.0f / (ft-fb);
+
+ m4x4_zero( ortho.mtx.p );
+ ortho.mtx.p[0][0] = 2.0f * rl;
+ ortho.mtx.p[1][1] = 2.0f * tb;
+ ortho.mtx.p[3][0] = (fr + fl) * -rl;
+ ortho.mtx.p[3][1] = (ft + fb) * -tb;
+ ortho.mtx.p[3][3] = 1.0f;
+ m4x3_identity( ortho.transform );
+ vg_camera_update_view( &ortho );
+ m4x4_mul( ortho.mtx.p, ortho.mtx.v, ortho.mtx.pv ); /* HACK */
+ vg_camera_finalize( &ortho );
+
+ /* icons */
+ font3d_bind( &gui.font, k_font_shader_default, 0, &ortho );
+ vg_model_bind_mesh( &gui.model_icons );
+
+ m4x3f mmdl;
+ m4x3_identity( mmdl );
+ shader_model_font_uMdl( mmdl );
+
+ vg_tex_bind( GL_TEXTURE_2D, &gui.model_icons.textures[0].tex, 0 );
+ shader_model_font_uTexMain( 0 );
+
+ for( u32 i=0; i<gui.icon_draw_count; i++ )
+ {
+ struct icon_call *call = &gui.icon_draw_buffer[i];
+
+ if( call->colour_changed )
+ shader_model_font_uColour( call->colour );
+ shader_model_font_uOffset( call->location );
+
+ i32 index = gui.icon_submeshes[ call->icon ];
+ mdl_submesh *sm = &gui.model_icons.submeshes[ index ];
+ if( sm )
+ vg_model_draw_submesh( sm );
+ }
+
+ gui.icon_draw_count = 0;
+}
+
+VG_API void _gui_draw( ui_context *ctx )
+{
+ /* helpers
+ * ----------------------------------------------------------------- */
+
+ gui.factive = vg_lerpf( gui.factive, gui.helper_count?1.0f:0.0f, vg.time_frame_delta*2.0f );
+
+ {
+ ui_px y = 80;
+ ui_px w = 360, h = 60;
+ ctx->font = &vgf_default_large;
+ for( u32 i=0; i<VG_ARRAY_LEN(gui.notifiers); i ++ )
+ {
+ struct gui_notifier *notifier = &gui.notifiers[i];
+ notifier->time_left -= vg.time_frame_delta;
+ if( notifier->time_left > 0.0f )
+ {
+ const float k_trans = 0.2;
+ float t0 = notifier->time_left,
+ t1 = notifier->duration - t0,
+ t = vg_smoothstepf( vg_minf( vg_minf( k_trans, t0 ), t1 ) / k_trans ),
+ x = (f32)(w+8) * t;
+ ui_rect box = { _vg_window.w - (ui_px)x, y, w, h };
+ ui_fill( ctx, box, ui_opacity( GUI_COL_DARK, t*0.6f ) );
+ ui_outline( ctx, box, 1, ui_opacity( GUI_COL_NORM, t*0.6f ), 0 );
+ ui_text( ctx, box, notifier->string, 1, k_ui_align_middle_center, ui_colour( ctx, notifier->colour ) );
+ }
+ y += h + 8;
+ }
+ }
+
+ if( _cutscene.state >= k_cutscene_state_ready )
+ {
+ ctx->font = &vgf_default_small;
+ return;
+ }
+
+ ctx->font = &vgf_default_title;
+ ui_px height = ctx->font->ch + 16;
+ ui_rect lwr = { 0, _vg_window.h - height, _vg_window.w, height };
+
+ ui_px x = 0;
+ for( u32 i=0; i<gui.helper_count; i++ )
+ {
+ struct gui_helper *helper = &gui.helpers[i];
+
+ char buf[128];
+ vg_str str;
+ vg_strnull( &str, buf, sizeof(buf) );
+ vg_input_string( &str, helper->binding, 1 );
+
+ ui_rect box = { x, lwr[1], 1000, lwr[3] };
+
+ u32 fg = 0;
+ f32 opacity = 0.4f;
+ if( helper->greyed )
+ {
+ fg = ui_colour(ctx, k_ui_fg+2);
+ opacity = 0.1f;
+ }
+
+ struct ui_vert *bg = ui_fill( ctx, box, ui_opacity( GUI_COL_DARK, opacity ) );
+ u32 w;
+ box[0] += 16;
+ w = ui_text( ctx, box, buf, 1, k_ui_align_middle_left, fg );
+ w *= ctx->font->sx;
+ bg[1].co[0] = x + w + 32;
+ bg[2].co[0] = x + w + 32;
+ x += w + 32;
+
+ box[0] = x;
+ bg = ui_fill( ctx, box, ui_opacity( GUI_COL_NORM, opacity*0.7f ) );
+ box[0] += 8;
+ w = ui_text( ctx, box, helper->text, 1, k_ui_align_middle_left, fg );
+ w *= ctx->font->sx;
+ bg[1].co[0] = box[0] + w + 16;
+ bg[2].co[0] = box[0] + w + 16;
+ x += w + 32;
+ }
+
+ if( (gui.helper_mode == k_gui_helper_mode_black_bars) && gui.helper_count )
+ {
+ ui_rect box = { x, lwr[1], _vg_window.w - x, height };
+ ui_fill( ctx, box, ui_opacity( GUI_COL_DARK, 0.4f ) );
+
+ box[0] = 0;
+ box[1] = 0;
+ box[2] = _vg_window.w;
+ ui_fill( ctx, box, ui_opacity( GUI_COL_DARK, 0.4f ) );
+ }
+
+ vg_ui.frosting = gui.factive*0.015f;
+ ui_flush( ctx, k_ui_shader_colour, NULL );
+ vg_ui.frosting = 0.0f;
+
+ f64 loc_t = (vg.time_real - gui.location_time) / 5.0;
+ if( (loc_t < 1.0) && (gui.location_time != 0.0) )
+ {
+ f32 t = 1.0f-vg_minf(1.0f,vg_minf(loc_t*20.0f,2.0f-loc_t*2.0f)),
+ o = 1.0f-t*t*(2.0f-t);
+
+ ui_rect box = { 0, (_vg_window.h*2)/3 - height/2, _vg_window.w, height };
+ ui_fill( ctx, box, ui_opacity( GUI_COL_NORM, 0.5f ) );
+ ui_text( ctx, box, gui.location, 1, k_ui_align_middle_center, 0 );
+
+ vg_ui.colour[3] = o;
+ ui_flush( ctx, k_ui_shader_colour, NULL );
+ }
+
+ vg_ui.colour[3] = 1.0f;
+ ctx->font = &vgf_default_small;
+}
+
+static int gui_location_print_ccmd( int argc, const char *argv[] )
+{
+ if( argc > 0 )
+ {
+ char new_loc[64];
+ vg_str str;
+ vg_strnull( &str, new_loc, 64 );
+ for( int i=0; i<argc; i++ )
+ {
+ vg_strcat( &str, argv[i] );
+ vg_strcat( &str, " " );
+ }
+ if( !strcmp(gui.location,new_loc) ) return 0;
+ vg_strncpy( new_loc, gui.location, 64, k_strncpy_always_add_null );
+ gui.location_time = vg.time_real;
+ }
+ return 0;
+}
+
+static void gui_draw_icon( enum gui_icon icon, v2f co, f32 size )
+{
+ if( gui.icon_draw_count == VG_ARRAY_LEN(gui.icon_draw_buffer) )
+ return;
+
+ struct icon_call *call = &gui.icon_draw_buffer[ gui.icon_draw_count ++ ];
+
+ call->icon = icon;
+ call->location[0] = co[0] * (f32)_vg_window.w;
+ call->location[1] = co[1] * (f32)_vg_window.h;
+ call->location[2] = 0.0f;
+ call->location[3] = size * (f32)_vg_window.w;
+
+ v4_copy( gui.cur_icon_colour, call->colour );
+ call->colour_changed = gui.colour_changed;
+ gui.colour_changed = 0;
+}
+
+static void gui_icon_setcolour( v4f colour ){
+ gui.colour_changed = 1;
+ v4_copy( colour, gui.cur_icon_colour );
+}
+
+VG_API void _gui_register(void)
+{
+ vg_console_reg_cmd( "gui_location", gui_location_print_ccmd, NULL );
+}
+
+static void _gui_load_content_async( void *_, vg_async_info *async )
+{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+ font3d_load( &gui.font, "models/rs_font.mdl", VG_STACK_USE_HEAP );
+
+ vg_model *mdl = &gui.model_icons;
+ vg_model_load( mdl, VG_MODEL_ENGINE_STANDARD, "models/rs_icons.mdl", VG_STACK_USE_HEAP );
+ VG_ASSERT( mdl->texture_count );
+ gui.icon_submeshes[ k_gui_icon_tick1 ] = vg_model_get_submesh_index( mdl, "icon_tick1" );
+ gui.icon_submeshes[ k_gui_icon_tick2 ] = vg_model_get_submesh_index( mdl, "icon_tick2" );
+ gui.icon_submeshes[ k_gui_icon_run ] = vg_model_get_submesh_index( mdl, "icon_run" );
+ gui.icon_submeshes[ k_gui_icon_challenge ] = vg_model_get_submesh_index( mdl, "icon_challenge" );
+ gui.icon_submeshes[ k_gui_icon_exclaim ] = vg_model_get_submesh_index( mdl, "icon_exclaim" );
+ gui.icon_submeshes[ k_gui_icon_board ] = vg_model_get_submesh_index( mdl, "icon_board" );
+ gui.icon_submeshes[ k_gui_icon_world ] = vg_model_get_submesh_index( mdl, "icon_world" );
+ gui.icon_submeshes[ k_gui_icon_rift ] = vg_model_get_submesh_index( mdl, "icon_rift" );
+ gui.icon_submeshes[ k_gui_icon_rift_run ] = vg_model_get_submesh_index( mdl, "icon_rift_run" );
+ gui.icon_submeshes[ k_gui_icon_rift_run_2d ] = vg_model_get_submesh_index( mdl, "icon_rift_run2d" );
+ gui.icon_submeshes[ k_gui_icon_friend ] = vg_model_get_submesh_index( mdl, "icon_friend" );
+ gui.icon_submeshes[ k_gui_icon_player ] = vg_model_get_submesh_index( mdl, "icon_player" );
+ gui.icon_submeshes[ k_gui_icon_player2d ] = vg_model_get_submesh_index( mdl, "icon_player2d" );
+ gui.icon_submeshes[ k_gui_icon_glider ] = vg_model_get_submesh_index( mdl, "icon_glider" );
+ gui.icon_submeshes[ k_gui_icon_spawn ] = vg_model_get_submesh_index( mdl, "icon_spawn" );
+ gui.icon_submeshes[ k_gui_icon_spawn_select ] = vg_model_get_submesh_index( mdl, "icon_spawn_select" );
+ gui.icon_submeshes[ k_gui_icon_rift_run_gold ] = vg_model_get_submesh_index( mdl,"icon_rift_run_medal_gold");
+ gui.icon_submeshes[ k_gui_icon_rift_run_silver]= vg_model_get_submesh_index( mdl,"icon_rift_run_medal_silver");
+ gui.icon_submeshes[ k_gui_icon_story2d ]= vg_model_get_submesh_index( mdl,"icon_story2d");
+ gui.icon_submeshes[ k_gui_icon_story_done2d ]= vg_model_get_submesh_index( mdl,"icon_story_done2d");
+}
+
+VG_API void _gui_init(void)
+{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_gui_load_content_async );
+}
+
+VG_API bool _gui_helpers_active(void)
+{
+ return gui.helper_count > 0;
+}
-#pragma once
-#include "font.h"
-#include "input.h"
-#include "player.h"
-#include "vg/vg_engine.h"
-#include "vg/vg_ui/imgui.h"
-
+#if defined( SR_IMPLEMENTATION )
+# include "src/gui.c"
+#else
#define GUI_COL_DARK ui_opacity( 0x00000000, 0.7f )
#define GUI_COL_NORM ui_opacity( 0x00101010, 0.7f )
#define GUI_COL_ACTIVE ui_opacity( 0x00444444, 0.7f )
#define GUI_COL_CLICK ui_opacity( 0x00858585, 0.7f )
#define GUI_COL_HI ui_opacity( 0x00ffffff, 0.8f )
-enum gui_icon {
+enum gui_helper_mode
+{
+ k_gui_helper_mode_default,
+ k_gui_helper_mode_black_bars,
+ k_gui_helper_mode_clear
+};
+
+enum gui_icon
+{
k_gui_icon_tick1 = 0,
k_gui_icon_tick2,
k_gui_icon_run,
k_gui_icon_spawn_select,
k_gui_icon_story2d,
k_gui_icon_story_done2d,
-
k_gui_icon_count,
};
-#define GUI_HELPER_TEXT_LENGTH 32
-
-struct
-{
- struct gui_helper
- {
- vg_input_op *binding;
- char text[GUI_HELPER_TEXT_LENGTH];
- int greyed;
- }
- helpers[4];
- u32 helper_count;
-
- enum gui_helper_mode
- {
- k_gui_helper_mode_default,
- k_gui_helper_mode_black_bars,
- k_gui_helper_mode_clear
- }
- helper_mode;
-
- struct gui_notifier
- {
- const char *string;
- f32 duration, time_left; /* seconds */
- u32 colour;
- }
- notifiers[ 4 ];
-
- struct icon_call
- {
- enum gui_icon icon;
- v4f location;
- v4f colour;
- int colour_changed;
- }
- icon_draw_buffer[64];
- u32 icon_draw_count;
- v4f cur_icon_colour;
- int colour_changed;
-
- char location[64];
- f64 location_time;
-
- f32 factive;
- font3d font;
-
- v3f trick_co;
-
- mdl_context model_icons;
- GLuint icons_texture;
- glmesh icons_mesh;
-
- i32 icon_submeshes[ k_gui_icon_count ];
-}
-static gui = {.cur_icon_colour = {1.0f,1.0f,1.0f,1.0f},.colour_changed=1};
-
-void gui_notify( const char *string, f32 duration, u32 colour )
-{
- // JINGLE SOME KEYS HERE
- // JINGLE SOME KEYS HERE
- // JINGLE SOME KEYS HERE
- // JINGLE SOME KEYS HERE
- // JINGLE SOME KEYS HERE
- struct gui_notifier *notifier = NULL;
- for( u32 i=0; i<VG_ARRAY_LEN(gui.notifiers); i ++ )
- {
- notifier = &gui.notifiers[i];
- if( notifier->time_left > 0.0f )
- {
- notifier = NULL;
- continue;
- }
- else break;
- }
-
- if( !notifier )
- return;
-
- notifier->string = string;
- notifier->duration = duration;
- notifier->time_left = duration;
- notifier->colour = colour;
-}
-
-static void gui_helper_reset( enum gui_helper_mode mode )
-{
- gui.helper_count = 0;
- gui.helper_mode = mode;
-}
-
-static struct gui_helper *gui_new_helper( vg_input_op *bind, vg_str *out_text )
-{
- if( gui.helper_count >= VG_ARRAY_LEN(gui.helpers) ){
- vg_error( "Too many helpers\n" );
- return NULL;
- }
-
- struct gui_helper *helper = &gui.helpers[ gui.helper_count ++ ];
- helper->greyed = 0;
- helper->binding = bind;
- vg_strnull( out_text, helper->text, sizeof(helper->text) );
- return helper;
-}
-
-static void gui_render_icons(void)
-{
- vg_camera ortho;
-
- float fl = 0.0f,
- fr = vg.window_x,
- fb = 0.0f,
- ft = vg.window_y,
- rl = 1.0f / (fr-fl),
- tb = 1.0f / (ft-fb);
-
- m4x4_zero( ortho.mtx.p );
- ortho.mtx.p[0][0] = 2.0f * rl;
- ortho.mtx.p[1][1] = 2.0f * tb;
- ortho.mtx.p[3][0] = (fr + fl) * -rl;
- ortho.mtx.p[3][1] = (ft + fb) * -tb;
- ortho.mtx.p[3][3] = 1.0f;
- m4x3_identity( ortho.transform );
- vg_camera_update_view( &ortho );
- m4x4_mul( ortho.mtx.p, ortho.mtx.v, ortho.mtx.pv ); /* HACK */
- vg_camera_finalize( &ortho );
-
- /* icons */
- font3d_bind( &gui.font, k_font_shader_default, 0, NULL, &ortho );
- mesh_bind( &gui.icons_mesh );
-
- m4x3f mmdl;
- m4x3_identity( mmdl );
- shader_model_font_uMdl( mmdl );
-
- glActiveTexture( GL_TEXTURE0 );
- glBindTexture( GL_TEXTURE_2D, gui.icons_texture );
- shader_model_font_uTexMain( 0 );
-
- for( u32 i=0; i<gui.icon_draw_count; i++ )
- {
- struct icon_call *call = &gui.icon_draw_buffer[i];
-
- if( call->colour_changed )
- shader_model_font_uColour( call->colour );
- shader_model_font_uOffset( call->location );
-
- i32 index = gui.icon_submeshes[ call->icon ];
- mdl_submesh *sm = &gui.model_icons.submeshes[ index ];
- if( sm )
- mdl_draw_submesh( sm );
- }
-
- gui.icon_draw_count = 0;
-}
-
-static void gui_draw( ui_context *ctx )
-{
- /* helpers
- * ----------------------------------------------------------------- */
-
- gui.factive = vg_lerpf( gui.factive, gui.helper_count?1.0f:0.0f, vg.time_frame_delta*2.0f );
-
- {
- ui_px y = 80;
- ui_px w = 360, h = 60;
- ctx->font = &vgf_default_large;
- for( u32 i=0; i<VG_ARRAY_LEN(gui.notifiers); i ++ )
- {
- struct gui_notifier *notifier = &gui.notifiers[i];
- notifier->time_left -= vg.time_frame_delta;
- if( notifier->time_left > 0.0f )
- {
- const float k_trans = 0.2;
- float t0 = notifier->time_left,
- t1 = notifier->duration - t0,
- t = vg_smoothstepf( vg_minf( vg_minf( k_trans, t0 ), t1 ) / k_trans ),
- x = (f32)(w+8) * t;
- ui_rect box = { vg.window_x - (ui_px)x, y, w, h };
- ui_fill( ctx, box, ui_opacity( GUI_COL_DARK, t*0.6f ) );
- ui_outline( ctx, box, 1, ui_opacity( GUI_COL_NORM, t*0.6f ), 0 );
- ui_text( ctx, box, notifier->string, 1, k_ui_align_middle_center, ui_colour( ctx, notifier->colour ) );
- }
- y += h + 8;
- }
- }
-
- if( _cutscene.state >= k_cutscene_state_ready )
- {
- ctx->font = &vgf_default_small;
- return;
- }
-
- ctx->font = &vgf_default_title;
- ui_px height = ctx->font->ch + 16;
- ui_rect lwr = { 0, vg.window_y - height, vg.window_x, height };
-
- ui_px x = 0;
- for( u32 i=0; i<gui.helper_count; i++ )
- {
- struct gui_helper *helper = &gui.helpers[i];
-
- char buf[128];
- vg_str str;
- vg_strnull( &str, buf, sizeof(buf) );
- vg_input_string( &str, helper->binding, 1 );
-
- ui_rect box = { x, lwr[1], 1000, lwr[3] };
-
- u32 fg = 0;
- f32 opacity = 0.4f;
- if( helper->greyed )
- {
- fg = ui_colour(ctx, k_ui_fg+2);
- opacity = 0.1f;
- }
-
- struct ui_vert *bg = ui_fill( ctx, box, ui_opacity( GUI_COL_DARK, opacity ) );
- u32 w;
- box[0] += 16;
- w = ui_text( ctx, box, buf, 1, k_ui_align_middle_left, fg );
- w *= ctx->font->sx;
- bg[1].co[0] = x + w + 32;
- bg[2].co[0] = x + w + 32;
- x += w + 32;
-
- box[0] = x;
- bg = ui_fill( ctx, box, ui_opacity( GUI_COL_NORM, opacity*0.7f ) );
- box[0] += 8;
- w = ui_text( ctx, box, helper->text, 1, k_ui_align_middle_left, fg );
- w *= ctx->font->sx;
- bg[1].co[0] = box[0] + w + 16;
- bg[2].co[0] = box[0] + w + 16;
- x += w + 32;
- }
-
- if( (gui.helper_mode == k_gui_helper_mode_black_bars) && gui.helper_count )
- {
- ui_rect box = { x, lwr[1], vg.window_x - x, height };
- ui_fill( ctx, box, ui_opacity( GUI_COL_DARK, 0.4f ) );
-
- box[0] = 0;
- box[1] = 0;
- box[2] = vg.window_x;
- ui_fill( ctx, box, ui_opacity( GUI_COL_DARK, 0.4f ) );
- }
-
- vg_ui.frosting = gui.factive*0.015f;
- ui_flush( ctx, k_ui_shader_colour, NULL );
- vg_ui.frosting = 0.0f;
-
- f64 loc_t = (vg.time_real - gui.location_time) / 5.0;
- if( (loc_t < 1.0) && (gui.location_time != 0.0) )
- {
- f32 t = 1.0f-vg_minf(1.0f,vg_minf(loc_t*20.0f,2.0f-loc_t*2.0f)),
- o = 1.0f-t*t*(2.0f-t);
-
- ui_rect box = { 0, (vg.window_y*2)/3 - height/2, vg.window_x, height };
- ui_fill( ctx, box, ui_opacity( GUI_COL_NORM, 0.5f ) );
- ui_text( ctx, box, gui.location, 1, k_ui_align_middle_center, 0 );
-
- vg_ui.colour[3] = o;
- ui_flush( ctx, k_ui_shader_colour, NULL );
- }
-
- vg_ui.colour[3] = 1.0f;
- ctx->font = &vgf_default_small;
-}
-
-static int gui_location_print_ccmd( int argc, const char *argv[] )
-{
- if( argc > 0 )
- {
- char new_loc[64];
- vg_str str;
- vg_strnull( &str, new_loc, 64 );
- for( int i=0; i<argc; i++ )
- {
- vg_strcat( &str, argv[i] );
- vg_strcat( &str, " " );
- }
- if( !strcmp(gui.location,new_loc) ) return 0;
- vg_strncpy( new_loc, gui.location, 64, k_strncpy_always_add_null );
- gui.location_time = vg.time_real;
- }
- return 0;
-}
-
-static void gui_draw_icon( enum gui_icon icon, v2f co, f32 size )
-{
- if( gui.icon_draw_count == VG_ARRAY_LEN(gui.icon_draw_buffer) )
- return;
-
- struct icon_call *call = &gui.icon_draw_buffer[ gui.icon_draw_count ++ ];
-
- call->icon = icon;
- call->location[0] = co[0] * (f32)vg.window_x;
- call->location[1] = co[1] * (f32)vg.window_y;
- call->location[2] = 0.0f;
- call->location[3] = size * (f32)vg.window_x;
-
- v4_copy( gui.cur_icon_colour, call->colour );
- call->colour_changed = gui.colour_changed;
- gui.colour_changed = 0;
-}
-
-static void gui_icon_setcolour( v4f colour ){
- gui.colour_changed = 1;
- v4_copy( colour, gui.cur_icon_colour );
-}
-
-void gui_register(void)
-{
- vg_console_reg_cmd( "gui_location", gui_location_print_ccmd, NULL );
-}
-
-static void gui_init(void)
-{
- THREAD_1;
- font3d_load( &gui.font, "models/rs_font.mdl", &vg.rtmem );
+VG_API void _gui_register(void);
+VG_API void _gui_init(void);
- /* load icons */
- mdl_context *mdl = &gui.model_icons;
- mdl_open( mdl, "models/rs_icons.mdl", &vg.rtmem );
- mdl_load_metadata_block( mdl, &vg.rtmem );
+VG_API struct gui_helper *_gui_new_helper( vg_input_op *bind, vg_str *out_text );
+VG_API void _gui_helper_reset( enum gui_helper_mode mode );
+VG_API void _gui_notify( const char *string, f32 duration, u32 colour );
- gui.icon_submeshes[ k_gui_icon_tick1 ] = mdl_get_submesh_index( mdl, "icon_tick1" );
- gui.icon_submeshes[ k_gui_icon_tick2 ] = mdl_get_submesh_index( mdl, "icon_tick2" );
- gui.icon_submeshes[ k_gui_icon_run ] = mdl_get_submesh_index( mdl, "icon_run" );
- gui.icon_submeshes[ k_gui_icon_challenge ] = mdl_get_submesh_index( mdl, "icon_challenge" );
- gui.icon_submeshes[ k_gui_icon_exclaim ] = mdl_get_submesh_index( mdl, "icon_exclaim" );
- gui.icon_submeshes[ k_gui_icon_board ] = mdl_get_submesh_index( mdl, "icon_board" );
- gui.icon_submeshes[ k_gui_icon_world ] = mdl_get_submesh_index( mdl, "icon_world" );
- gui.icon_submeshes[ k_gui_icon_rift ] = mdl_get_submesh_index( mdl, "icon_rift" );
- gui.icon_submeshes[ k_gui_icon_rift_run ] = mdl_get_submesh_index( mdl, "icon_rift_run" );
- gui.icon_submeshes[ k_gui_icon_rift_run_2d ] = mdl_get_submesh_index( mdl, "icon_rift_run2d" );
- gui.icon_submeshes[ k_gui_icon_friend ] = mdl_get_submesh_index( mdl, "icon_friend" );
- gui.icon_submeshes[ k_gui_icon_player ] = mdl_get_submesh_index( mdl, "icon_player" );
- gui.icon_submeshes[ k_gui_icon_player2d ] = mdl_get_submesh_index( mdl, "icon_player2d" );
- gui.icon_submeshes[ k_gui_icon_glider ] = mdl_get_submesh_index( mdl, "icon_glider" );
- gui.icon_submeshes[ k_gui_icon_spawn ] = mdl_get_submesh_index( mdl, "icon_spawn" );
- gui.icon_submeshes[ k_gui_icon_spawn_select ] = mdl_get_submesh_index( mdl, "icon_spawn_select" );
- gui.icon_submeshes[ k_gui_icon_rift_run_gold ] = mdl_get_submesh_index( mdl,"icon_rift_run_medal_gold");
- gui.icon_submeshes[ k_gui_icon_rift_run_silver]= mdl_get_submesh_index( mdl,"icon_rift_run_medal_silver");
- gui.icon_submeshes[ k_gui_icon_story2d ]= mdl_get_submesh_index( mdl,"icon_story2d");
- gui.icon_submeshes[ k_gui_icon_story_done2d ]= mdl_get_submesh_index( mdl,"icon_story_done2d");
+VG_API void _gui_draw( ui_context *ctx );
+VG_API void _gui_render_icons(void);
+VG_API bool _gui_helpers_active(void);
- vg_stack_clear( &vg.scratch );
- if( !gui.model_icons.texture_count )
- vg_fatal_error( "No texture in menu file" );
- mdl_texture *tex0 = &gui.model_icons.textures[ 0 ];
- void *data = vg_stack_allocate( &vg.scratch, tex0->file.pack_size, 8, "Pack data" );
- mdl_fread_pack_file( &gui.model_icons, &tex0->file, data );
- vg_tex2d_load_qoi_async( data, tex0->file.pack_size, VG_TEX2D_LINEAR|VG_TEX2D_CLAMP, &gui.icons_texture );
- mdl_async_load_glmesh( &gui.model_icons, &gui.icons_mesh, NULL );
- mdl_close( &gui.model_icons );
-}
+#endif
--- /dev/null
+#define INPUT_BASIC( KB, JS ) \
+ (vg_input_op[]){vg_keyboard, KB, vg_joy_button, JS, vg_end}
+
+// TODO: This can probably be converted into a KV file and then compiled down into the vg_input ops.. ?
+static vg_input_op *input_button_list[] = {
+[k_srbind_jump] = INPUT_BASIC( SDLK_SPACE, SDL_CONTROLLER_BUTTON_A ),
+[k_srbind_push] = INPUT_BASIC( SDLK_w, SDL_CONTROLLER_BUTTON_B ),
+[k_srbind_trick0] = (vg_input_op[]){
+ vg_mouse, SDL_BUTTON_LEFT,
+ vg_joy_button, SDL_CONTROLLER_BUTTON_A, vg_end
+},
+[k_srbind_trick1] = (vg_input_op[]){
+ vg_mouse, SDL_BUTTON_RIGHT,
+ vg_joy_button, SDL_CONTROLLER_BUTTON_B, vg_end
+},
+[k_srbind_trick2] = (vg_input_op[]){
+ vg_mouse, SDL_BUTTON_LEFT, vg_mode_mul, vg_mouse, SDL_BUTTON_RIGHT,
+ vg_mode_absmax, vg_joy_button, SDL_CONTROLLER_BUTTON_X, vg_end
+},
+[k_srbind_skate] = INPUT_BASIC( SDLK_e, SDL_CONTROLLER_BUTTON_Y ),
+[k_srbind_use] = INPUT_BASIC( SDLK_e, SDL_CONTROLLER_BUTTON_X ),
+[k_srbind_reset] = INPUT_BASIC( SDLK_r, SDL_CONTROLLER_BUTTON_DPAD_UP ),
+[k_srbind_camera]= INPUT_BASIC( SDLK_c, SDL_CONTROLLER_BUTTON_DPAD_RIGHT ),
+[k_srbind_mleft] = INPUT_BASIC( SDLK_LEFT, SDL_CONTROLLER_BUTTON_DPAD_LEFT ),
+[k_srbind_mright]= INPUT_BASIC( SDLK_RIGHT, SDL_CONTROLLER_BUTTON_DPAD_RIGHT ),
+[k_srbind_world_left] = INPUT_BASIC( SDLK_LEFT, SDL_CONTROLLER_BUTTON_DPAD_LEFT ),
+[k_srbind_world_right]= INPUT_BASIC( SDLK_RIGHT, SDL_CONTROLLER_BUTTON_DPAD_RIGHT ),
+[k_srbind_mup] = INPUT_BASIC( SDLK_UP, SDL_CONTROLLER_BUTTON_DPAD_UP ),
+[k_srbind_mdown] = INPUT_BASIC( SDLK_DOWN, SDL_CONTROLLER_BUTTON_DPAD_DOWN ),
+[k_srbind_mback] = INPUT_BASIC( SDLK_ESCAPE, SDL_CONTROLLER_BUTTON_B ),
+[k_srbind_mopen] = INPUT_BASIC( SDLK_ESCAPE, SDL_CONTROLLER_BUTTON_START ),
+[k_srbind_mquick] = INPUT_BASIC( SDLK_q, SDL_CONTROLLER_BUTTON_DPAD_LEFT ),
+[k_srbind_mclose]= (vg_input_op[]){ vg_joy_button, SDL_CONTROLLER_BUTTON_START, vg_end },
+[k_srbind_mhub] = INPUT_BASIC( SDLK_h, SDL_CONTROLLER_BUTTON_Y ),
+[k_srbind_maccept] = (vg_input_op[]){
+ vg_keyboard, SDLK_e, vg_gui_visible, 0,
+ vg_keyboard, SDLK_RETURN, vg_keyboard, SDLK_RETURN2,
+ vg_gui_visible, 1,
+ vg_joy_button, SDL_CONTROLLER_BUTTON_A, vg_end
+},
+[k_srbind_replay_play] = INPUT_BASIC( SDLK_SPACE, SDL_CONTROLLER_BUTTON_A ),
+[k_srbind_replay_resume] = (vg_input_op[]){vg_end},//INPUT_BASIC( SDLK_SPACE, SDL_CONTROLLER_BUTTON_ ),
+[k_srbind_replay_freecam] = INPUT_BASIC( SDLK_f, SDL_CONTROLLER_BUTTON_Y ),
+[k_srbind_replay_hide_ui] = INPUT_BASIC( SDLK_h, SDL_CONTROLLER_BUTTON_X ),
+[k_srbind_sit] = INPUT_BASIC( SDLK_z, SDL_CONTROLLER_BUTTON_B ),
+[k_srbind_lobby] = INPUT_BASIC( SDLK_TAB, SDL_CONTROLLER_BUTTON_DPAD_LEFT ),
+[k_srbind_chat ] = (vg_input_op[]){ vg_keyboard, SDLK_y, vg_end },
+[k_srbind_run ] = (vg_input_op[]){ vg_keyboard, SDLK_LSHIFT,
+ vg_joy_axis, SDL_CONTROLLER_AXIS_TRIGGERLEFT, vg_end },
+
+[k_srbind_miniworld_resume] = (vg_input_op[]){
+ vg_keyboard, SDLK_RETURN, vg_gui_visible, 0,
+ vg_keyboard, SDLK_RETURN2,
+ vg_gui_visible, 1,
+ vg_joy_button, SDL_CONTROLLER_BUTTON_X, vg_end
+},
+[k_srbind_miniworld_teleport]= INPUT_BASIC( SDLK_q,
+ SDL_CONTROLLER_BUTTON_LEFTSHOULDER ),
+[k_srbind_skid] = (vg_input_op[]){ vg_keyboard, SDLK_LCTRL, vg_end },
+[k_srbind_devbutton] = (vg_input_op[]){ vg_keyboard, SDLK_3, vg_end },
+[k_srbind_max]=NULL
+};
+
+static vg_input_op *input_axis_list[] = {
+[k_sraxis_grab] = (vg_input_op[]){
+ vg_keyboard, SDLK_LSHIFT,
+ vg_joy_axis, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, vg_end
+},
+[k_sraxis_mbrowse_h] = (vg_input_op[]){
+ vg_mode_sub, vg_keyboard, SDLK_LEFT,
+ vg_mode_add, vg_keyboard, SDLK_RIGHT,
+ vg_mode_add, vg_joy_axis, SDL_CONTROLLER_AXIS_LEFTX,
+ vg_end
+},
+[k_sraxis_mbrowse_v] = (vg_input_op[]){
+ vg_mode_sub, vg_keyboard, SDLK_DOWN,
+ vg_mode_add, vg_keyboard, SDLK_UP,
+ vg_mode_sub, vg_joy_axis, SDL_CONTROLLER_AXIS_LEFTY,
+ vg_end
+},
+[k_sraxis_replay_h] = (vg_input_op[]){
+ vg_mode_sub, vg_keyboard, SDLK_q,
+ vg_mode_add, vg_keyboard, SDLK_e,
+ vg_mode_sub, vg_joy_axis, SDL_CONTROLLER_AXIS_TRIGGERLEFT,
+ vg_mode_add, vg_joy_axis, SDL_CONTROLLER_AXIS_TRIGGERRIGHT,
+ vg_end
+},
+[k_sraxis_skid] = (vg_input_op[]){
+ vg_mode_sub, vg_joy_button, SDL_CONTROLLER_BUTTON_LEFTSHOULDER,
+ vg_mode_add, vg_joy_button, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER,
+ vg_end
+},
+[k_sraxis_max]=NULL
+};
+
+static vg_input_op *input_joy_list[] = {
+[k_srjoystick_steer] = (vg_input_op[]){
+ vg_index, 0, vg_mode_sub, vg_keyboard, SDLK_a,
+ vg_mode_add, vg_keyboard, SDLK_d,
+ vg_index, 1, vg_mode_sub, vg_keyboard, SDLK_w,
+ vg_mode_add, vg_keyboard, SDLK_s,
+ vg_mode_absmax, vg_joy_ls,
+ vg_end
+},
+[k_srjoystick_grab] = (vg_input_op[]){
+ vg_joy_rs, vg_end
+},
+[k_srjoystick_look] = (vg_input_op[]){
+ vg_joy_rs, vg_end
+},
+[k_srjoystick_max]=NULL
+};
+
+struct
+{
+ float axis_states[ k_sraxis_max ][2];
+ v2f joystick_states[ k_srjoystick_max ][2];
+ u8 button_states[ k_srbind_max ][2];
+
+ enum input_state
+ {
+ k_input_state_enabled,
+ k_input_state_resume,
+ k_input_state_resuming,
+ k_input_state_pause
+ }
+ state;
+}
+static srinput;
+
+static bool input_filter_generic(void)
+{
+ if( (srinput.state != k_input_state_enabled) || vg_console.enabled || (workshop_form.page != k_workshop_form_hidden) )
+ return 1;
+ else
+ return 0;
+}
+
+static bool buttons_filter_fixed(void)
+{
+ if( input_filter_generic() )
+ return 1;
+ if( vg.gameloop_stage == k_gameloop_update_fixed )
+ if( vg.fixed_iterations > 0 )
+ return 1;
+
+ return 0;
+}
+
+/* Rising edge of button */
+bool button_down( enum sr_bind button )
+{
+ if( buttons_filter_fixed() )
+ return 0;
+
+ if( (skaterift.activity == k_skaterift_menu) &&
+ (button < k_srbind_mopen) &&
+ (vg_input.display_input_method != k_input_method_kbm) )
+ return 0;
+
+ if( srinput.button_states[ button ][0] && !srinput.button_states[ button ][1] )
+ return 1;
+
+ return 0;
+}
+
+/* Falling edge of button */
+bool button_up( enum sr_bind button )
+{
+ if( buttons_filter_fixed() )
+ return 0;
+
+ if( (skaterift.activity == k_skaterift_menu) &&
+ (button < k_srbind_mopen) &&
+ (vg_input.display_input_method != k_input_method_kbm) )
+ return 0;
+
+ if( !srinput.button_states[ button ][0] && srinput.button_states[ button ][1] )
+ return 1;
+
+ return 0;
+}
+
+/* State of button */
+bool button_press( enum sr_bind button )
+{
+ if( input_filter_generic() )
+ return 0;
+
+ if( (skaterift.activity == k_skaterift_menu) &&
+ (button < k_srbind_mopen) &&
+ (vg_input.display_input_method != k_input_method_kbm))
+ return 0;
+
+ return srinput.button_states[ button ][0];
+}
+
+void joystick_state( enum sr_joystick joystick, v2f state )
+{
+ /* TODO: This fucking sucks */
+ if( (skaterift.activity == k_skaterift_menu) && (vg_input.display_input_method != k_input_method_kbm) &&
+ (menu.main_index != k_menu_main_map) &&
+ !((menu.main_index == k_menu_main_online) && menu.choosing_country ) )
+ {
+ v2_zero( state );
+ return;
+ }
+
+ if( input_filter_generic() )
+ v2_zero( state );
+ else
+ v2_copy( srinput.joystick_states[ joystick ][0], state );
+}
+
+f32 axis_state( enum sr_axis axis )
+{
+ if( (skaterift.activity == k_skaterift_menu) &&
+ (axis < k_sraxis_mbrowse_h ) &&
+ (vg_input.display_input_method != k_input_method_kbm))
+ return 0;
+
+ if( input_filter_generic() )
+ return 0.0f;
+
+ return srinput.axis_states[axis][0];
+}
+
+void skaterift_preupdate_inputs(void)
+{
+ if( srinput.state == k_input_state_resuming )
+ srinput.state = k_input_state_enabled;
+
+ if( srinput.state == k_input_state_resume )
+ srinput.state = k_input_state_resuming;
+
+ for( u32 i=0; i<k_srbind_max; i++ )
+ {
+ srinput.button_states[i][1] = srinput.button_states[i][0];
+ srinput.button_states[i][0] = 0;
+ }
+
+ for( u32 i=0; i<k_srjoystick_max; i++ )
+ {
+ v2_copy( srinput.joystick_states[i][0], srinput.joystick_states[i][1] );
+ v2_zero( srinput.joystick_states[i][0] );
+ }
+
+ for( u32 i=0; i<k_sraxis_max; i++ )
+ {
+ srinput.axis_states[i][1] = srinput.axis_states[i][0];
+ srinput.axis_states[i][0] = 0.0f;
+ }
+
+ for( int i=0; i<k_srbind_max; i++ )
+ {
+ vg_input_op *prog = input_button_list[i];
+ if( prog )
+ vg_exec_input_program( k_vg_input_type_button_u8, prog, &srinput.button_states[i][0] );
+ }
+
+ for( int i=0; i<k_sraxis_max; i++ )
+ {
+ vg_input_op *prog = input_axis_list[i];
+ if( prog )
+ vg_exec_input_program( k_vg_input_type_axis_f32, prog, &srinput.axis_states[i][0] );
+ }
+
+ for( int i=0; i<k_srjoystick_max; i++ )
+ {
+ vg_input_op *prog = input_joy_list[i];
+ if( prog )
+ vg_exec_input_program( k_vg_input_type_joy_v2f, prog, srinput.joystick_states[i][0] );
+ }
+
+ f32 x = srinput.axis_states[k_sraxis_mbrowse_h][0],
+ y = srinput.axis_states[k_sraxis_mbrowse_v][0],
+ sensitivity = 0.35f;
+
+ if( fabsf(x) > sensitivity )
+ {
+ if( x > 0.0f ) srinput.button_states[k_srbind_mright][0] = 1;
+ else srinput.button_states[k_srbind_mleft][0] = 1;
+ }
+
+ if( fabsf(y) > sensitivity )
+ {
+ if( y > 0.0f ) srinput.button_states[k_srbind_mup][0] = 1;
+ else srinput.button_states[k_srbind_mdown][0] = 1;
+ }
+}
-#pragma once
-#include "vg/vg_platform.h"
-#include "vg/vg_console.h"
-#include "vg/vg_input.h"
-#include "vg/vg_m.h"
-#include "font.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/input.c"
+#else
enum sr_bind
{
k_sraxis_max
};
+bool button_down( enum sr_bind button );
+bool button_up( enum sr_bind button );
+bool button_press( enum sr_bind button );
+void joystick_state( enum sr_joystick joystick, v2f state );
+f32 axis_state( enum sr_axis axis );
+void skaterift_preupdate_inputs(void);
-#define INPUT_BASIC( KB, JS ) \
- (vg_input_op[]){vg_keyboard, KB, vg_joy_button, JS, vg_end}
-
-static vg_input_op *input_button_list[] = {
-[k_srbind_jump] = INPUT_BASIC( SDLK_SPACE, SDL_CONTROLLER_BUTTON_A ),
-[k_srbind_push] = INPUT_BASIC( SDLK_w, SDL_CONTROLLER_BUTTON_B ),
-[k_srbind_trick0] = (vg_input_op[]){
- vg_mouse, SDL_BUTTON_LEFT,
- vg_joy_button, SDL_CONTROLLER_BUTTON_A, vg_end
-},
-[k_srbind_trick1] = (vg_input_op[]){
- vg_mouse, SDL_BUTTON_RIGHT,
- vg_joy_button, SDL_CONTROLLER_BUTTON_B, vg_end
-},
-[k_srbind_trick2] = (vg_input_op[]){
- vg_mouse, SDL_BUTTON_LEFT, vg_mode_mul, vg_mouse, SDL_BUTTON_RIGHT,
- vg_mode_absmax, vg_joy_button, SDL_CONTROLLER_BUTTON_X, vg_end
-},
-[k_srbind_skate] = INPUT_BASIC( SDLK_e, SDL_CONTROLLER_BUTTON_Y ),
-[k_srbind_use] = INPUT_BASIC( SDLK_e, SDL_CONTROLLER_BUTTON_X ),
-[k_srbind_reset] = INPUT_BASIC( SDLK_r, SDL_CONTROLLER_BUTTON_DPAD_UP ),
-[k_srbind_camera]= INPUT_BASIC( SDLK_c, SDL_CONTROLLER_BUTTON_DPAD_RIGHT ),
-[k_srbind_mleft] = INPUT_BASIC( SDLK_LEFT, SDL_CONTROLLER_BUTTON_DPAD_LEFT ),
-[k_srbind_mright]= INPUT_BASIC( SDLK_RIGHT, SDL_CONTROLLER_BUTTON_DPAD_RIGHT ),
-[k_srbind_world_left] = INPUT_BASIC( SDLK_LEFT, SDL_CONTROLLER_BUTTON_DPAD_LEFT ),
-[k_srbind_world_right]= INPUT_BASIC( SDLK_RIGHT, SDL_CONTROLLER_BUTTON_DPAD_RIGHT ),
-[k_srbind_mup] = INPUT_BASIC( SDLK_UP, SDL_CONTROLLER_BUTTON_DPAD_UP ),
-[k_srbind_mdown] = INPUT_BASIC( SDLK_DOWN, SDL_CONTROLLER_BUTTON_DPAD_DOWN ),
-[k_srbind_mback] = INPUT_BASIC( SDLK_ESCAPE, SDL_CONTROLLER_BUTTON_B ),
-[k_srbind_mopen] = INPUT_BASIC( SDLK_ESCAPE, SDL_CONTROLLER_BUTTON_START ),
-[k_srbind_mquick] = INPUT_BASIC( SDLK_q, SDL_CONTROLLER_BUTTON_DPAD_LEFT ),
-[k_srbind_mclose]= (vg_input_op[]){ vg_joy_button, SDL_CONTROLLER_BUTTON_START, vg_end },
-[k_srbind_mhub] = INPUT_BASIC( SDLK_h, SDL_CONTROLLER_BUTTON_Y ),
-[k_srbind_maccept] = (vg_input_op[]){
- vg_keyboard, SDLK_e, vg_gui_visible, 0,
- vg_keyboard, SDLK_RETURN, vg_keyboard, SDLK_RETURN2,
- vg_gui_visible, 1,
- vg_joy_button, SDL_CONTROLLER_BUTTON_A, vg_end
-},
-[k_srbind_replay_play] = INPUT_BASIC( SDLK_SPACE, SDL_CONTROLLER_BUTTON_A ),
-[k_srbind_replay_resume] = (vg_input_op[]){vg_end},//INPUT_BASIC( SDLK_SPACE, SDL_CONTROLLER_BUTTON_ ),
-[k_srbind_replay_freecam] = INPUT_BASIC( SDLK_f, SDL_CONTROLLER_BUTTON_Y ),
-[k_srbind_replay_hide_ui] = INPUT_BASIC( SDLK_h, SDL_CONTROLLER_BUTTON_X ),
-[k_srbind_sit] = INPUT_BASIC( SDLK_z, SDL_CONTROLLER_BUTTON_B ),
-[k_srbind_lobby] = INPUT_BASIC( SDLK_TAB, SDL_CONTROLLER_BUTTON_DPAD_LEFT ),
-[k_srbind_chat ] = (vg_input_op[]){ vg_keyboard, SDLK_y, vg_end },
-[k_srbind_run ] = (vg_input_op[]){ vg_keyboard, SDLK_LSHIFT,
- vg_joy_axis, SDL_CONTROLLER_AXIS_TRIGGERLEFT, vg_end },
-
-[k_srbind_miniworld_resume] = (vg_input_op[]){
- vg_keyboard, SDLK_RETURN, vg_gui_visible, 0,
- vg_keyboard, SDLK_RETURN2,
- vg_gui_visible, 1,
- vg_joy_button, SDL_CONTROLLER_BUTTON_X, vg_end
-},
-[k_srbind_miniworld_teleport]= INPUT_BASIC( SDLK_q,
- SDL_CONTROLLER_BUTTON_LEFTSHOULDER ),
-[k_srbind_skid] = (vg_input_op[]){ vg_keyboard, SDLK_LCTRL, vg_end },
-[k_srbind_devbutton] = (vg_input_op[]){ vg_keyboard, SDLK_3, vg_end },
-[k_srbind_max]=NULL
-};
-
-static vg_input_op *input_axis_list[] = {
-[k_sraxis_grab] = (vg_input_op[]){
- vg_keyboard, SDLK_LSHIFT,
- vg_joy_axis, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, vg_end
-},
-[k_sraxis_mbrowse_h] = (vg_input_op[]){
- vg_mode_sub, vg_keyboard, SDLK_LEFT,
- vg_mode_add, vg_keyboard, SDLK_RIGHT,
- vg_mode_add, vg_joy_axis, SDL_CONTROLLER_AXIS_LEFTX,
- vg_end
-},
-[k_sraxis_mbrowse_v] = (vg_input_op[]){
- vg_mode_sub, vg_keyboard, SDLK_DOWN,
- vg_mode_add, vg_keyboard, SDLK_UP,
- vg_mode_sub, vg_joy_axis, SDL_CONTROLLER_AXIS_LEFTY,
- vg_end
-},
-[k_sraxis_replay_h] = (vg_input_op[]){
- vg_mode_sub, vg_keyboard, SDLK_q,
- vg_mode_add, vg_keyboard, SDLK_e,
- vg_mode_sub, vg_joy_axis, SDL_CONTROLLER_AXIS_TRIGGERLEFT,
- vg_mode_add, vg_joy_axis, SDL_CONTROLLER_AXIS_TRIGGERRIGHT,
- vg_end
-},
-[k_sraxis_skid] = (vg_input_op[]){
- vg_mode_sub, vg_joy_button, SDL_CONTROLLER_BUTTON_LEFTSHOULDER,
- vg_mode_add, vg_joy_button, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER,
- vg_end
-},
-[k_sraxis_max]=NULL
-};
-
-static vg_input_op *input_joy_list[] = {
-[k_srjoystick_steer] = (vg_input_op[]){
- vg_index, 0, vg_mode_sub, vg_keyboard, SDLK_a,
- vg_mode_add, vg_keyboard, SDLK_d,
- vg_index, 1, vg_mode_sub, vg_keyboard, SDLK_w,
- vg_mode_add, vg_keyboard, SDLK_s,
- vg_mode_absmax, vg_joy_ls,
- vg_end
-},
-[k_srjoystick_grab] = (vg_input_op[]){
- vg_joy_rs, vg_end
-},
-[k_srjoystick_look] = (vg_input_op[]){
- vg_joy_rs, vg_end
-},
-[k_srjoystick_max]=NULL
-};
-
-struct
-{
- float axis_states[ k_sraxis_max ][2];
- v2f joystick_states[ k_srjoystick_max ][2];
- u8 button_states[ k_srbind_max ][2];
-
- enum input_state
- {
- k_input_state_enabled,
- k_input_state_resume,
- k_input_state_resuming,
- k_input_state_pause
- }
- state;
-}
-static srinput;
-
-static int input_filter_generic(void)
-{
- if( (srinput.state != k_input_state_enabled)
- || vg_console.enabled
- || (workshop_form.page != k_workshop_form_hidden) )
- return 1;
- else
- return 0;
-}
-
-static int buttons_filter_fixed(void)
-{
- if( input_filter_generic() )
- return 1;
- if( vg.engine_stage == k_engine_stage_update_fixed )
- if( vg.fixed_iterations > 0 )
- return 1;
-
- return 0;
-}
-
-/* Rising edge of button */
-static int button_down( enum sr_bind button )
-{
- if( buttons_filter_fixed() )
- return 0;
-
- if( (skaterift.activity == k_skaterift_menu) && (button < k_srbind_mopen) && (vg_input.display_input_method != k_input_method_kbm) )
- return 0;
-
- if( srinput.button_states[ button ][0] && !srinput.button_states[ button ][1] )
- return 1;
-
- return 0;
-}
-
-/* Falling edge of button */
-static int button_up( enum sr_bind button )
-{
- if( buttons_filter_fixed() )
- return 0;
-
- if( (skaterift.activity == k_skaterift_menu) && (button < k_srbind_mopen) && (vg_input.display_input_method != k_input_method_kbm) )
- return 0;
-
- if( !srinput.button_states[ button ][0] && srinput.button_states[ button ][1] )
- return 1;
-
- return 0;
-}
-
-/* State of button */
-static int button_press( enum sr_bind button )
-{
- if( input_filter_generic() )
- return 0;
-
- if( (skaterift.activity == k_skaterift_menu) && (button < k_srbind_mopen) && (vg_input.display_input_method != k_input_method_kbm))
- return 0;
-
- return srinput.button_states[ button ][0];
-}
-
-static void joystick_state( enum sr_joystick joystick, v2f state )
-{
- /* TODO: This fucking sucks */
- if( (skaterift.activity == k_skaterift_menu) && (vg_input.display_input_method != k_input_method_kbm) &&
- (menu.main_index != k_menu_main_map) &&
- !((menu.main_index == k_menu_main_online) && menu.choosing_country ) )
- {
- v2_zero( state );
- return;
- }
-
- if( input_filter_generic() )
- v2_zero( state );
- else
- v2_copy( srinput.joystick_states[ joystick ][0], state );
-}
-
-static float axis_state( enum sr_axis axis )
-{
- if( (skaterift.activity == k_skaterift_menu) &&
- (axis < k_sraxis_mbrowse_h ) &&
- (vg_input.display_input_method != k_input_method_kbm))
- return 0;
-
- if( input_filter_generic() )
- return 0.0f;
-
- return srinput.axis_states[axis][0];
-}
-
-static void skaterift_preupdate_inputs(void)
-{
- if( srinput.state == k_input_state_resuming )
- srinput.state = k_input_state_enabled;
-
- if( srinput.state == k_input_state_resume )
- srinput.state = k_input_state_resuming;
-
- for( u32 i=0; i<k_srbind_max; i++ )
- {
- srinput.button_states[i][1] = srinput.button_states[i][0];
- srinput.button_states[i][0] = 0;
- }
-
- for( u32 i=0; i<k_srjoystick_max; i++ )
- {
- v2_copy( srinput.joystick_states[i][0], srinput.joystick_states[i][1] );
- v2_zero( srinput.joystick_states[i][0] );
- }
-
- for( u32 i=0; i<k_sraxis_max; i++ )
- {
- srinput.axis_states[i][1] = srinput.axis_states[i][0];
- srinput.axis_states[i][0] = 0.0f;
- }
-
- for( int i=0; i<k_srbind_max; i++ )
- {
- vg_input_op *prog = input_button_list[i];
- if( prog )
- vg_exec_input_program( k_vg_input_type_button_u8, prog, &srinput.button_states[i][0] );
- }
-
- for( int i=0; i<k_sraxis_max; i++ )
- {
- vg_input_op *prog = input_axis_list[i];
- if( prog )
- vg_exec_input_program( k_vg_input_type_axis_f32, prog, &srinput.axis_states[i][0] );
- }
-
- for( int i=0; i<k_srjoystick_max; i++ )
- {
- vg_input_op *prog = input_joy_list[i];
- if( prog )
- vg_exec_input_program( k_vg_input_type_joy_v2f, prog, srinput.joystick_states[i][0] );
- }
-
- f32 x = srinput.axis_states[k_sraxis_mbrowse_h][0],
- y = srinput.axis_states[k_sraxis_mbrowse_v][0],
- sensitivity = 0.35f;
-
- if( fabsf(x) > sensitivity )
- {
- if( x > 0.0f ) srinput.button_states[k_srbind_mright][0] = 1;
- else srinput.button_states[k_srbind_mleft][0] = 1;
- }
-
- if( fabsf(y) > sensitivity )
- {
- if( y > 0.0f ) srinput.button_states[k_srbind_mup][0] = 1;
- else srinput.button_states[k_srbind_mdown][0] = 1;
- }
-}
+#endif
-#pragma once
-#include "skaterift.h"
-#include "menu.h"
-#include "model.h"
-#include "entity.h"
-#include "input.h"
-#include "world_map.h"
-#include "audio.h"
-#include "workshop.h"
-#include "gui.h"
-#include "control_overlay.h"
-#include "network.h"
-#include "shaders/model_menu.h"
-#include "ent_atom.h"
-
struct global_menu menu = { .skip_starter = 0, .prof_row = -1 };
void menu_at_begin(void)
return 1;
}
-void menu_register(void)
+VG_API void _menu_register(void)
{
vg_console_reg_var( "skip_starter_menu", &menu.skip_starter, k_var_dtype_i32, VG_VAR_PERSISTENT );
vg_console_reg_cmd( "menu_impromptu", cmd_menu_impromptu, NULL );
}
-void menu_init(void)
+static void _menu_load_content_async( void *_, vg_async_info *async )
+{
+ u32 flags = VG_TEX_CLAMP|VG_TEX_NOMIP|VG_TEX_NEAREST;
+ _vg_tex_load( &menu.prem_tex, "textures/prem.qoi", flags );
+ _vg_tex_load( &menu.guide_pump_tex, "textures/guide_pump.qoi", flags );
+ _vg_tex_load( &menu.guide_fliptrick_tex, "textures/guide_fliptrick.qoi", flags );
+}
+
+VG_API void _menu_init(void)
{
- u32 flags = VG_TEX2D_CLAMP|VG_TEX2D_NOMIP|VG_TEX2D_NEAREST;
- vg_tex2d_load_qoi_async_file( "textures/prem.qoi", flags, &menu.prem_tex );
- vg_tex2d_load_qoi_async_file( "textures/guide_pump.qoi", flags, &menu.guide_pump_tex );
- vg_tex2d_load_qoi_async_file( "textures/guide_fliptrick.qoi", flags, &menu.guide_fliptrick_tex );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_menu_load_content_async );
}
static void menu_update_world_filter(void)
menu.world_list_selected_index[ super_id ] = index;
menu.clicked_world_id = addon;
- vg_msg msg;
- vg_msg_init( &msg, reg->metadata, reg->metadata_len );
const char *name = NULL;
- if( vg_msg_seekframe( &msg, "workshop" ) )
- name = vg_msg_getkvstr( &msg, "title" );
+ u32 workshop_block = vg_kv_find( ®->metadata, 0, "workshop" );
+ if( workshop_block )
+ name = vg_kv_value( ®->metadata, vg_kv_find( ®->metadata, workshop_block, "title" ), NULL );
if( !name )
name = reg->alias.folder;
menu.clicked_world_name = name;
void menu_open( enum menu_page page )
{
- gui_helper_reset( k_gui_helper_mode_clear );
+ _gui_helper_reset( k_gui_helper_mode_clear );
skaterift.activity = k_skaterift_menu;
if( _cutscene.state != k_cutscene_state_none )
ui_text( ctx, rect, label, 1, k_ui_align_middle_center, colour? colour: ui_colour(ctx, k_ui_blue+k_ui_brighter) );
}
-static u32 medal_colour( ui_context *ctx, u32 flags )
+u32 medal_colour( ui_context *ctx, u32 flags )
{
if( flags & k_ent_route_flag_achieve_gold )
return ui_colour( ctx, k_ui_yellow );
flags |= MENU_WORLD_FLAG_HUB;
const char *name = NULL;
- vg_msg msg;
- vg_msg_init( &msg, reg->metadata, reg->metadata_len );
-
- if( vg_msg_seekframe( &msg, "workshop" ) )
- name = vg_msg_getkvstr( &msg, "title" );
+ u32 workshop_block = vg_kv_find( ®->metadata, 0, "workshop" );
+ if( workshop_block )
+ name = vg_kv_value( ®->metadata, vg_kv_find( ®->metadata, workshop_block, "title" ), NULL );
if( !name )
name = reg->alias.folder;
//menu_try_find_cam( 3 );
ui_rect panel = { 0,0, 800, 200 },
- screen = { 0,0, vg.window_x,vg.window_y };
+ screen = { 0,0, _vg_window.w,_vg_window.h };
ui_rect_center( screen, panel );
ui_fill( ctx, panel, GUI_COL_DARK );
ui_outline( ctx, panel, 1, GUI_COL_NORM, 0 );
}
- if( vg.settings_open )
+ if( _vg_settings_is_open() )
{
if( button_down( k_srbind_mback ) )
{
vg_audio_lock();
vg_audio_oneshot( &audio_ui[3], 1.0f, 0.0f, 0, 0 );
vg_audio_unlock();
- vg_settings_close();
+ _vg_settings_close();
srinput.state = k_input_state_resume;
}
if( menu.page == k_menu_page_credits )
{
ui_rect panel = { 0,0, 600, 400 },
- screen = { 0,0, vg.window_x,vg.window_y };
+ screen = { 0,0, _vg_window.w,_vg_window.h };
ui_rect_center( screen, panel );
ui_fill( ctx, panel, GUI_COL_DARK );
ui_outline( ctx, panel, 1, GUI_COL_NORM, 0 );
{
i32 R = menu_nav( &menu.intro_row, mv, 3 );
ui_rect panel = { 0,0, 600, 400 },
- screen = { 0,0, vg.window_x,vg.window_y };
+ screen = { 0,0, _vg_window.w,_vg_window.h };
ui_rect_center( screen, panel );
ui_fill( ctx, panel, ui_opacity( GUI_COL_DARK, 0.35f ) );
ui_outline( ctx, panel, 1, GUI_COL_NORM, 0 );
ui_split( panel, k_ui_axis_h, 28, 0, title, panel );
ctx->font = &vgf_default_large;
- menu_checkbox( ctx, panel, R == 0, "Show controls overlay (good for new players)", &control_overlay.enabled );
+ menu_checkbox( ctx, panel, R == 0, "Show controls overlay (good for new players)", &_control_overlay.enabled );
menu_checkbox( ctx, panel, R == 1, "Auto connect to global server", &network_client.auto_connect );
ui_rect end = { panel[0], panel[1] + panel[3] - 100, panel[2], 100 };
{
i32 R = menu_nav( &menu.prem_row, mh, 1 );
ui_rect panel = { 0,0, 600, 400+240 },
- screen = { 0,0, vg.window_x,vg.window_y };
+ screen = { 0,0, _vg_window.w,_vg_window.h };
ui_rect_center( screen, panel );
ui_fill( ctx, panel, ui_opacity( GUI_COL_DARK, 0.35f ) );
ui_outline( ctx, panel, 1, GUI_COL_NORM, 0 );
/* PAGE impromptu */
else if( menu.page == k_menu_page_impromptu_guide )
{
- ui_rect screen = { 0,0, vg.window_x,vg.window_y };
+ ui_rect screen = { 0,0, _vg_window.w,_vg_window.h };
ui_rect image = { 0,0, 780, 840 };
ui_rect panel;
else if( menu.page == k_menu_page_quick )
{
ui_px pad = 64;
- ui_rect panel = { 24, pad, 300, vg.window_y-(pad*2) };
+ ui_rect panel = { 24, pad, 300, _vg_window.h-(pad*2) };
ui_fill( ctx, panel, ui_opacity( GUI_COL_DARK, 0.35f ) );
ui_outline( ctx, panel, 1, GUI_COL_NORM, 0 );
ui_rect_pad( panel, (ui_px[]){8,8} );
if( world_clear_event( k_world_event_challenge ) )
{
_ent_challenge_clear( af_arritm( &_world.main.ent_challenge, mdl_entity_id_id( _world.active_challenge_id ) ) );
- gui_helper_reset( k_gui_helper_mode_clear );
+ _gui_helper_reset( k_gui_helper_mode_clear );
_world.challenge_state = k_challenge_state_none;
_world.active_challenge_id = 0;
_world.challenge_target = NULL;
else if( menu.page == k_menu_page_spectate )
{
ui_px pad = 64;
- ui_rect panel = { 24, pad, 300, vg.window_y-(pad*2) };
+ ui_rect panel = { 24, pad, 300, _vg_window.h-(pad*2) };
ui_fill( ctx, panel, ui_opacity( GUI_COL_DARK, 0.35f ) );
ui_outline( ctx, panel, 1, GUI_COL_NORM, 0 );
ui_rect_pad( panel, (ui_px[]){8,8} );
localplayer.immobile = 1;
vg_camera_copy( &localplayer.cam, &netplayers.spectate_camera );
- gui_helper_reset( k_gui_helper_mode_black_bars );
+ _gui_helper_reset( k_gui_helper_mode_black_bars );
vg_str text;
- if( gui_new_helper( input_button_list[k_srbind_mback], &text ))
+ if( _gui_new_helper( input_button_list[k_srbind_mback], &text ))
vg_strcat( &text, "Stop spectating" );
}
{
i32 R = menu_nav( &menu.cs_row, mh, 1 );
ui_rect panel = { 0,0, 600, 160 },
- screen = { 0,0, vg.window_x,vg.window_y };
+ screen = { 0,0, _vg_window.w,_vg_window.h };
ui_rect_center( screen, panel );
ui_fill( ctx, panel, ui_opacity( GUI_COL_DARK, 0.35f ) );
ui_outline( ctx, panel, 1, GUI_COL_NORM, 0 );
ctx->font = &vgf_default_title;
ui_px height = ctx->font->ch + 16;
- ui_rect topbar = { 0, 0, vg.window_x, height };
+ ui_rect topbar = { 0, 0, _vg_window.w, height };
const char *opts[] = {
[k_menu_main_main] = "Menu",
}
if( draw )
- ui_fill( ctx, (ui_rect){ x+8,0, vg.window_x-(x+8),height }, GUI_COL_NORM );
+ ui_fill( ctx, (ui_rect){ x+8,0, _vg_window.w-(x+8),height }, GUI_COL_NORM );
else
{
- x = vg.window_x/2 - x/2;
+ x = _vg_window.w/2 - x/2;
ui_fill( ctx, (ui_rect){ 0, 0, x-8, height }, GUI_COL_NORM );
}
}
menu_backable_to_exit = 1;
menu.bg_blur = 0;
- world_map_gui( ctx, (ui_rect){ 0, height, vg.window_x, vg.window_y - height }, mh, mv, &menu_backable_to_exit );
+ world_map_gui( ctx, (ui_rect){ 0, height, _vg_window.w, _vg_window.h - height }, mh, mv, &menu_backable_to_exit );
if( world_map.spawn_timer > 0.0f )
menu_backable_to_exit = 0;
}
else /* menu.main_index != k_menu_main_map) */
{
- ui_rect list0 = { vg.window_x/2 - 512/2, height+32, 512, vg.window_y-height-64 }, list;
+ ui_rect list0 = { _vg_window.w/2 - 512/2, height+32, 512, _vg_window.h-height-64 }, list;
rect_copy( list0, list );
ui_rect_pad( list, (ui_px[2]){8,8} );
ui_rect end = { list[0], list[1]+list[3]-64, list[2], 72 };
if( menu_button( ctx, end, R == 3, 1, "Quit Game" ) )
- {
- vg.window_should_close = 1;
- }
+ _vg_terminate();
}
/* PAGE main */
else if( menu.main_index == k_menu_main_online )
{
menu_backable_to_exit = 0;
bool close = _user_profile_country_picker( ctx, (ui_rect){ 8, height+32,
- vg.window_x-16, vg.window_y-(height+32+16) } );
+ _vg_window.w-16, _vg_window.h-(height+32+16) } );
if( close )
menu.choosing_country = 0;
}
ctx->font = &vgf_default_large;
list[1] -= 8;
menu_heading( ctx, list, "Game", 0 );
- menu_checkbox( ctx, list, R == 0, "Show controls overlay", &control_overlay.enabled );
+ menu_checkbox( ctx, list, R == 0, "Show controls overlay", &_control_overlay.enabled );
menu_checkbox( ctx, list, R == 1, "Auto connect to global server", &network_client.auto_connect );
menu_heading( ctx, list, "Audio/Video", 0 );
menu_heading( ctx, end, "Advanced", 0 );
if( menu_button( ctx, end, R == 8, 1, "Open Engine Settings" ) )
{
- vg_settings_open();
+ _vg_settings_open();
}
}
/* PAGE guide */
ui_px w = 700,
marg = list0[0]+list0[2],
- pw = vg.window_x - marg,
+ pw = _vg_window.w - marg,
infx = pw/2 - w/2 + marg;
ui_rect inf = { infx, height +32, w, 800 };
-#pragma once
+#if defined( SR_IMPLEMENTATION )
+# include "src/menu.c"
+#else
#define MENU_STACK_SIZE 8
#define MENU_WORLD_MAX_COUNT 10
#define MENU_WORLD_FLAG_DONE 0x2
#define MENU_WORLD_FLAG_LOCKED 0x4
-#include "vg/vg_engine.h"
-#include "entity.h"
-#include "world_map.h"
-
enum menu_page
{
k_menu_page_any,
const char *web_link; /* if set; modal */
i32 web_choice;
- GLuint prem_tex, guide_pump_tex, guide_fliptrick_tex;
+ vg_tex prem_tex, guide_pump_tex, guide_fliptrick_tex;
addon_id world_list_entries[ MENU_WORLD_MAX_COUNT ];
const char *world_list_names[ MENU_WORLD_MAX_COUNT ];
}
extern menu;
-void menu_register(void);
-void menu_init(void);
+VG_API void _menu_register(void);
+VG_API void _menu_init(void);
+
void menu_at_begin(void);
void menu_gui( ui_context *ctx );
void menu_open( enum menu_page page );
bool menu_options( ui_context *ctx, ui_rect inout_panel, bool select, i32 *subselect_x, const char *str_label,
const char *options, u32 *data, i32 mh, i32 menter );
void menu_decor_select( ui_context *ctx, ui_rect rect );
+u32 medal_colour( ui_context *ctx, u32 flags );
+
+#endif
-#include "metascene.h"
-#include "vg/vg_magi.h"
-
-struct _cutscene _cutscene;
-
-void metascene_load( ms_context *ms, const char *path, void *alloc )
+void metascene_load( metascene *ms, const c8 *path, vg_stack_allocator *stack )
{
- af_open( &ms->af, path, MS_VERSION_MIN, MS_VERSION_NR, alloc );
- AF_LOAD_ARRAY_STRUCT( &ms->af, &ms->infos, ms_scene_info, alloc );
- AF_LOAD_ARRAY_STRUCT( &ms->af, &ms->instances, ms_instance, alloc );
- AF_LOAD_ARRAY_STRUCT( &ms->af, &ms->overrides, ms_override, alloc );
- AF_LOAD_ARRAY_STRUCT( &ms->af, &ms->strips, ms_strip, alloc );
- AF_LOAD_ARRAY_STRUCT( &ms->af, &ms->tracks, ms_track, alloc );
- AF_LOAD_ARRAY_STRUCT( &ms->af, &ms->keyframes, ms_keyframe, alloc );
- AF_LOAD_ARRAY_STRUCT( &ms->af, &ms->cameras, ent_camera, alloc );
- AF_LOAD_ARRAY_STRUCT( &ms->af, &ms->audios, ent_audio, alloc );
- AF_LOAD_ARRAY_STRUCT( &ms->af, &ms->audio_clips, ent_audio_clip, alloc );
- af_load_array( &ms->af, &ms->curves, "ms_curves", alloc, sizeof(ms_curve_keyframe) );
- af_close( &ms->af );
-
- if( af_arrcount( &ms->infos ) )
- {
- ms_scene_info *src_inf = af_arritm( &ms->infos, 0 );
- ms->info = *src_inf;
- }
- else
- vg_fatal_error( "No scene info in metascene.\n" );
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+ vg_zero_mem( ms, sizeof(metascene) );
+
+ vg_stream stream;
+ VG_ASSERT( vg_file_stream_open( &stream, path, VG_STREAM_READ ) );
+
+ u32 temp_frame = _vg_start_temp_frame();
+
+ array_file_context af;
+ VG_ASSERT( af_open_stream( &af, &stream, MS_VERSION_MIN, MS_VERSION_NR, _vg_temp_stack() ) );
+
+ array_file_ptr strings;
+ af_load_array( &af, &strings, "strings", stack, 1 );
+ ms->packed_strings = strings.data;
+
+ AF_LOAD_ARRAY_STRUCT( &af, &ms->infos, ms_scene_info, stack );
+ AF_LOAD_ARRAY_STRUCT( &af, &ms->instances, ms_instance, stack );
+ AF_LOAD_ARRAY_STRUCT( &af, &ms->overrides, ms_override, stack );
+ AF_LOAD_ARRAY_STRUCT( &af, &ms->strips, ms_strip, stack );
+ AF_LOAD_ARRAY_STRUCT( &af, &ms->tracks, ms_track, stack );
+ AF_LOAD_ARRAY_STRUCT( &af, &ms->keyframes, ms_keyframe, stack );
+ AF_LOAD_ARRAY_STRUCT( &af, &ms->cameras, ent_camera, stack );
+ AF_LOAD_ARRAY_STRUCT( &af, &ms->audios, ent_audio, stack );
+ AF_LOAD_ARRAY_STRUCT( &af, &ms->audio_clips, ent_audio_clip, stack );
+ af_load_array( &af, &ms->curves, "ms_curves", stack, sizeof(ms_curve_keyframe) );
+
+ VG_ASSERT( af_arrcount( &ms->infos ) );
+ ms_scene_info *src_inf = af_arritm( &ms->infos, 0 );
+ ms->info = *src_inf;
+
+ vg_file_stream_close( &stream );
+ _vg_end_temp_frame( temp_frame );
}
-struct cs_instance *_cutscene_get_first_model_instance( const char *mdl_name )
+u32 skeleton_bone_id( ms_skeleton *skele, const char *name )
{
- for( u32 i=0; i<_cutscene.instance_count; i ++ )
- {
- struct cs_instance *inst = &_cutscene.instances[i];
- struct model_ref *mref = &_cutscene.refs[ inst->ref_id ];
-
- if( vg_str_eq( mdl_name, mref->name ) )
- return inst;
- }
+ for( u32 i=1; i<skele->bone_count; i++ )
+ if( !strcmp( skele->bones[i].name, name ))
+ return i;
- return NULL;
-}
+ vg_error( "skeleton_bone_id( *, \"%s\" );\n", name );
+ vg_fatal_error( "Bone does not exist\n" );
-void _cutscene_unload(void)
-{
- vg_info( "Unloading cutscene\n" );
- vg_audio_lock();
- vg_audio_set_flagged_pause( AUDIO_FLAG_CUTSCENE, 0 );
- vg_audio_fadeout_flagged_audio( AUDIO_FLAG_CUTSCENE, 1.0f );
- vg_audio_unlock();
-
- for( u32 i=0; i<_cutscene.unique_refs; i ++ )
- mdl_sync_std_unload( &_cutscene.refs[i].mdl );
-
- _cutscene.unique_refs = 0;
- _cutscene.active_camera = NULL;
- _cutscene.strip = 0;
- _cutscene.time = 0.0f;
- _cutscene.active_samplers = 0;
- _cutscene.state = k_cutscene_state_unloading;
- _cutscene.player_binding = NULL;
- _cutscene.subtitle = NULL;
- _cutscene.raiser_entity = 0;
- _cutscene.fadeout = 0;
- _cutscene.skipped = 0;
- _cutscene.fadeout_start = 0.0f;
+ return 0;
}
-/*
- * Find associated entity data. We should also probably do this on the world
- * thingy
- */
-struct cs_asoc
+void keyframe_copy_pose( ms_keyframe *kfa, ms_keyframe *kfb, int num )
{
- mdl_context *orig_data;
- u16 entity_type,
- entity_index;
- ms_override *override;
-};
-
-static void _cutscene_override_asoc( u32 instance_id, u32 override_index, struct cs_asoc *out_asoc )
-{
- struct cs_instance *instance = &_cutscene.instances[ instance_id ];
- mdl_context *mdl = &_cutscene.refs[ instance->ref_id ].mdl;
-
- ms_instance *oins = af_arritm( &_cutscene.meta.instances, instance_id );
- ms_override *override = af_arritm( &_cutscene.meta.overrides, oins->override_start + override_index );
-
- out_asoc->orig_data = mdl;
- out_asoc->entity_type = override->entity_type;
- out_asoc->override = override;
- const char *name = af_str( &_cutscene.meta.af, override->pstr_name );
- u32 name_hash = af_str_hash( &_cutscene.meta.af, override->pstr_name );
-
- if( out_asoc->entity_type != 28 )
- goto NOT_IMPLEMENTED;
-
- for( u32 j=0; j<mdl->armature_count; j ++ )
- {
- mdl_armature *armature = &mdl->armatures[ j ];
- if( af_str_eq( &mdl->af, armature->pstr_name, name, name_hash ) )
- {
- out_asoc->entity_index = j;
- return;
- }
- }
-
-NOT_IMPLEMENTED:
-
- vg_fatal_error( "The data association was not found.\n"
- " Entity Type: %u\n"
- " Entity name: %s\n", override->entity_type, name );
+ for( int i=0; i<num; i++ )
+ kfb[i] = kfa[i];
}
-static void _cutscene_get_strip_asoc( ms_strip *strip, struct cs_asoc *out_asoc )
+
+/* apply a rotation from the perspective of root */
+void keyframe_rotate_around( ms_keyframe *kf, v3f origin, v3f offset, v4f q )
{
- VG_ASSERT( strip->mode & k_ms_strip_mode_animation );
- if( strip->strip.instance_id == 0xffffffff )
- {
- out_asoc->orig_data = NULL;// &_cutscene.meta;
- out_asoc->entity_type = mdl_entity_id_type( strip->strip.object_id );
- out_asoc->entity_index = mdl_entity_id_id( strip->strip.object_id );
- out_asoc->override = NULL;
- }
- else
- _cutscene_override_asoc( strip->strip.instance_id, strip->strip.object_id, out_asoc );
+ v3f v0, co;
+ v3_add( kf->co, offset, co );
+ v3_sub( co, origin, v0 );
+ q_mulv( q, v0, v0 );
+ v3_add( v0, origin, co );
+ v3_sub( co, offset, kf->co );
+
+ q_mul( q, kf->q, kf->q );
+ q_normalize( kf->q );
}
-static void sync_cutscene_loaded( void *userdata )
+void keyframe_lerp( ms_keyframe *kfa, ms_keyframe *kfb, f32 t, ms_keyframe *kfd )
{
- THREAD_0;
-
- vg_info( "Cutscene loaded\n" );
- _cutscene.state = k_cutscene_state_ready;
+ v3_lerp( kfa->co, kfb->co, t, kfd->co );
+ q_nlerp( kfa->q, kfb->q, t, kfd->q );
+ v3_lerp( kfa->s, kfb->s, t, kfd->s );
}
-struct cutscene_load_info
-{
- u32 nothing;
- char path[];
-};
-static void cutscene_load_thread( vg_async_task *task )
+/*
+ * Lerp between two sets of keyframes and store in dest. Rotations use Nlerp.
+ */
+void keyframe_lerp_pose( ms_keyframe *kfa, ms_keyframe *kfb, float t, ms_keyframe *kfd, int count )
{
- struct cutscene_load_info *info = (void *)task->data;
- vg_info( "Loading cutscene: %s\n", info->path );
-
- vg_stack_init( &_cutscene.stack, NULL, VG_MB(20), "Cutscene Stack" );
- metascene_load( &_cutscene.meta, info->path, &_cutscene.stack );
-
- _cutscene.instance_count = af_arrcount( &_cutscene.meta.instances );
- _cutscene.instances = vg_stack_allocate( &_cutscene.stack, sizeof(struct cs_instance) * _cutscene.instance_count,
- 8, "Instances" );
-
- _cutscene.refs = vg_stack_allocate( &_cutscene.stack, 0, 8, "References" );
- _cutscene.unique_refs = 0;
- for( u32 i=0; i < _cutscene.instance_count; i ++ )
+ if( t <= 0.0001f )
{
- ms_instance *instance = af_arritm( &_cutscene.meta.instances, i );
- const char *name = af_str( &_cutscene.meta.af, instance->pstr_name );
- u32 name_hash = af_str_hash( &_cutscene.meta.af, instance->pstr_name );
-
- struct model_ref *ref = NULL;
- u32 ref_id = 0;
-
- for( u32 j=0; j<_cutscene.unique_refs; j ++ )
- {
- struct model_ref *ref_j = &_cutscene.refs[ j ];
-
- if( af_str_eq( &_cutscene.meta.af, instance->pstr_name, ref_j->name, ref_j->name_hash ) )
- {
- ref = ref_j;
- ref_id = j;
- break;
- }
- }
-
- if( !ref )
- {
- _cutscene.refs = vg_stack_extend_last( &_cutscene.stack, sizeof(struct model_ref) );
- ref_id = _cutscene.unique_refs;
- ref = &_cutscene.refs[ ref_id ];
- ref->name = name;
- ref->name_hash = name_hash;
- ref->reference_count = 0;
- vg_info( "Indexed reference '%s'\n", name );
- _cutscene.unique_refs ++;
- }
-
- ref->reference_count ++;
- _cutscene.instances[ i ].ref_id = ref_id;
- _cutscene.instances[ i ].skinning_data = NULL;
- _cutscene.instances[ i ].disable_render = 0;
- }
-
- /* load model data */
- for( u32 i=0; i<_cutscene.unique_refs; i ++ )
- {
- struct model_ref *ref = &_cutscene.refs[ i ];
- char mdl_path_buf[ 512 ];
- vg_str mdl_path;
- vg_strnull( &mdl_path, mdl_path_buf, sizeof(mdl_path_buf) );
- vg_strcat( &mdl_path, ref->name );
- vg_strcat( &mdl_path, ".mdl" );
-
- vg_info( "Loading instance model: %s\n", mdl_path.buffer );
- mdl_open( &ref->mdl, mdl_path.buffer, &_cutscene.stack );
- mdl_load_metadata_block( &ref->mdl, &_cutscene.stack );
- mdl_async_full_load_std( &ref->mdl, NULL );
- mdl_close( &ref->mdl );
-
- u32 skeleton_count = ref->mdl.armature_count;
- if( skeleton_count )
- {
- ref->skeletons = vg_stack_allocate( &_cutscene.stack, sizeof(struct cs_skeleton) * skeleton_count, 8, "Skeletons" );
- ref->total_skinning_bones = 0;
- for( u32 j=0; j<skeleton_count; j ++ )
- {
- struct cs_skeleton *skele = &ref->skeletons[ j ];
- skeleton_setup( &skele->sk, &ref->mdl, j, &_cutscene.stack );
- skele->skinning_offset = ref->total_skinning_bones;
- ref->total_skinning_bones += skele->sk.bone_count;
- }
- }
- else
- {
- ref->skeletons = NULL;
- ref->total_skinning_bones = 0;
- }
- }
-
- /* allocate skinning memory per-instance */
- for( u32 i=0; i<_cutscene.instance_count; i ++ )
- {
- struct cs_instance *ins = &_cutscene.instances[ i ];
- struct model_ref *ref = &_cutscene.refs[ ins->ref_id ];
-
- ins->skinning_data = vg_stack_allocate( &_cutscene.stack, sizeof(m4x3f) * ref->total_skinning_bones,
- 8, "Skinning Data" );
- for( u32 j=0; j<ref->total_skinning_bones; j ++ )
- m4x3_identity( ins->skinning_data[ j ] );
-
- /* load overrides */
- ms_instance *oins = af_arritm( &_cutscene.meta.instances, i );
- for( u32 j=0; j<oins->override_count; j ++ )
- {
- ms_override *override = af_arritm( &_cutscene.meta.overrides, oins->override_start + j );
-
- struct cs_asoc asoc;
- _cutscene_override_asoc( i, j, &asoc );
-
- VG_ASSERT( asoc.entity_type == 28 );
-
- struct cs_skeleton *skele = &ref->skeletons[ asoc.entity_index ];
- m4x3f mmdl;
- mdl_transform_m4x3( &override->transform, mmdl );
-
- for( u32 l=0; l<skele->sk.bone_count; l ++ )
- m4x3_copy( mmdl, ins->skinning_data[skele->skinning_offset+l] );
- }
+ keyframe_copy_pose( kfa, kfd, count );
+ return;
}
-
- /* audio packs */
- for( u32 j=0; j<af_arrcount( &_cutscene.meta.audios ); j++ )
+ else if( t >= 0.9999f )
{
- ent_audio *audio = af_arritm( &_cutscene.meta.audios, j );
-
- for( u32 k=0; k<audio->clip_count; k++ )
- {
- ent_audio_clip *clip = af_arritm( &_cutscene.meta.audio_clips, audio->clip_start+k );
-
- if( clip->_.file.pack_size )
- vg_error( "Currently not support packed audio in metascene..." );
- else
- {
- clip->_.clip.path = af_str( &_cutscene.meta.af, clip->_.file.pstr_path );
- clip->_.clip.flags = audio->flags;
- clip->_.clip.any_data = NULL;
- clip->_.clip.size = 0;
- }
-
- audio_clip_load( &clip->_.clip, &_cutscene.stack );
- }
+ keyframe_copy_pose( kfb, kfd, count );
+ return;
}
- vg_async_call( &vg.main_tasks, sync_cutscene_loaded, NULL );
+ for( int i=0; i<count; i++ )
+ keyframe_lerp( kfa+i, kfb+i, t, kfd+i );
}
-bool _cutscene_load_and_play( const char *path, bool freeze_player, u32 raiser_entity )
+void skeleton_lerp_pose( ms_skeleton *skele, ms_keyframe *kfa, ms_keyframe *kfb, float t, ms_keyframe *kfd )
{
- if( _cutscene.state != k_cutscene_state_none )
- {
- vg_error( "Tried to play cutscene '%s' while already playing one.\n", path );
- return 0;
- }
-
- _cutscene.raiser_entity = raiser_entity;
-
- for( u32 i=0; i<k_npc_max; i ++ )
- _ent_npc_set_in_cutscene( i, 0 );
-
- _cutscene.state = k_cutscene_state_loading;
- _cutscene.time = 0.0f;
- _cutscene.strip = 0;
- _cutscene.active_samplers = 0;
- _cutscene.freeze_player = freeze_player;
+ keyframe_lerp_pose( kfa, kfb, t, kfd, skele->bone_count-1 );
+}
- u32 len = strlen( path ) +1;
- vg_async_task *task = vg_allocate_async_task( &vg.loader_tasks, sizeof(struct cutscene_load_info) + len, 1 );
- struct cutscene_load_info *info = (void *)task->data;
- strcpy( info->path, path );
- vg_async_task_dispatch( task, cutscene_load_thread );
- return 1;
+void skeleton_copy_pose( ms_skeleton *skele, ms_keyframe *kfa, ms_keyframe *kfd )
+{
+ keyframe_copy_pose( kfa, kfd, skele->bone_count-1 );
}
/*
- * Currently draws everything as skinned meshes.
+ * Sample animation between 2 closest frames using time value. Output is a
+ * keyframe buffer that is allocated with an appropriate size
+ *
+ * Time is in SECONDS
*/
-void cutscene_render_instance( struct cs_instance *ins, world_instance *world, vg_camera *cam )
+void skeleton_sample_anim( ms_skeleton *skele, ms_skeletal_animation *anim, f32 time, ms_keyframe *output )
{
- if( ins->disable_render )
- return;
+ ms_strip *strip = anim->strip;
+ f32 animtime = fmodf( time*anim->framerate, (f32)strip->strip.length ),
+ animframe = floorf( animtime ),
+ t = animtime - animframe;
- struct model_ref *ref = &_cutscene.refs[ ins->ref_id ];
- mdl_context *mdl = &ref->mdl;
- mesh_bind( &mdl->mesh );
+ u32 frame = (u32)animframe % strip->strip.length,
+ next = (frame+1) % strip->strip.length;
- shader_model_character_view_use();
- shader_model_character_view_uCamera( cam->transform[3] );
- shader_model_character_view_uPv( cam->mtx.pv );
- shader_model_character_view_uDepthMode( 0 );
- shader_model_character_view_uShadeless( 0 );
- shader_model_character_view_uUvOffset( (v2f){0,0} );
+ ms_keyframe *base = anim->keyframes_base + strip->strip.count*frame,
+ *nbase = anim->keyframes_base + strip->strip.count*next;
- WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, model_character_view );
+ skeleton_lerp_pose( skele, base, nbase, t, output );
+}
- glActiveTexture( GL_TEXTURE0 );
- shader_model_character_view_uTexMain( 0 );
+/* time is in SECONDS */
+int skeleton_sample_anim_clamped( ms_skeleton *skele, ms_skeletal_animation *anim, f32 time, ms_keyframe *output )
+{
+ ms_strip *strip = anim->strip;
+ f32 end = (strip->strip.length-1)/anim->framerate;
+ skeleton_sample_anim( skele, anim, vg_minf( end, time ), output );
- u32 armature_id = 0x00;
- u32 material_id = 0x00;
- bool using_additive = 0;
+ if( time > end ) return 0;
+ else return 1;
+}
- for( u32 i=0; i<mdl->mesh_count; i ++ )
- {
- mdl_mesh *mesh = &mdl->meshes[ i ];
- VG_ASSERT( mesh->armature_id );
+static int should_apply_bone( ms_skeleton *skele, u32 id, anim_apply type )
+{
+ ms_skeleton_bone *sb = &skele->bones[ id ],
+ *sp = &skele->bones[ sb->parent ];
- if( mesh->armature_id != armature_id )
+ if( type == k_anim_apply_defer_ik )
+ {
+ if( ((sp->flags & k_bone_flag_ik) && !(sb->flags & k_bone_flag_ik)) || sp->defer )
{
- armature_id = mesh->armature_id;
- u32 sk_index = mdl_entity_id_id( armature_id );
-
- struct cs_skeleton *skele = &ref->skeletons[ sk_index ];
- m4x3f *skinning_data = ins->skinning_data + skele->skinning_offset;
- glUniformMatrix4x3fv( _uniform_model_character_view_uTransforms, skele->sk.bone_count, 0,
- (const GLfloat *)skinning_data );
+ sb->defer = 1;
+ return 0;
}
-
- for( u32 j=0; j<mesh->submesh_count; j ++ )
+ else
{
- mdl_submesh *sm = &mdl->submeshes[ mesh->submesh_start+j ];
- VG_ASSERT( sm->material_id );
-
- if( sm->material_id != material_id )
- {
- mdl_material *m = &mdl->materials[ sm->material_id-1 ];
- VG_ASSERT( m->shader == k_shader_standard );
-
- struct shader_props_standard *props = m->props.compiled;
- VG_ASSERT( props->tex_diffuse );
-
- mdl_texture *tex = &mdl->textures[ props->tex_diffuse-1 ];
- glBindTexture( GL_TEXTURE_2D, tex->glname );
-
- if( props->render_flags & k_material_render_additive )
- {
- using_additive = 1;
- glDepthMask(GL_FALSE);
- glEnable(GL_BLEND);
- glBlendFunc(GL_ONE, GL_ONE);
- glBlendEquation(GL_FUNC_ADD);
- glDisable( GL_CULL_FACE );
- shader_model_character_view_uShadeless( 1 );
- }
- else
- {
- if( using_additive )
- {
- using_additive = 0;
- glDepthMask(GL_TRUE);
- glDisable(GL_BLEND);
- glEnable( GL_CULL_FACE );
- shader_model_character_view_uShadeless( 0 );
- }
- }
- }
-
- mdl_draw_submesh( sm );
+ sb->defer = 0;
+ return 1;
}
}
-
- if( using_additive )
- {
- shader_model_character_view_uShadeless( 0 );
- glDepthMask(GL_TRUE);
- glDisable(GL_BLEND);
- }
-}
-
-#define CS_LOCATION 0
-#define CS_ANGLES 4
-#define CS_FOV 8
-
-struct cs_link_info
-{
- f32 *target;
- u32 semantic_type;
-};
-
-static bool link_internal_datapath( struct cs_asoc *asoc, const char *datapath, struct cs_link_info *out_link )
-{
- if( asoc->entity_type != k_ent_camera )
+ else if( type == k_anim_apply_deffered_only )
{
- vg_warn( "Failed link %d#%d:'%s'\n", asoc->entity_type, asoc->entity_index, datapath );
- VG_ASSERT( 0 );
- }
- ent_camera *cam = af_arritm( &_cutscene.meta.cameras, asoc->entity_index );
-
- struct
- {
- const char *prefix;
- f32 *arr;
- u32 semantic;
- }
- reference[] =
- {
- { "location:", cam->co, CS_LOCATION },
- { "rotation_euler:", cam->r, CS_ANGLES },
- { "lens:", &cam->fov, CS_FOV }
- };
-
- for( u32 i=0; i<VG_ARRAY_LEN(reference); i ++ )
- {
- u32 len = strlen( reference[i].prefix );
- if( !strncmp( reference[i].prefix, datapath, len ) )
- {
- i32 offset = atoi( datapath + len );
- out_link->target = reference[i].arr + offset;
- out_link->semantic_type = reference[i].semantic + offset;
-
- vg_info( "Linked %d#%d:'%s'\n", asoc->entity_type, asoc->entity_index, datapath );
+ if( sb->defer )
return 1;
- }
+ else
+ return 0;
}
- vg_warn( "Failed link %d#%d:'%s'\n", asoc->entity_type, asoc->entity_index, datapath );
- return 0;
-}
-
-ent_camera *_cutscene_active_camera(void)
-{
- return _cutscene.active_camera;
+ return 1;
}
-void cutscene_update( f32 delta )
+/*
+ * Apply block of keyframes to skeletons final pose
+ */
+void skeleton_apply_pose( ms_skeleton *skele, ms_keyframe *pose, anim_apply passtype, m4x3f *final_mtx )
{
- if( _cutscene.state == k_cutscene_state_unloading )
+ if( passtype == k_anim_apply_absolute )
{
- // NOTE: This somestimes still fails!
- if( !vg_audio_flagged_stopped( AUDIO_FLAG_CUTSCENE ) )
+ for( u32 i=1; i<skele->bone_count; i++ )
{
- static u32 ticker = 0;
- ticker ++;
- if( ticker > 50 )
- {
- vg_low( "waiting for audio to stop...\n" );
- ticker = 0;
- }
- return;
- }
-
- vg_stack_free( &_cutscene.stack );
- _cutscene.state = k_cutscene_state_none;
- _cutscene.marker_this_frame = NULL;
- _cutscene.subtitle = NULL;
- _cutscene.raiser_entity = 0;
- vg_info( "Finished unloading cutscene\n" );
- return;
- }
-
- if( _cutscene.state == k_cutscene_state_ready )
- {
- _cutscene.player_binding = _cutscene_get_first_model_instance( "models/ch_none" );
- if( _cutscene.player_binding )
- _cutscene.player_binding->disable_render = 1;
+ ms_keyframe *kf = &pose[i-1];
- /* start playing */
- if( _cutscene.freeze_player )
- localplayer.immobile = 1;
+ v3f *posemtx = final_mtx[i];
- vg_audio_lock();
- for( u32 j=0; j<af_arrcount( &_cutscene.meta.audios ); j++ )
- {
- ent_audio *audio = af_arritm( &_cutscene.meta.audios, j );
- ent_audio_clip *clip = af_arritm( &_cutscene.meta.audio_clips, audio->clip_start );
-
- if( audio->flags & AUDIO_FLAG_AUTO_START )
- {
- const u16 group = 0xfff1;
- const u32 flags = AUDIO_FLAG_CUTSCENE;
-
- if( audio->flags & AUDIO_FLAG_SPACIAL_3D )
- vg_audio_oneshot_3d( &clip->_.clip, audio->transform.co, audio->transform.s[0], audio->volume, group,flags);
- else
- vg_audio_oneshot( &clip->_.clip, 1.0f, 0.0f, group, flags );
- }
+ q_m3x3( kf->q, posemtx );
+ m3x3_scale( posemtx, kf->s );
+ v3_copy( kf->co, posemtx[3] );
}
- vg_audio_unlock();
-
- _cutscene.state = k_cutscene_state_playing;
- _world_raise_event( _cutscene.raiser_entity, "start" );
+ return;
}
- if( _cutscene.state != k_cutscene_state_playing )
- return;
+ m4x3_identity( final_mtx[0] );
+ skele->bones[0].defer = 0;
+ skele->bones[0].flags &= ~k_bone_flag_ik;
- _cutscene.marker_this_frame = NULL;
- _cutscene.time += delta;
- i32 frame = _cutscene.time * _cutscene.meta.info.framerate;
-
- /* clear out finished samplers */
- bool move = 0;
- u32 j = 0;
- for( u32 i=0; i<_cutscene.active_samplers; i ++ )
+ for( u32 i=1; i<skele->bone_count; i++ )
{
- struct cs_sampler *si = &_cutscene.samplers[i];
-
- if( frame > (si->strip->offset + (i32)si->strip->strip.length) )
- move = 1;
- else
- {
- if( move )
- {
- struct cs_sampler *sj = &_cutscene.samplers[j];
- *sj = *si;
- }
-
- j ++;
- }
- }
- _cutscene.active_samplers = j;
+ ms_skeleton_bone *sb = &skele->bones[i],
+ *sp = &skele->bones[sb->parent];
+ if( !should_apply_bone( skele, i, passtype ) )
+ continue;
- /* add new samplers as we get to them */
- for( u32 i=_cutscene.strip; i<af_arrcount(&_cutscene.meta.strips); i ++ )
- {
- ms_strip *strip = af_arritm(&_cutscene.meta.strips, i);
-
- if( frame < strip->offset )
- break;
-
- if( strip->mode & k_ms_strip_mode_animation )
- {
- if( frame > strip->offset + (i32)strip->strip.length )
- {
- vg_warn( "Skipping?\n" );
- _cutscene.strip ++;
- continue;
- }
-
- if( _cutscene.skipped == 2 )
- {
- _cutscene.strip ++;
- continue;
- }
-
- if( strip->strip.instance_id == 0xffffffff )
- {
- const char *strip_name = af_str( &_cutscene.meta.af, strip->strip.pstr_name );
- vg_info( "+ Strip: '%s' entity: %u\n", strip_name, strip->strip.object_id );
-
- /* internal link */
- struct cs_asoc asoc;
- _cutscene_get_strip_asoc( strip, &asoc );
-
- if( strip->mode == k_ms_strip_mode_curves )
- {
- for( u32 j=0; j<strip->strip.count; j ++ )
- {
- ms_track *track = af_arritm( &_cutscene.meta.tracks, strip->strip.start + j );
- const char *datapath = af_str( &_cutscene.meta.af, track->pstr_datapath );
-
- struct cs_link_info link;
- if( !link_internal_datapath( &asoc, datapath, &link ) )
- continue;
-
- VG_ASSERT( _cutscene.active_samplers < VG_ARRAY_LEN(_cutscene.samplers) );
- struct cs_sampler *samp = &_cutscene.samplers[ _cutscene.active_samplers ++ ];
- samp->strip = strip;
- samp->curves.track = track;
-
- samp->curves.target = link.target;
- samp->curves.semantic = link.semantic_type;
- samp->curves.keyframe = 0;
- samp->override = asoc.override;
- VG_ASSERT( samp->curves.target );
- }
- }
- else VG_ASSERT(0);
- }
- else
- {
- /* external link */
- struct cs_instance *ins = &_cutscene.instances[ strip->strip.instance_id ];
- struct cs_asoc asoc;
- _cutscene_get_strip_asoc( strip, &asoc );
- VG_ASSERT( asoc.entity_type == 28 );
-
- if( strip->mode == k_ms_strip_mode_keyframes )
- {
- VG_ASSERT( _cutscene.active_samplers < VG_ARRAY_LEN(_cutscene.samplers) );
-
- struct cs_sampler *samp = &_cutscene.samplers[ _cutscene.active_samplers ++ ];
- struct model_ref *ref = &_cutscene.refs[ ins->ref_id ];
- struct cs_skeleton *skele = &ref->skeletons[ asoc.entity_index ];
-
- samp->strip = strip;
- samp->skeleton.skinning_data = &ins->skinning_data[ skele->skinning_offset ];
- samp->skeleton.ref_sk = &skele->sk;
- samp->override = asoc.override;
- }
- else
- {
- VG_ASSERT(0);
- }
- }
- }
- else
- {
- if( strip->mode == k_ms_strip_mode_camera )
- {
- u32 type = mdl_entity_id_type( strip->camera.entity_id ),
- index = mdl_entity_id_id( strip->camera.entity_id );
- VG_ASSERT( type == k_ent_camera );
- ent_camera *cam = af_arritm( &_cutscene.meta.cameras, index );
- _cutscene.active_camera = cam;
- }
-
- if( strip->mode == k_ms_strip_mode_fadeout )
- {
- _cutscene.fadeout = 1;
- _cutscene.fadeout_start = _cutscene.time;
- }
-
- if( strip->mode == k_ms_strip_mode_subtitle )
- {
- // FIXME: COLOURS
- _cutscene.subtitle = af_str( &_cutscene.meta.af, strip->subtitle.pstr_en );
- }
-
- if( strip->mode == k_ms_strip_mode_event )
- {
- const char *str = af_str( &_cutscene.meta.af, strip->event.pstr_string );
- vg_info( "cutscene event: %s\n", str );
- _world_raise_event( _cutscene.raiser_entity, str );
- }
- }
+ sb->defer = 0;
- _cutscene.strip ++;
- }
+ /* process pose */
+ m4x3f posemtx;
- /* sample da samplers */
- for( u32 i=0; i<_cutscene.active_samplers && (_cutscene.skipped != 2); i ++ )
- {
- struct cs_sampler *samp = &_cutscene.samplers[ i ];
+ v3f temp_delta;
+ v3_sub( skele->bones[i].co, skele->bones[sb->parent].co, temp_delta );
- if( samp->strip->mode == k_ms_strip_mode_keyframes )
- {
- struct skeleton_anim temp_anim =
- {
- .strip = samp->strip,
- .framerate = _cutscene.meta.info.framerate,
- .keyframes_base = af_arritm( &_cutscene.meta.keyframes, samp->strip->strip.start )
- };
-
- f32 t = _cutscene.time;
- t -= (f32)samp->strip->offset / _cutscene.meta.info.framerate;
-
- struct skeleton *ref_sk = samp->skeleton.ref_sk;
- m4x3f *final_mtx = samp->skeleton.skinning_data;
-
- ms_keyframe pose[32];
- skeleton_sample_anim_clamped( ref_sk, &temp_anim, t, pose );
-
- skeleton_apply_pose( ref_sk, pose, k_anim_apply_defer_ik, final_mtx );
- skeleton_apply_ik_pass( ref_sk, final_mtx );
- skeleton_apply_pose( ref_sk, pose, k_anim_apply_deffered_only, final_mtx );
- skeleton_apply_inverses( ref_sk, final_mtx );
-
- if( samp->override )
- {
- m4x3f mmdl;
- mdl_transform_m4x3( &samp->override->transform, mmdl );
- skeleton_apply_transform( ref_sk, mmdl, final_mtx );
- }
-
- skeleton_debug( ref_sk, final_mtx );
- }
- else
- {
- f32 scene_t = _cutscene.time * _cutscene.meta.info.framerate,
- t = (f32)(scene_t - samp->strip->offset) + samp->strip->strip.timing_offset;
-
- ms_curve_keyframe *kl = af_arritm( &_cutscene.meta.curves,
- samp->curves.track->keyframe_start + samp->curves.keyframe ),
- *kr = NULL;
-
- if( t > kl->co[0] )
- {
- if( samp->curves.track->keyframe_count > 1 )
- {
- for( u32 j=samp->curves.keyframe+1; j<samp->curves.track->keyframe_count; j ++ )
- {
- kr = af_arritm( &_cutscene.meta.curves, samp->curves.track->keyframe_start + j );
- if( kr->co[0] <= t )
- {
- kl = kr;
- kr = NULL;
- samp->curves.keyframe = j;
- }
- else break;
- }
- }
- }
-
- if( kl && kr )
- *samp->curves.target = explicit_bezier( kl->co, kl->r, kr->l, kr->co, t );
- else
- *samp->curves.target = kl->co[1];
-
- if( samp->curves.semantic == CS_FOV )
- {
- f32 mm = *samp->curves.target,
- fov = 2.0f * 57.2957795f * atanf( (36.0f*0.5f) / mm );
- *samp->curves.target = fov;
- }
- }
- }
+ /* pose matrix */
+ ms_keyframe *kf = &pose[i-1];
+ q_m3x3( kf->q, posemtx );
+ m3x3_scale( posemtx, kf->s );
+ v3_copy( kf->co, posemtx[3] );
+ v3_add( temp_delta, posemtx[3], posemtx[3] );
- for( u32 i=0; i<af_arrcount( &_cutscene.meta.cameras ); i ++ )
- {
- ent_camera *cam = af_arritm( &_cutscene.meta.cameras, i );
- vg_line_cross( cam->co, VG__RED, 0.2f );
+ /* final matrix */
+ m4x3_mul( final_mtx[ sb->parent ], posemtx, final_mtx[i] );
}
+}
- f32 scene_t = _cutscene.time * _cutscene.meta.info.framerate,
- end_t = _cutscene.meta.info.end_frame;
-
- if( scene_t >= end_t )
+/*
+ * Take the final matrices and decompose it into an absolute positioned anim
+ */
+void skeleton_decompose_mtx_absolute( ms_skeleton *skele, ms_keyframe *anim, m4x3f *final_mtx )
+{
+ for( u32 i=1; i<skele->bone_count; i++ )
{
- if( _cutscene.strip != af_arrcount(&_cutscene.meta.strips) )
- {
- _cutscene.time = 9999999.9f;
- _cutscene.skipped = 2; /* signal we can ignore animation strips, just want events for correctness */
- return;
- }
- _world_raise_event( _cutscene.raiser_entity, "end" );
-
- if( _cutscene.freeze_player )
- localplayer.immobile = 0;
-
- _cutscene_unload();
+ ms_skeleton_bone *sb = &skele->bones[i];
+ ms_keyframe *kf = &anim[i-1];
+ m4x3_decompose( final_mtx[i], kf->co, kf->q, kf->s );
}
}
-void cutscene_render_fadeout(void)
+/*
+ * 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..
+ */
+void skeleton_inverse_for_ik( ms_skeleton *skele, v3f ivaxis, u32 id, m3x3f inverse )
{
- bool render = 0;
- f32 render_alpha = 0.0f;
+ v3_copy( ivaxis, inverse[0] );
+ v3_copy( skele->bones[id].end, inverse[1] );
+ v3_normalize( inverse[1] );
+ v3_cross( inverse[0], inverse[1], inverse[2] );
+ m3x3_transpose( inverse, inverse );
+}
- if( _cutscene.state >= k_cutscene_state_ready )
- {
- if( _cutscene.fadeout )
- {
- f32 l = ((f32)_cutscene.meta.info.end_frame/(f32)_cutscene.meta.info.framerate) - _cutscene.fadeout_start,
- t = (_cutscene.time - _cutscene.fadeout_start) / l;
- render = 1;
- render_alpha = t;
- _cutscene.fadeout_cooldown = 1.0f;
- }
- }
- else
- {
- if( _cutscene.fadeout_cooldown > 0.0f )
- {
- render = 1;
- render_alpha = _cutscene.fadeout_cooldown;
- _cutscene.fadeout_cooldown -= vg.time_delta;
- }
+/*
+ * Creates inverse rotation matrices which the IK system uses.
+ */
+void skeleton_create_inverses( ms_skeleton *skele )
+{
+ /* IK: inverse 'plane-bone space' axis '(^axis,^bone,...)[base] */
+ for( u32 i=0; i<skele->ik_count; i++ )
+ {
+ ms_skeleton_ik *ik = &skele->ik[i];
+ 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_cross( iv0, iv1, ivaxis );
+ v3_normalize( ivaxis );
+
+ skeleton_inverse_for_ik( skele, ivaxis, ik->lower, ik->ia );
+ skeleton_inverse_for_ik( skele, ivaxis, ik->upper, ik->ib );
}
+}
- if( render )
+/*
+ * Apply a model matrix to all bones, should be done last
+ */
+void skeleton_apply_transform( ms_skeleton *skele, m4x3f transform, m4x3f *final_mtx )
+{
+ for( u32 i=0; i<skele->bone_count; i++ )
{
- glEnable(GL_BLEND);
- glDisable(GL_DEPTH_TEST);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glBlendEquation(GL_FUNC_ADD);
-
- shader_blitcolour_use();
- shader_blitcolour_uColour( (v4f){ 0.04f, 0.02f, 0.03f, vg_clampf( render_alpha, 0.0f, 1.0f ) } );
- render_fsquad();
+ ms_skeleton_bone *sb = &skele->bones[i];
+ m4x3_mul( transform, final_mtx[i], final_mtx[i] );
}
}
-void cutscene_render( world_instance *world, vg_camera *cam )
+/*
+ * Apply an inverse matrix to all bones which maps vertices from bind space into
+ * bone relative positions
+ */
+void skeleton_apply_inverses( ms_skeleton *skele, m4x3f *final_mtx )
{
- if( _cutscene.state >= k_cutscene_state_ready )
+ for( u32 i=0; i<skele->bone_count; i++ )
{
- for( u32 i=0; i<_cutscene.instance_count; i ++ )
- cutscene_render_instance( &_cutscene.instances[i], world, cam );
+ ms_skeleton_bone *sb = &skele->bones[i];
+ m4x3f inverse;
+ m3x3_identity( inverse );
+ v3_negate( sb->co, inverse[3] );
+ m4x3_mul( final_mtx[i], inverse, final_mtx[i] );
}
}
-void _cutscene_gui( ui_context *ctx )
+/*
+ * Apply all IK modifiers (2 bone ik reference from blender is supported)
+ */
+void skeleton_apply_ik_pass( ms_skeleton *skele, m4x3f *final_mtx )
{
- if( _cutscene.subtitle )
- {
- ctx->font = &vgf_default_small;
- ctx->kern[1] = 16;
- ui_px scale = 2;
- ui_rect box = { 0,0, 1000, 80*2 };
- ui_rect_center( (ui_rect){0,0,vg.window_x,vg.window_y}, box );
- box[1] = vg.window_y - (box[3] + 8);
-
- i32 lines = 1;
-
- const char *_c = _cutscene.subtitle;
- u8 c;
-
- i32 length = 0;
- ui_px y = box[1];
-
- while(1)
- {
- c = *(_c ++);
-
- /* TODO: This is pasted straight from vg_ui, maybe create a vg_ui_text_iter() ...? */
- if( c == '\x1B' )
- {
- while( (c = *(_c ++)) )
- {
- if( c == 'm' )
- break;
- }
-
- if( c == 0 )
- break;
- else
- continue;
- }
-
- if( c >= 32 )
- length ++;
- else if( c == '\n' || c == '\0' )
- {
- ui_px w = length * ctx->font->sx*scale + 16;
- ui_rect background_rect = { vg.window_x/2 - w/2, y-8, w, ctx->font->sy*scale+16 };
-
- ui_fill( ctx, background_rect, ui_opacity( GUI_COL_DARK, 0.75f ) );
- y += (ctx->font->sy)*scale + 16;
- length = 0;
- lines ++;
- }
-
- if( c == '\0' )
- break;
- }
-
- ui_text( ctx, box, _cutscene.subtitle, scale, k_ui_align_center, 0 );
- ctx->font = &vgf_default_small;
- ctx->kern[1] = 0;
+ for( u32 i=0; i<skele->ik_count; i++ )
+ {
+ ms_skeleton_ik *ik = &skele->ik[i];
+ v3f v0, /* base -> target */
+ v1, /* base -> pole */
+ vaxis;
+
+ v3f co_base,
+ co_target,
+ co_pole;
+
+ v3_copy( final_mtx[ik->lower][3], co_base );
+ v3_copy( final_mtx[ik->target][3], co_target );
+ v3_copy( final_mtx[ik->pole][3], co_pole );
+
+ v3_sub( co_target, co_base, v0 );
+ v3_sub( co_pole, co_base, v1 );
+ v3_cross( v0, v1, vaxis );
+ v3_normalize( vaxis );
+ v3_normalize( v0 );
+ v3_cross( vaxis, v0, v1 );
+
+ /* localize problem into [x:v0,y:v1] 2d plane */
+ v2f base = { v3_dot( v0, co_base ), v3_dot( v1, co_base ) },
+ end = { v3_dot( v0, co_target ), v3_dot( v1, co_target ) },
+ knee;
+
+ /* Compute angles (basic trig)*/
+ v2f delta;
+ v2_sub( end, base, delta );
+
+ f32 l1 = v3_length( skele->bones[ik->lower].end ),
+ l2 = v3_length( skele->bones[ik->upper].end ),
+ d = vg_clampf( v2_length(delta), fabsf(l1 - l2), l1+l2-0.00001f ),
+ c = acosf( (l1*l1 + d*d - l2*l2) / (2.0f*l1*d) ),
+ rot = atan2f( delta[1], delta[0] ) + c - VG_PIf/2.0f;
+
+ knee[0] = sinf(-rot) * l1;
+ knee[1] = cosf(-rot) * l1;
+
+ m4x3_identity( final_mtx[ik->lower] );
+ m4x3_identity( final_mtx[ik->upper] );
+
+ /* create rotation matrix */
+ v3f co_knee;
+ v3_muladds( co_base, v0, knee[0], co_knee );
+ v3_muladds( co_knee, v1, knee[1], co_knee );
+ vg_line( co_base, co_knee, 0xff00ff00 );
+
+ m4x3f transform;
+ v3_copy( vaxis, transform[0] );
+ v3_muls( v0, knee[0], transform[1] );
+ v3_muladds( transform[1], v1, knee[1], transform[1] );
+ v3_normalize( transform[1] );
+ v3_cross( transform[0], transform[1], transform[2] );
+ v3_copy( co_base, transform[3] );
+
+ m3x3_mul( transform, ik->ia, transform );
+ m4x3_copy( transform, final_mtx[ik->lower] );
+
+ /* upper/knee bone */
+ v3_copy( vaxis, transform[0] );
+ v3_sub( co_target, co_knee, transform[1] );
+ v3_normalize( transform[1] );
+ v3_cross( transform[0], transform[1], transform[2] );
+ v3_copy( co_knee, transform[3] );
+
+ m3x3_mul( transform, ik->ib, transform );
+ m4x3_copy( transform, final_mtx[ik->upper] );
}
}
-/* cutscene magi
- * ----------------------------------------------------------------------------
+/*
+ * Applies the typical operations that you want for an IK rig:
+ * Pose, IK, Pose(deferred), Inverses, Transform
*/
+void skeleton_apply_standard( ms_skeleton *skele, ms_keyframe *pose, m4x3f transform, m4x3f *final_mtx )
+{
+ skeleton_apply_pose( skele, pose, k_anim_apply_defer_ik, final_mtx );
+ skeleton_apply_ik_pass( skele, final_mtx );
+ skeleton_apply_pose( skele, pose, k_anim_apply_deffered_only, final_mtx );
+ skeleton_apply_inverses( skele, final_mtx );
+ skeleton_apply_transform( skele, transform, final_mtx );
+}
-static void cb_cutscene_view( ui_context *ctx, ui_rect rect, struct vg_magi_panel *magi )
+void skeleton_alloc_from( ms_skeleton *skele, vg_stack_allocator *stack, vg_model *model, mdl_armature *armature )
{
- if( _cutscene.state == k_cutscene_state_none )
- {
- ui_text( ctx, rect, "No cutscene loaded.", 1, k_ui_align_middle_center, 0 );
- return;
- }
+ skele->bone_count = armature->bone_count+1;
+ skele->ik_count = 0;
+ skele->collider_count = 0;
- if( _cutscene.state == k_cutscene_state_loading )
+ for( u32 i=0; i<armature->bone_count; i++ )
{
- ui_text( ctx, rect, "Cutscene loading..", 1, k_ui_align_middle_center, 0 );
- return;
+ mdl_bone *bone = &model->bones[ armature->bone_start+i ];
+ if( bone->flags & k_bone_flag_ik )
+ skele->ik_count ++;
+ if( bone->collider )
+ skele->collider_count ++;
}
- if( _cutscene.state == k_cutscene_state_unloading )
- {
- ui_text( ctx, rect, "Cutscene UN-loading..", 1, k_ui_align_middle_center, 0 );
- return;
- }
+ u32 bone_size = sizeof(ms_skeleton_bone) * skele->bone_count,
+ ik_size = sizeof(ms_skeleton_ik) * skele->ik_count;
- ms_strip *usage[8];
- for( u32 i=0; i<VG_ARRAY_LEN(usage); i ++ ) usage[i] = NULL;
+ skele->bones = vg_stack_allocate( stack, bone_size, 8, NULL );
+ skele->ik = vg_stack_allocate( stack, ik_size, 8, NULL );
- ui_rect panel_l, panel_r;
- ui_split( rect, k_ui_axis_v, 400, 4, panel_l, panel_r );
+ memset( skele->bones, 0, bone_size );
+ memset( skele->ik, 0, ik_size );
+}
- if( ui_clip( rect, panel_l, panel_l ) )
- {
- ui_px root[2] = { panel_l[0]+8, panel_l[1]+8 };
- ui_rect box = { root[0], root[1], panel_l[2]-16, 16 };
+/* Setup a skeleton from model. mdl's metadata should stick around */
+void skeleton_setup( ms_skeleton *skele, vg_model *model, u32 index, vg_stack_allocator *stack )
+{
+ u32 ik_count = 0, collider_count = 0;
+ skele->bone_count = 0;
+ skele->bones = NULL;
- for( u32 i=0; i<_cutscene.unique_refs; i ++ )
- {
- struct model_ref *mref = &_cutscene.refs[i];
+ if( !model->armature_count )
+ vg_fatal_error( "No skeleton in model\n" );
- char inf[128];
- snprintf( inf, sizeof(inf), "%s (%u references)", mref->name, mref->reference_count );
- ui_text( ctx, box, inf, 1, k_ui_align_middle_left, 0 );
- box[1] += 16;
- }
- }
+ mdl_armature *armature = &model->armatures[ index ];
+ skeleton_alloc_from( skele, stack, model, armature );
- if( ui_clip( rect, panel_r, panel_r ) )
+ for( u32 i=0; i<armature->bone_count; i++ )
{
- ui_px root[2] = { panel_r[0]+8, panel_r[1]+8 };
+ mdl_bone *bone = &model->bones[ armature->bone_start+i ];
+ ms_skeleton_bone *sb = &skele->bones[i+1];
+
+ v3_copy( bone->co, sb->co );
+ v3_copy( bone->end, sb->end );
- for( u32 i=0; i<af_arrcount(&_cutscene.meta.strips); i ++ )
+ sb->parent = bone->parent;
+ sb->name = af_str( model->packed_strings, bone->pstr_name );
+ sb->flags = bone->flags;
+ sb->collider = bone->collider;
+ sb->orig_bone = bone;
+
+ if( sb->flags & k_bone_flag_ik )
{
- ms_strip *strip = af_arritm(&_cutscene.meta.strips, i );
-
- if( !(strip->mode & k_ms_strip_mode_animation) )
- {
- ui_rect box = { root[0]+strip->offset, root[1], 1, panel_r[3]-16 };
- ui_fill( ctx, box, 0xff00ff00 );
-
- box[1] += box[3] -16;
- box[2] = 200;
- box[3] = 16;
-
- if( ui_clip( panel_r, box, box ) )
- {
- if( strip->mode == k_ms_strip_mode_camera )
- ui_text( ctx, box, "Camera", 1, k_ui_align_middle_left, 0 );
- if( strip->mode == k_ms_strip_mode_subtitle )
- ui_text( ctx, box, "\"", 1, k_ui_align_middle_left, 0 );
- if( strip->mode == k_ms_strip_mode_fadeout )
- ui_text( ctx, box, "\\", 1, k_ui_align_middle_left, 0 );
- }
- continue;
- }
+ skele->bones[ sb->parent ].flags |= k_bone_flag_ik;
- u32 layer = 0;
- for( u32 k=0; k<VG_ARRAY_LEN(usage); k ++ )
- {
- if( usage[k] )
- if( usage[k]->offset + (i32)usage[k]->strip.length < strip->offset )
- usage[k] = NULL;
-
- if( !usage[k] )
- {
- usage[k] = strip;
- layer = k;
- break;
- }
- }
-
- ui_rect box = { strip->offset, layer*32, (i32)strip->strip.length, 30 };
- box[0] += root[0];
- box[1] += root[1];
-
- if( ui_clip( panel_r, box, box ) )
- {
- u32 colour = af_str_hash( &_cutscene.meta.af, strip->strip.pstr_name );
- ui_fill( ctx, box, colour | 0xff000000 );
- ui_text( ctx, box, af_str( &_cutscene.meta.af, strip->strip.pstr_name ), 1, k_ui_align_middle_center, 0 );
- }
+ if( ik_count == skele->ik_count )
+ vg_fatal_error( "Too many ik bones, corrupt model file\n" );
+
+ ms_skeleton_ik *ik = &skele->ik[ ik_count ++ ];
+ ik->upper = i+1;
+ ik->lower = bone->parent;
+ ik->target = bone->ik_target;
+ ik->pole = bone->ik_pole;
}
- ui_rect cursor = { (f32)_cutscene.time*_cutscene.meta.info.framerate, 0, 1, VG_ARRAY_LEN(usage)*32 };
- cursor[0] += root[0];
- cursor[1] += root[1];
- if( ui_clip( panel_r, cursor, cursor ) )
- ui_fill( ctx, cursor, 0xffffffff );
+ box_copy( bone->hitbox, sb->hitbox );
+
+ if( bone->collider )
+ {
+ if( collider_count == skele->collider_count )
+ vg_fatal_error( "Too many collider bones\n" );
+ collider_count ++;
+ }
}
-}
-static int cmd_cutscene_play( int argc, const char *argv[] )
-{
- if( argc == 1 )
- _cutscene_load_and_play( argv[0], 0, 0 );
- return 1;
-}
+ /* fill in implicit root bone */
+ v3_zero( skele->bones[0].co );
+ v3_copy( (v3f){0.0f,1.0f,0.0f}, skele->bones[0].end );
+ skele->bones[0].parent = 0xffffffff;
+ skele->bones[0].flags = 0;
+ skele->bones[0].name = "[root]";
-static int cmd_cutscene_inspector( int argc, const char *argv[] )
-{
- ui_px w = 800, h = 400;
- struct vg_magi_panel *magi = _vg_magi_open( w, h, VG_MAGI_ALL );
- magi->title = "Cutscene Inpsector";
- magi->data = NULL;
- magi->ui_cb = cb_cutscene_view;
- magi->close_cb = NULL;
- return 1;
+ skeleton_create_inverses( skele );
+ vg_success( "Loaded skeleton with %u bones\n", skele->bone_count );
+ vg_success( " %u colliders\n", skele->collider_count );
}
-void cutscene_register(void)
+void skeleton_debug( ms_skeleton *skele, m4x3f *final_mtx )
{
- vg_console_reg_cmd( "cutscene_play", cmd_cutscene_play, NULL );
- vg_console_reg_cmd( "cutscene_inspector", cmd_cutscene_inspector, NULL );
+ for( u32 i=1; i<skele->bone_count; i ++ )
+ {
+ ms_skeleton_bone *sb = &skele->bones[i];
+ v3f p0, p1;
+ v3_copy( sb->co, p0 );
+ v3_add( p0, sb->end, p1 );
+
+ m4x3_mulv( final_mtx[i], p0, p0 );
+ m4x3_mulv( final_mtx[i], p1, p1 );
+
+ if( sb->flags & k_bone_flag_deform )
+ {
+ if( sb->flags & k_bone_flag_ik )
+ vg_line( p0, p1, 0xff0000ff );
+ else
+ vg_line( p0, p1, 0xffcccccc );
+ }
+ else
+ vg_line( p0, p1, 0xff00ffff );
+ }
}
-#pragma once
-#include "model.h"
-#include "world.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/metascene.c"
+#else
#define MS_VERSION_NR 2
#define MS_VERSION_MIN 2
+typedef struct metascene metascene;
typedef struct ms_scene_info ms_scene_info;
-typedef struct ms_context ms_context;
typedef struct ms_instance ms_instance;
typedef struct ms_override ms_override;
typedef struct ms_strip ms_strip;
u32 end_frame;
};
-struct ms_context
+struct metascene
{
- array_file_context af;
+ const void *packed_strings;
ms_scene_info info;
struct array_file_ptr infos,
v2f co, l, r;
};
-struct cs_instance
-{
- bool disable_render;
- u32 ref_id;
- m4x3f *skinning_data;
-};
-
-struct cs_subtitle
-{
- const char *key, *value;
-};
+/* skeletons
+ * ------------------------------------------------------------------------------------------------------------------ */
-#include "skeleton.h"
+typedef struct ms_skeleton ms_skeleton;
+typedef struct ms_skeleton_bone ms_skeleton_bone;
+typedef struct ms_skeleton_ik ms_skeleton_ik;
-struct _cutscene
+struct ms_skeleton
{
- ms_context meta;
- vg_stack_allocator stack;
-
- enum cutscene_state
+ struct ms_skeleton_bone
{
- k_cutscene_state_none,
- k_cutscene_state_loading,
- k_cutscene_state_unloading,
- k_cutscene_state_ready,
- k_cutscene_state_playing,
- k_cutscene_state_done,
- }
- state;
+ v3f co, end;
+ u32 parent;
- struct model_ref
- {
- const char *name;
- u32 name_hash;
- u32 reference_count;
+ u32 flags;
+ int defer;
- mdl_context mdl;
-
- struct cs_skeleton
- {
- struct skeleton sk;
- u32 skinning_offset;
- }
- *skeletons;
- u32 total_skinning_bones;
+ //ms_keyframe kf;
+ mdl_bone *orig_bone;
+ u32 collider; // TODO: SOA
+ boxf hitbox; // TODO: SOA
+ const char *name; // TODO: SOA
}
- * refs;
- u32 unique_refs;
-
- struct cs_instance *instances;
- u32 instance_count;
+ *bones;
+ u32 bone_count;
- struct cs_sampler
+ struct ms_skeleton_ik
{
- ms_strip *strip;
- ms_override *override;
- union
- {
- struct
- {
- ms_track *track;
- f32 *target;
- u32 keyframe;
- u32 semantic;
- }
- curves;
-
- struct
- {
- struct skeleton *ref_sk;
- m4x3f *skinning_data;
- }
- skeleton;
- };
+ u32 lower, upper, target, pole;
+ m3x3f ia, ib;
}
- samplers[32];
- u32 active_samplers;
+ *ik;
+ u32 ik_count;
- ent_camera *active_camera;
- struct cs_instance *player_binding;
+ u32 collider_count,
+ bindable_count;
+};
- u32 strip;
- f32 time;
+void metascene_load( metascene *ms, const c8 *path, vg_stack_allocator *stack );
- bool fadeout;
- u8 skipped;
- f32 fadeout_start, fadeout_cooldown;
+void keyframe_copy_pose( ms_keyframe *kfa, ms_keyframe *kfb, int num );
+void keyframe_rotate_around( ms_keyframe *kf, v3f origin, v3f offset, v4f q );
+void keyframe_lerp( ms_keyframe *kfa, ms_keyframe *kfb, f32 t, ms_keyframe *kfd );
+void keyframe_lerp_pose( ms_keyframe *kfa, ms_keyframe *kfb, float t, ms_keyframe *kfd, int count );
- const char *marker_this_frame;
- const char *subtitle;
- bool subtitle_length_warning;
+void skeleton_alloc_from( ms_skeleton *skele, vg_stack_allocator *stack, vg_model *model, mdl_armature *armature );
+u32 skeleton_bone_id( ms_skeleton *skele, const char *name );
+void skeleton_lerp_pose( ms_skeleton *skele, ms_keyframe *kfa, ms_keyframe *kfb, float t, ms_keyframe *kfd );
+void skeleton_copy_pose( ms_skeleton *skele, ms_keyframe *kfa, ms_keyframe *kfd );
- bool freeze_player;
+typedef struct ms_skeletal_animation ms_skeletal_animation;
+struct ms_skeletal_animation
+{
+ ms_strip *strip;
+ ms_keyframe *keyframes_base;
+ f32 framerate;
+};
- u32 raiser_entity;
+void skeleton_sample_anim( ms_skeleton *skele, ms_skeletal_animation *anim, f32 time, ms_keyframe *output );
+int skeleton_sample_anim_clamped( ms_skeleton *skele, ms_skeletal_animation *anim, f32 time, ms_keyframe *output );
+
+typedef enum anim_apply
+{
+ k_anim_apply_always,
+ k_anim_apply_defer_ik,
+ k_anim_apply_deffered_only,
+ k_anim_apply_absolute
}
-extern _cutscene;
-
-void metascene_load( ms_context *ms, const char *path, void *alloc );
-void cutscene_register(void);
-void cutscene_render( world_instance *world, vg_camera *cam );
-void cutscene_render_fadeout(void);
-bool _cutscene_load_and_play( const char *path, bool freeze_player, u32 raiser_entity );
-void _cutscene_unload(void);
-void cutscene_update( f32 delta );
-ent_camera *_cutscene_active_camera(void);
-void _cutscene_gui( ui_context *ctx );
-
-struct cs_instance *_cutscene_get_first_model_instance( const char *mdl_name );
+anim_apply;
+
+void skeleton_apply_pose( ms_skeleton *skele, ms_keyframe *pose, anim_apply passtype, m4x3f *final_mtx );
+void skeleton_decompose_mtx_absolute( ms_skeleton *skele, ms_keyframe *anim, m4x3f *final_mtx );
+void skeleton_inverse_for_ik( ms_skeleton *skele, v3f ivaxis, u32 id, m3x3f inverse );
+void skeleton_create_inverses( ms_skeleton *skele );
+void skeleton_apply_transform( ms_skeleton *skele, m4x3f transform, m4x3f *final_mtx );
+void skeleton_apply_inverses( ms_skeleton *skele, m4x3f *final_mtx );
+void skeleton_apply_ik_pass( ms_skeleton *skele, m4x3f *final_mtx );
+void skeleton_apply_standard( ms_skeleton *skele, ms_keyframe *pose, m4x3f transform, m4x3f *final_mtx );
+void skeleton_setup( ms_skeleton *skele, vg_model *model, u32 index, vg_stack_allocator *stack );
+void skeleton_debug( ms_skeleton *skele, m4x3f *final_mtx );
+
+#endif
-/*
- * Copyright (C) 2021-2025 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#pragma once
-
-#include "vg/vg_io.h"
-
-#ifdef VG_3D
-#include "vg/vg_tex.h"
-#endif
-
-#include "vg/vg_msg.h"
-#include "vg/vg_string.h"
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include "model.h"
-#include "shader_props.h"
-#include "array_file.h"
-
/*
* Model implementation
*/
-void mdl_fread_pack_file( mdl_context *mdl, mdl_file *info, void *dst )
+VG_TIER_0 vg_stream *vg_model_stream_pack_stream( vg_model_stream_context *ctx, mdl_file *file )
{
- if( !info->pack_size )
+ if( !file->pack_size )
{
- vg_info( "Packed file is only a header; it is not packed" );
- vg_info( "path: %s\n", af_str( &mdl->af, info->pstr_path ) );
- vg_fatal_error( "" );
+ vg_fatal_error( "Packed file is only a header; it is not packed"
+ "path: %s\n", af_str( &ctx->model->packed_strings, file->pstr_path ) );
}
-
- fseek( mdl->af.fp, mdl->pack_base_offset + info->pack_offset, SEEK_SET );
- u64 l = fread( dst, info->pack_size, 1, mdl->af.fp );
-
- if( l != 1 )
- {
- af_close( &mdl->af );
- vg_fatal_error( "Pack data corruption\n" );
- }
-}
-
-void mdl_load_mesh_block( mdl_context *mdl, vg_stack_allocator *stack )
-{
- struct array_file_ptr ptr;
- AF_LOAD_ARRAY_STRUCT( &mdl->af, &ptr, mdl_vert, stack );
- mdl->verts = ptr.data;
- mdl->vert_count = ptr.count;
-
- AF_LOAD_ARRAY_STRUCT( &mdl->af, &ptr, mdl_indice, stack );
- mdl->indices = ptr.data;
- mdl->indice_count = ptr.count;
+ vg_stream_seek( &ctx->stream, ctx->model->pack_base_offset + file->pack_offset );
+ ctx->stream.byte_limit = ctx->model->pack_base_offset + file->pack_offset + file->pack_size;
+ return &ctx->stream;
}
-void mdl_load_metadata_block( mdl_context *mdl, vg_stack_allocator *stack )
+/* This also compiles them */
+VG_TIER_2 static void vg_model_stream_materials( vg_model_stream_context *ctx, vg_stack_allocator *stack )
{
- struct array_file_ptr ptr;
- AF_LOAD_ARRAY_STRUCT( &mdl->af, &ptr, mdl_mesh, stack );
- mdl->meshes = ptr.data;
- mdl->mesh_count = ptr.count;
-
- AF_LOAD_ARRAY_STRUCT( &mdl->af, &ptr, mdl_submesh, stack );
- mdl->submeshes = ptr.data;
- mdl->submesh_count = ptr.count;
-
- AF_LOAD_ARRAY_STRUCT( &mdl->af, &ptr, mdl_texture, stack );
- mdl->textures = ptr.data;
- mdl->texture_count = ptr.count;
+ array_file_ptr mats_ptr;
+ AF_LOAD_ARRAY_STRUCT( &ctx->af, &mats_ptr, mdl_material, stack );
+ ctx->model->materials = mats_ptr.data;
+ ctx->model->material_count = mats_ptr.count;
+
+ u32 size = sizeof(union shader_props) * mats_ptr.count;
+ ctx->model->shader_props = vg_stack_allocate( stack, size, 8, "Compiled shader properties" );
+
+ /*
+ * Step 0:
+ * Acquiring the data source
+ *
+ * Step 1:
+ * Converting into formal KV structure
+ * We have 3 different modes;
+ * v101+: old simple binary structures, requires 'generating' correct kvs
+ * v106+: deprecated 'vg_msg' similar to kvs, only requires conversion
+ * v110+: text KV's, direct parsing into vg_kvs
+ *
+ * Step 2:
+ * Formal KV structure is then compiled into the binary union
+ */
+
+ /* step0 ----------------------------- */
+ u32 temp_frame = _vg_start_temp_frame();
+ {
+ array_file_ptr v101_materials;
+ array_file_ptr v106_data;
+ array_file_ptr v110_data;
- AF_LOAD_ARRAY_STRUCT( &mdl->af, &ptr, mdl_armature, stack );
- mdl->armatures = ptr.data;
- mdl->armature_count = ptr.count;
+#if (VG_MODEL_VERSION_MIN <= 105)
+ if( ctx->model->version <= 105 )
+ af_load_array( &ctx->af, &v101_materials, "mdl_material", _vg_temp_stack(), sizeof(struct mdl_material_v101) );
+ else
+#endif
+ if( ctx->model->version <= 109 )
+ af_load_array( &ctx->af, &v106_data, "shader_data", _vg_temp_stack(), 1 );
+ else
+ af_load_array( &ctx->af, &v110_data, "shader_props", _vg_temp_stack(), 1 );
- AF_LOAD_ARRAY_STRUCT( &mdl->af, &ptr, mdl_bone, stack );
- mdl->bones = ptr.data;
- mdl->bone_count = ptr.count;
+ vg_kvs kvs;
+ vg_kvs_init( &kvs, _vg_temp_stack() );
- mdl_load_materials( mdl, stack );
-}
+ /* step1 ----------------------------- */
+#if (VG_MODEL_VERSION_MIN <= 105)
+ if( ctx->model->version <= 105 )
+ {
+ for( u32 i=0; i<ctx->model->material_count; i ++ )
+ {
+ mdl_material *mat = &ctx->model->materials[ i ];
+ struct mdl_material_v101 *old = af_arritm( &v101_materials, i );
+
+ mat->props.kv_root = vg_kv_append( &kvs, 0, NULL, NULL );
+
+ vg_kv_append( &kvs, mat->props.kv_root, "version", "101" );
+ vg_kv_append_vu32( &kvs, mat->props.kv_root, "tex_diffuse", &old->tex_diffuse, 1 );
+
+ if( mat->shader == k_shader_cubemap )
+ {
+ vg_kv_append_vu32( &kvs, mat->props.kv_root, "cubemap", &old->tex_none0, 1 );
+ vg_kv_append_vf32( &kvs, mat->props.kv_root, "tint", old->colour, 4 );
+ }
+ else if( mat->shader == k_shader_terrain_blend )
+ {
+ vg_kv_append_vf32( &kvs, mat->props.kv_root, "sand_colour", old->colour, 4 );
+ vg_kv_append_vf32( &kvs, mat->props.kv_root, "blend_offset", old->colour1, 2 );
+ }
+ else if( mat->shader == k_shader_standard_vertex_blend )
+ {
+ vg_kv_append_vf32( &kvs, mat->props.kv_root, "blend_offset", old->colour1, 2 );
+ }
+ else if( mat->shader == k_shader_water )
+ {
+ vg_kv_append_vf32( &kvs, mat->props.kv_root, "shore_colour", old->colour, 4 );
+ vg_kv_append_vf32( &kvs, mat->props.kv_root, "deep_colour", old->colour1, 4 );
+ }
+ }
+ }
-static void *mdl_shader_standard( vg_msg *msg, vg_stack_allocator *stack )
-{
- struct shader_props_standard *props = VG_STACK_ALLOCATE_STRUCT( stack, struct shader_props_standard );
- vg_msg_getkvintg( msg, "tex_diffuse", k_vg_msg_u32, &props->tex_diffuse, NULL );
- vg_msg_getkvintg( msg, "render_flags", k_vg_msg_u32, &props->render_flags, NULL );
- return props;
-}
+ else
+#endif
-static void *mdl_shader_terrain( vg_msg *msg, vg_stack_allocator *stack )
-{
- struct shader_props_terrain *props = VG_STACK_ALLOCATE_STRUCT( stack, struct shader_props_terrain );
- vg_msg_getkvintg( msg, "tex_diffuse", k_vg_msg_u32, &props->tex_diffuse, NULL );
- vg_msg_getkvvecf( msg, "sand_colour", k_vg_msg_v4f, props->sand_colour, (v4f){ 0.79, 0.63, 0.48, 1.0 } );
- vg_msg_getkvvecf( msg, "blend_offset", k_vg_msg_v2f, props->blend_offset, (v2f){ 0.5, 0.0 } );
+ if( ctx->model->version <= 109 )
+ {
+ for( u32 i=0; i<ctx->model->material_count; i ++ )
+ {
+ mdl_material *mat = &ctx->model->materials[ i ];
+ mat->props.kv_root = vg_kv_append( &kvs, 0, NULL, NULL );
+ vg_kv_append( &kvs, mat->props.kv_root, "version", "106" );
- return props;
-}
+ void *buffer = NULL;
+ if( v106_data.data )
+ buffer = v106_data.data + mat->props.kvs.offset;
-static void *mdl_shader_vertex_blend( vg_msg *msg, vg_stack_allocator *stack )
-{
- struct shader_props_vertex_blend *props = VG_STACK_ALLOCATE_STRUCT( stack, struct shader_props_vertex_blend );
- vg_msg_getkvintg( msg, "tex_diffuse", k_vg_msg_u32, &props->tex_diffuse, NULL );
- vg_msg_getkvvecf( msg, "blend_offset", k_vg_msg_v2f, props->blend_offset, (v2f){ 0.5, 0.0 } );
- return props;
-}
+ vg_kvs_append_from_legacy_msg2( &kvs, mat->props.kv_root, buffer, mat->props.kvs.size );
+ }
+ }
+ else
+ {
+ for( u32 i=0; i<ctx->model->material_count; i ++ )
+ {
+ mdl_material *mat = &ctx->model->materials[ i ];
+ mat->props.kv_root = vg_kv_append( &kvs, 0, NULL, NULL );
+ vg_kv_append( &kvs, mat->props.kv_root, "version", "110" );
-static void *mdl_shader_water( vg_msg *msg, vg_stack_allocator *stack )
-{
- struct shader_props_water *props = VG_STACK_ALLOCATE_STRUCT( stack, struct shader_props_water );
- vg_msg_getkvvecf( msg, "shore_colour", k_vg_msg_v4f, props->shore_colour, (v4f){0.03,0.32,0.61,1.0} );
- vg_msg_getkvvecf( msg, "deep_colour", k_vg_msg_v4f, props->deep_colour, (v4f){0.0,0.006,0.03,1.0} );
- vg_msg_getkvintg( msg, "fog_scale", k_vg_msg_f32, &props->fog_scale, (f32[]){0.04} );
- vg_msg_getkvintg( msg, "fresnel", k_vg_msg_f32, &props->fresnel, (f32[]){5.0} );
- vg_msg_getkvintg( msg, "water_scale", k_vg_msg_f32, &props->water_sale, (f32[]){ 0.008 } );
- vg_msg_getkvvecf( msg, "wave_speed", k_vg_msg_v4f, props->wave_speed, (v4f){0.008,0.006,0.003,0.03} );
- return props;
-}
+ const c8 *buffer = NULL;
+ if( v110_data.data )
+ buffer = v110_data.data + mat->props.kvs.offset;
-void *mdl_shader_cubemapped( vg_msg *msg, vg_stack_allocator *stack )
-{
- struct shader_props_cubemapped *props = VG_STACK_ALLOCATE_STRUCT( stack, struct shader_props_cubemapped );
- vg_msg_getkvintg( msg, "tex_diffuse", k_vg_msg_u32, &props->tex_diffuse, NULL );
- vg_msg_getkvintg( msg, "cubemap_entity", k_vg_msg_u32, &props->cubemap_entity, NULL );
- vg_msg_getkvvecf( msg, "tint", k_vg_msg_v4f, props->tint, (v4f){1.0,1.0,1.0,1.0} );
- return props;
-}
+ vg_stream kv_stream;
+ vg_buffer_stream_open( &kv_stream, buffer, mat->props.kvs.size, VG_STREAM_READ );
-// TODO: Shitty place for this to be
-const char *_shader_prop_workshop_keys[] =
-{
- [k_workshop_shader_part_truck1 ] = "truck1",
- [k_workshop_shader_part_truck2 ] = "truck2",
- [k_workshop_shader_part_wheel1 ] = "wheel1",
- [k_workshop_shader_part_wheel2 ] = "wheel2",
- [k_workshop_shader_part_wheel3 ] = "wheel3",
- [k_workshop_shader_part_wheel4 ] = "wheel4",
- [k_workshop_shader_part_edge ] = "edge",
- [k_workshop_shader_part_griptape] = "griptape",
- [k_workshop_shader_part_deck ] = "deck"
-};
+ vg_kv_parser parser;
+ vg_kv_parser_init( &parser, &kvs, mat->props.kv_root );
+ vg_kv_parse_stream( &parser, &kv_stream );
+ }
+ }
-void *mdl_shader_workshop( vg_msg *msg, vg_stack_allocator *stack )
-{
- struct shader_props_workshop *props = VG_STACK_ALLOCATE_STRUCT( stack, struct shader_props_workshop );
- for( u32 i=0; i<k_workshop_shader_part_max; i ++ )
- vg_msg_getkvintg( msg, _shader_prop_workshop_keys[i], k_vg_msg_u32, &props->tex_all[i], NULL );
+ vg_kv_write wtest = { .fp = stdout, .depth = 0 };
+ vg_kv_print_tree( &wtest, &kvs, 0 );
- return props;
+ /* step2 ----------------------------- */
+ for( u32 i=0; i<ctx->model->material_count; i ++ )
+ {
+ mdl_material *mat = &ctx->model->materials[ i ];
+ u32 root = mat->props.kv_root;
+ union shader_props *props = &ctx->model->shader_props[ i ];
+
+ if( mat->shader == k_shader_standard ||
+ mat->shader == k_shader_standard_cutout ||
+ mat->shader == k_shader_foliage ||
+ mat->shader == k_shader_fxglow )
+ {
+ vg_kv_read_vu32( &kvs, root, "tex_diffuse", (u32[]){0}, &props->standard.tex_diffuse, 1 );
+ vg_kv_read_vu32( &kvs, root, "render_flags", (u32[]){0}, &props->standard.render_flags, 1 );
+ }
+ else if( mat->shader == k_shader_standard_vertex_blend )
+ {
+ vg_kv_read_vu32( &kvs, root, "tex_diffuse", (u32[]){0}, &props->vertex_blend.tex_diffuse, 1 );
+ vg_kv_read_vf32( &kvs, root, "blend_offset", (v2f){ 0.5, 0.0 }, props->vertex_blend.blend_offset, 2 );
+ }
+ else if( mat->shader == k_shader_cubemap )
+ {
+ vg_kv_read_vu32( &kvs, root, "tex_diffuse", (u32[]){0}, &props->cubemapped.tex_diffuse, 1 );
+ vg_kv_read_vu32( &kvs, root, "cubemap_entity", (u32[]){0}, &props->cubemapped.cubemap_entity, 1 );
+ vg_kv_read_vf32( &kvs, root, "tint", (v4f){1.0,1.0,1.0,1.0}, props->cubemapped.tint, 4 );
+ }
+ else if( mat->shader == k_shader_terrain_blend )
+ {
+ vg_kv_read_vu32( &kvs, root, "tex_diffuse", (u32[]){0}, &props->terrain.tex_diffuse, 1 );
+ vg_kv_read_vf32( &kvs, root, "sand_colour", (v4f){ 0.79, 0.63, 0.48, 1.0 }, props->terrain.sand_colour, 4 );
+ vg_kv_read_vf32( &kvs, root, "blend_offset", (v2f){ 0.5, 0.0 }, props->terrain.blend_offset, 2 );
+ }
+ else if( mat->shader == k_shader_water )
+ {
+ vg_kv_read_vf32( &kvs, root, "shore_colour", (v4f){0.03,0.32,0.61,1.0}, props->water.shore_colour, 4 );
+ vg_kv_read_vf32( &kvs, root, "deep_colour", (v4f){0.0,0.006,0.03,1.0}, props->water.deep_colour, 4 );
+ vg_kv_read_vf32( &kvs, root, "fog_scale", (f32[]){0.04}, &props->water.fog_scale, 1 );
+ vg_kv_read_vf32( &kvs, root, "fresnel", (f32[]){5.0}, &props->water.fresnel, 1 );
+ vg_kv_read_vf32( &kvs, root, "water_scale", (f32[]){ 0.008 }, &props->water.water_sale, 1 );
+ vg_kv_read_vf32( &kvs, root, "wave_speed", (v4f){0.008,0.006,0.003,0.03}, props->water.wave_speed, 4 );
+ }
+ else if( mat->shader == k_shader_workshop )
+ {
+ const c8 *_shader_prop_workshop_keys[] =
+ {
+ [k_workshop_shader_part_truck1 ] = "truck1",
+ [k_workshop_shader_part_truck2 ] = "truck2",
+ [k_workshop_shader_part_wheel1 ] = "wheel1",
+ [k_workshop_shader_part_wheel2 ] = "wheel2",
+ [k_workshop_shader_part_wheel3 ] = "wheel3",
+ [k_workshop_shader_part_wheel4 ] = "wheel4",
+ [k_workshop_shader_part_edge ] = "edge",
+ [k_workshop_shader_part_griptape] = "griptape",
+ [k_workshop_shader_part_deck ] = "deck"
+ };
+
+ for( u32 j=0; j<k_workshop_shader_part_max; j ++ )
+ vg_kv_read_vu32( &kvs, root, _shader_prop_workshop_keys[j], (u32[]){0}, &props->workshop.tex_all[j], 1 );
+ }
+ }
+ }
+ _vg_end_temp_frame( temp_frame );
}
-static bool mdl_legacy_v105_properties( struct mdl_material_v105 *mat, vg_msg *dst )
+VG_TIER_2 void vg_model_stream_metadata( vg_model_stream_context *ctx, vg_stack_allocator *stack )
{
- vg_msg_wkvnum( dst, "tex_diffuse", k_vg_msg_u32, 1, &mat->tex_diffuse );
+ array_file_ptr strings;
+ af_load_array( &ctx->af, &strings, "strings", stack, 1 );
+ ctx->model->packed_strings = strings.data;
+ ctx->model->flags |= VG_MODEL_CPU_METADATA;
- if( mat->shader == k_shader_cubemap )
- {
- vg_msg_wkvnum( dst, "cubemap", k_vg_msg_u32, 1, &mat->tex_none0 );
- vg_msg_wkvnum( dst, "tint", k_vg_msg_f32, 4, mat->colour );
- }
- else if( mat->shader == k_shader_terrain_blend )
- {
- vg_msg_wkvnum( dst, "sand_colour", k_vg_msg_f32, 4, mat->colour );
- vg_msg_wkvnum( dst, "blend_offset", k_vg_msg_f32, 2, mat->colour1 );
- }
- else if( mat->shader == k_shader_standard_vertex_blend )
- {
- vg_msg_wkvnum( dst, "blend_offset", k_vg_msg_f32, 2, mat->colour1 );
- }
- else if( mat->shader == k_shader_water )
- {
- vg_msg_wkvnum( dst, "shore_colour", k_vg_msg_f32, 4, mat->colour );
- vg_msg_wkvnum( dst, "deep_colour", k_vg_msg_f32, 4, mat->colour1 );
- }
+ array_file_meta *pack = af_find_array( &ctx->af, "pack" );
+ if( pack ) ctx->model->pack_base_offset = pack->file_offset;
+ else ctx->model->pack_base_offset = 0;
- return 1;
-}
+ struct array_file_ptr ptr;
+ AF_LOAD_ARRAY_STRUCT( &ctx->af, &ptr, mdl_mesh, stack );
+ ctx->model->meshes = ptr.data;
+ ctx->model->mesh_count = ptr.count;
-void mdl_load_materials( mdl_context *mdl, vg_stack_allocator *stack )
-{
- array_file_ptr mats_ptr;
- AF_LOAD_ARRAY_STRUCT( &mdl->af, &mats_ptr, mdl_material, stack );
- mdl->materials = mats_ptr.data;
- mdl->material_count = mats_ptr.count;
-
-#if (MDL_VERSION_MIN <= 105)
- array_file_ptr legacy_materials;
- if( mdl->version <= 105 )
- af_load_array( &mdl->af, &legacy_materials, "mdl_material", stack, sizeof(struct mdl_material_v105) );
-#endif
+ AF_LOAD_ARRAY_STRUCT( &ctx->af, &ptr, mdl_submesh, stack );
+ ctx->model->submeshes = ptr.data;
+ ctx->model->submesh_count = ptr.count;
- array_file_ptr data;
- af_load_array( &mdl->af, &data, "shader_data", stack, 1 );
+ AF_LOAD_ARRAY_STRUCT( &ctx->af, &ptr, mdl_texture, stack );
+ ctx->model->textures = ptr.data;
+ ctx->model->texture_count = ptr.count;
- for( u32 i=0; i<mdl->material_count; i ++ )
- {
- mdl_material *mat = &mdl->materials[ i ];
- vg_msg msg;
+ AF_LOAD_ARRAY_STRUCT( &ctx->af, &ptr, mdl_armature, stack );
+ ctx->model->armatures = ptr.data;
+ ctx->model->armature_count = ptr.count;
-#if (MDL_VERSION_MIN <= 105)
- u8 legacy_buf[512];
- if( mdl->version <= 105 )
- {
- vg_msg_init( &msg, legacy_buf, sizeof(legacy_buf) );
- mdl_legacy_v105_properties( af_arritm( &legacy_materials,i ), &msg );
- vg_msg_init( &msg, legacy_buf, msg.cur.co );
- }
- else
-#endif
- {
- vg_msg_init( &msg, data.data? (data.data + mat->props.kvs.offset): NULL, mat->props.kvs.size );
- }
+ AF_LOAD_ARRAY_STRUCT( &ctx->af, &ptr, mdl_bone, stack );
+ ctx->model->bones = ptr.data;
+ ctx->model->bone_count = ptr.count;
- if( mat->shader == k_shader_standard ||
- mat->shader == k_shader_standard_cutout ||
- mat->shader == k_shader_foliage ||
- mat->shader == k_shader_fxglow )
- {
- mat->props.compiled = mdl_shader_standard( &msg, stack );
- }
- else if( mat->shader == k_shader_standard_vertex_blend )
- {
- mat->props.compiled = mdl_shader_vertex_blend( &msg, stack );
- }
- else if( mat->shader == k_shader_cubemap )
- {
- mat->props.compiled = mdl_shader_cubemapped( &msg, stack );
- }
- else if( mat->shader == k_shader_terrain_blend )
- {
- mat->props.compiled = mdl_shader_terrain( &msg, stack );
- }
- else if( mat->shader == k_shader_water )
- {
- mat->props.compiled = mdl_shader_water( &msg, stack );
- }
- else if( mat->shader == k_shader_workshop )
- {
- mat->props.compiled = mdl_shader_workshop( &msg, stack );
- }
- else
- mat->props.compiled = NULL;
- }
+ vg_model_stream_materials( ctx, stack );
}
-/*
- * if calling mdl_open, and the file does not exist, the game will fatal quit
- */
-void mdl_open( mdl_context *mdl, const char *path, vg_stack_allocator *stack )
+VG_TIER_2 void vg_model_stream_meshes_cpu( vg_model_stream_context *ctx, vg_stack_allocator *stack )
{
- memset( mdl, 0, sizeof( mdl_context ) );
- af_open( &mdl->af, path, MDL_VERSION_MIN, MDL_VERSION_NR, stack );
- mdl->version = mdl->af.header.version;
-
- array_file_meta *pack = af_find_array( &mdl->af, "pack" );
- if( pack )
- mdl->pack_base_offset = pack->file_offset;
- else
- mdl->pack_base_offset = 0;
-}
+ VG_ASSERT( ctx->model->flags & VG_MODEL_CPU_METADATA );
+ ctx->model->flags |= VG_MODEL_CPU_MESHES;
-/*
- * close file handle
- */
-void mdl_close( mdl_context *mdl )
-{
- af_close( &mdl->af );
-}
-
-/* useful things you can do with the model */
+ struct array_file_ptr ptr;
+ AF_LOAD_ARRAY_STRUCT( &ctx->af, &ptr, mdl_vert, stack );
+ ctx->model->verts = ptr.data;
+ ctx->model->vert_count = ptr.count;
-void mdl_transform_m4x3( mdl_transform *transform, m4x3f mtx )
-{
- q_m3x3( transform->q, mtx );
- v3_muls( mtx[0], transform->s[0], mtx[0] );
- v3_muls( mtx[1], transform->s[1], mtx[1] );
- v3_muls( mtx[2], transform->s[2], mtx[2] );
- v3_copy( transform->co, mtx[3] );
+ AF_LOAD_ARRAY_STRUCT( &ctx->af, &ptr, mdl_indice, stack );
+ ctx->model->indices = ptr.data;
+ ctx->model->indice_count = ptr.count;
}
-/*
- * Simple mesh interface for OpenGL
- * ----------------------------------------------------------------------------
- */
+#if defined( VG_ENGINE )
+struct model_upload_task
+{
+ vg_model *model;
+ mdl_vert *vert_buffer;
+ u32 *indice_buffer;
+};
-#ifdef VG_3D
-static void mesh_upload( glmesh *mesh, mdl_vert *verts, u32 vert_count, u32 *indices, u32 indice_count )
+VG_TIER_0 static void vg_model_upload_task( struct model_upload_task *in_args )
{
- glGenVertexArrays( 1, &mesh->vao );
- glGenBuffers( 1, &mesh->vbo );
- glGenBuffers( 1, &mesh->ebo );
- glBindVertexArray( mesh->vao );
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
- size_t stride = sizeof(mdl_vert);
+ glGenVertexArrays( 1, &in_args->model->vao );
+ glBindVertexArray( in_args->model->vao );
+ glGenBuffers( 1, &in_args->model->vbo );
+ glGenBuffers( 1, &in_args->model->ebo );
- glBindBuffer( GL_ARRAY_BUFFER, mesh->vbo );
- glBufferData( GL_ARRAY_BUFFER, vert_count*stride, verts, GL_STATIC_DRAW );
+ u32 stride = sizeof(mdl_vert);
+ glBindBuffer( GL_ARRAY_BUFFER, in_args->model->vbo );
+ glBufferData( GL_ARRAY_BUFFER, in_args->model->vert_count*stride, in_args->vert_buffer, GL_STATIC_DRAW );
- glBindVertexArray( mesh->vao );
- glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, mesh->ebo );
- glBufferData( GL_ELEMENT_ARRAY_BUFFER, indice_count*sizeof(u32), indices, GL_STATIC_DRAW );
+ glBindVertexArray( in_args->model->vao );
+ glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, in_args->model->ebo );
+ glBufferData( GL_ELEMENT_ARRAY_BUFFER, in_args->model->indice_count*sizeof(u32),
+ in_args->indice_buffer, GL_STATIC_DRAW );
/* 0: coordinates */
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0 );
/* 5: groups */
glVertexAttribIPointer( 5, 4, GL_UNSIGNED_BYTE, stride, (void *)offsetof(mdl_vert, groups) );
glEnableVertexAttribArray( 5 );
-
- mesh->indice_count = indice_count;
- mesh->loaded = 1;
-}
-
-void mesh_bind( glmesh *mesh )
-{
- glBindVertexArray( mesh->vao );
-}
-
-void mesh_drawn( u32 start, u32 count )
-{
- glDrawElements( GL_TRIANGLES, count, GL_UNSIGNED_INT, (void *)(start*sizeof(u32)) );
-}
-
-void mesh_draw( glmesh *mesh )
-{
- mesh_drawn( 0, mesh->indice_count );
-}
-
-void mesh_free( glmesh *mesh )
-{
- if( mesh->loaded )
- {
- glDeleteVertexArrays( 1, &mesh->vao );
- glDeleteBuffers( 1, &mesh->ebo );
- glDeleteBuffers( 1, &mesh->vbo );
- mesh->loaded = 0;
- }
-}
-
-void mdl_draw_submesh( mdl_submesh *sm )
-{
- mesh_drawn( sm->indice_start, sm->indice_count );
}
#endif
-i32 mdl_get_mesh_index( mdl_context *mdl, const char *name )
+#if defined( VG_ENGINE )
+VG_TIER_2 void vg_model_stream_meshes_gpu( vg_model_stream_context *ctx, u32 *fixup_table )
{
- u32 hash = vg_strdjb2( name );
- for( u32 i=0; i<mdl->mesh_count; i++ )
- {
- mdl_mesh *mesh = &mdl->meshes[ i ];
- if( af_str_eq( &mdl->af, mesh->pstr_name, name, hash ) )
- return i;
- }
- return -1;
-}
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+ VG_ASSERT( ctx->model->flags & VG_MODEL_CPU_METADATA );
+ ctx->model->flags |= VG_MODEL_GPU_MESHES;
-i32 mdl_get_submesh_index( mdl_context *mdl, const char *mesh_name )
-{
- i32 mesh_index = mdl_get_mesh_index( mdl, mesh_name );
- if( mesh_index == -1 )
- return -1;
-
- mdl_mesh *mesh = &mdl->meshes[ mesh_index ];
- if( !mesh->submesh_count )
- return -1;
+ /* NOTE: We could check here if we already have CPU meshes and use those buffers.
+ * In very rare instances (1 time) we use both paths. */
- return mesh->submesh_start;
-}
-
-#ifdef VG_3D
-struct payload_glmesh_load
-{
- mdl_vert *verts;
- u32 *indices;
-
- u32 vertex_count,
- indice_count;
-
- glmesh *mesh;
-};
-
-static void _sync_mdl_load_glmesh( vg_async_task *task )
-{
- THREAD_0;
-
- struct payload_glmesh_load *job = (void *)task->data;
- mesh_upload( job->mesh, job->verts, job->vertex_count, job->indices, job->indice_count );
-}
-
-void mdl_async_load_glmesh( mdl_context *mdl, glmesh *mesh, u32 *fixup_table )
-{
- THREAD_1;
-
- array_file_meta *arr_vertices = af_find_array( &mdl->af, "mdl_vert" );
- array_file_meta *arr_indices = af_find_array( &mdl->af, "mdl_indice" );
+ array_file_meta *arr_vertices = af_find_array( &ctx->af, "mdl_vert" );
+ array_file_meta *arr_indices = af_find_array( &ctx->af, "mdl_indice" );
if( arr_vertices && arr_indices )
{
u32 size_verts = vg_align8(sizeof(mdl_vert)*arr_vertices->item_count),
size_indices = vg_align8(sizeof(mdl_indice)*arr_indices->item_count),
- size_hdr = vg_align8(sizeof(struct payload_glmesh_load)),
+ size_hdr = vg_align8(sizeof(struct model_upload_task)),
total = size_hdr + size_verts + size_indices;
- vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, total, 1 );
- struct payload_glmesh_load *job = (void *)task->data;
+ struct model_upload_task *out_args = _vg_async_alloc( VG_THREAD_MAIN_ID, total );
+
+ out_args->model = ctx->model;
+ out_args->vert_buffer = ((void*)out_args) + size_hdr;
+ out_args->indice_buffer = ((void*)out_args) + size_hdr + size_verts;
+ ctx->model->vert_count = arr_vertices->item_count;
+ ctx->model->indice_count = arr_indices->item_count;
- job->mesh = mesh;
- job->verts = (void*)(task->data + size_hdr);
- job->indices = (void*)(task->data + size_hdr + size_verts);
- job->vertex_count = arr_vertices->item_count;
- job->indice_count = arr_indices->item_count;
- af_load_array_file_buffer( &mdl->af, arr_vertices, job->verts, sizeof(mdl_vert) );
- af_load_array_file_buffer( &mdl->af, arr_indices, job->indices, sizeof(mdl_indice) );
+ af_load_array_file_buffer( &ctx->af, arr_vertices, out_args->vert_buffer, sizeof(mdl_vert) );
+ af_load_array_file_buffer( &ctx->af, arr_indices, out_args->indice_buffer, sizeof(mdl_indice) );
if( fixup_table )
{
- for( u32 i=0; i<job->vertex_count; i ++ )
+ for( u32 i=0; i<ctx->model->vert_count; i ++ )
{
- mdl_vert *vert = &job->verts[i];
-
+ mdl_vert *vert = &out_args->vert_buffer[i];
for( u32 j=0; j<4; j++ )
vert->groups[j] = fixup_table[vert->groups[j]];
}
* Unpack the indices (if there are meshes)
* ---------------------------------------------------------
*/
-
- if( mdl->submesh_count )
+ if( ctx->model->submesh_count )
{
- mdl_submesh *sm = &mdl->submeshes[ 0 ];
+ mdl_submesh *sm = &ctx->model->submeshes[ 0 ];
u32 offset = sm->vertex_count;
- for( u32 i=1; i<mdl->submesh_count; i++ )
+ for( u32 i=1; i<ctx->model->submesh_count; i++ )
{
- mdl_submesh *sm = &mdl->submeshes[ i ];
- u32 *indices = job->indices + sm->indice_start;
+ mdl_submesh *sm = &ctx->model->submeshes[ i ];
+ u32 *indices = out_args->indice_buffer + sm->indice_start;
for( u32 j=0; j<sm->indice_count; j++ )
indices[j] += offset;
}
}
- /*
- * Dispatch
- * -------------------------
- */
-
- vg_async_task_dispatch( task, _sync_mdl_load_glmesh );
+ _vg_async_send( out_args, (vg_async_fn)vg_model_upload_task );
}
else
vg_fatal_error( "No vertex/indice data in model file\n" );
}
-/* uploads the glmesh, and textures. everything is saved into the mdl_context */
-void mdl_async_full_load_std( mdl_context *mdl, u32 *fixup_table )
+VG_TIER_2 void vg_model_stream_textures_gpu( vg_model_stream_context *ctx )
{
- THREAD_1;
- mdl_async_load_glmesh( mdl, &mdl->mesh, fixup_table );
-
- for( u32 i=0; i<mdl->texture_count; i ++ )
+ VG_ASSERT( ctx->model->flags & VG_MODEL_CPU_METADATA );
+ ctx->model->flags |= VG_MODEL_GPU_TEXTURES;
+ for( u32 i=0; i<ctx->model->texture_count; i ++ )
+ {
+ mdl_texture *tex = &ctx->model->textures[ i ];
+ mdl_file pack_info = tex->file;
+ _vg_tex_load_stream( &tex->tex, vg_model_stream_pack_stream( ctx, &pack_info ),
+ VG_TEX_REPEAT | VG_TEX_NEAREST | VG_TEX_NOMIP );
+ }
+}
+#endif
+
+VG_TIER_1 bool vg_model_stream_open( vg_model_stream_context *ctx, vg_model *model, const c8 *path )
+{
+ vg_zero_mem( ctx, sizeof(vg_model_stream_context) );
+ vg_zero_mem( model, sizeof(vg_model) );
+ if( vg_file_stream_open( &ctx->stream, path, VG_STREAM_READ ) )
{
- vg_stack_clear( &vg.scratch );
- mdl_texture *tex = &mdl->textures[ i ];
+ ctx->model = model;
+ ctx->temp_frame = _vg_start_temp_frame();
+ if( !af_open_stream( &ctx->af, &ctx->stream, VG_MODEL_VERSION_MIN, VG_MODEL_VERSION_NR, _vg_temp_stack() ) )
+ {
+ vg_file_stream_close( &ctx->stream );
+ _vg_end_temp_frame( ctx->temp_frame );
+ return 0;
+ }
+ ctx->model->version = ctx->af.header.version;
+ return 1;
+ }
+ else return 0;
+}
+
+VG_TIER_0 void vg_model_stream_close( vg_model_stream_context *ctx )
+{
+ vg_file_stream_close( &ctx->stream );
+ _vg_end_temp_frame( ctx->temp_frame );
+}
+
+VG_TIER_2 bool vg_model_load( vg_model *model, u32 model_flags, const c8 *path, vg_stack_allocator *stack )
+{
+ bool success = 0;
+ model_flags |= VG_MODEL_CPU_METADATA;
+
+ vg_model_stream_context ctx;
+ if( vg_model_stream_open( &ctx, model, path ) )
+ {
+ if( model_flags & VG_MODEL_CPU_METADATA )
+ vg_model_stream_metadata( &ctx, stack );
+
+ if( model_flags & VG_MODEL_CPU_MESHES )
+ vg_model_stream_meshes_cpu( &ctx, stack );
+
+#if defined( VG_ENGINE )
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+ if( model_flags & VG_MODEL_GPU_MESHES )
+ vg_model_stream_meshes_gpu( &ctx, NULL );
+
+ if( model_flags & VG_MODEL_GPU_TEXTURES )
+ vg_model_stream_textures_gpu( &ctx );
+#endif
- void *data = vg_stack_allocate( &vg.scratch, tex->file.pack_size, 8, "MDL Pack Data" );
- mdl_fread_pack_file( mdl, &tex->file, data );
- vg_tex2d_load_qoi_async( data, tex->file.pack_size, VG_TEX2D_CLAMP|VG_TEX2D_NEAREST, &tex->glname );
+ vg_model_stream_close( &ctx );
+ success = 1;
}
+ return success;
}
-void mdl_sync_std_unload( mdl_context *mdl )
+#if defined( VG_ENGINE )
+VG_TIER_0 void vg_model_unload_gpu( vg_model *model )
{
- mesh_free( &mdl->mesh );
+ if( model->flags & VG_MODEL_GPU_MESHES )
+ {
+ model->flags &= ~(u32)(VG_MODEL_GPU_MESHES);
+ glDeleteVertexArrays( 1, &model->vao );
+ glDeleteBuffers( 1, &model->ebo );
+ glDeleteBuffers( 1, &model->vbo );
+ }
+
+ if( model->flags & VG_MODEL_GPU_TEXTURES )
+ for( u32 i=0; i<model->texture_count; i ++ )
+ vg_tex_delete( &model->textures[i].tex );
+}
+#endif
- for( u32 i=0; i<mdl->texture_count; i ++ )
- glDeleteTextures( 1, &mdl->textures[i].glname );
+VG_TIER_0 void mdl_transform_m4x3( mdl_transform *transform, m4x3f mtx )
+{
+ q_m3x3( transform->q, mtx );
+ v3_muls( mtx[0], transform->s[0], mtx[0] );
+ v3_muls( mtx[1], transform->s[1], mtx[1] );
+ v3_muls( mtx[2], transform->s[2], mtx[2] );
+ v3_copy( transform->co, mtx[3] );
+}
+
+#if defined( VG_ENGINE )
+
+VG_TIER_0 void vg_model_bind_mesh( vg_model *model )
+{
+ glBindVertexArray( model->vao );
+}
+
+VG_TIER_0 void vg_model_draw_elements( u32 start, u32 count )
+{
+ glDrawElements( GL_TRIANGLES, count, GL_UNSIGNED_INT, (void *)(start*sizeof(u32)) );
+}
+
+VG_TIER_0 void vg_model_draw_submesh( mdl_submesh *sm )
+{
+ vg_model_draw_elements( sm->indice_start, sm->indice_count );
}
#endif
+VG_TIER_0 i32 vg_model_get_mesh_index( vg_model *model, const c8 *name )
+{
+ u32 hash = vg_strdjb2( name );
+ for( u32 i=0; i<model->mesh_count; i++ )
+ {
+ mdl_mesh *mesh = &model->meshes[ i ];
+ if( af_str_eq( model->packed_strings, mesh->pstr_name, name, hash ) )
+ return i;
+ }
+ return -1;
+}
+
+VG_TIER_0 i32 vg_model_get_submesh_index( vg_model *model, const c8 *mesh_name )
+{
+ i32 mesh_index = vg_model_get_mesh_index( model, mesh_name );
+ if( mesh_index == -1 )
+ return -1;
+
+ mdl_mesh *mesh = &model->meshes[ mesh_index ];
+ if( !mesh->submesh_count )
+ return -1;
+
+ return mesh->submesh_start;
+}
+
+#if defined( VG_ENGINE )
void mdl_compiler_init( mdl_compiler *compiler )
{
vg_stack_init( &compiler->stack, NULL, VG_MB(10), "MDL Compiler" );
u32 texture_id = compiler->textures->element_count + 1;
mdl_texture *texture = af_compiler_allocate_items( &compiler->af, compiler->textures, 1 )->data;
- texture->glname = 0;
mdl_compiler_pack_data( compiler, name, data, data_len, &texture->file );
return texture_id;
}
-void mdl_compiler_push_shaderdata( mdl_compiler *compiler, u32 shader_id, vg_msg *shader_kvs )
+void mdl_compiler_push_shaderdata( mdl_compiler *compiler, u32 shader_id, vg_kvs *shader_kvs )
{
mdl_material *current_material = compiler->materials->last->data;
current_material->shader = shader_id;
current_material->props.kvs.offset = compiler->shader_data->element_count;
+
+ // FIXME FIXME FIXME FIXME FIXME NEED TO FLATTEN OUT THE KVS INTO STRINGYMABOB!!!!!!!!!!!!!!!!
+#if 0
current_material->props.kvs.size = shader_kvs->cur.co;
void *dest = af_compiler_allocate_items( &compiler->af, compiler->shader_data, vg_align8(shader_kvs->cur.co) )->data;
memcpy( dest, shader_kvs->buf, shader_kvs->cur.co );
+#endif
}
void mdl_compiler_free( mdl_compiler *compiler )
{
vg_stack_free( &compiler->stack );
}
+
+#endif
-/*
- * Copyright (C) 2021-2024 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
+#if defined( SR_IMPLEMENTATION )
+# include "src/model.c"
+#else
-#pragma once
+#define VG_MODEL_VERSION_MIN 101
+#define VG_MODEL_VERSION_NR 109
+
+#define VG_MODEL_CPU_METADATA 0x4
+#define VG_MODEL_CPU_MESHES 0x8
+
+#if defined( VG_ENGINE )
+# define VG_MODEL_GPU_TEXTURES 0x1
+# define VG_MODEL_GPU_MESHES 0x2
+# define VG_MODEL_ENGINE_STANDARD (VG_MODEL_CPU_METADATA|VG_MODEL_GPU_TEXTURES|VG_MODEL_GPU_MESHES)
+# define VG_MODEL_ENGINE_PROCEDURAL_SOURCE (VG_MODEL_CPU_METADATA|VG_MODEL_GPU_TEXTURES|VG_MODEL_CPU_MESHES)
+#endif
+
+typedef u32 mdl_indice;
+typedef struct mdl_vert mdl_vert;
+typedef struct mdl_transform mdl_transform;
+typedef struct mdl_submesh mdl_submesh;
+typedef struct mdl_material mdl_material;
+typedef struct mdl_bone mdl_bone;
+typedef struct mdl_armature mdl_armature;
+typedef struct mdl_animation mdl_animation;
+typedef struct mdl_mesh mdl_mesh;
+typedef struct mdl_file mdl_file;
+typedef union mdl_texture mdl_texture;
+typedef struct mdl_header mdl_header;
+
+typedef struct vg_model vg_model;
+typedef struct vg_model_stream_context vg_model_stream_context;
+
+
+/* Load model the easy way */
+VG_TIER_2 bool vg_model_load( vg_model *model, u32 model_flags, const c8 *path, vg_stack_allocator *stack );
+
+#if defined( VG_ENGINE )
+VG_TIER_0 void vg_model_unload_gpu( vg_model *model );
+#endif
+
+/* Sub functions for each part of the load process
+ * --------------------------------------------------------------------------------------------------------------- */
+struct vg_model_stream_context
+{
+ vg_stream stream;
+ array_file_context af;
+ vg_model *model;
+
+ u32 temp_frame;
+};
+
+VG_TIER_1 bool vg_model_stream_open( vg_model_stream_context *ctx, vg_model *model, const c8 *path );
+VG_TIER_0 void vg_model_stream_close( vg_model_stream_context *ctx );
+
+/* Parts which you might want (currently they all require metadata to be explicitly loaded) */
+VG_TIER_2 void vg_model_stream_metadata( vg_model_stream_context *ctx, vg_stack_allocator *stack );
+VG_TIER_2 void vg_model_stream_meshes_cpu( vg_model_stream_context *ctx, vg_stack_allocator *stack );
+
+#if defined( VG_ENGINE )
+VG_TIER_2 void vg_model_stream_meshes_gpu( vg_model_stream_context *ctx, u32 *fixup_table );
+VG_TIER_2 void vg_model_stream_textures_gpu( vg_model_stream_context *ctx );
+#endif
+
+VG_TIER_0 vg_stream *vg_model_stream_pack_stream( vg_model_stream_context *ctx, mdl_file *file );
-#define MDL_VERSION_MIN 101
-#define MDL_VERSION_NR 109
-#include "array_file.h"
+
+/* Rendering operations
+ * ----------------------------------------------------------------------------------------------------------------- */
+#if defined( VG_ENGINE )
+VG_TIER_0 void vg_model_bind_mesh( vg_model *model );
+VG_TIER_0 void vg_model_draw_elements( u32 start, u32 count );
+VG_TIER_0 void vg_model_draw_submesh( mdl_submesh *sm );
+#endif
+
+VG_TIER_0 i32 vg_model_get_mesh_index( vg_model *model, const c8 *name );
+VG_TIER_0 i32 vg_model_get_submesh_index( vg_model *model, const c8 *mesh_name );
+
+VG_TIER_0 void mdl_transform_m4x3( mdl_transform *transform, m4x3f mtx );
+
+
+
+/* model compiler
+ * ----------------------------------------------------------------------------------------------------------------- */
+#if defined( VG_ENGINE )
+typedef struct mdl_compiler mdl_compiler;
+struct mdl_compiler
+{
+ af_compiler af;
+ af_compiler_index *meshes,
+ *submeshes,
+ *vertices,
+ *indices,
+ *bones,
+ *materials,
+ *shader_data,
+ *armatures,
+ *textures,
+ *pack_data;
+ vg_stack_allocator stack;
+};
+#endif
enum mdl_shader{
k_shader_standard = 0,
#pragma pack(pop)
-typedef u32 mdl_indice;
-
-typedef struct mdl_context mdl_context;
-typedef struct mdl_vert mdl_vert;
-typedef struct mdl_transform mdl_transform;
-typedef struct mdl_submesh mdl_submesh;
-typedef struct mdl_material mdl_material;
-typedef struct mdl_bone mdl_bone;
-typedef struct mdl_armature mdl_armature;
-typedef struct mdl_animation mdl_animation;
-typedef struct mdl_mesh mdl_mesh;
-typedef struct mdl_file mdl_file;
-typedef struct mdl_texture mdl_texture;
-typedef struct mdl_header mdl_header;
-
-typedef struct glmesh glmesh;
-struct glmesh
-{
- u32 vao, vbo, ebo;
- u32 indice_count;
- u32 loaded;
-};
-
struct mdl_transform
{
v3f co, s;
v4f q;
};
-static void transform_identity( mdl_transform *transform )
+VG_TIER_0 static inline void transform_identity( mdl_transform *transform )
{
v3_zero( transform->co );
q_identity( transform->q );
v3_fill( transform->s, 1.0f );
}
-static void mdl_transform_vector( mdl_transform *transform, v3f vec, v3f dest )
+VG_TIER_0 static inline void mdl_transform_vector( mdl_transform *transform, v3f vec, v3f dest )
{
v3_mul( transform->s, vec, dest );
q_mulv( transform->q, dest, dest );
}
-static void mdl_transform_point( mdl_transform *transform, v3f co, v3f dest )
+VG_TIER_0 static inline void mdl_transform_point( mdl_transform *transform, v3f co, v3f dest )
{
mdl_transform_vector( transform, co, dest );
v3_add( transform->co, dest, dest );
}
-static void mdl_transform_mul( mdl_transform *a, mdl_transform *b,
- mdl_transform *d )
+VG_TIER_0 static inline void mdl_transform_mul( mdl_transform *a, mdl_transform *b, mdl_transform *d )
{
mdl_transform_point( a, b->co, d->co );
q_mul( a->q, b->q, d->q );
v3_mul( a->s, b->s, d->s );
}
-struct mdl_file
-{
- u32 pstr_path,
- pack_offset,
- pack_size;
-};
-
-#if (MDL_VERSION_MIN <= 105)
-struct mdl_material_v105
+#if (VG_MODEL_VERSION_MIN <= 105)
+struct mdl_material_v101
{
u32 pstr_name,
shader,
/* -> vg_msg containing KV properties */
}
kvs;
- void *compiled; /* -> shader specific structure for render */
+ u32 kv_root;
}
props;
};
pstr_name; // v107+
};
-// struct mdl_animation
-// {
-// u32 pstr_name,
-// length;
-// float rate;
-// u32 offset;
-// };
-
struct mdl_submesh
{
u32 indice_start,
armature_id;
};
-struct mdl_texture
+struct mdl_file
+{
+ u32 pstr_path,
+ pack_offset,
+ pack_size;
+};
+
+union mdl_texture
{
mdl_file file;
- u32 glname;
+ vg_tex tex;
};
-struct mdl_context
+struct vg_model
{
- array_file_context af;
u32 version;
+ u32 flags;
+
+ /* VG_MODEL_CPU_METADATA ---------------------- */
+ const void *packed_strings;
+ union shader_props *shader_props;
mdl_mesh *meshes;
u32 mesh_count;
mdl_bone *bones;
u32 bone_count;
+ /* VG_MODEL_CPU_MESHES ---------------------- */
mdl_vert *verts;
u32 vert_count;
-
u32 *indices;
u32 indice_count;
u32 pack_base_offset;
- /* runtime */
- glmesh mesh;
+ /* VG_MODEL_GPU_MESHES ----------------------- */
+#if defined( VG_ENGINE )
+ GLuint vao, vbo, ebo;
+#endif
};
-void mesh_bind( glmesh *mesh );
-void mesh_drawn( u32 start, u32 count );
-void mesh_draw( glmesh *mesh );
-void mesh_free( glmesh *mesh );
-
-/* file context management */
-void mdl_open( mdl_context *mdl, const char *path, vg_stack_allocator *stack );
-void mdl_close( mdl_context *mdl );
-
-/* pack access */
-void mdl_fread_pack_file( mdl_context *mdl, mdl_file *info, void *dst );
-
-/* standard array groups */
-void mdl_load_metadata_block( mdl_context *mdl, vg_stack_allocator *stack );
-void mdl_load_mesh_block( mdl_context *mdl, vg_stack_allocator *stack );
-void mdl_load_materials( mdl_context *mdl, vg_stack_allocator *stack );
-
-/* load mesh */
-void mdl_async_load_glmesh( mdl_context *mdl, glmesh *mesh, u32 *fixup_table );
-
-/* load textures and mesh */
-void mdl_async_full_load_std( mdl_context *mdl, u32 *fixup_table );
-void mdl_sync_std_unload( mdl_context *mdl );
-
-/* rendering */
-void mdl_draw_submesh( mdl_submesh *sm );
-i32 mdl_get_mesh_index( mdl_context *mdl, const char *name );
-i32 mdl_get_submesh_index( mdl_context *mdl, const char *mesh_name );
-
-void mdl_transform_m4x3( mdl_transform *transform, m4x3f mtx );
-
-/* model compiler
- * --------------------------------- */
-
-typedef struct mdl_compiler mdl_compiler;
-struct mdl_compiler
-{
- af_compiler af;
- af_compiler_index *meshes,
- *submeshes,
- *vertices,
- *indices,
- *bones,
- *materials,
- *shader_data,
- *armatures,
- *textures,
- *pack_data;
-
- vg_stack_allocator stack;
-};
+#endif
-#include "skaterift.h"
-#include "vg/vg_steam2.h"
-#include "player.h"
-#include "network.h"
-#include "network_msg.h"
-#include "network_common.h"
-#include "player_remote.h"
-#include "world.h"
-#include "world_sfd.h"
-#include "world_routes.h"
-#include "vg/vg_ui/imgui.h"
-#include "gui.h"
-#include "ent_region.h"
-#include "vg/vg_loader.h"
-#include "network_requests.h"
-
-#ifdef _WIN32
- #include <winsock2.h>
- #include <ws2tcpip.h>
-#else
- #include <sys/socket.h>
- #include <sys/types.h>
- #include <netdb.h>
-#endif
-
struct network_client network_client =
{
.auth_mode = eServerModeAuthentication,
void network_status_string( vg_str *str, u32 *colour )
{
- if( g_client.demo_mode )
+ if( _is_running_demo() )
{
vg_strcat( str, "Unavailible in demo" );
*colour = 0xff0000a0;
vg_strcat( str, "No Connection" );
else if( state == k_ESteamNetworkingConnectionState_Connecting )
{
- vg_strcatf( str, "Connecting... %s", network_client.host_adress );
+ if( network_client.resolve_state == k_resolve_state_resolving )
+ vg_strcatf( str, "Connecting... <resolving>" );
+ else
+ vg_strcatf( str, "Connecting... %s", network_client.adress );
if( network_client.retries )
{
vg_strcat( str, "\n(" );
- vg_strcati32( str, network_client.retries );
+ vg_strcati64( str, network_client.retries, 10 );
vg_strcat( str, " retries)" );
}
}
else if( state == k_ESteamNetworkingConnectionState_Connected )
{
- vg_strcatf( str, "Connected to:\n%s", network_client.host_adress );
+ if( network_client.resolve_state == k_resolve_state_resolving ) // Should this ever happen? No I dont think so
+ vg_strcatf( str, "Connected to: <resolving>" );
+ else
+ vg_strcatf( str, "Connected to: %s", network_client.adress );
*colour = 0xff00a020;
}
else if( state == k_ESteamNetworkingConnectionState_ClosedByPeer )
ui_fill( ctx, r, bg );
ui_text( ctx, r, buf, 1, k_ui_align_center, 0 );
ui_flush( ctx, k_ui_shader_colour, NULL );
-
- skaterift.rt_textures[ k_skaterift_rt_server_status ] = g_render.fb_network_status->attachments[0].id;
+ skaterift.rt_textures[ k_skaterift_rt_server_status ] = &g_render.fb_network_status->attachments[0].tex;
}
void cb_skaterift_connection_changed( SteamNetConnectionStatusChangedCallback_t *info )
if( !network_connected() )
return;
- vg_info( "User: " PRINTF_U64 ", change: %u\n", info->m_ulSteamID, info->m_nChangeFlags );
-
if( info->m_ulSteamID == SteamAPI_ISteamUser_GetSteamID( _steam_api.pSteamUser ) )
if( info->m_nChangeFlags & k_EPersonaChangeName )
network_send_username();
}
}
-void network_set_host( const char *host_str, const char *port_str )
+void network_set_host( const c8 *host_str, const c8 *port_str )
{
- vg_strncpy( host_str, network_client.host_adress, sizeof(network_client.host_adress), k_strncpy_overflow_fatal );
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ VG_ASSERT( network_client.resolve_state != k_resolve_state_resolving );
+ vg_strncpy( host_str, network_client.adress, sizeof(network_client.adress), k_strncpy_overflow_fatal );
memset( &network_client.ip, 0, sizeof(network_client.ip) );
network_client.resolve_state = k_resolve_state_no;
if( port_str )
{
- vg_strncpy( port_str, network_client.host_port, sizeof(network_client.host_port), k_strncpy_overflow_fatal );
+ vg_strncpy( port_str, network_client.port, sizeof(network_client.port), k_strncpy_overflow_fatal );
}
else
{
vg_str str;
- vg_strnull( &str, network_client.host_port, sizeof(network_client.host_port) );
- vg_strcati32( &str, NETWORK_PORT );
+ vg_strnull( &str, network_client.port, sizeof(network_client.port) );
+ vg_strcati64( &str, NETWORK_PORT, 10 );
}
- network_client.ip.m_port = atoi( network_client.host_port );
+ network_client.ip.m_port = atoi( network_client.port );
}
static void network_connect(void)
}
}
-struct resolve_info
+static void _network_resolve_numeric(void)
{
- enum resolve_opt
- {
- k_resolve_opt_resolve,
- k_resolve_opt_parse_numeric,
- k_resolve_opt_ipv6,
- k_resolve_opt_fail
- }
- opt;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ SteamAPI_SteamNetworkingIPAddr_ParseString( &network_client.ip, network_client.adress );
+ network_client.ip.m_port = atoi( network_client.port );
+ network_client.resolve_state = k_resolve_state_resolved;
+}
- union
- {
- struct
- {
- char port[8], adress[256];
- }
- host;
- struct addrinfo *ipv6;
- }
- alias;
+struct network_resolved_info
+{
+ bool ok;
+ bool needs_numeric_conversion;
};
-static void _network_resolve_host( vg_async_task *co_task )
+static void _network_resolve_complete( struct network_resolved_info *in_args, vg_async_info *async )
{
- if( co_task )
+ if( in_args->ok )
{
- struct resolve_info *co_info = (void *)co_task->data;
- if( co_info->opt == k_resolve_opt_resolve )
- {
- THREAD_1;
+ if( in_args->needs_numeric_conversion )
+ _network_resolve_numeric();
+ network_client.resolve_state = k_resolve_state_resolved;
+ }
+ else
+ network_client.resolve_state = k_resolve_state_no;
+}
- vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, sizeof(struct resolve_info), 1 );
- struct resolve_info *info = (void *)task->data;
- vg_info( "Resolving host.. %s (:%s)\n", co_info->alias.host.adress, co_info->alias.host.port );
+static void _network_resolve_host_async( void *_, vg_async_info *async )
+{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
- /* Obtain address(es) matching host/port. */
+ /* Obtain address(es) matching host/port. */
+ struct addrinfo hints;
+ memset( &hints, 0, sizeof(hints) );
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG;
+ hints.ai_protocol = 0;
- struct addrinfo hints;
- memset( &hints, 0, sizeof(hints) );
- hints.ai_family = AF_INET6;
- hints.ai_socktype = SOCK_DGRAM;
- hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG;
- hints.ai_protocol = 0;
+ bool ok = 0, needs_numeric_conversion = 0;
- int s = getaddrinfo( co_info->alias.host.adress, co_info->alias.host.port, &hints, &info->alias.ipv6 );
- if( s != 0 )
- {
+ struct addrinfo *ipv6;
+ int s = getaddrinfo( network_client.adress, network_client.port, &hints, &ipv6 );
+ if( s != 0 )
+ {
#ifndef _WIN32
- vg_error( "getaddrinfo: %s\n", gai_strerror(s) );
+ vg_error( "getaddrinfo: %s\n", gai_strerror(s) );
#endif
- if( !strcmp( co_info->alias.host.adress, "skaterift.com" ) )
- {
- vg_warn( "getaddrinfo failed for skaterift.com;\n "
- "falling back to a hardcoded IPv4. This might be wrong.\n" );
-
- strcpy( info->alias.host.adress, "46.101.34.155" );
- strcpy( info->alias.host.port, "27408" );
- info->opt = k_resolve_opt_parse_numeric;
- vg_async_task_dispatch( task, _network_resolve_host );
- return;
- }
- else
- {
- info->opt = k_resolve_opt_fail;
- vg_async_task_dispatch( task, _network_resolve_host );
- return;
- }
- }
- else
- {
- info->opt = k_resolve_opt_ipv6;
- vg_async_task_dispatch( task, _network_resolve_host );
- return;
- }
- }
- else
+ if( !strcmp( network_client.adress, "skaterift.com" ) )
{
- THREAD_0;
+ vg_warn( "getaddrinfo failed for skaterift.com;\n "
+ "falling back to a hardcoded IPv4. This might be wrong.\n" );
- if( co_info->opt == k_resolve_opt_fail )
- {
- network_client.resolve_state = k_resolve_state_no;
- return;
- }
- else if( co_info->opt == k_resolve_opt_ipv6 )
- {
- struct sockaddr_in6 *inaddr = (struct sockaddr_in6 *)co_info->alias.ipv6->ai_addr;
- memcpy( network_client.ip.m_ipv6, &inaddr->sin6_addr, 16 );
- freeaddrinfo( co_info->alias.ipv6 );
- network_client.resolve_state = k_resolve_state_resolved;
- return;
- }
- else if( co_info->opt == k_resolve_opt_parse_numeric )
- {
- strcpy( network_client.host_adress, co_info->alias.host.adress );
- strcpy( network_client.host_port, co_info->alias.host.port );
- goto parse_numeric;
- }
+ strcpy( network_client.adress, "46.101.34.155" );
+ strcpy( network_client.port, "27408" );
+ ok = 1;
+ needs_numeric_conversion = 1;
}
}
else
{
- THREAD_0;
- if( (network_client.host_adress[0] >= '0') && (network_client.host_adress[0] <= '9') )
- goto parse_numeric;
- else
- {
- network_client.resolve_state = k_resolve_state_resolving;
- vg_async_task *task = vg_allocate_async_task( &vg.loader_tasks, sizeof(struct resolve_info), 1 );
- struct resolve_info *info = (void *)task->data;
- info->opt = k_resolve_opt_resolve;
- strcpy( info->alias.host.port, network_client.host_port );
- strcpy( info->alias.host.adress, network_client.host_adress );
- vg_async_task_dispatch( task, _network_resolve_host );
- return;
- }
+ struct sockaddr_in6 *inaddr = (struct sockaddr_in6 *)ipv6->ai_addr;
+ memcpy( network_client.ip.m_ipv6, &inaddr->sin6_addr, 16 );
+ freeaddrinfo( ipv6 );
+ ok = 1;
}
- VG_ASSERT(0);
-parse_numeric:
+ struct network_resolved_info *out_args = _vg_async_alloc( VG_THREAD_MAIN_ID, sizeof(struct network_resolved_info) );
+ out_args->ok = ok;
+ out_args->needs_numeric_conversion = needs_numeric_conversion;
+ _vg_async_send( out_args, (vg_async_fn)_network_resolve_complete );
+}
- THREAD_0;
- SteamAPI_SteamNetworkingIPAddr_ParseString( &network_client.ip, network_client.host_adress );
- network_client.ip.m_port = atoi( network_client.host_port );
- network_client.resolve_state = k_resolve_state_resolved;
+static void _network_resolve_host(void)
+{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ VG_ASSERT( network_client.resolve_state == k_resolve_state_no );
+
+ if( (network_client.adress[0] >= '0') && (network_client.adress[0] <= '9') )
+ _network_resolve_numeric();
+ else
+ {
+ network_client.resolve_state = k_resolve_state_resolving;
+ _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_network_resolve_host_async );
+ }
}
-void network_update(void)
+VG_API void _network_update(void)
{
if( _steam_api.disabled )
return;
- if( g_client.demo_mode )
+ if( _is_running_demo() )
return;
ESteamNetworkingConnectionState state = network_client.state;
-
if( network_client.user_intent == k_server_intent_offline )
{
if( state != k_ESteamNetworkingConnectionState_None )
return;
if( network_client.resolve_state == k_resolve_state_no )
- _network_resolve_host(NULL);
+ _network_resolve_host();
else if( network_client.resolve_state == k_resolve_state_resolved )
network_connect();
return 0;
}
-void network_register(void)
+VG_API void _network_register(void)
{
vg_console_reg_var( "auto_connect", &network_client.auto_connect, k_var_dtype_i32, VG_VAR_PERSISTENT );
vg_console_reg_cmd( "rcon", cmd_network_send_rcon, NULL );
}
-void network_init(void)
+static void _network_end(void)
{
- _net_requests_init();
-}
-
-void network_end(void)
-{
- /* TODO: Send buffered highscores that were not already */
if( (network_client.state == k_ESteamNetworkingConnectionState_Connected) ||
(network_client.state == k_ESteamNetworkingConnectionState_Connecting) )
{
}
}
-#include "network_requests.c"
+VG_API void _network_init(void)
+{
+ _vg_add_exit_function( _network_end );
+ _net_requests_init();
+ render_server_status_gui();
+}
-/*
- * Copyright (C) 2021-2025 Mt.ZERO Software, Harry Godden - All Rights Reserved
- * All trademarks are property of their respective owners
- */
-
-#pragma once
-#include "vg/vg_platform.h"
-#include "vg/vg_steam2.h"
-#include "vg/vg_mem_pool.h"
-#include "vg/vg_msg.h"
-#include "network_common.h"
-#include "network_msg.h"
-#include "addon_types.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/network.c"
+#else
/*
* Interface
void on_persona_state_change( CallbackMsg_t *msg );
void request_auth_ticket(void);
-/* Call it at start; Connects us to the gameserver */
-void network_register(void);
-void network_init(void);
-
-/* Run this from main loop */
-void network_update(void);
-
-/* Call it at shutdown */
-void network_end(void);
+VG_API void _network_register(void);
+VG_API void _network_init(void);
+VG_API void _network_update(void);
/*
* Can buffer up a bunch of these by calling many times, they will be
i32 auto_connect;
SteamNetworkingIPAddr ip;
- char host_port[8], host_adress[256];
+ c8 port[8], adress[256];
enum resolve_state
{
void cb_skaterift_connection_changed( SteamNetConnectionStatusChangedCallback_t *info );
void cb_skaterift_persona_changed( PersonaStateChange_t *info );
+
+#endif
-#pragma once
-#include "vg/vg_platform.h"
-#include "vg/vg_string.h"
+#if defined( SR_IMPLEMENTATION )
+//# include "src/network_common.c"
+#else
#define NETWORK_USERNAME_MAX 32
#define NETWORK_MAX_PLAYERS 20
#define NETWORK_PORT 27408
#define NETWORK_PORT_STR(STR, X) STR #X
-#include "addon_types.h"
-
static u32 network_msgstring( const char *src, u32 m_cbSize, u32 base_size, char *buf, u32 buf_size )
{
u32 string_len = VG_MIN( m_cbSize - base_size, buf_size );
return ((N-a)*((N-a)-1))/2 - b + a;
}
+
+#endif
-#ifndef NETWORK_COMPRESSION_H
-#define NETWORK_COMPRESSION_H
-
-#include "vg/vg_platform.h"
-#include "vg/vg_m.h"
+#if defined( SR_IMPLEMENTATION )
+//# include "src/network_compression.c"
+#else
typedef struct bitpack_ctx bitpack_ctx;
struct bitpack_ctx {
}
}
-#endif /* NETWORK_COMPRESSION_H */
+#endif
-/*
- * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#ifndef NETWORK_MSG_H
-#define NETWORK_MSG_H
-
-#include "world_info.h"
-#include "vg/vg_platform.h"
-;
+#if defined( SR_IMPLEMENTATION )
+//# include "src/network_msg.c"
+#else
#pragma pack(push,1)
-#include "network_requests.h"
-
struct _net_requests _net_requests;
const char *request_status_string( enum request_status status )
vg_low( "req[%s%s##%hu" KWHT "] State: %s\n", colour, associated_username, request_id, request_state_str );
}
-void network_send_request( netmsg_request *packet, vg_msg *body,
+void network_send_request( const c8 *body, u32 body_length,
void (*callback)( void *data, u32 data_size, u64 userdata, enum request_status status ),
u64 userdata )
{
- u32 len = 0;
- if( body )
- {
- len = body->cur.co;
- vg_msg_print( body, len );
-
- if( body->error != k_vg_msg_error_OK )
- {
- vg_error( "Body not OK\n" );
- return;
- }
- }
+ VG_ASSERT( body_length <= 512 );
+ netmsg_request *packet = alloca( sizeof(netmsg_request) + 512 );
+ packet->inetmsg_id = k_inetmsg_request;
if( callback )
{
packet->uid = 0;
SteamAPI_ISteamNetworkingSockets_SendMessageToConnection( _steam_api.pSteamNetworkingSockets, network_client.remote,
- packet, sizeof(netmsg_request)+len,
+ packet, sizeof(netmsg_request) + body_length,
k_nSteamNetworkingSend_Reliable, NULL );
}
static void network_scoreboard_callback( void *data, u32 data_size, u64 userdata, enum request_status status )
{
+ // FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////
+#if 0
if( status == k_request_status_ok )
{
vg_msg msg;
}
else
world_routes_recv_scoreboard( &_world.main, NULL, userdata, status );
+#endif
}
/* mod_uid: world mod uid,
if( !network_connected() )
return;
+ // FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////
+#if 0
netmsg_request *packet = alloca( sizeof(netmsg_request) + 512 );
packet->inetmsg_id = k_inetmsg_request;
vg_msg_wkvstr( &data, "route", route_uid );
vg_msg_wkvnum( &data, "week", k_vg_msg_u32, 1, &week );
network_send_request( packet, &data, network_scoreboard_callback, userdata );
+#endif
+ // FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////
}
void network_publish_laptime( const char *mod_uid, const char *route_uid, f64 lap_time )
i32 time_centiseconds = lap_time * 100.0;
+ // FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////
+#if 0
netmsg_request *packet = alloca( sizeof(netmsg_request) + 512 );
packet->inetmsg_id = k_inetmsg_request;
f64 time_real = vg.time_real;
vg_msg_wkvnum( &data, "end", k_vg_msg_f64, 1, &time_real );
network_send_request( packet, &data, NULL, 0 );
+#endif
+ // FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////
}
static void _delete_request( u16 request_id )
_net_requests_reset( "Defined server Error (Our end is ok)\n" );
}
-void _net_requests_init(void)
+VG_API void _net_requests_init(void)
{
u32 alloc_size = sizeof(net_request)*NETWORK_MAX_REQUESTS;
- _net_requests.transfer_buffer = vg_stack_allocate( &vg.rtmem, VG_MB(4), 8, "Request transfer data buffer" );
+ _net_requests.transfer_buffer = vg_malloc( VG_MB(4) );
_net_requests.global_uid = time(NULL) ^ 0x35aa3203;
- vg_pool_init( &_net_requests.pool, &_net_requests.inactive, NETWORK_MAX_REQUESTS, &vg.rtmem );
+ vg_pool_init( &_net_requests.pool, &_net_requests.inactive, NETWORK_MAX_REQUESTS, NULL );
}
void _net_requests_update(void)
-#pragma once
-#include "network.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/network_requests.c"
+#else
#define TRANSFER_TIMEOUT_SECONDS 5.0f
#define NETWORK_MAX_REQUESTS 8
}
extern _net_requests;
-void network_send_request( netmsg_request *req, vg_msg *body,
+VG_API void _net_requests_init(void);
+
+const char *request_status_string( enum request_status status );
+void network_send_request( const c8 *body, u32 body_length,
void (*callback)( void *data, u32 data_size, u64 userdata, enum request_status status ),
u64 userdata );
void _net_handle_response_message( SteamNetworkingMessage_t *msg );
-void _net_requests_init(void);
void _net_requests_deleteall(void);
void _net_requests_update(void);
+
+#endif
-#include "vg/vg_lines.h"
-#include "particle.h"
-#include "shaders/particle.h"
-
struct particle_system particles_grind = {
.scale = 0.02f,
.velocity_scale = 0.001f,
.width = 0.25f
};
+VG_API void _particles_init( void )
+{
+ particle_system_init( &particles_grind, 300, VG_STACK_USE_HEAP );
+ particle_system_init( &particles_env, 200, VG_STACK_USE_HEAP );
+}
+
void particle_spawn( particle_system *sys, v3f co, v3f v, f32 lifetime, u32 colour )
{
if( sys->alive == sys->max )
void particle_system_debug( particle_system *sys )
{
- for( u32 i=0; i<sys->alive; i ++ ){
+ for( u32 i=0; i<sys->alive; i ++ )
+ {
particle *p = &sys->array[i];
v3f p1;
v3_muladds( p->co, p->v, 0.2f, p1 );
}
}
-struct particle_init_args
+VG_TIER_2 void particle_system_init( particle_system *sys, u32 max, vg_stack_allocator *stack )
{
- particle_system *sys;
- u16 indices[];
-};
-static void particle_init_task( vg_async_task *task )
-{
- struct particle_init_args *args = (void *)task->data;
- particle_system *sys = args->sys;
-
- glGenVertexArrays( 1, &sys->vao );
- glGenBuffers( 1, &sys->vbo );
- glGenBuffers( 1, &sys->ebo );
- glBindVertexArray( sys->vao );
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ u32 stride = sizeof(particle_vert);
- size_t stride = sizeof(particle_vert);
+ sys->max = max;
+ sys->array = vg_stack_allocate( stack, max*sizeof(particle), 8, "Particle array" );
+ sys->vertices = vg_stack_allocate( stack, max*stride*4, 8, "Particle vertices" );
- glBindBuffer( GL_ARRAY_BUFFER, sys->vbo );
- glBufferData( GL_ARRAY_BUFFER, sys->max*stride*4, NULL, GL_DYNAMIC_DRAW );
- glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, sys->ebo );
- glBufferData( GL_ELEMENT_ARRAY_BUFFER, sys->max*sizeof(u16)*6, args->indices, GL_STATIC_DRAW );
+ u32 temp_frame = _vg_start_temp_frame();
+ {
+ u16 *indices = vg_stack_allocate( _vg_temp_stack(), sizeof(u16) * max * 6, 8, "Temp indices" );
+ for( u32 i=0; i<max; i ++ )
+ {
+ indices[i*6+0] = i*4;
+ indices[i*6+1] = i*4+1;
+ indices[i*6+2] = i*4+2;
+ indices[i*6+3] = i*4;
+ indices[i*6+4] = i*4+2;
+ indices[i*6+5] = i*4+3;
+ }
+
+ glGenVertexArrays( 1, &sys->vao );
+ glGenBuffers( 1, &sys->vbo );
+ glGenBuffers( 1, &sys->ebo );
+ glBindVertexArray( sys->vao );
+
+ glBindBuffer( GL_ARRAY_BUFFER, sys->vbo );
+ glBufferData( GL_ARRAY_BUFFER, sys->max*stride*4, NULL, GL_DYNAMIC_DRAW );
+ glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, sys->ebo );
+ glBufferData( GL_ELEMENT_ARRAY_BUFFER, max*sizeof(u16)*6, indices, GL_STATIC_DRAW );
+ }
+ _vg_end_temp_frame( temp_frame );
/* 0: coordinates */
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0 );
glEnableVertexAttribArray( 1 );
}
-void particle_alloc( particle_system *sys, u32 max )
-{
- size_t stride = sizeof(particle_vert);
-
- sys->max = max;
- sys->array = vg_stack_allocate( &vg.rtmem, max*sizeof(particle), 8, "Particle array" );
- sys->vertices = vg_stack_allocate( &vg.rtmem, max*stride*4, 8, "Particle vertices" );
-
- vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, sizeof(particle_system *) + max*sizeof(u16)*6, 1 );
- struct particle_init_args *init = (void *)task->data;
- init->sys = sys;
-
- for( u32 i=0; i<max; i ++ )
- {
- init->indices[i*6+0] = i*4;
- init->indices[i*6+1] = i*4+1;
- init->indices[i*6+2] = i*4+2;
- init->indices[i*6+3] = i*4;
- init->indices[i*6+4] = i*4+2;
- init->indices[i*6+5] = i*4+3;
- }
- vg_async_task_dispatch( task, particle_init_task );
-}
-
void particle_system_prerender( particle_system *sys )
{
for( u32 i=0; i<sys->alive; i ++ ){
-#pragma once
-#include "skaterift.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/particle.c"
+#else
typedef struct particle_system particle_system;
typedef struct particle particle;
}
extern particles_grind, particles_env;
-void particle_alloc( particle_system *sys, u32 max );
+VG_API void _particles_init( void );
+VG_TIER_2 void particle_system_init( particle_system *sys, u32 max, vg_stack_allocator *stack );
+
void particle_system_update( particle_system *sys, f32 dt );
void particle_system_debug( particle_system *sys );
void particle_system_prerender( particle_system *sys );
void particle_system_render( particle_system *sys, vg_camera *cam );
-void particle_spawn( particle_system *sys,
- v3f co, v3f v, f32 lifetime, u32 colour );
-void particle_spawn_cone( particle_system *sys,
- v3f co, v3f dir, f32 angle, f32 speed,
- f32 lifetime, u32 colour );
+void particle_spawn( particle_system *sys, v3f co, v3f v, f32 lifetime, u32 colour );
+void particle_spawn_cone( particle_system *sys, v3f co, v3f dir, f32 angle, f32 speed, f32 lifetime, u32 colour );
+#endif
+++ /dev/null
-/*
- * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#ifndef PHYSICS_TEST_H
-#define PHYSICS_TEST_H
-
-#include "rigidbody.h"
-#include "player.h"
-
-rigidbody ground = { .type = k_rb_shape_box,
- .bbx = {{-100.0f,-1.0f,-100.0f},{100.0f,0.0f,100.0f}},
- .co = {0.0f, 0.0f, 0.0f},
- .q = {0.0f,0.0f,0.0f,1.0f},
- .is_world = 1 };
-
-rigidbody blocky =
- {
- .type = k_rb_shape_box,
- .bbx = {{-2.0f,-1.0f,-3.0f},{2.0f,1.0f,2.0f}},
- .co = {30.0f,2.0f,30.0f},
- .q = {0.0f,0.0f,0.0f,1.0f},
- .is_world = 1
- };
-
-rigidbody marko =
-{
- .type = k_rb_shape_box,
- .bbx = {{-0.5f,-0.5f,-0.5f},{0.5f,0.5f,0.5f}},
- .co = {-36.0f,8.0f,-36.0f},
- .q = {0.0f,0.0f,0.0f,1.0f},
- .is_world = 0
-};
-
-scene epic_scene;
-
-rigidbody epic_scene_rb =
-{
- .type = k_rb_shape_scene,
- .co = {0.0f,0.0f,0.0f},
- .q = {0.0f,0.0f,0.0f,1.0f},
- .is_world = 1,
- .inf.scene = { .pscene = &epic_scene }
-};
-
-rigidbody funnel[4] = {
- {
- .type = k_rb_shape_box,
- .bbx = {{-20.0f,-1.0f,-20.0f},{20.0f,1.0f,20.0f}},
- .co = {-10.0f,5.0f,0.0f},
- .is_world = 1
- },
- {
- .type = k_rb_shape_box,
- .bbx = {{-20.0f,-1.0f,-20.0f},{20.0f,1.0f,20.0f}},
- .co = { 10.0f,5.0f,0.0f},
- .is_world = 1
- },
- {
- .type = k_rb_shape_box,
- .bbx = {{-20.0f,-1.0f,-20.0f},{20.0f,1.0f,20.0f}},
- .co = { 0.0f,5.0f,10.0f},
- .is_world = 1
- },
- {
- .type = k_rb_shape_box,
- .bbx = {{-20.0f,-1.0f,-20.0f},{20.0f,1.0f,20.0f}},
- .co = {0.0f,5.0f,-10.0f},
- .is_world = 1
- }
-};
-
-rigidbody jeff1 = { .type = k_rb_shape_capsule,
- .inf.capsule = { .radius = 0.75f, .height = 3.0f },
- .co = {30.0f, 4.0f, 30.0f },
- .q = {1.0f,0.0f,0.0f,0.0f}
-};
-
-rigidbody ball = { .type = k_rb_shape_sphere,
- .inf.sphere = { .radius = 2.0f },
- .co = {0.0f,20.0f,2.0f},
- .q = {0.0f,0.0f,0.0f,1.0f}},
-
- ball1= { .type = k_rb_shape_sphere,
- .inf.sphere = { .radius = 2.0f },
- .co = {0.1f,25.0f,0.2f},
- .q = {0.0f,0.0f,0.0f,1.0f}};
-
-rigidbody jeffs[16];
-
-static void reorg_jeffs(void)
-{
- for( int i=0; i<vg_list_size(jeffs); i++ )
- {
- v3_copy( (v3f){ (vg_randf()-0.5f) * 10.0f,
- (vg_randf()-0.5f) * 10.0f + 17.0f,
- (vg_randf()-0.5f) * 10.0f }, jeffs[i].co );
- v4_copy( (v4f){ vg_randf(), vg_randf(), vg_randf(), vg_randf() },
- jeffs[i].q );
- q_normalize( jeffs[i].q );
-
- jeffs[i].type = k_rb_shape_capsule;
- jeffs[i].inf.capsule.radius = 0.75f;
- jeffs[i].inf.capsule.height = 3.0f;
-
- rb_init( &jeffs[i] );
- }
-}
-
-static void physics_test_start(void)
-{
- q_axis_angle( funnel[0].q, (v3f){1.0f,0.0f,0.0f}, 0.6f );
- q_axis_angle( funnel[1].q, (v3f){1.0f,0.0f,0.0f}, -0.6f );
- q_axis_angle( funnel[2].q, (v3f){0.0f,0.0f,1.0f}, 0.6f );
- q_axis_angle( funnel[3].q, (v3f){0.0f,0.0f,1.0f}, -0.6f );
-
- for( int i=0; i<4; i++ )
- rb_init( &funnel[i] );
-
- reorg_jeffs();
-
- rb_init( &ground );
- rb_init( &ball );
- rb_init( &ball1 );
- rb_init( &jeff1 );
- rb_init( &blocky );
-
- scene_init( &epic_scene );
-
- mdl_header *mdl = mdl_load( "models/epic_scene.mdl" );
-
- m4x3f transform;
- m4x3_identity( transform );
-
- for( int i=0; i<mdl->node_count; i++ )
- {
- mdl_node *pnode = mdl_node_from_id( mdl, i );
-
- for( int j=0; j<pnode->submesh_count; j++ )
- {
- mdl_submesh *sm = mdl_node_submesh( mdl, pnode, j );
- scene_add_submesh( &epic_scene, mdl, sm, transform );
- }
- }
-
- vg_free( mdl );
- scene_bh_create( &epic_scene );
-
- rb_init( &epic_scene_rb );
- rb_init( &marko );
-}
-
-static void physics_test_update(void)
-{
- player_freecam();
- player_camera_update();
-
- for( int i=0; i<4; i++ )
- rb_debug( &funnel[i], 0xff0060e0 );
- rb_debug( &ground, 0xff00ff00 );
- rb_debug( &ball, 0xffe00040 );
- rb_debug( &ball1, 0xff00e050 );
-
- rb_debug( &blocky, 0xffcccccc );
- rb_debug( &jeff1, 0xff00ffff );
-
- rb_debug( &epic_scene_rb, 0xffcccccc );
- rb_debug( &marko, 0xffffcc00 );
-
- {
-
- rb_solver_reset();
-
- for( int i=0; i<4; i++ )
- {
- rigidbody *fn = &funnel[i];
- rb_collide( &ball, fn );
- rb_collide( &ball1, fn );
- rb_collide( &jeff1, fn );
-
- for( int i=0; i<vg_list_size(jeffs); i++ )
- rb_collide( jeffs+i, fn );
- }
-
- for( int i=0; i<vg_list_size(jeffs)-1; i++ )
- {
- for( int j=i+1; j<vg_list_size(jeffs); j++ )
- {
- rb_collide( jeffs+i, jeffs+j );
- }
- }
-
- for( int i=0; i<vg_list_size(jeffs); i++ )
- {
- rb_collide( jeffs+i, &ground );
- rb_collide( jeffs+i, &ball );
- rb_collide( jeffs+i, &ball1 );
- rb_collide( jeffs+i, &jeff1 );
- }
-
- rb_collide( &jeff1, &ground );
- rb_collide( &jeff1, &blocky );
- rb_collide( &jeff1, &ball );
- rb_collide( &jeff1, &ball1 );
-
- rb_collide( &ball, &ground );
- rb_collide( &ball1, &ground );
- rb_collide( &ball1, &ball );
- rb_collide( &marko, &epic_scene_rb );
-
- rb_presolve_contacts( rb_contact_buffer, rb_contact_count );
- for( int i=0; i<8; i++ )
- rb_solve_contacts( rb_contact_buffer, rb_contact_count );
-
-
- /* ITERATE */
- {
- for( int i=0; i<vg_list_size(jeffs); i++ )
- {
- rb_debug( &jeffs[i], (u32[]){ 0xff0000ff, 0xff00ff00, 0xff00ffff,
- 0xffff0000, 0xffff00ff, 0xffffff00,
- }[i%6] );
- rb_iter( jeffs+i );
- }
-
- rb_iter( &ball );
- rb_iter( &ball1 );
- rb_iter( &jeff1 );
- rb_iter( &marko );
- }
-
- /* POSITION OVERRIDE */
- {
- if(glfwGetKey( vg.window, GLFW_KEY_L ))
- {
- m4x3_mulv( player.camera, (v3f){0.0f,0.0f,-5.0f}, marko.co );
- v3_zero( marko.v );
- v3_zero( marko.w );
- }
- if(glfwGetKey( vg.window, GLFW_KEY_K ))
- {
- m4x3_mulv( player.camera, (v3f){0.0f,0.0f,-5.0f}, ball.co );
- v3_zero( ball.v );
- v3_zero( ball.w );
- }
- if(glfwGetKey( vg.window, GLFW_KEY_J ))
- {
- m4x3_mulv( player.camera, (v3f){0.0f,0.0f,-5.0f}, ball1.co );
- v3_zero( ball1.v );
- v3_zero( ball1.w );
- }
-
- if(glfwGetKey( vg.window, GLFW_KEY_H ))
- {
- reorg_jeffs();
- }
- }
-
- /* UPDATE TRANSFORMS */
- for( int i=0; i<vg_list_size(jeffs); i++ )
- {
- rb_update_transform(jeffs+i);
- }
-
- rb_update_transform( &ball );
- rb_update_transform( &ball1 );
- rb_update_transform( &jeff1 );
- rb_update_transform( &marko );
-
- }
-}
-
-static void physics_test_render(void)
-{
- m4x4f world_4x4;
- m4x3_expand( player.camera_inverse, world_4x4 );
-
- gpipeline.fov = 60.0f;
- m4x4_projection( vg_pv, gpipeline.fov,
- (float)vg_window_x / (float)vg_window_y,
- 0.1f, 2100.0f );
-
- m4x4_mul( vg_pv, world_4x4, vg_pv );
- glEnable( GL_DEPTH_TEST );
-
- glDisable( GL_DEPTH_TEST );
- vg_lines_drawall( (float *)vg_pv );
-}
-
-#endif /* PHYSICS_TEST_H */
-#include "player.h"
-#include "addon.h"
-#include "player_model.h"
-#include "input.h"
-#include "world.h"
-#include "audio.h"
-#include "network.h"
-#include "network_common.h"
-#include "world_routes.h"
-#include "gui.h"
-
-#include "shaders/model_entity.h"
-#include "shaders/model_character_view.h"
-#include "shaders/model_board_view.h"
-
-#include "player_walk.h"
-#include "player_dead.h"
-#include "player_skate.h"
-#include "player_basic_info.h"
-#include "player_glide.h"
-#include <string.h>
-
i32 k_invert_y = 0;
struct localplayer localplayer =
{
return 1;
}
-void player_register(void)
+VG_API void _player_register(void)
{
vg_console_reg_var( "player_battery", &localplayer.has_battery, k_var_dtype_i32, 0 );
vg_console_reg_cmd( "respawn", localplayer_cmd_respawn, NULL );
}
}
-void player_init(void)
-{
- mdl_context *mdl = &localplayer.battery;
- mdl_open( mdl, "models/battery.mdl", &vg.rtmem );
- mdl_load_metadata_block( mdl, &vg.rtmem );
- mdl_async_full_load_std( mdl, NULL );
- mdl_close( mdl );
-}
-
void player__debugtext( ui_context *ctx, int size, const char *fmt, ... )
{
char buffer[ 1024 ];
localplayer.playermodel.cache_slot = addon_cache_create_viewer( k_addon_type_player, addon_id );
}
-void player__bind(void)
+VG_API void _player_init(void)
{
for( u32 i=0; i<k_player_subsystem_max; i++ )
{
struct player_subsystem_interface *sys = player_subsystems[i];
- if( sys && sys->bind )
- sys->bind();
+ if( sys && sys->init )
+ sys->init();
}
}
glider_physics( (v2f){0,0} );
- if( localplayer.rb.co[1] < _world.main.scene_geo.bbx[0][1] - 40.0f )
+ if( localplayer.rb.co[1] < _world.main.scene_geometry.bbx[0][1] - 40.0f )
{
ent_spawn *rp = world_find_closest_spawn( &_world.main, localplayer.rb.co );
if( rp )
_world.copy_of_nonlocal_sender.key = 0;
_world.copy_of_nonlocal_sender.submesh_start = 0;
_world.copy_of_nonlocal_sender.submesh_count = 0;
- vg_strncpy( af_str( &world->meta.af, gate->key ), _world.nonlocal_destination_key, 32, k_strncpy_overflow_fatal );
+ vg_strncpy( af_str( world->meta.packed_strings, gate->key ), _world.nonlocal_destination_key,
+ 32, k_strncpy_overflow_fatal );
player__clean_refs();
skaterift_load_world_start( gate->remote_addon_id, 0 );
return;
/* we want the regular transform here no the inversion */
m4x3_expand( transport, transport_4 );
- m4x4_mul( world_gates.cam.mtx.pv, transport_4, world_gates.cam.mtx.pv );
- m4x4_mul( world_gates.cam.mtx.v, transport_4, world_gates.cam.mtx.v );
+ m4x4_mul( _world_gates.cam.mtx.pv, transport_4, _world_gates.cam.mtx.pv );
+ m4x4_mul( _world_gates.cam.mtx.v, transport_4, _world_gates.cam.mtx.v );
}
void player__im_gui( ui_context *ctx )
if( !k_player_debug_info ) return;
ui_rect box = {
- vg.window_x - 300,
+ _vg_window.w - 300,
0,
300,
- vg.window_y
+ _vg_window.h
};
ui_fill( ctx, box, (ui_colour(ctx, k_ui_bg)&0x00ffffff)|0x50000000 );
player__debugtext( ctx, 1, "time_rate: %.4f", skaterift.time_rate );
player__debugtext( ctx, 2, "player" );
- player__debugtext( ctx, 1, "angles: " PRINTF_v3f( localplayer.cam.angles ) );
+ player__debugtext( ctx, 1, "angles: %.2f %.2f %.2f",
+ localplayer.cam.angles[0],localplayer.cam.angles[1],localplayer.cam.angles[2] );
if( player_subsystems[ localplayer.subsystem ]->im_gui )
player_subsystems[ localplayer.subsystem ]->im_gui( ctx );
void player__clean_refs(void)
{
- gui_helper_reset( k_gui_helper_mode_clear );
+ _gui_helper_reset( k_gui_helper_mode_clear );
_world.challenge_target = NULL;
_world.challenge_timer = 0.0f;
-#pragma once
-#include "vg/vg_platform.h"
-
-struct player_cam_controller {
- enum camera_mode{
- k_cam_firstperson = 1,
- k_cam_thirdperson = 0
- }
- camera_mode;
- f32 camera_type_blend;
-
- v3f fpv_offset, /* expressed relative to rigidbody */
- tpv_offset,
- tpv_offset_extra,
- fpv_viewpoint, /* expressed relative to neck bone inverse final*/
- fpv_offset_smooth,
- fpv_viewpoint_smooth,
- tpv_offset_smooth,
- tpv_lpf,
- cam_velocity_smooth;
-};
-
-#include "player_common.h"
-#include "network_compression.h"
-#include "player_effects.h"
-#include "player_api.h"
-#include "player_ragdoll.h"
-#include "player_model.h"
-#include "player_render.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/player.c"
+#else
struct player_subsystem_interface
{
void(*system_register)(void);
- void(*bind)(void);
+ void(*init)(void);
+ void(*load_resources)(void);
void(*pre_update)(void);
void(*update)(void);
void(*post_update)(void);
/*
* Rendering
*/
- mdl_context skeleton_meta;
- mdl_context battery;
- ms_context animations;
- struct skeleton skeleton;
+ vg_model skeleton_meta;
+ vg_model battery;
+ metascene animations;
+ ms_skeleton skeleton;
i32 has_battery;
u8 id_hip,
* ---------------------------------------------------------
*/
-void player_register(void);
-void player_init(void);
+VG_API void _player_init(void);
+VG_API void _player_register(void);
+
void player__debugtext( ui_context *ctx, int size, const char *fmt, ... );
-void player__use_mesh( glmesh *mesh );
void player__use_model( u16 reg_id );
void player__bind(void);
void player__kill(void);
void player__begin_holdout( v3f offset );
-void player_get_anim( skeleton_anim *out_anim, const char *name );
+void player_get_anim( ms_skeletal_animation *out_anim, const char *name );
int localplayer_cmd_respawn( int argc, const char *argv[] );
void player_apply_transport_to_cam( m4x3f transport );
void player__clear_sfx_buffer(void);
-void player__networked_sfx( u8 system, u8 priority, u8 id,
- v3f pos, f32 volume );
+void player__networked_sfx( u8 system, u8 priority, u8 id, v3f pos, f32 volume );
void net_sfx_exchange( bitpack_ctx *ctx, struct net_sfx *sfx );
void net_sfx_play( struct net_sfx *sfx );
+
+#endif
-#pragma once
-#include "model.h"
-#include "metascene.h"
+#if defined( SR_IMPLEMENTATION )
+//# include "src/player_api.c"
+#else
typedef struct player_instance player_instance;
typedef struct player_pose player_pose;
-struct player_pose{
- enum player_pose_type {
+struct player_cam_controller
+{
+ enum camera_mode
+ {
+ k_cam_firstperson = 1,
+ k_cam_thirdperson = 0
+ }
+ camera_mode;
+ f32 camera_type_blend;
+
+ v3f fpv_offset, /* expressed relative to rigidbody */
+ tpv_offset,
+ tpv_offset_extra,
+ fpv_viewpoint, /* expressed relative to neck bone inverse final*/
+ fpv_offset_smooth,
+ fpv_viewpoint_smooth,
+ tpv_offset_smooth,
+ tpv_lpf,
+ cam_velocity_smooth;
+};
+
+struct player_pose
+{
+ enum player_pose_type
+ {
k_player_pose_type_ik, /* regular IK animation */
k_player_pose_type_fk_2,
}
ms_keyframe keyframes[32];
- struct player_board_pose {
+ struct player_board_pose
+ {
f32 lean;
}
board;
};
-enum player_subsystem{
+enum player_subsystem
+{
k_player_subsystem_walk = 0,
k_player_subsystem_skate = 1,
k_player_subsystem_dead = 2,
k_player_subsystem_max,
k_player_subsystem_invalid = 255
};
+
+enum player_die_type
+{
+ k_player_die_type_generic,
+ k_player_die_type_head,
+ k_player_die_type_feet,
+ k_player_die_type_water
+};
+
+#endif
-#include "player_basic_info.h"
-#include "network_compression.h"
-
struct player_basic_info player_basic_info;
struct player_subsystem_interface player_subsystem_basic_info =
{
-#pragma once
-#include "player.h"
-#include "player_api.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/player_basic_info.c"
+#else
struct player_basic_info
{
void player__basic_info_animator_exchange(bitpack_ctx *ctx, void *data);
void player__basic_info_pose( void *_animator, player_pose *pose );
+#endif
-#include "ent_skateshop.h"
-#include "player.h"
-#include "input.h"
-#include "menu.h"
-#include "vg/vg_perlin.h"
-
float player_get_heading_yaw(void)
{
v3f xz;
-#pragma once
-#include "player_api.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/player_common.c"
+#else
static float
k_cam_spring = 20.0f,
void player_look( v3f angles, float speed );
void player__cam_iterate(void);
f32 player_get_heading_yaw(void);
+void compute_cam_controller_offsets( enum player_subsystem system, struct player_cam_controller *cc );
+
+#endif
-#include "skaterift.h"
-#include "player_dead.h"
-#include "gui.h"
-
struct player_dead player_dead;
struct player_subsystem_interface player_subsystem_dead = {
.update = player__dead_update,
.pose = player__dead_pose,
.post_animate = player__dead_post_animate,
.im_gui = player__dead_im_gui,
- .bind = player__dead_bind,
+ .load_resources = player__dead_load_resources,
.animator_data = &player_dead.animator,
.animator_size = sizeof(player_dead.animator),
}
}
- gui_helper_reset( k_gui_helper_mode_clear );
+ _gui_helper_reset( k_gui_helper_mode_clear );
}
}
else
{
localplayer_cmd_respawn(0,NULL);
srinput.state = k_input_state_resume;
- gui_helper_reset( k_gui_helper_mode_clear );
+ _gui_helper_reset( k_gui_helper_mode_clear );
}
}
}
struct player_dead *d = &player_dead;
struct player_dead_animator *animator = &d->animator;
struct player_ragdoll *rd = &localplayer.ragdoll;
- struct skeleton *sk = &localplayer.skeleton;
+ ms_skeleton *sk = &localplayer.skeleton;
m4x3f transforms[ 32 ];
/* bones without colliders transforms */
for( u32 i=1; i<sk->bone_count; i++ )
{
- struct skeleton_bone *sb = &sk->bones[i];
+ ms_skeleton_bone *sb = &sk->bones[i];
if( sb->parent && !sb->collider )
{
/* measurements */
for( u32 i=1; i<sk->bone_count; i++ )
{
- struct skeleton_bone *sb = &sk->bones[i];
+ ms_skeleton_bone *sb = &sk->bones[i];
v3_zero( animator->transforms[i].co );
q_identity( animator->transforms[i].q );
{
struct player_dead_animator *animator = _animator;
struct player_ragdoll *rd = &localplayer.ragdoll;
- struct skeleton *sk = &localplayer.skeleton;
+ ms_skeleton *sk = &localplayer.skeleton;
pose->type = k_player_pose_type_fk_2;
pose->board.lean = 0.0f;
return;
localplayer.fell_since_last_gate = 1;
-
localplayer.subsystem = k_player_subsystem_dead;
copy_localplayer_to_ragdoll( &localplayer.ragdoll, type );
v3_copy( part->rb.co, player_dead.co_lpf );
v3_copy( part->rb.v, player_dead.v_lpf );
v3_copy( part->rb.w, player_dead.w_lpf );
-
- gui_helper_reset( k_gui_helper_mode_black_bars );
+ _gui_helper_reset( k_gui_helper_mode_black_bars );
vg_str str;
- if( (player_dead.helper_getup = gui_new_helper(input_button_list[k_srbind_skate], &str) ))
+ if( (player_dead.helper_getup = _gui_new_helper(input_button_list[k_srbind_skate], &str) ))
{
vg_strcat( &str, "Get Up" );
-
if( (_world.event == k_world_event_challenge) && (_world.challenge_state >= k_challenge_state_running) )
{
vg_strcat( &str, " (Exit challenge)" );
-
struct gui_helper *helper;
- if( (helper = gui_new_helper(input_button_list[k_srbind_reset], &str)) )
- {
+ if( (helper = _gui_new_helper(input_button_list[k_srbind_reset], &str)) )
vg_strcat( &str, "Retry" );
- }
}
player_dead.helper_getup->greyed = 1;
void player__dead_animator_exchange( bitpack_ctx *ctx, void *data )
{
struct player_dead_animator *animator = data;
-
for( u32 i=0; i<localplayer.skeleton.bone_count; i ++ )
{
bitpack_qv3f( ctx, 24, -1024.0f, 1024.0f, animator->transforms[i].co );
}
}
-void player__dead_bind(void)
+void player__dead_load_resources(void)
{
- struct skeleton *sk = &localplayer.skeleton;
+ ms_skeleton *sk = &localplayer.skeleton;
player_get_anim( &player_dead.anim_bail, "pose_bail_ball" );
}
-#pragma once
-#include "player.h"
-#include "player_api.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/player_dead.c"
+#else
struct player_dead
{
}
animator;
- skeleton_anim anim_bail;
+ ms_skeletal_animation anim_bail;
struct gui_helper *helper_getup;
}
extern player_dead;
void player__dead_pose (void *animator, player_pose *pose);
void player__dead_post_animate(void);
void player__dead_im_gui ( ui_context *ctx );
-void player__dead_bind (void);
+void player__dead_load_resources(void);
void player__dead_transition ( enum player_die_type type );
void player__dead_animator_exchange( bitpack_ctx *ctx, void *data );
+#endif
+++ /dev/null
-#include "player_drive.h"
-#include "input.h"
-
-struct player_drive player_drive;
-struct player_subsystem_interface player_subsystem_drive =
-{
- .pre_update = player__drive_pre_update,
- .update = player__drive_update,
- .post_update = player__drive_post_update,
- .animate = player__drive_animate,
- .pose = player__drive_pose,
- .post_animate = player__drive_post_animate,
- .im_gui = player__drive_im_gui,
- .bind = player__drive_bind,
-
- .animator_data = NULL,
- .animator_size = 0,
- .name = "Drive"
-};
-
-void player__drive_pre_update(void)
-{
- drivable_vehicle *vehc = player_drive.vehicle;
-
- v2f steer;
- joystick_state( k_srjoystick_steer, steer );
-
- vehc->steer = vg_lerpf( vehc->steer, steer[0] * 0.4f,
- vg.time_fixed_delta * 8.0f );
- vehc->drive = steer[1];
-}
-
-void player__drive_update(void){}
-
-void player__drive_post_update(void)
-{
- v3_copy( player_drive.vehicle->rb.co,localplayer.rb.co );
- v3_copy( player_drive.vehicle->rb.v, localplayer.rb.v );
- v4_copy( player_drive.vehicle->rb.q, localplayer.rb.q );
- v3_copy( player_drive.vehicle->rb.w, localplayer.rb.w );
-}
-
-void player__drive_animate(void){}
-
-void player__drive_pose( void *animator, player_pose *pose )
-{
- struct skeleton *sk = &localplayer.skeleton;
-
- skeleton_sample_anim( sk, &player_drive.anim_drive, 0.0f, pose->keyframes );
- v3_copy( localplayer.rb.co, pose->root_co );
- v4_copy( localplayer.rb.q, pose->root_q );
-}
-
-void player__drive_post_animate(void)
-{
- if( localplayer.cam_control.camera_mode == k_cam_firstperson )
- localplayer.cam_velocity_influence = 0.0f;
- else
- localplayer.cam_velocity_influence = 1.0f;
-
- rigidbody *rb = &gzoomer.rb;
- float yaw = atan2f( -rb->to_world[2][0], rb->to_world[2][2] ),
- pitch = atan2f
- (
- -rb->to_world[2][1],
- sqrtf
- (
- rb->to_world[2][0]*rb->to_world[2][0] +
- rb->to_world[2][2]*rb->to_world[2][2]
- )
- );
-
- localplayer.angles[0] = yaw;
- localplayer.angles[1] = pitch;
-}
-
-void player__drive_im_gui( ui_context *ctx )
-{
- player__debugtext( ctx, 1, "Nothing here" );
-}
-
-void player__drive_bind(void)
-{
- struct skeleton *sk = &localplayer.skeleton;
- player_drive.vehicle = &gzoomer;
- player_get_anim( &player_drive.anim_drive, "idle_cycle+y" );
-}
+++ /dev/null
-#pragma once
-#include "player.h"
-#include "vehicle.h"
-
-struct player_drive
-{
- drivable_vehicle *vehicle;
- skeleton_anim anim_drive;
-}
-extern player_drive;
-extern struct player_subsystem_interface player_subsystem_drive;
-
-void player__drive_pre_update(void);
-void player__drive_update(void);
-void player__drive_post_update(void);
-void player__drive_animate(void);
-void player__drive_pose( void *animator, player_pose *pose );
-
-void player__drive_post_animate(void);
-void player__drive_im_gui( ui_context *ctx );
-void player__drive_bind(void);
-#include "player.h"
-#include "player_effects.h"
-#include "player_render.h"
-#include "particle.h"
-
void effect_blink_apply( effect_blink *ef, player_pose *pose, f32 dt )
{
if( ef->t < 0.0f ){
-#pragma once
-#include "vg/vg_platform.h"
-#include "player_render.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/player_effects.c"
+#else
typedef struct effect_blink effect_blink;
typedef struct effect_spark effect_spark;
effect_blink blink;
effect_spark spark, sand;
};
+
+#endif
-#include "player_glide.h"
-#include "vg/vg_rigidbody.h"
-#include "scene_rigidbody.h"
-#include "shaders/model_board_view.h"
-#include "shaders/model_entity.h"
-#include "input.h"
-#include "skaterift.h"
-
-#include "player_dead.h"
-#include "player_skate.h"
-
trail_system trails_glider[] = {
{
.width = 0.035f,
.post_animate = player_glide_post_animate,
.network_animator_exchange = player_glide_animator_exchange,
.im_gui = player_glide_im_gui,
- .bind = player_glide_bind,
+ .load_resources = player_glide_load_resources,
+ .init = player_glide_init,
.system_register = player_glide_register,
.animator_data = &player_glide.animator,
player_skate.state.activity_prev = k_skate_activity_air;
q_mulv( localplayer.rb.q, (v3f){0.0f,1.0f,0.0f}, player_skate.state.cog );
- v3_add( player_skate.state.cog, localplayer.rb.co,
- player_skate.state.cog );
+ v3_add( player_skate.state.cog, localplayer.rb.co, player_skate.state.cog );
v3_copy( localplayer.rb.v, player_skate.state.cog_v );
player__begin_holdout( (v3f){0.0f,0.0f,0.0f} );
}
}
-static void massless_accel( rigidbody *rb, v3f delta, v3f impulse ){
+static void massless_accel( rigidbody *rb, v3f delta, v3f impulse )
+{
/* linear */
v3_muladds( rb->v, impulse, vg.time_fixed_delta, rb->v );
v3_muladds( rb->w, wa, vg.time_fixed_delta, rb->w );
}
-static void calculate_lift( v3f vl, f32 aoa_bias,
- v3f axis, v3f back, f32 power,
- v3f out_force ){
+static void calculate_lift( v3f vl, f32 aoa_bias, v3f axis, v3f back, f32 power, v3f out_force )
+{
v3f up;
v3_cross( back, axis, up );
v3_cross( wind, axis, lift_dir );
/* this is where induced drag (from the flappy things) would go */
-
v3_muls( lift_dir, L, out_force );
}
-static void calculate_drag( v3f vl, f32 cd, v3f out_force ){
+static void calculate_drag( v3f vl, f32 cd, v3f out_force )
+{
f32 v2 = v3_length2( vl );
v3f dir;
v3_copy( vl, dir );
m3x3_mulv( rb->to_local, rb->w, wl );
v3f F, Flift, Fslip, Fdrag, FslipW, FliftW;
-
- calculate_lift( vl, steer[1]*k_glide_steer,
- (v3f){1,0,0},
+ calculate_lift( vl, steer[1]*k_glide_steer, (v3f){1,0,0},
(v3f){0,sinf(k_glide_wing_orient),cosf(k_glide_wing_orient)},
k_glide_cl, Flift );
+
v3_copy( Flift, player_glide.info_lift );
v3_cross( (v3f){0,0,0}, Flift, FliftW );
- calculate_lift( vl, 0.0f,
- (v3f){0,1,0},(v3f){0,0,1},
- k_glide_cs, Fslip );
+ calculate_lift( vl, 0.0f, (v3f){0,1,0},(v3f){0,0,1}, k_glide_cs, Fslip );
v3_copy( Fslip, player_glide.info_slip );
v3_cross( (v3f){0,k_glide_lift_pitch,k_glide_slip_yaw}, Fslip, FslipW );
v3f balance = {0.0f,-k_glide_balance,0.0f};
m3x3_mulv( rb->to_local, balance, balance );
- v3f Fw = {
+ v3f Fw =
+ {
steer[1]*k_glide_steer - balance[2],
0.0f,
-steer[0]*k_glide_steer + balance[0],
};
- if( player_glide.ticker ){
+ if( player_glide.ticker )
+ {
player_glide.ticker --;
return 0;
}
rigidbody _null = {0};
_null.inv_mass = 0.0f;
m3x3_zero( _null.iI );
- for( u32 i=0; i < VG_ARRAY_LEN(player_glide.parts); i ++ ){
+ for( u32 i=0; i < VG_ARRAY_LEN(player_glide.parts); i ++ )
+ {
m4x3f mmdl;
m4x3_mul( rb->to_world, player_glide.parts[i].mdl, mmdl );
- if( player_glide.parts[i].shape == k_rb_shape_capsule ){
- vg_line_capsule( mmdl,
- player_glide.parts[i].inf.r,
- player_glide.parts[i].inf.h,
- VG__BLACK );
+ if( player_glide.parts[i].shape == k_rb_shape_capsule )
+ {
+ vg_line_capsule( mmdl, player_glide.parts[i].inf.r, player_glide.parts[i].inf.h, VG__BLACK );
}
- else if( player_glide.parts[i].shape == k_rb_shape_sphere ){
+ else if( player_glide.parts[i].shape == k_rb_shape_sphere )
vg_line_sphere( mmdl, player_glide.parts[i].r, 0 );
- }
- if( rb_global_has_space() ){
+ if( rb_global_has_space() )
+ {
rb_ct *buf = rb_global_buffer();
-
u32 l = 0;
- if( player_glide.parts[i].shape == k_rb_shape_capsule ){
- l = rb_capsule__scene( mmdl, &player_glide.parts[i].inf,
- NULL, world->geo_bh, buf,
+ if( player_glide.parts[i].shape == k_rb_shape_capsule )
+ {
+ l = rb_capsule__scene( mmdl, &player_glide.parts[i].inf, NULL, &world->geometry_bh, buf,
k_material_flag_ghosts );
}
- else if( player_glide.parts[i].shape == k_rb_shape_sphere ){
- l = rb_sphere__scene( mmdl, player_glide.parts[i].r,
- NULL, world->geo_bh, buf,
+ else if( player_glide.parts[i].shape == k_rb_shape_sphere )
+ {
+ l = rb_sphere__scene( mmdl, player_glide.parts[i].r, NULL, &world->geometry_bh, buf,
k_material_flag_ghosts );
}
- if( player_glide.parts[i].is_damage && l ){
+ if( player_glide.parts[i].is_damage && l )
bottom_hit = 1;
- }
- for( u32 j=0; j<l; j ++ ){
+ for( u32 j=0; j<l; j ++ )
+ {
buf[j].rba = rb;
buf[j].rbb = &_null;
}
-
rb_contact_count += l;
}
}
- rb_presolve_contacts( rb_contact_buffer,
- vg.time_fixed_delta, rb_contact_count );
+ rb_presolve_contacts( rb_contact_buffer, vg.time_fixed_delta, rb_contact_count );
for( u32 i=0; i<10; i ++ )
rb_solve_contacts( rb_contact_buffer, rb_contact_count );
void player_glide_pose( void *_animator, player_pose *pose )
{
- struct skeleton *sk = &localplayer.skeleton;
+ ms_skeleton *sk = &localplayer.skeleton;
struct player_glide_animator *animator = _animator;
pose->type = k_player_pose_type_ik;
pose->board.lean = 0.0f;
void player_glide_equip_glider(void)
{
- if( !localplayer.have_glider ){
+ if( !localplayer.have_glider )
+ {
localplayer.have_glider = 1;
localplayer.glider_orphan = 0;
player_glide.t = -1.0f;
}
}
-static int ccmd_player_glider_spawn( int argc, const char *argv[] ){
+static int ccmd_player_glider_spawn( int argc, const char *argv[] )
+{
if( vg_console.cheats ){
player_glide_equip_glider();
}
vg_console_reg_cmd( "spawn_glider", ccmd_player_glider_spawn, NULL );
}
-void player_glide_bind(void)
+void player_glide_init(void)
{
- THREAD_1;
f32 mass = 0.0f,k_density = 8.0f;
m3x3f I;
m3x3_zero( I );
- for( u32 i=0; i<VG_ARRAY_LEN(player_glide.parts); i ++ ){
+ for( u32 i=0; i<VG_ARRAY_LEN(player_glide.parts); i ++ )
+ {
/* create part transform matrix */
v4f qp, qy, qr, q;
q_axis_angle( qp, (v3f){1,0,0}, player_glide.parts[i].euler[0] );
/* add it to inertia model */
- if( player_glide.parts[i].shape == k_rb_shape_capsule ){
+ if( player_glide.parts[i].shape == k_rb_shape_capsule )
+ {
f32 r = player_glide.parts[i].inf.r,
h = player_glide.parts[i].inf.h,
pv = vg_capsule_volume( r, h ),
vg_translate_inertia( pI, pm, player_glide.parts[i].co );
m3x3_add( I, pI, I );
}
- else if( player_glide.parts[i].shape == k_rb_shape_sphere ){
+ else if( player_glide.parts[i].shape == k_rb_shape_sphere )
+ {
f32 r = player_glide.parts[i].r,
pv = vg_sphere_volume( r ),
pm = pv * k_density;
m3x3_inv( I, player_glide.rb.iI );
player_glide.rb.inv_mass = 1.0f / mass;
+ /* allocate effects */
+ for( u32 i=0; i<VG_ARRAY_LEN(trails_glider); i ++ )
+ trail_alloc( &trails_glider[i], 200, VG_STACK_USE_HEAP );
+}
+
+void player_glide_load_resources(void)
+{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+
/* resources */
- struct skeleton *sk = &localplayer.skeleton;
+ ms_skeleton *sk = &localplayer.skeleton;
player_get_anim( &player_glide.anim_glide, "glide_pose" );
- mdl_context *mdl = &player_glide.glider;
-
- mdl_open( mdl, "models/glider.mdl", &vg.rtmem );
- mdl_load_metadata_block( mdl, &vg.rtmem );
- mdl_async_full_load_std( mdl, NULL );
+ vg_model_stream_context ctx;
+ VG_ASSERT( vg_model_stream_open( &ctx, &player_glide.glider, "models/glider.mdl" ) );
+ vg_model_stream_metadata( &ctx, VG_STACK_USE_HEAP );
+ vg_model_stream_meshes_gpu( &ctx, NULL );
+ vg_model_stream_textures_gpu( &ctx );
/* load trail positions */
array_file_ptr markers;
- AF_LOAD_ARRAY_STRUCT( &mdl->af, &markers, ent_marker, &vg.scratch );
- mdl_close( mdl );
-
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &markers, ent_marker, _vg_temp_stack() );
for( u32 i=0; i<af_arrcount( &markers ); i ++ )
{
ent_marker *marker = af_arritm( &markers, i );
v3_copy( marker->transform.co, player_glide.trail_positions[ player_glide.trail_count ++ ] );
-
if( player_glide.trail_count == VG_ARRAY_LEN(trails_glider) )
break;
}
-
- /* allocate effects */
- for( u32 i=0; i<VG_ARRAY_LEN(trails_glider); i ++ )
- trail_alloc( &trails_glider[i], 200 );
+ vg_model_stream_close( &ctx );
}
void player_glide_transition(void)
player__begin_holdout( (v3f){0,0,0} );
}
-void render_glider_model( vg_camera *cam, world_instance *world, m4x3f mmdl, enum board_shader shader, mdl_context *mdl )
+void render_glider_model( vg_camera *cam, world_instance *world, m4x3f mmdl, enum board_shader shader, vg_model *model )
{
u32 current_mat = 0xffffffff;
- glActiveTexture( GL_TEXTURE0 );
- mesh_bind( &mdl->mesh );
+ vg_model_bind_mesh( model );
- for( u32 i=0; i<mdl->mesh_count; i ++ )
+ for( u32 i=0; i<model->mesh_count; i ++ )
{
- mdl_mesh *mesh = &mdl->meshes[ i ];
+ mdl_mesh *mesh = &model->meshes[ i ];
m4x3f mmmdl;
mdl_transform_m4x3( &mesh->transform, mmmdl );
for( u32 j=0; j<mesh->submesh_count; j ++ )
{
- mdl_submesh *sm = &mdl->submeshes[ mesh->submesh_start+j ];
+ mdl_submesh *sm = &model->submeshes[ mesh->submesh_start+j ];
if( !sm->material_id )
{
vg_error( "Invalid material ID 0\n" );
if( sm->material_id != current_mat )
{
- mdl_material *mat = &mdl->materials[ sm->material_id-1 ];
+ mdl_material *mat = &model->materials[ sm->material_id-1 ];
GLuint tex = vg.tex_missing;
if( mat->shader == k_shader_standard )
{
- struct shader_props_standard *props = mat->props.compiled;
-
- u32 index = props->tex_diffuse-1;
- mdl_texture *ptex = &mdl->textures[ index ];
- tex = ptex->glname;
+ union shader_props *props = &model->shader_props[ sm->material_id-1 ];
+ u32 index = props->standard.tex_diffuse-1;
+ mdl_texture *mdl_tex = &model->textures[ index ];
+ vg_tex_bind( GL_TEXTURE_2D, &mdl_tex->tex, 0 );
}
+ else
+ vg_tex_bind( GL_TEXTURE_2D, NULL, 0 );
- glBindTexture( GL_TEXTURE_2D, tex );
current_mat = sm->material_id;
}
- mdl_draw_submesh( sm );
+ vg_model_draw_submesh( sm );
}
}
}
shader_model_board_view_uInverseRatioMain,
cam );
- WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, model_board_view );
+ WORLD_LINK_LIGHTING( world, model_board_view );
ms_keyframe kf_res;
if( localplayer.glider_orphan )
vg_slewf( &player_glide.t, target, vg.time_frame_delta * 4.0f );
ms_keyframe kf_backpack;
- struct skeleton *sk = &localplayer.skeleton;
+ ms_skeleton *sk = &localplayer.skeleton;
m4x3_mulv( localplayer.final_mtx[localplayer.id_chest ], sk->bones[localplayer.id_chest].co, kf_backpack.co );
v4f qyaw, qpitch, qchest, q;
-#pragma once
-#include "player.h"
-#include "player_render.h"
-#include "trail.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/player_glide.c"
+#else
struct player_glide
{
- struct skeleton_anim anim_glide;
+ ms_skeletal_animation anim_glide;
struct player_glide_animator
{
f32 t;
- struct {
+ struct
+ {
v3f co, euler;
m4x3f mdl;
-
- union {
+ union
+ {
rb_capsule inf;
f32 r;
};
u32 trail_count;
v3f trail_positions[2];
- mdl_context glider, battery;
+ vg_model glider, battery;
}
extern player_glide;
extern struct player_subsystem_interface player_subsystem_glide;
void player_glide_register(void);
+void player_glide_init(void);
+void player_glide_pre_update(void);
+void player_glide_load_resources(void);
void player_glide_pre_update(void);
void player_glide_update(void);
void player_glide_post_update(void);
void player_glide_transition(void);
bool glider_physics( v2f steer );
void player_glide_animator_exchange( bitpack_ctx *ctx, void *data );
-void player_glide_render( vg_camera *cam, world_instance *world,
- player_pose *pose );
-void render_glider_model( vg_camera *cam, world_instance *world, m4x3f mmdl, enum board_shader shader, mdl_context *mdl );
+void player_glide_render( vg_camera *cam, world_instance *world, player_pose *pose );
+void render_glider_model( vg_camera *cam, world_instance *world, m4x3f mmdl, enum board_shader shader, vg_model *model );
void player_glide_remote_animator_exchange( bitpack_ctx *ctx, void *data );
void player_glide_equip_glider(void);
void player_glide_render_effects( vg_camera *cam );
+#endif
+++ /dev/null
-/*
- * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#pragma once
-#include "model.h"
-#include "skeleton.h"
-#include "player_ragdoll.h"
-
-#include "shaders/model_character_view.h"
-#pragma once
-#include "vg/vg_rigidbody.h"
-#include "vg/vg_rigidbody_collision.h"
-#include "vg/vg_rigidbody_constraints.h"
-#include "scene_rigidbody.h"
-
-#include "player.h"
-#include "player_dead.h"
-#include "audio.h"
-
static float k_ragdoll_floatyiness = 20.0f,
k_ragdoll_floatydrag = 1.0f,
k_ragdoll_limit_scale = 1.0f,
return 0;
}
-void player_ragdoll_register(void)
+VG_API void _player_ragdoll_register(void)
{
VG_VAR_F32( k_ragdoll_active_threshold );
VG_VAR_F32( k_ragdoll_angular_drag );
vg_console_reg_cmd( "ragdoll", dev_ragdoll_saveload, NULL );
}
-void player_init_ragdoll_bone_collider( struct skeleton_bone *bone,
- struct ragdoll_part *rp )
+void player_init_ragdoll_bone_collider( ms_skeleton_bone *bone, struct ragdoll_part *rp )
{
f32 k_density = 8.0f,
k_inertia_scale = 2.0f;
/*
* Setup ragdoll colliders from skeleton
*/
-void setup_ragdoll_from_skeleton( struct skeleton *sk,
- struct player_ragdoll *rd )
+void setup_ragdoll_from_skeleton( ms_skeleton *sk, struct player_ragdoll *rd )
{
rd->part_count = 0;
rd->position_constraints_count = 0;
rd->cone_constraints_count = 0;
- for( u32 i=1; i<sk->bone_count; i ++ ){
- struct skeleton_bone *bone = &sk->bones[i];
+ for( u32 i=1; i<sk->bone_count; i ++ )
+ {
+ ms_skeleton_bone *bone = &sk->bones[i];
/*
* Bones with colliders
struct rb_constr_pos *c = &rd->position_constraints[ conid ];
- struct skeleton_bone *bj = &sk->bones[rp->bone_id];
+ ms_skeleton_bone *bj = &sk->bones[rp->bone_id];
struct ragdoll_part *pp = &rd->parts[rp->parent];
- struct skeleton_bone *bp = &sk->bones[pp->bone_id];
+ ms_skeleton_bone *bp = &sk->bones[pp->bone_id];
rd->constraint_associations[conid][0] = rp->parent;
rd->constraint_associations[conid][1] = part_id;
localplayer.final_mtx[part->bone_id] );
}
- for( u32 i=1; i<localplayer.skeleton.bone_count; i++ ){
- struct skeleton_bone *sb = &localplayer.skeleton.bones[i];
+ for( u32 i=1; i<localplayer.skeleton.bone_count; i++ )
+ {
+ ms_skeleton_bone *sb = &localplayer.skeleton.bones[i];
- if( sb->parent && !sb->collider ){
+ if( sb->parent && !sb->collider )
+ {
v3f delta;
v3_sub( localplayer.skeleton.bones[i].co,
localplayer.skeleton.bones[sb->parent].co, delta );
rb_solver_reset();
- float contact_velocities[256];
+ f32 contact_velocities[256];
rigidbody _null = {0};
_null.inv_mass = 0.0f;
m3x3_zero( _null.iI );
- for( int i=0; i<rd->part_count; i ++ ){
+ for( int i=0; i<rd->part_count; i ++ )
+ {
v4_copy( rd->parts[i].rb.q, rd->parts[i].prev_q );
v3_copy( rd->parts[i].rb.co, rd->parts[i].prev_co );
- if( rb_global_has_space() ){
+ if( rb_global_has_space() )
+ {
rb_ct *buf = rb_global_buffer();
-
int l;
- if( rd->parts[i].type == k_bone_collider_capsule ){
- l = rb_capsule__scene( rd->parts[i].rb.to_world,
- &rd->parts[i].inf.capsule,
- NULL, world->geo_bh, buf,
- k_material_flag_ghosts );
+ if( rd->parts[i].type == k_bone_collider_capsule )
+ {
+ l = rb_capsule__scene( rd->parts[i].rb.to_world, &rd->parts[i].inf.capsule,
+ NULL, &world->geometry_bh, buf, k_material_flag_ghosts );
}
- else if( rd->parts[i].type == k_bone_collider_box ){
- l = rb_box__scene( rd->parts[i].rb.to_world,
- rd->parts[i].inf.box,
- NULL, world->geo_bh, buf,
- k_material_flag_ghosts );
+ else if( rd->parts[i].type == k_bone_collider_box )
+ {
+ l = rb_box__scene( rd->parts[i].rb.to_world, rd->parts[i].inf.box,
+ NULL, &world->geometry_bh, buf, k_material_flag_ghosts );
}
- else continue;
+ else
+ continue;
- for( int j=0; j<l; j++ ){
+ for( int j=0; j<l; j++ )
+ {
buf[j].rba = &rd->parts[i].rb;
buf[j].rbb = &_null;
}
/*
* self-collision
*/
- for( int i=0; i<rd->part_count-1; i ++ ){
- for( int j=i+1; j<rd->part_count; j ++ ){
- if( rd->parts[j].parent != i ){
+ for( int i=0; i<rd->part_count-1; i ++ )
+ {
+ for( int j=i+1; j<rd->part_count; j ++ )
+ {
+ if( rd->parts[j].parent != i )
+ {
if( !rb_global_has_space() )
break;
&rd->parts[j].inf.capsule,
buf );
- for( int k=0; k<l; k++ ){
+ for( int k=0; k<l; k++ )
+ {
buf[k].rba = &rd->parts[i].rb;
buf[k].rbb = &rd->parts[j].rb;
}
struct ragdoll_part *pj = &rd->parts[j];
if( run_sim )
- {
- rb_effect_simple_bouyency( &pj->rb, world->water.plane,
- k_ragdoll_floatyiness,
- k_ragdoll_floatydrag );
- }
+ rb_effect_simple_bouyency( &pj->rb, world->water.plane, k_ragdoll_floatyiness, k_ragdoll_floatydrag );
}
}
/*
* PRESOLVE
*/
- for( u32 i=0; i<rb_contact_count; i++ ){
+ for( u32 i=0; i<rb_contact_count; i++ )
+ {
rb_ct *ct = &rb_contact_buffer[i];
-
v3f rv, ra, rb;
v3_sub( ct->co, ct->rba->co, ra );
v3_sub( ct->co, ct->rbb->co, rb );
rb_rcv( ct->rba, ct->rbb, ra, rb, rv );
- float vn = v3_dot( rv, ct->n );
-
+ f32 vn = v3_dot( rv, ct->n );
contact_velocities[i] = vn;
}
- rb_presolve_contacts( rb_contact_buffer, vg.time_fixed_delta,
- rb_contact_count );
- rb_presolve_swingtwist_constraints( rd->cone_constraints,
- rd->cone_constraints_count );
+ rb_presolve_contacts( rb_contact_buffer, vg.time_fixed_delta, rb_contact_count );
+ rb_presolve_swingtwist_constraints( rd->cone_constraints, rd->cone_constraints_count );
/*
* DEBUG
*/
- if( k_ragdoll_debug_collider ){
- for( u32 i=0; i<rd->part_count; i ++ ){
+ if( k_ragdoll_debug_collider )
+ {
+ for( u32 i=0; i<rd->part_count; i ++ )
+ {
struct ragdoll_part *rp = &rd->parts[i];
- if( rp->type == k_bone_collider_capsule ){
- vg_line_capsule( rp->rb.to_world,
- rp->inf.capsule.r, rp->inf.capsule.h, rp->colour );
- }
- else if( rp->type == k_bone_collider_box ){
- vg_line_boxf_transformed( rp->rb.to_world,
- rp->inf.box, rp->colour );
- }
+ if( rp->type == k_bone_collider_capsule )
+ vg_line_capsule( rp->rb.to_world, rp->inf.capsule.r, rp->inf.capsule.h, rp->colour );
+ else if( rp->type == k_bone_collider_box )
+ vg_line_boxf_transformed( rp->rb.to_world, rp->inf.box, rp->colour );
}
}
- if( k_ragdoll_debug_constraints ){
- rb_debug_position_constraints( rd->position_constraints,
- rd->position_constraints_count );
-
- rb_debug_swingtwist_constraints( rd->cone_constraints,
- rd->cone_constraints_count );
+ if( k_ragdoll_debug_constraints )
+ {
+ rb_debug_position_constraints( rd->position_constraints, rd->position_constraints_count );
+ rb_debug_swingtwist_constraints( rd->cone_constraints, rd->cone_constraints_count );
}
/*
* SOLVE CONSTRAINTS & Integrate
*/
- if( run_sim ){
+ if( run_sim )
+ {
/* the solver is not very quickly converging so... */
- for( int i=0; i<40; i++ ){
- if( i<20 ){
+ for( int i=0; i<40; i++ )
+ {
+ if( i<20 )
+ {
rb_solve_contacts( rb_contact_buffer, rb_contact_count );
- rb_solve_swingtwist_constraints( rd->cone_constraints,
- rd->cone_constraints_count );
- rb_postsolve_swingtwist_constraints( rd->cone_constraints,
- rd->cone_constraints_count );
+ rb_solve_swingtwist_constraints( rd->cone_constraints, rd->cone_constraints_count );
+ rb_postsolve_swingtwist_constraints( rd->cone_constraints, rd->cone_constraints_count );
}
- rb_solve_position_constraints( rd->position_constraints,
- rd->position_constraints_count );
+ rb_solve_position_constraints( rd->position_constraints, rd->position_constraints_count );
}
- rb_correct_position_constraints( rd->position_constraints,
- rd->position_constraints_count,
- k_ragdoll_correction * 0.5f );
- rb_correct_swingtwist_constraints( rd->cone_constraints,
- rd->cone_constraints_count,
- k_ragdoll_correction * 0.25f );
+ rb_correct_position_constraints( rd->position_constraints, rd->position_constraints_count, k_ragdoll_correction * 0.5f );
+ rb_correct_swingtwist_constraints( rd->cone_constraints, rd->cone_constraints_count, k_ragdoll_correction * 0.25f );
- for( int i=0; i<rd->part_count; i++ ){
+ for( int i=0; i<rd->part_count; i++ )
+ {
rb_iter( &rd->parts[i].rb );
v3f w;
v3_copy( rd->parts[i].rb.w, w );
- if( v3_length2( w ) > 0.00001f ){
+ if( v3_length2( w ) > 0.00001f )
+ {
v3_normalize( w );
- v3_muladds( rd->parts[i].rb.w, w, -k_ragdoll_angular_drag,
- rd->parts[i].rb.w );
+ v3_muladds( rd->parts[i].rb.w, w, -k_ragdoll_angular_drag, rd->parts[i].rb.w );
}
}
}
rb_ct *stress = NULL;
- float max_stress = 1.0f;
-
- for( u32 i=0; i<rb_contact_count; i++ ){
+ f32 max_stress = 1.0f;
+ for( u32 i=0; i<rb_contact_count; i++ )
+ {
rb_ct *ct = &rb_contact_buffer[i];
v3f rv, ra, rb;
v3_sub( ct->co, ct->rba->co, ra );
v3_sub( ct->co, ct->rbb->co, rb );
rb_rcv( ct->rba, ct->rbb, ra, rb, rv );
- float vn = v3_dot( rv, ct->n );
-
- float s = fabsf(vn - contact_velocities[i]);
- if( s > max_stress ){
+ f32 vn = v3_dot( rv, ct->n );
+ f32 s = fabsf(vn - contact_velocities[i]);
+ if( s > max_stress )
+ {
stress = ct;
max_stress = s;
}
/*
* motorized joints
*/
- if( run_sim &&
- (v3_length2(player_dead.v_lpf)>(k_ragdoll_active_threshold*
- k_ragdoll_active_threshold)) ){
+ if( run_sim && (v3_length2(player_dead.v_lpf)>(k_ragdoll_active_threshold*k_ragdoll_active_threshold)) )
+ {
ms_keyframe anim[32];
- skeleton_sample_anim( &localplayer.skeleton, &player_dead.anim_bail,
- 0.0f, anim );
+ skeleton_sample_anim( &localplayer.skeleton, &player_dead.anim_bail, 0.0f, anim );
- for( u32 i=0; i<rd->cone_constraints_count; i ++ ){
+ for( u32 i=0; i<rd->cone_constraints_count; i ++ )
+ {
rb_constr_swingtwist *st = &rd->cone_constraints[i];
rb_constr_pos *pc = &rd->position_constraints[i];
}
}
- if( temp_filter ){
+ if( temp_filter )
+ {
temp_filter --;
return;
}
-#pragma once
-
-/*
- * Copyright (C) 2021-2024 Mt.ZERO Software - All Rights Reserved
- *
- * Ragdoll system
- */
-
-#include "player_api.h"
-#include "skeleton.h"
-#include "vg/vg_rigidbody.h"
-#include "vg/vg_rigidbody_constraints.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/player_ragdoll.c"
+#else
struct player_ragdoll{
struct ragdoll_part{
int shoes[2];
};
-enum player_die_type {
- k_player_die_type_generic,
- k_player_die_type_head,
- k_player_die_type_feet,
- k_player_die_type_water
-};
+VG_API void _player_ragdoll_register(void);
-void player_ragdoll_register(void);
-void player_init_ragdoll_bone_collider( struct skeleton_bone *bone,
- struct ragdoll_part *rp );
+void player_init_ragdoll_bone_collider( ms_skeleton_bone *bone, struct ragdoll_part *rp );
u32 ragdoll_bone_parent( struct player_ragdoll *rd, u32 bone_id );
-void setup_ragdoll_from_skeleton( struct skeleton *sk,
- struct player_ragdoll *rd );
+void setup_ragdoll_from_skeleton( ms_skeleton *sk, struct player_ragdoll *rd );
void copy_ragdoll_pose_to_localplayer( struct player_ragdoll *rd );
-void copy_localplayer_to_ragdoll( struct player_ragdoll *rd,
- enum player_die_type type );
+void copy_localplayer_to_ragdoll( struct player_ragdoll *rd, enum player_die_type type );
void player_debug_ragdoll(void);
void player_ragdoll_iter( struct player_ragdoll *rd );
+
+#endif
-#include "player_remote.h"
-#include "skeleton.h"
-#include "player_render.h"
-#include "player_api.h"
-#include "network_common.h"
-#include "addon.h"
-#include "font.h"
-#include "gui.h"
-#include "ent_region.h"
-#include "shaders/model_entity.h"
-#include "vg/vg_steam2.h"
-#include "vg/vg_magi.h"
-
struct global_netplayers netplayers;
static i32 k_show_own_name = 0;
{
menu_close(); /* sets state to default */
menu_open( k_menu_page_quick );
- gui_helper_reset( k_gui_helper_mode_clear );
+ _gui_helper_reset( k_gui_helper_mode_clear );
localplayer.immobile = 0;
}
}
struct player_effects_data *out_effects,
bool *out_render_glider, vg_camera *out_camera )
{
- struct skeleton *sk = &localplayer.skeleton;
+ ms_skeleton *sk = &localplayer.skeleton;
struct player_subsystem_interface *sys0 = player_subsystems[i0->subsystem],
*sys1 = NULL;
}
struct network_player *player = &netplayers.list[ index ];
- struct skeleton *sk = &localplayer.skeleton;
+ ms_skeleton *sk = &localplayer.skeleton;
m4x3f *final_mtx = &netplayers.final_mtx[ sk->bone_count*index ];
v3f *glider_mtx = netplayers.glider_mtx[ index ];
struct player_board_pose *board_pose = &netplayers.board_poses[index];
gliders ++;
}
- struct skeleton *sk = &localplayer.skeleton;
+ ms_skeleton *sk = &localplayer.skeleton;
for( u32 j=0; j<draw_list_count; j ++ )
{
shader_model_entity_uTexMain( 0 );
shader_model_entity_uCamera( cam->transform[3] );
shader_model_entity_uPv( cam->mtx.pv );
-
- WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, model_entity );
+ WORLD_LINK_LIGHTING( world, model_entity );
for( u32 j=0; j<draw_list_count; j ++ )
{
/*
* animator->root_co of remote player
*/
-static void remote_player_position( int id, v3f out_co ){
- struct skeleton *sk = &localplayer.skeleton;
+static void remote_player_position( int id, v3f out_co )
+{
+ ms_skeleton *sk = &localplayer.skeleton;
m4x3f *final_mtx = &netplayers.final_mtx[ sk->bone_count*id ];
v3_copy( final_mtx[0][3], out_co );
}
float k_max = 32000.0f;
- out_point[0] = vg_clampf(wpos[0] * vg.window_x, -k_max, k_max );
- out_point[1] = vg_clampf((1.0f-wpos[1]) * vg.window_y, -k_max, k_max );
+ out_point[0] = vg_clampf(wpos[0] * _vg_window.w, -k_max, k_max );
+ out_point[1] = vg_clampf((1.0f-wpos[1]) * _vg_window.h, -k_max, k_max );
return 1;
}
else
#if 0
vg_strcatch( &str, (char)k_SRglyph_vg_circle );
#endif
- vg_strcati32( &str, player->medals[i] );
+ vg_strcati64( &str, player->medals[i], 10 );
ui_text( ctx, col, buf, 1, k_ui_align_middle_center,
ui_colour( ctx, (enum ui_scheme_colour[]){
return;
ui_px y = 50, width = 200, height = 42, gap = 2,
- x = vg.window_x - width;
+ x = _vg_window.w - width;
ctx->font = &vgf_default_large;
ui_text( ctx, (ui_rect){ x, 0, width, height }, "In World", 1, k_ui_align_middle_center, 0 );
if( netplayers.chatting == 1 )
{
ui_rect box = { 0, 0, 400, 40 },
- window = { 0, 0, vg.window_x, vg.window_y };
+ window = { 0, 0, _vg_window.w, _vg_window.h };
ui_rect_center( window, box );
struct ui_textbox_callbacks callbacks =
return 1;
}
-void remote_players_register(void)
+VG_API void _remote_players_register(void)
{
vg_console_reg_cmd( "network_info", cmd_network_info, NULL );
vg_console_reg_cmd( "add_test_players", remote_players_randomize, NULL );
vg_console_reg_var( "k_show_own_name", &k_show_own_name, k_var_dtype_i32, 0 );
}
-void remote_players_init(void)
+VG_API void _remote_players_init(void)
{
for( u32 i=0; i<NETWORK_SFX_QUEUE_LENGTH; i ++ )
netplayers.sfx_queue[i].system = k_player_subsystem_invalid;
struct network_player *player = &netplayers.list[ netplayers.spectate_index ];
if( !player->active || !player->same_world )
{
- gui_helper_reset( k_gui_helper_mode_clear );
+ _gui_helper_reset( k_gui_helper_mode_clear );
localplayer.immobile = 0;
skaterift.activity = k_skaterift_default;
return;
-#pragma once
-#include "player.h"
-#include "network.h"
-#include "network_common.h"
-#include "player_render.h"
-#include "player_effects.h"
-#include "player_api.h"
-
-#include "player_skate.h"
-#include "player_walk.h"
-#include "player_dead.h"
-#include "player_basic_info.h"
-#include "player_glide.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/player_remote.c"
+#else
#define NETWORK_SFX_QUEUE_LENGTH 12
u32 spectate_index;
vg_camera spectate_camera;
- struct interp_buffer {
+ struct interp_buffer
+ {
/* collect the most recent 6 frames of animation data */
struct interp_frame
{
}
extern netplayers;
+VG_API void _remote_players_register(void);
+VG_API void _remote_players_init(void);
+
void player_remote_rx_200_300( SteamNetworkingMessage_t *msg );
void remote_player_debug_update(void);
void remote_player_send_playerframe(void);
void render_remote_players( world_instance *world, vg_camera *cam );
void relink_all_remote_player_worlds(void);
void player_remote_update_friendflags( struct network_player *remote );
-void remote_players_register(void);
-void remote_players_init(void);
void remote_sfx_pre_update(void);
void remote_players_imgui_world( ui_context *ctx, world_instance *world, m4x4f pv, f32 max_dist, int geo_cull );
void remote_players_imgui_lobby( ui_context *ctx );
void decode_playerframe( netmsg_playerframe *frame, u32 data_length, struct interp_frame *dest,
struct net_sfx *sfx_buffer, u32 *inout_sfx_buffer_len );
void _network_get_spectate_cam( vg_camera *cam );
+
+#endif
-#include "player.h"
-#include "player_render.h"
-#include "vg/vg_camera.h"
-#include "player_model.h"
-#include "ent_skateshop.h"
-#include "audio.h"
-#include "input.h"
-
-#include "shaders/model_character_view.h"
-#include "shaders/model_board_view.h"
-#include "shaders/model_entity.h"
-#include "shaders/model_board_view.h"
-#include "depth_compare.h"
-
-#include "network.h"
-#include "player_remote.h"
-#include "player_glide.h"
-#include "metascene.h"
-
-void player_load_animations( const char *path )
+static void _player_render_load_content_async( void *_, vg_async_info *async )
{
- metascene_load( &localplayer.animations, path, &vg.rtmem );
-}
-
-void player_get_anim( skeleton_anim *out_anim, const char *name )
-{
- ms_context *ms = &localplayer.animations;
- u32 hash = vg_strdjb2( name );
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
- for( u32 i=0; i<af_arrcount( &ms->strips ); i ++ )
- {
- ms_strip *strip = af_arritm( &ms->strips, i );
- if( strip->mode != k_ms_strip_mode_keyframes )
- continue;
-
- if( af_str_eq( &ms->af, strip->strip.pstr_name, name, hash ) )
- {
- out_anim->strip = strip;
- out_anim->framerate = localplayer.animations.info.framerate;
- out_anim->keyframes_base = af_arritm( &localplayer.animations.keyframes, strip->strip.start );
- return;
- }
- }
- vg_fatal_error( "Failed to find animation '%s' in metascene.\n", name );
-}
-
-void player_load_animation_reference( const char *path )
-{
- mdl_context *meta = &localplayer.skeleton_meta;
- mdl_open( meta, path, &vg.rtmem );
- mdl_load_metadata_block( meta, &vg.rtmem );
- mdl_close( meta );
-
- struct skeleton *sk = &localplayer.skeleton;
- skeleton_setup( sk, meta, 0, &vg.rtmem );
+ vg_model_load( &localplayer.skeleton_meta, VG_MODEL_CPU_METADATA, "models/ch_none.mdl", NULL );
+ ms_skeleton *sk = &localplayer.skeleton;
+ skeleton_setup( sk, &localplayer.skeleton_meta, 0, VG_STACK_USE_HEAP );
localplayer.id_world = skeleton_bone_id( sk, "world" );
localplayer.id_hip = skeleton_bone_id( sk, "hips" );
localplayer.id_ik_knee_r = skeleton_bone_id( sk, "knee.R" );
localplayer.id_eyes = skeleton_bone_id( sk, "eyes" );
- for( i32 i=0; i<sk->bone_count; i ++ ){
+ for( i32 i=0; i<sk->bone_count; i ++ )
localplayer.skeleton_mirror[i] = 0;
- }
-
- for( i32 i=1; i<sk->bone_count-1; i ++ ){
- struct skeleton_bone *si = &sk->bones[i];
+ for( i32 i=1; i<sk->bone_count-1; i ++ )
+ {
+ ms_skeleton_bone *si = &sk->bones[i];
char tmp[64];
vg_str str;
vg_strnull( &str, tmp, 64 );
vg_strcat( &str, si->name );
char *L = vg_strch( &str, 'L' );
- if( !L ) continue;
+ if( !L )
+ continue;
u32 len = L-tmp;
- for( i32 j=i+1; j<sk->bone_count; j ++ ){
- struct skeleton_bone *sj = &sk->bones[j];
-
- if( !strncmp( si->name, sj->name, len ) ){
- if( sj->name[len] == 'R' ){
+ for( i32 j=i+1; j<sk->bone_count; j ++ )
+ {
+ ms_skeleton_bone *sj = &sk->bones[j];
+ if( !strncmp( si->name, sj->name, len ) )
+ {
+ if( sj->name[len] == 'R' )
+ {
localplayer.skeleton_mirror[i] = j;
localplayer.skeleton_mirror[j] = i;
break;
}
}
}
-
setup_ragdoll_from_skeleton( sk, &localplayer.ragdoll );
- /* allocate matrix buffers for localplayer and remote players */
+ /* allocate matrix buffers for localplayer and remote players. uh this is a bit crappy? */
u32 mtx_size = sizeof(m4x3f)*sk->bone_count;
- localplayer.final_mtx = vg_stack_allocate( &vg.rtmem, mtx_size, 8, "Final MTX" );
- netplayers.final_mtx = vg_stack_allocate( &vg.rtmem, mtx_size*NETWORK_MAX_PLAYERS, 8, "Network final MTX" );
- netplayers.glider_mtx = vg_stack_allocate( &vg.rtmem, sizeof(m4x3f)*NETWORK_MAX_PLAYERS, 8, "Glider MTX" );
+ localplayer.final_mtx = vg_stack_allocate( VG_STACK_USE_HEAP, mtx_size, 8, "Final MTX" );
+ netplayers.final_mtx = vg_stack_allocate( VG_STACK_USE_HEAP, mtx_size*NETWORK_MAX_PLAYERS, 8, "Network final MTX" );
+ netplayers.glider_mtx = vg_stack_allocate( VG_STACK_USE_HEAP, sizeof(m4x3f)*NETWORK_MAX_PLAYERS, 8, "Glider MTX" );
+ _replay2.final_mtx = vg_stack_allocate( VG_STACK_USE_HEAP, mtx_size, 8, "Replay Final MTX" );
+ metascene_load( &localplayer.animations, "metascenes/skater.ms", NULL );
+
+ player_model_load( &localplayer.fallback_model, "models/ch_none.mdl", VG_STACK_USE_HEAP );
+ player_board_load( &localplayer.fallback_board, "models/board_none.mdl", VG_STACK_USE_HEAP );
+ vg_model_load( &localplayer.battery, VG_MODEL_ENGINE_STANDARD, "models/battery.mdl", VG_STACK_USE_HEAP );
+
+ for( u32 i=0; i<k_player_subsystem_max; i++ )
+ {
+ struct player_subsystem_interface *sys = player_subsystems[i];
+ if( sys && sys->load_resources )
+ sys->load_resources();
+ }
+}
+
+VG_API void _player_render_init(void)
+{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_player_render_load_content_async );
+}
+
+void player_get_anim( ms_skeletal_animation *out_anim, const char *name )
+{
+ metascene *ms = &localplayer.animations;
+ u32 hash = vg_strdjb2( name );
+
+ for( u32 i=0; i<af_arrcount( &ms->strips ); i ++ )
+ {
+ ms_strip *strip = af_arritm( &ms->strips, i );
+ if( strip->mode != k_ms_strip_mode_keyframes )
+ continue;
+
+ if( af_str_eq( ms->packed_strings, strip->strip.pstr_name, name, hash ) )
+ {
+ out_anim->strip = strip;
+ out_anim->framerate = localplayer.animations.info.framerate;
+ out_anim->keyframes_base = af_arritm( &localplayer.animations.keyframes, strip->strip.start );
+ return;
+ }
+ }
+ vg_fatal_error( "Failed to find animation '%s' in metascene.\n", name );
}
/* TODO: allow error handling */
-void player_board_load( player_board *board, const char *path, void *arena )
+void player_board_load( player_board *board, const c8 *path, vg_stack_allocator *stack )
{
- THREAD_1;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
- mdl_open( &board->mdl, path, arena );
- mdl_load_metadata_block( &board->mdl, arena );
- mdl_async_full_load_std( &board->mdl, NULL );
+ vg_model_stream_context ctx;
+ VG_ASSERT( vg_model_stream_open( &ctx, &board->model, path ) );
+ vg_model_stream_metadata( &ctx, stack );
+ vg_model_stream_meshes_gpu( &ctx, NULL );
+ vg_model_stream_textures_gpu( &ctx );
array_file_ptr markers;
- AF_LOAD_ARRAY_STRUCT( &board->mdl.af, &markers, ent_marker, &vg.scratch );
-
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &markers, ent_marker, _vg_temp_stack() );
for( int i=0; i<4; i++ )
board->wheels[i].indice_count = 0;
for( int i=0; i<2; i++ )
board->trucks[i].indice_count = 0;
board->board.indice_count = 0;
- for( u32 i=0; i<board->mdl.mesh_count; i++ )
+ for( u32 i=0; i<board->model.mesh_count; i++ )
{
- mdl_mesh *mesh = &board->mdl.meshes[ i ];
-
+ mdl_mesh *mesh = &board->model.meshes[ i ];
if( mdl_entity_id_type( mesh->entity_id ) != k_ent_marker )
continue;
u32 index = mdl_entity_id_id( mesh->entity_id );
ent_marker *marker = af_arritm( &markers, index );
- mdl_submesh *sm0 = &board->mdl.submeshes[ mesh->submesh_start ];
+ mdl_submesh *sm0 = &board->model.submeshes[ mesh->submesh_start ];
- const char *alias = af_str( &board->mdl.af, marker->pstr_alias );
+ const char *alias = af_str( board->model.packed_strings, marker->pstr_alias );
u32 lr = marker->transform.co[0] > 0.0f? 1: 0,
fb = marker->transform.co[2] > 0.0f? 0: 1;
- if( !strcmp( alias, "wheel" ) ){
+ if( !strcmp( alias, "wheel" ) )
+ {
u32 id = fb<<1 | lr;
board->wheels[ id ] = *sm0;
v3_copy( marker->transform.co, board->wheel_positions[ id ] );
}
- else if( !strcmp( alias, "board" ) ){
+ else if( !strcmp( alias, "board" ) )
+ {
board->board = *sm0;
v3_copy( marker->transform.co, board->board_position );
}
- else if( !strcmp( alias, "truck" ) ){
+ else if( !strcmp( alias, "truck" ) )
+ {
board->trucks[ fb ] = *sm0;
v3_copy( marker->transform.co, board->truck_positions[ fb ] );
}
}
- mdl_close( &board->mdl );
+ vg_model_stream_close( &ctx );
}
void player_board_unload( struct player_board *board )
{
- THREAD_0;
- mdl_sync_std_unload( &board->mdl );
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ vg_model_unload_gpu( &board->model );
}
-void player_model_load( player_model *pm, const char *path, void *arena )
+void player_model_load( player_model *pm, const c8 *path, vg_stack_allocator *stack )
{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
pm->flags = 0x0;
- mdl_open( &pm->mdl, path, arena );
- mdl_load_metadata_block( &pm->mdl, arena );
- AF_LOAD_ARRAY_STRUCT( &pm->mdl.af, &pm->editer_property, editer_property, arena );
- AF_LOAD_ARRAY_STRUCT( &pm->mdl.af, &pm->editer_item, editer_item, arena );
+ vg_model_stream_context ctx;
+ VG_ASSERT( vg_model_stream_open( &ctx, &pm->model, path ) );
+ vg_model_stream_metadata( &ctx, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &pm->editer_property, editer_property, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &pm->editer_item, editer_item, stack );
if( af_arrcount( &pm->editer_item ) )
pm->flags |= PLAYER_MODEL_FLAG_CUSTOMIZABLE;
- VG_ASSERT( pm->mdl.armature_count );
- mdl_armature *armature = &pm->mdl.armatures[ 0 ];
+ VG_ASSERT( pm->model.armature_count );
+ mdl_armature *armature = &pm->model.armatures[ 0 ];
u32 fixup_table[ armature->bone_count+1 ];
for( u32 i=0; i<armature->bone_count+1; i ++ )
for( u32 i=1; i<localplayer.skeleton.bone_count; i ++ )
{
- struct skeleton_bone *sb = &localplayer.skeleton.bones[i];
+ ms_skeleton_bone *sb = &localplayer.skeleton.bones[i];
u32 hash = vg_strdjb2( sb->name );
bool found = 0;
for( u32 j=1; j<armature->bone_count; j ++ )
{
- mdl_bone *bone = &pm->mdl.bones[ armature->bone_start+j ];
+ mdl_bone *bone = &pm->model.bones[ armature->bone_start+j ];
- if( af_str_eq( &pm->mdl.af, bone->pstr_name, sb->name, hash ) )
+ if( af_str_eq( pm->model.packed_strings, bone->pstr_name, sb->name, hash ) )
{
fixup_table[j+1] = i;
found = 1;
vg_low( "Reference skeleton has a bone called '%s', retargetee has no such bone..\n", sb->name );
}
- mdl_async_full_load_std( &pm->mdl, fixup_table );
- mdl_close( &pm->mdl );
+ vg_model_stream_meshes_gpu( &ctx, fixup_table );
+ vg_model_stream_close( &ctx );
}
void player_model_unload( player_model *pm )
{
- THREAD_0;
- mdl_sync_std_unload( &pm->mdl );
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ vg_model_unload_gpu( &pm->model );
}
-void apply_full_skeleton_pose( struct skeleton *sk, player_pose *pose,
- m4x3f *final_mtx ){
+void apply_full_skeleton_pose( ms_skeleton *sk, player_pose *pose, m4x3f *final_mtx )
+{
m4x3f transform;
q_m3x3( pose->root_q, transform );
v3_copy( pose->root_co, transform[3] );
- if( pose->type == k_player_pose_type_ik ){
- skeleton_apply_pose( sk, pose->keyframes,
- k_anim_apply_defer_ik, final_mtx );
+ if( pose->type == k_player_pose_type_ik )
+ {
+ skeleton_apply_pose( sk, pose->keyframes, k_anim_apply_defer_ik, final_mtx );
skeleton_apply_ik_pass( sk, final_mtx );
- skeleton_apply_pose( sk, pose->keyframes,
- k_anim_apply_deffered_only, final_mtx );
+ skeleton_apply_pose( sk, pose->keyframes, k_anim_apply_deffered_only, final_mtx );
skeleton_apply_inverses( sk, final_mtx );
skeleton_apply_transform( sk, transform, final_mtx );
}
- else if( pose->type == k_player_pose_type_fk_2 ){
- skeleton_apply_pose( sk, pose->keyframes,
- k_anim_apply_always, final_mtx );
+ else if( pose->type == k_player_pose_type_fk_2 )
+ {
+ skeleton_apply_pose( sk, pose->keyframes, k_anim_apply_always, final_mtx );
skeleton_apply_inverses( sk, final_mtx );
skeleton_apply_transform( sk, transform, final_mtx );
}
player_pose *pose = &localplayer.pose;
sys->pose( sys->animator_data, pose );
- struct skeleton *sk = &localplayer.skeleton;
+ ms_skeleton *sk = &localplayer.skeleton;
if( localplayer.holdout_time > 0.0f )
{
void lerp_player_pose( player_pose *pose0, player_pose *pose1, f32 t, player_pose *posed )
{
- struct skeleton *sk = &localplayer.skeleton;
+ ms_skeleton *sk = &localplayer.skeleton;
v3_lerp( pose0->root_co, pose1->root_co, t, posed->root_co );
q_nlerp( pose0->root_q, pose1->root_q, t, posed->root_q );
v3_zero( vp1 );
}
- struct ub_world_lighting *ubo = &_world.main.ub_lighting;
+ struct ub_world_lighting *ubo = &world_render.ub_lighting;
v3f *board_mtx = localplayer.final_mtx[ localplayer.id_board ];
m4x3_mulv( board_mtx, vp0, ubo->g_board_0 );
m4x3_mulv( board_mtx, vp1, ubo->g_board_1 );
void render_board( vg_camera *cam, world_instance *world,
struct player_board *board, m4x3f root,
struct player_board_pose *pose,
- enum board_shader shader )
+enum board_shader shader )
{
if( !board )
board = &localplayer.fallback_board;
*/
v3f inverse;
-
- VG_ASSERT( board->mdl.texture_count );
-
- glActiveTexture( GL_TEXTURE0 );
- glBindTexture( GL_TEXTURE_2D, board->mdl.textures[0].glname );
+ VG_ASSERT( board->model.texture_count );
+ vg_tex_bind( GL_TEXTURE_2D, &board->model.textures[0].tex, 0 );
if( shader == k_board_shader_player )
{
shader_model_board_view_uInverseRatioMain,
cam );
- WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, model_board_view );
+ WORLD_LINK_LIGHTING( world, model_board_view );
}
else if( shader == k_board_shader_entity )
{
shader_model_entity_uCamera( cam->transform[3] );
shader_model_entity_uPv( cam->mtx.pv );
- WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, model_entity );
+ WORLD_LINK_LIGHTING( world, model_entity );
}
- mesh_bind( &board->mdl.mesh );
-
+ vg_model_bind_mesh( &board->model );
m4x4f m4mdl;
if( board->board.indice_count )
}
else
shader_model_board_view_uMdl( mlocal );
-
- mdl_draw_submesh( &board->board );
+ vg_model_draw_submesh( &board->board );
}
for( int i=0; i<2; i++ ){
v3_copy( board->truck_positions[i], mlocal[3] );
m4x3_mul( root, mlocal, mlocal );
- if( shader == k_board_shader_entity ){
+ if( shader == k_board_shader_entity )
+ {
m4x3_expand( mlocal, m4mdl );
m4x4_mul( cam->mtx_prev.pv, m4mdl, m4mdl );
shader_model_entity_uPvmPrev( m4mdl );
else
shader_model_board_view_uMdl( mlocal );
- mdl_draw_submesh( &board->trucks[i] );
+ vg_model_draw_submesh( &board->trucks[i] );
}
for( int i=0; i<4; i++ ){
v3_copy( board->wheel_positions[i], mlocal[3] );
m4x3_mul( root, mlocal, mlocal );
- if( shader == k_board_shader_entity ){
+ if( shader == k_board_shader_entity )
+ {
m4x3_expand( mlocal, m4mdl );
m4x4_mul( cam->mtx_prev.pv, m4mdl, m4mdl );
shader_model_entity_uPvmPrev( m4mdl );
else
shader_model_board_view_uMdl( mlocal );
- mdl_draw_submesh( &board->wheels[i] );
+ vg_model_draw_submesh( &board->wheels[i] );
}
}
void render_playermodel( vg_camera *cam, world_instance *world,
int depth_compare,
player_model_view *view,
- struct skeleton *skeleton,
+ ms_skeleton *skeleton,
m4x3f *final_mtx )
{
bool fallback = 0;
shader_model_character_view_use();
- glActiveTexture( GL_TEXTURE0 );
- VG_ASSERT( model->mdl.texture_count );
- glBindTexture( GL_TEXTURE_2D, model->mdl.textures[0].glname );
+ VG_ASSERT( model->model.texture_count );
+ vg_tex_bind( GL_TEXTURE_2D, &model->model.textures[0].tex, 0 );
shader_model_character_view_uTexMain( 0 );
shader_model_character_view_uCamera( cam->transform[3] );
cam );
}
- WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, model_character_view );
-
- glUniformMatrix4x3fv( _uniform_model_character_view_uTransforms,
- skeleton->bone_count,
- 0,
- (const GLfloat *)final_mtx );
+ WORLD_LINK_LIGHTING( world, model_character_view );
+ shader_model_character_view_uTransforms( final_mtx, skeleton->bone_count );
- mesh_bind( &model->mdl.mesh );
-
+ vg_model_bind_mesh( &model->model );
if( !fallback && (model->flags & PLAYER_MODEL_FLAG_CUSTOMIZABLE) )
{
if( view->cpart_dirty )
if( (0x1 << j) & item->discard_mask & view->discard )
continue;
- mdl_submesh *sm = &model->mdl.submeshes[ item->submesh_start + j ];
- mdl_draw_submesh( sm );
+ mdl_submesh *sm = &model->model.submeshes[ item->submesh_start + j ];
+ vg_model_draw_submesh( sm );
}
}
}
else
- mesh_draw( &model->mdl.mesh );
+ {
+ for( u32 i=0; i<model->model.mesh_count; i ++ )
+ {
+ mdl_mesh *mesh = &model->model.meshes[ i ];
+ for( u32 j=0; j<mesh->submesh_count; j ++ )
+ {
+ mdl_submesh *sm = &model->model.submeshes[ mesh->submesh_start+j ];
+ vg_model_draw_submesh( sm );
+ }
+ }
+ }
}
void player__render( vg_camera *cam )
if( localplayer.has_battery )
{
ms_keyframe kf_backpack;
- struct skeleton *sk = &localplayer.skeleton;
+ ms_skeleton *sk = &localplayer.skeleton;
m4x3_mulv( localplayer.final_mtx[localplayer.id_chest ], sk->bones[localplayer.id_chest].co, kf_backpack.co );
v4f qyaw, qpitch, qchest, q;
void player_mirror_pose( ms_keyframe pose[32], ms_keyframe mirrored[32] )
{
ms_keyframe temp[32];
-
- struct skeleton *sk = &localplayer.skeleton;
+ ms_skeleton *sk = &localplayer.skeleton;
for( u32 i=1; i<sk->bone_count; i ++ )
{
ms_keyframe *dest = &temp[i-1];
view->property_values[i]._f32 = ((f32)(c - (u8)'A') / (f32)((u8)'Z' - (u8)'A')) * prop->max._f32;
else if( prop->ui_type == k_editer_type_selecter )
{
- const char *options = af_str( &model->mdl.af, prop->max.pstr_options );
+ const char *options = af_str( model->model.packed_strings, prop->max.pstr_options );
bool valid = 0;
for( u32 j=0; options[j]; j ++ )
{
for( u32 i=0; i<af_arrcount( &model->editer_item ); i ++ )
{
editer_item *item = af_arritm( &model->editer_item, i );
- const char *visibility_string = af_str( &model->mdl.af, item->pstr_visibility );
+ const char *visibility_string = af_str( model->model.packed_strings, item->pstr_visibility );
bool visible = 1;
u32 hash;
if( prop->ui_type == k_editer_type_slider )
continue;
- if( af_str_hash( &model->mdl.af, prop->pstr_alias ) == hash )
+ if( af_str_hash( model->model.packed_strings, prop->pstr_alias ) == hash )
{
- const char *alias = af_str( &model->mdl.af, prop->pstr_alias );
+ const c8 *alias = af_str( model->model.packed_strings, prop->pstr_alias );
bool matched = 1;
for( u32 l=0; l < (j-token_j); l ++ )
{
-#pragma once
-#include "model.h"
-#include "skeleton.h"
-#include "vg/vg_camera.h"
-#include "world.h"
-#include "player_render.h"
-#include "player_api.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/player_render.c"
+#else
enum eboard_truck{
k_board_truck_back = 0,
typedef struct player_board player_board;
struct player_board
{
- mdl_context mdl;
-
+ vg_model model;
v4f wheel_positions[4],
truck_positions[2],
board_position;
typedef struct player_model player_model;
struct player_model
{
- mdl_context mdl;
+ vg_model model;
u32 flags;
array_file_ptr editer_property, editer_item;
u32 list_id_heads;
k_board_shader_entity
};
-void player_board_load( player_board *board, const char *path, void *arena );
+VG_API void _player_render_init(void);
+
+void player_board_load( player_board *board, const c8 *path, vg_stack_allocator *stack );
void player_board_unload( player_board *mdl );
-void player_model_load( player_model *pm, const char *path, void *arena );
+void player_model_load( player_model *pm, const c8 *path, vg_stack_allocator *stack );
void player_model_unload( player_model *pm );
void render_board( vg_camera *cam, world_instance *world,
void render_playermodel( vg_camera *cam, world_instance *world,
int depth_compare,
player_model_view *playermodel,
- struct skeleton *skeleton,
+ ms_skeleton *skeleton,
m4x3f *final_mtx );
-void apply_full_skeleton_pose( struct skeleton *sk, player_pose *pose, m4x3f *final_mtx );
+void apply_full_skeleton_pose( ms_skeleton *sk, player_pose *pose, m4x3f *final_mtx );
void lerp_player_pose( player_pose *pose0, player_pose *pose1, f32 t, player_pose *posed );
void player_mirror_pose( ms_keyframe pose[32], ms_keyframe mirrored[32] );
void player__observe_system( enum player_subsystem id );
void playermodel_use_cpart( player_model_view *model, const char cpart[ ADDON_CPART_MAX ] );
void playermodel_create_binary_configuration( player_model_view *view, struct player_model *model );
void playermodel_set_from_uid( player_model_view *model, const char uid[ ADDON_UID_MAX ] );
+
+#endif
-#include "player_skate.h"
-#include "player.h"
-#include "audio.h"
-#include "vg/vg_perlin.h"
-#include "vg/vg_lines.h"
-#include "menu.h"
-#include "ent_skateshop.h"
-#include "addon.h"
-#include "input.h"
-#include "ent_tornado.h"
-
-#include "vg/vg_rigidbody.h"
-#include "scene_rigidbody.h"
-#include "player_glide.h"
-#include "player_dead.h"
-#include "player_walk.h"
-#include <string.h>
-
struct player_skate player_skate;
struct player_subsystem_interface player_subsystem_skate =
{
.system_register = player__skate_register,
- .bind = player__skate_bind,
+ .load_resources = player__skate_load_resources,
.pre_update = player__skate_pre_update,
.update = player__skate_update,
.transport = player__skate_transport,
.name = "Skate"
};
-void player__skate_bind(void){
- struct skeleton *sk = &localplayer.skeleton;
- rb_update_matrices( &localplayer.rb );
-
- struct { struct skeleton_anim *anim; const char *name; }
- bindings[] = {
+void player__skate_load_resources(void)
+{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+ ms_skeleton *sk = &localplayer.skeleton;
+ struct { ms_skeletal_animation *anim; const char *name; }
+ bindings[] =
+ {
{ &player_skate.anim_grind, "pose_grind" },
{ &player_skate.anim_grind_jump, "pose_grind_jump" },
{ &player_skate.anim_stand, "pose_stand" },
player_get_anim( bindings[i].anim, bindings[i].name );
}
+void player__skate_init(void)
+{
+ rb_update_matrices( &localplayer.rb );
+}
+
void player__skate_kill_audio(void)
{
vg_audio_lock();
world_instance *world = &_world.main;
int len = 0;
- len = rb_sphere__scene( mtx, r, NULL, world->geo_bh, man,
- k_material_flag_walking );
-
- for( int i=0; i<len; i++ ){
+ len = rb_sphere__scene( mtx, r, NULL, &world->geometry_bh, man, k_material_flag_walking );
+ for( int i=0; i<len; i++ )
+ {
man[i].rba = &localplayer.rb;
man[i].rbb = NULL;
}
rb_manifold_filter_coplanar( man, len, 0.03f );
-
- if( len > 1 ){
+ if( len > 1 )
+ {
rb_manifold_filter_backface( man, len );
rb_manifold_filter_joint_edges( man, len, 0.03f );
rb_manifold_filter_pairs( man, len, 0.03f );
bh_iter_init_box( 0, &it, box );
i32 idx;
- while( bh_next( world->geo_bh, &it, &idx ) ){
- u32 *ptri = &world->scene_geo.arrindices[ idx*3 ];
+ while( bh_next( &world->geometry_bh, &it, &idx ) )
+ {
+ u32 *ptri = &world->scene_geometry.indice_buffer[ idx*3 ];
v3f tri[3];
struct world_surface *surf = world_tri_index_surface(world,ptri[0]);
continue;
for( int j=0; j<3; j++ )
- v3_copy( world->scene_geo.arrvertices[ptri[j]].co, tri[j] );
+ v3_copy( world->scene_geometry.vertex_buffer[ptri[j]].co, tri[j] );
for( int j=0; j<3; j++ ){
int i0 = j,
v3f closest={0.0f,0.0f,0.0f};
if( search_for_grind )
{
- if( bh_closest_point(trace_world->geo_bh,co1,closest,1.0f) != -1 )
+ if( bh_closest_point( &trace_world->geometry_bh,co1,closest,1.0f ) != -1 )
{
float min_dist = 0.75f;
min_dist *= min_dist;
v3_copy( co, inf->log[ inf->log_length ++ ] );
v3_copy( n, inf->n );
- u32 *tri = &trace_world->scene_geo.arrindices[ idx*3 ];
+ u32 *tri = &trace_world->scene_geometry.indice_buffer[ idx*3 ];
struct world_surface *surf =
world_tri_index_surface( trace_world, tri[0] );
(button_press( k_srbind_trick2 ) );
}
-void player__skate_pre_update(void){
+void player__skate_pre_update(void)
+{
struct player_skate_state *state = &player_skate.state;
- if( state->activity == k_skate_activity_handplant ){
+ if( state->activity == k_skate_activity_handplant )
+ {
state->handplant_t += vg.time_delta;
ms_keyframe hpose[32];
- struct skeleton_anim *anim = &player_skate.anim_handplant;
+ ms_skeletal_animation *anim = &player_skate.anim_handplant;
- int end = !skeleton_sample_anim_clamped(
- &localplayer.skeleton, anim,
- state->handplant_t, hpose );
+ int end = !skeleton_sample_anim_clamped( &localplayer.skeleton, anim, state->handplant_t, hpose );
if( state->reverse < 0.0f )
player_mirror_pose( hpose, hpose );
else{
/* fallback: use the closes point to the trucks */
v3f closest;
- int idx = bh_closest_point( world->geo_bh, midpoint, closest, 0.1f );
-
- if( idx != -1 ){
- u32 *tri = &world->scene_geo.arrindices[ idx * 3 ];
+ int idx = bh_closest_point( &world->geometry_bh, midpoint, closest, 0.1f );
+ if( idx != -1 )
+ {
+ u32 *tri = &world->scene_geometry.indice_buffer[ idx * 3 ];
v3f verts[3];
for( int j=0; j<3; j++ )
- v3_copy( world->scene_geo.arrvertices[ tri[j] ].co, verts[j] );
+ v3_copy( world->scene_geometry.vertex_buffer[ tri[j] ].co, verts[j] );
v3f vert0, vert1, n;
v3_sub( verts[1], verts[0], vert0 );
return 0;
v3_cross( n, localplayer.rb.to_world[2], v0 );
- v3_muladds( v0, localplayer.rb.to_world[2],
- -v3_dot( localplayer.rb.to_world[2], v0 ), v0 );
+ v3_muladds( v0, localplayer.rb.to_world[2], -v3_dot( localplayer.rb.to_world[2], v0 ), v0 );
v3_normalize( v0 );
v3f t;
float slap = 0.0f;
- if( state->activity <= k_skate_activity_air_to_grind ){
+ if( state->activity <= k_skate_activity_air_to_grind )
+ {
float min_dist = 0.6f;
- for( int i=0; i<2; i++ ){
+ for( int i=0; i<2; i++ )
+ {
v3f wpos, closest;
m4x3_mulv( localplayer.rb.to_world, wheels[i].pos, wpos );
- if( bh_closest_point( world->geo_bh, wpos, closest, min_dist ) != -1 ){
+ if( bh_closest_point( &world->geometry_bh, wpos, closest, min_dist ) != -1 )
min_dist = vg_minf( min_dist, v3_dist( closest, wpos ) );
- }
}
min_dist -= 0.2f;
float vy = vg_maxf( 0.0f, localplayer.rb.v[1] );
/* board capsule */
rb_ct *cman = &manifold[manifold_len];
- int l = rb_capsule__scene( mtx, &capsule, NULL, world->geo_bh, cman, k_material_flag_walking );
+ int l = rb_capsule__scene( mtx, &capsule, NULL, &world->geometry_bh, cman, k_material_flag_walking );
/* weld joints */
for( int i=0; i<l; i ++ )
cman[l].type = k_contact_type_edge;
animator->handplant_t = state->handplant_t;
}
-void player__skate_pose( void *_animator, player_pose *pose ){
- struct skeleton *sk = &localplayer.skeleton;
+void player__skate_pose( void *_animator, player_pose *pose )
+{
+ ms_skeleton *sk = &localplayer.skeleton;
struct player_skate_animator *animator = _animator;
pose->type = k_player_pose_type_ik;
skeleton_lerp_pose( sk, bpose, mirrored, animator->z, bpose );
skeleton_lerp_pose( sk, apose, bpose, animator->slide, apose );
- if( animator->reverse > 0.0f ){
- skeleton_sample_anim( sk, &player_skate.anim_push, animator->push_time,
- bpose );
- }
- else{
- skeleton_sample_anim( sk, &player_skate.anim_push_reverse,
- animator->push_time, bpose );
- }
+ if( animator->reverse > 0.0f )
+ skeleton_sample_anim( sk, &player_skate.anim_push, animator->push_time, bpose );
+ else
+ skeleton_sample_anim( sk, &player_skate.anim_push_reverse, animator->push_time, bpose );
skeleton_lerp_pose( sk, apose, bpose, animator->push, apose );
- struct skeleton_anim *jump_anim = animator->jump_dir?
- &player_skate.anim_ollie:
- &player_skate.anim_ollie_reverse;
+ ms_skeletal_animation *jump_anim = animator->jump_dir?
+ &player_skate.anim_ollie:
+ &player_skate.anim_ollie_reverse;
f32 setup_blend = vg_minf( animator->jump, 1.0f );
skeleton_sample_anim_clamped( sk, jump_anim, animator->jump_time, bpose );
if( animator->activity == k_skate_activity_handplant )
{
- struct skeleton_anim *anim = &player_skate.anim_handplant;
+ ms_skeletal_animation *anim = &player_skate.anim_handplant;
ms_keyframe hpose[32];
skeleton_sample_anim_clamped( sk, anim, animator->handplant_t, hpose );
struct player_board *board,
struct player_effects_data *effect_data )
{
- struct skeleton *sk = &localplayer.skeleton;
+ ms_skeleton *sk = &localplayer.skeleton;
struct player_skate_animator *animator = _animator;
v3f vp0, vp1, vpc;
-#pragma once
-#include "vg/vg_audio.h"
-#include "player.h"
-#include "player_api.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/player_skate.c"
+#else
typedef struct jump_info jump_info;
/* animation /audio
* --------------------------------------------------------------*/
- struct skeleton_anim anim_stand, anim_highg, anim_slide,
- anim_air, anim_grind, anim_grind_jump,
- anim_push, anim_push_reverse,
- anim_ollie, anim_ollie_reverse,
- anim_grabs, anim_stop,
- anim_handplant;
+ ms_skeletal_animation anim_stand, anim_highg, anim_slide,
+ anim_air, anim_grind, anim_grind_jump,
+ anim_push, anim_push_reverse,
+ anim_ollie, anim_ollie_reverse,
+ anim_grabs, anim_stop,
+ anim_handplant;
/* vectors representing the direction of the axels in localspace */
v3f truckv0[2];
VG_VAR_F32( k_anim_transition, flags=VG_VAR_CHEAT );
}
-void player__skate_bind (void);
+void player__skate_load_resources(void);
void player__skate_pre_update (void);
void player__skate_update (void);
void player__skate_transport( m4x3f transport );
void player__approximate_best_trajectory(void);
void player__skate_comp_audio( void *animator );
void player__skate_kill_audio(void);
+
+#endif
-#include "vg/vg_rigidbody_collision.h"
-
-#include "skaterift.h"
-#include "player_walk.h"
-#include "player_skate.h"
-#include "player_dead.h"
-#include "player.h"
-#include "input.h"
-#include "audio.h"
-#include "scene_rigidbody.h"
-
struct player_walk player_walk;
struct player_subsystem_interface player_subsystem_walk =
{
.system_register = player__walk_register,
- .bind = player__walk_bind,
+ .load_resources = player__walk_load_resources,
.pre_update = player__walk_pre_update,
.update = player__walk_update,
.transport = player__walk_transport,
return 0;
}
-static bool player__preupdate_anim( struct skeleton_anim *anim, f32 *t, f32 speed )
+static bool player__preupdate_anim( ms_skeletal_animation *anim, f32 *t, f32 speed )
{
f32 length = (f32)(anim->strip->strip.length-1) / anim->framerate;
*t += (vg.time_delta * speed) / length;
* Collision detection
*/
- len = rb_capsule__scene( mtx, &w->collider, NULL, world->geo_bh, manifold, 0 );
+ len = rb_capsule__scene( mtx, &w->collider, NULL, &world->geometry_bh, manifold, 0 );
for( u32 i=0; i<af_arrcount( &world->ent_prop ); i ++ )
{
{
struct player_walk *w = &player_walk;
struct player_walk_animator *animator = &w->animator;
- struct skeleton_anim *anim = &w->anim_drop_in;
+ ms_skeletal_animation *anim = &w->anim_drop_in;
f32 length = (f32)(anim->strip->strip.length-1) / anim->framerate,
time = w->state.transition_t;
ms_keyframe bpose[32];
struct player_walk *w = &player_walk;
- struct skeleton *sk = &localplayer.skeleton;
+ ms_skeleton *sk = &localplayer.skeleton;
f32 t = animator->transition_t,
st = t * ((f32)(w->anim_sit.strip->strip.length-1)/30.0f);
};
static void player_walk_pose_transition(
- struct player_walk_animator *animator, struct skeleton_anim *anim,
+ struct player_walk_animator *animator, ms_skeletal_animation *anim,
enum walk_transition_type type,
ms_keyframe apose[32], f32 *mask, player_pose *pose ){
ms_keyframe bpose[32];
struct player_walk *w = &player_walk;
- struct skeleton *sk = &localplayer.skeleton;
+ ms_skeleton *sk = &localplayer.skeleton;
f32 length = (f32)(anim->strip->strip.length-1) / anim->framerate,
t = animator->transition_t * length,
void player__walk_pose( void *_animator, player_pose *pose ){
struct player_walk *w = &player_walk;
struct player_walk_animator *animator = _animator;
- struct skeleton *sk = &localplayer.skeleton;
+ ms_skeleton *sk = &localplayer.skeleton;
v3_copy( animator->root_co, pose->root_co );
v4_copy( animator->root_q, pose->root_q );
[w->surface] );
}
-void player__walk_bind(void)
+void player__walk_load_resources(void)
{
struct player_walk *w = &player_walk;
- struct skeleton *sk = &localplayer.skeleton;
+ ms_skeleton *sk = &localplayer.skeleton;
player_get_anim( &w->anim_idle, "idle_cycle+y" );
player_get_anim( &w->anim_walk, "walk+y" );
-#pragma once
-#include "player.h"
-#include "player_api.h"
-#include "vg/vg_rigidbody.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/player_walk.c"
+#else
#define PLAYER_JUMP_EPSILON 0.1 /* 100ms jump allowance */
f32 move_speed;
enum mdl_surface_prop surface;
- struct skeleton_anim anim_walk, anim_run, anim_idle, anim_jump,
- anim_jump_to_air, anim_drop_in, anim_intro,
- anim_sit, anim_popoff;
+ ms_skeletal_animation anim_walk, anim_run, anim_idle, anim_jump,
+ anim_jump_to_air, anim_drop_in, anim_intro,
+ anim_sit, anim_popoff;
struct player_walk_animator {
v3f root_co;
void player__walk_pose (void *animator, player_pose *pose);
void player__walk_post_animate(void);
void player__walk_im_gui ( ui_context *ctx );
-void player__walk_bind (void);
+void player__walk_load_resources(void);
void player__walk_reset (void);
void player__walk_restore (void);
void player__walk_animator_exchange( bitpack_ctx *ctx, void *data );
void player__walk_transition( bool grounded, f32 board_yaw );
void player__walk_sfx_oneshot( u8 id, v3f pos, f32 volume );
void player__walk_upright(void);
+
+#endif
-#include "render.h"
-#include "vg/vg_engine.h"
-#include "vg/vg_platform.h"
-#include "vg/vg_framebuffer.h"
-
-static void async_render_init( void *userdata )
-{
- THREAD_0;
- f32 rh = 0x1p-4f, ih = 0.3f;
-
- float quad[] = {
- 0.00f,0.00f, 1.00f,1.00f, 0.00f,1.00f, /* fsquad */
- 0.00f,0.00f, 1.00f,0.00f, 1.00f,1.00f,
-
- 0.00f,0.00f, 1.00f,rh, 0.00f,rh, /* fsquad1 */
- 0.00f,0.00f, 1.00f,0.00f, 1.00f,rh,
- 0.00f,1.00f, 0.00f,1.0f-rh,1.00f,1.0f-rh,
- 0.00f,1.00f, 1.00f,1.0f-rh,1.00f,1.0f,
-
- /* 9x9 debug grid */
- /* row0 */
- 0.00f,0.00f, 0.30f,0.30f, 0.00f,0.30f,
- 0.00f,0.00f, 0.30f,0.00f, 0.30f,0.30f,
- 0.30f,0.00f, 0.60f,0.30f, 0.30f,0.30f,
- 0.30f,0.00f, 0.60f,0.00f, 0.60f,0.30f,
- 0.60f,0.00f, 0.90f,0.30f, 0.60f,0.30f,
- 0.60f,0.00f, 0.90f,0.00f, 0.90f,0.30f,
- /* row1 */
- 0.00f,0.30f, 0.30f,0.60f, 0.00f,0.60f,
- 0.00f,0.30f, 0.30f,0.30f, 0.30f,0.60f,
- 0.30f,0.30f, 0.60f,0.60f, 0.30f,0.60f,
- 0.30f,0.30f, 0.60f,0.30f, 0.60f,0.60f,
- 0.60f,0.30f, 0.90f,0.60f, 0.60f,0.60f,
- 0.60f,0.30f, 0.90f,0.30f, 0.90f,0.60f,
- /* row2 */
- 0.00f,0.60f, 0.30f,0.90f, 0.00f,0.90f,
- 0.00f,0.60f, 0.30f,0.60f, 0.30f,0.90f,
- 0.30f,0.60f, 0.60f,0.90f, 0.30f,0.90f,
- 0.30f,0.60f, 0.60f,0.60f, 0.60f,0.90f,
- 0.60f,0.60f, 0.90f,0.90f, 0.60f,0.90f,
- 0.60f,0.60f, 0.90f,0.60f, 0.90f,0.90f,
-
- 0.00f,ih, 1.00f,ih+rh, 0.00f,ih+rh, /* fsquad2 */
- 0.00f,ih, 1.00f,ih, 1.00f,ih+rh,
- };
-
- glGenVertexArrays( 1, &g_render.fsquad.vao );
- glGenBuffers( 1, &g_render.fsquad.vbo );
- glBindVertexArray( g_render.fsquad.vao );
- glBindBuffer( GL_ARRAY_BUFFER, g_render.fsquad.vbo );
- glBufferData( GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW );
- glBindVertexArray( g_render.fsquad.vao );
- glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE,
- sizeof(float)*2, (void*)0 );
- glEnableVertexAttribArray( 0 );
-
- glBindFramebuffer( GL_FRAMEBUFFER, 0 );
- g_render.ready = 1;
-}
-
-void render_register(void)
+VG_API void _render_register(void)
{
vg_console_reg_var( "fov", &k_fov, k_var_dtype_f32, VG_VAR_PERSISTENT );
vg_console_reg_var( "cam_height", &k_cam_height, k_var_dtype_f32, VG_VAR_PERSISTENT );
}
-void render_init(void)
+VG_API void _render_init(void)
{
- THREAD_1;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
/*
* Workshop preview
*/
- g_render.fb_workshop_preview = vg_framebuffer_allocate( &vg.rtmem, 2, 1 );
+ g_render.fb_workshop_preview = _vg_framebuffer_alloc( NULL, 2, 1 );
g_render.fb_workshop_preview->display_name = "workshop_preview";
g_render.fb_workshop_preview->resolution_div = 0;
g_render.fb_workshop_preview->fixed_w = WORKSHOP_PREVIEW_WIDTH;
.internalformat = GL_DEPTH24_STENCIL8,
.attachment = GL_DEPTH_STENCIL_ATTACHMENT
};
- vg_framebuffer_create( g_render.fb_workshop_preview );
+ vg_framebuffer_init( g_render.fb_workshop_preview );
/*
* Network status
*/
- g_render.fb_network_status = vg_framebuffer_allocate( &vg.rtmem, 1, 1 );
+ g_render.fb_network_status = _vg_framebuffer_alloc( VG_STACK_USE_HEAP, 1, 1 );
g_render.fb_network_status->display_name = "network_status_ui";
g_render.fb_network_status->resolution_div = 0;
g_render.fb_network_status->fixed_w = 128;
.type = GL_UNSIGNED_BYTE,
.attachment = GL_COLOR_ATTACHMENT0
};
- vg_framebuffer_create( g_render.fb_network_status );
+ vg_framebuffer_init( g_render.fb_network_status );
- g_render.fb_compass = vg_framebuffer_allocate( &vg.rtmem, 1, 1 );
+ g_render.fb_compass = _vg_framebuffer_alloc( VG_STACK_USE_HEAP, 1, 1 );
g_render.fb_compass->display_name = "compass";
g_render.fb_compass->resolution_div = 0;
g_render.fb_compass->fixed_w = 800;
.type = GL_UNSIGNED_BYTE,
.attachment = GL_COLOR_ATTACHMENT0
};
- vg_framebuffer_create( g_render.fb_compass );
+ vg_framebuffer_init( g_render.fb_compass );
+
+ f32 rh = 0x1p-4f, ih = 0.3f;
+
+ /* TODO: Is this duplicated with vg_render? */
+ f32 quad[] =
+ {
+ 0.00f,0.00f, 1.00f,1.00f, 0.00f,1.00f, /* fsquad */
+ 0.00f,0.00f, 1.00f,0.00f, 1.00f,1.00f,
+
+ 0.00f,0.00f, 1.00f,rh, 0.00f,rh, /* fsquad1 */
+ 0.00f,0.00f, 1.00f,0.00f, 1.00f,rh,
+ 0.00f,1.00f, 0.00f,1.0f-rh,1.00f,1.0f-rh,
+ 0.00f,1.00f, 1.00f,1.0f-rh,1.00f,1.0f,
+
+ /* 9x9 debug grid */
+ /* row0 */
+ 0.00f,0.00f, 0.30f,0.30f, 0.00f,0.30f,
+ 0.00f,0.00f, 0.30f,0.00f, 0.30f,0.30f,
+ 0.30f,0.00f, 0.60f,0.30f, 0.30f,0.30f,
+ 0.30f,0.00f, 0.60f,0.00f, 0.60f,0.30f,
+ 0.60f,0.00f, 0.90f,0.30f, 0.60f,0.30f,
+ 0.60f,0.00f, 0.90f,0.00f, 0.90f,0.30f,
+ /* row1 */
+ 0.00f,0.30f, 0.30f,0.60f, 0.00f,0.60f,
+ 0.00f,0.30f, 0.30f,0.30f, 0.30f,0.60f,
+ 0.30f,0.30f, 0.60f,0.60f, 0.30f,0.60f,
+ 0.30f,0.30f, 0.60f,0.30f, 0.60f,0.60f,
+ 0.60f,0.30f, 0.90f,0.60f, 0.60f,0.60f,
+ 0.60f,0.30f, 0.90f,0.30f, 0.90f,0.60f,
+ /* row2 */
+ 0.00f,0.60f, 0.30f,0.90f, 0.00f,0.90f,
+ 0.00f,0.60f, 0.30f,0.60f, 0.30f,0.90f,
+ 0.30f,0.60f, 0.60f,0.90f, 0.30f,0.90f,
+ 0.30f,0.60f, 0.60f,0.60f, 0.60f,0.90f,
+ 0.60f,0.60f, 0.90f,0.90f, 0.60f,0.90f,
+ 0.60f,0.60f, 0.90f,0.60f, 0.90f,0.90f,
+
+ 0.00f,ih, 1.00f,ih+rh, 0.00f,ih+rh, /* fsquad2 */
+ 0.00f,ih, 1.00f,ih, 1.00f,ih+rh,
+ };
- vg_async_call( &vg.main_tasks, async_render_init, NULL );
+ glGenVertexArrays( 1, &g_render.fsq_vao );
+ glBindVertexArray( g_render.fsq_vao );
+ glGenBuffers( 1, &g_render.fsq_vbo );
+ glBindBuffer( GL_ARRAY_BUFFER, g_render.fsq_vbo );
+ glBufferData( GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW );
+ glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, sizeof(float)*2, (void*)0 );
+ glEnableVertexAttribArray( 0 );
+ glBindFramebuffer( GL_FRAMEBUFFER, 0 );
}
/*
- * Utility
+ * Utility (TODO: ARE THESE DUPED WITH VG CODE???????????????????????)
*/
void render_fsquad(void)
{
- glBindVertexArray( g_render.fsquad.vao );
+ glBindVertexArray( g_render.fsq_vao );
glDrawArrays( GL_TRIANGLES, 0, 6 );
}
void render_fsquad1(void)
{
- glBindVertexArray( g_render.fsquad.vao );
+ glBindVertexArray( g_render.fsq_vao );
glDrawArrays( GL_TRIANGLES, 6, 6+6 );
}
void render_fsquad2(void)
{
- glBindVertexArray( g_render.fsquad.vao );
+ glBindVertexArray( g_render.fsq_vao );
glDrawArrays( GL_TRIANGLES, 66+6,6 );
}
-/*
- * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-#pragma once
-#include "common.h"
-#include "model.h"
-#include "shader_props.h"
-#include "vg/vg_framebuffer.h"
-#include "vg/vg_camera.h"
-
-#include "shaders/blitblur.h"
-#include "shaders/blitcolour.h"
-#include "shaders/blit_transition.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/render.c"
+#else
#define WORKSHOP_PREVIEW_WIDTH 504
#define WORKSHOP_PREVIEW_HEIGHT 336
*/
struct pipeline
{
- glmesh fsquad;
+ GLuint fsq_vao, fsq_vbo;
vg_framebuffer *fb_workshop_preview,
*fb_network_status,
*fb_compass;
- int ready;
-
v2f blur_override;
vg_camera cam;
}
static g_render;
-void render_register(void);
-void render_init(void);
+void _render_register(void);
+VG_API void _render_init(void);
+
void render_fsquad(void);
void render_fsquad1(void);
void render_fsquad2(void);
void postprocess_to_screen( vg_framebuffer *fb );
+
+#endif
-#include "replay2.h"
+struct _replay2
+{
+ enum replay_type type;
+
+ vg_queue buffer;
+
+ /* TODO: Modifiers / keyframes lane */
+
+ u32 cursor_frame_offset;
+ f64 cursor;
+ enum replay_control {
+ k_replay_control_scrub = 0x00,
+ k_replay_control_play = 0x01,
+ k_replay_control_resume= 0x02
+ }
+ replay_control;
+ f32 track_velocity;
+
+ bool cursor_decoded;
+
+ struct net_sfx sfx_queue[ 8 ];
+ u32 sfx_queue_length;
+ f64 sfx_basetime;
+
+ vg_camera replay_freecam, playback_cam;
+ bool use_freecam;
+ bool hide_ui;
+ v3f freecam_v, freecam_w;
+
+ f64 start_t, end_t;
+ bool highlight;
+ f64 highlight_start, highlight_length;
+
+ bool animation_dirty;
+ addon_cache_id board_cache_id;
+ player_model_view playermodel;
+
+ struct player_effects_data effect_data;
+ bool render_glider;
+ m4x3f *final_mtx, glider_mtx;
+ struct player_board_pose board_pose;
+}
+_replay2;
+
+f32 _replay2_playback_velocity(void)
+{
+ return _replay2.track_velocity;
+}
+
+struct _remote_replay
+{
+ u32 total_chunks,
+ chunks_downloaded;
+
+ u64 steamid;
+ struct remote_replay_chunk
+ {
+ u32 minute;
+ enum chunk_state
+ {
+ k_chunk_state_none,
+ k_chunk_state_cache_check,
+ k_chunk_state_downloading,
+ k_chunk_state_processed,
+ k_chunk_state_broken
+ }
+ state;
+ }
+ chunks[8];
+ f64 min_frame_t;
+
+ enum remote_replay_state
+ {
+ k_remote_replay_state_none,
+
+ k_remote_replay_state_init,
+ k_remote_replay_state_getinfo,
+
+ k_remote_replay_state_waitnext,
+ k_remote_replay_state_downloading,
+ k_remote_replay_state_failed,
+ k_remote_replay_state_ready,
+ }
+ state;
+ i64 last_second;
+ f64 end_offset, start_offset; /* from the download */
+
+ struct interp_frame interp0, interp1;
+ vg_queue buffer;
+}
+_remote_replay;
-struct _remote_replay _remote_replay;
-struct _replay2 _replay2;
+void _remote_replay_reset( u32 centiseconds, i64 last_second, u64 steamid )
+{
+ u32 minutes_span = (centiseconds+(200*60)) / (100*60);
+ u32 last_minute = (u32)( last_second / 60 );
+
+ vg_queue_clear( &_remote_replay.buffer );
+ _remote_replay.min_frame_t = 0.0;
+ _remote_replay.total_chunks = minutes_span;
+ _remote_replay.chunks_downloaded = 0;
+ _remote_replay.steamid = steamid;
+ _remote_replay.state = k_remote_replay_state_init;
+ _remote_replay.last_second = last_second;
+
+ for( u32 i=0; i<minutes_span; i ++ )
+ {
+ struct remote_replay_chunk *chunk = &_remote_replay.chunks[i];
+ chunk->minute = last_minute - minutes_span + 1 + i;
+ chunk->state = k_chunk_state_none;
+ }
+}
static int cmd_replay2_manual_download( int argc, const char *argv[] )
{
chunk->state = k_chunk_state_none;
}
- gui_helper_reset( k_gui_helper_mode_clear );
+ _gui_helper_reset( k_gui_helper_mode_clear );
_replay2_open_player( k_replay_type_network, 0 );
return 1;
}
-void _replay2_register(void)
+VG_API void _replay2_register(void)
{
vg_console_reg_cmd( "replay2_watch", cmd_replay2_manual_download, NULL );
}
-void _replay2_init(void)
+VG_API void _replay2_init(void)
{
- u32 MB = 1024*1024,
- size = 4*MB;
-
- _remote_replay.buffer.buffer = vg_stack_allocate( &vg.rtmem, size, 8, "Remote replay buffer" );
- _remote_replay.buffer.size = size;
+ _remote_replay.buffer.buffer = vg_stack_allocate( NULL, VG_MB(4), 8, "Remote replay buffer" );
+ _remote_replay.buffer.size = VG_MB(4);
- _replay2.buffer.buffer = vg_stack_allocate( &vg.rtmem, size*2, 8, "Replay buffer" );
- _replay2.buffer.size = size*2;
-
- struct skeleton *sk = &localplayer.skeleton;
- u32 mtx_size = sizeof(m4x3f)*sk->bone_count;
- _replay2.final_mtx = vg_stack_allocate( &vg.rtmem, mtx_size, 8, "Replay Final MTX" );
+ _replay2.buffer.buffer = vg_stack_allocate( NULL, VG_MB(8), 8, "Replay buffer" );
+ _replay2.buffer.size = VG_MB(8);
}
void _replay2_clear_local_buffer(void)
localplayer.immobile = 0;
}
+static void replay_file_path( c8 path[1024], u64 steamid, i64 last_second, u32 minute, enum remote_replay_state state )
+{
+ vg_str path_str;
+ vg_strnull( &path_str, path, 1024 );
+ vg_strcat( &path_str, "replaydata/" );
+ vg_strcatu64( &path_str, steamid, 16 );
+ vg_strcat( &path_str, "@" );
+
+ if( state == k_remote_replay_state_getinfo )
+ {
+ vg_strcati64( &path_str, last_second, 16 );
+ vg_strcat( &path_str, ".kv" );
+ }
+ else
+ vg_strcatu64( &path_str, minute, 16 );
+}
+
/* remote replay downloader
* ------------------------------------------------------------------ */
static void replay_download_callback( void *data, u32 data_size, u64 userdata, enum request_status status )
{
- THREAD_0;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
bool is_from_network = userdata;
{
char path[1024];
if( _remote_replay.state == k_remote_replay_state_getinfo )
- snprintf( path, sizeof(path), "replaydata/" PRINTF_X64 "@" PRINTF_X64 ".bkv",
- _remote_replay.steamid, _remote_replay.last_second );
+ replay_file_path( path, _remote_replay.steamid, _remote_replay.last_second, 0, _remote_replay.state );
else
- snprintf( path, sizeof(path), "replaydata/" PRINTF_X64 "@%x", _remote_replay.steamid, chunk->minute );
+ replay_file_path( path, _remote_replay.steamid, 0, chunk->minute, _remote_replay.state );
FILE *fp = fopen( path, "wb" );
if( fp )
if( _remote_replay.state == k_remote_replay_state_getinfo )
{
- vg_msg kvs;
- vg_msg_init( &kvs, data, data_size );
-
- u32 centiseconds = 0;
- vg_msg_getkvintg( &kvs, "centiseconds", k_vg_msg_u32, ¢iseconds, NULL );
- u32 end_offset_seconds = 0;
- vg_msg_getkvintg( &kvs, "end_offset", k_vg_msg_u32, &end_offset_seconds, NULL );
- _remote_replay.end_offset = end_offset_seconds;
- _remote_replay.start_offset = _remote_replay.end_offset + ((f64)centiseconds / 100.0);
-
- vg_info( "end_offset: -%f\n", _remote_replay.end_offset );
- vg_info( "start_offset: -%f\n", _remote_replay.start_offset );
-
- vg_msg_cursor orig = kvs.cur;
- if( vg_msg_seekframe( &kvs, "playerinfo" ) )
+ u32 temp_frame = _vg_start_temp_frame();
{
- const char *board_str = vg_msg_getkvstr( &kvs, "board" );
- const char *playermodel_str = vg_msg_getkvstr( &kvs, "player" );
+ /* TODO This is like, totally duplicated code man */
+ vg_stream kv_stream;
+ vg_buffer_stream_open( &kv_stream, data, data_size, VG_STREAM_READ );
+ vg_kvs kvs;
+ vg_kvs_init( &kvs, _vg_temp_stack() );
+ vg_kv_parser parser;
+ vg_kv_parser_init( &parser, &kvs, 0 );
+ vg_kv_parse_stream( &parser, &kv_stream );
- vg_info( "board_str: %s\n", board_str );
- vg_info( "playermodel_str: %s\n", playermodel_str );
+ u32 centiseconds = 0;
+ vg_kv_read_vu32( &kvs, 0, "centiseconds", NULL, ¢iseconds, 1 );
- if( playermodel_str )
- {
- addon_cache_unwatch( k_addon_type_player, _replay2.playermodel.cache_slot );
- playermodel_set_from_uid( &_replay2.playermodel, playermodel_str );
- }
+ u32 end_offset_seconds = 0;
+ vg_kv_read_vu32( &kvs, 0, "end_offset", NULL, &end_offset_seconds, 1 );
+
+ _remote_replay.end_offset = end_offset_seconds;
+ _remote_replay.start_offset = _remote_replay.end_offset + ((f64)centiseconds / 100.0);
- if( board_str )
+ vg_info( "end_offset: -%f\n", _remote_replay.end_offset );
+ vg_info( "start_offset: -%f\n", _remote_replay.start_offset );
+
+ u32 player_info_block = vg_kv_find( &kvs, 0, "playerinfo" );
+ if( player_info_block )
{
- addon_cache_unwatch( k_addon_type_board, _replay2.board_cache_id );
- _replay2.board_cache_id = addon_cache_create_viewer_from_uid( k_addon_type_board, board_str );
+ const c8 *board_str = vg_kv_value( &kvs, vg_kv_find( &kvs, player_info_block, "board" ), NULL );
+ const c8 *playermodel_str = vg_kv_value( &kvs, vg_kv_find( &kvs, player_info_block, "player" ), NULL );
+ vg_info( "board_str: %s\n", board_str );
+ vg_info( "playermodel_str: %s\n", playermodel_str );
+
+ if( playermodel_str )
+ {
+ addon_cache_unwatch( k_addon_type_player, _replay2.playermodel.cache_slot );
+ playermodel_set_from_uid( &_replay2.playermodel, playermodel_str );
+ }
+
+ if( board_str )
+ {
+ addon_cache_unwatch( k_addon_type_board, _replay2.board_cache_id );
+ _replay2.board_cache_id = addon_cache_create_viewer_from_uid( k_addon_type_board, board_str );
+ }
}
}
+ _vg_end_temp_frame( temp_frame );
_remote_replay.state = k_remote_replay_state_waitnext;
return;
}
_remote_replay.min_frame_t = playerframe->timestamp;
- replay2_frame *dst_frame = vg_queue_alloc( buffer, sizeof(replay2_frame) + snm->msg_size, NULL );
+ replay2_frame *dst_frame = vg_queue_alloc( buffer, sizeof(replay2_frame) + snm->msg_size );
if( !dst_frame )
{
vg_error( "Out of mem adding frame!\n" );
u32 data_length;
u8 data[];
};
-static void async_cache_check_result( vg_async_task *task )
+static void async_cache_check_result( struct async_cache_check_result *in_args, vg_async_info *async )
{
- THREAD_0;
- struct async_cache_check_result *result = (void *)task->data;
-
- if( result->found_in_cache )
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ if( in_args->found_in_cache )
{
- if( result->broken )
+ if( in_args->broken )
replay_download_callback( NULL, 0, 0, k_request_status_not_found );
else
- replay_download_callback( result->data, result->data_length, 0, k_request_status_ok );
+ replay_download_callback( in_args->data, in_args->data_length, 0, k_request_status_ok );
}
else
{
vg_make_directory( "replaydata" );
+ // FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////
+#if 0
netmsg_request *packet = alloca( sizeof(netmsg_request) + 512 );
packet->inetmsg_id = k_inetmsg_request;
else
vg_msg_wkvnum( &data, "lastsec", k_vg_msg_i64, 1, &_remote_replay.last_second );
network_send_request( packet, &data, replay_download_callback, 1 );
+#endif
+ // FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////
}
}
static const u32 k_download_option_preparing = 0x00;
static const u32 k_download_option_data = 0x00;
-static void _remote_replay_cache_check( void *userdata )
+static void _remote_replay_cache_check( void *_, vg_async_info *async )
{
char path[1024];
if( _remote_replay.state == k_remote_replay_state_getinfo )
- {
- snprintf( path, sizeof(path), "replaydata/" PRINTF_X64 "@" PRINTF_X64 ".bvk",
- _remote_replay.steamid, _remote_replay.last_second );
- }
+ replay_file_path( path, _remote_replay.steamid, _remote_replay.last_second, 0, _remote_replay.state );
else
{
struct remote_replay_chunk *chunk = &_remote_replay.chunks[ _remote_replay.chunks_downloaded ];
- snprintf( path, sizeof(path), "replaydata/" PRINTF_X64 "@%x", _remote_replay.steamid, chunk->minute );
+ replay_file_path( path, _remote_replay.steamid, 0, chunk->minute, _remote_replay.state );
}
- vg_async_task *result_task =
- vg_allocate_async_task( &vg.main_tasks, sizeof(struct async_cache_check_result) + 8*1024*1024, 1 );
- struct async_cache_check_result *result = (void *)result_task->data;
- result->broken = 0;
+ struct async_cache_check_result *out_args =
+ _vg_async_alloc( VG_THREAD_MAIN_ID, sizeof(struct async_cache_check_result) + 8*1024*1024 );
+ out_args->broken = 0;
FILE *fp = fopen( path, "rb" );
if( fp )
{
- result->found_in_cache = 1;
- result->data_length = fread( result->data, 1, 20*1024*1024, fp );
-
+ out_args->found_in_cache = 1;
+ out_args->data_length = fread( out_args->data, 1, 20*1024*1024, fp );
if( !feof( fp ) )
- result->broken = 1;
-
+ out_args->broken = 1;
fclose( fp );
}
else
{
- result->found_in_cache = 0;
- result->data_length = 0;
+ out_args->found_in_cache = 0;
+ out_args->data_length = 0;
}
- vg_async_task_dispatch( result_task, async_cache_check_result );
+ _vg_async_send( out_args, (vg_async_fn)async_cache_check_result );
}
static void _remote_replay_pre_update(void)
if( _remote_replay.state == k_remote_replay_state_init )
{
_remote_replay.state = k_remote_replay_state_getinfo;
- vg_async_call( &vg.loader_tasks, _remote_replay_cache_check, NULL );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_remote_replay_cache_check );
}
else if( _remote_replay.state == k_remote_replay_state_waitnext )
{
if( chunk->state == k_chunk_state_none )
{
chunk->state = k_chunk_state_cache_check;
- vg_async_call( &vg.loader_tasks, _remote_replay_cache_check, NULL );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_remote_replay_cache_check );
}
}
}
}
if( _replay2.use_freecam )
- freecam_preupdate();
+ {
+ vg_camera *cam = &_replay2.replay_freecam;
+ v3f angles;
+ v3_copy( cam->angles, angles );
+ player_look( angles, 1.0f );
+
+ f32 decay = vg_maxf(0.0f,1.0f-vg.time_frame_delta*10.0f);
+
+ v3f d;
+ v3_sub( angles, cam->angles, d );
+ v3_muladds( _replay2.freecam_w, d, 20.0f, _replay2.freecam_w );
+ v3_muls( _replay2.freecam_w, decay, _replay2.freecam_w );
+ v3_muladds( cam->angles, _replay2.freecam_w, vg.time_frame_delta, cam->angles );
+ cam->angles[1] = vg_clampf( cam->angles[1], -VG_PIf*0.5f,VG_PIf*0.5f);
+
+ vg_camera_update_transform( cam );
+
+ v3f lookdir = { 0.0f, 0.0f, -1.0f },
+ sidedir = { 1.0f, 0.0f, 0.0f };
+
+ m3x3_mulv( cam->transform, lookdir, lookdir );
+ m3x3_mulv( cam->transform, sidedir, sidedir );
+
+ v2f input;
+ joystick_state( k_srjoystick_steer, input );
+ v2_muls( input, vg.time_frame_delta*6.0f*20.0f, input );
+
+ v3_muladds( _replay2.freecam_v, lookdir, -input[1], _replay2.freecam_v );
+ v3_muladds( _replay2.freecam_v, sidedir, input[0], _replay2.freecam_v );
+
+ v3_muls( _replay2.freecam_v, decay, _replay2.freecam_v );
+ v3_muladds( cam->pos,_replay2.freecam_v, vg.time_frame_delta, cam->pos );
+ }
if( _replay2.animation_dirty )
{
}
}
-void _replay2_render_player( world_instance *world, vg_camera *cam )
+void _replay2_render_player( vg_camera *cam )
{
if( skaterift.activity != k_skaterift_replay )
return;
- struct skeleton *sk = &localplayer.skeleton;
- render_playermodel( cam, world, 0, &_replay2.playermodel, sk, _replay2.final_mtx );
+ ms_skeleton *sk = &localplayer.skeleton;
+ render_playermodel( cam, &_world.main, 0, &_replay2.playermodel, sk, _replay2.final_mtx );
struct player_board *board = addon_cache_item_data( k_addon_type_board, _replay2.board_cache_id, 1 );
- render_board( cam, world, board, _replay2.final_mtx[localplayer.id_board],
+ render_board( cam, &_world.main, board, _replay2.final_mtx[localplayer.id_board],
&_replay2.board_pose, k_board_shader_player );
#if 0
shader_model_entity_uCamera( cam->transform[3] );
shader_model_entity_uPv( cam->mtx.pv );
- WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, model_entity );
+ WORLD_LINK_LIGHTING( world, model_entity );
for( u32 j=0; j<draw_list_count; j ++ )
{
{
if( _remote_replay.state < k_remote_replay_state_ready )
{
- ui_rect box = { vg.window_x/2 - 200, vg.window_y/2-80, 400, 160 };
+ ui_rect box = { _vg_window.w/2 - 200, _vg_window.h/2-80, 400, 160 };
ui_fill( ctx, box, ui_opacity( GUI_COL_DARK, 0.36f ) );
ui_rect titlebox, boxbox, boxboxline;
ui_split_ratio( box, k_ui_axis_h, 0.5f, 8, titlebox, boxbox );
if( buffer->allocation_count < 2 )
{
ctx->font = &vgf_default_large;
- ui_rect box = { vg.window_x/2 - 200, 40, 400, ctx->font->sy };
+ ui_rect box = { _vg_window.w/2 - 200, 40, 400, ctx->font->sy };
ui_text( ctx, box, KRED "\x06\x02--- Corrupt replay ---", 1, k_ui_align_center, 0 );
// TODO
return;
cur = (_replay2.cursor - start) / len;
/* mainbar */
- ui_rect timeline = { 8, vg.window_y-(32+8), vg.window_x-16, 32 };
+ ui_rect timeline = { 8, _vg_window.h-(32+8), _vg_window.w-16, 32 };
ui_rect start_box;
ui_split( timeline, k_ui_axis_v, 32, 8, start_box, timeline );
/* helpers */
ctx->font = &vgf_default_large;
- ui_rect helper_list_l = { 10, timeline[1] - (ctx->font->sy+8), vg.window_x/2, ctx->font->sy };
+ ui_rect helper_list_l = { 10, timeline[1] - (ctx->font->sy+8), _vg_window.w/2, ctx->font->sy };
char buf[256];
vg_str str;
vg_strnull( &str, buf, sizeof(buf) );
ui_text( ctx, helper_list_l, buf, 1, k_ui_align_left, 0 );
helper_list_l[1] -= helper_list_l[3]+2;
- ui_rect helper_list_r = { vg.window_x/2, timeline[1] - (ctx->font->sy+8), vg.window_x/2-10, ctx->font->sy };
+ ui_rect helper_list_r = { _vg_window.w/2, timeline[1] - (ctx->font->sy+8), _vg_window.w/2-10, ctx->font->sy };
vg_strnull( &str, buf, sizeof(buf) );
vg_input_string( &str, input_button_list[k_srbind_mback], 1 );
vg_strcat( &str, "\x07 Exit Replay" );
if( _replay2.use_freecam )
{
- ui_rect box = { vg.window_x/2 - 200, 40, 400, ctx->font->sy };
+ ui_rect box = { _vg_window.w/2 - 200, 40, 400, ctx->font->sy };
ui_text( ctx, box, KYEL "\x06\x02--- Freecam Enabled ---", 1, k_ui_align_center, 0 );
}
sfx_size = vg_align8( localplayer.local_sfx_buffer_count * sizeof(struct net_sfx) ),
total_size = sizeof(replay2_frame) + animator_size + glider_size + sfx_size;
- replay2_frame *dest_frame = vg_queue_alloc( buffer, total_size, NULL );
+ replay2_frame *dest_frame = vg_queue_alloc( buffer, total_size );
if( !dest_frame )
{
while( buffer->allocation_count )
{
vg_queue_pop( buffer );
- dest_frame = vg_queue_alloc( buffer, total_size, NULL );
+ dest_frame = vg_queue_alloc( buffer, total_size );
if( dest_frame )
break;
}
-#pragma once
-#include "vg/vg_mem_queue.h"
-#include "player_effects.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/replay2.c"
+#else
+
+enum replay_type
+{
+ k_replay_type_local,
+ k_replay_type_network
+};
typedef struct replay2_frame replay2_frame;
struct replay2_frame
v4f q;
};
-struct _remote_replay
-{
- u32 total_chunks,
- chunks_downloaded;
-
- u64 steamid;
- struct remote_replay_chunk
- {
- u32 minute;
- enum chunk_state
- {
- k_chunk_state_none,
- k_chunk_state_cache_check,
- k_chunk_state_downloading,
- k_chunk_state_processed,
- k_chunk_state_broken
- }
- state;
- }
- chunks[8];
- f64 min_frame_t;
-
- enum remote_replay_state
- {
- k_remote_replay_state_none,
-
- k_remote_replay_state_init,
- k_remote_replay_state_getinfo,
-
- k_remote_replay_state_waitnext,
- k_remote_replay_state_downloading,
- k_remote_replay_state_failed,
- k_remote_replay_state_ready,
- }
- state;
- i64 last_second;
- f64 end_offset, start_offset; /* from the download */
+VG_API void _replay2_register(void);
+VG_API void _replay2_init(void);
- struct interp_frame interp0, interp1;
- vg_queue buffer;
-}
-extern _remote_replay;
+f32 _replay2_playback_velocity(void);
-struct _replay2
-{
- enum replay_type
- {
- k_replay_type_local,
- k_replay_type_network
- }
- type;
-
- vg_queue buffer;
-
- /* TODO: Modifiers / keyframes lane */
-
- u32 cursor_frame_offset;
- f64 cursor;
- enum replay_control {
- k_replay_control_scrub = 0x00,
- k_replay_control_play = 0x01,
- k_replay_control_resume= 0x02
- }
- replay_control;
- f32 track_velocity;
-
- bool cursor_decoded;
-
- struct net_sfx sfx_queue[ 8 ];
- u32 sfx_queue_length;
- f64 sfx_basetime;
-
- vg_camera replay_freecam, playback_cam;
- bool use_freecam;
- bool hide_ui;
- v3f freecam_v, freecam_w;
-
- f64 start_t, end_t;
- bool highlight;
- f64 highlight_start, highlight_length;
-
- bool animation_dirty;
- addon_cache_id board_cache_id;
- player_model_view playermodel;
-
- struct player_effects_data effect_data;
- bool render_glider;
- m4x3f *final_mtx, glider_mtx;
- struct player_board_pose board_pose;
-}
-extern _replay2;
-
-void _replay2_register(void);
-void _replay2_init(void);
+void _remote_replay_reset( u32 centiseconds, i64 last_second, u64 steamid );
void _replay2_pre_update(void);
void _replay2_imgui( ui_context *ctx );
void _replay2_open_player( enum replay_type type, bool end );
-void _replay2_render_player( world_instance *world, vg_camera *cam );
+void _replay2_render_player( vg_camera *cam );
void _replay2_seek( f64 t, bool play_sounds );
void _replay2_get_camera( vg_camera *cam );
void _replay2_decode(void);
void _replay2_record_local_frame(void);
void _replay2_clear_local_buffer(void);
+
+#endif
-#include "skaterift.h"
-#include "save.h"
-#include "addon.h"
-#include "vg/vg_msg.h"
-#include "vg/vg_log.h"
-#include "vg/vg_loader.h"
-#include "world.h"
-#include "player.h"
-
-static const char *str_skaterift_main_save = "save.bkv";
+static const char *str_skaterift_main_save = "save.kv";
static f64 _last_autosave;
void savedata_file_write( savedata_file *file )
{
+#if 0
savedata_file *sav = file;
FILE *fp = fopen( sav->path, "wb" );
if( fp )
}
else
vg_error( "Error writing savedata (%s)\n", sav->path );
+#endif
}
static void savedata_file_write_task( vg_async_task *task )
void savedata_file_read( savedata_file *file )
{
+ vg_zero_mem( &file->kvs, sizeof(vg_kvs) );
+#if 0
FILE *fp = fopen( file->path, "rb" );
if( fp )
{
vg_msg_init( &file->msg, file->buf, 0 );
vg_warn( "Error reading savedata (%s)\n", file->path );
}
+#endif
}
static void skaterift_write_addon( vg_msg *msg, const char *key, addon_id id )
{
+#if 0
char uid[ ADDON_UID_MAX ];
addon_make_uid( id, uid );
vg_msg_wkvstr( msg, key, uid );
+#endif
}
static void skaterift_write_viewslot( vg_msg *msg, const char *key, enum addon_type type, u16 cache_id )
{
- THREAD_0;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
if( !cache_id )
return;
+#if 0
addon_cache_entry *entry = get_addon_cache_entry( type, cache_id );
char uid[ ADDON_UID_MAX ];
addon_make_uid_cpart( entry->addon_id, uid, entry->local_cpart );
vg_msg_wkvstr( msg, key, uid );
+#endif
}
void init_savefile( savedata_file *file, const char *path )
{
memset( file, 0, sizeof(savedata_file) );
strcpy( file->path, path );
+#if 0
vg_msg_init( &file->msg, file->buf, sizeof(file->buf) );
+#endif
}
void write_savefile( savedata_file *file, bool async )
{
+#if 0
if( async )
{
vg_async_task *task = vg_allocate_async_task( &vg.loader_tasks, sizeof(savedata_file), 1 );
}
else
savedata_file_write( file );
+#endif
}
void skaterift_write_all_savedata( bool async )
{
+#if 0
savedata_file file;
/* main file */
vg_msg_end_frame( &file.msg );
write_savefile( &file, async );
}
+#endif
}
void skaterift_autosave_synchronous(void)
{
+#if 0
skaterift_write_all_savedata( 0 );
+#endif
}
void skaterift_autosave_update( void )
{
+#if 0
if( (vg.time - _last_autosave) > 60.0 )
{
skaterift_write_all_savedata(1);
_last_autosave = vg.time;
}
+#endif
}
struct equip_saved_items_info
};
static void equip_async( vg_async_task *task )
{
- THREAD_0;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
struct equip_saved_items_info *info = (void *)task->data;
localplayer.board_view_slot = addon_cache_create_viewer( k_addon_type_board, info->board_id );
void skaterift_load_mainsave(void)
{
- THREAD_1;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+
+#if 0
savedata_file file;
strcpy( file.path, str_skaterift_main_save );
vg_info( "Starting new story!\n" );
_world.load_addon = _addon_mount_from_folder_path( "maps/dev_heaven", k_addon_type_world, ".mdl" );
}
+#endif
}
-#pragma once
-#include "vg/vg_platform.h"
-#include "vg/vg_msg.h"
-#include "addon.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/save.c"
+#else
typedef struct savedata_file savedata_file;
struct savedata_file
{
char path[256];
- u8 buf[2048];
- vg_msg msg;
+ vg_kvs kvs;
};
void savedata_file_read( savedata_file *file );
void init_savefile( savedata_file *file, const char *path );
void write_savefile( savedata_file *file, bool async );
+
+#endif
--- /dev/null
+/* How many save files can be 'open' at once */
+#define MAX_SAVE_FILES 3
+
+// In the future
+// #define MAX_SAVE_SLOTS 4
+
+VG_API void _skaterift_autosave_post_update( void )
+{
+ VG_ASSERT(0);
+}
+
+#if 0
+
+struct
+{
+ struct savefile
+ {
+ bool ready;
+ vg_stack_allocator stack;
+ vg_kvs kvs;
+
+ u16 addon_id; /* 0 for main save */
+ }
+ files[ MAX_SAVE_FILES ];
+ vg_pool pool;
+ vg_pool_chain inactive, active;
+}
+_savedata;
+
+void _savedata_init(void)
+{
+ vg_pool_init( &_savedata.pool, &_savedata.inactive, MAX_SAVE_FILES, &vg.rtmem );
+}
+
+
+// Loading
+while( ... )
+{
+ if( stage == init )
+ {
+ world->savefile = savedata_handle( world->addon );
+ if( world->savefile )
+ stage = read_save;
+ }
+ else if( stage == read_save )
+ {
+ if( savedata_loaded( world->savefile ) )
+ {
+ // read save
+ stage = ready;
+ }
+ }
+}
+
+
+// Game loop
+if( autosave_timer() )
+{
+ world_autosave(); -> savedata_sync( world->savefile );
+}
+
+// Unload
+savedata_sync( world->savefile );
+savedata_release_handle( world->addon );
+
+
+
+
+
+
+
+static u16 _savedata_handle_fork( u16 save_handle )
+{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ if( vg_pool_reference( &_savedata.pool, save_handle, 1 ) == 1 )
+ vg_pool_switch( &_savedata.pool, &_savedata.inactive, &_savedata.active );
+
+ return save_handle;
+}
+
+void _savedata_handle_release( u16 save_handle )
+{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ if( vg_pool_reference( &_savedata.pool, save_handle, 0 ) == 0 )
+ vg_pool_switch( &_savedata.pool, &_savedata.active, &_savedata.inactive );
+}
+
+struct savedata_async_info
+{
+ u16 save_handle;
+};
+static savedata_async( vg_async_queue *queue, void( *fn )(u16), u16 handle )
+{
+ vg_async_task *task = vg_allocate_async_task( queue, sizeof(struct savedata_async_info), 1 );
+ struct savedata_async_info *info = (void *)complete_task->data;
+ info->save_handle = handle;
+ vg_async_task_dispatch( task, savedata_load );
+}
+
+static savedata_task_complete( vg_async_task *task )
+{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ struct savedata_async_info *info = (void *)task->data;
+ struct savefile *sf = &_savedata.files[ vg_pool_index( &_savedata.pool, info->save_handle ) ];
+ sf->ready = 1;
+ _savedata_handle_release( info->save_handle );
+}
+
+void savedata_load( vg_async_task *task )
+{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+ struct savedata_async_info *info = (void *)task->data;
+ struct savefile *sf = &_savedata.files[ vg_pool_index( &_savedata.pool, info->save_handle ) ];
+
+ vg_stack_clear( &sf->stack );
+ vg_kvs_init( &sf->kvs, &sf->stack );
+
+ c8 path[ 256 ];
+ addon_make_savedata_path( sf->addon_id, path );
+
+ vg_file file;
+ if( vg_file_stream_open( &file, path ) )
+ {
+ vg_kv_parser parser;
+ vg_kv_parser_init( &parser, &sf->kvs, 0 );
+
+ c8 chunk[ 1024 ];
+read_more:;
+ u32 l = vg_file_stream( &file, chunk, sizeof(chunk) );
+ vg_kv_parse_buffer( &parser, chunk, l );
+
+ if( l == sizeof(chunk) )
+ goto read_more;
+
+ vg_file_stream_close( &file );
+ }
+ else
+ vg_low( "Savefile '%s' did not exist yet. Creating.\n" );
+
+ vg_async_task *complete_task = vg_allocate_async_task( &vg.main_tasks, sizeof(struct savedata_async_info), 1 );
+ struct savedata_async_info *info = (void *)complete_task->data;
+ info->save_handle = info->save
+ vg_async_task_dispatch( load_task, savedata_load );
+}
+
+u16 _savedata_handle( addon_id addon )
+{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+
+ u16 save_handle = _savedata.active.head;
+ while( save_handle )
+ {
+ if( _savedata.files[ vg_pool_index( &_savedata.pool, save_handle ) ].addon_id == addon )
+ return _savedata_handle_fork( save_handle );
+
+ save_handle = vg_pool_next( &_savedata.pool, save_handle, 1 );
+ }
+
+ save_handle = _savedata.inactive.tail;
+ if( save_handle )
+ {
+ vg_async_task *load_task = vg_allocate_async_task( &vg.loader_tasks, sizeof(struct savedata_async_info), 1 );
+ struct savedata_async_info *info = (void *)load_task->data;
+ info->save_handle = _savedata_handle_fork( save_handle );
+ vg_async_task_dispatch( load_task, savedata_load );
+ return _savedata_handle_fork( save_handle );
+ }
+
+ return 0;
+}
+
+bool _savedata_ready( u16 save_handle )
+{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ return _savedata.files[ vg_pool_index( &_savedata.pool, save_handle ) ].ready;
+}
+
+#endif
--- /dev/null
+#if defined( SR_IMPLEMENTATION )
+# include "src/save2.c"
+#else
+
+VG_API void _skaterift_autosave_post_update( void );
+
+#endif
-#include "scene.h"
-
-u32 scene_mem_required( scene_context *ctx )
-{
- u32 vertex_length = vg_align8(ctx->max_vertices * sizeof(scene_vert)),
- index_length = vg_align8(ctx->max_indices * sizeof(u32));
-
- return vertex_length + index_length;
-}
-
-void scene_init( scene_context *ctx, u32 max_vertices, u32 max_indices )
+VG_TIER_2 void scene_builder_init( scene_builder_context *ctx, u32 max_vertices, u32 max_indices, vg_stack_allocator *stack )
{
- ctx->vertex_count = 0;
- ctx->indice_count = 0;
- ctx->max_vertices = max_vertices;
- ctx->max_indices = max_indices;
- ctx->arrindices = NULL; /* must be filled out by user */
- ctx->arrvertices = NULL;
-
- memset( &ctx->submesh, 0, sizeof(mdl_submesh) );
-
- v3_fill( ctx->bbx[0], 999999.9f );
- v3_fill( ctx->bbx[1], -999999.9f );
+ vg_zero_mem( ctx, sizeof(scene_builder_context) );
+ u32 vertex_block_size = vg_align8( max_vertices * sizeof(scene_vert) ),
+ indice_block_size = vg_align8( max_indices * sizeof(u32) );
+ ctx->base_buffer_size = vertex_block_size + indice_block_size;
+ ctx->base_buffer = vg_stack_allocate( stack, ctx->base_buffer_size, 8, "Scene data" );
+ vg_stack_init( &ctx->vertex_stack, ctx->base_buffer, vertex_block_size, "Scene vertices" );
+ vg_stack_init( &ctx->indice_stack, ctx->base_buffer + vertex_block_size, indice_block_size, "Scene indices" );
+ v3_fill( ctx->scene.bbx[0], 999999.9f );
+ v3_fill( ctx->scene.bbx[1], -999999.9f );
}
-void scene_supply_buffer( scene_context *ctx, void *buffer )
+VG_TIER_2 void scene_builder_compact_memory( scene_builder_context *ctx, vg_stack_allocator *stack )
{
- u32 vertex_length = vg_align8( ctx->max_vertices * sizeof(scene_vert) );
-
- ctx->arrvertices = buffer;
- ctx->arrindices = (u32*)(((u8*)buffer) + vertex_length);
+ void *new_indice_location = ctx->base_buffer + vg_align8( ctx->vertex_stack.offset );
+ memmove( new_indice_location, ctx->indice_stack.data, ctx->indice_stack.offset );
+ ctx->vertex_stack.capacity = ctx->vertex_stack.offset;
+ ctx->indice_stack.capacity = ctx->indice_stack.offset;
+ ctx->indice_stack.data = new_indice_location;
+ u32 new_size = vg_align8( ctx->vertex_stack.capacity ) + vg_align8( ctx->indice_stack.capacity );
+ vg_stack_extend_last( stack, (i32)new_size - (i32)ctx->base_buffer_size );
+ ctx->base_buffer_size = new_size;
}
-void scene_vert_pack_norm( scene_vert *vert, v3f norm, f32 blend )
+VG_TIER_0 void scene_vert_pack_norm( scene_vert *vert, v3f norm, f32 blend )
{
v3f n;
v3_muls( norm, 127.0f, n );
vert->norm[3] = blend * 127.0f;
}
-/*
- * Append a model into the scene with a given transform
- */
-void scene_add_mdl_submesh( scene_context *ctx, mdl_context *mdl,
- mdl_submesh *sm, m4x3f transform )
+VG_TIER_0 void scene_builder_add_model_submesh( scene_builder_context *ctx, vg_model *model, mdl_submesh *sm, m4x3f transform )
{
- if( ctx->vertex_count + sm->vertex_count > ctx->max_vertices ){
- vg_fatal_error( "Scene vertex buffer overflow (%u exceeds %u)\n",
- ctx->vertex_count + sm->vertex_count,
- ctx->max_vertices );
- }
-
- if( ctx->indice_count + sm->indice_count > ctx->max_indices ){
- vg_fatal_error( "Scene index buffer overflow (%u exceeds %u)\n",
- ctx->indice_count + sm->indice_count,
- ctx->max_indices );
- }
-
- mdl_vert *src_verts = mdl->verts + sm->vertex_start;
- scene_vert *dst_verts = &ctx->arrvertices[ ctx->vertex_count ];
-
- u32 *src_indices = mdl->indices + sm->indice_start,
- *dst_indices = &ctx->arrindices[ ctx->indice_count ];
+ VG_ASSERT( model->flags & VG_MODEL_CPU_MESHES );
+ mdl_vert *src_verts = model->verts + sm->vertex_start;
+ scene_vert *dst_verts = vg_stack_allocate( &ctx->vertex_stack, sizeof(scene_vert)*sm->vertex_count, 1, "Verts (submesh)" );
+ u32 *src_indices = model->indices + sm->indice_start,
+ *dst_indices = vg_stack_allocate( &ctx->indice_stack, sizeof(u32)*sm->indice_count, 1, "Indices (submesh)" );
/* Transform and place vertices */
boxf bbxnew;
box_init_inf( bbxnew );
m4x3_expand_aabb_aabb( transform, bbxnew, sm->bbx );
- box_concat( ctx->bbx, bbxnew );
+ box_concat( ctx->scene.bbx, bbxnew );
m3x3f normal_matrix;
m3x3_copy( transform, normal_matrix );
v3_normalize( normal_matrix[1] );
v3_normalize( normal_matrix[2] );
- for( u32 i=0; i<sm->vertex_count; i++ ){
+ for( u32 i=0; i<sm->vertex_count; i++ )
+ {
mdl_vert *src = &src_verts[i];
scene_vert *pvert = &dst_verts[i];
-
m4x3_mulv( transform, src->co, pvert->co );
v3f normal;
m3x3_mulv( normal_matrix, src->norm, normal );
scene_vert_pack_norm( pvert, normal, src->colour[0]*(1.0f/255.0f) );
-
v2_copy( src->uv, pvert->uv );
}
u32 real_indices = 0;
- for( u32 i=0; i<sm->indice_count/3; i++ ){
+ for( u32 i=0; i<sm->indice_count/3; i++ )
+ {
u32 *src = &src_indices[i*3],
*dst = &dst_indices[real_indices];
-
v3f ab, ac, tn;
v3_sub( src_verts[src[2]].co, src_verts[src[0]].co, ab );
v3_sub( src_verts[src[1]].co, src_verts[src[0]].co, ac );
v3_cross( ac, ab, tn );
-
#if 0
if( v3_length2( tn ) <= 0.00001f )
continue;
#endif
-
- dst[0] = src[0] + ctx->vertex_count;
- dst[1] = src[1] + ctx->vertex_count;
- dst[2] = src[2] + ctx->vertex_count;
+ dst[0] = src[0] + ctx->scene.vertex_count;
+ dst[1] = src[1] + ctx->scene.vertex_count;
+ dst[2] = src[2] + ctx->scene.vertex_count;
real_indices += 3;
}
-
if( real_indices != sm->indice_count )
vg_warn( "Zero area triangles in model\n" );
-
- ctx->vertex_count += sm->vertex_count;
- ctx->indice_count += real_indices;
+ ctx->scene.vertex_count += sm->vertex_count;
+ ctx->scene.indice_count += real_indices;
}
/*
* One by one adders for simplified access (mostly procedural stuff)
*/
-void scene_push_tri( scene_context *ctx, u32 tri[3] )
+VG_TIER_0 void scene_builder_push_tri( scene_builder_context *ctx, u32 tri[3] )
{
- if( ctx->indice_count + 3 > ctx->max_indices )
- vg_fatal_error( "Scene indice buffer overflow (%u exceeds %u)\n",
- ctx->indice_count+3, ctx->max_indices );
-
- u32 *dst = &ctx->arrindices[ ctx->indice_count ];
-
+ u32 *dst = vg_stack_allocate( &ctx->indice_stack, sizeof(u32)*3, 1, "Indices (single tri)" );
dst[0] = tri[0];
dst[1] = tri[1];
dst[2] = tri[2];
-
- ctx->indice_count += 3;
+ ctx->scene.indice_count += 3;
}
-void scene_push_vert( scene_context *ctx, scene_vert *v )
+VG_TIER_0 void scene_builder_push_vert( scene_builder_context *ctx, scene_vert *v )
{
- if( ctx->vertex_count + 1 > ctx->max_vertices )
- vg_fatal_error( "Scene vertex buffer overflow (%u exceeds %u)\n",
- ctx->vertex_count+1, ctx->max_vertices );
-
- scene_vert *dst = &ctx->arrvertices[ ctx->vertex_count ];
+ scene_vert *dst = vg_stack_allocate( &ctx->vertex_stack, sizeof(scene_vert), 1, "Single vert" );
*dst = *v;
-
- ctx->vertex_count ++;
+ ctx->scene.vertex_count ++;
}
-void scene_copy_slice( scene_context *ctx, mdl_submesh *sm )
+VG_TIER_0 void scene_builder_get_submesh( scene_builder_context *ctx, mdl_submesh *sm )
{
- sm->indice_start = ctx->submesh.indice_start;
- sm->indice_count = ctx->indice_count - sm->indice_start;
-
- sm->vertex_start = ctx->submesh.vertex_start;
- sm->vertex_count = ctx->vertex_count - sm->vertex_start;
-
- ctx->submesh.indice_start = ctx->indice_count;
- ctx->submesh.vertex_start = ctx->vertex_count;
+ vg_zero_mem( sm, sizeof(mdl_submesh) );
+ sm->indice_start = ctx->current_submesh.indice_start;
+ sm->indice_count = ctx->scene.indice_count - sm->indice_start;
+ sm->vertex_start = ctx->current_submesh.vertex_start;
+ sm->vertex_count = ctx->scene.vertex_count - sm->vertex_start;
+ ctx->current_submesh.indice_start = ctx->scene.indice_count;
+ ctx->current_submesh.vertex_start = ctx->scene.vertex_count;
}
-void scene_set_vertex_flags( scene_context *ctx,
- u32 start, u32 count, u16 flags )
+VG_TIER_0 void scene_builder_set_vertex_flags( scene_builder_context *ctx, u32 start, u32 count, u16 flags )
{
+ scene_vert *verts = vg_stack_pointer( &ctx->vertex_stack, sizeof(scene_vert)*start );
for( u32 i=0; i<count; i++ )
- ctx->arrvertices[ start + i ].flags = flags;
+ verts[ start + i ].flags = flags;
}
-struct scene_upload_info{
- scene_context *ctx;
- glmesh *mesh;
-};
-
-void async_scene_upload( vg_async_task *task )
+VG_TIER_0 void scene_builder_save_scene( scene_builder_context *ctx, vg_scene *out_scene )
{
- THREAD_0;
-
- struct scene_upload_info *info = (void *)task->data;
-
- glmesh *mesh = info->mesh;
- scene_context *ctx = info->ctx;
-
- glGenVertexArrays( 1, &mesh->vao );
- glGenBuffers( 1, &mesh->vbo );
- glGenBuffers( 1, &mesh->ebo );
- glBindVertexArray( mesh->vao );
-
- size_t stride = sizeof(scene_vert);
-
- glBindBuffer( GL_ARRAY_BUFFER, mesh->vbo );
- glBufferData( GL_ARRAY_BUFFER, ctx->vertex_count*stride, ctx->arrvertices, GL_STATIC_DRAW );
+ *out_scene = ctx->scene;
+ out_scene->vertex_buffer = vg_stack_pointer( &ctx->vertex_stack, 0 );
+ out_scene->indice_buffer = vg_stack_pointer( &ctx->indice_stack, 0 );
+}
- glBindVertexArray( mesh->vao );
- glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, mesh->ebo );
- glBufferData( GL_ELEMENT_ARRAY_BUFFER, ctx->indice_count*sizeof(u32), ctx->arrindices, GL_STATIC_DRAW );
+struct scene_upload_task
+{
+ vg_scene scene;
+ scene_mesh *out_mesh;
+};
+static void scene_upload_task( struct scene_upload_task *in_args )
+{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+
+ glGenVertexArrays( 1, &in_args->out_mesh->vao );
+ glBindVertexArray( in_args->out_mesh->vao );
+ glGenBuffers( 1, &in_args->out_mesh->vbo );
+ glGenBuffers( 1, &in_args->out_mesh->ebo );
+
+ u32 stride = sizeof(scene_vert);
+ glBindBuffer( GL_ARRAY_BUFFER, in_args->out_mesh->vbo );
+ glBufferData( GL_ARRAY_BUFFER, in_args->scene.vertex_count*stride, in_args->scene.vertex_buffer, GL_STATIC_DRAW );
+ glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, in_args->out_mesh->ebo );
+ glBufferData( GL_ELEMENT_ARRAY_BUFFER, in_args->scene.indice_count * sizeof(u32),
+ in_args->scene.indice_buffer, GL_STATIC_DRAW );
/* 0: coordinates */
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0 );
glVertexAttribPointer( 2, 2, GL_FLOAT, GL_FALSE, stride, (void *)offsetof(scene_vert, uv) );
glEnableVertexAttribArray( 2 );
- mesh->indice_count = ctx->indice_count;
- mesh->loaded = 1;
-
- vg_info( "Scene upload ( XYZ_f32 UV_f32 XYZW_i8 )[ u32 ]\n" );
- vg_info( " indices:%u\n", ctx->indice_count );
- vg_info( " verts:%u\n", ctx->vertex_count );
+ vg_info( "Scene uploadd ( XYZ_f32 UV_f32 XYZW_i8 )[ u32 ]\n" );
+ vg_info( " indices:%u\n", in_args->scene.indice_count );
+ vg_info( " verts:%u\n", in_args->scene.vertex_count );
}
-vg_async_task *scene_alloc_async( scene_context *scene, glmesh *mesh, u32 max_vertices, u32 max_indices )
+VG_TIER_2 void scene_builder_upload_async( scene_builder_context *ctx, scene_mesh *out_mesh )
{
- THREAD_1;
-
- scene_init( scene, max_vertices, max_indices );
- u32 buf_size = scene_mem_required( scene );
-
- u32 hdr_size = vg_align8(sizeof(struct scene_upload_info));
- vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, hdr_size + buf_size, 1 );
-
- struct scene_upload_info *info = (void *)task->data;
-
- info->mesh = mesh;
- info->ctx = scene;
- scene_supply_buffer( scene, task->data + hdr_size );
- return task;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+ u32 task_args_size = vg_align8( sizeof(struct scene_upload_task) ),
+ vertex_buffer_size = vg_align8( sizeof(scene_vert) * ctx->scene.vertex_count ),
+ index_buffer_size = vg_align8( sizeof(u32) * ctx->scene.indice_count ),
+ total = task_args_size + vertex_buffer_size + index_buffer_size;
+ struct scene_upload_task *out_args = _vg_async_alloc( VG_THREAD_MAIN_ID, total );
+ out_args->scene.vertex_buffer = ((void *)out_args) + task_args_size;
+ out_args->scene.indice_buffer = ((void *)out_args) + task_args_size + vertex_buffer_size;
+ out_args->scene.vertex_count = ctx->scene.vertex_count;
+ out_args->scene.indice_count = ctx->scene.indice_count;
+ out_args->out_mesh = out_mesh;
+ memcpy( out_args->scene.vertex_buffer, ctx->scene.vertex_buffer, sizeof(scene_vert) * ctx->scene.vertex_count );
+ memcpy( out_args->scene.indice_buffer, ctx->scene.indice_buffer, sizeof(u32) * ctx->scene.indice_count );
+ _vg_async_send( out_args, (vg_async_fn)scene_upload_task );
}
/*
* BVH implementation
*/
-static void scene_bh_expand_bound( void *user, boxf bound, u32 item_index )
+static void scene_bh_expand_bound( vg_scene *scene, boxf bound, u32 item_index )
{
- scene_context *s = user;
- scene_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] ];
-
+ scene_vert *pa = &scene->vertex_buffer[ scene->indice_buffer[item_index*3+0] ],
+ *pb = &scene->vertex_buffer[ scene->indice_buffer[item_index*3+1] ],
+ *pc = &scene->vertex_buffer[ scene->indice_buffer[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 )
+static f32 scene_bh_centroid( vg_scene *scene, u32 item_index, i32 axis )
{
- scene_context *s = user;
- scene_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] ];
-
+ scene_vert *pa = &scene->vertex_buffer[ scene->indice_buffer[item_index*3+0] ],
+ *pb = &scene->vertex_buffer[ scene->indice_buffer[item_index*3+1] ],
+ *pc = &scene->vertex_buffer[ scene->indice_buffer[item_index*3+2] ];
#if 0
float min, max;
#endif
}
-static void scene_bh_swap( void *user, u32 ia, u32 ib )
+static void scene_bh_swap( vg_scene *scene, u32 ia, u32 ib )
{
- scene_context *s = user;
-
- u32 *ti = &s->arrindices[ia*3];
- u32 *tj = &s->arrindices[ib*3];
+ u32 *ti = &scene->indice_buffer[ia*3];
+ u32 *tj = &scene->indice_buffer[ib*3];
u32 temp[3];
temp[0] = ti[0];
tj[2] = temp[2];
}
-static void scene_bh_debug( void *user, u32 item_index )
+static void scene_bh_debug( vg_scene *scene, u32 item_index )
{
- scene_context *s = user;
u32 idx = item_index*3;
- scene_vert *pa = &s->arrvertices[ s->arrindices[ idx+0 ] ],
- *pb = &s->arrvertices[ s->arrindices[ idx+1 ] ],
- *pc = &s->arrvertices[ s->arrindices[ idx+2 ] ];
-
+ scene_vert *pa = &scene->vertex_buffer[ scene->indice_buffer[item_index*3+0] ],
+ *pb = &scene->vertex_buffer[ scene->indice_buffer[item_index*3+1] ],
+ *pc = &scene->vertex_buffer[ scene->indice_buffer[item_index*3+2] ];
vg_line( pa->co, pb->co, 0xff0000ff );
vg_line( pb->co, pc->co, 0xff0000ff );
vg_line( pc->co, pa->co, 0xff0000ff );
}
-static void scene_bh_closest( void *user, u32 index, v3f point, v3f closest )
+static void scene_bh_closest( vg_scene *scene, u32 index, v3f point, v3f closest )
{
- scene_context *s = user;
-
v3f positions[3];
- u32 *tri = &s->arrindices[ index*3 ];
+ u32 *tri = &scene->indice_buffer[ index*3 ];
for( int i=0; i<3; i++ )
- v3_copy( s->arrvertices[tri[i]].co, positions[i] );
-
+ v3_copy( scene->vertex_buffer[tri[i]].co, positions[i] );
closest_on_triangle_1( point, positions, closest );
}
-bh_system bh_system_scene =
+static bh_system bh_system_scene =
{
- .expand_bound = scene_bh_expand_bound,
- .item_centroid = scene_bh_centroid,
- .item_closest = scene_bh_closest,
- .item_swap = scene_bh_swap,
- .item_debug = scene_bh_debug,
+ .expand_bound = (bh_expand_fn)scene_bh_expand_bound,
+ .item_centroid = (bh_centroid_fn)scene_bh_centroid,
+ .item_closest = (bh_closest_fn)scene_bh_closest,
+ .item_swap = (bh_swap_fn)scene_bh_swap,
+ .item_debug = (bh_debug_fn)scene_bh_debug,
};
/*
* An extra step is added onto the end to calculate the hit normal
*/
-int scene_raycast( scene_context *s, bh_tree *bh,
- v3f co, v3f dir, ray_hit *hit, u16 ignore )
+VG_TIER_0 i32 scene_raycast( vg_scene *scene, bh_tree *bh, v3f co, v3f dir, ray_hit *hit, u16 ignore )
{
hit->tri = NULL;
-
bh_iter it;
bh_iter_init_ray( 0, &it, co, dir, hit->dist );
i32 idx;
- while( bh_next( bh, &it, &idx ) ){
- u32 *tri = &s->arrindices[ idx*3 ];
-
- if( s->arrvertices[tri[0]].flags & ignore ) continue;
+ while( bh_next( bh, &it, &idx ) )
+ {
+ u32 *tri = &scene->indice_buffer[ idx*3 ];
+ if( scene->vertex_buffer[tri[0]].flags & ignore )
+ continue;
v3f vs[3];
for( u32 i=0; i<3; i++ )
- v3_copy( s->arrvertices[tri[i]].co, vs[i] );
+ v3_copy( scene->vertex_buffer[tri[i]].co, vs[i] );
f32 t;
- if( ray_tri( vs, co, dir, &t, 0 ) ){
- if( t < hit->dist ){
+ if( ray_tri( vs, co, dir, &t, 0 ) )
+ {
+ if( t < hit->dist )
+ {
hit->dist = t;
hit->tri = tri;
}
}
}
- if( hit->tri ){
+ if( hit->tri )
+ {
v3f v0, v1;
-
- float *pa = s->arrvertices[hit->tri[0]].co,
- *pb = s->arrvertices[hit->tri[1]].co,
- *pc = s->arrvertices[hit->tri[2]].co;
+ f32 *pa = scene->vertex_buffer[hit->tri[0]].co,
+ *pb = scene->vertex_buffer[hit->tri[1]].co,
+ *pc = scene->vertex_buffer[hit->tri[2]].co;
v3_sub( pa, pb, v0 );
v3_sub( pc, pb, v1 );
return hit->tri?1:0;
}
-bh_tree *scene_bh_create( void *lin_alloc, scene_context *s )
+VG_TIER_1 void scene_bh_create( vg_scene *scene, bh_tree *bh, vg_stack_allocator *stack )
+{
+ u32 triangle_count = scene->indice_count / 3;
+ return bh_create( bh, &bh_system_scene, scene, triangle_count, 2, stack );
+}
+
+VG_TIER_0 void scene_mesh_bind( scene_mesh *mesh )
+{
+ glBindVertexArray( mesh->vao );
+}
+
+VG_TIER_0 void scene_mesh_free( scene_mesh *mesh )
{
- u32 triangle_count = s->indice_count / 3;
- return bh_create( lin_alloc, &bh_system_scene, s, triangle_count, 2 );
+ glDeleteVertexArrays( 1, &mesh->vao );
+ glDeleteBuffers( 1, &mesh->ebo );
+ glDeleteBuffers( 1, &mesh->vbo );
}
-#pragma once
-#include "vg/vg_bvh.h"
-#include "common.h"
-#include "model.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/scene.c"
+#else
-typedef struct scene_context scene_context;
+typedef struct scene_builder_context scene_builder_context;
typedef struct scene_vert scene_vert;
+typedef struct scene_mesh scene_mesh;
+typedef struct vg_scene vg_scene;
#pragma pack(push,1)
#pragma pack(pop)
-/*
- * 1. this should probably be a CONTEXT based approach unlike this mess.
- * take a bit of the mdl_context ideas and redo this header. its messed up
- * pretty bad right now.
- */
-
-struct scene_context
+struct vg_scene
{
- scene_vert *arrvertices;
- u32 *arrindices;
+ scene_vert *vertex_buffer;
+ u32 *indice_buffer;
+ u32 vertex_count, indice_count;
+ boxf bbx;
+};
- u32 vertex_count, indice_count,
- max_vertices, max_indices;
+struct scene_builder_context
+{
+ vg_scene scene;
+ u32 base_buffer_size;
+ void *base_buffer;
+ vg_stack_allocator vertex_stack, indice_stack;
+ mdl_submesh current_submesh;
+};
+struct scene_mesh
+{
boxf bbx;
- mdl_submesh submesh;
+ GLuint vao, vbo, ebo;
};
-extern bh_system bh_system_scene;
-bh_tree *scene_bh_create( void *lin_alloc, scene_context *s );
-int scene_raycast( scene_context *s, bh_tree *bh, v3f co, v3f dir, ray_hit *hit, u16 ignore );
-vg_async_task *scene_alloc_async( scene_context *scene, glmesh *mesh, u32 max_vertices, u32 max_indices );
-void scene_copy_slice( scene_context *ctx, mdl_submesh *sm );
-void scene_push_vert( scene_context *ctx, scene_vert *v );
-void scene_vert_pack_norm( scene_vert *vert, v3f norm, f32 blend );
-void scene_push_tri( scene_context *ctx, u32 tri[3] );
-void scene_add_mdl_submesh( scene_context *ctx, mdl_context *mdl, mdl_submesh *sm, m4x3f transform );
-void scene_set_vertex_flags( scene_context *ctx, u32 start, u32 count, u16 flags );
-void scene_supply_buffer( scene_context *ctx, void *buffer );
-void scene_init( scene_context *ctx, u32 max_vertices, u32 max_indices );
-u32 scene_mem_required( scene_context *ctx );
-void async_scene_upload( vg_async_task *task );
+VG_TIER_2 void scene_builder_init( scene_builder_context *ctx, u32 max_vertices, u32 max_indices, vg_stack_allocator *stack );
+VG_TIER_2 void scene_builder_compact_memory( scene_builder_context *ctx, vg_stack_allocator *stack );
+VG_TIER_0 void scene_vert_pack_norm( scene_vert *vert, v3f norm, f32 blend );
+VG_TIER_0 void scene_builder_add_model_submesh( scene_builder_context *ctx, vg_model *model, mdl_submesh *sm, m4x3f transform );
+VG_TIER_0 void scene_builder_push_tri( scene_builder_context *ctx, u32 tri[3] );
+VG_TIER_0 void scene_builder_push_vert( scene_builder_context *ctx, scene_vert *v );
+VG_TIER_0 void scene_builder_get_submesh( scene_builder_context *ctx, mdl_submesh *sm );
+VG_TIER_0 void scene_builder_set_vertex_flags( scene_builder_context *ctx, u32 start, u32 count, u16 flags );
+VG_TIER_2 void scene_builder_upload_async( scene_builder_context *ctx, scene_mesh *out_mesh );
+VG_TIER_0 void scene_builder_save_scene( scene_builder_context *ctx, vg_scene *out_scene );
+
+VG_TIER_0 void scene_mesh_bind( scene_mesh *mesh );
+VG_TIER_0 void scene_mesh_free( scene_mesh *mesh );
+
+VG_TIER_0 i32 scene_raycast( vg_scene *scene, bh_tree *bh, v3f co, v3f dir, ray_hit *hit, u16 ignore );
+VG_TIER_1 void scene_bh_create( vg_scene *scene, bh_tree *bh, vg_stack_allocator *stack );
+
+#endif
--- /dev/null
+VG_TIER_0 i32 rb_sphere__scene( m4x3f mtxA, f32 r,
+ m4x3f mtxB, bh_tree *scene_bh,
+ rb_ct *buf, u16 ignore )
+{
+ vg_scene *scene = scene_bh->user;
+ i32 count = 0;
+
+ boxf box;
+ v3_sub( mtxA[3], (v3f){ r,r,r }, box[0] );
+ v3_add( mtxA[3], (v3f){ r,r,r }, box[1] );
+
+ bh_iter it;
+ i32 idx;
+ bh_iter_init_box( 0, &it, box );
+
+ while( bh_next( scene_bh, &it, &idx ) )
+ {
+ u32 *ptri = &scene->indice_buffer[ idx*3 ];
+ v3f tri[3];
+
+ if( scene->vertex_buffer[ptri[0]].flags & ignore )
+ continue;
+
+ for( u32 j=0; j<3; j++ )
+ v3_copy( scene->vertex_buffer[ptri[j]].co, tri[j] );
+ buf[ count ].element_id = ptri[0];
+
+ vg_line( tri[0],tri[1],0x70ff6000 );
+ vg_line( tri[1],tri[2],0x70ff6000 );
+ vg_line( tri[2],tri[0],0x70ff6000 );
+
+ i32 contact = rb_sphere__triangle( mtxA, r, tri, &buf[count] );
+ count += contact;
+
+ if( count == 16 )
+ {
+ vg_warn( "Exceeding sphere_vs_scene capacity. Geometry too dense!\n" );
+ return count;
+ }
+ }
+ return count;
+}
+
+VG_TIER_0 i32 rb_box__scene( m4x3f mtxA, boxf bbx,
+ m4x3f mtxB, bh_tree *scene_bh,
+ rb_ct *buf, u16 ignore )
+{
+ vg_scene *scene = scene_bh->user;
+ v3f tri[3];
+
+ v3f extent, center;
+ v3_sub( bbx[1], bbx[0], extent );
+ v3_muls( extent, 0.5f, extent );
+ v3_add( bbx[0], extent, center );
+
+ f32 r = v3_length(extent);
+ boxf world_bbx;
+ v3_fill( world_bbx[0], -r );
+ v3_fill( world_bbx[1], r );
+ for( u32 i=0; i<2; i++ )
+ {
+ v3_add( center, world_bbx[i], world_bbx[i] );
+ v3_add( mtxA[3], world_bbx[i], world_bbx[i] );
+ }
+
+ m4x3f to_local;
+ m4x3_invert_affine( mtxA, to_local );
+
+ bh_iter it;
+ bh_iter_init_box( 0, &it, world_bbx );
+ i32 idx;
+ i32 count = 0;
+
+ vg_line_boxf( world_bbx, VG__RED );
+
+ while( bh_next( scene_bh, &it, &idx ) )
+ {
+ u32 *ptri = &scene->indice_buffer[ idx*3 ];
+ if( scene->vertex_buffer[ptri[0]].flags & ignore )
+ continue;
+
+ for( u32 j=0; j<3; j++ )
+ v3_copy( scene->vertex_buffer[ptri[j]].co, tri[j] );
+
+ if( rb_box_triangle_sat( extent, center, to_local, tri ) )
+ {
+ vg_line(tri[0],tri[1],0xff50ff00 );
+ vg_line(tri[1],tri[2],0xff50ff00 );
+ vg_line(tri[2],tri[0],0xff50ff00 );
+ }
+ else
+ {
+ vg_line(tri[0],tri[1],0xff0000ff );
+ vg_line(tri[1],tri[2],0xff0000ff );
+ vg_line(tri[2],tri[0],0xff0000ff );
+ continue;
+ }
+
+ v3f v0,v1,n;
+ v3_sub( tri[1], tri[0], v0 );
+ v3_sub( tri[2], tri[0], v1 );
+ v3_cross( v0, v1, n );
+
+ if( v3_length2( n ) <= 0.00001f )
+ {
+#ifdef RIGIDBODY_CRY_ABOUT_EVERYTHING
+ vg_error( "Zero area triangle!\n" );
+#endif
+ return 0;
+ }
+ v3_normalize( n );
+
+ /* find best feature */
+ f32 best = v3_dot( mtxA[0], n );
+ i32 axis = 0;
+
+ for( i32 i=1; i<3; i++ )
+ {
+ f32 c = v3_dot( mtxA[i], n );
+ if( fabsf(c) > fabsf(best) )
+ {
+ best = c;
+ axis = i;
+ }
+ }
+
+ v3f manifold[4];
+ if( axis == 0 )
+ {
+ f32 px = best > 0.0f? bbx[0][0]: bbx[1][0];
+ manifold[0][0] = px;
+ manifold[0][1] = bbx[0][1];
+ manifold[0][2] = bbx[0][2];
+ manifold[1][0] = px;
+ manifold[1][1] = bbx[1][1];
+ manifold[1][2] = bbx[0][2];
+ manifold[2][0] = px;
+ manifold[2][1] = bbx[1][1];
+ manifold[2][2] = bbx[1][2];
+ manifold[3][0] = px;
+ manifold[3][1] = bbx[0][1];
+ manifold[3][2] = bbx[1][2];
+ }
+ else if( axis == 1 )
+ {
+ f32 py = best > 0.0f? bbx[0][1]: bbx[1][1];
+ manifold[0][0] = bbx[0][0];
+ manifold[0][1] = py;
+ manifold[0][2] = bbx[0][2];
+ manifold[1][0] = bbx[1][0];
+ manifold[1][1] = py;
+ manifold[1][2] = bbx[0][2];
+ manifold[2][0] = bbx[1][0];
+ manifold[2][1] = py;
+ manifold[2][2] = bbx[1][2];
+ manifold[3][0] = bbx[0][0];
+ manifold[3][1] = py;
+ manifold[3][2] = bbx[1][2];
+ }
+ else
+ {
+ f32 pz = best > 0.0f? bbx[0][2]: bbx[1][2];
+ manifold[0][0] = bbx[0][0];
+ manifold[0][1] = bbx[0][1];
+ manifold[0][2] = pz;
+ manifold[1][0] = bbx[1][0];
+ manifold[1][1] = bbx[0][1];
+ manifold[1][2] = pz;
+ manifold[2][0] = bbx[1][0];
+ manifold[2][1] = bbx[1][1];
+ manifold[2][2] = pz;
+ manifold[3][0] = bbx[0][0];
+ manifold[3][1] = bbx[1][1];
+ manifold[3][2] = pz;
+ }
+
+ for( u32 j=0; j<4; j++ )
+ m4x3_mulv( mtxA, manifold[j], manifold[j] );
+
+ vg_line( manifold[0], manifold[1], 0xffffffff );
+ vg_line( manifold[1], manifold[2], 0xffffffff );
+ vg_line( manifold[2], manifold[3], 0xffffffff );
+ vg_line( manifold[3], manifold[0], 0xffffffff );
+
+ for( u32 j=0; j<4; j++ )
+ {
+ rb_ct *ct = buf+count;
+ v3_copy( manifold[j], ct->co );
+ v3_copy( n, ct->n );
+
+ f32 l0 = v3_dot( tri[0], n ),
+ l1 = v3_dot( manifold[j], n );
+
+ ct->p = (l0-l1)*0.5f;
+ if( ct->p < 0.0f )
+ continue;
+
+ ct->type = k_contact_type_default;
+ count ++;
+
+ if( count >= 12 )
+ return count;
+ }
+ }
+ return count;
+}
+
+/* mtxB is defined only for tradition; it is not used currently */
+VG_TIER_0 i32 rb_capsule__scene( m4x3f mtxA, rb_capsule *c,
+ m4x3f mtxB, bh_tree *scene_bh,
+ rb_ct *buf, u16 ignore )
+{
+ vg_scene *scene = scene_bh->user;
+ i32 count = 0;
+ boxf bbx;
+ v3_sub( mtxA[3], (v3f){ c->h, c->h, c->h }, bbx[0] );
+ v3_add( mtxA[3], (v3f){ c->h, c->h, c->h }, bbx[1] );
+
+
+ bh_iter it;
+ bh_iter_init_box( 0, &it, bbx );
+ i32 idx;
+ while( bh_next( scene_bh, &it, &idx ) )
+ {
+ u32 *ptri = &scene->indice_buffer[ idx*3 ];
+ if( scene->vertex_buffer[ptri[0]].flags & ignore )
+ continue;
+
+ v3f tri[3];
+ for( u32 j=0; j<3; j++ )
+ v3_copy( scene->vertex_buffer[ptri[j]].co, tri[j] );
+
+ buf[ count ].element_id = ptri[0];
+ i32 contact = rb_capsule__triangle( mtxA, c, tri, &buf[count] );
+ count += contact;
+
+ if( count >= 16 )
+ {
+ vg_warn("Exceeding capsule_vs_scene capacity. Geometry too dense!\n");
+ return count;
+ }
+ }
+
+ return count;
+}
-#pragma once
+#if defined( SR_IMPLEMENTATION )
+# include "src/scene_rigidbody.c"
+#else
-/*
- * Copyright (C) 2021-2024 Mt.ZERO Software - All Rights Reserved
- *
- * Describes intereactions between vg rigidbody objects and skaterift's scene
- * description
- */
+VG_TIER_0 i32 rb_sphere__scene( m4x3f mtxA, f32 r,
+ m4x3f mtxB, bh_tree *scene_bh,
+ rb_ct *buf, u16 ignore );
-#include "scene.h"
-#include "vg/vg_rigidbody.h"
-#include "vg/vg_rigidbody_collision.h"
-
-static int rb_sphere__scene( m4x3f mtxA, f32 r,
- m4x3f mtxB, bh_tree *scene_bh, rb_ct *buf,
- u16 ignore ){
- scene_context *sc = scene_bh->user;
-
- int count = 0;
-
- boxf box;
- v3_sub( mtxA[3], (v3f){ r,r,r }, box[0] );
- v3_add( mtxA[3], (v3f){ r,r,r }, box[1] );
-
- bh_iter it;
- i32 idx;
- bh_iter_init_box( 0, &it, box );
-
- while( bh_next( scene_bh, &it, &idx ) ){
- u32 *ptri = &sc->arrindices[ idx*3 ];
- v3f tri[3];
-
- if( sc->arrvertices[ptri[0]].flags & ignore ) continue;
-
- for( int j=0; j<3; j++ )
- v3_copy( sc->arrvertices[ptri[j]].co, tri[j] );
-
- buf[ count ].element_id = ptri[0];
-
- vg_line( tri[0],tri[1],0x70ff6000 );
- vg_line( tri[1],tri[2],0x70ff6000 );
- vg_line( tri[2],tri[0],0x70ff6000 );
-
- int contact = rb_sphere__triangle( mtxA, r, tri, &buf[count] );
- count += contact;
-
- if( count == 16 ){
- vg_warn( "Exceeding sphere_vs_scene capacity. Geometry too dense!\n" );
- return count;
- }
- }
-
- return count;
-}
-
-static int rb_box__scene( m4x3f mtxA, boxf bbx,
- m4x3f mtxB, bh_tree *scene_bh,
- rb_ct *buf, u16 ignore ){
- scene_context *sc = scene_bh->user;
- v3f tri[3];
-
- v3f extent, center;
- v3_sub( bbx[1], bbx[0], extent );
- v3_muls( extent, 0.5f, extent );
- v3_add( bbx[0], extent, center );
-
- f32 r = v3_length(extent);
- boxf world_bbx;
- v3_fill( world_bbx[0], -r );
- v3_fill( world_bbx[1], r );
- for( int i=0; i<2; i++ ){
- v3_add( center, world_bbx[i], world_bbx[i] );
- v3_add( mtxA[3], world_bbx[i], world_bbx[i] );
- }
-
- m4x3f to_local;
- m4x3_invert_affine( mtxA, to_local );
-
- bh_iter it;
- bh_iter_init_box( 0, &it, world_bbx );
- int idx;
- int count = 0;
-
- vg_line_boxf( world_bbx, VG__RED );
-
- while( bh_next( scene_bh, &it, &idx ) ){
- u32 *ptri = &sc->arrindices[ idx*3 ];
- if( sc->arrvertices[ptri[0]].flags & ignore ) continue;
-
- for( int j=0; j<3; j++ )
- v3_copy( sc->arrvertices[ptri[j]].co, tri[j] );
-
- if( rb_box_triangle_sat( extent, center, to_local, tri ) ){
- vg_line(tri[0],tri[1],0xff50ff00 );
- vg_line(tri[1],tri[2],0xff50ff00 );
- vg_line(tri[2],tri[0],0xff50ff00 );
- }
- else{
- vg_line(tri[0],tri[1],0xff0000ff );
- vg_line(tri[1],tri[2],0xff0000ff );
- vg_line(tri[2],tri[0],0xff0000ff );
- continue;
- }
-
- v3f v0,v1,n;
- v3_sub( tri[1], tri[0], v0 );
- v3_sub( tri[2], tri[0], v1 );
- v3_cross( v0, v1, n );
-
- if( v3_length2( n ) <= 0.00001f ){
-#ifdef RIGIDBODY_CRY_ABOUT_EVERYTHING
- vg_error( "Zero area triangle!\n" );
-#endif
- return 0;
- }
-
- v3_normalize( n );
-
- /* find best feature */
- f32 best = v3_dot( mtxA[0], n );
- int axis = 0;
-
- for( int i=1; i<3; i++ ){
- f32 c = v3_dot( mtxA[i], n );
-
- if( fabsf(c) > fabsf(best) ){
- best = c;
- axis = i;
- }
- }
-
- v3f manifold[4];
-
- if( axis == 0 ){
- f32 px = best > 0.0f? bbx[0][0]: bbx[1][0];
- manifold[0][0] = px;
- manifold[0][1] = bbx[0][1];
- manifold[0][2] = bbx[0][2];
- manifold[1][0] = px;
- manifold[1][1] = bbx[1][1];
- manifold[1][2] = bbx[0][2];
- manifold[2][0] = px;
- manifold[2][1] = bbx[1][1];
- manifold[2][2] = bbx[1][2];
- manifold[3][0] = px;
- manifold[3][1] = bbx[0][1];
- manifold[3][2] = bbx[1][2];
- }
- else if( axis == 1 ){
- f32 py = best > 0.0f? bbx[0][1]: bbx[1][1];
- manifold[0][0] = bbx[0][0];
- manifold[0][1] = py;
- manifold[0][2] = bbx[0][2];
- manifold[1][0] = bbx[1][0];
- manifold[1][1] = py;
- manifold[1][2] = bbx[0][2];
- manifold[2][0] = bbx[1][0];
- manifold[2][1] = py;
- manifold[2][2] = bbx[1][2];
- manifold[3][0] = bbx[0][0];
- manifold[3][1] = py;
- manifold[3][2] = bbx[1][2];
- }
- else{
- f32 pz = best > 0.0f? bbx[0][2]: bbx[1][2];
- manifold[0][0] = bbx[0][0];
- manifold[0][1] = bbx[0][1];
- manifold[0][2] = pz;
- manifold[1][0] = bbx[1][0];
- manifold[1][1] = bbx[0][1];
- manifold[1][2] = pz;
- manifold[2][0] = bbx[1][0];
- manifold[2][1] = bbx[1][1];
- manifold[2][2] = pz;
- manifold[3][0] = bbx[0][0];
- manifold[3][1] = bbx[1][1];
- manifold[3][2] = pz;
- }
-
- for( int j=0; j<4; j++ )
- m4x3_mulv( mtxA, manifold[j], manifold[j] );
-
- vg_line( manifold[0], manifold[1], 0xffffffff );
- vg_line( manifold[1], manifold[2], 0xffffffff );
- vg_line( manifold[2], manifold[3], 0xffffffff );
- vg_line( manifold[3], manifold[0], 0xffffffff );
-
- for( int j=0; j<4; j++ ){
- rb_ct *ct = buf+count;
-
- v3_copy( manifold[j], ct->co );
- v3_copy( n, ct->n );
-
- f32 l0 = v3_dot( tri[0], n ),
- l1 = v3_dot( manifold[j], n );
-
- ct->p = (l0-l1)*0.5f;
- if( ct->p < 0.0f )
- continue;
-
- ct->type = k_contact_type_default;
- count ++;
-
- if( count >= 12 )
- return count;
- }
- }
- return count;
-}
+VG_TIER_0 i32 rb_box__scene( m4x3f mtxA, boxf bbx,
+ m4x3f mtxB, bh_tree *scene_bh,
+ rb_ct *buf, u16 ignore );
/* mtxB is defined only for tradition; it is not used currently */
-static int rb_capsule__scene( m4x3f mtxA, rb_capsule *c,
- m4x3f mtxB, bh_tree *scene_bh,
- rb_ct *buf, u16 ignore ){
- int count = 0;
-
- boxf bbx;
- v3_sub( mtxA[3], (v3f){ c->h, c->h, c->h }, bbx[0] );
- v3_add( mtxA[3], (v3f){ c->h, c->h, c->h }, bbx[1] );
-
- scene_context *sc = scene_bh->user;
-
- bh_iter it;
- bh_iter_init_box( 0, &it, bbx );
- i32 idx;
- while( bh_next( scene_bh, &it, &idx ) ){
- u32 *ptri = &sc->arrindices[ idx*3 ];
- if( sc->arrvertices[ptri[0]].flags & ignore ) continue;
-
- v3f tri[3];
- for( int j=0; j<3; j++ )
- v3_copy( sc->arrvertices[ptri[j]].co, tri[j] );
-
- buf[ count ].element_id = ptri[0];
-
- int contact = rb_capsule__triangle( mtxA, c, tri, &buf[count] );
- count += contact;
-
- if( count >= 16 ){
- vg_warn("Exceeding capsule_vs_scene capacity. Geometry too dense!\n");
- return count;
- }
- }
-
- return count;
-}
+VG_TIER_0 i32 rb_capsule__scene( m4x3f mtxA, rb_capsule *c,
+ m4x3f mtxB, bh_tree *scene_bh,
+ rb_ct *buf, u16 ignore );
+#endif
{
struct script_event_world_io *inf = event->info;
world_instance *world = &_world.main;
- if( AF_STR_EQ( &world->meta.af, inf->event->pstr_recieve_event, "open" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, inf->event->pstr_recieve_event, "open" ) )
{
// TODO: Make this dynamiclly fetched from a handler for the entity itself. (or not, fuck you)
if( inf->event->flags & k_ent_event_data_const_entity_id )
while( _ent_list_iter( &iter ) )
{
ent_marker *marker = af_arritm( &world->ent_marker, iter.index );
- const char *alias = af_str( &world->meta.af, marker->pstr_alias );
+ const char *alias = af_str( world->meta.packed_strings, marker->pstr_alias );
if( !strcmp( alias, "$board_position" ) )
v3_copy( marker->transform.co, _board_maker.origin );
{
struct script_event_world_io *inf = event->info;
world_instance *world = &_world.main;
- if( AF_STR_EQ( &world->meta.af, inf->event->pstr_recieve_event, "boost" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, inf->event->pstr_recieve_event, "boost" ) )
{
// TODO: Make this dynamiclly fetched from a handler for the entity itself. (or not, fuck you)
if( inf->event->flags & k_ent_event_data_const_entity_id )
{
struct script_event_world_io *inf = event->info;
world_instance *world = &_world.main;
- if( AF_STR_EQ( &world->meta.af, inf->event->pstr_recieve_event, "explode" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, inf->event->pstr_recieve_event, "explode" ) )
{
// TODO: Make this dynamiclly fetched from a handler for the entity itself. (or not, fuck you)
if( inf->event->flags & k_ent_event_data_const_entity_id )
{
struct script_event_world_io *inf = event->info;
world_instance *world = &_world.main;
- if( AF_STR_EQ( &world->meta.af, inf->event->pstr_recieve_event, "unlock_mtzero" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, inf->event->pstr_recieve_event, "unlock_mtzero" ) )
{
- gui_notify( "\xb8 Mt.Zero Unlocked!", 8.0f, k_ui_green );
+ _gui_notify( "\xb8 Mt.Zero Unlocked!", 8.0f, k_ui_green );
}
- if( AF_STR_EQ( &world->meta.af, inf->event->pstr_recieve_event, "unlock_city" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, inf->event->pstr_recieve_event, "unlock_city" ) )
{
- gui_notify( "\xb8 Downtown Unlocked!", 8.0f, k_ui_green );
+ _gui_notify( "\xb8 Downtown Unlocked!", 8.0f, k_ui_green );
}
- if( AF_STR_EQ( &world->meta.af, inf->event->pstr_recieve_event, "unlock_valley" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, inf->event->pstr_recieve_event, "unlock_valley" ) )
{
- gui_notify( "\xb8 Valley Unlocked!", 8.0f, k_ui_green );
+ _gui_notify( "\xb8 Valley Unlocked!", 8.0f, k_ui_green );
}
}
return 1;
if( event->type == k_escript_event_allocate )
{
struct script_event_allocate *event_info = event->info;
- struct script_speed *s = VG_STACK_ALLOCATE_STRUCT( event_info->heap, struct script_speed );
+ struct script_speed *s = vg_stack_allocate( event_info->heap, sizeof(struct script_speed), 8, "Script data" );
s->ok = 0;
s->init = 0;
event_info->userdata = s;
if( event->type == k_escript_event_allocate )
{
struct script_event_allocate *event_info = event->info;
- struct script_volcano *v = VG_STACK_ALLOCATE_STRUCT( event_info->heap, struct script_volcano );
+ struct script_volcano *v = vg_stack_allocate( event_info->heap, sizeof(struct script_volcano), 8, "Script data" );
v->docks_wait = 0;
v->stopped_timer = 0.0f;
event_info->userdata = v;
struct script_event_world_io *inf = event->info;
world_instance *world = &_world.main;
- if( AF_STR_EQ( &world->meta.af, inf->event->pstr_recieve_event, "unlock_docks" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, inf->event->pstr_recieve_event, "unlock_docks" ) )
{
v->docks_wait = 1;
}
+++ /dev/null
-#pragma once
-#include "network_msg.h"
-#pragma once
-#include "vg/vg_platform.h"
+#if defined( SR_IMPLEMENTATION )
+//# include "src/shader_props.c"
+#else
enum material_render_flag
{
k_material_render_additive = 0x20
};
-struct shader_props_standard
-{
- u32 tex_diffuse;
- u32 render_flags;
-};
-
-struct shader_props_terrain
-{
- u32 tex_diffuse;
- v2f blend_offset;
- v4f sand_colour;
-};
-
-struct shader_props_vertex_blend
-{
- u32 tex_diffuse;
- v2f blend_offset;
-};
-
-struct shader_props_water
-{
- v4f shore_colour;
- v4f deep_colour;
- f32 fog_scale;
- f32 fresnel;
- f32 water_sale;
- v4f wave_speed;
-};
-
-struct shader_props_cubemapped
-{
- u32 tex_diffuse;
- u32 cubemap_entity;
- v4f tint;
-};
-
enum workshop_shader_part
{
k_workshop_shader_part_truck1,
k_workshop_shader_part_deck,
k_workshop_shader_part_max
};
-struct shader_props_workshop
+
+union shader_props
{
- u32 tex_all[k_workshop_shader_part_max];
+ struct shader_props_standard
+ {
+ u32 tex_diffuse;
+ u32 render_flags;
+ }
+ standard;
+
+ struct shader_props_terrain
+ {
+ u32 tex_diffuse;
+ v2f blend_offset;
+ v4f sand_colour;
+ }
+ terrain;
+
+ struct shader_props_vertex_blend
+ {
+ u32 tex_diffuse;
+ v2f blend_offset;
+ }
+ vertex_blend;
+
+ struct shader_props_water
+ {
+ v4f shore_colour;
+ v4f deep_colour;
+ f32 fog_scale;
+ f32 fresnel;
+ f32 water_sale;
+ v4f wave_speed;
+ }
+ water;
+
+ struct shader_props_cubemapped
+ {
+ u32 tex_diffuse;
+ u32 cubemap_entity;
+ v4f tint;
+ }
+ cubemapped;
+
+ struct shader_props_workshop
+ {
+ u32 tex_all[k_workshop_shader_part_max];
+ }
+ workshop;
};
+
extern const char *_shader_prop_workshop_keys[k_workshop_shader_part_max];
+
+#endif
-/*
- * =============================================================================
- *
- * Copyright . . . -----, ,----- ,---. .---.
- * 2021-2025 |\ /| | / | | | | /|
- * | \ / | +-- / +----- +---' | / |
- * | \ / | | / | | \ | / |
- * | \/ | | / | | \ | / |
- * ' ' '--' [] '----- '----- ' ' '---' SOFTWARE
- *
- * =============================================================================
- */
-
-#define SR_ALLOW_REWIND_HUB
-
-#ifdef _WIN32
- #include <winsock2.h>
-#endif
-
-/*
- * system headers
- * --------------------- */
-
-#include "vg/vg_opt.h"
-#include "vg/vg_loader.h"
-#include "vg/vg_io.h"
-
-#include "skaterift.h"
-#include "render.h"
-#include "world.h"
-#include "font.h"
-#include "player.h"
-#include "network.h"
-#include "menu.h"
-#include "save.h"
-#include "player_remote.h"
-#include "particle.h"
-#include "trail.h"
-#include "freecam.h"
-#include "ent_tornado.h"
-#include "ent_skateshop.h"
-#include "ent_camera.h"
-#include "world_map.h"
-#include "gui.h"
-#include "workshop.h"
-#include "audio.h"
-#include "player_render.h"
-#include "control_overlay.h"
-#include "client.h"
-#include "skaterift_script.h"
-#include "ent_challenge.h"
-#include "ent_script.h"
-#include "board_maker.h"
-#include "compass.h"
-#include "replay2.h"
-#include "user_profile.h"
-#include "ent_route.h"
-#include "ent_npc.h"
-#include "ent_list.h"
-#include "ent_atom.h"
-
-struct skaterift_globals skaterift =
-{
- .time_rate = 1.0f,
-};
-
-static void skaterift_load_player_content(void)
-{
- particle_alloc( &particles_grind, 300 );
- particle_alloc( &particles_env, 200 );
-
- player_load_animation_reference( "models/ch_none.mdl" );
- player_load_animations( "metascenes/skater.ms" );
- player_model_load( &localplayer.fallback_model, "models/ch_none.mdl", &vg.rtmem );
- player__bind();
- player_board_load( &localplayer.fallback_board, "models/board_none.mdl", &vg.rtmem );
-}
-
-int skaterift_quit_command( int argc, const char *argv[] )
-{
- if( argc >= 1 )
- if( !strcmp( argv[0], "1" ) )
- skaterift.no_save_location = 1;
-
- vg.window_should_close = 1;
- return 1;
-}
-
-static void game_load_co( vg_coroutine *co )
-{
- if( co_begin( co ) )
- {
- co_thread( co, 0, &vg.main_tasks );
- co_thread( co, 1, &vg.loader_tasks );
- }
-
- if( co_step( co, 1 ) )
- {
- vg_loader_step( render_init, NULL );
-
- /* please forgive me! */
- if( g_client.demo_mode != 2 )
- {
- u32 sz; char *drm;
- if( (drm = vg_file_read( &vg.scratch, "DRM", &sz, 1 )) )
- if( !strcmp(drm, "blibby!") )
- g_client.demo_mode = 0;
- }
-
- vg_loader_step( remote_players_init, NULL );
-
- vg_loader_step( network_init, network_end );
- vg_loader_set_user_information( "Initializing subsystems" );
- vg_loader_step( menu_init, NULL );
- vg_loader_step( _user_profile_init, NULL );
- vg_loader_step( control_overlay_init, NULL );
- vg_loader_step( world_init, NULL );
- vg_loader_step( gui_init, NULL );
- vg_loader_step( compass_init, NULL );
-
- vg_loader_step( player_init, NULL );
-
- /* content stuff */
- vg_loader_step( addon_system_init, NULL );
- vg_loader_step( skateshop_init, NULL );
- vg_loader_step( world_map_init, NULL );
- vg_loader_step( skaterift_load_player_content, NULL );
- vg_loader_step( _replay2_init, NULL );
- vg_loader_step( _ent_npc_init, NULL );
-
- vg_loader_set_user_information( "Compiling shaders" );
- vg_bake_shaders();
-
- vg_loader_set_user_information( "Loading content files" );
- vg_loader_step( audio_init, NULL );
-
- _world.default_hub_addon = _addon_mount_from_folder_path( "maps/dev_hub", k_addon_type_world, ".mdl" );
- VG_ASSERT( _world.default_hub_addon );
-
- vg_loader_set_user_information( "Mounting addons" );
- _addon_mount_content_folder( k_addon_type_player, "playermodels", ".mdl" );
- _addon_mount_content_folder( k_addon_type_board, "boards", ".mdl" );
- _addon_mount_content_folder( k_addon_type_world, "maps", ".mdl" );
- }
-
- if( co_step( co, 0 ) )
- {
- _mount_workshop_addons( NULL );
- _ent_atom_init();
- }
-
- /* stalling for workshop to complete */
- if( co_step( co, 1 ) ){}
- if( co_step( co, 0 ) ){}
-
- if( co_step( co, 1 ) )
- {
- /* initializing / loading world. */
- vg_loader_set_user_information( "Loading savedata" );
- skaterift_load_mainsave();
-
- if( skaterift.override_load_world )
- _world.load_addon = _addon_mount_from_folder_path( skaterift.override_load_world, k_addon_type_world, ".mdl" );
-
- _world.loader_instance = &_world.main;
- _world.loader_preview_mode = 0;
- _world.loader_stack = _world.stack;
-
- if( !_world.load_addon )
- {
- vg_warn( "Falling back to default hub world...\n" );
- _world.load_addon = _world.default_hub_addon;
- }
-
- _world_loader_set_addon( _world.load_addon );
- }
-
- if( co_step( co, 0 ) )
- {
- _world.loader_state = k_world_loader_ready;
-
- if( network_client.auto_connect )
- network_client.user_intent = k_server_intent_online;
- menu_at_begin();
- }
-
- if( co_step( co, 1 ) )
- {
- vg_loader_step( NULL, skaterift_autosave_synchronous );
- _vg_tower_set_flag( vg.sig_client, 1 );
- }
-
- co_end( co );
-}
-
-/*
- * UPDATE LOOP
- * ---------------------------------------------------------------------------*/
-
-static void draw_origin_axis(void)
-{
- vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 1.0f, 0.0f, 0.0f }, 0xffff0000 );
- vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 0.0f, 1.0f, 0.0f }, 0xff00ff00 );
- vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 0.0f, 0.0f, 1.0f }, 0xff0000ff );
-}
-void skaterift_change_client_world_preupdate(void);
-
-void vg_pre_update(void)
-{
- if( !_vg_tower_clearence( _vg_tower_mask(vg.sig_engine)|_vg_tower_mask(vg.sig_client) ) )
- return;
-
- skaterift_preupdate_inputs();
- world_switcher_update();
-
- if( !_vg_tower_clearence( skaterift.full_ready_mask ) )
- return;
-
- //draw_origin_axis();
- //_skaterift_script_update();
- _addon_system_pre_update();
- network_update();
-
- /* time rate */
- f32 target = 1;
- if( skaterift.activity & k_skaterift_replay )
- target = 0;
-
- if( skaterift.activity == k_skaterift_spectate )
- {
- if( button_down( k_srbind_mback ) )
- {
- vg_audio_lock();
- vg_audio_oneshot( &audio_ui[3], 1.0f, 0.0f, 0, 0 );
- vg_audio_unlock();
- menu_close(); /* sets tate to default*/
- menu_open( k_menu_page_quick );
- gui_helper_reset( k_gui_helper_mode_clear );
- localplayer.immobile = 0;
- }
- }
-
- world_update( &_world.main, localplayer.rb.co );
- _board_maker_pre_update();
-
- cutscene_update( vg.time_rate * vg.time_frame_delta );
-
- if( !((skaterift.activity == k_skaterift_menu) && (menu.page != k_menu_page_quick)) )
- player__pre_update();
-
- _replay2_pre_update();
- remote_sfx_pre_update();
-
- v3f listen_co;
- v3_copy( localplayer.rb.co, listen_co );
- if( skaterift.activity & k_skaterift_menu )
- {
- if( menu.page != k_menu_page_quick )
- {
- if( menu.bg_cam )
- v3_copy( menu.bg_cam->co, listen_co );
- else target = 0;
- }
- }
- audio_ambient_sprites_update( &_world.main, listen_co );
-
- vg_slewf( &skaterift.time_rate, target, vg.time_frame_delta * (1.0f/0.3f) );
- vg.time_rate = vg_smoothstepf( skaterift.time_rate );
-}
-
-void vg_fixed_update(void)
-{
- if( !_vg_tower_clearence( skaterift.full_ready_mask ) )
- return;
-
- world_routes_fixedupdate( &_world.main );
- player__update();
-}
-
-void vg_post_update(void)
-{
- if( !_vg_tower_clearence( skaterift.full_ready_mask ) )
- return;
-
- player__post_update();
-
- float dist;
- int sample_index;
- world_audio_sample_distances( localplayer.rb.co, &sample_index, &dist );
-
- vg_audio_lock();
- vg_dsp.echo_distances[sample_index] = dist;
-
- v3f ears = { 1.0f,0.0f,0.0f };
- m3x3_mulv( g_render.cam.transform, ears, ears );
- v3_copy( ears, _vg_audio.controls.listener_right_ear_direction );
- v3_copy( g_render.cam.transform[3], _vg_audio.controls.listener_position );
-
- if( localplayer.gate_waiting )
- m4x3_mulv( localplayer.gate_waiting->transport, _vg_audio.controls.listener_position, _vg_audio.controls.listener_position );
-
- v3_copy( localplayer.rb.v, _vg_audio.controls.listener_velocity );
- vg_audio_unlock();
-
- skaterift_autosave_update();
-
- localplayer.immunity = 0;
-}
-
-/*
- * RENDERING
- * ---------------------------------------------------------------------------*/
-
-static void render_player_transparent(void)
-{
- if( (skaterift.activity == k_skaterift_menu) &&
- (menu.page == k_menu_page_main) &&
- (menu.main_index == k_menu_main_guide) )
- {
- return;
- }
-
- if( skaterift.activity == k_skaterift_replay )
- return;
-
- static vg_camera small_cam; /* DOES NOT NEED TO BE STATIC BUT MINGW
- SAIS OTHERWISE */
-
- m4x3_copy( g_render.cam.transform, small_cam.transform );
-
- small_cam.fov = g_render.cam.fov;
- small_cam.nearz = 0.05f;
- small_cam.farz = 60.0f;
-
- vg_camera_update_view( &small_cam );
- vg_camera_update_projection( &small_cam, vg.window_x, vg.window_y );
- vg_camera_finalize( &small_cam );
-
- /* Draw player to window buffer and blend background ontop */
- player__render( &small_cam );
-}
-
-static void render_scene(void)
-{
-}
-
-static void skaterift_composite_maincamera(void)
-{
- /* world entity driven camera
- * ------------------------------------------------------------------------------ */
- if( _world.entity_set_camera )
- {
- _world.entity_set_camera = 0;
- _world.entity_camera_modulate = vg_minf( 1.0f, _world.entity_camera_modulate+vg.time_frame_delta );
- }
- else
- {
- _world.entity_camera_modulate = vg_maxf( 0.0f, _world.entity_camera_modulate-vg.time_frame_delta );
- }
-
- vg_camera_lerp( &localplayer.cam, &_world.entity_driven_camera,
- vg_smoothstepf(_world.entity_camera_modulate), &g_render.cam );
-
- /* replay camera
- * ------------------------------------------------------------------ */
- if( skaterift.activity == k_skaterift_replay )
- {
- _replay2_get_camera( &g_render.cam );
- }
-
- if( skaterift.activity == k_skaterift_spectate )
- {
- _network_get_spectate_cam( &g_render.cam );
- }
-
- g_render.cam.nearz = 0.1f;
- g_render.cam.farz = 2100.0f;
-
- /* menu override camera
- * -------------------------------------------------------------------- */
- if( (skaterift.activity == k_skaterift_menu) && menu.bg_cam )
- {
- ent_camera_unpack( menu.bg_cam, &g_render.cam );
- }
-
- /* cutscene camera TODO: Fix the action camera
- * ---------------------------------------------------------------- */
- ent_camera *cs_cam = _cutscene_active_camera();
- if( cs_cam )
- ent_camera_unpack( cs_cam, &g_render.cam );
-
- world_map_get_transition_cam( &g_render.cam );
-
- vg_camera_update_transform( &g_render.cam );
-
- vg_camera_update_view( &g_render.cam );
- vg_camera_update_projection( &g_render.cam, vg.window_x, vg.window_y );
- vg_camera_finalize( &g_render.cam );
-}
-
-static void render_main_game(void)
-{
- if( (_cutscene.state >= k_cutscene_state_ready) && _cutscene.player_binding )
- {
- struct cs_instance *inst = _cutscene.player_binding;
- struct skeleton *sk = &localplayer.skeleton;
- for( u32 i=0; i<sk->bone_count; i ++ )
- m4x3_copy( inst->skinning_data[i], localplayer.final_mtx[i] );
- }
- else if( skaterift.activity == k_skaterift_replay ){}
- else
- {
- player__animate();
- _replay2_record_local_frame();
- }
-
- animate_remote_players();
- player__pre_render();
-
- skaterift_composite_maincamera();
-
- bool render_actual_game = !menu_viewing_map();
- bool render_stenciled = 0;
-
- if( render_actual_game )
- {
- world_instance *world = &_world.main;
- render_world_cubemaps( world );
- }
-
- /* variable res target */
- vg_framebuffer_bind( _vg_render.fb_main, _vg_render.scale );
- glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
- glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT );
-
- if( !render_actual_game )
- {
- render_world_map();
-
- if( world_map_get_transition_cam(NULL) )
- {
- glEnable( GL_STENCIL_TEST );
- glDisable( GL_DEPTH_TEST );
- glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
- glStencilFunc( GL_ALWAYS, 1, 0xFF );
- glStencilMask( 0xFF );
-
- shader_blit_transition_use();
- shader_blit_transition_uInverseRatio( (v2f){1.0f,1.0f} );
- shader_blit_transition_uT( -(sqrtf(2)+0.5f) * world_map.spawn_timer );
- render_fsquad();
- render_stenciled = 1;
- render_actual_game = 1;
- }
- }
-
- if( render_actual_game )
- {
- /* Draw world */
- glEnable( GL_DEPTH_TEST );
- world_prerender( &_world.main );
-
- render_world( &_world.main, &g_render.cam, render_stenciled, 0, 1, 1, _vg_render.fb_main );
-
- particle_system_update( &particles_grind, vg.time_delta );
- //particle_system_debug( &particles_grind );
- particle_system_prerender( &particles_grind );
- particle_system_render( &particles_grind, &g_render.cam );
-
- ent_tornado_pre_update();
- particle_system_update( &particles_env, vg.time_delta );
- particle_system_prerender( &particles_env );
- particle_system_render( &particles_env, &g_render.cam );
-
- player_glide_render_effects( &g_render.cam );
- }
-
- glEnable( GL_DEPTH_TEST );
-
- /* full res target */
- glBindFramebuffer( GL_FRAMEBUFFER, 0 );
- glViewport( 0,0, vg.window_x, vg.window_y );
-
- if( render_actual_game && !render_stenciled )
- {
- render_player_transparent(); /* needs to read the depth buffer before we fuck
- it up with the oblique rendering inside the
- portals */
-
- /* continue with variable rate */
- vg_framebuffer_bind( _vg_render.fb_main, _vg_render.scale );
- render_world_gates( &_world.main, &g_render.cam, _vg_render.fb_main );
- }
-
- /* composite */
- if( (skaterift.activity == k_skaterift_menu) && menu.bg_blur )
- v2_muls( (v2f){ 0.04f, 0.001f }, 1.0f-skaterift.time_rate, g_render.blur_override );
- else
- v2_zero( g_render.blur_override );
-
- vg_postprocess_to_screen( _vg_render.fb_main );
- cutscene_render_fadeout();
-
- if( gui.helper_count == 0 )
- control_overlay_render();
-}
-
-void vg_render(void)
-{
- if( !_vg_tower_clearence( skaterift.full_ready_mask ) )
- {
- vg_loader_render();
- return;
- }
-
- glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-
- glViewport( 0,0, vg.window_x, vg.window_y );
- glDisable( GL_DEPTH_TEST );
- glDisable( GL_BLEND );
-
- glClearColor( 1.0f, 0.0f, 0.0f, 0.0f );
- glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
-
- render_main_game();
- m4x4_copy( g_render.cam.mtx.pv, vg.pv );
-
- /* Other shite */
- glDisable(GL_BLEND);
- glDisable(GL_DEPTH_TEST);
- vg_lines_drawall();
- glViewport( 0,0, vg.window_x, vg.window_y );
-
- gui_render_icons();
-
- compass_render_texture();
-}
-
-void vg_gui( ui_context *ctx )
-{
- if( !_vg_tower_clearence( skaterift.full_ready_mask ) )
- return;
-
- glBindFramebuffer( GL_FRAMEBUFFER, 0 );
- glViewport( 0,0, vg.window_x, vg.window_y );
-
- gui_draw( ctx );
- compass_render_imgui( ctx );
-
- if( k_light_editor )
- imgui_world_light_edit( ctx, &_world.main );
-
- vg_ui.tex_bg = _vg_render.fb_main->attachments[0].id;
- vg_framebuffer_inverse_ratio( _vg_render.fb_main, vg_ui.bg_inverse_ratio );
-
- _cutscene_gui( ctx );
- _board_maker_ui( ctx );
- menu_gui( ctx );
- player__im_gui( ctx );
- world_instance *world = &_world.main;
-
- if( skaterift.activity != k_skaterift_replay )
- {
- world_routes_imgui( ctx, world );
- _ent_route_imgui( ctx );
- }
- _replay2_imgui( ctx );
- workshop_form_gui( ctx );
- world_gui( ctx, world );
-
- if( menu_viewing_map() )
- {
- remote_players_imgui_world( ctx, &_world.main, vg.pv, 2000.0f, 0 );
- //remote_players_imgui_lobby( ctx );
- }
- else
- {
- remote_players_chat_imgui( ctx ); /* TODO: conditional */
- remote_players_imgui_world( ctx, &_world.main, vg.pv, 100.0f, 1 );
- }
-}
-
-void vg_framebuffer_resize( int w, int h )
-{
-}
-
-#include "vg/vg_ui/filebrowser.c"
-#include "addon.c"
-#include "addon_types.c"
-#include "audio.c"
-#include "ent_challenge.c"
-#include "ent_glider.c"
-#include "entity.c"
-#include "ent_objective.c"
-#include "ent_region.c"
-#include "ent_relay.c"
-#include "ent_route.c"
-#include "ent_skateshop.c"
-#include "ent_tornado.c"
-#include "ent_traffic.c"
-#include "ent_prop.c"
-#include "ent_script.c"
-#include "freecam.c"
-#include "menu.c"
-#include "network.c"
-#include "particle.c"
-#include "player_basic_info.c"
-#include "player.c"
-#include "player_common.c"
-#include "player_dead.c"
-#include "player_effects.c"
-#include "player_glide.c"
-#include "player_ragdoll.c"
-#include "player_remote.c"
-#include "player_render.c"
-#include "player_skate.c"
-#include "player_walk.c"
-#include "render.c"
-#include "save.c"
-#include "scene.c"
-#include "trail.c"
-#include "workshop.c"
-#include "world_audio.c"
-#include "world.c"
-#include "world_entity.c"
-#include "world_gate.c"
-#include "world_gen.c"
-#include "world_load.c"
-#include "world_map.c"
-#include "world_physics.c"
-#include "world_render.c"
-#include "world_routes.c"
-#include "world_routes_ui.c"
-#include "world_sfd.c"
-#include "world_volumes.c"
-#include "world_water.c"
-#include "array_file.c"
-#include "model.c"
-#include "metascene.c"
-#include "control_overlay.c"
-#include "ent_camera.c"
-#include "skaterift_script.c"
-#include "board_maker.c"
-#include "compass.c"
-#include "replay2.c"
-#include "user_profile.c"
-#include "ent_npc.c"
-#include "ent_list.c"
-#include "ent_cutscene.c"
-#include "ent_atom.c"
-
-static void _handle_vg_signal( vg_signal_id id, bool state )
-{
- if( (id == vg.sig_engine) && state )
- {
- //vg_audio.always_keep_compressed = 1;
- co_run( game_load_co, NULL );
- }
-}
-
-int main( int argc, const char *argv[] )
-{
- vg_init( argc, argv, "Voyager Game Engine" );
- vg_stack_init( &vg.rtmem, NULL, VG_MB(200), "RT Memory" );
- vg_stack_set_flags( &vg.rtmem, VG_STACK_ALLOCATOR_METADATA );
- vg_stack_init( &vg.scratch, NULL, VG_MB(10), "Scratch" );
-
- network_set_host( "skaterift.com", NULL );
-
- {
- const char *arg;
- if( vg_long_opt( "noauth", "Disable server authentication" ) )
- network_client.auth_mode = eServerModeNoAuthentication;
-
- if( (arg = vg_long_opt_arg( "server", "Specify server address" )) )
- network_set_host( arg, NULL );
-
- if( vg_long_opt( "demo", "Turn demo mode on" ) )
- g_client.demo_mode = 2;
-
- if( (arg = vg_long_opt_arg( "world", "Specify path to world to load" )) )
- skaterift.override_load_world = arg;
- }
-
- skaterift.sig_world = _vg_tower_create_signal( "World Loaded" );
- skaterift.full_ready_mask = _vg_tower_mask( skaterift.sig_world ) |
- _vg_tower_mask( vg.sig_engine ) |
- _vg_tower_mask( vg.sig_client );
- _vg_tower_register_trigger( _vg_tower_mask( vg.sig_engine ), _handle_vg_signal );
-
- vg_console_reg_cmd( "quit", skaterift_quit_command, NULL );
- vg_console_reg_cmd( "load_world", skaterift_load_world_command, NULL );
- vg_console_reg_var( "immobile", &localplayer.immobile, k_var_dtype_i32, 0 );
- vg_console_reg_var( "allow_resume", &skaterift.allow_replay_resume, k_var_dtype_i32, VG_VAR_CHEAT );
- vg_console_reg_var( "boost_scale", &skaterift.boost_scale, k_var_dtype_f32, VG_VAR_CHEAT );
-
- /* TODO Modules that do this automatically.... */
- render_register();
- remote_players_register();
- network_register();
- menu_register();
- control_overlay_register();
- world_render_register();
- gui_register();
- compass_register();
- player_register();
- player_ragdoll_register();
- cutscene_register();
- workshop_register();
- ent_tornado_register();
- _replay2_register();
- _ent_atom_register();
- _ent_challenge_register();
-
- _steam_api.demo_mode = g_client.demo_mode; // FIXME Fuck you
- _steam_api.cb_connection_changed = cb_skaterift_connection_changed;
- _steam_api.cb_persona_changed = cb_skaterift_persona_changed;
-
- vg_run();
- return 0;
-}
+++ /dev/null
-#pragma once
-#define SKATERIFT
-#define SKATERIFT_APPID 2103940
-
-#define SKATERIFT_WORLD_READY 0x10000
-
-#include "vg/vg_engine.h"
-#include "vg/vg_camera.h"
-
-enum skaterift_rt
-{
- k_skaterift_rt_workshop_preview,
- k_skaterift_rt_server_status,
- k_skaterift_rt_max
-};
-
-struct skaterift_globals
-{
- f32 time_rate;
-
- enum skaterift_activity {
- k_skaterift_default = 0x00, /* regular playing */
- k_skaterift_replay = 0x01,
- k_skaterift_spectate = 0x02,
- k_skaterift_menu = 0x04,
- k_skaterift_activity_max = 0x8
- }
- activity;
-
- GLuint rt_textures[k_skaterift_rt_max];
-
- u32 achievements;
- i32 allow_replay_resume;
- vg_signal_id sig_world;
- u64 full_ready_mask;
-
- const char *override_load_world;
-
- f32 boost_scale;
- bool no_save_location;
-}
-extern skaterift;
--- /dev/null
+#if defined( _WIN32 )
+ #include <winsock2.h>
+ #include <ws2tcpip.h>
+#else
+ #include <sys/socket.h>
+ #include <sys/types.h>
+ #include <netdb.h>
+#endif
+
+/* Core system level ------------------------------------------------------------------------------------------------ */
+
+#if defined( SR_ALL )
+# include "addon_types.h"
+# include "addon.h"
+#endif
+
+#if defined( SR_MODEL ) || defined( SR_ALL )
+# include "array_file.h"
+# include "shader_props.h"
+# include "model.h"
+#endif
+
+#if defined( SR_ALL )
+/* TODO: entity needs to be split -> model.h + some kind of helper logic file */
+# include "entity.h"
+
+# include "client.h"
+# include "demo_check.h"
+
+/* graphics */
+# include "render.h"
+# include "depth_compare.h"
+# include "particle.h"
+# include "trail.h"
+# include "font.h"
+# include "scene.h"
+# include "scene_rigidbody.h"
+# include "metascene.h"
+
+# include "atom.h"
+# include "audio.h"
+# include "compass.h"
+# include "control_overlay.h"
+# include "input.h"
+# include "cutscene.h"
+# include "gui.h"
+
+# include "network_msg.h"
+# include "network_common.h"
+# include "network.h"
+# include "network_compression.h"
+# include "network_requests.h"
+
+# include "replay2.h"
+# include "save2.h"
+# include "user_profile.h"
+
+/* World level ------------------------------------------------------------------------------------------------------ */
+# include "world.h"
+# include "world_audio.h"
+# include "world_entity.h"
+# include "world_gate.h"
+# include "world_gen.h"
+# include "world_info.h"
+# include "world_load.h"
+# include "world_map.h"
+# include "world_physics.h"
+# include "world_render.h"
+# include "world_routes.h"
+# include "world_routes_ui.h"
+# include "world_sfd.h"
+# include "world_volumes.h"
+# include "world_water.h"
+
+# include "ent_atom.h"
+# include "ent_camera.h"
+# include "ent_challenge.h"
+# include "ent_cutscene.h"
+# include "ent_glider.h"
+# include "ent_list.h"
+# include "ent_npc.h"
+# include "ent_objective.h"
+# include "ent_prop.h"
+# include "ent_region.h"
+# include "ent_relay.h"
+# include "ent_route.h"
+# include "ent_script.h"
+# include "ent_skateshop.h"
+# include "ent_tornado.h"
+# include "ent_traffic.h"
+
+# include "board_maker.h"
+
+/* Player lavel ----------------------------------------------------------------------------------------------------- */
+# include "player_api.h"
+# include "player_basic_info.h"
+# include "player_common.h"
+# include "player_render.h"
+# include "player_effects.h"
+
+# include "player_dead.h"
+# include "player_glide.h"
+# include "player_ragdoll.h"
+# include "player_skate.h"
+# include "player_walk.h"
+
+# include "player.h"
+# include "player_remote.h"
+
+# include "menu.h"
+# include "workshop.h"
+#endif
+
+#if defined( SR_GAMESERVER )
+# include "gameserver.h"
+# include "gameserver_database.h"
+# include "gameserver_db.h"
+# include "gameserver_monitor.h"
+# include "gameserver_replay.h"
+# include "gameserver_requests.h"
+#endif
+++ /dev/null
-#if 0
-
-#include "ent_script.h"
-
-const char *_script_linear_story[] =
-{
- "start",
- "volc",
- "volc:tutorial",
- "volc:leaving",
-
- "mz",
- /* NOTES: we need to block the player in to force them to talk to mike so they don't get lost? Or at least put
- * mike right in the way of where you gotta go. Perhaps on the docks.
- */
-
- "mz:town_region",
- "mz:battery_jump",
- "mz:leaving_pt1",
- "mz:start_pt2",
- "mz:megapark_region",
- "mz:leaving_pt2",
-
- "city",
- "city:main_region",
- "city:finale",
- "city:leaving",
-
- "valley",
- "valley:main_region",
- "valley:rocket_inspection",
- "valley:cave",
- "valley:finale",
- "valley:leaving",
-
- NULL
-};
-
-struct script_save_atom
-{
- const char *alias;
-
- enum save_atom_type
- {
- k_atom_type_numeric,
- k_atom_type_enum
- }
- type;
-
- const char **enum_values;
- u64 status;
-}
-_skaterift_script_savedata[] =
-{
- { "story", k_atom_type_enum, _script_linear_story },
- { "unlock_docks_view" },
-
- { "unlock_valley_view" },
- { "unlock_mtzero_view" },
- { "unlock_city_view" },
-
- { "board_maker_unlock" },
- { "board_maker_hub_view" },
-
- { "ch1s3_view" },
- { "ch1s3b_view" },
- { "ch1s4_view" },
- { "ch1s5_view" },
-
-#if 0
- { "board_maker_unlock" },
- { "board_maker_hub_view" },
- { "intro_view" },
- { "hub_info_view" },
-
- { "ch1s2_view" },
- { "ch1s3_view" },
- { "ch1s3b_view" },
- { "ch1s4_view" },
- { "ch1s5_view" },
- { "ch1s6a_view" },
- { "unlock_docks_view" },
-
- { "unlock_mtzero" },
- { "ch2s1_view" },
- { "ch2s2_view" },
- { "ch2s3_view" },
- { "battery_jump_view" },
- { "ch2s4_view" },
- { "ch2s5_view" }, /* is the trigger for the second map */
- { "ch2s6_view" },
- { "ch2e1_view" },
-
- { "unlock_city" },
- { "unlock_city_view" },
- { "ch3s1_view" },
- { "ch3s2_view" },
- { "ch3s3_view" },
- { "city_finale" },
-
- { "unlock_valley" },
-
- { "valley_progress" },
-
- { "ch4s1a_view" },
- { "ch4s2_view" },
- { "valley_cave" },
- { "ch4s1_view" },
- { "valley_finale" },
- { "ch4s3_view" },
- { "rocket_launch_view" },
-
- { "unlock_venus" },
-#endif
-};
-
-struct script_save_atom *_skaterift_get_atom( const char *alias )
-{
- for( u32 i=0; i<VG_ARRAY_LEN( _skaterift_script_savedata ); i ++ )
- {
- struct script_save_atom *atom = &_skaterift_script_savedata[i];
- if( !strcmp( alias, atom->alias ) )
- return atom;
- }
- return NULL;
-}
-
-u64 _skaterift_atom_enum_index( const char *atom_alias, const char *value, u64 fallback_value )
-{
- struct script_save_atom *atom = _skaterift_get_atom( atom_alias );
- if( !atom )
- {
- vg_error( "No atom aliased '%s'\n", atom_alias );
- return 0;
- }
-
- VG_ASSERT( atom->type == k_atom_type_enum );
- if( value )
- {
- for( u32 i=0; i<32; i ++ )
- {
- if( !atom->enum_values[i] )
- {
- vg_warn( "Atom '%s' does't contain the value '%s'\n", atom->alias, value );
- return fallback_value;
- }
- if( !strcmp( atom->enum_values[i], value ) )
- return i;
- }
- vg_warn( "Atom '%s' exceeds max enum values (%u)\n", atom->alias, 32 );
- }
- return fallback_value;
-}
-
-u64 _skaterift_atom_status( const char *atom_alias )
-{
- struct script_save_atom *atom = _skaterift_get_atom( atom_alias );
- if( !atom )
- {
- vg_error( "No atom aliased '%s'\n", atom_alias );
- return 0;
- }
- else return atom->status;
-}
-
-void _skaterift_atom_set( const char *atom_alias, u64 value )
-{
- struct script_save_atom *atom = _skaterift_get_atom( atom_alias );
- if( !atom )
- {
- vg_error( "No atom aliased '%s'\n", atom_alias );
- return;
- }
-
- atom->status = value;
-
-#if 0
- struct script_event_atom_changed info;
- info.alias = atom_alias;
- info.value = value;
- struct ent_script_event event;
- event.type = k_escript_event_atom_changed;
- event.info = &info;
- ent_script_propogate_event( &_world.main, &event );
-#endif
-}
-
-void _skaterift_atom_set_enum( const char *atom_alias, const char *value )
-{
- _skaterift_atom_set( atom_alias, _skaterift_atom_enum_index( atom_alias, value, 0 ) );
-}
-
-void _skaterift_script_write_savedata( vg_msg *sav )
-{
- for( u32 i=0; i<VG_ARRAY_LEN( _skaterift_script_savedata ); i ++ )
- {
- struct script_save_atom *atom = &_skaterift_script_savedata[i];
- if( atom->type == k_atom_type_numeric )
- vg_msg_wkvnum( sav, atom->alias, k_vg_msg_u64, 1, &atom->status );
- else
- vg_msg_wkvstr( sav, atom->alias, atom->enum_values[ atom->status ] );
- }
-}
-
-void _skaterift_script_load_savedata( vg_msg *sav )
-{
- for( u32 i=0; i<VG_ARRAY_LEN( _skaterift_script_savedata ); i ++ )
- {
- struct script_save_atom *atom = &_skaterift_script_savedata[i];
- if( atom->type == k_atom_type_numeric )
- vg_msg_getkvintg( sav, atom->alias, k_vg_msg_u64, &atom->status, NULL );
- else
- atom->status = _skaterift_atom_enum_index( atom->alias, vg_msg_getkvstr( sav, atom->alias ), 0 );
- }
-}
-
-/* script events
- * ------------------------------------------------------------------------------------------------------------- */
-
-bool on_cutscene_marker( ent_script_event *event, const char *marker )
-{
- if( event->type != k_escript_event_allocate )
- {
- if( _cutscene.state == k_cutscene_state_playing )
- {
- if( _cutscene.marker_this_frame )
- {
- if( vg_str_eq( marker, _cutscene.marker_this_frame ) )
- return 1;
- }
- }
- }
- return 0;
-}
-
-bool on_world_start( ent_script_event *event )
-{
- return event->type == k_escript_event_world_start;
-}
-
-bool on_atom_changed( ent_script_event *event, const char *atom_alias, u64 *out_value )
-{
- if( event->type == k_escript_event_atom_changed )
- {
- struct script_event_atom_changed *atom_info = event->info;
- if( !strcmp( atom_alias, atom_info->alias ) )
- {
- *out_value = atom_info->value;
- return 1;
- }
- }
- else if( event->type == k_escript_event_world_start )
- {
- *out_value = _skaterift_atom_status( atom_alias );
- return 1;
- }
-
- return 0;
-}
-
-#if 0
-bool on_function_trigger( ent_script_event *event, i32 function_id )
-{
- if( event->type == k_escript_event_call )
- {
- struct script_event_call *call_info = event->info;
- if( call_info->function_id == function_id )
- return 1;
- }
-
- return 0;
-}
-
-bool on_atom_once( ent_script_event *event, const char *atom_alias )
-{
- if( event->type != k_escript_event_allocate )
- {
- if( _skaterift_atom_status( atom_alias ) != 1 )
- {
- _skaterift_atom_set( atom_alias, 1 );
- return 1;
- }
- }
-
- return 0;
-}
-#endif
-
-#include "scripts/generic.c"
-#include "scripts/blocker_break.c"
-
-#include "scripts/heaven.c"
-#include "scripts/hub.c"
-#include "scripts/tutorial_island.c"
-#include "scripts/mtzero.c"
-#include "scripts/city.c"
-#include "scripts/valley.c"
-
-#include "scripts/cutscene.c"
-#include "scripts/explode.c"
-
-/* console eventts
- * ------------------------------------------------------------------------------------------------------------- */
-
-static int _skaterift_script_ccmd( int argc, const char *argv[] )
-{
- if( argc < 2 )
- {
- vg_error( "Usage: script <command> <data name> <optional set-value>\n" );
- return 0;
- }
-
- bool all = 0;
- if( !strcmp( argv[1], "all" ) )
- all = 1;
-
- world_instance *world = &_world.main;
-
- if( !strcmp( argv[0], "atom" ) )
- {
- for( u32 i=0; i<VG_ARRAY_LEN( _skaterift_script_savedata ); i ++ )
- {
- struct script_save_atom *atom = &_skaterift_script_savedata[i];
- if( all || !strcmp( argv[1], atom->alias ) )
- {
- if( argc==3 )
- {
- u64 value = 0;
- if( atom->type == k_atom_type_numeric )
- value = atol(argv[2]);
- else
- value = _skaterift_atom_enum_index( atom->alias, argv[2], atom->status );
- _skaterift_atom_set( atom->alias, value );
- }
- else
- {
- if( atom->type == k_atom_type_numeric )
- vg_info( "%s: %lu\n", atom->alias, atom->status );
- else
- vg_info( "%s: '%s' (%lu)\n", atom->alias, atom->enum_values[ atom->status ], atom->status );
- }
- }
- }
-
- return 1;
- }
- else if( !strcmp( argv[0], "challenge" ) )
- {
- u32 index = 0;
- for( u32 i=0; i<af_arrcount( &world->ent_challenge ); i ++ )
- {
- ent_challenge *challenge = af_arritm( &world->ent_challenge, i );
- const char *alias = af_str( &world->meta.af, challenge->pstr_alias );
-
- if( all || (atoi( argv[1] ) == index) )
- {
- if( argc==3 )
- {
- challenge->status = atoi( argv[2] );
- ent_region_re_eval( world );
-
- struct ent_script_event event;
- struct script_event_completion_changed inf = {
- .entity_id = mdl_entity_id( k_ent_challenge, i ),
- .completion_flags = 0
- };
- event.type = k_escript_event_completion_changed;
- event.info = &inf;
- ent_script_propogate_event( world, &event );
- }
- else
- vg_info( "[challenge %u '%s'] %u\n", index, alias, challenge->status );
- }
-
- index ++;
- }
- for( u32 i=0; i<af_arrcount( &world->ent_route ); i ++ )
- {
- ent_route *route = af_arritm( &world->ent_route, i );
- const char *alias = af_str( &world->meta.af, route->pstr_name );
-
- if( all || (atoi( argv[1] ) == index) )
- {
- if( argc==3 )
- {
- route->flags &= ~((u32)(k_ent_route_flag_achieve_gold|k_ent_route_flag_achieve_silver));
-
- if( !strcmp( argv[2], "silver" ) )
- route->flags |= (u32)(k_ent_route_flag_achieve_silver);
-
- if( !strcmp( argv[2], "gold" ) )
- route->flags |= (u32)(k_ent_route_flag_achieve_gold|k_ent_route_flag_achieve_silver);
- ent_region_re_eval( world );
-
- struct ent_script_event event;
- struct script_event_completion_changed inf = {
- .entity_id = mdl_entity_id( k_ent_route, i ),
- .completion_flags = route->flags
- };
- event.type = k_escript_event_completion_changed;
- event.info = &inf;
- ent_script_propogate_event( world, &event );
- }
- else
- vg_info( "[route %u '%s'] %s%s\n", index, alias,
- (route->flags & k_ent_route_flag_achieve_silver? "SILVER": "_____"),
- (route->flags & k_ent_route_flag_achieve_gold? "_GOLD": "_____" ) );
- }
-
- index ++;
- }
- return 1;
- }
- else if( !strcmp( argv[0], "trigger" ) )
- {
- if( !strcmp( argv[1], "start" ) )
- {
- ent_script_start( &_world.main );
- return 1;
- }
- else
- {
- vg_error( "Dont know event '%s'.\n", argv[1] );
- return 0;
- }
- }
- else
- {
- vg_error( "'%s' is not a command\n", argv[0] );
- return 0;
- }
-}
-
-static void _skaterift_script_ccmd_poll( int argc, const char *argv[] )
-{
- const char *term = argv[argc-1];
- world_instance *world = &_world.main;
-
- if( argc == 1 )
- {
- console_suggest_score_text( "atom", term, 0 );
- console_suggest_score_text( "trigger", term, 0 );
- console_suggest_score_text( "challenge", term, 0 );
- }
- else if( argc == 2 )
- {
- if( !strcmp( argv[0], "atom" ) )
- {
- console_suggest_score_text( "all", term, 0 );
- for( u32 i=0; i<VG_ARRAY_LEN( _skaterift_script_savedata ); i ++ )
- {
- struct script_save_atom *atom = &_skaterift_script_savedata[i];
- console_suggest_score_text( atom->alias, term, 0 );
- }
- }
- else if( !strcmp( argv[0], "trigger" ) )
- {
- console_suggest_score_text( "start", term, 0 );
- }
- else if( !strcmp( argv[0], "challenge" ) )
- {
- // CANT DO THIS WHILE WE DONT HAVE STRING ESCAPING IN THE CONSOLE
-#if 0
- for( u32 i=0; i<af_arrcount( &world->ent_challenge ); i ++ )
- {
- ent_challenge *challenge = af_arritm( &world->ent_challenge, i );
- console_suggest_score_text( af_str( &world->meta.af, challenge->pstr_alias ), term, 0 );
- }
- for( u32 i=0; i<af_arrcount( &world->ent_route ); i ++ )
- {
- ent_route *route = af_arritm( &world->ent_route, i );
- console_suggest_score_text( af_str( &world->meta.af, route->pstr_name ), term, 0 );
- }
-#endif
- }
- }
- else if( argc == 3 )
- {
- if( !strcmp( argv[0], "atom" ) )
- {
- if( strcmp( argv[1], "all" ) )
- {
- struct script_save_atom *atom = _skaterift_get_atom( argv[1] );
- if( atom->type == k_atom_type_enum )
- {
- for( u32 i=0; i<32; i ++ )
- {
- if( !atom->enum_values[i] )
- break;
- console_suggest_score_text( atom->enum_values[i], term, 0 );
- }
- }
- }
- }
- else if( !strcmp( argv[0], "challenge" ) )
- {
- // CANT DO THIS WHILE WE DONT HAVE STRING ESCAPING IN THE CONSOLE
-#if 0
- for( u32 i=0; i<af_arrcount( &world->ent_route ); i ++ )
- {
- ent_route *route = af_arritm( &world->ent_route, i );
- const char *alias = af_str( &world->meta.af, route->pstr_name );
- if( !strcmp( argv[1], alias ) )
- {
- console_suggest_score_text( "silver", term, 0 );
- console_suggest_score_text( "gold", term, 0 );
- break;
- }
- }
-#endif
- }
- }
-}
-
-void _skaterift_script_init(void)
-{
- vg_console_reg_cmd( "script", _skaterift_script_ccmd, _skaterift_script_ccmd_poll );
-}
-
-
-#endif
+++ /dev/null
-#pragma once
-#if 0
-#include "ent_script.h"
-#define ATOM_MAX 0xfffffffffffffffflu
-
-void _skaterift_script_init(void);
-void _skaterift_script_write_savedata( vg_msg *sav );
-void _skaterift_script_load_savedata( vg_msg *sav );
-
-u64 _skaterift_atom_status( const char *atom_alias );
-u64 _skaterift_atom_enum_index( const char *atom_alias, const char *value, u64 fallback_value );
-void _skaterift_atom_set( const char *atom_alias, u64 value );
-void _skaterift_atom_set_enum( const char *atom_alias, const char *value );
-
-bool on_world_start( ent_script_event *event );
-bool on_atom_changed( ent_script_event *event, const char *atom_alias, u64 *out_value );
-bool on_cutscene_marker( ent_script_event *event, const char *marker );
-bool on_function_trigger( ent_script_event *event, i32 function_id );
-bool on_atom_once( ent_script_event *event, const char *atom_alias );
-bool on_advancement( ent_script_event *event );
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#pragma once
-#include "vg/vg_lines.h"
-#include "model.h"
-#include "metascene.h"
-
-struct skeleton
-{
- struct skeleton_bone
- {
- v3f co, end;
- u32 parent;
-
- u32 flags;
- int defer;
-
- //ms_keyframe kf;
- mdl_bone *orig_bone;
-
- u32 collider;
- boxf hitbox;
- const char *name;
- }
- *bones;
- u32 bone_count;
-
- struct skeleton_ik
- {
- u32 lower, upper, target, pole;
- m3x3f ia, ib;
- }
- *ik;
- u32 ik_count;
-
- u32 collider_count,
- bindable_count;
-};
-
-typedef struct skeleton_anim skeleton_anim;
-struct skeleton_anim
-{
- ms_strip *strip;
- ms_keyframe *keyframes_base;
- f32 framerate;
-};
-
-static u32 skeleton_bone_id( struct skeleton *skele, const char *name )
-{
- for( u32 i=1; i<skele->bone_count; i++ )
- if( !strcmp( skele->bones[i].name, name ))
- return i;
-
- vg_error( "skeleton_bone_id( *, \"%s\" );\n", name );
- vg_fatal_error( "Bone does not exist\n" );
-
- return 0;
-}
-
-static void keyframe_copy_pose( ms_keyframe *kfa, ms_keyframe *kfb, int num )
-{
- for( int i=0; i<num; i++ )
- kfb[i] = kfa[i];
-}
-
-
-/* apply a rotation from the perspective of root */
-static void keyframe_rotate_around( ms_keyframe *kf, v3f origin, v3f offset, v4f q )
-{
- v3f v0, co;
- v3_add( kf->co, offset, co );
- v3_sub( co, origin, v0 );
- q_mulv( q, v0, v0 );
- v3_add( v0, origin, co );
- v3_sub( co, offset, kf->co );
-
- q_mul( q, kf->q, kf->q );
- q_normalize( kf->q );
-}
-
-static void keyframe_lerp( ms_keyframe *kfa, ms_keyframe *kfb, f32 t, ms_keyframe *kfd )
-{
- v3_lerp( kfa->co, kfb->co, t, kfd->co );
- q_nlerp( kfa->q, kfb->q, t, kfd->q );
- v3_lerp( kfa->s, kfb->s, t, kfd->s );
-}
-
-/*
- * Lerp between two sets of keyframes and store in dest. Rotations use Nlerp.
- */
-static void keyframe_lerp_pose( ms_keyframe *kfa, ms_keyframe *kfb, float t, ms_keyframe *kfd, int count )
-{
- if( t <= 0.0001f )
- {
- keyframe_copy_pose( kfa, kfd, count );
- return;
- }
- else if( t >= 0.9999f )
- {
- keyframe_copy_pose( kfb, kfd, count );
- return;
- }
-
- for( int i=0; i<count; i++ )
- keyframe_lerp( kfa+i, kfb+i, t, kfd+i );
-}
-
-static void skeleton_lerp_pose( struct skeleton *skele, ms_keyframe *kfa, ms_keyframe *kfb, float t, ms_keyframe *kfd )
-{
- keyframe_lerp_pose( kfa, kfb, t, kfd, skele->bone_count-1 );
-}
-
-static void skeleton_copy_pose( struct skeleton *skele, ms_keyframe *kfa, ms_keyframe *kfd )
-{
- keyframe_copy_pose( kfa, kfd, skele->bone_count-1 );
-}
-
-/*
- * Sample animation between 2 closest frames using time value. Output is a
- * keyframe buffer that is allocated with an appropriate size
- *
- * Time is in SECONDS
- */
-void skeleton_sample_anim( struct skeleton *skele, skeleton_anim *anim, f32 time, ms_keyframe *output )
-{
- ms_strip *strip = anim->strip;
- f32 animtime = fmodf( time*anim->framerate, (f32)strip->strip.length ),
- animframe = floorf( animtime ),
- t = animtime - animframe;
-
- u32 frame = (u32)animframe % strip->strip.length,
- next = (frame+1) % strip->strip.length;
-
- ms_keyframe *base = anim->keyframes_base + strip->strip.count*frame,
- *nbase = anim->keyframes_base + strip->strip.count*next;
-
- skeleton_lerp_pose( skele, base, nbase, t, output );
-}
-
-/* time is in SECONDS */
-int skeleton_sample_anim_clamped( struct skeleton *skele, skeleton_anim *anim, f32 time, ms_keyframe *output )
-{
- ms_strip *strip = anim->strip;
- f32 end = (strip->strip.length-1)/anim->framerate;
- skeleton_sample_anim( skele, anim, vg_minf( end, time ), output );
-
- if( time > end ) return 0;
- else return 1;
-}
-
-typedef enum anim_apply
-{
- k_anim_apply_always,
- k_anim_apply_defer_ik,
- k_anim_apply_deffered_only,
- k_anim_apply_absolute
-}
-anim_apply;
-
-static int should_apply_bone( struct skeleton *skele, u32 id, anim_apply type )
-{
- struct skeleton_bone *sb = &skele->bones[ id ],
- *sp = &skele->bones[ sb->parent ];
-
- if( type == k_anim_apply_defer_ik )
- {
- if( ((sp->flags & k_bone_flag_ik) && !(sb->flags & k_bone_flag_ik)) || sp->defer )
- {
- sb->defer = 1;
- return 0;
- }
- else
- {
- sb->defer = 0;
- return 1;
- }
- }
- else if( type == k_anim_apply_deffered_only )
- {
- if( sb->defer )
- return 1;
- else
- return 0;
- }
-
- return 1;
-}
-
-/*
- * Apply block of keyframes to skeletons final pose
- */
-static void skeleton_apply_pose( struct skeleton *skele, ms_keyframe *pose, anim_apply passtype, m4x3f *final_mtx )
-{
- if( passtype == k_anim_apply_absolute )
- {
- for( u32 i=1; i<skele->bone_count; i++ )
- {
- ms_keyframe *kf = &pose[i-1];
-
- v3f *posemtx = final_mtx[i];
-
- q_m3x3( kf->q, posemtx );
- m3x3_scale( posemtx, kf->s );
- v3_copy( kf->co, posemtx[3] );
- }
- return;
- }
-
- m4x3_identity( final_mtx[0] );
- skele->bones[0].defer = 0;
- skele->bones[0].flags &= ~k_bone_flag_ik;
-
- for( u32 i=1; i<skele->bone_count; i++ )
- {
- struct skeleton_bone *sb = &skele->bones[i],
- *sp = &skele->bones[sb->parent];
- if( !should_apply_bone( skele, i, passtype ) )
- continue;
-
- sb->defer = 0;
-
- /* process pose */
- m4x3f posemtx;
-
- v3f temp_delta;
- v3_sub( skele->bones[i].co, skele->bones[sb->parent].co, temp_delta );
-
- /* pose matrix */
- ms_keyframe *kf = &pose[i-1];
- q_m3x3( kf->q, posemtx );
- m3x3_scale( posemtx, kf->s );
- v3_copy( kf->co, posemtx[3] );
- v3_add( temp_delta, posemtx[3], posemtx[3] );
-
- /* final matrix */
- m4x3_mul( final_mtx[ sb->parent ], posemtx, final_mtx[i] );
- }
-}
-
-/*
- * Take the final matrices and decompose it into an absolute positioned anim
- */
-static void skeleton_decompose_mtx_absolute( struct skeleton *skele, ms_keyframe *anim, m4x3f *final_mtx )
-{
- for( u32 i=1; i<skele->bone_count; i++ )
- {
- struct skeleton_bone *sb = &skele->bones[i];
- ms_keyframe *kf = &anim[i-1];
- m4x3_decompose( final_mtx[i], kf->co, kf->q, kf->s );
- }
-}
-
-/*
- * 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, v3f ivaxis, u32 id, m3x3f inverse )
-{
- v3_copy( ivaxis, inverse[0] );
- v3_copy( skele->bones[id].end, inverse[1] );
- v3_normalize( inverse[1] );
- v3_cross( inverse[0], inverse[1], inverse[2] );
- m3x3_transpose( inverse, inverse );
-}
-
-/*
- * Creates inverse rotation matrices which the IK system uses.
- */
-static void skeleton_create_inverses( struct skeleton *skele )
-{
- /* IK: inverse 'plane-bone space' axis '(^axis,^bone,...)[base] */
- for( u32 i=0; i<skele->ik_count; i++ )
- {
- struct skeleton_ik *ik = &skele->ik[i];
- 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_cross( iv0, iv1, ivaxis );
- v3_normalize( ivaxis );
-
- skeleton_inverse_for_ik( skele, ivaxis, ik->lower, ik->ia );
- skeleton_inverse_for_ik( skele, ivaxis, ik->upper, ik->ib );
- }
-}
-
-/*
- * Apply a model matrix to all bones, should be done last
- */
-static void skeleton_apply_transform( struct skeleton *skele, m4x3f transform, m4x3f *final_mtx )
-{
- for( u32 i=0; i<skele->bone_count; i++ )
- {
- struct skeleton_bone *sb = &skele->bones[i];
- m4x3_mul( transform, final_mtx[i], final_mtx[i] );
- }
-}
-
-/*
- * 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, m4x3f *final_mtx )
-{
- for( u32 i=0; i<skele->bone_count; i++ )
- {
- struct skeleton_bone *sb = &skele->bones[i];
- m4x3f inverse;
- m3x3_identity( inverse );
- v3_negate( sb->co, inverse[3] );
- m4x3_mul( final_mtx[i], inverse, final_mtx[i] );
- }
-}
-
-/*
- * Apply all IK modifiers (2 bone ik reference from blender is supported)
- */
-static void skeleton_apply_ik_pass( struct skeleton *skele, m4x3f *final_mtx )
-{
- for( u32 i=0; i<skele->ik_count; i++ )
- {
- struct skeleton_ik *ik = &skele->ik[i];
- v3f v0, /* base -> target */
- v1, /* base -> pole */
- vaxis;
-
- v3f co_base,
- co_target,
- co_pole;
-
- v3_copy( final_mtx[ik->lower][3], co_base );
- v3_copy( final_mtx[ik->target][3], co_target );
- v3_copy( final_mtx[ik->pole][3], co_pole );
-
- v3_sub( co_target, co_base, v0 );
- v3_sub( co_pole, co_base, v1 );
- v3_cross( v0, v1, vaxis );
- v3_normalize( vaxis );
- v3_normalize( v0 );
- v3_cross( vaxis, v0, v1 );
-
- /* localize problem into [x:v0,y:v1] 2d plane */
- v2f base = { v3_dot( v0, co_base ), v3_dot( v1, co_base ) },
- end = { v3_dot( v0, co_target ), v3_dot( v1, co_target ) },
- knee;
-
- /* Compute angles (basic trig)*/
- v2f delta;
- v2_sub( end, base, delta );
-
- f32 l1 = v3_length( skele->bones[ik->lower].end ),
- l2 = v3_length( skele->bones[ik->upper].end ),
- d = vg_clampf( v2_length(delta), fabsf(l1 - l2), l1+l2-0.00001f ),
- c = acosf( (l1*l1 + d*d - l2*l2) / (2.0f*l1*d) ),
- rot = atan2f( delta[1], delta[0] ) + c - VG_PIf/2.0f;
-
- knee[0] = sinf(-rot) * l1;
- knee[1] = cosf(-rot) * l1;
-
- m4x3_identity( final_mtx[ik->lower] );
- m4x3_identity( final_mtx[ik->upper] );
-
- /* create rotation matrix */
- v3f co_knee;
- v3_muladds( co_base, v0, knee[0], co_knee );
- v3_muladds( co_knee, v1, knee[1], co_knee );
- vg_line( co_base, co_knee, 0xff00ff00 );
-
- m4x3f transform;
- v3_copy( vaxis, transform[0] );
- v3_muls( v0, knee[0], transform[1] );
- v3_muladds( transform[1], v1, knee[1], transform[1] );
- v3_normalize( transform[1] );
- v3_cross( transform[0], transform[1], transform[2] );
- v3_copy( co_base, transform[3] );
-
- m3x3_mul( transform, ik->ia, transform );
- m4x3_copy( transform, final_mtx[ik->lower] );
-
- /* upper/knee bone */
- v3_copy( vaxis, transform[0] );
- v3_sub( co_target, co_knee, transform[1] );
- v3_normalize( transform[1] );
- v3_cross( transform[0], transform[1], transform[2] );
- v3_copy( co_knee, transform[3] );
-
- m3x3_mul( transform, ik->ib, transform );
- m4x3_copy( transform, final_mtx[ik->upper] );
- }
-}
-
-/*
- * 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, ms_keyframe *pose, m4x3f transform, m4x3f *final_mtx )
-{
- skeleton_apply_pose( skele, pose, k_anim_apply_defer_ik, final_mtx );
- skeleton_apply_ik_pass( skele, final_mtx );
- skeleton_apply_pose( skele, pose, k_anim_apply_deffered_only, final_mtx );
- skeleton_apply_inverses( skele, final_mtx );
- skeleton_apply_transform( skele, transform, final_mtx );
-}
-
-static void skeleton_alloc_from( struct skeleton *skele, vg_stack_allocator *stack, mdl_context *mdl, mdl_armature *armature )
-{
- skele->bone_count = armature->bone_count+1;
- skele->ik_count = 0;
- skele->collider_count = 0;
-
- for( u32 i=0; i<armature->bone_count; i++ )
- {
- mdl_bone *bone = &mdl->bones[ armature->bone_start+i ];
- if( bone->flags & k_bone_flag_ik )
- skele->ik_count ++;
- if( bone->collider )
- skele->collider_count ++;
- }
-
- u32 bone_size = sizeof(struct skeleton_bone) * skele->bone_count,
- ik_size = sizeof(struct skeleton_ik) * skele->ik_count;
-
- skele->bones = vg_stack_allocate( stack, bone_size, 8, NULL );
- skele->ik = vg_stack_allocate( stack, ik_size, 8, NULL );
-
- memset( skele->bones, 0, bone_size );
- memset( skele->ik, 0, ik_size );
-}
-
-static void skeleton_fatal_err(void)
-{
- vg_fatal_error( "Skeleton setup failed" );
-}
-
-/* Setup a skeleton from model. mdl's metadata should stick around */
-void skeleton_setup( struct skeleton *skele, mdl_context *mdl, u32 index, vg_stack_allocator *stack )
-{
- u32 ik_count = 0, collider_count = 0;
- skele->bone_count = 0;
- skele->bones = NULL;
-
- if( !mdl->armature_count )
- {
- vg_error( "No skeleton in model\n" );
- skeleton_fatal_err();
- }
-
- mdl_armature *armature = &mdl->armatures[ index ];
- skeleton_alloc_from( skele, stack, mdl, armature );
-
- for( u32 i=0; i<armature->bone_count; i++ )
- {
- mdl_bone *bone = &mdl->bones[ armature->bone_start+i ];
- struct skeleton_bone *sb = &skele->bones[i+1];
-
- v3_copy( bone->co, sb->co );
- v3_copy( bone->end, sb->end );
-
- sb->parent = bone->parent;
- sb->name = af_str( &mdl->af, bone->pstr_name );
- sb->flags = bone->flags;
- sb->collider = bone->collider;
- sb->orig_bone = bone;
-
- if( sb->flags & k_bone_flag_ik )
- {
- skele->bones[ sb->parent ].flags |= k_bone_flag_ik;
-
- if( ik_count == skele->ik_count )
- {
- vg_error( "Too many ik bones, corrupt model file\n" );
- skeleton_fatal_err();
- }
-
- struct skeleton_ik *ik = &skele->ik[ ik_count ++ ];
- ik->upper = i+1;
- ik->lower = bone->parent;
- ik->target = bone->ik_target;
- ik->pole = bone->ik_pole;
- }
-
- box_copy( bone->hitbox, sb->hitbox );
-
- if( bone->collider )
- {
- if( collider_count == skele->collider_count )
- {
- vg_error( "Too many collider bones\n" );
- skeleton_fatal_err();
- }
- collider_count ++;
- }
- }
-
- /* fill in implicit root bone */
- v3_zero( skele->bones[0].co );
- v3_copy( (v3f){0.0f,1.0f,0.0f}, skele->bones[0].end );
- skele->bones[0].parent = 0xffffffff;
- skele->bones[0].flags = 0;
- skele->bones[0].name = "[root]";
-
- skeleton_create_inverses( skele );
- vg_success( "Loaded skeleton with %u bones\n", skele->bone_count );
- vg_success( " %u colliders\n", skele->collider_count );
-}
-
-static void skeleton_debug( struct skeleton *skele, m4x3f *final_mtx )
-{
- for( u32 i=1; i<skele->bone_count; i ++ )
- {
- struct skeleton_bone *sb = &skele->bones[i];
- v3f p0, p1;
- v3_copy( sb->co, p0 );
- v3_add( p0, sb->end, p1 );
-
- m4x3_mulv( final_mtx[i], p0, p0 );
- m4x3_mulv( final_mtx[i], p1, p1 );
-
- if( sb->flags & k_bone_flag_deform )
- {
- if( sb->flags & k_bone_flag_ik )
- vg_line( p0, p1, 0xff0000ff );
- else
- vg_line( p0, p1, 0xffcccccc );
- }
- else
- vg_line( p0, p1, 0xff00ffff );
- }
-}
+++ /dev/null
-#ifndef TRAFFIC_H
-#define TRAFFIC_H
-
-#include "common.h"
-#include "model.h"
-#include "rigidbody.h"
-#include "world.h"
-
-typedef struct traffic_node traffic_node;
-typedef struct traffic_driver traffic_driver;
-
-struct traffic_node
-{
- v3f co, h;
-
- union
- {
- struct{ traffic_node *next, *next1; };
- struct{ mdl_node *mn_next, *mn_next1; };
- };
-};
-
-struct traffic_driver
-{
- m4x3f transform;
-
- traffic_node *current;
- int option;
- float t, speed;
-};
-
-static float eval_bezier_length( v3f p0, v3f p1, v3f h0, v3f h1, int res )
-{
- float length = 0.0f, m = 1.0f/(float)res;
- v3f l, p;
- v3_copy( p0, l );
-
- for( int i=0; i<res; i++ )
- {
- float t = (float)(i+1)*m;
- eval_bezier_time(p0,p1,h0,h1,t,p);
- length += v3_dist( p,l );
- v3_copy( p, l );
- }
-
- return length;
-}
-
-static void traffic_finalize( traffic_node *system, int count )
-{
- for( int i=0; i<count; i++ )
- {
- traffic_node *tn = &system[i];
-
- if( tn->mn_next )
- tn->next = &system[ tn->mn_next->sub_uid ];
- if( tn->mn_next1 )
- tn->next1 = &system[ tn->mn_next1->sub_uid ];
- }
-}
-
-static void traffic_visualize_link( traffic_node *ta, traffic_node *tb )
-{
- v3f p0, p1, h0, h1, p, l;
-
- if( !tb ) return;
-
- v3_copy( ta->co, p0 );
- v3_muladds( ta->co, ta->h, 1.0f, h0 );
- v3_copy( tb->co, p1 );
- v3_muladds( tb->co, tb->h, -1.0f, h1 );
- v3_copy( p0, l );
-
- vg_line_pt3( h0, 0.2f, 0xff00ff00 );
- vg_line_pt3( h1, 0.2f, 0xffff00ff );
- vg_line( p0, h0, 0xff000000 );
- vg_line( p1, h1, 0xff000000 );
-
- for( int i=0; i<5; i++ )
- {
- float t = (float)(i+1)/5.0f;
- eval_bezier_time( p0, p1, h0, h1, t, p );
-
- vg_line( p, l, 0xffffffff );
- v3_copy( p, l );
- }
-}
-
-static void sample_wheel_floor( v3f pos )
-{
- v3f ground;
- v3_copy( pos, ground );
- ground[1] += 4.0f;
-
- ray_hit hit;
- hit.dist = 8.0f;
-
- if( ray_world( ground, (v3f){0.0f,-1.0f,0.0f}, &hit ))
- {
- v3_copy( hit.pos, pos );
- }
-}
-
-static void traffic_drive( traffic_driver *driver )
-{
- traffic_node *next, *current = driver->current;
-
- if( !current ) return;
- next = driver->option==0? current->next: current->next1;
-
- if( driver->t > 1.0f )
- {
- driver->t = driver->t - floorf( driver->t );
- driver->current = driver->option==0? current->next: current->next1;
- driver->option = 0;
-
- current = driver->current;
- if( !current )
- return;
-
- if( current->next && current->next1 )
- if( vg_randf() > 0.5f )
- driver->option = 1;
- }
-
- traffic_visualize_link( current, next );
-
- /*
- * Calculate the speed of the curve at the current point. On the reference
- * curve the rate should come out to be exactly 1 ktimestep traveled.
- * Dividing this distance by ktimestep gives us the modifier to use.
- */
- v3f p0,p1,h0,h1,pc,pn;
-
- v3_copy( current->co, p0 );
- v3_muladds( current->co, current->h, 1.0f, h0 );
- v3_copy( next->co, p1 );
- v3_muladds( next->co, next->h, -1.0f, h1 );
-
- eval_bezier_time( p0,p1,h0,h1, driver->t, pc );
- eval_bezier_time( p0,p1,h0,h1, driver->t + vg.time_delta, pn );
-
- float mod = vg.time_delta / v3_dist( pc, pn );
- v3f dir,side,up;
- v3_sub( pn, pc, dir );
- v3_normalize(dir);
-
- /*
- * Stick the car on the ground by casting rays where the wheels are
- */
- side[0] = -dir[2];
- side[1] = 0.0f;
- side[2] = dir[0];
- v3_normalize(side);
-
- v3f fl, fr, bc;
- v3_muladds( pc, dir, 2.0f, fr );
- v3_muladds( pc, dir, 2.0f, fl );
- v3_muladds( pc, dir, -2.0f, bc );
- v3_muladds( fr, side, 1.0f, fr );
- v3_muladds( fl, side, -1.0f, fl );
-
- sample_wheel_floor( fl );
- sample_wheel_floor( fr );
- sample_wheel_floor( bc );
-
- vg_line( fl, fr, 0xff00ffff );
- vg_line( fr, bc, 0xff00ffff );
- vg_line( bc, fl, 0xff00ffff );
-
- v3f norm;
- v3f v0, v1;
- v3_sub( fr, fl, v0 );
- v3_sub( bc, fl, v1 );
- v3_cross( v1, v0, norm );
- v3_normalize( norm );
-
- /*
- * Jesus take the wheel
- */
- float steer_penalty = 1.0f-v3_dot( dir, driver->transform[0] );
- steer_penalty /= vg.time_delta;
- steer_penalty *= 30.0f;
-
- float target_speed = vg_maxf( 16.0f * (1.0f-steer_penalty), 0.1f ),
- accel = target_speed - driver->speed;
- driver->speed = stable_force( driver->speed, accel*vg.time_delta*2.0f );
- driver->t += driver->speed*mod*vg.time_delta;
-
- /*
- * Update transform
- */
- v3_cross( dir, norm, side );
- v3_copy( dir, driver->transform[0] );
- v3_copy( norm, driver->transform[1] );
- v3_copy( side, driver->transform[2] );
-
- v3_add( fl, fr, pc );
- v3_add( bc, pc, pc );
- v3_muls( pc, 1.0f/3.0f, pc );
- v3_copy( pc, driver->transform[3] );
-}
-
-static void traffic_visualize( traffic_node *system, int count )
-{
- for( int i=0; i<count; i++ )
- {
- traffic_node *tn = &system[i];
-
- traffic_visualize_link( tn, tn->next );
- traffic_visualize_link( tn, tn->next1 );
- }
-}
-
-static void traffic_visualize_car( traffic_driver *driver )
-{
- vg_line_boxf_transformed( driver->transform,
- (boxf){{-1.0f,0.0f,-0.5f},
- { 1.0f,0.0f, 0.5f}}, 0xff00ff00 );
-}
-
-#endif /* TRAFFIC_H */
-#pragma once
-#include "vg/vg_engine.h"
-#include "vg/vg_platform.h"
-#include "vg/vg_m.h"
-#include "vg/vg_lines.h"
-#include "vg/vg_camera.h"
-#include "trail.h"
-#include "shaders/particle.h"
-#include "shaders/trail.h"
-
-static void trail_increment( trail_system *sys ){
+static void trail_increment( trail_system *sys )
+{
sys->head ++;
-
if( sys->head == sys->max )
sys->head = 0;
-
/* undesirable effect: will remove active points if out of space! */
if( sys->count < sys->max )
sys->count ++;
}
}
-struct trail_init_args {
- trail_system *sys;
-};
-
-void async_trail_init( vg_async_task *task )
+void trail_alloc( trail_system *sys, u32 max, vg_stack_allocator *stack )
{
- THREAD_0;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN|VG_THREAD_OWNS_OPENGL ) );
- struct trail_init_args *args = (void *)task->data;
- trail_system *sys = args->sys;
+ u32 stride = sizeof(trail_vert);
+ sys->max = max;
+ sys->array = vg_stack_allocate( NULL, max*sizeof(trail_point), 8, "Trail array" );
+ sys->vertices = vg_stack_allocate( NULL, max*stride*2, 8, "Trail vertices" );
glGenVertexArrays( 1, &sys->vao );
glGenBuffers( 1, &sys->vbo );
glBindVertexArray( sys->vao );
- size_t stride = sizeof(trail_vert);
-
glBindBuffer( GL_ARRAY_BUFFER, sys->vbo );
glBufferData( GL_ARRAY_BUFFER, sys->max*stride*2, NULL, GL_DYNAMIC_DRAW );
glEnableVertexAttribArray( 0 );
}
-void trail_alloc( trail_system *sys, u32 max )
-{
- THREAD_1;
-
- size_t stride = sizeof(trail_vert);
- sys->max = max;
- sys->array = vg_stack_allocate( &vg.rtmem, max*sizeof(trail_point), 8, "Trail array" );
- sys->vertices = vg_stack_allocate( &vg.rtmem, max*stride*2, 8, "Trail vertices" );
-
- vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, sizeof(struct trail_init_args), 1 );
- struct trail_init_args *init = (void *)task->data;
- init->sys = sys;
- vg_async_task_dispatch( task, async_trail_init );
-}
-
void trail_system_prerender( trail_system *sys )
{
- if( sys->count < 2 ) return;
+ if( sys->count < 2 )
+ return;
- for( i32 i=0; i<sys->count; i ++ ){
+ for( i32 i=0; i<sys->count; i ++ )
+ {
i32 i0 = sys->head - sys->count + i;
- if( i0 < 0 ) i0 += sys->max;
+ if( i0 < 0 )
+ i0 += sys->max;
trail_point *p0 = &sys->array[i0];
trail_vert *v0 = &sys->vertices[i*2+0],
v0->co[3] = p0->alpha;
v1->co[3] = p0->alpha;
}
-
glBindVertexArray( sys->vao );
- size_t stride = sizeof(trail_vert);
+ u32 stride = sizeof(trail_vert);
glBindBuffer( GL_ARRAY_BUFFER, sys->vbo );
glBufferSubData( GL_ARRAY_BUFFER, 0, sys->count*stride*2, sys->vertices );
}
void trail_system_render( trail_system *sys, vg_camera *cam )
{
- if( sys->count < 2 ) return;
+ if( sys->count < 2 )
+ return;
glDisable( GL_CULL_FACE );
glEnable( GL_DEPTH_TEST );
-#pragma once
+#if defined( SR_IMPLEMENTATION )
+# include "src/trail.c"
+#else
typedef struct trail_system trail_system;
typedef struct trail_point trail_point;
f32 width, lifetime, min_dist;
};
-void trail_alloc( trail_system *sys, u32 max );
-void trail_system_update( trail_system *sys, f32 dt, v3f co,
- v3f normal, f32 alpha );
+void trail_alloc( trail_system *sys, u32 max, vg_stack_allocator *stack );
+void trail_system_update( trail_system *sys, f32 dt, v3f co, v3f normal, f32 alpha );
void trail_system_debug( trail_system *sys );
void trail_system_prerender( trail_system *sys );
void trail_system_render( trail_system *sys, vg_camera *cam );
+
+#endif
--- /dev/null
+#include "vg/vg.hconf"
+
+#define SR_ALL
+#include "src/skaterift.hconf"
+
+#define SR_IMPLEMENTATION
+#include "src/skaterift.hconf"
+#undef SR_IMPLEMENTATION
-#include "user_profile.h"
-
struct menu_icon_inf
{
u16 desc_offset;
u32 country_index;
- u16 race3, race10;
+ u32 race3, race10;
f32 timer;
enum user_profile_state
v2f country_coords;
bool has_avatar;
- GLuint cc_tex, map_tex, icon_tex, no_avatar_tex, avatar_tex;
+ vg_tex cc_tex, map_tex, icon_tex, no_avatar_tex, avatar_tex;
}
_user_profile = { .country_coords = {0.5f, 0.5f} };
#include "cc.h"
-void _user_profile_init(void)
+static void _user_profile_load_content_async( void *_, vg_async_info *async )
+{
+ u32 flags = VG_TEX_CLAMP|VG_TEX_NEAREST;
+ _vg_tex_load( &_user_profile.cc_tex, "textures/cc.qoi", flags );
+ _vg_tex_load( &_user_profile.map_tex, "textures/world_map.qoi", flags );
+ _vg_tex_load( &_user_profile.icon_tex, "textures/menu_icons.qoi", flags );
+ _vg_tex_load( &_user_profile.no_avatar_tex, "textures/no_avatar.qoi", flags );
+ _vg_tex_load( &_user_profile.avatar_tex, "textures/no_avatar.qoi", flags );
+}
+
+VG_API void _user_profile_init(void)
{
- vg_tex2d_load_qoi_async_file( "textures/cc.qoi", VG_TEX2D_CLAMP, &_user_profile.cc_tex );
- vg_tex2d_load_qoi_async_file( "textures/world_map.qoi", VG_TEX2D_CLAMP, &_user_profile.map_tex );
- vg_tex2d_load_qoi_async_file( "textures/menu_icons.qoi", VG_TEX2D_CLAMP, &_user_profile.icon_tex );
- vg_tex2d_load_qoi_async_file( "textures/no_avatar.qoi", VG_TEX2D_CLAMP, &_user_profile.no_avatar_tex );
- vg_tex2d_load_qoi_async_file( "textures/no_avatar.qoi", VG_TEX2D_CLAMP, &_user_profile.avatar_tex );
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_user_profile_load_content_async );
}
static void _profile_download_callback( void *data, u32 data_size, u64 userdata, enum request_status status )
{
- THREAD_0;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
u64 steamid = userdata;
if( steamid != _user_profile.current_steamid )
_user_profile.state = k_user_profile_state_open;
- vg_msg body;
- vg_msg_init( &body, data, data_size );
+ u32 temp_frame = _vg_start_temp_frame();
+ {
+ vg_stream kv_stream;
+ vg_buffer_stream_open( &kv_stream, data, data_size, VG_STREAM_READ );
- const char *username = vg_msg_getkvstr( &body, "username" );
- vg_strncpy( username, _user_profile.username, sizeof(_user_profile.username), k_strncpy_always_add_null );
+ vg_kvs kvs;
+ vg_kvs_init( &kvs, _vg_temp_stack() );
+ vg_kv_parser parser;
+ vg_kv_parser_init( &parser, &kvs, 0 );
+ vg_kv_parse_stream( &parser, &kv_stream );
- vg_msg_getkvintg( &body, "flags", k_vg_msg_u32, &_user_profile.flags, NULL );
- vg_msg_getkvintg( &body, "race3", k_vg_msg_u16, &_user_profile.race3, NULL );
- vg_msg_getkvintg( &body, "race10", k_vg_msg_u16, &_user_profile.race10, NULL );
- _user_profile.country_index = 0;
+ const c8 *username = vg_kv_value( &kvs, vg_kv_find( &kvs, 0, "username" ), NULL );
+ vg_strncpy( username, _user_profile.username, sizeof(_user_profile.username), k_strncpy_always_add_null );
- const char *cc = vg_msg_getkvstr( &body, "cc" );
+ vg_kv_read_vu32( &kvs, 0, "flags", NULL, &_user_profile.flags, 1 );
+ vg_kv_read_vu32( &kvs, 0, "race3", NULL, &_user_profile.race3, 1 );
+ vg_kv_read_vu32( &kvs, 0, "race10", NULL, &_user_profile.race10, 1 );
+ _user_profile.country_index = 0;
- if( cc && strlen(cc)>=2 )
- {
- for( u32 i=0; i<k_country_count; i ++ )
+ const c8 *cc = vg_kv_value( &kvs, vg_kv_find( &kvs, 0, "cc" ), NULL );
+ if( cc && strlen(cc)>=2 )
{
- if( (k_country_iso2[i*3+0] == cc[0]) && (k_country_iso2[i*3+1] == cc[1]) )
+ for( u32 i=0; i<k_country_count; i ++ )
{
- _user_profile.country_index = i+1;
- break;
+ if( (k_country_iso2[i*3+0] == cc[0]) && (k_country_iso2[i*3+1] == cc[1]) )
+ {
+ _user_profile.country_index = i+1;
+ break;
+ }
}
}
}
+ _vg_end_temp_frame( temp_frame );
}
void _user_profile_ui( ui_context *ctx, ui_rect box, u64 steamid )
_user_profile.current_steamid = steamid;
_user_profile.timer = 1.0f;
+ // FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////
+#if 0
vg_info( "Request profile for: "PRINTF_U64"\n", steamid );
- netmsg_request *packet = alloca( sizeof(netmsg_request) + 512 );
- packet->inetmsg_id = k_inetmsg_request;
-
vg_msg data;
vg_msg_init( &data, packet->buffer, 512 );
vg_msg_wkvstr( &data, "endpoint", "profile" );
vg_msg_wkvnum( &data, "steamid", k_vg_msg_u64, 1, &steamid );
- network_send_request( packet, &data, _profile_download_callback, steamid );
+
+ const c8 *yep_fix_me = "endpoint profile\n"
+ "steamid 1234\n";
+ network_send_request( yep_fix_me, 0, _profile_download_callback, steamid );
+#endif
+ // FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////
u64 me_id = SteamAPI_ISteamUser_GetSteamID( _steam_api.pSteamUser );
bool isme = 0;
if( SteamAPI_ISteamUtils_GetImageRGBA( _steam_api.pSteamUtils, avatar_handle, tmp, w*h*4 ) )
{
- glBindTexture( GL_TEXTURE_2D, _user_profile.avatar_tex );
+ vg_tex_bind( GL_TEXTURE_2D, &_user_profile.avatar_tex, 0 );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, tmp );
_user_profile.has_avatar = 1;
}
x = (i & 0xf)*16,
y = ((i>>4) & 0xf)*16;
ui_fill_rect( ctx, flag, 0xffffffff, (ui_px[4]){ x,y,x+16,y+16 } );
-
- struct ui_batch_shader_data_image inf = { .resource = &_user_profile.cc_tex };
- ui_flush( ctx, k_ui_shader_image, &inf );
+ ui_flush( ctx, k_ui_shader_image, &_user_profile.cc_tex );
}
ui_image( ctx, pfp, _user_profile.has_avatar? &_user_profile.avatar_tex: &_user_profile.no_avatar_tex, 1 );
w = ((icon_index>>3) & 0x7)*32;
ui_fill_rect( ctx, medal_box, 0xffffffff, (ui_px[4]){ z,w,z+32,w+32 } );
}
-
- struct ui_batch_shader_data_image inf = { .resource = &_user_profile.icon_tex };
- ui_flush( ctx, k_ui_shader_image, &inf );
+ ui_flush( ctx, k_ui_shader_image, &_user_profile.icon_tex );
x = base;
for( u32 i=0; i<medal_count; i ++ )
vg_str str;
vg_strnull( &str, buf, sizeof(buf) );
vg_strcatch( &str, 'x' );
- vg_strcati32( &str, medal_list[i].count );
+ vg_strcati64( &str, medal_list[i].count, 10 );
ui_text( ctx, count_box, buf, 1, k_ui_align_middle, ui_colour(ctx,k_ui_fg) );
}
}
vg_ui.frosting = 0.0f;
ui_fill_rect( ctx, box, 0xffffffff, (ui_px[4]){ 0,0,256,256 } );
-
- struct ui_batch_shader_data_image inf1 = { .resource = &_user_profile.map_tex };
- ui_flush( ctx, k_ui_shader_image, &inf1 );
+ ui_flush( ctx, k_ui_shader_image, &_user_profile.map_tex );
for( u32 i=0; i<k_country_count; i ++ )
{
y = ((min_country>>4) & 0xf)*16;
ui_fill_rect( ctx, min_country_rect, 0xffffffff, (ui_px[4]){ x,y,x+16,y+16 } );
}
-
- struct ui_batch_shader_data_image inf = { .resource = &_user_profile.cc_tex };
- ui_flush( ctx, k_ui_shader_image, &inf );
+ ui_flush( ctx, k_ui_shader_image, &_user_profile.cc_tex );
if( min_country >= 0 )
{
netmsg_request *packet = alloca( sizeof(netmsg_request) + 512 );
packet->inetmsg_id = k_inetmsg_request;
- vg_msg data;
- vg_msg_init( &data, packet->buffer, 512 );
- vg_msg_wkvstr( &data, "endpoint", "profile" );
+ u32 temp_frame = _vg_start_temp_frame();
+ {
+ vg_kvs kvs;
+ vg_kvs_init( &kvs, _vg_temp_stack() );
+ vg_kv_append( &kvs, 0, "endpoint", "profile" );
+ u32 index = _user_profile.country_index;
+ vg_kv_append( &kvs, 0, "cc",index == 0? "00": k_country_iso2+(index-1)*3 );
+ }
+ _vg_end_temp_frame( temp_frame );
- u32 index = _user_profile.country_index;
- vg_msg_wkvstr( &data, "cc", index == 0? "00": k_country_iso2+(index-1)*3 );
- network_send_request( packet, &data, _profile_download_callback, 0 );
+ VG_ASSERT(0);
+ // FIXME FIXME FIXME FIXME
+ //network_send_request( todo, 0, _profile_download_callback, 0 );
}
return close;
-#pragma once
-void _user_profile_init(void);
+#if defined( SR_IMPLEMENTATION )
+# include "src/user_profile.c"
+#else
+
+VG_API void _user_profile_init(void);
void _user_profile_ui( ui_context *ctx, ui_rect box, u64 steamid );
bool _user_profile_country_picker( ui_context *ctx, ui_rect box );
+
+#endif
void vg_render(void)
{
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
- glViewport( 0,0, vg.window_x, vg.window_y );
+ glViewport( 0,0, _vg_window.w, _vg_window.h );
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT );
}
{
ui_capture_mouse( ctx, 1 );
- ui_rect rect = { 8,8, vg.window_x-16, vg.window_y-16 };
+ ui_rect rect = { 8,8, _vg_window.w-16, _vg_window.h-16 };
}
-#include "skaterift.h"
-#include "vehicle.h"
-#include "scene_rigidbody.h"
-
struct drivable_vehicle gzoomer =
{
.rb.co = {-2000,-2000,-2000}
-#pragma once
-#include "vg/vg_rigidbody.h"
-#include "player.h"
-#include "world.h"
-#include "world_physics.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/vehicle.c"
+#else
static float k_car_spring = 1.0f,
k_car_spring_damp = 0.001f,
void vehicle_solve_friction(void);
void vehicle_update_fixed(void);
void vehicle_update_post(void);
+
+#endif
-#include "vg/vg_engine.h"
-#include "vg/vg_tex.h"
-#include "vg/vg_image.h"
-#include "vg/vg_msg.h"
-#include "vg/vg_binstr.h"
-#include "vg/vg_loader.h"
-#include "vg/vg_io.h"
-#include "ent_skateshop.h"
-
-#include "vg/vg_steam2.h"
-#include "workshop.h"
-
struct workshop_form workshop_form;
static struct ui_enum_opt workshop_form_visibility_opts[] = {
*/
static void workshop_form_upload_submission( PublishedFileId_t file_id, char *metadata )
{
- THREAD_0;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
UGCUpdateHandle_t handle = SteamAPI_ISteamUGC_StartItemUpdate( _steam_api.pSteamUGC, SKATERIFT_APPID, file_id );
/* TODO: Handle failure cases for these */
/*
* Steam API call result for when we've created a new item on their network, or
* not, if it has failed
+ *
+ * FIXME FIXME FIXME FIXME FIXME FIXME FIXME
*/
static void on_workshop_createitem( void *data, void *user )
{
/*
* Starts the workshop upload process through Steam API
*/
-static void workshop_form_async_submit_begin( void *userdata )
+static void workshop_form_async_submit_begin( void *_, vg_async_info *async )
{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_OWNS_STEAM ) );
+
/* use existing file */
if( workshop_form.submission.file_id )
{
- workshop_form_upload_submission( workshop_form.submission.file_id, userdata );
+ workshop_form_upload_submission( workshop_form.submission.file_id, "undefined" );
}
else
{
vg_steam_api_call *call = vg_alloc_async_steam_api_call();
- call->userdata = userdata;
+ call->userdata = "undefined";
call->cb = on_workshop_createitem;
call->id = SteamAPI_ISteamUGC_CreateItem( _steam_api.pSteamUGC, SKATERIFT_APPID, k_EWorkshopFileTypeCommunity );
}
}
-static void _workshop_form_end_op( void *userdata )
+static void _workshop_form_end_op( void *_, vg_async_info *async )
{
workshop_form.op = k_workshop_op_none;
}
/*
* Thread which kicks off the upload process
*/
-static void _workshop_form_submit_t1( void *userdata )
+static void _workshop_form_submit_t1( void *_, vg_async_info *async )
{
char path_buf[4096];
vg_str folder;
if( !vg_strgood(&folder) )
{
vg_error( "addon folder path too long\n" );
- vg_async_call( &vg.main_tasks, _workshop_form_end_op, NULL );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)_workshop_form_end_op );
return;
}
- /*
- * Create the metadata file
- * -----------------------------------------------------------------------*/
- u8 descriptor_buf[ 512 ];
- vg_msg descriptor;
- vg_msg_init( &descriptor, descriptor_buf, sizeof(descriptor_buf) );
- vg_stack_clear( &vg.scratch );
-
- /* short description */
- vg_msg_frame( &descriptor, "workshop" );
- {
- vg_msg_wkvstr( &descriptor, "title", workshop_form.submission.title );
- //vg_msg_wkvstr( &descriptor, "author", "unknown" );
- vg_msg_wkvnum( &descriptor, "type", k_vg_msg_u32, 1, &workshop_form.submission.type );
- vg_msg_wkvstr( &descriptor, "folder", workshop_form.addon_folder );
- }
- vg_msg_end_frame( &descriptor );
- //vg_msg_wkvstr( &descriptor, "location", "USA" );
-
- char *short_descriptor_str = vg_stack_allocate( &vg.scratch, descriptor.cur.co*2+1, 1, "Descriptor String" );
- vg_bin_str( descriptor_buf, short_descriptor_str, descriptor.cur.co );
- short_descriptor_str[descriptor.cur.co*2] = '\0';
- vg_info( "binstr: %s\n", short_descriptor_str );
-
vg_dir dir;
if( vg_dir_open( &dir, folder.buffer ) != k_dir_open_ok )
{
vg_error( "could not open addon folder '%s'\n", folder.buffer );
- vg_async_call( &vg.main_tasks, _workshop_form_end_op, NULL );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)_workshop_form_end_op );
return;
}
- while( vg_dir_next_entry(&dir) )
+ u32 temp_frame = _vg_start_temp_frame();
{
- if( vg_dir_entry_type(&dir) == k_vg_entry_type_file )
+ vg_kvs kvs;
+ vg_kvs_init( &kvs, _vg_temp_stack() );
+
+ while( vg_dir_next_entry(&dir) )
{
- const char *d_name = vg_dir_entry_name(&dir);
- if( d_name[0] == '.' ) continue;
+ if( vg_dir_entry_type(&dir) == k_vg_entry_type_file )
+ {
+ const char *d_name = vg_dir_entry_name(&dir);
+ if( d_name[0] == '.' ) continue;
- vg_str file = folder;
- vg_strcat( &file, "/" );
- vg_strcat( &file, d_name );
- if( !vg_strgood( &file ) ) continue;
+ vg_str file = folder;
+ vg_strcat( &file, "/" );
+ vg_strcat( &file, d_name );
+ if( !vg_strgood( &file ) ) continue;
- char *ext = vg_strch( &file, '.' );
- if( !ext ) continue;
- if( strcmp(ext,".mdl") ) continue;
+ char *ext = vg_strch( &file, '.' );
+ if( !ext ) continue;
+ if( strcmp(ext,".mdl") ) continue;
- vg_msg_wkvstr( &descriptor, "content", d_name );
- break;
+ vg_kv_append( &kvs, 0, "content", d_name );
+ break;
+ }
}
- }
- vg_dir_close(&dir);
+ vg_dir_close(&dir);
- vg_str descriptor_file = folder;
- vg_strcat( &descriptor_file, "/addon.inf" );
- if( !vg_strgood(&descriptor_file) ){
- vg_error( "Addon info path too long\n" );
- vg_async_call( &vg.main_tasks, _workshop_form_end_op, NULL );
- return;
- }
-
- FILE *fp = fopen( descriptor_file.buffer, "wb" );
- if( !fp )
- {
- vg_error( "Could not open addon info file '%s'\n", descriptor_file.buffer );
- vg_async_call( &vg.main_tasks, _workshop_form_end_op, NULL );
- return;
+ u32 workshop_block = vg_kv_append( &kvs, 0, "workshop", NULL );
+ vg_kv_append( &kvs, workshop_block, "title", workshop_form.submission.title );
+ vg_kv_append_vu32( &kvs, workshop_block, "type", &workshop_form.submission.type, 1 );
+ vg_kv_append( &kvs, workshop_block, "folder", workshop_form.addon_folder );
+
+
+ vg_str descriptor_file = folder;
+ vg_strcat( &descriptor_file, "/addon.kv" );
+ if( !vg_strgood(&descriptor_file) )
+ {
+ vg_error( "Addon info path too long\n" );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)_workshop_form_end_op );
+ _vg_end_temp_frame( temp_frame );
+ return;
+ }
+
+ // FIXME FIXME FIXME FIXME FIXME
+ vg_error( "FIXME!!!!!!\n" );
+ VG_ASSERT(0);
+#if 0
+ FILE *fp = fopen( descriptor_file.buffer, "wb" );
+ if( !fp )
+ {
+ vg_error( "Could not open addon info file '%s'\n", descriptor_file.buffer );
+ vg_async_call( &vg.main_tasks, _workshop_form_end_op, NULL );
+ return;
+ }
+ fwrite( descriptor_buf, descriptor.cur.co, 1, fp );
+ fclose( fp );
+#endif
}
- fwrite( descriptor_buf, descriptor.cur.co, 1, fp );
- fclose( fp );
+ _vg_end_temp_frame( temp_frame );
/* Save the preview
* -----------------------------------------------------------------------*/
if( !vg_strgood(&preview) )
{
vg_error( "preview image path too long\n" );
- vg_async_call( &vg.main_tasks, _workshop_form_end_op, NULL );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)_workshop_form_end_op );
return;
}
stbi_flip_vertically_on_write(1);
stbi_write_jpg( preview.buffer, w,h, 3, workshop_form.img_buffer, 90 );
- vg_async_call( &vg.main_tasks, workshop_form_async_submit_begin, short_descriptor_str );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)workshop_form_async_submit_begin );
}
/*
int w, h;
vg_framebuffer_get_res( g_render.fb_workshop_preview, &w, &h );
- vg_stack_clear( &vg.scratch );
- workshop_form.img_buffer = vg_stack_allocate( &vg.scratch, w*h*3, 8, "Image buffer" );
+
+ // FIXME FIXME
+ //workshop_form.img_buffer = vg_stack_allocate( &vg.scratch, w*h*3, 8, "Image buffer" );
vg_info( "read framebuffer: glReadPixels( %dx%d )\n", w,h );
workshop_form.img_w = w;
workshop_form.img_h = h;
- vg_async_call( &vg.loader_tasks, _workshop_form_submit_t1, NULL );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_workshop_form_submit_t1 );
}
/*
/*
* Reciever for completion of the model file load
*/
-static void workshop_form_loadmodel_async_complete( void *userdata )
+static void workshop_form_loadmodel_async_complete( void *_, vg_async_info *async )
{
- THREAD_0;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
v2_zero( workshop_form.view_angles );
v3_zero( workshop_form.view_offset );
/*
* Thread which loads the model from the disk
*/
-static void _workshop_form_load_t1( void *userdata )
+static void _workshop_form_load_t1( void *_, vg_async_info *async )
{
- THREAD_1;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
char path_buf[4096];
vg_str folder;
if( !vg_strgood(&folder) )
{
vg_error( "workshop async load failed: path too long\n" );
- vg_async_call( &vg.main_tasks, _workshop_form_end_op, NULL );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)_workshop_form_end_op );
return;
}
if( vg_dir_open( &dir, folder.buffer ) != k_dir_open_ok )
{
vg_error( "workshop async load failed: could not open folder\n" );
- vg_async_call( &vg.main_tasks, _workshop_form_end_op, NULL );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)_workshop_form_end_op );
return;
}
if( !found_mdl )
{
vg_error( "workshop async load failed: no model files found\n" );
- vg_async_call( &vg.main_tasks, _workshop_form_end_op, NULL );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)_workshop_form_end_op );
return;
}
player_model_load( &workshop_form.player_model, path_buf, &workshop_form.model_stack );
}
- vg_async_call( &vg.main_tasks, workshop_form_loadmodel_async_complete, NULL );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)workshop_form_loadmodel_async_complete );
}
/*
*/
static void workshop_op_load_model( ui_context *ctx )
{
- THREAD_0;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
world_instance *world = &_world.main;
workshop_form.view_world = world;
}
workshop_form.op = k_workshop_op_loading_model;
- vg_async_call( &vg.loader_tasks, _workshop_form_load_t1, NULL );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_workshop_form_load_t1 );
}
/*
/*
* The image has been decoded and is ready to slap into the framebuffer
*/
+
+// FIXME FIXME FIXME
static void workshop_form_async_imageload( void *data )
{
- THREAD_0;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
if( data )
{
vg_framebuffer_attachment *a = &g_render.fb_workshop_preview->attachments[0];
- glBindTexture( GL_TEXTURE_2D, a->id );
+ vg_tex_bind( GL_TEXTURE_2D, &a->tex, 6 );
glTexSubImage2D( GL_TEXTURE_2D, 0,0,0, WORKSHOP_PREVIEW_WIDTH, WORKSHOP_PREVIEW_HEIGHT, a->format, a->type, data );
stbi_image_free( data );
vg_success( "Loaded workshop preview image\n" );
/*
* Load the image located at ./workshop_preview.jpg into our framebuffer
*/
-static void _workshop_load_preview_t1( void *userdata )
+static void _workshop_load_preview_t1( void *_, vg_async_info *async )
{
- THREAD_1;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
char path_buf[ 4096 ];
vg_str path;
{
if( (x == WORKSHOP_PREVIEW_WIDTH) && (y == WORKSHOP_PREVIEW_HEIGHT) )
{
- vg_async_call( &vg.main_tasks, workshop_form_async_imageload, rgb );
+ //FIXME FIXME
+ //vg_async_call( &vg.main_tasks, workshop_form_async_imageload, rgb );
}
else
{
vg_error( "Resolution does not match framebuffer, so we can't show it\n" );
stbi_image_free( rgb );
- vg_async_call( &vg.main_tasks, workshop_form_async_imageload, NULL );
+
+ // FIXME FIXME
+ //vg_async_call( &vg.main_tasks, workshop_form_async_imageload, NULL );
}
}
else
{
- vg_async_call( &vg.main_tasks, workshop_form_async_imageload, NULL );
+ // FIXME FIXME
+ //vg_async_call( &vg.main_tasks, workshop_form_async_imageload, NULL );
}
}
else
{
- vg_async_call( &vg.main_tasks, workshop_form_async_imageload, NULL );
+ // FIXME FIXME
+ //vg_async_call( &vg.main_tasks, workshop_form_async_imageload, NULL );
}
}
*/
static void workshop_op_download_and_view_submission( int result_index )
{
- THREAD_0;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
workshop_form.op = k_workshop_op_downloading_submission;
SteamUGCDetails_t details;
vg_strncpy( details.m_rgchTitle, workshop_form.submission.title,
VG_ARRAY_LEN( workshop_form.submission.title ), k_strncpy_always_add_null );
- snprintf( workshop_form.addon_folder, VG_ARRAY_LEN( workshop_form.addon_folder ),
- "Steam Cloud ("PRINTF_U64")", details.m_nPublishedFileId );
+ vg_str folder_str;
+ vg_strnull( &folder_str, workshop_form.addon_folder, sizeof(workshop_form.addon_folder) );
+ vg_strcat( &folder_str, "Steam Cloud (" );
+ vg_strcatu64( &folder_str, details.m_nPublishedFileId, 16 );
workshop_form.submission.file_id = details.m_nPublishedFileId;
workshop_form.file_intent = k_workshop_form_file_intent_keep_old;
workshop_form.submission.type = k_addon_type_none;
workshop_form.submission.submission_type_selection = k_addon_type_none;
+ // FIXME FIXME FIXME FIXME:::::::::::::
+#if 0
if( have_meta )
{
u32 len = strlen(metadata_str);
{
vg_error( "No metadata was returned with this item.\n" );
}
+#endif
vg_framebuffer_bind( g_render.fb_workshop_preview, 1.0f );
glClearColor( 0.2f, 0.0f, 0.0f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
- glViewport( 0,0, vg.window_x, vg.window_y );
-
- vg_async_call( &vg.loader_tasks, _workshop_load_preview_t1, NULL );
+ glViewport( 0,0, _vg_window.w, _vg_window.h );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_workshop_load_preview_t1 );
}
else
{
return 0;
}
-void workshop_register(void)
+VG_API void _workshop_register(void)
{
vg_console_reg_cmd( "workshop_submit", workshop_submit_command, NULL );
}
render_world( &_world.main, &g_render.cam, 0, 0, 1, 1, g_render.fb_workshop_preview );
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
- glViewport( 0,0, vg.window_x, vg.window_y );
+ glViewport( 0,0, _vg_window.w, _vg_window.h );
}
/*
glEnable( GL_DEPTH_TEST );
glDisable( GL_BLEND );
- struct skeleton *sk = &localplayer.skeleton;
+ ms_skeleton *sk = &localplayer.skeleton;
player_pose res;
res.type = k_player_pose_type_ik;
- skeleton_anim anim;
+ ms_skeletal_animation anim;
player_get_anim( &anim, "idle_cycle+y" );
skeleton_sample_anim( sk, &anim, vg.time*0.1f, res.keyframes );
q_axis_angle( res.root_q, (v3f){0.0f,1.0f,0.0f}, VG_PIf );
render_playermodel( &cam, &_world.main, 0, &workshop_form.playermodel_view, sk, localplayer.final_mtx );
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
- glViewport( 0,0, vg.window_x, vg.window_y );
+ glViewport( 0,0, _vg_window.w, _vg_window.h );
}
/*
* pre-render step, but that includes timer stuff
*/
struct player_board *board = &workshop_form.board_model;
- struct ub_world_lighting *ubo = &world->ub_lighting;
+ struct ub_world_lighting *ubo = &world_render.ub_lighting;
v3f vp0, vp1;
v3_copy((v3f){0.0f,0.1f, board->truck_positions[0][2]}, vp0 );
v3_copy((v3f){0.0f,0.1f, board->truck_positions[1][2]}, vp1 );
m4x3_mulv( mmdl1, vp0, ubo->g_board_0 );
m4x3_mulv( mmdl1, vp1, ubo->g_board_1 );
- glBindBuffer( GL_UNIFORM_BUFFER, world->ubo_lighting );
- glBufferSubData( GL_UNIFORM_BUFFER, 0, sizeof(struct ub_world_lighting), &world->ub_lighting );
+ glBindBuffer( GL_UNIFORM_BUFFER, world_render.ubo_lighting );
+ glBufferSubData( GL_UNIFORM_BUFFER, 0, sizeof(struct ub_world_lighting), &world_render.ub_lighting );
render_world( world, &cam, 0, 0, 0, 0, g_render.fb_workshop_preview );
struct player_board_pose pose = {0};
render_board( &cam, world, board, mmdl1, &pose, k_board_shader_entity );
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
- glViewport( 0,0, vg.window_x, vg.window_y );
+ glViewport( 0,0, _vg_window.w, _vg_window.h );
}
/*
enum addon_type type = workshop_form.submission.type;
if( workshop_form.file_intent == k_workshop_form_file_intent_keep_old )
{
- ui_image( ctx, img_box, &g_render.fb_workshop_preview->attachments[0].id, 0 );
+ // FIXME FIXME
+ // ui_image( ctx, img_box, &g_render.fb_workshop_preview->attachments[0].id, 0 );
}
else if( workshop_form.file_intent == k_workshop_form_file_intent_new )
{
- ui_image( ctx, img_box, &g_render.fb_workshop_preview->attachments[0].id, 0 );
+ // FIXME FIXME
+ // ui_image( ctx, img_box, &g_render.fb_workshop_preview->attachments[0].id, 0 );
if( type == k_addon_type_world )
return;
vg_str str;
vg_strnull( &str, buf, sizeof(buf) );
vg_strcat( &str, "page " );
- vg_strcati32( &str, workshop_form.view_published_page_id+1 );
+ vg_strcati64( &str, workshop_form.view_published_page_id+1, 10 );
vg_strcatch( &str, '/' );
- vg_strcati32( &str, workshop_form.view_published_page_count );
+ vg_strcati64( &str, workshop_form.view_published_page_count, 10 );
ui_rect_pad( controls, (ui_px[2]){0,4} );
ui_rect info;
return;
ui_rect null;
- ui_rect screen = { 0, 0, vg.window_x, vg.window_y };
+ ui_rect screen = { 0, 0, _vg_window.w, _vg_window.h };
ui_rect window = { 0, 0, 1000, 700 };
ui_rect_center( screen, window );
ctx->wants_mouse = 1;
-#pragma once
-#include "addon_types.h"
-#include "vg/vg_steam2.h"
-#include "skaterift.h"
-#include "ent_skateshop.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/workshop.c"
+#else
struct async_workshop_filepath_info{
PublishedFileId_t id;
}
extern workshop_form;
-void workshop_register(void);
+VG_API void _workshop_register(void);
+
int workshop_submit_command( int argc, const char *argv[] );
void async_workshop_get_filepath( void *data, u32 len );
void async_workshop_get_installed_files( void *data, u32 len );
void workshop_load_metadata( const char *path,struct workshop_file_info *info );
void workshop_form_gui( ui_context *ctx );
+
+#endif
-/*
- * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#include "skaterift.h"
-#include "world.h"
-#include "network.h"
-#include "vg/vg_loader.h"
-#include "vg/vg_mem.h"
-#include "save.h"
-#include "player.h"
-#include "ent_traffic.h"
-
struct world_static _world;
-void world_init(void)
+VG_API void _world_init(void)
{
- vg_loader_step( world_render_init, NULL );
- vg_loader_step( world_sfd_init, NULL );
- vg_loader_step( world_water_init, NULL );
- vg_loader_step( world_gates_init, NULL );
- vg_loader_step( world_routes_init, NULL );
+ _world_render_init();
+ _world_sfd_init();
+ _world_water_init();
+ _world_gates_init();
+ _world_routes_init();
/* Allocate dynamic world memory arena */
- _world.stack = vg_stack_make_substack( &vg.rtmem, VG_MB(76), "World main data" );
- vg_stack_set_flags( _world.stack, VG_STACK_ALLOCATOR_METADATA );
- _world.preview_stack = vg_stack_make_substack( &vg.rtmem, VG_MB(32), "World preview data" );
- vg_stack_set_flags( _world.preview_stack, VG_STACK_ALLOCATOR_METADATA );
+ vg_stack_init( &_world.stack, VG_STACK_USE_HEAP, VG_MB(76), "World main data" );
+ vg_stack_init( &_world.preview_stack, VG_STACK_USE_HEAP, VG_MB(32), "World preview data" );
}
void world_update( world_instance *world, v3f pos )
world_sfd_update( world, pos );
world_volumes_update( world, pos );
ent_skateshop_update();
- ent_challenge_update();
+ _ent_challenge_update();
ent_prop_update( world );
+ _world_audio_update( pos );
}
void world_gui( ui_context *ctx, world_instance *world )
{
- ent_skateshop_gui( ctx );
+ _ent_skateshop_gui( ctx );
_ent_challenge_ui( ctx );
}
-/*
- * Copyright (C) 2021-2024 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#pragma once
-#include "render.h"
-#include "network_msg.h"
-#include "addon.h"
-#include "scene.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/world.c"
+#else
/* types
*/
typedef struct world_instance world_instance;
-/* submodule headers */
-#include "world_entity.h"
-#include "world_gate.h"
-#include "world_gen.h"
-#include "world_info.h"
-#include "world_physics.h"
-#include "world_render.h"
-#include "world_sfd.h"
-#include "world_volumes.h"
-#include "world_water.h"
-#include "world_audio.h"
-#include "world_routes.h"
-#include "world_routes_ui.h"
-
/* console variables */
static f32 k_day_length = 30.0f; /* minutes */
f64 time;
f32 tar_min, tar_max;
-
- /* STD140 */
- struct ub_world_lighting{
- v4f g_cube_min,
- g_cube_inv_range;
-
- v4f g_water_plane,
- g_depth_bounds;
-
- v4f g_daysky_colour;
- v4f g_nightsky_colour;
- v4f g_sunset_colour;
- v4f g_ambient_colour;
- v4f g_sunset_ambient;
- v4f g_sun_colour;
- v4f g_sun_dir;
- v4f g_board_0;
- v4f g_board_1;
-
- float g_water_fog;
- float g_time;
- float g_realtime;
- float g_shadow_length;
- float g_shadow_spread;
-
- float g_time_of_day;
- float g_day_phase;
- float g_sunset_phase;
-
- int g_light_preview;
- int g_shadow_samples;
-
- int g_debug_indices;
- int g_debug_complexity;
- }
- ub_lighting;
- GLuint ubo_lighting;
- int ubo_bind_point;
-
GLuint tbo_light_entities,
tex_light_entities,
tex_light_cubes;
float probabilities[3];
v3i light_cubes;
- vg_framebuffer *heightmap;
/*
* Dynamically allocated when world_load is called.
/*
* Main world .mdl
*/
- mdl_context meta;
+ vg_model meta;
- GLuint *textures;
- u32 texture_count;
-
- struct world_surface{
- mdl_material info;
+ struct world_surface
+ {
+ mdl_material info;
mdl_submesh sm_geo,
sm_no_collide;
u32 flags;
ent_atom,
ent_cutscene;
- GLuint *nonlocal_gates_cubemaps;
+ vg_tex *nonlocal_gates_cubemaps;
u32 nonlocal_gate_count;
enum skybox {
*/
/* world geometry */
- scene_context scene_geo,
- scene_geo_gpu,
- scene_no_collide,
- scene_lines;
+ vg_scene scene_geometry;
+ scene_mesh main_scene_mesh,
+ line_scene_mesh,
+ transparent_scene_mesh;
/* spacial mappings */
- bh_tree *geo_bh,
- *entity_bh;
- u32 *entity_list;
+ bh_tree geometry_bh,
+ entity_bh;
- /* graphics */
- glmesh mesh_route_lines;
- glmesh mesh_geo,
- mesh_no_collide;
+ u32 *entity_list;
u32 cubemap_cooldown, cubemap_side;
/* leaderboards */
* Allocated as system memory
* --------------------------------------------------------------------------
*/
- vg_stack_allocator *stack, *preview_stack;
+ vg_stack_allocator stack, preview_stack;
u32 current_run_version;
f64 last_gate_hit_time;
}
extern _world;
-void world_init(void);
+VG_API void _world_init(void);
void skaterift_world_load_thread( void *_ );
void world_update( world_instance *world, v3f pos );
bool world_clear_event( enum world_event activity );
void world_set_entity_driven_camera( vg_camera *cam );
void world_gui( ui_context *ctx, world_instance *world );
+
+#endif
-#include "audio.h"
-#include "world_audio.h"
-
/*
* Trace out a random point, near the player to try and determine water areas
*/
return k_audio_sprite_type_none;
}
+void _world_audio_update( v3f co )
+{
+ static float accum = 0.0f;
+ accum += vg.time_delta;
+
+ if( accum > 0.1f )
+ accum -= 0.1f;
+ else return;
+
+ v3f sprite_pos;
+ enum audio_sprite_type sprite_type = world_audio_sample_sprite_random( co, sprite_pos );
+
+ if( sprite_type != k_audio_sprite_type_none )
+ {
+ if( sprite_type == k_audio_sprite_type_grass )
+ {
+ audio_ambient_sprite_play( sprite_pos, &audio_grass[vg_randu32(&vg.rand)%4] );
+ }
+ else if( sprite_type == k_audio_sprite_type_water )
+ {
+ if( _world.main.water.enabled )
+ {
+ audio_ambient_sprite_play( sprite_pos, &audio_water[vg_randu32(&vg.rand)%6] );
+ }
+ }
+ }
+}
+
void world_audio_sample_distances( v3f co, int *index, float *value )
{
float inr3 = 0.57735027,
-#pragma once
-#include "world.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/world_audio.c"
+#else
void world_fadeout_audio( world_instance *world );
void world_audio_sample_distances( v3f co, int *index, float *value );
enum audio_sprite_type
world_audio_sample_sprite_random( v3f origin, v3f output );
+void _world_audio_update( v3f co );
+
+#endif
-#include "vg/vg_steam2.h"
-#include "model.h"
-#include "entity.h"
-#include "world.h"
-#include "world_load.h"
-#include "save.h"
-#include "vg/vg_msg.h"
-#include "menu.h"
-#include "ent_challenge.h"
-#include "ent_skateshop.h"
-#include "ent_route.h"
-#include "ent_traffic.h"
-#include "ent_glider.h"
-#include "ent_region.h"
-#include "ent_camera.h"
-#include "ent_atom.h"
-#include "ent_cutscene.h"
-#include "input.h"
-#include "player_walk.h"
-
bh_system bh_system_entity_list =
{
.expand_bound = entity_bh_expand_bound,
static void _event_trigger( ent_event *event );
-void world_gen_entities_init( world_instance *world )
+void world_gen_entities_init( world_instance *world, vg_model_stream_context *ctx )
{
- THREAD_1;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
/* lights */
for( u32 j=0; j<af_arrcount(&world->ent_light); j ++ )
if( world->nonlocal_gate_count )
{
- world->nonlocal_gates_cubemaps = vg_stack_allocate( world->stack, world->nonlocal_gate_count*sizeof(GLuint),
+ world->nonlocal_gates_cubemaps = vg_stack_allocate( world->stack, world->nonlocal_gate_count*sizeof(vg_tex),
8, "Non-local cubemaps" );
- for( u32 i=0; i<world->nonlocal_gate_count; i ++ )
- world->nonlocal_gates_cubemaps[i] = 0;
+ vg_zero_mem( world->nonlocal_gates_cubemaps, world->nonlocal_gate_count*sizeof(vg_tex) );
for( u32 j=0; j<af_arrcount(&world->ent_gate); j ++ )
{
if( gate->remote_addon_id )
{
char cubemap_path[256];
- nonlocal_gate_cubemap_path( gate->remote_addon_id, af_str( &world->meta.af, gate->key ), cubemap_path );
- vg_tex2d_load_qoi_async_file( cubemap_path, VG_TEX2D_CUBEMAP,
- &world->nonlocal_gates_cubemaps[ gate->cubemap_id ] );
+ nonlocal_gate_cubemap_path( gate->remote_addon_id, af_str( world->meta.packed_strings, gate->key ), cubemap_path );
+
+ u32 flags = VG_TEX_CUBEMAP|VG_TEX_CLAMP|VG_TEX_LINEAR|VG_TEX_NOMIP;
+ _vg_tex_load( &world->nonlocal_gates_cubemaps[ gate->cubemap_id ], cubemap_path, flags );
}
}
}
for( u32 k=0; k<audio->clip_count; k++ )
{
ent_audio_clip *clip = af_arritm( &world->ent_audio_clip, audio->clip_start+k );
+
if( clip->_.file.pack_size )
{
u32 size = clip->_.file.pack_size,
offset = clip->_.file.pack_offset;
- /* embedded files are fine to clear the scratch buffer, only
- * external audio uses it */
-
- vg_stack_clear( &vg.scratch );
- void *data = vg_stack_allocate( &vg.scratch, clip->_.file.pack_size, 8, "Pack data" );
-
- mdl_fread_pack_file( &world->meta, &clip->_.file, data );
+ clip->_.clip.any_data = vg_stack_allocate( world->stack, clip->_.file.pack_size, 8, "Pack data" );
+ vg_stream_read( vg_model_stream_pack_stream( ctx, &clip->_.file ), clip->_.clip.any_data, clip->_.file.pack_size );
clip->_.clip.path = NULL;
clip->_.clip.flags = audio->flags;
- clip->_.clip.any_data = data;
clip->_.clip.size = size;
}
else
{
- clip->_.clip.path = af_str( &world->meta.af, clip->_.file.pstr_path );
+ clip->_.clip.path = af_str( world->meta.packed_strings, clip->_.file.pstr_path );
clip->_.clip.flags = audio->flags;
clip->_.clip.any_data = NULL;
clip->_.clip.size = 0;
}
- audio_clip_load( &clip->_.clip, world->stack );
+ vg_audio_clip_load( &clip->_.clip, world->stack );
}
}
for( u32 i=0; i<VG_ARRAY_LEN(indexables); i++ )
indexed_count += af_arrcount( indexables[i].array );
vg_info( "indexing %u entities\n", indexed_count );
-
world->entity_list = vg_stack_allocate( world->stack, indexed_count*sizeof(u32), 4, "Entity List");
u32 index=0;
for( u32 j=0; j<count; j ++ )
world->entity_list[index ++] = mdl_entity_id( type, j );
}
-
- world->entity_bh = bh_create( world->stack, &bh_system_entity_list, world, indexed_count, 2 );
+ bh_create( &world->entity_bh, &bh_system_entity_list, world, indexed_count, 2, world->stack );
/* FIXME: This should be scene geometry instead?????????? */
- world->tar_min = world->entity_bh->nodes[0].bbx[0][1];
- world->tar_max = world->entity_bh->nodes[0].bbx[1][1] + 20.0f;
+ world->tar_min = world->entity_bh.nodes[0].bbx[0][1];
+ world->tar_max = world->entity_bh.nodes[0].bbx[1][1] + 20.0f;
for( u32 i=0; i<af_arrcount(&world->ent_marker); i++ )
{
ent_marker *marker = af_arritm( &world->ent_marker, i );
- if( AF_STR_EQ( &world->meta.af, marker->pstr_alias, "tar_min" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, marker->pstr_alias, "tar_min" ) )
world->tar_min = marker->transform.co[1];
- if( AF_STR_EQ( &world->meta.af, marker->pstr_alias, "tar_max" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, marker->pstr_alias, "tar_max" ) )
world->tar_max = marker->transform.co[1];
}
}
for( u32 i=0; i<af_arrcount(&world->ent_spawn); i++ )
{
r = af_arritm( &world->ent_spawn, i );
- if( af_str_eq( &world->meta.af, r->pstr_name, name, hash ) )
+ if( af_str_eq( world->meta.packed_strings, r->pstr_name, name, hash ) )
{
rp = r;
break;
v3f sound_co;
v3_copy( audio->transform.co, sound_co );
- if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "spawn_particle" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "spawn_particle" ) )
{
// TODO: Make this dynamiclly fetched from a handler for the entity itself. (or not, fuck you)
if( mdl_entity_id_type( event->source_entity_id ) == k_ent_volume )
return k_entity_event_result_invalid;
}
}
- else if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "play" ) ){}
+ else if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "play" ) ){}
else return k_entity_event_result_unhandled;
ent_audio_trigger( audio, sound_co );
world_instance *world = &_world.main;
ent_light *light = af_arritm( &world->ent_light, mdl_entity_id_id( event->recieve_entity_id ) );
- if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "on" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "on" ) )
{
if( event->flags & k_ent_event_data_const_i32 )
{
entity_event_result ent_ccmd_event( ent_event *event )
{
world_instance *world = &_world.main;
- if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "exec" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "exec" ) )
{
ent_ccmd *ccmd = af_arritm( &world->ent_ccmd, mdl_entity_id_id( event->recieve_entity_id ));
- const char *cmd_text = af_str( &world->meta.af, ccmd->pstr_command );
+ const char *cmd_text = af_str( world->meta.packed_strings, ccmd->pstr_command );
vg_info( "ccmd: %s\n", cmd_text );
vg_execute_console_input( cmd_text, 0, 1 );
return k_entity_event_result_OK;
vg_fatal_error( "Programming error\n" );
}
-void world_entity_start( world_instance *world, vg_msg *sav )
+void world_entity_start( world_instance *world, vg_kvs *savedata )
{
vg_info( "Start instance %p\n", world );
k_gravity = 9.6f;
for( u32 i=0; i<af_arrcount( &world->ent_event ); i ++ )
{
ent_event *event = af_arritm( &world->ent_event, i );
- if( AF_STR_EQ( &world->meta.af, event->pstr_source_event, "init" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, event->pstr_source_event, "init" ) )
_event_trigger( event );
}
for( u32 i=0; i<af_arrcount(&world->ent_challenge); i++ )
{
ent_challenge *challenge = af_arritm( &world->ent_challenge, i );
- const char *alias = af_str( &world->meta.af, challenge->pstr_alias );
- vg_msg_getkvintg( sav, alias, k_vg_msg_u32, &challenge->status, NULL );
+ const char *alias = af_str( world->meta.packed_strings, challenge->pstr_alias );
+ vg_kv_read_vu32( savedata, 0, alias, NULL, &challenge->status, 1 );
_ent_challenge_clear( challenge );
}
- vg_msg routes_block = *sav;
- if( vg_msg_seekframe( &routes_block, "routes" ) )
+ u32 routes_block = vg_kv_find( savedata, 0, "routes" );
+ if( routes_block )
{
for( u32 i=0; i<af_arrcount(&world->ent_route); i++ )
{
ent_route *route = af_arritm( &world->ent_route, i );
- vg_msg route_info = routes_block;
- if( vg_msg_seekframe( &route_info, af_str(&world->meta.af,route->pstr_name) ) )
+
+ u32 route_info = vg_kv_find( savedata, routes_block, af_str(world->meta.packed_strings,route->pstr_name) );
+ if( route_info )
{
u32 flags;
- vg_msg_getkvintg( &route_info, "flags", k_vg_msg_u32, &flags, NULL );
+ vg_kv_read_vu32( savedata, route_info, "flags", NULL, &flags, 1 );
route->flags |= flags;
-
- vg_msg_getkvintg( &route_info, "best_laptime", k_vg_msg_f64, &route->best_laptime, NULL );
+
+ f32 best_time;
+ vg_kv_read_vf32( savedata, route_info, "best_laptime", NULL, &best_time, 1 );
+ route->best_laptime = best_time;
f32 sections[ route->checkpoints_count ];
- vg_msg_cmd cmd;
- if( vg_msg_getkvcmd( &route_info, "sections", &cmd ) )
- vg_msg_cast( cmd.value, cmd.code, sections, k_vg_msg_f32 | vg_msg_count_bits(route->checkpoints_count) );
- else
- for( u32 j=0; j<route->checkpoints_count; j ++ )
- sections[j] = 0.0f;
+ for( u32 j=0; j<route->checkpoints_count; j ++ )
+ sections[j] = 0.0f;
+
+ vg_zero_mem( sections, sizeof(sections) );
+ vg_kv_read_vf32( savedata, route_info, "sections", NULL, sections, route->checkpoints_count );
for( u32 j=0; j<route->checkpoints_count; j ++ )
{
_atom_list_clear( k_atom_list_world );
- vg_msg_cursor orig = sav->cur;
- if( vg_msg_seekframe( sav, "atoms" ) )
+ u32 atoms_block = vg_kv_find( savedata, 0, "atoms" );
+ if( atoms_block )
{
- vg_msg_cmd cmd;
- while( vg_msg_next( sav, &cmd ) )
+ u32 key = vg_kv_child( savedata, atoms_block, 0 );
+ while( key )
{
- if( cmd.code == k_vg_msg_endframe ) break;
- i32 value = 0;
- vg_msg_cast( cmd.value, cmd.code, &value, k_vg_msg_i32 );
- _atom_set( k_atom_list_world, cmd.key, value );
+ vg_strp s = { .buffer = vg_kv_value( savedata, key, NULL ) };
+
+ i64 value;
+ vg_strp_i64( &s, &value );
+ _atom_set( k_atom_list_world, vg_kv_key( savedata, key, NULL ), (i32)value );
+
+ key = vg_kv_next( savedata, key );
}
}
else
{
enum e_atom_list list = (atom->flags & k_ent_atom_global)? k_atom_list_global: k_atom_list_world;
- value = _atom_get( list, af_str( &world->meta.af, atom->pstr_alias ) );
+ value = _atom_get( list, af_str( world->meta.packed_strings, atom->pstr_alias ) );
}
_world_raise_event( mdl_entity_id( k_ent_atom, i ), "changed" );
_world_raise_event( mdl_entity_id( k_ent_atom, i ), value? "true": "false" );
ent_challenge *challenge = af_arritm( &world->ent_challenge, i );
_world_raise_event( mdl_entity_id( k_ent_challenge, i ), challenge->status? "true": "false" );
}
-
- sav->cur = orig;
}
-void world_entity_serialize( world_instance *world, vg_msg *sav )
+void world_entity_serialize( world_instance *world, vg_kvs *savedata )
{
for( u32 i=0; i<af_arrcount(&world->ent_challenge); i++ )
{
ent_challenge *challenge = af_arritm(&world->ent_challenge,i);
- const char *alias = af_str( &world->meta.af, challenge->pstr_alias );
- vg_msg_wkvnum( sav, alias, k_vg_msg_u32, 1, &challenge->status );
+ const char *alias = af_str( world->meta.packed_strings, challenge->pstr_alias );
+ vg_kv_append_vu32( savedata, 0, alias, &challenge->status, 1 );
}
if( af_arrcount(&world->ent_route) )
{
- vg_msg_frame( sav, "routes" );
+ u32 routes_block = vg_kv_append( savedata, 0, "routes", NULL );
for( u32 i=0; i<af_arrcount(&world->ent_route); i++ )
{
ent_route *route = af_arritm( &world->ent_route, i );
- vg_msg_frame( sav, af_str( &world->meta.af, route->pstr_name ) );
+
+ u32 route_info = vg_kv_append( savedata, routes_block, af_str( world->meta.packed_strings, route->pstr_name ), NULL );
{
- vg_msg_wkvnum( sav, "flags", k_vg_msg_u32, 1, &route->flags );
- vg_msg_wkvnum( sav, "best_laptime", k_vg_msg_f64, 1, &route->best_laptime );
+ vg_kv_append_vu32( savedata, route_info, "flags", &route->flags, 1 );
+ vg_kv_append_vf32( savedata, route_info, "best_laptime", (f32[]){ route->best_laptime }, 1 );
f32 sections[ route->checkpoints_count ];
-
for( u32 j=0; j<route->checkpoints_count; j ++ )
{
ent_checkpoint *cp = af_arritm( &world->ent_checkpoint, route->checkpoints_start + j );
sections[j] = cp->best_time;
}
-
- vg_msg_wkvnum( sav, "sections", k_vg_msg_f32, route->checkpoints_count, sections );
+ vg_kv_append_vf32( savedata, route_info, "sections", sections, route->checkpoints_count );
}
- vg_msg_end_frame( sav );
}
- vg_msg_end_frame( sav );
}
}
if( event->source_entity_id != caller )
continue;
- if( af_str_eq( &world->meta.af, event->pstr_source_event, event_alias, event_alias_hash ) )
+ if( af_str_eq( world->meta.packed_strings, event->pstr_source_event, event_alias, event_alias_hash ) )
{
if( event->delay > 0.001f )
{
if( event->flags & k_ent_event_data_const_string )
{
vg_info( "[event '%s'] %x -> %x ('%s') with '%s'\n",
- af_str( &world->meta.af, event->pstr_source_event ), event->source_entity_id,
- event->recieve_entity_id, af_str( &world->meta.af, event->pstr_recieve_event ),
- af_str( &world->meta.af, event->data.const_pstr ) );
+ af_str( world->meta.packed_strings, event->pstr_source_event ), event->source_entity_id,
+ event->recieve_entity_id, af_str( world->meta.packed_strings, event->pstr_recieve_event ),
+ af_str( world->meta.packed_strings, event->data.const_pstr ) );
}
else if( event->flags & k_ent_event_data_const_i32 )
{
vg_info( "[event '%s'] %x -> %x ('%s') with %d\n",
- af_str( &world->meta.af, event->pstr_source_event ), event->source_entity_id,
- event->recieve_entity_id, af_str( &world->meta.af, event->pstr_recieve_event ),
+ af_str( world->meta.packed_strings, event->pstr_source_event ), event->source_entity_id,
+ event->recieve_entity_id, af_str( world->meta.packed_strings, event->pstr_recieve_event ),
event->data.const_i32 );
}
else if( event->flags & k_ent_event_data_const_f32 )
{
vg_info( "[event '%s'] %x -> %x ('%s') with %ff\n",
- af_str( &world->meta.af, event->pstr_source_event ), event->source_entity_id,
- event->recieve_entity_id, af_str( &world->meta.af, event->pstr_recieve_event ),
+ af_str( world->meta.packed_strings, event->pstr_source_event ), event->source_entity_id,
+ event->recieve_entity_id, af_str( world->meta.packed_strings, event->pstr_recieve_event ),
event->data.const_f32 );
}
else if( event->flags & k_ent_event_data_const_f32 )
{
vg_info( "[event '%s'] %x -> %x ('%s') void\n",
- af_str( &world->meta.af, event->pstr_source_event ), event->source_entity_id,
- event->recieve_entity_id, af_str( &world->meta.af, event->pstr_recieve_event ));
+ af_str( world->meta.packed_strings, event->pstr_source_event ), event->source_entity_id,
+ event->recieve_entity_id, af_str( world->meta.packed_strings, event->pstr_recieve_event ));
}
enum entity_event_result res = table[type]( event );
if( res == k_entity_event_result_unhandled )
{
vg_warn( "Call to entity %x#%x was unhandled (no event '%s').\n", type, index,
- af_str( &world->meta.af, event->pstr_recieve_event ) );
+ af_str( world->meta.packed_strings, event->pstr_recieve_event ) );
}
else if( res == k_entity_event_result_invalid )
vg_warn( "Call to entity %x#%x invalid.\n", type, index );
-#pragma once
-#include "world.h"
-#include "entity.h"
-#include "vg/vg_bvh.h"
-#include "vg/vg_msg.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/world_entity.c"
+#else
-void world_gen_entities_init( world_instance *world );
+void world_gen_entities_init( world_instance *world, vg_model_stream_context *ctx );
ent_spawn *world_find_spawn_by_name( world_instance *world, const char *name );
ent_spawn *world_find_closest_spawn( world_instance *world, v3f position );
void world_default_spawn_pos( world_instance *world, v3f pos );
-void world_entity_start( world_instance *world, vg_msg *sav );
-void world_entity_serialize( world_instance *world, vg_msg *sav );
+void world_entity_start( world_instance *world, vg_kvs *savedata );
+void world_entity_serialize( world_instance *world, vg_kvs *savedata );
//entity_call_result ent_volume_call( world_instance *world, ent_call *call );
//entity_call_result ent_audio_call( world_instance *world, ent_call *call );
extern bh_system bh_system_entity_list;
void _world_raise_event( u32 caller, const char *event_alias );
void _ent_update(void);
+
+#endif
-/*
- * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#ifndef WORLD_GATE_C
-#define WORLD_GATE_C
-
-#include "world.h"
-#include "world_gate.h"
-
-#include "skaterift.h"
-#include "common.h"
-#include "model.h"
-#include "entity.h"
-#include "render.h"
-
-#include "world_water.h"
-#include "player_remote.h"
-#include "shaders/model_gate_unlinked.h"
-#include <string.h>
-
-struct world_gates world_gates;
+struct _world_gates _world_gates;
/*
* Update the transform matrices for gate
*/
-void gate_transform_update( ent_gate *gate )
+VG_TIER_0 void gate_transform_update( ent_gate *gate )
{
if( gate->flags & k_ent_gate_flip )
{
m4x3_mul( recv_to_world, to_local, gate->transport );
}
-void world_gates_init(void)
+static void _world_gates_load_content_async( void *_, vg_async_info *async )
{
- THREAD_1;
- vg_info( "world_gates_init\n" );
- vg_stack_clear( &vg.scratch );
-
- mdl_context mgate;
- mdl_open( &mgate, "models/rs_gate.mdl", &vg.scratch );
- mdl_load_metadata_block( &mgate, &vg.scratch );
-
- world_gates.sm_surface = mgate.submeshes[ mdl_get_submesh_index( &mgate, "rs_gate" ) ];
-
- const char *names[] = { "rs_gate_marker", "rs_gate_marker.001",
- "rs_gate_marker.002", "rs_gate_marker.003" };
-
- for( int i=0; i<4; i++ )
- world_gates.sm_marker[i] = mgate.submeshes[ mdl_get_submesh_index( &mgate, names[i] ) ];
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+ vg_model_load( &_world_gates.model, VG_MODEL_ENGINE_STANDARD, "models/rs_gate.mdl", VG_STACK_USE_HEAP );
+ _world_gates.sm_surface = _world_gates.model.submeshes[ vg_model_get_submesh_index( &_world_gates.model, "rs_gate" ) ];
+ const c8 *names[] = { "rs_gate_marker", "rs_gate_marker.001",
+ "rs_gate_marker.002", "rs_gate_marker.003" };
+ for( u32 i=0; i<4; i++ )
+ _world_gates.sm_marker[i] = _world_gates.model.submeshes[ vg_model_get_submesh_index( &_world_gates.model,names[i] ) ];
+}
- mdl_async_load_glmesh( &mgate, &world_gates.mesh, NULL );
- mdl_close( &mgate );
+VG_API void _world_gates_init(void)
+{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_world_gates_load_content_async );
}
void ent_gate_get_mdl_mtx( ent_gate *gate, m4x3f mmdl )
{
if( gate->flags & k_ent_gate_custom_mesh )
{
- mesh_bind( &world->mesh_no_collide );
+ scene_mesh_bind( &world->transparent_scene_mesh );
for( u32 i=0; i<gate->submesh_count; i++ )
{
mdl_submesh *sm = &world->meta.submeshes[ gate->submesh_start+i ];
- mdl_draw_submesh( sm );
+ vg_model_draw_submesh( sm );
}
}
else
{
- mesh_bind( &world_gates.mesh );
- mdl_draw_submesh( &world_gates.sm_surface );
+ vg_model_bind_mesh( &_world_gates.model );
+ vg_model_draw_submesh( &_world_gates.sm_surface );
}
}
}
/* update gate camera */
- world_gates.cam.fov = cam->fov;
- world_gates.cam.nearz = 0.1f;
- world_gates.cam.farz = 2000.0f;
+ _world_gates.cam.fov = cam->fov;
+ _world_gates.cam.nearz = 0.1f;
+ _world_gates.cam.farz = 2000.0f;
- m4x3_mul( gate->transport, cam->transform, world_gates.cam.transform );
- vg_camera_update_view( &world_gates.cam );
- vg_camera_update_projection( &world_gates.cam, vg.window_x, vg.window_y );
+ m4x3_mul( gate->transport, cam->transform, _world_gates.cam.transform );
+ vg_camera_update_view( &_world_gates.cam );
+ vg_camera_update_projection( &_world_gates.cam, _vg_window.w, _vg_window.h );
/* Add special clipping plane to projection */
v4f surface;
q_mulv( gate->q[1], (v3f){0.0f,0.0f,-1.0f}, surface );
surface[3] = v3_dot( surface, gate->co[1] );
- m4x3_mulp( world_gates.cam.transform_inverse, surface, surface );
+ m4x3_mulp( _world_gates.cam.transform_inverse, surface, surface );
surface[3] = -fabsf(surface[3]);
if( dist < -0.5f )
- m4x4_clip_projection( world_gates.cam.mtx.p, surface );
+ m4x4_clip_projection( _world_gates.cam.mtx.p, surface );
/* Ready to draw with new camrea */
- vg_camera_finalize( &world_gates.cam );
+ vg_camera_finalize( &_world_gates.cam );
- vg_line_point( world_gates.cam.transform[3], 0.3f, 0xff00ff00 );
+ vg_line_point( _world_gates.cam.transform[3], 0.3f, 0xff00ff00 );
shader_model_gate_use();
shader_model_gate_uPv( cam->mtx.pv );
shader_model_gate_uColour( (v4f){0.0f,1.0f,0.0f,0.0f} );
shader_model_gate_uTime( vg.time*0.25f );
shader_model_gate_uInvRes( (v2f){
- 1.0f / (float)vg.window_x,
- 1.0f / (float)vg.window_y });
+ 1.0f / (float)_vg_window.w,
+ 1.0f / (float)_vg_window.h });
glEnable( GL_STENCIL_TEST );
glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
render_gate_mesh( world, gate );
if( world_inside )
- render_world( world_inside, &world_gates.cam, 1, !localplayer.gate_waiting, 1, 1, target_fb );
+ render_world( world_inside, &_world_gates.cam, 1, !localplayer.gate_waiting, 1, 1, target_fb );
return 1;
}
{
world_instance *world = &_world.main;
ent_gate *gate = af_arritm( &world->ent_gate, mdl_entity_id_id( event->recieve_entity_id ) );
- if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "lock" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "lock" ) )
{
// TODO: Make this dynamiclly fetched from a handler for the entity itself. (or not, fuck you)
if( event->flags == k_ent_event_data_const_i32 )
*/
void world_link_gates( world_instance *world )
{
- THREAD_1;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
bool found_nonlocal_reciever = 0;
{
if( gate->target )
{
- const char *dest_world = af_str( &world->meta.af, gate->target );
+ const char *dest_world = af_str( world->meta.packed_strings, gate->target );
addon_alias q;
if( addon_parse_uid( dest_world, &q ) )
if( _world.travelled_through_nonlocal_gate )
{
- const char *key = af_str( &world->meta.af, gate->key );
+ const char *key = af_str( world->meta.packed_strings, gate->key );
if( vg_str_eq( key, _world.nonlocal_destination_key ) )
{
if( found_nonlocal_reciever )
_world.travelled_through_nonlocal_gate = 0;
}
}
-
-#endif /* WORLD_GATE_C */
-/*
- * Copyright (C) 2021-2024 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
+#if defined( SR_IMPLEMENTATION )
+# include "src/world_gate.c"
+#else
-#pragma once
-
-#include "vg/vg_camera.h"
-#include "world.h"
-#include "shaders/model_gate.h"
-#include "entity.h"
-
-struct world_gates
+struct _world_gates
{
- glmesh mesh;
+ vg_model model;
mdl_submesh sm_surface, sm_marker[4];
vg_camera cam;
-
v3f userportal_co;
}
-extern world_gates;
+extern _world_gates;
-void world_gates_init(void);
-void gate_transform_update( ent_gate *gate );
+VG_API void _world_gates_init(void);
+
+VG_TIER_0 void gate_transform_update( ent_gate *gate );
int render_gate( world_instance *world, world_instance *world_inside,
ent_gate *gate, vg_camera *cam, vg_framebuffer *target_fb );
void world_unlink_nonlocal( world_instance *world );
void render_gate_unlinked( world_instance *world, ent_gate *gate, vg_camera *cam );
void nonlocal_gate_cubemap_path( addon_id world_addon_id, const char *gate_key, char path[256] );
+
+#endif
-/*
- * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
- *
- * World generation/population. Different to regular loading, since it needs to
- * create geometry, apply procedural stuff and save that image to files etc.
- */
-#include "world.h"
-#include "world_gen.h"
-#include "world_load.h"
-#include "world_volumes.h"
-#include "world_gate.h"
-#include <string.h>
-
/*
* Add all triangles from the model, which match the material ID
* applies affine transform to the model
*/
-static void world_add_all_if_material( m4x3f transform, scene_context *scene,
- mdl_context *mdl, u32 id )
+static void world_add_all_if_material( m4x3f transform, scene_builder_context *builder, vg_model *mdl, u32 id )
{
for( u32 i=0; i<mdl->mesh_count; i++ )
{
mdl_mesh *mesh = &mdl->meshes[ i ];
-
for( u32 j=0; j<mesh->submesh_count; j++ )
{
mdl_submesh *sm = &mdl->submeshes[ mesh->submesh_start+j ];
m4x3f transform2;
mdl_transform_m4x3( &mesh->transform, transform2 );
m4x3_mul( transform, transform2, transform2 );
-
- scene_add_mdl_submesh( scene, mdl, sm, transform2 );
+ scene_builder_add_model_submesh( builder, mdl, sm, transform2 );
}
}
}
* | |
* |________|
*/
-static void world_gen_add_blob( vg_rand *rand, world_instance *world,
- scene_context *scene, ray_hit *hit )
+static void world_gen_add_blob( vg_rand *rand, world_instance *world, scene_builder_context *builder, ray_hit *hit )
{
m4x3f transform;
v4f qsurface, qrandom;
v3_cross( (v3f){0.0f,1.0f,0.0f}, hit->normal, axis );
- float angle = v3_dot(hit->normal,(v3f){0.0f,1.0f,0.0f});
+ f32 angle = v3_dot(hit->normal,(v3f){0.0f,1.0f,0.0f});
q_axis_angle( qsurface, axis, angle );
q_axis_angle( qrandom, (v3f){0.0f,1.0f,0.0f}, vg_randf64(rand)*VG_TAUf );
q_mul( qsurface, qrandom, qsurface );
};
const u32 indices[] = { 0,1,3, 0,3,2, 2,3,5, 2,5,4 };
+ scene_vert *dst_verts = vg_stack_allocate( &builder->vertex_stack, sizeof(scene_vert)*VG_ARRAY_LEN(verts), 1, "verts" );
+ u32 *dst_indices = vg_stack_allocate( &builder->indice_stack, sizeof(u32)*VG_ARRAY_LEN(indices), 1, "indices" );
+ scene_vert *ref = &world->scene_geometry.vertex_buffer[ hit->tri[0] ];
- if( scene->vertex_count + VG_ARRAY_LEN(verts) > scene->max_vertices )
- vg_fatal_error( "Scene vertex buffer overflow" );
-
- if( scene->indice_count + VG_ARRAY_LEN(indices) > scene->max_indices )
- vg_fatal_error( "Scene index buffer overflow" );
-
- scene_vert *dst_verts = &scene->arrvertices[ scene->vertex_count ];
- u32 *dst_indices = &scene->arrindices [ scene->indice_count ];
-
- scene_vert *ref = &world->scene_geo.arrvertices[ hit->tri[0] ];
-
- for( u32 i=0; i<VG_ARRAY_LEN(verts); i++ ){
+ for( u32 i=0; i<VG_ARRAY_LEN(verts); i++ )
+ {
scene_vert *pvert = &dst_verts[ i ],
*src = &verts[ i ];
-
m4x3_mulv( transform, src->co, pvert->co );
scene_vert_pack_norm( pvert, transform[1], 0.0f );
-
v2_copy( ref->uv, pvert->uv );
}
for( u32 i=0; i<VG_ARRAY_LEN(indices); i++ )
- dst_indices[i] = indices[i] + scene->vertex_count;
+ dst_indices[i] = indices[i] + builder->scene.vertex_count;
- scene->vertex_count += VG_ARRAY_LEN(verts);
- scene->indice_count += VG_ARRAY_LEN(indices);
+ builder->scene.vertex_count += VG_ARRAY_LEN(verts);
+ builder->scene.indice_count += VG_ARRAY_LEN(indices);
}
/*
* Sprinkle foliage models over the map on terrain material
*/
-static void world_apply_procedural_foliage( world_instance *world,
- scene_context *scene,
- struct world_surface *mat )
+static void world_apply_procedural_foliage( world_instance *world, scene_builder_context *builder, struct world_surface *mat )
{
if( (vg.quality_profile == k_quality_profile_low) ||
(vg.quality_profile == k_quality_profile_min) )
vg_info( "Applying foliage (%u)\n", mat->info.pstr_name );
v3f volume;
- v3_sub( world->scene_geo.bbx[1], world->scene_geo.bbx[0], volume );
+ v3_sub( world->scene_geometry.bbx[1], world->scene_geometry.bbx[0], volume );
volume[1] = 1.0f;
int count = 0;
- float area = volume[0]*volume[2];
+ f32 area = volume[0]*volume[2];
u32 particles = 0.08f * area;
vg_info( "Map area: %f. Max particles: %u\n", area, particles );
v3f pos;
v3_mul( volume, (v3f){ vg_randf64(), 1000.0f, vg_randf64() }, pos );
pos[1] = 1000.0f;
- v3_add( pos, world->scene_geo.bbx[0], pos );
+ v3_add( pos, world->scene_geometry.bbx[0], pos );
ray_hit hit;
hit.dist = INFINITY;
const f32 tile_scale = 16.0f;
v2i tiles = { volume[0]/tile_scale, volume[2]/tile_scale };
-
u32 per_tile = particles/(tiles[0]*tiles[1]);
- for( i32 x=0; x<tiles[0]; x ++ ){
- for( i32 z=0; z<tiles[1]; z ++ ){
- for( u32 i=0; i<per_tile; i ++ ){
+ for( i32 x=0; x<tiles[0]; x ++ )
+ {
+ for( i32 z=0; z<tiles[1]; z ++ )
+ {
+ for( u32 i=0; i<per_tile; i ++ )
+ {
v3f co = { (f32)x+vg_randf64(&rand), 0, (f32)z+vg_randf64(&rand) };
v3_muls( co, tile_scale, co );
co[1] = 1000.0f;
- v3_add( co, world->scene_geo.bbx[0], co );
+ v3_add( co, world->scene_geometry.bbx[0], co );
ray_hit hit;
hit.dist = INFINITY;
- if( ray_world( world, co, (v3f){0.0f,-1.0f,0.0f}, &hit,
- k_material_flag_ghosts )){
+ if( ray_world( world, co, (v3f){0.0f,-1.0f,0.0f}, &hit, k_material_flag_ghosts ))
+ {
struct world_surface *m1 = ray_hit_surface( world, &hit );
- if((hit.normal[1] > 0.8f) && (m1 == mat) &&
- (hit.pos[1] > 0.0f+10.0f)){
- world_gen_add_blob( &rand, world, scene, &hit );
+ if((hit.normal[1] > 0.8f) && (m1 == mat) && (hit.pos[1] > 0.0f+10.0f))
+ {
+ world_gen_add_blob( &rand, world, builder, &hit );
count ++;
}
}
#endif
-
-
u64 t1 = SDL_GetPerformanceCounter(),
utime_blobs = t1-t0,
ufreq = SDL_GetPerformanceFrequency();
f64 ftime_blobs = ((f64)utime_blobs / (f64)ufreq)*1000.0;
-
- vg_info( "%d foliage models added. %f%% (%fms)\n", count,
- 100.0*((f64)count/(f64)particles), ftime_blobs);
+ vg_info( "%d foliage models added. %f%% (%fms)\n", count, 100.0*((f64)count/(f64)particles), ftime_blobs);
}
-static
-void world_unpack_submesh_dynamic( world_instance *world,
- scene_context *scene, mdl_submesh *sm ){
- if( sm->flags & k_submesh_flag_consumed ) return;
+static void world_unpack_submesh_dynamic( world_instance *world, scene_builder_context *builder, mdl_submesh *sm )
+{
+ if( sm->flags & k_submesh_flag_consumed )
+ return;
m4x3f identity;
m4x3_identity( identity );
- scene_add_mdl_submesh( scene, &world->meta, sm, identity );
-
- scene_copy_slice( scene, sm );
+ scene_builder_add_model_submesh( builder, &world->meta, sm, identity );
+ scene_builder_get_submesh( builder, sm );
sm->flags |= k_submesh_flag_consumed;
}
/*
* Compile meshes into the world scenes
*/
- u32 geo_max_verts = 320000,
- geo_max_indices = 1200000;
- scene_init( &world->scene_geo, geo_max_verts, geo_max_indices );
- u8 *buffer = vg_stack_allocate( world->stack, scene_mem_required( &world->scene_geo ), 8, "Geometry buffer" );
- scene_supply_buffer( &world->scene_geo, buffer );
+
+ scene_builder_context geo_ctx;
+ scene_builder_init( &geo_ctx, 320000, 1200000, world->stack );
m4x3f midentity;
m4x3_identity( midentity );
for( u32 i=0; i<world->surface_count; i++ )
{
struct world_surface *surf = &world->surfaces[ i ];
-
if( surf->info.flags & k_material_flag_collision )
- world_add_all_if_material( midentity, &world->scene_geo, &world->meta, i );
+ world_add_all_if_material( midentity, &geo_ctx, &world->meta, i );
- scene_copy_slice( &world->scene_geo, &surf->sm_geo );
- scene_set_vertex_flags( &world->scene_geo,
- surf->sm_geo.vertex_start,
- surf->sm_geo.vertex_count,
- (u16)(surf->info.flags & 0xffff) );
+ scene_builder_get_submesh( &geo_ctx, &surf->sm_geo );
+ scene_builder_set_vertex_flags( &geo_ctx,
+ surf->sm_geo.vertex_start,
+ surf->sm_geo.vertex_count,
+ (u16)(surf->info.flags & 0xffff) );
}
- /* reduce down to minimum size */
- u32 new_vert_max = world->scene_geo.vertex_count,
- new_vert_size = vg_align8(new_vert_max*sizeof(scene_vert)),
- new_indice_len = world->scene_geo.indice_count*sizeof(u32);
- u32 *src_indices = world->scene_geo.arrindices,
- *dst_indices = (u32 *)(buffer + new_vert_size);
- memmove( dst_indices, src_indices, new_indice_len );
-
- world->scene_geo.max_indices = world->scene_geo.indice_count;
- world->scene_geo.max_vertices = world->scene_geo.vertex_count;
- buffer = vg_stack_resize_last( world->stack, scene_mem_required( &world->scene_geo ) );
-
- world->scene_geo.arrvertices = (scene_vert *)(buffer);
- world->scene_geo.arrindices = (u32 *)(buffer + new_vert_size);
-
- /* create a copy for the GPU (bvh scrambles the data) */
- scene_context *gpu_scene = &world->scene_geo_gpu;
- vg_async_task *task = scene_alloc_async( gpu_scene, &world->mesh_geo, geo_max_verts, geo_max_indices );
- memcpy( gpu_scene->arrvertices, world->scene_geo.arrvertices, world->scene_geo.vertex_count*sizeof(scene_vert) );
- memcpy( gpu_scene->arrindices, world->scene_geo.arrindices, world->scene_geo.indice_count*sizeof(u32) );
- gpu_scene->vertex_count = world->scene_geo.vertex_count;
- gpu_scene->indice_count = world->scene_geo.indice_count;
- box_copy( world->scene_geo.bbx, gpu_scene->bbx );
- vg_async_task_dispatch( task, async_scene_upload );
+ scene_builder_compact_memory( &geo_ctx, world->stack );
+ scene_builder_save_scene( &geo_ctx, &world->scene_geometry );
+ scene_builder_upload_async( &geo_ctx, &world->main_scene_mesh );
if( !_world.loader_preview_mode )
{
vg_info( "creating bvh\n" );
- world->geo_bh = scene_bh_create( world->stack, &world->scene_geo );
+ // NOTE: destructive to geometry ordering (material/surface indices become garbage)
+ scene_bh_create( &world->scene_geometry, &world->geometry_bh, world->stack );
}
/*
* Generate scene: non-collidable geometry
* ----------------------------------------------------------------
*/
- vg_info( "Generating non-collidable geometry\n" );
- vg_async_task *task2 = scene_alloc_async( &world->scene_no_collide, &world->mesh_no_collide, 250000, 500000 );
+
+ u32 temp_frame = _vg_start_temp_frame();
+ scene_builder_context trans_ctx;
+ scene_builder_init( &trans_ctx, 250000, 500000, _vg_temp_stack() );
for( u32 i=0; i<world->surface_count; i++ )
{
struct world_surface *surf = &world->surfaces[ i ];
-
if( !(surf->info.flags & k_material_flag_collision) )
- world_add_all_if_material( midentity, &world->scene_no_collide, &world->meta, i );
+ world_add_all_if_material( midentity, &trans_ctx, &world->meta, i );
if( !_world.loader_preview_mode )
- {
if( surf->info.flags & k_material_flag_grow_grass )
- world_apply_procedural_foliage( world, &world->scene_no_collide, surf );
- }
-
- scene_copy_slice( &world->scene_no_collide, &surf->sm_no_collide );
+ world_apply_procedural_foliage( world, &trans_ctx, surf );
+ scene_builder_get_submesh( &trans_ctx, &surf->sm_no_collide );
}
if( _world.loader_preview_mode )
- goto IL_UPLOAD;
+ {
+ scene_builder_upload_async( &trans_ctx, &world->transparent_scene_mesh );
+ _vg_end_temp_frame( temp_frame );
+ return;
+ }
/* unpack traffic models.. TODO: should we just put all these submeshes in a
* dynamic models list? and then the actual entitities point to the
for( u32 j=0; j<vehc->submesh_count; j++ )
{
mdl_submesh *sm = &world->meta.submeshes[ vehc->submesh_start+j ];
- world_unpack_submesh_dynamic( world, &world->scene_no_collide, sm );
+ world_unpack_submesh_dynamic( world, &trans_ctx, sm );
world->surfaces[ sm->material_id ].flags |= WORLD_SURFACE_HAS_TRAFFIC;
}
}
for( u32 i=0; i<af_arrcount( &world->ent_objective ); i++ )
{
ent_objective *objective = af_arritm( &world->ent_objective, i );
-
for( u32 j=0; j<objective->submesh_count; j ++ )
{
mdl_submesh *sm = &world->meta.submeshes[ objective->submesh_start+j ];
- world_unpack_submesh_dynamic( world, &world->scene_no_collide, sm );
+ world_unpack_submesh_dynamic( world, &trans_ctx, sm );
}
}
/* unpack region models */
- for( u32 i=0; i<af_arrcount( &world->ent_region ); i++ ){
+ for( u32 i=0; i<af_arrcount( &world->ent_region ); i++ )
+ {
ent_region *region = af_arritm( &world->ent_region, i );
-
for( u32 j=0; j<region->submesh_count; j ++ )
{
mdl_submesh *sm = &world->meta.submeshes[ region->submesh_start+j ];
- world_unpack_submesh_dynamic( world, &world->scene_no_collide, sm );
+ world_unpack_submesh_dynamic( world, &trans_ctx, sm );
}
}
for( u32 i=0; i<af_arrcount( &world->ent_gate ); i++ )
{
ent_gate *gate = af_arritm( &world->ent_gate, i );
- if( !(gate->flags & k_ent_gate_custom_mesh) ) continue;
-
+ if( !(gate->flags & k_ent_gate_custom_mesh) )
+ continue;
for( u32 j=0; j<gate->submesh_count; j ++ )
{
mdl_submesh *sm = &world->meta.submeshes[ gate->submesh_start+j ];
- world_unpack_submesh_dynamic( world, &world->scene_no_collide, sm );
+ world_unpack_submesh_dynamic( world, &trans_ctx, sm );
}
}
for( u32 i=0; i<af_arrcount( &world->ent_prop ); i++ )
{
ent_prop *prop = af_arritm( &world->ent_prop, i );
-
for( u32 j=0; j<prop->submesh_count; j ++ )
{
mdl_submesh *sm = &world->meta.submeshes[ prop->submesh_start+j ];
world->surfaces[ sm->material_id ].flags |= WORLD_SURFACE_HAS_PROPS;
- world_unpack_submesh_dynamic( world, &world->scene_no_collide, sm );
+ world_unpack_submesh_dynamic( world, &trans_ctx, sm );
}
}
-IL_UPLOAD:
- vg_async_task_dispatch( task2, async_scene_upload );
+ scene_builder_upload_async( &trans_ctx, &world->transparent_scene_mesh );
+ _vg_end_temp_frame( temp_frame );
+ return;
}
/* signed distance function for cone */
static f32 fsd_cone_infinite( v3f p, v2f c )
{
v2f q = { v2_length( (v2f){ p[0], p[2] } ), -p[1] };
- float s = vg_maxf( 0.0f, v2_dot( q, c ) );
+ f32 s = vg_maxf( 0.0f, v2_dot( q, c ) );
v2f v0;
v2_muls( c, s, v0 );
v2_sub( q, v0, v0 );
- float d = v2_length( v0 );
+ f32 d = v2_length( v0 );
return d * ((q[0]*c[1]-q[1]*c[0]<0.0f)?-1.0f:1.0f);
}
v3i count;
u8 data[];
};
-static void async_upload_light_indices_task( vg_async_task *task )
+static void async_upload_light_indices_task( struct light_indices_upload_info *in_args, vg_async_info *async )
{
- THREAD_0;
- struct light_indices_upload_info *info = (void *)task->data;
-
- glGenTextures( 1, &info->world->tex_light_cubes );
- glBindTexture( GL_TEXTURE_3D, info->world->tex_light_cubes );
- glTexImage3D( GL_TEXTURE_3D, 0, GL_RG32UI, info->count[0], info->count[1], info->count[2],
- 0, GL_RG_INTEGER, GL_UNSIGNED_INT, info->data );
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ glGenTextures( 1, &in_args->world->tex_light_cubes );
+ glBindTexture( GL_TEXTURE_3D, in_args->world->tex_light_cubes );
+ glTexImage3D( GL_TEXTURE_3D, 0, GL_RG32UI, in_args->count[0], in_args->count[1], in_args->count[2],
+ 0, GL_RG_INTEGER, GL_UNSIGNED_INT, in_args->data );
glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
}
{
/* light cubes */
v3f cubes_min, cubes_max;
- v3_muls( world->scene_geo.bbx[0], 1.0f/k_world_light_cube_size, cubes_min );
- v3_muls( world->scene_geo.bbx[1], 1.0f/k_world_light_cube_size, cubes_max );
+ v3_muls( world->scene_geometry.bbx[0], 1.0f/k_world_light_cube_size, cubes_min );
+ v3_muls( world->scene_geometry.bbx[1], 1.0f/k_world_light_cube_size, cubes_max );
v3_sub( cubes_min, (v3f){ 0.5f, 0.5f, 0.5f }, cubes_min );
v3_add( cubes_max, (v3f){ 0.5f, 0.5f, 0.5f }, cubes_max );
v3i icubes_min, icubes_max;
- for( int i=0; i<3; i++ ){
+ for( int i=0; i<3; i++ )
+ {
icubes_min[i] = cubes_min[i];
icubes_max[i] = cubes_max[i];
}
v3f cube_size;
-
v3i icubes_count;
v3i_sub( icubes_max, icubes_min, icubes_count );
- for( int i=0; i<3; i++ ){
+ for( int i=0; i<3; i++ )
+ {
int clamped_count = VG_MIN( 128, icubes_count[i]+1 );
- float clamped_max = icubes_min[i] + clamped_count,
- max = icubes_min[i] + icubes_count[i]+1;
+ f32 clamped_max = icubes_min[i] + clamped_count,
+ max = icubes_min[i] + icubes_count[i]+1;
icubes_count[i] = clamped_count;
cube_size[i] = (max / clamped_max) * k_world_light_cube_size;
v3_mul( cubes_min, cube_size, cubes_min );
v3_mul( cubes_max, cube_size, cubes_max );
- for( int i=0; i<3; i++ ){
- float range = cubes_max[i]-cubes_min[i];
- world->ub_lighting.g_cube_inv_range[i] = 1.0f / range;
- world->ub_lighting.g_cube_inv_range[i] *= (float)icubes_count[i];
-
+ for( int i=0; i<3; i++ )
+ {
+ f32 range = cubes_max[i]-cubes_min[i];
+ world_render.ub_lighting.g_cube_inv_range[i] = 1.0f / range;
+ world_render.ub_lighting.g_cube_inv_range[i] *= (f32)icubes_count[i];
vg_info( "cubes[%d]: %d\n", i, icubes_count[i] );
}
u32 data_size = total_cubes*sizeof(u32)*2;
- vg_async_task *task =
- vg_allocate_async_task( &vg.main_tasks, sizeof(struct light_indices_upload_info) + data_size, 1 );
- struct light_indices_upload_info *info = (void *)task->data;
- info->world = world;
- u32 *cubes_index = (void *)info->data;
+ struct light_indices_upload_info *out_args =
+ _vg_async_alloc( VG_THREAD_MAIN_ID, sizeof(struct light_indices_upload_info) + data_size );
+ out_args->world = world;
+ u32 *cubes_index = (void *)out_args->data;
for( int i=0; i<3; i++ )
- info->count[i] = icubes_count[i];
+ out_args->count[i] = icubes_count[i];
vg_info( "Computing light cubes (%d) [%f %f %f] -> [%f %f %f]\n",
total_cubes, cubes_min[0], -cubes_min[2], cubes_min[1],
cubes_max[0], -cubes_max[2], cubes_max[1] );
- v3_copy( cubes_min, world->ub_lighting.g_cube_min );
+ v3_copy( cubes_min, world_render.ub_lighting.g_cube_min );
- float bound_radius = v3_length( cube_size );
+ f32 bound_radius = v3_length( cube_size );
for( int iz = 0; iz<icubes_count[2]; iz ++ )
{
for( int ix = 0; ix<icubes_count[0]; ix++ )
{
boxf bbx;
- v3_div( (v3f){ ix, iy, iz }, world->ub_lighting.g_cube_inv_range,
- bbx[0] );
- v3_div( (v3f){ ix+1, iy+1, iz+1 },
- world->ub_lighting.g_cube_inv_range,
- bbx[1] );
+ v3_div( (v3f){ ix, iy, iz }, world_render.ub_lighting.g_cube_inv_range, bbx[0] );
+ v3_div( (v3f){ ix+1, iy+1, iz+1 }, world_render.ub_lighting.g_cube_inv_range, bbx[1] );
- v3_add( bbx[0], world->ub_lighting.g_cube_min, bbx[0] );
- v3_add( bbx[1], world->ub_lighting.g_cube_min, bbx[1] );
+ v3_add( bbx[0], world_render.ub_lighting.g_cube_min, bbx[0] );
+ v3_add( bbx[1], world_render.ub_lighting.g_cube_min, bbx[1] );
v3f center;
v3_add( bbx[0], bbx[1], center );
u32 indices[6] = { 0, 0, 0, 0, 0, 0 };
u32 count = 0;
- float influences[6] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
+ f32 influences[6] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
const int N = VG_ARRAY_LEN( influences );
for( u32 j=0; j<af_arrcount(&world->ent_light); j ++ )
v3f local;
m4x3_mulv( light->inverse_world, center, local );
- float r = fsd_cone_infinite( local, light->angle_sin_cos );
-
+ f32 r = fsd_cone_infinite( local, light->angle_sin_cos );
if( r > bound_radius )
continue;
}
}
}
- vg_async_task_dispatch( task, async_upload_light_indices_task );
+ _vg_async_send( out_args, (vg_async_fn)async_upload_light_indices_task );
}
/*
* Rendering pass needed to complete the world
*/
-void async_world_postprocess( void *userdata )
+void async_world_postprocess( void *_, vg_async_info *async )
{
/* create scene lighting buffer */
- world_instance *world = userdata;
-
- u32 size = VG_MAX(af_arrcount(&world->ent_light),1) * sizeof(float)*12;
+ world_instance *world = _world.loader_instance;
+ u32 size = VG_MAX(af_arrcount(&world->ent_light),1) * sizeof(f32)*12;
vg_info( "Upload %ubytes (lighting)\n", size );
glGenBuffers( 1, &world->tbo_light_entities );
if( !light->daytime )
{
u32 hash = (i * 29986577u) & 0xffu;
- float switch_on = hash;
- switch_on *= (1.0f/255.0f);
+ f32 switch_on = hash;
+ switch_on *= (1.0f/255.0f);
light_dst[i*3+0][3] = 0.44f + switch_on * 0.015f;
}
/* Upload lighting uniform buffer */
if( world->water.enabled )
- v4_copy( world->water.plane, world->ub_lighting.g_water_plane );
+ v4_copy( world->water.plane, world_render.ub_lighting.g_water_plane );
v4f info_vec;
- v3f *bounds = world->scene_geo.bbx;
+ v3f *bounds = world->scene_geometry.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, world->ub_lighting.g_depth_bounds );
+ v4_copy( info_vec, world_render.ub_lighting.g_depth_bounds );
/*
* Rendering the depth map
vg_camera ortho;
v3f extent;
- v3_sub( world->scene_geo.bbx[1], world->scene_geo.bbx[0], extent );
+ v3_sub( world->scene_geometry.bbx[1], world->scene_geometry.bbx[0], extent );
- 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);
+ f32 fl = world->scene_geometry.bbx[0][0],
+ fr = world->scene_geometry.bbx[1][0],
+ fb = world->scene_geometry.bbx[0][2],
+ ft = world->scene_geometry.bbx[1][2],
+ rl = 1.0f / (fr-fl),
+ tb = 1.0f / (ft-fb);
m4x4_zero( ortho.mtx.p );
ortho.mtx.p[0][0] = 2.0f * rl;
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glDisable(GL_CULL_FACE);
- vg_framebuffer_bind( world->heightmap, 1.0f );
+ vg_framebuffer_bind( world_render.heightmap, 1.0f );
shader_blitcolour_use();
shader_blitcolour_uColour( (v4f){-9999.0f,-9999.0f,-9999.0f,-9999.0f} );
render_fsquad();
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
/* upload full buffer */
- glBindBuffer( GL_UNIFORM_BUFFER, world->ubo_lighting );
- glBufferSubData( GL_UNIFORM_BUFFER, 0, sizeof(struct ub_world_lighting), &world->ub_lighting );
+ glBindBuffer( GL_UNIFORM_BUFFER, world_render.ubo_lighting );
+ glBufferSubData( GL_UNIFORM_BUFFER, 0, sizeof(struct ub_world_lighting), &world_render.ub_lighting );
/*
* Allocate cubemaps
/* Loads textures from the pack file */
void world_gen_load_surfaces( world_instance *world )
{
- THREAD_1;
- if( _world.loader_preview_mode )
- {
- world->texture_count = 0;
- }
- else
- {
- vg_info( "Loading textures\n" );
- world->texture_count = world->meta.texture_count+1;
- world->textures = vg_stack_allocate( world->stack, sizeof(GLuint)*world->texture_count, 8, "Textures" );
- world->textures[0] = vg.tex_missing;
-
- for( u32 i=0; i<world->meta.texture_count; i++ )
- {
- mdl_texture *tex = &world->meta.textures[ i ];
-
- if( !tex->file.pack_size )
- {
- vg_fatal_error( "World models must have packed textures!" );
- }
-
- vg_stack_clear( &vg.scratch );
- void *src_data = vg_stack_allocate( &vg.scratch, tex->file.pack_size, 8, "Pack Data" );
- mdl_fread_pack_file( &world->meta, &tex->file, src_data );
-
- vg_tex2d_load_qoi_async( src_data, tex->file.pack_size,
- VG_TEX2D_NEAREST|VG_TEX2D_REPEAT,
- &world->textures[i+1] );
- }
- }
-
- vg_info( "Loading materials\n" );
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
world->surface_count = world->meta.material_count+1;
world->surfaces = vg_stack_allocate( world->stack, sizeof(struct world_surface)*world->surface_count, 8, "Surfaces" );
surf->flags = 0;
if( surf->info.shader == k_shader_water )
- {
- struct shader_props_water *props = surf->info.props.compiled;
- world->ub_lighting.g_water_fog = props->fog_scale;
- }
+ world_render.ub_lighting.g_water_fog = world->meta.shader_props[i].water.fog_scale;
if( surf->info.shader == k_shader_standard_cutout || surf->info.shader == k_shader_foliage )
- {
- struct shader_props_standard *props = surf->info.props.compiled;
- surf->alpha_tex = props->tex_diffuse;
- }
+ surf->alpha_tex = world->meta.shader_props[i].standard.tex_diffuse;
else
surf->alpha_tex = 0;
}
-/*
- * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
- *
- * World generation/population. Different to regular loading, since it needs to
- * create geometry, apply procedural stuff and save that image to files etc.
- */
-
-#pragma once
-#include "world.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/world_gen.c"
+#else
void world_init_blank( world_instance *world );
void world_gen_load_surfaces( world_instance *world );
void world_gen_generate_meshes( world_instance *world );
void world_gen_compute_light_indices( world_instance *world );
-void async_world_postprocess( void *userdata );
+void async_world_postprocess( void *_, vg_async_info *async );
+
+#endif
-/*
- * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#ifndef WORLD_INFO_H
-#define WORLD_INFO_H
-
-/* Purely an information header, shares common strings across client and
- * server programs. */
+#if defined( SR_IMPLEMENTATION )
+#else
struct track_info
{
-#include "world_load.h"
-#include "world_routes.h"
-#include "world_gate.h"
-#include "ent_skateshop.h"
-#include "addon.h"
-#include "save.h"
-#include "vg/vg_msg.h"
-#include "network.h"
-#include "player_remote.h"
-#include "vg/vg_loader.h"
-#include "vg/vg_io.h"
-#include <string.h>
-#include "ent_atom.h"
-
/*
* load the .mdl file located in path as a world instance
*/
static void world_instance_load_mdl( world_instance *world, const char *path, vg_stack_allocator *stack )
{
- vg_loader_set_user_information( "Loading world data" );
+ _vg_loader_set_user_information( "Loading world data" );
world_init_blank( world );
world->stack = stack;
vg_info( "Loading world model: %s\n", path );
- mdl_context *meta = &world->meta;
- array_file_context *af = &meta->af;
-
- mdl_open( meta, path, world->stack );
- mdl_load_metadata_block( meta, world->stack );
- mdl_load_mesh_block( meta, world->stack );
+ vg_model_stream_context ctx;
+ vg_model_stream_open( &ctx, &world->meta, path );
+ vg_model_stream_metadata( &ctx, stack );
+ vg_model_stream_meshes_cpu( &ctx, stack ); // NOTE: Maybe this can go in temp storage now.
+
+ if( !_world.loader_preview_mode )
+ vg_model_stream_textures_gpu( &ctx );
bool load_all = !_world.loader_preview_mode;
-
if( load_all )
{
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_gate, ent_gate, stack );
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_camera, ent_camera, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_gate, ent_gate, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_camera, ent_camera, stack );
#if (MDL_VERSION_MIN <= 107)
- if( meta->version <= 107 )
+ if( world->meta.version <= 107 )
{
+ u32 temp_frame = _vg_start_temp_frame();
array_file_ptr legacy_cameras;
- af_load_array( af, &legacy_cameras, "ent_camera", &vg.scratch, sizeof(struct ent_camera_v107) );
-
+ af_load_array( &ctx.af, &legacy_cameras, "ent_camera", _vg_temp_stack(), sizeof(struct ent_camera_v107) );
for( u32 i=0; i<af_arrcount(&legacy_cameras); i ++ )
- {
fix_ent_camera_v107( af_arritm( &legacy_cameras, i ), af_arritm( &world->ent_camera, i ) );
- }
+ _vg_end_temp_frame( temp_frame );
}
#endif
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_spawn, ent_spawn, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_spawn, ent_spawn, stack );
if( af_arrcount( &world->ent_spawn ) == 0 )
{
}
}
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_light, ent_light, stack );
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_route_node,ent_route_node, stack );
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_path_index,ent_path_index, stack );
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_checkpoint,ent_checkpoint, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_light, ent_light, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_route_node,ent_route_node, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_path_index,ent_path_index, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_checkpoint,ent_checkpoint, stack );
}
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_route, ent_route, stack );
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_region, ent_region, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_route, ent_route, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_region, ent_region, stack );
if( load_all )
{
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_water, ent_water, stack );
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_audio_clip,ent_audio_clip, stack );
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_audio, ent_audio, stack );
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_volume, ent_volume, stack );
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_traffic, ent_traffic, stack );
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_marker, ent_marker, stack );
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_skateshop, ent_skateshop, stack );
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_swspreview,ent_swspreview, stack );
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_ccmd, ent_ccmd, stack );
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_objective, ent_objective, stack );
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_challenge, ent_challenge, stack );
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_cubemap, ent_cubemap, stack );
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_prop, ent_prop, stack );
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_glider, ent_glider, stack );
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_list, ent_list, stack );
- AF_LOAD_ARRAY_STRUCT( af, &world->file_entity_ref, file_entity_ref, stack );
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_script, ent_script, stack );
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_event, ent_event, stack );
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_npc, ent_npc, stack );
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_atom, ent_atom, stack );
- AF_LOAD_ARRAY_STRUCT( af, &world->ent_cutscene, ent_cutscene, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_water, ent_water, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_audio_clip,ent_audio_clip, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_audio, ent_audio, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_volume, ent_volume, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_traffic, ent_traffic, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_marker, ent_marker, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_skateshop, ent_skateshop, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_swspreview,ent_swspreview, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_ccmd, ent_ccmd, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_objective, ent_objective, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_challenge, ent_challenge, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_cubemap, ent_cubemap, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_prop, ent_prop, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_glider, ent_glider, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_list, ent_list, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->file_entity_ref, file_entity_ref, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_script, ent_script, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_event, ent_event, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_npc, ent_npc, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_atom, ent_atom, stack );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_cutscene, ent_cutscene, stack );
}
- array_file_ptr infos;
- AF_LOAD_ARRAY_STRUCT( af, &infos, ent_worldinfo, &vg.scratch );
-
- world->skybox = k_skybox_default;
- if( af_arrcount(&infos) )
+ u32 temp_frame = _vg_start_temp_frame();
{
- world->info = *((ent_worldinfo *)af_arritm(&infos,0));
+ array_file_ptr infos;
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &infos, ent_worldinfo, _vg_temp_stack() );
- if( world->meta.version >= 104 )
+ world->skybox = k_skybox_default;
+ if( af_arrcount(&infos) )
{
- if( AF_STR_EQ( &world->meta.af, world->info.pstr_skybox, "space" ))
- {
- world->skybox = k_skybox_space;
- }
- }
+ world->info = *((ent_worldinfo *)af_arritm(&infos,0));
+ if( world->meta.version >= 104 )
+ if( AF_STR_EQ( world->meta.packed_strings, world->info.pstr_skybox, "space" ))
+ world->skybox = k_skybox_space;
- if( world->meta.version < 108 )
- world->info.wind_scale = 0.5f;
- }
- else
- {
- world->info.pstr_author = 0;
- world->info.pstr_desc = 0;
- world->info.pstr_name = 0;
- world->info.timezone = 0.0f;
- world->info.flags = 0;
+ if( world->meta.version < 108 )
+ world->info.wind_scale = 0.5f;
+ }
+ else
+ {
+ world->info.pstr_author = 0;
+ world->info.pstr_desc = 0;
+ world->info.pstr_name = 0;
+ world->info.timezone = 0.0f;
+ world->info.flags = 0;
+ }
}
+ _vg_end_temp_frame( temp_frame );
- vg_loader_set_user_information( "Compiling world details" );
-
+ _vg_loader_set_user_information( "Compiling world details" );
time_t seconds = time(NULL) % ((u32)vg_maxf(1.0f,k_day_length)*60);
world->time = ((f64)(seconds)/(k_day_length*60.0));
world->time += (world->info.timezone/24.0);
if( load_all )
{
world_gen_routes_ent_init( world );
- world_gen_entities_init( world );
+ world_gen_entities_init( world, &ctx );
}
+ vg_model_stream_close( &ctx );
+
u64 t6 = SDL_GetPerformanceCounter();
/* main bulk */
world_gen_compute_light_indices( world );
u64 t3 = SDL_GetPerformanceCounter();
- mdl_close( meta );
u64 utime_mesh = t1-t0,
utime_route = t2-t1,
world->routes_ui = vg_stack_allocate( stack, sizeof(struct route_ui)*af_arrcount(&world->ent_route), 8, "Route UI buffer" );
ent_script_alloc( world, stack );
- vg_loader_set_user_information( "Postprocessing world" );
- vg_async_call( &vg.main_tasks, async_world_postprocess, world );
+ _vg_loader_set_user_information( "Postprocessing world" );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)async_world_postprocess );
}
}
static void async_world_loader_done( void *userdata )
{
- THREAD_0;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
_world.loader_state = k_world_loader_init;
_world.loader_instance->complete = 1;
}
-
-struct world_load_info
-{
- bool OK;
- char path[4096];
-};
-void skaterift_world_load_t1( vg_async_task *task )
+void skaterift_world_load_t1( struct world_load_info *in_args, vg_async_info *async )
{
- THREAD_1;
- struct world_load_info *info = (void *)task->data;
-
- if( !info->OK )
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+ if( !in_args->OK )
return;
- vg_loader_set_user_information( "Scanning world directory" );
+ _vg_loader_set_user_information( "Scanning world directory" );
addon_reg *reg = addon_details( _world.load_addon );
_world.loader_instance->addon_id = _world.load_addon;
char path_buf[ 4096 ];
vg_str path;
vg_strnull( &path, path_buf, sizeof( path_buf ) );
- vg_strcat( &path, info->path );
+ vg_strcat( &path, in_args->path );
vg_str folder = path;
if( !vg_strgood( &folder ) )
}
world_instance_load_mdl( _world.loader_instance, mdl_path, _world.loader_stack );
- vg_async_call( &vg.main_tasks, async_world_loader_done, NULL );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)async_world_loader_done );
}
struct world_savedata_info
{
- savedata_file save;
+ //savedata_file save;
world_instance *instance;
};
-void async_worldsave_go( vg_async_task *task )
+void async_worldsave_go( struct world_savedata_info *in_args, vg_async_info *async )
{
- THREAD_0;
- struct world_savedata_info *info = (void *)task->data;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ VG_ASSERT( 0 );
- vg_msg sav;
- vg_msg_init( &sav, info->save.buf, info->save.msg.max );
+ // FIXME FIXME FIXME
+
+#if 0
+ struct world_savedata_info *info = (void *)task->data;
/* start entities in the world */
- world_entity_start( info->instance, &sav );
+ world_entity_start( info->instance, &info->save.kvs );
/* start player in the world */
if( _world.travelled_through_nonlocal_gate )
else
{
bool restored_player_position = 0;
-
- vg_msg_init( &sav, info->save.buf, info->save.msg.max );
- vg_msg player_frame = sav;
- if( vg_msg_seekframe( &player_frame, "player" ) )
+
+ u32 player_block = vg_kv_find( &info->save.kvs, 0, "player" );
+ if( player_block )
{
- if( vg_msg_getkvvecf( &player_frame, "co", k_vg_msg_v3f, localplayer.rb.co, NULL ) )
+ if( vg_kv_read_vf32( &info->save.kvs, player_block, "co", NULL, localplayer.rb.co, 3 ) )
restored_player_position = 1;
}
network_send_item( k_netmsg_playeritem_world0 );
_world.loader_state = k_world_loader_done;
_world.load_addon = 0;
- _vg_tower_set_flag( skaterift.sig_world, 1 );
menu_on_world_change( _world.main.addon_id );
relink_all_remote_player_worlds();
vg_audio_lock();
vg_audio_oneshot( &audio_ui[2], 1.0f, 0.0f, 0, 0 );
vg_audio_unlock();
+#endif
}
-void load_world_savedata_t1( void *userdata )
+void load_world_savedata_t1( void *_, vg_async_info *async )
{
- THREAD_1;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+ VG_ASSERT( 0 );
+ // FIXME FIXME
+#if 0
vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, sizeof(struct world_savedata_info), 1 );
struct world_savedata_info *info = (void *)task->data;
addon_make_savedata_path( _world.load_addon, info->save.path );
savedata_file_read( &info->save );
vg_async_task_dispatch( task, async_worldsave_go );
+#endif
}
void world_switcher_update(void)
if( _world.loader_state == k_world_loader_saving_current )
{
- skaterift_write_all_savedata(1);
+ VG_ASSERT(0);
+ //FIXME FIXME FIMXE
+ //skaterift_write_all_savedata(1);
_world.loader_state = k_world_loader_unloading_current;
- vg_loader_set_user_information( "Unloading current world" );
+ _vg_loader_set_user_information( "Unloading current world" );
}
/* pre-load step aka waiting for audio to end. */
world_instance_free_graphics_data( &_world.main );
_world.main.complete = 0;
_world.loader_state = k_world_loader_ready;
- vg_loader_set_user_information( "Waiting for loading thread" );
+ _vg_loader_set_user_information( "Waiting for loading thread" );
}
if( _world.loader_state == k_world_loader_ready )
{
_world.loader_state = k_world_loader_loading;
vg_stack_clear( _world.loader_stack );
- vg_async_task *task = vg_allocate_async_task( &vg.loader_tasks, sizeof(struct world_load_info), 1 );
- struct world_load_info *info = (void *)task->data;
+
+ struct world_load_info *out_args = _vg_async_alloc( VG_THREAD_ASYNC_ID, sizeof(struct world_load_info) );
vg_str folder_str;
- vg_strnull( &folder_str, info->path, sizeof(info->path) );
- info->OK = addon_get_content_folder( _world.load_addon, &folder_str );
- vg_async_task_dispatch( task, skaterift_world_load_t1 );
+ vg_strnull( &folder_str, out_args->path, sizeof(out_args->path) );
+ out_args->OK = addon_get_content_folder( _world.load_addon, &folder_str );
+ _vg_async_send( out_args, (vg_async_fn)skaterift_world_load_t1 );
}
if( _world.loader_state == k_world_loader_init )
else
{
_world.loader_state = k_world_loader_load_savedata;
- vg_async_call( &vg.loader_tasks, load_world_savedata_t1, NULL );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)load_world_savedata_t1 );
}
}
}
void skaterift_load_world_start( addon_id addon_id, bool preview )
{
- if( !_vg_tower_clearence( skaterift.full_ready_mask ) )
- {
- vg_error( "Cannot start changeworld while client is not ready?\n" );
- return;
- }
-
if( _world.loader_state != k_world_loader_done )
{
vg_error( "Cannot start changeworld while loader is not done?\n" );
if( addon_id != world->addon_id )
_world.previous_world_addon = _world.main.addon_id;
- _vg_tower_set_flag( skaterift.sig_world, 0 );
_replay2_clear_local_buffer();
_world.loader_state = k_world_loader_saving_current;
_world.event = k_world_event_none;
player__clear_world_dependent_variables();
relink_all_remote_player_worlds();
_ent_npc_reset();
- vg_loader_set_user_information( "Saving current world" );
+ _vg_loader_set_user_information( "Saving current world" );
}
else
_world.loader_state = k_world_loader_ready;
char uid[ADDON_UID_MAX];
addon_make_uid( addon_id, uid );
vg_info( "loading world: %s %s\n", uid, preview? "(preview mode)": "" );
- vg_stack_clear( &vg.scratch ); /* ?? */
if( preview )
{
}
_world.loader_instance = world;
- _world.loader_stack = preview? _world.preview_stack: _world.stack;
+ _world.loader_stack = preview? &_world.preview_stack:& _world.stack;
_world.loader_preview_mode = preview;
_world_loader_set_addon( addon_id );
}
if( addon_id )
{
bool allowed = 1;
- if( g_client.demo_mode )
+ if( _is_running_demo() )
{
addon_reg *reg = addon_details( addon_id );
if( reg )
void world_instance_free_graphics_data( world_instance *world )
{
/* free meshes */
- mesh_free( &world->mesh_route_lines );
- mesh_free( &world->mesh_geo );
- mesh_free( &world->mesh_no_collide );
+ scene_mesh_free( &world->main_scene_mesh );
+ scene_mesh_free( &world->line_scene_mesh );
+ scene_mesh_free( &world->transparent_scene_mesh );
glDeleteBuffers( 1, &world->tbo_light_entities );
glDeleteTextures( 1, &world->tex_light_entities );
glDeleteTextures( 1, &world->tex_light_cubes );
/* delete textures and meshes */
- if( world->texture_count )
- glDeleteTextures( world->texture_count-1, world->textures+1 );
+ vg_model_unload_gpu( &world->meta );
for( u32 i=0; i<af_arrcount(&world->ent_cubemap); i++ )
{
glDeleteRenderbuffers( 1, &cm->renderbuffer_id );
}
- if( world->nonlocal_gate_count )
- glDeleteTextures( world->nonlocal_gate_count, world->nonlocal_gates_cubemaps );
+ for( u32 i=0; i<world->nonlocal_gate_count; i ++ )
+ vg_tex_delete( &world->nonlocal_gates_cubemaps[i] );
}
/*
*/
void world_init_blank( world_instance *world )
{
- memset( &world->meta, 0, sizeof(mdl_context) );
-
- world->textures = NULL;
- world->texture_count = 0;
+ vg_zero_mem( &world->meta, sizeof(vg_model) );
world->surfaces = NULL;
world->surface_count = 0;
-
- world->geo_bh = NULL;
- world->entity_bh = NULL;
world->entity_list = NULL;
world->rendering_gate = NULL;
/* default lighting conditions
* -------------------------------------------------------------*/
- struct ub_world_lighting *state = &world->ub_lighting;
+ struct ub_world_lighting *state = &world_render.ub_lighting;
state->g_light_preview = 0;
state->g_shadow_samples = 8;
-#pragma once
-#include <time.h>
-
-#include "world.h"
-#include "addon.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/world_load.c"
+#else
int skaterift_load_world_command( int argc, const char *argv[] );
void skaterift_load_world_start( addon_id addon, bool preview_mode );
void world_switcher_update(void);
void world_instance_free_graphics_data( world_instance *world );
vg_async_task *world_load_go(void);
-void skaterift_world_load_t1( vg_async_task *task );
+
+struct world_load_info
+{
+ bool OK;
+ char path[4096];
+};
+void skaterift_world_load_t1( struct world_load_info *in_args, vg_async_info *async );
+
+#endif
-#include "skaterift.h"
-#include "world_map.h"
-#include "world.h"
-#include "input.h"
-#include "gui.h"
-#include "menu.h"
-#include "scene.h"
-#include "shaders/model_superworld.h"
-
struct world_map world_map;
static void world_map_get_dir( v3f dir )
void world_map_initialize_view(void)
{
world_instance *world = &_world.main;
- v3f *bbx = world->scene_geo.bbx;
+ v3f *bbx = world->scene_geometry.bbx;
respawn_world_to_plane_pos( localplayer.rb.co, world_map.plane_pos );
world_map.boom_dist = 400.0f;
}
vg_camera_update_transform( &world_map.final_cam );
vg_camera_update_view( &world_map.final_cam );
- vg_camera_update_projection( &world_map.final_cam, vg.window_x, vg.window_y );
+ vg_camera_update_projection( &world_map.final_cam, _vg_window.w, _vg_window.h );
vg_camera_finalize( &world_map.final_cam );
vg_camera_finalize( &world_map.final_cam );
}
glDrawBuffers( 1, (GLenum[]){ GL_COLOR_ATTACHMENT0 } );
v3f bg;
- v3_muls( world->ub_lighting.g_daysky_colour,
- world->ub_lighting.g_day_phase - world->ub_lighting.g_sunset_phase*0.1f, bg );
+ v3_muls( world_render.ub_lighting.g_daysky_colour,
+ world_render.ub_lighting.g_day_phase - world_render.ub_lighting.g_sunset_phase*0.1f, bg );
- v3_muladds( bg, world->ub_lighting.g_sunset_colour, (1.0f-0.5f)*world->ub_lighting.g_sunset_phase, bg );
- v3_muladds( bg, world->ub_lighting.g_nightsky_colour, (1.0f-world->ub_lighting.g_day_phase), bg );
+ v3_muladds( bg, world_render.ub_lighting.g_sunset_colour, (1.0f-0.5f)*world_render.ub_lighting.g_sunset_phase, bg );
+ v3_muladds( bg, world_render.ub_lighting.g_nightsky_colour, (1.0f-world_render.ub_lighting.g_day_phase), bg );
glClearColor( bg[0], bg[1], bg[2], 0.0f );
glClear( GL_COLOR_BUFFER_BIT );
v3_normalize(dir);
v3f centroid;
- v3_add( world->scene_geo.bbx[0], world->scene_geo.bbx[1], centroid );
+ v3_add( world->scene_geometry.bbx[0], world->scene_geometry.bbx[1], centroid );
v3_muls( centroid, 0.5f, centroid );
v3_muladds( centroid, dir, 900.0f, cam.pos );
v3_angles( dir, cam.angles );
v3f v0, v1;
v3_sub( centroid, cam.pos, v0 );
- v3_sub( world->scene_geo.bbx[1], cam.pos, v1 );
+ v3_sub( world->scene_geometry.bbx[1], cam.pos, v1 );
v3_normalize( v0 );
v3_normalize( v1 );
shader_model_superworld_uColour( (v4f){0.4f,0.8f,0.0f,0.0f} );
shader_model_superworld_uTime( vg.time*0.25f );
- mesh_bind( &world_map.superworld_mesh );
- mdl_context *model = &world_map.superworld_meta;
+ vg_model *model = &world_map.superworld_meta;
+ vg_model_bind_mesh( model );
for( u32 i=0; i<model->mesh_count; i ++ )
{
mdl_mesh *mesh = &model->meshes[i];
-
q_axis_angle( mesh->transform.q, (v3f){0,1,0}, vg.time_real*0.4f );
m4x3f mmdl;
for( u32 j=0; j<mesh->submesh_count; j ++ )
{
mdl_submesh *submesh = &model->submeshes[ mesh->submesh_start + j ];
- mdl_draw_submesh( submesh );
+ vg_model_draw_submesh( submesh );
}
}
if( selected_type == k_ent_challenge )
{
ent_challenge *challenge = af_arritm( &world->ent_challenge, selected_index );
- name = af_str( &world->meta.af, challenge->pstr_alias );
+ name = af_str( world->meta.packed_strings, challenge->pstr_alias );
}
else if( selected_type == k_ent_route )
{
ent_route *route = af_arritm( &world->ent_route, selected_index );
- name = af_str( &world->meta.af, route->pstr_name );
+ name = af_str( world->meta.packed_strings, route->pstr_name );
ent_route_leaderboard_ui( ctx, spawn_box, selected_index );
}
ui_text( ctx, name_box, name, 1, k_ui_align_middle_center, 0 );
}
else
{
- title_text = af_str( &world->meta.af, world->info.pstr_name );
+ title_text = af_str( world->meta.packed_strings, world->info.pstr_name );
subtitle_text = "Current Location";
ctx->font = &vgf_default_title;
upper_title[2] = ui_text_line_width(ctx,title_text) + 24;
m2x2_mulv( rm, steer, steer );
v2_muladds( world_map.plane_pos, steer, vg.time_frame_delta * 200.0f, world_map.plane_pos );
- v3f *bbx = world->scene_geo.bbx;
+ v3f *bbx = world->scene_geometry.bbx;
v2_minv( (v2f){ bbx[1][0], bbx[1][2] }, world_map.plane_pos, world_map.plane_pos );
v2_maxv( (v2f){ bbx[0][0], bbx[0][2] }, world_map.plane_pos, world_map.plane_pos );
if( vg_input.display_input_method == k_input_method_kbm )
{
- world_map.view_centroid[0] = ((f32)ctx->mouse[0] / (f32)vg.window_x)*2.0f - 1.0f;
- world_map.view_centroid[1] = -(((f32)ctx->mouse[1] / (f32)vg.window_y)*2.0f - 1.0f);
+ world_map.view_centroid[0] = ((f32)ctx->mouse[0] / (f32)_vg_window.w)*2.0f - 1.0f;
+ world_map.view_centroid[1] = -(((f32)ctx->mouse[1] / (f32)_vg_window.h)*2.0f - 1.0f);
}
else
{
continue;
ent_list *list = af_arritm( &world->ent_list, mdl_entity_id_id( list_id ) );
- const char *title = af_str( &world->meta.af, region->pstr_title );
+ const char *title = af_str( world->meta.packed_strings, region->pstr_title );
ctx->font = &vgf_default_large;
ui_rect title_box;
vg_strnull( &str, buf, sizeof(buf) );
vg_strcat( &str, "(Race) " );
- vg_strcat( &str, af_str( &world->meta.af, route->pstr_name ));
+ vg_strcat( &str, af_str( world->meta.packed_strings, route->pstr_name ));
if( route->flags & k_ent_route_flag_achieve_silver )
vg_strcat( &str, " \xb3");
else
{
vg_strnull( &str, buf, sizeof(buf) );
- vg_strcat( &str, af_str( &world->meta.af,challenge->pstr_alias));
+ vg_strcat( &str, af_str( world->meta.packed_strings,challenge->pstr_alias));
u32 flags = 0x00;
if( challenge->status )
#if 0
ctx->font = &vgf_default_large;
- ui_rect title = { vg.window_x/2- 512/2, height+8, 512, 64 };
+ ui_rect title = { _vg_window.w/2- 512/2, height+8, 512, 64 };
ui_px x = 8,
y = height+8;
vg_strnull( &str, buf, sizeof(buf) );
world_instance *world = &_world.main;
- const char *world_name = af_str( &world->meta.af, world->info.pstr_name );
+ const char *world_name = af_str( world->meta.packed_strings, world->info.pstr_name );
vg_strnull( &str, buf, sizeof(buf) );
vg_strcat( &str, world_name );
vs[3].co[1] = stat_panel[1];
ui_rect back_button = {0,0,300,32};
- ui_rect_center( (ui_rect){0,0,vg.window_x,vg.window_y}, back_button );
+ ui_rect_center( (ui_rect){0,0,_vg_window.w,_vg_window.h}, back_button );
if( ui_button_text( ctx, back_button, "up", 1 ) == k_ui_button_click )
{
world_map.activity = k_map_activity_
planet_box[0] += 4;
planet_box[2] = WORKSHOP_PREVIEW_WIDTH;
planet_box[3] = WORKSHOP_PREVIEW_HEIGHT;
- ui_image( ctx, planet_box, &g_render.fb_workshop_preview->attachments[0].id, 0 );
+ ui_image( ctx, planet_box, &g_render.fb_workshop_preview->attachments[0].tex, 0 );
ui_rect planet_box_title;
ui_split( planet_box, k_ui_axis_h, 28, 0, planet_box_title, planet_box );
if( menu.clicked_world_id != _world.main.addon_id )
{
- if( g_client.demo_mode )
+ if( _is_running_demo() )
{
addon_reg *reg = addon_details( menu.clicked_world_id );
if( reg )
}
}
-void world_map_init(void)
+static void _world_map_load_content_async( void *_, vg_async_info *async )
+{
+ vg_model_stream_context ctx;
+ VG_ASSERT( vg_model_stream_open( &ctx, &world_map.superworld_meta, "models/rs_superworlds.mdl" ) );
+ vg_model_stream_metadata( &ctx, VG_STACK_USE_HEAP );
+ vg_model_stream_meshes_gpu( &ctx, NULL );
+ vg_model_stream_textures_gpu( &ctx );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world_map.ent_camera, ent_camera, NULL );
+ AF_LOAD_ARRAY_STRUCT( &ctx.af, &world_map.ent_marker, ent_marker, NULL );
+ vg_model_stream_close( &ctx );
+}
+
+VG_API void _world_map_init(void)
{
- mdl_context *model = &world_map.superworld_meta;
- mdl_open( model, "models/rs_superworlds.mdl", &vg.rtmem );
- mdl_load_metadata_block( model, &vg.rtmem );
- mdl_async_load_glmesh( model, &world_map.superworld_mesh, NULL );
- AF_LOAD_ARRAY_STRUCT( &model->af, &world_map.ent_camera, ent_camera, &vg.rtmem );
- AF_LOAD_ARRAY_STRUCT( &model->af, &world_map.ent_marker, ent_marker, &vg.rtmem );
- mdl_close( model );
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_world_map_load_content_async );
world_map.superworld_cam.nearz = 0.1f;
world_map.superworld_cam.farz = 250.0f;
-#pragma once
-#include "vg/vg_platform.h"
-#include "vg/vg_camera.h"
-#include "world_entity.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/world_map.c"
+#else
+
enum superworld
{
k_superworld_venus_moon = 0,
}
activity;
- mdl_context superworld_meta;
- glmesh superworld_mesh;
+ vg_model superworld_meta;
array_file_ptr ent_camera,
ent_marker,
ent_challenge;
extern world_map;
void world_map_gui( ui_context *ctx, ui_rect main_area, i32 mh, i32 mv, bool *allow_back_to_exit );
void render_world_map(void);
-void world_map_init(void);
+VG_API void _world_map_init(void);
void world_map_initialize_view(void);
bool world_map_get_transition_cam( vg_camera *cam );
[k_superworld_campaign] = "Earth",
[k_superworld_steam_workshop] = "Steam Workshop Planet",
};
+
+#endif
-#ifndef WORLD_PHYSICS_C
-#define WORLD_PHYSICS_C
-
-#include "world.h"
-#include "world_physics.h"
-
void ray_world_get_tri( world_instance *world, ray_hit *hit, v3f tri[3] )
{
for( int i=0; i<3; i++ )
- v3_copy( world->scene_geo.arrvertices[ hit->tri[i] ].co, tri[i] );
+ v3_copy( world->scene_geometry.vertex_buffer[ hit->tri[i] ].co, tri[i] );
}
-int ray_world( world_instance *world,
- v3f pos, v3f dir, ray_hit *hit, u16 ignore )
+int ray_world( world_instance *world, v3f pos, v3f dir, ray_hit *hit, u16 ignore )
{
- return scene_raycast( &world->scene_geo, world->geo_bh, pos, dir, hit,
- ignore );
+ return scene_raycast( &world->scene_geometry, &world->geometry_bh, pos, dir, hit, ignore );
}
/*
bh_iter it;
bh_iter_init_box( 0, &it, region );
i32 idx;
- while( bh_next( world->geo_bh, &it, &idx ) ){
- u32 *ptri = &world->scene_geo.arrindices[ idx*3 ];
- if( world->scene_geo.arrvertices[ptri[0]].flags & ignore ) continue;
+ while( bh_next( &world->geometry_bh, &it, &idx ) )
+ {
+ u32 *ptri = &world->scene_geometry.indice_buffer[ idx*3 ];
+ if( world->scene_geometry.vertex_buffer[ptri[0]].flags & ignore ) continue;
v3f tri[3];
boxf box;
box_init_inf( box );
- for( int j=0; j<3; j++ ){
- v3_copy( world->scene_geo.arrvertices[ptri[j]].co, tri[j] );
+ for( int j=0; j<3; j++ )
+ {
+ v3_copy( world->scene_geometry.vertex_buffer[ptri[j]].co, tri[j] );
box_addpt( box, tri[j] );
}
{
return world_tri_index_surface( world, hit->tri[0] );
}
-
-#endif /* WORLD_PHYSICS_C */
-#pragma once
-#include "world.h"
-#include "vg/vg_rigidbody.h"
-#include "vg/vg_rigidbody_collision.h"
-#include "vg/vg_bvh.h"
-
-void ray_world_get_tri( world_instance *world,
- ray_hit *hit, v3f tri[3] );
-
-int ray_world( world_instance *world,
- v3f pos, v3f dir, ray_hit *hit, u16 ignore );
-
-int spherecast_world( world_instance *world,
- v3f pa, v3f pb, float r, float *t, v3f n,
- u16 ignore );
-
-struct world_surface *world_tri_index_surface( world_instance *world,
- u32 index );
-
-struct world_surface *world_contact_surface( world_instance *world,
- rb_ct *ct );
-
-struct world_surface *ray_hit_surface( world_instance *world,
- ray_hit *hit );
+#if defined( SR_IMPLEMENTATION )
+# include "src/world_physics.c"
+#else
+
+void ray_world_get_tri( world_instance *world, ray_hit *hit, v3f tri[3] );
+int ray_world( world_instance *world, v3f pos, v3f dir, ray_hit *hit, u16 ignore );
+int spherecast_world( world_instance *world, v3f pa, v3f pb, float r, float *t, v3f n, u16 ignore );
+struct world_surface *world_tri_index_surface( world_instance *world, u32 index );
+struct world_surface *world_contact_surface( world_instance *world, rb_ct *ct );
+struct world_surface *ray_hit_surface( world_instance *world, ray_hit *hit );
+
+#endif
-/*
- * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#include "world.h"
-#include "world_render.h"
-#include "font.h"
-#include "gui.h"
-#include "world_map.h"
-#include "player_remote.h"
-#include "ent_skateshop.h"
-#include "shaders/model_entity.h"
-#include "shaders/model_sky_cubemap.h"
-#include "shaders/scene_preview.h"
-#include "shaders/scene_override.h"
-#include "board_maker.h"
-
struct world_render world_render;
static int ccmd_render_portals( int argc, const char *argv[] );
return 0;
}
-static void async_world_render_init( void *userdata )
-{
- vg_info( "Allocate uniform buffers\n" );
-
- world_instance *world = &_world.main;
- world->ubo_bind_point = 0;
- glGenBuffers( 1, &world->ubo_lighting );
- glBindBuffer( GL_UNIFORM_BUFFER, world->ubo_lighting );
- glBufferData( GL_UNIFORM_BUFFER, sizeof(struct ub_world_lighting), NULL, GL_DYNAMIC_DRAW );
- glBindBufferBase( GL_UNIFORM_BUFFER, 0, world->ubo_lighting );
-}
-
-void world_render_register(void)
+VG_API void _world_render_register(void)
{
VG_VAR_F32( k_day_length );
VG_VAR_I32( k_debug_light_indices );
vg_console_reg_cmd( "render_portals", ccmd_render_portals, NULL );
}
-void world_render_init(void)
+static void _world_render_load_content_async( void *_, vg_async_info *async )
{
- THREAD_1;
- vg_info( "Loading world resources\n" );
- vg_stack_clear( &vg.scratch );
-
- mdl_context msky;
- mdl_open( &msky, "models/rs_skydome.mdl", &vg.scratch );
- mdl_load_metadata_block( &msky, &vg.scratch );
- mdl_async_load_glmesh( &msky, &world_render.skydome, NULL );
- world_render.skydome_complete_mesh = msky.submeshes[ mdl_get_submesh_index( &msky, "dome_complete" ) ];
- world_render.skydome_squanched_mesh = msky.submeshes[ mdl_get_submesh_index( &msky, "dome_squanched" ) ];
- mdl_close( &msky );
-
- vg_info( "Loading default world textures\n" );
- vg_tex2d_load_qoi_async_file( "textures/garbage.qoi",
- VG_TEX2D_NEAREST|VG_TEX2D_REPEAT,
- &world_render.tex_terrain_noise );
-
- vg_info( "Allocate frame buffers\n" );
- world_instance *world = &_world.main;
- world->heightmap = vg_framebuffer_allocate( &vg.rtmem, 1, 0 );
- world->heightmap->display_name = NULL;
- world->heightmap->fixed_w = 1024;
- world->heightmap->fixed_h = 1024;
- world->heightmap->resolution_div = 0;
- world->heightmap->attachments[0] = (vg_framebuffer_attachment)
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+
+ vg_model_load( &world_render.skydome, VG_MODEL_ENGINE_STANDARD, "models/rs_skydome.mdl", VG_STACK_USE_HEAP );
+ world_render.skydome_complete_mesh = vg_model_get_submesh_index( &world_render.skydome, "dome_complete" );
+ world_render.skydome_squanched_mesh = vg_model_get_submesh_index( &world_render.skydome, "dome_squanched" );
+
+ u32 flags = VG_TEX_NEAREST|VG_TEX_REPEAT|VG_TEX_NOMIP;
+ _vg_tex_load( &world_render.tex_terrain_noise, "textures/garbage.qoi", flags );
+}
+
+VG_API void _world_render_init(void)
+{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_world_render_load_content_async );
+
+ world_render.heightmap = _vg_framebuffer_alloc( VG_STACK_USE_HEAP, 1, 0 );
+ world_render.heightmap->display_name = NULL;
+ world_render.heightmap->fixed_w = 1024;
+ world_render.heightmap->fixed_h = 1024;
+ world_render.heightmap->resolution_div = 0;
+ world_render.heightmap->attachments[0] = (vg_framebuffer_attachment)
{
NULL, k_framebuffer_attachment_type_texture,
.internalformat = GL_RG16F,
.type = GL_FLOAT,
.attachment = GL_COLOR_ATTACHMENT0
};
- vg_framebuffer_create( world->heightmap );
- vg_async_call( &vg.main_tasks, async_world_render_init, NULL );
+ vg_framebuffer_init( world_render.heightmap );
+
+ world_render.ubo_bind_point = 0;
+ glGenBuffers( 1, &world_render.ubo_lighting );
+ glBindBuffer( GL_UNIFORM_BUFFER, world_render.ubo_lighting );
+ glBufferData( GL_UNIFORM_BUFFER, sizeof(struct ub_world_lighting), NULL, GL_DYNAMIC_DRAW );
+ glBindBufferBase( GL_UNIFORM_BUFFER, 0, world_render.ubo_lighting );
}
/*
* standard uniform bindings
* ----------------------------------------------------------------------------
*/
-void world_link_lighting_ub( world_instance *world, GLuint shader )
+void world_link_lighting( world_instance *world,
+ enum e_shader_gl_name shader,
+ enum e_shader_gl_name uniform_block_index,
+ enum e_shader_gl_name uniform_position_tex,
+ enum e_shader_gl_name uniform_light_array,
+ enum e_shader_gl_name uniform_light_index )
{
- GLuint idx = glGetUniformBlockIndex( shader, "ub_world_lighting" );
- glUniformBlockBinding( shader, idx, world->ubo_bind_point );
-}
+ glUniformBlockBinding( _vg_shader_names[ shader ], _vg_shader_names[ uniform_block_index ],
+ world_render.ubo_bind_point );
-void world_bind_position_texture( world_instance *world,
- GLuint shader, GLuint location,
- int slot )
-{
- vg_framebuffer_bind_texture( world->heightmap, 0, slot );
- glUniform1i( location, slot );
-}
+ vg_framebuffer_bind_texture( world_render.heightmap, 0, 2 );
+ glUniform1i( _vg_shader_names[ uniform_position_tex ], 2 );
-void world_bind_light_array( world_instance *world,
- GLuint shader, GLuint location,
- int slot )
-{
- glActiveTexture( GL_TEXTURE0 + slot );
+ glActiveTexture( GL_TEXTURE0 + 3 );
glBindTexture( GL_TEXTURE_BUFFER, world->tex_light_entities );
- glUniform1i( location, slot );
-}
+ glUniform1i( _vg_shader_names[ uniform_light_array ], 3 );
-void world_bind_light_index( world_instance *world,
- GLuint shader, GLuint location,
- int slot )
-{
- glActiveTexture( GL_TEXTURE0 + slot );
+ glActiveTexture( GL_TEXTURE0 + 4 );
glBindTexture( GL_TEXTURE_3D, world->tex_light_cubes );
- glUniform1i( location, slot );
+ glUniform1i( _vg_shader_names[ uniform_light_index ], 4 );
}
-void bind_terrain_noise(void)
+void world_link_terrain_noise( world_instance *world, enum e_shader_gl_name uniform_sampler )
{
- glActiveTexture( GL_TEXTURE0 );
- glBindTexture( GL_TEXTURE_2D, world_render.tex_terrain_noise );
+ vg_tex_bind( GL_TEXTURE_2D, &world_render.tex_terrain_noise, 0 );
+ glUniform1i( _vg_shader_names[ uniform_sampler ], 0 );
}
/*
* Get OpenGL texture name from texture ID.
*/
-static GLuint world_get_texture( world_instance *world, u32 id ){
+static vg_tex *world_get_texture( world_instance *world, u32 id )
+{
if( id & 0x80000000 ) return skaterift.rt_textures[id & ~0x80000000];
- else return world->textures[ id ];
+ else return id? &world->meta.textures[ id-1 ].tex: NULL;
}
/*
enum mdl_shader shader;
enum world_geo_type geo_type;
- void (*fn_bind)( world_instance *world, struct world_surface *mat );
+ void (*fn_bind)( world_instance *world, u32 surface_id );
void (*fn_set_mdl)( m4x3f mdl );
void (*fn_set_uPvmPrev)( m4x4f pvm );
void (*fn_set_uNormalMtx)( m3x3f mnorm );
pass->fn_set_mdl( mmdl );
pass->fn_set_uPvmPrev( m4mdl );
- mdl_draw_submesh( sm );
+ vg_model_draw_submesh( sm );
}
}
*/
static void world_render_props( world_instance *world, u32 material_id, struct world_pass *pass )
{
- struct world_surface *mat = &world->surfaces[ material_id ];
- if( !(mat->flags & WORLD_SURFACE_HAS_PROPS) ) return;
+ struct world_surface *surf = &world->surfaces[ material_id ];
+ if( !(surf->flags & WORLD_SURFACE_HAS_PROPS) )
+ return;
- pass->fn_bind( world, mat );
+ VG_ASSERT( material_id );
+ pass->fn_bind( world, material_id );
for( u32 j=0; j<af_arrcount( &world->ent_prop ); j++ )
{
*/
static void world_render_traffic( world_instance *world, u32 material_id,struct world_pass *pass )
{
- struct world_surface *mat = &world->surfaces[ material_id ];
- if( !(mat->flags & WORLD_SURFACE_HAS_TRAFFIC) )
+ struct world_surface *surf = &world->surfaces[ material_id ];
+ if( !(surf->flags & WORLD_SURFACE_HAS_TRAFFIC) )
return;
- pass->fn_bind( world, mat );
+ VG_ASSERT( material_id );
+ pass->fn_bind( world, material_id );
for( u32 j=0; j<af_arrcount( &world->ent_traffic ); j++ ){
ent_traffic *traffic = af_arritm( &world->ent_traffic, j );
*/
static void world_render_pass( world_instance *world, struct world_pass *pass )
{
- for( int i=0; i<world->surface_count; i++ )
+ for( int i=1; i<world->surface_count; i++ )
{
- struct world_surface *mat = &world->surfaces[i];
+ struct world_surface *surf = &world->surfaces[i];
- if( mat->info.shader == pass->shader )
+ if( surf->info.shader == pass->shader )
{
mdl_submesh *sm;
if( pass->geo_type == k_world_geo_type_solid )
{
- sm = &mat->sm_geo;
+ sm = &surf->sm_geo;
}
else
{
world_render_traffic( world, i, pass );
world_render_props( world, i, pass );
- sm = &mat->sm_no_collide;
+ sm = &surf->sm_no_collide;
}
if( !sm->indice_count )
m4x3_identity( mmdl );
pass->fn_set_mdl( mmdl );
pass->fn_set_uPvmPrev( pass->cam->mtx_prev.pv );
- pass->fn_bind( world, mat );
- mdl_draw_submesh( sm );
+ pass->fn_bind( world, i );
+ vg_model_draw_submesh( sm );
}
}
}
static void world_render_both_stages( world_instance *world,
struct world_pass *pass )
{
- mesh_bind( &world->mesh_geo );
+ scene_mesh_bind( &world->main_scene_mesh );
pass->geo_type = k_world_geo_type_solid;
world_render_pass( world, pass );
glDisable( GL_CULL_FACE );
- mesh_bind( &world->mesh_no_collide );
+ scene_mesh_bind( &world->transparent_scene_mesh );
pass->geo_type = k_world_geo_type_nonsolid;
world_render_pass( world, pass );
glEnable( GL_CULL_FACE );
}
-static void bindpoint_world_vb( world_instance *world,
- struct world_surface *mat )
+static void bindpoint_world_vb( world_instance *world, u32 surface_id )
{
- struct shader_props_vertex_blend *props = mat->info.props.compiled;
-
- glActiveTexture( GL_TEXTURE1 );
- glBindTexture( GL_TEXTURE_2D, world_get_texture(world, props->tex_diffuse) );
+ union shader_props *props = &world->meta.shader_props[ surface_id -1 ];
+ vg_tex_bind( GL_TEXTURE_2D, world_get_texture(world, props->vertex_blend.tex_diffuse), 1 );
#if 0
shader_scene_vertex_blend_uOffset( props->blend_offset );
shader_scene_vertex_blend_use();
shader_scene_vertex_blend_uTexGarbage(0);
shader_scene_vertex_blend_uTexGradients(1);
- WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_vertex_blend );
-
- glActiveTexture( GL_TEXTURE0 );
- glBindTexture( GL_TEXTURE_2D, world_render.tex_terrain_noise );
+ WORLD_LINK_LIGHTING( world, scene_vertex_blend );
+ vg_tex_bind( GL_TEXTURE_2D, &world_render.tex_terrain_noise, 0 );
shader_scene_vertex_blend_uPv( cam->mtx.pv );
shader_scene_vertex_blend_uCamera( cam->transform[3] );
shader_scene_standard_uTexGarbage(0);
shader_scene_standard_uTexMain(1);
shader_scene_standard_uPv( cam->mtx.pv );
- WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_standard );
-
- bind_terrain_noise();
+ WORLD_LINK_LIGHTING( world, scene_standard );
+ world_link_terrain_noise( world, k_uniform_scene_standard_uTexGarbage );
shader_scene_standard_uCamera( cam->transform[3] );
}
-static void bindpoint_standard( world_instance *world,
- struct world_surface *mat )
+static void bindpoint_standard( world_instance *world, u32 surface_id )
{
- struct shader_props_standard *props = mat->info.props.compiled;
-
- glActiveTexture( GL_TEXTURE1 );
- glBindTexture( GL_TEXTURE_2D, world_get_texture(world, props->tex_diffuse) );
+ union shader_props *props = &world->meta.shader_props[ surface_id -1 ];
+ vg_tex_bind( GL_TEXTURE_2D, world_get_texture(world, props->standard.tex_diffuse), 1 );
}
static void render_world_standard( world_instance *world, vg_camera *cam )
world_render_both_stages( world, &pass );
}
-static void bindpoint_world_cubemapped( world_instance *world, struct world_surface *mat )
+static void bindpoint_world_cubemapped( world_instance *world, u32 surface_id )
{
- struct shader_props_cubemapped *props = mat->info.props.compiled;
+ union shader_props *props = &world->meta.shader_props[ surface_id -1 ];
+ vg_tex_bind( GL_TEXTURE_2D, world_get_texture( world, props->cubemapped.tex_diffuse ), 1 );
- glActiveTexture( GL_TEXTURE1 );
- glBindTexture( GL_TEXTURE_2D,
- world_get_texture( world,props->tex_diffuse ) );
-
- u32 cubemap_id = props->cubemap_entity,
+ u32 cubemap_id = props->cubemapped.cubemap_entity,
cubemap_index = 0;
if( mdl_entity_id_type( cubemap_id ) == k_ent_cubemap )
glActiveTexture( GL_TEXTURE10 );
glBindTexture( GL_TEXTURE_CUBE_MAP, cm->texture_id );
- shader_scene_cubemapped_uColour( props->tint );
+ shader_scene_cubemapped_uColour( props->cubemapped.tint );
}
-static void bindpoint_world_cubemapped_disabled( world_instance *world,
- struct world_surface *mat )
+static void bindpoint_world_cubemapped_disabled( world_instance *world, u32 surface_id )
{
- struct shader_props_cubemapped *props = mat->info.props.compiled;
-
- glActiveTexture( GL_TEXTURE1 );
- glBindTexture( GL_TEXTURE_2D,
- world_get_texture( world, props->tex_diffuse ) );
+ union shader_props *props = &world->meta.shader_props[ surface_id -1 ];
+ vg_tex_bind( GL_TEXTURE_2D, world_get_texture( world, props->cubemapped.tex_diffuse ), 1 );
}
static void render_world_cubemapped( world_instance *world, vg_camera *cam, int enabled )
shader_scene_cubemapped_uTexCubemap(10);
shader_scene_cubemapped_uPv( cam->mtx.pv );
- WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_cubemapped );
+ WORLD_LINK_LIGHTING( world, scene_cubemapped );
- bind_terrain_noise();
+ world_link_terrain_noise( world, k_uniform_scene_cubemapped_uTexGarbage );
shader_scene_cubemapped_uCamera( cam->transform[3] );
struct world_pass pass =
static void render_world_alphatest( world_instance *world, vg_camera *cam )
{
shader_scene_standard_alphatest_use();
- shader_scene_standard_alphatest_uTexGarbage(0);
shader_scene_standard_alphatest_uTexMain(1);
shader_scene_standard_alphatest_uPv( cam->mtx.pv );
- WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_standard_alphatest );
+ WORLD_LINK_LIGHTING( world, scene_standard_alphatest );
- bind_terrain_noise();
+ world_link_terrain_noise( world, k_uniform_scene_standard_uTexGarbage );
shader_scene_standard_alphatest_uCamera( cam->transform[3] );
glDisable(GL_CULL_FACE);
static void render_world_foliage( world_instance *world, vg_camera *cam )
{
shader_scene_foliage_use();
- shader_scene_foliage_uTexGarbage(0);
shader_scene_foliage_uTexMain(1);
shader_scene_foliage_uPv( cam->mtx.pv );
shader_scene_foliage_uTime( vg.time );
shader_scene_foliage_uAmt( world->info.wind_scale );
- WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_foliage );
- bind_terrain_noise();
+ WORLD_LINK_LIGHTING( world, scene_foliage );
+ world_link_terrain_noise( world, k_uniform_scene_foliage_uTexGarbage );
shader_scene_foliage_uCamera( cam->transform[3] );
glDisable(GL_CULL_FACE);
bh_iter it;
bh_iter_init_range( 0, &it, pos, radius+10.0f );
i32 idx;
- while( bh_next( world->entity_bh, &it, &idx ) )
+ while( bh_next( &world->entity_bh, &it, &idx ) )
{
u32 id = world->entity_list[ idx ],
type = mdl_entity_id_type( id ),
/* render objectives */
glDisable( GL_CULL_FACE );
- mesh_bind( &world->mesh_no_collide );
+ scene_mesh_bind( &world->transparent_scene_mesh );
u32 last_material = 0;
for( u32 i=0; i<objective_count; i++ )
{
if( sm->material_id != last_material )
{
last_material = sm->material_id;
- pass->fn_bind( world, &world->surfaces[sm->material_id] );
+ VG_ASSERT( sm->material_id );
+ pass->fn_bind( world, sm->material_id );
}
- mdl_draw_submesh( sm );
+ vg_model_draw_submesh( sm );
}
}
/* render texts */
- font3d_bind( &gui.font, k_font_shader_world, 0, world, &g_render.cam );
+ font3d_bind( &gui.font, k_font_shader_world, 0, &g_render.cam );
u32 count = 0, total = 0;
for( u32 i=0; i<af_arrcount(&world->ent_challenge); i++ )
char buf[32];
vg_str str;
vg_strnull( &str, buf, sizeof(buf) );
- vg_strcati32( &str, count );
+ vg_strcati64( &str, count, 10 );
vg_strcatch( &str, '/' );
- vg_strcati32( &str, total );
+ vg_strcati64( &str, total, 10 );
f32 w = font3d_string_width( 1, buf );
m4x3f mlocal;
}
}
-static void bindpoint_fxglow( world_instance *world, struct world_surface *mat )
+static void bindpoint_fxglow( world_instance *world, u32 surface_id )
{
- struct shader_props_standard *props = mat->info.props.compiled;
-
- glActiveTexture( GL_TEXTURE1 );
- glBindTexture( GL_TEXTURE_2D, world_get_texture(world, props->tex_diffuse) );
+ union shader_props *props = &world->meta.shader_props[ surface_id -1 ];
+ vg_tex_bind( GL_TEXTURE_2D, world_get_texture(world, props->standard.tex_diffuse), 1 );
}
static void render_world_fxglow( world_instance *host_world,
shader_scene_fxglow_uUvOffset( (v2f){ 0.0f, 0.0f } );
shader_scene_fxglow_uTexMain(1);
shader_scene_fxglow_uPv( cam->mtx.pv );
- //WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_fxglow );
+ //WORLD_LINK_LIGHTING( world, scene_fxglow );
shader_scene_fxglow_uCamera( cam->transform[3] );
glDisable(GL_CULL_FACE);
if( regions )
{
- mesh_bind( &world->mesh_no_collide );
+ scene_mesh_bind( &world->transparent_scene_mesh );
u32 last_material = 0;
for( u32 i=0; i<af_arrcount(&world->ent_region); i ++ )
if( sm->material_id != last_material )
{
last_material = sm->material_id;
- pass.fn_bind( world, &world->surfaces[sm->material_id] );
+ VG_ASSERT( sm->material_id );
+ pass.fn_bind( world, sm->material_id );
}
- mdl_draw_submesh( sm );
+ vg_model_draw_submesh( sm );
}
}
}
glEnable(GL_CULL_FACE);
}
-static void bindpoint_terrain( world_instance *world,
- struct world_surface *mat )
+static void bindpoint_terrain( world_instance *world, u32 surface_id )
{
- struct shader_props_terrain *props = mat->info.props.compiled;
+ union shader_props *props = &world->meta.shader_props[ surface_id -1 ];
- glActiveTexture( GL_TEXTURE1 );
- glBindTexture( GL_TEXTURE_2D, world_get_texture(world, props->tex_diffuse) );
- shader_scene_terrain_uBlendOffset( props->blend_offset );
- shader_scene_terrain_uSandColour( props->sand_colour );
+ vg_tex_bind( GL_TEXTURE_2D, world_get_texture(world, props->terrain.tex_diffuse), 1 );
+ shader_scene_terrain_uBlendOffset( props->terrain.blend_offset );
+ shader_scene_terrain_uSandColour( props->terrain.sand_colour );
}
-static void bindpoint_override( world_instance *world, struct world_surface *mat )
+static void bindpoint_override( world_instance *world, u32 surface_id )
{
- f32 skate_surface = mat->info.flags & k_material_flag_skate_target? 1.0f: 0.0f;
+ struct world_surface *surf = &world->surfaces[ surface_id ];
+ f32 skate_surface = surf->info.flags & k_material_flag_skate_target? 1.0f: 0.0f;
shader_scene_override_uSurfaceInfo( (v4f){ skate_surface, 0,0,0 } );
- if( mat->info.flags & k_material_flag_collision )
+ if( surf->info.flags & k_material_flag_collision )
{
shader_scene_override_uAlphatest(0);
}
else
{
- glActiveTexture( GL_TEXTURE1 );
- glBindTexture( GL_TEXTURE_2D, world_get_texture(world, mat->alpha_tex) );
+ vg_tex_bind( GL_TEXTURE_2D, world_get_texture(world, surf->alpha_tex), 1 );
shader_scene_override_uAlphatest(1);
}
}
-static void bindpoint_world_preview( world_instance *world, struct world_surface *mat )
+static void bindpoint_world_preview( world_instance *world, u32 surface_id )
{
- f32 skate_surface = mat->info.flags & k_material_flag_skate_target? 1.0f: 0.0f;
+ union shader_props *props = &world->meta.shader_props[ surface_id -1 ];
+ struct world_surface *surf = &world->surfaces[ surface_id ];
+
+ f32 skate_surface = surf->info.flags & k_material_flag_skate_target? 1.0f: 0.0f;
shader_scene_preview_uSurfaceInfo( (v4f){ skate_surface, 0,0,0 } );
- if( mat->info.flags & k_material_flag_collision )
+ if( surf->info.flags & k_material_flag_collision )
{
}
else
shader_scene_terrain_uTexGarbage(0);
shader_scene_terrain_uTexGradients(1);
- WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_terrain );
- glActiveTexture( GL_TEXTURE0 );
- glBindTexture( GL_TEXTURE_2D, world_render.tex_terrain_noise );
+ WORLD_LINK_LIGHTING( world, scene_terrain );
+ vg_tex_bind( GL_TEXTURE_2D, &world_render.tex_terrain_noise, 0 );
shader_scene_terrain_uPv( cam->mtx.pv );
shader_scene_terrain_uCamera( cam->transform[3] );
shader_model_sky_uPv( pv );
shader_model_sky_uPvmPrev( pv_prev );
shader_model_sky_uTexGarbage(0);
- world_link_lighting_ub( world, _shader_model_sky.id );
+ glUniformBlockBinding( _vg_shader_names[ k_shader_model_sky ],
+ _vg_shader_names[ k_uniform_block_model_sky_ub_world_lighting ],
+ world_render.ubo_bind_point );
- glActiveTexture( GL_TEXTURE0 );
- glBindTexture( GL_TEXTURE_2D, world_render.tex_terrain_noise );
+ vg_tex_bind( GL_TEXTURE_2D, &world_render.tex_terrain_noise, 0 );
}
- else if( world->skybox == k_skybox_space ){
+ else if( world->skybox == k_skybox_space )
+ {
shader_model_sky_space_use();
-
shader_model_sky_space_uMdl( identity_matrix );
shader_model_sky_space_uPv( pv );
shader_model_sky_space_uPvmPrev( pv_prev );
shader_model_sky_space_uTexGarbage(0);
- world_link_lighting_ub( world, _shader_model_sky_space.id );
+ glUniformBlockBinding( _vg_shader_names[ k_shader_model_sky_space ],
+ _vg_shader_names[ k_uniform_block_model_sky_space_ub_world_lighting ],
+ world_render.ubo_bind_point );
- glActiveTexture( GL_TEXTURE0 );
- glBindTexture( GL_TEXTURE_2D, world_render.tex_terrain_noise );
+ vg_tex_bind( GL_TEXTURE_2D, &world_render.tex_terrain_noise, 0 );
}
else if( world->skybox == k_skybox_cubemap )
{
/* TODO */
}
- else {
+ else
vg_fatal_error( "Programming error\n" );
- }
glDepthMask( GL_FALSE );
glDisable( GL_DEPTH_TEST );
- mesh_bind( &world_render.skydome );
- mdl_draw_submesh( &world_render.skydome_complete_mesh );
+ vg_model_bind_mesh( &world_render.skydome );
+ vg_model_draw_submesh( &world_render.skydome.submeshes[ world_render.skydome_complete_mesh ]);
glEnable( GL_DEPTH_TEST );
glDepthMask( GL_TRUE );
shader_model_sky_cubemap_uPv( cam->mtx.pv );
shader_model_sky_cubemap_uPvmPrev( pvm );
shader_model_sky_cubemap_uTexCubemap(10);
-
- glActiveTexture( GL_TEXTURE10 );
- glBindTexture( GL_TEXTURE_CUBE_MAP, world->nonlocal_gates_cubemaps[ gate->cubemap_id ] );
+ vg_tex_bind( GL_TEXTURE_CUBE_MAP, &world->nonlocal_gates_cubemaps[ gate->cubemap_id ], 10 );
glClear( GL_DEPTH_BUFFER_BIT );
glStencilFunc( GL_EQUAL, 1, 0xFF );
glEnable( GL_CULL_FACE );
glEnable( GL_STENCIL_TEST );
- mesh_bind( &world_render.skydome );
- mdl_draw_submesh( &world_render.skydome_squanched_mesh );
+ vg_model_bind_mesh( &world_render.skydome );
+ vg_model_draw_submesh( &world_render.skydome.submeshes[ world_render.skydome_squanched_mesh ]);
glStencilMask( 0xFF );
glStencilFunc( GL_ALWAYS, 1, 0xFF );
world->time = world->info.timezone;
}
- struct ub_world_lighting *state = &world->ub_lighting;
+ struct ub_world_lighting *state = &world_render.ub_lighting;
state->g_time = world->time;
state->g_realtime = vg.time_real;
world->probabilities[ k_probability_curve_wildlife_night ] =
1.0f-powf(fabsf((state->g_time_of_day-0.5f)*5.0f),5.0f);
- glBindBuffer( GL_UNIFORM_BUFFER, world->ubo_lighting );
- glBufferSubData( GL_UNIFORM_BUFFER, 0,
- sizeof(struct ub_world_lighting), &world->ub_lighting );
+ glBindBuffer( GL_UNIFORM_BUFFER, world_render.ubo_lighting );
+ glBufferSubData( GL_UNIFORM_BUFFER, 0, sizeof(struct ub_world_lighting), &world_render.ub_lighting );
}
static void render_other_entities( world_instance *world, vg_camera *cam )
glider_count = 0;
i32 idx;
- while( bh_next( world->entity_bh, &it, &idx ) ){
+ while( bh_next( &world->entity_bh, &it, &idx ) )
+ {
u32 id = world->entity_list[ idx ],
type = mdl_entity_id_type( id ),
index = mdl_entity_id_id( id );
shader_model_entity_uTexMain( 0 );
shader_model_entity_uCamera( cam->transform[3] );
shader_model_entity_uPv( cam->mtx.pv );
- WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, model_entity );
+ WORLD_LINK_LIGHTING( world, model_entity );
for( u32 j=0; j<glider_count; j ++ )
{
render_glider_model( cam, world, mdl, k_board_shader_entity, &player_glide.glider );
}
- cutscene_render( world, cam );
+ _cutscene_render( cam );
_ent_npc_render( cam );
}
render_remote_players( world, cam );
render_other_entities( world, cam );
- _replay2_render_player( world, cam );
+ _replay2_render_player( cam );
_board_maker_render( world, cam );
m4x3f mmdl, m3x3f mnormal,
m4x4f mpvm_prev )
{
- for( int i=0; i<world->surface_count; i++ )
+ for( int i=1; i<world->surface_count; i++ )
{
struct world_surface *mat = &world->surfaces[i];
if( mat->info.flags & k_material_flag_ghosts ) continue;
pass->fn_set_mdl( mmdl );
pass->fn_set_uNormalMtx( mnormal );
pass->fn_set_uPvmPrev( mpvm_prev );
- pass->fn_bind( world, mat );
- mdl_draw_submesh( sm );
+ pass->fn_bind( world, i );
+ vg_model_draw_submesh( sm );
}
}
};
shader_scene_override_use();
- shader_scene_override_uTexGarbage(0);
shader_scene_override_uTexMain(1);
shader_scene_override_uPv( pass.cam->mtx.pv );
shader_scene_override_uMapInfo( map_info );
- WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( lighting_source, scene_override );
- bind_terrain_noise();
+ WORLD_LINK_LIGHTING( lighting_source, scene_override );
+ world_link_terrain_noise( world, k_uniform_scene_override_uTexGarbage );
shader_scene_override_uCamera( pass.cam->transform[3] );
glDisable( GL_CULL_FACE );
- mesh_bind( &world->mesh_geo );
+ scene_mesh_bind( &world->main_scene_mesh );
pass.geo_type = k_world_geo_type_solid;
render_world_override_pass( world, &pass, mmdl, mnormal, mpvm_prev );
- mesh_bind( &world->mesh_no_collide );
+ scene_mesh_bind( &world->transparent_scene_mesh );
pass.geo_type = k_world_geo_type_nonsolid;
render_world_override_pass( world, &pass, mmdl, mnormal, mpvm_prev );
glEnable( GL_CULL_FACE );
v3_normalize( mnormal[2] );
glEnable( GL_CULL_FACE );
- mesh_bind( &world->mesh_geo );
+ scene_mesh_bind( &world->main_scene_mesh );
pass.geo_type = k_world_geo_type_solid;
render_world_override_pass( world, &pass, mmdl, mnormal, mpvm_prev );
glDisable( GL_CULL_FACE );
- mesh_bind( &world->mesh_no_collide );
+ scene_mesh_bind( &world->transparent_scene_mesh );
pass.geo_type = k_world_geo_type_nonsolid;
render_world_override_pass( world, &pass, mmdl, mnormal, mpvm_prev );
.fixed_h = WORLD_CUBEMAP_RES,
.id = cm->framebuffer_id,
.attachment_count = 0,
- .attachments = NULL
};
render_cubemap_side( world, cm->co, identity, world->cubemap_side, &temp_vg_framebuffer );
}
.colorspace = 0
};
- u8 *src_image = malloc( 512*512*3*6 );
- u8 *compressed_image = malloc( vg_query_qoi_storage_size( &desc ) );
+ u32 temp_frame = _vg_start_temp_frame();
+ u8 *src_image = vg_stack_allocate( _vg_temp_stack(), 512*512*3*6, 8, "RGBA Image data" );
GLuint temp_tex, temp_fb, temp_rb;
glGenFramebuffers( 1, &temp_fb );
.fixed_h = 512,
.id = temp_fb,
.attachment_count = 0,
- .attachments = NULL
};
world_instance *world = &_world.main;
}
char path[256];
- nonlocal_gate_cubemap_path( world->addon_id, af_str( &world->meta.af, gate->key ), path );
+ nonlocal_gate_cubemap_path( world->addon_id, af_str( world->meta.packed_strings, gate->key ), path );
- int file_size;
- if( vg_encode_qoi2( src_image, &desc, compressed_image, &file_size ) )
- vg_asset_write( path, compressed_image, file_size );
+ vg_stream file;
+ if( vg_file_stream_open( &file, path, VG_STREAM_WRITE ) )
+ {
+ vg_qoi_stream_encode( &desc, src_image, &file, 0 );
+ vg_file_stream_close( &file );
+ }
}
}
e0:glDeleteTextures( 1, &temp_tex );
glDeleteFramebuffers( 1, &temp_fb );
glDeleteRenderbuffers( 1, &temp_rb );
- free( src_image );
- free( compressed_image );
+ _vg_end_temp_frame( temp_frame );
}
static int ccmd_render_portals( int argc, const char *argv[] )
shader_scene_depth_uPv( cam->mtx.pv );
shader_scene_depth_uPvmPrev( cam->mtx_prev.pv );
shader_scene_depth_uMdl( identity_matrix );
- world_link_lighting_ub( world, _shader_scene_depth.id );
+ glUniformBlockBinding( _vg_shader_names[ k_shader_scene_depth ],
+ _vg_shader_names[ k_uniform_block_scene_depth_ub_world_lighting ],
+ world_render.ubo_bind_point );
- mesh_bind( &world->mesh_geo );
+ scene_mesh_bind( &world->main_scene_mesh );
for( int i=0; i<world->surface_count; i++ )
{
struct world_surface *mat = &world->surfaces[i];
if( mat->info.flags & k_material_flag_ghosts ) continue;
mdl_submesh *sm = &mat->sm_geo;
- mdl_draw_submesh( sm );
+ vg_model_draw_submesh( sm );
}
}
shader_scene_position_uPv( cam->mtx.pv );
shader_scene_position_uPvmPrev( cam->mtx_prev.pv );
shader_scene_position_uMdl( identity_matrix );
- world_link_lighting_ub( world, _shader_scene_position.id );
+ glUniformBlockBinding( _vg_shader_names[ k_shader_scene_position ],
+ _vg_shader_names[ k_uniform_block_scene_position_ub_world_lighting ],
+ world_render.ubo_bind_point );
- mesh_bind( &world->mesh_geo );
+ scene_mesh_bind( &world->main_scene_mesh );
for( int i=0; i<world->surface_count; i++ )
{
struct world_surface *mat = &world->surfaces[i];
if( mat->info.flags & k_material_flag_ghosts ) continue;
mdl_submesh *sm = &mat->sm_geo;
- mdl_draw_submesh( sm );
+ vg_model_draw_submesh( sm );
}
}
static f32 *skybox_prop_location( world_instance *world, i32 index ){
switch( index ){
- case 0: return world->ub_lighting.g_daysky_colour; break;
- case 1: return world->ub_lighting.g_nightsky_colour; break;
- case 2: return world->ub_lighting.g_sunset_colour; break;
- case 3: return world->ub_lighting.g_ambient_colour; break;
- case 4: return world->ub_lighting.g_sun_colour; break;
+ case 0: return world_render.ub_lighting.g_daysky_colour; break;
+ case 1: return world_render.ub_lighting.g_nightsky_colour; break;
+ case 2: return world_render.ub_lighting.g_sunset_colour; break;
+ case 3: return world_render.ub_lighting.g_ambient_colour; break;
+ case 4: return world_render.ub_lighting.g_sun_colour; break;
default: return NULL;
}
}
void imgui_world_light_edit( ui_context *ctx, world_instance *world )
{
- ui_rect panel = { vg.window_x-400, 0, 400, vg.window_y };
+ ui_rect panel = { _vg_window.w-400, 0, 400, _vg_window.h };
ui_fill( ctx, panel, ui_colour( ctx, k_ui_bg+1 ) );
ui_outline( ctx, panel, 1, ui_colour( ctx, k_ui_bg+7 ), 0 );
ui_rect_pad( panel, (ui_px[2]){ 8, 8 } );
-/*
- * Copyright (C) 2021-2024 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#pragma once
+#if defined( SR_IMPLEMENTATION )
+# include "src/world_render.c"
+#else
#define WORLD_CUBEMAP_RES 32
-#include "vg/vg_camera.h"
-#include "world.h"
-#include "shaders/scene_standard.h"
-#include "shaders/scene_standard_alphatest.h"
-#include "shaders/scene_foliage.h"
-#include "shaders/scene_override.h"
-#include "shaders/scene_cubemapped.h"
-#include "shaders/scene_vertex_blend.h"
-#include "shaders/scene_terrain.h"
-#include "shaders/scene_fxglow.h"
-#include "shaders/scene_depth.h"
-#include "shaders/scene_position.h"
-#include "shaders/scene_font.h"
-#include "shaders/model_sky.h"
-#include "shaders/model_sky_space.h"
-
static const float k_world_light_cube_size = 8.0f;
struct world_render
{
- GLuint tex_terrain_noise;
+ vg_tex tex_terrain_noise;
/* rendering */
- glmesh skydome;
- mdl_submesh skydome_complete_mesh,
- skydome_squanched_mesh;
+ vg_model skydome;
+ i32 skydome_complete_mesh,
+ skydome_squanched_mesh;
v3f render_gate_pos;
struct timer_text{
}
text_particles[6*4];
u32 text_particle_count;
+
+ /* STD140 */
+ struct ub_world_lighting{
+ v4f g_cube_min,
+ g_cube_inv_range;
+
+ v4f g_water_plane,
+ g_depth_bounds;
+
+ v4f g_daysky_colour;
+ v4f g_nightsky_colour;
+ v4f g_sunset_colour;
+ v4f g_ambient_colour;
+ v4f g_sunset_ambient;
+ v4f g_sun_colour;
+ v4f g_sun_dir;
+ v4f g_board_0;
+ v4f g_board_1;
+
+ float g_water_fog;
+ float g_time;
+ float g_realtime;
+ float g_shadow_length;
+ float g_shadow_spread;
+
+ float g_time_of_day;
+ float g_day_phase;
+ float g_sunset_phase;
+
+ int g_light_preview;
+ int g_shadow_samples;
+
+ int g_debug_indices;
+ int g_debug_complexity;
+ }
+ ub_lighting;
+ GLuint ubo_lighting;
+ int ubo_bind_point;
+ vg_framebuffer *heightmap;
}
extern world_render;
-void world_render_register(void);
-void world_render_init(void);
+VG_API void _world_render_register(void);
+VG_API void _world_render_init(void);
void world_prerender( world_instance *world );
-void world_link_lighting_ub( world_instance *world, GLuint shader );
-void world_bind_position_texture( world_instance *world,
- GLuint shader, GLuint location,
- int slot );
-void world_bind_light_array( world_instance *world,
- GLuint shader, GLuint location,
- int slot );
-void world_bind_light_index( world_instance *world,
- GLuint shader, GLuint location,
- int slot );
+void world_link_lighting( world_instance *world,
+ enum e_shader_gl_name shader,
+ enum e_shader_gl_name uniform_block_index,
+ enum e_shader_gl_name uniform_position_tex,
+ enum e_shader_gl_name uniform_light_array,
+ enum e_shader_gl_name uniform_light_index );
+
+void world_link_terrain_noise( world_instance *world, enum e_shader_gl_name uniform_sampler );
+
+#define WORLD_LINK_LIGHTING( WORLD, SHADER_NAME ) \
+ world_link_lighting( WORLD, \
+ k_shader_##SHADER_NAME, \
+ k_uniform_block_##SHADER_NAME##_ub_world_lighting, \
+ k_uniform_##SHADER_NAME##_g_world_depth, \
+ k_uniform_##SHADER_NAME##_uLightsArray, \
+ k_uniform_##SHADER_NAME##_uLightsIndex )
+
+#define WORLD_LINK_TERRAIN_NOISE( WORLD, SHADER_NAME ) \
+ world_link_terrain_noise( WORLD, k_uniform_##SHADER_NAME##_uTexGarbage )
+
void render_world_position( world_instance *world, vg_camera *cam );
void render_world_depth( world_instance *world, vg_camera *cam );
void render_world( world_instance *world, vg_camera *cam,
void render_world_gates( world_instance *world, vg_camera *cam, vg_framebuffer *target_fb );
void imgui_world_light_edit( ui_context *ctx, world_instance *world );
-#define WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( WORLD, SHADER ) \
- world_link_lighting_ub( WORLD, _shader_##SHADER.id ); \
- world_bind_position_texture( WORLD, _shader_##SHADER.id, \
- _uniform_##SHADER##_g_world_depth, 2 ); \
- world_bind_light_array( WORLD, _shader_##SHADER.id, \
- _uniform_##SHADER##_uLightsArray, 3 ); \
- world_bind_light_index( WORLD, _shader_##SHADER.id, \
- _uniform_##SHADER##_uLightsIndex, 4 );
-
+#endif
-#pragma once
-
-/*
- * Copyright (C) 2021-2024 Mt.ZERO Software - All Rights Reserved
- *
- * World routes
- */
-
-#include <time.h>
-#include "entity.h"
-#include "world_routes.h"
-#include "world_gate.h"
-#include "world_load.h"
-#include "network.h"
-
-#include "font.h"
-#include "gui.h"
-#include "network_msg.h"
-#include "network_common.h"
-
-#include "shaders/scene_route.h"
-#include "shaders/routeui.h"
-#include "ent_region.h"
-#include "scene_rigidbody.h"
-
void world_routes_clear( world_instance *world )
{
for( u32 i=0; i<af_arrcount( &world->ent_route ); i++ )
world_instance *world = &_world.main;
ent_route *route = af_arritm( &world->ent_route, route_index );
- const char *route_name = af_str( &world->meta.af, route->pstr_name);
+ const char *route_name = af_str( world->meta.packed_strings, route->pstr_name);
vg_info( "------- time lap %s -------\n", route_name );
double start_time = 0.0;
if( (route->flags & k_ent_route_flag_achieve_gold) && !(original_flags & k_ent_route_flag_achieve_gold) )
{
- gui_notify( "\xb3 Route completed in gold!", 5.0f, k_ui_yellow );
+ _gui_notify( "\xb3 Route completed in gold!", 5.0f, k_ui_yellow );
}
else if( (route->flags & k_ent_route_flag_achieve_silver) && !(original_flags & k_ent_route_flag_achieve_silver) )
{
- gui_notify( "\xb3 Route completed in silver!", 5.0f, k_ui_fg );
+ _gui_notify( "\xb3 Route completed in silver!", 5.0f, k_ui_fg );
}
struct ent_script_event event;
char mod_uid[ ADDON_UID_MAX ];
addon_make_uid( _world.main.addon_id, mod_uid );
- network_publish_laptime( mod_uid, af_str( &world->meta.af, route->pstr_name ), lap_time );
+ network_publish_laptime( mod_uid, af_str( world->meta.packed_strings, route->pstr_name ), lap_time );
}
route->valid_checkpoints = valid_sections+1;
}
-static
-void world_routes_place_curve( world_instance *world, ent_route *route,
- v4f h[3], v3f n0, v3f n2, scene_context *scene )
+static void world_routes_place_curve( world_instance *world, ent_route *route,
+ v4f h[3], v3f n0, v3f n2, scene_builder_context *builder )
{
- float t;
+ f32 t;
v3f p, pd;
int last_valid=0;
- float total_length = 0.0f,
- travel_length = 0.0;
+ f32 total_length = 0.0f,
+ travel_length = 0.0;
v3f last;
v3_copy( h[0], last );
- for( int it=0; it<128; it ++ ){
- t = (float)(it+1) * (1.0f/128.0f);
+ for( int it=0; it<128; it ++ )
+ {
+ t = (f32)(it+1) * (1.0f/128.0f);
eval_bezier3( h[0], h[1], h[2], t, p );
total_length += v3_dist( p, last );
v3_copy( p, last );
}
- float patch_size = 4.0f,
- patch_count = ceilf( total_length / patch_size );
+ f32 patch_size = 4.0f,
+ patch_count = ceilf( total_length / patch_size );
t = 0.0f;
v3_copy( h[0], last );
- for( int it=0; it<128; it ++ ){
- float const k_sample_dist = 0.0025f,
- k_line_width = 1.5f;
+ for( int it=0; it<128; it ++ )
+ {
+ f32 const k_sample_dist = 0.0025f,
+ k_line_width = 1.5f;
eval_bezier3( h[0], h[1], h[2], t, p );
eval_bezier3( h[0], h[1], h[2], t+k_sample_dist, pd );
travel_length += v3_dist( p, last );
- float mod = k_sample_dist / v3_dist( p, pd );
+ f32 mod = k_sample_dist / v3_dist( p, pd );
v3f v0,up, right;
v3_cross( up, v0, right );
v3_normalize( right );
- float cur_x = (1.0f-t)*h[0][3] + t*h[2][3];
+ f32 cur_x = (1.0f-t)*h[0][3] + t*h[2][3];
v3f sc, sa, sb, down;
v3_muladds( p, right, cur_x * k_line_width, sc );
int resa = ray_world( world, sa, down, &ha, k_material_flag_ghosts ),
resb = ray_world( world, sb, down, &hb, k_material_flag_ghosts );
- if( resa && resb ){
+ if( resa && resb )
+ {
struct world_surface *surfa = ray_hit_surface( world, &ha ),
*surfb = ray_hit_surface( world, &hb );
{
scene_vert va, vb;
- float gap = vg_fractf(cur_x*0.5f)*0.02f;
+ f32 gap = vg_fractf(cur_x*0.5f)*0.02f;
v3_muladds( ha.pos, up, 0.06f+gap, va.co );
v3_muladds( hb.pos, up, 0.06f+gap, vb.co );
scene_vert_pack_norm( &va, up, 0.0f );
scene_vert_pack_norm( &vb, up, 0.0f );
- float t1 = (travel_length / total_length) * patch_count;
+ f32 t1 = (travel_length / total_length) * patch_count;
va.uv[0] = t1;
va.uv[1] = 0.0f;
vb.uv[0] = t1;
vb.uv[1] = 1.0f;
- scene_push_vert( scene, &va );
- scene_push_vert( scene, &vb );
+ scene_builder_push_vert( builder, &va );
+ scene_builder_push_vert( builder, &vb );
- if( last_valid ){
+ if( last_valid )
+ {
/* Connect them with triangles */
- scene_push_tri( scene, (u32[3]){
- last_valid+0-2, last_valid+1-2, last_valid+2-2} );
- scene_push_tri( scene, (u32[3]){
- last_valid+1-2, last_valid+3-2, last_valid+2-2} );
+ scene_builder_push_tri( builder, (u32[3]){ last_valid+0-2, last_valid+1-2, last_valid+2-2} );
+ scene_builder_push_tri( builder, (u32[3]){ last_valid+1-2, last_valid+3-2, last_valid+2-2} );
}
- last_valid = scene->vertex_count;
+ last_valid = builder->scene.vertex_count;
}
else
last_valid = 0;
}
}
-static void world_routes_gen_meshes( world_instance *world, u32 route_id, scene_context *sc )
+static void world_routes_gen_meshes( world_instance *world, u32 route_id, scene_builder_context *builder )
{
ent_route *route = af_arritm( &world->ent_route, route_id );
u8 colour[4];
colour[1] = route->colour[1] * 255.0f;
colour[2] = route->colour[2] * 255.0f;
colour[3] = route->colour[3] * 255.0f;
-
u32 last_valid = 0;
for( int i=0; i<route->checkpoints_count; i++ )
v3_add( (v3f){0.0f,0.1f,0.0f}, start_gate->co[0], p[0] );
p[0][3] = start_gate->ref_count;
- p[0][3] -= (float)start_gate->route_count * 0.5f;
+ p[0][3] -= (f32)start_gate->route_count * 0.5f;
start_gate->ref_count ++;
if( !c0->path_count )
index->index );
v3f v0;
v3_sub( rn->co, both[j]->co[0], v0 );
- float d = v3_dot( v0, both[j]->to_world[2] );
+ f32 d = v3_dot( v0, both[j]->to_world[2] );
- v3_muladds( both[j]->co[0], both[j]->to_world[2], d,
- temp_alignments[j] );
+ v3_muladds( both[j]->co[0], both[j]->to_world[2], d, temp_alignments[j] );
v3_add( (v3f){0.0f,0.1f,0.0f}, temp_alignments[j], temp_alignments[j]);
}
v3_copy( rn->co, p[1] );
p[1][3] = rn->ref_count;
- p[1][3] -= (float)rn->ref_total * 0.5f;
+ p[1][3] -= (f32)rn->ref_total * 0.5f;
rn->ref_count ++;
if( j+1 < c0->path_count )
v3_lerp( p[1], rn->co, 0.5f, p[2] );
p[2][3] = rn->ref_count;
- p[2][3] -= (float)rn->ref_total * 0.5f;
+ p[2][3] -= (f32)rn->ref_total * 0.5f;
}
else
{
if( i == route->checkpoints_count-1)
p[2][3] -= 1.0f;
- p[2][3] -= (float)collector->route_count * 0.5f;
+ p[2][3] -= (f32)collector->route_count * 0.5f;
//collector->ref_count ++;
}
* --------------------------------------*/
v3f surf0, surf2, n0, n2;
- if( bh_closest_point( world->geo_bh, p[0], surf0, 5.0f ) == -1 )
+ if( bh_closest_point( &world->geometry_bh, p[0], surf0, 5.0f ) == -1 )
v3_add( (v3f){0.0f,-0.1f,0.0f}, p[0], surf0 );
- if( bh_closest_point( world->geo_bh, p[2], surf2, 5.0f ) == -1 )
+ if( bh_closest_point( &world->geometry_bh, p[2], surf2, 5.0f ) == -1 )
v3_add( (v3f){0.0f,-0.1f,0.0f}, p[2], surf2 );
v3_sub( surf0, p[0], n0 );
v3_normalize( n0 );
v3_normalize( n2 );
- world_routes_place_curve( world, route, p, n0, n2, sc );
+ world_routes_place_curve( world, route, p, n0, n2, builder );
/* --- */
v4_copy( p[2], p[0] );
}
}
- scene_copy_slice( sc, &route->sm );
+ scene_builder_get_submesh( builder, &route->sm );
}
struct world_surface *world_tri_index_surface( world_instance *world,
*/
void world_gen_routes_generate( world_instance *world )
{
- THREAD_1;
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
vg_info( "Generating route meshes\n" );
- vg_async_task *task = scene_alloc_async( &world->scene_lines, &world->mesh_route_lines, 200000, 300000 );
for( u32 i=0; i<af_arrcount(&world->ent_gate); i++ )
{
rn->ref_total = 0;
}
- for( u32 k=0; k<af_arrcount(&world->ent_route); k++ ){
+ for( u32 k=0; k<af_arrcount(&world->ent_route); k++ )
+ {
ent_route *route = af_arritm( &world->ent_route, k );
-
- for( int i=0; i<route->checkpoints_count; i++ ){
+ for( int i=0; i<route->checkpoints_count; i++ )
+ {
int i0 = route->checkpoints_start+i,
i1 = route->checkpoints_start+((i+1)%route->checkpoints_count);
if( !c0->path_count )
continue;
- for( int j=0; j<c0->path_count; j ++ ){
- ent_path_index *index = af_arritm( &world->ent_path_index,
- c0->path_start+j );
- ent_route_node *rn = af_arritm( &world->ent_route_node,
- index->index );
+ for( int j=0; j<c0->path_count; j ++ )
+ {
+ ent_path_index *index = af_arritm( &world->ent_path_index, c0->path_start+j );
+ ent_route_node *rn = af_arritm( &world->ent_route_node, index->index );
rn->ref_total ++;
}
}
}
+ u32 temp_frame = _vg_start_temp_frame();
+ scene_builder_context builder;
+ scene_builder_init( &builder, 200000, 300000, _vg_temp_stack() );
for( u32 i=0; i<af_arrcount(&world->ent_route); i++ )
- world_routes_gen_meshes( world, i, &world->scene_lines );
+ world_routes_gen_meshes( world, i, &builder );
+ scene_builder_upload_async( &builder, &world->line_scene_mesh );
+ _vg_end_temp_frame( temp_frame );
- vg_async_task_dispatch( task, async_scene_upload );
world_routes_clear( world );
}
route->flags |= k_ent_route_flag_out_of_zone;
route->anon.official_track_id = 0xffffffff;
- const char *route_name = af_str( &world->meta.af, route->pstr_name );
+ const char *route_name = af_str( world->meta.packed_strings, route->pstr_name );
for( u32 j=0; j<VG_ARRAY_LEN(track_infos); j ++ )
{
if( !strcmp( track_infos[j].name, route_name ))
world_routes_clear( world );
}
-void world_routes_recv_scoreboard( world_instance *world, vg_msg *body, u32 route_id, enum request_status status )
+void world_routes_recv_scoreboard( world_instance *world, vg_kvs *kvs, u32 route_id, enum request_status status )
{
+ // FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////
+#if 0
if( route_id >= af_arrcount( &world->ent_route ) )
{
vg_error( "Scoreboard route_id out of range (%u)\n", route_id );
memcpy( board->data, body->buf, body->max );
board->data_len = body->max;
+#endif
}
/*
* -----------------------------------------------------------------------------
*/
-void world_routes_init(void)
+VG_API void _world_routes_init(void)
{
_world.current_run_version = 200;
_world.time = 300.0;
_null.inv_mass = 0.0f;
m3x3_zero( _null.iI );
- for( u32 i=0; i<world_render.text_particle_count; i++ ){
+ for( u32 i=0; i<world_render.text_particle_count; i++ )
+ {
struct text_particle *particle = &world_render.text_particles[i];
-
- if( rb_global_has_space() ){
+ if( rb_global_has_space() )
+ {
rb_ct *buf = rb_global_buffer();
-
- int l = rb_sphere__scene( particle->rb.to_world,
- particle->radius,
- NULL, world->geo_bh, buf,
+ i32 l = rb_sphere__scene( particle->rb.to_world, particle->radius, NULL, &world->geometry_bh, buf,
k_material_flag_ghosts );
-
- for( int j=0; j<l; j++ ){
+ for( int j=0; j<l; j++ )
+ {
buf[j].rba = &particle->rb;
buf[j].rbb = &_null;
}
-
rb_contact_count += l;
}
}
- rb_presolve_contacts( rb_contact_buffer,
- vg.time_fixed_delta, rb_contact_count );
+ rb_presolve_contacts( rb_contact_buffer, vg.time_fixed_delta, rb_contact_count );
- for( int i=0; i<rb_contact_count; i++ ){
+ for( int i=0; i<rb_contact_count; i++ )
rb_contact_restitution( rb_contact_buffer+i, vg_randf64(&vg.rand) );
- }
- for( int i=0; i<6; i++ ){
+ for( int i=0; i<6; i++ )
rb_solve_contacts( rb_contact_buffer, rb_contact_count );
- }
- for( u32 i=0; i<world_render.text_particle_count; i++ ){
+ for( u32 i=0; i<world_render.text_particle_count; i++ )
+ {
struct text_particle *particle = &world_render.text_particles[i];
rb_iter( &particle->rb );
}
- for( u32 i=0; i<world_render.text_particle_count; i++ ){
+ for( u32 i=0; i<world_render.text_particle_count; i++ )
+ {
struct text_particle *particle = &world_render.text_particles[i];
rb_update_matrices( &particle->rb );
}
}
-void bind_terrain_noise(void);
-void world_bind_light_array( world_instance *world,
- GLuint shader, GLuint location,
- int slot );
-void world_bind_light_index( world_instance *world,
- GLuint shader, GLuint location,
- int slot );
-
void world_routes_update_timer_texts( world_instance *world )
{
world_render.timer_text_count = 0;
}
}
- float h0 = 0.8f,
- h1 = 1.2f,
- depth = 0.4f,
- size = 0.4f;
+ f32 h0 = 0.8f,
+ h1 = 1.2f,
+ depth = 0.4f,
+ size = 0.4f;
struct timer_text *text = &world_render.timer_texts[ world_render.timer_text_count ++ ];
text->gate = gate;
double lap_time = _world.time - route->timing_base,
time_centiseconds = lap_time * 100.0;
- if( time_centiseconds > (float)0xfffe ) time_centiseconds = 0.0;
+ if( time_centiseconds > (f32)0xfffe ) time_centiseconds = 0.0;
u16 centiseconds = time_centiseconds,
seconds = centiseconds / 100,
if( minutes )
{
- vg_strcati32r( &str, minutes, 1, ' ' );
+ vg_strcati64r( &str, minutes, 10, 1, ' ' );
vg_strcatch( &str, ':' );
}
if( seconds >= 10 || minutes )
{
- vg_strcati32r( &str, seconds, 2, '0' );
+ vg_strcati64r( &str, seconds, 10, 2, '0' );
}
else
{
- vg_strcati32r( &str, seconds, 1, '0' );
+ vg_strcati64r( &str, seconds, 10, 1, '0' );
}
vg_strcatch( &str, '.' );
- vg_strcati32r( &str, centiseconds, 1, '0' );
+ vg_strcati64r( &str, centiseconds, 10, 1, '0' );
}
else
{
- vg_strcati32r( &str, route->valid_checkpoints, 1, ' ' );
+ vg_strcati64r( &str, route->valid_checkpoints, 10, 1, ' ' );
vg_strcatch( &str, '/' );
- vg_strcati32r( &str, route->checkpoints_count + 1, 1, ' ' );
+ vg_strcati64r( &str, route->checkpoints_count + 1, 10, 1, ' ' );
}
gui_font3d.font = &gui.font;
- float align_r = font3d_string_width( 0, text->text );
- align_r *= size;
+ f32 align_r = font3d_string_width( 0, text->text );
+ align_r *= size;
v3f positions[] = {
{ -0.92f, h0, depth },
ent_gate_get_mdl_mtx( gate, mmdl );
m3x3_copy( mmdl, text->transform );
- float ratio = v3_length(text->transform[0]) / v3_length(text->transform[1]);
+ f32 ratio = v3_length(text->transform[0]) / v3_length(text->transform[1]);
m3x3_scale( text->transform, (v3f){ size, size*ratio, 0.1f } );
m4x3_mulv( mmdl, positions[j], text->transform[3] );
v3_zero( offset );
v4f colour;
- float brightness = 0.3f + world->ub_lighting.g_day_phase;
+ f32 brightness = 0.3f + world_render.ub_lighting.g_day_phase;
v3_muls( text->route->colour, brightness, colour );
colour[3] = 1.0f-text->route->factive;
m4x3_mul( world_mmdl, mmdl, mmdl );
shader_model_gate_uMdl( mmdl );
- mdl_draw_submesh( &world_gates.sm_marker[j] );
+ vg_model_draw_submesh( &_world_gates.sm_marker[j] );
break;
}
}
int viewing_from_gate, int viewing_from_hub )
{
shader_scene_route_use();
- shader_scene_route_uTexGarbage(0);
- world_link_lighting_ub( host_world, _shader_scene_route.id );
- world_bind_position_texture( host_world, _shader_scene_route.id,
- _uniform_scene_route_g_world_depth, 2 );
- world_bind_light_array( host_world, _shader_scene_route.id,
- _uniform_scene_route_uLightsArray, 3 );
- world_bind_light_index( host_world, _shader_scene_route.id,
- _uniform_scene_route_uLightsIndex, 4 );
- bind_terrain_noise();
+ world_link_terrain_noise( host_world, k_uniform_scene_route_uTexGarbage );
+ WORLD_LINK_LIGHTING( host_world, scene_route );
shader_scene_route_uPv( cam->mtx.pv );
shader_scene_route_uCamera( cam->transform[3] );
- mesh_bind( &world->mesh_route_lines );
-
+ scene_mesh_bind( &world->line_scene_mesh );
for( u32 i=0; i<af_arrcount(&world->ent_route); i++ )
{
ent_route *route = af_arritm( &world->ent_route, i );
-
f32 t = viewing_from_hub? 1.0f: route->factive;
v4f colour;
colour[3] = t*0.2f;
shader_scene_route_uColour( colour );
- mdl_draw_submesh( &route->sm );
+ vg_model_draw_submesh( &route->sm );
}
/* timers
* ---------------------------------------------------- */
if( !viewing_from_gate && !viewing_from_hub )
{
- font3d_bind( &gui.font, k_font_shader_default, 0, world, cam );
+ font3d_bind( &gui.font, k_font_shader_default, 0, cam );
for( u32 i=0; i<world_render.timer_text_count; i++ )
{
struct timer_text *text = &world_render.timer_texts[i];
v4f colour;
- float brightness = 0.3f + world->ub_lighting.g_day_phase;
+ f32 brightness = 0.3f + world_render.ub_lighting.g_day_phase;
v3_muls( text->route->colour, brightness, colour );
colour[3] = 1.0f-text->route->factive;
m4x3_mul( model, particle->mlocal, particle->mdl );
shader_model_font_uMdl( particle->mdl );
shader_model_font_uColour( particle->colour );
-
- mesh_drawn( particle->glyph->indice_start, particle->glyph->indice_count );
+ vg_model_draw_elements( particle->glyph->indice_start, particle->glyph->indice_count );
}
}
shader_model_gate_uPv( cam->mtx.pv );
shader_model_gate_uCam( cam->pos );
shader_model_gate_uTime( vg.time*0.25f );
- shader_model_gate_uInvRes( (v2f){
- 1.0f / (float)vg.window_x,
- 1.0f / (float)vg.window_y });
-
- mesh_bind( &world_gates.mesh );
+ shader_model_gate_uInvRes( (v2f){ 1.0f/(f32)_vg_window.w, 1.0f/(f32)_vg_window.h });
+ vg_model_bind_mesh( &_world_gates.model );
/* skip writing into the motion vectors for this */
glDrawBuffers( 1, (GLenum[]){ GL_COLOR_ATTACHMENT0 } );
}
}
}
- else{
- for( u32 i=0; i<af_arrcount(&world->ent_route); i++ ){
+ else
+ {
+ for( u32 i=0; i<af_arrcount(&world->ent_route); i++ )
+ {
ent_route *route = af_arritm( &world->ent_route, i );
-
- if( route->active_checkpoint != 0xffff ){
+ if( route->active_checkpoint != 0xffff )
+ {
v4f colour;
- float brightness = 0.3f + world->ub_lighting.g_day_phase;
+ f32 brightness = 0.3f + world_render.ub_lighting.g_day_phase;
v3_muls( route->colour, brightness, colour );
colour[3] = 1.0f-route->factive;
-/*
- * Copyright (C) 2021-2025 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
+#if defined( SR_IMPLEMENTATION )
+# include "src/world_routes.c"
+#else
-#pragma once
-#include "vg/vg_camera.h"
-#include "vg/vg_msg.h"
-#include "world.h"
-#include "network_msg.h"
+VG_API void _world_routes_init(void);
-void world_routes_init(void);
void world_routes_fracture( world_instance *world, ent_gate *gate, v3f imp_co, v3f imp_v );
void world_routes_activate_entry_gate( world_instance *world, ent_gate *rg );
void render_world_routes( world_instance *world,
void world_routes_update( world_instance *world );
void world_routes_fixedupdate( world_instance *world );
void world_routes_clear( world_instance *world );
-void world_routes_recv_scoreboard( world_instance *world,
- vg_msg *body, u32 route_id,
- enum request_status status );
+void world_routes_recv_scoreboard( world_instance *world, vg_kvs *kvs, u32 route_id, enum request_status status );
+
+#endif
-#include "skaterift.h"
-#include "world_routes_ui.h"
-#include "world_routes.h"
-#include "player.h"
-
static u32 v4_rgba( v4f colour )
{
u32 r = vg_minf(1.0f,colour[0])*255.0f,
else
vg_strcatch( &str, '-' );
- vg_strcati32( &str, s );
+ vg_strcati64( &str, s, 10 );
vg_strcatch( &str, '.' );
- vg_strcati32( &str, ds );
+ vg_strcati64( &str, ds, 10 );
ui_text( ctx, rect, buf, 1, k_ui_align_middle_center, 0 );
}
-#pragma once
-#include "world_routes.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/world_routes_ui.c"
+#else
struct route_ui{};
void world_routes_imgui( ui_context *ctx, world_instance *world );
+
+#endif
-#ifndef SFD_C
-#define SFD_C
-
-#include "world_sfd.h"
-#include "shaders/scene_scoretext.h"
-#include "shaders/scene_vertex_blend.h"
-#include "network.h"
-#include "entity.h"
-#include "network_common.h"
-#include "world_routes.h"
-
struct world_sfd world_sfd;
static f32 sfd_encode_glyph( char c ){
{
board = &world->leaderboard_cache[ world_sfd.active_route_board ];
ent_route *route = af_arritm( &world->ent_route, world_sfd.active_route_board );
- title = af_str( &world->meta.af, route->pstr_name );
+ title = af_str( world->meta.packed_strings, route->pstr_name );
}
for( u32 i=0; i<13; i++ )
vg_str s;
vg_strnull( &s, buf, 32 );
vg_strcat( &s, "Error: " );
- vg_strcati32( &s, board->status );
+ vg_strcati64( &s, board->status, 10 );
sfd_encode( (v2i){-1,4}, buf, k_world_sfd_center );
return;
}
+ // FIXME FIXME
+ sfd_encode( (v2i){-1,0}, "FIX ME!!!!!", k_world_sfd_right );
+#if 0
vg_msg body;
vg_msg_init( &body, board->data, board->data_len );
char buf[100];
vg_str str;
vg_strnull( &str, buf, 100 );
- vg_strcati32( &str, l );
+ vg_strcati64( &str, l, 10 );
vg_strcat( &str, " " );
if( username )
seconds %= 60;
minutes %= 60;
if( minutes > 9 ) vg_strcat( &str, "?" );
- else vg_strcati32( &str, minutes );
+ else vg_strcati64( &str, minutes, 10 );
vg_strcat( &str, ":" );
- vg_strcati32r( &str, seconds, 2, '0' );
+ vg_strcati64r( &str, seconds, 10, 2, '0' );
vg_strcat( &str, "." );
- vg_strcati32r( &str, centiseconds, 2, '0' );
+ vg_strcati64r( &str, centiseconds, 10, 2, '0' );
sfd_encode( (v2i){-1,l}, str.buffer, k_world_sfd_right );
l ++;
{
sfd_encode( (v2i){-1,4}, "No records", k_world_sfd_center );
}
+#endif
}
void world_sfd_update( world_instance *world, v3f pos )
char mod_uid[ ADDON_UID_MAX ];
addon_make_uid( _world.main.addon_id, mod_uid );
- network_request_scoreboard( mod_uid, af_str( &world->meta.af, route->pstr_name ),
+ network_request_scoreboard( mod_uid, af_str( world->meta.packed_strings, route->pstr_name ),
NETWORK_LEADERBOARD_ALLTIME_AND_CURRENT_WEEK, closest );
}
}
void bind_terrain_noise(void);
void sfd_render( world_instance *world, vg_camera *cam, m4x3f transform )
{
+#if 0
mesh_bind( &world_sfd.mesh_display );
shader_scene_scoretext_use();
shader_scene_scoretext_uTexMain(1);
- WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_scoretext );
+ WORLD_LINK_LIGHTING( world, scene_scoretext );
bind_terrain_noise();
shader_scene_vertex_blend_use();
shader_scene_vertex_blend_uTexGarbage(0);
shader_scene_vertex_blend_uTexGradients(1);
- WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_vertex_blend );
+ WORLD_LINK_LIGHTING( world, scene_vertex_blend );
bind_terrain_noise();
- glActiveTexture( GL_TEXTURE1 );
- glBindTexture( GL_TEXTURE_2D, world_sfd.tex_scoretex );
+
+ VG_ASSERT(0);
+ // FIXME FIXME FIXME
+ // glActiveTexture( GL_TEXTURE1 );
+ // glBindTexture( GL_TEXTURE_2D, world_sfd.tex_scoretex );
shader_scene_vertex_blend_uPv( cam->mtx.pv );
shader_scene_vertex_blend_uPvmPrev( pvm_prev );
shader_scene_vertex_blend_uCamera( cam->transform[3] );
mesh_bind( &world_sfd.mesh_base );
- mdl_draw_submesh( &world_sfd.sm_base );
+ vg_model_draw_submesh( &world_sfd.sm_base );
+#endif
}
-void world_sfd_init(void)
+static void _world_sfd_load_content( void *_, vg_async_info *async )
{
- THREAD_1;
- vg_info( "world_sfd_init\n" );
- vg_stack_clear( &vg.scratch );
+ // FIXME FIXME FIXME
+ VG_ASSERT( 0 );
+#if 0
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+
+ u32 temp_frame = _vg_start_temp_frame();
+ vg_model scoreboard_mdl;
+ VG_ASSERT( vg_model_load( &scoreboard_mdl, VG_MODEL_ENGINE_PROCEDURAL_SOURCE, "models/rs_scoretext.mdl",
+ _vg_temp_stack() ));
+
+
+ _vg_end_temp_frame( temp_frame );
+
mdl_context mscoreboard;
- mdl_open( &mscoreboard, "models/rs_scoretext.mdl", &vg.scratch );
+ mdl_open( &mscoreboard, , &vg.scratch );
mdl_load_metadata_block( &mscoreboard, &vg.scratch );
mdl_async_load_glmesh( &mscoreboard, &world_sfd.mesh_base, NULL );
-
mdl_load_mesh_block( &mscoreboard, &vg.scratch );
scene_context *scene = &world_sfd.scene;
{
scene_vert *vert = &scene->arrvertices[ vert_start+j ];
- float const k_glyph_uvw = 1.0f/64.0f;
+ f32 const k_glyph_uvw = 1.0f/64.0f;
vert->uv[0] -= k_glyph_uvw * (float)(i-1);
vert->norm[3] = i*42;
}
}
- vg_async_task_dispatch( task, async_scene_upload );
- vg_tex2d_load_qoi_async_file( "textures/scoretext.qoi", VG_TEX2D_CLAMP|VG_TEX2D_NEAREST, &world_sfd.tex_scoretex );
mdl_close( &mscoreboard );
+#endif
+}
- int w = 27,
+VG_API void _world_sfd_init(void)
+{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_world_sfd_load_content );
+
+ i32 w = 27,
h = 13;
world_sfd.w = w;
world_sfd.h = h;
- world_sfd.buffer = vg_stack_allocate( &vg.rtmem, 2*w*h*sizeof(f32), 8, "SFD Buffer" );
+ world_sfd.buffer = vg_stack_allocate( VG_STACK_USE_HEAP, 2*w*h*sizeof(f32), 8, "SFD Buffer" );
- for( int i=0; i<w*h*2; i++ )
+ for( i32 i=0; i<w*h*2; i++ )
world_sfd.buffer[i] = 0.0f;
}
-
-#endif /* WORLD_SFD_C */
-/*
- * Copyright (C) 2021-2024 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-#pragma once
-#include "world.h"
-#include "world_routes.h"
-#include "scene.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/world_sfd.c"
+#else
struct world_sfd
{
- GLuint tex_scoretex;
-
- glmesh mesh_base, mesh_display;
mdl_submesh sm_base;
u32 active_route_board;
- scene_context scene;
//u32 view_weekly;
u32 run_selecteion;
}
extern world_sfd;
-void world_sfd_init(void);
+VG_API void _world_sfd_init(void);
enum world_sfd_align {
k_world_sfd_left,
void world_sfd_update( world_instance *world, v3f pos );
void sfd_render( world_instance *world, vg_camera *cam, m4x3f transform );
void world_sfd_compile_active_scores(void);
+
+#endif
-#include "world_volumes.h"
-
struct _world_volumes _world_volumes;
void world_volumes_update( world_instance *world, v3f pos )
{
if( world_clear_event( k_world_event_interact ) )
{
- gui_helper_reset( k_gui_helper_mode_clear );
+ _gui_helper_reset( k_gui_helper_mode_clear );
}
}
}
bh_iter_init_range( 0, &it, pos, radius );
i32 idx;
- while( bh_next( world->entity_bh, &it, &idx ) )
+ while( bh_next( &world->entity_bh, &it, &idx ) )
{
u32 id = world->entity_list[ idx ],
type = mdl_entity_id_type( id ),
{
if( world_set_event( k_world_event_interact ) )
{
- gui_helper_reset( k_gui_helper_mode_black_bars );
+ _gui_helper_reset( k_gui_helper_mode_black_bars );
vg_str text;
- if( gui_new_helper( input_button_list[k_srbind_maccept], &text ))
- vg_strcat( &text, af_str( &world->meta.af, volume->interact.pstr_text ) );
+ if( _gui_new_helper( input_button_list[k_srbind_maccept], &text ))
+ vg_strcat( &text, af_str( world->meta.packed_strings, volume->interact.pstr_text ) );
_world_volumes.active_volume_interact = id;
}
}
if( world_clear_event( k_world_event_interact ) )
{
_world_volumes.active_volume_interact = 0;
- gui_helper_reset( k_gui_helper_mode_clear );
+ _gui_helper_reset( k_gui_helper_mode_clear );
}
}
else if( button_down( k_srbind_maccept ) && (_cutscene.state == k_cutscene_state_none)
if( world_clear_event( k_world_event_interact ) )
{
_world_volumes.active_volume_interact = 0;
- gui_helper_reset( k_gui_helper_mode_clear );
+ _gui_helper_reset( k_gui_helper_mode_clear );
}
}
-#pragma once
-#include "world.h"
-#include "vg/vg_bvh.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/world_volumes.c"
+#else
struct _world_volumes
{
void world_volumes_update( world_instance *world, v3f pos );
void world_volumes_start( world_instance *world );
+
+#endif
-/*
- * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#include "world_water.h"
-#include "world_render.h"
-#include "render.h"
-#include "shaders/scene_water.h"
-#include "shaders/scene_water_fast.h"
-#include "scene.h"
-#include "player.h"
-#include "player_walk.h"
-#include "player_dead.h"
-
struct world_water world_water;
-void world_water_init(void)
+static void _world_water_load_content( void *_, vg_async_info *async )
{
- vg_info( "world_water_init\n" );
-
- vg_tex2d_load_qoi_async_file( "textures/water_surf.qoi",
- VG_TEX2D_LINEAR|VG_TEX2D_REPEAT,
- &world_water.tex_water_surf );
+ _vg_tex_load( &world_water.tex_water_surf, "textures/water_surf.qoi", VG_TEX_LINEAR|VG_TEX_REPEAT );
+}
- vg_success( "done\n" );
+VG_API void _world_water_init(void)
+{
+ VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+ _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_world_water_load_content );
}
void water_set_surface( world_instance *world, float height )
v4_copy( (v4f){ 0.0f, 1.0f, 0.0f, height }, world->water.plane );
}
-void world_link_lighting_ub( world_instance *world, GLuint shader );
-void world_bind_position_texture( world_instance *world,
- GLuint shader, GLuint location,
- int slot );
-void world_bind_light_array( world_instance *world,
- GLuint shader, GLuint location,
- int slot );
-void world_bind_light_index( world_instance *world,
- GLuint shader, GLuint location,
- int slot );
-
/*
* Does not write motion vectors
*/
vg_framebuffer_bind_texture( _vg_render.fb_water_reflection, 0, 0 );
shader_scene_water_uTexMain( 0 );
- glActiveTexture( GL_TEXTURE1 );
- glBindTexture( GL_TEXTURE_2D, world_water.tex_water_surf );
+ vg_tex_bind( GL_TEXTURE_2D, &world_water.tex_water_surf, 1 );
shader_scene_water_uTexDudv( 1 );
- shader_scene_water_uInvRes( (v2f){
- 1.0f / (float)vg.window_x,
- 1.0f / (float)vg.window_y });
-
- WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_water );
+ shader_scene_water_uInvRes( (v2f){ 1.0f / (f32)_vg_window.w, 1.0f / (f32)_vg_window.h });
+ WORLD_LINK_LIGHTING( world, scene_water );
vg_framebuffer_bind_texture( _vg_render.fb_water_beneath, 0, 5 );
shader_scene_water_uTexBack( 5 );
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glBlendEquation(GL_FUNC_ADD);
- mesh_bind( &world->mesh_no_collide );
-
+ scene_mesh_bind( &world->transparent_scene_mesh );
for( int i=0; i<world->surface_count; i++ )
{
struct world_surface *mat = &world->surfaces[i];
- struct shader_props_water *props = mat->info.props.compiled;
if( mat->info.shader == k_shader_water )
{
- shader_scene_water_uShoreColour( props->shore_colour );
- shader_scene_water_uOceanColour( props->deep_colour );
- shader_scene_water_uFresnel( props->fresnel );
- shader_scene_water_uWaterScale( props->water_sale );
- shader_scene_water_uWaveSpeed( props->wave_speed );
-
- mdl_draw_submesh( &mat->sm_no_collide );
+ VG_ASSERT(i);
+ union shader_props *props = &world->meta.shader_props[i-1];
+ shader_scene_water_uShoreColour( props->water.shore_colour );
+ shader_scene_water_uOceanColour( props->water.deep_colour );
+ shader_scene_water_uFresnel( props->water.fresnel );
+ shader_scene_water_uWaterScale( props->water.water_sale );
+ shader_scene_water_uWaveSpeed( props->water.wave_speed );
+ vg_model_draw_submesh( &mat->sm_no_collide );
}
}
{
shader_scene_water_fast_use();
- glActiveTexture( GL_TEXTURE1 );
- glBindTexture( GL_TEXTURE_2D, world_water.tex_water_surf );
+ vg_tex_bind( GL_TEXTURE_2D, &world_water.tex_water_surf, 1 );
shader_scene_water_fast_uTexDudv( 1 );
shader_scene_water_fast_uTime( _world.time );
shader_scene_water_fast_uCamera( cam->transform[3] );
shader_scene_water_fast_uSurfaceY( world->water.height );
-
- WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_water_fast );
+ WORLD_LINK_LIGHTING( world, scene_water_fast );
m4x3f full;
m4x3_identity( full );
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glBlendEquation(GL_FUNC_ADD);
- mesh_bind( &world->mesh_no_collide );
-
+ scene_mesh_bind( &world->transparent_scene_mesh );
for( int i=0; i<world->surface_count; i++ )
{
struct world_surface *mat = &world->surfaces[i];
- struct shader_props_water *props = mat->info.props.compiled;
if( mat->info.shader == k_shader_water )
{
- shader_scene_water_fast_uShoreColour( props->shore_colour );
- shader_scene_water_fast_uOceanColour( props->deep_colour );
+ VG_ASSERT(i);
+ union shader_props *props = &world->meta.shader_props[i-1];
+ shader_scene_water_fast_uShoreColour( props->water.shore_colour );
+ shader_scene_water_fast_uOceanColour( props->water.deep_colour );
- mdl_draw_submesh( &mat->sm_no_collide );
+ vg_model_draw_submesh( &mat->sm_no_collide );
}
}
{
vg_str str;
struct gui_helper *helper;
- if( (helper = gui_new_helper(input_button_list[k_srbind_reset], &str)) )
+ if( (helper = _gui_new_helper(input_button_list[k_srbind_reset], &str)) )
{
vg_strcat( &str, "Respawn" );
}
entity_event_result ent_water_event( ent_event *event )
{
world_instance *world = &_world.main;
- if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "drown" ) )
+ if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "drown" ) )
{
world_water_drown();
return k_entity_event_result_OK;
-/*
- * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
+#if defined( SR_IMPLEMENTATION )
+# include "src/world_water.c"
+#else
-#pragma once
-#include "world.h"
-
-struct world_water{
- GLuint tex_water_surf;
+struct world_water
+{
+ vg_tex tex_water_surf;
}
extern world_water;
-void world_water_init(void);
+
+VG_API void _world_water_init(void);
void water_set_surface( world_instance *world, f32 height );
void render_water_texture( world_instance *world, vg_camera *cam );
void render_water_surface( world_instance *world, vg_camera *cam );
entity_event_result ent_water_event( ent_event *event );
bool world_water_player_safe( world_instance *world, f32 allowance );
+
+#endif