PointCloudOctreeGeometry.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. import { EventDispatcher } from "./EventDispatcher.js";
  2. import * as THREE from "../libs/three.js/build/three.module.js";
  3. import {PointCloudTreeNode} from "./PointCloudTree.js";
  4. import {XHRFactory} from "./XHRFactory.js";
  5. import {Utils} from "./utils.js";
  6. export class PointCloudOctreeGeometry extends EventDispatcher{
  7. constructor(){
  8. super()
  9. this.url = null;
  10. this.octreeDir = null;
  11. this.spacing = 0;
  12. this.boundingBox = null;
  13. this.root = null;
  14. this.nodes = null;
  15. this.pointAttributes = null;
  16. this.hierarchyStepSize = -1;
  17. this.loader = null;
  18. }
  19. }
  20. export class PointCloudOctreeGeometryNode extends PointCloudTreeNode{
  21. constructor(name, pcoGeometry, boundingBox){
  22. super();
  23. this.id = PointCloudOctreeGeometryNode.IDCount++;
  24. this.name = name;
  25. this.index = parseInt(name.charAt(name.length - 1));
  26. this.pcoGeometry = pcoGeometry;
  27. this.geometry = null;
  28. this.boundingBox = boundingBox;
  29. this.boundingSphere = boundingBox.getBoundingSphere(new THREE.Sphere());
  30. this.children = {};
  31. this.numPoints = 0;
  32. this.level = null;
  33. this.loaded = false;
  34. this.oneTimeDisposeHandlers = [];
  35. }
  36. isGeometryNode(){
  37. return true;
  38. }
  39. getLevel(){
  40. return this.level;
  41. }
  42. isTreeNode(){
  43. return false;
  44. }
  45. isLoaded(){
  46. return this.loaded;
  47. }
  48. getBoundingSphere(){
  49. return this.boundingSphere;
  50. }
  51. getBoundingBox(){
  52. return this.boundingBox;
  53. }
  54. getChildren(){
  55. let children = [];
  56. for (let i = 0; i < 8; i++) {
  57. if (this.children[i]) {
  58. children.push(this.children[i]);
  59. }
  60. }
  61. return children;
  62. }
  63. getBoundingBox(){
  64. return this.boundingBox;
  65. }
  66. getURL(){
  67. let url = '';
  68. let version = this.pcoGeometry.loader.version;
  69. if (version.equalOrHigher('1.5')) {
  70. url = this.pcoGeometry.octreeDir + '/' + this.getHierarchyPath() + '/' + this.name;
  71. } else if (version.equalOrHigher('1.4')) {
  72. url = this.pcoGeometry.octreeDir + '/' + this.name;
  73. } else if (version.upTo('1.3')) {
  74. url = this.pcoGeometry.octreeDir + '/' + this.name;
  75. }
  76. return url;
  77. }
  78. getHierarchyPath(){
  79. let path = 'r/';
  80. let hierarchyStepSize = this.pcoGeometry.hierarchyStepSize;
  81. let indices = this.name.substr(1);
  82. let numParts = Math.floor(indices.length / hierarchyStepSize);
  83. for (let i = 0; i < numParts; i++) {
  84. path += indices.substr(i * hierarchyStepSize, hierarchyStepSize) + '/';
  85. }
  86. path = path.slice(0, -1);
  87. return path;
  88. }
  89. addChild(child) {
  90. this.children[child.index] = child;
  91. child.parent = this;
  92. }
  93. load(){
  94. if (this.loading === true || this.loaded === true || Potree.numNodesLoading >= Potree.maxNodesLoading) {
  95. return;
  96. }
  97. this.loading = true;
  98. Potree.numNodesLoading++;
  99. if (this.pcoGeometry.loader.version.equalOrHigher('1.5')) {
  100. if ((this.level % this.pcoGeometry.hierarchyStepSize) === 0 && this.hasChildren) {
  101. this.loadHierachyThenPoints();
  102. } else {
  103. this.loadPoints();
  104. }
  105. } else {
  106. this.loadPoints();
  107. }
  108. }
  109. loadPoints(){
  110. this.pcoGeometry.loader.load(this);
  111. }
  112. loadHierachyThenPoints(pointcloud){
  113. let node = this;
  114. // load hierarchy
  115. let callback = function (node, hbuffer) {
  116. let tStart = performance.now();
  117. let view = new DataView(hbuffer);
  118. let stack = [];
  119. let children = view.getUint8(0);
  120. let numPoints = view.getUint32(1, true);
  121. node.numPoints = numPoints;
  122. stack.push({children: children, numPoints: numPoints, name: node.name});
  123. let decoded = [];
  124. let offset = 5;
  125. while (stack.length > 0) {
  126. let snode = stack.shift();
  127. let mask = 1;
  128. for (let i = 0; i < 8; i++) {
  129. if ((snode.children & mask) !== 0) {
  130. let childName = snode.name + i;
  131. let childChildren = view.getUint8(offset);
  132. let childNumPoints = view.getUint32(offset + 1, true);
  133. stack.push({children: childChildren, numPoints: childNumPoints, name: childName});
  134. decoded.push({children: childChildren, numPoints: childNumPoints, name: childName});
  135. offset += 5;
  136. }
  137. mask = mask * 2;
  138. }
  139. if (offset === hbuffer.byteLength) {
  140. break;
  141. }
  142. }
  143. // console.log(decoded);
  144. let nodes = {};
  145. nodes[node.name] = node;
  146. let pco = node.pcoGeometry;
  147. for (let i = 0; i < decoded.length; i++) {
  148. let name = decoded[i].name;
  149. let decodedNumPoints = decoded[i].numPoints;
  150. let index = parseInt(name.charAt(name.length - 1));
  151. let parentName = name.substring(0, name.length - 1);
  152. let parentNode = nodes[parentName];
  153. let level = name.length - 1;
  154. pco.emit('updateNodeMaxLevel',level);//add
  155. let boundingBox = Utils.createChildAABB(parentNode.boundingBox, index);
  156. let currentNode = new PointCloudOctreeGeometryNode(name, pco, boundingBox);
  157. currentNode.level = level;
  158. currentNode.numPoints = decodedNumPoints;
  159. currentNode.hasChildren = decoded[i].children > 0;
  160. currentNode.spacing = pco.spacing / Math.pow(2, level);
  161. parentNode.addChild(currentNode);
  162. nodes[name] = currentNode;
  163. }
  164. let duration = performance.now() - tStart;
  165. if(duration > 5){
  166. /* let msg = `duration: ${duration}ms, numNodes: ${decoded.length}`;
  167. console.log(msg); */
  168. }
  169. node.loadPoints();
  170. };
  171. if ((node.level % node.pcoGeometry.hierarchyStepSize) === 0) {
  172. // let hurl = node.pcoGeometry.octreeDir + "/../hierarchy/" + node.name + ".hrc";
  173. let hurl = node.pcoGeometry.octreeDir + '/' + node.getHierarchyPath() + '/' + node.name + '.hrc';
  174. let xhr = XHRFactory.createXMLHttpRequest();
  175. xhr.open('GET', hurl, true);
  176. xhr.responseType = 'arraybuffer';
  177. xhr.overrideMimeType('text/plain; charset=x-user-defined');
  178. xhr.onreadystatechange = () => {
  179. if (xhr.readyState === 4) {
  180. if (xhr.status === 200 || xhr.status === 0) {
  181. let hbuffer = xhr.response;
  182. callback(node, hbuffer);
  183. } else {
  184. console.log('Failed to load file! HTTP status: ' + xhr.status + ', file: ' + hurl);
  185. Potree.numNodesLoading--;
  186. }
  187. }
  188. };
  189. try {
  190. xhr.send(null);
  191. } catch (e) {
  192. console.log('fehler beim laden der punktwolke: ' + e);
  193. }
  194. }
  195. }
  196. getNumPoints(){
  197. return this.numPoints;
  198. }
  199. dispose(){
  200. if (this.geometry && this.parent != null) {
  201. this.geometry.dispose();
  202. this.geometry = null;
  203. this.loaded = false;
  204. this.dispatchEvent( { type: 'dispose' } );
  205. for (let i = 0; i < this.oneTimeDisposeHandlers.length; i++) {
  206. let handler = this.oneTimeDisposeHandlers[i];
  207. handler();
  208. }
  209. this.oneTimeDisposeHandlers = [];
  210. }
  211. }
  212. traverse(t, e){//add from navvis 25.js
  213. void 0 === e && (e = !0);
  214. for (var n, i = e ? [this] : []; void 0 !== (n = i.pop()); ) {
  215. t(n);
  216. for (var o = 0, r = n.children; o < r.length; o++) {
  217. var a = r[o];
  218. null !== a && i.push(a)
  219. }
  220. }
  221. }
  222. }
  223. PointCloudOctreeGeometryNode.IDCount = 0;