s@name = sprintf('%04d',@primnum);
padzero doesn't work in vex, so you have to use sprintf and the `%04d` method - don't forget those little backticks
s@name = sprintf('%04d',@primnum);
padzero doesn't work in vex, so you have to use sprintf and the `%04d` method - don't forget those little backticks
VEX code taken from this forum post, by user F1 -
Curling hair curves with VEX - General Houdini Questions - od|forum (odforce.net)
Very hand bit of code that can curl up your curves for hairstyles, bits of fluff or any other curly things you might imagine.
If you're going to use a path deform SOP after this (eg, you're using the curves to deform a bunch of snakes) you'll want to Attribute Delete the Normal "N" attribute that this script creates. Otherwise your geo might come out a bit flat/squashed/wrong in places.
// Primitive wrangle.
#define TWO_PI 6.2831852 addpointattrib(0, "N", {0, 0, 0}); int pts[] = primpoints(0, @primnum); int npt = len(pts); // Loop variables. vector rest = point(0, "P", pts[0]); vector prev_pos = rest; matrix3 frame = ident(); for (int i = 0; i < npt; i++) { vector pos = point(0, "P", pts[i]); vector delta = pos - rest; rest = pos; // Make normal. Point normals could be used instead. vector normal = normalize(cross(cross({0, 1, 0}, delta), delta)); if (length(normal) == 0) { normal = {0, 0, 1}; } // Drive a shape with ramps and multipliers. vector axis; float ramp, angle; // Twist the bend axis. axis = normalize(delta); ramp = chramp("twist_profile", (float) i / npt); angle = fit01(ramp, -TWO_PI, TWO_PI) * ch("twist") / (npt - 1); rotate(frame, angle, axis); // Bend the curve. axis = normalize(cross(normal, delta)); ramp = chramp("bend_profile", (float) i / npt); angle = fit01(ramp, -TWO_PI, TWO_PI) * ch("bend") / (npt - 1); rotate(frame, angle, axis); // Compute new position and normal. vector new_pos = delta * frame + prev_pos; prev_pos = new_pos; setpointattrib(0, "P", pts[i], new_pos); setpointattrib(0, "N", pts[i], normal * frame); }
// Primitive wrangle. int pts[] = primpoints(0, @primnum); vector rest = point(0, "P", pts[0]); vector prev_pos = rest; matrix3 frame = ident(); for (int i = 0; i < len(pts); i++) { vector pos = point(0, "P", pts[i]); rotate(frame, 0.1, {0, 0, 1}); vector new_pos = (pos - rest) * frame + prev_pos; rest = pos; prev_pos = new_pos; setpointattrib(0, "P", pts[i], new_pos); }
use case - you have a bunch of curves and want to give them individual point colours - but you want the points to all use the same id.
an Enumerate sop node will let you store the number value in each point or primitive. Lets use the primitive option, then attribute promote it to points so that each curve's points all contain the same identifiable attribute.
More of a reminder for myself... Quite a good primer on Kine FX, full body IK, posing and animation
https://youtu.be/S4Bzhnepovk
We use the setattribtypeinfo function to force an attribute to be a color type. Just like Cd usually is.
This will probably streamlined and not necessary in future versions of Blender, but it seems like it is still necessary atm (Jan 2023)
using a point wrangle, set to detail (so it only runs once)
setattribtypeinfo(0,"point","attributename","color");
here I'm forcing an attribute called attributename to be recognised as a color type & not just 3 floats.
I'm using the rop_alembic output to write the abc file.
Sometimes you need to use the current loop or the current piece number in an expression on one of the nodes in the same loop. You can get this information with a Block Begin SOP node that uses the Fetch Metadata method.
Set up a looping block using the instructions above.
Select the Block Begin SOP node, and then in the Parameter Editor click Create Meta Import Node.
This button adds a second Block Begin SOP node to the side of the existing one. This node is set up to generate an empty geometry with some detail attributes.
The detail attributes are as follows:
numiterations
The expected total number of iterations, taking into account the Max Iterations and Single Pass parameters on the Block End SOP node of the loop.
iteration
The current iteration number, always starting at 0
and increasing by 1 each loop.
value
In piecewise loops, this is the current value of the attribute. For example, the piece
integer or name
string, or if there is no attribute, the current point or primitive number.
In simple repetition loops, this is a floating point value starting at the Block End SOP’s Start Value and increasing by the specified Increment each loop.
ivalue
In simple repetition, this is an integer version of value
. This can be useful if the value is naturally an integer (for example, starts at 1
and increments by 2
) and/or if values are over 24 million (where floating point numbers lose precision).
To grab the value of these attributes in a node inside the loop, do the following:
In a Houdini expression, use the detail expression function.
For example:
detail("../block_begin2", "iteration", 0)
In an Attribute Wrangle SOP node, use the detail VEX function.
In Python, use hou.Geometry.attribValue():
node("../block_begin2").geometry().attribValue("iteration")
-8.26+detail("../foreach_count1", "iteration",0)*4
-8.26+(detail("../foreach_count1", "iteration",0)-1)*4
This does not create interior detail - but is good for troublesome geo.