From e5dfbef890431a69291a9f0a9ca4a88ea8d0705a Mon Sep 17 00:00:00 2001 From: hgn Date: Tue, 11 Apr 2023 17:12:25 +0100 Subject: [PATCH 1/1] a change to rigidbody semantics --- common.h | 3 - highscores.h | 3 +- player.c | 6 +- player_dead.c | 12 +- player_ragdoll.h | 94 ++--- rigidbody.h | 958 ++++++++--------------------------------------- skaterift.c | 2 +- world.h | 47 ++- world_gen.h | 9 +- world_routes.h | 213 +++++++---- 10 files changed, 382 insertions(+), 965 deletions(-) diff --git a/common.h b/common.h index 0aaab5d..9eda6f6 100644 --- a/common.h +++ b/common.h @@ -17,9 +17,6 @@ #define RESET_MAX_TIME 45.0 VG_STATIC v3f TEMP_BOARD_0, TEMP_BOARD_1; -#include "font.h" -VG_STATIC font3d test_font; - enum menu_controller_type { k_menu_controller_type_keyboard, diff --git a/highscores.h b/highscores.h index f49537f..079e4d8 100644 --- a/highscores.h +++ b/highscores.h @@ -482,8 +482,7 @@ VG_STATIC void highscore_strr( char *buf, const char *str, int len, int width ) VG_STATIC void highscore_intr( char *buf, int value, int len, char alt ) { int i=0; - while(value) - { + while(value){ if( i>=len ) return; diff --git a/player.c b/player.c index ea29b4c..01a0b52 100644 --- a/player.c +++ b/player.c @@ -385,10 +385,6 @@ VG_STATIC void player__pre_render( player_instance *player ) float budget = vg.time_delta, overall_length = player->rewind_length; -#if 0 - world_routes_rollback_time( player.rewind_time / overall_length ); -#endif - for( int i=0; (i<10)&&(player->rewind_time>0.0f)&&(budget>0.0f); i++ ){ /* Interpolate frames */ int i0 = floorf( player->rewind_time ), @@ -400,7 +396,7 @@ VG_STATIC void player__pre_render( player_instance *player ) float dist = vg_maxf( v3_dist( fr->pos, fr1->pos ), 0.001f ), subl = vg_fractf( player->rewind_time ) + 0.001f, - sramp= 3.0f-(1.0f/(0.4f+0.4f*player->rewind_time)), + sramp = 3.0f-(1.0f/(0.4f+0.4f*player->rewind_time)), speed = sramp*28.0f + 0.5f*player->rewind_time, mod = speed * (budget / dist), diff --git a/player_dead.c b/player_dead.c index da23487..e06c20a 100644 --- a/player_dead.c +++ b/player_dead.c @@ -31,9 +31,9 @@ VG_STATIC void player__dead_post_animate( player_instance *player ) struct ragdoll_part *part = &player->ragdoll.parts[ av->id_hip-1 ]; - v3_lerp( d->co_lpf, part->rb.co, vg.frame_delta*4.0f, d->co_lpf ); - v3_lerp( d->v_lpf, part->rb.v, vg.frame_delta*4.0f, d->v_lpf ); - v3_lerp( d->w_lpf, part->rb.w, vg.frame_delta*4.0f, d->w_lpf ); + v3_lerp( d->co_lpf, part->obj.rb.co, vg.frame_delta*4.0f, d->co_lpf ); + v3_lerp( d->v_lpf, part->obj.rb.v, vg.frame_delta*4.0f, d->v_lpf ); + v3_lerp( d->w_lpf, part->obj.rb.w, vg.frame_delta*4.0f, d->w_lpf ); v3_copy( d->co_lpf, player->rb.co ); v3_copy( d->v_lpf, player->rb.v ); @@ -54,9 +54,9 @@ VG_STATIC void player__dead_transition ( player_instance *player ) struct player_avatar *av = player->playeravatar; struct ragdoll_part *part = &player->ragdoll.parts[ av->id_hip-1 ]; struct player_dead *d = &player->_dead; - v3_copy( part->rb.co, d->co_lpf ); - v3_copy( part->rb.v, d->v_lpf ); - v3_copy( part->rb.w, d->w_lpf ); + v3_copy( part->obj.rb.co, d->co_lpf ); + v3_copy( part->obj.rb.v, d->v_lpf ); + v3_copy( part->obj.rb.w, d->w_lpf ); } #endif /* PLAYER_DEAD_C */ diff --git a/player_ragdoll.h b/player_ragdoll.h index e471163..c44060a 100644 --- a/player_ragdoll.h +++ b/player_ragdoll.h @@ -9,10 +9,8 @@ #include "world.h" #include "audio.h" -struct player_ragdoll -{ - struct ragdoll_part - { +struct player_ragdoll{ + struct ragdoll_part{ u32 bone_id; /* Collider transform relative to bone */ @@ -22,7 +20,7 @@ struct player_ragdoll u32 use_limits; v3f limits[2]; - rigidbody rb; + rb_object obj; u32 parent; u32 colour; } @@ -49,11 +47,11 @@ VG_STATIC void player_init_ragdoll_bone_collider( struct skeleton_bone *bone, v3_muls( delta, 0.5f, delta ); v3_add( bone->hitbox[0], delta, rp->collider_mtx[3] ); - v3_copy( delta, rp->rb.bbx[1] ); - v3_muls( delta, -1.0f, rp->rb.bbx[0] ); + v3_copy( delta, rp->obj.rb.bbx[1] ); + v3_muls( delta, -1.0f, rp->obj.rb.bbx[0] ); - q_identity( rp->rb.q ); - rp->rb.type = k_rb_shape_box; + q_identity( rp->obj.rb.q ); + rp->obj.type = k_rb_shape_box; rp->colour = 0xffcccccc; } else if( bone->collider == k_bone_collider_capsule ){ @@ -84,9 +82,9 @@ VG_STATIC void player_init_ragdoll_bone_collider( struct skeleton_bone *bone, v3_add( bone->hitbox[0], bone->hitbox[1], rp->collider_mtx[3] ); v3_muls( rp->collider_mtx[3], 0.5f, rp->collider_mtx[3] ); - rp->rb.type = k_rb_shape_capsule; - rp->rb.inf.capsule.height = l; - rp->rb.inf.capsule.radius = r; + rp->obj.type = k_rb_shape_capsule; + rp->obj.inf.capsule.height = l; + rp->obj.inf.capsule.radius = r; rp->colour = 0xff000000 | (0xff << (major_axis*8)); } @@ -98,10 +96,11 @@ VG_STATIC void player_init_ragdoll_bone_collider( struct skeleton_bone *bone, m4x3_invert_affine( rp->collider_mtx, rp->inv_collider_mtx ); /* Position collider into rest */ - m3x3_q( rp->collider_mtx, rp->rb.q ); - v3_add( rp->collider_mtx[3], bone->co, rp->rb.co ); - rp->rb.is_world = 0; - rb_init( &rp->rb ); + m3x3_q( rp->collider_mtx, rp->obj.rb.q ); + v3_add( rp->collider_mtx[3], bone->co, rp->obj.rb.co ); + v3_zero( rp->obj.rb.v ); + v3_zero( rp->obj.rb.w ); + rb_init_object( &rp->obj ); } /* @@ -168,8 +167,8 @@ VG_STATIC void player_setup_ragdoll_from_avatar( struct player_ragdoll *rd, struct skeleton_bone *bp = &av->sk.bones[pp->bone_id]; /* Convention: rba -- parent, rbb -- child */ - c->rba = &pp->rb; - c->rbb = &rp->rb; + c->rba = &pp->obj.rb; + c->rbb = &rp->obj.rb; v3f delta; v3_sub( bj->co, bp->co, delta ); @@ -182,8 +181,8 @@ VG_STATIC void player_setup_ragdoll_from_avatar( struct player_ragdoll *rd, struct rb_constr_swingtwist *a = &rd->cone_constraints[ rd->cone_constraints_count ++ ]; - a->rba = &pp->rb; - a->rbb = &rp->rb; + a->rba = &pp->obj.rb; + a->rbb = &rp->obj.rb; a->conet = cosf( inf->conet )-0.0001f; /* Store constraint in local space vectors */ @@ -218,7 +217,7 @@ VG_STATIC void copy_ragdoll_pose_to_avatar( struct player_ragdoll *rd, struct ragdoll_part *part = &rd->parts[i]; m4x3f offset; m3x3_identity(offset); - m4x3_mul( part->rb.to_world, part->inv_collider_mtx, + m4x3_mul( part->obj.rb.to_world, part->inv_collider_mtx, av->sk.final_mtx[part->bone_id] ); } @@ -256,16 +255,16 @@ VG_STATIC void copy_avatar_pose_to_ragdoll( struct player_avatar *av, m4x3_mulv( av->sk.final_mtx[bone], av->sk.bones[bone].co, pos ); m3x3_mulv( av->sk.final_mtx[bone], part->collider_mtx[3], offset ); - v3_add( pos, offset, part->rb.co ); + v3_add( pos, offset, part->obj.rb.co ); m3x3f r; m3x3_mul( av->sk.final_mtx[bone], part->collider_mtx, r ); - m3x3_q( r, part->rb.q ); + m3x3_q( r, part->obj.rb.q ); - v3_copy( velocity, part->rb.v ); - v3_zero( part->rb.w ); + v3_copy( velocity, part->obj.rb.v ); + v3_zero( part->obj.rb.w ); - rb_update_transform( &part->rb ); + rb_update_transform( &part->obj.rb ); } } @@ -301,21 +300,21 @@ VG_STATIC void player_ragdoll_iter( struct player_ragdoll *rd ) int l; - if( rd->parts[i].rb.type == k_rb_shape_capsule ){ - l = rb_capsule__scene( rd->parts[i].rb.to_world, - &rd->parts[i].rb.inf.capsule, + 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 ); } - else if( rd->parts[i].rb.type == k_rb_shape_box ){ - l = rb_box__scene( rd->parts[i].rb.to_world, - rd->parts[i].rb.bbx, + 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 ); } else continue; for( int j=0; jparts[i].rb; - buf[j].rbb = &world->rb_geo; + buf[j].rba = &rd->parts[i].obj.rb; + buf[j].rbb = &world->rb_geo.rb; } rb_contact_count += l; @@ -331,23 +330,23 @@ VG_STATIC void player_ragdoll_iter( struct player_ragdoll *rd ) if( !rb_global_has_space() ) break; - if( rd->parts[j].rb.type != k_rb_shape_capsule ) + if( rd->parts[j].obj.type != k_rb_shape_capsule ) continue; - if( rd->parts[i].rb.type != k_rb_shape_capsule ) + if( rd->parts[i].obj.type != k_rb_shape_capsule ) continue; rb_ct *buf = rb_global_buffer(); - int l = rb_capsule__capsule( rd->parts[i].rb.to_world, - &rd->parts[i].rb.inf.capsule, - rd->parts[j].rb.to_world, - &rd->parts[j].rb.inf.capsule, + int l = rb_capsule__capsule( rd->parts[i].obj.rb.to_world, + &rd->parts[i].obj.inf.capsule, + rd->parts[j].obj.rb.to_world, + &rd->parts[j].obj.inf.capsule, buf ); for( int k=0; kparts[i].rb; - buf[k].rbb = &rd->parts[j].rb; + buf[k].rba = &rd->parts[i].obj.rb; + buf[k].rbb = &rd->parts[j].obj.rb; } rb_contact_count += l; @@ -360,8 +359,9 @@ VG_STATIC void player_ragdoll_iter( struct player_ragdoll *rd ) if( run_sim ){ v4f plane = {0.0f,1.0f,0.0f,0.0f}; - rb_effect_simple_bouyency( &pj->rb, plane, k_ragdoll_floatyiness, - k_ragdoll_floatydrag ); + rb_effect_simple_bouyency( &pj->obj.rb, plane, + k_ragdoll_floatyiness, + k_ragdoll_floatydrag ); } } @@ -389,7 +389,7 @@ VG_STATIC void player_ragdoll_iter( struct player_ragdoll *rd ) */ if( k_ragdoll_debug_collider ){ for( u32 i=0; ipart_count; i ++ ) - rb_debug( &rd->parts[i].rb, rd->parts[i].colour ); + rb_object_debug( &rd->parts[i].obj, rd->parts[i].colour ); } if( k_ragdoll_debug_constraints ){ @@ -413,10 +413,10 @@ VG_STATIC void player_ragdoll_iter( struct player_ragdoll *rd ) } for( int i=0; ipart_count; i++ ) - rb_iter( &rd->parts[i].rb ); + rb_iter( &rd->parts[i].obj.rb ); for( int i=0; ipart_count; i++ ) - rb_update_transform( &rd->parts[i].rb ); + rb_update_transform( &rd->parts[i].obj.rb ); rb_correct_swingtwist_constraints( rd->cone_constraints, rd->cone_constraints_count, 0.25f ); diff --git a/rigidbody.h b/rigidbody.h index 3987913..f2f36cb 100644 --- a/rigidbody.h +++ b/rigidbody.h @@ -72,6 +72,7 @@ VG_STATIC void rb_register_cvar(void) */ typedef struct rigidbody rigidbody; +typedef struct rb_object rb_object; typedef struct contact rb_ct; typedef struct rb_sphere rb_sphere; typedef struct rb_capsule rb_capsule; @@ -97,8 +98,20 @@ struct rigidbody v3f co, v, w; v4f q; - enum rb_shape - { + boxf bbx, bbx_world; + float inv_mass; + + /* inertia model and inverse world tensor */ + v3f I; + m3x3f iI, iIw; + m4x3f to_world, to_local; +}; + +/* simple objects */ +struct rb_object +{ + rigidbody rb; + enum rb_shape{ k_rb_shape_box = 0, k_rb_shape_sphere = 1, k_rb_shape_capsule = 2, @@ -113,19 +126,6 @@ struct rigidbody struct rb_scene scene; } inf; - - v3f right, up, forward; - - int is_world; - - boxf bbx, bbx_world; - float inv_mass; - - /* inertia model and inverse world tensor */ - v3f I; - m3x3f iI, iIw; - - m4x3f to_world, to_local; }; VG_STATIC struct contact @@ -343,28 +343,24 @@ VG_STATIC void debug_capsule( m4x3f m, float radius, float h, u32 colour ) } } -VG_STATIC void rb_debug( rigidbody *rb, u32 colour ) +VG_STATIC void rb_object_debug( rb_object *obj, u32 colour ) { - if( rb->type == k_rb_shape_box ) - { - v3f *box = rb->bbx; - vg_line_boxf_transformed( rb->to_world, rb->bbx, colour ); + if( obj->type == k_rb_shape_box ){ + v3f *box = obj->rb.bbx; + vg_line_boxf_transformed( obj->rb.to_world, obj->rb.bbx, colour ); } - else if( rb->type == k_rb_shape_sphere ) - { - debug_sphere( rb->to_world, rb->inf.sphere.radius, colour ); + else if( obj->type == k_rb_shape_sphere ){ + debug_sphere( obj->rb.to_world, obj->inf.sphere.radius, colour ); } - else if( rb->type == k_rb_shape_capsule ) - { + else if( obj->type == k_rb_shape_capsule ){ m4x3f m0, m1; - float h = rb->inf.capsule.height, - r = rb->inf.capsule.radius; + float h = obj->inf.capsule.height, + r = obj->inf.capsule.radius; - debug_capsule( rb->to_world, r, h, colour ); + debug_capsule( obj->rb.to_world, r, h, colour ); } - else if( rb->type == k_rb_shape_scene ) - { - vg_line_boxf( rb->bbx, colour ); + else if( obj->type == k_rb_shape_scene ){ + vg_line_boxf( obj->rb.bbx, colour ); } } @@ -394,9 +390,11 @@ VG_STATIC void rb_update_transform( rigidbody *rb ) m4x3_invert_affine( rb->to_world, rb->to_local ); +#if 0 m3x3_mulv( rb->to_world, (v3f){1.0f,0.0f, 0.0f}, rb->right ); m3x3_mulv( rb->to_world, (v3f){0.0f,1.0f, 0.0f}, rb->up ); m3x3_mulv( rb->to_world, (v3f){0.0f,0.0f,-1.0f}, rb->forward ); +#endif m3x3_mul( rb->iI, rb->to_local, rb->iIw ); m3x3_mul( rb->to_world, rb->iIw, rb->iIw ); @@ -408,47 +406,13 @@ VG_STATIC void rb_update_transform( rigidbody *rb ) * Extrapolate rigidbody into a transform based on vg accumulator. * Useful for rendering */ -#if 0 -__attribute__ ((deprecated)) -VG_STATIC void rb_extrapolate_transform( rigidbody *rb, m4x3f transform ) -{ - float substep = vg_clampf( vg.accumulator / k_rb_delta, 0.0f, 1.0f ); - - v3f co; - v4f q; - - v3_muladds( rb->co, rb->v, k_rb_delta*substep, co ); - - if( v3_length2( rb->w ) > 0.0f ) - { - v4f rotation; - v3f axis; - v3_copy( rb->w, axis ); - - float mag = v3_length( axis ); - v3_divs( axis, mag, axis ); - q_axis_angle( rotation, axis, mag*k_rb_delta*substep ); - q_mul( rotation, rb->q, q ); - q_normalize( q ); - } - else - { - v4_copy( rb->q, q ); - } - - q_m3x3( q, transform ); - v3_copy( co, transform[3] ); -} -#endif - VG_STATIC void rb_extrapolate( rigidbody *rb, v3f co, v4f q ) { float substep = vg_clampf( vg.accumulator / k_rb_delta, 0.0f, 1.0f ); v3_muladds( rb->co, rb->v, k_rb_delta*substep, co ); - if( v3_length2( rb->w ) > 0.0f ) - { + if( v3_length2( rb->w ) > 0.0f ){ v4f rotation; v3f axis; v3_copy( rb->w, axis ); @@ -459,8 +423,7 @@ VG_STATIC void rb_extrapolate( rigidbody *rb, v3f co, v4f q ) q_mul( rotation, rb->q, q ); q_normalize( q ); } - else - { + else{ v4_copy( rb->q, q ); } } @@ -468,52 +431,47 @@ VG_STATIC void rb_extrapolate( rigidbody *rb, v3f co, v4f q ) /* * Initialize rigidbody and calculate masses, inertia */ -VG_STATIC void rb_init( rigidbody *rb ) +VG_STATIC void rb_init_object( rb_object *obj ) { float volume = 1.0f; + int inert = 0; - if( rb->type == k_rb_shape_box ) - { + if( obj->type == k_rb_shape_box ){ v3f dims; - v3_sub( rb->bbx[1], rb->bbx[0], dims ); + v3_sub( obj->rb.bbx[1], obj->rb.bbx[0], dims ); volume = dims[0]*dims[1]*dims[2]; } - else if( rb->type == k_rb_shape_sphere ) - { - volume = sphere_volume( rb->inf.sphere.radius ); - v3_fill( rb->bbx[0], -rb->inf.sphere.radius ); - v3_fill( rb->bbx[1], rb->inf.sphere.radius ); + else if( obj->type == k_rb_shape_sphere ){ + volume = sphere_volume( obj->inf.sphere.radius ); + v3_fill( obj->rb.bbx[0], -obj->inf.sphere.radius ); + v3_fill( obj->rb.bbx[1], obj->inf.sphere.radius ); } - else if( rb->type == k_rb_shape_capsule ) - { - float r = rb->inf.capsule.radius, - h = rb->inf.capsule.height; + else if( obj->type == k_rb_shape_capsule ){ + float r = obj->inf.capsule.radius, + h = obj->inf.capsule.height; volume = sphere_volume( r ) + VG_PIf * r*r * (h - r*2.0f); - v3_fill( rb->bbx[0], -r ); - v3_fill( rb->bbx[1], r ); - rb->bbx[0][1] = -h; - rb->bbx[1][1] = h; + v3_fill( obj->rb.bbx[0], -r ); + v3_fill( obj->rb.bbx[1], r ); + obj->rb.bbx[0][1] = -h; + obj->rb.bbx[1][1] = h; } - else if( rb->type == k_rb_shape_scene ) - { - rb->is_world = 1; - box_copy( rb->inf.scene.bh_scene->nodes[0].bbx, rb->bbx ); + else if( obj->type == k_rb_shape_scene ){ + inert = 1; + box_copy( obj->inf.scene.bh_scene->nodes[0].bbx, obj->rb.bbx ); } - if( rb->is_world ) - { - rb->inv_mass = 0.0f; - v3_zero( rb->I ); - m3x3_zero(rb->iI); + if( inert ){ + obj->rb.inv_mass = 0.0f; + v3_zero( obj->rb.I ); + m3x3_zero( obj->rb.iI ); } - else - { + else{ float mass = 2.0f*volume; - rb->inv_mass = 1.0f/mass; + obj->rb.inv_mass = 1.0f/mass; v3f extent; - v3_sub( rb->bbx[1], rb->bbx[0], extent ); + v3_sub( obj->rb.bbx[1], obj->rb.bbx[0], extent ); v3_muls( extent, 0.5f, extent ); /* local intertia tensor */ @@ -522,21 +480,18 @@ VG_STATIC void rb_init( rigidbody *rb ) ey2 = scale*extent[1]*extent[1], ez2 = scale*extent[2]*extent[2]; - rb->I[0] = ((1.0f/12.0f) * mass * (ey2+ez2)); - rb->I[1] = ((1.0f/12.0f) * mass * (ex2+ez2)); - rb->I[2] = ((1.0f/12.0f) * mass * (ex2+ey2)); + obj->rb.I[0] = ((1.0f/12.0f) * mass * (ey2+ez2)); + obj->rb.I[1] = ((1.0f/12.0f) * mass * (ex2+ez2)); + obj->rb.I[2] = ((1.0f/12.0f) * mass * (ex2+ey2)); - m3x3_identity( rb->iI ); - rb->iI[0][0] = rb->I[0]; - rb->iI[1][1] = rb->I[1]; - rb->iI[2][2] = rb->I[2]; - m3x3_inv( rb->iI, rb->iI ); + m3x3_identity( obj->rb.iI ); + obj->rb.iI[0][0] = obj->rb.I[0]; + obj->rb.iI[1][1] = obj->rb.I[1]; + obj->rb.iI[2][2] = obj->rb.I[2]; + m3x3_inv( obj->rb.iI, obj->rb.iI ); } - v3_zero( rb->v ); - v3_zero( rb->w ); - - rb_update_transform( rb ); + rb_update_transform( &obj->rb ); } VG_STATIC void rb_iter( rigidbody *rb ) @@ -661,8 +616,7 @@ VG_STATIC int rb_manifold_apply_filtered( rb_ct *man, int len ) { int k = 0; - for( int i=0; itype == k_contact_type_disabled ) @@ -679,8 +633,7 @@ VG_STATIC int rb_manifold_apply_filtered( rb_ct *man, int len ) */ VG_STATIC void rb_manifold_contact_weld( rb_ct *ci, rb_ct *cj, float r ) { - if( v3_dist2( ci->co, cj->co ) < r*r ) - { + if( v3_dist2( ci->co, cj->co ) < r*r ){ cj->type = k_contact_type_disabled; ci->p = (ci->p + cj->p) * 0.5f; @@ -693,13 +646,11 @@ VG_STATIC void rb_manifold_contact_weld( rb_ct *ci, rb_ct *cj, float r ) float c0 = v3_dot( ci->n, delta ), c1 = v3_dot( cj->n, delta ); - if( c0 < 0.0f || c1 < 0.0f ) - { + if( c0 < 0.0f || c1 < 0.0f ){ /* error */ ci->type = k_contact_type_disabled; } - else - { + else{ v3f n; v3_muls( ci->n, c0, n ); v3_muladds( n, cj->n, c1, n ); @@ -714,14 +665,12 @@ VG_STATIC void rb_manifold_contact_weld( rb_ct *ci, rb_ct *cj, float r ) */ VG_STATIC void rb_manifold_filter_joint_edges( rb_ct *man, int len, float r ) { - for( int i=0; itype != k_contact_type_edge ) continue; - for( int j=i+1; jtype != k_contact_type_edge ) continue; @@ -738,21 +687,18 @@ VG_STATIC void rb_manifold_filter_joint_edges( rb_ct *man, int len, float r ) */ VG_STATIC void rb_manifold_filter_pairs( rb_ct *man, int len, float r ) { - for( int i=0; itype == k_contact_type_disabled ) continue; - for( int j=i+1; jtype == k_contact_type_disabled ) continue; - if( v3_dist2( ci->co, cj->co ) < r*r ) - { + if( v3_dist2( ci->co, cj->co ) < r*r ){ cj->type = k_contact_type_disabled; v3_add( cj->n, ci->n, ci->n ); ci->p += cj->p; @@ -760,8 +706,7 @@ VG_STATIC void rb_manifold_filter_pairs( rb_ct *man, int len, float r ) } } - if( similar ) - { + if( similar ){ float n = 1.0f/((float)similar+1.0f); v3_muls( ci->n, n, ci->n ); ci->p *= n; @@ -779,8 +724,7 @@ VG_STATIC void rb_manifold_filter_pairs( rb_ct *man, int len, float r ) */ VG_STATIC void rb_manifold_filter_backface( rb_ct *man, int len ) { - for( int i=0; itype == k_contact_type_disabled ) continue; @@ -798,8 +742,7 @@ VG_STATIC void rb_manifold_filter_backface( rb_ct *man, int len ) */ VG_STATIC void rb_manifold_filter_coplanar( rb_ct *man, int len, float w ) { - for( int i=0; itype == k_contact_type_disabled || ci->type == k_contact_type_edge ) @@ -807,8 +750,7 @@ VG_STATIC void rb_manifold_filter_coplanar( rb_ct *man, int len, float w ) float d1 = v3_dot( ci->co, ci->n ); - for( int j=0; jco, ci->n ), d = d2-d1; - if( fabsf( d ) <= w ) - { + if( fabsf( d ) <= w ){ cj->type = k_contact_type_disabled; } } @@ -871,17 +812,14 @@ VG_STATIC void rb_capsule_manifold( v3f pa, v3f pb, float t, float r, v3f delta; v3_sub( pa, pb, delta ); - if( v3_length2(delta) < r*r ) - { - if( t < manifold->t0 ) - { + if( v3_length2(delta) < r*r ){ + if( t < manifold->t0 ){ v3_copy( delta, manifold->d0 ); manifold->t0 = t; manifold->r0 = r; } - if( t > manifold->t1 ) - { + if( t > manifold->t1 ){ v3_copy( delta, manifold->d1 ); manifold->t1 = t; manifold->r1 = r; @@ -895,70 +833,6 @@ VG_STATIC void rb_capsule_manifold_init( capsule_manifold *manifold ) manifold->t1 = -INFINITY; } -#if 0 -__attribute__ ((deprecated)) -VG_STATIC int rb_capsule_manifold_done( rigidbody *rba, rigidbody *rbb, - capsule_manifold *manifold, rb_ct *buf ) -{ - float h = rba->inf.capsule.height, - ra = rba->inf.capsule.radius; - - v3f p0, p1; - v3_muladds( rba->co, rba->up, -h*0.5f+ra, p0 ); - v3_muladds( rba->co, rba->up, h*0.5f-ra, p1 ); - - int count = 0; - if( manifold->t0 <= 1.0f ) - { - rb_ct *ct = buf; - - v3f pa; - v3_muls( p0, 1.0f-manifold->t0, pa ); - v3_muladds( pa, p1, manifold->t0, pa ); - - float d = v3_length( manifold->d0 ); - v3_muls( manifold->d0, 1.0f/d, ct->n ); - v3_muladds( pa, ct->n, -ra, ct->co ); - - ct->p = manifold->r0 - d; - ct->rba = rba; - ct->rbb = rbb; - ct->type = k_contact_type_default; - - count ++; - } - - if( (manifold->t1 >= 0.0f) && (manifold->t0 != manifold->t1) ) - { - rb_ct *ct = buf+count; - - v3f pa; - v3_muls( p0, 1.0f-manifold->t1, pa ); - v3_muladds( pa, p1, manifold->t1, pa ); - - float d = v3_length( manifold->d1 ); - v3_muls( manifold->d1, 1.0f/d, ct->n ); - v3_muladds( pa, ct->n, -ra, ct->co ); - - ct->p = manifold->r1 - d; - ct->rba = rba; - ct->rbb = rbb; - ct->type = k_contact_type_default; - - count ++; - } - - /* - * Debugging - */ - - if( count == 2 ) - vg_line( buf[0].co, buf[1].co, 0xff0000ff ); - - return count; -} -#endif - VG_STATIC int rb_capsule__manifold_done( m4x3f mtx, rb_capsule *c, capsule_manifold *manifold, rb_ct *buf ) @@ -968,8 +842,7 @@ VG_STATIC int rb_capsule__manifold_done( m4x3f mtx, rb_capsule *c, v3_muladds( mtx[3], mtx[1], c->height*0.5f-c->radius, p1 ); int count = 0; - if( manifold->t0 <= 1.0f ) - { + if( manifold->t0 <= 1.0f ){ rb_ct *ct = buf; v3f pa; @@ -985,8 +858,7 @@ VG_STATIC int rb_capsule__manifold_done( m4x3f mtx, rb_capsule *c, count ++; } - if( (manifold->t1 >= 0.0f) && (manifold->t0 != manifold->t1) ) - { + if( (manifold->t1 >= 0.0f) && (manifold->t0 != manifold->t1) ){ rb_ct *ct = buf+count; v3f pa; @@ -1013,15 +885,16 @@ VG_STATIC int rb_capsule__manifold_done( m4x3f mtx, rb_capsule *c, return count; } -VG_STATIC int rb_capsule_sphere( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) +VG_STATIC int rb_capsule_sphere( rb_object *obja, rb_object *objb, rb_ct *buf ) { - float h = rba->inf.capsule.height, - ra = rba->inf.capsule.radius, - rb = rbb->inf.sphere.radius; + rigidbody *rba = &obja->rb, *rbb = &objb->rb; + float h = obja->inf.capsule.height, + ra = obja->inf.capsule.radius, + rb = objb->inf.sphere.radius; v3f p0, p1; - v3_muladds( rba->co, rba->up, -h*0.5f+ra, p0 ); - v3_muladds( rba->co, rba->up, h*0.5f-ra, p1 ); + v3_muladds( rba->co, rba->to_world[1], -h*0.5f+ra, p0 ); + v3_muladds( rba->co, rba->to_world[1], h*0.5f-ra, p1 ); v3f c, delta; closest_point_segment( p0, p1, rbb->co, c ); @@ -1030,8 +903,7 @@ VG_STATIC int rb_capsule_sphere( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) float d2 = v3_length2(delta), r = ra + rb; - if( d2 < r*r ) - { + if( d2 < r*r ){ float d = sqrtf(d2); rb_ct *ct = buf; @@ -1219,23 +1091,22 @@ VG_STATIC int rb_capsule_box( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) } #endif -VG_STATIC int rb_sphere_box( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) +VG_STATIC int rb_sphere_box( rb_object *obja, rb_object *objb, rb_ct *buf ) { v3f co, delta; + rigidbody *rba = &obja->rb, *rbb = &objb->rb; closest_point_obb( rba->co, rbb->bbx, rbb->to_world, rbb->to_local, co ); v3_sub( rba->co, co, delta ); float d2 = v3_length2(delta), - r = rba->inf.sphere.radius; + r = obja->inf.sphere.radius; - if( d2 <= r*r ) - { + if( d2 <= r*r ){ float d; rb_ct *ct = buf; - if( d2 <= 0.0001f ) - { + if( d2 <= 0.0001f ){ v3_sub( rba->co, rbb->co, delta ); /* @@ -1243,25 +1114,24 @@ VG_STATIC int rb_sphere_box( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) * object back outside the box. Since there isnt a clear seperating * vector already, especially on really high aspect boxes. */ - float lx = v3_dot( rbb->right, delta ), - ly = v3_dot( rbb->up, delta ), - lz = v3_dot( rbb->forward, delta ), + float lx = v3_dot( rbb->to_world[0], delta ), + ly = v3_dot( rbb->to_world[1], delta ), + lz = v3_dot( rbb->to_world[2], delta ), px = rbb->bbx[1][0] - fabsf(lx), py = rbb->bbx[1][1] - fabsf(ly), pz = rbb->bbx[1][2] - fabsf(lz); if( px < py && px < pz ) - v3_muls( rbb->right, vg_signf(lx), ct->n ); + v3_muls( rbb->to_world[0], vg_signf(lx), ct->n ); else if( py < pz ) - v3_muls( rbb->up, vg_signf(ly), ct->n ); + v3_muls( rbb->to_world[1], vg_signf(ly), ct->n ); else - v3_muls( rbb->forward, vg_signf(lz), ct->n ); + v3_muls( rbb->to_world[2], vg_signf(lz), ct->n ); v3_muladds( rba->co, ct->n, -r, ct->co ); ct->p = r; } - else - { + else{ d = sqrtf(d2); v3_muls( delta, 1.0f/d, ct->n ); ct->p = r-d; @@ -1277,24 +1147,24 @@ VG_STATIC int rb_sphere_box( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) return 0; } -VG_STATIC int rb_sphere_sphere( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) +VG_STATIC int rb_sphere_sphere( rb_object *obja, rb_object *objb, rb_ct *buf ) { + rigidbody *rba = &obja->rb, *rbb = &objb->rb; v3f delta; v3_sub( rba->co, rbb->co, delta ); float d2 = v3_length2(delta), - r = rba->inf.sphere.radius + rbb->inf.sphere.radius; + r = obja->inf.sphere.radius + objb->inf.sphere.radius; - if( d2 < r*r ) - { + if( d2 < r*r ){ float d = sqrtf(d2); rb_ct *ct = buf; v3_muls( delta, 1.0f/d, ct->n ); v3f p0, p1; - v3_muladds( rba->co, ct->n,-rba->inf.sphere.radius, p0 ); - v3_muladds( rbb->co, ct->n, rbb->inf.sphere.radius, p1 ); + v3_muladds( rba->co, ct->n,-obja->inf.sphere.radius, p0 ); + v3_muladds( rbb->co, ct->n, objb->inf.sphere.radius, p1 ); v3_add( p0, p1, ct->co ); v3_muls( ct->co, 0.5f, ct->co ); ct->type = k_contact_type_default; @@ -1370,8 +1240,7 @@ VG_STATIC int rb_sphere__triangle( m4x3f mtxA, rb_sphere *b, float d2 = v3_length2( delta ), r = b->radius; - if( d2 <= r*r ) - { + if( d2 <= r*r ){ rb_ct *ct = buf; v3f ab, ac, tn; @@ -1380,8 +1249,7 @@ VG_STATIC int rb_sphere__triangle( m4x3f mtxA, rb_sphere *b, v3_cross( ac, ab, tn ); v3_copy( tn, ct->n ); - if( v3_length2( ct->n ) <= 0.00001f ) - { + if( v3_length2( ct->n ) <= 0.00001f ){ vg_error( "Zero area triangle!\n" ); return 0; } @@ -1399,100 +1267,6 @@ VG_STATIC int rb_sphere__triangle( m4x3f mtxA, rb_sphere *b, return 0; } -VG_STATIC void rb_debug_sharp_scene_edges( rigidbody *rbb, float sharp_ang, - boxf box, u32 colour ) -{ - sharp_ang = cosf( sharp_ang ); - - scene *sc = rbb->inf.scene.bh_scene->user; - vg_line_boxf( box, 0xff00ff00 ); - - bh_iter it; - bh_iter_init( 0, &it ); - int idx; - - while( bh_next( rbb->inf.scene.bh_scene, &it, box, &idx ) ) - { - u32 *ptri = &sc->arrindices[ idx*3 ]; - v3f tri[3]; - - for( int j=0; j<3; j++ ) - v3_copy( sc->arrvertices[ptri[j]].co, tri[j] ); - - for( int j=0; j<3; j++ ) - { -#if 0 - v3f edir; - v3_sub( tri[(j+1)%3], tri[j], edir ); - - if( v3_dot( edir, (v3f){ 0.5184758473652127f, - 0.2073903389460850f, - -0.8295613557843402f } ) < 0.0f ) - continue; -#endif - - bh_iter jt; - bh_iter_init( 0, &jt ); - - boxf region; - float const k_r = 0.02f; - v3_add( (v3f){ k_r, k_r, k_r }, tri[j], region[1] ); - v3_add( (v3f){ -k_r, -k_r, -k_r }, tri[j], region[0] ); - - int jdx; - while( bh_next( rbb->inf.scene.bh_scene, &jt, region, &jdx ) ) - { - if( idx <= jdx ) - continue; - - u32 *ptrj = &sc->arrindices[ jdx*3 ]; - v3f trj[3]; - - for( int k=0; k<3; k++ ) - v3_copy( sc->arrvertices[ptrj[k]].co, trj[k] ); - - for( int k=0; k<3; k++ ) - { - if( v3_dist2( tri[j], trj[k] ) <= k_r*k_r ) - { - int jp1 = (j+1)%3, - jp2 = (j+2)%3, - km1 = (k+3-1)%3, - km2 = (k+3-2)%3; - - if( v3_dist2( tri[jp1], trj[km1] ) <= k_r*k_r ) - { - v3f b0, b1, b2; - v3_sub( tri[jp1], tri[j], b0 ); - v3_sub( tri[jp2], tri[j], b1 ); - v3_sub( trj[km2], tri[j], b2 ); - - v3f cx0, cx1; - v3_cross( b0, b1, cx0 ); - v3_cross( b2, b0, cx1 ); - - float polarity = v3_dot( cx0, b2 ); - - if( polarity < 0.0f ) - { -#if 0 - vg_line( tri[j], tri[jp1], 0xff00ff00 ); - float ang = v3_dot(cx0,cx1) / - (v3_length(cx0)*v3_length(cx1)); - if( ang < sharp_ang ) - { - vg_line( tri[j], tri[jp1], 0xff00ff00 ); - } -#endif - } - } - } - } - } - } - } -} - VG_STATIC int rb_sphere__scene( m4x3f mtxA, rb_sphere *b, m4x3f mtxB, rb_scene *s, rb_ct *buf ) { @@ -1534,46 +1308,6 @@ VG_STATIC int rb_sphere__scene( m4x3f mtxA, rb_sphere *b, return count; } -#if 0 -__attribute__ ((deprecated)) -VG_STATIC int rb_sphere_scene( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) -{ - scene *sc = rbb->inf.scene.bh_scene->user; - - bh_iter it; - bh_iter_init( 0, &it ); - int idx; - - int count = 0; - - while( bh_next( rbb->inf.scene.bh_scene, &it, rba->bbx_world, &idx ) ) - { - u32 *ptri = &sc->arrindices[ idx*3 ]; - v3f tri[3]; - - for( int j=0; j<3; j++ ) - v3_copy( sc->arrvertices[ptri[j]].co, tri[j] ); - - buf[ count ].element_id = ptri[0]; - - vg_line( tri[0],tri[1],0x70ff6000 ); - vg_line( tri[1],tri[2],0x70ff6000 ); - vg_line( tri[2],tri[0],0x70ff6000 ); - - int contact = rb_sphere_triangle( rba, rbb, tri, buf+count ); - count += contact; - - if( count == 16 ) - { - vg_warn( "Exceeding sphere_vs_scene capacity. Geometry too dense!\n" ); - return count; - } - } - - return count; -} -#endif - VG_STATIC int rb_box__scene( m4x3f mtxA, boxf bbx, m4x3f mtxB, rb_scene *s, rb_ct *buf ) { @@ -1720,183 +1454,36 @@ VG_STATIC int rb_box__scene( m4x3f mtxA, boxf bbx, return count; } -#if 0 -__attribute__ ((deprecated)) -VG_STATIC int rb_box_scene( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) +VG_STATIC int rb_capsule__triangle( m4x3f mtxA, rb_capsule *c, + v3f tri[3], rb_ct *buf ) { - scene *sc = rbb->inf.scene.bh_scene->user; - - v3f tri[3]; + v3f pc, p0w, p1w; + v3_muladds( mtxA[3], mtxA[1], -c->height*0.5f+c->radius, p0w ); + v3_muladds( mtxA[3], mtxA[1], c->height*0.5f-c->radius, p1w ); - bh_iter it; - bh_iter_init( 0, &it ); - int idx; + capsule_manifold manifold; + rb_capsule_manifold_init( &manifold ); + + v3f c0, c1; + closest_on_triangle_1( p0w, tri, c0 ); + closest_on_triangle_1( p1w, tri, c1 ); - int count = 0; + v3f d0, d1, da; + v3_sub( c0, p0w, d0 ); + v3_sub( c1, p1w, d1 ); + v3_sub( p1w, p0w, da ); - while( bh_next( rbb->inf.scene.bh_scene, &it, rba->bbx_world, &idx ) ) - { - u32 *ptri = &sc->arrindices[ idx*3 ]; + v3_normalize(d0); + v3_normalize(d1); + v3_normalize(da); - for( int j=0; j<3; j++ ) - v3_copy( sc->arrvertices[ptri[j]].co, tri[j] ); - - if( rb_box_triangle_sat( rba, tri ) ) - { - vg_line(tri[0],tri[1],0xff50ff00 ); - vg_line(tri[1],tri[2],0xff50ff00 ); - vg_line(tri[2],tri[0],0xff50ff00 ); - } - else - { - vg_line(tri[0],tri[1],0xff0000ff ); - vg_line(tri[1],tri[2],0xff0000ff ); - vg_line(tri[2],tri[0],0xff0000ff ); - - continue; - } - - v3f v0,v1,n; - v3_sub( tri[1], tri[0], v0 ); - v3_sub( tri[2], tri[0], v1 ); - v3_cross( v0, v1, n ); - v3_normalize( n ); - - /* find best feature */ - float best = v3_dot( rba->right, n ); - int axis = 0; - - float cy = v3_dot( rba->up, n ); - if( fabsf(cy) > fabsf(best) ) - { - best = cy; - axis = 1; - } - - float cz = -v3_dot( rba->forward, n ); - if( fabsf(cz) > fabsf(best) ) - { - best = cz; - axis = 2; - } - - v3f manifold[4]; - - if( axis == 0 ) - { - float px = best > 0.0f? rba->bbx[0][0]: rba->bbx[1][0]; - manifold[0][0] = px; - manifold[0][1] = rba->bbx[0][1]; - manifold[0][2] = rba->bbx[0][2]; - manifold[1][0] = px; - manifold[1][1] = rba->bbx[1][1]; - manifold[1][2] = rba->bbx[0][2]; - manifold[2][0] = px; - manifold[2][1] = rba->bbx[1][1]; - manifold[2][2] = rba->bbx[1][2]; - manifold[3][0] = px; - manifold[3][1] = rba->bbx[0][1]; - manifold[3][2] = rba->bbx[1][2]; - } - else if( axis == 1 ) - { - float py = best > 0.0f? rba->bbx[0][1]: rba->bbx[1][1]; - manifold[0][0] = rba->bbx[0][0]; - manifold[0][1] = py; - manifold[0][2] = rba->bbx[0][2]; - manifold[1][0] = rba->bbx[1][0]; - manifold[1][1] = py; - manifold[1][2] = rba->bbx[0][2]; - manifold[2][0] = rba->bbx[1][0]; - manifold[2][1] = py; - manifold[2][2] = rba->bbx[1][2]; - manifold[3][0] = rba->bbx[0][0]; - manifold[3][1] = py; - manifold[3][2] = rba->bbx[1][2]; - } - else - { - float pz = best > 0.0f? rba->bbx[0][2]: rba->bbx[1][2]; - manifold[0][0] = rba->bbx[0][0]; - manifold[0][1] = rba->bbx[0][1]; - manifold[0][2] = pz; - manifold[1][0] = rba->bbx[1][0]; - manifold[1][1] = rba->bbx[0][1]; - manifold[1][2] = pz; - manifold[2][0] = rba->bbx[1][0]; - manifold[2][1] = rba->bbx[1][1]; - manifold[2][2] = pz; - manifold[3][0] = rba->bbx[0][0]; - manifold[3][1] = rba->bbx[1][1]; - manifold[3][2] = pz; - } - - for( int j=0; j<4; j++ ) - m4x3_mulv( rba->to_world, manifold[j], manifold[j] ); - - vg_line( manifold[0], manifold[1], 0xffffffff ); - vg_line( manifold[1], manifold[2], 0xffffffff ); - vg_line( manifold[2], manifold[3], 0xffffffff ); - vg_line( manifold[3], manifold[0], 0xffffffff ); - - for( int j=0; j<4; j++ ) - { - rb_ct *ct = buf+count; - - v3_copy( manifold[j], ct->co ); - v3_copy( n, ct->n ); - - float l0 = v3_dot( tri[0], n ), - l1 = v3_dot( manifold[j], n ); - - ct->p = (l0-l1)*0.5f; - if( ct->p < 0.0f ) - continue; - - ct->type = k_contact_type_default; - ct->rba = rba; - ct->rbb = rbb; - count ++; - - if( count >= 12 ) - return count; - } - } - return count; -} -#endif - -VG_STATIC int rb_capsule__triangle( m4x3f mtxA, rb_capsule *c, - v3f tri[3], rb_ct *buf ) -{ - v3f pc, p0w, p1w; - v3_muladds( mtxA[3], mtxA[1], -c->height*0.5f+c->radius, p0w ); - v3_muladds( mtxA[3], mtxA[1], c->height*0.5f-c->radius, p1w ); - - capsule_manifold manifold; - rb_capsule_manifold_init( &manifold ); - - v3f c0, c1; - closest_on_triangle_1( p0w, tri, c0 ); - closest_on_triangle_1( p1w, tri, c1 ); - - v3f d0, d1, da; - v3_sub( c0, p0w, d0 ); - v3_sub( c1, p1w, d1 ); - v3_sub( p1w, p0w, da ); - - v3_normalize(d0); - v3_normalize(d1); - v3_normalize(da); - - if( v3_dot( da, d0 ) <= 0.01f ) - rb_capsule_manifold( p0w, c0, 0.0f, c->radius, &manifold ); + if( v3_dot( da, d0 ) <= 0.01f ) + rb_capsule_manifold( p0w, c0, 0.0f, c->radius, &manifold ); if( v3_dot( da, d1 ) >= -0.01f ) rb_capsule_manifold( p1w, c1, 1.0f, c->radius, &manifold ); - for( int i=0; i<3; i++ ) - { + for( int i=0; i<3; i++ ){ int i0 = i, i1 = (i+1)%3; @@ -1919,68 +1506,6 @@ VG_STATIC int rb_capsule__triangle( m4x3f mtxA, rb_capsule *c, return count; } -/* - * Generates up to two contacts; optimised for the most stable manifold - */ -#if 0 -__attribute__ ((deprecated)) -VG_STATIC int rb_capsule_triangle( rigidbody *rba, rigidbody *rbb, - v3f tri[3], rb_ct *buf ) -{ - float h = rba->inf.capsule.height, - r = rba->inf.capsule.radius; - - v3f pc, p0w, p1w; - v3_muladds( rba->co, rba->up, -h*0.5f+r, p0w ); - v3_muladds( rba->co, rba->up, h*0.5f-r, p1w ); - - capsule_manifold manifold; - rb_capsule_manifold_init( &manifold ); - - v3f c0, c1; - closest_on_triangle_1( p0w, tri, c0 ); - closest_on_triangle_1( p1w, tri, c1 ); - - v3f d0, d1, da; - v3_sub( c0, p0w, d0 ); - v3_sub( c1, p1w, d1 ); - v3_sub( p1w, p0w, da ); - - v3_normalize(d0); - v3_normalize(d1); - v3_normalize(da); - - if( v3_dot( da, d0 ) <= 0.01f ) - rb_capsule_manifold( p0w, c0, 0.0f, r, &manifold ); - - if( v3_dot( da, d1 ) >= -0.01f ) - rb_capsule_manifold( p1w, c1, 1.0f, r, &manifold ); - - for( int i=0; i<3; i++ ) - { - int i0 = i, - i1 = (i+1)%3; - - v3f ca, cb; - float ta, tb; - closest_segment_segment( p0w, p1w, tri[i0], tri[i1], &ta, &tb, ca, cb ); - rb_capsule_manifold( ca, cb, ta, r, &manifold ); - } - - v3f v0, v1, n; - v3_sub( tri[1], tri[0], v0 ); - v3_sub( tri[2], tri[0], v1 ); - v3_cross( v0, v1, n ); - v3_normalize( n ); - - int count = rb_capsule_manifold_done( rba, rbb, &manifold, buf ); - for( int i=0; iinf.scene.bh_scene->user; - - bh_iter it; - bh_iter_init( 0, &it ); - int idx; - - int count = 0; - - while( bh_next( rbb->inf.scene.bh_scene, &it, rba->bbx_world, &idx ) ) - { - u32 *ptri = &sc->arrindices[ idx*3 ]; - v3f tri[3]; - - for( int j=0; j<3; j++ ) - v3_copy( sc->arrvertices[ptri[j]].co, tri[j] ); - - buf[ count ].element_id = ptri[0]; - -#if 0 - vg_line( tri[0],tri[1],0x70ff6000 ); - vg_line( tri[1],tri[2],0x70ff6000 ); - vg_line( tri[2],tri[0],0x70ff6000 ); -#endif - - int contact = rb_capsule_triangle( rba, rbb, tri, buf+count ); - count += contact; - - if( count == 16 ) - { - vg_warn("Exceeding capsule_vs_scene capacity. Geometry too dense!\n"); - return count; - } - } - - return count; -} - -VG_STATIC int rb_scene_capsule( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) -{ - return rb_capsule_scene( rbb, rba, buf ); -} -#endif - -VG_STATIC int RB_MATRIX_ERROR( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) -{ -#if 0 - vg_error( "Collision type is unimplemented between types %d and %d\n", - rba->type, rbb->type ); -#endif - - return 0; -} - -VG_STATIC int rb_sphere_capsule( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) -{ - return rb_capsule_sphere( rbb, rba, buf ); -} - -#if 0 -VG_STATIC int rb_box_capsule( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) -{ - return rb_capsule_box( rbb, rba, buf ); -} -#endif - -VG_STATIC int rb_box_sphere( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) -{ - return rb_sphere_box( rbb, rba, buf ); -} - -#if 0 -VG_STATIC int rb_scene_box( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) -{ - return rb_box_scene( rbb, rba, buf ); -} -#endif - -#if 0 -VG_STATIC int (*rb_jump_table[4][4])( rigidbody *a, rigidbody *b, rb_ct *buf ) = -{ - /* box */ /* Sphere */ /* Capsule */ /* Mesh */ - { RB_MATRIX_ERROR, rb_box_sphere, rb_box_capsule, rb_box_scene }, - { rb_sphere_box, rb_sphere_sphere, rb_sphere_capsule, rb_sphere_scene }, - { rb_capsule_box, rb_capsule_sphere, rb_capsule_capsule, rb_capsule_scene }, - { rb_scene_box, RB_MATRIX_ERROR, rb_scene_capsule, RB_MATRIX_ERROR } -}; - -VG_STATIC int rb_collide( rigidbody *rba, rigidbody *rbb ) -{ - int (*collider_jump)(rigidbody *rba, rigidbody *rbb, rb_ct *buf ) - = rb_jump_table[rba->type][rbb->type]; - - /* - * 12 is the maximum manifold size we can generate, so we are forced to abort - * potentially checking any more. - */ - if( rb_contact_count + 12 > vg_list_size(rb_contact_buffer) ) - { - vg_warn( "Too many contacts made in global collider buffer (%d of %d\n)", - rb_contact_count, vg_list_size(rb_contact_buffer) ); - return 0; - } - - /* - * FUTURE: Replace this with a more dedicated broad phase pass - */ - if( box_overlap( rba->bbx_world, rbb->bbx_world ) ) - { - int count = collider_jump( rba, rbb, rb_contact_buffer+rb_contact_count); - rb_contact_count += count; - return count; - } - else - return 0; -} -#endif - VG_STATIC int rb_global_has_space( void ) { if( rb_contact_count + 16 > vg_list_size(rb_contact_buffer) ) @@ -2328,8 +1732,7 @@ VG_STATIC void rb_solve_contacts( rb_ct *buf, int len ) VG_STATIC void rb_debug_position_constraints( rb_constr_pos *buffer, int len ) { - for( int i=0; irba, *rbb = constr->rbb; @@ -2351,8 +1754,7 @@ VG_STATIC void rb_presolve_swingtwist_constraints( rb_constr_swingtwist *buf, { float size = 0.12f; - for( int i=0; itangent_violation = ((lx*lx + ly*ly) > fn*fn) || (fn <= 0.0f); - if( st->tangent_violation ) - { + if( st->tangent_violation ){ /* Calculate a good position and the axis to solve on */ v2f closest, tangent, p = { fx/fabsf(fn), fy/fabsf(fn) }; @@ -2415,8 +1816,7 @@ VG_STATIC void rb_presolve_swingtwist_constraints( rb_constr_swingtwist *buf, float angle = v3_dot( refaxis, vxb ); st->axis_violation = fabsf(angle) < st->conet; - if( st->axis_violation ) - { + if( st->axis_violation ){ v3f dir_test; v3_cross( refaxis, vxb, dir_test ); @@ -2446,8 +1846,7 @@ VG_STATIC void rb_debug_swingtwist_constraints( rb_constr_swingtwist *buf, { float size = 0.12f; - for( int i=0; itangent_violation ) - { + if( st->tangent_violation ){ v3_muladds( center, st->tangent_target, size, p0 ); vg_line( center, p0, 0xff00ff00 ); @@ -2476,8 +1874,7 @@ VG_STATIC void rb_debug_swingtwist_constraints( rb_constr_swingtwist *buf, vg_line( p1, p0, 0xff000000 ); } - for( int x=0; x<32; x++ ) - { + for( int x=0; x<32; x++ ){ float t0 = ((float)x * (1.0f/32.0f)) * VG_TAUf, t1 = (((float)x+1.0f) * (1.0f/32.0f)) * VG_TAUf, c0 = cosf( t0 ), @@ -2515,8 +1912,7 @@ VG_STATIC void rb_debug_swingtwist_constraints( rb_constr_swingtwist *buf, vg_line( p0, p1, 0xff0000ff ); - if( st->axis_violation ) - { + if( st->axis_violation ){ v3_muladds( p0, st->axis_target, size*1.25f, p1 ); vg_line( p0, p1, 0xffffff00 ); vg_line_pt3( p1, 0.0025f, 0xffffff80 ); @@ -2544,8 +1940,7 @@ VG_STATIC void rb_debug_swingtwist_constraints( rb_constr_swingtwist *buf, */ VG_STATIC void rb_solve_position_constraints( rb_constr_pos *buf, int len ) { - for( int i=0; irba, *rbb = constr->rbb; @@ -2613,8 +2008,7 @@ VG_STATIC void rb_solve_swingtwist_constraints( rb_constr_swingtwist *buf, { float size = 0.12f; - for( int i=0; iaxis_violation ) @@ -2639,8 +2033,7 @@ VG_STATIC void rb_solve_swingtwist_constraints( rb_constr_swingtwist *buf, v3_dot( st->axis, st->rba->w ); } - for( int i=0; itangent_violation ) @@ -2712,8 +2105,7 @@ VG_STATIC void rb_solve_constr_angle( rigidbody *rba, rigidbody *rbb, VG_STATIC void rb_correct_position_constraints( rb_constr_pos *buf, int len, float amt ) { - for( int i=0; irba, *rbb = constr->rbb; @@ -2732,8 +2124,7 @@ VG_STATIC void rb_correct_position_constraints( rb_constr_pos *buf, int len, VG_STATIC void rb_correct_swingtwist_constraints( rb_constr_swingtwist *buf, int len, float amt ) { - for( int i=0; itangent_violation ) @@ -2744,8 +2135,7 @@ VG_STATIC void rb_correct_swingtwist_constraints( rb_constr_swingtwist *buf, float angle = v3_dot( va, st->tangent_target ); - if( fabsf(angle) < 0.9999f ) - { + if( fabsf(angle) < 0.9999f ){ v3f axis; v3_cross( va, st->tangent_target, axis ); @@ -2756,8 +2146,7 @@ VG_STATIC void rb_correct_swingtwist_constraints( rb_constr_swingtwist *buf, } } - for( int i=0; iaxis_violation ) @@ -2768,8 +2157,7 @@ VG_STATIC void rb_correct_swingtwist_constraints( rb_constr_swingtwist *buf, float angle = v3_dot( vxb, st->axis_target ); - if( fabsf(angle) < 0.9999f ) - { + if( fabsf(angle) < 0.9999f ){ v3f axis; v3_cross( vxb, st->axis_target, axis ); @@ -2783,8 +2171,7 @@ VG_STATIC void rb_correct_swingtwist_constraints( rb_constr_swingtwist *buf, VG_STATIC void rb_correct_contact_constraints( rb_ct *buf, int len, float amt ) { - for( int i=0; irba, *rbb = ct->rbb; @@ -2833,49 +2220,4 @@ VG_STATIC void rb_effect_spring_target_vector( rigidbody *rba, v3f ra, v3f rt, v3_muladds( rba->w, axis, (Fs+Fd) * timestep, rba->w ); } -/* - * ----------------------------------------------------------------------------- - * BVH implementation, this is ONLY for VG_STATIC rigidbodies, its to slow for - * realtime use. - * ----------------------------------------------------------------------------- - */ - -VG_STATIC void rb_bh_expand_bound( void *user, boxf bound, u32 item_index ) -{ - rigidbody *rb = &((rigidbody *)user)[ item_index ]; - box_concat( bound, rb->bbx_world ); -} - -VG_STATIC float rb_bh_centroid( void *user, u32 item_index, int axis ) -{ - rigidbody *rb = &((rigidbody *)user)[ item_index ]; - return (rb->bbx_world[axis][0] + rb->bbx_world[1][axis]) * 0.5f; -} - -VG_STATIC void rb_bh_swap( void *user, u32 ia, u32 ib ) -{ - rigidbody temp, *rba, *rbb; - rba = &((rigidbody *)user)[ ia ]; - rbb = &((rigidbody *)user)[ ib ]; - - temp = *rba; - *rba = *rbb; - *rbb = temp; -} - -VG_STATIC void rb_bh_debug( void *user, u32 item_index ) -{ - rigidbody *rb = &((rigidbody *)user)[ item_index ]; - rb_debug( rb, 0xff00ffff ); -} - -VG_STATIC bh_system bh_system_rigidbodies = -{ - .expand_bound = rb_bh_expand_bound, - .item_centroid = rb_bh_centroid, - .item_swap = rb_bh_swap, - .item_debug = rb_bh_debug, - .cast_ray = NULL -}; - #endif /* RIGIDBODY_H */ diff --git a/skaterift.c b/skaterift.c index 3033277..9c83a88 100644 --- a/skaterift.c +++ b/skaterift.c @@ -220,7 +220,7 @@ VG_STATIC void vg_load(void) vg_loader_step( world_init, NULL ); vg_loader_step( font3d_init, NULL ); - font3d_load( &test_font, "models/rs_font.mdl", vg_mem.rtmemory ); + font3d_load( &world_global.font, "models/rs_font.mdl", vg_mem.rtmemory ); //vg_loader_step( player_init, NULL ); //vg_loader_step( vehicle_init, NULL ); diff --git a/world.h b/world.h index 41191b8..c99cfdc 100644 --- a/world.h +++ b/world.h @@ -19,6 +19,7 @@ typedef struct world_instance world_instance; #include "bvh.h" #include "model.h" #include "entity.h" +#include "font.h" #include "shaders/scene_standard.h" #include "shaders/scene_standard_alphatest.h" @@ -54,16 +55,14 @@ enum geo_type static const float k_light_cube_size = 8.0f; -struct world_instance -{ +struct world_instance { /* Fixed items * ------------------------------------------------------- */ char world_name[ 64 ]; - struct - { + struct{ boxf depthbounds; int depth_computed; @@ -74,8 +73,7 @@ struct world_instance water; /* STD140 */ - struct ub_world_lighting - { + struct ub_world_lighting{ v4f g_cube_min, g_cube_inv_range; @@ -138,8 +136,7 @@ struct world_instance GLuint *textures; u32 texture_count; - struct world_surface - { + struct world_surface{ mdl_material info; mdl_submesh sm_geo, sm_no_collide; @@ -182,11 +179,10 @@ struct world_instance mesh_no_collide, mesh_water; - rigidbody rb_geo; /* todo.. ... */ + rb_object rb_geo; }; -VG_STATIC struct world_global -{ +VG_STATIC struct world_global{ /* * Allocated as system memory * -------------------------------------------------------------------------- @@ -205,15 +201,13 @@ VG_STATIC struct world_global double time, rewind_from, rewind_to, last_use; /* water rendering */ - struct - { + struct{ struct framebuffer fbreflect, fbdepth; } water; /* split flap display */ - struct - { + struct{ glmesh mesh_base, mesh_display; mdl_submesh sm_base; u32 active_route_board; @@ -231,6 +225,26 @@ VG_STATIC struct world_global world_instance worlds[4]; u32 world_count; u32 active_world; + + /* text particles */ + font3d font; + + struct timer_text{ + char text[8]; + m4x3f transform; + ent_gate *gate; + ent_route *route; + } + timer_texts[4]; + u32 timer_text_count; + + struct text_particle{ + rigidbody *rb; + ent_glyph *glyph; + } + text_particles[6*4]; + u32 text_particle_count; + } world_global; @@ -502,8 +516,9 @@ VG_STATIC void world_update( world_instance *world, v3f pos ) world_global.sky_target_rate, vg.time_delta * 5.0 ); + world_routes_update_timer_texts( world ); world_routes_update( world ); - world_routes_debug( world ); + //world_routes_debug( world ); /* ---- SFD ------------ */ diff --git a/world_gen.h b/world_gen.h index 3117dc0..ded2efe 100644 --- a/world_gen.h +++ b/world_gen.h @@ -166,13 +166,14 @@ VG_STATIC void world_generate( world_instance *world ) world->geo_bh = scene_bh_create( world_global.generic_heap, world->scene_geo ); - v3_zero( world->rb_geo.co ); - q_identity( world->rb_geo.q ); + v3_zero( world->rb_geo.rb.co ); + v3_zero( world->rb_geo.rb.v ); + q_identity( world->rb_geo.rb.q ); + v3_zero( world->rb_geo.rb.w ); world->rb_geo.type = k_rb_shape_scene; world->rb_geo.inf.scene.bh_scene = world->geo_bh; - world->rb_geo.is_world = 1; - rb_init( &world->rb_geo ); + rb_init_object( &world->rb_geo ); /* * Generate scene: non-collidable geometry diff --git a/world_routes.h b/world_routes.h index 5a81d0c..792b7e8 100644 --- a/world_routes.h +++ b/world_routes.h @@ -94,20 +94,16 @@ VG_STATIC void world_routes_time_lap( world_instance *world, ent_route *route ) if( i == 0 ) start_time = rg->timing_time; else{ - if( last_version+1 == rg->timing_version ) - valid_count ++; - else - valid_count = 0; + if( last_version+1 == rg->timing_version ) valid_count ++; + else valid_count = 0; } last_version = rg->timing_version; vg_info( "%u %f\n", rg->timing_version, rg->timing_time ); } - if( world_global.current_run_version == last_version+1 ) - valid_count ++; - else - valid_count = 0; + if( world_global.current_run_version == last_version+1 ) valid_count ++; + else valid_count = 0; vg_info( "%u %f\n", world_global.current_run_version, world_global.time ); @@ -606,6 +602,132 @@ VG_STATIC void world_bind_light_index( world_instance *world, GLuint shader, GLuint location, int slot ); +VG_STATIC void world_routes_update_timer_texts( world_instance *world ) +{ + world_global.timer_text_count = 0; + + for( u32 i=0; ient_route); i++ ){ + ent_route *route = mdl_arritm( &world->ent_route, i ); + + if( route->active_checkpoint != 0xffff ){ + u32 next = route->active_checkpoint+1; + next = next % route->checkpoints_count; + next += route->checkpoints_start; + + ent_checkpoint *cp = mdl_arritm( &world->ent_checkpoint, next ); + ent_gate *gate = mdl_arritm( &world->ent_gate, cp->gate_index ); + ent_gate *dest = mdl_arritm( &world->ent_gate, gate->target ); + + u32 j=0; + for( ; j<4; j++ ){ + if( dest->routes[j] == i ){ + break; + } + } + + float h0 = 0.8f, + h1 = 1.2f, + depth = 0.4f, + size = 0.4f; + + struct timer_text *text = + &world_global.timer_texts[ world_global.timer_text_count ++ ]; + + text->gate = gate; + text->route = route; + + if( route->valid_checkpoints >= route->checkpoints_count ){ + double lap_time = world_global.time - route->timing_base, + time_centiseconds = lap_time * 100.0; + + if( time_centiseconds > (float)0xfffe ) time_centiseconds = 0.0; + + u16 centiseconds = time_centiseconds, + seconds = centiseconds / 100, + minutes = seconds / 60; + + centiseconds %= 100; + seconds %= 60; + minutes %= 60; + + if( minutes > 9 ) minutes = 9; + + int j=0; + if( minutes ){ + highscore_intr( text->text, minutes, 1, ' ' ); j++; + text->text[j++] = ':'; + } + + if( seconds >= 10 || minutes ){ + highscore_intr( text->text+j, seconds, 2, '0' ); j+=2; + } + else{ + highscore_intr( text->text+j, seconds, 1, '0' ); j++; + } + + text->text[j++] = '.'; + highscore_intr( text->text+j, centiseconds, 1, '0' ); j++; + text->text[j] = '\0'; + } + else{ + highscore_intr( text->text, route->valid_checkpoints, 1, ' ' ); + text->text[1] = '/'; + highscore_intr( text->text+2, route->checkpoints_count+1, 1, ' ' ); + text->text[3] = '\0'; + } + + float align_r = font3d_string_width( &world_global.font, 0, + text->text ); + align_r *= size; + + v3f positions[] = { + { -0.92f, h0, depth }, + { 0.92f - align_r, h0, depth }, + { -0.92f, h1, depth }, + { 0.92f - align_r, h1, depth }, + }; + + if( dest->route_count == 1 ){ + positions[0][0] = -align_r*0.5f; + positions[0][1] = h1; + } + + m3x3_copy( gate->to_world, text->transform ); + float ratio = v3_length(text->transform[0]) / + v3_length(text->transform[1]); + + m3x3_scale( text->transform, (v3f){ size, size*ratio, 0.1f } ); + m4x3_mulv( gate->to_world, positions[j], text->transform[3] ); + } + } +} + +VG_STATIC void world_routes_fracture( world_instance *world, ent_gate *gate ) +{ + world_global.text_particle_count = 0; + + for( u32 i=0; igate == gate ){ + v3f co, s; + v4f q; + m4x3_decompose( text->transform, co, q, s ); + + for( u32 j=0;; j++ ){ + char c = text->text[j]; + if( !c ) break; + + if( c < '0' || c > '9' ) continue; + + struct text_particle *particle = + &world_global.text_particles[world_global.text_particle_count++]; + + } + } + } +} + VG_STATIC void render_world_routes( world_instance *world, camera *cam, int layer_depth ) { @@ -646,74 +768,19 @@ VG_STATIC void render_world_routes( world_instance *world, camera *cam, /* timers * ---------------------------------------------------- */ if( layer_depth == 0 ){ - font3d_bind( &test_font, cam ); - - for( u32 i=0; ient_route); i++ ){ - ent_route *route = mdl_arritm( &world->ent_route, i ); - - if( route->active_checkpoint != 0xffff ){ - v4f colour; - float brightness = 0.3f + world->ub_lighting.g_day_phase; - v3_muls( route->colour, brightness, colour ); - colour[3] = 1.0f-route->factive; - - shader_model_font_uColour( colour ); - - u32 next = route->active_checkpoint+1+layer_depth; - next = next % route->checkpoints_count; - next += route->checkpoints_start; + font3d_bind( &world_global.font, cam ); - ent_checkpoint *cp = mdl_arritm( &world->ent_checkpoint, next ); - ent_gate *gate = mdl_arritm( &world->ent_gate, cp->gate_index ); + for( u32 i=0; iroutes[j] == i ){ - break; - } - } - float h0 = 0.8f, - h1 = 1.2f, - depth = 0.4f, - size = 0.4f; - - char text[256]; - - if( route->valid_checkpoints >= route->checkpoints_count ){ - double lap_time = world_global.time - route->timing_base; - snprintf( text, 255, "%.1f", lap_time ); - } - else{ - snprintf( text, 255, "%hu/%hu", route->valid_checkpoints, - route->checkpoints_count ); - } - - float align_r = font3d_string_width( &test_font, 0, text ) * size; - - v3f positions[] = { - { -0.92f, h0, depth }, - { 0.92f - align_r, h0, depth }, - { -0.92f, h1, depth }, - { 0.92f - align_r, h1, depth }, - }; - - ent_gate *dest = mdl_arritm( &world->ent_gate, gate->target ); - - if( dest->route_count == 1 ){ - positions[0][0] = -align_r*0.5f; - positions[0][1] = h1; - } - - m4x3f model; - m3x3_copy( gate->to_world, model ); - float ratio = v3_length(model[0]) / v3_length(model[1]); - - m3x3_scale( model, (v3f){ size, size*ratio, 0.1f } ); - m4x3_mulv( gate->to_world, positions[j], model[3] ); + v4f colour; + float brightness = 0.3f + world->ub_lighting.g_day_phase; + v3_muls( text->route->colour, brightness, colour ); + colour[3] = 1.0f-text->route->factive; - font3d_simple_draw( &test_font, 0, text, cam, model ); - } + shader_model_font_uColour( colour ); + font3d_simple_draw( &world_global.font, 0, text->text, + cam, text->transform ); } } -- 2.25.1