Directions From Growth

comments 15
Free Tutorials

When dealing with growth solvers, often you not only need the growth itself, but a direction vector. For exapmple to copy feathers onto a surface, or other directed object, like knitting loops. In this tutorial Manuel explains how to calculate direction vectors on the surface by using the gradient.

The gradient is the vector that points in the direction of the steepest ascent of a function. I’s a concept of differential geometry.
Fortunately we don’t have to compute the gradient ourselves, but we can use the inbuilt “Polyframe” node, that is capable of calculating the gradient of an attribute.

Download Geometry

Download Project File

Liked it? Take a second to support Manuel on Patreon!
Become a patron at Patreon!


  1. Thank you sir ! It’s really great!

    Can I copy a line at each point to make this line perfectly fit the surface of the model ?

  2. Alexander

    Thank you, you’re cool!

    I can not understand why two cross-products? Why did not you use the normal for the second vector in the matrix?

    • Because the normal is not guaranteed to be orthogonal to the gradient vector. The double cross product makes sure that the vectors are orthogonal.

  3. Thank you so much for your wonderful tutorials, beautiful stuff. 🙂

  4. How could you control the speed of the growth?
    I have wondered this about speeding up and slowing down the solver node. I know you could use more substeps to speed it up but you can’t go below 1 if it needs to be slower. Something that could be added to the wrangle?

    • Your best bet is to use the accumulated infection value to do the growth as a second step after the solver. So let the solver finish for all the points. Then use a second VOP to remap the infection value to form an attribute that controls visibility.

    • The render setup will be put on patreon the week after FMX

  5. With the “foreach( int pnt; neighbours)”. For the current run time variable “pnt”, is it a global variable for the point number? I apologize but I don’t understand how it knows what point number it is.

    (I’m sure this is derp obvious but I am currently chewing on foreach loops and trying to get them down pat)

  6. Very cool! However, when I try to load my own geometry into the file node which is an OBJ of similar size / complexity, nothing seems to happen. Is there something to be aware of in terms of preparing external geo before loading?

  7. Viduttam

    Hi Manuel, thanks a lot for this one. It has literally cleared out so many of my concepts. One quick question is that I want to use this technique on deforming geometry. I’m using a point deform to ensure that the point numbers remain consistent across the deformation before feeding it to the SOP solver. In the SOP Solver, if I just use the pointwrangle on the previous frame, the growth works however as I’m not taking into account the next frame, the geo is static as the growth progresses. I threw in a attrib transfer in the SOP solver and I’m transfering the infect and neighbours attributes over. Now the geo is deforming alongwith the groth. However, the growth appears to be stuck in world space to the original point poitions of the source points. I know I’m missing something. I’d be really grateful for any assitance. Once again thanks a lot for your awesome videos!

  8. Within the Solver, VEX is not accepting: @infect += accum/len(neighbours); Error reads; Read-Only expression on left side of assign.
    Using H Apprentice 16.5.496 on PC

    • I’ve noticed that sometimes when dividing float values with integer values you’ll run into this issue. Try to write it this way to make the result of the “len(neighbours)” to be interpreted as a float.

      @infect += accum / float(len(neighbours));

    • Thanks for letting us know and sorry for the inconvenience. Fixed the link. Cheers, Mo

Leave a Reply