X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=rigidbody.h;h=04d5a9c9830c824d466b7c3fb7cff82364556726;hb=ec0918b2ef17a71418a57417689fd3042915aeeb;hp=10b4359f56537641354c59e982e0d9d8a37b6098;hpb=6294ef64d948eab2365e39a2645c9843aa96fba8;p=carveJwlIkooP6JGAAIwe30JlM.git diff --git a/rigidbody.h b/rigidbody.h index 10b4359..04d5a9c 100644 --- a/rigidbody.h +++ b/rigidbody.h @@ -103,6 +103,7 @@ VG_STATIC struct contact normal_mass, tangent_mass[2]; u32 element_id; + int cluster; } rb_contact_buffer[256]; VG_STATIC int rb_contact_count = 0; @@ -1247,12 +1248,19 @@ VG_STATIC int rb_sphere_sphere( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) 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 ); @@ -1289,24 +1297,142 @@ VG_STATIC int rb_sphere_scene( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) 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; iarrindices[ 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; kco, 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; iunique_cos[i0], inf->unique_cos[i1] ), + e1 = VG_MAX( inf->unique_cos[i0], inf->unique_cos[i1] ), + matched = 0; + + for( int k=0; kunique_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; iunique_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 ) { @@ -1315,6 +1441,62 @@ VG_STATIC int rb_sphere_scene( rigidbody *rba, rigidbody *rbb, rb_ct *buf ) } } +#ifdef RIGIDBODY_DYNAMIC_MESH_EDGES + for( int i=0; icollided || 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; }