DecoderWorker.js 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. /**
  2. * Some types of possible point attribute data formats
  3. *
  4. * @class
  5. */
  6. var PointAttributeTypes = {
  7. DATA_TYPE_DOUBLE: {
  8. ordinal: 0,
  9. name: "double",
  10. size: 8
  11. },
  12. DATA_TYPE_FLOAT: {
  13. ordinal: 1,
  14. name: "float",
  15. size: 4
  16. },
  17. DATA_TYPE_INT8: {
  18. ordinal: 2,
  19. name: "int8",
  20. size: 1
  21. },
  22. DATA_TYPE_UINT8: {
  23. ordinal: 3,
  24. name: "uint8",
  25. size: 1
  26. },
  27. DATA_TYPE_INT16: {
  28. ordinal: 4,
  29. name: "int16",
  30. size: 2
  31. },
  32. DATA_TYPE_UINT16: {
  33. ordinal: 5,
  34. name: "uint16",
  35. size: 2
  36. },
  37. DATA_TYPE_INT32: {
  38. ordinal: 6,
  39. name: "int32",
  40. size: 4
  41. },
  42. DATA_TYPE_UINT32: {
  43. ordinal: 7,
  44. name: "uint32",
  45. size: 4
  46. },
  47. DATA_TYPE_INT64: {
  48. ordinal: 8,
  49. name: "int64",
  50. size: 8
  51. },
  52. DATA_TYPE_UINT64: {
  53. ordinal: 9,
  54. name: "uint64",
  55. size: 8
  56. }
  57. };
  58. var i = 0;
  59. for (var obj in PointAttributeTypes) {
  60. PointAttributeTypes[i] = PointAttributeTypes[obj];
  61. i++;
  62. }
  63. class PointAttribute {
  64. constructor(name, type, numElements) {
  65. this.name = name;
  66. this.type = type;
  67. this.numElements = numElements;
  68. this.byteSize = this.numElements * this.type.size;
  69. this.description = "";
  70. this.range = [Infinity, -Infinity];
  71. }
  72. }
  73. PointAttribute.POSITION_CARTESIAN = new PointAttribute("POSITION_CARTESIAN", PointAttributeTypes.DATA_TYPE_FLOAT, 3);
  74. PointAttribute.RGBA_PACKED = new PointAttribute("COLOR_PACKED", PointAttributeTypes.DATA_TYPE_INT8, 4);
  75. PointAttribute.COLOR_PACKED = PointAttribute.RGBA_PACKED;
  76. PointAttribute.RGB_PACKED = new PointAttribute("COLOR_PACKED", PointAttributeTypes.DATA_TYPE_INT8, 3);
  77. PointAttribute.NORMAL_FLOATS = new PointAttribute("NORMAL_FLOATS", PointAttributeTypes.DATA_TYPE_FLOAT, 3);
  78. PointAttribute.INTENSITY = new PointAttribute("INTENSITY", PointAttributeTypes.DATA_TYPE_UINT16, 1);
  79. PointAttribute.CLASSIFICATION = new PointAttribute("CLASSIFICATION", PointAttributeTypes.DATA_TYPE_UINT8, 1);
  80. PointAttribute.NORMAL_SPHEREMAPPED = new PointAttribute("NORMAL_SPHEREMAPPED", PointAttributeTypes.DATA_TYPE_UINT8, 2);
  81. PointAttribute.NORMAL_OCT16 = new PointAttribute("NORMAL_OCT16", PointAttributeTypes.DATA_TYPE_UINT8, 2);
  82. PointAttribute.NORMAL = new PointAttribute("NORMAL", PointAttributeTypes.DATA_TYPE_FLOAT, 3);
  83. PointAttribute.RETURN_NUMBER = new PointAttribute("RETURN_NUMBER", PointAttributeTypes.DATA_TYPE_UINT8, 1);
  84. PointAttribute.NUMBER_OF_RETURNS = new PointAttribute("NUMBER_OF_RETURNS", PointAttributeTypes.DATA_TYPE_UINT8, 1);
  85. PointAttribute.SOURCE_ID = new PointAttribute("SOURCE_ID", PointAttributeTypes.DATA_TYPE_UINT16, 1);
  86. PointAttribute.INDICES = new PointAttribute("INDICES", PointAttributeTypes.DATA_TYPE_UINT32, 1);
  87. PointAttribute.SPACING = new PointAttribute("SPACING", PointAttributeTypes.DATA_TYPE_FLOAT, 1);
  88. PointAttribute.GPS_TIME = new PointAttribute("GPS_TIME", PointAttributeTypes.DATA_TYPE_DOUBLE, 1);
  89. // import {Version} from "../../Version.js";
  90. var typedArrayMapping = {
  91. "int8": Int8Array,
  92. "int16": Int16Array,
  93. "int32": Int32Array,
  94. "int64": Float64Array,
  95. "uint8": Uint8Array,
  96. "uint16": Uint16Array,
  97. "uint32": Uint32Array,
  98. "uint64": Float64Array,
  99. "float": Float32Array,
  100. "double": Float64Array
  101. };
  102. Potree = {};
  103. onmessage = function onmessage(event) {
  104. var {
  105. buffer,
  106. pointAttributes,
  107. scale,
  108. name,
  109. min,
  110. max,
  111. size,
  112. offset,
  113. numPoints
  114. } = event.data;
  115. var tStart = performance.now();
  116. var view = new DataView(buffer);
  117. var attributeBuffers = {};
  118. var attributeOffset = 0;
  119. var bytesPerPoint = 0;
  120. for (var pointAttribute of pointAttributes.attributes) {
  121. bytesPerPoint += pointAttribute.byteSize;
  122. }
  123. var gridSize = 32;
  124. var grid = new Uint32Array(gridSize ** 3);
  125. var toIndex = (x, y, z) => {
  126. // let dx = gridSize * (x - min.x) / size.x;
  127. // let dy = gridSize * (y - min.y) / size.y;
  128. // let dz = gridSize * (z - min.z) / size.z;
  129. // min is already subtracted
  130. var dx = gridSize * x / size.x;
  131. var dy = gridSize * y / size.y;
  132. var dz = gridSize * z / size.z;
  133. var ix = Math.min(parseInt(dx), gridSize - 1);
  134. var iy = Math.min(parseInt(dy), gridSize - 1);
  135. var iz = Math.min(parseInt(dz), gridSize - 1);
  136. var index = ix + iy * gridSize + iz * gridSize * gridSize;
  137. return index;
  138. };
  139. var numOccupiedCells = 0;
  140. for (var _pointAttribute of pointAttributes.attributes) {
  141. if (["POSITION_CARTESIAN", "position"].includes(_pointAttribute.name)) {
  142. var buff = new ArrayBuffer(numPoints * 4 * 3);
  143. var positions = new Float32Array(buff);
  144. for (var j = 0; j < numPoints; j++) {
  145. var pointOffset = j * bytesPerPoint;
  146. var x = view.getInt32(pointOffset + attributeOffset + 0, true) * scale[0] + offset[0] - min.x;
  147. var y = view.getInt32(pointOffset + attributeOffset + 4, true) * scale[1] + offset[1] - min.y;
  148. var z = view.getInt32(pointOffset + attributeOffset + 8, true) * scale[2] + offset[2] - min.z;
  149. var index = toIndex(x, y, z);
  150. var count = grid[index]++;
  151. if (count === 0) {
  152. numOccupiedCells++;
  153. }
  154. positions[3 * j + 0] = x;
  155. positions[3 * j + 1] = y;
  156. positions[3 * j + 2] = z;
  157. }
  158. attributeBuffers[_pointAttribute.name] = {
  159. buffer: buff,
  160. attribute: _pointAttribute
  161. };
  162. } else if (["RGBA", "rgba"].includes(_pointAttribute.name)) {
  163. var _buff = new ArrayBuffer(numPoints * 4);
  164. var colors = new Uint8Array(_buff);
  165. for (var _j = 0; _j < numPoints; _j++) {
  166. var _pointOffset = _j * bytesPerPoint;
  167. var r = view.getUint16(_pointOffset + attributeOffset + 0, true);
  168. var g = view.getUint16(_pointOffset + attributeOffset + 2, true);
  169. var b = view.getUint16(_pointOffset + attributeOffset + 4, true);
  170. colors[4 * _j + 0] = r > 255 ? r / 256 : r;
  171. colors[4 * _j + 1] = g > 255 ? g / 256 : g;
  172. colors[4 * _j + 2] = b > 255 ? b / 256 : b;
  173. }
  174. attributeBuffers[_pointAttribute.name] = {
  175. buffer: _buff,
  176. attribute: _pointAttribute
  177. };
  178. } else {
  179. var _buff2 = new ArrayBuffer(numPoints * 4);
  180. var f32 = new Float32Array(_buff2);
  181. var TypedArray = typedArrayMapping[_pointAttribute.type.name];
  182. preciseBuffer = new TypedArray(numPoints);
  183. var [_offset, _scale] = [0, 1];
  184. var getterMap = {
  185. "int8": view.getInt8,
  186. "int16": view.getInt16,
  187. "int32": view.getInt32,
  188. // "int64": view.getInt64,
  189. "uint8": view.getUint8,
  190. "uint16": view.getUint16,
  191. "uint32": view.getUint32,
  192. // "uint64": view.getUint64,
  193. "float": view.getFloat32,
  194. "double": view.getFloat64
  195. };
  196. var getter = getterMap[_pointAttribute.type.name].bind(view);
  197. // compute offset and scale to pack larger types into 32 bit floats
  198. if (_pointAttribute.type.size > 4) {
  199. var [amin, amax] = _pointAttribute.range;
  200. _offset = amin;
  201. _scale = 1 / (amax - amin);
  202. }
  203. for (var _j2 = 0; _j2 < numPoints; _j2++) {
  204. var _pointOffset2 = _j2 * bytesPerPoint;
  205. var value = getter(_pointOffset2 + attributeOffset, true);
  206. f32[_j2] = (value - _offset) * _scale;
  207. preciseBuffer[_j2] = value;
  208. }
  209. attributeBuffers[_pointAttribute.name] = {
  210. buffer: _buff2,
  211. preciseBuffer: preciseBuffer,
  212. attribute: _pointAttribute,
  213. offset: _offset,
  214. scale: _scale
  215. };
  216. }
  217. attributeOffset += _pointAttribute.byteSize;
  218. }
  219. var occupancy = parseInt(numPoints / numOccupiedCells);
  220. // console.log(`${name}: #points: ${numPoints}: #occupiedCells: ${numOccupiedCells}, occupancy: ${occupancy} points/cell`);
  221. {
  222. // add indices
  223. var _buff3 = new ArrayBuffer(numPoints * 4);
  224. var indices = new Uint32Array(_buff3);
  225. for (var i = 0; i < numPoints; i++) {
  226. indices[i] = i;
  227. }
  228. attributeBuffers["INDICES"] = {
  229. buffer: _buff3,
  230. attribute: PointAttribute.INDICES
  231. };
  232. }
  233. {
  234. // handle attribute vectors
  235. var vectors = pointAttributes.vectors;
  236. for (var vector of vectors) {
  237. var {
  238. name: _name,
  239. attributes
  240. } = vector;
  241. var numVectorElements = attributes.length;
  242. var _buffer = new ArrayBuffer(numVectorElements * numPoints * 4);
  243. var _f = new Float32Array(_buffer);
  244. var iElement = 0;
  245. for (var sourceName of attributes) {
  246. var sourceBuffer = attributeBuffers[sourceName];
  247. var {
  248. offset: _offset2,
  249. scale: _scale2
  250. } = sourceBuffer;
  251. var _view = new DataView(sourceBuffer.buffer);
  252. var _getter = _view.getFloat32.bind(_view);
  253. for (var _j3 = 0; _j3 < numPoints; _j3++) {
  254. var _value = _getter(_j3 * 4, true);
  255. _f[_j3 * numVectorElements + iElement] = _value / _scale2 + _offset2;
  256. }
  257. iElement++;
  258. }
  259. var vecAttribute = new PointAttribute(_name, PointAttributeTypes.DATA_TYPE_FLOAT, 3);
  260. attributeBuffers[_name] = {
  261. buffer: _buffer,
  262. attribute: vecAttribute
  263. };
  264. }
  265. }
  266. // let duration = performance.now() - tStart;
  267. // let pointsPerMs = numPoints / duration;
  268. // console.log(`duration: ${duration.toFixed(1)}ms, #points: ${numPoints}, points/ms: ${pointsPerMs.toFixed(1)}`);
  269. var message = {
  270. buffer: buffer,
  271. attributeBuffers: attributeBuffers,
  272. density: occupancy
  273. };
  274. var transferables = [];
  275. for (var property in message.attributeBuffers) {
  276. transferables.push(message.attributeBuffers[property].buffer);
  277. }
  278. transferables.push(buffer);
  279. postMessage(message, transferables);
  280. };