From cae97e278f176f56a91127ee4c7c3c4a77b56678 Mon Sep 17 00:00:00 2001 From: hgn Date: Mon, 24 Mar 2025 18:28:14 +0000 Subject: [PATCH] Add compass --- build.c | 1 + content_skaterift/models/rs_compass.mdl | Bin 0 -> 24328 bytes shaders/compass.fs | 12 ++ shaders/compass.vs | 17 +++ src/compass.c | 171 ++++++++++++++++++++++++ src/compass.h | 27 ++++ src/gui.h | 70 +++++----- src/model.c | 19 +-- src/model.h | 4 +- src/player_glide.c | 3 +- src/render.c | 15 +++ src/render.h | 3 +- src/skaterift.c | 9 ++ src/world_gate.c | 10 +- src/world_render.c | 4 +- src/world_sfd.c | 19 +-- 16 files changed, 309 insertions(+), 75 deletions(-) create mode 100644 content_skaterift/models/rs_compass.mdl create mode 100644 shaders/compass.fs create mode 100644 shaders/compass.vs create mode 100644 src/compass.c create mode 100644 src/compass.h diff --git a/build.c b/build.c index 634262a..c35905b 100644 --- a/build.c +++ b/build.c @@ -192,6 +192,7 @@ void build_shaders(void){ _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" ); diff --git a/content_skaterift/models/rs_compass.mdl b/content_skaterift/models/rs_compass.mdl new file mode 100644 index 0000000000000000000000000000000000000000..23ef7baf00d1bc4f7cf570eda963c817c85356c0 GIT binary patch literal 24328 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 1.0f ) + return 0; + + compass_project( base_projection, a, height ); + return 1; +} + +static bool compass_co( m3x3f base_projection, v3f co, f32 height ) +{ + v3f v0; + v3_sub( co, g_render.cam.pos, v0 ); + v0[1] = 0.0f; + v3_normalize( v0 ); + f32 a = atan2f( v0[0], -v0[2] ); + return compass_a( base_projection, a, height ); +} + +void compass_render_texture(void) +{ + if( skaterift.activity == k_skaterift_replay ) + return; + + vg_framebuffer_bind( g_render.fb_compass, 1.0f ); + + glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); + glClear( GL_COLOR_BUFFER_BIT ); + glDisable( GL_DEPTH_TEST ); + glDisable( GL_BLEND ); + + m3x3f projection; + m3x3_identity( projection ); + projection[0][0] = 512.0f/400.0f; + projection[1][1] = 512.0f/50.0f; + + mdl_context *mdl = &_compass.mdl; + mesh_bind( &mdl->mesh ); + + shader_compass_use(); + shader_compass_uTexMain( 0 ); + glActiveTexture( GL_TEXTURE0 ); + glBindTexture( GL_TEXTURE_2D, mdl->textures[0].glname ); + + /* base */ + shader_compass_uColour( (v4f){ 1,1,1,0.4 } ); + compass_project( projection, 0,0 ); + mdl_draw_submesh( &mdl->submeshes[ _compass.sm_comp_bar ] ); + + if( compass_a( projection, 0.0f, 0 ) ) + mdl_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 ] ); + + if( compass_a( projection, VG_PIf, 0 ) ) + mdl_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 ] ); + + 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 ] ); + } + } + + /* TODO: Players and friends */ + shader_compass_uColour( (v4f){ 1,1,1,1 } ); + + world_instance *world = &_world.main; + + /* story markers */ + for( u32 i=0; ient_marker); i ++ ) + { + ent_marker *marker = af_arritm( &world->ent_marker, i ); + if( marker->flags & k_ent_marker_flag_hidden ) + continue; + + 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 ] ); + } + } + + /* gates n shit */ + f32 t = (_world.time - _world.last_gate_hit_time) / 30.0f; + f32 alpha = vg_clampf( 2.0f-t, 0.0f, 1.0f ); + if( alpha > 0.001f ) + { + for( u32 i=0; ient_route); i++ ) + { + ent_route *route = af_arritm( &world->ent_route, i ); + + if( route->active_checkpoint != 0xffff ) + { + v4f colour; + v3_copy( route->colour, colour ); + + colour[3] = alpha; + shader_compass_uColour( colour ); + + u32 next = route->active_checkpoint+1; + next = next % route->checkpoints_count; + next += route->checkpoints_start; + + ent_checkpoint *cp = af_arritm( &world->ent_checkpoint, next ); + 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 ] ); + } + } + } +} + +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_flush( ctx, k_ui_shader_colour, NULL ); + vg_ui.colour[3] = _compass.alpha; + ui_image( ctx, rect, &g_render.fb_compass->attachments[0].id ); + vg_ui.colour[3] = 1.0f; +} diff --git a/src/compass.h b/src/compass.h new file mode 100644 index 0000000..1d9c807 --- /dev/null +++ b/src/compass.h @@ -0,0 +1,27 @@ +#pragma once +#include "vg/vg_framebuffer.h" + +struct _compass +{ + mdl_context mdl; + + i32 sm_comp, + sm_comp_bar, + sm_comp_dot, + sm_comp_e, + sm_comp_fade, + sm_comp_friend, + sm_comp_gate, + sm_comp_n, + sm_comp_notify, + sm_comp_person, + sm_comp_s, + sm_comp_w; + + f32 alpha; +} +extern _compass; + +void compass_init(void); +void compass_render_texture(void); +void compass_render_imgui( ui_context *ctx ); diff --git a/src/gui.h b/src/gui.h index 93a4613..468cdd5 100644 --- a/src/gui.h +++ b/src/gui.h @@ -80,7 +80,7 @@ struct GLuint icons_texture; glmesh icons_mesh; - mdl_submesh *icons[ k_gui_icon_count ]; + i32 icon_submeshes[ k_gui_icon_count ]; } static gui = {.cur_icon_colour = {1.0f,1.0f,1.0f,1.0f},.colour_changed=1}; @@ -138,15 +138,16 @@ static void gui_render_icons(void) glBindTexture( GL_TEXTURE_2D, gui.icons_texture ); shader_model_font_uTexMain( 0 ); - for( u32 i=0; icolour_changed ) shader_model_font_uColour( call->colour ); - shader_model_font_uOffset( call->location ); - mdl_submesh *sm = gui.icons[ call->icon ]; + i32 index = gui.icon_submeshes[ call->icon ]; + mdl_submesh *sm = &gui.model_icons.submeshes[ index ]; if( sm ) mdl_draw_submesh( sm ); } @@ -283,16 +284,6 @@ static void gui_icon_setcolour( v4f colour ){ v4_copy( colour, gui.cur_icon_colour ); } -static mdl_submesh *gui_find_icon( const char *name ) -{ - mdl_mesh *mesh = mdl_find_mesh( &gui.model_icons, name ); - if( mesh ) - if( mesh->submesh_count ) - return &gui.model_icons.submeshes[ mesh->submesh_start ]; - - return NULL; -} - static void gui_init(void) { font3d_load( &gui.font, "models/rs_font.mdl", vg_mem.rtmemory ); @@ -300,28 +291,30 @@ static void gui_init(void) /* load icons */ void *alloc = vg_mem.rtmemory; - mdl_open( &gui.model_icons, "models/rs_icons.mdl", alloc ); - mdl_load_metadata_block( &gui.model_icons, alloc ); - - gui.icons[ k_gui_icon_tick ] = gui_find_icon( "icon_tick" ); - gui.icons[ k_gui_icon_tick_2d ] = gui_find_icon( "icon_tick2d" ); - gui.icons[ k_gui_icon_exclaim ] = gui_find_icon( "icon_exclaim" ); - gui.icons[ k_gui_icon_exclaim_2d ] = gui_find_icon( "icon_exclaim2d" ); - gui.icons[ k_gui_icon_board ] = gui_find_icon( "icon_board" ); - gui.icons[ k_gui_icon_world ] = gui_find_icon( "icon_world" ); - gui.icons[ k_gui_icon_rift ] = gui_find_icon( "icon_rift" ); - gui.icons[ k_gui_icon_rift_run ] = gui_find_icon( "icon_rift_run" ); - gui.icons[ k_gui_icon_rift_run_2d ] = gui_find_icon( "icon_rift_run2d" ); - gui.icons[ k_gui_icon_friend ] = gui_find_icon( "icon_friend" ); - gui.icons[ k_gui_icon_player ] = gui_find_icon( "icon_player" ); - gui.icons[ k_gui_icon_player2d ] = gui_find_icon( "icon_player2d" ); - gui.icons[ k_gui_icon_glider ] = gui_find_icon( "icon_glider" ); - gui.icons[ k_gui_icon_spawn ] = gui_find_icon( "icon_spawn" ); - gui.icons[ k_gui_icon_spawn_select ] = gui_find_icon( "icon_spawn_select" ); - gui.icons[ k_gui_icon_rift_run_gold ] = gui_find_icon("icon_rift_run_medal_gold"); - gui.icons[ k_gui_icon_rift_run_silver]= gui_find_icon("icon_rift_run_medal_silver"); - gui.icons[ k_gui_icon_story2d ]= gui_find_icon("icon_story2d"); - gui.icons[ k_gui_icon_story_done2d ]= gui_find_icon("icon_story_done2d"); + + mdl_context *mdl = &gui.model_icons; + mdl_open( mdl, "models/rs_icons.mdl", alloc ); + mdl_load_metadata_block( mdl, alloc ); + + gui.icon_submeshes[ k_gui_icon_tick ] = mdl_get_submesh_index( mdl, "icon_tick" ); + gui.icon_submeshes[ k_gui_icon_tick_2d ] = mdl_get_submesh_index( mdl, "icon_tick2d" ); + gui.icon_submeshes[ k_gui_icon_exclaim ] = mdl_get_submesh_index( mdl, "icon_exclaim" ); + gui.icon_submeshes[ k_gui_icon_exclaim_2d ] = mdl_get_submesh_index( mdl, "icon_exclaim2d" ); + 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_linear_clear( vg_mem.scratch ); if( !gui.model_icons.texture_count ) @@ -329,10 +322,7 @@ static void gui_init(void) mdl_texture *tex0 = &gui.model_icons.textures[ 0 ]; void *data = vg_linear_alloc( vg_mem.scratch, tex0->file.pack_size ); 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 ); - + 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 ); } diff --git a/src/model.c b/src/model.c index 200452c..dea1bb8 100644 --- a/src/model.c +++ b/src/model.c @@ -373,26 +373,29 @@ void mdl_draw_submesh( mdl_submesh *sm ) } #endif -mdl_mesh *mdl_find_mesh( mdl_context *mdl, const char *name ) +i32 mdl_get_mesh_index( mdl_context *mdl, const char *name ) { u32 hash = vg_strdjb2( name ); for( u32 i=0; imesh_count; i++ ) { mdl_mesh *mesh = &mdl->meshes[ i ]; if( af_str_eq( &mdl->af, mesh->pstr_name, name, hash ) ) - return mesh; + return i; } - return NULL; + return -1; } -mdl_submesh *mdl_find_submesh( mdl_context *mdl, const char *mesh_name ) +i32 mdl_get_submesh_index( mdl_context *mdl, const char *mesh_name ) { - mdl_mesh *mesh = mdl_find_mesh( mdl, mesh_name ); + i32 mesh_index = mdl_get_mesh_index( mdl, mesh_name ); + if( mesh_index == -1 ) + return -1; - if( !mesh ) return NULL; - if( !mesh->submesh_count ) return NULL; + mdl_mesh *mesh = &mdl->meshes[ mesh_index ]; + if( !mesh->submesh_count ) + return -1; - return &mdl->submeshes[ mesh->submesh_start ]; + return mesh->submesh_start; } #ifdef VG_3D diff --git a/src/model.h b/src/model.h index 43dd7fa..818ca12 100644 --- a/src/model.h +++ b/src/model.h @@ -310,8 +310,8 @@ void mdl_sync_std_unload( mdl_context *mdl ); /* rendering */ void mdl_draw_submesh( mdl_submesh *sm ); -mdl_mesh *mdl_find_mesh( mdl_context *mdl, const char *name ); -mdl_submesh *mdl_find_submesh( mdl_context *mdl, const char *mesh_name ); +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 ); diff --git a/src/player_glide.c b/src/player_glide.c index a108f33..b132ea7 100644 --- a/src/player_glide.c +++ b/src/player_glide.c @@ -466,8 +466,7 @@ void player_glide_bind(void) for( u32 i=0; itransform.co, - player_glide.trail_positions[ player_glide.trail_count ++ ] ); + v3_copy( marker->transform.co, player_glide.trail_positions[ player_glide.trail_count ++ ] ); if( player_glide.trail_count == VG_ARRAY_LEN(trails_glider) ) break; diff --git a/src/render.c b/src/render.c index 6399db4..190c506 100644 --- a/src/render.c +++ b/src/render.c @@ -106,6 +106,21 @@ void render_init(void) }; vg_framebuffer_create( g_render.fb_network_status ); + g_render.fb_compass = vg_framebuffer_allocate( alloc, 1, 1 ); + g_render.fb_compass->display_name = "compass"; + g_render.fb_compass->resolution_div = 0; + g_render.fb_compass->fixed_w = 800; + g_render.fb_compass->fixed_h = 100; + g_render.fb_compass->attachments[0] = (vg_framebuffer_attachment) + { + "colour", k_framebuffer_attachment_type_texture, + .internalformat = GL_RGBA, + .format = GL_RGBA, + .type = GL_UNSIGNED_BYTE, + .attachment = GL_COLOR_ATTACHMENT0 + }; + vg_framebuffer_create( g_render.fb_compass ); + vg_async_call( async_render_init, NULL, 0 ); } diff --git a/src/render.h b/src/render.h index a401714..15bb6b6 100644 --- a/src/render.h +++ b/src/render.h @@ -26,7 +26,8 @@ struct pipeline glmesh fsquad; vg_framebuffer *fb_workshop_preview, - *fb_network_status; + *fb_network_status, + *fb_compass; int ready; v2f blur_override; diff --git a/src/skaterift.c b/src/skaterift.c index 8c690d3..0c6b89d 100644 --- a/src/skaterift.c +++ b/src/skaterift.c @@ -53,6 +53,7 @@ #include "ent_challenge.h" #include "ent_script.h" #include "board_maker.h" +#include "compass.h" struct skaterift_globals skaterift = { @@ -92,6 +93,7 @@ void game_load(void) vg_loader_step( world_init, NULL ); vg_loader_step( vehicle_init, NULL ); vg_loader_step( gui_init, NULL ); + vg_loader_step( compass_init, NULL ); vg_loader_step( player_init, NULL ); vg_loader_step( player_ragdoll_init, NULL ); @@ -503,6 +505,8 @@ void vg_render(void) glViewport( 0,0, vg.window_x, vg.window_y ); gui_render_icons(); + + compass_render_texture(); } void vg_gui( ui_context *ctx ) @@ -510,7 +514,11 @@ void vg_gui( ui_context *ctx ) if( g_client.unreadyness ) 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 ); @@ -606,6 +614,7 @@ void vg_framebuffer_resize( int w, int h ) #include "ent_camera.c" #include "skaterift_script.c" #include "board_maker.c" +#include "compass.c" //TODO //#include "vg/submodules/hashmap.c/hashmap.c" diff --git a/src/world_gate.c b/src/world_gate.c index 4402730..1b6c9be 100644 --- a/src/world_gate.c +++ b/src/world_gate.c @@ -55,19 +55,13 @@ void world_gates_init(void) mdl_open( &mgate, "models/rs_gate.mdl", vg_mem.scratch ); mdl_load_metadata_block( &mgate, vg_mem.scratch ); - mdl_mesh *surface = mdl_find_mesh( &mgate, "rs_gate" ); - mdl_submesh *sm = &mgate.submeshes[ surface->submesh_start ]; - world_gates.sm_surface = *sm; + 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++ ) - { - mdl_mesh *marker = mdl_find_mesh( &mgate, names[i] ); - sm = &mgate.submeshes[ marker->submesh_start ]; - world_gates.sm_marker[i] = *sm; - } + world_gates.sm_marker[i] = mgate.submeshes[ mdl_get_submesh_index( &mgate, names[i] ) ]; mdl_async_load_glmesh( &mgate, &world_gates.mesh, NULL ); mdl_close( &mgate ); diff --git a/src/world_render.c b/src/world_render.c index 1a2a070..0eb8101 100644 --- a/src/world_render.c +++ b/src/world_render.c @@ -61,8 +61,8 @@ void world_render_init(void) mdl_open( &msky, "models/rs_skydome.mdl", vg_mem.scratch ); mdl_load_metadata_block( &msky, vg_mem.scratch ); mdl_async_load_glmesh( &msky, &world_render.skydome, NULL ); - world_render.skydome_complete_mesh = *mdl_find_submesh( &msky, "dome_complete" ); - world_render.skydome_squanched_mesh = *mdl_find_submesh( &msky, "dome_squanched" ); + 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" ); diff --git a/src/world_sfd.c b/src/world_sfd.c index d3362ed..80cb56e 100644 --- a/src/world_sfd.c +++ b/src/world_sfd.c @@ -314,26 +314,21 @@ void world_sfd_init(void) mdl_load_mesh_block( &mscoreboard, vg_mem.scratch ); scene_context *scene = &world_sfd.scene; - vg_async_item *call = scene_alloc_async( scene, &world_sfd.mesh_display, - 3000, 8000 ); + vg_async_item *call = scene_alloc_async( scene, &world_sfd.mesh_display, 3000, 8000 ); - - mdl_mesh *m_backer = mdl_find_mesh( &mscoreboard, "backer" ), - *m_card = mdl_find_mesh( &mscoreboard, "score_card" ); - - mdl_submesh - *sm_backer = &mscoreboard.submeshes[ m_backer->submesh_start ], - *sm_card = &mscoreboard.submeshes[ m_card->submesh_start ]; - world_sfd.sm_base = *sm_backer; + mdl_submesh *sm_card = &mscoreboard.submeshes[ mdl_get_submesh_index( &mscoreboard, "score_card" ) ]; + world_sfd.sm_base = mscoreboard.submeshes[ mdl_get_submesh_index( &mscoreboard, "backer" ) ]; m4x3f identity; m4x3_identity( identity ); - for( int i=0;i<4;i++ ){ + for( int i=0;i<4;i++ ) + { u32 vert_start = scene->vertex_count; scene_add_mdl_submesh( scene, &mscoreboard, sm_card, identity ); - for( int j=0; jvertex_count; j++ ){ + for( int j=0; jvertex_count; j++ ) + { scene_vert *vert = &scene->arrvertices[ vert_start+j ]; float const k_glyph_uvw = 1.0f/64.0f; -- 2.25.1