@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
140 lines (139 loc) • 5.41 kB
JavaScript
"use strict";
import { BaseSopOperation } from "./_Base";
import { Vector3, Matrix4, BufferGeometry } from "three";
import { ObjectType } from "../../../core/geometry/Constant";
import { CoreGeometryUtilCircle } from "../../../core/geometry/util/Circle";
import { CoreGeometryUtilCurve } from "../../../core/geometry/util/Curve";
import { CoreGeometryOperationSkin } from "../../../core/geometry/operation/Skin";
import { isBooleanTrue } from "../../../core/Type";
import { CoreGeometryBuilderMerge } from "../../../core/geometry/modules/three/builders/Merge";
import { addAttributesFromPoint } from "../../../core/geometry/util/addAttributesFromPoint";
import { pointsFromObject } from "../../../core/geometry/entities/point/CorePointUtils";
import { corePointClassFactory } from "../../../core/geometry/CoreObjectFactory";
import { copyObject3DProperties } from "../../../core/geometry/modules/three/ThreejsObjectUtils";
import { SopType } from "../../poly/registers/nodes/types/Sop";
const ORIGIN = new Vector3(0, 0, 0);
const UP = new Vector3(0, 1, 0);
const lookAtMat = new Matrix4();
const translateMat = new Matrix4();
const currentPos = new Vector3();
const prevPos = new Vector3();
const nextPos = new Vector3();
const delta = new Vector3();
const deltaNext = new Vector3();
const deltaPrev = new Vector3();
const _points = [];
export class PolywireSopOperation extends BaseSopOperation {
static type() {
return SopType.POLYWIRE;
}
cook(inputCoreGroups, params) {
const coreGroup = inputCoreGroups[0];
const inputObjects = coreGroup.threejsObjects();
const newObjects = [];
for (const inputObject of inputObjects) {
const geometries = [];
if (inputObject.isLineSegments) {
this._createTube(inputObject, params, geometries);
}
const mergedGeometry = CoreGeometryBuilderMerge.merge(geometries);
if (mergedGeometry) {
const newObject = this.createObject(mergedGeometry, ObjectType.MESH);
copyObject3DProperties(inputObject, newObject);
newObjects.push(newObject);
}
}
return this.createCoreGroupFromObjects(newObjects);
}
_createTube(lineSegment, params, geometries) {
var _a;
const geometry = lineSegment.geometry;
const corePointClass = corePointClassFactory(lineSegment);
const attributeNames = corePointClass.attributeNamesMatchingMask(lineSegment, params.attributesToCopy);
pointsFromObject(lineSegment, _points);
const indices = (_a = geometry.getIndex()) == null ? void 0 : _a.array;
if (!indices) {
return;
}
const accumulatedCurvePointIndices = CoreGeometryUtilCurve.accumulatedCurvePointIndices(indices);
for (let curvePointIndices of accumulatedCurvePointIndices) {
const currentPoints = curvePointIndices.map((index) => _points[index]);
this._createTubeFromPoints(currentPoints, attributeNames, params, geometries);
}
}
_createTubeFromPoints(points, attributeNames, params, geometries) {
if (points.length <= 1) {
return;
}
const options = {
radius: params.radius,
segments: params.segmentsRadial,
arcAngle: 360,
connectLastPoint: true
};
const circleTemplate = CoreGeometryUtilCircle.create(options);
const circles = [];
let i = 0;
for (let point of points) {
point.position(currentPos);
let prevPoint = points[i - 1];
let nextPoint = points[i + 1];
if (prevPoint && nextPoint) {
nextPoint.position(nextPos);
deltaNext.copy(nextPos).sub(currentPos);
prevPoint.position(prevPos);
deltaPrev.copy(prevPos).sub(currentPos).multiplyScalar(-1);
delta.lerpVectors(deltaNext, deltaPrev, 0.5);
} else {
if (nextPoint) {
nextPoint.position(nextPos);
delta.copy(nextPos).sub(currentPos);
} else {
nextPoint = points[i - 1];
nextPoint.position(nextPos);
delta.copy(nextPos).sub(currentPos).multiplyScalar(-1);
}
}
lookAtMat.identity();
lookAtMat.lookAt(ORIGIN, delta.multiplyScalar(-1), UP);
translateMat.identity();
translateMat.makeTranslation(currentPos.x, currentPos.y, currentPos.z);
const newCircle = circleTemplate.clone();
newCircle.applyMatrix4(lookAtMat);
newCircle.applyMatrix4(translateMat);
const positionIndex = attributeNames.indexOf("position");
if (positionIndex >= 0) {
attributeNames.splice(positionIndex, 1);
}
addAttributesFromPoint(newCircle, point, attributeNames);
circles.push(newCircle);
i++;
}
for (let i2 = 0; i2 < circles.length; i2++) {
if (i2 > 0) {
const circle = circles[i2];
const prevCircle = circles[i2 - 1];
const geometry = this._skin(prevCircle, circle);
geometries.push(geometry);
}
}
if (isBooleanTrue(params.closed)) {
const circle = circles[0];
const prevCircle = circles[circles.length - 1];
const geometry = this._skin(prevCircle, circle);
geometries.push(geometry);
}
}
_skin(geometry1, geometry0) {
const geometry = new BufferGeometry();
const operation = new CoreGeometryOperationSkin(geometry, geometry1, geometry0);
operation.process();
return geometry;
}
}
PolywireSopOperation.DEFAULT_PARAMS = {
radius: 1,
segmentsRadial: 8,
closed: true,
attributesToCopy: "*"
};