UNPKG

@polygonjs/polygonjs

Version:

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

178 lines (163 loc) 5.35 kB
import {BaseSopOperation} from './_Base'; import {CoreGroup} from '../../../core/geometry/Group'; import {Vector3} from 'three'; import {InputCloneMode} from '../../../engine/poly/InputCloneMode'; import {Mesh} from 'three'; import {Object3D} from 'three'; import {Matrix4} from 'three'; import {TypeAssert} from '../../poly/Assert'; import {Plane} from 'three'; import {BufferGeometry} from 'three'; import {DefaultOperationParams} from '../../../core/operations/_Base'; import { pointsFromObject } from '../../../core/geometry/entities/point/CorePointUtils'; import { CorePoint } from '../../../core/geometry/entities/point/CorePoint'; import { CoreObjectType } from '../../../core/geometry/ObjectContent'; export enum ShearMode { MATRIX = 'matrix', AXIS = 'axis', } export const SHEAR_MODES: ShearMode[] = [ShearMode.MATRIX, ShearMode.AXIS]; export enum ShearCenterMode { BBOX_CENTER = 'bbox center', BBOX_CENTER_OFFSET = 'bbox center offset', CUSTOM = 'custom', } export const SHEAR_CENTER_MODES: ShearCenterMode[] = [ ShearCenterMode.BBOX_CENTER, ShearCenterMode.BBOX_CENTER_OFFSET, ShearCenterMode.CUSTOM, ]; const _points:CorePoint<CoreObjectType>[]=[] interface ShearSopParams extends DefaultOperationParams { mode: number; // matrix mode xy: number; xz: number; yx: number; yz: number; zx: number; zy: number; // axis mode centerMode: number; centerOffset: Vector3; center: Vector3; planeAxis: Vector3; axis: Vector3; axisAmount: number; } export class ShearSopOperation extends BaseSopOperation { static override readonly DEFAULT_PARAMS: ShearSopParams = { mode: SHEAR_MODES.indexOf(ShearMode.AXIS), // matrix mode xy: 0, xz: 0, yx: 0, yz: 0, zx: 0, zy: 0, // axis mode centerMode: SHEAR_CENTER_MODES.indexOf(ShearCenterMode.BBOX_CENTER), centerOffset: new Vector3(0, 0, 0), center: new Vector3(0, 0, 0), planeAxis: new Vector3(0, 0, 1), axis: new Vector3(0, 1, 0), axisAmount: 0, }; static override readonly INPUT_CLONED_STATE = InputCloneMode.FROM_NODE; static override type(): Readonly<'shear'> { return 'shear'; } private _m4 = new Matrix4(); override cook(input_contents: CoreGroup[], params: ShearSopParams) { const objects = input_contents[0].threejsObjects(); this._applyShear(objects, params); return input_contents[0]; } private _applyShear(objects: Object3D[], params: ShearSopParams) { const mode = SHEAR_MODES[params.mode]; switch (mode) { case ShearMode.MATRIX: { return this._applyMatrixShear(objects, params); } case ShearMode.AXIS: { return this._applyAxisShear(objects, params); } } TypeAssert.unreachable(mode); } private _applyMatrixShear(objects: Object3D[], params: ShearSopParams) { this._m4.makeShear(params.xy, params.xz, params.yx, params.yz, params.zx, params.zy); for (let object of objects) { const mesh = object as Mesh; const geometry = mesh.geometry; if (geometry) { geometry.applyMatrix4(this._m4); } } } private _axisNormalized = new Vector3(); private _center = new Vector3(); private _pointPos = new Vector3(); private _axisPlane = new Plane(); private _pointOnPlane = new Vector3(); private _delta = new Vector3(); private _deltaNormalized = new Vector3(); private _offset = new Vector3(); private _applyAxisShear(objects: Object3D[], params: ShearSopParams) { this._axisNormalized.copy(params.axis); this._axisNormalized.normalize(); for (let object of objects) { const mesh = object as Mesh; const geometry = mesh.geometry; if (geometry) { this._getAxisModeCenter(geometry, params); this._axisPlane.setFromNormalAndCoplanarPoint(params.planeAxis, this._center); pointsFromObject(object,_points) for (const point of _points) { point.position(this._pointPos); this._axisPlane.projectPoint(this._pointPos, this._pointOnPlane); this._delta.copy(this._pointOnPlane).sub(this._pointPos); const distToPlane = this._delta.length(); this._deltaNormalized.copy(this._delta).normalize(); this._offset.copy(this._axisNormalized).multiplyScalar(params.axisAmount * distToPlane); if (this._delta.dot(params.planeAxis) > 0) { this._offset.multiplyScalar(-1); } this._pointPos.add(this._offset); point.setPosition(this._pointPos); } } } } private _getAxisModeCenter(geometry: BufferGeometry, params: ShearSopParams) { const mode = SHEAR_CENTER_MODES[params.centerMode]; switch (mode) { case ShearCenterMode.BBOX_CENTER: { return this._getAxisModeCenterBbox(geometry, params); } case ShearCenterMode.BBOX_CENTER_OFFSET: { return this._getAxisModeCenterBboxOffset(geometry, params); } case ShearCenterMode.CUSTOM: { return this._getAxisModeCenterCustom(params); } } TypeAssert.unreachable(mode); } private _getAxisModeCenterBbox(geometry: BufferGeometry, params: ShearSopParams) { geometry.computeBoundingBox(); const box = geometry.boundingBox; if (box) { box.getCenter(this._center); } else { this._center.set(0, 0, 0); } } private _getAxisModeCenterBboxOffset(geometry: BufferGeometry, params: ShearSopParams) { this._getAxisModeCenterBbox(geometry, params); this._center.add(params.centerOffset); } private _getAxisModeCenterCustom(params: ShearSopParams) { return this._center.copy(params.center); } }