drawing jit.path (using spline interpolation) output with jsui

soundyi's icon

Hi there, I try to create a "base point" editor for jit.path with jsui, that is capable of visualizing the spline interpolated path.

According to the jit.path docs, we get Hermite splines and a single tangent for each point, when calculating the handles.

Looking at the Mgraphics docs I see the curve_to method that paints a cubic Bezier spline (or adds its to the path) and needs 2 control points.

Is there a way to bridge or translate the Hermit spline tangent into the 2 cubic Bezier spline control points ... essentially painting the spline interpolated jit.path within jsui?

Googleing for Hermite spline to cubic Bezier spline has made me blind ;-).

Rob Ramirez's icon

you can use the jit.path outputeval message to output a matrix of evaluated path values, which you can draw with Mgraphics. you will have to handle the transformations from GL world to Mgraphics canvas. You could also send the point values matrix to this Mgraphics for user interaction, and then send those edited values back to the path using the edit message. A rudimentary starting point pasted below.

Max Patch
Copy patch and select New From Clipboard in Max.

soundyi's icon

Thanks @Rob ... really appreciate your "code starter", but sadly I am still on Max 8, could you please convert the v8ui into a jsui?

As there is only the compressed Max patcher code I have (or at least I don't know how) no means to extract the js code by myself.

Regarding "transformations from GL world to Mgraphics canvas" : I think the js code will shed some light on it, but what is the key for the "world space" transformation - is it only the difference of the origin location?

In the Mgraphics quick start guide there is a section "The mgraphics Coordinate Systems" which makes it clear that the origin [0,0] is in the left top corner and as far as I remember OpenGL world is always screen centered, so the origin of [0, 0, 0] is always in the center of the visible area.

In the Max 8 The jsui Object I saw usage of 2 functions of the sketch object : screentoworld and worldtoscreen. Can I use these for the transformation?

Are there other aspects of world space difference I have to be aware of - besides that patching & presentation rectangle should be the same thing?

Rob Ramirez's icon

here ya go, probably just need to convert a few let to var:

mgraphics.init();
mgraphics.autofill = 0;
mgraphics.relative_coords = 0;

let matrix = null;
function paint()
{
	if(matrix) {
		var viewsize = mgraphics.size;
		var width = viewsize[0];
		var height = viewsize[1];
	    
		var bgcolor = this.patcher.bgcolor;
	        var needlecolor = this.patcher.color;
	
		mgraphics.set_source_rgba(bgcolor);
		mgraphics.rectangle(0, 0, width, height);
		mgraphics.fill();
		
		mgraphics.set_source_rgba(needlecolor);
		mgraphics.set_line_width(1);
		
		let c = matrix.getcell(0);
		mgraphics.move_to(transform(c, width, height));
		for(let i = 0; i < matrix.dim; i++) {
			let c = matrix.getcell(i);
			mgraphics.line_to(transform(c, width, height));
		}
		mgraphics.stroke();
	}
}

function transform(p, w, h)
{
	let x = (p[0] / 6.28) * w;
	let y = (1-p[1]) * h * .5;
	return [x, y];
}

function jit_matrix(s)
{
	matrix = new JitterMatrix(s);
	mgraphics.redraw();
}

soundyi's icon

Thanks @Rob ... but there seems to be more v8 goodness that I have to recode for the ancient jsui ;-).

I get an errror message in the console : mgraphics: not enough arguments for set_source_rgba.

I guess this related to moderns JavaScript destructing syntax ... implicit unpack goodness that come with v8 ... I will figure it out.

Joshua Kit Clayton's icon

This has to do with some legacy behavior with patcher attributes, and how historically they were defined as functions for setting the values (before attributes even existed in max).

For jsui you will need to use the following approach (which will also work in v8)

var bgcolor = this.patcher.getattr("bgcolor");
var needlecolor = this.patcher.getattr("color");	
soundyi's icon

Thanks @Joshua ... these things are hard to find without a "build time compiler" - as nice as JavaScript is, as hard is the bug hunting sometimes ;-).