Idea of a auto-retopology algorithm
This one is an idea I had for a possible multithreaded bakeable auto-retopology algorithm.
The main goal of this post is for people to try to highlight as many problems as this algorithm can encounter, or point out if there is already another better solution i don't know about :))
The algorithm is explained as pseudo-code with images, as I tried to make it as easy to understand as possible, but there is my personal opinion on the approach too
Notes:
- When I talk about "cubes" i mean voxels; however, I think that way it is easier to visualize even if you don't understand voxels.
- There are three sets of images, the first one has a easy topology on a character's arm, the second one has a more difficult topology on a plane. The last one has a finger-like terrible topology with a gap in it.
- There is no implementation of the algorithm, and the images were made by hand-modeling the interaction of the algorithm to the environment. The results may vary, if i'm in the wrong
- Non-connected edges means there is no direct path through the face that also doesn't go through a seam
#########
ALGORITHM
#########
Make a cube grid along the mesh of the model, the size of them being inverse proportion of vertex density times a constant (resolution chosen by user)
0 < t <= number of threads
Choose t of the cubes, project
it to the mesh in a way that you get a single plane (skinwrap modifier-like projection)
and (multithread lock) lock them as a in-use resource, assign them to a cube from the grid
.
In the first iteration the grid can be moved to match better the first created plane
Now starts a loop that can be multithreaded:
For every edge of the original mesh that intercepts the plane:
get the vector of the edge, and record it. All vectors will be used as to determine were the face/faces should be extruded to
My approach would be to hash the xyz direction of the vector into a hashmap/array of 6 pre-defined groups (+x, -x, +y, -y, +z, -z) and make the arithmetic mean of the vectors that land in each position (And therefore you need to keep track of how many vectors you have stored). This mean, together with the vector of the edge being extruded gives the program where to place the new edge. Also, if there is too much difference between two oposite axis, it means there is a split in the edge flow, and it should spawn two faces instead of only one
 If two vertex have no direct path trough the plane:  . split the cube into smaller cubes, leaving the non-connected sub-groups in these smaller cubes, and leave those cubes for later iterations
Once done, for each non-connected edge of the final mesh's edges, check every neighbour cube:
If it already has a face: . If the angle between the calculated vector and the ocupied face's closest edge is big enough (i guess greater than around -20º): . . extrude a new face
 . . If the angle is not too big (i guess less than around 20º):  . . . connect the adjacent edges
. . Otherwise:
 . . . If the distance between the edges is too small:  . . . . merge them at center  . Otherwise:  . . create a new face from the two edges  Otherwise, if there is no face nearby:  . Extrude the face along the calculated edge
This picture ends up with a non-desirable topology because of the edge flow. It could be an option to check for curvature in the mesh before extruding it curved
Once you have a face created:
unlock the in-use cube
lock the nearest cube
assign the new created face to that nearest cube
`
Repeat the loop until completion
Pseudo-code (no images) pastebin.com/cU7e5zKv
In my opinion this algorithm is good because:
- It can be multithreaded easily
- Generates mostly quads
- Follows the flow of the edges
- Can be set to depend on vertex denisty
- Although it may need auxiliar voxel remeshing, once you've got the grid it should work in planes and non-waterproof meshes
- Linear in complexity
- Hard edges may be faked with seams
- It can be "baked" meaning you'd only have to update modified vertices, which maybe can become a real-time auto-retopology tool
And also has its drawbacks
- It does need to have three meshes, which may lead to high ram usage
- It tends to generate tris around hard edges
- Although it is linear in complexity, it needs to iterate over a lot of edges
Thank you for reading this
3 Comments
An interesting approach to auto re-topology for sure!
I think a major problem with your approach is the reliance on the base mesh topology. A good retopology algorithm must be able to work on all kinds of meshes. (4 good examples are: heavily decimated mesh, OpenVDB remesh result, photo scans, unoptimal multiresolution) In the best case scenario an algorithm would output the exact same mesh no matter how you change the topology of a surface as long as you do not change the shape)
To reduce this issue you could replace working on input edges with surface walking. (if you wish to place an edge, you sort of think about the base mesh as a 2d surface and you move on it until you for example achieve a desired distance from start)
Also instead of placing quads one by one you could think of each vertex as a magnet that repels away from vertices near it. Then after you evened out the vertices you just need to connect them by edges and fill out the faces.
Also here are some things that I can think of that a good algorithm can handle. I find it useful to think about this things when creating a topology algorithm.
Also useful food for thought: youtube.com/watch
* @Lapis Sea * You are right, I can see it making a mess with photo-scans or high density, pointy meshes.
Also, it could give different results even with the same mesh with no changes (The algorithm heavily depends on the starting point)
Based on your comment, I've seen one problem I think I can improve, and I have also seen some more problems it cannot solve right now.
The thing I think I can improve is tris around hard edges. By tracing hard edges with quads at the beggining (from sharper angle to softer) you could have less tris. The angles would be decided from the base mesh and the generated cube grid (to detect high density corners). After that step, the algorithm could be used to fill out the mesh
But the issues still remain
Also I have one doubt, regarding the "mirror awareness" point. Do you mean to take input from an external source that tells you if there is any mirroring (like a boolean given from Blender, pex) or for the algorithm to detect mirroring? The algorithm would need a lot of improvements to being useful, but I think I'll keep thinking about it in case I can come up with something
(Specially the edge spiraling one I had totally forgotten about looks to me like a fun hard puzzle to think about)
Thank you very much for your comment, I have so much reading to do :D
If I were to think of anything else, I will post it
* @saisua * Oh sorry I should have explained the mirror awareness. Basically, instead of needing to bisect the model and remesh that the algorithm should know to take in to account only half of the mesh what will almost always create nicer topology due to extra context given.
Quadriflow example:
i.imgur.com/esESa21.png
i.imgur.com/mHJcCK0.png