Draw in Space like Google Tilt Brush?

Possible with built-in nodes, at least in a basic way?

I imagine:

  1. Draw to the viewer with (for example) the mouse on the 2D plane like posted here
  2. Rotate the scene with a draggable camera (and/or animate rotation of a perspective camera, like here)
  3. Then (most importantly), draw to the current viewer 2D plane, rotate camera, keep drawing, rotate, etc.

(Pretty sure @George_Toledo pursued this concept with some super interesting 3D sculpting stuff in QC (and for other devs?) as well. I suppose this is related to some of the VR/AR tools coming down the road, too.)

@cwright made an awesome qtz called draw in space that does this, in response to this post at kineme.net. This was achieved with the following javascript:

var result = new Object();

function matrixMult(matrix, point)
	var temp = new Array();
	temp[0] = matrix[0][0] * point[0] + matrix[0][1] * point[1] + matrix[0][2] * point[2];
	temp[1] = matrix[1][0] * point[0] + matrix[1][1] * point[1] + matrix[1][2] * point[2];
	temp[2] = matrix[2][0] * point[0] + matrix[2][1] * point[1] + matrix[2][2] * point[2];
	point[0] = temp[0];
	point[1] = temp[1];
	point[2] = temp[2];

function transformPoint(point, xTheta, yTheta, zTheta)
	sinX = Math.sin(xTheta);
	cosX = Math.cos(xTheta);
	sinY = Math.sin(yTheta);
	cosY = Math.cos(yTheta);
	sinZ = Math.sin(zTheta);
	cosZ = Math.cos(zTheta);

	// todo:  do the math, and get this right
	//[[cosY*cosZ, cosX*-sinZ, sinY],
	//[sinX*sinY*cosZ+cosX*sinZ, sinX*sinY*-sinZ+cosX*cosZ, -sinX*cosY],
	//[cosX*-sinY*cosZ+sinX*sinZ, cosX*sinY*sinZ+sinX*cosZ, cosX*cosY]];
	var matrix;

	matrix =
	matrixMult(matrix, point);
	matrix =
	matrixMult(matrix, point);
	matrix = 
	matrixMult(matrix, point);

function (__structure points) main (__number inputX, __number inputY, __boolean draw, __boolean reset, __number xTheta, __number yTheta, __number zTheta)
	if(reset || result.points == undefined)
		result.points = new Array;
		var point = new Array;
		point[0] = inputX;
		point[1] = inputY;
		point[2] = 0;
		transformPoint(point, xTheta*Math.PI/180, yTheta*Math.PI/180, zTheta*Math.PI/180);
	return result;

Progress, still an unsolved problem: the Draggable Camera stays active all the time, is there a way to disable it while drawing with the mouse?

In this comp I can draw to the 2D viewer plane, then I can drag the camera view, then I can draw again, but when I switch back to the camera again it jumps to the current transform value, because the camera is always active.

draw_in_space.vuo (10.2 KB)

Instead of spacebar, could you use one of the modifier keys (Command, Option, Control, Shift) on `Make Draggable Camera’? That would simplify things.

Yep, that helps. Thanks, Jaymie. Still issues, but I think they can be solved.

Ok, here’s the first bit of success, working except for one issue: when rendering, any drawn line disappears the moment the mouse button is released. Closing/reopening the viewer might fix it, or closing/reopening the comp usually does get it to work. Also, it takes a good bit of time for the viewer to open after hitting render.

Left mouse button draws, command button allows rotating the camera, right button to clear.

DrawInSpace0.vuo (11.2 KB)

Link to DrawInSpace0 above is updated.

Seems this comp should work fine, but the problem persists: when the viewer launches, it’s 50/50 whether drawn lines will stay on the screen like they are supposed to. Show events looks good to me. I don’t know what I can do to troubleshoot this. Is this a bug?

Besides this problem, which I realize now really threw me off when building it, I am super happy with this comp, so much cool Vuo potential!

Looks like there’s a race between the Left Mouse Button : Released and Left Button to Draw : Drag Ended to reach the Enqueue node. The triggers fire at nearly the same time. When Drag Ended wins the race, the line is drawn as expected. When Released wins the race, the line gets cleared before it can be drawn.

Hmm, it seems you’re saying all I’d need to do is replace Released with Drag Ended to clear the Enqueue, but that’s not working…

I was beginning to suspect something like that. I’ll see if I can figure out what to do. Thank you!

Still fresh but looking good so far – looks like using a Spin Off Event from Drag Ended gets the events to land in the right order. Great!

DrawInSpace_fixed.vuo (11 KB)

One more fix to “DrawInSpace_fixed.vuo”, updated. Thanks again, @jstrecker!

1 Like

This is pretty cool. @jersmi! Thanks for sharing. Surprising how few patches, a testament to Vuo’s compositional power.  

1 Like

Thanks! I should post to the composition gallery…

Could anyone help translate these formulas into Vuo? Parallel Curves -- from Wolfram MathWorld

This is the start of something to get Draw in Space working to draw more artistically shaped lines using triangle strips, “calligraphic” strokes etc. The attached comp stroke gets the current and next points and uses Normalize Point * difference to generate the stroke width. (Test comp uses Make Random List together with Make Points along Spline to generate arbitrary curve points (Set Seed is published to change up the test curve). To see the filled stroke you’ll need bss’s `Make Triangle Strip Object’ node from the Node Gallery.)

Other terms: “curve offset”, “parallel curve” on Wikipedia, “equidistant curve” on math overflow.com). This image from mathoverflow.com is like tools in Adobe Illustrator for stroke offset, with rounded cap (caps would be awesome, of course…):

offset stroke with rounded caps

Another CG term that makes sense is “skeletal strokes”, a technical term from CG world that goes back decades (related to beziér curves, etc.), which also suggests shaping the geometry in combination with texturing (like vector graphics software – brush strokes either from vector shapes or textures). Amounts to using an arbitrary curve as a skeleton around which one generates interesting offsets. Indicated by the quality/quantity of publications on these concepts, the good news is that the problem was solved long ago.

The current Draw in Space uses line strips with points to compensate for the gaps in the lines. Any way to have more expressive drawing needs to encompass the concepts above. So the plan has been to use Triangle Strips (and grateful to @BodySoulSpirit for submitting that node).

(Another point of reference, an early interactive web art piece – I still remember discovering Golan Levin’s piece, Yellowtail, for the first time, with its moving calligraphic lines, still lovely. Now you can buy it as an iPhone app for $0.99 USD).  

offsetCurve-test-UnitNormal.vuo (19.7 KB)

Another keyword term, on the 3D side: spline mesh, tools for extrusion, one an article here for “procedural racetracks”: http://blog.meltinglogic.com/2013/12/how-to-generate-procedural-racetracks/

Edit: In order to generate a 2D parallel curve, looks like I’ll first need to generate splines and control points mathematically, i.e., without the help of Make Points along Spline, then generate the other points for the parallel curve. Looking at these:

Ok, progress. Babe in the woods, like most things GL related, playing catch up with the math to do anything cool. I do think what I have here is becoming a nice next chapter for the “draw in space” composition – customized meshes. Of course GL artists have been all over custom meshes for a while, a lot of cool stuff out there.

Questions about shading: I am using the bss triangle strip and triangle fan nodes from the node library for this. Super grateful for those, but they are not set up for texturing beyond unlit color. I am wondering a couple things: one, could I simply edit @BodySoulSpirit’s node in a text editor to add the appropriate stuff to support texture coordinates, then save it as a new node? If so, where could I find the code to insert (for a wannabe coder willing to try)?

And two, even if this is possible, is it going to be a total pain to try and map brush stroke textures to the triangle strip meshes, especially ones being drawn with the mouse, i.e., not pre-calculated to set and forget the texture mappings? Are there things I can do to help the cause?

Or maybe I just need to focus on manipulating the geometry for now…

Edit: one more q, are there any tools for inserting/forcing a shader (or lighting, anything) onto the mesh? Not having any luck, maybe I’m missing something.

Problems I need to solve at present:

  • Sharp curves – the folders at sharp corners are a known classic issue, I knew the math for this method would not solve it coming in, baby steps. Is there a 3D object tool in Vuo that can clean any of that up? (Wanted to try Union 3D Object but it is crashing the comp loader with the bss custom nodes).
  • Round “end caps” using triangle fans work, but it shows how the first and last points on the line where they connect need another point to make the transition from line to cap more seamless.

Working so far:

End cap issue:

Sharp curve issue:

Another example:


offsetCurve-test2.vuo (49.1 KB)

Problem – doesn’t work to turn the pictured section for “rounded caps” into a subcomp, no output, why? (I want to turn parts of the comp into subcomps so I can try/continue it in the Draw in Space comp.)

A section I tried to turn into a subcomp:

The subcomp (simplified trying to get it to work):


jersmi.makeParametricCirclePoints.vuo (4.8 KB)

How do you have the subcomposition hooked up in its parent composition? If I connect cables to both input ports, it seems to work…

I don’t know if it’s the look you’re going for, but a totally different approach would be to use Dilate Image or Cartoon Image to draw a thick rounded stroke. DilateDrawParallel.vuo (3.53 KB) CartoonDrawParallel.vuo (3.76 KB)

Thank you, @jstrecker! Pretty sure I did not fire an event to both ports – the why’s of events/ports can still confuse me, unfortunately.

I appreciate those comps using dilate and cartoon draw very much, cool to see those. That could spark a nice final approach, hmm. Of course there we’re talking about creating/shading pixels whereas I’ve been trying to (first) wrangle the geometry to be able to (eventually) apply transformations/effects to a triangle strip mesh (2D/3D twist/turn/bulge, etc.) using the Draw in Space approach. (Also the approach using an image “brush” + feedback as well.) All good stuff!  

The parabox nodes added a little flexibility to what you could do with a 2D thing like that, because it was possible to write to frag depth in a fine grained way so that the lines could cull against forward rendered objects, like 3D models or whatever. And you could distort the underlying grid with vertex shader, do some normal mapping effects, etc.