{
d += contact.dist;
+#if 0
vg_line( origin, contact.pos, 0xff0000ff );
vg_line_pt3( contact.pos, 0.1f, 0xff0000ff );
if( lv )
vg_line( contact.pos, last, 0xffffffff );
+#endif
+
v3_copy( contact.pos, last );
lv = 1;
}
{
v3f p1;
v3_muladds( origin, dir, sample_dist, p1 );
+
+#if 0
vg_line( origin, p1, 0xffcccccc );
+#endif
d += sample_dist;
lv = 0;
}
else
{
+#if 0
vg_line( pos, contact.pos, 0xff0000ff );
vg_line_pt3( contact.pos, 0.3f, 0xff0000ff );
+#endif
return k_audio_sprite_type_none;
}
}
reverse;
float grab, jump, pushing, push_time;
+ v2f grab_mouse_delta;
+
double start_push;
int in_air, on_board, jump_charge, jump_dir;
*input_js1v,
*input_js2h,
*input_js2v,
- *input_emjs2h,
- *input_emjs2v,
*input_jump,
*input_push,
*input_walkh,
player.input_grab = vg_create_named_input( "grab", k_input_type_axis_norm );
player.input_js2h = vg_create_named_input( "grab-h", k_input_type_axis );
player.input_js2v = vg_create_named_input( "grab-v", k_input_type_axis );
- player.input_emjs2h = vg_create_named_input( "kbgrab-h", k_input_type_axis );
- player.input_emjs2v = vg_create_named_input( "kbgrab-v", k_input_type_axis );
player.input_jump = vg_create_named_input( "jump", k_input_type_button );
player.input_push = vg_create_named_input( "push", k_input_type_axis_norm );
"bind -steer-v w",
"bind +steer-v s",
- "bind grab gp-rt",
- "bind grab-h gp-rs-h",
- "bind grab-v gp-rs-v",
-
- "bind -kbgrab-h left",
- "bind +kbgrab-h right",
- "bind -kbgrab-v down",
- "bind +kbgrab-v up",
+ "bind grab gp-rt",
+ "bind +grab shift",
+ "bind grab-h gp-rs-h",
+ "bind grab-v gp-rs-v",
"bind jump space",
"bind jump gp-a",
"bind push gp-lt",
- "bind +push shift",
+ "bind +push w",
- "bind walk-h gp-ls-h",
- "bind walk-v gp-ls-v",
+ "bind walk-h gp-ls-h",
+ "bind walk-v -gp-ls-v",
"bind +walk-h d",
"bind -walk-h a",
"bind +walk-v w",
skeleton_sample_anim( sk, player.mdl.anim_air, air_frame, apose );
static v2f grab_choice;
- v2_lerp( grab_choice, (v2f){vg_get_axis("grabh"), vg_get_axis("grabv")},
- 0.04f, grab_choice );
+
+ v2f grab_input = { player.input_js2h->axis.value,
+ player.input_js2v->axis.value };
+ v2_add( player.phys.grab_mouse_delta, grab_input, grab_input );
+ if( v2_length2( grab_input ) <= 0.001f )
+ grab_input[0] = -1.0f;
+ else
+ v2_normalize_clamp( grab_input );
+ v2_lerp( grab_choice, grab_input, 2.4f*vg.time_delta, grab_choice );
float ang = atan2f( grab_choice[0], grab_choice[1] ),
ang_unit = (ang+VG_PIf) * (1.0f/VG_TAUf),
vel[1] += pump;
-
m3x3_mulv( phys->rb.to_world, vel, phys->rb.v );
- float steer = player.input_js1h->axis.value,
+ float input = player.input_js1h->axis.value,
+ grab = player.input_grab->axis.value,
+ steer = input * (1.0f-(phys->jump+grab)*0.4f),
steer_scaled = vg_signf(steer) * powf(steer,2.0f) * k_steer_ground;
phys->iY -= steer_scaled * VG_TIMESTEP_FIXED;
time_to_impact += pstep;
}
- float steerh = player.input_js1h->axis.value,
- steerv = player.input_js1v->axis.value;
+ v2f steer = { player.input_js1h->axis.value,
+ player.input_js1v->axis.value };
- phys->iY -= steerh * k_steer_air * VG_TIMESTEP_FIXED;
+ float l2 = v2_length2( steer );
+ if( l2 > 1.0f )
+ v2_muls( steer, 1.0f/sqrtf(l2), steer );
- {
- float iX = steerv *
- phys->reverse * k_steer_air * limiter * VG_TIMESTEP_FIXED;
+ phys->iY -= steer[0] * k_steer_air * VG_TIMESTEP_FIXED;
- static float siX = 0.0f;
- siX = vg_lerpf( siX, iX, k_steer_air_lerp );
-
- v4f rotate;
- q_axis_angle( rotate, phys->rb.right, siX );
- q_mul( rotate, phys->rb.q, phys->rb.q );
- }
+ float iX = steer[1] *
+ phys->reverse * k_steer_air * limiter * VG_TIMESTEP_FIXED;
+
+ static float siX = 0.0f;
+ siX = vg_lerpf( siX, iX, k_steer_air_lerp );
+
+ v4f rotate;
+ q_axis_angle( rotate, phys->rb.right, siX );
+ q_mul( rotate, phys->rb.q, phys->rb.q );
#if 0
v2f target = {0.0f,0.0f};
}
}
- float grabt = vg_maxf( player.input_grab->axis.value,
- vg_maxf( fabsf( player.input_emjs2h->axis.value ),
- fabsf( player.input_emjs2v->axis.value ) )
- );
+ float grabt = player.input_grab->axis.value;
+
+ if( grabt > 0.5f )
+ {
+ v2_muladds( phys->grab_mouse_delta, vg.mouse_delta, 0.02f,
+ phys->grab_mouse_delta );
+ v2_normalize_clamp( phys->grab_mouse_delta );
+ }
+ else
+ v2_zero( phys->grab_mouse_delta );
phys->grab = vg_lerpf( phys->grab, grabt, 0.14f );
player.phys.pushing = 0.0f;
if( !phys->in_air )
{
-#if 0
- 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 );
- }
-#else
-
/* 20/10/22: make this only go axisways instead, may effect velocities. */
v3f projected, axis;
q_mul( correction, phys->rb.q, phys->rb.q );
}
-
-#endif
-
float const DOWNFORCE = -k_downforce*VG_TIMESTEP_FIXED;
v3_muladds( phys->rb.v, phys->rb.up, DOWNFORCE, phys->rb.v );
normal_mass, tangent_mass[2];
u32 element_id;
+ int cluster;
}
rb_contact_buffer[256];
VG_STATIC int rb_contact_count = 0;
return 0;
}
+#define RIGIDBODY_DYNAMIC_MESH_EDGES
+
VG_STATIC int rb_sphere_triangle( rigidbody *rba, rigidbody *rbb,
v3f tri[3], rb_ct *buf )
{
v3f delta, co;
+#ifdef RIGIDBODY_DYNAMIC_MESH_EDGES
+ closest_on_triangle( rba->co, tri, co );
+#else
closest_on_triangle_1( rba->co, tri, co );
+#endif
+
v3_sub( rba->co, co, delta );
vg_line( rba->co, co, 0xffff0000 );
scene *sc = rbb->inf.scene.bh_scene->user;
u32 geo[128];
- v3f tri[3];
- int len = bh_select( rbb->inf.scene.bh_scene, rba->bbx_world, geo, 128 );
+ int len = bh_select( rbb->inf.scene.bh_scene, rba->bbx_world, geo, 128 );
int count = 0;
+#ifdef RIGIDBODY_DYNAMIC_MESH_EDGES
+ /* !experimental! build edge array on the fly. time could be improved! */
+
+ v3f co_picture[128*3];
+ int unique_cos = 0;
+
+ struct face_info
+ {
+ int unique_cos[3]; /* indexes co_picture array */
+ int collided;
+ v3f normal;
+ u32 element_id;
+ }
+ faces[128];
+
+ /* create geometry picture */
+ for( int i=0; i<len; i++ )
+ {
+ u32 *tri_indices = &sc->arrindices[ geo[i]*3 ];
+ struct face_info *inf = &faces[i];
+ inf->element_id = tri_indices[0];
+ inf->collided = 0;
+
+ for( int j=0; j<3; j++ )
+ {
+ struct mdl_vert *pvert = &sc->arrvertices[tri_indices[j]];
+
+ for( int k=0; k<unique_cos; k++ )
+ {
+ if( v3_dist( pvert->co, co_picture[k] ) < 0.01f*0.01f )
+ {
+ inf->unique_cos[j] = k;
+ goto next_vert;
+ }
+ }
+
+ inf->unique_cos[j] = unique_cos;
+ v3_copy( pvert->co, co_picture[ unique_cos ++ ] );
+next_vert:;
+ }
+
+ v3f ab, ac;
+ v3_sub( co_picture[inf->unique_cos[2]],
+ co_picture[inf->unique_cos[0]], ab );
+
+ v3_sub( co_picture[inf->unique_cos[1]],
+ co_picture[inf->unique_cos[0]], ac );
+ v3_cross( ac, ab, inf->normal );
+ v3_normalize( inf->normal );
+ }
+
+
+ /* build edges brute force */
+ int edge_picture[ 128*3 ][4];
+ int unique_edges = 0;
+
+ for( int i=0; i<len; i++ )
+ {
+ struct face_info *inf = &faces[i];
+
+ for( int j=0; j<3; j++ )
+ {
+ int i0 = j,
+ i1 = (j+1)%3,
+ e0 = VG_MIN( inf->unique_cos[i0], inf->unique_cos[i1] ),
+ e1 = VG_MAX( inf->unique_cos[i0], inf->unique_cos[i1] ),
+ matched = 0;
+
+ for( int k=0; k<unique_edges; k ++ )
+ {
+ int k0 = VG_MIN( edge_picture[k][0], edge_picture[k][1] ),
+ k1 = VG_MAX( edge_picture[k][0], edge_picture[k][1] );
+
+ /* matched ! */
+ if( (k0 == e0) && (k1 == e1) )
+ {
+ edge_picture[ k ][3] = i;
+ matched = 1;
+ break;
+ }
+ }
+
+ if( !matched )
+ {
+ /* create new edge */
+ edge_picture[ unique_edges ][0] = inf->unique_cos[i0];
+ edge_picture[ unique_edges ][1] = inf->unique_cos[i1];
+
+ edge_picture[ unique_edges ][2] = i;
+ edge_picture[ unique_edges ][3] = -1;
+
+ unique_edges ++;
+ }
+ }
+ }
+#endif
+
+ v3f tri[3];
+
for( int i=0; i<len; i++ )
{
+#ifdef RIGIDBODY_DYNAMIC_MESH_EDGES
+ struct face_info *inf = &faces[i];
+
+ float *v0 = co_picture[inf->unique_cos[0]],
+ *v1 = co_picture[inf->unique_cos[1]],
+ *v2 = co_picture[inf->unique_cos[2]];
+
+ v3_copy( v0, tri[0] );
+ v3_copy( v1, tri[1] );
+ v3_copy( v2, tri[2] );
+
+ buf[count].element_id = inf->element_id;
+#else
u32 *ptri = &sc->arrindices[ geo[i]*3 ];
for( int j=0; j<3; j++ )
v3_copy( sc->arrvertices[ptri[j]].co, tri[j] );
-
- vg_line(tri[0],tri[1],0xff00ff00 );
- vg_line(tri[1],tri[2],0xff00ff00 );
- vg_line(tri[2],tri[0],0xff00ff00 );
buf[count].element_id = ptri[0];
- count += rb_sphere_triangle( rba, rbb, tri, buf+count );
+#endif
+
+ vg_line( tri[0],tri[1],0x10ffffff );
+ vg_line( tri[1],tri[2],0x10ffffff );
+ vg_line( tri[2],tri[0],0x10ffffff );
+
+ int hits = rb_sphere_triangle( rba, rbb, tri, buf+count );
+#ifdef RIGIDBODY_DYNAMIC_MESH_EDGES
+ if( hits )
+ inf->collided = 1;
+#endif
+ count += hits;
if( count == 12 )
{
}
}
+#ifdef RIGIDBODY_DYNAMIC_MESH_EDGES
+ for( int i=0; i<unique_edges; i++ )
+ {
+ int *edge = edge_picture[i];
+
+ if( edge[3] == -1 )
+ continue;
+
+ struct face_info *inf_i = &faces[edge[2]],
+ *inf_j = &faces[edge[3]];
+
+ if( inf_i->collided || inf_j->collided )
+ continue;
+
+ v3f co, delta;
+ closest_point_segment( co_picture[edge[0]], co_picture[edge[1]],
+ rba->co, co );
+
+ v3_sub( rba->co, co, delta );
+ float d2 = v3_length2( delta ),
+ r = rba->inf.sphere.radius;
+
+ if( d2 < r*r )
+ {
+ float d = sqrtf(d2);
+
+ v3_muls( delta, 1.0f/d, delta );
+ float c0 = v3_dot( inf_i->normal, delta ),
+ c1 = v3_dot( inf_j->normal, delta );
+
+ if( c0 < 0.0f || c1 < 0.0f )
+ continue;
+
+ rb_ct *ct = buf+count;
+
+ v3_muls( inf_i->normal, c0, ct->n );
+ v3_muladds( ct->n, inf_j->normal, c1, ct->n );
+ v3_normalize( ct->n );
+
+ v3_copy( co, ct->co );
+ ct->p = r-d;
+ ct->rba = rba;
+ ct->rbb = rbb;
+ ct->element_id = inf_i->element_id;
+
+ count ++;
+
+ if( count == 12 )
+ {
+ vg_warn( "Geometry too dense!\n" );
+ return count;
+ }
+ }
+ }
+#endif
+
return count;
}