UNPKG

@thi.ng/scenegraph

Version:

Extensible 2D/3D scene graph with @thi.ng/hiccup-canvas support

79 lines (78 loc) 2.26 kB
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 (const 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 };