LittleDraw: Drawing from inside blocks

jfriedmanjfriedman Fabric for Houdini Posts: 81 ✭✭
edited September 2016 in 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.


Sign In or Register to comment.