2
2
// SPDX-License-Identifier: MIT
3
3
// Copyright (c) vis.gl contributors
4
4
5
- import { AnimationLoopTemplate , AnimationProps , GroupNode , ModelNode } from '@luma.gl/engine' ;
5
+ import { AnimationLoopTemplate , AnimationProps , ModelNode } from '@luma.gl/engine' ;
6
6
import { Device } from '@luma.gl/core' ;
7
7
import { load } from '@loaders.gl/core' ;
8
8
import { LightingProps } from '@luma.gl/shadertools' ;
9
- import { createScenegraphsFromGLTF , GLTFAnimator } from '@luma.gl/gltf' ;
9
+ import { createScenegraphsFromGLTF } from '@luma.gl/gltf' ;
10
10
import { GLTFLoader , postProcessGLTF } from '@loaders.gl/gltf' ;
11
11
import { Matrix4 } from '@math.gl/core' ;
12
12
13
13
/* eslint-disable camelcase */
14
14
15
15
const MODEL_DIRECTORY_URL =
16
- 'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/' ;
17
- const MODEL_LIST_URL =
18
- 'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/model-index.json' ;
16
+ 'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models' ;
17
+ const MODEL_LIST_URL = `${ MODEL_DIRECTORY_URL } /model-index.json` ;
19
18
20
19
const lightSources = {
21
20
ambientLight : {
@@ -43,11 +42,10 @@ const lightSources = {
43
42
44
43
export default class AppAnimationLoopTemplate extends AnimationLoopTemplate {
45
44
device : Device ;
46
- scenes : GroupNode [ ] = [ ] ;
47
- animator ?: GLTFAnimator ;
45
+ scenegraphsFromGLTF ?: ReturnType < typeof createScenegraphsFromGLTF > ;
48
46
center = [ 0 , 0 , 0 ] ;
49
47
cameraPos = [ 0 , 0 , 0 ] ;
50
- time : number = 0 ;
48
+ mouseCameraTime : number = 0 ;
51
49
options : Record < string , boolean > = {
52
50
cameraAnimation : true ,
53
51
gltfAnimation : false ,
@@ -79,33 +77,40 @@ export default class AppAnimationLoopTemplate extends AnimationLoopTemplate {
79
77
}
80
78
) ;
81
79
} ) ;
80
+
81
+ this . device . getDefaultCanvasContext ( ) . canvas . addEventListener ( 'mousemove' , event => {
82
+ const e = event as MouseEvent ;
83
+ if ( e . buttons ) {
84
+ this . mouseCameraTime -= e . movementX * 3.5 ;
85
+ }
86
+ } ) ;
82
87
}
83
88
84
89
onFinalize ( ) {
85
- this . scenes [ 0 ] . traverse ( node => ( node as ModelNode ) . model . destroy ( ) ) ;
90
+ this . scenegraphsFromGLTF ?. scenes [ 0 ] . traverse ( node => ( node as ModelNode ) . model . destroy ( ) ) ;
86
91
}
87
92
88
93
onRender ( { aspect, device, time} : AnimationProps ) : void {
89
- if ( ! this . scenes ?. length ) return ;
94
+ if ( ! this . scenegraphsFromGLTF ?. scenes ?. length ) return ;
90
95
const renderPass = device . beginRenderPass ( { clearColor : [ 0 , 0 , 0 , 1 ] , clearDepth : 1 } ) ;
91
96
92
97
const far = 2 * this . cameraPos [ 0 ] ;
93
98
const near = far / 1000 ;
94
99
const projectionMatrix = new Matrix4 ( ) . perspective ( { fovy : Math . PI / 3 , aspect, near, far} ) ;
95
- const cameraTime = this . options [ 'cameraAnimation' ] ? time : 0 ;
100
+ const cameraTime = this . options [ 'cameraAnimation' ] ? time : this . mouseCameraTime ;
96
101
const cameraPos = [
97
102
this . cameraPos [ 0 ] * Math . sin ( 0.001 * cameraTime ) ,
98
103
this . cameraPos [ 1 ] ,
99
104
this . cameraPos [ 2 ] * Math . cos ( 0.001 * cameraTime )
100
105
] ;
101
106
102
107
if ( this . options [ 'gltfAnimation' ] ) {
103
- this . animator ?. setTime ( time ) ;
108
+ this . scenegraphsFromGLTF . animator ?. setTime ( time ) ;
104
109
}
105
110
106
111
const viewMatrix = new Matrix4 ( ) . lookAt ( { eye : cameraPos , center : this . center } ) ;
107
112
108
- this . scenes [ 0 ] . traverse ( ( node , { worldMatrix : modelMatrix } ) => {
113
+ this . scenegraphsFromGLTF . scenes [ 0 ] . traverse ( ( node , { worldMatrix : modelMatrix } ) => {
109
114
const { model} = node as ModelNode ;
110
115
111
116
const modelViewProjectionMatrix = new Matrix4 ( projectionMatrix )
@@ -119,6 +124,11 @@ export default class AppAnimationLoopTemplate extends AnimationLoopTemplate {
119
124
modelViewProjectionMatrix,
120
125
modelMatrix,
121
126
normalMatrix : new Matrix4 ( modelMatrix ) . invert ( ) . transpose ( )
127
+ } ,
128
+ skin : {
129
+ // TODO: This is required to trigger getUniforms() of skin.
130
+ // Fix it, then remove this.
131
+ scenegraphsFromGLTF : this . scenegraphsFromGLTF
122
132
}
123
133
} ) ;
124
134
model . draw ( renderPass ) ;
@@ -143,20 +153,17 @@ export default class AppAnimationLoopTemplate extends AnimationLoopTemplate {
143
153
) ;
144
154
const processedGLTF = postProcessGLTF ( gltf ) ;
145
155
146
- const { scenes , animator } = createScenegraphsFromGLTF ( this . device , processedGLTF , {
156
+ this . scenegraphsFromGLTF = createScenegraphsFromGLTF ( this . device , processedGLTF , {
147
157
lights : true ,
148
158
imageBasedLightingEnvironment : undefined ,
149
159
pbrDebug : false
150
160
} ) ;
151
161
152
- this . scenes = scenes ;
153
- this . animator = animator ;
154
-
155
162
// Calculate nice camera view
156
163
// TODO move to utility in gltf module
157
164
let min = [ Infinity , Infinity , Infinity ] ;
158
165
let max = [ 0 , 0 , 0 ] ;
159
- this . scenes [ 0 ] . traverse ( node => {
166
+ this . scenegraphsFromGLTF ?. scenes [ 0 ] . traverse ( node => {
160
167
const { bounds} = node as ModelNode ;
161
168
min = min . map ( ( n , i ) => Math . min ( n , bounds [ 0 ] [ i ] , bounds [ 1 ] [ i ] ) ) ;
162
169
max = max . map ( ( n , i ) => Math . max ( n , bounds [ 0 ] [ i ] , bounds [ 1 ] [ i ] ) ) ;
@@ -167,6 +174,8 @@ export default class AppAnimationLoopTemplate extends AnimationLoopTemplate {
167
174
canvas . style . opacity = '1' ;
168
175
showError ( ) ;
169
176
} catch ( error ) {
177
+ // eslint-disable-next-line no-console
178
+ console . error ( error ) ;
170
179
showError ( error as Error ) ;
171
180
}
172
181
}
@@ -194,6 +203,7 @@ function setModelMenu(
194
203
} ) ;
195
204
196
205
modelSelector . append ( ...options ) ;
206
+ modelSelector . value = currentItem ;
197
207
}
198
208
199
209
function setOptionsUI ( options : Record < string , boolean > ) {
0 commit comments