Selaa lähdekoodia

Merge pull request #4499 from bghgary/gltf-lod-fix

Fix bug with MSFT_lod extension in glTF loader
David Catuhe 7 vuotta sitten
vanhempi
commit
c62e5c286c

+ 5 - 27
loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts

@@ -17,34 +17,12 @@ module BABYLON.GLTF2.Extensions {
     export class KHR_materials_pbrSpecularGlossiness extends GLTFLoaderExtension {
         public readonly name = NAME;
 
-        protected _loadMaterialAsync(context: string, material: _ILoaderMaterial, mesh: _ILoaderMesh, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<void>> {
+        protected _loadMaterialPropertiesAsync(context: string, material: _ILoaderMaterial, babylonMaterial: Material): Nullable<Promise<void>> {
             return this._loadExtensionAsync<IKHRMaterialsPbrSpecularGlossiness>(context, material, (extensionContext, extension) => {
-                material._babylonData = material._babylonData || {};
-                let babylonData = material._babylonData[babylonDrawMode];
-                if (!babylonData) {
-                    const promises = new Array<Promise<void>>();
-
-                    const name = material.name || `materialSG_${material._index}`;
-                    const babylonMaterial = this._loader._createMaterial(name, babylonDrawMode);
-
-                    promises.push(this._loader._loadMaterialBasePropertiesAsync(context, material, babylonMaterial));
-                    promises.push(this._loadSpecularGlossinessPropertiesAsync(extensionContext, material, extension, babylonMaterial));
-
-                    this._loader._parent.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
-
-                    babylonData = {
-                        material: babylonMaterial,
-                        meshes: [],
-                        loaded: Promise.all(promises).then(() => {})
-                    };
-
-                    material._babylonData[babylonDrawMode] = babylonData;
-                }
-
-                babylonData.meshes.push(babylonMesh);
-
-                assign(babylonData.material);
-                return babylonData.loaded;
+                const promises = new Array<Promise<void>>();
+                promises.push(this._loader._loadMaterialBasePropertiesAsync(context, material, babylonMaterial as PBRMaterial));
+                promises.push(this._loadSpecularGlossinessPropertiesAsync(extensionContext, material, extension, babylonMaterial as PBRMaterial));
+                return Promise.all(promises).then(() => {});
             });
         }
 

+ 4 - 25
loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts

@@ -9,38 +9,17 @@ module BABYLON.GLTF2.Extensions {
     export class KHR_materials_unlit extends GLTFLoaderExtension {
         public readonly name = NAME;
 
-        protected _loadMaterialAsync(context: string, material: _ILoaderMaterial, mesh: _ILoaderMesh, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<void>> {
+        protected _loadMaterialPropertiesAsync(context: string, material: _ILoaderMaterial, babylonMaterial: Material): Nullable<Promise<void>> {
             return this._loadExtensionAsync<{}>(context, material, () => {
-                material._babylonData = material._babylonData || {};
-                let babylonData = material._babylonData[babylonDrawMode];
-                if (!babylonData) {
-                    const name = material.name || `materialUnlit_${material._index}`;
-                    const babylonMaterial = this._loader._createMaterial(name, babylonDrawMode);
-                    babylonMaterial.unlit = true;
-
-                    const promise = this._loadUnlitPropertiesAsync(context, material, babylonMaterial);
-
-                    this._loader._parent.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
-
-                    babylonData = {
-                        material: babylonMaterial,
-                        meshes: [],
-                        loaded: promise
-                    };
-
-                    material._babylonData[babylonDrawMode] = babylonData;
-                }
-
-                babylonData.meshes.push(babylonMesh);
-
-                assign(babylonData.material);
-                return babylonData.loaded;
+                return this._loadUnlitPropertiesAsync(context, material, babylonMaterial as PBRMaterial);
             });
         }
 
         private _loadUnlitPropertiesAsync(context: string, material: _ILoaderMaterial, babylonMaterial: PBRMaterial): Promise<void> {
             const promises = new Array<Promise<void>>();
 
+            babylonMaterial.unlit = true;
+
             // Ensure metallic workflow
             babylonMaterial.metallic = 1;
             babylonMaterial.roughness = 1;

+ 19 - 1
loaders/src/glTF/2.0/Extensions/MSFT_lod.ts

@@ -116,8 +116,9 @@ module BABYLON.GLTF2.Extensions {
                         if (indexLOD !== 0) {
                             const previousNodeLOD = nodeLODs[indexLOD - 1];
                             if (previousNodeLOD._babylonMesh) {
-                                previousNodeLOD._babylonMesh.dispose(false, true);
+                                previousNodeLOD._babylonMesh.dispose();
                                 delete previousNodeLOD._babylonMesh;
+                                this._disposeUnusedMaterials();
                             }
                         }
                     });
@@ -228,6 +229,23 @@ module BABYLON.GLTF2.Extensions {
             properties.push(property);
             return properties;
         }
+
+        private _disposeUnusedMaterials(): void {
+            const materials = this._loader._gltf.materials;
+            if (materials) {
+                for (const material of materials) {
+                    if (material._babylonData) {
+                        for (const drawMode in material._babylonData) {
+                            const babylonData = material._babylonData[drawMode];
+                            if (babylonData.meshes.length === 0) {
+                                babylonData.material.dispose(false, true);
+                                delete material._babylonData[drawMode];
+                            }
+                        }
+                    }
+                }
+            }
+        }
     }
 
     GLTFLoader._Register(NAME, loader => new MSFT_lod(loader));

+ 22 - 9
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -1286,35 +1286,48 @@ module BABYLON.GLTF2 {
             material._babylonData = material._babylonData || {};
             let babylonData = material._babylonData[babylonDrawMode];
             if (!babylonData) {
-                const promises = new Array<Promise<void>>();
-
                 this._parent._logOpen(`${context} ${material.name || ""}`);
 
-                const name = material.name || `material_${material._index}`;
+                const name = material.name || `material${material._index}`;
                 const babylonMaterial = this._createMaterial(name, babylonDrawMode);
 
-                promises.push(this._loadMaterialBasePropertiesAsync(context, material, babylonMaterial));
-                promises.push(this._loadMaterialMetallicRoughnessPropertiesAsync(context, material, babylonMaterial));
-
-                this._parent.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
-
                 babylonData = {
                     material: babylonMaterial,
                     meshes: [],
-                    loaded: Promise.all(promises).then(() => {})
+                    loaded: this._loadMaterialPropertiesAsync(context, material, babylonMaterial)
                 };
 
                 material._babylonData[babylonDrawMode] = babylonData;
 
+                this._parent.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
+
                 this._parent._logClose();
             }
 
             babylonData.meshes.push(babylonMesh);
+            babylonMesh.onDisposeObservable.addOnce(() => {
+                const index = babylonData.meshes.indexOf(babylonMesh);
+                if (index !== -1) {
+                    babylonData.meshes.splice(index, 1);
+                }
+            });
 
             assign(babylonData.material);
             return babylonData.loaded;
         }
 
+        public _loadMaterialPropertiesAsync(context: string, material: _ILoaderMaterial, babylonMaterial: Material): Promise<void> {
+            const promise = GLTFLoaderExtension._LoadMaterialPropertiesAsync(this, context, material, babylonMaterial);
+            if (promise) {
+                return promise;
+            }
+
+            const promises = new Array<Promise<void>>();
+            promises.push(this._loadMaterialBasePropertiesAsync(context, material, babylonMaterial as PBRMaterial));
+            promises.push(this._loadMaterialMetallicRoughnessPropertiesAsync(context, material, babylonMaterial as PBRMaterial));
+            return Promise.all(promises).then(() => {});
+        }
+
         public _createMaterial(name: string, drawMode: number): PBRMaterial {
             const babylonMaterial = new PBRMaterial(name, this._babylonScene);
             babylonMaterial.sideOrientation = this._babylonScene.useRightHandedSystem ? Material.CounterClockWiseSideOrientation : Material.ClockWiseSideOrientation;

+ 14 - 0
loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts

@@ -59,6 +59,12 @@ module BABYLON.GLTF2 {
         protected _loadMaterialAsync(context: string, material: _ILoaderMaterial, mesh: _ILoaderMesh, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<void>> { return null; }
 
         /**
+         * Override this method to modify the default behavior for loading material properties.
+         * @hidden
+         */
+        protected _loadMaterialPropertiesAsync(context: string, material: _ILoaderMaterial, babylonMaterial: Material): Nullable<Promise<void>> { return null; }
+
+        /**
          * Override this method to modify the default behavior for loading textures.
          * @hidden
          */
@@ -161,6 +167,14 @@ module BABYLON.GLTF2 {
         }
 
         /**
+         * Helper method called by the loader to allow extensions to override loading material properties.
+         * @hidden
+         */
+        public static _LoadMaterialPropertiesAsync(loader: GLTFLoader, context: string, material: _ILoaderMaterial, babylonMaterial: Material): Nullable<Promise<void>> {
+            return loader._applyExtensions(extension => extension._loadMaterialPropertiesAsync(context, material, babylonMaterial));
+        }
+
+        /**
          * Helper method called by the loader to allow extensions to override loading textures.
          * @hidden
          */