UNPKG

@polygonjs/polygonjs

Version:

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

96 lines (84 loc) 3.28 kB
import {Vector3, BufferGeometry, Float32BufferAttribute} from 'three'; import {BaseCorePoint} from '../../../entities/point/CorePoint'; import {uniqWithoutPreservingOrder, arrayCompact} from '../../../../ArrayUtils'; import {PolyDictionary} from '../../../../../types/GlobalTypes'; import {CoreObjectType, ObjectContent} from '../../../ObjectContent'; export abstract class CoreGeometryBuilderBase { fromPoints<T extends CoreObjectType>(object: ObjectContent<T>, points: BaseCorePoint[]): BufferGeometry { points = this._filterPoints(points); const geometry = new BufferGeometry(); // const coreGeometry = new CoreGeometry(geometry); const firstPoint = points[0]; if (!firstPoint) { return geometry; } const oldGeometry = firstPoint.geometry(); if (!oldGeometry) { return 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._indicesFromPoints(new_index_by_old_index, oldGeometry); if (indices) { geometry.setIndex(indices); } // attributes const {attributes} = oldGeometry; // const new_attributes = {} for (const attribute_name of Object.keys(attributes)) { const attrib_values = firstPoint.userDataAttribs()[attribute_name]; const is_attrib_indexed = attrib_values != null; if (is_attrib_indexed) { const new_values: string[] = []; const uniqValues: string[] = []; uniqWithoutPreservingOrder( points.map((point) => point.indexedAttribValue(attribute_name)), uniqValues ); arrayCompact(uniqValues, new_values); const new_index_by_value: PolyDictionary<number> = {}; new_values.forEach((new_value, i) => (new_index_by_value[new_value] = i)); firstPoint.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 (const point of points) { // const old_index = old_attrib_array[point.index()] const oldIndex = point.indexedAttribValue(attribute_name); if (oldIndex) { const new_index = new_index_by_value[oldIndex]; 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 _filterPoints(points: BaseCorePoint[]): BaseCorePoint[]; protected abstract _indicesFromPoints( new_index_by_old_index: PolyDictionary<number>, old_geometry: BufferGeometry ): number[] | undefined; }