+VG_STATIC void player_do_motion(void)
+{
+ if( world.water.enabled )
+ {
+ if( (player.rb.co[1] < 0.0f) && !player.is_dead )
+ {
+ audio_lock();
+ audio_player_set_flags( &audio_player_extra, AUDIO_FLAG_SPACIAL_3D );
+ audio_player_set_position( &audio_player_extra, player.rb.co );
+ audio_player_set_vol( &audio_player_extra, 20.0f );
+ audio_player_playclip( &audio_player_extra, &audio_splash );
+ audio_unlock();
+
+ player_kill();
+ }
+ }
+
+ v3f prevco;
+ v3_copy( player.rb.co, prevco );
+
+ if( player.controller == k_player_controller_skate )
+ {
+#if 0
+ player_skate_update();
+#endif
+ }
+ else
+ player_walk_physics( &player_walky );
+
+
+ /* Real angular velocity integration */
+#if 0
+ v3_lerp( phys->rb.w, (v3f){0.0f,0.0f,0.0f}, 0.125f*0.5f, phys->rb.w );
+ if( v3_length2( phys->rb.w ) > 0.0f )
+ {
+ v4f rotation;
+ v3f axis;
+ v3_copy( phys->rb.w, axis );
+
+ float mag = v3_length( axis );
+ v3_divs( axis, mag, axis );
+ q_axis_angle( rotation, axis, mag*k_rb_delta );
+ q_mul( rotation, phys->rb.q, phys->rb.q );
+ }
+
+ /* Faux angular velocity */
+ v4f rotate;
+
+ float lerpq = (player_skate.activity == k_skate_activity_air)? 0.04f: 0.3f;
+ phys->siY = vg_lerpf( phys->siY, phys->iY, lerpq );
+
+ q_axis_angle( rotate, phys->rb.up, phys->siY );
+ q_mul( rotate, phys->rb.q, phys->rb.q );
+ phys->iY = 0.0f;
+#endif
+
+ /*
+ * Gate intersection, by tracing a line over the gate planes
+ */
+#if 0
+ for( int i=0; i<world.gate_count; i++ )
+ {
+ struct route_gate *rg = &world.gates[i];
+ teleport_gate *gate = &rg->gate;
+
+ if( gate_intersect( gate, phys->rb.co, prevco ) )
+ {
+ m4x3_mulv( gate->transport, phys->rb.co, phys->rb.co );
+ m4x3_mulv( gate->transport, phys->cog, phys->cog );
+ m3x3_mulv( gate->transport, phys->cog_v, phys->cog_v );
+ m3x3_mulv( gate->transport, phys->rb.v, phys->rb.v );
+ m3x3_mulv( gate->transport, phys->vl, phys->vl );
+ m3x3_mulv( gate->transport, phys->v_last, phys->v_last );
+ m3x3_mulv( gate->transport, phys->m, phys->m );
+ m3x3_mulv( gate->transport, phys->bob, phys->bob );
+
+ /* Pre-emptively edit the camera matrices so that the motion vectors
+ * are correct */
+ m4x3f transport_i;
+ m4x4f transport_4;
+ m4x3_invert_affine( gate->transport, transport_i );
+ m4x3_expand( transport_i, transport_4 );
+ m4x4_mul( main_camera.mtx.pv, transport_4, main_camera.mtx.pv );
+ m4x4_mul( main_camera.mtx.v, transport_4, main_camera.mtx.v );
+
+ v4f transport_rotation;
+ m3x3_q( gate->transport, transport_rotation );
+ q_mul( transport_rotation, phys->rb.q, phys->rb.q );
+
+ world_routes_activate_gate( i );
+
+ if( phys->controller == k_player_controller_walk )
+ {
+ v3f fwd_dir = {cosf(player.angles[0]),
+ 0.0f,
+ sinf(player.angles[0])};
+ m3x3_mulv( gate->transport, fwd_dir, fwd_dir );
+
+ player.angles[0] = atan2f( fwd_dir[2], fwd_dir[0] );
+ }
+
+ player.rewind_length = 0;
+ player.rewind_total_length = 0.0f;
+ player.rewind_incrementer = 10000;
+ player_save_frame();
+
+ audio_lock();
+ audio_play_oneshot( &audio_gate_pass, 1.0f );
+ audio_unlock();
+ break;
+ }
+ }
+#endif
+
+ rb_update_transform( &player.rb );
+}
+