@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
124 lines (123 loc) • 4.55 kB
JavaScript
;
import { BaseSopOperation } from "./_Base";
import { Vector2, Vector3, PlaneGeometry, Quaternion, BoxGeometry, Box3 } from "three";
import { CoreTransform, rotateGeometry } from "../../../core/Transform";
import { InputCloneMode } from "../../../engine/poly/InputCloneMode";
import { isBooleanTrue } from "../../../core/BooleanValue";
import { ObjectType } from "../../../core/geometry/Constant";
const tmpBox = new Box3();
const tmpBoxPreRotation = new Box3();
const tmpSize = new Vector3();
const tmpCenter = new Vector3();
const DEFAULT_UP = new Vector3(0, 0, 1);
const q = new Quaternion();
export const DEFAULT_PARAMS = {
size: new Vector2(1, 1),
useSegmentsCount: false,
stepSize: 1,
segments: new Vector2(1, 1),
direction: new Vector3(0, 1, 0),
center: new Vector3(0, 0, 0),
asLines: false
};
const _segmentsCount = new Vector2(1, 1);
export class PlaneSopOperation extends BaseSopOperation {
constructor() {
super(...arguments);
this._coreTransform = new CoreTransform();
}
static type() {
return "plane";
}
cook(inputCoreGroups, params) {
const coreGroup = inputCoreGroups[0];
if (coreGroup) {
return this._cookWithInput(coreGroup, params);
} else {
return this._cookWithoutInput(params);
}
}
_cookWithoutInput(params) {
const geometry = this._createPlane(params.size, params);
rotateGeometry(geometry, DEFAULT_UP, params.direction);
const matrix = this._coreTransform.translationMatrix(params.center);
geometry.applyMatrix4(matrix);
const object = this._createPlaneObject(geometry, params);
return this.createCoreGroupFromObjects([object]);
}
_cookWithInput(coreGroup, params) {
coreGroup.boundingBox(tmpBoxPreRotation);
tmpBoxPreRotation.getCenter(tmpCenter);
coreGroup.boundingBox(tmpBox);
tmpBox.getSize(tmpSize);
tmpBox.getCenter(tmpCenter);
const boxGeometry = new BoxGeometry(tmpSize.x, tmpSize.y, tmpSize.z, 1, 1, 1);
function _applyInputQuaternion(_q) {
boxGeometry.applyQuaternion(_q);
boxGeometry.computeBoundingBox();
}
function _setInputRotation() {
q.setFromUnitVectors(DEFAULT_UP, params.direction);
_applyInputQuaternion(q);
}
_setInputRotation();
const bboxPostRotation = boxGeometry.boundingBox;
bboxPostRotation.getSize(tmpSize);
const size2d = new Vector2(tmpSize.x, tmpSize.y);
const geometry = this._createPlane(size2d, params);
rotateGeometry(geometry, DEFAULT_UP, params.direction);
geometry.translate(tmpCenter.x, tmpCenter.y, tmpCenter.z);
const object = this._createPlaneObject(geometry, params);
return this.createCoreGroupFromObjects([object]);
}
_createPlaneObject(geometry, params) {
return BaseSopOperation.createObject(geometry, params.asLines ? ObjectType.LINE_SEGMENTS : ObjectType.MESH);
}
_createPlane(size, params) {
size = size.clone();
if (isBooleanTrue(params.useSegmentsCount)) {
_segmentsCount.x = Math.floor(params.segments.x);
_segmentsCount.y = Math.floor(params.segments.y);
} else {
if (params.stepSize > 0) {
size.x = Math.max(size.x, params.stepSize);
size.y = Math.max(size.y, params.stepSize);
_segmentsCount.x = Math.floor(size.x / params.stepSize);
_segmentsCount.y = Math.floor(size.y / params.stepSize);
size.x = _segmentsCount.x * params.stepSize;
size.y = _segmentsCount.y * params.stepSize;
}
}
const geometry = new PlaneGeometry(size.x, size.y, _segmentsCount.x, _segmentsCount.y);
if (isBooleanTrue(params.asLines)) {
const gridX = Math.floor(_segmentsCount.x);
const gridY = Math.floor(_segmentsCount.y);
const gridX1 = gridX + 1;
const indices = [];
for (let iy = 0; iy < gridY; iy++) {
for (let ix = 0; ix < gridX; ix++) {
const a = ix + gridX1 * iy;
const b = ix + gridX1 * (iy + 1);
const d = ix + 1 + gridX1 * iy;
indices.push(a, b);
indices.push(a, d);
const lastX = ix == gridX - 1;
const lastY = iy == gridY - 1;
if (lastX || lastY) {
const c = ix + 1 + gridX1 * (iy + 1);
if (lastX) {
indices.push(d, c);
}
if (lastY) {
indices.push(b, c);
}
}
}
}
geometry.setIndex(indices);
}
return geometry;
}
}
PlaneSopOperation.DEFAULT_PARAMS = DEFAULT_PARAMS;
PlaneSopOperation.INPUT_CLONED_STATE = InputCloneMode.NEVER;