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.

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

To simulate drooping leaves:

- 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]))

- Then set
`tiltU`and`bendMagU`expressions to:bendMagU()

- Set
`tiltU`and`bendMagV`to:bendMagV()

Note: Be sure the Control using is set to Attribute.

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:

- 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()))

- 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 `tiltU`and `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.