instance support
[carveJwlIkooP6JGAAIwe30JlM.git] / world.h
diff --git a/world.h b/world.h
index add08b7c30d1180a1125a8a4c9a10dd2c9102c5e..e8c47d22085b8edad828aeccdaac3082739d97a0 100644 (file)
--- a/world.h
+++ b/world.h
@@ -48,17 +48,31 @@ static struct gworld
    /* Physics */
    rigidbody temp_rbs[128];
    u32 rb_count;
-   bh_tree bhcubes;
    
    /* Rendering & geometry */
-   scene geo, foliage, props;
-   mdl_submesh sm_surface, sm_other;
+   scene geo, foliage;
+   rigidbody rb_geo;
+
+   mdl_submesh sm_geo_std_oob, sm_geo_std, sm_geo_vb;
 
    glmesh skybox, skydome;
    mdl_submesh dome_upper, dome_lower;
 
    glmesh cars;
    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;
 
@@ -81,7 +95,7 @@ static int ray_world( v3f pos, v3f dir, ray_hit *hit )
 
 static int ray_hit_is_ramp( ray_hit *hit )
 {
-   return hit->tri[0] < world.sm_surface.vertex_count;
+   return hit->tri[0] > world.sm_geo_std_oob.vertex_count;
 }
 
 static void world_register(void)
@@ -100,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; i<mdl->node_count; i++ )
    {
@@ -112,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 );
          }
       }
    }
@@ -177,52 +210,7 @@ static void world_load(void)
    world.gate_count = 0;
    world.rb_count = 0;
    world.traffic_count = 0;
-
-   scene_init( &world.geo );
-   scene_init( &world.props );
-
-   /* 
-    * 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 )
-      add_all_if_material( &world.geo, mworld, mat_surf );
-   if( mat_vertex_blend )
-      add_all_if_material( &world.geo, mworld, mat_vertex_blend );
-
-
-   scene_copy_slice( &world.geo, &world.sm_surface );
-
-   if( mat_surf_oob )
-      add_all_if_material( &world.geo, mworld, mat_surf_oob );
-   else
-      vg_warn( "No OOB surface\n" );
-
-   scene_bh_create( &world.geo );
-   scene_upload( &world.geo );
-
-   if( mat_vertex_blend )
-      add_all_if_material( &world.props, mworld, mat_vertex_blend );
-
-   /* TODO  bvh? */
+   world.instance_cache = NULL;
    
    /*
     * Process entities
@@ -311,18 +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; 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)];
 
-   scene_upload( &world.props );
+   /* 
+    * 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;
+   }
 
-   bh_create( &world.bhcubes, 
-         &bh_system_rigidbodies, world.temp_rbs, world.rb_count );
+   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 );
 
    /* 
@@ -378,7 +457,14 @@ static void world_load(void)
 
    winfo->g_water_fog = 0.04f;
    render_update_lighting_ub();
+   
 
+   world.mr_ball.type = k_rb_shape_sphere;
+   world.mr_ball.inf.sphere.radius = 2.0f;
+   v3_copy( (v3f){ 0.0f, 110.0f, 0.0f }, world.mr_ball.co );
+
+   q_identity(world.mr_ball.q);
+   rb_init( &world.mr_ball );
 }
 
 static void world_init(void)
@@ -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,15 +489,32 @@ 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 
+    */
+   v3_zero( world.rb_geo.co );
+   q_identity( world.rb_geo.q );
+
+   world.rb_geo.type = k_rb_shape_scene;
+   world.rb_geo.inf.scene.pscene = &world.geo;
+   world.rb_geo.is_world = 1;
+   rb_init( &world.rb_geo );
 }
 
 static void world_update(void)
 {
+#if 0
+   rb_solver_reset();
+   rb_build_manifold_terrain_sphere( &world.mr_ball );
+   
+   for( int i=0; i<5; i++ )
+      rb_solve_contacts( rb_contact_buffer, rb_contact_count );
+
+   rb_iter( &world.mr_ball );
+   rb_update_transform( &world.mr_ball );
+   rb_debug( &world.mr_ball, 0 );
+#endif
+
    for( int i=0; i<vg_list_size(world.van_man); i++ )
    {
       traffic_drive( &world.van_man[i] );
@@ -423,7 +532,7 @@ static void bind_terrain_textures(void)
    vg_tex2d_bind( &tex_terrain_colours, 1 );
 }
 
-static void render_props( m4x4f projection, v3f camera )
+static void render_world_vb( m4x4f projection, v3f camera )
 {
    m4x3f identity_matrix;
    m4x3_identity( identity_matrix );
@@ -438,8 +547,8 @@ static void render_props( m4x4f projection, v3f camera )
    shader_vblend_uMdl( identity_matrix );
    shader_vblend_uCamera( camera );
 
-   scene_bind( &world.props );
-   scene_draw( &world.props );
+   scene_bind( &world.geo );
+   mdl_draw_submesh( &world.sm_geo_vb );
 
    mesh_bind( &world.cars );
 
@@ -466,7 +575,8 @@ static void render_terrain( m4x4f projection, v3f camera )
    shader_terrain_uCamera( camera );
 
    scene_bind( &world.geo );
-   scene_draw( &world.geo );
+   mdl_draw_submesh( &world.sm_geo_std_oob );
+   mdl_draw_submesh( &world.sm_geo_std );
 
    glDisable(GL_CULL_FACE);
    scene_bind( &world.foliage );
@@ -532,7 +642,7 @@ static void render_sky(m4x3f camera)
 static void render_world( m4x4f projection, m4x3f camera )
 {
    render_sky( camera );
-   render_props( projection, camera[3] );
+   render_world_vb( projection, camera[3] );
    render_terrain( projection, camera[3] );
 }
 
@@ -555,9 +665,6 @@ static void render_world_depth( m4x4f projection, m4x3f camera )
    scene_draw( &world.foliage );
    glEnable(GL_CULL_FACE);
 #endif
-
-   scene_bind( &world.props );
-   scene_draw( &world.props );
 }
 
 #endif /* WORLD_H */