Browse Source

New option for mesh: ```mesh.showBoundingBox``` to display mesh's bounding box. You can configure back and front color using ```scene.getBoundingBoxRenderer()```. This function returns a ```BABYLON.BoundingBoxRenderer``` where you can define ```backColor```, ```frontColor``` and ```showBackLines```

David Catuhe 11 years ago
parent
commit
eb3c65db3e

+ 1 - 0
Babylon/Mesh/babylon.mesh.js

@@ -78,6 +78,7 @@ var BABYLON = BABYLON || {};
     BABYLON.Mesh.prototype.renderingGroupId = 0;
 
     BABYLON.Mesh.prototype.infiniteDistance = false;
+    BABYLON.Mesh.prototype.showBoundingBox = false;
 
     // Properties
 

+ 6 - 4
Babylon/Mesh/babylon.vertexBuffer.js

@@ -3,9 +3,9 @@
 var BABYLON = BABYLON || {};
 
 (function () {
-    BABYLON.VertexBuffer = function (mesh, data, kind, updatable) {
+    BABYLON.VertexBuffer = function (mesh, data, kind, updatable, engine) {
         this._mesh = mesh;
-        this._engine = mesh.getScene().getEngine();
+        this._engine = engine || mesh.getScene().getEngine();
         this._updatable = updatable;
         
         if (updatable) {
@@ -21,7 +21,9 @@ var BABYLON = BABYLON || {};
         switch (kind) {
             case BABYLON.VertexBuffer.PositionKind:
                 this._strideSize = 3;
-                this._mesh._resetPointsArrayCache();
+                if (this._mesh) {
+                    this._mesh._resetPointsArrayCache();
+                }
                 break;
             case BABYLON.VertexBuffer.NormalKind:
                 this._strideSize = 3;
@@ -62,7 +64,7 @@ var BABYLON = BABYLON || {};
         this._engine.updateDynamicVertexBuffer(this._buffer, data);
         this._data = data;
         
-        if (this._kind === BABYLON.VertexBuffer.PositionKind) {
+        if (this._kind === BABYLON.VertexBuffer.PositionKind && this._mesh) {
             this._mesh._resetPointsArrayCache();
         }
     };

+ 84 - 0
Babylon/Rendering/babylon.boundingBoxRenderer.js

@@ -0,0 +1,84 @@
+"use strict";
+
+var BABYLON = BABYLON || {};
+
+(function () {
+    BABYLON.BoundingBoxRenderer = function (scene) {
+        this._scene = scene;
+        this._colorShader = new BABYLON.ShaderMaterial("colorShader", scene, "color",
+        {
+            attributes: ["position"],
+            uniforms: ["worldViewProjection", "color"]
+        });
+        this.frontColor = new BABYLON.Color3(1, 1, 1);
+        this.backColor = new BABYLON.Color3(0.1, 0.1, 0.1);
+
+        var engine = this._scene.getEngine();
+        var boxdata = BABYLON.VertexData.CreateBox(1.0);
+        this._vb = new BABYLON.VertexBuffer(null, boxdata.positions, BABYLON.VertexBuffer.PositionKind, false, engine);
+        this._ib = engine.createIndexBuffer([0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 7, 1, 6, 2, 5, 3, 4]);
+
+        this.renderList = new BABYLON.Tools.SmartArray(32);
+    };
+
+    // Members
+    BABYLON.BoundingBoxRenderer.prototype.showBackLines = true;
+
+    // Functions
+    BABYLON.BoundingBoxRenderer.prototype.reset = function() {
+        this.renderList.reset();
+    };
+
+    BABYLON.BoundingBoxRenderer.prototype.render = function () {
+        if (this.renderList.length == 0 || !this._colorShader.isReady()) {
+            return;
+        }
+
+        var engine = this._scene.getEngine();
+        engine.setDepthWrite(false);
+        this._colorShader._preBind();
+        for (var boundingBoxIndex = 0; boundingBoxIndex < this.renderList.length; boundingBoxIndex++) {
+            var mesh = this.renderList.data[boundingBoxIndex];
+            var boundingBox = mesh.getBoundingInfo().boundingBox;
+            var min = boundingBox.minimum;
+            var max = boundingBox.maximum;
+            var diff = max.subtract(min);
+            var median = min.add(diff.scale(0.5));
+
+            var worldMatrix = BABYLON.Matrix.Scaling(diff.x, diff.y, diff.z)
+                .multiply(BABYLON.Matrix.Translation(median.x, median.y, median.z))
+                .multiply(mesh.getWorldMatrix());
+
+            // VBOs
+            engine.bindBuffers(this._vb._buffer, this._ib, [3], 3 * 4, this._colorShader.getEffect());
+
+            if (this.showBackLines) {
+                // Back
+                engine.setDepthFunctionToGreaterOrEqual();
+                this._colorShader.setColor3("color", this.backColor);
+                this._colorShader.bind(worldMatrix, mesh);
+
+                // Draw order
+                engine.draw(false, 0, 24);
+            }
+
+            // Front
+            engine.setDepthFunctionToLess();
+            this._colorShader.setColor3("color", this.frontColor);
+            this._colorShader.bind(worldMatrix, mesh);
+
+            // Draw order
+            engine.draw(false, 0, 24);
+        }
+        this._colorShader.unbind();
+        engine.setDepthFunctionToLessOrEqual();
+        engine.setDepthWrite(true);
+    };
+
+
+    BABYLON.BoundingBoxRenderer.prototype.dispose = function () {
+        this._colorShader.dispose();
+        this._vb.dispose();
+        this._scene.getEngine()._releaseBuffer(this._ib);
+    };
+})();

+ 7 - 0
Babylon/Shaders/color.fragment.fx

@@ -0,0 +1,7 @@
+precision mediump float;
+
+uniform vec3 color;
+
+void main(void) {
+	gl_FragColor = vec4(color, 1.);
+}

+ 11 - 0
Babylon/Shaders/color.vertex.fx

@@ -0,0 +1,11 @@
+precision mediump float;
+
+// Attributes
+attribute vec3 position;
+
+// Uniforms
+uniform mat4 worldViewProjection;
+
+void main(void) {
+	gl_Position = worldViewProjection * vec4(position, 1.0);
+}

+ 16 - 0
Babylon/babylon.engine.js

@@ -161,6 +161,22 @@ var BABYLON = BABYLON || {};
     };
 
     // Methods
+    BABYLON.Engine.prototype.setDepthFunctionToGreater = function() {
+        this._gl.depthFunc(this._gl.GREATER);
+    };
+
+    BABYLON.Engine.prototype.setDepthFunctionToGreaterOrEqual = function () {
+        this._gl.depthFunc(this._gl.GEQUAL);
+    };
+
+    BABYLON.Engine.prototype.setDepthFunctionToLess = function () {
+        this._gl.depthFunc(this._gl.LESS);
+    };
+
+    BABYLON.Engine.prototype.setDepthFunctionToLessOrEqual = function () {
+        this._gl.depthFunc(this._gl.LEQUAL);
+    };
+
     BABYLON.Engine.prototype.stopRenderLoop = function () {
         this._renderFunction = null;
         this._runningLoop = false;

+ 29 - 8
Babylon/babylon.scene.js

@@ -3,7 +3,7 @@
 var BABYLON = BABYLON || {};
 
 (function () {
-    BABYLON.Scene = function (engine) {
+    BABYLON.Scene = function(engine) {
         this._engine = engine;
         this.autoClear = true;
         this.clearColor = new BABYLON.Color3(0.2, 0.2, 0.3);
@@ -106,9 +106,16 @@ var BABYLON = BABYLON || {};
 
         // Multi-cameras
         this.activeCameras = [];
+
+        // Render bounding boxes
+        this._boundingBoxRenderer = new BABYLON.BoundingBoxRenderer(this);
+    };
+
+    // Properties 
+    BABYLON.Scene.prototype.getBoundingBoxRenderer = function () {
+        return this._boundingBoxRenderer;
     };
 
-    // Properties   
     BABYLON.Scene.prototype.getEngine = function () {
         return this._engine;
     };
@@ -409,7 +416,7 @@ var BABYLON = BABYLON || {};
     };
 
     BABYLON.Scene.prototype.getLastMeshByID = function (id) {
-        for (var index = this.meshes.length - 1; index >= 0 ; index--) {
+        for (var index = this.meshes.length - 1; index >= 0; index--) {
             if (this.meshes[index].id === id) {
                 return this.meshes[index];
             }
@@ -419,19 +426,19 @@ var BABYLON = BABYLON || {};
     };
 
     BABYLON.Scene.prototype.getLastEntryByID = function (id) {
-        for (var index = this.meshes.length - 1; index >= 0 ; index--) {
+        for (var index = this.meshes.length - 1; index >= 0; index--) {
             if (this.meshes[index].id === id) {
                 return this.meshes[index];
             }
         }
 
-        for (var index = this.cameras.length - 1; index >= 0 ; index--) {
+        for (var index = this.cameras.length - 1; index >= 0; index--) {
             if (this.cameras[index].id === id) {
                 return this.cameras[index];
             }
         }
 
-        for (var index = this.lights.length - 1; index >= 0 ; index--) {
+        for (var index = this.lights.length - 1; index >= 0; index--) {
             if (this.lights[index].id === id) {
                 return this.lights[index];
             }
@@ -451,7 +458,7 @@ var BABYLON = BABYLON || {};
     };
 
     BABYLON.Scene.prototype.getLastSkeletonByID = function (id) {
-        for (var index = this.skeletons.length - 1; index >= 0 ; index--) {
+        for (var index = this.skeletons.length - 1; index >= 0; index--) {
             if (this.skeletons[index].id === id) {
                 return this.skeletons[index];
             }
@@ -511,6 +518,7 @@ var BABYLON = BABYLON || {};
         this._processedMaterials.reset();
         this._activeParticleSystems.reset();
         this._activeSkeletons.reset();
+        this._boundingBoxRenderer.reset();
 
         if (!this._frustumPlanes) {
             this._frustumPlanes = BABYLON.Frustum.GetPlanes(this._transformMatrix);
@@ -545,6 +553,10 @@ var BABYLON = BABYLON || {};
                         }
                         mesh._renderId = this._renderId;
 
+                        if (mesh.showBoundingBox) {
+                            this._boundingBoxRenderer.renderList.push(mesh);
+                        }
+
                         if (mesh.skeleton) {
                             this._activeSkeletons.pushNoDuplicate(mesh.skeleton);
                         }
@@ -584,6 +596,10 @@ var BABYLON = BABYLON || {};
                         this._activeSkeletons.pushNoDuplicate(mesh.skeleton);
                     }
 
+                    if (mesh.showBoundingBox) {
+                        this._boundingBoxRenderer.renderList.push(mesh);
+                    }
+
                     for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
                         var subMesh = mesh.subMeshes[subIndex];
 
@@ -676,6 +692,9 @@ var BABYLON = BABYLON || {};
         // Render
         this._renderingManager.render(null, null, true, true);
 
+        // Bounding boxes
+        this._boundingBoxRenderer.render();
+
         // Lens flares
         for (var lensFlareSystemIndex = 0; lensFlareSystemIndex < this.lensFlareSystems.length; lensFlareSystemIndex++) {
             this.lensFlareSystems[lensFlareSystemIndex].render();
@@ -798,6 +817,8 @@ var BABYLON = BABYLON || {};
 
         this.skeletons = [];
 
+        this._boundingBoxRenderer.dispose();
+
         // Detach cameras
         var canvas = this._engine.getRenderingCanvas();
         var index;
@@ -1084,7 +1105,7 @@ var BABYLON = BABYLON || {};
     };
 
     // Tags
-    BABYLON.Scene.prototype._getByTags = function(list, tagsQuery) {
+    BABYLON.Scene.prototype._getByTags = function (list, tagsQuery) {
         if (tagsQuery === undefined) {
             // returns the complete list (could be done with BABYLON.Tags.MatchesQuery but no need to have a for-loop here)
             return list;

File diff suppressed because it is too large
+ 4 - 2
babylon.1.11.0-beta.js