Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(PointCloud): increase range of picking to u32 #2288

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ The following people have contributed to iTowns.
* [Madec Germerie-Guizouarn](https://github.com/mgermerie)
* [Mathieu Brédif](https://github.com/mbredif)
* [Aymeric Dutremble](https://github.com/a-dutremble)
* [Raphaël Duhen](https://github.com/HoloTheDrunk)

* [CIRIL Group](https://www.cirilgroup.com/en/):
* [Vincent Jaillot](https://github.com/jailln)
Expand Down
6 changes: 3 additions & 3 deletions src/Core/Picking.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,11 @@ export default {

traversePickingCircle(radius, (x, y) => {
const idx = (y * 2 * radius + x) * 4;
const data = buffer.slice(idx, idx + 4);
const data = buffer.slice(idx, idx + 3);

// see PotreeProvider and the construction of unique_id
const objId = (data[0] << 8) | data[1];
const index = (data[2] << 8) | data[3];
const objId = data[0];
const index = (data[1] << 16) | data[2];
Comment on lines +151 to +155
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You encode each 48-bits unique_id value as 3 uint16. However, you read the resulting texture with a uint8 buffer (see c3dEngine#renderViewToBuffer)...

I don't think values are preserved here.

Copy link
Contributor Author

@HoloTheDrunk HoloTheDrunk Jun 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can provide a u16 buffer ourselves

- const buffer = view.mainLoop.gfxEngine.renderViewToBuffer(
-     { camera: view.camera, scene: tileLayer.object3d },
-     {
-         x: viewCoords.x - radius,
-         y: viewCoords.y - radius,
-         width: 1 + radius * 2,
-         height: 1 + radius * 2,
-     });
+ const zone = {
+     x: viewCoords.x - radius,
+     y: viewCoords.y - radius,
+     width: 1 + radius * 2,
+     height: 1 + radius * 2,
+ };
+ zone.buffer = new Uint16Array(4 * zone.width * zone.height);
+ const buffer = view.mainLoop.gfxEngine.renderViewToBuffer(
+     { camera: view.camera, scene: tileLayer.object3d },
+     zone,
+ );

But looking into things a bit more I'm not sure how this is gonna interact with the default fullSizeRenderTarget used by the c3DEngine that gets created with u8 rgba formatting.
I currently don't have an example I could use to check for this issue, as the results don't change for the example I originally used for this PR (potree 3d map).


const r = { objId, index };

Expand Down
59 changes: 43 additions & 16 deletions src/Provider/PointCloudProvider.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,52 @@
import * as THREE from 'three';
import Extent from 'Core/Geographic/Extent';

const CLOUD_ID_WORD_COUNT = 1;
const MAX_CLOUDS = 2 ** (CLOUD_ID_WORD_COUNT * 16);

const POINT_ID_WORD_COUNT = 2;
const MAX_POINTS_PER_CLOUD = 2 ** (POINT_ID_WORD_COUNT * 16);

const ID_WORD_COUNT = POINT_ID_WORD_COUNT + CLOUD_ID_WORD_COUNT;

let nextuuid = 1;
/**
* Generate a unique ID for every point in a cloud.
* @param {THREE.Points} points - The point cloud to add IDs to.
* @returns {THREE.Points} The resulting point cloud.
*/
function addPickingAttribute(points) {
// generate unique id for picking
const numPoints = points.geometry.attributes.position.count;
const ids = new Uint8Array(4 * numPoints);
const baseId = nextuuid++;
if (numPoints > 0xffff || baseId > 0xffff) {
// TODO: fixme
console.warn('Currently picking is limited to Points with less than 65535 elements and less than 65535 Points instances');
const cloudId = nextuuid++;

if (
numPoints >= MAX_POINTS_PER_CLOUD ||
cloudId > MAX_CLOUDS
) {
console.warn(
`Too many points or clouds: ${numPoints} points and ${cloudId} clouds.\n` +
`Picking is currently limited to Points with less than ${MAX_POINTS_PER_CLOUD} elements and less than ${MAX_CLOUDS} Points instances`,
);
return points;
}
for (let i = 0; i < numPoints; i++) {
// todo numpoints > 16bits
const v = (baseId << 16) | i;
ids[4 * i + 0] = (v & 0xff000000) >> 24;
ids[4 * i + 1] = (v & 0x00ff0000) >> 16;
ids[4 * i + 2] = (v & 0x0000ff00) >> 8;
ids[4 * i + 3] = (v & 0x000000ff) >> 0;

// Generate and store an ID for every single point
const ids = new Uint16Array(ID_WORD_COUNT * numPoints);
for (let pointId = 0; pointId < numPoints; pointId++) {
// Full ID:
// word word word
// \__/ \_______/
// cloudId pointId
ids[ID_WORD_COUNT * pointId + 2] = pointId & 0x0000_ffff;
ids[ID_WORD_COUNT * pointId + 1] = (pointId & 0xffff_0000) >> 16;
ids[ID_WORD_COUNT * pointId] = cloudId;
}

points.baseId = baseId;
points.geometry.setAttribute('unique_id', new THREE.BufferAttribute(ids, 4, true));
points.baseId = cloudId;
points.geometry.setAttribute(
'unique_id',
new THREE.BufferAttribute(ids, 3, true),
);
return points;
}

Expand All @@ -41,7 +65,10 @@ export default {
points.updateMatrix();
points.tightbbox = geometry.boundingBox.applyMatrix4(points.matrix);
points.layer = layer;
points.extent = Extent.fromBox3(command.view.referenceCrs, node.bbox);
points.extent = Extent.fromBox3(
command.view.referenceCrs,
node.bbox,
);
points.userData.node = node;
return points;
});
Expand Down
4 changes: 2 additions & 2 deletions src/Renderer/Shader/PointsVS.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ uniform float maxAttenuatedSize;

attribute vec3 color;
attribute vec2 range;
attribute vec4 unique_id;
attribute vec3 unique_id;
attribute float intensity;
attribute float classification;
attribute float pointSourceID;
Expand Down Expand Up @@ -95,7 +95,7 @@ void main() {
#endif

if (picking) {
vColor = unique_id;
vColor = vec4(unique_id, 1.0);
} else {
vColor.a = opacity;
if (applyOpacityClassication || mode == PNTS_MODE_CLASSIFICATION) {
Expand Down
Loading