From: hgn Date: Tue, 26 Jul 2022 07:13:28 +0000 (+0100) Subject: instance support X-Git-Url: https://skaterift.com/git/?a=commitdiff_plain;h=1c97cb161f885ad24d3356d92c8f4fd0e252bc61;p=carveJwlIkooP6JGAAIwe30JlM.git instance support --- diff --git a/blender_export.py b/blender_export.py index 05f687a..8424753 100644 --- a/blender_export.py +++ b/blender_export.py @@ -96,14 +96,16 @@ class classtype_car_path(Structure): _fields_ = [("target",c_uint32), ("target1",c_uint32)] +class classtype_instance(Structure): + _pack_ = 1 + _fields_ = [("pstr_file",c_uint32)] + # Exporter # ============================================================================== def write_model(name): print( F"Create mode {name}" ) - collection = bpy.data.collections[name] - header = mdl_header() header.identifier = 0xABCD0000 header.version = 0 @@ -179,6 +181,8 @@ def write_model(name): # Do exporting # print( " assigning ids" ) + collection = bpy.data.collections[name] + header.node_count = 1 for obj in collection.all_objects: obj.cv_data.uid = header.node_count @@ -210,11 +214,7 @@ def write_model(name): node.offset = entdata_length classtype = obj.cv_data.classtype - if classtype == 'k_classtype_none': - node.classtype = 0 - node.offset = 0 - - elif classtype == 'k_classtype_gate': + if classtype == 'k_classtype_gate': node.classtype = 1 entdata_length += sizeof( classtype_gate ) @@ -260,6 +260,20 @@ def write_model(name): pn.target1 = obj.cv_data.target1.cv_data.uid entdata_buffer += [pn] + elif obj.is_instancer: + target = obj.instance_collection + + node.classtype = 6 + entdata_length += sizeof( classtype_instance ) + + inst = classtype_instance() + inst.pstr_file = emplace_string( F"models/{target.name}.mdl" ) + entdata_buffer += [inst] + + # classtype == 'k_classtype_none': + else: + node.classtype = 0 + node.offset = 0 # Process meshes # diff --git a/character.h b/character.h index daa2e99..3858f24 100644 --- a/character.h +++ b/character.h @@ -434,6 +434,7 @@ void character_pose_blend( struct character *ch, character_pose *pose, float q ) v3_muladds( ch->cam_pos, pose->cam, q, ch->cam_pos ); } +#if 1 static void character_final_pose( struct character *ch, v3f cog, character_pose *pose, float q ) @@ -466,6 +467,34 @@ void character_final_pose( struct character *ch, v3f cog, character_pose_blend( ch, &npose, q ); } +#else +static +void character_final_pose( struct character *ch, v4f rot, + character_pose *pose, float q ) +{ + character_pose npose; + + m4x3f tr; + q_m3x3( rot, tr ); + v3_zero( tr[3] ); + + m4x3_mulv( tr, pose->b0, npose.b0 ); + m4x3_mulv( tr, pose->b1, npose.b1 ); + m4x3_mulv( tr, pose->p, npose.p ); + m4x3_mulv( tr, pose->pl, npose.pl ); + m4x3_mulv( tr, pose->pr, npose.pr ); + m4x3_mulv( tr, pose->hl, npose.hl ); + m4x3_mulv( tr, pose->hr, npose.hr ); + m4x3_mulv( tr, pose->apl, npose.apl ); + m4x3_mulv( tr, pose->apr, npose.apr ); + + v3_copy( pose->fr, npose.fr ); + v3_copy( pose->fl, npose.fl ); + v3_copy( pose->cam, npose.cam ); + + character_pose_blend( ch, &npose, q ); +} +#endif static void character_yaw_upper( struct character *ch, float yaw ) { diff --git a/common.h b/common.h index 2ee2d7c..c22fd45 100644 --- a/common.h +++ b/common.h @@ -16,7 +16,8 @@ enum classtype k_classtype_block = 2, k_classtype_spawn = 3, k_classtype_water = 4, - k_classtype_car_path = 5 + k_classtype_car_path = 5, + k_classtype_instance = 6 }; /* TODO: he needs a home somewhere */ diff --git a/model.h b/model.h index a65f11f..4fdd860 100644 --- a/model.h +++ b/model.h @@ -14,7 +14,7 @@ typedef struct mdl_header mdl_header; #define MDL_SIZE_MAX 0x1000000 #define MDL_VERT_MAX 1000000 #define MDL_INDICE_MAX 1000000 -#define MDL_MATERIAL_MAX 500 +#define MDL_MATERIAL_MAX 32 #define MDL_NODE_MAX 4000 #define MDL_SUBMESH_MAX 8000 #define MDL_STRING_LENGTH_MAX 64 @@ -100,6 +100,11 @@ struct classtype_car_path u32 target, target1; }; +struct classtype_instance +{ + u32 pstr_file; +}; + #pragma pack(pop) /* @@ -411,5 +416,42 @@ static void *mdl_get_entdata( mdl_header *mdl, mdl_node *pnode ) return mdl_baseptr( mdl, mdl->entdata_offset ) + pnode->offset; } +static void mdl_link_materials( mdl_header *root, mdl_header *child ) +{ + u32 lookup[MDL_MATERIAL_MAX]; + + for( int i=0; imaterial_count; i++ ) + { + mdl_material *mi = mdl_material_from_id( child, i ); + const char *si = mdl_pstr( child, mi->pstr_name ); + + lookup[i] = 0; + + for( int j=0; jmaterial_count; j++ ) + { + mdl_material *mj = mdl_material_from_id( root, j ); + const char *sj = mdl_pstr( root, mj->pstr_name ); + + if( !strcmp( si, sj ) ) + { + lookup[i] = j; + break; + } + } + + if( lookup[i] == 0 && i != 0 ) + { + vg_warn( "Could not link material '%s' (not present in root model)\n", + si ); + } + } + + for( int i=0; isubmesh_count; i++ ) + { + mdl_submesh *sm = mdl_submesh_from_id( child, i ); + sm->material_id = lookup[sm->material_id]; + } +} + #endif diff --git a/models/cubeh.mdl b/models/cubeh.mdl new file mode 100644 index 0000000..66380cb Binary files /dev/null and b/models/cubeh.mdl differ diff --git a/models/export 10.mdl b/models/export 10.mdl new file mode 100644 index 0000000..9f0a845 Binary files /dev/null and b/models/export 10.mdl differ diff --git a/models/mp_dev.mdl b/models/mp_dev.mdl index 3a57c6c..65cfcf4 100644 Binary files a/models/mp_dev.mdl and b/models/mp_dev.mdl differ diff --git a/models/rs_vig.mdl b/models/rs_vig.mdl new file mode 100644 index 0000000..37bde7b Binary files /dev/null and b/models/rs_vig.mdl differ diff --git a/player.h b/player.h index 1d54fe9..2860d19 100644 --- a/player.h +++ b/player.h @@ -14,16 +14,17 @@ static float k_walkspeed = 2.0f, k_board_radius = 0.3f, - k_board_length = 0.55f, + k_board_length = 0.45f, k_board_allowance = 0.04f, - k_friction_lat = 8.68f, - k_friction_resistance = 0.02f, + k_friction_lat = 8.8f, + k_friction_resistance = 0.01f, k_max_push_speed = 16.0f, k_push_accel = 5.0f, k_push_cycle_rate = 8.0f, k_steer_ground = 2.5f, k_steer_air = 3.6f, k_steer_air_lerp = 0.3f, + k_pump_force = 000.0f, k_downforce = 5.0f; static int freecam = 0; @@ -288,7 +289,8 @@ static void player_physics_control(void) for( int i=0; i<5; i++ ) { vel[2] = stable_force( vel[2], vg_signf( vel[2] ) * fwd_resistance ); - vel[0] = stable_force( vel[0], vg_signf( vel[0] ) * -8.78f *substep ); + vel[0] = stable_force( vel[0], + vg_signf( vel[0] ) * -k_friction_lat*substep ); } static double start_push = 0.0; @@ -304,6 +306,19 @@ static void player_physics_control(void) new_vel -= vg_minf(current, k_max_push_speed); vel[2] -= new_vel * player.reverse; } + + /* Pumping */ + static float previous = 0.0f; + float delta = previous - player.grab, + pump = delta * k_pump_force*ktimestep; + previous = player.grab; + + v3f p1; + v3_muladds( player.rb.co, player.rb.up, pump, p1 ); + vg_line( player.rb.co, p1, 0xff0000ff ); + + vel[1] += pump; + m3x3_mulv( player.rb.to_world, vel, player.rb.v ); @@ -411,9 +426,13 @@ static void player_physics(void) m3x3_copy( player.rb.to_world, player.collide_front.to_world ); m3x3_copy( player.rb.to_world, player.collide_back.to_world ); - m4x3_mulv( player.rb.to_world, (v3f){0.0f,0.0f,-k_board_length}, rbf->co ); + + player.air_blend = vg_lerpf( player.air_blend, player.in_air, 0.1f ); + float h = player.air_blend*0.2f; + + m4x3_mulv( player.rb.to_world, (v3f){0.0f,h,-k_board_length}, rbf->co ); v3_copy( rbf->co, rbf->to_world[3] ); - m4x3_mulv( player.rb.to_world, (v3f){0.0f,0.0f, k_board_length}, rbb->co ); + m4x3_mulv( player.rb.to_world, (v3f){0.0f,h, k_board_length}, rbb->co ); v3_copy( rbb->co, rbb->to_world[3] ); m4x3_invert_affine( rbf->to_world, rbf->to_local ); @@ -534,14 +553,17 @@ static void player_physics(void) } } + float grabt = vg_get_axis( "grabr" )*0.5f+0.5f; + player.grab = vg_lerpf( player.grab, grabt, 0.14f ); + if( !player.in_air ) { v3f axis; float angle = v3_dot( player.rb.up, surface_avg ); v3_cross( player.rb.up, surface_avg, axis ); - float cz = v3_dot( player.rb.forward, axis ); - v3_muls( player.rb.forward, cz, axis ); + //float cz = v3_dot( player.rb.forward, axis ); + //v3_muls( player.rb.forward, cz, axis ); if( angle < 0.999f ) { @@ -1602,14 +1624,12 @@ static void player_animate(void) /* Head */ float lslip = fabsf(player.slip); - - float grabt = vg_get_axis( "grabr" )*0.5f+0.5f; - player.grab = vg_lerpf( player.grab, grabt, 0.04f ); float kheight = 2.0f, kleg = 0.6f; v3f offset; + v3_zero( offset ); m3x3_mulv( player.rb.to_local, player.bob, offset ); static float speed_wobble = 0.0f, speed_wobble_2 = 0.0f; @@ -1629,11 +1649,30 @@ static void player_animate(void) offset[0] = vg_clampf( offset[0], -0.8f, 0.8f ); offset[1] = vg_clampf( offset[1], -0.5f, 0.0f ); + /* + * Player rotation + */ +#if 0 + float angle = v3_dot( player.rb.up, (v3f){0.0f,1.0f,0.0f} ); + v3f axis; + v3_cross( player.rb.up, (v3f){0.0f,1.0f,0.0f}, axis ); + + v4f correction; + if( angle < 0.99f && 0 ) + { + m3x3_mulv( player.rb.to_local, axis, axis ); + q_axis_angle( correction, axis, acosf(angle) ); + } + else + { + q_identity( correction ); + } /* * Animation blending * =========================================== */ +#endif static float fslide = 0.0f; static float fdirz = 0.0f; @@ -1673,7 +1712,7 @@ static void player_animate(void) character_final_pose( &player.mdl, offset, &pose_slide1, amt_slide*(1.0f-fdirx) ); - character_final_pose( &player.mdl, (v3f){0.0f,0.0f,0.0f}, + character_final_pose( &player.mdl, (v4f){0.0f,0.0f,0.0f,1.0f}, &pose_fly, amt_air ); /* diff --git a/world.h b/world.h index 0ebf23a..e8c47d2 100644 --- a/world.h +++ b/world.h @@ -62,6 +62,17 @@ static struct gworld mdl_submesh car_holden; rigidbody mr_ball; + + /* Load time */ + + struct instance_cache + { + mdl_header *mdl; + u32 pstr_file; + } + * instance_cache; + u32 instance_cache_count, + instance_cache_cap; } world; @@ -103,7 +114,8 @@ static void world_free(void) static void render_world_depth( m4x4f projection, m4x3f camera ); -static void add_all_if_material( scene *pscene, mdl_header *mdl, u32 id ) +static void add_all_if_material( m4x3f transform, scene *pscene, + mdl_header *mdl, u32 id ) { for( int i=0; inode_count; i++ ) { @@ -115,9 +127,27 @@ static void add_all_if_material( scene *pscene, mdl_header *mdl, u32 id ) if( sm->material_id == id ) { - m4x3f transform; - mdl_node_transform( pnode, transform ); - scene_add_submesh( pscene, mdl, sm, transform ); + m4x3f transform2; + mdl_node_transform( pnode, transform2 ); + m4x3_mul( transform, transform2, transform2 ); + + scene_add_submesh( pscene, mdl, sm, transform2 ); + } + } + + if( pnode->classtype == k_classtype_instance ) + { + if( pnode->sub_uid ) + { + u32 instance_id = pnode->sub_uid -1; + struct instance_cache *cache = &world.instance_cache[instance_id]; + mdl_header *mdl2 = cache->mdl; + + m4x3f transform2; + mdl_node_transform( pnode, transform2 ); + m4x3_mul( transform, transform2, transform2 ); + + add_all_if_material( transform2, pscene, mdl2, id ); } } } @@ -180,47 +210,7 @@ static void world_load(void) world.gate_count = 0; world.rb_count = 0; world.traffic_count = 0; - - scene_init( &world.geo ); - - /* - * Compile meshes into the world scenes - */ - u32 mat_surf = 0, - mat_surf_oob = 0, - mat_vertex_blend = 0; - - for( int i=1; imaterial_count; i++ ) - { - mdl_material *mat = mdl_material_from_id( mworld, i ); - const char *mat_name = mdl_pstr( mworld, mat->pstr_name ); - - vg_info( "%d %s\n", mat->pstr_name, mat_name ); - - if( !strcmp( "surf", mat_name )) - mat_surf = i; - else if( !strcmp( "surf_oob", mat_name )) - mat_surf_oob = i; - else if( !strcmp( "vertex_blend", mat_name )) - mat_vertex_blend = i; - } - - if( mat_surf_oob ) - add_all_if_material( &world.geo, mworld, mat_surf_oob ); - else - vg_warn( "No OOB surface\n" ); - scene_copy_slice( &world.geo, &world.sm_geo_std_oob ); - - if( mat_surf ) - add_all_if_material( &world.geo, mworld, mat_surf ); - scene_copy_slice( &world.geo, &world.sm_geo_std ); - - if( mat_vertex_blend ) - add_all_if_material( &world.geo, mworld, mat_vertex_blend ); - scene_copy_slice( &world.geo, &world.sm_geo_vb ); - - scene_upload( &world.geo ); - scene_bh_create( &world.geo ); + world.instance_cache = NULL; /* * Process entities @@ -309,13 +299,109 @@ static void world_load(void) pnode->sub_uid = world.traffic_count ++; } + else if( pnode->classtype == k_classtype_instance ) + { + struct classtype_instance *inst = mdl_get_entdata( mworld, pnode ); + pnode->sub_uid = 0; + + int cached = 0; + for( int i=0; ipstr_file == cache->pstr_file ) + { + cached = 1; + pnode->sub_uid = i+1; + break; + } + } + + if( !cached ) + { + world.instance_cache = buffer_reserve( + world.instance_cache, world.instance_cache_count, + &world.instance_cache_cap, 1, + sizeof(struct instance_cache) ); + + struct instance_cache *cache = + &world.instance_cache[world.instance_cache_count]; + + const char *filename = mdl_pstr(mworld, inst->pstr_file); + + cache->pstr_file = inst->pstr_file; + cache->mdl = mdl_load( filename ); + + if( cache->mdl ) + { + world.instance_cache_count ++; + pnode->sub_uid = world.instance_cache_count; + mdl_link_materials( mworld, cache->mdl ); + vg_success( "Cached %s\n", filename ); + } + else + { + vg_warn( "Failed to cache %s\n", filename ); + } + } + } } + world.instance_cache = buffer_fix( world.instance_cache, + world.instance_cache_count, + &world.instance_cache_cap, + sizeof( struct instance_cache ) ); + traffic_finalize( world.traffic, world.traffic_count ); for( int i=0; imaterial_count; i++ ) + { + mdl_material *mat = mdl_material_from_id( mworld, i ); + const char *mat_name = mdl_pstr( mworld, mat->pstr_name ); + + if( !strcmp( "surf", mat_name )) + mat_surf = i; + else if( !strcmp( "surf_oob", mat_name )) + mat_surf_oob = i; + else if( !strcmp( "vertex_blend", mat_name )) + mat_vertex_blend = i; + } + + vg_info( "surf %d\noob %d\nvert_blend %d\n", mat_surf, mat_surf_oob, + mat_vertex_blend ); + + m4x3f midentity; + m4x3_identity( midentity ); + + if( mat_surf_oob ) + add_all_if_material( midentity, &world.geo, mworld, mat_surf_oob ); + else + vg_warn( "No OOB surface\n" ); + scene_copy_slice( &world.geo, &world.sm_geo_std_oob ); + + if( mat_surf ) + add_all_if_material( midentity, &world.geo, mworld, mat_surf ); + scene_copy_slice( &world.geo, &world.sm_geo_std ); + + if( mat_vertex_blend ) + add_all_if_material( midentity, &world.geo, mworld, mat_vertex_blend ); + scene_copy_slice( &world.geo, &world.sm_geo_vb ); + + scene_upload( &world.geo ); + scene_bh_create( &world.geo ); + world_apply_foliage(); + free( world.instance_cache ); free( mworld ); /* @@ -386,6 +472,12 @@ static void world_init(void) vg_tex2d_init( (vg_tex2d *[]){ &tex_terrain_colours, &tex_terrain_noise }, 2 ); + mdl_header *mcars = mdl_load( "models/rs_cars.mdl" ); + mdl_unpack_glmesh( mcars, &world.cars ); + mdl_node *nholden = mdl_node_from_name( mcars, "holden" ); + world.car_holden = *mdl_node_submesh( mcars, nholden, 0 ); + free(mcars); + mdl_header *msky = mdl_load("models/rs_skydome.mdl"); mdl_unpack_glmesh( msky, &world.skydome ); @@ -397,12 +489,6 @@ static void world_init(void) world.dome_upper = *mdl_node_submesh( msky, nupper, 0 ); free(msky); - mdl_header *mcars = mdl_load( "models/rs_cars.mdl" ); - mdl_unpack_glmesh( mcars, &world.cars ); - mdl_node *nholden = mdl_node_from_name( mcars, "holden" ); - world.car_holden = *mdl_node_submesh( mcars, nholden, 0 ); - free(mcars); - /* * Setup scene collider */