UNPKG

@polygonjs/polygonjs

Version:

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

202 lines (201 loc) 6.78 kB
"use strict"; import { TypedSopNode } from "./_Base"; import { CoreTransform, ROTATION_ORDERS, RotationOrder, TransformTargetType, TRANSFORM_TARGET_TYPES } from "../../../core/Transform"; import { InputCloneMode } from "../../poly/InputCloneMode"; import { Vector3 } from "three"; 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 } from "../../../core/geometry/Attribute"; import { SopType } from "../../poly/registers/nodes/types/Sop"; class TransformMultiSopParamConfig extends NodeParamsConfig { constructor() { super(...arguments); /** @param defines if this applies to objects or geometries */ this.applyOn = ParamConfig.INTEGER(TRANSFORM_TARGET_TYPES.indexOf(TransformTargetType.GEOMETRY), { menu: { entries: TRANSFORM_TARGET_TYPES.map((target_type, i) => { return { name: target_type, value: i }; }) } }); /** @param number of transformations this can apply */ this.count = ParamConfig.INTEGER(2, { range: [0, max_transform_count], rangeLocked: [true, true] }); // 0 /** @param transform 0 rotation order */ this.rotationOrder0 = ParamConfig.INTEGER(ROT_ORDER_DEFAULT, { separatorBefore: true, ...ROT_ORDER_MENU_ENTRIES, ...visible_for_count(0) }); /** @param rotation 0 */ this.r0 = ParamConfig.VECTOR3([0, 0, 0], { ...visible_for_count(0) }); // 1 /** @param transform 1 rotation order */ this.rotationOrder1 = ParamConfig.INTEGER(ROT_ORDER_DEFAULT, { separatorBefore: true, ...ROT_ORDER_MENU_ENTRIES, ...visible_for_count(1) }); /** @param rotation 1 */ this.r1 = ParamConfig.VECTOR3([0, 0, 0], { ...visible_for_count(1) }); // 2 /** @param transform 2 rotation order */ this.rotationOrder2 = ParamConfig.INTEGER(ROT_ORDER_DEFAULT, { separatorBefore: true, ...ROT_ORDER_MENU_ENTRIES, ...visible_for_count(2) }); /** @param rotation 2 */ this.r2 = ParamConfig.VECTOR3([0, 0, 0], { ...visible_for_count(2) }); // 3 /** @param transform 3 rotation order */ this.rotationOrder3 = ParamConfig.INTEGER(ROT_ORDER_DEFAULT, { separatorBefore: true, ...ROT_ORDER_MENU_ENTRIES, ...visible_for_count(3) }); /** @param rotation 3 */ this.r3 = ParamConfig.VECTOR3([0, 0, 0], { ...visible_for_count(3) }); // 4 /** @param transform 4 rotation order */ this.rotationOrder4 = ParamConfig.INTEGER(ROT_ORDER_DEFAULT, { separatorBefore: true, ...ROT_ORDER_MENU_ENTRIES, ...visible_for_count(4) }); /** @param rotation 4 */ this.r4 = ParamConfig.VECTOR3([0, 0, 0], { ...visible_for_count(4) }); // 5 /** @param transform 5 rotation order */ this.rotationOrder5 = ParamConfig.INTEGER(ROT_ORDER_DEFAULT, { separatorBefore: true, ...ROT_ORDER_MENU_ENTRIES, ...visible_for_count(5) }); /** @param rotation 5 */ this.r5 = ParamConfig.VECTOR3([0, 0, 0], { ...visible_for_count(5) }); } } const ParamsConfig = new TransformMultiSopParamConfig(); export class TransformMultiSopNode extends TypedSopNode { constructor() { super(...arguments); this.paramsConfig = ParamsConfig; this._core_transform = new CoreTransform(); this._t = new Vector3(0, 0, 0); this._s = new Vector3(1, 1, 1); this._scale = 1; } static type() { return SopType.TRANSFORM_MULTI; } initializeNode() { this.io.inputs.setCount(1, 2); this.io.inputs.initInputsClonedState([InputCloneMode.FROM_NODE, InputCloneMode.NEVER]); } _createRotAndIndexPairs() { return [ [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] ]; } _rotAndIndexPairs() { return this.__rotAndIndexPairs = this.__rotAndIndexPairs || this._createRotAndIndexPairs(); } cook(input_contents) { const objects = input_contents[0].threejsObjectsWithGeo(); const src_object = input_contents[1] ? input_contents[1].threejsObjectsWithGeo()[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.GEOMETRY: { return this._apply_matrix_to_geometries(objects, src_object); } case TransformTargetType.OBJECT: { return this._apply_matrix_to_objects(objects, src_object); } } TypeAssert.unreachable(mode); } _apply_matrix_to_geometries(objects, src_object) { if (src_object) { const src_geometry = src_object.geometry; if (src_geometry) { const attributes_to_copy = [Attribute.POSITION, Attribute.NORMAL, Attribute.TANGENT]; for (const attrib_name of attributes_to_copy) { const src = src_geometry.attributes[attrib_name]; for (const 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._rotAndIndexPairs()[i]; const matrix = this._matrix(pair[0].value, pair[1].value); for (const object of objects) { object.geometry.applyMatrix4(matrix); } } } _apply_matrix_to_objects(objects, src_object) { if (src_object) { for (const 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._rotAndIndexPairs()[i]; const matrix = this._matrix(pair[0].value, pair[1].value); for (const 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]); } }