Using jit.submatrix in Javascript

Peter Castine's icon

I am trying to use the matrixcalc() method on a jit.submatrix inside a Javascript and it seems not to behave as I expect.

The goal of this little project is to take text and convert it into a texture for further use (rotation/translation/scaling) in OpenGL, all using procedural Javascript coding.

Here's the code in question

var matrix    = new JitterObject("jit.matrix"),
    render    = new JitterObject("jit.gl.render", matrix.name),
    text2d    = new JitterObject("jit.gl.text2d", matrix.name),
    findbounds    = new JitterObject("jit.findbounds"),
    submatrix    = new JitterObject("jit.submatrix");

// Prepare up OpenGL context (jit.gl.render and jit.matrix)
render.erase_color = [0, 0, 0, 1];
render.blend_enable = 1;
matrix.dim = [500, 28];

// Set up text (jit.gl.text2d)
text2d.color = [1, 1, 1, 1];
text2d.font("Chalkduster");
text2d.size(14);
text2d.position = render.screentoworld(0, 14);
text2d.text("Testing a text");

// Render the text
render.erase();
render.drawswap();
    // Let jit.findbounds do its stuff
findbounds.min = [.5, .5, .5, .5];
findbounds.max = [1, 1, 1, 1];
findbounds.matrixcalc(matrix);
// findbounds.boundmin and findbounds.boundmax now have the dimensions of the text

// Set up submatrix and process main matrix
submatrix.offset = [findbounds.boundmin[0], findbounds.boundmin[1]];
submatrix.dim    =  [findbounds.boundmax[0] - findbounds.boundmin[0],
            findbounds.boundmax[1] - indbounds.boundmin[1] ];
// Variables texMatrix and textureID are declared globally
texMatrix = new JitterObject("jit.matrix", 4, "char", submatrix.dim[0], submatrix.dim[1]);
submatrix.matrixcalc(matrix, texMatrix); // Is this working?
textureID = texMatrix.name + "Tex";
outlet(0, "render", "texture", textureID, "jit_matrix", texMatrix.name);

This takes some inspiration from Vanille Béchamel's example of measuring the start and end of rendered text inside Javascript. I am trying to extend that to create a submatrix that is just the area of the original matrix containing that text so that I can use it as a texture. The point of *that* exercise being that rendering text has been significantly slowing down my redraw rate in 3D scenes using several texts, and using textures in OpenGL land is supposed to give better performance.

Any suggestions?

Peter Castine's icon

PS: I noticed some work with jit.submatrix in Wes Smith's Lua announcement (now merely 4 years old), where he uses a frommatrix() method instead of matrixcalc(). I'm not sure if this is a Lua peculiarity or if this might be applicable to Javascripting.

I'm not finding any documentation on this, am I missing something obvious?

Wesley Smith's icon

Hi Peter,
jit.submatrix doesn't exist in JavaScript with Jitter. It was in the jit.gl.lua I released years ago as a beta as you astutely noted, but I had to do quite a bit of work to get that to happen. The situation for jit.submatrix is quite a bit different than what it is for the other 100+ jitter objects that are easily wrap-able in a scripting environment. In the official release of jit.gl.lua included in Max6, jit.submatrix is no more.

That said, it should be possible to make a jit.submatrix-like interface in JS or Lua using jit.matrix and the dst-/src-dim attributes, the only difference being that there would need to be a temp buffer for the submatrix, which is not such a terrible cost IMHO.

Peter Castine's icon

Thanks, Wes, even if that isn't quite the news I had hoped for.

I'm confident that I could build a jit.submatrix lookalike using the C API, having done something similar a few years ago for the BIX project. The Javascript API does not, I think, expose as much of the innards of Jitter data structures. But if you say it can be done, I'm game to take a stab at it.

Would you have the time to sketch out any more of the nitty-gritty involved? I know y'all're very busy with Max 6, but I would be grateful for any pointers. There's still lots of the Javascript/Jitter world where I don't my way around as well.

Best -- P.

Jesse's icon
Max Patch
Copy patch and select New From Clipboard in Max.

Here's something to get you started.

2737.js.submatrix.js
js
Peter Castine's icon

Thank you, Jesse! This is a big help.

Peter Castine's icon

Further unto… I've got the code now working, but the rendered text looks really awful. I'll attach examples of rendering directly to the screen ("Happiness") and by generating an intermediary matrix (as above -- "Dynamics). Rendering directly to screen looks much better but kills the redraw rate (a half-dozen texts can cut FPS from 33 to about half that).

For the record, I modified the code from my first posting as follows (everything up to the jit.findbounds methods is the same).

// Set up texture matrix and process main matrix
var d = [findbounds.boundmax[0], findbounds.boundmax[1]]
this.texMatrix = new JitterObject("jit.matrix", 4, "char", d[0], d[1]);
this.texMatrix.usesrcdim    = 1;
this.texMatrix.srcdimstart    = [findbounds.boundmin[0], findbounds.boundmin[1]];
this.texMatrix.srcdimend    = d;
this.texMatrix.frommatrix(matrix);
// The following works but is inefficient.
for(var i = 0; i < this.texMatrix.dim[0]; i++) for (var j = 0; j < this.texMatrix.dim[1]; j++) {
    var cell = this.texMatrix.getcell(i, j);
    cell[0] = (cell[1] > 50) ? 255 : cell[1];    // Arbitrary threshhold but works reasonably well for my purposes.
    this.texMatrix.setcell2d(i, j, cell);
    }
this.textureID = this.texMatrix.name + "Tex";
outlet(0, "render", "texture", this.textureID, "jit_matrix", this.texMatrix.name);

Any suggestions for how to get the text to render more sharply than this?

2785.TextRenderedinSoftware.png
png
Peter Castine's icon

OK, found a solution for this. Basically, I render the text to a matrix at double the font size I actually want it, then scale the texture back down by 50% when drawing to screen. Not sure why this trick should be necessary, but it works. And performance stays pretty hip.

To render smaller font sizes a factor of 4 works even better.

Memo Akten's icon

Hi all, I was looking to do something similar, but to copy to a subregion of a destination matrix as well. I posted separately, link below, but I thought I'd link here as well in case someone stumbles across this post looking for a similar answer.
https://cycling74.com/forums/copy-from-a-portion-of-matrix-to-another-portion-of-a-matrix-in-javascript/