Archive and vegetation instancing expressions

Force primitives to point vertical

If you are grooming a field of grass without guides, and your ground plane is uneven or undulates, the grass will point in the direction of the surface normal by default. To get your grass blades to point vertically by default, you must change the orientation so that each blade points upward (or at least an approximation) using the following to expressions:

tiltU: (90 - acosd(dot(norm($dPdu),[0,1,0]))) / 90
tiltV: (90 - acosd(dot(norm($dPdv),[0,1,0]))) / 90
A combination of these expressions adjusts the tiltU (Tilt U) and tiltU (Tilt V) attributes, and accounts for any change between the iso-tangents and the up-vector. If you need more precision with your grass direction, see Grow in Exact Direction, below.
Note: You can also use the alignU, alignV and alignN expressions.

Always Droop Down

If you have a scene where you want to simulate leaves drooping, you can use the following procedure without guides.

To simulate drooping leaves:

  1. First, in the XGen Expression Editor, create two global expressions:
    float bendMagU  -acosd(dot(abs(norm($N)),[0,1,0]))/180*(dot(norm($dPdu),[0,1,0]))
    float bendMagV  -acosd(dot(abs(norm($N)),[0,1,0]))/180*(dot(norm($dPdv),[0,1,0]))
  2. Then set tiltU and bendMagU expressions to:
    bendMagU()
  3. Set tiltU and bendMagV to:
    bendMagV()
    Note: Be sure the Control using is set to Attribute.

Grow in Exact Direction

The Always Grow Vertical tip works well for grass, but it is not exact as it is constrained by tiltU and tiltV limitations, which mean you cannot use the expressions to push past the tangent plane. If you need more precision, for example, in a pine tree with needles pointing in a specific direction, including into the surface from which the needles are generated, try the following workflow:

To specify a precise direction:

  1. Create four global expressions:
    vector dir 
    $x = -0.0750; # -1.000, 1.000
    $y = 0.2550; # -1.000, 1.000
    $z = 0.1650; # -1.000, 1.000
    norm([$x, $y, $z])
    float   dotU  dot( norm($dPdu), dir() )
    float   dotV  dot( norm($dPdv), dir() )
    float   len   100.0 * (abs(dotU()) + abs(dotV()))
  2. Enter the following spline primitive attributes:
    tiltU  dotU() / len()
    tiltV  dotV() / len()
    tiltN  acosd( dot($N, dir()) )

This provides the direction, normalized, in the dir global expression. This can be a constant, as in this example, or it could be a painted normal map that you convert back into a proper normalized vector.

This procedure works because the global expression determines which direction the primitive should be rotated. If you change that to a small value and fill it with tiltUand tiltV expressions, you can use tiltN for the real rotation. This overcomes the tangent plane and creates the magnitude required for aligning the primitive with the direction vector. Without the global expressions, the direction is not guaranteed, only the magnitude of the rotation.