PointCloudOctreeGeometry.js 6.3 KB

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