Hi there,
I have already written the p5.3D library, for adding 3D text and images into WebGL, but currently this only works for Global Mode.
I’m not sure exactly what needs to be done, or how it needs to be reformatted, to make it work for Instance Mode. Has anyone else on here already converted a library to do this, or understands what is required?
1 Like
Right okay, but that means that in the instance mode, you’re calling the function and passing in the instance. In other libraries, the function can be called by the instance i.e.
var sketch = p5(function(p){p.setup(){...}; p.draw(){p.function(){}}})
as opposed to
var sketch = p5(function(p){p.setup(){...}; p.draw(){function(p){}}})
I understand how you achieved that, though thank you for explaining, my previous comment was just saying that I don’t want to have to pass in the sketch’s references, and I know there are other ways to do it from what I have seen other libraries use. It is these methods that I want to implement.
1 Like
- Yes, there is a way to do it. But not when using the keyword
new
.
- And guess what: p5js keeps a secret property when global mode is active → p5.instance.
- You can write your classes’ constructor to request a p5 object, but fallback to p5.instance in case your library’s user decided not to pass it.
- Something like this:
this.p = p instanceof p5 && p || p5.instance;
- I’ve refactored your classes Object3D & Word3D’s constructors to do just that:
"use strict";
class Object3D {
constructor({ p, depth=1, size=1, resolution=1,
bevelled=false, threshold=60 }) {
this.p = p instanceof p5 && p || p5.instance;
this.depth = +depth;
this.size = +size;
this.resX = this.resY = +resolution;
this.bevelled = bevelled;
this.threshold = +threshold;
this.edges = Int32Array.of(resolution, 0);
}
}
class Word3D extends Object3D {
constructor({ p, string='', depth, size, resolution, bevelled=true,
font='Times New Roman', style='bold' }) {
super({ p, depth, size, resolution, bevelled, threshold: 160 });
this.string = string.split('').join(String.fromCharCode(8202));
this.stringLength = string.length;
this.font = font;
this.style = style;
}
}
- Another trick is that some p5js classes secretly store the sketch’s p5 object!
- For example: class p5.Element has hidden property _pInst.
- While class p5.Vector has hidden property p5.
- Possibly, other p5js classes may do the same, but I didn’t fully research them all yet.
- Your class Canvas3D happens to require a p5.Graphics object as parameter canvas.
- The p5.Graphics is a subclass of p5.Element.
- Therefore, it’s got the hidden property p5.Element::_pInst too!
- So we can rewrite Canvas3D::constructor() to grab a p5 via a p5.Graphics object like this:
class Canvas3D extends Object3D {
constructor({ canvas, depth, size, resolution, bevelled }) {
super({ p: canvas._pInst, depth, size, resolution, bevelled });
this.canvas = canvas;
}
}
1 Like
- Now the solution you’re looking for: Not request the p5 object from your library’s user!
- You already know by now that directly instantiating classes using the keyword
new
can’t consistently get a sketch’s p5 object, unless they require it as their constructor()'s parameter.
- There are some workarounds though like p5.instance, p5.Element::pInst, p5.Vector::p5, etc.
- However, they’re all circumstantial and don’t work for all cases.
- What you need to do instead is adding an instantiator method in the class p5’s prototype{} object.
- B/c it’s a p5 method, it automatically receives the p5’s object via the keyword
this
every time it’s invoked!
- That’s exactly how p5 methods like createVector(), createCanvas(), createGraphics(), createElement(), etc. work!
- They all instantiate a class in our place passing the p5’s
this
as 1 of the arguments behind-the-scenes.
- You’d only need to advice your library’s users to prefer those createXXX() methods rather than directly instantiating a class via
new
:
p5.prototype.createWord3D(string, depth, size, resolution, bevelled, font, style) {
return new Word3D({ p: this, string, depth, size, resolution, bevelled, font, style });
}
1 Like
That’s awesome, thank you very much for your help on this. It now works exactly as intended, and the “create” syntax is nicer anyway since it’s closer to what already exists.
It can be found here: https://github.com/FreddieRa/p5.3D
1 Like