@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
143 lines (142 loc) • 5.56 kB
JavaScript
"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 = ",";