_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
# 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
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 )
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
#
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 )
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 )
{
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 */
#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
u32 target, target1;
};
+struct classtype_instance
+{
+ u32 pstr_file;
+};
+
#pragma pack(pop)
/*
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; i<child->material_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; j<root->material_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; i<child->submesh_count; i++ )
+ {
+ mdl_submesh *sm = mdl_submesh_from_id( child, i );
+ sm->material_id = lookup[sm->material_id];
+ }
+}
+
#endif
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;
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;
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 );
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 );
}
}
+ 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 )
{
/* 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;
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;
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 );
/*
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;
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; i<mdl->node_count; i++ )
{
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 );
}
}
}
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; i<mworld->material_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
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; i<world.instance_cache_count; i++ )
+ {
+ struct instance_cache *cache = &world.instance_cache[i];
+ if( inst->pstr_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; i<vg_list_size(world.van_man); i++ )
world.van_man[i].current =&world.traffic[vg_randint(world.traffic_count)];
+ /*
+ * Compile meshes into the world scenes
+ */
+ scene_init( &world.geo );
+
+ u32 mat_surf = 0,
+ mat_surf_oob = 0,
+ mat_vertex_blend = 0;
+
+ for( int i=1; i<mworld->material_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 );
/*
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 );
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
*/