UNPKG

@polygonjs/polygonjs

Version:

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

97 lines (91 loc) 3.2 kB
import {BaseSopOperation} from './_Base'; import {CoreGroup, Object3DWithGeometry} from '../../../core/geometry/Group'; import {InputCloneMode} from '../../../engine/poly/InputCloneMode'; import {Vector3, Object3D, Plane, Mesh} from 'three'; import {DefaultOperationParams} from '../../../core/operations/_Base'; import {CoreMask} from '../../../core/geometry/Mask'; import {SopType} from '../../poly/registers/nodes/types/Sop'; import {withChildrenRemoved} from '../../../core/geometry/util/HierarchyRemoved'; import {object3DHasGeometry} from '../../../core/geometry/GeometryUtils'; import {CoreObjectType, ObjectContent} from '../../../core/geometry/ObjectContent'; import {ThreejsCoreObject} from '../../../core/geometry/modules/three/ThreejsCoreObject'; import {meshInverse} from '../../../core/geometry/util/MeshInverse'; const _axis = new Vector3(); const _pos = new Vector3(); const _projectedPos = new Vector3(); const _delta = new Vector3(); const _plane = new Plane(); interface MirrorSopParams extends DefaultOperationParams { group: string; // axis: Vector3; center: Vector3; preserveInput: boolean; } export class MirrorSopOperation extends BaseSopOperation { static override readonly DEFAULT_PARAMS: MirrorSopParams = { group: '*', axis: new Vector3(1, 0, 0), center: new Vector3(0, 0, 0), preserveInput: true, }; static override readonly INPUT_CLONED_STATE = InputCloneMode.FROM_NODE; static override type(): Readonly<SopType.MIRROR> { return SopType.MIRROR; } override cook(inputCoreGroups: CoreGroup[], params: MirrorSopParams) { const coreGroup = inputCoreGroups[0]; const newObjects = coreGroup.allObjects(); const objects = CoreMask.filterThreejsObjects(coreGroup, { group: params.group, }).filter(object3DHasGeometry); // _axis.copy(params.axis).normalize(); _plane.constant = -params.center.dot(_axis); _plane.normal.copy(_axis); // for (const object of objects) { this._applyOrCreateMirrorObject(object, _plane, params, newObjects); } return this.createCoreGroupFromObjects(newObjects); } private _applyOrCreateMirrorObject( object: Object3D, plane: Plane, params: MirrorSopParams, newObjects: ObjectContent<CoreObjectType>[] ) { if (params.preserveInput) { const clonedObject = withChildrenRemoved<Object3D>(object, () => ThreejsCoreObject.clone(object)); this._mirrorObject(clonedObject, plane); if (clonedObject) { if (object.parent) { object.parent.add(clonedObject); } else { newObjects.push(clonedObject); } } } else { this._mirrorObject(object, plane); } } private _mirrorObject(object: Object3D, plane: Plane) { const geometry = (object as Object3DWithGeometry).geometry; if (!geometry) { return; } const position = geometry.getAttribute('position'); const pointsCount = position.count; const positions = position.array; for (let i = 0; i < pointsCount; i++) { _pos.fromArray(positions, i * 3); plane.projectPoint(_pos, _projectedPos); _delta.copy(_pos).sub(_projectedPos); _projectedPos.sub(_delta); _projectedPos.toArray(positions, i * 3); } if ((object as Mesh).isMesh) { meshInverse(object as Mesh); } } }