From: hgn Date: Fri, 21 Jul 2023 01:35:50 +0000 (+0100) Subject: some gate improvements X-Git-Url: https://harrygodden.com/git/?a=commitdiff_plain;h=6ab4435fb19beb6af6c52691793d5ca17a120f69;p=carveJwlIkooP6JGAAIwe30JlM.git some gate improvements --- diff --git a/blender_export.py b/blender_export.py index 820c49a..8eb39a3 100644 --- a/blender_export.py +++ b/blender_export.py @@ -39,6 +39,8 @@ sr_entity_list = [ ('ent_challenge', 'Challenge', '', 18 ) ] +MDL_VERSION_NR = 102 + def get_entity_enum_id( alias ): #{ for et in sr_entity_list:#{ @@ -186,7 +188,7 @@ class version_refcount_union(Union): class ent_gate(Structure): #{ - _fields_ = [("type",c_uint32), + _fields_ = [("flags",c_uint32), ("target", c_uint32), ("key",c_uint32), ("dimensions", c_float*3), @@ -197,7 +199,10 @@ class ent_gate(Structure): ("_anonymous_union",version_refcount_union), ("timing_time",c_double), ("routes",c_uint16*4), - ("route_count",c_uint8)] + ("route_count",c_uint8), + ("submesh_start",c_uint32), # v102+ + ("submesh_count",c_uint32), # v102+ (can be 0) + ] #} class ent_route_node(Structure): @@ -1572,6 +1577,12 @@ def sr_compile( collection ): if ent_type == 'ent_font_variant': continue if ent_type == 'ent_menuitem': continue if ent_type == 'ent_challenge': continue + + #TODO: This is messy. + if ent_type == 'ent_gate':#{ + obj_data = obj.SR_data.ent_gate[0] + if obj_data.custom: continue + #} #-------------------------- print( F'[SR] {i: 3}/{mesh_count} {obj.name:<40}', end='\r' ) @@ -1619,18 +1630,27 @@ def sr_compile( collection ): obj_data = obj.SR_data.ent_gate[0] mesh_data = obj.data.SR_data.ent_gate[0] + flags = 0x0000 + if obj_data.tipo == 'default':#{ if obj_data.target:#{ gate.target = sr_compile.entity_ids[obj_data.target.name] - gate.type = 1 + flags |= 0x0001 #} #} elif obj_data.tipo == 'nonlocal':#{ gate.target = 0 gate.key = sr_compile_string(obj_data.key) - gate.type = 2 + flags |= 0x0002 + #} + + if obj_data.flip: flags |= 0x0004 + if obj_data.custom:#{ + flags |= 0x0008 + gate.submesh_start, gate.submesh_count, _ = \ + sr_compile_mesh_internal( obj ) #} - else: gate.type = 0 + gate.flags = flags gate.dimensions[0] = mesh_data.dimensions[0] gate.dimensions[1] = mesh_data.dimensions[1] @@ -1996,7 +2016,7 @@ def sr_compile( collection ): os.makedirs(os.path.dirname(path),exist_ok=True) fp = open( path, "wb" ) header = mdl_header() - header.version = 101 + header.version = MDL_VERSION_NR sr_array_title( header.arrays, \ 'index', len(file_array_instructions), \ sizeof(mdl_array), header_size ) @@ -2380,7 +2400,10 @@ class SR_OBJECT_ENT_GATE(bpy.types.PropertyGroup): key: bpy.props.StringProperty() tipo: bpy.props.EnumProperty(items=(('default', 'Default', ""), - ('nonlocal', 'Non-Local', ""),)) + ('nonlocal', 'Non-Local', ""))) + + flip: bpy.props.BoolProperty( name="Flip exit", default=False ) + custom: bpy.props.BoolProperty( name="Mesh is surface", default=False ) @staticmethod def sr_inspector( layout, data ): @@ -2390,6 +2413,10 @@ class SR_OBJECT_ENT_GATE(bpy.types.PropertyGroup): if data[0].tipo == 'default': box.prop( data[0], 'target' ) elif data[0].tipo == 'nonlocal': box.prop( data[0], 'key' ) + + flags = box.box() + flags.prop( data[0], 'flip' ) + flags.prop( data[0], 'custom' ) #} #} diff --git a/entity.h b/entity.h index 05294f3..da2341e 100644 --- a/entity.h +++ b/entity.h @@ -91,15 +91,27 @@ struct ent_light{ v2f angle_sin_cos; }; +/* v101 */ +#if 0 enum gate_type{ k_gate_type_unlinked = 0, k_gate_type_teleport = 1, k_gate_type_nonlocal_unlinked = 2, k_gate_type_nonlocel = 3 }; +#endif + +/* v102+ */ +enum ent_gate_flag{ + k_ent_gate_linked = 0x1, /* this is a working portal */ + k_ent_gate_nonlocal = 0x2, /* use the key string to link this portal. + NOTE: if set, it adds the flip flag. */ + k_ent_gate_flip = 0x4, /* flip direction 180* for exiting portal */ + k_ent_gate_custom_mesh = 0x8, /* use a custom submesh instead of default */ +}; struct ent_gate{ - u32 type, + u32 flags, target, key; @@ -122,6 +134,9 @@ struct ent_gate{ double timing_time; u16 routes[4]; /* routes that pass through this gate */ u8 route_count; + + /* v102+ */ + u32 submesh_start, submesh_count; }; struct ent_route_node{ diff --git a/maps_src/mp_spawn/main.mdl b/maps_src/mp_spawn/main.mdl index 5df1a39..4467e7b 100644 Binary files a/maps_src/mp_spawn/main.mdl and b/maps_src/mp_spawn/main.mdl differ diff --git a/model.h b/model.h index 6ff0a85..f9ec815 100644 --- a/model.h +++ b/model.h @@ -7,7 +7,8 @@ #include "skaterift.h" -#define MDL_VERSION_NR 101 +#define MDL_VERSION_MIN 101 +#define MDL_VERSION_NR 102 enum mdl_shader { @@ -414,10 +415,10 @@ VG_STATIC void mdl_open( mdl_context *mdl, const char *path, void *lin_alloc ) if( l != 1 ) mdl_load_fatal_corrupt( mdl ); - if( mdl->info.version < MDL_VERSION_NR ){ + if( mdl->info.version < MDL_VERSION_MIN ){ vg_warn( "For model: %s\n", path ); - vg_warn( " version: %u (current: %u)\n", mdl->info.version, - MDL_VERSION_NR ); + vg_warn( " version: %u (min: %u, current: %u)\n", + mdl->info.version, MDL_VERSION_MIN, MDL_VERSION_NR ); vg_fatal_error( "Legacy model version incompatable" ); } diff --git a/player.c b/player.c index b67e050..ab39319 100644 --- a/player.c +++ b/player.c @@ -164,7 +164,7 @@ void player__pass_gate( player_instance *player, ent_gate *gate ) m4x3_mulv( gate->transport, player->cam.pos, player->cam.pos ); - if( gate->type == k_gate_type_nonlocel ) + if( gate->flags & k_ent_gate_nonlocal ) world_static.active_world = gate->target; audio_lock(); diff --git a/player_skate.c b/player_skate.c index ac14239..baa1ce7 100644 --- a/player_skate.c +++ b/player_skate.c @@ -499,7 +499,7 @@ void player__approximate_best_trajectory( player_instance *player ) m4x3_mulv( gate->transport, launch_co, launch_co ); m3x3_mul( gate->transport, basis, basis ); - if( gate->type == k_gate_type_nonlocel ){ + if( gate->flags & k_ent_gate_nonlocal ){ trace_world = &world_static.worlds[ gate->target ]; } } diff --git a/shaders/model_gate.h b/shaders/model_gate.h index fc9c1ea..cd2c29b 100644 --- a/shaders/model_gate.h +++ b/shaders/model_gate.h @@ -12,9 +12,6 @@ static struct vg_shader _shader_model_gate = { "layout (location=0) in vec3 a_co;\n" "layout (location=1) in vec3 a_norm;\n" "layout (location=2) in vec2 a_uv;\n" -"layout (location=3) in vec4 a_colour;\n" -"layout (location=4) in vec4 a_weights;\n" -"layout (location=5) in ivec4 a_groups;\n" "\n" "uniform mat4 uPv;\n" "uniform mat4x3 uMdl;\n" diff --git a/shaders/model_gate.vs b/shaders/model_gate.vs index edea94d..ce70d52 100644 --- a/shaders/model_gate.vs +++ b/shaders/model_gate.vs @@ -1,9 +1,6 @@ layout (location=0) in vec3 a_co; layout (location=1) in vec3 a_norm; layout (location=2) in vec2 a_uv; -layout (location=3) in vec4 a_colour; -layout (location=4) in vec4 a_weights; -layout (location=5) in ivec4 a_groups; uniform mat4 uPv; uniform mat4x3 uMdl; diff --git a/world_entity.c b/world_entity.c index db1d244..7e285d4 100644 --- a/world_entity.c +++ b/world_entity.c @@ -26,7 +26,7 @@ VG_STATIC void world_gen_entities_init(void){ for( u32 j=0; jent_gate); j ++ ){ ent_gate *gate = mdl_arritm( &world->ent_gate, j ); - if( gate->type == k_gate_type_teleport ){ + if( !(gate->flags & k_ent_gate_nonlocal) ) { gate_transform_update( gate ); } } diff --git a/world_gate.c b/world_gate.c index a61bc16..a4cf8fd 100644 --- a/world_gate.c +++ b/world_gate.c @@ -20,8 +20,13 @@ /* * Update the transform matrices for gate */ -VG_STATIC void gate_transform_update( ent_gate *gate ) -{ +VG_STATIC void gate_transform_update( ent_gate *gate ){ + if( gate->flags & k_ent_gate_flip ){ + v4f qflip; + q_axis_angle( qflip, (v3f){0.0f,1.0f,0.0f}, VG_PIf ); + q_mul( gate->q[1], qflip, gate->q[1] ); + } + m4x3f to_local, recv_to_world; q_m3x3( gate->q[0], gate->to_world ); @@ -32,9 +37,6 @@ VG_STATIC void gate_transform_update( ent_gate *gate ) q_m3x3( gate->q[1], recv_to_world ); v3_copy( gate->co[1], recv_to_world[3] ); m4x3_mul( recv_to_world, to_local, gate->transport ); - - m3x3_scale( gate->to_world, (v3f){ gate->dimensions[0], - gate->dimensions[1], 1.0f } ); } VG_STATIC void world_gates_init(void) @@ -69,7 +71,7 @@ VG_STATIC void world_gates_init(void) /* * Render the view through a gate */ -VG_STATIC int render_gate( world_instance *world_inside, +VG_STATIC int render_gate( world_instance *world, world_instance *world_inside, ent_gate *gate, camera *cam, int layer_depth ) { v3f viewdir, gatedir; @@ -89,19 +91,20 @@ VG_STATIC int render_gate( world_instance *world_inside, return 0; { - v3f a,b,c,d; + f32 w = gate->dimensions[0], + h = gate->dimensions[1]; - m4x3_mulv( gate->to_world, (v3f){-1.0f,-1.0f,0.0f}, a ); - m4x3_mulv( gate->to_world, (v3f){ 1.0f,-1.0f,0.0f}, b ); - m4x3_mulv( gate->to_world, (v3f){ 1.0f, 1.0f,0.0f}, c ); - m4x3_mulv( gate->to_world, (v3f){-1.0f, 1.0f,0.0f}, d ); + v3f a,b,c,d; + m4x3_mulv( gate->to_world, (v3f){-w,-h,0.0f}, a ); + m4x3_mulv( gate->to_world, (v3f){ w,-h,0.0f}, b ); + m4x3_mulv( gate->to_world, (v3f){ w, h,0.0f}, c ); + m4x3_mulv( gate->to_world, (v3f){-w, h,0.0f}, d ); vg_line( a,b, 0xffffa000 ); vg_line( b,c, 0xffffa000 ); vg_line( c,d, 0xffffa000 ); vg_line( d,a, 0xffffa000 ); - - vg_line2( gate->co[0], gate->co[1], 0xff0000ff, 0x00000000 ); + vg_line( gate->co[0], gate->co[1], 0xff0000ff ); } /* update gate camera */ @@ -131,7 +134,6 @@ VG_STATIC int render_gate( world_instance *world_inside, { shader_model_gate_use(); shader_model_gate_uPv( cam->mtx.pv ); - shader_model_gate_uMdl( gate->to_world ); shader_model_gate_uCam( cam->pos ); shader_model_gate_uColour( (v4f){0.0f,1.0f,0.0f,0.0f} ); shader_model_gate_uTime( vg.time*0.25f ); @@ -143,13 +145,33 @@ VG_STATIC int render_gate( world_instance *world_inside, glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE ); glStencilFunc( GL_ALWAYS, 1, 0xFF ); glStencilMask( 0xFF ); + glDisable( GL_CULL_FACE ); + + m4x3f mmdl; + m4x3_copy( gate->to_world, mmdl ); + + if( gate->flags & k_ent_gate_custom_mesh ){ + mesh_bind( &world->mesh_no_collide ); + for( u32 i=0; isubmesh_count; i++ ){ + mdl_submesh *sm = mdl_arritm( &world->meta.submeshs, + gate->submesh_start+i ); + mdl_draw_submesh( sm ); + } + } + else { + m3x3_scale( mmdl, (v3f){ gate->dimensions[0], + gate->dimensions[1], 1.0f } ); + + mesh_bind( &world_gates.mesh ); + mdl_draw_submesh( &world_gates.sm_surface ); + } - mesh_bind( &world_gates.mesh ); - mdl_draw_submesh( &world_gates.sm_surface ); + shader_model_gate_uMdl( mmdl ); glClear( GL_DEPTH_BUFFER_BIT ); glStencilFunc( GL_EQUAL, 1, 0xFF ); glStencilMask( 0x00 ); + glEnable( GL_CULL_FACE ); } render_world( world_inside, &world_gates.cam, layer_depth ); @@ -225,7 +247,8 @@ VG_STATIC int gate_intersect( ent_gate *gate, v3f pos, v3f last ) v2f xy; if( gate_intersect_plane( gate, pos, last, xy ) ){ - if( fabsf(xy[0]) <= 1.0f && fabsf(xy[1]) <= 1.0f ){ + if( (fabsf(xy[0]) <= gate->dimensions[0]) && + (fabsf(xy[1]) <= gate->dimensions[1]) ){ return 1; } } @@ -237,15 +260,13 @@ VG_STATIC int gate_intersect( ent_gate *gate, v3f pos, v3f last ) * Intersect all gates in the world */ VG_STATIC ent_gate *world_intersect_gates( world_instance *world, - v3f pos, v3f last ) -{ + v3f pos, v3f last ){ for( u32 i=0; ient_gate); i++ ){ ent_gate *gate = mdl_arritm( &world->ent_gate, i ); - if( gate->type == k_gate_type_unlinked || - gate->type == k_gate_type_nonlocal_unlinked ) - continue; - if( gate->type == k_gate_type_nonlocel ){ + if( !(gate->flags & k_ent_gate_linked) ) continue; + + if( gate->flags & k_ent_gate_nonlocal ){ if( world_loader.state != k_world_loader_none ){ continue; } @@ -262,13 +283,12 @@ VG_STATIC ent_gate *world_intersect_gates( world_instance *world, /* * detatches any nonlocal gates */ -VG_STATIC void world_unlink_nonlocal( world_instance *world ) -{ +VG_STATIC void world_unlink_nonlocal( world_instance *world ){ for( u32 j=0; jent_gate); j ++ ){ ent_gate *gate = mdl_arritm( &world->ent_gate, j ); - if( gate->type == k_gate_type_nonlocel ){ - gate->type = k_gate_type_nonlocal_unlinked; + if( gate->flags & k_ent_gate_nonlocal ){ + gate->flags &= ~k_ent_gate_linked; } } } @@ -284,51 +304,66 @@ VG_STATIC void world_link_nonlocal_async( void *payload, u32 size ) for( u32 j=0; jent_gate); j ++ ){ ent_gate *gate = mdl_arritm( &world->ent_gate, j ); - if( gate->type == k_gate_type_nonlocal_unlinked ){ - const char *key = mdl_pstr( &world->meta, gate->key ); - vg_info( "key: %s\n", key ); + if( !(gate->flags & k_ent_gate_nonlocal) ) continue; + if( gate->flags & k_ent_gate_linked ) continue; + + const char *key = mdl_pstr( &world->meta, gate->key ); + vg_info( "key: %s\n", key ); + + for( u32 i=0; istatus != k_world_status_loaded ) continue; + vg_info( "Checking world %u for key matches\n", i ); + + for( u32 j=0; jent_gate ); j++ ){ + ent_gate *gate2 = mdl_arritm( &other->ent_gate, j ); - for( u32 i=0; istatus != k_world_status_loaded ) continue; - vg_info( "Checking world %u for key matches\n", i ); + if( !(gate2->flags & k_ent_gate_nonlocal) ) continue; + if( gate2->flags & k_ent_gate_linked ) continue; - for( u32 j=0; jent_gate ); j++ ){ - ent_gate *gate2 = mdl_arritm( &other->ent_gate, j ); - if( gate2->type != k_gate_type_nonlocal_unlinked ) continue; + const char *key2 = mdl_pstr( &other->meta, gate2->key ); + vg_info( " key2: %s\n", key2 ); - const char *key2 = mdl_pstr( &other->meta, gate2->key ); - vg_info( " key2: %s\n", key2 ); + if( strcmp( key, key2 ) ) continue; - if( strcmp( key, key2 ) ) continue; + vg_success( "Non-local matching pair '%s' found. (%u:%u)\n", + key, world_id, i ); - vg_success( "Non-local matching pair '%s' found. (%u:%u)\n", - key, world_id, i ); - - gate->type = k_gate_type_nonlocel; - gate2->type = k_gate_type_nonlocel; - gate->target = i; - gate2->target = world_id; + gate->flags |= k_ent_gate_linked; + gate2->flags |= k_ent_gate_linked; + gate->target = i; + gate2->target = world_id; - v3_copy( gate->co[0], gate2->co[1] ); - v3_copy( gate2->co[0], gate->co[1] ); - v4_copy( gate->q[0], gate2->q[1] ); - v4_copy( gate2->q[0], gate->q[1] ); + v3_copy( gate->co[0], gate2->co[1] ); + v3_copy( gate2->co[0], gate->co[1] ); + v4_copy( gate->q[0], gate2->q[1] ); + v4_copy( gate2->q[0], gate->q[1] ); + if( other->meta.info.version >= 102 ){ + gate->flags |= k_ent_gate_flip; + gate2->flags |= k_ent_gate_flip; + } + else { + /* LEGACY BEHAVIOUR: v101 + * this would flip both the client worlds portal's entrance and + * exit. effectively the clients portal would be the opposite + * to the hub worlds one. new behaviour is to just flip the + * destinations so the rules are consistent in each world. + */ v4f qflip; q_axis_angle( qflip, (v3f){0.0f,1.0f,0.0f}, VG_PIf ); q_mul( gate->q[0], qflip, gate->q[0] ); q_mul( gate->q[1], qflip, gate->q[1] ); + } - gate_transform_update( gate ); - gate_transform_update( gate2 ); + gate_transform_update( gate ); + gate_transform_update( gate2 ); - goto matched; - } + goto matched; } -matched:; } +matched:; } } diff --git a/world_gate.h b/world_gate.h index b45c70d..4b3299a 100644 --- a/world_gate.h +++ b/world_gate.h @@ -20,7 +20,7 @@ VG_STATIC void world_gates_init(void); VG_STATIC void gate_transform_update( ent_gate *gate ); VG_STATIC void world_link_nonlocal_async( void *payload, u32 size ); VG_STATIC void world_unlink_nonlocal( world_instance *world ); -VG_STATIC int render_gate( world_instance *world_inside, +VG_STATIC int render_gate( world_instance *world, world_instance *world_inside, ent_gate *gate, camera *cam, int layer_depth ); VG_STATIC int gate_intersect( ent_gate *gate, v3f pos, v3f last ); diff --git a/world_gen.c b/world_gen.c index c31c2c2..5f7b9a3 100644 --- a/world_gen.c +++ b/world_gen.c @@ -282,6 +282,19 @@ VG_STATIC void world_gen_generate_meshes(void) } } + /* unpack gate models */ + for( u32 i=0; ient_gate ); i++ ){ + ent_gate *gate = mdl_arritm( &world->ent_gate, i ); + + if( !(gate->flags & k_ent_gate_custom_mesh) ) continue; + + for( u32 j=0; jsubmesh_count; j ++ ){ + mdl_submesh *sm = mdl_arritm( &world->meta.submeshs, + gate->submesh_start+j ); + world_unpack_submesh_dynamic( world, &world->scene_no_collide, sm ); + } + } + vg_async_dispatch( call, async_scene_upload ); } diff --git a/world_render.c b/world_render.c index a33d774..a7ff25c 100644 --- a/world_render.c +++ b/world_render.c @@ -520,7 +520,7 @@ VG_STATIC void render_world_gates( world_instance *world, camera *cam, for( u32 i=0; ient_gate); i++ ){ ent_gate *gi = mdl_arritm( &world->ent_gate, i ); - if( gi->type == k_gate_type_unlinked ) + if( !(gi->flags & k_ent_gate_linked) ) continue; float dist = v3_dist2( gi->co[0], cam->transform[3] ); @@ -533,25 +533,20 @@ VG_STATIC void render_world_gates( world_instance *world, camera *cam, } } + world->rendering_gate = gate; if( gate ){ - /* should really be set in fixed update since its used in the physics - * of most systems. too bad! */ - world->rendering_gate = gate; - - if( gate->type == k_gate_type_teleport ){ - render_gate( world, gate, cam, layer_depth ); - } - else if( gate->type == k_gate_type_nonlocel ){ + if( gate->flags & k_ent_gate_nonlocal ){ if( world_loader.state != k_world_loader_none ){ world->rendering_gate = NULL; return; } world_instance *dest_world = &world_static.worlds[ gate->target ]; - render_gate( dest_world, gate, cam, layer_depth ); + render_gate( world, dest_world, gate, cam, layer_depth ); + } + else{ + render_gate( world, world, gate, cam, layer_depth ); } - else - world->rendering_gate = NULL; } } diff --git a/world_routes.c b/world_routes.c index d2816d1..44d055b 100644 --- a/world_routes.c +++ b/world_routes.c @@ -133,7 +133,7 @@ VG_STATIC void world_routes_activate_entry_gate( world_instance *world, world_static.last_use = world_static.time; /* disable all routes and leave the world */ - if( rg->type == k_gate_type_nonlocel ){ + if( rg->flags & k_ent_gate_nonlocal ){ for( u32 i=0; ient_route); i++ ){ ent_route *route = mdl_arritm( &world->ent_route, i ); route->active_checkpoint = 0xffff; @@ -912,7 +912,8 @@ VG_STATIC void world_gen_routes_ent_init(void) } } - if( gate->type == k_gate_type_teleport ){ + if( (gate->flags & k_ent_gate_linked) & + !(gate->flags & k_ent_gate_nonlocal) ){ gate = mdl_arritm(&world->ent_gate, gate->target ); for( u32 k=0; k<4; k++ ){