Houdini 12 Reference

## Important

This cookbook refers to the old expression language. For information on Python expressions, see the Houdini Object Model section.

## Choosing a random number seed

The rand(seed) function always returns the same number when given the same `seed` value. This makes “random” values repeatable between playbacks. However, you must be careful to supply a seed value that varies.

The current frame number (`\$F`) is usually a good seed value, however:

• If you need random values for a sub-frame process, use the fractional frame number `\$FF` instead of `\$F`.

• If you need more than one random value, such as R, G, and B values for a random color, give each call to `rand` a different seed value by modifying the `\$F`, otherwise each call will return the same number and the color will be gray.

R

G

B

`rand(\$F)`

`rand(\$F * 10)`

`rand(\$F * 100)`

• If you need random values that vary across geometry, use a variable like `\$PT` (the current point number) as the seed. If the value needs to be random across the geometry and across time, combine `\$PT` and `\$F`.

```  rand(\$PT / \$F)
```

## Random number from X to Y

The rand(seed) function returns a random number from 0 to 1. Use the fit01(value, min, max) function to map the random value to a different range. For example, use `fit01(rand(\$F), -10, -10)` for a random number from -10 to 10.

(This is the same as `rand(\$F)*20 - 10` but it saves you from having to do the calculation necessary to work out what to multiply and subtract to get the desired range.)

## Use modulus to cycle expression values

The modulus operator, a % b , returns the remainder after dividing a by b.

This is very useful in expressions, because no matter how big a gets, the result will keep cycling from 0 to b-1. For example, `\$F % 120` is a ramp from 0 to 119 which repeats at frame 120, 240, 360, and so on.

The modulus operator works on any real number, not just integers. Therefore, the value returned might not be what you expect. For example: `3.1415 % 1` returns `0.1415`, and `34.999 % 5` returns `4.999`.

## Use sin to smoothly cycle between two values

Use an expression like sin(\$F * 10) in an object’s translate-X parameter to animate it moving smoothly back and forth.

Take the absolute (always positive) value of the expression, abs(sin(\$F * 10)), in an object’s translate-Y parameter to make it bounce up and down, reversing smoothly at the top and sharply at the bottom.

To make the bounce decay over time, create a spare parameter to hold the decay rate. Change the bounce expression to multiply by the decay parameter: `(abs(sin(\$F * 10)) * ch("./decay")`. Then, edit the curve of the decay parameter to go from 1 to 0 over time.

## Grab the value of another parameter

Use the `ch("pathname")` function to grab the value of another parameter.

For example, to have a Tube SOP change its height based on the translation of an object named logo, set the tube’s Height parameter to the expression `ch("/obj/logo/ty")`.

To create `ch()` references easily, press on the source parameter and choose Copy Parameter, then press on the target parameter and choose Paste Copied References.

You can use the channel value within an arithmetic expression, for example `ch("/obj/\$OS/spare1") + ch("/obj/\$OS/tx") + 2` takes the value of the channel \$OS/spare1 and adds the X value of that point plus two.

The `chf()` function is the same as ch() function, but you can specify the frame at which to sample the value of the named parameter. For example, `chf("/obj/logo/ty", 14)` grabs the value of the logo’s translate-Y at frame 14. Use `\$F` to offset from the current frame, for example `chf("/obj/logo/ty", \$F + 14)` grabs the value 14 frames in the future.

The chs() function returns the value as a string. This is also useful for checkbox parameters because it returns “on” or “off” instead of float values.

## Get the nodes connected to the current node

You can get the path of the node connected to a node’s input with the opinput(operator_path, input_index) function. You can use this to automate path references in nodes. For example, if you want to get the number of incoming points from the node connected to the current node’s first input, use:

```npoints( "../" + opinput(".", 0) )
```

## Waves

The following expression examples were created by using a Grid op set to 1 row by 180 columns, and Connectivity set to Rows. To this, a Point op was appended. To use these as a segment expression, use the same expression in a channel, and replace the position variable (\$PT, \$TX or \$BBZ) with \$T.

### Sine and cosine

The sine (and cosine) function are extremely versatile for the creation of all kinds of shapes. The basic sine function can be used to transform a line or surface on the XZ plane into an oscillating wave.

The general form for a geometric sine wave is:

 Position Y `sin ( \$TX * frequency ) * amplitude + offset`

For wave motion, you could use this segment expression:

 Position Y `sin ( \$T * frequency ) * amplitude + offset`

Where:

 `\$TX` The basis for the wave: to animate the geometry of the wave, this could be set instead to (\$TX + \$F). frequency Controls the number of waves. You could set this to the bounding box position, \$BBX, to make the waves more frequent towards the end of the line. amplitude Controls the height of waves. You could set this to the bounding box position, \$BBX, to flatten the waves toward the end of the line, or the current frame, \$F, to make the waves larger as the animation progresses. s offset Translates the waves.

### Ripples

To get ripples radiating from a center, base the sine function on the distance of the point to the center of the surface:

 Position Y `sin(sqrt((\$BBX-0.5)^2+(\$BBZ-0.5)^2)*1080)`

To animate this, add a time-based variable to the expression:

`sin(sqrt((\$BBX-0.5)^2+(\$BBZ-0.5)^2)*720+\$F*4)`

### Arcs

You can make Arcs, Circles, Ellipses and Spirals by modifying a point’s position in two axes using a sine and a cosine function:

 Position X `cos (\$PT * arcangle) * radiusX + offsetX` Position Y `sin (\$PT * arcangle) * radiusY + offsetY`

or

 Position X `cos (\$T * arcangle) * radiusX + offsetX` Position Y `sin (\$T * arcangle) * radiusY + offsetY`

Where:

• The angle subtended by this expression equals arcangle * total number of points.

• radiusX and radiusY are the radius of the circle. If differing, then an ellipse is generated. If set to a variable such as `\$PTthen` a spiral may be generated. offsetX and offsetY translate the arc.

### Circle

images/xCircle.jpg

 Position X `cos (\$PT*2) pos y = sin (\$PT*2)`

This expression is useful as a segment expression when you want an object to go in the path of a circle and maintain the same orientation of the object (if you use a rotation channel, the orientation will rotate as well).

 Position X `cos (\$T * 180) ty = sin (\$T * 180)`

### Elliptical arc

 Position X `cos (\$PT) * 2 pos y = sin (\$PT) * 0.7`

Change values of the multiplier (2 and 0.7 in the example) to change the aspect ratio of the arc.

### Logarithmic Spiral

This creates a logarithmic spiral, reminiscent of nautilus shells.

 Position X `cos (\$PT * 2) * \$PT / 200 - 0.2` Position Y `sin (\$PT * 2) * \$PT / 200 + 0.2`

### 3D Spiral

The height of the spiral versus the spiral size can be controlled by the Position in Z.

 Position X `cos (\$PT * 5) * \$PT / 500` Position Y `sin (\$PT * 5) * \$PT / 500` Position Z `\$PT / 200`

### Randomize

 Position Y `\$TY + rand (\$PT) * 0.2`

### Clamping

 Position Y `clamp ( (sin(\$TX * 1080) *0.3), -0.1, 0.28)`

clamp ensures a value stays in a certain range. For example, clamp(\$TX, minvalue, maxvalue) clamps the x position to be between minvalue and maxvalue. Step

 Position Y `int (\$TX * 10) * 0.1`

General form:

 Position Y `int (\$TX * frequency) * amplitude`

### Square wave

 Position Y `int (\$TX * 10) % 2 * 0.3`

General form:

 Position Y `int (\$TX * frequency) % 2 * amplitude`

### Sawtooth wave

 Position Y `\$TX % 0.15`

General form:

 Position Y `\$TX % frequency * amplitude`

### Triangular wave

 Position Y `abs ( \$BBX * 5 % 1 - 0.5 )`

General form:

 Position Y `abs ( \$BBX * frequency % amplitude - .5 * amplitude )`

### Stepping triangular wave

 Position Y `abs(int(\$BBX*8) % 12 - 3 )* 0.2`

General form:

 Position Y `abs(int(\$BBX * frequency) % step-0.5*step)*amplitude`

## Deformations

You can use a Point SOP referencing a spare parameter to shear, taper, squash, bend, and apply other deformations to geometry.

You can also achieve these effects with the Twist.

### Shear

Shears geometry in any direction, X, Y, or Z. To shear about the bottom of an object in the X direction, first add a Point sop and set it’s display flag, then add the channel spare1 (use Edit > Add User Defined Channels...). Then in the Point sop, change the Translate X to:

 Position X `\$TX + \$BBY * (ch("spare1"))`

You can animate the amount of shearing with the spare parameter.

### Taper

Taper is similar to shear; you can taper in any direction. To taper in the X direction, use a Point op, and add a spare channel. Change pos x to any of the following:

 Position X `\$TX * ( ch("spare1") ^ \$BBY ) Pos X = \$TX * ( 1 / ch("spare1") ^ \$BBY )` Position Y `\$TX * ( 1 - (\$BBY * ch("spare1") -1 )) `

You can animate the amount of shearing with the spare parameter. For this expression, the spare parameter must be greater than 0 or an error will occur.

### Squash and Stretch

Squash and stretch is a traditional animation technique where if an object scales up in one direction (stretch) there will be a corresponding scale down in the other direction.

A simple way of doing squash and stretch is with a Transform sop and using only the scaling channels: sx, sy, and sz. Use the sy channel to scale the object using the any function ( ease(), bezier(), etc. ). Then in the sx and sz channel segment use:

 Scale X `1/sqrt( ch("sy") )` Scale Z `1/sqrt( ch("sy") )`

Now when you animate the Scale Y (sy) channel, the relative volume of the object is preserved.

### Bulge and Pinch

To get a squash and stretch where the only the middle of the object is affected (so it bulges or pinches), use a Point op with spare1 channel as your controlling channel. Change pos x and pos z to:

 Position X `\$TX + sin(\$BBY*180)*(1/(ch("spare1"))-1)*(\$BBX-0.5)` Position Z `\$TZ + sin(\$BBY*180)*(1/(ch("spare1"))-1)*(\$BBZ-0.5)`

To get a smooth bulge/pinch, precede the Point op with a Refine op, and increase the U and V Divisions over a range of 0 - 1. You can also use a Twist or Lattice op to get bulging effects.

### Twist

To twist an object around its center, append a Point op and create a spare channel. Change the pos x and pos z to:

 Position X `(\$TX-\$CEX) * cos( ch("spare1") * (\$BBY-0.5)) - (\$TZ-\$CEZ) * sin( ch("spare1") *(\$BBY-0.5)) + \$CEX` Position Z `(\$TX-\$CEX) * sin( ch("spare1") * (\$BBY-0.5)) + (\$TZ-\$CEZ) * cos( ch("spare1") *(\$BBY-0.5)) + \$CEZ`

For greater control, precede the Point op with a Refine op, and increase the U and V Divisions over a range of 0 - 1. You can also use a Twist or Lattice op to get twist effects.

### Bend

To bend an object, use a Point sop and create a spare channel. Change the pos x and pos z to:

 Position X `\$TX * cos(\$BBY*ch("spare1")) - \$TY * sin(\$BBY*ch("spare1"))` Position Y `\$TX * sin(\$BBY*ch("spare1")) + \$TY * cos(\$BBY*ch("spare1"))`

As with twist, you may want finer control by preceding the Point op with a Refine op, and increase the U and V Divisions over a range of 0 - 1. You can also use a Twist or Lattice op to get bend effects.

## Repeat animation curves

Use the repeat function to copy or repeat repetitive motion. The basic form for the repeat function is:

`repeat (start_keyframe, end_keyframe)`

If you have keyframes at 0, 22, and 36, and you want to repeat the curve from 0 to 36, you select the segment from frames 36- , and enter:

`cycle(0,36)`

This works within a channel, without referencing another channel.

Your repeat range must be outside the range of the currently selected segment. For example, if you have keyframes at frames 0, 22, and 36, you cannot select the segment from 0-22 and assign a `cycle()` function with values within the range of 0-22, because it would be trying to repeat values of itself that have not yet been determined.

## Iso-surface node equations

The Iso Surface SOP creates surfaces from equations.

You can set up the IsoSurface SOP with an expression having three dimensions, each taking a real value. The IsoSurface SOP can then create a surface from every point inside a bounding box where the expression equals 0.

For example, the default expression

`\$X*\$X + \$Y*\$Y + \$Z*\$Z - 1`

...plots a sphere (the expression is less than 0 inside a unit sphere, greater than 0 outside a unit sphere, and equal to 0 at the surface of a unit sphere).

This may seem like a difficult way to define a sphere, but combined with the rich array of functions available to expressions, it has the potential to create complex and strange surfaces. For example, noise(\$X, \$Y, \$Z) plots a random jumble of surfaces.

### Fireball

Here is an expression to define a flaming star:

 Implicit function `noise((\$X*\$X + \$Y*\$Y + \$Z*\$Z)^.5/3, atan2(\$Y,\$X)/8, atan2(\$Z,\$Y)/8) + (1 - (\$X*\$X + \$Y*\$Y + \$Z*\$Z)^.5/5)` Minimum bounds -10 -10 -10 Maximum bounds 10 10 10 Divisions 40 40 40

In this equation, the rectangular (Cartesian) coordinate system has been moved to a spherical (polar) coordinate system. The star diminishes as the distance from the center increases.

• Use \$F (current frame) as a variable in an equation to make it animate over time.

• The if function is perfectly valid in IsoSurface SOP equations, and you can use it to construct geometry piecewise.