Initial project import
This commit is contained in:
319
node_modules/three-stdlib/loaders/PLYLoader.cjs
generated
vendored
Normal file
319
node_modules/three-stdlib/loaders/PLYLoader.cjs
generated
vendored
Normal file
@@ -0,0 +1,319 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
||||
const THREE = require("three");
|
||||
const LoaderUtils = require("../_polyfill/LoaderUtils.cjs");
|
||||
class PLYLoader extends THREE.Loader {
|
||||
constructor(manager) {
|
||||
super(manager);
|
||||
this.propertyNameMapping = {};
|
||||
}
|
||||
load(url, onLoad, onProgress, onError) {
|
||||
const scope = this;
|
||||
const loader = new THREE.FileLoader(this.manager);
|
||||
loader.setPath(this.path);
|
||||
loader.setResponseType("arraybuffer");
|
||||
loader.setRequestHeader(this.requestHeader);
|
||||
loader.setWithCredentials(this.withCredentials);
|
||||
loader.load(
|
||||
url,
|
||||
function(text) {
|
||||
try {
|
||||
onLoad(scope.parse(text));
|
||||
} catch (e) {
|
||||
if (onError) {
|
||||
onError(e);
|
||||
} else {
|
||||
console.error(e);
|
||||
}
|
||||
scope.manager.itemError(url);
|
||||
}
|
||||
},
|
||||
onProgress,
|
||||
onError
|
||||
);
|
||||
}
|
||||
setPropertyNameMapping(mapping) {
|
||||
this.propertyNameMapping = mapping;
|
||||
}
|
||||
parse(data) {
|
||||
function parseHeader(data2) {
|
||||
const patternHeader = /ply([\s\S]*)end_header\r?\n/;
|
||||
let headerText = "";
|
||||
let headerLength = 0;
|
||||
const result = patternHeader.exec(data2);
|
||||
if (result !== null) {
|
||||
headerText = result[1];
|
||||
headerLength = new Blob([result[0]]).size;
|
||||
}
|
||||
const header = {
|
||||
comments: [],
|
||||
elements: [],
|
||||
headerLength,
|
||||
objInfo: ""
|
||||
};
|
||||
const lines = headerText.split("\n");
|
||||
let currentElement;
|
||||
function make_ply_element_property(propertValues, propertyNameMapping) {
|
||||
const property = { type: propertValues[0] };
|
||||
if (property.type === "list") {
|
||||
property.name = propertValues[3];
|
||||
property.countType = propertValues[1];
|
||||
property.itemType = propertValues[2];
|
||||
} else {
|
||||
property.name = propertValues[1];
|
||||
}
|
||||
if (property.name in propertyNameMapping) {
|
||||
property.name = propertyNameMapping[property.name];
|
||||
}
|
||||
return property;
|
||||
}
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
let line = lines[i];
|
||||
line = line.trim();
|
||||
if (line === "")
|
||||
continue;
|
||||
const lineValues = line.split(/\s+/);
|
||||
const lineType = lineValues.shift();
|
||||
line = lineValues.join(" ");
|
||||
switch (lineType) {
|
||||
case "format":
|
||||
header.format = lineValues[0];
|
||||
header.version = lineValues[1];
|
||||
break;
|
||||
case "comment":
|
||||
header.comments.push(line);
|
||||
break;
|
||||
case "element":
|
||||
if (currentElement !== void 0) {
|
||||
header.elements.push(currentElement);
|
||||
}
|
||||
currentElement = {};
|
||||
currentElement.name = lineValues[0];
|
||||
currentElement.count = parseInt(lineValues[1]);
|
||||
currentElement.properties = [];
|
||||
break;
|
||||
case "property":
|
||||
currentElement.properties.push(make_ply_element_property(lineValues, scope.propertyNameMapping));
|
||||
break;
|
||||
case "obj_info":
|
||||
header.objInfo = line;
|
||||
break;
|
||||
default:
|
||||
console.log("unhandled", lineType, lineValues);
|
||||
}
|
||||
}
|
||||
if (currentElement !== void 0) {
|
||||
header.elements.push(currentElement);
|
||||
}
|
||||
return header;
|
||||
}
|
||||
function parseASCIINumber(n, type) {
|
||||
switch (type) {
|
||||
case "char":
|
||||
case "uchar":
|
||||
case "short":
|
||||
case "ushort":
|
||||
case "int":
|
||||
case "uint":
|
||||
case "int8":
|
||||
case "uint8":
|
||||
case "int16":
|
||||
case "uint16":
|
||||
case "int32":
|
||||
case "uint32":
|
||||
return parseInt(n);
|
||||
case "float":
|
||||
case "double":
|
||||
case "float32":
|
||||
case "float64":
|
||||
return parseFloat(n);
|
||||
}
|
||||
}
|
||||
function parseASCIIElement(properties, line) {
|
||||
const values = line.split(/\s+/);
|
||||
const element = {};
|
||||
for (let i = 0; i < properties.length; i++) {
|
||||
if (properties[i].type === "list") {
|
||||
const list = [];
|
||||
const n = parseASCIINumber(values.shift(), properties[i].countType);
|
||||
for (let j = 0; j < n; j++) {
|
||||
list.push(parseASCIINumber(values.shift(), properties[i].itemType));
|
||||
}
|
||||
element[properties[i].name] = list;
|
||||
} else {
|
||||
element[properties[i].name] = parseASCIINumber(values.shift(), properties[i].type);
|
||||
}
|
||||
}
|
||||
return element;
|
||||
}
|
||||
function parseASCII(data2, header) {
|
||||
const buffer = {
|
||||
indices: [],
|
||||
vertices: [],
|
||||
normals: [],
|
||||
uvs: [],
|
||||
faceVertexUvs: [],
|
||||
colors: []
|
||||
};
|
||||
let result;
|
||||
const patternBody = /end_header\s([\s\S]*)$/;
|
||||
let body = "";
|
||||
if ((result = patternBody.exec(data2)) !== null) {
|
||||
body = result[1];
|
||||
}
|
||||
const lines = body.split("\n");
|
||||
let currentElement = 0;
|
||||
let currentElementCount = 0;
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
let line = lines[i];
|
||||
line = line.trim();
|
||||
if (line === "") {
|
||||
continue;
|
||||
}
|
||||
if (currentElementCount >= header.elements[currentElement].count) {
|
||||
currentElement++;
|
||||
currentElementCount = 0;
|
||||
}
|
||||
const element = parseASCIIElement(header.elements[currentElement].properties, line);
|
||||
handleElement(buffer, header.elements[currentElement].name, element);
|
||||
currentElementCount++;
|
||||
}
|
||||
return postProcess(buffer);
|
||||
}
|
||||
function postProcess(buffer) {
|
||||
let geometry2 = new THREE.BufferGeometry();
|
||||
if (buffer.indices.length > 0) {
|
||||
geometry2.setIndex(buffer.indices);
|
||||
}
|
||||
geometry2.setAttribute("position", new THREE.Float32BufferAttribute(buffer.vertices, 3));
|
||||
if (buffer.normals.length > 0) {
|
||||
geometry2.setAttribute("normal", new THREE.Float32BufferAttribute(buffer.normals, 3));
|
||||
}
|
||||
if (buffer.uvs.length > 0) {
|
||||
geometry2.setAttribute("uv", new THREE.Float32BufferAttribute(buffer.uvs, 2));
|
||||
}
|
||||
if (buffer.colors.length > 0) {
|
||||
geometry2.setAttribute("color", new THREE.Float32BufferAttribute(buffer.colors, 3));
|
||||
}
|
||||
if (buffer.faceVertexUvs.length > 0) {
|
||||
geometry2 = geometry2.toNonIndexed();
|
||||
geometry2.setAttribute("uv", new THREE.Float32BufferAttribute(buffer.faceVertexUvs, 2));
|
||||
}
|
||||
geometry2.computeBoundingSphere();
|
||||
return geometry2;
|
||||
}
|
||||
function handleElement(buffer, elementName, element) {
|
||||
if (elementName === "vertex") {
|
||||
buffer.vertices.push(element.x, element.y, element.z);
|
||||
if ("nx" in element && "ny" in element && "nz" in element) {
|
||||
buffer.normals.push(element.nx, element.ny, element.nz);
|
||||
}
|
||||
if ("s" in element && "t" in element) {
|
||||
buffer.uvs.push(element.s, element.t);
|
||||
}
|
||||
if ("red" in element && "green" in element && "blue" in element) {
|
||||
buffer.colors.push(element.red / 255, element.green / 255, element.blue / 255);
|
||||
}
|
||||
} else if (elementName === "face") {
|
||||
const vertex_indices = element.vertex_indices || element.vertex_index;
|
||||
const texcoord = element.texcoord;
|
||||
if (vertex_indices.length === 3) {
|
||||
buffer.indices.push(vertex_indices[0], vertex_indices[1], vertex_indices[2]);
|
||||
if (texcoord && texcoord.length === 6) {
|
||||
buffer.faceVertexUvs.push(texcoord[0], texcoord[1]);
|
||||
buffer.faceVertexUvs.push(texcoord[2], texcoord[3]);
|
||||
buffer.faceVertexUvs.push(texcoord[4], texcoord[5]);
|
||||
}
|
||||
} else if (vertex_indices.length === 4) {
|
||||
buffer.indices.push(vertex_indices[0], vertex_indices[1], vertex_indices[3]);
|
||||
buffer.indices.push(vertex_indices[1], vertex_indices[2], vertex_indices[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
function binaryRead(dataview, at, type, little_endian) {
|
||||
switch (type) {
|
||||
case "int8":
|
||||
case "char":
|
||||
return [dataview.getInt8(at), 1];
|
||||
case "uint8":
|
||||
case "uchar":
|
||||
return [dataview.getUint8(at), 1];
|
||||
case "int16":
|
||||
case "short":
|
||||
return [dataview.getInt16(at, little_endian), 2];
|
||||
case "uint16":
|
||||
case "ushort":
|
||||
return [dataview.getUint16(at, little_endian), 2];
|
||||
case "int32":
|
||||
case "int":
|
||||
return [dataview.getInt32(at, little_endian), 4];
|
||||
case "uint32":
|
||||
case "uint":
|
||||
return [dataview.getUint32(at, little_endian), 4];
|
||||
case "float32":
|
||||
case "float":
|
||||
return [dataview.getFloat32(at, little_endian), 4];
|
||||
case "float64":
|
||||
case "double":
|
||||
return [dataview.getFloat64(at, little_endian), 8];
|
||||
}
|
||||
}
|
||||
function binaryReadElement(dataview, at, properties, little_endian) {
|
||||
const element = {};
|
||||
let result, read = 0;
|
||||
for (let i = 0; i < properties.length; i++) {
|
||||
if (properties[i].type === "list") {
|
||||
const list = [];
|
||||
result = binaryRead(dataview, at + read, properties[i].countType, little_endian);
|
||||
const n = result[0];
|
||||
read += result[1];
|
||||
for (let j = 0; j < n; j++) {
|
||||
result = binaryRead(dataview, at + read, properties[i].itemType, little_endian);
|
||||
list.push(result[0]);
|
||||
read += result[1];
|
||||
}
|
||||
element[properties[i].name] = list;
|
||||
} else {
|
||||
result = binaryRead(dataview, at + read, properties[i].type, little_endian);
|
||||
element[properties[i].name] = result[0];
|
||||
read += result[1];
|
||||
}
|
||||
}
|
||||
return [element, read];
|
||||
}
|
||||
function parseBinary(data2, header) {
|
||||
const buffer = {
|
||||
indices: [],
|
||||
vertices: [],
|
||||
normals: [],
|
||||
uvs: [],
|
||||
faceVertexUvs: [],
|
||||
colors: []
|
||||
};
|
||||
const little_endian = header.format === "binary_little_endian";
|
||||
const body = new DataView(data2, header.headerLength);
|
||||
let result, loc = 0;
|
||||
for (let currentElement = 0; currentElement < header.elements.length; currentElement++) {
|
||||
for (let currentElementCount = 0; currentElementCount < header.elements[currentElement].count; currentElementCount++) {
|
||||
result = binaryReadElement(body, loc, header.elements[currentElement].properties, little_endian);
|
||||
loc += result[1];
|
||||
const element = result[0];
|
||||
handleElement(buffer, header.elements[currentElement].name, element);
|
||||
}
|
||||
}
|
||||
return postProcess(buffer);
|
||||
}
|
||||
let geometry;
|
||||
const scope = this;
|
||||
if (data instanceof ArrayBuffer) {
|
||||
const text = LoaderUtils.decodeText(new Uint8Array(data));
|
||||
const header = parseHeader(text);
|
||||
geometry = header.format === "ascii" ? parseASCII(text, header) : parseBinary(data, header);
|
||||
} else {
|
||||
geometry = parseASCII(data, parseHeader(data));
|
||||
}
|
||||
return geometry;
|
||||
}
|
||||
}
|
||||
exports.PLYLoader = PLYLoader;
|
||||
//# sourceMappingURL=PLYLoader.cjs.map
|
||||
Reference in New Issue
Block a user