UNPKG

polygonjs-engine

Version:

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

141 lines (130 loc) 4.72 kB
import {BaseSopOperation} from './_Base'; import {DefaultOperationParams} from '../_Base'; import {CoreGroup} from '../../../core/geometry/Group'; import {BufferAttribute} from 'three/src/core/BufferAttribute'; import {InputCloneMode} from '../../../engine/poly/InputCloneMode'; import {Vector3} from 'three/src/math/Vector3'; import {CoreString} from '../../String'; interface AttribNormalizeSopParams extends DefaultOperationParams { mode: number; name: string; changeName: boolean; newName: string; } export enum NormalizeMode { MIN_MAX_TO_01 = 'min/max to 0/1', VECTOR_TO_LENGTH_1 = 'vectors to length 1', } export const NORMALIZE_MODES: NormalizeMode[] = [NormalizeMode.MIN_MAX_TO_01, NormalizeMode.VECTOR_TO_LENGTH_1]; export class AttribNormalizeSopOperation extends BaseSopOperation { static readonly DEFAULT_PARAMS: AttribNormalizeSopParams = { mode: 0, name: 'position', changeName: false, newName: '', }; static readonly INPUT_CLONED_STATE = InputCloneMode.FROM_NODE; static type(): Readonly<'attribNormalize'> { return 'attribNormalize'; } cook(input_contents: CoreGroup[], params: AttribNormalizeSopParams) { const core_group = input_contents[0]; const objects = input_contents[0].objectsWithGeo(); const attrib_names = CoreString.attribNames(params.name); for (let object of objects) { const geometry = object.geometry; for (let attrib_name of attrib_names) { const src_attrib = geometry.getAttribute(attrib_name) as BufferAttribute; if (src_attrib) { let dest_attrib: BufferAttribute | undefined = src_attrib; if (params.changeName && params.newName != '') { dest_attrib = geometry.getAttribute(params.newName) as BufferAttribute; if (dest_attrib) { dest_attrib.needsUpdate = true; } dest_attrib = dest_attrib || src_attrib.clone(); } this._normalize_attribute(src_attrib, dest_attrib, params); } } } return core_group; } private _normalize_attribute( src_attrib: BufferAttribute, dest_attrib: BufferAttribute, params: AttribNormalizeSopParams ) { const mode = NORMALIZE_MODES[params.mode]; switch (mode) { case NormalizeMode.MIN_MAX_TO_01: return this._normalize_from_min_max_to_01(src_attrib, dest_attrib); case NormalizeMode.VECTOR_TO_LENGTH_1: return this._normalize_vectors(src_attrib, dest_attrib); } } private min3: Vector3 = new Vector3(); private max3: Vector3 = new Vector3(); private _normalize_from_min_max_to_01(src_attrib: BufferAttribute, dest_attrib: BufferAttribute) { const attrib_size = src_attrib.itemSize; const src_array = src_attrib.array as number[]; const dest_array = dest_attrib.array as number[]; // const values = points.map((point) => point.attribValue(params.name)); switch (attrib_size) { case 1: { const minf = Math.min(...src_array); const maxf = Math.max(...src_array); for (let i = 0; i < dest_array.length; i++) { dest_array[i] = (src_array[i] - minf) / (maxf - minf); } return; } case 3: { const points_count = src_array.length / attrib_size; const xs = new Array(points_count); const ys = new Array(points_count); const zs = new Array(points_count); let j = 0; for (let i = 0; i < points_count; i++) { j = i * attrib_size; xs[i] = src_array[j + 0]; ys[i] = src_array[j + 1]; zs[i] = src_array[j + 2]; } this.min3.set(Math.min(...xs), Math.min(...ys), Math.min(...zs)); this.max3.set(Math.max(...xs), Math.max(...ys), Math.max(...zs)); for (let i = 0; i < points_count; i++) { j = i * attrib_size; dest_array[j + 0] = (xs[i] - this.min3.x) / (this.max3.x - this.min3.x); dest_array[j + 1] = (ys[i] - this.min3.y) / (this.max3.y - this.min3.y); dest_array[j + 2] = (zs[i] - this.min3.z) / (this.max3.z - this.min3.z); } return; } } // let target_name = params.name; // if (params.changeName) { // target_name = params.newName; // if (!core_group.hasAttrib(target_name)) { // core_group.addNumericVertexAttrib(target_name, attrib_size, 0); // } // } // normalized_values.forEach((normalized_value, i) => { // const point = points[i]; // point.setAttribValue(target_name, normalized_value); // }); } private _vec: Vector3 = new Vector3(); private _normalize_vectors(src_attrib: BufferAttribute, dest_attrib: BufferAttribute) { const src_array = src_attrib.array; const dest_array = dest_attrib.array; const elements_count = src_array.length; if (src_attrib.itemSize == 3) { for (let i = 0; i < elements_count; i += 3) { this._vec.fromArray(src_array, i); this._vec.normalize(); this._vec.toArray(dest_array, i); } } } }