+
+ v3_add( ct->n, surface_normal, surface_normal );
+ }
+
+ if( manifold_len )
+ {
+ v3_muls( surface_normal, 1.0f/(float)manifold_len, surface_normal );
+
+ float a = v3_dot( player->rb.to_world[1], surface_normal );
+
+ if( a <= 0.9999f )
+ {
+ v3f axis;
+ v3_cross( surface_normal, player->rb.to_world[1], axis );
+
+ float Fs = -a * k_board_spring,
+ Fd = -v3_dot( player->rb.w, axis ) * k_board_dampener;
+
+ v3_muladds( player->rb.w, axis, (Fs+Fd) * s->substep_delta,
+ player->rb.w );
+ }
+ }
+
+ v3f extent = { w, 0.1f, k_board_length };
+ float ex2 = k_board_interia*extent[0]*extent[0],
+ ey2 = k_board_interia*extent[1]*extent[1],
+ ez2 = k_board_interia*extent[2]*extent[2];
+
+ float mass = 2.0f * (extent[0]*extent[1]*extent[2]);
+ float inv_mass = 1.0f/mass;
+
+ v3f I;
+ I[0] = ((1.0f/12.0f) * mass * (ey2+ez2));
+ I[1] = ((1.0f/12.0f) * mass * (ex2+ez2));
+ I[2] = ((1.0f/12.0f) * mass * (ex2+ey2));
+
+ m3x3f iI;
+ m3x3_identity( iI );
+ iI[0][0] = I[0];
+ iI[1][1] = I[1];
+ iI[2][2] = I[2];
+ m3x3_inv( iI, iI );
+
+ m3x3f iIw;
+ m3x3_mul( iI, player->rb.to_local, iIw );
+ m3x3_mul( player->rb.to_world, iIw, iIw );
+
+ for( int j=0; j<10; j++ )
+ {
+ for( int i=0; i<manifold_len; i++ )
+ {
+ struct contact *ct = &manifold[i];
+
+ v3f rv, delta;
+ v3_sub( ct->co, player->rb.co, delta );
+ v3_cross( player->rb.w, delta, rv );
+ v3_add( player->rb.v, rv, rv );
+
+ v3f raCn;
+ v3_cross( delta, ct->n, raCn );
+
+ v3f raCnI, rbCnI;
+ m3x3_mulv( iIw, raCn, raCnI );
+
+ float normal_mass = 1.0f / (inv_mass + v3_dot(raCn,raCnI));
+ float vn = v3_dot( rv, ct->n );
+
+
+
+
+ float lambda = normal_mass * ( -vn + ct->bias );
+
+ float temp = ct->norm_impulse;
+ ct->norm_impulse = vg_maxf( temp + lambda, 0.0f );
+ lambda = ct->norm_impulse - temp;
+
+ v3f impulse;
+ v3_muls( ct->n, lambda, impulse );
+
+#if 0
+ if( fabsf(v3_dot( impulse, player->rb.to_world[2] )) > 10.0f ||
+ fabsf(v3_dot( impulse, player->rb.to_world[1] )) > 50.0f )
+ {
+ player__dead_transition( player );
+ return;
+ }