polygonjs-engine
Version:
node-based webgl 3D engine https://polygonjs.com
88 lines (76 loc) • 3.1 kB
text/typescript
import {CorePoint} from '../Point';
import {BufferGeometry} from 'three/src/core/BufferGeometry';
import {CoreGeometry} from '../Geometry';
import {Float32BufferAttribute} from 'three/src/core/BufferAttribute';
import {Vector3} from 'three/src/math/Vector3';
import {ArrayUtils} from '../../ArrayUtils';
import {PolyDictionary} from '../../../types/GlobalTypes';
export abstract class CoreGeometryBuilderBase {
from_points(points: CorePoint[]) {
points = this._filter_points(points);
const geometry = new BufferGeometry();
const core_geometry = new CoreGeometry(geometry);
const first_point = points[0];
if (first_point != null) {
const old_geometry = first_point.geometry();
const old_core_geometry = first_point.core_geometry();
// index
const new_index_by_old_index: PolyDictionary<number> = {};
for (let i = 0; i < points.length; i++) {
new_index_by_old_index[points[i].index()] = i;
}
const indices = this._indices_from_points(new_index_by_old_index, old_geometry);
if (indices) {
geometry.setIndex(indices);
}
// attributes
const {attributes} = old_geometry;
// const new_attributes = {}
for (let attribute_name of Object.keys(attributes)) {
const attrib_values = old_core_geometry.userDataAttribs()[attribute_name];
const is_attrib_indexed = attrib_values != null;
if (is_attrib_indexed) {
const new_values: string[] = ArrayUtils.uniq(
points.map((point) => point.indexedAttribValue(attribute_name))
);
const new_index_by_value: PolyDictionary<number> = {};
new_values.forEach((new_value, i) => (new_index_by_value[new_value] = i));
core_geometry.userDataAttribs()[attribute_name] = new_values;
// const old_attrib = old_geometry.getAttribute(attribute_name)
// const old_attrib_array = old_attrib.array
const new_attrib_indices = [];
for (let point of points) {
// const old_index = old_attrib_array[point.index()]
const new_index = new_index_by_value[point.indexedAttribValue(attribute_name)];
new_attrib_indices.push(new_index);
}
geometry.setAttribute(attribute_name, new Float32BufferAttribute(new_attrib_indices, 1));
} else {
const attrib_size = attributes[attribute_name].itemSize;
const values: number[] = new Array(points.length * attrib_size);
switch (attrib_size) {
case 1:
for (let i = 0; i < points.length; i++) {
values[i] = points[i].attribValue(attribute_name) as number;
}
break;
default:
let value: Vector3;
for (let i = 0; i < points.length; i++) {
value = points[i].attribValue(attribute_name) as Vector3;
value.toArray(values, i * attrib_size);
}
break;
}
geometry.setAttribute(attribute_name, new Float32BufferAttribute(values, attrib_size));
}
}
}
return geometry;
}
protected abstract _filter_points(points: CorePoint[]): CorePoint[];
protected abstract _indices_from_points(
new_index_by_old_index: PolyDictionary<number>,
old_geometry: BufferGeometry
): number[] | undefined;
}