-#if 0
-static inline void skate_grind_coordv2i( v2f co, v2i d )
-{
- const float k_inv_res = 1.0f/0.01f;
- d[0] = floorf( co[0] * k_inv_res );
- d[1] = floorf( co[1] * k_inv_res );
-}
-
-static inline u32 skate_grind_hashv2i( v2i d )
-{
- return (d[0] * 92837111) ^ (d[1] * 689287499);
-}
-
-static inline u32 skate_grind_hashv2f( v2f co )
-{
- v2i d;
- skate_grind_coordv2i( co, d );
- return skate_grind_hashv2i( d );
-}
-
-VG_STATIC int skate_grind_scansq( player_instance *player, v3f pos,
- v3f result_co, v3f result_dir, v3f result_n )
-{
- v4f plane;
- v3_copy( player->rb.v, plane );
- v3_normalize( plane );
- plane[3] = v3_dot( plane, pos );
-
- boxf box;
- float r = k_board_length;
- v3_add( pos, (v3f){ r, r, r }, box[1] );
- v3_sub( pos, (v3f){ r, r, r }, box[0] );
-
- vg_line_boxf( box, VG__BLACK );
-
- m4x3f mtx;
- m3x3_copy( player->rb.to_world, mtx );
- v3_copy( pos, mtx[3] );
-
- bh_iter it;
- bh_iter_init( 0, &it );
- int idx;
-
- struct grind_sample
- {
- v2f co;
- v2f normal;
- v3f normal3,
- centroid;
- }
- samples[48];
-
- int sample_count = 0;
-
- v2f support_min,
- support_max;
-
- v3f support_axis;
- v3_cross( plane, (v3f){0.0f,1.0f,0.0f}, support_axis );
- v3_normalize( support_axis );
-
- while( bh_next( world.geo_bh, &it, box, &idx ) )
- {
- u32 *ptri = &world.scene_geo->arrindices[ idx*3 ];
- v3f tri[3];
-
- for( int j=0; j<3; j++ )
- v3_copy( world.scene_geo->arrvertices[ptri[j]].co, tri[j] );
-
- for( int j=0; j<3; j++ )
- {
- int i0 = j,
- i1 = (j+1) % 3;
-
- struct grind_sample *sample = &samples[ sample_count ];
- v3f co;
-
- if( plane_segment( plane, tri[i0], tri[i1], co ) )
- {
- v3f d;
- v3_sub( co, pos, d );
- if( v3_length2( d ) > r*r )
- continue;
-
- v3f va, vb, normal;
- v3_sub( tri[1], tri[0], va );
- v3_sub( tri[2], tri[0], vb );
- v3_cross( va, vb, normal );
-
- sample->normal[0] = v3_dot( support_axis, normal );
- sample->normal[1] = normal[1];
- sample->co[0] = v3_dot( support_axis, d );
- sample->co[1] = d[1];
-
- v3_copy( normal, sample->normal3 ); /* normalize later
- if we want to us it */
-
- v3_muls( tri[0], 1.0f/3.0f, sample->centroid );
- v3_muladds( sample->centroid, tri[1], 1.0f/3.0f, sample->centroid );
- v3_muladds( sample->centroid, tri[2], 1.0f/3.0f, sample->centroid );
-
- v2_normalize( sample->normal );
- sample_count ++;
-
- if( sample_count == vg_list_size( samples ) )
- {
- break;
- }
- }
- }
- }
-
- if( sample_count < 2 )
- return 0;
-
-
-
- /* spacial hashing */
-
- const int k_hashmap_size = 128;
- u32 hashmap[k_hashmap_size+1];
- u32 entries[48];
-
- for( int i=0; i<k_hashmap_size+1; i++ )
- hashmap[i] = 0;
-
- for( int i=0; i<sample_count; i++ )
- {
- u32 h = skate_grind_hashv2f( samples[i].co ) % k_hashmap_size;
- hashmap[ h ] ++;
- }
-
- /* partial sums */
- for( int i=0; i<k_hashmap_size; i++ )
- {
- hashmap[i+1] += hashmap[i];
- }
-
- /* trash compactor */
- for( int i=0; i<sample_count; i++ )
- {
- u32 h = skate_grind_hashv2f( samples[i].co ) % k_hashmap_size;
- hashmap[ h ] --;
-
- entries[ hashmap[h] ] = i;
- }
-
-
- v3f
- average_direction,
- average_normal;
-
- v2f min_co, max_co;
- v2_fill( min_co, INFINITY );
- v2_fill( max_co, -INFINITY );
-
- v3_zero( average_direction );
- v3_zero( average_normal );
-
- int passed_samples = 0;
-
- for( int i=0; i<sample_count; i++ )
- {
- struct grind_sample *si, *sj;
- si = &samples[i];
-
- v2i start;
- skate_grind_coordv2i( si->co, start );
-
- v2i offsets[] = { {-1,-1},{ 0,-1},{ 1,-1},
- {-1, 0},{ 0, 0},{ 1, 0},
- {-1, 1},{ 0, 1},{ 1, 1} };
-
- for( int j=0; j<vg_list_size(offsets); j++ )
- {
- v2i cell;
- v2i_add( start, offsets[j], cell );
-
- u32 h = skate_grind_hashv2i( cell ) % k_hashmap_size;
-
- int start = hashmap[ h ],
- end = hashmap[ h+1 ];
-
- for( int k=start; k<end; k++ )
- {
- int idx = entries[ k ];
- if( idx <= i )
- continue;
-
- sj = &samples[idx];
-
- /* non overlapping */
- if( v2_dist2( si->co, sj->co ) >= (0.01f*0.01f) )
- continue;
-
- /* not sharp angle */
- if( v2_dot( si->normal, sj->normal ) >= 0.7f )
- continue;
-
- /* not convex */
- v3f v0;
- v3_sub( sj->centroid, si->centroid, v0 );
- if( v3_dot( v0, si->normal3 ) >= 0.0f ||
- v3_dot( v0, sj->normal3 ) <= 0.0f )
- continue;
-
- v2_minv( sj->co, min_co, min_co );
- v2_maxv( sj->co, max_co, max_co );
-
- v3f n0, n1, dir;
- v3_copy( si->normal3, n0 );
- v3_copy( sj->normal3, n1 );
- v3_cross( n0, n1, dir );
- v3_normalize( dir );
-
- /* make sure the directions all face a common hemisphere */
- v3_muls( dir, vg_signf(v3_dot(dir,plane)), dir );
- v3_add( average_direction, dir, average_direction );
-
- if( si->normal3[1] > sj->normal3[1] )
- v3_add( si->normal3, average_normal, average_normal );
- else
- v3_add( sj->normal3, average_normal, average_normal );
-
- passed_samples ++;
- }
- }
- }
-
- if( !passed_samples )
- return 0;
-
- if( (v3_length2( average_direction ) <= 0.001f) ||
- (v3_length2( average_normal ) <= 0.001f ) )
- return 0;
-
- float div = 1.0f/(float)passed_samples;
- v3_normalize( average_direction );
- v3_normalize( average_normal );
-
- v2f average_coord;
- v2_add( min_co, max_co, average_coord );
- v2_muls( average_coord, 0.5f, average_coord );
-
-
- v3_muls( support_axis, average_coord[0], result_co );
- result_co[1] += average_coord[1];
- v3_add( pos, result_co, result_co );
-
-#if 0
- vg_line_pt3( result_co, 0.02f, VG__GREEN );
-
- v3f p0, p1;
- v3_muladds( result_co, average_direction, 0.35f, p0 );
- v3_muladds( result_co, average_direction, -0.35f, p1 );
- vg_line( p0, p1, VG__PINK );
-#endif
-
- v3_copy( average_normal, result_n );
- v3_copy( average_direction, result_dir );
-
- return passed_samples;