@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
178 lines (163 loc) • 5.35 kB
text/typescript
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);
}
}