}
VG_STATIC void player_integrate(void);
+
+VG_STATIC int player_walk_surface_standable( v3f n )
+{
+ return v3_dot( n, (v3f){0.0f,1.0f,0.0f} ) > 0.5f;
+}
+
+VG_STATIC void player_walk_stepdown(void)
+{
+ struct player_phys *phys = &player.phys;
+ float max_dist = 0.4f;
+
+ v3f pa, pb;
+ v3_copy( phys->rb.co, pa );
+ pa[1] += 0.3f;
+
+ v3_muladds( pa, (v3f){0.01f,1.0f,0.01f}, -max_dist, pb );
+ vg_line( pa, pb, 0xff000000 );
+
+ /* TODO: Make #define */
+ float r = 0.3f,
+ t;
+
+ v3f n;
+ if( spherecast_world( pa, pb, r, &t, n ) != -1 )
+ {
+ if( player_walk_surface_standable( n ) )
+ {
+ phys->in_air = 0;
+ v3_lerp( pa, pb, t+0.001f, phys->rb.co );
+ phys->rb.co[1] -= 0.3f;
+ }
+ }
+}
+
/*
* Entire Walking physics model
* TODO: sleep when under certain velotiy
phys->in_air = 1;
return;
}
+
+ /* Check if grounded by current manifold */
+ phys->in_air = 1;
+ for( int i=0; i<len; i++ )
+ {
+ struct contact *ct = &manifold[i];
+ if( player_walk_surface_standable( ct->n ) )
+ phys->in_air = 0;
+ }
+
+ /* otherwise... */
+ if( phys->in_air )
+ player_walk_stepdown();
+#if 0
/* if we've put us in the air, step down slowly */
phys->in_air = 1;
float max_dist = 0.3f,
start_y = phys->rb.co[1];
+ v3f pa, pb;
+ v3_copy( phys->rb.co, pa );
+ v3_muladds( pa, (v3f){0.0f,1.0f,0.0f}, -max_dist, pb );
+
+
for( int j=0; j<8; j++ )
{
for( int i=0; i<len; i++ )
/* Transitioning into air mode */
phys->rb.co[1] = start_y;
+#endif
}
}
v3f p0, p1, c0, c1;
v3_muladds( phys->rb.co, phys->rb.forward, 0.5f, p0 );
v3_muladds( phys->rb.co, phys->rb.forward, -0.5f, p1 );
- v3_muladds( p0, phys->rb.up, 0.125f, p0 );
- v3_muladds( p1, phys->rb.up, 0.125f, p1 );
+ v3_muladds( p0, phys->rb.up, 0.125f-0.15f, p0 );
+ v3_muladds( p1, phys->rb.up, 0.125f-0.15f, p1 );
float const k_r = 0.25f;
struct grind_edge *closest_edge = player_grind_collect_edge( p0, p1,
return k;
}
+/*
+ * Merge two contacts if they are within radius(r) of eachother
+ */
+VG_STATIC void rb_manifold_contact_weld( rb_ct *ci, rb_ct *cj, float r )
+{
+ if( v3_dist2( ci->co, cj->co ) < r*r )
+ {
+ cj->type = k_contact_type_disabled;
+ ci->p = (ci->p + cj->p) * 0.5f;
+
+ v3_add( ci->co, cj->co, ci->co );
+ v3_muls( ci->co, 0.5f, ci->co );
+
+ v3f delta;
+ v3_sub( ci->rba->co, ci->co, delta );
+
+ float c0 = v3_dot( ci->n, delta ),
+ c1 = v3_dot( cj->n, delta );
+
+ if( c0 < 0.0f || c1 < 0.0f )
+ {
+ /* error */
+ ci->type = k_contact_type_disabled;
+ }
+ else
+ {
+ v3f n;
+ v3_muls( ci->n, c0, n );
+ v3_muladds( n, cj->n, c1, n );
+ v3_normalize( n );
+ v3_copy( n, ci->n );
+ }
+ }
+}
+
+/*
+ *
+ */
VG_STATIC void rb_manifold_filter_joint_edges( rb_ct *man, int len, float r )
{
for( int i=0; i<len-1; i++ )
rb_ct *cj = &man[j];
if( cj->type != k_contact_type_edge )
continue;
-
- if( v3_dist2( ci->co, cj->co ) < r*r )
- {
- cj->type = k_contact_type_disabled;
- ci->p = (ci->p + cj->p) * 0.5f;
-
- v3_add( ci->co, cj->co, ci->co );
- v3_muls( ci->co, 0.5f, ci->co );
-
- v3f delta;
- v3_sub( ci->rba->co, ci->co, delta );
-
- float c0 = v3_dot( ci->n, delta ),
- c1 = v3_dot( cj->n, delta );
-
- if( c0 < 0.0f || c1 < 0.0f )
- {
- /* error */
- ci->type = k_contact_type_disabled;
- }
- else
- {
- v3f n;
- v3_muls( ci->n, c0, n );
- v3_muladds( n, cj->n, c1, n );
- v3_normalize( n );
- v3_copy( n, ci->n );
- }
- }
+
+ rb_manifold_contact_weld( ci, cj, r );
}
}
}
/*
* Resolve overlapping pairs
+ *
+ * TODO: Remove?
*/
VG_STATIC void rb_manifold_filter_pairs( rb_ct *man, int len, float r )
{
v3_sub( tri[1], tri[0], ac );
v3_cross( ac, ab, tn );
v3_copy( tn, ct->n );
+
+ if( v3_length2( ct->n ) <= 0.00001f )
+ {
+ vg_error( "Zero area triangle!\n" );
+ return 0;
+ }
+
v3_normalize( ct->n );
float d = sqrtf(d2);
/* 'systems' are completely loaded now */
strcpy( world.world_name, "maps/mp_mtzero.mdl" );
+#if 0
strcpy( world.world_name, "maps/mp_gridmap.mdl" );
+#endif
world_load();
vg_console_load_autos();
}