@sauskylark/potree
Version:
WebGL point cloud viewer
155 lines (122 loc) • 4.84 kB
JavaScript
import * as THREE from "../../libs/three.js/build/three.module.js";
import {Version} from "../Version.js";
import {XHRFactory} from "../XHRFactory.js";
export class BinaryLoader{
constructor(version, boundingBox, scale){
if (typeof (version) === 'string') {
this.version = new Version(version);
} else {
this.version = version;
}
this.boundingBox = boundingBox;
this.scale = scale;
}
load(node){
if (node.loaded) {
return;
}
let url = node.getURL();
if (this.version.equalOrHigher('1.4')) {
url += '.bin';
}
let xhr = XHRFactory.createXMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'arraybuffer';
xhr.overrideMimeType('text/plain; charset=x-user-defined');
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if((xhr.status === 200 || xhr.status === 0) && xhr.response !== null){
let buffer = xhr.response;
this.parse(node, buffer);
} else {
//console.error(`Failed to load file! HTTP status: ${xhr.status}, file: ${url}`);
throw new Error(`Failed to load file! HTTP status: ${xhr.status}, file: ${url}`);
}
}
};
try {
xhr.send(null);
} catch (e) {
console.log('fehler beim laden der punktwolke: ' + e);
}
};
parse(node, buffer){
let pointAttributes = node.pcoGeometry.pointAttributes;
let numPoints = buffer.byteLength / node.pcoGeometry.pointAttributes.byteSize;
if (this.version.upTo('1.5')) {
node.numPoints = numPoints;
}
let workerPath = Potree.scriptPath + '/workers/BinaryDecoderWorker.js';
let worker = Potree.workerPool.getWorker(workerPath);
worker.onmessage = function (e) {
let data = e.data;
let buffers = data.attributeBuffers;
let tightBoundingBox = new THREE.Box3(
new THREE.Vector3().fromArray(data.tightBoundingBox.min),
new THREE.Vector3().fromArray(data.tightBoundingBox.max)
);
Potree.workerPool.returnWorker(workerPath, worker);
let geometry = new THREE.BufferGeometry();
for(let property in buffers){
let buffer = buffers[property].buffer;
let batchAttribute = buffers[property].attribute;
if (property === "POSITION_CARTESIAN") {
geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(buffer), 3));
} else if (property === "rgba") {
geometry.setAttribute("rgba", new THREE.BufferAttribute(new Uint8Array(buffer), 4, true));
} else if (property === "NORMAL_SPHEREMAPPED") {
geometry.setAttribute('normal', new THREE.BufferAttribute(new Float32Array(buffer), 3));
} else if (property === "NORMAL_OCT16") {
geometry.setAttribute('normal', new THREE.BufferAttribute(new Float32Array(buffer), 3));
} else if (property === "NORMAL") {
geometry.setAttribute('normal', new THREE.BufferAttribute(new Float32Array(buffer), 3));
} else if (property === "INDICES") {
let bufferAttribute = new THREE.BufferAttribute(new Uint8Array(buffer), 4);
bufferAttribute.normalized = true;
geometry.setAttribute('indices', bufferAttribute);
} else if (property === "SPACING") {
let bufferAttribute = new THREE.BufferAttribute(new Float32Array(buffer), 1);
geometry.setAttribute('spacing', bufferAttribute);
} else {
const bufferAttribute = new THREE.BufferAttribute(new Float32Array(buffer), 1);
bufferAttribute.potree = {
offset: buffers[property].offset,
scale: buffers[property].scale,
preciseBuffer: buffers[property].preciseBuffer,
range: batchAttribute.range,
};
geometry.setAttribute(property, bufferAttribute);
const attribute = pointAttributes.attributes.find(a => a.name === batchAttribute.name);
attribute.range[0] = Math.min(attribute.range[0], batchAttribute.range[0]);
attribute.range[1] = Math.max(attribute.range[1], batchAttribute.range[1]);
if(node.getLevel() === 0){
attribute.initialRange = batchAttribute.range;
}
}
}
tightBoundingBox.max.sub(tightBoundingBox.min);
tightBoundingBox.min.set(0, 0, 0);
let numPoints = e.data.buffer.byteLength / pointAttributes.byteSize;
node.numPoints = numPoints;
node.geometry = geometry;
node.mean = new THREE.Vector3(...data.mean);
node.tightBoundingBox = tightBoundingBox;
node.loaded = true;
node.loading = false;
node.estimatedSpacing = data.estimatedSpacing;
Potree.numNodesLoading--;
};
let message = {
buffer: buffer,
pointAttributes: pointAttributes,
version: this.version.version,
min: [ node.boundingBox.min.x, node.boundingBox.min.y, node.boundingBox.min.z ],
offset: [node.pcoGeometry.offset.x, node.pcoGeometry.offset.y, node.pcoGeometry.offset.z],
scale: this.scale,
spacing: node.spacing,
hasChildren: node.hasChildren,
name: node.name
};
worker.postMessage(message, [message.buffer]);
};
}