Utility class that computes a vertex-to-bone volumetric geodesic distance matrix. It subsamples mesh vertices, computes direct distances from bone segments, tests occlusion against a voxel grid, prunes outliers, fills invisible entries by using surface geodesic distances between subsamples, and maps results back to full vertex set.
using AutoRig.Mesh;
using AutoRig.Voxel;
namespace AutoRig.Dl.RigNet;
using Vector3 = System.Numerics.Vector3;
/// <summary>
/// Vertex→bone volumetric geodesic distances (quick_start.calc_geodesic_matrix):
/// straight-line distance where the bone can "see" the vertex, otherwise a detour
/// over the surface to the nearest visible vertex. Visibility uses the solid
/// voxelization (segment fully inside ⇒ unoccluded) instead of the reference's
/// triangle ray casts; sub-sampling is deterministic instead of random.
/// </summary>
public static class VolumetricGeodesic
{
/// <summary>
/// Computes the [V, B] distance matrix. Vertices are strided down to
/// <paramref name="maxSubsamples"/> for the heavy part and mapped back by
/// nearest subsample, like the reference's subsampling=True path.
/// </summary>
public static float[,] Compute(
RigMesh mesh, SkinBone[] bones, SurfaceGeodesic surfaceGeodesic, VoxelGrid voxels,
int maxSubsamples = 1500 )
{
ArgumentNullException.ThrowIfNull( mesh );
var vertices = mesh.Positions;
// Deterministic strided subsample.
var subCount = Math.Min( vertices.Length, maxSubsamples );
var subIndices = new int[subCount];
for ( var i = 0; i < subCount; i++ )
subIndices[i] = (int)((long)i * vertices.Length / subCount);
// pts2line: distance and nearest point on each bone segment.
var distance = new float[subCount, bones.Length];
var visible = new bool[subCount, bones.Length];
for ( var s = 0; s < subCount; s++ )
{
var p = vertices[subIndices[s]];
for ( var b = 0; b < bones.Length; b++ )
{
var origin = ClosestOnSegment( bones[b].Start, bones[b].End, p );
distance[s, b] = Vector3.Distance( origin, p );
visible[s, b] = IsUnoccluded( origin, p, voxels );
}
}
// Prune "visible but far": beyond 1.3 × the 15th percentile per bone.
var visibleDistances = new List<float>();
for ( var b = 0; b < bones.Length; b++ )
{
visibleDistances.Clear();
for ( var s = 0; s < subCount; s++ )
if ( visible[s, b] )
visibleDistances.Add( distance[s, b] );
if ( visibleDistances.Count == 0 )
continue;
var threshold = Percentile( visibleDistances, 15f );
for ( var s = 0; s < subCount; s++ )
if ( distance[s, b] > 1.3f * threshold )
visible[s, b] = false;
}
// Visible → direct distance; invisible → surface detour to the nearest
// visible subsample; no visible at all → direct distance.
var matrix = new float[subCount, bones.Length];
var visibleIds = new List<int>();
for ( var b = 0; b < bones.Length; b++ )
{
visibleIds.Clear();
for ( var s = 0; s < subCount; s++ )
{
if ( visible[s, b] )
{
visibleIds.Add( s );
matrix[s, b] = distance[s, b];
}
}
if ( visibleIds.Count == 0 )
{
for ( var s = 0; s < subCount; s++ )
matrix[s, b] = distance[s, b];
continue;
}
for ( var s = 0; s < subCount; s++ )
{
if ( visible[s, b] )
continue;
var bestGeo = float.MaxValue;
var bestVisible = visibleIds[0];
foreach ( var v in visibleIds )
{
var g = surfaceGeodesic.Distance( subIndices[s], subIndices[v] );
if ( g < bestGeo )
{
bestGeo = g;
bestVisible = v;
}
}
matrix[s, b] = bestGeo + matrix[bestVisible, b];
}
}
if ( subCount == vertices.Length )
return matrix;
// Map every vertex to its nearest subsample.
var full = new float[vertices.Length, bones.Length];
for ( var v = 0; v < vertices.Length; v++ )
{
var best = 0;
var bestDistance = float.MaxValue;
for ( var s = 0; s < subCount; s++ )
{
var d = Vector3.DistanceSquared( vertices[v], vertices[subIndices[s]] );
if ( d < bestDistance )
{
bestDistance = d;
best = s;
}
}
for ( var b = 0; b < bones.Length; b++ )
full[v, b] = matrix[best, b];
}
return full;
}
/// <summary>Segment fully inside the solid voxelization ⇒ nothing occludes it.</summary>
public static bool IsUnoccluded( Vector3 from, Vector3 to, VoxelGrid voxels )
{
var length = Vector3.Distance( from, to );
var steps = Math.Max( 1, (int)(length / (voxels.CellSize * 0.5f)) );
for ( var i = 0; i <= steps; i++ )
{
var p = Vector3.Lerp( from, to, i / (float)steps );
var (x, y, z) = voxels.VoxelOf( p );
if ( !voxels.IsSolid( x, y, z ) )
return false;
}
return true;
}
static Vector3 ClosestOnSegment( Vector3 a, Vector3 b, Vector3 p )
{
var ab = b - a;
var lengthSq = ab.LengthSquared();
if ( lengthSq < 1e-8f )
return a;
var t = Math.Clamp( Vector3.Dot( p - a, ab ) / lengthSq, 0f, 1f );
return a + ab * t;
}
/// <summary>numpy-style linear-interpolated percentile.</summary>
public static float Percentile( List<float> values, float percent )
{
var sorted = values.OrderBy( v => v ).ToArray();
if ( sorted.Length == 1 )
return sorted[0];
var rank = percent / 100f * (sorted.Length - 1);
var low = (int)MathF.Floor( rank );
var high = Math.Min( low + 1, sorted.Length - 1 );
return sorted[low] + (sorted[high] - sorted[low]) * (rank - low);
}
}