瀏覽代碼

Adding occlusion query and basic object checks

DESKTOP-QJU4N0L\mityh 8 年之前
父節點
當前提交
3d6a807e71
共有 23 個文件被更改,包括 14136 次插入13952 次删除
  1. 3467 3451
      dist/preview release/babylon.d.ts
  2. 42 42
      dist/preview release/babylon.js
  3. 38 1
      dist/preview release/babylon.max.js
  4. 3467 3451
      dist/preview release/babylon.module.d.ts
  5. 43 43
      dist/preview release/babylon.worker.js
  6. 3299 3283
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts
  7. 31 31
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js
  8. 38 1
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js
  9. 3299 3283
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.module.d.ts
  10. 1 1
      dist/preview release/gui/babylon.gui.min.js
  11. 263 263
      dist/preview release/inspector/babylon.inspector.bundle.js
  12. 3 3
      dist/preview release/inspector/babylon.inspector.min.js
  13. 2 2
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  14. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  15. 2 2
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  16. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js
  17. 1 1
      dist/preview release/materialsLibrary/babylon.customMaterial.min.js
  18. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.min.js
  19. 1 1
      dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js
  20. 1 1
      dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js
  21. 65 59
      src/Mesh/babylon.abstractMesh.ts
  22. 57 29
      src/Mesh/babylon.mesh.ts
  23. 13 1
      src/babylon.mixins.ts

文件差異過大導致無法顯示
+ 3467 - 3451
dist/preview release/babylon.d.ts


文件差異過大導致無法顯示
+ 42 - 42
dist/preview release/babylon.js


+ 38 - 1
dist/preview release/babylon.max.js

@@ -11779,6 +11779,11 @@ var BABYLON;
             // Properties
             _this.definedFacingForward = true; // orientation for POV movement & rotation
             _this.position = BABYLON.Vector3.Zero();
+            _this._gl = _this.getEngine()._gl;
+            _this.occlusionType = AbstractMesh.OCCLUSION_TYPE_NO_VALUE;
+            _this.occlusionRetryCount = -1;
+            _this.occlusionQuery = _this._gl.createQuery();
+            _this.isOcclusionQueryInProgress = false;
             _this._rotation = BABYLON.Vector3.Zero();
             _this._scaling = BABYLON.Vector3.One();
             _this.billboardMode = AbstractMesh.BILLBOARDMODE_NONE;
@@ -13807,6 +13812,9 @@ var BABYLON;
         AbstractMesh._BILLBOARDMODE_Y = 2;
         AbstractMesh._BILLBOARDMODE_Z = 4;
         AbstractMesh._BILLBOARDMODE_ALL = 7;
+        AbstractMesh.OCCLUSION_TYPE_NO_VALUE = 0;
+        AbstractMesh.OCCLUSION_TYPE_OPTIMISITC = 1;
+        AbstractMesh.OCCLUSION_TYPE_STRICT = 2;
         AbstractMesh._rotationAxisCache = new BABYLON.Quaternion();
         AbstractMesh._lookAtVectorCache = new BABYLON.Vector3(0, 0, 0);
         return AbstractMesh;
@@ -21450,6 +21458,26 @@ var BABYLON;
          * Returns the Mesh.
          */
         Mesh.prototype.render = function (subMesh, enableAlphaMode) {
+            // check occlusion query in progress
+            if (this.occlusionType !== BABYLON.AbstractMesh.OCCLUSION_TYPE_NO_VALUE && this.isOcclusionQueryInProgress) {
+                console.log("Enter occlusion check");
+                var isOcclusionQueryAvailable = this._gl.getQueryParameter(this.occlusionQuery, this._gl.QUERY_RESULT_AVAILABLE);
+                console.log("isOcclusionQueryAvailable" + isOcclusionQueryAvailable);
+                if (isOcclusionQueryAvailable) {
+                    var occlusionQueryResult = this._gl.getQueryParameter(this.occlusionQuery, this._gl.QUERY_RESULT);
+                    console.log("occlusionQueryResult" + occlusionQueryResult);
+                    this.isOcclusionQueryInProgress = false;
+                    if (occlusionQueryResult === 1) {
+                        // draw
+                    }
+                    else {
+                        return this;
+                    }
+                }
+                else {
+                    return this;
+                }
+            }
             var scene = this.getScene();
             // Managing instances
             var batch = this._getInstancesRenderList(subMesh._id);
@@ -21507,7 +21535,16 @@ var BABYLON;
                 effectiveMaterial.bind(world, this);
             }
             // Draw
-            this._processRendering(subMesh, effect, fillMode, batch, hardwareInstancedRendering, this._onBeforeDraw, effectiveMaterial);
+            if (this.occlusionType !== BABYLON.AbstractMesh.OCCLUSION_TYPE_NO_VALUE) {
+                console.log("Enter Draw");
+                this._gl.beginQuery(this._gl.ANY_SAMPLES_PASSED, this.occlusionQuery);
+                this._processRendering(subMesh, effect, fillMode, batch, hardwareInstancedRendering, this._onBeforeDraw, effectiveMaterial);
+                this._gl.endQuery(this._gl.ANY_SAMPLES_PASSED);
+                this.isOcclusionQueryInProgress = true;
+            }
+            else {
+                this._processRendering(subMesh, effect, fillMode, batch, hardwareInstancedRendering, this._onBeforeDraw, effectiveMaterial);
+            }
             // Unbind
             effectiveMaterial.unbind();
             // Outline - step 2

文件差異過大導致無法顯示
+ 3467 - 3451
dist/preview release/babylon.module.d.ts


文件差異過大導致無法顯示
+ 43 - 43
dist/preview release/babylon.worker.js


文件差異過大導致無法顯示
+ 3299 - 3283
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts


文件差異過大導致無法顯示
+ 31 - 31
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js


+ 38 - 1
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js

@@ -11779,6 +11779,11 @@ var BABYLON;
             // Properties
             _this.definedFacingForward = true; // orientation for POV movement & rotation
             _this.position = BABYLON.Vector3.Zero();
+            _this._gl = _this.getEngine()._gl;
+            _this.occlusionType = AbstractMesh.OCCLUSION_TYPE_NO_VALUE;
+            _this.occlusionRetryCount = -1;
+            _this.occlusionQuery = _this._gl.createQuery();
+            _this.isOcclusionQueryInProgress = false;
             _this._rotation = BABYLON.Vector3.Zero();
             _this._scaling = BABYLON.Vector3.One();
             _this.billboardMode = AbstractMesh.BILLBOARDMODE_NONE;
@@ -13807,6 +13812,9 @@ var BABYLON;
         AbstractMesh._BILLBOARDMODE_Y = 2;
         AbstractMesh._BILLBOARDMODE_Z = 4;
         AbstractMesh._BILLBOARDMODE_ALL = 7;
+        AbstractMesh.OCCLUSION_TYPE_NO_VALUE = 0;
+        AbstractMesh.OCCLUSION_TYPE_OPTIMISITC = 1;
+        AbstractMesh.OCCLUSION_TYPE_STRICT = 2;
         AbstractMesh._rotationAxisCache = new BABYLON.Quaternion();
         AbstractMesh._lookAtVectorCache = new BABYLON.Vector3(0, 0, 0);
         return AbstractMesh;
@@ -21450,6 +21458,26 @@ var BABYLON;
          * Returns the Mesh.
          */
         Mesh.prototype.render = function (subMesh, enableAlphaMode) {
+            // check occlusion query in progress
+            if (this.occlusionType !== BABYLON.AbstractMesh.OCCLUSION_TYPE_NO_VALUE && this.isOcclusionQueryInProgress) {
+                console.log("Enter occlusion check");
+                var isOcclusionQueryAvailable = this._gl.getQueryParameter(this.occlusionQuery, this._gl.QUERY_RESULT_AVAILABLE);
+                console.log("isOcclusionQueryAvailable" + isOcclusionQueryAvailable);
+                if (isOcclusionQueryAvailable) {
+                    var occlusionQueryResult = this._gl.getQueryParameter(this.occlusionQuery, this._gl.QUERY_RESULT);
+                    console.log("occlusionQueryResult" + occlusionQueryResult);
+                    this.isOcclusionQueryInProgress = false;
+                    if (occlusionQueryResult === 1) {
+                        // draw
+                    }
+                    else {
+                        return this;
+                    }
+                }
+                else {
+                    return this;
+                }
+            }
             var scene = this.getScene();
             // Managing instances
             var batch = this._getInstancesRenderList(subMesh._id);
@@ -21507,7 +21535,16 @@ var BABYLON;
                 effectiveMaterial.bind(world, this);
             }
             // Draw
-            this._processRendering(subMesh, effect, fillMode, batch, hardwareInstancedRendering, this._onBeforeDraw, effectiveMaterial);
+            if (this.occlusionType !== BABYLON.AbstractMesh.OCCLUSION_TYPE_NO_VALUE) {
+                console.log("Enter Draw");
+                this._gl.beginQuery(this._gl.ANY_SAMPLES_PASSED, this.occlusionQuery);
+                this._processRendering(subMesh, effect, fillMode, batch, hardwareInstancedRendering, this._onBeforeDraw, effectiveMaterial);
+                this._gl.endQuery(this._gl.ANY_SAMPLES_PASSED);
+                this.isOcclusionQueryInProgress = true;
+            }
+            else {
+                this._processRendering(subMesh, effect, fillMode, batch, hardwareInstancedRendering, this._onBeforeDraw, effectiveMaterial);
+            }
             // Unbind
             effectiveMaterial.unbind();
             // Outline - step 2

文件差異過大導致無法顯示
+ 3299 - 3283
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.module.d.ts


文件差異過大導致無法顯示
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js


文件差異過大導致無法顯示
+ 263 - 263
dist/preview release/inspector/babylon.inspector.bundle.js


文件差異過大導致無法顯示
+ 3 - 3
dist/preview release/inspector/babylon.inspector.min.js


文件差異過大導致無法顯示
+ 2 - 2
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


文件差異過大導致無法顯示
+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


文件差異過大導致無法顯示
+ 2 - 2
dist/preview release/loaders/babylon.glTFFileLoader.min.js


文件差異過大導致無法顯示
+ 1 - 1
dist/preview release/loaders/babylon.objFileLoader.min.js


文件差異過大導致無法顯示
+ 1 - 1
dist/preview release/materialsLibrary/babylon.customMaterial.min.js


文件差異過大導致無法顯示
+ 1 - 1
dist/preview release/materialsLibrary/babylon.waterMaterial.min.js


文件差異過大導致無法顯示
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js


文件差異過大導致無法顯示
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js


+ 65 - 59
src/Mesh/babylon.abstractMesh.ts

@@ -7,6 +7,10 @@
         private static _BILLBOARDMODE_Z = 4;
         private static _BILLBOARDMODE_ALL = 7;
 
+        public static OCCLUSION_TYPE_NO_VALUE = 0;
+        public static OCCLUSION_TYPE_OPTIMISITC = 1;
+        public static OCCLUSION_TYPE_STRICT = 2;
+
         public static get BILLBOARDMODE_NONE(): number {
             return AbstractMesh._BILLBOARDMODE_NONE;
         }
@@ -57,7 +61,7 @@
         }
         public set partitioningSubdivisions(nb: number) {
             this._partitioningSubdivisions = nb;
-        } 
+        }
         /**
          * The ratio (float) to apply to the bouding box size to set to the partioning space.  
          * Ex : 1.01 (default) the partioning space is 1% bigger than the bounding box.
@@ -121,6 +125,11 @@
         // Properties
         public definedFacingForward = true; // orientation for POV movement & rotation
         public position = Vector3.Zero();
+        protected _gl = this.getEngine()._gl;
+        public occlusionType = AbstractMesh.OCCLUSION_TYPE_NO_VALUE;
+        public occlusionRetryCount = -1;
+        public occlusionQuery = this._gl.createQuery();
+        public isOcclusionQueryInProgress = false;
         private _rotation = Vector3.Zero();
         private _rotationQuaternion: Quaternion;
         private _scaling = Vector3.One();
@@ -153,7 +162,7 @@
             if (!this.subMeshes) {
                 return;
             }
-            
+
             for (var subMesh of this.subMeshes) {
                 subMesh.setEffect(null);
             }
@@ -189,7 +198,7 @@
 
             this._hasVertexAlpha = value;
             this._markSubMeshesAsAttributesDirty();
-        }        
+        }
 
         private _useVertexColors = true;
         public get useVertexColors(): boolean {
@@ -202,7 +211,7 @@
 
             this._useVertexColors = value;
             this._markSubMeshesAsAttributesDirty();
-        }         
+        }
 
         private _computeBonesUsingShaders = true;
         public get computeBonesUsingShaders(): boolean {
@@ -215,7 +224,7 @@
 
             this._computeBonesUsingShaders = value;
             this._markSubMeshesAsAttributesDirty();
-        }                
+        }
 
         private _numBoneInfluencers = 4;
         public get numBoneInfluencers(): number {
@@ -228,7 +237,7 @@
 
             this._numBoneInfluencers = value;
             this._markSubMeshesAsAttributesDirty();
-        }           
+        }
 
         private _applyFog = true;
         public get applyFog(): boolean {
@@ -241,7 +250,7 @@
 
             this._applyFog = value;
             this._markSubMeshesAsMiscDirty();
-        }  
+        }
 
         public scalingDeterminant = 1;
 
@@ -288,24 +297,24 @@
         private _oldPositionForCollisions = new Vector3(0, 0, 0);
         private _diffPositionForCollisions = new Vector3(0, 0, 0);
         private _newPositionForCollisions = new Vector3(0, 0, 0);
-        
-        
+
+
         public get collisionMask(): number {
             return this._collisionMask;
         }
-        
+
         public set collisionMask(mask: number) {
             this._collisionMask = !isNaN(mask) ? mask : -1;
         }
-        
+
         public get collisionGroup(): number {
             return this._collisionGroup;
         }
-        
+
         public set collisionGroup(mask: number) {
             this._collisionGroup = !isNaN(mask) ? mask : -1;
         }
-        
+
         // Attach to bone
         private _meshToBoneReferal: AbstractMesh;
 
@@ -443,7 +452,7 @@
                 if (isIn) {
                     return;
                 }
-                this._lightSources.splice(index, 1);            
+                this._lightSources.splice(index, 1);
             }
 
             this._markSubMeshesAsLightDirty();
@@ -455,14 +464,14 @@
             if (index === -1) {
                 return;
             }
-            this._lightSources.splice(index, 1);       
+            this._lightSources.splice(index, 1);
         }
 
         private _markSubMeshesAsDirty(func: (defines: MaterialDefines) => void) {
             if (!this.subMeshes) {
                 return;
             }
-            
+
             for (var subMesh of this.subMeshes) {
                 if (subMesh._materialDefines) {
                     func(subMesh._materialDefines);
@@ -482,7 +491,7 @@
             if (!this.subMeshes) {
                 return;
             }
-            
+
             for (var subMesh of this.subMeshes) {
                 var material = subMesh.getMaterial();
                 if (material) {
@@ -727,7 +736,7 @@
         public _activate(renderId: number): void {
             this._renderId = renderId;
         }
-   
+
         /**
          * Returns the last update of the World matrix
          * Returns a Matrix.  
@@ -736,7 +745,7 @@
             if (this._masterMesh) {
                 return this._masterMesh.getWorldMatrix();
             }
-            
+
             if (this._currentRenderId !== this.getScene().getRenderId() || !this.isSynchronized()) {
                 this.computeWorldMatrix();
             }
@@ -817,7 +826,7 @@
             }
             return this;
         }
-        
+
         /**
          * Rotates the mesh around the axis vector for the passed angle (amount) expressed in radians, in world space.  
          * Note that the property `rotationQuaternion` is then automatically updated and the property `rotation` is set to (0,0,0) and no longer used.  
@@ -845,7 +854,7 @@
 
             return this;
         }
-        
+
         /**
          * Translates the mesh along the axis vector for the passed distance in the given space.  
          * space (default LOCAL) can be either BABYLON.Space.LOCAL, either BABYLON.Space.WORLD.
@@ -1170,7 +1179,7 @@
             // Composing transformations
             this._pivotMatrix.multiplyToRef(Tmp.Matrix[1], Tmp.Matrix[4]);
             Tmp.Matrix[4].multiplyToRef(Tmp.Matrix[0], Tmp.Matrix[5]);
-            
+
             // Billboarding (testing PG:http://www.babylonjs-playground.com/#UJEIL#13)
             if (this.billboardMode !== AbstractMesh.BILLBOARDMODE_NONE && this.getScene().activeCamera) {
                 if ((this.billboardMode & AbstractMesh.BILLBOARDMODE_ALL) !== AbstractMesh.BILLBOARDMODE_ALL) {
@@ -1191,21 +1200,18 @@
                     currentPosition.subtractInPlace(this.getScene().activeCamera.globalPosition);
 
                     var finalEuler = Tmp.Vector3[4].copyFromFloats(0, 0, 0);
-                    if ((this.billboardMode & AbstractMesh.BILLBOARDMODE_X) === AbstractMesh.BILLBOARDMODE_X)
-                    {
+                    if ((this.billboardMode & AbstractMesh.BILLBOARDMODE_X) === AbstractMesh.BILLBOARDMODE_X) {
                         finalEuler.x = Math.atan2(-currentPosition.y, currentPosition.z);
                     }
-                    
-                    if ((this.billboardMode & AbstractMesh.BILLBOARDMODE_Y) === AbstractMesh.BILLBOARDMODE_Y)
-                    {
+
+                    if ((this.billboardMode & AbstractMesh.BILLBOARDMODE_Y) === AbstractMesh.BILLBOARDMODE_Y) {
                         finalEuler.y = Math.atan2(currentPosition.x, currentPosition.z);
                     }
-                    
-                    if ((this.billboardMode & AbstractMesh.BILLBOARDMODE_Z) === AbstractMesh.BILLBOARDMODE_Z)
-                    {
+
+                    if ((this.billboardMode & AbstractMesh.BILLBOARDMODE_Z) === AbstractMesh.BILLBOARDMODE_Z) {
                         finalEuler.z = Math.atan2(currentPosition.y, currentPosition.x);
                     }
- 
+
                     Matrix.RotationYawPitchRollToRef(finalEuler.y, finalEuler.x, finalEuler.z, Tmp.Matrix[0]);
                 } else {
                     Tmp.Matrix[1].copyFrom(this.getScene().activeCamera.getViewMatrix());
@@ -1230,12 +1236,12 @@
                     } else {
                         Tmp.Matrix[5].copyFrom(this.parent.getWorldMatrix());
                     }
-                    
+
                     this._localWorld.getTranslationToRef(Tmp.Vector3[5]);
                     Vector3.TransformCoordinatesToRef(Tmp.Vector3[5], Tmp.Matrix[5], Tmp.Vector3[5]);
                     this._worldMatrix.copyFrom(this._localWorld);
                     this._worldMatrix.setTranslation(Tmp.Vector3[5]);
-                    
+
                 } else {
                     if (this._meshToBoneReferal) {
                         this._localWorld.multiplyToRef(this.parent.getWorldMatrix(), Tmp.Matrix[6]);
@@ -1753,7 +1759,7 @@
             }
 
             // SubMeshes
-            if (this.getClassName() !== "InstancedMesh"){
+            if (this.getClassName() !== "InstancedMesh") {
                 this.releaseSubMeshes();
             }
 
@@ -1814,11 +1820,11 @@
          * Returns a new Vector3 what is the localAxis, expressed in the mesh local space, rotated like the mesh.  
          * This Vector3 is expressed in the World space.  
          */
-        public getDirection(localAxis:Vector3): Vector3 {
+        public getDirection(localAxis: Vector3): Vector3 {
             var result = Vector3.Zero();
 
             this.getDirectionToRef(localAxis, result);
-            
+
             return result;
         }
 
@@ -1828,19 +1834,19 @@
          * result is computed in the Wordl space from the mesh World matrix.  
          * Returns the AbstractMesh.  
          */
-        public getDirectionToRef(localAxis:Vector3, result:Vector3): AbstractMesh {
+        public getDirectionToRef(localAxis: Vector3, result: Vector3): AbstractMesh {
             Vector3.TransformNormalToRef(localAxis, this.getWorldMatrix(), result);
             return this;
         }
 
-        public setPivotPoint(point:Vector3, space:Space = Space.LOCAL): AbstractMesh {
+        public setPivotPoint(point: Vector3, space: Space = Space.LOCAL): AbstractMesh {
 
-            if(this.getScene().getRenderId() == 0){
+            if (this.getScene().getRenderId() == 0) {
                 this.computeWorldMatrix(true);
             }
 
             var wm = this.getWorldMatrix();
-            
+
             if (space == Space.WORLD) {
                 var tmat = Tmp.Matrix[0];
                 wm.invertToRef(tmat);
@@ -1868,7 +1874,7 @@
          * Sets the passed Vector3 "result" with the coordinates of the mesh pivot point in the local space.   
          * Returns the AbstractMesh.   
          */
-        public getPivotPointToRef(result:Vector3): AbstractMesh{
+        public getPivotPointToRef(result: Vector3): AbstractMesh {
             result.x = -this._pivotMatrix.m[12];
             result.y = -this._pivotMatrix.m[13];
             result.z = -this._pivotMatrix.m[14];
@@ -1888,12 +1894,12 @@
          * Defines the passed mesh as the parent of the current mesh.  
          * Returns the AbstractMesh.  
          */
-        public setParent(mesh:AbstractMesh): AbstractMesh {
-            
+        public setParent(mesh: AbstractMesh): AbstractMesh {
+
             var child = this;
             var parent = mesh;
 
-            if(mesh == null){
+            if (mesh == null) {
 
                 var rotation = Tmp.Quaternion[0];
                 var position = Tmp.Vector3[0];
@@ -1912,7 +1918,7 @@
                 child.position.z = position.z;
 
             } else {
-  
+
                 var rotation = Tmp.Quaternion[0];
                 var position = Tmp.Vector3[0];
                 var scale = Tmp.Vector3[1];
@@ -1957,7 +1963,7 @@
          * Adds the passed mesh as a child to the current mesh.  
          * Returns the AbstractMesh.  
          */
-        public addChild(mesh:AbstractMesh): AbstractMesh {
+        public addChild(mesh: AbstractMesh): AbstractMesh {
             mesh.setParent(this);
             return this;
         }
@@ -1966,7 +1972,7 @@
          * Removes the passed mesh from the current mesh children list.  
          * Returns the AbstractMesh.  
          */
-        public removeChild(mesh:AbstractMesh): AbstractMesh {
+        public removeChild(mesh: AbstractMesh): AbstractMesh {
             mesh.setParent(null);
             return this;
         }
@@ -1975,7 +1981,7 @@
          * Sets the Vector3 "result" coordinates with the mesh pivot point World coordinates.  
          * Returns the AbstractMesh.  
          */
-        public getAbsolutePivotPointToRef(result:Vector3): AbstractMesh {
+        public getAbsolutePivotPointToRef(result: Vector3): AbstractMesh {
             result.x = this._pivotMatrix.m[12];
             result.y = this._pivotMatrix.m[13];
             result.z = this._pivotMatrix.m[14];
@@ -1984,7 +1990,7 @@
             return this;
         }
 
-       // Facet data
+        // Facet data
         /** 
          *  Initialize the facet data arrays : facetNormals, facetPositions and facetPartitioning.   
          * Returns the AbstractMesh.  
@@ -2006,7 +2012,7 @@
                 this._facetNormals[f] = Vector3.Zero();
                 this._facetPositions[f] = Vector3.Zero();
             }
-            this._facetDataEnabled = true;           
+            this._facetDataEnabled = true;
             return this;
         }
 
@@ -2037,7 +2043,7 @@
             this._subDiv.Y = this._subDiv.Y < 1 ? 1 : this._subDiv.Y;
             this._subDiv.Z = this._subDiv.Z < 1 ? 1 : this._subDiv.Z;
             // set the parameters for ComputeNormals()
-            this._facetParameters.facetNormals = this.getFacetLocalNormals(); 
+            this._facetParameters.facetNormals = this.getFacetLocalNormals();
             this._facetParameters.facetPositions = this.getFacetLocalPositions();
             this._facetParameters.facetPartitioning = this.getFacetLocalPartitioning();
             this._facetParameters.bInfo = bInfo;
@@ -2065,7 +2071,7 @@
             if (!this._facetPositions) {
                 this.updateFacetData();
             }
-            return this._facetPositions;           
+            return this._facetPositions;
         }
         /**
          * Returns the facetLocalPartioning array.
@@ -2156,7 +2162,7 @@
          */
         public getClosestFacetAtLocalCoordinates(x: number, y: number, z: number, projected?: Vector3, checkFace: boolean = false, facing: boolean = true): number {
             var closest = null;
-            var tmpx = 0.0;         
+            var tmpx = 0.0;
             var tmpy = 0.0;
             var tmpz = 0.0;
             var d = 0.0;            // tmp dot facet normal * facet position
@@ -2179,14 +2185,14 @@
             var p0;                                     // current facet barycenter position
             // loop on all the facets in the current partitioning block
             for (var idx = 0; idx < facetsInBlock.length; idx++) {
-                fib = facetsInBlock[idx];           
+                fib = facetsInBlock[idx];
                 norm = facetNormals[fib];
                 p0 = facetPositions[fib];
 
                 d = (x - p0.x) * norm.x + (y - p0.y) * norm.y + (z - p0.z) * norm.z;
-                if ( !checkFace || (checkFace && facing && d >= 0.0) || (checkFace && !facing && d <= 0.0) ) {
+                if (!checkFace || (checkFace && facing && d >= 0.0) || (checkFace && !facing && d <= 0.0)) {
                     // compute (x,y,z) projection on the facet = (projx, projy, projz)
-                    d = norm.x * p0.x + norm.y * p0.y + norm.z * p0.z; 
+                    d = norm.x * p0.x + norm.y * p0.y + norm.z * p0.z;
                     t0 = -(norm.x * x + norm.y * y + norm.z * z - d) / (norm.x * norm.x + norm.y * norm.y + norm.z * norm.z);
                     projx = x + norm.x * t0;
                     projy = y + norm.y * t0;
@@ -2198,7 +2204,7 @@
                     tmpDistance = tmpx * tmpx + tmpy * tmpy + tmpz * tmpz;             // compute length between (x, y, z) and its projection on the facet
                     if (tmpDistance < shortest) {                                      // just keep the closest facet to (x, y, z)
                         shortest = tmpDistance;
-                        closest = fib; 
+                        closest = fib;
                         if (projected) {
                             projected.x = projx;
                             projected.y = projy;
@@ -2238,7 +2244,7 @@
             var positions = this.getVerticesData(VertexBuffer.PositionKind);
             var indices = this.getIndices();
             var normals: number[] | Float32Array;
-            
+
             if (this.isVerticesDataPresent(VertexBuffer.NormalKind)) {
                 normals = this.getVerticesData(VertexBuffer.NormalKind);
             } else {
@@ -2247,7 +2253,7 @@
 
             VertexData.ComputeNormals(positions, indices, normals, { useRightHandedSystem: this.getScene().useRightHandedSystem });
             this.setVerticesData(VertexBuffer.NormalKind, normals, updatable);
-        } 
+        }
 
     }
 }

+ 57 - 29
src/Mesh/babylon.mesh.ts

@@ -137,7 +137,7 @@
         private _sourceNormals: Float32Array;   // Will be used to save original normals when using software skinning
 
         // Will be used to save a source mesh reference, If any
-        private _source: BABYLON.Mesh = null; 
+        private _source: BABYLON.Mesh = null;
         public get source(): BABYLON.Mesh {
             return this._source;
         }
@@ -224,7 +224,7 @@
          */
         public getClassName(): string {
             return "Mesh";
-        }   
+        }
 
         /**
          * Returns a string.  
@@ -648,7 +648,7 @@
             if (this.subMeshes && this.subMeshes.length > 0) {
                 var totalIndices = this.getIndices().length;
                 let needToRecreate = false;
-    
+
                 if (force) {
                     needToRecreate = true;
                 } else {
@@ -1107,6 +1107,29 @@
          * Returns the Mesh.   
          */
         public render(subMesh: SubMesh, enableAlphaMode: boolean): Mesh {
+            
+            // check occlusion query in progress
+            if (this.occlusionType !== AbstractMesh.OCCLUSION_TYPE_NO_VALUE && this.isOcclusionQueryInProgress) {
+                console.log("Enter occlusion check");
+                var isOcclusionQueryAvailable = this._gl.getQueryParameter(this.occlusionQuery, this._gl.QUERY_RESULT_AVAILABLE) as boolean;
+                console.log("isOcclusionQueryAvailable" + isOcclusionQueryAvailable);
+                if (isOcclusionQueryAvailable) {
+                    var occlusionQueryResult = this._gl.getQueryParameter(this.occlusionQuery, this._gl.QUERY_RESULT) as number;
+                    console.log("occlusionQueryResult" + occlusionQueryResult);
+
+                    this.isOcclusionQueryInProgress = false;
+                    if (occlusionQueryResult === 1) {
+                        // draw
+                    }
+                    else {
+                        return this;
+                    }
+                }
+                else {
+                    return this;
+                }
+            }
+
             var scene = this.getScene();
 
             // Managing instances
@@ -1146,7 +1169,7 @@
             if (enableAlphaMode) {
                 engine.setAlphaMode(effectiveMaterial.alphaMode);
             }
-            
+
             // Outline - step 1
             var savedDepthWrite = engine.getDepthWrite();
             if (this.renderOutline) {
@@ -1169,7 +1192,7 @@
             this._bind(subMesh, effect, fillMode);
 
             var world = this.getWorldMatrix();
-            
+
             if (effectiveMaterial.storeEffectOnSubMeshes) {
                 effectiveMaterial.bindForSubMesh(world, this, subMesh);
             } else {
@@ -1177,7 +1200,16 @@
             }
 
             // Draw
-            this._processRendering(subMesh, effect, fillMode, batch, hardwareInstancedRendering, this._onBeforeDraw, effectiveMaterial);
+            if (this.occlusionType !== AbstractMesh.OCCLUSION_TYPE_NO_VALUE) {
+                console.log("Enter Draw");
+                this._gl.beginQuery(this._gl.ANY_SAMPLES_PASSED, this.occlusionQuery);
+                this._processRendering(subMesh, effect, fillMode, batch, hardwareInstancedRendering, this._onBeforeDraw, effectiveMaterial);
+                this._gl.endQuery(this._gl.ANY_SAMPLES_PASSED);
+                this.isOcclusionQueryInProgress = true;
+            }
+            else {
+                this._processRendering(subMesh, effect, fillMode, batch, hardwareInstancedRendering, this._onBeforeDraw, effectiveMaterial);
+            }
 
             // Unbind
             effectiveMaterial.unbind();
@@ -1270,8 +1302,7 @@
                     this._delayLoadingFunction(JSON.parse(data), this);
                 }
 
-                this.instances.forEach(instance =>
-                {
+                this.instances.forEach(instance => {
                     instance._syncSubMeshes();
                 });
 
@@ -2004,7 +2035,7 @@
             // Alpha
             serializationObject.alphaIndex = this.alphaIndex;
             serializationObject.hasVertexAlpha = this.hasVertexAlpha;
-            
+
             // Overlay
             serializationObject.overlayAlpha = this.overlayAlpha;
             serializationObject.overlayColor = this.overlayColor.asArray();
@@ -2018,7 +2049,7 @@
                 serializationObject.actions = this.actionManager.serialize(this.name);
             }
         }
-        
+
         public _syncGeometryWithMorphTargetManager() {
             if (!this.geometry) {
                 return;
@@ -2046,22 +2077,19 @@
                 }
             } else {
                 var index = 0;
-                
+
                 // Positions
-                while (this.geometry.isVerticesDataPresent(VertexBuffer.PositionKind + index))
-                {
+                while (this.geometry.isVerticesDataPresent(VertexBuffer.PositionKind + index)) {
                     this.geometry.removeVerticesData(VertexBuffer.PositionKind + index);
-                    
-                    if (this.geometry.isVerticesDataPresent(VertexBuffer.NormalKind + index))
-                    {
+
+                    if (this.geometry.isVerticesDataPresent(VertexBuffer.NormalKind + index)) {
                         this.geometry.removeVerticesData(VertexBuffer.NormalKind + index);
                     }
-                    if (this.geometry.isVerticesDataPresent(VertexBuffer.TangentKind + index))
-                    {
+                    if (this.geometry.isVerticesDataPresent(VertexBuffer.TangentKind + index)) {
                         this.geometry.removeVerticesData(VertexBuffer.TangentKind + index);
                     }
                     index++;
-                }    
+                }
             }
         }
 
@@ -2072,7 +2100,7 @@
          * The parameter `rootUrl` is a string, it's the root URL to prefix the `delayLoadingFile` property with
          */
         public static Parse(parsedMesh: any, scene: Scene, rootUrl: string): Mesh {
-            var mesh : Mesh;
+            var mesh: Mesh;
 
             if (parsedMesh.type && parsedMesh.type === "GroundMesh") {
                 mesh = GroundMesh.Parse(parsedMesh, scene);
@@ -2137,7 +2165,7 @@
             if (parsedMesh.isBlocker !== undefined) {
                 mesh.isBlocker = parsedMesh.isBlocker;
             }
-            
+
             mesh._shouldGenerateFlatShading = parsedMesh.useFlatShading;
 
             // freezeWorldMatrix
@@ -2547,12 +2575,12 @@
                 sideOrientation: sideOrientation
             }
             return MeshBuilder.CreatePolygon(name, options, scene);
-		}
+        }
 
-       /**
-         * Creates an extruded polygon mesh, with depth in the Y direction. 
-         * Please consider using the same method from the MeshBuilder class instead. 
-		*/
+        /**
+          * Creates an extruded polygon mesh, with depth in the Y direction. 
+          * Please consider using the same method from the MeshBuilder class instead. 
+         */
         public static ExtrudePolygon(name: string, shape: Vector3[], depth: number, scene: Scene, holes?: Vector3[][], updatable?: boolean, sideOrientation?: number): Mesh {
             var options = {
                 shape: shape,
@@ -2562,7 +2590,7 @@
                 sideOrientation: sideOrientation
             }
             return MeshBuilder.ExtrudePolygon(name, options, scene);
-		}
+        }
 
         /**
          * Creates an extruded shape mesh.    
@@ -3090,12 +3118,12 @@
 
             // Subdivide
             if (subdivideWithSubMeshes) {
-                
+
                 //-- Suppresions du submesh global
                 meshSubclass.releaseSubMeshes();
                 index = 0;
                 var offset = 0;
-                
+
                 //-- aplique la subdivision en fonction du tableau d'indices
                 while (index < indiceArray.length) {
                     BABYLON.SubMesh.CreateFromIndices(0, offset, indiceArray[index], meshSubclass);

+ 13 - 1
src/babylon.mixins.ts

@@ -44,6 +44,12 @@ interface WebGLRenderingContext {
     getUniformBlockIndex(program: WebGLProgram, uniformBlockName: string): number;
     uniformBlockBinding(program: WebGLProgram, uniformBlockIndex: number, uniformBlockBinding: number): void;
 
+    // Occlusion Query
+    createQuery(): WebGLQuery;
+    beginQuery(target: number, query: WebGLQuery);
+    endQuery(target: number): void;
+    getQueryParameter(query: WebGLQuery, pname: number): any;
+
     MAX_SAMPLES: number;
     RGBA8: number;
     READ_FRAMEBUFFER: number;
@@ -55,7 +61,7 @@ interface WebGLRenderingContext {
     RGBA32F: number;
 
     DEPTH24_STENCIL8: number;
-    
+
     /* Multiple Render Targets */
     drawBuffers(buffers: number[]): void;
     readBuffer(src: number): void;
@@ -65,6 +71,12 @@ interface WebGLRenderingContext {
     readonly COLOR_ATTACHMENT1: number;                             // 0x8CE2
     readonly COLOR_ATTACHMENT2: number;                             // 0x8CE3
     readonly COLOR_ATTACHMENT3: number;                             // 0x8CE4
+
+    // Occlusion Query
+    ANY_SAMPLES_PASSED_CONSERVATIVE: number;
+    ANY_SAMPLES_PASSED: number;
+    QUERY_RESULT_AVAILABLE: number;
+    QUERY_RESULT: number;
 }
 
 interface HTMLURL {