class Version { constructor(version) { this.version = version; var vmLength = version.indexOf('.') === -1 ? version.length : version.indexOf('.'); this.versionMajor = parseInt(version.substr(0, vmLength)); this.versionMinor = parseInt(version.substr(vmLength + 1)); if (this.versionMinor.length === 0) { this.versionMinor = 0; } } newerThan(version) { var v = new Version(version); if (this.versionMajor > v.versionMajor) { return true; } else if (this.versionMajor === v.versionMajor && this.versionMinor > v.versionMinor) { return true; } else { return false; } } equalOrHigher(version) { var v = new Version(version); if (this.versionMajor > v.versionMajor) { return true; } else if (this.versionMajor === v.versionMajor && this.versionMinor >= v.versionMinor) { return true; } else { return false; } } upTo(version) { return !this.newerThan(version); } } /** * 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 * as THREE from "../../libs/three.js/build/three.module.js"; var typedArrayMapping = { "int8": Int8Array, "int16": Int16Array, "int32": Int32Array, "int64": Float64Array, "uint8": Uint8Array, "uint16": Uint16Array, "uint32": Uint32Array, "uint64": Float64Array, "float": Float32Array, "double": Float64Array }; var gs3dProplist = [ //'x', 'y', 'z', //'nx', 'ny', 'nz', 'f_dc_0', 'f_dc_1', 'f_dc_2', 'f_rest_0', 'f_rest_1', 'f_rest_2', 'f_rest_3', 'f_rest_4', 'f_rest_5', 'f_rest_6', 'f_rest_7', 'f_rest_8', 'opacity', 'scale_0', 'scale_1', 'scale_2', 'rot_0', 'rot_1', 'rot_2', 'rot_3']; var clamp = function clamp(value, min, max) { return Math.max(min, Math.min(max, value)); }; class Vector3 { constructor() { var x = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; var z = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; Object.defineProperty(this, 'isVector3', { value: true }); this.x = x; this.y = y; this.z = z; } set(x, y, z) { if (z === undefined) z = this.z; // sprite.scale.set(x,y) this.x = x; this.y = y; this.z = z; return this; } } class Quaternion { constructor() { var x = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; var z = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; var w = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1; Object.defineProperty(this, 'isQuaternion', { value: true }); this._x = x; this._y = y; this._z = z; this._w = w; } set(x, y, z, w) { this._x = x; this._y = y; this._z = z; this._w = w; //this._onChangeCallback(); return this; } length() { return Math.sqrt(this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w); } normalize() { var l = this.length(); if (l === 0) { this._x = 0; this._y = 0; this._z = 0; this._w = 1; } else { l = 1 / l; this._x = this._x * l; this._y = this._y * l; this._z = this._z * l; this._w = this._w * l; } //this._onChangeCallback(); return this; } } var _zero = new Vector3(0, 0, 0); var _one = new Vector3(1, 1, 1); class Matrix4 { constructor() { Object.defineProperty(this, 'isMatrix4', { value: true }); this.elements = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; if (arguments.length > 0) { console.error('THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.'); } } makeRotationFromQuaternion(q) { return this.compose(_zero, q, _one); } compose(position, quaternion, scale) { var te = this.elements; var x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w; var x2 = x + x, y2 = y + y, z2 = z + z; var xx = x * x2, xy = x * y2, xz = x * z2; var yy = y * y2, yz = y * z2, zz = z * z2; var wx = w * x2, wy = w * y2, wz = w * z2; var sx = scale.x, sy = scale.y, sz = scale.z; te[0] = (1 - (yy + zz)) * sx; te[1] = (xy + wz) * sx; te[2] = (xz - wy) * sx; te[3] = 0; te[4] = (xy - wz) * sy; te[5] = (1 - (xx + zz)) * sy; te[6] = (yz + wx) * sy; te[7] = 0; te[8] = (xz + wy) * sz; te[9] = (yz - wx) * sz; te[10] = (1 - (xx + yy)) * sz; te[11] = 0; te[12] = position.x; te[13] = position.y; te[14] = position.z; te[15] = 1; return this; } makeScale(x, y, z) { this.set(x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1); return this; } set(n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44) { var te = this.elements; te[0] = n11; te[4] = n12; te[8] = n13; te[12] = n14; te[1] = n21; te[5] = n22; te[9] = n23; te[13] = n24; te[2] = n31; te[6] = n32; te[10] = n33; te[14] = n34; te[3] = n41; te[7] = n42; te[11] = n43; te[15] = n44; return this; } } class Matrix3 { constructor() { Object.defineProperty(this, 'isMatrix3', { value: true }); this.elements = [1, 0, 0, 0, 1, 0, 0, 0, 1]; if (arguments.length > 0) { console.error('THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.'); } } copy(m) { var te = this.elements; var me = m.elements; te[0] = me[0]; te[1] = me[1]; te[2] = me[2]; te[3] = me[3]; te[4] = me[4]; te[5] = me[5]; te[6] = me[6]; te[7] = me[7]; te[8] = me[8]; return this; } multiply(m) { return this.multiplyMatrices(this, m); } premultiply(m) { return this.multiplyMatrices(m, this); } multiplyMatrices(a, b) { var ae = a.elements; var be = b.elements; var te = this.elements; var a11 = ae[0], a12 = ae[3], a13 = ae[6]; var a21 = ae[1], a22 = ae[4], a23 = ae[7]; var a31 = ae[2], a32 = ae[5], a33 = ae[8]; var b11 = be[0], b12 = be[3], b13 = be[6]; var b21 = be[1], b22 = be[4], b23 = be[7]; var b31 = be[2], b32 = be[5], b33 = be[8]; te[0] = a11 * b11 + a12 * b21 + a13 * b31; te[3] = a11 * b12 + a12 * b22 + a13 * b32; te[6] = a11 * b13 + a12 * b23 + a13 * b33; te[1] = a21 * b11 + a22 * b21 + a23 * b31; te[4] = a21 * b12 + a22 * b22 + a23 * b32; te[7] = a21 * b13 + a22 * b23 + a23 * b33; te[2] = a31 * b11 + a32 * b21 + a33 * b31; te[5] = a31 * b12 + a32 * b22 + a33 * b32; te[8] = a31 * b13 + a32 * b23 + a33 * b33; return this; } setFromMatrix4(m) { var me = m.elements; this.set(me[0], me[4], me[8], me[1], me[5], me[9], me[2], me[6], me[10]); return this; } set(n11, n12, n13, n21, n22, n23, n31, n32, n33) { var te = this.elements; te[0] = n11; te[1] = n21; te[2] = n31; te[3] = n12; te[4] = n22; te[5] = n32; te[6] = n13; te[7] = n23; te[8] = n33; return this; } transpose() { var tmp; var m = this.elements; tmp = m[1]; m[1] = m[3]; m[3] = tmp; tmp = m[2]; m[2] = m[6]; m[6] = tmp; tmp = m[5]; m[5] = m[7]; m[7] = tmp; return this; } } var toHalfFloat = function toHalfFloat(val) { // Source: http://gamedev.stackexchange.com/questions/17326/conversion-of-a-number-from-single-precision-floating-point-representation-to-a/17410#17410 /* This method is faster than the OpenEXR implementation (very often * used, eg. in Ogre), with the additional benefit of rounding, inspired * by James Tursa?s half-precision code. */ _floatView[0] = val; var x = _int32View[0]; var bits = x >> 16 & 0x8000; /* Get the sign */ var m = x >> 12 & 0x07ff; /* Keep one extra bit for rounding */ var e = x >> 23 & 0xff; /* Using int is faster here */ /* If zero, or denormal, or exponent underflows too much for a denormal * half, return signed zero. */ if (e < 103) return bits; /* If NaN, return NaN. If Inf or exponent overflow, return Inf. */ if (e > 142) { bits |= 0x7c00; /* If exponent was 0xff and one mantissa bit was set, it means NaN, * not Inf, so make sure we set one mantissa bit too. */ bits |= (e == 255 ? 0 : 1) && x & 0x007fffff; return bits; } /* If exponent underflows but not too much, return a denorma l */ if (e < 113) { m |= 0x0800; /* Extra rounding may overflow and set mantissa to 0 and exponent * to 1, which is OK. */ bits |= (m >> 114 - e) + (m >> 113 - e & 1); return bits; } bits |= e - 112 << 10 | m >> 1; /* Extra rounding. An overflow will set mantissa to 0 and increment * the exponent, which is OK. */ bits += m & 1; return bits; }; var computeCovariance = function () { //通过旋转和缩放计算协方差(决定姿态)得到6个数 var tempMatrix4 = new Matrix4(); var scaleMatrix = new Matrix3(); var rotationMatrix = new Matrix3(); var covarianceMatrix = new Matrix3(); var transformedCovariance = new Matrix3(); var transform3x3 = new Matrix3(); var transform3x3Transpose = new Matrix3(); var thf = toHalfFloat; //THREE.DataUtils.toHalfFloat.bind(THREE.DataUtils); return function (scale, rotation, transform, outCovariance) { var outOffset = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0; var desiredOutputCompressionLevel = arguments.length > 5 ? arguments[5] : undefined; tempMatrix4.makeScale(scale.x, scale.y, scale.z); scaleMatrix.setFromMatrix4(tempMatrix4); tempMatrix4.makeRotationFromQuaternion(rotation); rotationMatrix.setFromMatrix4(tempMatrix4); covarianceMatrix.copy(rotationMatrix).multiply(scaleMatrix); transformedCovariance.copy(covarianceMatrix).transpose().premultiply(covarianceMatrix); //为什么要乘以自己的转置呀? if (transform) { //场景的整体transform 如果可能移动就不传,在sort时直接乘 transform3x3.setFromMatrix4(transform); transform3x3Transpose.copy(transform3x3).transpose(); transformedCovariance.multiply(transform3x3Transpose); transformedCovariance.premultiply(transform3x3); } if (desiredOutputCompressionLevel === 1) { //压缩 outCovariance[outOffset] = thf(transformedCovariance.elements[0]); outCovariance[outOffset + 1] = thf(transformedCovariance.elements[3]); outCovariance[outOffset + 2] = thf(transformedCovariance.elements[6]); outCovariance[outOffset + 3] = thf(transformedCovariance.elements[4]); outCovariance[outOffset + 4] = thf(transformedCovariance.elements[7]); outCovariance[outOffset + 5] = thf(transformedCovariance.elements[8]); } else { outCovariance[outOffset] = transformedCovariance.elements[0]; outCovariance[outOffset + 1] = transformedCovariance.elements[3]; outCovariance[outOffset + 2] = transformedCovariance.elements[6]; outCovariance[outOffset + 3] = transformedCovariance.elements[4]; outCovariance[outOffset + 4] = transformedCovariance.elements[7]; outCovariance[outOffset + 5] = transformedCovariance.elements[8]; } /* Vrk 中的元素分别是transformedCovariance的 [ 0,3,6, 3,4,7, 6,7,8 ] */ }; }(); Potree = {}; onmessage = function onmessage(event) { performance.mark("binary-decoder-start"); var buffer = event.data.buffer; var pointAttributes = event.data.pointAttributes; var numPoints = buffer.byteLength / pointAttributes.byteSize; var view = new DataView(buffer); var version = new Version(event.data.version); var nodeOffset = event.data.offset; var scale = event.data.scale; var spacing = event.data.spacing; var hasChildren = event.data.hasChildren; var name = event.data.name; var tightBoxMin = [Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY]; var tightBoxMax = [Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY]; var mean = [0, 0, 0]; var pos = event.data.min; // add geometryNode.sceneNode.position node的偏移 var attributeBuffers = {}; var inOffset = 0; var hasGS3D = pointAttributes.attributes.some(e => e.name == 'GS3D'); var _loop = function _loop(pointAttribute) { if (pointAttribute.name === "POSITION_CARTESIAN") { var _buff = new ArrayBuffer(numPoints * 4 * 3); var positions = new Float32Array(_buff); for (var _j = 0; _j < numPoints; _j++) { var x = void 0, y = void 0, z = void 0; if (version.newerThan('1.3')) { x = view.getUint32(inOffset + _j * pointAttributes.byteSize + 0, true) * scale; y = view.getUint32(inOffset + _j * pointAttributes.byteSize + 4, true) * scale; z = view.getUint32(inOffset + _j * pointAttributes.byteSize + 8, true) * scale; } else { x = view.getFloat32(_j * pointAttributes.byteSize + 0, true) + nodeOffset[0]; y = view.getFloat32(_j * pointAttributes.byteSize + 4, true) + nodeOffset[1]; z = view.getFloat32(_j * pointAttributes.byteSize + 8, true) + nodeOffset[2]; } positions[3 * _j + 0] = x; positions[3 * _j + 1] = y; positions[3 * _j + 2] = z; mean[0] += x / numPoints; mean[1] += y / numPoints; mean[2] += z / numPoints; tightBoxMin[0] = Math.min(tightBoxMin[0], x); tightBoxMin[1] = Math.min(tightBoxMin[1], y); tightBoxMin[2] = Math.min(tightBoxMin[2], z); tightBoxMax[0] = Math.max(tightBoxMax[0], x); tightBoxMax[1] = Math.max(tightBoxMax[1], y); tightBoxMax[2] = Math.max(tightBoxMax[2], z); } attributeBuffers[pointAttribute.name] = { buffer: _buff, attribute: pointAttribute }; if (hasGS3D) { //add var buff2 = new ArrayBuffer(numPoints * 4 * 4); var buff3 = new ArrayBuffer(numPoints * 4 * 3); var centersInt = new Int32Array(buff2); var centersFloat = new Float32Array(buff3); for (var _i = 0; _i < numPoints; _i++) { centersFloat[3 * _i + 0] = positions[3 * _i + 0] + pos[0]; centersFloat[3 * _i + 1] = positions[3 * _i + 1] + pos[1]; centersFloat[3 * _i + 2] = positions[3 * _i + 2] + pos[2]; //centersFloat[4 * i + 3] = 1; centersInt[4 * _i + 0] = centersFloat[3 * _i + 0] * 1000; centersInt[4 * _i + 1] = centersFloat[3 * _i + 1] * 1000; centersInt[4 * _i + 2] = centersFloat[3 * _i + 2] * 1000; centersInt[4 * _i + 3] = 1000; } attributeBuffers['centersInt'] = { buffer: buff2, attribute: pointAttribute }; attributeBuffers['centersFloat'] = { buffer: buff3, attribute: pointAttribute }; } } else if (pointAttribute.name === "rgba") { var _buff2 = new ArrayBuffer(numPoints * 4); var colors = new Uint8Array(_buff2); for (var _j2 = 0; _j2 < numPoints; _j2++) { colors[4 * _j2 + 0] = view.getUint8(inOffset + _j2 * pointAttributes.byteSize + 0); colors[4 * _j2 + 1] = view.getUint8(inOffset + _j2 * pointAttributes.byteSize + 1); colors[4 * _j2 + 2] = view.getUint8(inOffset + _j2 * pointAttributes.byteSize + 2); } attributeBuffers[pointAttribute.name] = { buffer: _buff2, attribute: pointAttribute }; } else if (pointAttribute.name === "NORMAL_SPHEREMAPPED") { var _buff3 = new ArrayBuffer(numPoints * 4 * 3); var normals = new Float32Array(_buff3); for (var _j3 = 0; _j3 < numPoints; _j3++) { var bx = view.getUint8(inOffset + _j3 * pointAttributes.byteSize + 0); var by = view.getUint8(inOffset + _j3 * pointAttributes.byteSize + 1); var ex = bx / 255; var ey = by / 255; var nx = ex * 2 - 1; var ny = ey * 2 - 1; var nz = 1; var nw = -1; var l = nx * -nx + ny * -ny + nz * -nw; nz = l; nx = nx * Math.sqrt(l); ny = ny * Math.sqrt(l); nx = nx * 2; ny = ny * 2; nz = nz * 2 - 1; normals[3 * _j3 + 0] = nx; normals[3 * _j3 + 1] = ny; normals[3 * _j3 + 2] = nz; } attributeBuffers[pointAttribute.name] = { buffer: _buff3, attribute: pointAttribute }; } else if (pointAttribute.name === "NORMAL_OCT16") { //只需要2 byte! 原本需要12个byte var _buff4 = new ArrayBuffer(numPoints * 4 * 3); var _normals = new Float32Array(_buff4); for (var _j4 = 0; _j4 < numPoints; _j4++) { var _bx = view.getUint8(inOffset + _j4 * pointAttributes.byteSize + 0); var _by = view.getUint8(inOffset + _j4 * pointAttributes.byteSize + 1); var u = _bx / 255 * 2 - 1; var v = _by / 255 * 2 - 1; var _z = 1 - Math.abs(u) - Math.abs(v); var _x = 0; var _y = 0; if (_z >= 0) { _x = u; _y = v; } else { _x = -(v / Math.sign(v) - 1) / Math.sign(u); _y = -(u / Math.sign(u) - 1) / Math.sign(v); } var length = Math.sqrt(_x * _x + _y * _y + _z * _z); //因法线长度固定为1,所以只需要xy就能算出z(不过这里似乎是约定相加为1?) _x = _x / length; //x和y都只有一个byte,所以精度很低,只有256个分段 _y = _y / length; _z = _z / length; _normals[3 * _j4 + 0] = _x; _normals[3 * _j4 + 1] = _y; _normals[3 * _j4 + 2] = _z; } attributeBuffers[pointAttribute.name] = { buffer: _buff4, attribute: pointAttribute }; } else if (pointAttribute.name === "NORMAL") { var _buff5 = new ArrayBuffer(numPoints * 4 * 3); var _normals2 = new Float32Array(_buff5); for (var _j5 = 0; _j5 < numPoints; _j5++) { var _x2 = view.getFloat32(inOffset + _j5 * pointAttributes.byteSize + 0, true); var _y2 = view.getFloat32(inOffset + _j5 * pointAttributes.byteSize + 4, true); var _z2 = view.getFloat32(inOffset + _j5 * pointAttributes.byteSize + 8, true); _normals2[3 * _j5 + 0] = _x2; _normals2[3 * _j5 + 1] = _y2; _normals2[3 * _j5 + 2] = _z2; } attributeBuffers[pointAttribute.name] = { buffer: _buff5, attribute: pointAttribute }; } else if (pointAttribute.name === "IR" || pointAttribute.name === "TEMP") { //温度 ir是热成像的温度 temp是AI识别的温度 var _buff6 = new ArrayBuffer(numPoints * 4); //原本数据是uint16但是shader没办法接收,只能转了 var _f = new Float32Array(_buff6); //according to pointAttribute.type.name, 取值范围为 0 到 65535。 var min = Infinity, max = -Infinity, _v; for (var _j6 = 0; _j6 < numPoints; _j6++) { //仿照position的写法 填入数据 _f[_j6] = _v = view.getUint16(inOffset + _j6 * pointAttributes.byteSize, true) / 10; //开尔文 _v != 0 && (min = Math.min(min, _v)); //==0可能是没探测到所以跳过 _v != 0 && (max = Math.max(max, _v)); } //ir or temp 里面的值除以10就是开尔文温度 attributeBuffers[pointAttribute.name] = { buffer: _buff6, attribute: pointAttribute }; pointAttribute.range = [min, max]; //但每个geo范围不一样 } else if (pointAttribute.name === "SEG") { //类型 /* 1: concrete 2: wood 3: metal 4: glass 5: plastic 6: electric_wire */ var _buff7 = new ArrayBuffer(numPoints * 4); var _f2 = new Float32Array(_buff7); //according to pointAttribute.type.name, 取值范围为 0 到 65535。 for (var _j7 = 0; _j7 < numPoints; _j7++) { //仿照position的写法 填入数据 _f2[_j7] = view.getUint16(inOffset + _j7 * pointAttributes.byteSize, true); } //ir or temp 里面的值除以10就是开尔文温度哈 attributeBuffers[pointAttribute.name] = { buffer: _buff7, attribute: pointAttribute }; } else if (pointAttribute.name === "GS3D") { //add 见inriav1plyparser.js ////////////////////////////////////////////////////////// var _buff8 = new ArrayBuffer(numPoints * pointAttribute.byteSize); var _f3 = new Float32Array(_buff8); for (var _j8 = 0; _j8 < numPoints; _j8++) { //仿照position的写法 填入数据 for (var _i2 = 0; _i2 < pointAttribute.numElements; _i2++) { //f32[pointAttribute.numElements * j + i] = view.getUint32( inOffset + j * pointAttributes.byteSize + 4*i, true) * scale ; _f3[pointAttribute.numElements * _j8 + _i2] = view.getFloat32(inOffset + _j8 * pointAttributes.byteSize + 4 * _i2, true); //+ nodeOffset[0]; //是Uint32还是Float32? PlyParserUtils.js中写的是getFloat32 ( rawVertex[fieldId] = vertexData.getFloat32(offset + fieldOffsets[fieldId], true);) } } attributeBuffers[pointAttribute.name] = { buffer: _buff8, attribute: pointAttribute }; //得到颜色 var _buff9 = new ArrayBuffer(numPoints * 4); var _colors = new Uint8Array(_buff9); var SH_C0 = 0.28209479177387814; var offset_opa = gs3dProplist.indexOf('opacity'); var offset_col = gs3dProplist.indexOf('f_dc_0'); var getColor = index => { var value = (0.5 + SH_C0 * _f3[index + offset_col]) * 255; return clamp(Math.floor(value), 0, 255); }; var getOpacity = index => { var value = 1 / (1 + Math.exp(-_f3[index + offset_opa])) * 255; return clamp(Math.floor(value), 0, 255); }; for (var _j9 = 0; _j9 < numPoints; _j9++) { _colors[4 * _j9 + 0] = getColor(_j9 * pointAttribute.numElements + 0); _colors[4 * _j9 + 1] = getColor(_j9 * pointAttribute.numElements + 1); _colors[4 * _j9 + 2] = getColor(_j9 * pointAttribute.numElements + 2); _colors[4 * _j9 + 3] = getOpacity(_j9 * pointAttribute.numElements); } attributeBuffers['rgba'] = { buffer: _buff9, attribute: pointAttribute }; //compute cov: var _buff10 = new ArrayBuffer(numPoints * 24); //let buff3_ = new ArrayBuffer(numPoints * 12); var covs = new Float32Array(_buff10); //let scales = new Float32Array(buff3_); var offset_scale = gs3dProplist.indexOf('scale_0'); //第49个数开始是 var offset_rot = gs3dProplist.indexOf('rot_0'); var _scale2 = new Vector3(); var quaternion = new Quaternion(); var getScale = index => { var get = offset => { var s1 = _f3[index * pointAttribute.numElements + offset + offset_scale]; var s = Math.exp(s1); //scales[index*3+offset] = s return s; //0.2*Math.pow(1.1, f32[index * pointAttribute.numElements + offset + offset_scale]) }; _scale2.set(get(0), get(1), get(2)); }; var getQuatenion = index => { var get = offset => { return _f3[index * pointAttribute.numElements + offset + offset_rot]; }; //quaternion.set( get(0), get(1), get(2), get(3)) quaternion.set(get(1), get(2), get(3), get(0)); //w放到最后 另外如果compressionLevel不是0的话还要再加一步,见this.fbf(sectionFloatArray[rotationBase + 1] quaternion.normalize(); //有时候数据没归一化,结果splat看起来很大 }; for (var _j10 = 0; _j10 < numPoints; _j10++) { getScale(_j10); getQuatenion(_j10); computeCovariance(_scale2, quaternion, null, covs, 6 * _j10); } attributeBuffers['covs'] = { buffer: _buff10, attribute: pointAttribute }; //////////////////////////////////////////////////////////////////////////////// } else { var _buff12 = new ArrayBuffer(numPoints * 4); var _f4 = new Float32Array(_buff12); var TypedArray = typedArrayMapping[pointAttribute.type.name]; preciseBuffer = new TypedArray(numPoints); var [_min, _max] = [Infinity, -Infinity]; var [_offset2, _scale3] = [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) { for (var _j12 = 0; _j12 < numPoints; _j12++) { var _value = _getter(inOffset + _j12 * pointAttributes.byteSize, true); if (!Number.isNaN(_value)) { _min = Math.min(_min, _value); _max = Math.max(_max, _value); } } if (pointAttribute.initialRange != null) { _offset2 = pointAttribute.initialRange[0]; _scale3 = 1 / (pointAttribute.initialRange[1] - pointAttribute.initialRange[0]); } else { _offset2 = _min; _scale3 = 1 / (_max - _min); } } for (var _j13 = 0; _j13 < numPoints; _j13++) { var _value2 = _getter(inOffset + _j13 * pointAttributes.byteSize, true); if (!Number.isNaN(_value2)) { _min = Math.min(_min, _value2); _max = Math.max(_max, _value2); } _f4[_j13] = (_value2 - _offset2) * _scale3; preciseBuffer[_j13] = _value2; } pointAttribute.range = [_min, _max]; attributeBuffers[pointAttribute.name] = { buffer: _buff12, preciseBuffer: preciseBuffer, attribute: pointAttribute, offset: _offset2, scale: _scale3 }; } inOffset += pointAttribute.byteSize; }; for (var pointAttribute of pointAttributes.attributes) { _loop(pointAttribute); } { // add indices var buff = new ArrayBuffer(numPoints * 4); var indices = new Uint32Array(buff); for (var i = 0; i < numPoints; i++) { indices[i] = i; } attributeBuffers["INDICES"] = { buffer: buff, 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 f32 = new Float32Array(_buffer); var iElement = 0; for (var sourceName of attributes) { var sourceBuffer = attributeBuffers[sourceName]; var { offset, scale: _scale } = sourceBuffer; var _view = new DataView(sourceBuffer.buffer); var getter = _view.getFloat32.bind(_view); for (var j = 0; j < numPoints; j++) { var value = getter(j * 4, true); f32[j * numVectorElements + iElement] = value / _scale + offset; } iElement++; } var vecAttribute = new PointAttribute(_name, PointAttributeTypes.DATA_TYPE_FLOAT, 3); attributeBuffers[_name] = { buffer: _buffer, attribute: vecAttribute }; } } performance.mark("binary-decoder-end"); // { // print timings // //performance.measure("spacing", "spacing-start", "spacing-end"); // performance.measure("binary-decoder", "binary-decoder-start", "binary-decoder-end"); // let measure = performance.getEntriesByType("measure")[0]; // let dpp = 1000 * measure.duration / numPoints; // let pps = parseInt(numPoints / (measure.duration / 1000)); // let debugMessage = `${measure.duration.toFixed(3)} ms, ${numPoints} points, ${pps.toLocaleString()} points/sec`; // console.log(debugMessage); // } performance.clearMarks(); performance.clearMeasures(); var message = { buffer: buffer, mean: mean, attributeBuffers: attributeBuffers, tightBoundingBox: { min: tightBoxMin, max: tightBoxMax } }; var transferables = []; for (var property in message.attributeBuffers) { transferables.push(message.attributeBuffers[property].buffer); } transferables.push(buffer); postMessage(message, transferables); };