From 37a94faa6c819efb8604f83b2c78ceaca8aff8fe Mon Sep 17 00:00:00 2001 From: Alexandru Popovici Date: Tue, 19 Mar 2024 14:03:17 +0200 Subject: [PATCH] Measurements fixes (#2141) * TAS does not only test for intersections on front facing triangles anymore * Raycasting against a billboard speckle text before it's first frame is rejected * Handled WBX-353. Fixed an issue where measurement gizmos were given incorrect screen sizes. Possible fix for incorrect NDC normal calculation for perpendicular measurement normal indicator. Needs more mafs * When computing the perp measurement's normal line indicator we don't apply the perspective divide anymore after computing the normal in clip space. This fixes the issue where -Y normal direction was almost never correctly reported * Removed log --- packages/viewer-sandbox/src/main.ts | 2 ++ .../extensions/measurements/Measurement.ts | 1 + .../measurements/MeasurementPointGizmo.ts | 3 ++- .../measurements/MeasurementsExtension.ts | 1 + .../measurements/PerpendicularMeasurement.ts | 16 ++++++++-------- .../viewer/src/modules/objects/SpeckleText.ts | 3 +++ .../objects/TopLevelAccelerationStructure.ts | 4 ++-- 7 files changed, 19 insertions(+), 11 deletions(-) diff --git a/packages/viewer-sandbox/src/main.ts b/packages/viewer-sandbox/src/main.ts index c0a47310c..21b7037ce 100644 --- a/packages/viewer-sandbox/src/main.ts +++ b/packages/viewer-sandbox/src/main.ts @@ -366,6 +366,8 @@ const getStream = () => { // 'https://latest.speckle.dev/streams/aea12cab71/commits/787ade768e' // 'https://speckle.xyz/streams/a29e5c7772/commits/a8cfae2645' // 'https://latest.speckle.dev/streams/9d71f041b2/commits/01279333e5' + 'https://latest.speckle.dev/streams/65c512f4ea/commits/cc2490830a' + // 'https://latest.speckle.dev/streams/65c512f4ea/objects/882497528d1fa06660c28c1fd6aa15e0' // 'https://speckle.xyz/streams/b4086833f8/commits/94df4c6d16' // Rebar diff --git a/packages/viewer/src/modules/extensions/measurements/Measurement.ts b/packages/viewer/src/modules/extensions/measurements/Measurement.ts index e12c74f76..479898f1b 100644 --- a/packages/viewer/src/modules/extensions/measurements/Measurement.ts +++ b/packages/viewer/src/modules/extensions/measurements/Measurement.ts @@ -27,6 +27,7 @@ export abstract class Measurement extends Object3D { protected static vec3Buff4: Vector3 = new Vector3() protected static vec4Buff0: Vector4 = new Vector4() protected static vec4Buff1: Vector4 = new Vector4() + protected static vec4Buff2: Vector4 = new Vector4() protected static vec2Buff0: Vector2 = new Vector2() protected _state: MeasurementState = MeasurementState.HIDDEN diff --git a/packages/viewer/src/modules/extensions/measurements/MeasurementPointGizmo.ts b/packages/viewer/src/modules/extensions/measurements/MeasurementPointGizmo.ts index 66f3471cf..a9904b31e 100644 --- a/packages/viewer/src/modules/extensions/measurements/MeasurementPointGizmo.ts +++ b/packages/viewer/src/modules/extensions/measurements/MeasurementPointGizmo.ts @@ -8,6 +8,7 @@ import { Group, InterleavedBufferAttribute, Material, + MathUtils, Mesh, OrthographicCamera, PerspectiveCamera, @@ -202,7 +203,7 @@ export class MeasurementPointGizmo extends Group { point2.layers.set(ObjectLayers.MEASUREMENTS) this.point.add(point2) - this.text = new SpeckleText('test-text', ObjectLayers.MEASUREMENTS) + this.text = new SpeckleText(MathUtils.generateUUID(), ObjectLayers.MEASUREMENTS) this.text.textMesh.material = null this.add(this.point) diff --git a/packages/viewer/src/modules/extensions/measurements/MeasurementsExtension.ts b/packages/viewer/src/modules/extensions/measurements/MeasurementsExtension.ts index 6cadcbc09..e9f6294f0 100644 --- a/packages/viewer/src/modules/extensions/measurements/MeasurementsExtension.ts +++ b/packages/viewer/src/modules/extensions/measurements/MeasurementsExtension.ts @@ -117,6 +117,7 @@ export class MeasurementsExtension extends Extension { if (!this._enabled) return this._frameLock = false + this.renderer.renderer.getDrawingBufferSize(this.screenBuff0) if (this._activeMeasurement) this._activeMeasurement.frameUpdate( diff --git a/packages/viewer/src/modules/extensions/measurements/PerpendicularMeasurement.ts b/packages/viewer/src/modules/extensions/measurements/PerpendicularMeasurement.ts index a5a3785b7..7279440bb 100644 --- a/packages/viewer/src/modules/extensions/measurements/PerpendicularMeasurement.ts +++ b/packages/viewer/src/modules/extensions/measurements/PerpendicularMeasurement.ts @@ -1,4 +1,4 @@ -import { Box3, Camera, PerspectiveCamera, Plane, Vector2, Vector3 } from 'three' +import { Box3, Camera, Plane, Vector2, Vector3 } from 'three' import { MeasurementPointGizmo } from './MeasurementPointGizmo' import { getConversionFactor } from '../../converter/Units' import { Measurement, MeasurementState } from './Measurement' @@ -8,7 +8,7 @@ export class PerpendicularMeasurement extends Measurement { private startGizmo: MeasurementPointGizmo = null private endGizmo: MeasurementPointGizmo = null private midPoint: Vector3 = new Vector3() - private normalIndicatorPixelSize = 15 + private normalIndicatorPixelSize = 15 * window.devicePixelRatio public set isVisible(value: boolean) { this.startGizmo.enable(value, value, value, value) @@ -71,19 +71,18 @@ export class PerpendicularMeasurement extends Measurement { .applyMatrix4(this.renderingCamera.matrixWorldInverse) .applyMatrix4(this.renderingCamera.projectionMatrix) .normalize() + /** If we apply perspective division, the result is off **/ // Move to NDC - const normalpDiv = normalNDC.w === 0 ? 1 : normalNDC.w - normalNDC.multiplyScalar(1 / normalpDiv).normalize() - if (this.renderingCamera instanceof PerspectiveCamera) { - normalNDC.negate() - } + // const normalpDiv = normalNDC.w === 0 ? 1 : normalNDC.w + // normalNDC.multiplyScalar(1 / normalpDiv).normalize() + const pixelScale = Measurement.vec2Buff0.set( (this.normalIndicatorPixelSize / this.renderingSize.x) * 2, (this.normalIndicatorPixelSize / this.renderingSize.y) * 2 ) // Add the scaled NDC normal to the NDC start point, we get the end point in NDC - const endNDC = Measurement.vec4Buff0 + const endNDC = Measurement.vec4Buff2 .set(startNDC.x, startNDC.y, startNDC.z, 1) .add( Measurement.vec4Buff1.set( @@ -103,6 +102,7 @@ export class PerpendicularMeasurement extends Measurement { startLine0, Measurement.vec3Buff1.set(endNDC.x, endNDC.y, endNDC.z) ]) + this.endGizmo.enable(false, false, false, false) } diff --git a/packages/viewer/src/modules/objects/SpeckleText.ts b/packages/viewer/src/modules/objects/SpeckleText.ts index 1cf4821d0..6610d60c0 100644 --- a/packages/viewer/src/modules/objects/SpeckleText.ts +++ b/packages/viewer/src/modules/objects/SpeckleText.ts @@ -103,6 +103,8 @@ export class SpeckleText extends Mesh { this.onBeforeRender = (renderer) => { renderer.getDrawingBufferSize(this._resolution) } + /** Otherwise three.js is inconsistent in calling our 'onBeforeRender' */ + this.frustumCulled = false } public async update(params: SpeckleTextParams, updateFinished?: () => void) { @@ -162,6 +164,7 @@ export class SpeckleText extends Mesh { x = Math.sin(x / curveRadius) * curveRadius } if (this.textMesh.material.defines['BILLBOARD_FIXED']) { + if (this._resolution.length() === 0) return const billboardSize = new Vector2().set( (this.textMesh.material.billboardPixelHeight / this._resolution.x) * 2, (this.textMesh.material.billboardPixelHeight / this._resolution.y) * 2 diff --git a/packages/viewer/src/modules/objects/TopLevelAccelerationStructure.ts b/packages/viewer/src/modules/objects/TopLevelAccelerationStructure.ts index 72c9d3485..6d2b2f08d 100644 --- a/packages/viewer/src/modules/objects/TopLevelAccelerationStructure.ts +++ b/packages/viewer/src/modules/objects/TopLevelAccelerationStructure.ts @@ -159,7 +159,7 @@ export class TopLevelAccelerationStructure { rayBuff.copy(ray) const tasResults: Intersection[] = this.accelerationStructure.raycast( rayBuff, - FrontSide + materialOrSide ) if (!tasResults.length) return res @@ -192,7 +192,7 @@ export class TopLevelAccelerationStructure { rayBuff.copy(ray) const tasRes: Intersection = this.accelerationStructure.raycastFirst( rayBuff, - FrontSide + materialOrSide ) if (!tasRes) return res