If we don’t use scaling, it works well but there…
it doesn’t work at all… and I really don’t find why.
If you know it…
thank you VERY much in advance !!!
The sketch is here !
Otherwise, Openprocessing indicates an error that I don’t have at all on my computer when I run this sketch!
N.B. same sketch in Processing :
transform_java
Hi! I think I can see two problems in runOutMatrix
:
I think you aren’t accumulating the parent’s position, only its scale. The child’s total position should be createVector(parentX + parentScale * childX, parentY + parentScale + childY)
, as the parent’s scale also applies to the position relative to the parent.
It looks like you’re only accumulating position/scale from the direct parent, but that parent may also have a parent. Likely you will need to make your function recursive to account for that.
3 Likes
Also one thing that might be of interest is the DOMMatrixReadOnly
JavaScript class: DOMMatrixReadOnly It lets you keep track of a transform with multiple nested translations and scales and will also let you extend your code to include rotations too if you need.
It would let you do something like this:
class Thing {
globalTransform() {
let parentMatrix = new DOMMatrixReadOnly()
if (this.parent) {
parentMatrix = this.parent.globalTransform()
}
return parentMatrix
.translate(this.position.x, this.position.y)
.scale(this.scale)
}
runOutMatrix() {
push()
const m = this.globalMatrix()
applyMatrix(m.a, m.b, m.c, m.d, m.e, m.f)
// draw something here
pop()
for (const child of this.children) {
child.runOutMatrix()
}
}
4 Likes
THANK you beaucoup … (a lot)
It looks super interesting !!!
Yes indeed, taking care of the rotation is my next goal !
I will watch this very closely as soon as possible (I can’t wait!)… I have to take care of something else by Saturday evening - Sunday!
your webpage https://www.davepagurek.com/ seems very interesting too ( I’m going to come back to it later !)
1 Like
glv
August 24, 2025, 3:38pm
5
Hello @EricRogerGarcia ,
I did some more digging:
There may be something in there that can help with p5.js!
:)
There, it works!
(I didn’t have much time….)
(In Processing because I prefer Java for thinking!)
I will take care of the rotation issue now.
N.B. I absolutely need to solve this because the upcoming collision management will have to be done outside of the transformations applied to the objects for their display
P.S. I will also look at everything you told me about to learn new things!
thanks a lot !
Thing things;
void setup() {
size(1000, 600);
things=new Thing(width/2, height/2, 0.001);
for (int i=0; i<10; i++) {
Thing newThing=new Thing(random(width)-width/2, random(height)-height/2, random(1, 4));
things.addChild(newThing);
for (int j=0; j<5; j++) {
newThing.addChild(new Thing(random(width/2)-width/4, random(height/2)-height/4, random(1,4)));
}
}
frameRate(20);
}
void draw() {
background(200);
things.run();
things.scale += .003;
}
class Thing {
PVector position, globalPosition;
float scale, globalScale;
Thing parent;
ArrayList<Thing> children;
Thing(float x, float y, float scale) {
this.position=new PVector(x, y);
this.globalPosition=this.position.copy(); // globalPosition : Vector
this.scale=scale; // scale : Number
this.globalScale=scale;
parent=null; // parent : Thing
children = new ArrayList<>(); // children : Array<Thing>
}
void addChild(Thing child) { // child : Thing
this.children.add(child);
child.parent = this;
}
void runInMatrix() {
push();
translate(this.position.x, this.position.y); // translate first so position / parent coordinate system
scale(this.scale); // scale then: display in the scale of the parent * scale of the object
// display
if (parent==null) {
fill(0, 0, 0);
} else {
fill(255, 0, 0); // red
}
circle(0, 0, 20);
for (Thing child : this.children) {
child.runInMatrix();
}
pop();
}
void runOutMatrix() {
if (this.parent!=null) { // not the root Thing
this.globalScale = this.parent.globalScale * this.scale; // to show the object
this.globalPosition=this.parent.globalPosition.copy().add(position.copy().mult(parent.globalScale));
} else {
globalScale=scale;
}
//display
fill(0, 255, 0); // green
circle(this.globalPosition.x, this.globalPosition.y, 10*globalScale);
for (Thing child : this.children) {
child.runOutMatrix();
}
}
void run() {
this.runInMatrix();
this.runOutMatrix();
}
}
et voilà !!!
Thing things;
void setup() {
size(1000, 600);
things=new Thing(width/2, height/2, 40, 40, 0.6, 2)
.setRotationVelocity(0.01);
for (int i=0; i<10; i++) {
Thing newThing=new Thing(random(width)-width/2, random(height)-height/2, 40, 40, random(0, 2), random(1, 7))
.setRotationVelocity(0.02);
things.addChild(newThing);
for (int j=0; j<5; j++) {
newThing.addChild(new Thing(random(width/2)-width/4, random(height/2)-height/4, 40, 40, random(0, 2), random(1, 4)));
}
}
frameRate(20);
rectMode(CENTER);
}
void draw() {
background(200);
things.run();
}
class Thing {
PVector position, globalPosition;
float scale, globalScale;
Thing parent;
ArrayList<Thing> children;
float twidth, theight, rotation;
float globalRotation;
float rotationVelocity=0;
Thing(float x, float y, float w, float h, float scale, float r) {
this.position=new PVector(x, y);
this.globalPosition=this.position; // globalPosition : Vector
this.scale=scale; // scale : Number
this.globalScale=scale;
parent=null; // parent : Thing
children = new ArrayList<>(); // children : Array<Thing>
twidth = w;
theight = h;
rotation=r;
}
Thing setRotationVelocity(float rv) {
rotationVelocity=rv;
return this;
}
void runRotation() {
rotation+=rotationVelocity;
for (Thing child : this.children) {
child.runRotation();
}
}
void addChild(Thing child) { // child : Thing
this.children.add(child);
child.parent = this;
}
void runInMatrix() {
push();
translate(this.position.x, this.position.y); // translate first so position / parent coordinate system
scale(this.scale); // scale then: display in the scale of the parent * scale of the object
rotate(rotation);
// display
if (parent==null) {
fill(0, 0, 0);
} else {
fill(255, 0, 0); // red
}
rect(0, 0, twidth, theight);
for (Thing child : this.children) {
child.runInMatrix();
}
pop();
}
void runOutMatrix() {
if (this.parent!=null) { // not the root Thing
this.globalScale = this.parent.globalScale * this.scale; // to show the object
globalRotation=parent.globalRotation + this.rotation;
PVector positionWithScale = position.copy().mult(parent.globalScale);
globalPosition=parent.globalPosition.copy().add(positionWithScale.setHeading(position.heading()+parent.globalRotation));
} else { // root Thing
globalScale=scale;
globalRotation=rotation;
}
//display
fill(0, 255, 0); // green
resetMatrix();
translate(globalPosition.x, globalPosition.y);
rotate(globalRotation);
rect(0, 0, twidth*globalScale/2, theight*globalScale/2);
for (Thing child : this.children) {
child.runOutMatrix();
}
}
void run() {
runRotation();
this.runInMatrix();
this.runOutMatrix();
}
}