Boolean Curves With Geometry in Houdini

Cutting curves with geometry in Houdini is a bit tricky because a curve is made from a single primitive. So if you remove points from the middle of the curve, the curve will still continue through the cut. A way to solve this would be to delete the original primitives and rebuild them back again after the intersected points are deleted. The problem with this is that the points need to have an attribute specifying which primitive the points belong to. And this is the problem I’ve tackled here.

The idea behind the vex script is to iterate over the points on the primitive from root to tip and check if there’s any geometry intersecting the hair primitive. On every iteration, the script will create a class attribute on the point, and if there’s an intersection on the way, the class attrib will be incremented by one. This class attrib is needed to rebuild the primitives afterward with the add sop.

To check if there’s an intersection, the script calculates two distances. One to the next point on the same primitive, and one to the surface wired into the second stream of the point wrangle. If the distance to the surface is closer than the distance to the next point, the surface is intersecting the geo after the iterated point. This will cause an error if there’s a surface very close but not intersecting, so in this case, I would resample the curve more. Another way would be to search for the surface only in the direction of the tangent vector by raytracing with intersect vex function.

To check if the point is inside the geometry, the script calculates a vector pointing toward the surface of the intersection geometry and reads the normal vector from the closest point on the intersection geometry. If these two vectors point in the same direction, the point is inside the geometry. This can be checked with a dot product. If the dot product of two vectors equals 1, it means the vectors are in the same direction and if it is -1 then the vectors are in opposite directions. In this case, it’s close enough to know if the dot product is greater than 0.

One issue I came across was that in the intersection area, the class attribute got incremented on the point before the intersection and on the point after the intersection. To solve this I added another dot product rule to only increment the class attrib if the iterated point is inside the geometry.

Run this script in primitive wrangle:

int prim;
vector uv;

int pts[] = primpoints(0,@primnum);
int count1 = i@connected*(nprimitives(0)*53);

for ( int i=0; i<len(pts); i++ ){

    vector pos = point(0,"P",pts[i]);
    vector nbr_pos = point(0,"P",pts[i+1]);
   
    float nbr_dist = distance(pos,nbr_pos);
   
    float surface_dist = xyzdist(1,pos,prim,uv);
    vector npos = primuv(1,"P",prim,uv);
    vector N = primuv(1,"N",prim,uv);
   
    vector dir = npos-pos;
    float dot = dot(dir,N);
   
    if ( dot > 0 ) {
        setpointgroup(0,"delete",pts[i],1);
    }
   
    if ( nbr_dist < surface_dist ) {
        setpointattrib(0,"class",pts[i],count1);
    }
    else {
        if ( dot > 0 ) {
            setpointattrib(0,"class",pts[i],count1);    
            count1 += 1;
        }
        else {
            setpointattrib(0,"class",pts[i],count1);
        }
    }  
}
Previous
Previous

Procedural attribute remap to 0-1 space

Next
Next

Hair Interpolation in Houdini with VEX