UNPKG

@polygonjs/polygonjs

Version:

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

143 lines (142 loc) 5.56 kB
"use strict"; import { Float32BufferAttribute, Mesh } from "three"; import { BufferGeometry } from "three"; import { CoreAttributeData } from "../../geometry/AttributeData"; import { Attribute, CoreAttribute } from "../../geometry/Attribute"; import { AttribType } from "../../geometry/Constant"; import { isString } from "../../Type"; import { CoreBaseLoader } from "../_Base"; import { ThreejsPoint } from "../../geometry/modules/three/ThreejsPoint"; const dummyMesh = new Mesh(); const _CsvLoader = class extends CoreBaseLoader { constructor(url, attribute_names, _node) { super(url, _node); this.attribute_names = attribute_names; this._node = _node; this.attribute_names_from_first_line = false; this.lines = []; this.points_count = 0; this.attribute_values_by_name = {}; // const attribute_types_by_name: PolyDictionary<AttribType> = {}; // const attribute_sizes_by_name: PolyDictionary<1|2|3|4> = {}; this.attribute_data_by_name = {}; this._loading = false; if (!this.attribute_names) { this.attribute_names_from_first_line = true; } } async load() { if (this._loading) { console.warn("is already loading"); return; } this._loading = true; this.points_count = 0; await this.loadData(); this.infer_types(); this.read_values(); const geometry = this.create_points(); return geometry; } async loadData() { const url = this._urlToLoad(); const response = await fetch(url); const text = await response.text(); this.lines = text.split("\n"); if (!this.attribute_names) { this.attribute_names = this.lines[0].split(_CsvLoader.SEPARATOR); } this.attribute_names = this.attribute_names.map((name) => CoreAttribute.remapName(name)); for (const attribute_name of this.attribute_names) { this.attribute_values_by_name[attribute_name] = []; } } infer_types() { const first_values_index = this.attribute_names_from_first_line ? 1 : 0; const first_line = this.lines[first_values_index]; let line_attribute_values = first_line.split(_CsvLoader.SEPARATOR); for (let i = 0; i < line_attribute_values.length; i++) { const attribute_name = this.attribute_names[i]; const attribute_value = line_attribute_values[i]; const value = this._value_from_line_element(attribute_value); this.attribute_data_by_name[attribute_name] = CoreAttributeData.from_value(value); } } _value_from_line_element(attribute_value) { if (isString(attribute_value)) { if (`${parseFloat(attribute_value)}` === attribute_value) { return parseFloat(attribute_value); } else if (attribute_value[0] === "[" && attribute_value[attribute_value.length - 1] === "]") { const attribute_value_within_brackets = attribute_value.substring(1, attribute_value.length - 1); const elements_s = attribute_value_within_brackets.split(_CsvLoader.VECTOR_SEPARATOR); return elements_s.map((element_s) => parseFloat(element_s)); } else { return attribute_value; } } else { return attribute_value; } } read_values() { if (!this.attribute_names) { return; } const first_values_index = this.attribute_names_from_first_line ? 1 : 0; let line; for (let line_index = first_values_index; line_index < this.lines.length; line_index++) { line = this.lines[line_index]; const line_attribute_values = line.split(_CsvLoader.SEPARATOR); if (line_attribute_values.length >= this.attribute_names.length) { for (let i = 0; i < line_attribute_values.length; i++) { const attribute_name = this.attribute_names[i]; if (attribute_name) { const attribute_value = line_attribute_values[i]; const value = this._value_from_line_element(attribute_value); this.attribute_values_by_name[attribute_name].push(value); } } this.points_count += 1; } } if (!this.attribute_values_by_name[Attribute.POSITION]) { const positions = new Array(this.points_count * 3); positions.fill(0); this.attribute_values_by_name[Attribute.POSITION] = positions; this.attribute_data_by_name[Attribute.POSITION] = new CoreAttributeData(3, AttribType.NUMERIC); this.attribute_names.push(Attribute.POSITION); } } create_points() { if (!this.attribute_names) { return; } const geometry = new BufferGeometry(); dummyMesh.geometry = geometry; const corePointClass = ThreejsPoint; for (const attribute_name of this.attribute_names) { const attribute_values = this.attribute_values_by_name[attribute_name].flat(); const size = this.attribute_data_by_name[attribute_name].size(); const type = this.attribute_data_by_name[attribute_name].type(); if (type == AttribType.STRING) { const index_data = CoreAttribute.arrayToIndexedArrays(attribute_values); corePointClass.setIndexedAttribute( dummyMesh, attribute_name, index_data["values"], index_data["indices"] ); } else { geometry.setAttribute(attribute_name, new Float32BufferAttribute(attribute_values, size)); } } const indices = new Array(this.points_count); for (let i = 0; i < this.points_count; i++) { indices.push(i); } geometry.setIndex(indices); return geometry; } }; export let CsvLoader = _CsvLoader; CsvLoader.SEPARATOR = ","; CsvLoader.VECTOR_SEPARATOR = ",";