- for( int i=0; i<len; i++ )
- {
- struct contact *ct = &manifold[i];
-
- /*normal */
- float vn = -v3_dot( phys->rb.v, ct->n );
- vn += ct->bias;
-
- float temp = ct->norm_impulse;
- ct->norm_impulse = vg_maxf( temp + vn, 0.0f );
- vn = ct->norm_impulse - temp;
-
- v3f impulse;
- v3_muls( ct->n, vn, impulse );
-
- v3_add( impulse, phys->rb.v, phys->rb.v );
-
- /* friction */
- for( int j=0; j<2; j++ )
- {
- float f = k_friction * ct->norm_impulse,
- vt = v3_dot( phys->rb.v, ct->t[j] ),
- lambda = -vt;
-
- float temp = ct->tangent_impulse[j];
- ct->tangent_impulse[j] = vg_clampf( temp + lambda, -f, f );
- lambda = ct->tangent_impulse[j] - temp;
-
- v3_muladds( phys->rb.v, ct->t[j], lambda, phys->rb.v );
- }
- }
- }
-
- phys->in_air = len==0?1:0;
-
- if( !phys->in_air )
- {
- float const DOWNFORCE = -k_walk_downforce*VG_TIMESTEP_FIXED;
- v3_muladds( phys->rb.v, (v3f){0.0f,-1.0f,0.0f}, DOWNFORCE, phys->rb.v );
-
- if( vg_get_button("jump") )
- {
- phys->rb.v[1] = 5.0f;
- }
- }
-
- v3_zero( phys->rb.w );
- q_axis_angle( phys->rb.q, (v3f){0.0f,1.0f,0.0f}, -player.angles[0] );
-
- v3f forward_dir = { sinf(player.angles[0]),0.0f,-cosf(player.angles[0]) };
-
- v3f p1;
- v3_muladds( phys->rb.co, forward_dir, 2.0f, p1 );
- vg_line( phys->rb.co, p1, 0xff0000ff );
-
- player.walk = powf( vg_get_axis("walk/push")*0.5f + 0.5f, 4.0f );
-
- if( player.walk > 0.025f )
- {
- float
- speed = vg_lerpf( 0.025f*k_runspeed, k_runspeed, player.walk ),
- amt = k_walk_accel * VG_TIMESTEP_FIXED,
- zvel = v3_dot( phys->rb.v, forward_dir ),
- new_vel = vg_minf( zvel + amt, speed ),
- diff = new_vel - vg_minf( zvel, speed );
-
- if( !phys->in_air )
- {
- v3_muladds( phys->rb.v, forward_dir, diff, phys->rb.v );
- }
- }
-
- if( !phys->in_air )
- {
- phys->rb.v[0] *= 1.0f - (VG_TIMESTEP_FIXED * k_walk_friction);
- phys->rb.v[2] *= 1.0f - (VG_TIMESTEP_FIXED * k_walk_friction);
- }
-}
-
-/*
- * Physics collision detection, and control
- */
-static void player_physics(void)
-{
- struct player_phys *phys = &player.phys;
- /*
- * Update collision fronts
- */
-
- rigidbody *rbf = &player.collide_front,
- *rbb = &player.collide_back;
-
- m3x3_copy( phys->rb.to_world, player.collide_front.to_world );
- m3x3_copy( phys->rb.to_world, player.collide_back.to_world );
-
- player.air_blend = vg_lerpf( player.air_blend, phys->in_air, 0.1f );
- float h = player.air_blend*0.2f;
-
- m4x3_mulv( phys->rb.to_world, (v3f){0.0f,h,-k_board_length}, rbf->co );
- v3_copy( rbf->co, rbf->to_world[3] );
- m4x3_mulv( phys->rb.to_world, (v3f){0.0f,h, k_board_length}, rbb->co );
- v3_copy( rbb->co, rbb->to_world[3] );
-
- m4x3_invert_affine( rbf->to_world, rbf->to_local );
- m4x3_invert_affine( rbb->to_world, rbb->to_local );
-
- rb_update_bounds( rbf );
- rb_update_bounds( rbb );
-
- rb_debug( rbf, 0xff00ffff );
- rb_debug( rbb, 0xffffff00 );
-
- rb_ct manifold[64];
- int len = 0;
-
- len += rb_sphere_scene( rbf, &world.rb_geo, manifold+len );
- len += rb_sphere_scene( rbb, &world.rb_geo, manifold+len );
-
- rb_presolve_contacts( manifold, len );
- v3f surface_avg = {0.0f, 0.0f, 0.0f};
-
- if( !len )
- {
- player_start_air();
- }
- else
- {
- for( int i=0; i<len; i++ )
- {
- v3_add( manifold[i].n, surface_avg, surface_avg );
- }
-
- v3_normalize( surface_avg );
-
- if( v3_dot( phys->rb.v, surface_avg ) > 0.5f )
- {
- player_start_air();
- }
- else
- phys->in_air = 0;
- }
-
- for( int j=0; j<5; j++ )
- {
- for( int i=0; i<len; i++ )
- {
- struct contact *ct = &manifold[i];
-
- v3f dv, delta;
- v3_sub( ct->co, phys->rb.co, delta );
- v3_cross( phys->rb.w, delta, dv );
- v3_add( phys->rb.v, dv, dv );
-
- float vn = -v3_dot( dv, ct->n );
- vn += ct->bias;
-
- float temp = ct->norm_impulse;
- ct->norm_impulse = vg_maxf( temp + vn, 0.0f );
- vn = ct->norm_impulse - temp;
-
- v3f impulse;
- v3_muls( ct->n, vn, impulse );
-
- if( fabsf(v3_dot( impulse, phys->rb.forward )) > 10.0f ||
- fabsf(v3_dot( impulse, phys->rb.up )) > 50.0f )
- {
- player_kill();
- return;
- }
-
- v3_add( impulse, phys->rb.v, phys->rb.v );
- v3_cross( delta, impulse, impulse );
-
- /*
- * W Impulses are limited to the Y and X axises, we don't really want
- * roll angular velocities being included.
- *
- * Can also tweak the resistance of each axis here by scaling the wx,wy
- * components.
- */
-
- float wy = v3_dot( phys->rb.up, impulse ),
- wx = v3_dot( phys->rb.right, impulse )*1.5f;
-
- v3_muladds( phys->rb.w, phys->rb.up, wy, phys->rb.w );
- v3_muladds( phys->rb.w, phys->rb.right, wx, phys->rb.w );
- }
- }
-
- float grabt = vg_get_axis( "grab" )*0.5f+0.5f;
- phys->grab = vg_lerpf( phys->grab, grabt, 0.14f );
- player.phys.pushing = 0.0f;
-
- if( !phys->in_air )
- {
- v3f axis;
- float angle = v3_dot( phys->rb.up, surface_avg );
- v3_cross( phys->rb.up, surface_avg, axis );
-
- //float cz = v3_dot( player.rb.forward, axis );
- //v3_muls( player.rb.forward, cz, axis );
-
- if( angle < 0.999f )
- {
- v4f correction;
- q_axis_angle( correction, axis, acosf(angle)*18.0f*VG_TIMESTEP_FIXED );
- q_mul( correction, phys->rb.q, phys->rb.q );
- }
-
- float const DOWNFORCE = -k_downforce*VG_TIMESTEP_FIXED;
- v3_muladds( phys->rb.v, phys->rb.up, DOWNFORCE, phys->rb.v );
-
- player_physics_control();
-
- if( !phys->jump_charge && phys->jump > 0.2f )
- {
- v3f jumpdir;
-
- /* Launch more up if alignment is up else improve velocity */
- float aup = fabsf(v3_dot( (v3f){0.0f,1.0f,0.0f}, phys->rb.up )),
- mod = 0.5f,
- dir = mod + aup*(1.0f-mod);
-
- v3_copy( phys->rb.v, jumpdir );
- v3_normalize( jumpdir );
- v3_muls( jumpdir, 1.0f-dir, jumpdir );
- v3_muladds( jumpdir, phys->rb.up, dir, jumpdir );
- v3_normalize( jumpdir );
-
- float force = k_jump_force*phys->jump;
- v3_muladds( phys->rb.v, jumpdir, force, phys->rb.v );
- phys->jump = 0.0f;
-
- player.jump_time = vg.time;
-
- /* TODO: Move to audio file */
- audio_lock();
- audio_player_set_flags( &audio_player_extra, AUDIO_FLAG_SPACIAL_3D );
- audio_player_set_position( &audio_player_extra, phys->rb.co );
- audio_player_set_vol( &audio_player_extra, 20.0f );
- audio_player_playclip( &audio_player_extra, &audio_jumps[rand()%4] );
- audio_unlock();
- }