Skip to content

Commit

Permalink
fix(Potree1&2): linked to reprojection
Browse files Browse the repository at this point in the history
  • Loading branch information
ftoromanoff committed Feb 27, 2025
1 parent 51b6ff5 commit d358029
Show file tree
Hide file tree
Showing 11 changed files with 140 additions and 74 deletions.
20 changes: 12 additions & 8 deletions examples/potree2_25d_map.html
Original file line number Diff line number Diff line change
Expand Up @@ -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',
}),
});

Expand Down Expand Up @@ -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;

Expand Down
33 changes: 21 additions & 12 deletions examples/potree_25d_map.html
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;

Expand Down
65 changes: 39 additions & 26 deletions src/Core/Potree2Node.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
56 changes: 32 additions & 24 deletions src/Core/PotreeNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand Down
5 changes: 5 additions & 0 deletions src/Layer/Potree2Layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
5 changes: 5 additions & 0 deletions src/Layer/PotreeLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
7 changes: 6 additions & 1 deletion src/Parser/Potree2BinParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 };
Expand Down
4 changes: 4 additions & 0 deletions src/Parser/PotreeBinParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
*/
Expand Down Expand Up @@ -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);
Expand Down
9 changes: 7 additions & 2 deletions src/Parser/PotreeCinParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.');
}
Expand All @@ -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);
},
};
2 changes: 1 addition & 1 deletion src/Provider/PointCloudProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading

0 comments on commit d358029

Please sign in to comment.