static void player__setpos( v3f pos ){
v3_copy( pos, localplayer.rb.co );
v3_zero( localplayer.rb.v );
- rb_update_transform( &localplayer.rb );
+ rb_update_matrices( &localplayer.rb );
}
static void player__clean_refs(void){
if( (l < 0.9f) || (l > 1.1f) )
q_identity( localplayer.rb.q );
- rb_update_transform( &localplayer.rb );
+ rb_update_matrices( &localplayer.rb );
localplayer.subsystem = k_player_subsystem_walk;
player__walk_reset();
v3f ext_co;
v4f ext_q;
- rb_extrapolate( &part->obj.rb, ext_co, ext_q );
+ rb_extrapolate( &part->rb, ext_co, ext_q );
v3_lerp( d->co_lpf, ext_co, vg.time_frame_delta*4.0f, d->co_lpf );
- v3_lerp( d->v_lpf, part->obj.rb.v, vg.time_frame_delta*4.0f, d->v_lpf );
- v3_lerp( d->w_lpf, part->obj.rb.w, vg.time_frame_delta*4.0f, d->w_lpf );
+ v3_lerp( d->v_lpf, part->rb.v, vg.time_frame_delta*4.0f, d->v_lpf );
+ v3_lerp( d->w_lpf, part->rb.w, vg.time_frame_delta*4.0f, d->w_lpf );
v3_copy( d->co_lpf, localplayer.rb.co );
v3_zero( localplayer.rb.v );
v3f co_int;
float substep = vg.time_fixed_extrapolate;
- v3_lerp( part->prev_co, part->obj.rb.co, substep, co_int );
- q_nlerp( part->prev_q, part->obj.rb.q, substep, q_int );
- v4_copy( part->obj.rb.q, q_int );
+ v3_lerp( part->prev_co, part->rb.co, substep, co_int );
+ q_nlerp( part->prev_q, part->rb.q, substep, q_int );
+ v4_copy( part->rb.q, q_int );
q_m3x3( q_int, mtx );
v3_copy( co_int, mtx[3] );
struct ragdoll_part *part =
&localplayer.ragdoll.parts[ localplayer.id_hip-1 ];
- v3_copy( part->obj.rb.co, player_dead.co_lpf );
- v3_copy( part->obj.rb.v, player_dead.v_lpf );
- v3_copy( part->obj.rb.w, player_dead.w_lpf );
+ v3_copy( part->rb.co, player_dead.co_lpf );
+ v3_copy( part->rb.v, player_dead.v_lpf );
+ v3_copy( part->rb.w, player_dead.w_lpf );
gui_helper_clear();
vg_str str;
static void player__drive_update(void){}
static void player__drive_post_update(void){
- v3_copy( player_drive.vehicle->obj.rb.co,localplayer.rb.co );
- v3_copy( player_drive.vehicle->obj.rb.v, localplayer.rb.v );
- v4_copy( player_drive.vehicle->obj.rb.q, localplayer.rb.q );
- v3_copy( player_drive.vehicle->obj.rb.w, localplayer.rb.w );
+ v3_copy( player_drive.vehicle->rb.co,localplayer.rb.co );
+ v3_copy( player_drive.vehicle->rb.v, localplayer.rb.v );
+ v4_copy( player_drive.vehicle->rb.q, localplayer.rb.q );
+ v3_copy( player_drive.vehicle->rb.w, localplayer.rb.w );
}
static void player__drive_animate(void){}
else
localplayer.cam_velocity_influence = 1.0f;
- rigidbody *rb = &gzoomer.obj.rb;
+ rigidbody *rb = &gzoomer.rb;
float yaw = atan2f( -rb->to_world[2][0], rb->to_world[2][2] ),
pitch = atan2f
(
}
static void player_glide_update(void){
- rigidbody *rb = &localplayer.rb;
- vg_line_sphere( rb->to_world, 1.0f, 0 );
+ rigidbody *rb = &player_glide.rb;
v2f steer;
joystick_state( k_srjoystick_steer, steer );
m3x3_mulv( rb->to_world, Fw, Fw );
v3_muladds( rb->w, Fw, k_rb_delta, rb->w );
+ /*
+ * collisions & constraints
+ */
+ world_instance *world = world_current_instance();
+ rb_solver_reset();
+
+ rigidbody _null = {0};
+ _null.inv_mass = 0.0f;
+ m3x3_zero( _null.iI );
+ for( u32 i=0; i < vg_list_size(player_glide.parts); i ++ ){
+ m4x3f mmdl;
+ m4x3_mul( rb->to_world, player_glide.parts[i].mdl, mmdl );
+
+ if( player_glide.parts[i].shape == k_rb_shape_capsule ){
+ vg_line_capsule( mmdl,
+ player_glide.parts[i].inf.r,
+ player_glide.parts[i].inf.h,
+ VG__BLACK );
+ }
+ else if( player_glide.parts[i].shape == k_rb_shape_sphere ){
+ vg_line_sphere( mmdl, player_glide.parts[i].r, 0 );
+ }
+
+ if( rb_global_has_space() ){
+ rb_ct *buf = rb_global_buffer();
+
+ u32 l = 0;
+
+ if( player_glide.parts[i].shape == k_rb_shape_capsule ){
+ l = rb_capsule__scene( mmdl, &player_glide.parts[i].inf,
+ NULL, world->geo_bh, buf,
+ k_material_flag_ghosts );
+ }
+ else if( player_glide.parts[i].shape == k_rb_shape_sphere ){
+ l = rb_sphere__scene( mmdl, player_glide.parts[i].r,
+ NULL, world->geo_bh, buf,
+ k_material_flag_ghosts );
+ }
+
+ for( u32 j=0; j<l; j ++ ){
+ buf[j].rba = rb;
+ buf[j].rbb = &_null;
+ }
+
+ rb_contact_count += l;
+ }
+ }
+
+ rb_presolve_contacts( rb_contact_buffer, rb_contact_count );
+ for( u32 i=0; i<10; i ++ )
+ rb_solve_contacts( rb_contact_buffer, rb_contact_count );
+
rb_iter( rb );
- rb_update_transform( rb );
+ rb_update_matrices( rb );
}
static void player_glide_post_update(void){
+ v3_copy( player_glide.rb.co, localplayer.rb.co );
+ v4_copy( player_glide.rb.q, localplayer.rb.q );
+ v3_copy( player_glide.rb.v, localplayer.rb.v );
+ v3_copy( player_glide.rb.w, localplayer.rb.w );
+ rb_update_matrices( &localplayer.rb );
}
static void player_glide_animate(void){
VG_VAR_I32( k_glide_pause, flags=mask );
VG_VAR_F32( k_glide_balance, flags=mask );
VG_VAR_F32( k_glide_wing_orient, flags=mask );
+
+ f32 mass = 0.0f,
+ k_density = 8.0f,
+ k_inertia_scale = 1.0f;
+ m3x3f I;
+ m3x3_zero( I );
+
+ for( u32 i=0; i<vg_list_size(player_glide.parts); i ++ ){
+ /* create part transform matrix */
+ v4f qp, qy, qr, q;
+ q_axis_angle( qp, (v3f){1,0,0}, player_glide.parts[i].euler[0] );
+ q_axis_angle( qy, (v3f){0,1,0}, player_glide.parts[i].euler[1] );
+ q_axis_angle( qr, (v3f){0,0,1}, player_glide.parts[i].euler[2] );
+
+ q_mul( qr, qy, q );
+ q_mul( q, qp, q );
+
+ q_m3x3( q, player_glide.parts[i].mdl );
+ v3_copy( player_glide.parts[i].co, player_glide.parts[i].mdl[3] );
+
+ /* add it to inertia model */
+
+ if( player_glide.parts[i].shape == k_rb_shape_capsule ){
+ f32 r = player_glide.parts[i].inf.r,
+ h = player_glide.parts[i].inf.h,
+ pv = vg_capsule_volume( r, h ),
+ pm = pv * k_density;
+
+ mass += pm;
+
+ m3x3f pI;
+ rb_capsule_inertia( r, h, pm, pI );
+ rb_rotate_inertia( pI, player_glide.parts[i].mdl );
+ rb_translate_inertia( pI, pm, player_glide.parts[i].co );
+ m3x3_add( I, pI, I );
+ }
+ else if( player_glide.parts[i].shape == k_rb_shape_sphere ){
+ f32 r = player_glide.parts[i].r,
+ pv = vg_sphere_volume( r ),
+ pm = pv * k_density;
+
+ mass += pm;
+ m3x3f pI;
+ rb_sphere_inertia( r, pm, pI );
+ rb_translate_inertia( pI, pm, player_glide.parts[i].co );
+ m3x3_add( I, pI, I );
+ }
+ }
+
+ /* set inverses */
+ m3x3_inv( I, player_glide.rb.iI );
+ player_glide.rb.inv_mass = 1.0f / mass;
}
#endif /* PLAYER_GLIDE_C */
info_drag;
u32 ticker;
+
+ rigidbody rb;
+
+ struct {
+ v3f co, euler;
+ m4x3f mdl;
+
+ union {
+ rb_capsule inf;
+ f32 r;
+ };
+
+ enum rb_shape shape;
+ }
+ parts[3];
}
-static player_glide;
+static player_glide = {
+ .parts = {
+ {
+ .co = { 1.0f, 1.0f, -1.0f },
+ .euler = { VG_TAUf*0.25f, VG_TAUf*0.125f, 0.0f },
+ .shape = k_rb_shape_capsule,
+ .inf = { .h = 2.82842712475f, .r = 0.25f },
+ },
+ {
+ .co = { -1.0f, 1.0f, -1.0f },
+ .euler = { VG_TAUf*0.25f, -VG_TAUf*0.125f, 0.0f },
+ .shape = k_rb_shape_capsule,
+ .inf = { .h = 2.82842712475f, .r = 0.25f },
+ },
+ {
+ .co = { 0.0f, 0.0f, 0.0f },
+ .euler = { 0.0f, 0.0f, 0.0f },
+ .shape = k_rb_shape_sphere,
+ .r = 0.5f
+ }
+ }
+};
static void player_glide_pre_update(void);
static void player_glide_update(void);
static void player_init_ragdoll_bone_collider( struct skeleton_bone *bone,
struct ragdoll_part *rp )
{
+ f32 k_density = 8.0f,
+ k_inertia_scale = 2.0f;
+
m4x3_identity( rp->collider_mtx );
+ rp->type = bone->collider;
if( bone->collider == k_bone_collider_box ){
v3f delta;
v3_sub( bone->hitbox[1], bone->hitbox[0], delta );
v3_muls( delta, 0.5f, delta );
v3_add( bone->hitbox[0], delta, rp->collider_mtx[3] );
- v3_copy( delta, rp->obj.rb.bbx[1] );
- v3_muls( delta, -1.0f, rp->obj.rb.bbx[0] );
+ v3_muls( delta, -1.0f, rp->inf.box[0] );
+ v3_copy( delta, rp->inf.box[1] );
- q_identity( rp->obj.rb.q );
- rp->obj.type = k_rb_shape_box;
rp->colour = 0xffcccccc;
+
+ rb_setbody_box( &rp->rb, rp->inf.box, k_density, k_inertia_scale );
}
else if( bone->collider == k_bone_collider_capsule ){
v3f v0, v1, tx, ty;
v1[ major_axis ] = 1.0f;
v3_tangent_basis( v1, tx, ty );
- float r = (fabsf(v3_dot(tx,v0)) + fabsf(v3_dot(ty,v0))) * 0.25f,
- l = fabsf(v0[ major_axis ]);
-
+ rp->inf.capsule.r = (fabsf(v3_dot(tx,v0)) + fabsf(v3_dot(ty,v0))) * 0.25f;
+ rp->inf.capsule.h = fabsf(v0[ major_axis ]);
+
/* orientation */
v3_muls( tx, -1.0f, rp->collider_mtx[0] );
v3_muls( v1, -1.0f, rp->collider_mtx[1] );
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->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));
+
+ rb_setbody_capsule( &rp->rb, rp->inf.capsule.r, rp->inf.capsule.h,
+ k_density, k_inertia_scale );
}
else{
vg_warn( "type: %u\n", bone->collider );
m4x3_invert_affine( rp->collider_mtx, rp->inv_collider_mtx );
/* Position collider into rest */
- 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, 4.0f );
+ m3x3_q( rp->collider_mtx, rp->rb.q );
+ v3_add( rp->collider_mtx[3], bone->co, rp->rb.co );
+ v3_zero( rp->rb.v );
+ v3_zero( rp->rb.w );
+ rb_update_matrices( &rp->rb );
}
/*
rd->constraint_associations[conid][1] = part_id;
/* Convention: rba -- parent, rbb -- child */
- c->rba = &pp->obj.rb;
- c->rbb = &rp->obj.rb;
+ c->rba = &pp->rb;
+ c->rbb = &rp->rb;
v3f delta;
v3_sub( bj->co, bp->co, delta );
struct rb_constr_swingtwist *a =
&rd->cone_constraints[ rd->cone_constraints_count ++ ];
- a->rba = &pp->obj.rb;
- a->rbb = &rp->obj.rb;
+ a->rba = &pp->rb;
+ a->rbb = &rp->rb;
a->conet = cosf( inf->conet )-0.0001f;
/* Store constraint in local space vectors */
v3f co_int;
float substep = vg.time_fixed_extrapolate;
- v3_lerp( part->prev_co, part->obj.rb.co, substep, co_int );
- q_nlerp( part->prev_q, part->obj.rb.q, substep, q_int );
+ v3_lerp( part->prev_co, part->rb.co, substep, co_int );
+ q_nlerp( part->prev_q, part->rb.q, substep, q_int );
q_m3x3( q_int, mtx );
v3_copy( co_int, mtx[3] );
m4x3_mulv( bone_mtx, localplayer.skeleton.bones[bone].co, pos );
m3x3_mulv( bone_mtx, part->collider_mtx[3], offset );
- v3_add( pos, offset, part->obj.rb.co );
+ v3_add( pos, offset, part->rb.co );
m3x3f r;
m3x3_mul( bone_mtx, part->collider_mtx, r );
- m3x3_q( r, part->obj.rb.q );
+ m3x3_q( r, part->rb.q );
v3f ra, v;
- v3_sub( part->obj.rb.co, centroid, ra );
+ v3_sub( part->rb.co, centroid, ra );
v3_cross( localplayer.rb.w, ra, v );
- v3_add( localplayer.rb.v, v, part->obj.rb.v );
+ v3_add( localplayer.rb.v, v, part->rb.v );
if( type == k_player_die_type_feet ){
if( (bone == localplayer.id_foot_l) ||
(bone == localplayer.id_foot_r) ){
- v3_zero( part->obj.rb.v );
+ v3_zero( part->rb.v );
}
}
- v3_copy( localplayer.rb.w, part->obj.rb.w );
+ v3_copy( localplayer.rb.w, part->rb.w );
- v3_copy( part->obj.rb.co, part->prev_co );
- v4_copy( part->obj.rb.q, part->prev_q );
+ v3_copy( part->rb.co, part->prev_co );
+ v4_copy( part->rb.q, part->prev_q );
- rb_update_transform( &part->obj.rb );
+ rb_update_matrices( &part->rb );
}
}
float contact_velocities[256];
+ rigidbody _null = {0};
+ _null.inv_mass = 0.0f;
+ m3x3_zero( _null.iI );
+
for( int i=0; i<rd->part_count; i ++ ){
- v4_copy( rd->parts[i].obj.rb.q, rd->parts[i].prev_q );
- v3_copy( rd->parts[i].obj.rb.co, rd->parts[i].prev_co );
+ v4_copy( rd->parts[i].rb.q, rd->parts[i].prev_q );
+ v3_copy( rd->parts[i].rb.co, rd->parts[i].prev_co );
if( rb_global_has_space() ){
rb_ct *buf = rb_global_buffer();
int l;
- 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,
+ if( rd->parts[i].type == k_bone_collider_capsule ){
+ l = rb_capsule__scene( rd->parts[i].rb.to_world,
+ &rd->parts[i].inf.capsule,
+ NULL, world->geo_bh, 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,
+ else if( rd->parts[i].type == k_bone_collider_box ){
+ l = rb_box__scene( rd->parts[i].rb.to_world,
+ rd->parts[i].inf.box,
+ NULL, world->geo_bh, buf,
k_material_flag_ghosts );
}
else continue;
for( int j=0; j<l; j++ ){
- buf[j].rba = &rd->parts[i].obj.rb;
- buf[j].rbb = &world->rb_geo.rb;
+ buf[j].rba = &rd->parts[i].rb;
+ buf[j].rbb = &_null;
}
rb_contact_count += l;
if( !rb_global_has_space() )
break;
- if( rd->parts[j].obj.type != k_rb_shape_capsule )
+ if( rd->parts[j].type != k_bone_collider_capsule )
continue;
- if( rd->parts[i].obj.type != k_rb_shape_capsule )
+ if( rd->parts[i].type != k_bone_collider_capsule )
continue;
rb_ct *buf = rb_global_buffer();
- 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,
+ int l = rb_capsule__capsule( rd->parts[i].rb.to_world,
+ &rd->parts[i].inf.capsule,
+ rd->parts[j].rb.to_world,
+ &rd->parts[j].inf.capsule,
buf );
for( int k=0; k<l; k++ ){
- buf[k].rba = &rd->parts[i].obj.rb;
- buf[k].rbb = &rd->parts[j].obj.rb;
+ buf[k].rba = &rd->parts[i].rb;
+ buf[k].rbb = &rd->parts[j].rb;
}
rb_contact_count += l;
struct ragdoll_part *pj = &rd->parts[j];
if( run_sim ){
- rb_effect_simple_bouyency( &pj->obj.rb, world->water.plane,
+ rb_effect_simple_bouyency( &pj->rb, world->water.plane,
k_ragdoll_floatyiness,
k_ragdoll_floatydrag );
}
* DEBUG
*/
if( k_ragdoll_debug_collider ){
- for( u32 i=0; i<rd->part_count; i ++ )
- rb_object_debug( &rd->parts[i].obj, rd->parts[i].colour );
+ for( u32 i=0; i<rd->part_count; i ++ ){
+ struct ragdoll_part *rp = &rd->parts[i];
+
+ if( rp->type == k_bone_collider_capsule ){
+ vg_line_capsule( rp->rb.to_world,
+ rp->inf.capsule.r, rp->inf.capsule.h, rp->colour );
+ }
+ else if( rp->type == k_bone_collider_box ){
+ vg_line_boxf_transformed( rp->rb.to_world,
+ rp->inf.box, rp->colour );
+ }
+ }
}
if( k_ragdoll_debug_constraints ){
k_ragdoll_correction * 0.25f );
for( int i=0; i<rd->part_count; i++ ){
- rb_iter( &rd->parts[i].obj.rb );
+ rb_iter( &rd->parts[i].rb );
v3f w;
- v3_copy( rd->parts[i].obj.rb.w, w );
+ v3_copy( rd->parts[i].rb.w, w );
if( v3_length2( w ) > 0.00001f ){
v3_normalize( w );
- v3_muladds( rd->parts[i].obj.rb.w, w, -k_ragdoll_angular_drag,
- rd->parts[i].obj.rb.w );
+ v3_muladds( rd->parts[i].rb.w, w, -k_ragdoll_angular_drag,
+ rd->parts[i].rb.w );
}
}
for( int i=0; i<rd->part_count; i++ )
- rb_update_transform( &rd->parts[i].obj.rb );
+ rb_update_matrices( &rd->parts[i].rb );
}
rb_ct *stress = NULL;
u32 use_limits;
v3f limits[2];
- rb_object obj;
u32 parent;
u32 colour;
+
+ rigidbody rb;
+ enum bone_collider type;
+
+ union {
+ rb_capsule capsule;
+ boxf box;
+ }
+ inf;
}
parts[32];
u32 part_count;
else if( localplayer.subsystem == k_player_subsystem_dead ){
struct replay_rb *arr = dst;
for( u32 i=0; i<localplayer.ragdoll.part_count; i ++ ){
- rigidbody *rb = &localplayer.ragdoll.parts[i].obj.rb;
+ rigidbody *rb = &localplayer.ragdoll.parts[i].rb;
v3_copy( rb->co, arr[i].co );
v3_copy( rb->w, arr[i].w );
v3_copy( rb->v, arr[i].v );
for( u32 i=0; i<localplayer.ragdoll.part_count; i ++ ){
struct ragdoll_part *part = &localplayer.ragdoll.parts[i];
- rigidbody *rb = &part->obj.rb;
+ rigidbody *rb = &part->rb;
v3_copy( arr[i].co, rb->co );
v3_copy( arr[i].w, rb->w );
static void player__skate_bind(void){
struct skeleton *sk = &localplayer.skeleton;
- rb_update_transform( &localplayer.rb );
+ rb_update_matrices( &localplayer.rb );
struct { struct skeleton_anim **anim; const char *name; }
bindings[] = {
* Does collision detection on a sphere vs world, and applies some smoothing
* filters to the manifold afterwards
*/
-static int skate_collide_smooth( m4x3f mtx, rb_sphere *sphere, rb_ct *man ){
+static int skate_collide_smooth( m4x3f mtx, f32 r, rb_ct *man ){
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, r, NULL, world->geo_bh, man,
k_material_flag_walking );
for( int i=0; i<len; i++ ){
localplayer.rb.w );
state->flip_time += state->flip_rate * k_rb_delta;
- rb_update_transform( &localplayer.rb );
+ rb_update_matrices( &localplayer.rb );
}
static enum trick_type player_skate_trick_input(void){
m3x3_q( transfer, qtransfer );
q_mul( qtransfer, state->store_smoothed, state->smoothed_rotation );
q_normalize( state->smoothed_rotation );
- rb_update_transform( &localplayer.rb );
+ rb_update_matrices( &localplayer.rb );
if( end ){
state->activity = k_skate_activity_air;
if( state->activity <= k_skate_activity_air_to_grind ){
localplayer.subsystem = k_player_subsystem_glide;
+
+ v3_copy( localplayer.rb.co, player_glide.rb.co );
+ v4_copy( localplayer.rb.q, player_glide.rb.q );
+ v3_copy( localplayer.rb.v, player_glide.rb.v );
+ v3_copy( localplayer.rb.w, player_glide.rb.w );
+ rb_update_matrices( &player_glide.rb );
+
player__begin_holdout( (v3f){0,0,0} );
return;
}
v3_add( localplayer.rb.co, cg_offset, localplayer.rb.co );
}
- rb_update_transform( &localplayer.rb );
+ rb_update_matrices( &localplayer.rb );
localplayer.rb.v[1] += -state->gravity_bias * player_skate.substep_delta;
player_skate.substep -= player_skate.substep_delta;
k_material_flag_walking ) != -1) )
{
v3_lerp( start_co, localplayer.rb.co, t, localplayer.rb.co );
- rb_update_transform( &localplayer.rb );
+ rb_update_matrices( &localplayer.rb );
player__dead_transition( k_player_die_type_head );
return;
m4x3f mtx;
m3x3_identity( mtx );
m4x3_mulv( localplayer.rb.to_world, wheels[i].pos, mtx[3] );
-
- rb_sphere collider = { .radius = wheels[i].radius };
rb_ct *man = &manifold[ manifold_len ];
- int l = skate_collide_smooth( mtx, &collider, man );
+ int l = skate_collide_smooth( mtx, wheels[i].radius, man );
if( l )
wheels[i].state = k_collider_state_colliding;
}
float grind_radius = k_board_radius * 0.75f;
- rb_capsule capsule = { .height = (k_board_length+0.2f)*2.0f,
- .radius=grind_radius };
+ rb_capsule capsule = { .h = (k_board_length+0.2f)*2.0f,
+ .r = grind_radius };
m4x3f mtx;
v3_muls( localplayer.rb.to_world[0], 1.0f, mtx[0] );
v3_muls( localplayer.rb.to_world[2], -1.0f, mtx[1] );
rb_ct *cman = &manifold[manifold_len];
- int l = rb_capsule__scene( mtx, &capsule, NULL, &world->rb_geo.inf.scene,
+ int l = rb_capsule__scene( mtx, &capsule, NULL, world->geo_bh,
cman, k_material_flag_walking );
/* weld joints */
manifold_len += l;
if( vg_lines.draw )
- vg_line_capsule( mtx, capsule.radius, capsule.height, VG__WHITE );
+ vg_line_capsule( mtx, capsule.r, capsule.h, VG__WHITE );
/* add limits */
if( state->activity >= k_skate_activity_grind_any ){
v3f dt;
rb_depenetrate( manifold, manifold_len, dt );
v3_add( dt, localplayer.rb.co, localplayer.rb.co );
- rb_update_transform( &localplayer.rb );
+ rb_update_matrices( &localplayer.rb );
substep_count ++;
q_mul( transport_rotation, localplayer.rb.q, localplayer.rb.q );
q_mul( transport_rotation, state->smoothed_rotation,
state->smoothed_rotation );
- rb_update_transform( &localplayer.rb );
+ q_normalize( localplayer.rb.q );
+ q_normalize( state->smoothed_rotation );
+ rb_update_matrices( &localplayer.rb );
player__pass_gate( id );
}
player__begin_holdout( (v3f){0.0f,0.0f,0.0f} );
player__skate_reset_animator();
player__skate_clear_mechanics();
- rb_update_transform( &localplayer.rb );
+ rb_update_matrices( &localplayer.rb );
v3_copy( (v3f){yaw,0.0f,0.0f}, player_skate.state.trick_euler );
if( init == k_skate_activity_air )
v3f init_velocity;
player_walk_drop_in_vector( init_velocity );
- rb_update_transform( &localplayer.rb );
+ rb_update_matrices( &localplayer.rb );
v3_muladds( localplayer.rb.co, localplayer.rb.to_world[1], 1.0f,
player_skate.state.cog );
v3_copy( init_velocity, player_skate.state.cog_v );
enum walk_activity prev_state = w->state.activity;
- w->collider.height = 2.0f;
- w->collider.radius = 0.3f;
+ w->collider.h = 2.0f;
+ w->collider.r = 0.3f;
m4x3f mtx;
m3x3_copy( localplayer.rb.to_world, mtx );
v3_add( localplayer.rb.co, (v3f){0,1,0}, mtx[3] );
- vg_line_capsule( mtx, w->collider.radius, w->collider.height, VG__WHITE );
+ vg_line_capsule( mtx, w->collider.r, w->collider.h, VG__WHITE );
rb_ct manifold[64];
int len;
*/
len = rb_capsule__scene( mtx, &w->collider, NULL,
- &world->rb_geo.inf.scene, manifold, 0 );
+ world->geo_bh, manifold, 0 );
player_walk_custom_filter( world, manifold, len, 0.01f );
len = rb_manifold_apply_filtered( manifold, len );
v3f pa, pb;
v3_copy( localplayer.rb.co, pa );
- pa[1] += w->collider.radius + max_dist;
+ pa[1] += w->collider.r + max_dist;
v3_add( pa, (v3f){0, -max_dist * 2.0f, 0}, pb );
vg_line( pa, pb, 0xff000000 );
v3f n;
float t;
if( spherecast_world( world, pa, pb,
- w->collider.radius, &t, n, 0 ) != -1 ){
+ w->collider.r, &t, n, 0 ) != -1 ){
if( player_walk_normal_standable(n) ){
v3_lerp( pa, pb, t, localplayer.rb.co );
- localplayer.rb.co[1] += -w->collider.radius - k_penetration_slop;
+ localplayer.rb.co[1] += -w->collider.r - k_penetration_slop;
w->state.activity = k_walk_activity_ground;
float d = -v3_dot(n,localplayer.rb.v);
v3_muladds( localplayer.rb.co, localplayer.rb.v, k_rb_delta,
localplayer.rb.co );
v3_add( localplayer.rb.co, (v3f){0,1,0}, mtx[3] );
- vg_line_capsule( mtx, w->collider.radius, w->collider.height, VG__GREEN );
+ vg_line_capsule( mtx, w->collider.r, w->collider.h, VG__GREEN );
/*
* CCD routine
*/
v3f lwr_prev,
lwr_now,
- lwr_offs = { 0.0f, w->collider.radius, 0.0f };
+ lwr_offs = { 0.0f, w->collider.r, 0.0f };
v3_add( lwr_offs, w->state.prev_pos, lwr_prev );
v3_add( lwr_offs, localplayer.rb.co, lwr_now );
float movedist = v3_length( movedelta );
if( movedist > 0.3f ){
- float t, sr = w->collider.radius-0.04f;
+ float t, sr = w->collider.r-0.04f;
v3f n;
if( spherecast_world( world, lwr_prev, lwr_now, sr, &t, n, 0 ) != -1 ){
v3_lerp( lwr_prev, lwr_now, vg_maxf(0.01f,t), localplayer.rb.co );
- localplayer.rb.co[1] -= w->collider.radius;
- rb_update_transform( &localplayer.rb );
-
+ localplayer.rb.co[1] -= w->collider.r;
+ rb_update_matrices( &localplayer.rb );
v3_add( localplayer.rb.co, (v3f){0,1,0}, mtx[3] );
- vg_line_capsule( mtx, w->collider.radius, w->collider.height, VG__RED);
+ vg_line_capsule( mtx, w->collider.r, w->collider.h, VG__RED);
}
}
v4f transport_rotation;
m3x3_q( gate->transport, transport_rotation );
q_mul( transport_rotation, localplayer.rb.q, localplayer.rb.q );
-
- rb_update_transform( &localplayer.rb );
+ q_normalize( localplayer.rb.q );
+ rb_update_matrices( &localplayer.rb );
player__pass_gate( id );
}
- rb_update_transform( &localplayer.rb );
+ rb_update_matrices( &localplayer.rb );
if( (prev_state == k_walk_activity_oregular) ||
(prev_state == k_walk_activity_oair) ||
float substep = vg.time_fixed_extrapolate;
v3_muladds( mtx[3], localplayer.rb.v, k_rb_delta*substep, mtx[3] );
- vg_line_capsule( mtx, w->collider.radius, w->collider.height, VG__YELOW );
+ vg_line_capsule( mtx, w->collider.r, w->collider.h, VG__YELOW );
/* Calculate header */
v3f v;
v3_lerp( localplayer.rb.co, final_co, animator->transition_t,
localplayer.rb.co );
- rb_update_transform( &localplayer.rb );
+ rb_update_matrices( &localplayer.rb );
v3_muladds( localplayer.rb.co, localplayer.rb.to_world[1],
-0.1f*animator->transition_t, localplayer.rb.co );
w->state.walk_timer = 0.0f;
w->state.step_phase = 0;
w->animator.board_yaw = fmodf( board_yaw, 2.0f );
- rb_update_transform( &localplayer.rb );
+ rb_update_matrices( &localplayer.rb );
}
static void player__walk_reset(void){
q_axis_angle( localplayer.rb.q, (v3f){0.0f,1.0f,0.0f},
atan2f(fwd[0], fwd[2]) );
- rb_update_transform( &localplayer.rb );
+ rb_update_matrices( &localplayer.rb );
}
static void player__walk_animator_exchange( bitpack_ctx *ctx, void *data ){
#include <math.h>
-static bh_system bh_system_rigidbodies;
-
#ifndef RIGIDBODY_H
#define RIGIDBODY_H
k_penetration_slop = 0.01f,
k_inertia_scale = 4.0f,
k_phys_baumgarte = 0.2f,
- k_gravity = 9.6f;
+ k_gravity = 9.6f,
+ k_rb_density = 8.0f;
static float
k_limit_bias = 0.02f,
VG_VAR_F32( k_joint_impulse, flags=VG_VAR_CHEAT );
}
+enum rb_shape {
+ k_rb_shape_none = 0,
+ k_rb_shape_box = 1,
+ k_rb_shape_sphere = 2,
+ k_rb_shape_capsule = 3,
+};
+
/*
* -----------------------------------------------------------------------------
* structure definitions
*/
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;
-typedef struct rb_scene rb_scene;
-
-struct rb_sphere{
- float radius;
-};
struct rb_capsule{
- float height, radius;
-};
-
-struct rb_scene{
- bh_tree *bh_scene;
+ f32 h, r;
};
struct rigidbody{
v3f co, v, w;
v4f q;
- boxf bbx, bbx_world;
- float inv_mass;
+ f32 inv_mass;
- /* inertia model and inverse world tensor */
- m3x3f iI, iIw;
+ m3x3f iI, iIw; /* inertia model and inverse world tensor */
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,
- k_rb_shape_scene = 3
- }
- type;
-
- union{
- struct rb_sphere sphere;
- struct rb_capsule capsule;
- struct rb_scene scene;
- }
- inf;
-};
-
static struct contact{
rigidbody *rba, *rbb;
v3f co, n;
}
}
-
-static void rb_object_debug( rb_object *obj, u32 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( obj->type == k_rb_shape_sphere ){
- vg_line_sphere( obj->rb.to_world, obj->inf.sphere.radius, colour );
- }
- else if( obj->type == k_rb_shape_capsule ){
- m4x3f m0, m1;
- float h = obj->inf.capsule.height,
- r = obj->inf.capsule.radius;
-
- vg_line_capsule( obj->rb.to_world, r, h, colour );
- }
- else if( obj->type == k_rb_shape_scene ){
- vg_line_boxf( obj->rb.bbx, colour );
- }
-}
-
/*
* -----------------------------------------------------------------------------
* Integration
*/
/*
- * Update world space bounding box based on local one
- */
-static void rb_update_bounds( rigidbody *rb ){
- box_init_inf( rb->bbx_world );
- m4x3_expand_aabb_aabb( rb->to_world, rb->bbx_world, rb->bbx );
-}
-
-/*
- * Commit transform to rigidbody. Updates matrices
+ * Update ALL matrices and tensors on rigidbody
*/
-static void rb_update_transform( rigidbody *rb )
-{
- q_normalize( rb->q );
+static void rb_update_matrices( rigidbody *rb ){
+ //q_normalize( rb->q );
q_m3x3( rb->q, rb->to_world );
v3_copy( rb->co, rb->to_world[3] );
-
m4x3_invert_affine( rb->to_world, rb->to_local );
/* I = R I_0 R^T */
m3x3_mul( rb->to_world, rb->iI, rb->iIw );
m3x3_mul( rb->iIw, rb->to_local, rb->iIw );
-
- rb_update_bounds( rb );
}
/*
* Extrapolate rigidbody into a transform based on vg accumulator.
* Useful for rendering
*/
-static void rb_extrapolate( rigidbody *rb, v3f co, v4f q )
-{
+static void rb_extrapolate( rigidbody *rb, v3f co, v4f q ){
float substep = vg.time_fixed_extrapolate;
v3_muladds( rb->co, rb->v, k_rb_delta*substep, co );
}
/*
- * Initialize rigidbody and calculate masses, inertia
+ * Inertia
+ * -----------------------------------------------------------------------------
*/
-static void rb_init_object( rb_object *obj, f32 inertia_scale ){
- float volume = 1.0f;
- int inert = 0;
-
- if( obj->type == k_rb_shape_box ){
- v3f dims;
- v3_sub( obj->rb.bbx[1], obj->rb.bbx[0], dims );
- volume = dims[0]*dims[1]*dims[2];
- }
- else if( obj->type == k_rb_shape_sphere ){
- volume = vg_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( obj->type == k_rb_shape_capsule ){
- float r = obj->inf.capsule.radius,
- h = obj->inf.capsule.height;
- volume = vg_sphere_volume( r ) + VG_PIf * r*r * (h - r*2.0f);
-
- 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( obj->type == k_rb_shape_scene ){
- inert = 1;
- box_copy( obj->inf.scene.bh_scene->nodes[0].bbx, obj->rb.bbx );
- }
- if( inert ){
- obj->rb.inv_mass = 0.0f;
- m3x3_zero( obj->rb.iI );
- }
- else{
- f32 mass = 8.0f*volume;
- obj->rb.inv_mass = 1.0f/mass;
+/*
+ * Translate existing inertia tensor
+ */
+static void rb_translate_inertia( m3x3f inout_inertia, f32 mass, v3f d ){
+ /*
+ * I = I_0 + m*[(d.d)E_3 - d(X)d]
+ *
+ * I: updated tensor
+ * I_0: original tensor
+ * m: scalar mass
+ * d: translation vector
+ * (X): outer product
+ * E_3: identity matrix
+ */
+ m3x3f t, outer, scale;
+ m3x3_diagonal( t, v3_dot(d,d) );
+ m3x3_outer_product( outer, d, d );
+ m3x3_sub( t, outer, t );
+ m3x3_diagonal( scale, mass );
+ m3x3_mul( scale, t, t );
+ m3x3_add( inout_inertia, t, inout_inertia );
+}
+
+/*
+ * Rotate existing inertia tensor
+ */
+static void rb_rotate_inertia( m3x3f inout_inertia, m3x3f rotation ){
+ /*
+ * I = R I_0 R^T
+ *
+ * I: updated tensor
+ * I_0: original tensor
+ * R: rotation matrix
+ * R^T: tranposed rotation matrix
+ */
+
+ m3x3f Rt;
+ m3x3_transpose( rotation, Rt );
+ m3x3_mul( rotation, inout_inertia, inout_inertia );
+ m3x3_mul( inout_inertia, Rt, inout_inertia );
+}
+/*
+ * Create inertia tensor for box
+ */
+static void rb_box_inertia( boxf box, f32 mass, m3x3f out_inertia ){
+ v3f e, com;
+ v3_sub( box[1], box[0], e );
+ v3_muladds( box[0], e, 0.5f, com );
+
+ f32 ex2 = e[0]*e[0],
+ ey2 = e[1]*e[1],
+ ez2 = e[2]*e[2],
+ ix = (ey2+ez2) * mass * (1.0f/12.0f),
+ iy = (ex2+ez2) * mass * (1.0f/12.0f),
+ iz = (ex2+ey2) * mass * (1.0f/12.0f);
+
+ m3x3_identity( out_inertia );
+ m3x3_setdiagonalv3( out_inertia, (v3f){ ix, iy, iz } );
+ rb_translate_inertia( out_inertia, mass, com );
+}
+
+/*
+ * Create inertia tensor for sphere
+ */
+static void rb_sphere_inertia( f32 r, f32 mass, m3x3f out_inertia ){
+ f32 ixyz = r*r * mass * (2.0f/5.0f);
+
+ m3x3_identity( out_inertia );
+ m3x3_setdiagonalv3( out_inertia, (v3f){ ixyz, ixyz, ixyz } );
+}
- v3f extent, com;
- v3_sub( obj->rb.bbx[1], obj->rb.bbx[0], extent );
- v3_muladds( obj->rb.bbx[0], extent, 0.5f, com );
+/*
+ * Create inertia tensor for capsule
+ *
+ * TODO: UNTESTED
+ */
+static void rb_capsule_inertia( f32 r, f32 h, f32 mass, m3x3f out_inertia ){
+ f32 density = mass / vg_capsule_volume( r, h ),
+ ch = h-r*2.0f, /* cylinder height */
+ cm = VG_PIf * ch*r*r * density, /* cylinder mass */
+ hm = VG_TAUf * (1.0f/3.0f) * r*r*r * density, /* hemisphere mass */
+
+ iy = r*r*cm * 0.5f,
+ ixz = iy * 0.5f + cm*ch*ch*(1.0f/12.0f),
- /* local intertia tensor */
- f32 ex2 = extent[0]*extent[0],
- ey2 = extent[1]*extent[1],
- ez2 = extent[2]*extent[2];
+ aux0= (hm*2.0f*r*r)/5.0f;
- /* compute inertia tensor */
- v3f I;
+ iy += aux0 * 2.0f;
- if( obj->type == k_rb_shape_box ){
- I[0] = inertia_scale * (ey2+ez2) * mass * (1.0f/12.0f);
- I[1] = inertia_scale * (ex2+ez2) * mass * (1.0f/12.0f);
- I[2] = inertia_scale * (ex2+ey2) * mass * (1.0f/12.0f);
- }
- else if( obj->type == k_rb_shape_sphere ){
- f32 r = obj->inf.sphere.radius;
- v3_fill( I, inertia_scale * r*r * mass * (2.0f/5.0f) );
- }
- else if( obj->type == k_rb_shape_capsule ){
- f32 r = obj->inf.capsule.radius;
- I[1] = inertia_scale * r*r * mass * (2.0f/5.0f);
- I[0] = inertia_scale * (ey2+ez2) * mass * (1.0f/12.0f);
- I[2] = inertia_scale * (ey2+ex2) * mass * (1.0f/12.0f);
- }
- else {
- vg_fatal_error( "" );
- }
+ f32 aux1= ch*0.5f,
+ aux2= aux0 + hm*(aux1*aux1 + 3.0f*(1.0f/8.0f)*ch*r);
- m3x3f i;
- m3x3_identity( i );
- m3x3_setdiagonalv3( i, I );
+ ixz += aux2*2.0f;
- /* compute translation */
- m3x3f i_t, i_t_outer, i_t_scale;
- m3x3_diagonal( i_t, v3_dot(com,com) );
- m3x3_outer_product( i_t_outer, com, com );
- m3x3_sub( i_t, i_t_outer, i_t );
- m3x3_diagonal( i_t_scale, mass );
- m3x3_mul( i_t_scale, i_t, i_t );
+ m3x3_identity( out_inertia );
+ m3x3_setdiagonalv3( out_inertia, (v3f){ ixz, iy, ixz } );
+}
- /* TODO: compute rotation */
+static void rb_setbody_capsule( rigidbody *rb, f32 r, f32 h,
+ f32 density, f32 inertia_scale ){
+ f32 vol = vg_capsule_volume( r, h ),
+ mass = vol*density;
- /* add Ic and Ict */
- m3x3_add( i, i_t, i );
+ rb->inv_mass = 1.0f/mass;
- /* store as inverted */
- m3x3_inv( i, obj->rb.iI );
- }
+ m3x3f I;
+ rb_capsule_inertia( r, h, mass * inertia_scale, I );
+ m3x3_inv( I, rb->iI );
+}
+
+static void rb_setbody_box( rigidbody *rb, boxf box,
+ f32 density, f32 inertia_scale ){
+ f32 vol = vg_box_volume( box ),
+ mass = vol*density;
+
+ rb->inv_mass = 1.0f/mass;
+
+ m3x3f I;
+ rb_box_inertia( box, mass * inertia_scale, I );
+ m3x3_inv( I, rb->iI );
+}
- rb_update_transform( &obj->rb );
+static void rb_setbody_sphere( rigidbody *rb, f32 r,
+ f32 density, f32 inertia_scale ){
+ f32 vol = vg_sphere_volume( r ),
+ mass = vol*density;
+
+ rb->inv_mass = 1.0f/mass;
+ m3x3f I;
+ rb_sphere_inertia( r, mass * inertia_scale, I );
+ m3x3_inv( I, rb->iI );
}
static void rb_iter( rigidbody *rb ){
v3_lerp( rb->w, (v3f){0.0f,0.0f,0.0f}, 0.0025f, rb->w );
/* inegrate inertia */
- if( v3_length2( rb->w ) > 0.0f )
- {
+ if( v3_length2( rb->w ) > 0.0f ){
v4f rotation;
v3f axis;
v3_copy( rb->w, axis );
v3_divs( axis, mag, axis );
q_axis_angle( rotation, axis, mag*k_rb_delta );
q_mul( rotation, rb->q, rb->q );
+ q_normalize( rb->q );
}
-
-#if 0
- /* damping */
- v3_muls( rb->v, 1.0f/(1.0f+k_rb_delta*k_damp_linear), rb->v );
- v3_muls( rb->w, 1.0f/(1.0f+k_rb_delta*k_damp_angular), rb->w );
-#endif
}
-
/*
* -----------------------------------------------------------------------------
* Boolean shape overlap functions
}
static int rb_capsule__manifold_done( m4x3f mtx, rb_capsule *c,
- capsule_manifold *manifold,
- rb_ct *buf ){
+ capsule_manifold *manifold,
+ rb_ct *buf ){
v3f p0, p1;
- v3_muladds( mtx[3], mtx[1], -c->height*0.5f+c->radius, p0 );
- v3_muladds( mtx[3], mtx[1], c->height*0.5f-c->radius, p1 );
+ v3_muladds( mtx[3], mtx[1], -c->h*0.5f+c->r, p0 );
+ v3_muladds( mtx[3], mtx[1], c->h*0.5f-c->r, p1 );
int count = 0;
if( manifold->t0 <= 1.0f ){
float d = v3_length( manifold->d0 );
v3_muls( manifold->d0, 1.0f/d, ct->n );
- v3_muladds( pa, ct->n, -c->radius, ct->co );
+ v3_muladds( pa, ct->n, -c->r, ct->co );
ct->p = manifold->r0 - d;
ct->type = k_contact_type_default;
float d = v3_length( manifold->d1 );
v3_muls( manifold->d1, 1.0f/d, ct->n );
- v3_muladds( pa, ct->n, -c->radius, ct->co );
+ v3_muladds( pa, ct->n, -c->r, ct->co );
ct->p = manifold->r1 - d;
ct->type = k_contact_type_default;
return count;
}
+#if 0
static int rb_capsule_sphere( rb_object *obja, rb_object *objb, rb_ct *buf ){
rigidbody *rba = &obja->rb, *rbb = &objb->rb;
- float h = obja->inf.capsule.height,
- ra = obja->inf.capsule.radius,
- rb = objb->inf.sphere.radius;
+ float h = obja->inf.capsule.h,
+ ra = obja->inf.capsule.r,
+ rb = objb->inf.sphere.r;
v3f p0, p1;
v3_muladds( rba->co, rba->to_world[1], -h*0.5f+ra, p0 );
return 0;
}
+#endif
static int rb_capsule__capsule( m4x3f mtxA, rb_capsule *ca,
- m4x3f mtxB, rb_capsule *cb, rb_ct *buf ){
- float ha = ca->height,
- hb = cb->height,
- ra = ca->radius,
- rb = cb->radius,
- r = ra+rb;
+ m4x3f mtxB, rb_capsule *cb, rb_ct *buf ){
+ f32 ha = ca->h,
+ hb = cb->h,
+ ra = ca->r,
+ rb = cb->r,
+ r = ra+rb;
v3f p0, p1, p2, p3;
v3_muladds( mtxA[3], mtxA[1], -ha*0.5f+ra, p0 );
rb_capsule_manifold_init( &manifold );
v3f pa, pb;
- float ta, tb;
+ f32 ta, tb;
closest_segment_segment( p0, p1, p2, p3, &ta, &tb, pa, pb );
rb_capsule_manifold( pa, pb, ta, r, &manifold );
return rb_capsule__manifold_done( mtxA, ca, &manifold, buf );
}
+#if 0
static int rb_sphere_box( rb_object *obja, rb_object *objb, rb_ct *buf ){
v3f co, delta;
rigidbody *rba = &obja->rb, *rbb = &objb->rb;
return 0;
}
+#endif
+#if 0
static int rb_sphere_sphere( rb_object *obja, rb_object *objb, rb_ct *buf ){
rigidbody *rba = &obja->rb, *rbb = &objb->rb;
v3f delta;
return 0;
}
+#endif
-static int rb_sphere__triangle( m4x3f mtxA, rb_sphere *b,
- v3f tri[3], rb_ct *buf ){
+static int rb_sphere__triangle( m4x3f mtxA, f32 r,
+ v3f tri[3], rb_ct *buf ){
v3f delta, co;
enum contact_type type = closest_on_triangle_1( mtxA[3], tri, co );
-
v3_sub( mtxA[3], co, delta );
-
- float d2 = v3_length2( delta ),
- r = b->radius;
+ f32 d2 = v3_length2( delta );
if( d2 <= r*r ){
rb_ct *ct = buf;
return 0;
}
-static int rb_sphere__scene( m4x3f mtxA, rb_sphere *b,
- m4x3f mtxB, rb_scene *s, rb_ct *buf,
- u16 ignore ){
- scene_context *sc = s->bh_scene->user;
+static int rb_sphere__scene( m4x3f mtxA, f32 r,
+ m4x3f mtxB, bh_tree *scene_bh, rb_ct *buf,
+ u16 ignore ){
+ scene_context *sc = scene_bh->user;
int count = 0;
- float r = b->radius + 0.1f;
boxf box;
v3_sub( mtxA[3], (v3f){ r,r,r }, box[0] );
v3_add( mtxA[3], (v3f){ r,r,r }, box[1] );
i32 idx;
bh_iter_init_box( 0, &it, box );
- while( bh_next( s->bh_scene, &it, &idx ) ){
+ while( bh_next( scene_bh, &it, &idx ) ){
u32 *ptri = &sc->arrindices[ idx*3 ];
v3f tri[3];
vg_line( tri[1],tri[2],0x70ff6000 );
vg_line( tri[2],tri[0],0x70ff6000 );
- int contact = rb_sphere__triangle( mtxA, b, tri, &buf[count] );
+ int contact = rb_sphere__triangle( mtxA, r, tri, &buf[count] );
count += contact;
if( count == 16 ){
}
static int rb_box__scene( m4x3f mtxA, boxf bbx,
- m4x3f mtxB, rb_scene *s, rb_ct *buf, u16 ignore ){
- scene_context *sc = s->bh_scene->user;
+ m4x3f mtxB, bh_tree *scene_bh,
+ rb_ct *buf, u16 ignore ){
+ scene_context *sc = scene_bh->user;
v3f tri[3];
v3f extent, center;
vg_line_boxf( world_bbx, VG__RED );
- while( bh_next( s->bh_scene, &it, &idx ) ){
+ while( bh_next( scene_bh, &it, &idx ) ){
u32 *ptri = &sc->arrindices[ idx*3 ];
if( sc->arrvertices[ptri[0]].flags & ignore ) continue;
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 );
+ v3_muladds( mtxA[3], mtxA[1], -c->h*0.5f+c->r, p0w );
+ v3_muladds( mtxA[3], mtxA[1], c->h*0.5f-c->r, p1w );
capsule_manifold manifold;
rb_capsule_manifold_init( &manifold );
* not very 'correct' */
f32 dist;
if( ray_tri( tri, p0w, mtxA[1], &dist, 1 ) ){
- f32 l = c->height - c->radius*2.0f;
+ f32 l = c->h - c->r*2.0f;
if( (dist >= 0.0f) && (dist < l) ){
v3f co;
v3_muladds( p0w, mtxA[1], dist, co );
v3_sub( p0w, co, d0 );
v3_sub( p1w, co, d1 );
- f32 p = vg_minf( v3_dot( n, d0 ), v3_dot( n, d1 ) ) - c->radius;
+ f32 p = vg_minf( v3_dot( n, d0 ), v3_dot( n, d1 ) ) - c->r;
rb_ct *ct = buf;
ct->p = -p;
/* the two balls at the ends */
if( v3_dot( da, d0 ) <= 0.01f )
- rb_capsule_manifold( p0w, c0, 0.0f, c->radius, &manifold );
+ rb_capsule_manifold( p0w, c0, 0.0f, c->r, &manifold );
if( v3_dot( da, d1 ) >= -0.01f )
- rb_capsule_manifold( p1w, c1, 1.0f, c->radius, &manifold );
+ rb_capsule_manifold( p1w, c1, 1.0f, c->r, &manifold );
/* the edges to edges */
for( int i=0; i<3; i++ ){
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, c->radius, &manifold );
+ rb_capsule_manifold( ca, cb, ta, c->r, &manifold );
}
int count = rb_capsule__manifold_done( mtxA, c, &manifold, buf );
/* mtxB is defined only for tradition; it is not used currently */
static int rb_capsule__scene( m4x3f mtxA, rb_capsule *c,
- m4x3f mtxB, rb_scene *s,
- rb_ct *buf, u16 ignore ){
+ m4x3f mtxB, bh_tree *scene_bh,
+ rb_ct *buf, u16 ignore ){
int count = 0;
boxf bbx;
- v3_sub( mtxA[3], (v3f){ c->height, c->height, c->height }, bbx[0] );
- v3_add( mtxA[3], (v3f){ c->height, c->height, c->height }, bbx[1] );
+ v3_sub( mtxA[3], (v3f){ c->h, c->h, c->h }, bbx[0] );
+ v3_add( mtxA[3], (v3f){ c->h, c->h, c->h }, bbx[1] );
- scene_context *sc = s->bh_scene->user;
+ scene_context *sc = scene_bh->user;
bh_iter it;
bh_iter_init_box( 0, &it, bbx );
i32 idx;
- while( bh_next( s->bh_scene, &it, &idx ) ){
+ while( bh_next( scene_bh, &it, &idx ) ){
u32 *ptri = &sc->arrindices[ idx*3 ];
if( sc->arrvertices[ptri[0]].flags & ignore ) continue;
#if 1
v3_muladds( rbb->co, d, -1.0f * amt, rbb->co );
- rb_update_transform( rbb );
+ rb_update_matrices( rbb );
#else
f32 mt = 1.0f/(rba->inv_mass+rbb->inv_mass),
a = mt * (k_phys_baumgarte/k_rb_delta);
v4f correction;
q_axis_angle( correction, axis, angle );
q_mul( correction, st->rbb->q, st->rbb->q );
- rb_update_transform( st->rbb );
+ q_normalize( st->rbb->q );
+ rb_update_matrices( st->rbb );
#else
f32 mt = 1.0f/(st->rba->inv_mass+st->rbb->inv_mass),
wa = mt * acosf(angle) * (k_phys_baumgarte/k_rb_delta);
v4f correction;
q_axis_angle( correction, axis, angle );
q_mul( correction, st->rbb->q, st->rbb->q );
- rb_update_transform( st->rbb );
+ q_normalize( st->rbb->q );
+ rb_update_matrices( st->rbb );
#else
f32 mt = 1.0f/(st->rba->inv_mass+st->rbb->inv_mass),
wa = mt * acosf(angle) * (k_phys_baumgarte/k_rb_delta);
#include "rigidbody.h"
-static rb_object baller = {
- .type = k_rb_shape_box,
- .rb.bbx = {{ -0.1f, -0.2f, -0.1f },
- { 0.1f, 1.0f, 0.1f }},
+struct {
+ rigidbody rb;
+ boxf box;
+}
+static baller = {
.rb.q = { 0,0,0,1 },
+ .box = {{ -0.1f, -0.2f, -0.1f },
+ { 0.1f, 1.0f, 0.1f }},
};
static void testing_update(void){
v3_zero( baller.rb.w );
v3_zero( baller.rb.v );
q_identity( baller.rb.q );
- rb_update_transform( &baller.rb );
+ rb_update_matrices( &baller.rb );
}
- rb_object_debug( &baller, VG__RED );
+ vg_line_boxf_transformed( baller.rb.to_world, baller.box, VG__RED );
world_instance *world = world_current_instance();
+ rigidbody _null = {0};
+ _null.inv_mass = 0.0f;
+ m3x3_zero( _null.iI );
+
rb_solver_reset();
rb_ct *buf = rb_global_buffer();
- rb_contact_count += rb_box__scene( baller.rb.to_world, baller.rb.bbx,
- NULL, &world->rb_geo.inf.scene, buf,
+ rb_contact_count += rb_box__scene( baller.rb.to_world, baller.box,
+ NULL, world->geo_bh, buf,
k_material_flag_ghosts );
for( u32 j=0; j<rb_contact_count; j++ ){
buf[j].rba = &baller.rb;
- buf[j].rbb = &world->rb_geo.rb;
+ buf[j].rbb = &_null;
}
rb_presolve_contacts( rb_contact_buffer, rb_contact_count );
rb_solve_contacts( rb_contact_buffer, rb_contact_count );
rb_iter( &baller.rb );
- rb_update_transform( &baller.rb );
+ rb_update_matrices( &baller.rb );
}
static void testing_init(void){
- rb_init_object( &baller, 1.0f );
+ rb_setbody_box( &baller.rb, baller.box, 8.0f, 1.0f );
}
v3_muladds( ra, skaterift.cam.transform[2], -10.0f, rb );
float t;
- if( spherecast_world( world_current_instance(), ra, rb,
- gzoomer.obj.inf.sphere.radius, &t, rx, 0 ) != -1 )
+ if( spherecast_world( world_current_instance(),
+ ra, rb, 1.0f, &t, rx, 0 ) != -1 )
{
- v3_lerp( ra, rb, t, gzoomer.obj.rb.co );
- gzoomer.obj.rb.co[1] += 4.0f;
- q_axis_angle( gzoomer.obj.rb.q, (v3f){1.0f,0.0f,0.0f}, 0.001f );
- v3_zero( gzoomer.obj.rb.v );
- v3_zero( gzoomer.obj.rb.w );
+ v3_lerp( ra, rb, t, gzoomer.rb.co );
+ gzoomer.rb.co[1] += 4.0f;
+ q_axis_angle( gzoomer.rb.q, (v3f){1.0f,0.0f,0.0f}, 0.001f );
+ v3_zero( gzoomer.rb.v );
+ v3_zero( gzoomer.rb.w );
- rb_update_transform( &gzoomer.obj.rb );
+ rb_update_matrices( &gzoomer.rb );
gzoomer.alive = 1;
vg_success( "Spawned car\n" );
return 0;
}
-static void vehicle_init(void)
-{
- q_identity( gzoomer.obj.rb.q );
- v3_zero( gzoomer.obj.rb.w );
- v3_zero( gzoomer.obj.rb.v );
- v3_zero( gzoomer.obj.rb.co );
- rb_init_object( &gzoomer.obj, 1.0f );
+static void vehicle_init(void){
+ q_identity( gzoomer.rb.q );
+ v3_zero( gzoomer.rb.w );
+ v3_zero( gzoomer.rb.v );
+ v3_zero( gzoomer.rb.co );
+ rb_setbody_sphere( &gzoomer.rb, 1.0f, 8.0f, 1.0f );
VG_VAR_F32( k_car_spring, flags=VG_VAR_PERSISTENT );
VG_VAR_F32( k_car_spring_damp, flags=VG_VAR_PERSISTENT );
v3_copy((v3f){ 1.0f, -0.25f, 1.5f }, gzoomer.wheels_local[3] );
}
-static void vehicle_wheel_force( int index )
-{
+static void vehicle_wheel_force( int index ){
v3f pa, pb, n;
- m4x3_mulv( gzoomer.obj.rb.to_world, gzoomer.wheels_local[index], pa );
- v3_muladds( pa, gzoomer.obj.rb.to_world[1], -k_car_spring_length, pb );
+ m4x3_mulv( gzoomer.rb.to_world, gzoomer.wheels_local[index], pa );
+ v3_muladds( pa, gzoomer.rb.to_world[1], -k_car_spring_length, pb );
#if 1
v3_lerp( pa, pb, t, pc );
m4x3f mtx;
- m3x3_copy( gzoomer.obj.rb.to_world, mtx );
+ m3x3_copy( gzoomer.rb.to_world, mtx );
v3_copy( pc, mtx[3] );
vg_line_sphere( mtx, k_car_wheel_radius, VG__BLACK );
vg_line( pa, pc, VG__WHITE );
float Fv = (1.0f-t) * k_car_spring*k_rb_delta;
v3f delta;
- v3_sub( pa, gzoomer.obj.rb.co, delta );
+ v3_sub( pa, gzoomer.rb.co, delta );
v3f rv;
- v3_cross( gzoomer.obj.rb.w, delta, rv );
- v3_add( gzoomer.obj.rb.v, rv, rv );
+ v3_cross( gzoomer.rb.w, delta, rv );
+ v3_add( gzoomer.rb.v, rv, rv );
- Fv += v3_dot( rv, gzoomer.obj.rb.to_world[1] )
- * -k_car_spring_damp*k_rb_delta;
+ Fv += v3_dot(rv, gzoomer.rb.to_world[1]) * -k_car_spring_damp*k_rb_delta;
/* scale by normal incident */
- Fv *= v3_dot( n, gzoomer.obj.rb.to_world[1] );
+ Fv *= v3_dot( n, gzoomer.rb.to_world[1] );
v3f F;
- v3_muls( gzoomer.obj.rb.to_world[1], Fv, F );
-
- rb_linear_impulse( &gzoomer.obj.rb, delta, F );
+ v3_muls( gzoomer.rb.to_world[1], Fv, F );
+ rb_linear_impulse( &gzoomer.rb, delta, F );
/* friction vectors
* -------------------------------------------------------------*/
if( index <= 1 )
v3_cross( gzoomer.steerv, n, tx );
else
- v3_cross( n, gzoomer.obj.rb.to_world[2], tx );
+ v3_cross( n, gzoomer.rb.to_world[2], tx );
v3_cross( tx, n, ty );
v3_copy( tx, gzoomer.tangent_vectors[ index ][0] );
/* orient inverse inertia tensors */
v3f raW;
- m3x3_mulv( gzoomer.obj.rb.to_world, gzoomer.wheels_local[index], raW );
+ m3x3_mulv( gzoomer.rb.to_world, gzoomer.wheels_local[index], raW );
v3f raCtx, raCtxI, raCty, raCtyI;
v3_cross( tx, raW, raCtx );
v3_cross( ty, raW, raCty );
- m3x3_mulv( gzoomer.obj.rb.iIw, raCtx, raCtxI );
- m3x3_mulv( gzoomer.obj.rb.iIw, raCty, raCtyI );
+ m3x3_mulv( gzoomer.rb.iIw, raCtx, raCtxI );
+ m3x3_mulv( gzoomer.rb.iIw, raCty, raCtyI );
- gzoomer.tangent_mass[index][0] = gzoomer.obj.rb.inv_mass;
+ gzoomer.tangent_mass[index][0] = gzoomer.rb.inv_mass;
gzoomer.tangent_mass[index][0] += v3_dot( raCtx, raCtxI );
gzoomer.tangent_mass[index][0] = 1.0f/gzoomer.tangent_mass[index][0];
- gzoomer.tangent_mass[index][1] = gzoomer.obj.rb.inv_mass;
+ gzoomer.tangent_mass[index][1] = gzoomer.rb.inv_mass;
gzoomer.tangent_mass[index][1] += v3_dot( raCty, raCtyI );
gzoomer.tangent_mass[index][1] = 1.0f/gzoomer.tangent_mass[index][1];
/* apply drive force */
if( index >= 2 ){
v3_muls( ty, -gzoomer.drive * k_car_drive_force * k_rb_delta, F );
- rb_linear_impulse( &gzoomer.obj.rb, raW, F );
+ rb_linear_impulse( &gzoomer.rb, raW, F );
}
}
else{
}
}
-static void vehicle_solve_friction(void)
-{
- rigidbody *rb = &gzoomer.obj.rb;
+static void vehicle_solve_friction(void){
+ rigidbody *rb = &gzoomer.rb;
for( int i=0; i<4; i++ ){
v3f raW;
m3x3_mulv( rb->to_world, gzoomer.wheels_local[i], raW );
if( !gzoomer.alive )
return;
- rigidbody *rb = &gzoomer.obj.rb;
+ rigidbody *rb = &gzoomer.rb;
v3_muls( rb->to_world[2], -cosf(gzoomer.steer), gzoomer.steerv );
v3_muladds( gzoomer.steerv, rb->to_world[0],
for( int i=0; i<4; i++ )
vehicle_wheel_force( i );
+ rigidbody _null = {0};
+ _null.inv_mass = 0.0f;
+ m3x3_zero( _null.iI );
+
rb_ct manifold[64];
- int len = rb_sphere__scene( rb->to_world, &gzoomer.obj.inf.sphere, NULL,
- &world_current_instance()->rb_geo.inf.scene,
+ int len = rb_sphere__scene( rb->to_world, 1.0f, NULL,
+ world_current_instance()->geo_bh,
manifold, 0 );
for( int j=0; j<len; j++ ){
manifold[j].rba = rb;
- manifold[j].rbb = &world_current_instance()->rb_geo.rb;
+ manifold[j].rbb = &_null;
}
rb_manifold_filter_coplanar( manifold, len, 0.05f );
}
rb_iter( rb );
- rb_update_transform( rb );
+ rb_update_matrices( rb );
}
-static void vehicle_update_post(void)
-{
+static void vehicle_update_post(void){
if( !gzoomer.alive )
return;
- rb_object_debug( &gzoomer.obj, VG__WHITE );
+ vg_line_sphere( gzoomer.rb.to_world, 1.0f, VG__WHITE );
/* draw friction vectors */
v3f p0, px, py;
struct drivable_vehicle
{
int alive, inside;
- rb_object obj;
+ rigidbody rb;
v3f wheels[4];
}
static gzoomer =
{
- .obj = { .type = k_rb_shape_sphere, .inf.sphere.radius = 1.0f,
- .rb.co = {-2000,-2000,-2000}}
+ .rb.co = {-2000,-2000,-2000}
};
static int spawn_car( int argc, const char *argv[] );
mesh_water;
u32 cubemap_cooldown, cubemap_side;
- rb_object rb_geo;
-
/* leaderboards */
struct leaderboard_cache *leaderboard_cache;
/* need send off the memory to the gpu before we can create the bvh. */
vg_async_stall();
vg_info( "creating bvh\n" );
-
- /* setup spacial mapping and rigidbody */
world->geo_bh = scene_bh_create( world->heap, &world->scene_geo );
- 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;
- rb_init_object( &world->rb_geo, 0.0f );
-
/*
* Generate scene: non-collidable geometry
* ----------------------------------------------------------------
u32 timer_text_count;
struct text_particle{
- rb_object obj;
+ rigidbody rb;
m4x3f mlocal;
ent_glyph *glyph;
v4f colour;
-
m4x3f mdl;
+ f32 radius;
}
text_particles[6*4];
u32 text_particle_count;
for( u32 i=0; i<world_render.text_particle_count; i++ ){
struct text_particle *particle = &world_render.text_particles[i];
- rb_object_debug( &particle->obj, VG__RED );
+ //rb_object_debug( &particle->obj, VG__RED );
}
}
static void world_routes_fixedupdate( world_instance *world ){
rb_solver_reset();
+ rigidbody _null = {0};
+ _null.inv_mass = 0.0f;
+ m3x3_zero( _null.iI );
+
for( u32 i=0; i<world_render.text_particle_count; i++ ){
struct text_particle *particle = &world_render.text_particles[i];
if( rb_global_has_space() ){
rb_ct *buf = rb_global_buffer();
- int l = rb_sphere__scene( particle->obj.rb.to_world,
- &particle->obj.inf.sphere,
- NULL, &world->rb_geo.inf.scene, buf,
+ int l = rb_sphere__scene( particle->rb.to_world,
+ particle->radius,
+ NULL, world->geo_bh, buf,
k_material_flag_ghosts );
for( int j=0; j<l; j++ ){
- buf[j].rba = &particle->obj.rb;
- buf[j].rbb = &world->rb_geo.rb;
+ buf[j].rba = &particle->rb;
+ buf[j].rbb = &_null;
}
rb_contact_count += l;
for( u32 i=0; i<world_render.text_particle_count; i++ ){
struct text_particle *particle = &world_render.text_particles[i];
- rb_iter( &particle->obj.rb );
+ rb_iter( &particle->rb );
}
for( u32 i=0; i<world_render.text_particle_count; i++ ){
struct text_particle *particle = &world_render.text_particles[i];
- rb_update_transform( &particle->obj.rb );
+ rb_update_matrices( &particle->rb );
}
}
v3_add( offset, origin, world_co );
m4x3_mulv( transform, world_co, world_co );
- float r = vg_maxf( s[0]*glyph->size[0], s[1]*glyph->size[1] )*0.5f;
m3x3_identity( particle->mlocal );
m3x3_scale( particle->mlocal, s );
origin[2] *= s[2];
v3_muls( origin, -1.0f, particle->mlocal[3] );
- v3_copy( world_co, particle->obj.rb.co );
- v3_muls( imp_v, 1.0f+vg_randf64(&vg.rand), particle->obj.rb.v );
- particle->obj.rb.v[1] += 2.0f;
-
- v4_copy( q, particle->obj.rb.q );
- particle->obj.rb.w[0] = vg_randf64(&vg.rand)*2.0f-1.0f;
- particle->obj.rb.w[1] = vg_randf64(&vg.rand)*2.0f-1.0f;
- particle->obj.rb.w[2] = vg_randf64(&vg.rand)*2.0f-1.0f;
+ v3_copy( world_co, particle->rb.co );
+ v3_muls( imp_v, 1.0f+vg_randf64(&vg.rand), particle->rb.v );
+ particle->rb.v[1] += 2.0f;
- particle->obj.type = k_rb_shape_sphere;
- particle->obj.inf.sphere.radius = r*0.6f;
+ v4_copy( q, particle->rb.q );
+ particle->rb.w[0] = vg_randf64(&vg.rand)*2.0f-1.0f;
+ particle->rb.w[1] = vg_randf64(&vg.rand)*2.0f-1.0f;
+ particle->rb.w[2] = vg_randf64(&vg.rand)*2.0f-1.0f;
- rb_init_object( &particle->obj, 1.0f );
+ f32 r = vg_maxf( s[0]*glyph->size[0], s[1]*glyph->size[1] )*0.5f;
+ particle->radius = r*0.6f;
+ rb_setbody_sphere( &particle->rb, particle->radius, 1.0f, 1.0f );
}
offset[0] += glyph->size[0];
}
v4f q;
m4x3f model;
- rb_extrapolate( &particle->obj.rb, model[3], q );
+ rb_extrapolate( &particle->rb, model[3], q );
q_m3x3( q, model );
m4x3_mul( model, particle->mlocal, particle->mdl );