diff --git a/packages/viewer-sandbox/src/main.ts b/packages/viewer-sandbox/src/main.ts index 8ff20c996..7069c5751 100644 --- a/packages/viewer-sandbox/src/main.ts +++ b/packages/viewer-sandbox/src/main.ts @@ -40,7 +40,4 @@ sandbox.makeGenericUI() sandbox.makeSceneUI() sandbox.makeFilteringUI() // Load demo object -sandbox.loadUrl( - // 'https://speckle.xyz/streams/17b0b76d13/commits/1ba20ba64b?c=%5B700048.95339,5709850.71008,148.503,699898.46699,5710107.01323,-147.5969,0,1%5D' - 'https://latest.speckle.dev/streams/444bfbd6e4/commits/ee4fcfba43' -) +sandbox.loadUrl('https://latest.speckle.dev/streams/ca0378725b/commits/e5a66562cc') diff --git a/packages/viewer/src/modules/batching/Batcher.ts b/packages/viewer/src/modules/batching/Batcher.ts index 93acb268a..4ff65147c 100644 --- a/packages/viewer/src/modules/batching/Batcher.ts +++ b/packages/viewer/src/modules/batching/Batcher.ts @@ -36,7 +36,7 @@ export default class Batcher { ...Array.from(new Set(rendeViews.map((value) => value.renderMaterialHash))) ] - // console.warn(materialHashes) + console.warn(materialHashes) // console.warn(rendeViews) for (let i = 0; i < materialHashes.length; i++) { @@ -80,7 +80,7 @@ export default class Batcher { this.batches[batchID].setBatchMaterial(material) this.batches[batchID].buildBatch() - // console.warn(batch) + console.warn(batch) } } diff --git a/packages/viewer/src/modules/batching/PointBatch.ts b/packages/viewer/src/modules/batching/PointBatch.ts index 57e112ed5..6c2000261 100644 --- a/packages/viewer/src/modules/batching/PointBatch.ts +++ b/packages/viewer/src/modules/batching/PointBatch.ts @@ -6,6 +6,7 @@ import { Points, WebGLRenderer } from 'three' +import { Geometry } from '../converter/Geometry' import { NodeRenderView } from '../tree/NodeRenderView' import { World } from '../World' import { Batch, BatchUpdateRange, HideAllBatchUpdateRange } from './Batch' @@ -190,7 +191,7 @@ export default class PointBatch implements Batch { const attributeCount = this.renderViews.flatMap( (val: NodeRenderView) => val.renderData.geometry.attributes.POSITION ).length - const position = new Float32Array(attributeCount) + const position = new Float64Array(attributeCount) const color = new Float32Array(attributeCount).fill(1) let offset = 0 for (let k = 0; k < this.renderViews.length; k++) { @@ -221,11 +222,8 @@ export default class PointBatch implements Batch { } } - /** - * DUPLICATE from Geometry. Will unify in the future - */ private makePointGeometry( - position: Float32Array, + position: Float64Array, color: Float32Array ): BufferGeometry { this.geometry = new BufferGeometry() @@ -238,6 +236,7 @@ export default class PointBatch implements Batch { this.geometry.computeBoundingBox() World.expandWorld(this.geometry.boundingBox) + Geometry.updateRTEGeometry(this.geometry, position) return this.geometry } diff --git a/packages/viewer/src/modules/materials/Materials.ts b/packages/viewer/src/modules/materials/Materials.ts index 846816344..94ebf2d70 100644 --- a/packages/viewer/src/modules/materials/Materials.ts +++ b/packages/viewer/src/modules/materials/Materials.ts @@ -134,30 +134,39 @@ export default class Materials { ;(this.lineColoredMaterial).pixelThreshold = 0.5 ;(this.lineColoredMaterial).resolution = new Vector2() - this.pointCloudHighlightMaterial = new SpecklePointMaterial({ - color: 0xff0000, - vertexColors: true, - size: 2, - sizeAttenuation: false - // clippingPlanes: this.viewer.sectionBox.planes - }) + this.pointCloudHighlightMaterial = new SpecklePointMaterial( + { + color: 0xff0000, + vertexColors: true, + size: 2, + sizeAttenuation: false + // clippingPlanes: this.viewer.sectionBox.planes + }, + ['USE_RTE'] + ) - this.pointHighlightMaterial = new SpecklePointMaterial({ - color: 0xff0000, - vertexColors: false, - size: 2, - sizeAttenuation: false - // clippingPlanes: this.viewer.sectionBox.planes - }) + this.pointHighlightMaterial = new SpecklePointMaterial( + { + color: 0xff0000, + vertexColors: false, + size: 2, + sizeAttenuation: false + // clippingPlanes: this.viewer.sectionBox.planes + }, + ['USE_RTE'] + ) - this.pointGhostMaterial = new SpecklePointMaterial({ - color: 0xffffff, - vertexColors: false, - size: 2, - opacity: 0.01, - sizeAttenuation: false - // clippingPlanes: this.viewer.sectionBox.planes - }) + this.pointGhostMaterial = new SpecklePointMaterial( + { + color: 0xffffff, + vertexColors: false, + size: 2, + opacity: 0.01, + sizeAttenuation: false + // clippingPlanes: this.viewer.sectionBox.planes + }, + ['USE_RTE'] + ) this.meshGhostMaterial = new SpeckleStandardMaterial( { @@ -265,29 +274,38 @@ export default class Materials { ;(this.materialMap[hash]).pixelThreshold = 0.5 ;(this.materialMap[hash]).resolution = new Vector2() - this.materialMap[NodeRenderView.NullPointMaterialHash] = new SpecklePointMaterial({ - color: 0x7f7f7f, - vertexColors: false, - size: 2, - sizeAttenuation: false - // clippingPlanes: this.viewer.sectionBox.planes - }) - this.materialMap[NodeRenderView.NullPointCloudVertexColorsMaterialHash] = - new SpecklePointMaterial({ - color: 0xffffff, - vertexColors: true, - size: 2, - sizeAttenuation: false - // clippingPlanes: this.viewer.sectionBox.planes - }) - this.materialMap[NodeRenderView.NullPointCloudMaterialHash] = - new SpecklePointMaterial({ - color: 0xffffff, + this.materialMap[NodeRenderView.NullPointMaterialHash] = new SpecklePointMaterial( + { + color: 0x7f7f7f, vertexColors: false, size: 2, sizeAttenuation: false // clippingPlanes: this.viewer.sectionBox.planes - }) + }, + ['USE_RTE'] + ) + this.materialMap[NodeRenderView.NullPointCloudVertexColorsMaterialHash] = + new SpecklePointMaterial( + { + color: 0xffffff, + vertexColors: true, + size: 2, + sizeAttenuation: false + // clippingPlanes: this.viewer.sectionBox.planes + }, + ['USE_RTE'] + ) + this.materialMap[NodeRenderView.NullPointCloudMaterialHash] = + new SpecklePointMaterial( + { + color: 0xffffff, + vertexColors: false, + size: 2, + sizeAttenuation: false + // clippingPlanes: this.viewer.sectionBox.planes + }, + ['USE_RTE'] + ) } private makeMeshMaterial(materialData: RenderMaterial): Material { @@ -330,14 +348,29 @@ export default class Materials { } private makePointMaterial(materialData: RenderMaterial): Material { - const mat = new SpecklePointMaterial({ - color: materialData.color, - opacity: materialData.opacity, - vertexColors: false, - size: 2, - sizeAttenuation: false - // clippingPlanes: this.viewer.sectionBox.planes - }) + /** There's an issue with how the data is being sent. Some point clouds + * have render materials with 0x000000 as the base color + vertex colors + * By default three.js modulates the base color with the vertex colors + * But since the base color is black, the result is also black. We'll have + * to avoid this + */ + const isBaseColorBlack = materialData.color === -16777216 // 0xff000000 (black) + const safeColor = materialData.vertexColors + ? isBaseColorBlack + ? 0xffffff + : materialData.color + : materialData.color + const mat = new SpecklePointMaterial( + { + color: safeColor, + opacity: materialData.opacity, + vertexColors: materialData.vertexColors, + size: 2, + sizeAttenuation: false + // clippingPlanes: this.viewer.sectionBox.planes + }, + ['USE_RTE'] + ) mat.transparent = mat.opacity < 1 ? true : false mat.depthWrite = mat.transparent ? false : true mat.color.convertSRGBToLinear() @@ -472,19 +505,25 @@ export default class Materials { return mat } case GeometryType.POINT: - return new SpecklePointMaterial({ - color, - vertexColors: false, - size: 2, - sizeAttenuation: false - }) + return new SpecklePointMaterial( + { + color, + vertexColors: false, + size: 2, + sizeAttenuation: false + }, + ['USE_RTE'] + ) case GeometryType.POINT_CLOUD: - return new SpecklePointMaterial({ - color, - vertexColors: true, - size: 2, - sizeAttenuation: false - }) + return new SpecklePointMaterial( + { + color, + vertexColors: true, + size: 2, + sizeAttenuation: false + }, + ['USE_RTE'] + ) } } diff --git a/packages/viewer/src/modules/materials/SpecklePointMaterial.ts b/packages/viewer/src/modules/materials/SpecklePointMaterial.ts index 2264b22c6..5f25857f7 100644 --- a/packages/viewer/src/modules/materials/SpecklePointMaterial.ts +++ b/packages/viewer/src/modules/materials/SpecklePointMaterial.ts @@ -1,16 +1,42 @@ +/* eslint-disable camelcase */ /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-unused-vars */ import { specklePointVert } from './shaders/speckle-point-vert' import { specklePointFrag } from './shaders/speckle-point-frag' -import { PointsMaterial } from 'three' +import { Matrix4, PointsMaterial, ShaderLib, UniformsUtils, Vector3 } from 'three' +import { Geometry } from '../converter/Geometry' class SpecklePointMaterial extends PointsMaterial { + private static readonly matBuff: Matrix4 = new Matrix4() + private static readonly vecBuff0: Vector3 = new Vector3() + private static readonly vecBuff1: Vector3 = new Vector3() + private static readonly vecBuff2: Vector3 = new Vector3() + constructor(parameters, defines = []) { super(parameters) + this.userData.uViewer_high = { + value: new Vector3() + } + this.userData.uViewer_low = { + value: new Vector3() + } ;(this as any).vertProgram = specklePointVert ;(this as any).fragProgram = specklePointFrag + ;(this as any).uniforms = UniformsUtils.merge([ + ShaderLib.standard.uniforms, + { + uViewer_high: { + value: this.userData.uViewer_high.value + }, + uViewer_low: { + value: this.userData.uViewer_low.value + } + } + ]) this.onBeforeCompile = function (shader) { + shader.uniforms.uViewer_high = this.userData.uViewer_high + shader.uniforms.uViewer_low = this.userData.uViewer_low shader.vertexShader = this.vertProgram shader.fragmentShader = this.fragProgram } @@ -26,8 +52,43 @@ class SpecklePointMaterial extends PointsMaterial { copy(source) { super.copy(source) this.userData = {} + this.userData.uViewer_high = { + value: new Vector3() + } + this.userData.uViewer_low = { + value: new Vector3() + } + + this.defines['USE_RTE'] = ' ' + return this } + + onBeforeRender(_this, scene, camera, geometry, object, group) { + SpecklePointMaterial.matBuff.copy(camera.matrixWorldInverse) + SpecklePointMaterial.matBuff.elements[12] = 0 + SpecklePointMaterial.matBuff.elements[13] = 0 + SpecklePointMaterial.matBuff.elements[14] = 0 + SpecklePointMaterial.matBuff.multiply(object.matrixWorld) + object.modelViewMatrix.copy(SpecklePointMaterial.matBuff) + + SpecklePointMaterial.vecBuff0.set( + camera.matrixWorld.elements[12], + camera.matrixWorld.elements[13], + camera.matrixWorld.elements[14] + ) + + Geometry.DoubleToHighLowVector( + SpecklePointMaterial.vecBuff0, + SpecklePointMaterial.vecBuff1, + SpecklePointMaterial.vecBuff2 + ) + + this.userData.uViewer_low.value.copy(SpecklePointMaterial.vecBuff1) + this.userData.uViewer_high.value.copy(SpecklePointMaterial.vecBuff2) + + this.needsUpdate = true + } } export default SpecklePointMaterial diff --git a/packages/viewer/src/modules/materials/shaders/speckle-point-vert.ts b/packages/viewer/src/modules/materials/shaders/speckle-point-vert.ts index c97859794..d4f190bec 100644 --- a/packages/viewer/src/modules/materials/shaders/speckle-point-vert.ts +++ b/packages/viewer/src/modules/materials/shaders/speckle-point-vert.ts @@ -9,13 +9,43 @@ uniform float scale; #include #include +#ifdef USE_RTE + // The high component is stored as the default 'position' attribute buffer + attribute vec3 position_low; + uniform vec3 uViewer_high; + uniform vec3 uViewer_low; +#endif + void main() { #include #include #include #include - #include + // #include COMMENTED CHUNK + #ifdef USE_RTE + /* + Source https://github.com/virtualglobebook/OpenGlobe/blob/master/Source/Examples/Chapter05/Jitter/GPURelativeToEyeDSFUN90/Shaders/VS.glsl + Note here, we're storing the high part of the position encoding inside three's default 'position' attribute buffer so we avoid redundancy + */ + vec3 t1 = position_low.xyz - uViewer_low; + vec3 e = t1 - position_low.xyz; + vec3 t2 = ((-uViewer_low - e) + (position_low.xyz - (t1 - e))) + position.xyz - uViewer_high; + vec3 highDifference = t1 + t2; + vec3 lowDifference = t2 - (highDifference - t1); + vec4 mvPosition = vec4(highDifference.xyz + lowDifference.xyz , 1.); + #else + vec4 mvPosition = vec4( transformed, 1.0 ); + #endif + + #ifdef USE_INSTANCING + + mvPosition = instanceMatrix * mvPosition; + + #endif + mvPosition = modelViewMatrix * mvPosition; + + gl_Position = projectionMatrix * mvPosition; gl_PointSize = size;