+static void player_start_air(void)
+{
+ player.in_air = 1;
+
+ float pstep = ktimestep*10.0f;
+
+ float best_velocity_mod = 0.0f,
+ best_velocity_delta = -9999.9f;
+
+ v3f targetn;
+
+ v3f axis, vup;
+ m3x3_mulv( player.to_world, (v3f){0.0f,1.0f,0.0f}, vup );
+ v3_cross( vup, player.v, axis );
+ v3_normalize( axis );
+ player.land_log_count = 0;
+
+ m3x3_identity( player.vr );
+
+ for( int m=0;m<=5; m++ )
+ {
+ float vmod = ((float)m / 5.0f)*0.15f;
+
+ v3f pco, pco1, pv;
+ v3_copy( player.co, pco );
+ v3_copy( player.v, pv );
+
+ /*
+ * Try different 'rotations' of the velocity to find the best possible
+ * landing normal. This conserves magnitude at the expense of slightly
+ * unrealistic results
+ */
+
+ m3x3f vr;
+ v4f vr_q;
+
+ q_axis_angle( vr_q, axis, vmod );
+ q_m3x3( vr_q, vr );
+
+ for( int i=0; i<50; i++ )
+ {
+ v3_copy( pco, pco1 );
+ apply_gravity( pv, pstep );
+
+ m3x3_mulv( vr, pv, pv );
+ v3_muladds( pco, pv, pstep, pco );
+
+ vg_line( pco, pco1, i&0x1?0xff000000:0xffffffff );
+
+ v3f sh;
+ v3_copy( pco, sh );
+ int hit = sample_scene_height( &world.geo, sh, targetn );
+
+ if( sh[1] >= pco[1] && hit )
+ {
+ float land_delta = v3_dot( pv, targetn );
+
+ if( (land_delta < 0.0f) && (land_delta > best_velocity_delta) )
+ {
+ best_velocity_delta = land_delta;
+ best_velocity_mod = vmod;
+
+ v3_copy( sh, player.land_target );
+
+ q_axis_angle( vr_q, axis, vmod*0.1f );
+ q_m3x3( vr_q, player.vr );
+ }
+ v3_copy( sh, player.land_target_log[player.land_log_count ++] );
+ break;
+ }
+ }
+ }
+
+ //v3_rotate( player.v, best_velocity_mod, axis, player.v );
+
+ return;
+ v3_muls( player.v, best_velocity_mod, player.v );
+}
+
+static int sample_if_resistant( v3f pos )
+{
+ v3f ground, norm;
+ v3_copy( pos, ground );
+
+ if( sample_scene_height( &world.geo, ground, norm ) )
+ {
+ v3f angle;
+ v3_copy( player.v, angle );
+ v3_normalize( angle );
+ float resistance = v3_dot( norm, angle );
+
+ if( resistance < 0.25f )
+ {
+ v3_copy( ground, pos );
+ return 1;
+ }
+ }
+
+ return 0;
+}
+