diff --git a/src/ElevationControl/elevationControl.js b/src/ElevationControl/elevationControl.js index a8f4ebb..6a16562 100644 --- a/src/ElevationControl/elevationControl.js +++ b/src/ElevationControl/elevationControl.js @@ -61,6 +61,13 @@ function rebindElevationLabel() { label.textContent = `${low.toFixed(2)} to ${high.toFixed(2)}` } + // Adjust slider limits + slider.slider({ + min: -10000, + max: 0, + values: [-10000, 0] + }) + //clear any old namespaced handlers and attach fresh ones slider.off('slide.custom slidestop.custom change.custom') slider.on('slide.custom', update) diff --git a/src/potreeViewer.js b/src/potreeViewer.js index c05525e..0b5d915 100644 --- a/src/potreeViewer.js +++ b/src/potreeViewer.js @@ -42,6 +42,8 @@ export async function createPotreeViewer(containerId, pointcloudUrl, settings) { pc.material.pointSizeType = Potree.PointSizeType.ADAPTIVE pc.material.shape = Potree.PointShape.CIRCLE + overrideShaderForGradient(pc) + pc.material.elevationRange = [-10000, 0] pc.material.activeAttributeName = 'elevation' pc.material.gradient = Potree.Gradients['VIRIDIS'] @@ -64,3 +66,38 @@ function clampScrollRadius(e) { this.radiusDelta = newRadius - this.scene.view.radius this.stopTweens() } + +function overrideShaderForGradient(pc) { + const originalUpdateShaderSource = pc.material.updateShaderSource + pc.material.updateShaderSource = function () { + // Call the original updateShaderSource first + originalUpdateShaderSource.call(this) + + // Override the shader's getElevation function to use elevation relative to sealevel + this.vertexShader = this.vertexShader.replace( + /vec3 getElevation\(\)[\s\S]*?\}/, + ` + vec3 getElevation(){ + vec4 world = modelMatrix * vec4(position, 1.0); + float radius = length(world.xyz); + float latitude = asin(world.z / radius); + + const float a = 6378137.0; + const float b = 6356752.3; + + float cosLat = cos(latitude); + float sinLat = sin(latitude); + float numerator = (a*a * cosLat) * (a*a * cosLat) + (b*b * sinLat) * (b*b * sinLat); + float denominator = (a * cosLat) * (a * cosLat) + (b * sinLat) * (b * sinLat); + float radiusAtLatitude = sqrt(numerator / denominator); + + float w = (radius - radiusAtLatitude - elevationRange.x) / (elevationRange.y - elevationRange.x); + return texture2D(gradient, vec2(w, 1.0-w)).rgb; + } + ` + ) + + // Mark the material as needing recompilation + this.needsUpdate = true + } +}