Skip to content

Commit 4f7e758

Browse files
authored
fixed surface hotspot updates (#4867)
1 parent 626e975 commit 4f7e758

File tree

4 files changed

+54
-45
lines changed

4 files changed

+54
-45
lines changed

packages/model-viewer/src/features/annotation.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
import {Matrix4, Vector3} from 'three';
1818

19-
import ModelViewerElementBase, {$needsRender, $scene, $tick, toVector2D, toVector3D, Vector2D, Vector3D} from '../model-viewer-base.js';
19+
import ModelViewerElementBase, {$needsRender, $onModelLoad, $scene, $tick, toVector2D, toVector3D, Vector2D, Vector3D} from '../model-viewer-base.js';
2020
import {Hotspot, HotspotConfiguration} from '../three-components/Hotspot.js';
2121
import {Constructor} from '../utilities.js';
2222

@@ -101,14 +101,23 @@ export const AnnotationMixin = <T extends Constructor<ModelViewerElementBase>>(
101101
}
102102
}
103103

104+
[$onModelLoad]() {
105+
super[$onModelLoad]();
106+
107+
const scene = this[$scene];
108+
scene.forHotspots((hotspot) => {
109+
scene.updateSurfaceHotspot(hotspot);
110+
});
111+
}
112+
104113
[$tick](time: number, delta: number) {
105114
super[$tick](time, delta);
106115
const scene = this[$scene];
107116
const {annotationRenderer} = scene;
108117
const camera = scene.getCamera();
109118

110119
if (scene.shouldRender()) {
111-
scene.updateSurfaceHotspots();
120+
scene.animateSurfaceHotspots();
112121
scene.updateHotspotsVisibility(camera.position);
113122
annotationRenderer.domElement.style.display = '';
114123
annotationRenderer.render(scene, camera);
@@ -131,6 +140,7 @@ export const AnnotationMixin = <T extends Constructor<ModelViewerElementBase>>(
131140
hotspot.updatePosition(config.position);
132141
hotspot.updateNormal(config.normal);
133142
hotspot.surface = config.surface;
143+
this[$scene].updateSurfaceHotspot(hotspot);
134144
this[$needsRender]();
135145
}
136146

packages/model-viewer/src/test/features/annotation-spec.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
import {expect} from '@esm-bundle/chai';
1717
import {Vector3} from 'three';
1818

19-
import {ModelViewerElement} from '../../model-viewer.js';
2019
import {$needsRender, $scene, toVector3D, Vector2D, Vector3D} from '../../model-viewer-base.js';
20+
import {ModelViewerElement} from '../../model-viewer.js';
2121
import {Hotspot} from '../../three-components/Hotspot.js';
2222
import {ModelScene} from '../../three-components/ModelScene.js';
2323
import {timePasses, waitForEvent} from '../../utilities.js';
@@ -154,11 +154,11 @@ suite('Annotation', () => {
154154
});
155155

156156
test('updateHotspot does change the surface', () => {
157+
const hotspot = scene.target.children[numSlots - 1] as Hotspot;
158+
const {x} = hotspot.position;
157159
const surface = '0 0 1 2 3 0.217 0.341 0.442';
158160
element.updateHotspot({name: 'hotspot-1', surface});
159-
const {surface: internalSurface} =
160-
(scene.target.children[numSlots - 1] as Hotspot);
161-
expect(internalSurface).to.be.deep.equal(surface);
161+
expect(x).to.not.be.equal(hotspot.position.x);
162162
});
163163

164164
test('and removing it does not remove the slot', async () => {

packages/model-viewer/src/three-components/Hotspot.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,7 @@ export class Hotspot extends CSS2DObject {
143143
}
144144
}
145145

146-
updateSurface(forceUpdate: boolean) {
147-
if (!forceUpdate && this.initialized) {
148-
return;
149-
}
146+
updateSurface() {
150147
const {mesh, tri, bary} = this;
151148
if (mesh == null || tri == null || bary == null) {
152149
return;

packages/model-viewer/src/three-components/ModelScene.ts

Lines changed: 37 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -925,6 +925,7 @@ export class ModelScene extends Scene {
925925
// the slots appear in the shadow DOM and the elements get attached,
926926
// allowing us to dispatch events on them.
927927
this.annotationRenderer.domElement.appendChild(hotspot.element);
928+
this.updateSurfaceHotspot(hotspot);
928929
}
929930

930931
removeHotspot(hotspot: Hotspot) {
@@ -947,49 +948,50 @@ export class ModelScene extends Scene {
947948
/**
948949
* Lazy initializer for surface hotspots - will only run once.
949950
*/
950-
initializeSurface(hotspot: Hotspot) {
951-
if (hotspot.surface != null && hotspot.mesh == null) {
952-
const nodes = parseExpressions(hotspot.surface)[0].terms as NumberNode[];
953-
if (nodes.length != 8) {
954-
console.warn(hotspot.surface + ' does not have exactly 8 numbers.');
955-
return;
956-
}
957-
const primitiveNode =
958-
this.element.model![$nodeFromIndex](nodes[0].number, nodes[1].number);
959-
const tri =
960-
new Vector3(nodes[2].number, nodes[3].number, nodes[4].number);
961-
962-
if (primitiveNode == null) {
963-
console.warn(
964-
hotspot.surface +
965-
' does not match a node/primitive in this glTF! Skipping this hotspot.');
966-
return;
967-
}
968-
969-
const numVert = primitiveNode.mesh.geometry.attributes.position.count;
970-
if (tri.x >= numVert || tri.y >= numVert || tri.z >= numVert) {
971-
console.warn(
972-
hotspot.surface +
973-
' vertex indices out of range in this glTF! Skipping this hotspot.');
974-
return;
975-
}
951+
updateSurfaceHotspot(hotspot: Hotspot) {
952+
if (hotspot.surface == null || this.element.model == null) {
953+
return;
954+
}
955+
const nodes = parseExpressions(hotspot.surface)[0].terms as NumberNode[];
956+
if (nodes.length != 8) {
957+
console.warn(hotspot.surface + ' does not have exactly 8 numbers.');
958+
return;
959+
}
960+
const primitiveNode =
961+
this.element.model[$nodeFromIndex](nodes[0].number, nodes[1].number);
962+
if (primitiveNode == null) {
963+
console.warn(
964+
hotspot.surface +
965+
' does not match a node/primitive in this glTF! Skipping this hotspot.');
966+
return;
967+
}
976968

977-
const bary =
978-
new Vector3(nodes[5].number, nodes[6].number, nodes[7].number);
979-
hotspot.mesh = primitiveNode.mesh;
980-
hotspot.tri = tri;
981-
hotspot.bary = bary;
969+
const numVert = primitiveNode.mesh.geometry.attributes.position.count;
970+
const tri = new Vector3(nodes[2].number, nodes[3].number, nodes[4].number);
971+
if (tri.x >= numVert || tri.y >= numVert || tri.z >= numVert) {
972+
console.warn(
973+
hotspot.surface +
974+
' vertex indices out of range in this glTF! Skipping this hotspot.');
975+
return;
982976
}
977+
978+
const bary = new Vector3(nodes[5].number, nodes[6].number, nodes[7].number);
979+
hotspot.mesh = primitiveNode.mesh;
980+
hotspot.tri = tri;
981+
hotspot.bary = bary;
982+
983+
hotspot.updateSurface();
983984
}
984985

985986
/**
986987
* Update positions of surface hotspots to follow model animation.
987988
*/
988-
updateSurfaceHotspots() {
989-
const forceUpdate = !this.element.paused;
989+
animateSurfaceHotspots() {
990+
if (this.element.paused) {
991+
return;
992+
}
990993
this.forHotspots((hotspot) => {
991-
this.initializeSurface(hotspot);
992-
hotspot.updateSurface(forceUpdate);
994+
hotspot.updateSurface();
993995
});
994996
}
995997

0 commit comments

Comments
 (0)