@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
133 lines (111 loc) • 4.08 kB
text/typescript
import {BaseCorePoint, CorePoint} from '../entities/point/CorePoint';
import {Float32BufferAttribute, Vector2, BufferGeometry, Mesh, TypedArray} from 'three';
import {PolyDictionary} from '../../../types/GlobalTypes';
import {CoreObjectType, ObjectContent, isObject3D} from '../ObjectContent';
import {pointsFromObject, pointAttributeNames, pointAttributeSizes} from '../entities/point/CorePointUtils';
const _points:CorePoint<CoreObjectType>[]=[]
export class CoreGeometryUtilCurve {
static accumulatedCurvePointIndices(indices: TypedArray) {
let curve_point_indices: number[] = [];
const accumulated_curve_point_indices = [];
let last_index_added: number | null = null;
// indices.forEach((index, i) => {
let index: number;
for (let i = 0; i < indices.length; i++) {
if (i % 2 === 1) {
index = indices[i];
const previous_index = indices[i - 1];
// if the last added index, from the previous segment
// is the same as the start of the current segment (indices[i-1])
// then this is part of the same curve
if (last_index_added == null || previous_index === last_index_added) {
// add the first point
if (curve_point_indices.length === 0) {
curve_point_indices.push(previous_index);
}
curve_point_indices.push(index);
last_index_added = index;
} else {
// otherwise we create a new curve
accumulated_curve_point_indices.push(curve_point_indices);
// and reset the array
curve_point_indices = [previous_index, index];
last_index_added = index;
}
}
}
// also create with the remaining ones
accumulated_curve_point_indices.push(curve_point_indices);
return accumulated_curve_point_indices;
}
static create_line_segment_geometry(
points: BaseCorePoint[],
indices: number[],
attrib_names: string[],
attrib_sizes_by_name: PolyDictionary<number>
) {
// let new_positions: number[] = []
const new_indices: number[] = [];
const new_attribute_values_by_name: PolyDictionary<number[]> = {};
attrib_names.forEach((attrib_name) => {
new_attribute_values_by_name[attrib_name] = [];
});
indices.forEach((index, i) => {
const point = points[index];
// const position = point.position();
// new_positions.push(position.toArray());
attrib_names.forEach((attrib_name) => {
const attrib_value = point.attribValue(attrib_name);
const attrib_size = attrib_sizes_by_name[attrib_name];
let attrib_value_f: number[];
if (attrib_size > 1) {
attrib_value_f = (attrib_value as Vector2).toArray();
} else {
attrib_value_f = [attrib_value as number];
}
attrib_value_f.forEach((v: number) => {
new_attribute_values_by_name[attrib_name].push(v);
});
});
if (i > 0) {
new_indices.push(i - 1);
new_indices.push(i);
}
});
const geometry = new BufferGeometry();
attrib_names.forEach((attrib_name) => {
const attrib_size = attrib_sizes_by_name[attrib_name];
const values = new_attribute_values_by_name[attrib_name];
geometry.setAttribute(attrib_name, new Float32BufferAttribute(values, attrib_size));
});
geometry.setIndex(new_indices);
return geometry;
}
static line_segment_to_geometries<T extends CoreObjectType>(object: ObjectContent<T>) {
const geometries: BufferGeometry[] = [];
const attribNames = pointAttributeNames(object);
pointsFromObject(object,_points);
if (!isObject3D(object)) {
return;
}
const geometry = (object as Mesh).geometry;
if (!geometry) {
return;
}
const indices = (geometry.getIndex()?.array ) || new Uint32Array(0);
const accumulated_curve_point_indices = this.accumulatedCurvePointIndices(indices);
if (accumulated_curve_point_indices.length > 0) {
const attributeSizesByName = pointAttributeSizes(object);
accumulated_curve_point_indices.forEach((curvePointIndices, i) => {
const newGeometry = this.create_line_segment_geometry(
_points,
curvePointIndices,
attribNames,
attributeSizesByName
);
geometries.push(newGeometry);
});
}
return geometries;
}
}