From bccc603e5c169cb6a643be67f9898af8657519dc Mon Sep 17 00:00:00 2001 From: Frank3K <8014077+Frank3K@users.noreply.github.com> Date: Mon, 8 Jun 2026 22:23:55 +0200 Subject: [PATCH] fix: apply orientation to extra-model elements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `updateModelTransforms` accepted an `orientation` parameter but never used it, so `` had no effect. Parse the value with `parseExpressions`/`normalizeUnit` (supporting `deg`/`rad` units) and apply it as an Euler rotation on the model's quaternion, using the same `$roll $pitch $yaw` → `Euler(pitch, yaw, roll, 'YXZ')` convention as `applyTransform` and the documented `orientation` attribute. Also fix the multimodel example: bare numbers are treated as radians by the unit parser, and the axis ordering follows roll/pitch/yaw, so update the orientation attributes to `"0deg 0deg 30deg"` / `"0deg 0deg -30deg"` (yaw = third term) to produce the intended 30° Y-axis rotation. Add a test covering both initial application and dynamic updates of the orientation attribute. --- .../src/test/features/extra-model-spec.ts | 26 +++++++++++++++++++ .../src/three-components/ModelScene.ts | 13 +++++++++- .../examples/multimodel/index.html | 6 ++--- 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/packages/model-viewer/src/test/features/extra-model-spec.ts b/packages/model-viewer/src/test/features/extra-model-spec.ts index 0620eaba8a..f538c1550a 100644 --- a/packages/model-viewer/src/test/features/extra-model-spec.ts +++ b/packages/model-viewer/src/test/features/extra-model-spec.ts @@ -78,6 +78,32 @@ suite('ExtraModel', () => { expect(scene._models[1].position.x).to.equal(5); }); + test('applies orientation as rotation on the model quaternion', async () => { + element.loading = 'eager'; + element.src = CUBE_GLB_PATH; + + const extra = document.createElement('extra-model'); + extra.setAttribute('src', CUBE_GLB_PATH); + // yaw = 90deg (third term in roll/pitch/yaw) → Euler(0, π/2, 0, 'YXZ') + // → quaternion.y ≈ 0.707, quaternion.w ≈ 0.707 + extra.setAttribute('orientation', '0deg 0deg 90deg'); + element.appendChild(extra); + + await waitForEvent(element, 'load'); + + const scene = (element as any)[$scene]; + const q = scene._models[1].quaternion; + expect(q.y).to.be.closeTo(Math.sin(Math.PI / 4), 0.001); + expect(q.w).to.be.closeTo(Math.cos(Math.PI / 4), 0.001); + + // Update dynamically + extra.setAttribute('orientation', '0deg 0deg 0deg'); + await timePasses(); + + expect(scene._models[1].quaternion.y).to.be.closeTo(0, 0.001); + expect(scene._models[1].quaternion.w).to.be.closeTo(1, 0.001); + }); + test( 'does not calculate bounding box synchronously when offset changes', async () => { diff --git a/packages/model-viewer/src/three-components/ModelScene.ts b/packages/model-viewer/src/three-components/ModelScene.ts index 8a682f34ca..9201d174eb 100644 --- a/packages/model-viewer/src/three-components/ModelScene.ts +++ b/packages/model-viewer/src/three-components/ModelScene.ts @@ -323,7 +323,7 @@ export class ModelScene extends Scene { } updateModelTransforms( - index: number, offset?: string|null, _orientation?: string|null, + index: number, offset?: string|null, orientation?: string|null, scale?: string|null) { const model = this._models[index]; if (!model) @@ -339,6 +339,17 @@ export class ModelScene extends Scene { } } + if (orientation) { + const terms = parseExpressions(orientation)[0] + .terms as [NumberNode, NumberNode, NumberNode]; + if (terms.length >= 3) { + const roll = normalizeUnit(terms[0]).number; + const pitch = normalizeUnit(terms[1]).number; + const yaw = normalizeUnit(terms[2]).number; + model.quaternion.setFromEuler(new Euler(pitch, yaw, roll, 'YXZ')); + } + } + if (scale) { const parts = scale.split(' ') .map(s => s.trim()) diff --git a/packages/modelviewer.dev/examples/multimodel/index.html b/packages/modelviewer.dev/examples/multimodel/index.html index c89b5ba213..60c933e85a 100644 --- a/packages/modelviewer.dev/examples/multimodel/index.html +++ b/packages/modelviewer.dev/examples/multimodel/index.html @@ -137,12 +137,12 @@

Interact with Multiple Models

+ offset="-2.0 0 0" scale="0.2 0.2 0.2" orientation="0deg 0deg 30deg"> - + + offset="2.0 0 0" scale="0.3 0.3 0.3" orientation="0deg 0deg -30deg">