From e99db48354e0ce886d35a4b4337eedaee6faaa4e Mon Sep 17 00:00:00 2001 From: samaneh-kazemi Date: Wed, 13 Nov 2024 16:52:52 -0800 Subject: [PATCH 1/7] Introduce ModelData class --- packages/model-viewer/src/three-components/ModelScene.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/model-viewer/src/three-components/ModelScene.ts b/packages/model-viewer/src/three-components/ModelScene.ts index 1a16135409..452bac11c5 100644 --- a/packages/model-viewer/src/three-components/ModelScene.ts +++ b/packages/model-viewer/src/three-components/ModelScene.ts @@ -21,6 +21,7 @@ import {$currentGLTF, $model, $originalGltfJson} from '../features/scene-graph.j import {$nodeFromIndex, $nodeFromPoint} from '../features/scene-graph/model.js'; import ModelViewerElementBase, {$renderer, EffectComposerInterface, RendererInterface} from '../model-viewer-base.js'; import {ModelViewerElement} from '../model-viewer.js'; +import {ModelData} from 'np./ModelData.js'; import {normalizeUnit} from '../styles/conversions.js'; import {NumberNode, parseExpressions} from '../styles/parsers.js'; @@ -65,6 +66,7 @@ const ndc = new Vector2(); * Provides lights and cameras to be used in a renderer. */ export class ModelScene extends Scene { + public modelData: ModelData; public element: ModelViewerElement; public canvas: HTMLCanvasElement; public annotationRenderer = new CSS2DRenderer(); @@ -120,6 +122,8 @@ export class ModelScene extends Scene { constructor({canvas, element, width, height}: ModelSceneConfig) { super(); + this.modelData = new ModelData("url.glb"); + this.name = 'ModelScene'; this.element = element as ModelViewerElement; From 0982af8a44214d99acaa818f9abe6482976e53af Mon Sep 17 00:00:00 2001 From: samaneh-kazemi Date: Wed, 13 Nov 2024 16:58:30 -0800 Subject: [PATCH 2/7] Add ModelData class --- .../src/three-components/ModelData.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 packages/model-viewer/src/three-components/ModelData.ts diff --git a/packages/model-viewer/src/three-components/ModelData.ts b/packages/model-viewer/src/three-components/ModelData.ts new file mode 100644 index 0000000000..4842b1d593 --- /dev/null +++ b/packages/model-viewer/src/three-components/ModelData.ts @@ -0,0 +1,17 @@ +import {Object3D} from 'three'; + +/** + * A THREE.Scene object that takes a Model and CanvasHTMLElement and + * constructs a framed scene based off of the canvas dimensions. + * Provides lights and cameras to be used in a renderer. + */ +export class ModelData extends Object3D { +// ModelScene is going to have child of this types +public url: string|null = null; + +constructor(url: string) { + super(); + this.url = url; + console.log("ModelData constructor is called"); +} +} \ No newline at end of file From ca5ee9fe83b615336f2250c8223eea5f45c44353 Mon Sep 17 00:00:00 2001 From: samaneh-kazemi Date: Wed, 13 Nov 2024 17:03:28 -0800 Subject: [PATCH 3/7] fix typo --- packages/model-viewer/src/three-components/ModelScene.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/model-viewer/src/three-components/ModelScene.ts b/packages/model-viewer/src/three-components/ModelScene.ts index 452bac11c5..534f6fe23a 100644 --- a/packages/model-viewer/src/three-components/ModelScene.ts +++ b/packages/model-viewer/src/three-components/ModelScene.ts @@ -21,7 +21,7 @@ import {$currentGLTF, $model, $originalGltfJson} from '../features/scene-graph.j import {$nodeFromIndex, $nodeFromPoint} from '../features/scene-graph/model.js'; import ModelViewerElementBase, {$renderer, EffectComposerInterface, RendererInterface} from '../model-viewer-base.js'; import {ModelViewerElement} from '../model-viewer.js'; -import {ModelData} from 'np./ModelData.js'; +import {ModelData} from './ModelData.js'; import {normalizeUnit} from '../styles/conversions.js'; import {NumberNode, parseExpressions} from '../styles/parsers.js'; From d190c4ab6335bf8c6c8c45881fca933e326f9463 Mon Sep 17 00:00:00 2001 From: samaneh-kazemi Date: Fri, 15 Nov 2024 14:54:05 -0800 Subject: [PATCH 4/7] remove src from ModelScene --- packages/model-viewer/src/model-viewer-base.ts | 4 ++-- .../src/test/model-viewer-base-spec.ts | 6 +++--- .../src/three-components/ModelScene.ts | 18 +++++++++++++----- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/packages/model-viewer/src/model-viewer-base.ts b/packages/model-viewer/src/model-viewer-base.ts index 3077912a1d..002abb0de6 100644 --- a/packages/model-viewer/src/model-viewer-base.ts +++ b/packages/model-viewer/src/model-viewer-base.ts @@ -393,7 +393,7 @@ export default class ModelViewerElementBase extends ReactiveElement { this[$loaded] = false; this[$loadedTime] = 0; this[$scene].reset(); - } else if (this.src !== this[$scene].url) { + } else if (this.src !== this[$scene].modelData.url) { this[$loaded] = false; this[$loadedTime] = 0; this[$updateSource](); @@ -594,7 +594,7 @@ export default class ModelViewerElementBase extends ReactiveElement { async[$updateSource]() { const scene = this[$scene]; if (this.loaded || !this[$shouldAttemptPreload]() || - this.src === scene.url) { + this.src === scene.modelData.url) { return; } diff --git a/packages/model-viewer/src/test/model-viewer-base-spec.ts b/packages/model-viewer/src/test/model-viewer-base-spec.ts index 2db6684192..eaa37d7cf5 100644 --- a/packages/model-viewer/src/test/model-viewer-base-spec.ts +++ b/packages/model-viewer/src/test/model-viewer-base-spec.ts @@ -1,7 +1,7 @@ /* @license * Copyright 2019 Google LLC. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the 'License'); - * you may not use this file except in compliance with the License. + * you may not use this file except in iance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 @@ -92,7 +92,7 @@ suite('ModelViewerElementBase', () => { element.src = assetPath('models/Horse.glb'); await waitForEvent(element, 'load'); - expect(element[$scene].url) + expect(element[$scene].modelData.url) .to.be.equal(assetPath('models/Horse.glb')); }); @@ -102,7 +102,7 @@ suite('ModelViewerElementBase', () => { element.src = assetPath('models/Horse.glb'); await waitForEvent(element, 'load'); - expect(element[$scene].url) + expect(element[$scene].modelData.url) .to.be.equal(assetPath('models/Horse.glb')); }); }); diff --git a/packages/model-viewer/src/three-components/ModelScene.ts b/packages/model-viewer/src/three-components/ModelScene.ts index 534f6fe23a..0e5cc8ad16 100644 --- a/packages/model-viewer/src/three-components/ModelScene.ts +++ b/packages/model-viewer/src/three-components/ModelScene.ts @@ -84,7 +84,7 @@ export class ModelScene extends Scene { public camera = new PerspectiveCamera(45, 1, 0.1, 100); public xrCamera: Camera|null = null; - public url: string|null = null; + public pivot = new Object3D(); public target = new Object3D(); public animationNames: Array = []; @@ -205,14 +205,17 @@ export class ModelScene extends Scene { async setSource( url: string|null, progressCallback: (progress: number) => void = () => {}) { - if (!url || url === this.url) { + console.log("SK: ModelScene:SetSource Started"); + if (!url || url === this.modelData.url) { + console.log("SK: ModelScene:SetSource no change"); progressCallback(1); return; } this.reset(); - this.url = url; + this.modelData.url = url; if (this.externalRenderer != null) { + console.log("SK: ModelScene:SetSource externalRendere.load"); const framingInfo = await this.externalRenderer.load(progressCallback); this.boundingSphere.radius = framingInfo.framedRadius; @@ -223,6 +226,7 @@ export class ModelScene extends Scene { // If we have pending work due to a previous source change in progress, // cancel it so that we do not incur a race condition: if (this.cancelPendingSourceChange != null) { + console.log("SK: ModelScene:SetSource cancelPendingSourceChange"); this.cancelPendingSourceChange!(); this.cancelPendingSourceChange = null; } @@ -233,6 +237,7 @@ export class ModelScene extends Scene { gltf = await new Promise( async (resolve, reject) => { this.cancelPendingSourceChange = () => reject(); + console.log("SK: ModelScene:SetSource load gltf"); try { const result = await this.element[$renderer].loader.load( url, this.element, progressCallback); @@ -246,13 +251,16 @@ export class ModelScene extends Scene { // Loading was cancelled, so silently return return; } + console.log("SK: ModelScene:SetSource failed load gltf"); throw error; } this.cancelPendingSourceChange = null; this.reset(); - this.url = url; + this.modelData.url = url; + console.log("SK: ModelScene:SetSource gltf value", gltf); + this._currentGLTF = gltf; if (gltf != null) { @@ -289,7 +297,7 @@ export class ModelScene extends Scene { } reset() { - this.url = null; + this.modelData.url = null; this.renderCount = 0; this.queueRender(); if (this.shadow != null) { From d206e7733b02546f9b1b571f767865b990f6e6a1 Mon Sep 17 00:00:00 2001 From: Samaneh Kazemi Nafchi Date: Wed, 20 Nov 2024 10:12:09 -0800 Subject: [PATCH 5/7] testing new setup --- packages/model-viewer/src/three-components/ModelData.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/model-viewer/src/three-components/ModelData.ts b/packages/model-viewer/src/three-components/ModelData.ts index 4842b1d593..94f9c67f55 100644 --- a/packages/model-viewer/src/three-components/ModelData.ts +++ b/packages/model-viewer/src/three-components/ModelData.ts @@ -12,6 +12,7 @@ public url: string|null = null; constructor(url: string) { super(); this.url = url; + console.log("Testing new setup"); console.log("ModelData constructor is called"); } } \ No newline at end of file From e2483af5c03c40ac20ac49abfbb6dc98392a2903 Mon Sep 17 00:00:00 2001 From: samaneh-kazemi Date: Wed, 18 Dec 2024 17:05:21 -0800 Subject: [PATCH 6/7] Moved the loadModel logic and currentGltf property to modelData class. animation tests are failing need to figure out why. My guess is maybe the way we read animations on the test needs to be updated. --- .../src/test/model-viewer-base-spec.ts | 2 +- .../src/three-components/ModelData.ts | 53 +++++++++++++--- .../src/three-components/ModelScene.ts | 60 +++++++------------ 3 files changed, 68 insertions(+), 47 deletions(-) diff --git a/packages/model-viewer/src/test/model-viewer-base-spec.ts b/packages/model-viewer/src/test/model-viewer-base-spec.ts index eaa37d7cf5..e9045bf886 100644 --- a/packages/model-viewer/src/test/model-viewer-base-spec.ts +++ b/packages/model-viewer/src/test/model-viewer-base-spec.ts @@ -1,7 +1,7 @@ /* @license * Copyright 2019 Google LLC. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the 'License'); - * you may not use this file except in iance with the License. + * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 diff --git a/packages/model-viewer/src/three-components/ModelData.ts b/packages/model-viewer/src/three-components/ModelData.ts index 94f9c67f55..32d6312bd8 100644 --- a/packages/model-viewer/src/three-components/ModelData.ts +++ b/packages/model-viewer/src/three-components/ModelData.ts @@ -1,18 +1,57 @@ import {Object3D} from 'three'; +import {$renderer} from '../model-viewer-base.js'; +import {ModelViewerElement} from '../model-viewer.js'; + +import {ModelViewerGLTFInstance} from './gltf-instance/ModelViewerGLTFInstance.js'; + /** * A THREE.Scene object that takes a Model and CanvasHTMLElement and * constructs a framed scene based off of the canvas dimensions. * Provides lights and cameras to be used in a renderer. */ export class ModelData extends Object3D { -// ModelScene is going to have child of this types -public url: string|null = null; + // ModelScene is going to have child of this types + public url: string|null = null; + + public currentGLTF: ModelViewerGLTFInstance|null = null; -constructor(url: string) { + private cancelPendingSourceChange: (() => void)|null = null; + + constructor() { super(); - this.url = url; - console.log("Testing new setup"); - console.log("ModelData constructor is called"); -} + } + + + async loadModel( + url: string, element: ModelViewerElement, + progressCallback: (progress: number) => void): + Promise { + // If we have pending work due to a previous source change in progress, + // cancel it so that we do not incur a race condition: + if (this.cancelPendingSourceChange != null) { + this.cancelPendingSourceChange!(); + this.cancelPendingSourceChange = null; + } + + let gltf: ModelViewerGLTFInstance; + + try { + gltf = await new Promise( + async (resolve, reject) => { + this.cancelPendingSourceChange = () => reject(); + try { + const result = await element[$renderer].loader.load( + url, element, progressCallback); + resolve(result); + } catch (error) { + reject(error); + } + }); + } finally { + this.cancelPendingSourceChange = null; + } + + return gltf; + } } \ No newline at end of file diff --git a/packages/model-viewer/src/three-components/ModelScene.ts b/packages/model-viewer/src/three-components/ModelScene.ts index 0e5cc8ad16..8a8cb11c4f 100644 --- a/packages/model-viewer/src/three-components/ModelScene.ts +++ b/packages/model-viewer/src/three-components/ModelScene.ts @@ -21,7 +21,6 @@ import {$currentGLTF, $model, $originalGltfJson} from '../features/scene-graph.j import {$nodeFromIndex, $nodeFromPoint} from '../features/scene-graph/model.js'; import ModelViewerElementBase, {$renderer, EffectComposerInterface, RendererInterface} from '../model-viewer-base.js'; import {ModelViewerElement} from '../model-viewer.js'; -import {ModelData} from './ModelData.js'; import {normalizeUnit} from '../styles/conversions.js'; import {NumberNode, parseExpressions} from '../styles/parsers.js'; @@ -29,6 +28,7 @@ import {Damper, SETTLING_TIME} from './Damper.js'; import {ModelViewerGLTFInstance} from './gltf-instance/ModelViewerGLTFInstance.js'; import {GroundedSkybox} from './GroundedSkybox.js'; import {Hotspot} from './Hotspot.js'; +import {ModelData} from './ModelData.js'; import {Shadow} from './Shadow.js'; export const GROUNDED_SKYBOX_SIZE = 10; @@ -110,10 +110,8 @@ export class ModelScene extends Scene { private targetDamperY = new Damper(); private targetDamperZ = new Damper(); - private _currentGLTF: ModelViewerGLTFInstance|null = null; private _model: Object3D|null = null; private mixer: AnimationMixer; - private cancelPendingSourceChange: (() => void)|null = null; private animationsByName: Map = new Map(); private currentAnimationAction: AnimationAction|null = null; @@ -122,8 +120,6 @@ export class ModelScene extends Scene { constructor({canvas, element, width, height}: ModelSceneConfig) { super(); - this.modelData = new ModelData("url.glb"); - this.name = 'ModelScene'; this.element = element as ModelViewerElement; @@ -153,6 +149,8 @@ export class ModelScene extends Scene { style.top = '0'; this.element.shadowRoot!.querySelector('.default')!.appendChild(domElement); + this.modelData = new ModelData(); + this.schemaElement.setAttribute('type', 'application/ld+json'); } @@ -198,6 +196,8 @@ export class ModelScene extends Scene { await this.setupScene(); } + + /** * Sets the model via URL. */ @@ -205,17 +205,17 @@ export class ModelScene extends Scene { async setSource( url: string|null, progressCallback: (progress: number) => void = () => {}) { - console.log("SK: ModelScene:SetSource Started"); + console.log('SK: ModelScene:SetSource Started'); if (!url || url === this.modelData.url) { - console.log("SK: ModelScene:SetSource no change"); + console.log('SK: ModelScene:SetSource no change'); progressCallback(1); return; } this.reset(); - this.modelData.url = url; + this.modelData = new ModelData(); if (this.externalRenderer != null) { - console.log("SK: ModelScene:SetSource externalRendere.load"); + console.log('SK: ModelScene:SetSource externalRendere.load'); const framingInfo = await this.externalRenderer.load(progressCallback); this.boundingSphere.radius = framingInfo.framedRadius; @@ -223,45 +223,24 @@ export class ModelScene extends Scene { return; } - // If we have pending work due to a previous source change in progress, - // cancel it so that we do not incur a race condition: - if (this.cancelPendingSourceChange != null) { - console.log("SK: ModelScene:SetSource cancelPendingSourceChange"); - this.cancelPendingSourceChange!(); - this.cancelPendingSourceChange = null; - } - let gltf: ModelViewerGLTFInstance; try { - gltf = await new Promise( - async (resolve, reject) => { - this.cancelPendingSourceChange = () => reject(); - console.log("SK: ModelScene:SetSource load gltf"); - try { - const result = await this.element[$renderer].loader.load( - url, this.element, progressCallback); - resolve(result); - } catch (error) { - reject(error); - } - }); + gltf = + await this.modelData.loadModel(url, this.element, progressCallback); } catch (error) { if (error == null) { // Loading was cancelled, so silently return return; } - console.log("SK: ModelScene:SetSource failed load gltf"); - throw error; } - this.cancelPendingSourceChange = null; this.reset(); this.modelData.url = url; - console.log("SK: ModelScene:SetSource gltf value", gltf); + console.log('SK: ModelScene:SetSource gltf value', gltf); - this._currentGLTF = gltf; + this.modelData.currentGLTF = gltf; if (gltf != null) { this._model = gltf.scene; @@ -269,6 +248,9 @@ export class ModelScene extends Scene { } const {animations} = gltf!; + console.log('gltf:', gltf); + console.log('Samaneh:animation', animations); + const animationsByName = new Map(); const animationNames = []; @@ -311,10 +293,10 @@ export class ModelScene extends Scene { this._model = null; } - const gltf = this._currentGLTF; + const gltf = this.modelData.currentGLTF; if (gltf != null) { gltf.dispose(); - this._currentGLTF = null; + this.modelData.currentGLTF = null; } if (this.currentAnimationAction != null) { @@ -338,7 +320,7 @@ export class ModelScene extends Scene { } get currentGLTF() { - return this._currentGLTF; + return this.modelData.currentGLTF; } /** @@ -727,7 +709,7 @@ export class ModelScene extends Scene { name: string|null = null, crossfadeTime: number = 0, loopMode: AnimationActionLoopStyles = LoopRepeat, repetitionCount: number = Infinity) { - if (this._currentGLTF == null) { + if (this.modelData.currentGLTF == null) { return; } const {animations} = this; @@ -832,7 +814,7 @@ export class ModelScene extends Scene { */ setShadowIntensity(shadowIntensity: number) { this.shadowIntensity = shadowIntensity; - if (this._currentGLTF == null) { + if (this.modelData.currentGLTF == null) { return; } this.setBakedShadowVisibility(); From 709fd653d278e7caef741b6e71548aacde2ef0e1 Mon Sep 17 00:00:00 2001 From: samaneh-kazemi Date: Thu, 19 Dec 2024 11:51:35 -0800 Subject: [PATCH 7/7] Moved animations related properties to ModelData class. --- .../model-viewer/src/features/animation.ts | 4 +- .../src/test/features/animation-spec.ts | 4 +- .../src/three-components/ModelData.ts | 55 +++++++++++++++- .../src/three-components/ModelScene.ts | 64 ++++--------------- .../src/three-components/Shadow.ts | 2 +- 5 files changed, 71 insertions(+), 58 deletions(-) diff --git a/packages/model-viewer/src/features/animation.ts b/packages/model-viewer/src/features/animation.ts index 35fdf22d21..9f0a0e8fbe 100644 --- a/packages/model-viewer/src/features/animation.ts +++ b/packages/model-viewer/src/features/animation.ts @@ -75,14 +75,14 @@ export const AnimationMixin = >( */ get availableAnimations(): Array { if (this.loaded) { - return this[$scene].animationNames; + return this[$scene].modelData.animationNames; } return []; } get duration(): number { - return this[$scene].duration; + return this[$scene].modelData.duration; } get paused(): boolean { diff --git a/packages/model-viewer/src/test/features/animation-spec.ts b/packages/model-viewer/src/test/features/animation-spec.ts index 0c840e2bb0..8897705991 100644 --- a/packages/model-viewer/src/test/features/animation-spec.ts +++ b/packages/model-viewer/src/test/features/animation-spec.ts @@ -42,8 +42,8 @@ const animationIsPlaying = (element: any, animationName?: string): boolean => { const animationWithIndexIsPlaying = (element: any, animationIndex = 0): boolean => { - const {currentAnimationAction} = element[$scene]; - const {_currentGLTF} = element[$scene]; + const {currentAnimationAction, modelData} = element[$scene]; + const {_currentGLTF} = modelData.currentGLTF if (currentAnimationAction != null && animationIndex >= 0 && animationIndex < _currentGLTF.animations.length && diff --git a/packages/model-viewer/src/three-components/ModelData.ts b/packages/model-viewer/src/three-components/ModelData.ts index 32d6312bd8..6c9b8ba78e 100644 --- a/packages/model-viewer/src/three-components/ModelData.ts +++ b/packages/model-viewer/src/three-components/ModelData.ts @@ -1,4 +1,4 @@ -import {Object3D} from 'three'; +import {AnimationAction, AnimationClip, LoopPingPong, Object3D} from 'three'; import {$renderer} from '../model-viewer-base.js'; import {ModelViewerElement} from '../model-viewer.js'; @@ -18,11 +18,17 @@ export class ModelData extends Object3D { private cancelPendingSourceChange: (() => void)|null = null; + + // Animations + public animationNames: Array = []; + public animationsByName: Map = new Map(); + public currentAnimationAction: AnimationAction|null = null; + + constructor() { super(); } - async loadModel( url: string, element: ModelViewerElement, progressCallback: (progress: number) => void): @@ -54,4 +60,49 @@ export class ModelData extends Object3D { return gltf; } + + setUpAnimations() { + const {animations} = this.currentGLTF!; + console.log('Samaneh:animation', animations); + const animationsByName = new Map(); + const animationNames = []; + + for (const animation of animations) { + animationsByName.set(animation.name, animation); + animationNames.push(animation.name); + } + + this.animations = animations; + this.animationsByName = animationsByName; + this.animationNames = animationNames; + } + + + get animationTime(): number { + if (this.currentAnimationAction != null) { + const loopCount = + Math.max((this.currentAnimationAction as any)._loopCount, 0); + if (this.currentAnimationAction.loop === LoopPingPong && + (loopCount & 1) === 1) { + return this.duration - this.currentAnimationAction.time + } else { + return this.currentAnimationAction.time; + } + } + + return 0; + } + + get duration(): number { + if (this.currentAnimationAction != null && + this.currentAnimationAction.getClip()) { + return this.currentAnimationAction.getClip().duration; + } + + return 0; + } + + get hasActiveAnimation(): boolean { + return this.currentAnimationAction != null; + } } \ No newline at end of file diff --git a/packages/model-viewer/src/three-components/ModelScene.ts b/packages/model-viewer/src/three-components/ModelScene.ts index 8a8cb11c4f..9bc8bd8350 100644 --- a/packages/model-viewer/src/three-components/ModelScene.ts +++ b/packages/model-viewer/src/three-components/ModelScene.ts @@ -13,7 +13,7 @@ * limitations under the License. */ -import {ACESFilmicToneMapping, AnimationAction, AnimationActionLoopStyles, AnimationClip, AnimationMixer, AnimationMixerEventMap, Box3, Camera, Euler, Event as ThreeEvent, LoopPingPong, LoopRepeat, Material, Matrix3, Mesh, Object3D, PerspectiveCamera, Raycaster, Scene, Sphere, Texture, ToneMapping, Triangle, Vector2, Vector3, WebGLRenderer, XRTargetRaySpace} from 'three'; +import {ACESFilmicToneMapping, AnimationActionLoopStyles, AnimationMixer, AnimationMixerEventMap, Box3, Camera, Euler, Event as ThreeEvent, LoopRepeat, Material, Matrix3, Mesh, Object3D, PerspectiveCamera, Raycaster, Scene, Sphere, Texture, ToneMapping, Triangle, Vector2, Vector3, WebGLRenderer, XRTargetRaySpace} from 'three'; import {CSS2DRenderer} from 'three/examples/jsm/renderers/CSS2DRenderer.js'; import {reduceVertices} from 'three/examples/jsm/utils/SceneUtils.js'; @@ -87,7 +87,7 @@ export class ModelScene extends Scene { public pivot = new Object3D(); public target = new Object3D(); - public animationNames: Array = []; + public boundingBox = new Box3(); public boundingSphere = new Sphere(); public size = new Vector3(); @@ -112,8 +112,6 @@ export class ModelScene extends Scene { private _model: Object3D|null = null; private mixer: AnimationMixer; - private animationsByName: Map = new Map(); - private currentAnimationAction: AnimationAction|null = null; private groundedSkybox = new GroundedSkybox(); @@ -212,7 +210,7 @@ export class ModelScene extends Scene { return; } this.reset(); - this.modelData = new ModelData(); + if (this.externalRenderer != null) { console.log('SK: ModelScene:SetSource externalRendere.load'); @@ -247,21 +245,9 @@ export class ModelScene extends Scene { this.target.add(gltf.scene); } - const {animations} = gltf!; - console.log('gltf:', gltf); - console.log('Samaneh:animation', animations); - const animationsByName = new Map(); - const animationNames = []; - for (const animation of animations) { - animationsByName.set(animation.name, animation); - animationNames.push(animation.name); - } - - this.animations = animations; - this.animationsByName = animationsByName; - this.animationNames = animationNames; + this.modelData.setUpAnimations(); await this.setupScene(); } @@ -299,9 +285,9 @@ export class ModelScene extends Scene { this.modelData.currentGLTF = null; } - if (this.currentAnimationAction != null) { - this.currentAnimationAction.stop(); - this.currentAnimationAction = null; + if (this.modelData.currentAnimationAction != null) { + this.modelData.currentAnimationAction.stop(); + this.modelData.currentAnimationAction = null; } this.mixer.stopAllAction(); @@ -663,20 +649,7 @@ export class ModelScene extends Scene { this.queueShadowRender(); } - get animationTime(): number { - if (this.currentAnimationAction != null) { - const loopCount = - Math.max((this.currentAnimationAction as any)._loopCount, 0); - if (this.currentAnimationAction.loop === LoopPingPong && - (loopCount & 1) === 1) { - return this.duration - this.currentAnimationAction.time - } else { - return this.currentAnimationAction.time; - } - } - return 0; - } set animationTimeScale(value: number) { this.mixer.timeScale = value; @@ -686,18 +659,7 @@ export class ModelScene extends Scene { return this.mixer.timeScale; } - get duration(): number { - if (this.currentAnimationAction != null && - this.currentAnimationAction.getClip()) { - return this.currentAnimationAction.getClip().duration; - } - - return 0; - } - get hasActiveAnimation(): boolean { - return this.currentAnimationAction != null; - } /** * Plays an animation if there are any associated with the current model. @@ -712,7 +674,7 @@ export class ModelScene extends Scene { if (this.modelData.currentGLTF == null) { return; } - const {animations} = this; + const {animations} = this.modelData; if (animations == null || animations.length === 0) { return; } @@ -720,7 +682,7 @@ export class ModelScene extends Scene { let animationClip = null; if (name != null) { - animationClip = this.animationsByName.get(name); + animationClip = this.modelData.animationsByName.get(name); if (animationClip == null) { const parsedAnimationIndex = parseInt(name); @@ -737,10 +699,10 @@ export class ModelScene extends Scene { } try { - const {currentAnimationAction: lastAnimationAction} = this; + const {currentAnimationAction: lastAnimationAction} = this.modelData; const action = this.mixer.clipAction(animationClip, this); - this.currentAnimationAction = action; + this.modelData.currentAnimationAction = action; if (this.element.paused) { this.mixer.stopAllAction(); @@ -750,7 +712,7 @@ export class ModelScene extends Scene { action.crossFadeFrom(lastAnimationAction, crossfadeTime, false); } else if ( this.animationTimeScale > 0 && - this.animationTime == this.duration) { + this.animationTime == this.modelData.duration) { // This is a workaround for what I believe is a three.js bug. this.animationTime = 0; } @@ -768,7 +730,7 @@ export class ModelScene extends Scene { } stopAnimation() { - this.currentAnimationAction = null; + this.modelData.currentAnimationAction = null; this.mixer.stopAllAction(); } diff --git a/packages/model-viewer/src/three-components/Shadow.ts b/packages/model-viewer/src/three-components/Shadow.ts index f344f0fc03..7bf7a4b8cb 100644 --- a/packages/model-viewer/src/three-components/Shadow.ts +++ b/packages/model-viewer/src/three-components/Shadow.ts @@ -121,7 +121,7 @@ export class Shadow extends Object3D { setScene(scene: ModelScene, softness: number, side: Side) { const {boundingBox, size, rotation, position} = this; - this.isAnimated = scene.animationNames.length > 0; + this.isAnimated = scene.modelData.animationNames.length > 0; this.boundingBox.copy(scene.boundingBox); this.size.copy(scene.size); this.maxDimension = Math.max(size.x, size.y, size.z) *