UNPKG

polygonjs-engine

Version:

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

106 lines (105 loc) 3.98 kB
import {TypedSopNode} from "./_Base"; import {CoreGeometry} from "../../../core/geometry/Geometry"; import {CoreTransform, DEFAULT_ROTATION_ORDER} from "../../../core/Transform"; import {CoreGeometryUtilCircle} from "../../../core/geometry/util/Circle"; import {CoreGeometryUtilCurve} from "../../../core/geometry/util/Curve"; import {CoreGeometryOperationSkin} from "../../../core/geometry/operation/Skin"; import {Vector3 as Vector32} from "three/src/math/Vector3"; import {LineSegments as LineSegments2} from "three/src/objects/LineSegments"; import {BufferGeometry as BufferGeometry2} from "three/src/core/BufferGeometry"; import {InputCloneMode as InputCloneMode2} from "../../poly/InputCloneMode"; const POSITION_ATTRIBUTE_NAME = "position"; const DEFAULT_R = new Vector32(0, 0, 0); const DEFAULT_S = new Vector32(1, 1, 1); import {NodeParamsConfig, ParamConfig} from "../utils/params/ParamsConfig"; import {ObjectType} from "../../../core/geometry/Constant"; class PolywireSopParamsConfig extends NodeParamsConfig { constructor() { super(...arguments); this.radius = ParamConfig.FLOAT(1); this.segmentsRadial = ParamConfig.INTEGER(8, { range: [3, 20], rangeLocked: [true, false] }); this.closed = ParamConfig.BOOLEAN(0); } } const ParamsConfig2 = new PolywireSopParamsConfig(); export class PolywireSopNode extends TypedSopNode { constructor() { super(...arguments); this.params_config = ParamsConfig2; this._core_transform = new CoreTransform(); this._geometries = []; } static type() { return "polywire"; } static displayedInputNames() { return ["lines to create tubes from"]; } initializeNode() { this.io.inputs.setCount(1); this.io.inputs.initInputsClonedState(InputCloneMode2.NEVER); } cook(input_contents) { const core_group = input_contents[0]; this._geometries = []; for (let object of core_group.objects()) { if (object instanceof LineSegments2) { this._create_tube(object); } } const merged_geometry = CoreGeometry.merge_geometries(this._geometries); for (let geometry of this._geometries) { geometry.dispose(); } if (merged_geometry) { const object = this.create_object(merged_geometry, ObjectType.MESH); this.setObject(object); } else { this.setObjects([]); } } _create_tube(line_segment) { const geometry = line_segment.geometry; const wrapper = new CoreGeometry(geometry); const points = wrapper.points(); const indices = geometry.getIndex()?.array; const accumulated_curve_point_indices = CoreGeometryUtilCurve.accumulated_curve_point_indices(indices); for (let curve_point_indices of accumulated_curve_point_indices) { const current_points = curve_point_indices.map((index) => points[index]); this._create_tube_from_points(current_points); } } _create_tube_from_points(points) { if (points.length <= 1) { return; } const positions = points.map((point) => point.attribValue(POSITION_ATTRIBUTE_NAME)); const circle_template = CoreGeometryUtilCircle.create(this.pv.radius, this.pv.segmentsRadial); const circles = []; const scale = 1; for (let position of positions) { const t = position; const matrix = this._core_transform.matrix(t, DEFAULT_R, DEFAULT_S, scale, DEFAULT_ROTATION_ORDER); const new_circle = circle_template.clone(); new_circle.applyMatrix4(matrix); circles.push(new_circle); } for (let i = 0; i < circles.length; i++) { if (i > 0) { const circle = circles[i]; const prev_circle = circles[i - 1]; const geometry = this._skin(prev_circle, circle); this._geometries.push(geometry); } } } _skin(geometry1, geometry0) { const geometry = new BufferGeometry2(); const operation = new CoreGeometryOperationSkin(geometry, geometry1, geometry0); operation.process(); return geometry; } }