Introduction:

This is a tutorial for intermediate users – the second part out of the 2 part post of how to automatically remesh limbs (arms and legs). Unlike the beginner version, here the system is completely automated.

If you are looking for the beginner tutorial  go to ” HOUDINI – Procedurally Retopo Limbs – Beginner  TUTORIAL” or else (pun intended) continue reading.

Note: In case you get lost you can download the finished Retopo file and explore both examples of the tutorial inside. Plus a bonus selection method.

We will select the edge loop on the low poly (LP) base where your desired limb attaches and the end loop of where it ends on the high poly. Cut of the hand/foot if it’s connected. From the LP we will find how many edges our cylinder will need to have for a proper bridge and then find the centroid of each loop. We will use them to find the length of the arm and direction, to conform to the high poly. I will be using the forearm as an example.

Set up

1. Make a group of the low poly geometry. Not mandatory but useful when you want to reuse the system on the same mesh.

2. Let’s find the loops! Connect the LP with a Polyfill node set to single polygon. Delete everything but the ngons from the polyfill (patch group).

Use getbbox_max (wrangle node) to find a point on the patch of the arm then get its primitive. Again, blast the rest and group all the edges.

//finds the furthest point in X to use as source to find the unshared edges loop
vector bbx = getbbox_max(0);
float pt_pos = @P.x; int primitive[];

if (pt_pos==bbx[0])
{
primitive=pointprims(0,@ptnum);
setdetailattrib(0,"loop_src", primitive[0],"set");
}

Note: getbbox_max will find the furthest pt in the x,y,z axis and return a vector. You might need getbbox_min if your limb is on to the “left” rather than the “right” or you need to retopo legs which will use the Z axis of the getbbox_min.

Note: To select second element of a vector or array use square brackets after the variable name.

single_value_name = Vector_name[0];

0 for X, 1 for Y, 2 for Z

When we project will use normals and to do it properly the we need a cylinder radius larger than of the arm.

3. Take the ngon from the elbow and plug it to a measure node set to perimeter. With the help of some basic math and a wrangle node we will find “radius” of the arm.

C=2πr, therefore the radius is equal to: r=C/2π

$PI is the constant for PI, no need to declare it.

float perimeter = prim (0, “perimeter”, @primnum); // perimeter

float rad; //radius

rad = perimeter/($PI*2); //find radius length

setdetailattrib(0, “rad”, rad, “set”); //set radius attribute

4. Add npoints expression to find the number points of the loop of the arm, which is also the same number of edges.  Make an attribute out of that, so we can set the cylinder column count. Again, for perfect quad only bridge.

i@nm_sides = npoints(0);

5. Transfer the edge group to the LP mesh and untick the other group transfers, otherwise you will lose your previous groups.

6.  Now we have to find the centroid of the loop with getpointbbox_center(0) in a point sop set to position. Fuse the points, but untick remove degenerate. Do it for both loops.

7. After we get the centroids, its time to aim them. But how the heck do we point the normal of the elbow point to the wrist one. Simple! Subtract the point position of the point we want to aim from the point position we are aiming to. And add the result as your Normal.

@N (elbow) =@P(wrist)-@P(elbow)

8. To get distance between the wrist and the elbow we need a function. It’s called wait for it… “distance”… who would’ve guessed. And of course make an attribute out of it. I did this and the previous step in a single wrangle, to reuse some of the code.

Since we are going to place our cylinder at the elbow centroid, due to the changed normal direction, when we conform to the high poly, there will be an overlap with the preexisting geometry.

To fix that issue we will download compute min max from Orbolt, by Animatrix. The Houdini Digital Asset (HDA) finds the length of a geometry along a normal, the min and max (obviously) and some other things.

9. Plug each of our loops into the HDA and grab the new normal direction of elbow centroid with a “point” expression.  This distance from each of the compute min max nodes will be used to push the cylinder along z and subtract from the height. And just like that …Bam! No more overlapping.

Finally let’s start making the actual arm.

1. Create a cylinder and place at the 0 y axis (ch(“height”)/2 ). In the height field take the arm len attribute (between the points) and subtract the 2 extra length values from the 2 compute min max nodes. Use detail expression to get the those values.

Mine looks like this:

detail("../arm_len_n_direction","arm_len", 0)-detail("../base_excess_length/","length", 0)-detail("../HR_excess_length/","length", 0)

2. Then group the bottom points using @P.y>0.001 and promote to edges. This group will bridge with the main toplogy.

3. Slap a transform node afterwards and rotate 90 degrees along x. Scale the radius (X and Z axis) 1.5 times the rad attribute we found in step 10.(check which step is it, after I combine)

To actually avoid the overlapping I described earlier, move the cylinder along the Z axis with our length attribute from the compute min max of the elbow polygon.

Now comes the very easy part, basic nodes and no more coding!

4. Plug the centroid of the elbow and the cylinder to a copy to points node.

5. Ray sop (conform) to the high poly. Reverse the rays and set to normal

6. Bridge the forearm to the elbow with the groups we made earlier.

Note: If the forearm conform has weird edge flow you can add a smooth to the forearm only. Use inverted base mesh group (!grp_name) for that and ray again. Adjust the bias (you can use negative values as well) as needed to allow all the points to hit.

7. Blast the base mesh group so you can reuse the system for legs (or other). And you are done!

To be honest there is specialized software that can do much better automatic retopo than this “little” asset. But this can still be useful for meshes that don’t need the topology that has to follow every muscle strand. Plus you can now say:

I wrote a fully non-destructive procedural asset that automatically retoplogizes limbs.

If you got to the bottom and read everything, let me know what you thought  of the tutorial and share the page so others can learn!