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 );
+ rb_init_object( &rp->obj, 4.0f );
}
/*
* SOLVE CONSTRAINTS & Integrate
*/
if( run_sim ){
- for( int i=0; i<12; i++ ){
- rb_solve_contacts( rb_contact_buffer, rb_contact_count );
- rb_solve_swingtwist_constraints( rd->cone_constraints,
- rd->cone_constraints_count );
+ /* the solver is not very quickly converging so... */
+ for( int i=0; i<40; i++ ){
+ if( i<20 ){
+ rb_solve_contacts( rb_contact_buffer, rb_contact_count );
+ rb_solve_swingtwist_constraints( rd->cone_constraints,
+ rd->cone_constraints_count );
+ rb_postsolve_swingtwist_constraints( rd->cone_constraints,
+ rd->cone_constraints_count );
+ }
rb_solve_position_constraints( rd->position_constraints,
rd->position_constraints_count );
}
+ rb_correct_position_constraints( rd->position_constraints,
+ rd->position_constraints_count,
+ k_ragdoll_correction * 0.5f );
+ rb_correct_swingtwist_constraints( rd->cone_constraints,
+ rd->cone_constraints_count,
+ k_ragdoll_correction * 0.25f );
+
for( int i=0; i<rd->part_count; i++ ){
rb_iter( &rd->parts[i].obj.rb );
for( int i=0; i<rd->part_count; i++ )
rb_update_transform( &rd->parts[i].obj.rb );
-
- for( int i=0; i<5; i ++ ){
- rb_correct_swingtwist_constraints( rd->cone_constraints,
- rd->cone_constraints_count,
- k_ragdoll_correction * 0.25f );
-
- rb_correct_position_constraints( rd->position_constraints,
- rd->position_constraints_count,
- k_ragdoll_correction * 0.5f );
- }
}
rb_ct *stress = NULL;
k_damp_linear = 0.1f, /* scale velocity 1/(1+x) */
k_damp_angular = 0.1f, /* scale angular 1/(1+x) */
k_penetration_slop = 0.01f,
- k_inertia_scale = 8.0f,
+ k_inertia_scale = 4.0f,
k_phys_baumgarte = 0.2f,
k_gravity = 9.6f;
float inv_mass;
/* inertia model and inverse world tensor */
- v3f I;
m3x3f iI, iIw;
m4x3f to_world, to_local;
};
float conet;
float tangent_mass, axis_mass;
+
+ f32 conv_tangent, conv_axis;
};
/*
v3_copy( rb->co, rb->to_world[3] );
m4x3_invert_affine( rb->to_world, rb->to_local );
- m3x3_mul( rb->iI, rb->to_local, rb->iIw );
- m3x3_mul( rb->to_world, rb->iIw, rb->iIw );
+
+ /* 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 );
}
/*
* Initialize rigidbody and calculate masses, inertia
*/
-static void rb_init_object( rb_object *obj ){
+static void rb_init_object( rb_object *obj, f32 inertia_scale ){
float volume = 1.0f;
int inert = 0;
if( inert ){
obj->rb.inv_mass = 0.0f;
- v3_zero( obj->rb.I );
m3x3_zero( obj->rb.iI );
}
else{
- float mass = 2.0f*volume;
+ f32 mass = 8.0f*volume;
obj->rb.inv_mass = 1.0f/mass;
- v3f extent;
+ v3f extent, com;
v3_sub( obj->rb.bbx[1], obj->rb.bbx[0], extent );
- v3_muls( extent, 0.5f, extent );
+ v3_muladds( obj->rb.bbx[0], extent, 0.5f, com );
/* local intertia tensor */
- float scale = k_inertia_scale;
- float ex2 = scale*extent[0]*extent[0],
- ey2 = scale*extent[1]*extent[1],
- ez2 = scale*extent[2]*extent[2];
-
- obj->rb.I[0] = ((1.0f/12.0f) * mass * (ey2+ez2));
- obj->rb.I[1] = ((1.0f/12.0f) * mass * (ex2+ez2));
- obj->rb.I[2] = ((1.0f/12.0f) * mass * (ex2+ey2));
-
- m3x3_identity( obj->rb.iI );
- obj->rb.iI[0][0] = obj->rb.I[0];
- obj->rb.iI[1][1] = obj->rb.I[1];
- obj->rb.iI[2][2] = obj->rb.I[2];
- m3x3_inv( obj->rb.iI, obj->rb.iI );
+ f32 ex2 = extent[0]*extent[0],
+ ey2 = extent[1]*extent[1],
+ ez2 = extent[2]*extent[2];
+
+ /* compute inertia tensor */
+ v3f I;
+
+ 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( "" );
+ }
+
+ m3x3f i;
+ m3x3_identity( i );
+ m3x3_setdiagonalv3( i, I );
+
+ /* 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 );
+
+ /* TODO: compute rotation */
+
+ /* add Ic and Ict */
+ m3x3_add( i, i_t, i );
+
+ /* store as inverted */
+ m3x3_inv( i, obj->rb.iI );
}
rb_update_transform( &obj->rb );
}
static void rb_prepare_contact( rb_ct *ct, float timestep ){
- ct->bias = -0.2f * (timestep*3600.0f)
+ ct->bias = -k_phys_baumgarte * (timestep*3600.0f)
* vg_minf( 0.0f, -ct->p+k_penetration_slop );
v3_tangent_basis( ct->n, ct->t[0], ct->t[1] );
static void rb_presolve_swingtwist_constraints( rb_constr_swingtwist *buf,
int len ){
- float size = 0.12f;
-
for( int i=0; i<len; i++ ){
rb_constr_swingtwist *st = &buf[ i ];
static void rb_solve_swingtwist_constraints( rb_constr_swingtwist *buf,
int len ){
- float size = 0.12f;
-
for( int i=0; i<len; i++ ){
rb_constr_swingtwist *st = &buf[ i ];
}
}
+/* debugging */
+static void rb_postsolve_swingtwist_constraints( rb_constr_swingtwist *buf,
+ u32 len ){
+ for( int i=0; i<len; i++ ){
+ rb_constr_swingtwist *st = &buf[ i ];
+
+ if( !st->axis_violation ){
+ st->conv_axis = 0.0f;
+ continue;
+ }
+
+ f32 rv = v3_dot( st->axis, st->rbb->w ) -
+ v3_dot( st->axis, st->rba->w );
+
+ if( rv * (f32)st->axis_violation > 0.0f )
+ st->conv_axis = 0.0f;
+ else
+ st->conv_axis = rv;
+ }
+
+ for( int i=0; i<len; i++ ){
+ rb_constr_swingtwist *st = &buf[ i ];
+
+ if( !st->tangent_violation ){
+ st->conv_tangent = 0.0f;
+ continue;
+ }
+
+ f32 rv = v3_dot( st->tangent_axis, st->rbb->w ) -
+ v3_dot( st->tangent_axis, st->rba->w );
+
+ if( rv > 0.0f )
+ st->conv_tangent = 0.0f;
+ else
+ st->conv_tangent = rv;
+ }
+}
+
static void rb_solve_constr_angle( rigidbody *rba, rigidbody *rbb,
v3f ra, v3f rb ){
m3x3f ssra, ssrb, ssrat, ssrbt;
v3_add( rbb->co, p1, p1 );
v3_sub( p1, p0, d );
+#if 1
v3_muladds( rbb->co, d, -1.0f * amt, rbb->co );
rb_update_transform( rbb );
+#else
+ f32 mt = 1.0f/(rba->inv_mass+rbb->inv_mass),
+ a = mt * (k_phys_baumgarte/k_rb_delta);
+
+ v3_muladds( rba->v, d, a* rba->inv_mass, rba->v );
+ v3_muladds( rbb->v, d, a*-rbb->inv_mass, rbb->v );
+#endif
}
}
v3f va;
m3x3_mulv( st->rbb->to_world, st->coneva, va );
- float angle = v3_dot( va, st->tangent_target );
+ f32 angle = v3_dot( va, st->tangent_target );
if( fabsf(angle) < 0.9999f ){
v3f axis;
v3_cross( va, st->tangent_target, axis );
-
+#if 1
+ angle = acosf(angle) * amt;
v4f correction;
- q_axis_angle( correction, axis, acosf(angle) * amt );
+ q_axis_angle( correction, axis, angle );
q_mul( correction, st->rbb->q, st->rbb->q );
rb_update_transform( 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);
+ //v3_muladds( st->rba->w, axis, wa*-st->rba->inv_mass, st->rba->w );
+ v3_muladds( st->rbb->w, axis, wa* st->rbb->inv_mass, st->rbb->w );
+#endif
}
}
v3f vxb;
m3x3_mulv( st->rbb->to_world, st->conevxb, vxb );
- float angle = v3_dot( vxb, st->axis_target );
+ f32 angle = v3_dot( vxb, st->axis_target );
if( fabsf(angle) < 0.9999f ){
v3f axis;
v3_cross( vxb, st->axis_target, axis );
+#if 1
+ angle = acosf(angle) * amt;
v4f correction;
- q_axis_angle( correction, axis, acosf(angle) * amt );
+ q_axis_angle( correction, axis, angle );
q_mul( correction, st->rbb->q, st->rbb->q );
rb_update_transform( 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);
+ //v3_muladds( st->rba->w, axis, wa*-0.5f, st->rba->w );
+ v3_muladds( st->rbb->w, axis, wa* st->rbb->inv_mass, st->rbb->w );
+#endif
}
}
}