From fa74f2835a4a8edadaf07d28b6c55f8444e8ad79 Mon Sep 17 00:00:00 2001 From: ftoromanoff Date: Thu, 25 Jul 2024 09:27:14 +0200 Subject: [PATCH] feat(PointCloud): filtering points based on classification --- src/Renderer/PointsMaterial.js | 46 +++++++++++++++++++++++++++---- src/Renderer/Shader/PointsFS.glsl | 5 ++++ src/Renderer/Shader/PointsVS.glsl | 11 ++++++-- utils/debug/PointCloudDebug.js | 10 +++++++ 4 files changed, 63 insertions(+), 9 deletions(-) diff --git a/src/Renderer/PointsMaterial.js b/src/Renderer/PointsMaterial.js index c6dc4f7bbd..b2f5ffa9fc 100644 --- a/src/Renderer/PointsMaterial.js +++ b/src/Renderer/PointsMaterial.js @@ -123,19 +123,15 @@ function recomputeTexture(scheme, texture, nbClass) { for (let i = 0; i < width; i++) { let color; let opacity; - let visible = true; if (scheme[i]) { color = scheme[i].color; - visible = scheme[i].visible; opacity = scheme[i].opacity; } else if (scheme[i % nbClass]) { color = scheme[i % nbClass].color; - visible = scheme[i % nbClass].visible; opacity = scheme[i % nbClass].opacity; } else if (scheme.DEFAULT) { color = scheme.DEFAULT.color; - visible = scheme.DEFAULT.visible; opacity = scheme.DEFAULT.opacity; } else { color = white; @@ -146,9 +142,9 @@ function recomputeTexture(scheme, texture, nbClass) { data[j + 0] = parseInt(255 * color.r, 10); data[j + 1] = parseInt(255 * color.g, 10); data[j + 2] = parseInt(255 * color.b, 10); - data[j + 3] = visible ? parseInt(255 * opacity, 10) : 0; + data[j + 3] = parseInt(255 * opacity, 10); - needTransparency = needTransparency || opacity < 1 || !visible; + needTransparency = needTransparency || opacity < 1; } texture.needsUpdate = true; return needTransparency; @@ -258,6 +254,14 @@ class PointsMaterial extends THREE.ShaderMaterial { textureLUT.magFilter = THREE.NearestFilter; CommonMaterial.setUniformProperty(this, 'discreteTexture', textureLUT); + // add texture to apply visibility. + const dataVisi = new Uint8Array(256 * 1); + const textureVisi = new THREE.DataTexture(dataVisi, 256, 1, THREE.RedFormat); + + textureVisi.needsUpdate = true; + textureVisi.magFilter = THREE.NearestFilter; + CommonMaterial.setUniformProperty(this, 'visiTexture', textureVisi); + // Classification and other discrete values scheme this.classificationScheme = classificationScheme; this.discreteScheme = discreteScheme; @@ -265,6 +269,7 @@ class PointsMaterial extends THREE.ShaderMaterial { // Update classification and discrete Texture this.recomputeClassification(); this.recomputeDiscreteTexture(); + this.recomputeVisibleTexture(); // Gradient texture for continuous values this.gradient = gradient; @@ -386,6 +391,35 @@ class PointsMaterial extends THREE.ShaderMaterial { }); } + recomputeVisibleTexture() { + const texture = this.visiTexture; + const scheme = this.classificationScheme; + + const data = texture.image.data; + const width = texture.image.width; + + for (let i = 0; i < width; i++) { + let visible; + + if (scheme[i]) { + visible = scheme[i].visible; + } else if (scheme.DEFAULT) { + visible = scheme.DEFAULT.visible; + } else { + visible = true; + } + + data[i] = visible ? 255 : 0; + } + texture.needsUpdate = true; + + + this.dispatchEvent({ + type: 'material_property_changed', + target: this.uniforms, + }); + } + enablePicking(picking) { this.picking = picking; this.blending = picking ? THREE.NoBlending : THREE.NormalBlending; diff --git a/src/Renderer/Shader/PointsFS.glsl b/src/Renderer/Shader/PointsFS.glsl index 378c0d6491..cf554225a5 100644 --- a/src/Renderer/Shader/PointsFS.glsl +++ b/src/Renderer/Shader/PointsFS.glsl @@ -8,6 +8,8 @@ #include #include +varying float visible; + uniform vec3 diffuse; uniform float opacity; @@ -18,6 +20,9 @@ void main() { // Early discard (clipping planes and shape) #include + if (visible < 0.5) { + discard; + } if (shape == PNTS_SHAPE_CIRCLE) { //circular rendering in glsl if ((length(gl_PointCoord - 0.5) > 0.5)) { diff --git a/src/Renderer/Shader/PointsVS.glsl b/src/Renderer/Shader/PointsVS.glsl index 6dae914c36..eb879e0a67 100644 --- a/src/Renderer/Shader/PointsVS.glsl +++ b/src/Renderer/Shader/PointsVS.glsl @@ -4,13 +4,14 @@ #include #include varying vec4 vColor; // color_pars_vertex +varying float visible; #ifdef USE_POINTS_UV varying vec2 vUv; uniform mat3 uvTransform; #endif -#define NB_CLASS 8. +#define SOURCE_ID_GROUP 8. uniform float size; uniform float scale; @@ -25,6 +26,8 @@ uniform vec2 angleRange; uniform sampler2D classificationTexture; uniform sampler2D discreteTexture; uniform sampler2D gradientTexture; +uniform sampler2D visiTexture; + uniform int sizeMode; uniform float minAttenuatedSize; uniform float maxAttenuatedSize; @@ -39,12 +42,14 @@ attribute float numberOfReturns; attribute float scanAngle; void main() { + vec2 uv = vec2(classification/255., 0.5); + visible = texture2D(visiTexture, uv).r; + vColor = vec4(1.0); if (picking) { vColor = unique_id; } else { if (mode == PNTS_MODE_CLASSIFICATION) { - vec2 uv = vec2(classification/255., 0.5); vColor = texture2D(classificationTexture, uv); } else if (mode == PNTS_MODE_NORMAL) { vColor.rgb = abs(normal); @@ -84,7 +89,7 @@ void main() { vec2 uv = vec2(numberOfReturns/255., 0.5); vColor = texture2D(discreteTexture, uv); } else if (mode == PNTS_MODE_POINT_SOURCE_ID) { - vec2 uv = vec2(mod(pointSourceID, NB_CLASS)/255., 0.5); + vec2 uv = vec2(mod(pointSourceID, SOURCE_ID_GROUP)/255., 0.5); vColor = texture2D(discreteTexture, uv); } else if (mode == PNTS_MODE_SCAN_ANGLE) { float i = (scanAngle - angleRange.x) / (angleRange.y - angleRange.x); diff --git a/utils/debug/PointCloudDebug.js b/utils/debug/PointCloudDebug.js index c65992c575..2e1a8cb2fb 100644 --- a/utils/debug/PointCloudDebug.js +++ b/utils/debug/PointCloudDebug.js @@ -80,6 +80,16 @@ export default { layer.material.mode = PNTS_MODE[value]; update(); }); + + const classeUI = styleUI.addFolder('Classe Visibility').close(); + Object.entries(layer.material.classificationScheme).forEach((classe) => { + classeUI.add(classe[1], 'visible').name(classe[1].name) + .onChange(() => { + layer.material.recomputeVisibleTexture(); + update(); + }); + }); + const gradiantsNames = Object.keys(layer.material.gradients); styleUI.add({ gradient: gradiantsNames[0] }, 'gradient', gradiantsNames).name('gradient') .onChange((value) => {