@@ -4,11 +4,11 @@ import { Deferred } from "babylonjs/Misc/deferred";
4
4
import { Material } from "babylonjs/Materials/material" ;
5
5
import { TransformNode } from "babylonjs/Meshes/transformNode" ;
6
6
import { Mesh } from "babylonjs/Meshes/mesh" ;
7
- import { BaseTexture } from ' babylonjs/Materials/Textures/baseTexture' ;
7
+ import { BaseTexture } from " babylonjs/Materials/Textures/baseTexture" ;
8
8
import { INode , IMaterial , IBuffer , IScene } from "../glTFLoaderInterfaces" ;
9
9
import { IGLTFLoaderExtension } from "../glTFLoaderExtension" ;
10
10
import { GLTFLoader , ArrayItem } from "../glTFLoader" ;
11
- import { IProperty , IMSFTLOD } from ' babylonjs-gltf2interface' ;
11
+ import { IProperty , IMSFTLOD } from " babylonjs-gltf2interface" ;
12
12
13
13
const NAME = "MSFT_lod" ;
14
14
@@ -153,6 +153,11 @@ export class MSFT_lod implements IGLTFLoaderExtension {
153
153
154
154
const nodeLODs = this . _getLODs ( extensionContext , node , this . _loader . gltf . nodes , extension . ids ) ;
155
155
this . _loader . logOpen ( `${ extensionContext } ` ) ;
156
+ const transformNodes : Nullable < TransformNode > [ ] = [ ] ;
157
+
158
+ for ( let indexLOD = 0 ; indexLOD < nodeLODs . length ; indexLOD ++ ) {
159
+ transformNodes . push ( null ) ;
160
+ }
156
161
157
162
for ( let indexLOD = 0 ; indexLOD < nodeLODs . length ; indexLOD ++ ) {
158
163
const nodeLOD = nodeLODs [ indexLOD ] ;
@@ -162,9 +167,39 @@ export class MSFT_lod implements IGLTFLoaderExtension {
162
167
this . _nodeSignalLODs [ indexLOD ] = this . _nodeSignalLODs [ indexLOD ] || new Deferred ( ) ;
163
168
}
164
169
165
- const assign = ( babylonTransformNode : TransformNode ) => { babylonTransformNode . setEnabled ( false ) ; } ;
166
- const promise = this . _loader . loadNodeAsync ( `/nodes/${ nodeLOD . index } ` , nodeLOD , assign ) . then ( ( babylonMesh ) => {
167
- if ( indexLOD !== 0 ) {
170
+ const assign = ( babylonTransformNode : TransformNode , index : number ) => {
171
+ babylonTransformNode . setEnabled ( false ) ;
172
+ transformNodes [ index ] = babylonTransformNode ;
173
+
174
+ let fullArray = true ;
175
+ for ( let i = 0 ; i < transformNodes . length ; i ++ ) {
176
+ if ( ! transformNodes [ i ] ) {
177
+ fullArray = false ;
178
+ }
179
+ }
180
+
181
+ const lod0 = transformNodes [ transformNodes . length - 1 ] ;
182
+ if ( fullArray && lod0 ) {
183
+ const screenCoverages = lod0 . metadata ?. gltf ?. extras ?. MSFT_screencoverage as any [ ] ;
184
+
185
+ if ( screenCoverages && screenCoverages . length ) {
186
+ screenCoverages . reverse ( ) ;
187
+ ( lod0 as Mesh ) . useLODScreenCoverage = true ;
188
+ for ( let i = 0 ; i < transformNodes . length - 1 ; i ++ ) {
189
+ ( lod0 as Mesh ) . addLODLevel ( screenCoverages [ i + 1 ] , transformNodes [ i ] as Mesh ) ;
190
+ }
191
+ if ( screenCoverages [ 0 ] > 0 ) {
192
+ // Adding empty LOD
193
+ ( lod0 as Mesh ) . addLODLevel ( screenCoverages [ 0 ] , null ) ;
194
+ }
195
+ }
196
+ }
197
+ } ;
198
+
199
+ const promise = this . _loader . loadNodeAsync ( `/nodes/${ nodeLOD . index } ` , nodeLOD , ( node : TransformNode ) => assign ( node , indexLOD ) ) . then ( ( babylonMesh ) => {
200
+ const screenCoverages = ( nodeLODs [ nodeLODs . length - 1 ] . _babylonTransformNode as Mesh ) . metadata ?. gltf ?. extras ?. MSFT_screencoverage ;
201
+
202
+ if ( indexLOD !== 0 && ! screenCoverages ) {
168
203
// TODO: should not rely on _babylonTransformNode
169
204
const previousNodeLOD = nodeLODs [ indexLOD - 1 ] ;
170
205
if ( previousNodeLOD . _babylonTransformNode ) {
@@ -181,8 +216,7 @@ export class MSFT_lod implements IGLTFLoaderExtension {
181
216
182
217
if ( indexLOD === 0 ) {
183
218
firstPromise = promise ;
184
- }
185
- else {
219
+ } else {
186
220
this . _nodeIndexLOD = null ;
187
221
this . _nodePromiseLODs [ indexLOD ] . push ( promise ) ;
188
222
}
@@ -194,7 +228,13 @@ export class MSFT_lod implements IGLTFLoaderExtension {
194
228
}
195
229
196
230
/** @hidden */
197
- public _loadMaterialAsync ( context : string , material : IMaterial , babylonMesh : Nullable < Mesh > , babylonDrawMode : number , assign : ( babylonMaterial : Material ) => void ) : Nullable < Promise < Material > > {
231
+ public _loadMaterialAsync (
232
+ context : string ,
233
+ material : IMaterial ,
234
+ babylonMesh : Nullable < Mesh > ,
235
+ babylonDrawMode : number ,
236
+ assign : ( babylonMaterial : Material ) => void
237
+ ) : Nullable < Promise < Material > > {
198
238
// Don't load material LODs if already loading a node LOD.
199
239
if ( this . _nodeIndexLOD ) {
200
240
return null ;
@@ -213,31 +253,32 @@ export class MSFT_lod implements IGLTFLoaderExtension {
213
253
this . _materialIndexLOD = indexLOD ;
214
254
}
215
255
216
- const promise = this . _loader . _loadMaterialAsync ( `/materials/${ materialLOD . index } ` , materialLOD , babylonMesh , babylonDrawMode , ( babylonMaterial ) => {
217
- if ( indexLOD === 0 ) {
218
- assign ( babylonMaterial ) ;
219
- }
220
- } ) . then ( ( babylonMaterial ) => {
221
- if ( indexLOD !== 0 ) {
222
- assign ( babylonMaterial ) ;
223
-
224
- // TODO: should not rely on _data
225
- const previousDataLOD = materialLODs [ indexLOD - 1 ] . _data ! ;
226
- if ( previousDataLOD [ babylonDrawMode ] ) {
227
- this . _disposeMaterials ( [ previousDataLOD [ babylonDrawMode ] . babylonMaterial ] ) ;
228
- delete previousDataLOD [ babylonDrawMode ] ;
256
+ const promise = this . _loader
257
+ . _loadMaterialAsync ( `/materials/${ materialLOD . index } ` , materialLOD , babylonMesh , babylonDrawMode , ( babylonMaterial ) => {
258
+ if ( indexLOD === 0 ) {
259
+ assign ( babylonMaterial ) ;
260
+ }
261
+ } )
262
+ . then ( ( babylonMaterial ) => {
263
+ if ( indexLOD !== 0 ) {
264
+ assign ( babylonMaterial ) ;
265
+
266
+ // TODO: should not rely on _data
267
+ const previousDataLOD = materialLODs [ indexLOD - 1 ] . _data ! ;
268
+ if ( previousDataLOD [ babylonDrawMode ] ) {
269
+ this . _disposeMaterials ( [ previousDataLOD [ babylonDrawMode ] . babylonMaterial ] ) ;
270
+ delete previousDataLOD [ babylonDrawMode ] ;
271
+ }
229
272
}
230
- }
231
273
232
- return babylonMaterial ;
233
- } ) ;
274
+ return babylonMaterial ;
275
+ } ) ;
234
276
235
277
this . _materialPromiseLODs [ indexLOD ] = this . _materialPromiseLODs [ indexLOD ] || [ ] ;
236
278
237
279
if ( indexLOD === 0 ) {
238
280
firstPromise = promise ;
239
- }
240
- else {
281
+ } else {
241
282
this . _materialIndexLOD = null ;
242
283
this . _materialPromiseLODs [ indexLOD ] . push ( promise ) ;
243
284
}
@@ -258,8 +299,7 @@ export class MSFT_lod implements IGLTFLoaderExtension {
258
299
return this . _nodeSignalLODs [ this . _nodeIndexLOD - 1 ] . promise . then ( ( ) => {
259
300
return this . _loader . loadUriAsync ( context , property , uri ) ;
260
301
} ) ;
261
- }
262
- else if ( this . _materialIndexLOD !== null ) {
302
+ } else if ( this . _materialIndexLOD !== null ) {
263
303
this . _loader . log ( `deferred` ) ;
264
304
const previousIndexLOD = this . _materialIndexLOD - 1 ;
265
305
this . _materialSignalLODs [ previousIndexLOD ] = this . _materialSignalLODs [ previousIndexLOD ] || new Deferred < void > ( ) ;
@@ -285,8 +325,7 @@ export class MSFT_lod implements IGLTFLoaderExtension {
285
325
if ( bufferLOD ) {
286
326
bufferLOD . start = Math . min ( bufferLOD . start , start ) ;
287
327
bufferLOD . end = Math . max ( bufferLOD . end , end ) ;
288
- }
289
- else {
328
+ } else {
290
329
bufferLOD = { start : start , end : end , loaded : new Deferred ( ) } ;
291
330
bufferLODs [ indexLOD ] = bufferLOD ;
292
331
}
@@ -300,11 +339,9 @@ export class MSFT_lod implements IGLTFLoaderExtension {
300
339
301
340
if ( this . _nodeIndexLOD !== null ) {
302
341
return loadAsync ( this . _nodeBufferLODs , this . _nodeIndexLOD ) ;
303
- }
304
- else if ( this . _materialIndexLOD !== null ) {
342
+ } else if ( this . _materialIndexLOD !== null ) {
305
343
return loadAsync ( this . _materialBufferLODs , this . _materialIndexLOD ) ;
306
- }
307
- else {
344
+ } else {
308
345
return loadAsync ( this . _bufferLODs , 0 ) ;
309
346
}
310
347
}
@@ -316,11 +353,14 @@ export class MSFT_lod implements IGLTFLoaderExtension {
316
353
const bufferLOD = bufferLODs [ indexLOD ] ;
317
354
if ( bufferLOD ) {
318
355
this . _loader . log ( `Loading buffer range [${ bufferLOD . start } -${ bufferLOD . end } ]` ) ;
319
- this . _loader . bin ! . readAsync ( bufferLOD . start , bufferLOD . end - bufferLOD . start + 1 ) . then ( ( data ) => {
320
- bufferLOD . loaded . resolve ( data ) ;
321
- } , ( error ) => {
322
- bufferLOD . loaded . reject ( error ) ;
323
- } ) ;
356
+ this . _loader . bin ! . readAsync ( bufferLOD . start , bufferLOD . end - bufferLOD . start + 1 ) . then (
357
+ ( data ) => {
358
+ bufferLOD . loaded . resolve ( data ) ;
359
+ } ,
360
+ ( error ) => {
361
+ bufferLOD . loaded . reject ( error ) ;
362
+ }
363
+ ) ;
324
364
}
325
365
}
326
366
@@ -388,4 +428,4 @@ export class MSFT_lod implements IGLTFLoaderExtension {
388
428
}
389
429
}
390
430
391
- GLTFLoader . RegisterExtension ( NAME , ( loader ) => new MSFT_lod ( loader ) ) ;
431
+ GLTFLoader . RegisterExtension ( NAME , ( loader ) => new MSFT_lod ( loader ) ) ;
0 commit comments