@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
147 lines (146 loc) • 5.04 kB
JavaScript
;
import { BaseSopOperation } from "./_Base";
import { TypeAssert } from "../../../engine/poly/Assert";
import {
CoreTransform,
ROTATION_ORDERS,
RotationOrder,
TransformTargetType,
TRANSFORM_TARGET_TYPES
} from "../../../core/Transform";
import { InputCloneMode } from "../../../engine/poly/InputCloneMode";
import { coreObjectClassFactory } from "../../../core/geometry/CoreObjectFactory";
import { MathUtils, Vector3, Matrix4, Euler, Quaternion } from "three";
import {
OBJECT_TRANSFORM_SPACES,
OBJECT_TRANSFORM_MODES,
ObjectTransformMode,
ObjectTransformSpace,
applyTransformWithSpaceToObject
} from "../../../core/TransformSpace";
import { isObject3D } from "../../../core/geometry/ObjectContent";
import { CoreMask } from "../../../core/geometry/Mask";
import { SopType } from "../../poly/registers/nodes/types/Sop";
import { pointsFromObjectFromGroup } from "../../../core/geometry/entities/point/CorePointUtils";
const _r = new Vector3();
const _euler = new Euler();
const _q = new Quaternion();
const _s = new Vector3();
const _mat4 = new Matrix4();
const _pointPos = new Vector3();
const _points = [];
export class TransformSopOperation extends BaseSopOperation {
constructor() {
super(...arguments);
this._coreTransform = new CoreTransform();
}
static type() {
return SopType.TRANSFORM;
}
cook(inputCoreGroups, params) {
const coreGroup = inputCoreGroups[0];
const selectedObjects = CoreMask.filterObjects(coreGroup, params);
for (const inputObject of selectedObjects) {
this._applyTransform(inputObject, coreGroup, params);
}
coreGroup.resetBoundingBox();
return coreGroup;
}
_applyTransform(object, coreGroup, params) {
if (isObject3D(object)) {
this._applyTransformWithTransformTargetType(object, coreGroup, params);
} else {
this._applyTransformWithoutTransformTargetType(object, params);
}
}
_applyTransformWithoutTransformTargetType(object, params) {
this._updateObject(object, params);
}
_applyTransformWithTransformTargetType(object, coreGroup, params) {
const mode = TRANSFORM_TARGET_TYPES[params.applyOn];
switch (mode) {
case TransformTargetType.GEOMETRY: {
return this._updateGeometry(object, params);
}
case TransformTargetType.OBJECT: {
return this._updateObject(object, params);
}
}
TypeAssert.unreachable(mode);
}
_updateGeometry(object, params) {
const matrix = this._matrix(params);
const pointGroup = params.pointGroup;
if (pointGroup.trim() === "") {
const geometry = object.geometry;
if (geometry) {
geometry.translate(-params.pivot.x, -params.pivot.y, -params.pivot.z);
geometry.applyMatrix4(matrix);
geometry.translate(params.pivot.x, params.pivot.y, params.pivot.z);
}
} else {
pointsFromObjectFromGroup(object, pointGroup, _points);
for (const point of _points) {
const position = point.position(_pointPos).sub(params.pivot);
position.applyMatrix4(matrix);
point.setPosition(position.add(params.pivot));
}
}
}
_updateObject(object, params) {
const objectMode = OBJECT_TRANSFORM_MODES[params.objectMode];
switch (objectMode) {
case ObjectTransformMode.SET: {
return this._setMatrix(object, params);
}
case ObjectTransformMode.MULT: {
return this._multMatrix(object, params);
}
}
TypeAssert.unreachable(objectMode);
}
_setMatrix(object, params) {
const order = ROTATION_ORDERS[params.rotationOrder];
_r.copy(params.r).multiplyScalar(MathUtils.DEG2RAD);
_euler.set(_r.x, _r.y, _r.z, order);
_q.setFromEuler(_euler);
_s.copy(params.s).multiplyScalar(params.scale);
_mat4.compose(params.t, _q, _s);
coreObjectClassFactory(object).applyMatrix(
object,
_mat4,
TRANSFORM_TARGET_TYPES[params.applyOn],
ObjectTransformSpace.LOCAL,
ObjectTransformMode.SET
);
}
// private _objectPosition = new Vector3();
_multMatrix(object, params) {
const matrix = this._matrix(params);
const transformSpace = OBJECT_TRANSFORM_SPACES[params.objectTransformSpace];
applyTransformWithSpaceToObject(object, matrix, transformSpace, ObjectTransformMode.MULT);
}
_matrix(params) {
return this._coreTransform.matrix(
params.t,
params.r,
params.s,
params.scale,
ROTATION_ORDERS[params.rotationOrder]
);
}
}
TransformSopOperation.DEFAULT_PARAMS = {
applyOn: TRANSFORM_TARGET_TYPES.indexOf(TransformTargetType.GEOMETRY),
group: "",
objectMode: OBJECT_TRANSFORM_MODES.indexOf(ObjectTransformMode.SET),
objectTransformSpace: OBJECT_TRANSFORM_SPACES.indexOf(ObjectTransformSpace.PARENT),
pointGroup: "",
rotationOrder: ROTATION_ORDERS.indexOf(RotationOrder.XYZ),
t: new Vector3(0, 0, 0),
r: new Vector3(0, 0, 0),
s: new Vector3(1, 1, 1),
scale: 1,
pivot: new Vector3(0, 0, 0)
};
TransformSopOperation.INPUT_CLONED_STATE = InputCloneMode.FROM_NODE;