ソースを参照

Merge pull request #5624 from jbousquie/feature.CullingStrategy

Feature.culling strategy
David Catuhe 6 年 前
コミット
432e7890a1

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

@@ -83,6 +83,7 @@
 - Add support for setting renderingGroupId and creating instances to `AxesViewer` ([bghgary](https://github.com/bghgary))
 - Invert vScale of compressed ktx textures as they are inverted in the file and UNPACK_FLIP_Y_WEBGL is not supported by ktx ([TrevorDev](https://github.com/TrevorDev))
 - Enable dragging in boundingBoxGizmo without needing a parent ([TrevorDev](https://github.com/TrevorDev))
+- Added per mesh culling strategy ([jerome](https://github.com/jbousquie))  
 
 ### glTF Loader
 

+ 11 - 2
src/Culling/babylon.boundingInfo.ts

@@ -148,17 +148,26 @@ module BABYLON {
         /**
          * Returns `true` if the bounding info is within the frustum defined by the passed array of planes.
          * @param frustumPlanes defines the frustum to test
-         * @param strategy defines the strategy to use for the culling (default is BABYLON.Scene.CULLINGSTRATEGY_STANDARD)
+         * @param strategy defines the strategy to use for the culling (default is BABYLON.AbstractMesh.CULLINGSTRATEGY_STANDARD)
          * @returns true if the bounding info is in the frustum planes
          */
         public isInFrustum(frustumPlanes: Array<DeepImmutable<Plane>>, strategy: number = AbstractMesh.CULLINGSTRATEGY_STANDARD): boolean {
+            let inclusionTest = (strategy === AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION || strategy === AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION_THEN_BSPHERE_ONLY);
+            if (inclusionTest) {
+                if (this.boundingSphere.isCenterInFrustum(frustumPlanes)) {
+                    return true;
+                }
+            }
+
             if (!this.boundingSphere.isInFrustum(frustumPlanes)) {
                 return false;
             }
 
-            if (strategy === AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY) {
+            let bSphereOnlyTest = (strategy === AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY || strategy === AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION_THEN_BSPHERE_ONLY);
+            if (bSphereOnlyTest) {
                 return true;
             }
+
             return this.boundingBox.isInFrustum(frustumPlanes);
         }
 

+ 19 - 2
src/Culling/babylon.boundingSphere.ts

@@ -105,12 +105,29 @@ module BABYLON {
          * @returns true if there is an intersection
          */
         public isInFrustum(frustumPlanes: Array<DeepImmutable<Plane>>): boolean {
-            for (var i = 0; i < 6; i++) {
-                if (frustumPlanes[i].dotCoordinate(this.centerWorld) <= -this.radiusWorld) {
+            let center = this.centerWorld;
+            let radius = this.radiusWorld;
+            for (let i = 0; i < 6; i++) {
+                if (frustumPlanes[i].dotCoordinate(center) <= -radius) {
                     return false;
                 }
             }
+            return true;
+        }
 
+        /**
+         * Tests if the bounding sphere center is in between the frustum planes.
+         * Used for optimistic fast inclusion.
+         * @param frustumPlanes defines the frustum planes to test
+         * @returns true if the sphere center is in between the frustum planes
+         */
+        public isCenterInFrustum(frustumPlanes: Array<DeepImmutable<Plane>>): boolean {
+            let center = this.centerWorld;
+            for (let i = 0; i < 6; i++) {
+                if (frustumPlanes[i].dotCoordinate(center) < 0) {
+                    return false;
+                }
+            }
             return true;
         }
 

+ 42 - 3
src/Mesh/babylon.abstractMesh.ts

@@ -44,10 +44,40 @@ module BABYLON {
         /** Use a conservative occlusion algorithm */
         public static OCCLUSION_ALGORITHM_TYPE_CONSERVATIVE = 1;
 
-        /** Default culling strategy with bounding box and bounding sphere and then frustum culling */
+        /** Default culling strategy : this is an exclusion test and it's the more accurate.
+         *  Test order :
+         *  Is the bounding sphere outside the frustum ?
+         *  If not, are the bounding box vertices outside the frustum ?
+         *  It not, then the cullable object is in the frustum.
+         */
         public static readonly CULLINGSTRATEGY_STANDARD = 0;
-        /** Culling strategy with bounding sphere only and then frustum culling */
+        /** Culling strategy : Bounding Sphere Only.
+         *  This is an exclusion test. It's faster than the standard strategy because the bounding box is not tested.
+         *  It's also less accurate than the standard because some not visible objects can still be selected.
+         *  Test : is the bounding sphere outside the frustum ?
+         *  If not, then the cullable object is in the frustum.
+         */
         public static readonly CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY = 1;
+        /** Culling strategy : Optimistic Inclusion.
+         *  This in an inclusion test first, then the standard exclusion test.
+         *  This can be faster when a cullable object is expected to be almost always in the camera frustum.
+         *  This could also be a little slower than the standard test when the tested object center is not the frustum but one of its bounding box vertex is still inside.
+         *  Anyway, it's as accurate as the standard strategy.
+         *  Test :
+         *  Is the cullable object bounding sphere center in the frustum ?
+         *  If not, apply the default culling strategy.
+         */
+        public static readonly CULLINGSTRATEGY_OPTIMISTIC_INCLUSION = 2;
+        /** Culling strategy : Optimistic Inclusion then Bounding Sphere Only.
+         *  This in an inclusion test first, then the bounding sphere only exclusion test.
+         *  This can be the fastest test when a cullable object is expected to be almost always in the camera frustum.
+         *  This could also be a little slower than the BoundingSphereOnly strategy when the tested object center is not in the frustum but its bounding sphere still intersects it.
+         *  It's less accurate than the standard strategy and as accurate as the BoundingSphereOnly strategy.
+         *  Test :
+         *  Is the cullable object bounding sphere center in the frustum ?
+         *  If not, apply the Bounding Sphere Only strategy. No Bounding Box is tested here.
+         */
+        public static readonly CULLINGSTRATEGY_OPTIMISTIC_INCLUSION_THEN_BSPHERE_ONLY = 3;
 
         /**
          * No billboard
@@ -78,7 +108,16 @@ module BABYLON {
 
         private _facetData = new _FacetDataStorage();
 
-        /** Gets ot sets the culling strategy to use to find visible meshes */
+        /**
+         * The culling strategy to use to check whether the mesh must be rendered or not.
+         * This value can be changed at any time and will be used on the next render mesh selection.
+         * The possible values are :
+         * - AbstractMesh.CULLINGSTRATEGY_STANDARD
+         * - AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY
+         * - AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION
+         * - AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION_THEN_BSPHERE_ONLY
+         * Please read each static variable documentation to get details about the culling process.
+         * */
         public cullingStrategy = AbstractMesh.CULLINGSTRATEGY_STANDARD;
 
         /**