UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

174 lines (173 loc) 5.91 kB
"use strict"; import { TypedObjNode } from "./_Base"; import { Mesh } from "three"; import { FlagsControllerD } from "../utils/FlagsController"; import { AxesHelper } from "three"; import { HierarchyController } from "./utils/HierarchyController"; import { NodeContext } from "../../poly/NodeContext"; import { Vector3 } from "three"; import { Quaternion } from "three"; var BlendMode = /* @__PURE__ */ ((BlendMode2) => { BlendMode2["TOGETHER"] = "translate + rotate together"; BlendMode2["SEPARATELY"] = "translate + rotate separately"; return BlendMode2; })(BlendMode || {}); const BLEND_MODES = ["translate + rotate together" /* TOGETHER */, "translate + rotate separately" /* SEPARATELY */]; import { NodeParamsConfig, ParamConfig } from "../utils/params/ParamsConfig"; import { TypeAssert } from "../../poly/Assert"; import { isBooleanTrue } from "../../../core/Type"; class BlendObjParamConfig extends NodeParamsConfig { constructor() { super(...arguments); /** @param object to blend transform from */ this.object0 = ParamConfig.NODE_PATH("", { nodeSelection: { context: NodeContext.OBJ } }); /** @param object to blend transform to */ this.object1 = ParamConfig.NODE_PATH("", { nodeSelection: { context: NodeContext.OBJ } }); /** @param blend mode */ this.mode = ParamConfig.INTEGER(BLEND_MODES.indexOf("translate + rotate together" /* TOGETHER */), { menu: { entries: BLEND_MODES.map((name, value) => { return { name, value }; }) } }); /** @param blend value */ this.blend = ParamConfig.FLOAT(0, { visibleIf: { mode: BLEND_MODES.indexOf("translate + rotate together" /* TOGETHER */) }, range: [0, 1], rangeLocked: [false, false] }); /** @param blend translation value */ this.blendT = ParamConfig.FLOAT(0, { visibleIf: { mode: BLEND_MODES.indexOf("translate + rotate separately" /* SEPARATELY */) }, range: [0, 1], rangeLocked: [false, false] }); /** @param blend rotation value */ this.blendR = ParamConfig.FLOAT(0, { visibleIf: { mode: BLEND_MODES.indexOf("translate + rotate separately" /* SEPARATELY */) }, range: [0, 1], rangeLocked: [false, false] }); /** @param updateOnRender */ this.updateOnRender = ParamConfig.BOOLEAN(1); } } const ParamsConfig = new BlendObjParamConfig(); export class BlendObjNode extends TypedObjNode { constructor() { super(...arguments); this.paramsConfig = ParamsConfig; this.hierarchyController = new HierarchyController(this); this.flags = new FlagsControllerD(this); this._helper = new AxesHelper(1); this._t0 = new Vector3(); this._q0 = new Quaternion(); this._s0 = new Vector3(); this._t1 = new Vector3(); this._q1 = new Quaternion(); this._s1 = new Vector3(); } static type() { return "blend"; } createObject() { const object = new Mesh(); object.matrixAutoUpdate = false; object.onBeforeRender = this._onBeforeRender.bind(this); return object; } initializeNode() { this.hierarchyController.initializeNode(); this.io.inputs.setCount(0); this.addPostDirtyHook("blendOnDirty", () => { this.cookController.cookMainWithoutInputs(); }); this._updateHelperHierarchy(); this.flags.display.onUpdate(() => { this._updateHelperHierarchy(); }); } _updateHelperHierarchy() { if (this.flags.display.active()) { this.object.add(this._helper); } else { this.object.remove(this._helper); } } async cook() { this.object.frustumCulled = !this.pv.updateOnRender; const objNode0 = this.pv.object0.nodeWithContext(NodeContext.OBJ, this.states.error); const objNode1 = this.pv.object1.nodeWithContext(NodeContext.OBJ, this.states.error); if (objNode0 && objNode1) { if (objNode0.isDirty()) { await objNode0.compute(); } if (objNode1.isDirty()) { await objNode1.compute(); } this._object0 = objNode0.object; this._object1 = objNode1.object; this._computeBlendedMatrix(); } else { this.states.error.set("blend targets not found"); } this.cookController.endCook(); } _onBeforeRender() { if (!isBooleanTrue(this.pv.updateOnRender)) { return; } this._computeBlendedMatrix(); } _computeBlendedMatrix() { if (!(this._object0 && this._object1)) { return; } const mode = BLEND_MODES[this.pv.mode]; switch (mode) { case "translate + rotate together" /* TOGETHER */: return this._blendTogether(this._object0, this._object1); case "translate + rotate separately" /* SEPARATELY */: return this._blendSeparately(this._object0, this._object1); } TypeAssert.unreachable(mode); } _blendTogether(object0, object1) { this._decomposeMatrices(object0, object1); this._object.position.copy(this._t0).lerp(this._t1, this.pv.blend); this._object.quaternion.copy(this._q0).slerp(this._q1, this.pv.blend); if (!this._object.matrixAutoUpdate) { this._object.updateMatrix(); } } _blendSeparately(object0, object1) { this._decomposeMatrices(object0, object1); this._object.position.copy(this._t0).lerp(this._t1, this.pv.blendT); this._object.quaternion.copy(this._q0).slerp(this._q1, this.pv.blendR); if (!this._object.matrixAutoUpdate) { this._object.updateMatrix(); } } _decomposeMatrices(object0, object1) { this._updateMatrix(object0); this._updateMatrix(object1); object0.matrixWorld.decompose(this._t0, this._q0, this._s0); object1.matrixWorld.decompose(this._t1, this._q1, this._s1); } _updateMatrix(object) { if (!object.matrixAutoUpdate) { object.updateMatrix(); object.updateMatrixWorld(true); object.updateWorldMatrix(true, true); } } }