@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
202 lines (201 loc) • 6.78 kB
JavaScript
"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]);
}
}