Geodesic Voxel Binding for Production Character Meshes
Created on 2021-03-09T22:44:35-06:00
Voxelization
Find a bounding box for the model.
Use the bounding box to set up orthographic projection to render the model.
For each Z slice set the near and far clip planes to the slice boundary, render back faces in white and front faces in black (with no filtering for any faces.)
White pixels indicate the inside of a voxel.
+X, -X, +Y, -Y, +Z and -Z projection maps are created.
Internal voxels
Voxels are then classified as inside a mesh if two or more of these rules vote yes:
Vi(x, -x) : {0, 1} -> Vix || Vi-x Vi(y, -y) : {0, 1} -> Viy || Vi-y Vi(z, -z) : {0, 1} -> Viz || Vi-z
Mesh boundary voxels
We perform a final post-processing step to extract mesh boundary voxels. This is achieved by computing an octree from the mesh and testing for intersections against each voxel using Akenine-Moller’s ¨ separating axis theorem triangle/box overlap test [2001]. Remaining untagged voxels are considered external to the mesh domain.
Fixup
Allow selecting which views are used for projection.
"Voxel painting" to correct mistake regions.
Weighting
For each bone
Set the distance to non-exterior voxel to infinity.
For all voxels intersecting a bone set the distance to zero and put coordinates in work queue.
Take coordinate from queue. For all neighboring voxels with a worse distance update them and add to queue.
Repeat weighting process to get voxel map for each bone in rig.
Converting to weight paint
Compute distance from center of voxel to center of vertex `dij`.
Compute weight influence `wij` with the adjusted distance `dij`.
(1 / ((1 - alpha)(dij) + alpha * (dij)^2)^2
Alpha is a parameter between 0-1 (inclusive) controlling "bind smoothness."
Distance values are normalized using a bounding box so they are independent of mesh scale.
The falloff function is technically replacable. It was found to give good results on the author's test set.
Weights also have to be normalized afterward based on how many bones can be influenced per vertex.