Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!


First AnniversaryName Dropper10 CommentsFirst Comment

jfriedman ✭✭


Last Active
Fabric for Houdini
  • LittleDraw: Drawing from inside blocks

    Hello All,

    I've been getting my hands dirty with blocks and they're clearly a huge step forward for Canvas. I've also been teaching others how to use them and they're quite a natural way of doing things. There is something I've felt I've been missing, which is being able to do debug drawing from inside the blocks. So I've undertaken a little project (less than a day so far) to try to correct this. I say it's less than a day not to brag, but to say that I'm not married to anything here and it's submitted as much as an example of a possible workflow/technique as it is as an actual implementation.

    The result is here, a system called LittleDraw:

    What we have here is a graph with a modified copy of the "deformInPlace" compound. Inside the compound are some nodes getting the cross product of the normal and another such vector, (not a particularly interesting example), but then ordering those vectors drawn from inside the block.

    Inside the block, the user sees a new out port of type, LittleDrawJob. A little draw job is a way of ordering something small, like a single vector or color, to be drawn. Users can just wire these up ad-hoc as needed, to draw the intermediate data in their processes which ICE has shown us is invaluable in debugging and learning.

    LittleDrawJob types:

    LittleDrawVector: This draws a vector. You have the option of drawing it normalized to a unit vector or not.

    LittleDrawPoints: This also draws Vec3 data, but as positions. These are drawn as points in space, optionally with trails pointing back to the context point (the point the block was working on).

    LittleDrawColor: Ther are three nodes here that can draw either colors, vectors or scalars as colored points on the context point. The vectors can be "normalized" meaning they are remapped from [-1, 1] to [0, 1] (better to see things like normals). The scalars have an option for showing negative values inverted.

    LittleDrawAxes: Draws axes from either XFOs or Mat44s. Can be drawn with trails to the context point (like ICE).

    Soon: LittleDrawString, to draw text (thanks for the code @malbrecht). This way you can get numeric display of your intermediate data.

    Other little features of LittleDrawJobs:

    Each LittleDrawJob has a "other" port where you can plug in another LittleDrawJob. These can also be daisy chained.

    Each LittleDrawJob has a color port as well, which can be connected to some other logic to get more information into the drawing. For example, draw a vector, with its color controlled by some other piece of data.

    Making your own types of LittleDrawJobs:

    This is pretty straightfoward, the interface for these is really simple. Other extensions can add new types of LittleDrawJobs.

    Making a block node able to do LittleDrawJobs:

    This is pretty simple. If your block node is operating on an array of some size, you'll want an array of LittleDrawJobs of the same size. If nothing is plugged into the block's port, it'll be an array of nulls, which should be rather small. After that there are some helper functions to create lines and points (the only two types created right now) with vertex colors and draw them.


    The overhead on this when not drawing is pretty low, it's just filling an array with nulls, and then later iterating that to generate (no) geometry. It should be further possible to optimize this so that if the array is filled with only nulls, it can know that before looping through it again. I haven't timed anything carefully but I don't think it's very expensive to have this around when it's drawing nothing. Also you could have a switch on the outside of the block that disables them entirely and never pulls that port, never fills any array, so if you had that the overhead of having this without drawing should be basically nothing and conceivably something the compiler could even delete.

    When drawing it's definitely not optimized, and there is a lot of room for improvement. Right now it just loops through all the jobs each one adds their lines to the Lines and Points objects one at a time, but it seems to be just fine for debug drawing, and there's definitely room to optimize it later. It also feels faster than ICE drawing, just as a point of reference. It draws all the lines to one Lines object, so the drawing doesn't bog down the viewport with huge numbers of tiny drawings, like drawing axes instances sometimes does.

    Inline drawing / RTR2 / What may come

    The drawing itself is a pretty insignificant part of this, since this system creates a Lines and Points object to draw and then gives them to standard drawing functions. The other drawing systems, if they can draw those types, should be able to use this system as well.

    What I want out of this:

    I would like to have something in all the applicable block presets that does this job. I'm not married to this particular system, this is more submitted for inspiration and for anyone who might find it useful. (Not that I'd rule out this system being used in the built in Fabric Engine nodes).

    I would, however, argue that this job is important and something should do it. Being able to quickly and easily draw the intermediate stages of calculations that might go on in these blocks is very important in my opinion.

    Blocks are amazing:

    Are blocks amazing or what? Being able to control not just the contents of them but the context in which they operate in is so ridiculously powerful that this kind of thing, which was a very basic feature in ICE, isn't even hard to add. I think blocks are going to be huge.

  • Re: Dart Throw

    I've (finally) updated the extension to the newer version. The new version is about ~4x faster, and has point relaxing in it too. This was original based on Eric Mootz's, but has been modified to play better with different sized spheres. There are also some new functions for controling the size of points with a mesh scalar attribute, and some other things.


  • SimpLSystem - L-System collaborative project

    Hello All,

    I've made an L-system extension, called SimpLSystem. I was thinking about what I wanted to do with it, and I've decided I'd like to use it as the starting point to try to start a community project. So I changed the name to SimpLSystem (it was originally JFLSystem), cleaned up a bit, and starting writing this post.

    This project doesn't have any well defined goals at this point. As such, I'd like to invite anyone to discuss directions they'd like to go with it here. If you'd rather just do whatever you'd like with it on your own, please feel free to do that as well.

    This is a personal project not affiliated with Psyop, but I'd like to thank them anyway for being so supportive of this kind of thing.

    Background on L-systems:

    The repo contains the extension, and two sample canvas files. The canvas files contain the examples on Wikipedia. Theres one that implements them more or less straight ("wikipedia_examples_standard.canvas"), and one that has more creative interpretations of the same L-systems ("wikipedia_examples_interpreted.canvas"). All the pictures here are from the latter one.

    An interpretation of a Koch curve L-system

    About the project

    As far as I'm concerned the project doesn't really have any defined goals yet, just that I would like it to collaborative and in the community.

    A few possibilities for directions this could be taken: The most obvious one would probably be to develop applications of L-systems, such as dynamically creating plant geometry. Another direction would be just to generate arbitrary geometry - it currently just makes a Vec3[] for points, and Xfo[] for leaves. Another direction might be trying to take advantage of the new feature of evaluating DFG graphs in KL, to make the behavior of the evolving system programmable in interesting ways.

    An interpretation of a Pythagoras tree L-system

    Tech overview

    The system consists of two parts right now, the L-system, and the interpreter. The L-system defines and generates the strings, and the interpreter interprets the symbols in the resulting string and performs the walk ("walk the turtle").

    The only thing the interpreter can currently do is "walkTheTurtle()", which refers to turtle graphics (see the Wikipedia article). The system continually updates a Mat44 internally while interpreting string to keep the transform updated, and drops points along the way.

    That's it for the moment. Drawing Lines while it goes is (at least one) obvious next step.

    Technical details

    SimpLSystem - The Iterative grammar part of the L-system.

    • struct SimpLRule Defines an L-system rule, such as "A"->"AB".
    • object SimpLSystem The L-system object, initialized from an array of SimpLRules and a start string (axiom).
    • SimpLSystem.evolve(Size iterations) evolves the system iteratively, expanding the string formed.

    SimpLInterpreter - For interpreting the L-system into 3D space:

    • object SimpLInterpreter
    • SimpLInterpreter.addSymbol!(String symbol, Xfo transform, Integer leaf) Adds a symbol to the interpreter, and a transform to apply when encountering that symbol. Using this all the non-branching symbols such as translate forward, turn, roll, pitch and yaw in the usual ways, plus more.
    • SimpLInterpreter.addBranchSymbol(...) Adds two symbols, one to branch the tree (push a transform onto the stack), and one to unbranch the tree (pop a transform from the stack). Arbitrary transforms can be added on branching and unbranching as well.
    • SimpLInterpreter.walkTheTurtle(...) Walks down the string, applying the interpretations as it goes, generating an array of positions it visited along the way.

    There's also a compound for "add standard symbols", which adds F as move forward, +- for turn left and right, &^ for pitch up an down, \^ for roll left and right, | for turn around, and [] for push/branch and pop/unbranch.

    Non-standard things this particular L-system does:

    • SimpLSystem.partialEvolve!(Scalar iterations) evolves the system with partial iterations. 8.4 iterations would mean that the 9th iteration is only done on the first 40% of the string, and the remaining 60% of the original string left alone. This can make interesting half-formed L-systems, is helpful in debugging, and can be used to animate the system's construction.
    • Every symbol can have a full Xfo applied to it, not just an angle or walk distance. For example, you could apply a scaling every time the tree branches, or rotate slightly in one direction every time you walk forward.