UNPKG

polygonjs-engine

Version:

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

191 lines (190 loc) 6.79 kB
import {TypedSopNode} from "./_Base"; import { CoreTransform, ROTATION_ORDERS, RotationOrder, TransformTargetType, TRANSFORM_TARGET_TYPES } from "../../../core/Transform"; import {InputCloneMode as InputCloneMode2} from "../../poly/InputCloneMode"; import {Vector3 as Vector32} from "three/src/math/Vector3"; const max_transform_count = 6; const ROT_ORDER_DEFAULT = ROTATION_ORDERS.indexOf(RotationOrder.XYZ); const ROT_ORDER_MENU_ENTRIES = { menu: { entries: ROTATION_ORDERS.map((order, v) => { return {name: order, value: v}; }) } }; function visible_for_count(count) { const list = []; for (let i = count + 1; i <= max_transform_count; i++) { list.push({ count: i }); } return {visibleIf: list}; } import {NodeParamsConfig, ParamConfig} from "../utils/params/ParamsConfig"; import {TypeAssert} from "../../poly/Assert"; import {CoreAttribute, Attribute as Attribute2} from "../../../core/geometry/Attribute"; class TransformMultiSopParamConfig extends NodeParamsConfig { constructor() { super(...arguments); this.applyOn = ParamConfig.INTEGER(TRANSFORM_TARGET_TYPES.indexOf(TransformTargetType.GEOMETRIES), { menu: { entries: TRANSFORM_TARGET_TYPES.map((target_type, i) => { return {name: target_type, value: i}; }) } }); this.count = ParamConfig.INTEGER(2, { range: [0, max_transform_count], rangeLocked: [true, true] }); this.sep0 = ParamConfig.SEPARATOR(null, {...visible_for_count(0)}); this.rotationOrder0 = ParamConfig.INTEGER(ROT_ORDER_DEFAULT, { ...ROT_ORDER_MENU_ENTRIES, ...visible_for_count(0) }); this.r0 = ParamConfig.VECTOR3([0, 0, 0], {...visible_for_count(0)}); this.sep1 = ParamConfig.SEPARATOR(null, {...visible_for_count(1)}); this.rotationOrder1 = ParamConfig.INTEGER(ROT_ORDER_DEFAULT, { ...ROT_ORDER_MENU_ENTRIES, ...visible_for_count(1) }); this.r1 = ParamConfig.VECTOR3([0, 0, 0], {...visible_for_count(1)}); this.sep2 = ParamConfig.SEPARATOR(null, {...visible_for_count(2)}); this.rotationOrder2 = ParamConfig.INTEGER(ROT_ORDER_DEFAULT, { ...ROT_ORDER_MENU_ENTRIES, ...visible_for_count(2) }); this.r2 = ParamConfig.VECTOR3([0, 0, 0], {...visible_for_count(2)}); this.sep3 = ParamConfig.SEPARATOR(null, {...visible_for_count(3)}); this.rotationOrder3 = ParamConfig.INTEGER(ROT_ORDER_DEFAULT, { ...ROT_ORDER_MENU_ENTRIES, ...visible_for_count(3) }); this.r3 = ParamConfig.VECTOR3([0, 0, 0], {...visible_for_count(3)}); this.sep4 = ParamConfig.SEPARATOR(null, {...visible_for_count(4)}); this.rotationOrder4 = ParamConfig.INTEGER(ROT_ORDER_DEFAULT, { ...ROT_ORDER_MENU_ENTRIES, ...visible_for_count(4) }); this.r4 = ParamConfig.VECTOR3([0, 0, 0], {...visible_for_count(4)}); this.sep5 = ParamConfig.SEPARATOR(null, {...visible_for_count(5)}); this.rotationOrder5 = ParamConfig.INTEGER(ROT_ORDER_DEFAULT, { ...ROT_ORDER_MENU_ENTRIES, ...visible_for_count(5) }); this.r5 = ParamConfig.VECTOR3([0, 0, 0], {...visible_for_count(5)}); } } const ParamsConfig2 = new TransformMultiSopParamConfig(); export class TransformMultiSopNode extends TypedSopNode { constructor() { super(...arguments); this.params_config = ParamsConfig2; this._core_transform = new CoreTransform(); this._t = new Vector32(0, 0, 0); this._s = new Vector32(1, 1, 1); this._scale = 1; } static type() { return "transformMulti"; } static displayedInputNames() { return ["objects to transform", "objects to copy initial transform from"]; } initializeNode() { this.io.inputs.setCount(1, 2); this.io.inputs.initInputsClonedState([InputCloneMode2.FROM_NODE, InputCloneMode2.NEVER]); this.scene().dispatchController.onAddListener(() => { this.params.onParamsCreated("params_label", () => { this.params.label.init([this.p.applyOn], () => { return TRANSFORM_TARGET_TYPES[this.pv.applyOn]; }); }); }); this.params.onParamsCreated("cache param pairs", () => { this._rot_and_index_pairs = [ [this.p.r0, this.p.rotationOrder0], [this.p.r1, this.p.rotationOrder1], [this.p.r2, this.p.rotationOrder2], [this.p.r3, this.p.rotationOrder3], [this.p.r4, this.p.rotationOrder4], [this.p.r5, this.p.rotationOrder5] ]; }); } cook(input_contents) { const objects = input_contents[0].objectsWithGeo(); const src_object = input_contents[1] ? input_contents[1].objectsWithGeo()[0] : void 0; this._apply_transforms(objects, src_object); this.setObjects(objects); } _apply_transforms(objects, src_object) { const mode = TRANSFORM_TARGET_TYPES[this.pv.applyOn]; switch (mode) { case TransformTargetType.GEOMETRIES: { return this._apply_matrix_to_geometries(objects, src_object); } case TransformTargetType.OBJECTS: { return this._apply_matrix_to_objects(objects, src_object); } } TypeAssert.unreachable(mode); } _apply_matrix_to_geometries(objects, src_object) { if (!this._rot_and_index_pairs) { return; } if (src_object) { const src_geometry = src_object.geometry; if (src_geometry) { const attributes_to_copy = [Attribute2.POSITION, Attribute2.NORMAL, Attribute2.TANGENT]; for (let attrib_name of attributes_to_copy) { const src = src_geometry.attributes[attrib_name]; for (let object of objects) { const geometry = object.geometry; const dest = geometry.attributes[attrib_name]; if (src && dest) { CoreAttribute.copy(src, dest); } } } } } let pair; for (let i = 0; i < this.pv.count; i++) { pair = this._rot_and_index_pairs[i]; const matrix = this._matrix(pair[0].value, pair[1].value); for (let object of objects) { object.geometry.applyMatrix4(matrix); } } } _apply_matrix_to_objects(objects, src_object) { if (!this._rot_and_index_pairs) { return; } if (src_object) { for (let object of objects) { object.matrix.copy(src_object.matrix); object.matrix.decompose(object.position, object.quaternion, object.scale); } } let pair; for (let i = 0; i < this.pv.count; i++) { pair = this._rot_and_index_pairs[i]; const matrix = this._matrix(pair[0].value, pair[1].value); for (let object of objects) { object.applyMatrix4(matrix); } } } _matrix(r, rot_order_index) { return this._core_transform.matrix(this._t, r, this._s, this._scale, ROTATION_ORDERS[rot_order_index]); } }