seperation of body initialization, glider model
authorhgn <hgodden00@gmail.com>
Wed, 24 Jan 2024 06:32:18 +0000 (06:32 +0000)
committerhgn <hgodden00@gmail.com>
Wed, 24 Jan 2024 06:32:18 +0000 (06:32 +0000)
18 files changed:
player.c
player_dead.c
player_drive.c
player_glide.c
player_glide.h
player_ragdoll.c
player_ragdoll.h
player_replay.c
player_skate.c
player_walk.c
rigidbody.h
testing.c
vehicle.c
vehicle.h
world.h
world_gen.c
world_render.h
world_routes.c

index 3a5c10069b1c233ea3f490f6d1ee1639b69ae3e3..f52c8bdeb7b16c687a676f678f98eaf6bf93249a 100644 (file)
--- a/player.c
+++ b/player.c
@@ -245,7 +245,7 @@ static void player__im_gui(void)
 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){
@@ -277,7 +277,7 @@ static void player__reset(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();
index 7733c327e2b0668d9a6a7439fd7fda829cdf509b..625ff0e7643cae2dfb8c0d4c5a4cb9dc93cd1789 100644 (file)
@@ -15,11 +15,11 @@ static void player__dead_post_update(void){
 
    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 );
@@ -66,9 +66,9 @@ static void player__dead_animate(void){
       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] );
@@ -144,9 +144,9 @@ static void player__dead_transition( enum player_die_type type ){
 
    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;
index 38b7e58c8e586102bfd2afbec92a49d5c80aa916..7881302865b1a2bd2fbe0ad474abf98958a50390 100644 (file)
@@ -17,10 +17,10 @@ static void player__drive_pre_update(void){
 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){}
@@ -39,7 +39,7 @@ static void player__drive_post_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
                ( 
index 3ec1fac58ad9266c0e697d7fb716fb60f1dec208..3091e57e2173c123c37206ad8eb6a10492102046 100644 (file)
@@ -60,8 +60,7 @@ static void calculate_drag( v3f vl, f32 cd, v3f out_force ){
 }
 
 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 );
@@ -116,11 +115,68 @@ static void player_glide_update(void){
    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){
@@ -180,6 +236,58 @@ static void player_glide_bind(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 */
index e50fde3755b77d14e0032a69bdaebab02b7caf64..0794b1c9b9347bca0b7c83ef9f85058bcd5af93b 100644 (file)
@@ -17,8 +17,44 @@ struct player_glide {
        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);
index e1231bcbd6956ba83e47b70d7697d1059bf15ebb..093b86f0bee2d67db25b0c46653153a9987437b9 100644 (file)
@@ -55,20 +55,24 @@ static void player_ragdoll_init(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;
@@ -88,9 +92,9 @@ static void player_init_ragdoll_bone_collider( struct skeleton_bone *bone,
       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] );
@@ -98,11 +102,10 @@ 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->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 );
@@ -112,11 +115,11 @@ 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->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 );
 }
 
 /*
@@ -187,8 +190,8 @@ static void setup_ragdoll_from_skeleton( struct skeleton *sk,
          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 );
@@ -201,8 +204,8 @@ static void setup_ragdoll_from_skeleton( struct skeleton *sk,
          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 */
@@ -240,8 +243,8 @@ static void copy_ragdoll_pose_to_localplayer( struct player_ragdoll *rd ){
       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] );
@@ -292,30 +295,30 @@ static void copy_localplayer_to_ragdoll( struct player_ragdoll *rd,
 
       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 );
    }
 }
 
@@ -337,32 +340,36 @@ static void player_ragdoll_iter( struct player_ragdoll *rd ){
    
    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;
@@ -378,23 +385,23 @@ static void player_ragdoll_iter( struct player_ragdoll *rd ){
             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;
@@ -407,7 +414,7 @@ static void player_ragdoll_iter( struct player_ragdoll *rd ){
          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 );
          }
@@ -437,8 +444,18 @@ static void player_ragdoll_iter( struct player_ragdoll *rd ){
     * 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 ){
@@ -474,19 +491,19 @@ static void player_ragdoll_iter( struct player_ragdoll *rd ){
                                          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;
index 6f5a33137a8e5a48ef53b21da64d86b1a21555d7..77118f117389dfd5ad919ff66e4da17e4f215dd7 100644 (file)
@@ -20,9 +20,17 @@ struct player_ragdoll{
       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;
index 31c4c74ead695a6cf789c060337956d07b543aed..f3b4a51c0347d69c6ae07d40a0cb0063faec7bfb 100644 (file)
@@ -305,7 +305,7 @@ static void skaterift_record_frame( replay_buffer *replay,
       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 );
@@ -376,7 +376,7 @@ void skaterift_restore_frame( replay_frame *frame ){
 
       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 );
index 6d9aa924a1cbfc00dcb51bcb2828882c94675884..0cd5e35bd510a4b28d7d98e5761e82ee70dc7ad2 100644 (file)
@@ -12,7 +12,7 @@
 
 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[] = {
@@ -61,11 +61,11 @@ static void player__skate_kill_audio(void){
  * 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++ ){
@@ -1146,7 +1146,7 @@ static void skate_integrate(void){
                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){
@@ -1209,7 +1209,7 @@ static void player__skate_pre_update(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;
@@ -1222,6 +1222,13 @@ static void player__skate_pre_update(void){
 
       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;
       }
@@ -2466,7 +2473,7 @@ begin_collision:;
       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;
@@ -2486,7 +2493,7 @@ begin_collision:;
                           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;
@@ -2504,12 +2511,10 @@ begin_collision:;
       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;
 
@@ -2517,8 +2522,8 @@ begin_collision:;
    }
 
    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] );
@@ -2528,7 +2533,7 @@ begin_collision:;
 
    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 */
@@ -2540,7 +2545,7 @@ begin_collision:;
    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 ){
@@ -2640,7 +2645,7 @@ begin_collision:;
    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 ++;
 
@@ -2710,7 +2715,9 @@ begin_collision:;
       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 );
    }
 
index 9c23978a7d463b899bdcc55cda466b778bd75a03..6b0def6c9133831e174c3dbea412bb7067cc25ab 100644 (file)
@@ -47,7 +47,7 @@ static void player_walk_generic_to_skate( enum skate_activity init, f32 yaw ){
    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 )
@@ -68,7 +68,7 @@ static void player_walk_drop_in_to_skate(void){
    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 );
@@ -457,14 +457,14 @@ static void player_walk_update_generic(void){
 
    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;
@@ -479,7 +479,7 @@ static void player_walk_update_generic(void){
     */
 
    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 );
 
@@ -582,17 +582,17 @@ static void player_walk_update_generic(void){
 
       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);
@@ -622,7 +622,7 @@ static void player_walk_update_generic(void){
    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 
@@ -631,7 +631,7 @@ static void player_walk_update_generic(void){
     */
    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 );
@@ -642,16 +642,15 @@ static void player_walk_update_generic(void){
    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);
       }
    }
 
@@ -664,11 +663,11 @@ static void player_walk_update_generic(void){
       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) ||
@@ -690,7 +689,7 @@ static void player__walk_post_update(void){
 
    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;
@@ -797,7 +796,7 @@ static void player_walk_animate_drop_in(void){
    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 );
@@ -1132,7 +1131,7 @@ static void player__walk_transition( bool grounded, f32 board_yaw ){
    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){
@@ -1145,7 +1144,7 @@ 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 ){
index 992bdba981ffcc6b9b5e875f095383c9ef351dae..75139e0f77c6ccc24cf24a83f7860621e038fcb3 100644 (file)
@@ -13,8 +13,6 @@
 
 #include <math.h>
 
-static bh_system bh_system_rigidbodies;
-
 #ifndef RIGIDBODY_H
 #define RIGIDBODY_H
 
@@ -33,7 +31,8 @@ static const float
    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,
@@ -48,6 +47,13 @@ static void rb_register_cvar(void){
    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
@@ -55,55 +61,23 @@ 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;
-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;
@@ -162,27 +136,6 @@ static void rb_debug_contact( rb_ct *ct ){
    }
 }
 
-
-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
@@ -190,37 +143,24 @@ static void rb_object_debug( rb_object *obj, u32 colour ){
  */
 
 /*
- * 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 );
 
@@ -241,98 +181,141 @@ static void rb_extrapolate( rigidbody *rb, v3f co, v4f q )
 }
 
 /*
- * 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 ){
@@ -351,8 +334,7 @@ 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 );
@@ -361,16 +343,10 @@ static void rb_iter( rigidbody *rb ){
       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
@@ -658,11 +634,11 @@ static void rb_capsule_manifold_init( capsule_manifold *manifold ){
 }
 
 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 ){
@@ -674,7 +650,7 @@ static int rb_capsule__manifold_done( m4x3f mtx, rb_capsule *c,
 
       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;
@@ -690,7 +666,7 @@ static int rb_capsule__manifold_done( m4x3f mtx, rb_capsule *c,
 
       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;
@@ -708,11 +684,12 @@ static int rb_capsule__manifold_done( m4x3f mtx, rb_capsule *c,
    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 );
@@ -747,14 +724,15 @@ static int rb_capsule_sphere( rb_object *obja, rb_object *objb, rb_ct *buf ){
 
    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 );
@@ -766,7 +744,7 @@ static int rb_capsule__capsule( m4x3f mtxA, rb_capsule *ca,
    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 );
 
@@ -783,6 +761,7 @@ static int rb_capsule__capsule( m4x3f mtxA, rb_capsule *ca,
    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;
@@ -837,7 +816,9 @@ static int rb_sphere_box( rb_object *obja, rb_object *objb, rb_ct *buf ){
 
    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;
@@ -866,16 +847,14 @@ static int rb_sphere_sphere( rb_object *obja, rb_object *objb, rb_ct *buf ){
 
    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;
@@ -906,14 +885,13 @@ static int rb_sphere__triangle( m4x3f mtxA, rb_sphere *b,
    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] );
@@ -922,7 +900,7 @@ static int rb_sphere__scene( m4x3f mtxA, rb_sphere *b,
    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];
 
@@ -937,7 +915,7 @@ static int rb_sphere__scene( m4x3f mtxA, rb_sphere *b,
       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 ){
@@ -950,8 +928,9 @@ static int rb_sphere__scene( m4x3f mtxA, rb_sphere *b,
 }
 
 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;
@@ -978,7 +957,7 @@ static int rb_box__scene( m4x3f mtxA, boxf bbx,
 
    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;
 
@@ -1106,8 +1085,8 @@ static int rb_box__scene( m4x3f mtxA, boxf bbx,
 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 );
@@ -1131,7 +1110,7 @@ static int rb_capsule__triangle( m4x3f mtxA, rb_capsule *c,
     * 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 );
@@ -1141,7 +1120,7 @@ static int rb_capsule__triangle( m4x3f mtxA, rb_capsule *c,
          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;
@@ -1169,9 +1148,9 @@ static int rb_capsule__triangle( m4x3f mtxA, rb_capsule *c,
 
    /* 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++ ){
@@ -1181,7 +1160,7 @@ static int rb_capsule__triangle( m4x3f mtxA, rb_capsule *c,
       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 );
@@ -1193,20 +1172,20 @@ static int rb_capsule__triangle( m4x3f mtxA, rb_capsule *c,
 
 /* 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;
 
@@ -1833,7 +1812,7 @@ static void rb_correct_position_constraints( rb_constr_pos *buf, int len,
 
 #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);
@@ -1865,7 +1844,8 @@ static void rb_correct_swingtwist_constraints( rb_constr_swingtwist *buf,
          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);
@@ -1895,7 +1875,8 @@ static void rb_correct_swingtwist_constraints( rb_constr_swingtwist *buf,
          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);
index b5b4cecd9c9f19937e42632682011667c23c4155..ad98cce5e3c051f73972dd59254dd6abd2e9aa6d 100644 (file)
--- a/testing.c
+++ b/testing.c
@@ -1,10 +1,13 @@
 #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){
@@ -13,20 +16,24 @@ 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 );
@@ -35,9 +42,9 @@ static void testing_update(void){
       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 );
 }
index b367a1c785f68545ca1a62799c65a92add5dbc9e..3555a971ed35c140e15a63f252d243d13e7a6620 100644 (file)
--- a/vehicle.c
+++ b/vehicle.c
@@ -9,16 +9,16 @@ static int spawn_car( int argc, const char *argv[] ){
    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" );
@@ -30,13 +30,12 @@ static int spawn_car( int argc, const char *argv[] ){
    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 );
@@ -58,11 +57,10 @@ static void vehicle_init(void)
    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
@@ -89,7 +87,7 @@ static void vehicle_wheel_force( int index )
    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 );
@@ -100,22 +98,20 @@ static void vehicle_wheel_force( int index )
       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
        * -------------------------------------------------------------*/
@@ -124,7 +120,7 @@ static void vehicle_wheel_force( int index )
       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] );
@@ -136,26 +132,26 @@ static void vehicle_wheel_force( int index )
 
       /* 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{
@@ -165,9 +161,8 @@ static void vehicle_wheel_force( int index )
    }
 }
 
-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 );
@@ -203,7 +198,7 @@ static void vehicle_update_fixed(void)
    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], 
@@ -222,13 +217,17 @@ static void vehicle_update_fixed(void)
    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 );
 
@@ -246,15 +245,14 @@ static void vehicle_update_fixed(void)
    }
 
    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;
index bdd12f02329cfe6169912ccb9fe89e3bb5a53de0..ca8943d1453d4a6a15abc0d6c3a5791eae88ecfb 100644 (file)
--- a/vehicle.h
+++ b/vehicle.h
@@ -21,7 +21,7 @@ typedef struct drivable_vehicle drivable_vehicle;
 struct drivable_vehicle
 {
    int alive, inside;
-   rb_object obj;
+   rigidbody rb;
 
    v3f wheels[4];
 
@@ -37,8 +37,7 @@ struct drivable_vehicle
 }
 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[] );
diff --git a/world.h b/world.h
index 642e7578b44a6d32ce042a36ba9be4ff2e4ca97e..7b1074354901f8abb99718e9c09a1f5f8ab8de93 100644 (file)
--- a/world.h
+++ b/world.h
@@ -217,8 +217,6 @@ struct world_instance {
           mesh_water;
    u32 cubemap_cooldown, cubemap_side;
 
-   rb_object rb_geo;
-
    /* leaderboards */
    struct leaderboard_cache *leaderboard_cache;
 
index b86c5cf0dda46157f2aec2d2302ac860289c9098..6572876b15eb80e2c45084480f2c01424df26e05 100644 (file)
@@ -266,19 +266,8 @@ static void world_gen_generate_meshes( world_instance *world ){
    /* 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
     * ----------------------------------------------------------------
index 540e0be2aa5bb85f29e0d0ddddd78c6d085f9e5b..ecbd3d22ec093a78cb68dfb128df537b2a3f3340 100644 (file)
@@ -51,12 +51,12 @@ struct world_render{
    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;
index daba459fd6b50ba2ab67f337110abfc8d75924f9..b0af9048525e40b15f6bfdb5c44af64d25fa714e 100644 (file)
@@ -666,27 +666,31 @@ static void world_routes_update( world_instance *world ){
 
    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;
@@ -705,12 +709,12 @@ static void world_routes_fixedupdate( world_instance *world ){
 
    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 );
    }
 }
 
@@ -878,26 +882,24 @@ static void world_routes_fracture( world_instance *world, ent_gate *gate,
             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];
       }
@@ -1009,7 +1011,7 @@ static void render_world_routes( world_instance *world,
 
          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 );