UNPKG

@polygonjs/polygonjs

Version:

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

124 lines (123 loc) 4.55 kB
"use strict"; 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;