From 30b9ff229e0ee6441a5d86879d3e603ea1791c75 Mon Sep 17 00:00:00 2001 From: Jacob Bandes-Storch Date: Tue, 26 Sep 2023 12:26:19 -0700 Subject: [PATCH] Restore somewhat-correct bounding sphere calculation for three >=151 (#222) ### Public-Facing Changes Restored the bounding sphere behavior for three.js versions >=r151. ### Description InstancedMesh now supports bounding sphere calculation, but it uses `instanceMatrix` which we do not set in this code. Instead, fall back to the geometry's boundingSphere, which is what it used to do before r151. This only uses the non-instanced vertices, but the Label's `position` still gets correctly applied which makes depth sorting mostly work (the same way it used to). --- package.json | 2 +- src/LabelPool.ts | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index fb159e1..0c498ae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@foxglove/three-text", - "version": "0.2.1", + "version": "0.2.2", "description": "Render text in 3D using Signed Distance Fields", "license": "MIT", "repository": { diff --git a/src/LabelPool.ts b/src/LabelPool.ts index 09a3ab6..b394138 100644 --- a/src/LabelPool.ts +++ b/src/LabelPool.ts @@ -141,6 +141,22 @@ void main() { } } +/** + * Since THREE.js r151, InstancedMesh supports bounding sphere calculations using instanceMatrix. + * However, Label does not use instanceMatrix and the resulting bounding spheres are have NaN + * values. Instead, fall back to using the (non-instanced) bounding sphere of the geometry, which at + * least provides a semi-correct value based on the label's `position`. + */ +class InstancedMeshWithBasicBoundingSphere extends THREE.InstancedMesh { + override computeBoundingSphere(): void { + this.geometry.computeBoundingSphere(); + const boundingSphere = this.geometry.boundingSphere; + if (boundingSphere) { + (this.boundingSphere ??= new THREE.Sphere()).copy(boundingSphere); + } + } +} + export class Label extends THREE.Object3D { text = ""; mesh: THREE.InstancedMesh; @@ -183,7 +199,7 @@ export class Label extends THREE.Object3D { this.material = new LabelMaterial({ atlasTexture: labelPool.atlasTexture }); this.pickingMaterial = new LabelMaterial({ picking: true }); - this.mesh = new THREE.InstancedMesh(this.geometry, this.material, 0); + this.mesh = new InstancedMeshWithBasicBoundingSphere(this.geometry, this.material, 0); this.mesh.userData.pickingMaterial = this.pickingMaterial; this.mesh.onBeforeRender = (renderer, _scene, _camera, _geometry, _material, _group) => {