(function (global, factory) { if (typeof define === "function" && define.amd) { define(["exports", "three"], factory); } else if (typeof exports !== "undefined") { factory(exports, require("three")); } else { var mod = { exports: {} }; factory(mod.exports, global.three); global.PCDLoader = mod.exports; } })(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports, _three) { "use strict"; Object.defineProperty(_exports, "__esModule", { value: true }); _exports.PCDLoader = void 0; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } Object.defineProperty(subClass, "prototype", { value: Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }), writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } var PCDLoader = /*#__PURE__*/function (_Loader) { _inherits(PCDLoader, _Loader); var _super = _createSuper(PCDLoader); function PCDLoader(manager) { var _this; _classCallCheck(this, PCDLoader); _this = _super.call(this, manager); _this.littleEndian = true; return _this; } _createClass(PCDLoader, [{ key: "load", value: function load(url, onLoad, onProgress, onError) { var scope = this; var loader = new _three.FileLoader(scope.manager); loader.setPath(scope.path); loader.setResponseType('arraybuffer'); loader.setRequestHeader(scope.requestHeader); loader.setWithCredentials(scope.withCredentials); loader.load(url, function (data) { try { onLoad(scope.parse(data, url)); } catch (e) { if (onError) { onError(e); } else { console.error(e); } scope.manager.itemError(url); } }, onProgress, onError); } }, { key: "parse", value: function parse(data, url) { // from https://gitlab.com/taketwo/three-pcd-loader/blob/master/decompress-lzf.js function decompressLZF(inData, outLength) { var inLength = inData.length; var outData = new Uint8Array(outLength); var inPtr = 0; var outPtr = 0; var ctrl; var len; var ref; do { ctrl = inData[inPtr++]; if (ctrl < 1 << 5) { ctrl++; if (outPtr + ctrl > outLength) throw new Error('Output buffer is not large enough'); if (inPtr + ctrl > inLength) throw new Error('Invalid compressed data'); do { outData[outPtr++] = inData[inPtr++]; } while (--ctrl); } else { len = ctrl >> 5; ref = outPtr - ((ctrl & 0x1f) << 8) - 1; if (inPtr >= inLength) throw new Error('Invalid compressed data'); if (len === 7) { len += inData[inPtr++]; if (inPtr >= inLength) throw new Error('Invalid compressed data'); } ref -= inData[inPtr++]; if (outPtr + len + 2 > outLength) throw new Error('Output buffer is not large enough'); if (ref < 0) throw new Error('Invalid compressed data'); if (ref >= outPtr) throw new Error('Invalid compressed data'); do { outData[outPtr++] = outData[ref++]; } while (--len + 2); } } while (inPtr < inLength); return outData; } function parseHeader(data) { var PCDheader = {}; var result1 = data.search(/[\r\n]DATA\s(\S*)\s/i); var result2 = /[\r\n]DATA\s(\S*)\s/i.exec(data.substr(result1 - 1)); PCDheader.data = result2[1]; PCDheader.headerLen = result2[0].length + result1; PCDheader.str = data.substr(0, PCDheader.headerLen); // remove comments PCDheader.str = PCDheader.str.replace(/\#.*/gi, ''); // parse PCDheader.version = /VERSION (.*)/i.exec(PCDheader.str); PCDheader.fields = /FIELDS (.*)/i.exec(PCDheader.str); PCDheader.size = /SIZE (.*)/i.exec(PCDheader.str); PCDheader.type = /TYPE (.*)/i.exec(PCDheader.str); PCDheader.count = /COUNT (.*)/i.exec(PCDheader.str); PCDheader.width = /WIDTH (.*)/i.exec(PCDheader.str); PCDheader.height = /HEIGHT (.*)/i.exec(PCDheader.str); PCDheader.viewpoint = /VIEWPOINT (.*)/i.exec(PCDheader.str); PCDheader.points = /POINTS (.*)/i.exec(PCDheader.str); // evaluate if (PCDheader.version !== null) PCDheader.version = parseFloat(PCDheader.version[1]); if (PCDheader.fields !== null) PCDheader.fields = PCDheader.fields[1].split(' '); if (PCDheader.type !== null) PCDheader.type = PCDheader.type[1].split(' '); if (PCDheader.width !== null) PCDheader.width = parseInt(PCDheader.width[1]); if (PCDheader.height !== null) PCDheader.height = parseInt(PCDheader.height[1]); if (PCDheader.viewpoint !== null) PCDheader.viewpoint = PCDheader.viewpoint[1]; if (PCDheader.points !== null) PCDheader.points = parseInt(PCDheader.points[1], 10); if (PCDheader.points === null) PCDheader.points = PCDheader.width * PCDheader.height; if (PCDheader.size !== null) { PCDheader.size = PCDheader.size[1].split(' ').map(function (x) { return parseInt(x, 10); }); } if (PCDheader.count !== null) { PCDheader.count = PCDheader.count[1].split(' ').map(function (x) { return parseInt(x, 10); }); } else { PCDheader.count = []; for (var i = 0, l = PCDheader.fields.length; i < l; i++) { PCDheader.count.push(1); } } PCDheader.offset = {}; var sizeSum = 0; for (var _i = 0, _l = PCDheader.fields.length; _i < _l; _i++) { if (PCDheader.data === 'ascii') { PCDheader.offset[PCDheader.fields[_i]] = _i; } else { PCDheader.offset[PCDheader.fields[_i]] = sizeSum; sizeSum += PCDheader.size[_i] * PCDheader.count[_i]; } } // for binary only PCDheader.rowSize = sizeSum; return PCDheader; } var textData = _three.LoaderUtils.decodeText(new Uint8Array(data)); // parse header (always ascii format) var PCDheader = parseHeader(textData); // parse data var position = []; var normal = []; var color = []; // ascii if (PCDheader.data === 'ascii') { var offset = PCDheader.offset; var pcdData = textData.substr(PCDheader.headerLen); var lines = pcdData.split('\n'); for (var i = 0, l = lines.length; i < l; i++) { if (lines[i] === '') continue; var line = lines[i].split(' '); if (offset.x !== undefined) { position.push(parseFloat(line[offset.x])); position.push(parseFloat(line[offset.y])); position.push(parseFloat(line[offset.z])); } if (offset.rgb !== undefined) { var rgb = parseFloat(line[offset.rgb]); var r = rgb >> 16 & 0x0000ff; var g = rgb >> 8 & 0x0000ff; var b = rgb >> 0 & 0x0000ff; color.push(r / 255, g / 255, b / 255); } if (offset.normal_x !== undefined) { normal.push(parseFloat(line[offset.normal_x])); normal.push(parseFloat(line[offset.normal_y])); normal.push(parseFloat(line[offset.normal_z])); } } } // binary-compressed // normally data in PCD files are organized as array of structures: XYZRGBXYZRGB // binary compressed PCD files organize their data as structure of arrays: XXYYZZRGBRGB // that requires a totally different parsing approach compared to non-compressed data if (PCDheader.data === 'binary_compressed') { var sizes = new Uint32Array(data.slice(PCDheader.headerLen, PCDheader.headerLen + 8)); var compressedSize = sizes[0]; var decompressedSize = sizes[1]; var decompressed = decompressLZF(new Uint8Array(data, PCDheader.headerLen + 8, compressedSize), decompressedSize); var dataview = new DataView(decompressed.buffer); var _offset = PCDheader.offset; for (var _i2 = 0; _i2 < PCDheader.points; _i2++) { if (_offset.x !== undefined) { position.push(dataview.getFloat32(PCDheader.points * _offset.x + PCDheader.size[0] * _i2, this.littleEndian)); position.push(dataview.getFloat32(PCDheader.points * _offset.y + PCDheader.size[1] * _i2, this.littleEndian)); position.push(dataview.getFloat32(PCDheader.points * _offset.z + PCDheader.size[2] * _i2, this.littleEndian)); } if (_offset.rgb !== undefined) { color.push(dataview.getUint8(PCDheader.points * _offset.rgb + PCDheader.size[3] * _i2 + 0) / 255.0); color.push(dataview.getUint8(PCDheader.points * _offset.rgb + PCDheader.size[3] * _i2 + 1) / 255.0); color.push(dataview.getUint8(PCDheader.points * _offset.rgb + PCDheader.size[3] * _i2 + 2) / 255.0); } if (_offset.normal_x !== undefined) { normal.push(dataview.getFloat32(PCDheader.points * _offset.normal_x + PCDheader.size[4] * _i2, this.littleEndian)); normal.push(dataview.getFloat32(PCDheader.points * _offset.normal_y + PCDheader.size[5] * _i2, this.littleEndian)); normal.push(dataview.getFloat32(PCDheader.points * _offset.normal_z + PCDheader.size[6] * _i2, this.littleEndian)); } } } // binary if (PCDheader.data === 'binary') { var _dataview = new DataView(data, PCDheader.headerLen); var _offset2 = PCDheader.offset; for (var _i3 = 0, row = 0; _i3 < PCDheader.points; _i3++, row += PCDheader.rowSize) { if (_offset2.x !== undefined) { position.push(_dataview.getFloat32(row + _offset2.x, this.littleEndian)); position.push(_dataview.getFloat32(row + _offset2.y, this.littleEndian)); position.push(_dataview.getFloat32(row + _offset2.z, this.littleEndian)); } if (_offset2.rgb !== undefined) { color.push(_dataview.getUint8(row + _offset2.rgb + 2) / 255.0); color.push(_dataview.getUint8(row + _offset2.rgb + 1) / 255.0); color.push(_dataview.getUint8(row + _offset2.rgb + 0) / 255.0); } if (_offset2.normal_x !== undefined) { normal.push(_dataview.getFloat32(row + _offset2.normal_x, this.littleEndian)); normal.push(_dataview.getFloat32(row + _offset2.normal_y, this.littleEndian)); normal.push(_dataview.getFloat32(row + _offset2.normal_z, this.littleEndian)); } } } // build geometry var geometry = new _three.BufferGeometry(); if (position.length > 0) geometry.setAttribute('position', new _three.Float32BufferAttribute(position, 3)); if (normal.length > 0) geometry.setAttribute('normal', new _three.Float32BufferAttribute(normal, 3)); if (color.length > 0) geometry.setAttribute('color', new _three.Float32BufferAttribute(color, 3)); geometry.computeBoundingSphere(); // build material var material = new _three.PointsMaterial({ size: 0.005 }); if (color.length > 0) { material.vertexColors = true; } else { material.color.setHex(Math.random() * 0xffffff); } // build point cloud var mesh = new _three.Points(geometry, material); var name = url.split('').reverse().join(''); name = /([^\/]*)/.exec(name); name = name[1].split('').reverse().join(''); mesh.name = name; return mesh; } }]); return PCDLoader; }(_three.Loader); _exports.PCDLoader = PCDLoader; });