UV coordinates and displacements in Mantra






Houdini 16.0

1 Mantra shader

A bunch of randomly bend curves is converted into a volume resulting in a dense mesh with no texture coordinates. A Mantra shader refers back to the input curves, unwraps the surface at render time and applies texture-based displacements using these steps:

1) Transform position to world space. 
2) Curve IDs shown as random colors.
3) U value from curves in HSV colors.
4) Direction to nearest curve position. 
5) Tangents from curves set to absolute. 
6) Direction to curve oriented along tangents.
7) V coordinate enclosing each wire.
8) UV coordinates in red and green.
9) UV mapping an image texture.

string geo = 'op:/obj/curves/OUT';
P = ptransform('space:current', 'space:world', P);

int prim = -1;
vector uvw = vector(0.0);
float dist = xyzdist(geo, P, prim, uvw);
vector pos = primuv(geo, 'P', prim, uvw);
float u = primuv(geo, 'u', prim, uvw);
vector tangent = primuv(geo, 'tangentu', prim, uvw);
matrix3 rot = dihedral(tangent, {0,1,0});
vector dir = normalize(P - pos);
vector dir_mod = dir * rot;
float v = fit( atan2(dir_mod.z, dir_mod.x), -M_PI, M_PI, 0.0, 1.0 );

P = set(u, v, 0.0);

2 SOP variant

For UV unwrapping a mesh based on underlying curves, you can also use this code inside a Point or Vertex Wrangle:

// INPUT 1: CURVES with 'tangentu'-attribute 

int prim_crv;
vector uvw_crv;
float dist = xyzdist(1, v@P, prim_crv, uvw_crv);

vector tangent = primuv(1, 'tangentu', prim_crv, uvw_crv);
matrix3 rot = dihedral(tangent, {0,1,0});
vector pos = primuv(1, 'P', prim_crv, uvw_crv);
vector dir = normalize(pos - v@P) * rot;
float angle = fit11(atan(dir.z, dir.x) / M_PI, 0.0, 1.0);
float perim = primintrinsic(1, 'measuredperimeter', prim_crv);

float u = (angle * 2.0 * M_PI * dist);
float v = uvw_crv[0] * perim;
v@uv = set(u, v, 0.0);