123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 |
- /**
- * Some types of possible point attribute data formats
- *
- * @class
- */
- var PointAttributeTypes = {
- DATA_TYPE_DOUBLE: {
- ordinal: 0,
- name: "double",
- size: 8
- },
- DATA_TYPE_FLOAT: {
- ordinal: 1,
- name: "float",
- size: 4
- },
- DATA_TYPE_INT8: {
- ordinal: 2,
- name: "int8",
- size: 1
- },
- DATA_TYPE_UINT8: {
- ordinal: 3,
- name: "uint8",
- size: 1
- },
- DATA_TYPE_INT16: {
- ordinal: 4,
- name: "int16",
- size: 2
- },
- DATA_TYPE_UINT16: {
- ordinal: 5,
- name: "uint16",
- size: 2
- },
- DATA_TYPE_INT32: {
- ordinal: 6,
- name: "int32",
- size: 4
- },
- DATA_TYPE_UINT32: {
- ordinal: 7,
- name: "uint32",
- size: 4
- },
- DATA_TYPE_INT64: {
- ordinal: 8,
- name: "int64",
- size: 8
- },
- DATA_TYPE_UINT64: {
- ordinal: 9,
- name: "uint64",
- size: 8
- }
- };
- var i = 0;
- for (var obj in PointAttributeTypes) {
- PointAttributeTypes[i] = PointAttributeTypes[obj];
- i++;
- }
- class PointAttribute {
- constructor(name, type, numElements) {
- this.name = name;
- this.type = type;
- this.numElements = numElements;
- this.byteSize = this.numElements * this.type.size;
- this.description = "";
- this.range = [Infinity, -Infinity];
- }
- }
- PointAttribute.POSITION_CARTESIAN = new PointAttribute("POSITION_CARTESIAN", PointAttributeTypes.DATA_TYPE_FLOAT, 3);
- PointAttribute.RGBA_PACKED = new PointAttribute("COLOR_PACKED", PointAttributeTypes.DATA_TYPE_INT8, 4);
- PointAttribute.COLOR_PACKED = PointAttribute.RGBA_PACKED;
- PointAttribute.RGB_PACKED = new PointAttribute("COLOR_PACKED", PointAttributeTypes.DATA_TYPE_INT8, 3);
- PointAttribute.NORMAL_FLOATS = new PointAttribute("NORMAL_FLOATS", PointAttributeTypes.DATA_TYPE_FLOAT, 3);
- PointAttribute.INTENSITY = new PointAttribute("INTENSITY", PointAttributeTypes.DATA_TYPE_UINT16, 1);
- PointAttribute.CLASSIFICATION = new PointAttribute("CLASSIFICATION", PointAttributeTypes.DATA_TYPE_UINT8, 1);
- PointAttribute.NORMAL_SPHEREMAPPED = new PointAttribute("NORMAL_SPHEREMAPPED", PointAttributeTypes.DATA_TYPE_UINT8, 2);
- PointAttribute.NORMAL_OCT16 = new PointAttribute("NORMAL_OCT16", PointAttributeTypes.DATA_TYPE_UINT8, 2);
- PointAttribute.NORMAL = new PointAttribute("NORMAL", PointAttributeTypes.DATA_TYPE_FLOAT, 3);
- PointAttribute.RETURN_NUMBER = new PointAttribute("RETURN_NUMBER", PointAttributeTypes.DATA_TYPE_UINT8, 1);
- PointAttribute.NUMBER_OF_RETURNS = new PointAttribute("NUMBER_OF_RETURNS", PointAttributeTypes.DATA_TYPE_UINT8, 1);
- PointAttribute.SOURCE_ID = new PointAttribute("SOURCE_ID", PointAttributeTypes.DATA_TYPE_UINT16, 1);
- PointAttribute.INDICES = new PointAttribute("INDICES", PointAttributeTypes.DATA_TYPE_UINT32, 1);
- PointAttribute.SPACING = new PointAttribute("SPACING", PointAttributeTypes.DATA_TYPE_FLOAT, 1);
- PointAttribute.GPS_TIME = new PointAttribute("GPS_TIME", PointAttributeTypes.DATA_TYPE_DOUBLE, 1);
- // import {Version} from "../../Version.js";
- var typedArrayMapping = {
- "int8": Int8Array,
- "int16": Int16Array,
- "int32": Int32Array,
- "int64": Float64Array,
- "uint8": Uint8Array,
- "uint16": Uint16Array,
- "uint32": Uint32Array,
- "uint64": Float64Array,
- "float": Float32Array,
- "double": Float64Array
- };
- Potree = {};
- onmessage = function onmessage(event) {
- var {
- buffer,
- pointAttributes,
- scale,
- name,
- min,
- max,
- size,
- offset,
- numPoints
- } = event.data;
- var tStart = performance.now();
- var view = new DataView(buffer);
- var attributeBuffers = {};
- var attributeOffset = 0;
- var bytesPerPoint = 0;
- for (var pointAttribute of pointAttributes.attributes) {
- bytesPerPoint += pointAttribute.byteSize;
- }
- var gridSize = 32;
- var grid = new Uint32Array(gridSize ** 3);
- var toIndex = (x, y, z) => {
- // let dx = gridSize * (x - min.x) / size.x;
- // let dy = gridSize * (y - min.y) / size.y;
- // let dz = gridSize * (z - min.z) / size.z;
- // min is already subtracted
- var dx = gridSize * x / size.x;
- var dy = gridSize * y / size.y;
- var dz = gridSize * z / size.z;
- var ix = Math.min(parseInt(dx), gridSize - 1);
- var iy = Math.min(parseInt(dy), gridSize - 1);
- var iz = Math.min(parseInt(dz), gridSize - 1);
- var index = ix + iy * gridSize + iz * gridSize * gridSize;
- return index;
- };
- var numOccupiedCells = 0;
- for (var _pointAttribute of pointAttributes.attributes) {
- if (["POSITION_CARTESIAN", "position"].includes(_pointAttribute.name)) {
- var buff = new ArrayBuffer(numPoints * 4 * 3);
- var positions = new Float32Array(buff);
- for (var j = 0; j < numPoints; j++) {
- var pointOffset = j * bytesPerPoint;
- var x = view.getInt32(pointOffset + attributeOffset + 0, true) * scale[0] + offset[0] - min.x;
- var y = view.getInt32(pointOffset + attributeOffset + 4, true) * scale[1] + offset[1] - min.y;
- var z = view.getInt32(pointOffset + attributeOffset + 8, true) * scale[2] + offset[2] - min.z;
- var index = toIndex(x, y, z);
- var count = grid[index]++;
- if (count === 0) {
- numOccupiedCells++;
- }
- positions[3 * j + 0] = x;
- positions[3 * j + 1] = y;
- positions[3 * j + 2] = z;
- }
- attributeBuffers[_pointAttribute.name] = {
- buffer: buff,
- attribute: _pointAttribute
- };
- } else if (["RGBA", "rgba"].includes(_pointAttribute.name)) {
- var _buff = new ArrayBuffer(numPoints * 4);
- var colors = new Uint8Array(_buff);
- for (var _j = 0; _j < numPoints; _j++) {
- var _pointOffset = _j * bytesPerPoint;
- var r = view.getUint16(_pointOffset + attributeOffset + 0, true);
- var g = view.getUint16(_pointOffset + attributeOffset + 2, true);
- var b = view.getUint16(_pointOffset + attributeOffset + 4, true);
- colors[4 * _j + 0] = r > 255 ? r / 256 : r;
- colors[4 * _j + 1] = g > 255 ? g / 256 : g;
- colors[4 * _j + 2] = b > 255 ? b / 256 : b;
- }
- attributeBuffers[_pointAttribute.name] = {
- buffer: _buff,
- attribute: _pointAttribute
- };
- } else {
- var _buff2 = new ArrayBuffer(numPoints * 4);
- var f32 = new Float32Array(_buff2);
- var TypedArray = typedArrayMapping[_pointAttribute.type.name];
- preciseBuffer = new TypedArray(numPoints);
- var [_offset, _scale] = [0, 1];
- var getterMap = {
- "int8": view.getInt8,
- "int16": view.getInt16,
- "int32": view.getInt32,
- // "int64": view.getInt64,
- "uint8": view.getUint8,
- "uint16": view.getUint16,
- "uint32": view.getUint32,
- // "uint64": view.getUint64,
- "float": view.getFloat32,
- "double": view.getFloat64
- };
- var getter = getterMap[_pointAttribute.type.name].bind(view);
- // compute offset and scale to pack larger types into 32 bit floats
- if (_pointAttribute.type.size > 4) {
- var [amin, amax] = _pointAttribute.range;
- _offset = amin;
- _scale = 1 / (amax - amin);
- }
- for (var _j2 = 0; _j2 < numPoints; _j2++) {
- var _pointOffset2 = _j2 * bytesPerPoint;
- var value = getter(_pointOffset2 + attributeOffset, true);
- f32[_j2] = (value - _offset) * _scale;
- preciseBuffer[_j2] = value;
- }
- attributeBuffers[_pointAttribute.name] = {
- buffer: _buff2,
- preciseBuffer: preciseBuffer,
- attribute: _pointAttribute,
- offset: _offset,
- scale: _scale
- };
- }
- attributeOffset += _pointAttribute.byteSize;
- }
- var occupancy = parseInt(numPoints / numOccupiedCells);
- // console.log(`${name}: #points: ${numPoints}: #occupiedCells: ${numOccupiedCells}, occupancy: ${occupancy} points/cell`);
- {
- // add indices
- var _buff3 = new ArrayBuffer(numPoints * 4);
- var indices = new Uint32Array(_buff3);
- for (var i = 0; i < numPoints; i++) {
- indices[i] = i;
- }
- attributeBuffers["INDICES"] = {
- buffer: _buff3,
- attribute: PointAttribute.INDICES
- };
- }
- {
- // handle attribute vectors
- var vectors = pointAttributes.vectors;
- for (var vector of vectors) {
- var {
- name: _name,
- attributes
- } = vector;
- var numVectorElements = attributes.length;
- var _buffer = new ArrayBuffer(numVectorElements * numPoints * 4);
- var _f = new Float32Array(_buffer);
- var iElement = 0;
- for (var sourceName of attributes) {
- var sourceBuffer = attributeBuffers[sourceName];
- var {
- offset: _offset2,
- scale: _scale2
- } = sourceBuffer;
- var _view = new DataView(sourceBuffer.buffer);
- var _getter = _view.getFloat32.bind(_view);
- for (var _j3 = 0; _j3 < numPoints; _j3++) {
- var _value = _getter(_j3 * 4, true);
- _f[_j3 * numVectorElements + iElement] = _value / _scale2 + _offset2;
- }
- iElement++;
- }
- var vecAttribute = new PointAttribute(_name, PointAttributeTypes.DATA_TYPE_FLOAT, 3);
- attributeBuffers[_name] = {
- buffer: _buffer,
- attribute: vecAttribute
- };
- }
- }
- // let duration = performance.now() - tStart;
- // let pointsPerMs = numPoints / duration;
- // console.log(`duration: ${duration.toFixed(1)}ms, #points: ${numPoints}, points/ms: ${pointsPerMs.toFixed(1)}`);
- var message = {
- buffer: buffer,
- attributeBuffers: attributeBuffers,
- density: occupancy
- };
- var transferables = [];
- for (var property in message.attributeBuffers) {
- transferables.push(message.attributeBuffers[property].buffer);
- }
- transferables.push(buffer);
- postMessage(message, transferables);
- };
|