Skip to content

Hair and fur

Sample skin attributes using VEX

A common use case during grooming is sampling a custom attribute from the skin to curves. For example, this can be used to control the length of the hair or to adjust the width of the hair based on a skin attribute.

Sample attribute

We can use a simple method to copy attribute from the skin to the hair with VEX:

Point.wrangle
int prim;
vector primuv;
string skin_attrib = chs("attribute_name");
string output_attrib = chs("output_attribute");
int pts[] = primpoints(0, @primnum);
vector root_pos = point(0, "P", pts[0]);
xyzdist(1, root_pos, prim, primuv);
vector root_color = primuv(1, skin_attrib, prim, primuv);
foreach(int pt; pts) {
setpointattrib(geoself(), output_attrib, pt, root_color, "set");
}

First of all we have to inicialize our varibles:

  • int prim - variable to store the primitive number
  • vector primuv - variable to store the UV coordinates of the primitive
  • string skin_attrib - the name of the attribute on the skin
  • string output_attrib - the name of the attribute on the hair

Then we need get array of points for each primitive (our hair curves):

  • int pts[] = primpoints(0, @primnum);

After that, I want to get only the first point of the curve as the root position for the xyzdist function. I need to use only the root point to calculate the distance and sample the attribute from the skin. Then, I will propagate the sampled attribute from the root point to all points of the curve.

xyzdist() fuction used to find the closest point on the skin to the out point, and it return primitive number and UV coordinates of the closest point which we can use to sample attribute with primuv fuction.

  • first argument is the geometry to sample from ( in our case second input of the wrangle node 1)
  • second argument is the position to sample from
  • third argument is the primitive number of the closest point ( output argument)
  • fourth argument is the UV coordinates of the closest point ( output argument)

primuv() used to sample attribute from the skin

  • first argument is the geometry to sample from ( in our case second input of the wrangle node 1)
  • second argument is the name of the attribute to sample
  • third argument is the primitive number to sample from
  • fourth argument is the UV coordinates to sample from

After we have sampled the attribute from the skin, we can use a foreach loop to set the attribute on all points of the curve.

  • setpointattrib(geoself(), output_attrib, pt, root_color, "set"); - set the attribute on the point