@thi.ng/scenegraph
Version:
Extensible 2D/3D scene graph with @thi.ng/hiccup-canvas support
79 lines (78 loc) • 2.25 kB
JavaScript
import { isNumber } from "@thi.ng/checks/is-number";
import { invert44 } from "@thi.ng/matrices/invert";
import { mulM44 } from "@thi.ng/matrices/mulm";
import { mulV344 } from "@thi.ng/matrices/mulv";
import { transform44 } from "@thi.ng/matrices/transform";
import { madd3 } from "@thi.ng/vectors/madd";
import { set3 } from "@thi.ng/vectors/set";
import { setN3 } from "@thi.ng/vectors/setn";
import { sub3 } from "@thi.ng/vectors/sub";
import { ANode } from "./anode.js";
import { toHiccup } from "./hiccup.js";
class Node3D extends ANode {
translate;
rotate;
scale;
constructor(opts) {
super(opts);
this.translate = opts.translate ?? [0, 0, 0];
this.rotate = opts.rotate ?? [0, 0, 0];
const scale = opts.scale ?? 1;
this.scale = isNumber(scale) ? [scale, scale, scale] : scale;
this.update();
}
copy() {
return new Node3D({
id: this.id,
parent: this.parent,
translate: set3([], this.translate),
rotate: set3([], this.rotate),
scale: set3([], this.scale),
body: this.body
});
}
update() {
if (this.enabled) {
this.mat = transform44([], this.translate, this.rotate, this.scale);
if (this.parent) {
mulM44(this.mat, this.parent.mat, this.mat);
}
invert44(this.invMat, this.mat);
for (let c of this.children) {
c.update();
}
}
}
mapGlobalPoint(p) {
return mulV344([], this.invMat, p);
}
mapLocalPointToGlobal(p) {
return mulV344([], this.mat, p);
}
mapLocalPointToNode(dest, p) {
return mulV344(null, dest.invMat, mulV344([], this.mat, p));
}
scaleWithReferencePoint(ref, scale) {
if (this.enabled) {
const currScale = isNumber(this.scale) ? setN3([], this.scale) : this.scale;
const newScale = isNumber(scale) ? setN3([], scale) : scale;
const delta = sub3([], currScale, newScale);
this.scale = newScale;
this.translate = madd3([], ref, delta, this.translate);
this.update();
}
return this;
}
/**
* Future support planned. No immediate users of this method in a 3D context
* available thus far.
*
* @param ctx - arbitrary user data
*/
toHiccup(ctx) {
return toHiccup(this, ctx);
}
}
export {
Node3D
};