polygonjs-engine
Version:
node-based webgl 3D engine https://polygonjs.com
108 lines (90 loc) • 3.43 kB
text/typescript
/**
* Creates polygons between 2 lines
*
*
*/
import {BufferGeometry} from 'three/src/core/BufferGeometry';
import {Mesh} from 'three/src/objects/Mesh';
import {LineSegments} from 'three/src/objects/LineSegments';
import {TypedSopNode} from './_Base';
import {CoreGeometryUtilCurve} from '../../../core/geometry/util/Curve';
import {CoreGeometryOperationSkin} from '../../../core/geometry/operation/Skin';
import {CoreGroup} from '../../../core/geometry/Group';
import {NodeParamsConfig} from '../utils/params/ParamsConfig';
import {ArrayUtils} from '../../../core/ArrayUtils';
class SkinSopParamsConfig extends NodeParamsConfig {}
const ParamsConfig = new SkinSopParamsConfig();
export class SkinSopNode extends TypedSopNode<SkinSopParamsConfig> {
params_config = ParamsConfig;
static type() {
return 'skin';
}
static displayedInputNames(): string[] {
return ['lines to create polygons from', 'if used, lines from both inputs will be used'];
}
initializeNode() {
this.io.inputs.setCount(1, 2);
}
cook(input_contents: CoreGroup[]) {
const inputs_count = ArrayUtils.compact(this.io.inputs.inputs()).length;
switch (inputs_count) {
case 1:
return this.process_one_input(input_contents);
case 2:
return this.process_two_inputs(input_contents);
default:
return this.states.error.set('inputs count not valid');
}
}
process_one_input(input_contents: CoreGroup[]) {
const core_group0 = input_contents[0];
const line_segments0 = this._get_line_segments(core_group0);
const geometries: BufferGeometry[] = [];
if (line_segments0) {
const first_line_segment = line_segments0[0] as Mesh;
if (first_line_segment) {
const src_geometries = CoreGeometryUtilCurve.line_segment_to_geometries(
first_line_segment.geometry as BufferGeometry
);
src_geometries.forEach((src_geometry, i) => {
if (i > 0) {
const prev_src_geometry = src_geometries[i - 1];
const geometry = this._skin(prev_src_geometry, src_geometry);
geometries.push(geometry);
}
});
}
}
this.setGeometries(geometries);
}
process_two_inputs(input_contents: CoreGroup[]) {
const core_group0 = input_contents[0];
const core_group1 = input_contents[1];
const line_segments0 = this._get_line_segments(core_group0);
const line_segments1 = this._get_line_segments(core_group1);
const line_segments = ArrayUtils.sortBy([line_segments0, line_segments1], (array) => -array.length);
const smallest_array = line_segments[0];
const largest_array = line_segments[1];
const geometries: BufferGeometry[] = [];
smallest_array.forEach((line_segment, i) => {
const other_line_segment = largest_array[i];
if (line_segment != null && other_line_segment != null) {
const geo = (line_segment as Mesh).geometry as BufferGeometry;
const other_geo = (other_line_segment as Mesh).geometry as BufferGeometry;
const geometry = this._skin(geo, other_geo);
geometries.push(geometry);
}
});
this.setGeometries(geometries);
}
_get_line_segments(core_group: CoreGroup) {
return core_group.objects().filter((child) => (child as LineSegments).isLineSegments);
}
_skin(geometry1: BufferGeometry, geometry0: BufferGeometry) {
// TODO: maybe instead of doing this,
const geometry = new BufferGeometry();
const operation = new CoreGeometryOperationSkin(geometry, geometry1, geometry0);
operation.process();
return geometry;
}
}