Populating a UV-unwrapped mesh surface with inter-looped yarn curves.
A half circle is scaled inwards to shape a single knitting loop using a curve ramp along the Y-axis. The first two and last two points are flattened to Y zero for continuity to the next loops.
v@P.x *= chramp('shape', v@P.y);
v@P.y *= i@ptnum >= 2 && i@ptnum < i@numpt - 2;
After resampling the subdivision curve is bend using a cosine wave for inter-looping with the next row.
v@P.z = cos(v@P.y * M_PI * 2.0) * 0.1;
A new grid adopts the shape of the single loop several times along each grid line. While in uvw
the u
component gets tiled c
times to repeatedly sample the single loop's shape, u_2
in uvw_2
is rastered to individual pivot positions for each copy.
int c = chi('copies');
float u = vertexcurveparam(0, i@vtxnum);
vector uvw = set(frac(u * c), 0.0, 0.0);
vector pos = primuv(1, 'P', 0, uvw);
float u_2 = u / c + floor(u * c) / float(c);
vector uvw_2 = set(u_2, 0.0, 0.0);
vector pivot = primuv(0, 'P', i@primnum, uvw_2);
v@P = pos - pivot;
The inter-looped grid pattern is positioned to the mesh surface (stored as v@rest
) by matching the grid's bounding box with the mesh UVs. The depth d
of the knitting structure is used as a multiplier along with the transfered surface normals nml
.
v@P.y
gets temporarily overwritten with the distance to UV boundaries to prepare the clipping.
vector bb = relbbox(0, v@P);
float d = bb.z;
bb.z = 0.0;
int prim;
vector uvw;
float dist = uvdist(1, 'uv', bb, prim, uvw);
vector pos = primuv(1, 'P', prim, uvw);
vector nml = primuv(1, 'N', prim, uvw);
v@rest = pos + nml * d * 0.005;
v@P.y = dist - 1e-5;
After clipping grid curves when they shoot over the boundaries of the UV islands, the rest position gets assigned to the curves. A point scale defines the width of the curves for rendering in Solaris.
f@pscale = 0.003;