From 35b57a341eb37d863ec69e4f011a88b7bfba5c01 Mon Sep 17 00:00:00 2001 From: hgn Date: Mon, 7 Aug 2023 11:05:11 +0100 Subject: [PATCH] collision layers --- bvh.h | 2 ++ model.h | 21 +++++++++++++-------- player_ragdoll.c | 6 ++++-- player_skate.c | 30 +++++++++++++++++------------- player_walk.c | 18 ++++++++---------- rigidbody.h | 13 +++++++++---- scene.h | 42 ++++++++++++++++++++++++++++++++++++------ vehicle.c | 6 +++--- world_audio.c | 6 ++++-- world_gen.c | 7 ++++++- world_physics.c | 12 +++++++----- world_physics.h | 5 +++-- world_routes.c | 16 ++++++++-------- 13 files changed, 120 insertions(+), 64 deletions(-) diff --git a/bvh.h b/bvh.h index 1997bed..ce7fbe0 100644 --- a/bvh.h +++ b/bvh.h @@ -210,6 +210,7 @@ VG_STATIC void bh_debug_trace( bh_tree *bh, u32 inode, v3f pos, u32 colour ){ } } +#if 0 VG_STATIC int bh_ray( bh_tree *bh, v3f co, v3f dir, ray_hit *hit ){ if( bh->node_count < 2 ) return 0; @@ -258,6 +259,7 @@ VG_STATIC int bh_ray( bh_tree *bh, v3f co, v3f dir, ray_hit *hit ){ return count; } +#endif typedef struct bh_iter bh_iter; struct bh_iter{ diff --git a/model.h b/model.h index 43245ed..9f5bdb5 100644 --- a/model.h +++ b/model.h @@ -31,14 +31,19 @@ enum mdl_surface_prop{ }; enum material_flag{ - k_material_flag_skate_target = 0x00000001, - k_material_flag_collision = 0x00000002, - k_material_flag_grow_grass = 0x00000004, - k_material_flag_grindable = 0x00000008, - k_material_flag_invisible = 0x00000010, - k_material_flag_boundary = 0x00000020, - k_material_flag_preview_visibile = 0x00000040, - k_material_flag_walking = 0x00000080 + k_material_flag_skate_target = 0x0001, + k_material_flag_collision = 0x0002, + k_material_flag_grow_grass = 0x0004, + k_material_flag_grindable = 0x0008, + k_material_flag_invisible = 0x0010, + k_material_flag_boundary = 0x0020, + k_material_flag_preview_visibile = 0x0040, + k_material_flag_walking = 0x0080, + + k_material_flag_ghosts = + k_material_flag_boundary| + k_material_flag_invisible| + k_material_flag_walking }; #pragma pack(push,1) diff --git a/player_ragdoll.c b/player_ragdoll.c index 0952eb6..3dc7ba6 100644 --- a/player_ragdoll.c +++ b/player_ragdoll.c @@ -295,12 +295,14 @@ VG_STATIC void player_ragdoll_iter( struct player_ragdoll *rd ) if( rd->parts[i].obj.type == k_rb_shape_capsule ){ l = rb_capsule__scene( rd->parts[i].obj.rb.to_world, &rd->parts[i].obj.inf.capsule, - NULL, &world->rb_geo.inf.scene, buf ); + NULL, &world->rb_geo.inf.scene, buf, + k_material_flag_ghosts ); } else if( rd->parts[i].obj.type == k_rb_shape_box ){ l = rb_box__scene( rd->parts[i].obj.rb.to_world, rd->parts[i].obj.rb.bbx, - NULL, &world->rb_geo.inf.scene, buf ); + NULL, &world->rb_geo.inf.scene, buf, + k_material_flag_ghosts ); } else continue; diff --git a/player_skate.c b/player_skate.c index a789907..fcaffd9 100644 --- a/player_skate.c +++ b/player_skate.c @@ -59,18 +59,17 @@ VG_STATIC int skate_collide_smooth( player_instance *player, world_instance *world = world_current_instance(); int len = 0; - len = rb_sphere__scene( mtx, sphere, NULL, &world->rb_geo.inf.scene, man ); + len = rb_sphere__scene( mtx, sphere, NULL, &world->rb_geo.inf.scene, man, + k_material_flag_walking ); - for( int i=0; irb; man[i].rbb = NULL; } rb_manifold_filter_coplanar( man, len, 0.03f ); - if( len > 1 ) - { + if( len > 1 ){ rb_manifold_filter_backface( man, len ); rb_manifold_filter_joint_edges( man, len, 0.03f ); rb_manifold_filter_pairs( man, len, 0.03f ); @@ -511,7 +510,8 @@ void player__approximate_best_trajectory( player_instance *player ) float scan_radius = k_board_radius; scan_radius *= vg_clampf( t, 0.02f, 1.0f ); - int idx = spherecast_world(trace_world, co0, co1, scan_radius, &t1, n); + int idx = spherecast_world( trace_world, co0, co1, scan_radius, &t1, n, + k_material_flag_walking ); if( idx != -1 ){ v3f co; v3_lerp( co0, co1, t1, co ); @@ -598,7 +598,8 @@ void player__approximate_best_trajectory( player_instance *player ) v3f n; int idx = spherecast_world( world0, co0,co1, - k_board_radius*0.1f, &t1, n); + k_board_radius*0.1f, &t1, n, + k_material_flag_walking ); if( idx != -1 ){ goto invalidated_grind; } @@ -1332,7 +1333,7 @@ int skate_compute_surface_alignment( player_instance *player, v3_muladds( left, player->rb.to_world[1], k_board_radius, left ); ray_l.dist = 2.1f * k_board_radius; - res_l = ray_world( world, left, dir, &ray_l ); + res_l = ray_world( world, left, dir, &ray_l, k_material_flag_walking ); if( res_l ) break; @@ -1344,7 +1345,7 @@ int skate_compute_surface_alignment( player_instance *player, v3_muladds( right, player->rb.to_world[1], k_board_radius, right ); ray_r.dist = 2.1f * k_board_radius; - res_r = ray_world( world, right, dir, &ray_r ); + res_r = ray_world( world, right, dir, &ray_r, k_material_flag_walking ); if( res_r ) break; @@ -1511,7 +1512,8 @@ VG_STATIC int skate_point_visible( v3f origin, v3f target ){ v3_muls( dir, 1.0f/ray.dist, dir ); ray.dist -= 0.025f; - if( ray_world( world_current_instance(), origin, dir, &ray ) ) + if( ray_world( world_current_instance(), origin, dir, &ray, + k_material_flag_walking ) ) return 0; return 1; @@ -2282,7 +2284,8 @@ begin_collision:; v3f n; float cast_radius = wheels[i].radius - k_penetration_slop * 2.0f; - if( spherecast_world( world, current, future, cast_radius, &t, n ) != -1) + if( spherecast_world( world, current, future, cast_radius, &t, n, + k_material_flag_walking ) != -1) max_time = vg_minf( max_time, t * s->substep ); } @@ -2329,7 +2332,8 @@ begin_collision:; float t; v3f n; if( (v3_dist2( head_wp0, head_wp1 ) > 0.001f) && - (spherecast_world( world, head_wp0, head_wp1, 0.2f, &t, n ) != -1) ) + (spherecast_world( world, head_wp0, head_wp1, 0.2f, &t, n, + k_material_flag_walking ) != -1) ) { v3_lerp( start_co, player->rb.co, t, player->rb.co ); rb_update_transform( &player->rb ); @@ -2376,7 +2380,7 @@ begin_collision:; rb_ct *cman = &manifold[manifold_len]; int l = rb_capsule__scene( mtx, &capsule, NULL, &world->rb_geo.inf.scene, - cman ); + cman, k_material_flag_walking ); /* weld joints */ for( int i=0; idist = 2.0f; - if( ray_world( world, pos, ray_dir, ray ) ) - { + if( ray_world( world, pos, ray_dir, ray, 0 ) ){ vg_line( pos, ray->pos, VG__RED ); vg_line_point( ray->pos, 0.025f, VG__BLACK ); @@ -219,8 +218,7 @@ VG_STATIC int player_walk_scan_for_drop_in( player_instance *player ) ray_hit ray; ray.dist = k_board_length*2.0f + 0.6f; - if( ray_world( world, va, v0, &ray ) ) - { + if( ray_world( world, va, v0, &ray, 0 ) ){ vg_line( va, vb, VG__RED ); vg_line_point( ray.pos, 0.1f, VG__RED ); vg_error( "invalidated\n" ); @@ -228,8 +226,7 @@ VG_STATIC int player_walk_scan_for_drop_in( player_instance *player ) } v3_muls( v0, -1.0f, v0 ); - if( ray_world( world, vb, v0, &ray ) ) - { + if( ray_world( world, vb, v0, &ray, 0 ) ){ vg_line( va, vb, VG__RED ); vg_line_point( ray.pos, 0.1f, VG__RED ); vg_error( "invalidated\n" ); @@ -457,7 +454,7 @@ VG_STATIC void player__walk_update( player_instance *player ){ */ len = rb_capsule__scene( mtx, &w->collider, NULL, - &world->rb_geo.inf.scene, manifold ); + &world->rb_geo.inf.scene, manifold, 0 ); player_walk_custom_filter( world, manifold, len, 0.01f ); len = rb_manifold_apply_filtered( manifold, len ); @@ -570,7 +567,8 @@ VG_STATIC void player__walk_update( player_instance *player ){ v3f n; float t; - if( spherecast_world( world, pa, pb, w->collider.radius, &t, n ) != -1 ){ + if( spherecast_world( world, pa, pb, + w->collider.radius, &t, n, 0 ) != -1 ){ if( player_walk_normal_standable( player, n ) ){ v3_lerp( pa, pb, t, player->rb.co ); v3_muladds( player->rb.co, player->basis[1], @@ -624,13 +622,13 @@ VG_STATIC void player__walk_update( player_instance *player ){ float t, sr = w->collider.radius-0.04f; v3f n; - if( spherecast_world( world, lwr_prev, lwr_now, sr, &t, n ) != -1 ){ + if( spherecast_world( world, lwr_prev, lwr_now, sr, &t, n, 0 ) != -1 ){ v3_lerp( lwr_prev, lwr_now, vg_maxf(0.01f,t), player->rb.co ); player->rb.co[1] -= w->collider.radius; rb_update_transform( &player->rb ); v3_add( player->rb.co, player->basis[1], mtx[3] ); - vg_line_capsule( mtx, w->collider.radius, w->collider.height, VG__RED ); + vg_line_capsule( mtx, w->collider.radius, w->collider.height, VG__RED); } } diff --git a/rigidbody.h b/rigidbody.h index 1c1e8c8..d19b786 100644 --- a/rigidbody.h +++ b/rigidbody.h @@ -872,7 +872,8 @@ VG_STATIC int rb_sphere__triangle( m4x3f mtxA, rb_sphere *b, } VG_STATIC int rb_sphere__scene( m4x3f mtxA, rb_sphere *b, - m4x3f mtxB, rb_scene *s, rb_ct *buf ){ + m4x3f mtxB, rb_scene *s, rb_ct *buf, + u16 ignore ){ scene_context *sc = s->bh_scene->user; int count = 0; @@ -890,6 +891,8 @@ VG_STATIC int rb_sphere__scene( m4x3f mtxA, rb_sphere *b, u32 *ptri = &sc->arrindices[ idx*3 ]; v3f tri[3]; + if( sc->arrvertices[ptri[0]].flags & ignore ) continue; + for( int j=0; j<3; j++ ) v3_copy( sc->arrvertices[ptri[j]].co, tri[j] ); @@ -912,7 +915,7 @@ VG_STATIC int rb_sphere__scene( m4x3f mtxA, rb_sphere *b, } VG_STATIC int rb_box__scene( m4x3f mtxA, boxf bbx, - m4x3f mtxB, rb_scene *s, rb_ct *buf ){ + m4x3f mtxB, rb_scene *s, rb_ct *buf, u16 ignore ){ scene_context *sc = s->bh_scene->user; v3f tri[3]; @@ -942,6 +945,7 @@ VG_STATIC int rb_box__scene( m4x3f mtxA, boxf bbx, while( bh_next( s->bh_scene, &it, &idx ) ){ u32 *ptri = &sc->arrindices[ idx*3 ]; + if( sc->arrvertices[ptri[0]].flags & ignore ) continue; for( int j=0; j<3; j++ ) v3_copy( sc->arrvertices[ptri[j]].co, tri[j] ); @@ -1126,7 +1130,7 @@ VG_STATIC int rb_capsule__triangle( m4x3f mtxA, rb_capsule *c, /* mtxB is defined only for tradition; it is not used currently */ VG_STATIC int rb_capsule__scene( m4x3f mtxA, rb_capsule *c, m4x3f mtxB, rb_scene *s, - rb_ct *buf ){ + rb_ct *buf, u16 ignore ){ int count = 0; boxf bbx; @@ -1140,8 +1144,9 @@ VG_STATIC int rb_capsule__scene( m4x3f mtxA, rb_capsule *c, i32 idx; while( bh_next( s->bh_scene, &it, &idx ) ){ u32 *ptri = &sc->arrindices[ idx*3 ]; - v3f tri[3]; + if( sc->arrvertices[ptri[0]].flags & ignore ) continue; + v3f tri[3]; for( int j=0; j<3; j++ ) v3_copy( sc->arrvertices[ptri[j]].co, tri[j] ); diff --git a/scene.h b/scene.h index 83badb2..cee7e69 100644 --- a/scene.h +++ b/scene.h @@ -17,7 +17,8 @@ struct scene_vert v3f co; /* 3*32 */ v2f uv; /* 2*32 */ i8 norm[4]; /* 4*8 */ - u16 unused[4]; + u16 flags; /* only for the cpu. its junk on the gpu */ + u16 unused[3]; }; #pragma pack(pop) @@ -204,6 +205,12 @@ VG_STATIC void scene_copy_slice( scene_context *ctx, mdl_submesh *sm ) ctx->submesh.vertex_start = ctx->vertex_count; } +VG_STATIC void scene_set_vertex_flags( scene_context *ctx, + u32 start, u32 count, u16 flags ){ + for( u32 i=0; iarrvertices[ start + i ].flags = flags; +} + struct scene_upload_info{ scene_context *ctx; glmesh *mesh; @@ -364,6 +371,7 @@ VG_STATIC void scene_bh_debug( void *user, u32 item_index ) vg_line( pc->co, pa->co, 0xff0000ff ); } +#if 0 VG_STATIC int scene_bh_ray( void *user, u32 index, v3f co, v3f dir, ray_hit *hit ) { @@ -386,6 +394,7 @@ VG_STATIC int scene_bh_ray( void *user, u32 index, v3f co, return 0; } +#endif VG_STATIC void scene_bh_closest( void *user, u32 index, v3f point, v3f closest ) { @@ -406,18 +415,39 @@ VG_STATIC bh_system bh_system_scene = .item_closest = scene_bh_closest, .item_swap = scene_bh_swap, .item_debug = scene_bh_debug, - .cast_ray = scene_bh_ray }; /* * An extra step is added onto the end to calculate the hit normal */ VG_STATIC int scene_raycast( scene_context *s, bh_tree *bh, - v3f co, v3f dir, ray_hit *hit ) + v3f co, v3f dir, ray_hit *hit, u16 ignore ) { - int count = bh_ray( bh, co, dir, hit ); + hit->tri = NULL; + + bh_iter it; + bh_iter_init_ray( 0, &it, co, dir, hit->dist ); + i32 idx; + + while( bh_next( bh, &it, &idx ) ){ + u32 *tri = &s->arrindices[ idx*3 ]; + + if( s->arrvertices[tri[0]].flags & ignore ) continue; + + v3f vs[3]; + for( u32 i=0; i<3; i++ ) + v3_copy( s->arrvertices[tri[i]].co, vs[i] ); + + f32 t; + if( ray_tri( vs, co, dir, &t ) ){ + if( t < hit->dist ){ + hit->dist = t; + hit->tri = tri; + } + } + } - if( count ){ + if( hit->tri ){ v3f v0, v1; float *pa = s->arrvertices[hit->tri[0]].co, @@ -431,7 +461,7 @@ VG_STATIC int scene_raycast( scene_context *s, bh_tree *bh, v3_muladds( co, dir, hit->dist, hit->pos ); } - return count; + return hit->tri?1:0; } VG_STATIC bh_tree *scene_bh_create( void *lin_alloc, scene_context *s ) diff --git a/vehicle.c b/vehicle.c index a171a8d..d9c6d30 100644 --- a/vehicle.c +++ b/vehicle.c @@ -10,7 +10,7 @@ VG_STATIC int spawn_car( int argc, const char *argv[] ){ float t; if( spherecast_world( world_current_instance(), ra, rb, - gzoomer.obj.inf.sphere.radius, &t, rx ) != -1 ) + gzoomer.obj.inf.sphere.radius, &t, rx, 0 ) != -1 ) { v3_lerp( ra, rb, t, gzoomer.obj.rb.co ); gzoomer.obj.rb.co[1] += 4.0f; @@ -68,7 +68,7 @@ VG_STATIC void vehicle_wheel_force( int index ) #if 1 float t; if( spherecast_world( world_current_instance(), pa, pb, - k_car_wheel_radius, &t, n ) == -1 ) + k_car_wheel_radius, &t, n, 0 ) == -1 ) { t = 1.0f; } @@ -225,7 +225,7 @@ VG_STATIC void vehicle_update_fixed(void) rb_ct manifold[64]; int len = rb_sphere__scene( rb->to_world, &gzoomer.obj.inf.sphere, NULL, &world_current_instance()->rb_geo.inf.scene, - manifold ); + manifold, 0 ); for( int j=0; jrb_geo.rb; diff --git a/world_audio.c b/world_audio.c index a8e88d6..8a167e4 100644 --- a/world_audio.c +++ b/world_audio.c @@ -44,7 +44,8 @@ enum audio_sprite_type world_audio_sample_sprite_random(v3f origin, v3f output) world_instance *world = world_current_instance(); - if( ray_world( world, pos, (v3f){0.0f,-1.0f,0.0f}, &contact ) ){ + if( ray_world( world, pos, (v3f){0.0f,-1.0f,0.0f}, &contact, + k_material_flag_ghosts ) ){ struct world_surface *mat = ray_hit_surface( world, &contact ); if( mat->info.surface_prop == k_surface_prop_grass){ @@ -104,7 +105,8 @@ VG_STATIC void world_audio_sample_distances( v3f co, int *index, float *value ) float dist = 200.0f; for( int i=0; i<10; i++ ){ - if( ray_world( world_current_instance(), rc, rd, &ray ) ){ + if( ray_world( world_current_instance(), rc, rd, &ray, + k_material_flag_ghosts ) ){ dist = (float)i*5.0f + ray.dist; break; } diff --git a/world_gen.c b/world_gen.c index 2650539..b522cba 100644 --- a/world_gen.c +++ b/world_gen.c @@ -136,7 +136,8 @@ VG_STATIC void world_apply_procedural_foliage( world_instance *world, ray_hit hit; hit.dist = INFINITY; - if( ray_world( world, pos, (v3f){0.0f,-1.0f,0.0f}, &hit )){ + if( ray_world( world, pos, (v3f){0.0f,-1.0f,0.0f}, &hit, + k_material_flag_ghosts )){ struct world_surface *m1 = ray_hit_surface( world, &hit ); if((hit.normal[1] > 0.8f) && (m1 == mat) && (hit.pos[1] > 0.0f+10.0f)){ world_gen_add_blob( world, scene, &hit ); @@ -191,6 +192,10 @@ VG_STATIC void world_gen_generate_meshes( world_instance *world ){ &world->meta, i ); scene_copy_slice( &world->scene_geo, &surf->sm_geo ); + scene_set_vertex_flags( &world->scene_geo, + surf->sm_geo.vertex_start, + surf->sm_geo.vertex_count, + (u16)(surf->info.flags & 0xffff) ); } /* compress that bad boy */ diff --git a/world_physics.c b/world_physics.c index 96ffa2f..fb68eb5 100644 --- a/world_physics.c +++ b/world_physics.c @@ -12,16 +12,18 @@ VG_STATIC void ray_world_get_tri( world_instance *world, } VG_STATIC int ray_world( world_instance *world, - v3f pos, v3f dir, ray_hit *hit ) + v3f pos, v3f dir, ray_hit *hit, u16 ignore ) { - return scene_raycast( &world->scene_geo, world->geo_bh, pos, dir, hit ); + return scene_raycast( &world->scene_geo, world->geo_bh, pos, dir, hit, + ignore ); } /* * Cast a sphere from a to b and see what time it hits */ VG_STATIC int spherecast_world( world_instance *world, - v3f pa, v3f pb, float r, float *t, v3f n ) + v3f pa, v3f pb, float r, float *t, v3f n, + u16 ignore ) { boxf region; box_init_inf( region ); @@ -47,11 +49,11 @@ VG_STATIC int spherecast_world( world_instance *world, i32 idx; while( bh_next( world->geo_bh, &it, &idx ) ){ u32 *ptri = &world->scene_geo.arrindices[ idx*3 ]; - v3f tri[3]; + if( world->scene_geo.arrvertices[ptri[0]].flags & ignore ) continue; + v3f tri[3]; boxf box; box_init_inf( box ); - for( int j=0; j<3; j++ ){ v3_copy( world->scene_geo.arrvertices[ptri[j]].co, tri[j] ); box_addpt( box, tri[j] ); diff --git a/world_physics.h b/world_physics.h index 3a5561d..2a38330 100644 --- a/world_physics.h +++ b/world_physics.h @@ -8,10 +8,11 @@ VG_STATIC void ray_world_get_tri( world_instance *world, ray_hit *hit, v3f tri[3] ); VG_STATIC int ray_world( world_instance *world, - v3f pos, v3f dir, ray_hit *hit ); + v3f pos, v3f dir, ray_hit *hit, u16 ignore ); VG_STATIC int spherecast_world( world_instance *world, - v3f pa, v3f pb, float r, float *t, v3f n ); + v3f pa, v3f pb, float r, float *t, v3f n, + u16 ignore ); VG_STATIC struct world_surface *world_tri_index_surface( world_instance *world, u32 index ); diff --git a/world_routes.c b/world_routes.c index bd91b3c..8dd2a8f 100644 --- a/world_routes.c +++ b/world_routes.c @@ -365,8 +365,8 @@ void world_routes_place_curve( world_instance *world, ent_route *route, ha.dist = 8.0f; hb.dist = 8.0f; - int resa = ray_world( world, sa, down, &ha ), - resb = ray_world( world, sb, down, &hb ); + int resa = ray_world( world, sa, down, &ha, k_material_flag_ghosts ), + resb = ray_world( world, sb, down, &hb, k_material_flag_ghosts ); if( pcbuf && resa ){ world_routes_pointcloud_spot( world, pcbuf, ha.pos, @@ -712,6 +712,10 @@ VG_STATIC void world_routes_surface_grid( world_instance *world, u32 *tri = &world->scene_geo.arrindices[ idx*3 ]; v3f vs[3]; + u16 mask = k_material_flag_preview_visibile; + if( !(world->scene_geo.arrvertices[tri[0]].flags & mask) ) + continue; + for( u32 i=0; i<3; i++ ){ v3_copy( world->scene_geo.arrvertices[tri[i]].co, vs[i] ); } @@ -719,11 +723,6 @@ VG_STATIC void world_routes_surface_grid( world_instance *world, f32 t; if( ray_tri( vs, ro, dir, &t ) ){ v3_muladds( ro, dir, t, hit ); - struct world_surface *m1 = - world_tri_index_surface( world, tri[0] ); - - if( !(m1->info.flags & k_material_flag_preview_visibile) ) - continue; if( world->water.enabled ) if( hit[1] < world->water.height ) @@ -980,7 +979,8 @@ VG_STATIC void world_routes_fixedupdate( world_instance *world ) int l = rb_sphere__scene( particle->obj.rb.to_world, &particle->obj.inf.sphere, - NULL, &world->rb_geo.inf.scene, buf ); + NULL, &world->rb_geo.inf.scene, buf, + k_material_flag_ghosts ); for( int j=0; jobj.rb; -- 2.25.1