diff --git a/examples/potree2_25d_map.html b/examples/potree2_25d_map.html
index 7ecb9533d9..dd91ee4b91 100644
--- a/examples/potree2_25d_map.html
+++ b/examples/potree2_25d_map.html
@@ -64,7 +64,7 @@
source: new itowns.Potree2Source({
file: 'metadata.json',
url: 'https://raw.githubusercontent.com/iTowns/iTowns2-sample-data/master/pointclouds/potree2.0/lion',
- crs: view.referenceCrs,
+ crs: 'EPSG:3946',
}),
});
@@ -94,22 +94,26 @@
// add potreeLayer to scene
function onLayerReady() {
- var ratio;
var position;
var lookAt = new itowns.THREE.Vector3();
var size = new itowns.THREE.Vector3();
- potreeLayer.root.bbox.getSize(size);
- potreeLayer.root.bbox.getCenter(lookAt);
+ potreeLayer.root._bbox.getSize(size);
+ potreeLayer.root._bbox.getCenter(lookAt);
+ lookAt.z = potreeLayer.root._bbox.min.z;
debug.PointCloudDebug.initTools(view, potreeLayer, debugGui);
view.camera.camera3D.far = 2.0 * size.length();
- ratio = size.x / size.z;
- position = potreeLayer.root.bbox.min.clone().add(
- size.multiply({ x: 0, y: 0, z: ratio * 0.5 }));
- lookAt.z = potreeLayer.root.bbox.min.z;
+ // position = potreeLayer.root.bbox.min.clone().add(
+ // size.multiply({ x: 0, y: 0, z: (size.x / size.z) * 0.5 }));
+
+ var corner = new itowns.THREE.Vector3(...potreeLayer.source.metadata.boundingBox.min);
+ var position = corner.clone().add(
+ size.multiply({ x: 0, y: 0, z: (size.x / size.z) })
+ );
+
placeCamera(position, lookAt);
controls.moveSpeed = size.length() / 3;
diff --git a/examples/potree_25d_map.html b/examples/potree_25d_map.html
index 74efbfc34e..1917090a47 100644
--- a/examples/potree_25d_map.html
+++ b/examples/potree_25d_map.html
@@ -60,12 +60,13 @@
view.mainLoop.gfxEngine.renderer.setClearColor(0xcccccc);
// Configure Point Cloud layer
+ const potreeSource = new itowns.PotreeSource({
+ file: 'eglise_saint_blaise_arles.js',
+ url: 'https://raw.githubusercontent.com/iTowns/iTowns2-sample-data/master/pointclouds/eglise_saint_blaise_arles',
+ crs: 'EPSG:3946',
+ });
potreeLayer = new itowns.PotreeLayer('eglise_saint_blaise_arles', {
- source: new itowns.PotreeSource({
- file: 'eglise_saint_blaise_arles.js',
- url: 'https://raw.githubusercontent.com/iTowns/iTowns2-sample-data/master/pointclouds/eglise_saint_blaise_arles',
- crs: view.referenceCrs,
- }),
+ source: potreeSource,
});
// point selection on double-click
@@ -94,22 +95,30 @@
// add potreeLayer to scene
function onLayerReady() {
- var ratio;
var position;
var lookAt = new itowns.THREE.Vector3();
var size = new itowns.THREE.Vector3();
- potreeLayer.root.bbox.getSize(size);
- potreeLayer.root.bbox.getCenter(lookAt);
+ potreeLayer.root._bbox.getSize(size);
+ potreeLayer.root._bbox.getCenter(lookAt);
+ lookAt.z = potreeLayer.root._bbox.min.z;
debug.PointCloudDebug.initTools(view, potreeLayer, debugGui);
view.camera3D.far = 2.0 * size.length();
- ratio = size.x / size.z;
- position = potreeLayer.root.bbox.min.clone().add(
- size.multiply({ x: 0, y: 0, z: ratio * 0.5 }));
- lookAt.z = potreeLayer.root.bbox.min.z;
+ // position = potreeLayer.root.bbox.min.clone().add(
+ // size.multiply({ x: 0, y: 0, z: (size.x / size.z) * 0.5 }));
+
+ console.log(potreeLayer.source.boundsConforming);
+ var corner = new itowns.THREE.Vector3(...potreeLayer.source.boundsConforming.slice(0, 3));
+ console.log('corner', corner);
+ var position = corner.clone().add(
+ size.multiply({ x: 0, y: 0, z: (size.x / size.z) })
+ );
+
+ console.log(position, lookAt);
+
placeCamera(position, lookAt);
controls.moveSpeed = size.length() / 3;
diff --git a/src/Core/Potree2Node.js b/src/Core/Potree2Node.js
index 21de2cb172..8c265826f3 100644
--- a/src/Core/Potree2Node.js
+++ b/src/Core/Potree2Node.js
@@ -62,44 +62,50 @@ class Potree2Node extends PointCloudNode {
node.depth = this.depth + 1;
}
- createChildAABB(node, childIndex) {
+ createChildAABB(childNode, childIndex) {
// Code inspired from potree
- node.bbox.copy(this.bbox);
- this.bbox.getCenter(node.bbox.max);
- dHalfLength.copy(node.bbox.max).sub(this.bbox.min);
+ childNode._bbox.copy(this._bbox);
+ this._bbox.getCenter(childNode._bbox.max);
+ dHalfLength.copy(childNode._bbox.max).sub(this._bbox.min);
if (childIndex === 1) {
- node.bbox.min.z += dHalfLength.z;
- node.bbox.max.z += dHalfLength.z;
+ childNode._bbox.min.z += dHalfLength.z;
+ childNode._bbox.max.z += dHalfLength.z;
} else if (childIndex === 3) {
- node.bbox.min.z += dHalfLength.z;
- node.bbox.max.z += dHalfLength.z;
- node.bbox.min.y += dHalfLength.y;
- node.bbox.max.y += dHalfLength.y;
+ childNode._bbox.min.z += dHalfLength.z;
+ childNode._bbox.max.z += dHalfLength.z;
+ childNode._bbox.min.y += dHalfLength.y;
+ childNode._bbox.max.y += dHalfLength.y;
} else if (childIndex === 0) {
//
} else if (childIndex === 2) {
- node.bbox.min.y += dHalfLength.y;
- node.bbox.max.y += dHalfLength.y;
+ childNode._bbox.min.y += dHalfLength.y;
+ childNode._bbox.max.y += dHalfLength.y;
} else if (childIndex === 5) {
- node.bbox.min.z += dHalfLength.z;
- node.bbox.max.z += dHalfLength.z;
- node.bbox.min.x += dHalfLength.x;
- node.bbox.max.x += dHalfLength.x;
+ childNode._bbox.min.z += dHalfLength.z;
+ childNode._bbox.max.z += dHalfLength.z;
+ childNode._bbox.min.x += dHalfLength.x;
+ childNode._bbox.max.x += dHalfLength.x;
} else if (childIndex === 7) {
- node.bbox.min.add(dHalfLength);
- node.bbox.max.add(dHalfLength);
+ childNode._bbox.min.add(dHalfLength);
+ childNode._bbox.max.add(dHalfLength);
} else if (childIndex === 4) {
- node.bbox.min.x += dHalfLength.x;
- node.bbox.max.x += dHalfLength.x;
+ childNode._bbox.min.x += dHalfLength.x;
+ childNode._bbox.max.x += dHalfLength.x;
} else if (childIndex === 6) {
- node.bbox.min.y += dHalfLength.y;
- node.bbox.max.y += dHalfLength.y;
- node.bbox.min.x += dHalfLength.x;
- node.bbox.max.x += dHalfLength.x;
+ childNode._bbox.min.y += dHalfLength.y;
+ childNode._bbox.max.y += dHalfLength.y;
+ childNode._bbox.min.x += dHalfLength.x;
+ childNode._bbox.max.x += dHalfLength.x;
}
}
+ getCenter() {
+ // for potree we send the point use as origin for the data
+ // ie the min corner of the bbox
+ this.center = this._bbox.min;
+ }
+
get octreeIsLoaded() {
return !(this.childrenBitField && this.children.length === 0);
}
@@ -133,14 +139,19 @@ class Potree2Node extends PointCloudNode {
await this.loadOctree();
}
+ this.getCenter();
+
return this.layer.source.fetcher(this.url, this.networkOptions(this.byteOffset, this.byteSize))
.then(file => this.layer.source.parser(file, {
in: {
source: this.layer.source,
- bbox: this.bbox,
+ bbox: this._bbox,
numPoints: this.numPoints,
},
- out: this.layer,
+ out: {
+ ...this.layer,
+ center: this.center,
+ },
}))
.then((data) => {
this.loaded = true;
@@ -220,6 +231,8 @@ class Potree2Node extends PointCloudNode {
}
const child = new Potree2Node(numPoints, childMask, this.layer);
+ child._quaternion = this._quaternion;
+ child._position = this._position;
child.spacing = current.spacing / 2;
current.add(child, childIndex);
diff --git a/src/Core/PotreeNode.js b/src/Core/PotreeNode.js
index 48a9802318..a1a56602a3 100644
--- a/src/Core/PotreeNode.js
+++ b/src/Core/PotreeNode.js
@@ -26,44 +26,50 @@ class PotreeNode extends PointCloudNode {
}
}
- createChildAABB(node, childIndex) {
+ createChildAABB(childNode, childIndex) {
// Code inspired from potree
- node.bbox.copy(this.bbox);
- this.bbox.getCenter(node.bbox.max);
- dHalfLength.copy(node.bbox.max).sub(this.bbox.min);
+ childNode._bbox.copy(this._bbox);
+ this._bbox.getCenter(childNode._bbox.max);
+ dHalfLength.copy(childNode._bbox.max).sub(this._bbox.min);
if (childIndex === 1) {
- node.bbox.min.z += dHalfLength.z;
- node.bbox.max.z += dHalfLength.z;
+ childNode._bbox.min.z += dHalfLength.z;
+ childNode._bbox.max.z += dHalfLength.z;
} else if (childIndex === 3) {
- node.bbox.min.z += dHalfLength.z;
- node.bbox.max.z += dHalfLength.z;
- node.bbox.min.y += dHalfLength.y;
- node.bbox.max.y += dHalfLength.y;
+ childNode._bbox.min.z += dHalfLength.z;
+ childNode._bbox.max.z += dHalfLength.z;
+ childNode._bbox.min.y += dHalfLength.y;
+ childNode._bbox.max.y += dHalfLength.y;
} else if (childIndex === 0) {
//
} else if (childIndex === 2) {
- node.bbox.min.y += dHalfLength.y;
- node.bbox.max.y += dHalfLength.y;
+ childNode._bbox.min.y += dHalfLength.y;
+ childNode._bbox.max.y += dHalfLength.y;
} else if (childIndex === 5) {
- node.bbox.min.z += dHalfLength.z;
- node.bbox.max.z += dHalfLength.z;
- node.bbox.min.x += dHalfLength.x;
- node.bbox.max.x += dHalfLength.x;
+ childNode._bbox.min.z += dHalfLength.z;
+ childNode._bbox.max.z += dHalfLength.z;
+ childNode._bbox.min.x += dHalfLength.x;
+ childNode._bbox.max.x += dHalfLength.x;
} else if (childIndex === 7) {
- node.bbox.min.add(dHalfLength);
- node.bbox.max.add(dHalfLength);
+ childNode._bbox.min.add(dHalfLength);
+ childNode._bbox.max.add(dHalfLength);
} else if (childIndex === 4) {
- node.bbox.min.x += dHalfLength.x;
- node.bbox.max.x += dHalfLength.x;
+ childNode._bbox.min.x += dHalfLength.x;
+ childNode._bbox.max.x += dHalfLength.x;
} else if (childIndex === 6) {
- node.bbox.min.y += dHalfLength.y;
- node.bbox.max.y += dHalfLength.y;
- node.bbox.min.x += dHalfLength.x;
- node.bbox.max.x += dHalfLength.x;
+ childNode._bbox.min.y += dHalfLength.y;
+ childNode._bbox.max.y += dHalfLength.y;
+ childNode._bbox.min.x += dHalfLength.x;
+ childNode._bbox.max.x += dHalfLength.x;
}
}
+ getCenter() {
+ // for potree we send the point use as origin for the data
+ // ie the min corner of the bbox
+ this.center = this._bbox.min;
+ }
+
get octreeIsLoaded() {
return !(this.childrenBitField && this.children.length === 0);
}
@@ -93,6 +99,8 @@ class PotreeNode extends PointCloudNode {
const childrenBitField = view.getUint8(offset); offset += 1;
const numPoints = view.getUint32(offset, true) || this.numPoints; offset += 4;
const item = new PotreeNode(numPoints, childrenBitField, this.layer);
+ item._quaternion = this._quaternion;
+ item._position = this._position;
snode.add(item, indexChild, this);
stack.push(item);
}
diff --git a/src/Layer/Potree2Layer.js b/src/Layer/Potree2Layer.js
index 78678daea1..51b06aa065 100644
--- a/src/Layer/Potree2Layer.js
+++ b/src/Layer/Potree2Layer.js
@@ -181,6 +181,11 @@ class Potree2Layer extends PointCloudLayer {
return this.root.loadOctree().then(resolve);
});
}
+
+ setRootBbox(min, max) {
+ this.root._bbox.min.set(...min);
+ this.root._bbox.max.set(...max);
+ }
}
export default Potree2Layer;
diff --git a/src/Layer/PotreeLayer.js b/src/Layer/PotreeLayer.js
index 372baf8fbd..18a803f572 100644
--- a/src/Layer/PotreeLayer.js
+++ b/src/Layer/PotreeLayer.js
@@ -73,6 +73,11 @@ class PotreeLayer extends PointCloudLayer {
return this.root.loadOctree().then(resolve);
});
}
+
+ setRootBbox(min, max) {
+ this.root._bbox.min.set(...min);
+ this.root._bbox.max.set(...max);
+ }
}
export default PotreeLayer;
diff --git a/src/Parser/Potree2BinParser.js b/src/Parser/Potree2BinParser.js
index b13341d310..e568eeb77f 100644
--- a/src/Parser/Potree2BinParser.js
+++ b/src/Parser/Potree2BinParser.js
@@ -37,8 +37,10 @@ export default {
* @param {ArrayBuffer} buffer - the bin buffer.
* @param {Object} options
* @param {string[]} options.in.pointAttributes - the point attributes information contained in metadata.js
- * @return {Promise} - a promise that resolves with a THREE.BufferGeometry.
+ * @param {THREE.Box3} options.in.bbox - the bbox of the node
+ * @param {THREE.Vector3} options.out.center - the origin position of the data
*
+ * @return {Promise} - a promise that resolves with a THREE.BufferGeometry.
*/
parse: async function parse(buffer, options) {
const metadata = options.in.source.metadata;
@@ -95,6 +97,9 @@ export default {
}
});
+ geometry.userData.origin = options.out.center;
+ geometry.userData.rotation = new THREE.Quaternion();
+
geometry.computeBoundingBox();
return { geometry, density: data.density };
diff --git a/src/Parser/PotreeBinParser.js b/src/Parser/PotreeBinParser.js
index 996ab8e4eb..742392dc94 100644
--- a/src/Parser/PotreeBinParser.js
+++ b/src/Parser/PotreeBinParser.js
@@ -69,6 +69,7 @@ export default {
* @param {ArrayBuffer} buffer - the bin buffer.
* @param {Object} options
* @param {string[]} options.in.pointAttributes - the point attributes information contained in cloud.js
+ * @param {THREE.Vector3} options.out.center - the origin position of the data
* @return {Promise} - a promise that resolves with a THREE.BufferGeometry.
*
*/
@@ -103,6 +104,9 @@ export default {
geometry.setAttribute(attr.attributeName, new THREE.BufferAttribute(array, attr.numElements, attr.normalized));
}
+ geometry.userData.origin = options.out.center;
+ geometry.userData.rotation = new THREE.Quaternion();
+
geometry.computeBoundingBox();
return Promise.resolve(geometry);
diff --git a/src/Parser/PotreeCinParser.js b/src/Parser/PotreeCinParser.js
index 169a658da1..e82be0f34b 100644
--- a/src/Parser/PotreeCinParser.js
+++ b/src/Parser/PotreeCinParser.js
@@ -5,10 +5,12 @@ export default {
/** Parse .cin PotreeConverter format (see {@link https://github.com/peppsac/PotreeConverter/tree/custom_bin}) and convert to a THREE.BufferGeometry
* @function parse
* @param {ArrayBuffer} buffer - the cin buffer.
- * @return {Promise} - a promise that resolves with a THREE.BufferGeometry.
+ * @param {Object} options
+ * @param {THREE.Vector3} options.out.center - the origin position of the data
*
+ * @return {Promise} - a promise that resolves with a THREE.BufferGeometry.
*/
- parse: function parse(buffer) {
+ parse: function parse(buffer, options) {
if (!buffer) {
throw new Error('No array buffer provided.');
}
@@ -29,6 +31,9 @@ export default {
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 4, true));
geometry.boundingBox = box;
+ geometry.userData.origin = options.out.center;
+ geometry.userData.rotation = new THREE.Quaternion();
+
return Promise.resolve(geometry);
},
};
diff --git a/src/Provider/PointCloudProvider.js b/src/Provider/PointCloudProvider.js
index a933fc3826..1f4083581e 100644
--- a/src/Provider/PointCloudProvider.js
+++ b/src/Provider/PointCloudProvider.js
@@ -37,7 +37,7 @@ export default {
points.frustumCulled = false;
points.matrixAutoUpdate = false;
points.scale.copy(layer.scale);
- points.position.copy(geometry.userData.origin || node.bbox.min);
+ points.position.copy(geometry.userData.origin);
const quaternion = geometry.userData.rotation.clone().invert();
points.quaternion.copy(quaternion);
diff --git a/src/Source/PotreeSource.js b/src/Source/PotreeSource.js
index 4229c50d9c..8f3eaa1d92 100644
--- a/src/Source/PotreeSource.js
+++ b/src/Source/PotreeSource.js
@@ -77,6 +77,14 @@ class PotreeSource extends Source {
// https://github.com/PropellerAero/potree-propeller-private/blob/master/docs/file_format.md#cloudjs
this.whenReady = (source.cloud ? Promise.resolve(source.cloud) : Fetcher.json(`${this.url}/${this.file}`, this.networkOptions))
.then((cloud) => {
+ this.boundsConforming = [
+ cloud.tightBoundingBox.lx,
+ cloud.tightBoundingBox.ly,
+ cloud.tightBoundingBox.lz,
+ cloud.tightBoundingBox.ux,
+ cloud.tightBoundingBox.uy,
+ cloud.tightBoundingBox.uz,
+ ];
this.pointAttributes = cloud.pointAttributes;
this.baseurl = `${this.url}/${cloud.octreeDir}/r`;
this.extension = cloud.pointAttributes === 'CIN' ? 'cin' : 'bin';