Sfoglia il codice sorgente

BabylonFileLoader: LOD Support

Add support for LOD serialization to babylonFileLoader.ts and Babylon Entities
MackeyK24 6 anni fa
parent
commit
0af2aae9c6

+ 1 - 0
dist/preview release/what's new.md

@@ -144,6 +144,7 @@
 - Added `Matrix.RotationAlignToRef` method to obtain rotation matrix from one vector to another ([sable](https://github.com/thscott))
 - ArcRotateCamera will now cache the necessary matrices when modifying its upVector, instead of calculating them each time they're needed ([sable](https://github.com/thscott))
 - Update `DracoCompression` to use web workers ([bghgary](https://github.com/bghgary))
+- Added `LOD Babylon Mesh Entities` to support to babylonFileLoader.ts ([MackeyK24](https://github.com/mackeyk24))
 
 ### OBJ Loader
 - Add color vertex support (not part of standard) ([brianzinn](https://github.com/brianzinn))

+ 45 - 2
src/Loading/Plugins/babylonFileLoader.ts

@@ -61,6 +61,43 @@ var logOperation = (operation: string, producer: { file: string, name: string, v
     return operation + " of " + (producer ? producer.file + " from " + producer.name + " version: " + producer.version + ", exporter version: " + producer.exporter_version : "unknown");
 };
 
+var loadDetailLevels = (scene: Scene, mesh: any) => {
+    const mastermesh: Mesh = mesh;
+
+    // Every value specified in the ids array of the extension points to another mesh which should be used as the lower LOD level.
+    // The distances (or coverages) array values specified are used along with the lod mesh ids as a hint to determine the switching threshold for the various LODs.
+    if (mesh._waitingLods) {
+        if (mesh._waitingLods.ids && mesh._waitingLods.ids.length > 0) {
+            const lodmeshes: string[] = mesh._waitingLods.ids;
+            const wasenabled: boolean = mastermesh.isEnabled(false);
+            if (mesh._waitingLods.distances) {
+                const distances: number[] = mesh._waitingLods.distances;
+                if (distances.length >= lodmeshes.length) {
+                    const culling: number = (distances.length > lodmeshes.length) ? distances[distances.length - 1] : 0;
+                    mastermesh.setEnabled(false);
+                    for (let index = 0; index < lodmeshes.length; index++) {
+                        const lodid: string = lodmeshes[index];
+                        const lodmesh: Mesh = scene.getMeshByID(lodid) as Mesh;
+                        if (lodmesh != null) {
+                            lodmesh.parent = mastermesh;
+                            mastermesh.addLODLevel(distances[index], lodmesh);
+                        }
+                    }
+                    if (culling > 0) {
+                        mastermesh.addLODLevel(culling, null);
+                    }
+                    if (wasenabled === true) {
+                        mastermesh.setEnabled(true);
+                    }
+                } else {
+                    Tools.Warn("Invalid level of detail distances for " + mesh.name);
+                }
+            }
+        }
+        mesh._waitingLods = null;
+    }
+};
+
 var loadAssetContainer = (scene: Scene, data: string, rootUrl: string, onError?: (message: string, exception?: any) => void, addToScene = false): AssetContainer => {
     var container = new AssetContainer(scene);
 
@@ -290,7 +327,7 @@ var loadAssetContainer = (scene: Scene, data: string, rootUrl: string, onError?:
             }
         }
 
-        // Connect parents & children and parse actions
+        // Connect parents & children and parse actions and lods
         for (index = 0, cache = scene.transformNodes.length; index < cache; index++) {
             var transformNode = scene.transformNodes[index];
             if (transformNode._waitingParentId) {
@@ -304,6 +341,9 @@ var loadAssetContainer = (scene: Scene, data: string, rootUrl: string, onError?:
                 mesh.parent = scene.getLastEntryByID(mesh._waitingParentId);
                 mesh._waitingParentId = null;
             }
+            if (mesh._waitingLods) {
+                loadDetailLevels(scene, mesh);
+            }
         }
 
         // freeze world matrix application
@@ -517,7 +557,7 @@ SceneLoader.RegisterPlugin({
                     }
                 }
 
-                // Connecting parents
+                // Connecting parents and lods
                 var currentMesh: AbstractMesh;
                 for (index = 0, cache = scene.meshes.length; index < cache; index++) {
                     currentMesh = scene.meshes[index];
@@ -525,6 +565,9 @@ SceneLoader.RegisterPlugin({
                         currentMesh.parent = scene.getLastEntryByID(currentMesh._waitingParentId);
                         currentMesh._waitingParentId = null;
                     }
+                    if (currentMesh._waitingLods) {
+                        loadDetailLevels(scene, currentMesh);
+                    }
                 }
 
                 // freeze and compute world matrix application

+ 2 - 0
src/Meshes/abstractMesh.ts

@@ -598,6 +598,8 @@ export class AbstractMesh extends TransformNode implements IDisposable, ICullabl
 
     // Loading properties
     /** @hidden */
+    public _waitingLods: Nullable<any> = null;
+    /** @hidden */
     public _waitingActions: Nullable<any> = null;
     /** @hidden */
     public _waitingFreezeWorldMatrix: Nullable<boolean> = null;

+ 9 - 0
src/Meshes/mesh.ts

@@ -3109,6 +3109,15 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
             Mesh._PhysicsImpostorParser(scene, mesh, parsedMesh);
         }
 
+        // Levels
+        if (parsedMesh.lodMeshIds) {
+            mesh._waitingLods = {
+                ids: parsedMesh.lodMeshIds,
+                distances: (parsedMesh.lodDistances) ? parsedMesh.lodDistances : null,
+                coverages: (parsedMesh.lodCoverages) ? parsedMesh.lodCoverages : null
+            };
+        }
+
         // Instances
         if (parsedMesh.instances) {
             for (var index = 0; index < parsedMesh.instances.length; index++) {