Below you will find pages that utilize the taxonomy term “houdini”
Posts
Houdini - RBD Fracture and Sim Animated / Deforming Object
The effect: Pieces break apart according to a bunch of paths, on an object that is moving/deforming.
In parts, we have to:
(1) Fracture the sphere according to some paths.
(2) Have the pieces start out as part of the keyframed animation e.g. as part of the spinning globe, and then switch over to being simulated by the RBD Solver when some “trigger” happens.
@active and @deforming We learned previously, the RBD Solver looks for the attribute i@active on the pieces to determine whether they are “reactive” in a sim.
Posts
Houdini - Transferring Animation with Point Deform
Point Deform lets us transfer animation to any mesh (within reason) with just a buncha points. Lets create this contrived example, using this static mesh:
And this animated “point cloud”:
Wiring them up:
For the second input, we use a TimeShift to hold the first frame of the point cloud animation, which gives us the “rest lattice” that matches the static mesh’s topology (ideally).
All this essentially animates the mesh:
Posts
Vectors - Double Cross Product
We start with two vectors @N (yellow) – which is the primitive’s normal from a Normals SOP, and {0,1,0} – the global up (gray). When the primitive is not rotated, these two vectors are parallel.
By using a buncha cross, we can derive our main axes:
vector pink = cross(@N, {0, 1, 0}); // First cross product vector green = cross(pink, @N); // Second cross product, the "double cross" Note 1: The green vector is essentially an “up-ish” vector that is always parallel to the plane and never points downwards.
Posts
Houdini - Rotations and Look At
A point doesn’t “point” anywhere. Points have no implicit direction or orientation. The idea of “rotating a point” is essentially meaningless.
1. When we “rotate a point”, we are implicitly saying “translate this point around the origin”. Take this example of “rotating” points in a Point Wrangle:
matrix3 m = ident(); rotate(m, @Time, {0, 1, 0}); // Rotate on Y over @Time @P *= m; What we’re really doing is translating points around the origin:
Posts
Houdini VEX - Distance and Neighbours
1. The “workhorse” functions Most of the time, we use these to query distance: distance, xyzdist.
2. Query from a single point/prim When you ask: “Who’s next to me? Who’s nearby? Who’s connected to me?”. We ask this when we need to do stuff like growth propagation: nearpoint(s), neighbour(s), polyneighbours.
3. Specialized Other functions/operators that work with distance: surfacedist, pcfind, minpos, Find Shortest Path, Distance From Geometry
1a. distance An infrared ramp is used to color points based on their respective distances to the orbiting ball.
Posts
Vectors - Positions and Rotations
An arbitrary point in space (x,y,z) is a vector <x,y,z> from the origin. Adding a vector <a,b,c> to a point gives us another point. The vector <a,b,c> can be derived by subtracting P1 from P2. So far:
vector abc = {1, 2, 3}; vector P2 = P1 + abc; vector def = P2 - P1; // def == abc The vector <a,b,c> defines a line in space between P1 and P2.
Posts
Houdini - Moving Geometry with Particles
Transform Pieces moves stuff around with points.
[Above] We use one point to move one box.
Transform Pieces takes three inputs:
[ A ] Points to transform. [ B ] Points that will move the A-points. [ C ] Rest positions of B before the move.
Houdini binds the A-points to the B-points by matching a user-specified attribute that exists on both.
In our tree, Assemble packs the box – reducing it to a single A-point – which is then driven by the single B-point.
Posts
Houdini - Controlled Destruction - SOP Solver in DOPs
We can modify constraints and geos while a simulation runs by plugging in SOP Solvers inside a DOP.
The wirings go like this:
[Above] The blue SOP Solver messes with the incoming RBD Packed Object (after the Bullet Solver is done with it), and the red SOP Solver messes with the constraint network.
The various solvers plugged into the Multi Solver (green) are evaluated left-to-right.
In this case, the Bullet Solver does its thing to the packed object, moves shit around, then passes it to the blue SOP Solver.
Posts
Houdini - Animating Constraints
Since a Constraint Network is nothing more than geometry, we can animate it.
Here, we have a line connecting two points, constraining a ball. We move the line up, the ball follows along. Easy.
But not really. First, let’s do what is “intuitive” and setup a network like so:
The Transform SOP (red) moves the entire line up. And this is what we get:
When the sim runs, the constraint network moves up, but the ball doesn’t come along.
Posts
Houdini - Carving Lines and Segments
Animating the “First U” and “Second U” parameter of a Carve sorta makes the line appear or disappear.
This is also how you extract a segment of a line.
So far, the entire line is one primitive. What if we want to “break it up”? E.g. we want polylines between 1--2, 2--3, 3--4, etc. We would first need “unique points” e.g. 1--2, [x]--3, [x]--4.
If we enable Breakpoints > Cut all Internal U Breakpoints:
Posts
Houdini - Ray and Blend Shape
We have two grids, we scatter an equal number of points on both. Boys on the left, girls on the right.
Blend Shapes is a lerp function. You give it a “start” and “goal” state – boys at the start, girls at the goal – and Houdini interpolates between them.
In the operator, blend1 is the bias – a float 0 <> 1 that sets the current “state” along that interpolation.
Posts
Houdini - Constraints and anchor_id - Part 1
When Houdini builds a Constraint Network, as long as points have @name, it automagically connects points to the centroid of the object specified by @name.
[Left] We have a constraint network (in yellow). The points only have @name declared on them. [Right] Inside DOPs, Houdini finds the object, and smartly connects the bottom points to the centroid of the object. Which results in:
What we need is a way to tell Houdini which points on the target do we want each constraint point to be anchored to.
Posts
Houdini - Constraints and anchor_id - Part 2
See Part 1 here.
99% of the time, when you setup constraint points that are close to/on the surface of a geometry, you don’t actually need i@anchor_id.
[left] We have a constraint network with points that only have @name declared. The points on her body have @name = "thing", the ones on top @name = "".
[right] The constraint network that gets built inside DOPs is as expected, everything just works.
Posts
Houdini - Constraint Networks Basics
A constraint is a single primitive polyline connecting two points. Anything not this will be ignored.
The points tell Houdini what they constrain through a @name attribute. The bottom point, in this case, constrains something called “thing”.
If @name is an empty string [the top point], then it is a “world contraint” e.g. it’s pinned to wherever its position happen to be.
IMPORTANT The @name attribute must exist or the constraint will not be created.
Posts
Houdini VEX - Bias Lerp and Slerp
A bias value tells us where, along an interpolation, to grab a value from.
If we’re interpolating between the numbers 1 and 2, when bias == 0, the return value is 1. When bias == 1, the return value is 2. Thusly, bias == 0.5 would return 1.5.
There are two main functions to get this “return value”: lerp (for all numbers and vectors) and slerp (for quarternions).
Formally, to get the “middle” of interpolating between 1 and 2 (above example), we would write:
Posts
Houdini - POP Replicate - Fireworks
The basis of all “fireworks” like effects (or rocket boosters!).
Essentially, a single point with @v = {0, 1, 0} fed into a POP Replicate with Impulse set to $F%24==0 e.g. points are replicated every 24-frames.
Posts
Houdini - POP Wind vs POP Force
A POP Force is a pushing force – it accelerates particles – each step adds to the particle’s @v.
A POP Wind is a pulling force. If we have this setting:
An attribute is created on the particle called @targetv – in this case {0,2,0}. Over time, the particle will match its own @v to @targetv. This also means that the particle’s @v will never exceed @targetv – as apposed to a POP Force, which keeps adding to @v.
Posts
Houdini - Modeling With a Ramp
A ramp takes in a sample position 0 <> 1 (x-axis) and outputs the value sampled at that position from the y-axis.
Here, we take a Line SOP and create a line with direction {0, 1, 0}. We feed it into a Revolve SOP.
Before the Revolve, we use a Wrangle to push the @P.x of the points around with the ramp.
float pos = @ptnum/float(@numpt); // For each point 0.
Posts
Houdini - Animating with UV
The network, at the most basic level needs only 2 things: a path, and a point.
The magic sauce and engine that drives the whole thing is Attribute Interpolate. It expects points from its first input, and paths/primitives from its second input.
The points from the first input must have:
i@sourceprim – match this to a @primnum from the second input.
v@sourceprimuv – where to place the point on the sourceprim.
Posts
Houdini VEX - Noise and Curves
In these examples, we have a line along +x and we use noise functions to distort it along the y-axis.
Inside a Wrangle over points:
float offset = 0; // This is zero for simplicity @P.y = sin(@P * @Time + offset); The combined term of @P * @Time is the frequency of the curves. The higher this number – as @Time increases – the greater the frequency.
We start with the simplest, using sin:
Posts
Houdini VEX - Random Directed Vectors
This is a great way of getting “random” vectors but you need the vectors to be “clamped” to a certain range of “spread”.
To illustrate this, we’ll use a buncha points on a grid and “shoot” (aka move) them out “randomly” using sample functions.
1. Sample Direction Uniform vector2 u = rand(@ptnum); @P = sample_direction_uniform(u); Which gets us, well, a buncha points scattered in every direction.
2. Sample Hemisphere This function takes a center and a bias.
Posts
Houdini - Max, Min, Average of Attributes
Without writing Vex, append an Attribute Promote and promote the attribute to a detail, then use any of the promotion methods:
In this case, we want the maximums of @P – so we promote from Original name - P - to a New name of max which lets us then access max as a detail attribute!
Posts
Houdini - Scatter With Attribute
We’ll take this png.
Use an Attribute from Map to populate @Cd with color information from the image.
Now we can Scatter by density, and use Cd to drive the density.
Black and transparent pixels are treated as zero density, hence, will have no scattering.
Posts
Houdini - Using Measure
We use a Measure SOP to get the perimeter of each Voronoi fractured piece, then set that value as @pscale.
Copy to Points will pick up @pscale and apply it to every instance hence the bigger the piece, the bigger the instance.
Posts
Houdini - Multiplying Quaternions
From this exercise and the following lines:
vector4 o = dihedral({0, 0, 1}, @P); // align z-axis with @P vector We get this result:
Now we want to face her ass out, which means we gotta rotate her 90-degrees on her y-axis.
From this exercise, we learned how to build a quarternion from a rotation and an axis.
vector4 r = quaternion(set(0, radians(90), 0)); // e.g {0, 90, 0} - rotate y 90-deg We combine both the rotations by multiplying the quarternions, using qmultiply:
Posts
Houdini - Orientation
How Houdini determines orientation Houdini searches for these attributes, in this order. It goes down this list until none is found.
@orient attribute. Use this to orient copy/instances. Using @N as the Z-axis and +Y is up. Use @v e.g. velocity. If @rot exists, apply it to the above. Copy to Points We have a point with @N = {0, 1, 0} e.g. its normal pointing up (the yellow trail).
Posts
Houdini - Quaternions From Rotation and Axis
float deg = radians(@Frame % 360); @orient = quaternion(set(deg, 0, 0)); Substituting set(0, deg, 0) - Y-axis.
Substituting set(0, 0, deg) - Z-axis.
Posts
Houdini - Connecting Points on a Geometry
Lets start with a mesh like this (with points colored cause why not).
Keep only Points Use the Add operator (yes, use the “add” operator to remove stuff) like this:
To get just the points!
Remove faces, keep Points and Edges So we wanna remove the “primitive faces” but keep the points and edges (edges are technically primitives in Houdini). We can use:
Convert Lines Carve Ends - Close U > Unroll with New Points.
Posts
Houdini - Selecting Points on a Grid
Using neighbourcount in a Group Expression operator to get points on the outer edge of a grid:
neighbourcount(0, @ptnum) <= 3 To get only the corners:
neighbourcount(0, @ptnum) == 2
Posts
Houdini - Separate Pieces
We want to manipulate every face individually, so we have to “break up” the mesh into individual primitive pieces.
Use a facet operator, with “unique point” turned on. Then, use a primitive operator to do stuff, like scaling, which will get us:
Add a point to the center of each primitive Run a Wrangle SOP over primitives and simply add a point at each position:
int pt = addpoint(0, @P); setpointgroup(0, "centroids", pt, 1); // group just in case Which gives us this:
Posts
Houdini - Selecting With Bounding Box
Use the relbbox function in a Group Expression to select points at the “extremities” of a geo’s bounding box.
E.g. the “front facing” points here are +1 on the z-axis:
relbbox(0, @P).z == 1 And the “back facing” ones would be z == 0.
The “top” points are +1 on the y-axis:
relbbox(0, @P).y == 1 Using the same expression lets us also conveniently select the “topmost” point on a sphere:
Posts
Houdini - A solver is a reduce function
A solver is essentially a reduce function. It’s passed, as its first argument, the result of the previous loop’s evaluation.
A reduce function in Javascript:
const array1 = [1, 2, 3, 4]; function reducer(accumulator, currentValue) { return accumulator + currentValue } ; result = array1.reduce(reducer) //=> 10 Inside a solver:
As an example, we create a network with a single attribute @num = 0 and pass it into the solver.
Posts
Houdini - Solver as an Accumulator
The idea: Use a solver to accumulate boxes from each frame of a “simulation”.
E.g. we’re creating a reduce function that looks like this:
func accumulate(boxes []box, currBox box) { boxes = append(boxes, currBox) return boxes } To get started, we create one point on a grid on each frame.
We then copy a randomly colored box to each of those points, on each frame e.g. the box is given a different color on each frame, and then copied to the new point on that frame.
Posts
Houdini - Using a solver to persist attribute transfer
Here we have a bunch of curves that change color over time and transfers their @Cd to the grid when they come into contact with it.
When a frame cooks, Houdini evaluates the contact only on that frame, it has no “memory” as to whether they’ve touched before.
So how do we persist the color?
We do the attribute transfer inside a solver node, which will allow us to “accumulate” the paint just as we did with boxes.
Posts
Houdini - Startup Settings
The path to the user’s directory is stored in the environment variable HOUDINI_USER_PREF_DIR.
windows: ${HOME}\Documents\houdini18.0
Startup Scripts Startup scripts are located in ${$HOUDINI_USER_PREF_DIR}/scripts.
When Houdini starts up, it sources for 123.py. This is executed only once when Houdini launches.
To execute a script on each scene load, Houdini sources for 456.py in the same scripts folder. This file is also executed when Houdini first launches the default untitled.hip.
Posts
Houdini VEX - Attributes Inside VOPs
Inside a VOP node, an attribute is dubiously called a bound variable. We read/write attributes inside a VOP with the bind operator.
bind1 reads an attribute from outside the VOP called one.
bind2 creates an attribute and exports it outside.
The end result of this DAG is a red object!
Posts
Houdini VEX - Looping
A few variables are available for referencing in a Wrangle:
@ptnum – current point number up to @numpt @elemnum – current index of this element up to @numelem Their equivalents are @primnum, @numprim etc.
To loop over every point:
vector positions[] = {}; for (int i = 0; i < @numpt; i++) { vector p = point(geoself(), "P", i); push( positions, p); } Using foreach:
foreach(vector position; positions) { // Do something; }
Posts
Houdini VEX Attributes
Reading Attributes To access a point’s attributes:
@Cd = point(0, "Cd", @ptnum) // 0 is the input, or use 'geoself()' You can access point , prim , vertex, etc. See here.
Remember that inputs are zero-indexed.
To explicitly cast anything in VEX, use set.
float aFloat = 1.0; int cols = set(aFloat); // cast 'float' to 'int' int cols = (int)aFloat; // another way Setting Attributes To set an attribute:
Posts
Houdini VEX Groups
When you group stuff together with a Group SOP, Houdini simply creates an attribute called @group_{name} whose value is 1 or 0.
So to manually add an element to a group, just create the attribute on the element:
i@group_fuckheads = 1; // Remember to declare i! When acting on a point or prim from a detail:
setpointgroup(0, "selected", ptnum, 1); To check whether an element is in a group, just check for the attribute:
Posts
Houdini VEX Types
Type Syntax float f@name int i@name string s@name vector v@name vector2 u@name vector4 p@name matrix2 2@name matrix3 3@name matrix (4x4) 4@name integer array i[]@name vector array v[]@name string array s[]@name Declaring just a plain vector:
vector scale = {1,2,3}; A vector array: