+/*
+ * -----------------------------------------------------------------------------
+ * Manifold
+ * -----------------------------------------------------------------------------
+ */
+
+VG_STATIC int rb_manifold_apply_filtered( rb_ct *man, int len )
+{
+ int k = 0;
+
+ for( int i=0; i<len; i++ )
+ {
+ rb_ct *ct = &man[i];
+
+ if( ct->disabled )
+ continue;
+
+ man[k ++] = man[i];
+ }
+
+ return k;
+}
+
+/*
+ * Resolve overlapping pairs
+ */
+VG_STATIC void rb_manifold_filter_pairs( rb_ct *man, int len, float r )
+{
+ for( int i=0; i<len-1; i++ )
+ {
+ rb_ct *ci = &man[i];
+ int similar = 0;
+
+ if( ci->disabled ) continue;
+
+ for( int j=i+1; j<len; j++ )
+ {
+ rb_ct *cj = &man[j];
+
+ if( cj->disabled ) continue;
+
+ if( v3_dist2( ci->co, cj->co ) < r*r )
+ {
+ cj->disabled = 1;
+ v3_add( cj->n, ci->n, ci->n );
+ ci->p += cj->p;
+ similar ++;
+ }
+ }
+
+ if( similar )
+ {
+ float n = 1.0f/((float)similar+1.0f);
+ v3_muls( ci->n, n, ci->n );
+ ci->p *= n;
+
+ if( v3_length2(ci->n) < 0.1f*0.1f )
+ ci->disabled = 1;
+ else
+ v3_normalize( ci->n );
+ }
+ }
+}
+
+/*
+ * Remove contacts that are facing away from A
+ */
+VG_STATIC void rb_manifold_filter_backface( rb_ct *man, int len )
+{
+ for( int i=0; i<len; i++ )
+ {
+ rb_ct *ct = &man[i];
+ if( ct->disabled ) continue;
+
+ v3f delta;
+ v3_sub( ct->co, ct->rba->co, delta );
+
+ if( v3_dot( delta, ct->n ) > -0.001f )
+ ct->disabled = 1;
+ }
+}
+
+/*
+ * Filter out duplicate coplanar results. Good for spheres.
+ */
+VG_STATIC void rb_manifold_filter_coplanar( rb_ct *man, int len, float w )
+{
+ for( int i=0; i<len-1; i++ )
+ {
+ rb_ct *ci = &man[i];
+ if( ci->disabled ) continue;
+
+ float d1 = v3_dot( ci->co, ci->n );
+
+ for( int j=i+1; j<len; j++ )
+ {
+ rb_ct *cj = &man[j];
+ if( cj->disabled ) continue;
+
+ float d2 = v3_dot( cj->co, ci->n ),
+ d = d2-d1;
+
+ if( fabsf( d ) <= w )
+ cj->disabled = 1;
+ }
+ }
+}
+