Browse Source

- 1.3.0:
- Selection octrees
- Breaking changes: Meshes now use multi vertex buffers (one for each attribute) instead of a big one. This is for more flexibility. The .babylon file format has changed accordingly (no more .vertices property on meshes but .positions, .normals, .colors, .uvs, .uvs2)

deltakosh 12 years ago
parent
commit
eb9e3e6445
35 changed files with 769 additions and 408 deletions
  1. 41 0
      Babylon/Culling/Octrees/babylon.octree.js
  2. 65 0
      Babylon/Culling/Octrees/babylon.octreeBlock.js
  3. 43 25
      Babylon/Culling/babylon.boundingBox.js
  4. 3 3
      Babylon/Culling/babylon.boundingInfo.js
  5. 3 3
      Babylon/Culling/babylon.boundingSphere.js
  6. 5 0
      Babylon/Materials/babylon.effect.js
  7. 9 14
      Babylon/Materials/babylon.standardMaterial.js
  8. 188 155
      Babylon/Mesh/babylon.mesh.js
  9. 2 3
      Babylon/Mesh/babylon.subMesh.js
  10. 67 0
      Babylon/Mesh/babylon.vertexBuffer.js
  11. 4 0
      Babylon/Tools/babylon.math.js
  12. 17 21
      Babylon/Tools/babylon.sceneLoader.js
  13. 18 0
      Babylon/Tools/babylon.tools.js
  14. 24 26
      Babylon/babylon.engine.js
  15. 132 43
      Babylon/babylon.scene.js
  16. 40 25
      Exporters/Blender/io_export_babylon.py
  17. 9 5
      Samples/Scenes/Blender/blender.babylon
  18. 1 1
      Samples/Scenes/Customs/charting.js
  19. 1 1
      Samples/Scenes/Espilit/espilit.babylon
  20. 1 1
      Samples/Scenes/Flat2009/Flat2009.babylon
  21. 1 1
      Samples/Scenes/Heart/Heart.babylon
  22. 1 1
      Samples/Scenes/SpaceDek/SpaceDek.babylon
  23. 1 1
      Samples/Scenes/Spaceship/Spaceship.babylon
  24. 1 1
      Samples/Scenes/TheCar/TheCar.babylon
  25. 1 1
      Samples/Scenes/Viper/Viper.babylon
  26. 1 1
      Samples/Scenes/WCafe/WCafe.babylon
  27. 3 3
      Samples/Scenes/WorldMonger/babylon.js
  28. 14 15
      Samples/Scenes/WorldMonger/elevationControl.js
  29. 2 2
      Samples/babylon.js
  30. 6 1
      Samples/index.html
  31. 4 1
      Samples/index.js
  32. 0 13
      babylon.1.2.1.js
  33. 13 0
      babylon.1.3.0.js
  34. 1 0
      readme.md
  35. 47 41
      what's new.txt

+ 41 - 0
Babylon/Culling/Octrees/babylon.octree.js

@@ -0,0 +1,41 @@
+var BABYLON = BABYLON || {};
+
+(function () {
+    BABYLON.Octree = function () {
+        this.blocks = [];
+        this._selection = new BABYLON.Tools.SmartArray(256);
+    };
+    
+    // Methods
+    BABYLON.Octree.prototype.update = function (worldMin, worldMax, meshes) {
+        this.blocks = [];
+        var blockSize = new BABYLON.Vector3((worldMax.x - worldMin.x) / 2, (worldMax.y - worldMin.y) / 2, (worldMax.z - worldMin.z) / 2);
+
+        // Segmenting space
+        for (var x = 0; x < 2; x++) {
+            for (var y = 0; y < 2; y++) {
+                for (var z = 0; z < 2; z++) {
+                    var localMin = worldMin.add(blockSize.multiplyByFloats(x, y, z));
+                    var localMax = worldMin.add(blockSize.multiplyByFloats(x + 1, y + 1, z + 1));
+
+                    var block = new BABYLON.OctreeBlock(x, y, z, localMin, localMax);
+                    block.addEntries(meshes);
+                    this.blocks.push(block);
+                }
+            }
+        }
+    };
+
+    BABYLON.Octree.prototype.select = function (frustumPlanes) {
+        this._selection.reset();
+
+        for (var index = 0; index < this.blocks.length; index++) {
+            var block = this.blocks[index];
+            if (block.intersects(frustumPlanes)) {                
+                this._selection.push(block);
+            }
+        }
+
+        return this._selection;
+    };
+})();

+ 65 - 0
Babylon/Culling/Octrees/babylon.octreeBlock.js

@@ -0,0 +1,65 @@
+var BABYLON = BABYLON || {};
+
+(function () {
+    BABYLON.OctreeBlock = function (x, y, z, minPoint, maxPoint) {
+        this.subMeshes = [];
+        this.meshes = [];
+        this.x = x;
+        this.y = y;
+        this.z = z;
+
+        this._minPoint = minPoint;
+        this._maxPoint = maxPoint;
+        
+        this._boundingVectors = [];
+
+        this._boundingVectors.push(minPoint.clone());
+        this._boundingVectors.push(maxPoint.clone());
+
+        this._boundingVectors.push(minPoint.clone());
+        this._boundingVectors[2].x = maxPoint.x;
+
+        this._boundingVectors.push(minPoint.clone());
+        this._boundingVectors[3].y = maxPoint.y;
+
+        this._boundingVectors.push(minPoint.clone());
+        this._boundingVectors[4].z = maxPoint.z;
+
+        this._boundingVectors.push(maxPoint.clone());
+        this._boundingVectors[5].z = minPoint.z;
+
+        this._boundingVectors.push(maxPoint.clone());
+        this._boundingVectors[6].x = minPoint.x;
+
+        this._boundingVectors.push(maxPoint.clone());
+        this._boundingVectors[7].y = minPoint.y;
+    };
+
+    // Methods
+    BABYLON.OctreeBlock.prototype.addEntries = function (meshes) {
+        for (var index = 0; index < meshes.length; index++) {
+            var mesh = meshes[index];
+
+            if (mesh.getBoundingInfo().boundingBox.intersectsMinMax(this._minPoint, this._maxPoint)) {
+                var localMeshIndex = this.meshes.length;
+                this.meshes.push(mesh);
+
+                this.subMeshes[localMeshIndex] = [];
+                for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
+                    var subMesh = mesh.subMeshes[subIndex];
+                    if (mesh.subMeshes.length === 1 || subMesh.getBoundingInfo().boundingBox.intersectsMinMax(this._minPoint, this._maxPoint)) {
+                        this.subMeshes[localMeshIndex].push(subMesh);
+                    }
+                }
+            }
+        }
+    };
+
+    BABYLON.OctreeBlock.prototype.intersects = function(frustumPlanes) {
+        if (BABYLON.BoundingBox.IsInFrustrum(this._boundingVectors, frustumPlanes)) {
+            return true;
+        }
+
+        return false;
+    };
+})();

+ 43 - 25
Babylon/Culling/babylon.boundingBox.js

@@ -1,17 +1,17 @@
 var BABYLON = BABYLON || {};
 
 (function () {
-    BABYLON.BoundingBox = function (vertices, stride, start, count) {
+    BABYLON.BoundingBox = function (positions, start, count) {
         this.minimum = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
         this.maximum = new BABYLON.Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
 
-        for (var index = start; index < start + count; index += stride) {
-            var current = new BABYLON.Vector3(vertices[index], vertices[index + 1], vertices[index + 2]);
+        for (var index = start; index < start + count; index++) {
+            var current = new BABYLON.Vector3(positions[index * 3], positions[index * 3 + 1], positions[index * 3 + 2]);
 
             this.minimum = BABYLON.Vector3.Minimize(current, this.minimum);
             this.maximum = BABYLON.Vector3.Maximize(current, this.maximum);
         }
-        
+
         // Bounding vectors
         this.vectors = [];
 
@@ -35,12 +35,12 @@
 
         this.vectors.push(this.maximum.clone());
         this.vectors[7].y = this.minimum.y;
-        
+
         // OBB
         this.center = this.maximum.add(this.minimum).scale(0.5);
         this.extends = this.maximum.subtract(this.minimum).scale(0.5);
         this.directions = [BABYLON.Vector3.Zero(), BABYLON.Vector3.Zero(), BABYLON.Vector3.Zero()];
-        
+
         // World
         this.vectorsWorld = [];
         for (var index = 0; index < this.vectors.length; index++) {
@@ -49,7 +49,7 @@
         this.minimumWorld = BABYLON.Vector3.Zero();
         this.maximumWorld = BABYLON.Vector3.Zero();
     };
-    
+
     // Methods
     BABYLON.BoundingBox.prototype._update = function (world) {
         BABYLON.Vector3.FromFloatsToRef(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE, this.minimumWorld);
@@ -77,29 +77,16 @@
         // OBB
         this.maximumWorld.addToRef(this.minimumWorld, this.center);
         this.center.scaleInPlace(0.5);
-        
+
         BABYLON.Vector3.FromArrayToRef(world.m, 0, this.directions[0]);
         BABYLON.Vector3.FromArrayToRef(world.m, 4, this.directions[1]);
         BABYLON.Vector3.FromArrayToRef(world.m, 8, this.directions[2]);
     };
 
     BABYLON.BoundingBox.prototype.isInFrustrum = function (frustumPlanes) {
-        for (var p = 0; p < 6; p++) {
-            var inCount = 8;
-
-            for (var i = 0; i < 8; i++) {
-                if (frustumPlanes[p].dotCoordinate(this.vectorsWorld[i]) < 0) {
-                    --inCount;
-                } else {
-                    break;
-                }
-            }
-            if (inCount == 0)
-                return false;
-        }
-        return true;
+        return BABYLON.BoundingBox.IsInFrustrum(this.vectorsWorld, frustumPlanes);
     };
-    
+
     BABYLON.BoundingBox.prototype.intersectsPoint = function (point) {
         if (this.maximumWorld.x < point.x || this.minimumWorld.x > point.x)
             return false;
@@ -112,13 +99,26 @@
 
         return true;
     };
-    
-    BABYLON.BoundingBox.prototype.intersectsSphere = function (sphere) {    
+
+    BABYLON.BoundingBox.prototype.intersectsSphere = function (sphere) {
         var vector = BABYLON.Vector3.Clamp(sphere.centerWorld, this.minimumWorld, this.maximumWorld);
         var num = BABYLON.Vector3.DistanceSquared(sphere.centerWorld, vector);
         return (num <= (sphere.radiusWorld * sphere.radiusWorld));
     };
 
+    BABYLON.BoundingBox.prototype.intersectsMinMax = function (min, max) {
+        if (this.maximumWorld.x < min.x || this.minimumWorld.x > max.x)
+            return false;
+
+        if (this.maximumWorld.y < min.y || this.minimumWorld.y > max.y)
+            return false;
+
+        if (this.maximumWorld.z < min.z || this.minimumWorld.z > max.z)
+            return false;
+
+        return true;
+    };
+
     // Statics
     BABYLON.BoundingBox.intersects = function (box0, box1) {
         if (box0.maximumWorld.x < box1.minimumWorld.x || box0.minimumWorld.x > box1.maximumWorld.x)
@@ -132,4 +132,22 @@
 
         return true;
     };
+    
+    BABYLON.BoundingBox.IsInFrustrum = function (boundingVectors, frustumPlanes) {
+        for (var p = 0; p < 6; p++) {
+            var inCount = 8;
+
+            for (var i = 0; i < 8; i++) {
+                if (frustumPlanes[p].dotCoordinate(boundingVectors[i]) < 0) {
+                    --inCount;
+                } else {
+                    break;
+                }
+            }
+            if (inCount == 0)
+                return false;
+        }
+        return true;
+    };
+
 })();

+ 3 - 3
Babylon/Culling/babylon.boundingInfo.js

@@ -1,9 +1,9 @@
 var BABYLON = BABYLON || {};
 
 (function () {
-    BABYLON.BoundingInfo = function (vertices, stride, verticesStart, verticesCount) {
-        this.boundingBox = new BABYLON.BoundingBox(vertices, stride, verticesStart, verticesCount);
-        this.boundingSphere = new BABYLON.BoundingSphere(vertices, stride, verticesStart, verticesCount);
+    BABYLON.BoundingInfo = function (positions, verticesStart, verticesCount) {
+        this.boundingBox = new BABYLON.BoundingBox(positions, verticesStart, verticesCount);
+        this.boundingSphere = new BABYLON.BoundingSphere(positions, verticesStart, verticesCount);
     };
 
     // Methods

+ 3 - 3
Babylon/Culling/babylon.boundingSphere.js

@@ -1,12 +1,12 @@
 var BABYLON = BABYLON || {};
 
 (function () {
-    BABYLON.BoundingSphere = function (vertices, stride, start, count) {
+    BABYLON.BoundingSphere = function (positions, start, count) {
         var minimum = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
         var maximum = new BABYLON.Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
 
-        for (var index = start; index < start + count; index += stride) {
-            var current = new BABYLON.Vector3(vertices[index], vertices[index + 1], vertices[index + 2]);
+        for (var index = start; index < start + count; index++) {
+            var current = new BABYLON.Vector3(positions[index * 3], positions[index * 3 + 1], positions[index * 3 + 2]);
 
             minimum = BABYLON.Vector3.Minimize(current, minimum);
             maximum = BABYLON.Vector3.Maximize(current, maximum);

+ 5 - 0
Babylon/Materials/babylon.effect.js

@@ -10,6 +10,7 @@
         this._samplers = samplers;
         this._isReady = false;
         this._compilationError = "";
+        this._attributesNames = attributesNames;
 
         var that = this;
 
@@ -50,6 +51,10 @@
         return this._program;
     };
 
+    BABYLON.Effect.prototype.getAttributesNames = function () {
+        return this._attributesNames;
+    };
+
     BABYLON.Effect.prototype.getAttribute = function (index) {
         return this._attributes[index];
     };

+ 9 - 14
Babylon/Materials/babylon.standardMaterial.js

@@ -109,7 +109,7 @@
         if (this._scene.getEngine().getCaps().standardDerivatives && this.bumpTexture) {
             if (!this.bumpTexture.isReady()) {
                 return false;
-            } else {                
+            } else {
                 defines.push("#define BUMP");
             }
         }
@@ -169,20 +169,15 @@
 
         var attribs = ["position", "normal"];
         if (mesh) {
-            switch (mesh._uvCount) {
-                case 1:
-                    attribs.push("uv");
-                    defines.push("#define UV1");
-                    break;
-                case 2:
-                    attribs.push("uv");
-                    attribs.push("uv2");
-                    defines.push("#define UV1");
-                    defines.push("#define UV2");
-                    break;
+            if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)) {
+                attribs.push("uv");
+                defines.push("#define UV1");
+            }
+            if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UV2Kind)) {
+                attribs.push("uv2");
+                defines.push("#define UV2");
             }
-            
-            if (mesh._hasVertexColor){
+            if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.ColorKind)) {
                 attribs.push("color");
                 defines.push("#define VERTEXCOLOR");
             }

+ 188 - 155
Babylon/Mesh/babylon.mesh.js

@@ -1,18 +1,10 @@
 var BABYLON = BABYLON || {};
 
 (function () {
-    BABYLON.Mesh = function (name, vertexDeclaration, scene) {
+    BABYLON.Mesh = function (name, scene) {
         this.name = name;
         this.id = name;
         this._scene = scene;
-        this._vertexDeclaration = vertexDeclaration;
-
-        this._vertexStrideSize = 0;
-        for (var index = 0; index < vertexDeclaration.length; index++) {
-            this._vertexStrideSize += vertexDeclaration[index];
-        }
-
-        this._vertexStrideSize *= 4; // sizeof(float)
 
         this._totalVertices = 0;
         this._worldMatrix = BABYLON.Matrix.Identity();
@@ -27,6 +19,8 @@
         this._indices = [];
         this.subMeshes = [];
 
+        this._renderId = 0;
+
         // Animations
         this.animations = [];
 
@@ -46,7 +40,7 @@
         this._localScalingRotation = BABYLON.Matrix.Zero();
         this._localWorld = BABYLON.Matrix.Zero();
         this._worldMatrix = BABYLON.Matrix.Zero();
-        
+
         this._collisionsTransformMatrix = BABYLON.Matrix.Zero();
         this._collisionsScalingMatrix = BABYLON.Matrix.Zero();
     };
@@ -70,7 +64,8 @@
     BABYLON.Mesh.prototype.checkCollisions = false;
     BABYLON.Mesh.prototype.receiveShadows = false;
 
-    BABYLON.Mesh.prototype.onDispose = false;
+    BABYLON.Mesh.prototype._isDisposed = false;
+    BABYLON.Mesh.prototype.onDispose = null;
 
     // Properties
 
@@ -90,8 +85,12 @@
         return this._totalVertices;
     };
 
-    BABYLON.Mesh.prototype.getVertices = function () {
-        return this._vertices;
+    BABYLON.Mesh.prototype.getVerticesData = function (kind) {
+        return this._vertexBuffers[kind].getData();
+    };
+
+    BABYLON.Mesh.prototype.isVerticesDataPresent = function (kind) {
+        return this._vertexBuffers[kind] !== undefined;
     };
 
     BABYLON.Mesh.prototype.getTotalIndices = function () {
@@ -106,10 +105,6 @@
         return this._vertexStrideSize;
     };
 
-    BABYLON.Mesh.prototype.getFloatVertexStrideSize = function () {
-        return this._vertexStrideSize / 4;
-    };
-
     BABYLON.Mesh.prototype._needToSynchonizeChildren = function () {
         return this._childrenFlag;
     };
@@ -161,6 +156,9 @@
         return this._animationStarted;
     };
 
+    BABYLON.Mesh.prototype.isDisposed = function () {
+        return this._isDisposed;
+    };
     // Methods
     BABYLON.Mesh.prototype.computeWorldMatrix = function () {
         if (this.isSynchronized()) {
@@ -265,36 +263,31 @@
         }
     };
 
-    BABYLON.Mesh.prototype.setVertices = function (vertices, uvCount, updatable, hasVertexColor) {
-        if (this._vertexBuffer) {
-            this._scene.getEngine()._releaseBuffer(this._vertexBuffer);
+    BABYLON.Mesh.prototype.setVerticesData = function (data, kind, updatable) {
+        if (!this._vertexBuffers) {
+            this._vertexBuffers = {};
         }
 
-        this._uvCount = uvCount;
-        this._hasVertexColor = hasVertexColor;
-
-        if (updatable) {
-            this._vertexBuffer = this._scene.getEngine().createDynamicVertexBuffer(vertices.length * 4);
-            this._scene.getEngine().updateDynamicVertexBuffer(this._vertexBuffer, vertices);
-        } else {
-            this._vertexBuffer = this._scene.getEngine().createVertexBuffer(vertices);
+        if (this._vertexBuffers[kind]) {
+            this._vertexBuffers[kind].dispose();
         }
 
-        this._vertices = vertices;
+        this._vertexBuffers[kind] = new BABYLON.VertexBuffer(this, data, kind, updatable);
 
-        this._totalVertices = vertices.length / this.getFloatVertexStrideSize();
+        if (kind === BABYLON.VertexBuffer.PositionKind) {
+            var stride = this._vertexBuffers[kind].getStrideSize();
+            this._totalVertices = data.length / stride;
 
-        this._boundingInfo = new BABYLON.BoundingInfo(vertices, this.getFloatVertexStrideSize(), 0, vertices.length);
+            this._boundingInfo = new BABYLON.BoundingInfo(data, 0, this._totalVertices);
 
-        this._createGlobalSubMesh();
-        this._positions = null;
+            this._createGlobalSubMesh();
+        }
     };
 
-    BABYLON.Mesh.prototype.updateVertices = function (vertices) {
-        var engine = this._scene.getEngine();
-        engine.updateDynamicVertexBuffer(this._vertexBuffer, vertices);
-        this._vertices = vertices;
-        this._positions = null;
+    BABYLON.Mesh.prototype.updateVerticesData = function (kind, data) {
+        if (this._vertexBuffers[kind]) {
+            this._vertexBuffers[kind].update(data);
+        }
     };
 
     BABYLON.Mesh.prototype.setIndices = function (indices) {
@@ -310,7 +303,7 @@
 
     BABYLON.Mesh.prototype.bindAndDraw = function (subMesh, effect, wireframe) {
         var engine = this._scene.getEngine();
-        
+
         // Wireframe
         var indexToBind = this._indexBuffer;
         var useTriangles = true;
@@ -321,14 +314,14 @@
         }
 
         // VBOs
-        engine.bindBuffers(this._vertexBuffer, indexToBind, this._vertexDeclaration, this._vertexStrideSize, effect);
+        engine.bindMultiBuffers(this._vertexBuffers, indexToBind, effect);
 
         // Draw order
         engine.draw(useTriangles, useTriangles ? subMesh.indexStart : 0, useTriangles ? subMesh.indexCount : subMesh.linesIndexCount);
     };
 
     BABYLON.Mesh.prototype.render = function (subMesh) {
-        if (!this._vertexBuffer || !this._indexBuffer) {
+        if (!this._vertexBuffers || !this._indexBuffer) {
             return;
         }
 
@@ -449,16 +442,19 @@
     };
 
     // Cache
+    BABYLON.Mesh.prototype._resetPointsArrayCache = function () {
+        this._positions = null;
+    };
+
     BABYLON.Mesh.prototype._generatePointsArray = function () {
         if (this._positions)
             return;
 
         this._positions = [];
 
-        var stride = this.getFloatVertexStrideSize();
-
-        for (var index = 0; index < this._vertices.length; index += stride) {
-            this._positions.push(BABYLON.Vector3.FromArray(this._vertices, index));
+        var data = this._vertexBuffers[BABYLON.VertexBuffer.PositionKind].getData();
+        for (var index = 0; index < data.length; index += 3) {
+            this._positions.push(BABYLON.Vector3.FromArray(data, index));
         }
     };
 
@@ -553,23 +549,24 @@
 
     // Clone
     BABYLON.Mesh.prototype.clone = function (name, newParent) {
-        var result = new BABYLON.Mesh(name, this._vertexDeclaration, this._scene);
+        var result = new BABYLON.Mesh(name, this._scene);
 
-        BABYLON.Tools.DeepCopy(this, result, ["name", "material"], ["_uvCount", "_vertices", "_indices", "_totalVertices"]);
+        // Buffers
+        result._vertexBuffers = this._vertexBuffers;
+        this._vertexBuffers.references++;
+
+        result._indexBuffer = this._indexBuffer;
+        this._indexBuffer.references++;
+
+        // Deep copy
+        BABYLON.Tools.DeepCopy(this, result, ["name", "material"], ["_indices", "_totalVertices"]);
 
         // Bounding info
-        result._boundingInfo = new BABYLON.BoundingInfo(result._vertices, result.getFloatVertexStrideSize(), 0, result._vertices.length);
+        result._boundingInfo = new BABYLON.BoundingInfo(this._vertexBuffers[BABYLON.VertexBuffer.PositionKind].getData(), 0, this._totalVertices);
 
         // Material
         result.material = this.material;
 
-        // Buffers
-        result._vertexBuffer = this._vertexBuffer;
-        this._vertexBuffer.references++;
-
-        result._indexBuffer = this._indexBuffer;
-        this._indexBuffer.references++;
-
         // Parent
         if (newParent) {
             result.parent = newParent;
@@ -598,9 +595,9 @@
 
     // Dispose
     BABYLON.Mesh.prototype.dispose = function (doNotRecurse) {
-        if (this._vertexBuffer) {
+        if (this._vertexBuffers) {
             //this._scene.getEngine()._releaseBuffer(this._vertexBuffer);
-            this._vertexBuffer = null;
+            this._vertexBuffers = null;
         }
 
         if (this._indexBuffer) {
@@ -612,26 +609,26 @@
         var index = this._scene.meshes.indexOf(this);
         this._scene.meshes.splice(index, 1);
 
-        if (doNotRecurse) {
-            return;
-        }
-
-        // Particles
-        for (var index = 0; index < this._scene.particleSystems.length; index++) {
-            if (this._scene.particleSystems[index].emitter == this) {
-                this._scene.particleSystems[index].dispose();
-                index--;
+        if (!doNotRecurse) {
+            // Particles
+            for (var index = 0; index < this._scene.particleSystems.length; index++) {
+                if (this._scene.particleSystems[index].emitter == this) {
+                    this._scene.particleSystems[index].dispose();
+                    index--;
+                }
             }
-        }
 
-        // Children
-        var objects = this._scene.meshes.slice(0);
-        for (var index = 0; index < objects.length; index++) {
-            if (objects[index].parent == this) {
-                objects[index].dispose();
+            // Children
+            var objects = this._scene.meshes.slice(0);
+            for (var index = 0; index < objects.length; index++) {
+                if (objects[index].parent == this) {
+                    objects[index].dispose();
+                }
             }
         }
 
+        this._isDisposed = true;
+
         // Callback
         if (this.onDispose) {
             this.onDispose();
@@ -640,9 +637,9 @@
 
     // Statics
     BABYLON.Mesh.CreateBox = function (name, size, scene, updatable) {
-        var box = new BABYLON.Mesh(name, [3, 3, 2], scene);
+        var box = new BABYLON.Mesh(name, scene);
 
-        var normals = [
+        var normalsSource = [
             new BABYLON.Vector3(0, 0, 1),
             new BABYLON.Vector3(0, 0, -1),
             new BABYLON.Vector3(1, 0, 0),
@@ -652,18 +649,20 @@
         ];
 
         var indices = [];
-        var vertices = [];
+        var positions = [];
+        var normals = [];
+        var uvs = [];
 
         // Create each face in turn.
-        for (var index = 0; index < normals.length; index++) {
-            var normal = normals[index];
+        for (var index = 0; index < normalsSource.length; index++) {
+            var normal = normalsSource[index];
 
             // Get two vectors perpendicular to the face normal and to each other.
             var side1 = new BABYLON.Vector3(normal.y, normal.z, normal.x);
             var side2 = BABYLON.Vector3.Cross(normal, side1);
 
             // Six indices (two triangles) per face.
-            var verticesLength = vertices.length / 8;
+            var verticesLength = positions.length / 3;
             indices.push(verticesLength);
             indices.push(verticesLength + 1);
             indices.push(verticesLength + 2);
@@ -674,26 +673,36 @@
 
             // Four vertices per face.
             var vertex = normal.subtract(side1).subtract(side2).scale(size / 2);
-            vertices.push(vertex.x, vertex.y, vertex.z, normal.x, normal.y, normal.z, 1.0, 1.0);
+            positions.push(vertex.x, vertex.y, vertex.z);
+            normals.push(normal.x, normal.y, normal.z);
+            uvs.push(1.0, 1.0);
 
             vertex = normal.subtract(side1).add(side2).scale(size / 2);
-            vertices.push(vertex.x, vertex.y, vertex.z, normal.x, normal.y, normal.z, 0.0, 1.0);
+            positions.push(vertex.x, vertex.y, vertex.z);
+            normals.push(normal.x, normal.y, normal.z);
+            uvs.push(0.0, 1.0);
 
             vertex = normal.add(side1).add(side2).scale(size / 2);
-            vertices.push(vertex.x, vertex.y, vertex.z, normal.x, normal.y, normal.z, 0.0, 0.0);
+            positions.push(vertex.x, vertex.y, vertex.z);
+            normals.push(normal.x, normal.y, normal.z);
+            uvs.push(0.0, 0.0);
 
             vertex = normal.add(side1).subtract(side2).scale(size / 2);
-            vertices.push(vertex.x, vertex.y, vertex.z, normal.x, normal.y, normal.z, 1.0, 0.0);
+            positions.push(vertex.x, vertex.y, vertex.z);
+            normals.push(normal.x, normal.y, normal.z);
+            uvs.push(1.0, 0.0);
         }
 
-        box.setVertices(vertices, 1, updatable);
+        box.setVerticesData(positions, BABYLON.VertexBuffer.PositionKind, updatable);
+        box.setVerticesData(normals, BABYLON.VertexBuffer.NormalKind, updatable);
+        box.setVerticesData(uvs, BABYLON.VertexBuffer.UVKind, updatable);
         box.setIndices(indices);
 
         return box;
     };
 
     BABYLON.Mesh.CreateSphere = function (name, segments, diameter, scene, updatable) {
-        var sphere = new BABYLON.Mesh(name, [3, 3, 2], scene);
+        var sphere = new BABYLON.Mesh(name, scene);
 
         var radius = diameter / 2;
 
@@ -701,7 +710,9 @@
         var totalYRotationSteps = 2 * totalZRotationSteps;
 
         var indices = [];
-        var vertices = [];
+        var positions = [];
+        var normals = [];
+        var uvs = [];
 
         for (var zRotationStep = 0; zRotationStep <= totalZRotationSteps; zRotationStep++) {
             var normalizedZ = zRotationStep / totalZRotationSteps;
@@ -720,11 +731,13 @@
                 var vertex = complete.scale(radius);
                 var normal = BABYLON.Vector3.Normalize(vertex);
 
-                vertices.push(vertex.x, vertex.y, vertex.z, normal.x, normal.y, normal.z, normalizedZ, normalizedY);
+                positions.push(vertex.x, vertex.y, vertex.z);
+                normals.push(normal.x, normal.y, normal.z);
+                uvs.push(normalizedZ, normalizedY);
             }
 
             if (zRotationStep > 0) {
-                var verticesCount = vertices.length / 8;
+                var verticesCount = positions.length / 3;
                 for (var firstIndex = verticesCount - 2 * (totalYRotationSteps + 1) ; (firstIndex + totalYRotationSteps + 2) < verticesCount; firstIndex++) {
                     indices.push((firstIndex));
                     indices.push((firstIndex + 1));
@@ -737,7 +750,9 @@
             }
         }
 
-        sphere.setVertices(vertices, 1, updatable);
+        sphere.setVerticesData(positions, BABYLON.VertexBuffer.PositionKind, updatable);
+        sphere.setVerticesData(normals, BABYLON.VertexBuffer.NormalKind, updatable);
+        sphere.setVerticesData(uvs, BABYLON.VertexBuffer.UVKind, updatable);
         sphere.setIndices(indices);
 
         return sphere;
@@ -747,8 +762,10 @@
     BABYLON.Mesh.CreateCylinder = function (name, height, diameter, tessellation, scene, updatable) {
         var radius = diameter / 2;
         var indices = [];
-        var vertices = [];
-        var cylinder = new BABYLON.Mesh(name, [3, 3, 2], scene);
+        var positions = [];
+        var normals = [];
+        var uvs = [];
+        var cylinder = new BABYLON.Mesh(name, scene);
 
 
         var getCircleVector = function (i) {
@@ -771,7 +788,7 @@
                     i2 = tmp;
                 }
 
-                var vbase = vertices.length / cylinder.getFloatVertexStrideSize();
+                var vbase = positions.length / 3;
                 indices.push(vbase);
                 indices.push(vbase + i1);
                 indices.push(vbase + i2);
@@ -793,11 +810,9 @@
                 var position = circleVector.scale(radius).add(normal.scale(height));
                 var textureCoordinate = new BABYLON.Vector2(circleVector.x * textureScale.x + 0.5, circleVector.z * textureScale.y + 0.5);
 
-                vertices.push(
-                    position.x, position.y, position.z,
-                    normal.x, normal.y, normal.z,
-                    textureCoordinate.x, textureCoordinate.y
-                );
+                positions.push(position.x, position.y, position.z);
+                normals.push(normal.x, normal.y, normal.z);
+                uvs.push(textureCoordinate.x, textureCoordinate.y);
             }
         };
 
@@ -808,26 +823,22 @@
         var stride = tessellation + 1;
 
         // Create a ring of triangles around the outside of the cylinder.
-        for (var i = 0; i <= tessellation; i++)
-        {
+        for (var i = 0; i <= tessellation; i++) {
             var normal = getCircleVector(i);
             var sideOffset = normal.scale(radius);
             var textureCoordinate = new BABYLON.Vector2(i / tessellation, 0);
 
             var position = sideOffset.add(topOffset);
-            vertices.push(
-                            position.x, position.y, position.z,
-                            normal.x, normal.y, normal.z,
-                            textureCoordinate.x, textureCoordinate.y
-                        );
+            positions.push(position.x, position.y, position.z);
+            normals.push(normal.x, normal.y, normal.z);
+            uvs.push(textureCoordinate.x, textureCoordinate.y);
+
 
             position = sideOffset.subtract(topOffset);
             textureCoordinate.y += 1;
-            vertices.push(
-                            position.x, position.y, position.z,
-                            normal.x, normal.y, normal.z,
-                            textureCoordinate.x, textureCoordinate.y
-                        );
+            positions.push(position.x, position.y, position.z);
+            normals.push(normal.x, normal.y, normal.z);
+            uvs.push(textureCoordinate.x, textureCoordinate.y);
 
             indices.push(i * 2);
             indices.push((i * 2 + 2) % (stride * 2));
@@ -841,8 +852,10 @@
         // Create flat triangle fan caps to seal the top and bottom.
         createCylinderCap(true);
         createCylinderCap(false);
-        
-        cylinder.setVertices(vertices, 1, updatable);
+
+        cylinder.setVerticesData(positions, BABYLON.VertexBuffer.PositionKind, updatable);
+        cylinder.setVerticesData(normals, BABYLON.VertexBuffer.NormalKind, updatable);
+        cylinder.setVerticesData(uvs, BABYLON.VertexBuffer.UVKind, updatable);
         cylinder.setIndices(indices);
 
         return cylinder;
@@ -850,10 +863,12 @@
 
     // Torus  (Code from SharpDX.org)
     BABYLON.Mesh.CreateTorus = function (name, diameter, thickness, tessellation, scene, updatable) {
-        var torus = new BABYLON.Mesh(name, [3, 3, 2], scene);
+        var torus = new BABYLON.Mesh(name, scene);
 
         var indices = [];
-        var vertices = [];
+        var positions = [];
+        var normals = [];
+        var uvs = [];
 
         var stride = tessellation + 1;
 
@@ -879,11 +894,9 @@
                 position = BABYLON.Vector3.TransformCoordinates(position, transform);
                 normal = BABYLON.Vector3.TransformNormal(normal, transform);
 
-                vertices.push(
-                    position.x, position.y, position.z,
-                    normal.x, normal.y, normal.z,
-                    textureCoordinate.x, textureCoordinate.y
-                );
+                positions.push(position.x, position.y, position.z);
+                normals.push(normal.x, normal.y, normal.z);
+                uvs.push(textureCoordinate.x, textureCoordinate.y);
 
                 // And create indices for two triangles.
                 var nextI = (i + 1) % stride;
@@ -893,14 +906,15 @@
                 indices.push(i * stride + nextJ);
                 indices.push(nextI * stride + j);
 
-
                 indices.push(i * stride + nextJ);
                 indices.push(nextI * stride + nextJ);
                 indices.push(nextI * stride + j);
             }
         }
 
-        torus.setVertices(vertices, 1, updatable);
+        torus.setVerticesData(positions, BABYLON.VertexBuffer.PositionKind, updatable);
+        torus.setVerticesData(normals, BABYLON.VertexBuffer.NormalKind, updatable);
+        torus.setVerticesData(uvs, BABYLON.VertexBuffer.UVKind, updatable);
         torus.setIndices(indices);
 
         return torus;
@@ -909,17 +923,30 @@
 
     // Plane
     BABYLON.Mesh.CreatePlane = function (name, size, scene, updatable) {
-        var plane = new BABYLON.Mesh(name, [3, 3, 2], scene);
+        var plane = new BABYLON.Mesh(name, scene);
 
         var indices = [];
-        var vertices = [];
+        var positions = [];
+        var normals = [];
+        var uvs = [];
 
         // Vertices
         var halfSize = size / 2.0;
-        vertices.push(-halfSize, -halfSize, 0, 0, 0, -1.0, 0.0, 0.0);
-        vertices.push(halfSize, -halfSize, 0, 0, 0, -1.0, 1.0, 0.0);
-        vertices.push(halfSize, halfSize, 0, 0, 0, -1.0, 1.0, 1.0);
-        vertices.push(-halfSize, halfSize, 0, 0, 0, -1.0, 0.0, 1.0);
+        positions.push(-halfSize, -halfSize, 0);
+        normals.push(0, 0, -1.0);
+        uvs.push(0.0, 0.0);
+
+        positions.push(halfSize, -halfSize, 0);
+        normals.push(0, 0, -1.0);
+        uvs.push(1.0, 0.0);
+        
+        positions.push(halfSize, halfSize, 0);
+        normals.push(0, 0, -1.0);
+        uvs.push(1.0, 1.0);
+        
+        positions.push(-halfSize, halfSize, 0);
+        normals.push(0, 0, -1.0);
+        uvs.push(0.0, 1.0);
 
         // Indices
         indices.push(0);
@@ -930,17 +957,21 @@
         indices.push(2);
         indices.push(3);
 
-        plane.setVertices(vertices, 1, updatable);
+        plane.setVerticesData(positions, BABYLON.VertexBuffer.PositionKind, updatable);
+        plane.setVerticesData(normals, BABYLON.VertexBuffer.NormalKind, updatable);
+        plane.setVerticesData(uvs, BABYLON.VertexBuffer.UVKind, updatable);
         plane.setIndices(indices);
 
         return plane;
     };
 
     BABYLON.Mesh.CreateGround = function (name, width, height, subdivisions, scene, updatable) {
-        var ground = new BABYLON.Mesh(name, [3, 3, 2], scene);
+        var ground = new BABYLON.Mesh(name, scene);
 
         var indices = [];
-        var vertices = [];
+        var positions = [];
+        var normals = [];
+        var uvs = [];
         var row, col;
 
         for (row = 0; row <= subdivisions; row++) {
@@ -948,9 +979,9 @@
                 var position = new BABYLON.Vector3((col * width) / subdivisions - (width / 2.0), 0, ((subdivisions - row) * height) / subdivisions - (height / 2.0));
                 var normal = new BABYLON.Vector3(0, 1.0, 0);
 
-                vertices.push(position.x, position.y, position.z,
-                    normal.x, normal.y, normal.z,
-                    col / subdivisions, 1.0 - row / subdivisions);
+                positions.push(position.x, position.y, position.z);
+                normals.push(normal.x, normal.y, normal.z);
+                uvs.push(col / subdivisions, 1.0 - row / subdivisions);
             }
         }
 
@@ -966,19 +997,23 @@
             }
         }
 
-        ground.setVertices(vertices, 1, updatable);
+        ground.setVerticesData(positions, BABYLON.VertexBuffer.PositionKind, updatable);
+        ground.setVerticesData(normals, BABYLON.VertexBuffer.NormalKind, updatable);
+        ground.setVerticesData(uvs, BABYLON.VertexBuffer.UVKind, updatable);
         ground.setIndices(indices);
 
         return ground;
     };
 
     BABYLON.Mesh.CreateGroundFromHeightMap = function (name, url, width, height, subdivisions, minHeight, maxHeight, scene, updatable) {
-        var ground = new BABYLON.Mesh(name, [3, 3, 2], scene);
+        var ground = new BABYLON.Mesh(name, scene);
 
         var img = new Image();
         img.onload = function () {
             var indices = [];
-            var vertices = [];
+            var positions = [];
+            var normals = [];
+            var uvs = [];
             var row, col;
 
             // Getting height map data
@@ -1012,9 +1047,9 @@
                     position.y = minHeight + (maxHeight - minHeight) * gradient;
 
                     // Add  vertex
-                    vertices.push(position.x, position.y, position.z,
-                        0, 0, 0,
-                        col / subdivisions, 1.0 - row / subdivisions);
+                    positions.push(position.x, position.y, position.z);
+                    normals.push(0, 0, 0);
+                    uvs.push(col / subdivisions, 1.0 - row / subdivisions);
                 }
             }
 
@@ -1032,10 +1067,12 @@
             }
 
             // Normals
-            BABYLON.Mesh.ComputeNormal(vertices, indices, ground.getFloatVertexStrideSize());
+            BABYLON.Mesh.ComputeNormal(positions, normals, indices);
 
             // Transfer
-            ground.setVertices(vertices, 1, updatable);
+            ground.setVerticesData(positions, BABYLON.VertexBuffer.PositionKind, updatable);
+            ground.setVerticesData(normals, BABYLON.VertexBuffer.NormalKind, updatable);
+            ground.setVerticesData(uvs, BABYLON.VertexBuffer.UVKind, updatable);
             ground.setIndices(indices);
 
             ground._isReady = true;
@@ -1049,18 +1086,14 @@
     };
 
     // Tools
-    BABYLON.Mesh.ComputeNormal = function (vertices, indices, stride, normalOffset) {
-        var positions = [];
+    BABYLON.Mesh.ComputeNormal = function (positions, normals, indices) {
+        var positionVectors = [];
         var facesOfVertices = [];
         var index;
 
-        if (normalOffset === undefined) {
-            normalOffset = 3;
-        }
-
-        for (index = 0; index < vertices.length; index += stride) {
-            var position = new BABYLON.Vector3(vertices[index], vertices[index + 1], vertices[index + 2]);
-            positions.push(position);
+        for (index = 0; index < positions.length; index += 3) {
+            var vector3 = new BABYLON.Vector3(positions[index], positions[index + 1], positions[index + 2]);
+            positionVectors.push(vector3);
             facesOfVertices.push([]);
         }
         // Compute normals
@@ -1070,9 +1103,9 @@
             var i2 = indices[index * 3 + 1];
             var i3 = indices[index * 3 + 2];
 
-            var p1 = positions[i1];
-            var p2 = positions[i2];
-            var p3 = positions[i3];
+            var p1 = positionVectors[i1];
+            var p2 = positionVectors[i2];
+            var p3 = positionVectors[i3];
 
             var p1p2 = p1.subtract(p2);
             var p3p2 = p3.subtract(p2);
@@ -1083,7 +1116,7 @@
             facesOfVertices[i3].push(index);
         }
 
-        for (index = 0; index < positions.length; index++) {
+        for (index = 0; index < positionVectors.length; index++) {
             var faces = facesOfVertices[index];
 
             var normal = BABYLON.Vector3.Zero();
@@ -1093,9 +1126,9 @@
 
             normal = BABYLON.Vector3.Normalize(normal.scale(1.0 / faces.length));
 
-            vertices[index * stride + normalOffset] = normal.x;
-            vertices[index * stride + normalOffset + 1] = normal.y;
-            vertices[index * stride + normalOffset + 2] = normal.z;
+            normals[index * 3] = normal.x;
+            normals[index * 3 + 1] = normal.y;
+            normals[index * 3 + 2] = normal.z;
         }
     };
 })();

+ 2 - 3
Babylon/Mesh/babylon.subMesh.js

@@ -9,9 +9,8 @@
         this.verticesCount = verticesCount;
         this.indexStart = indexStart;
         this.indexCount = indexCount;
-
-        var stride = this._mesh.getFloatVertexStrideSize();
-        this._boundingInfo = new BABYLON.BoundingInfo(this._mesh.getVertices(), stride, verticesStart * stride, verticesCount * stride);
+        
+        this._boundingInfo = new BABYLON.BoundingInfo(this._mesh.getVerticesData(BABYLON.VertexBuffer.PositionKind), verticesStart, verticesCount);
     };
     
     //Properties

+ 67 - 0
Babylon/Mesh/babylon.vertexBuffer.js

@@ -0,0 +1,67 @@
+var BABYLON = BABYLON || {};
+
+(function () {
+    BABYLON.VertexBuffer = function (mesh, data, kind, updatable) {
+        this._mesh = mesh;
+        this._engine = mesh.getScene().getEngine();
+        
+        if (updatable) {
+            this._buffer = this._engine.createDynamicVertexBuffer(data.length * 4);
+            this._engine.updateDynamicVertexBuffer(this._buffer, data);
+        } else {
+            this._buffer = this._engine.createVertexBuffer(data);
+        }
+
+        this._data = data;
+        this._kind = kind;
+
+        switch (kind) {
+            case BABYLON.VertexBuffer.PositionKind:
+                this._strideSize = 3;
+                this._mesh._resetPointsArrayCache();
+                break;
+            case BABYLON.VertexBuffer.NormalKind:
+                this._strideSize = 3;
+                break;
+            case BABYLON.VertexBuffer.UVKind:
+                this._strideSize = 2;
+                break;
+            case BABYLON.VertexBuffer.UV2Kind:
+                this._strideSize = 2;
+                break;
+            case BABYLON.VertexBuffer.ColorKind:
+                this._strideSize = 4;
+                break;
+        }
+    };
+    
+    // Properties
+    BABYLON.VertexBuffer.prototype.getData = function() {
+        return this._data;
+    };
+    
+    BABYLON.VertexBuffer.prototype.getStrideSize = function () {
+        return this._strideSize;
+    };
+    
+    // Methods
+    BABYLON.VertexBuffer.prototype.update = function (data) {
+        this._engine.updateDynamicVertexBuffer(this._buffer, data);
+        this._data = data;
+        
+        if (this._kind === BABYLON.VertexBuffer.PositionKind) {
+            this._mesh._resetPointsArrayCache();
+        }
+    };
+
+    BABYLON.VertexBuffer.prototype.dispose = function() {
+        this._engine._releaseBuffer(this._buffer);
+    }; 
+        
+    // Enums
+    BABYLON.VertexBuffer.PositionKind   = "position";
+    BABYLON.VertexBuffer.NormalKind     = "normal";
+    BABYLON.VertexBuffer.UVKind         = "uv";
+    BABYLON.VertexBuffer.UV2Kind        = "uv2";
+    BABYLON.VertexBuffer.ColorKind      = "color";
+})();

+ 4 - 0
Babylon/Tools/babylon.math.js

@@ -576,6 +576,10 @@
         result.y = this.y * otherVector.y;
         result.z = this.z * otherVector.z;
     };
+    
+    BABYLON.Vector3.prototype.multiplyByFloats = function (x, y, z) {
+        return new BABYLON.Vector3(this.x * x, this.y * y, this.z * z);
+    };
 
     BABYLON.Vector3.prototype.divide = function (otherVector) {
         return new BABYLON.Vector3(this.x / otherVector.x, this.y / otherVector.y, this.z / otherVector.z);

+ 17 - 21
Babylon/Tools/babylon.sceneLoader.js

@@ -249,25 +249,7 @@
     };
 
     var parseMesh = function (parsedMesh, scene) {
-        var declaration =  [3, 3];
-        
-        // Texture coordinates
-        switch (parsedMesh.uvCount) {
-            case 1:
-                declaration.push(2);
-                break;
-            case 2:
-                declaration.push(2);
-                declaration.push(2);
-                break;
-        }
-
-        // Vertex color
-        if (parsedMesh.hasVertexColor) {
-            declaration.push(3);
-        }
-
-        var mesh = new BABYLON.Mesh(parsedMesh.name, declaration, scene);
+        var mesh = new BABYLON.Mesh(parsedMesh.name, scene);
         mesh.id = parsedMesh.id;
 
         mesh.position = BABYLON.Vector3.FromArray(parsedMesh.position);
@@ -287,8 +269,22 @@
 
         mesh.checkCollisions = parsedMesh.checkCollisions;
 
-        if (parsedMesh.vertices && parsedMesh.indices) {
-            mesh.setVertices(parsedMesh.vertices, parsedMesh.uvCount, false, parsedMesh.hasVertexColor);
+        if (parsedMesh.positions && parsedMesh.normals && parsedMesh.indices) {
+            mesh.setVerticesData(parsedMesh.positions, BABYLON.VertexBuffer.PositionKind, false);
+            mesh.setVerticesData(parsedMesh.normals, BABYLON.VertexBuffer.NormalKind, false);
+            
+            if (parsedMesh.uvs) {
+                mesh.setVerticesData(parsedMesh.uvs, BABYLON.VertexBuffer.UVKind, false);
+            }
+            
+            if (parsedMesh.uvs2) {
+                mesh.setVerticesData(parsedMesh.uvs2, BABYLON.VertexBuffer.UV2Kind, false);
+            }
+            
+            if (parsedMesh.colors) {
+                mesh.setVerticesData(parsedMesh.colors, BABYLON.VertexBuffer.ColorKind, false);
+            }
+
             mesh.setIndices(parsedMesh.indices);
         }
 

+ 18 - 0
Babylon/Tools/babylon.tools.js

@@ -34,6 +34,24 @@
         }
     };
     
+    BABYLON.Tools.SmartArray.prototype.concatWithNoDuplicate = function (array) {
+        if (array.length === 0) {
+            return;
+        }
+        if (this.length + array.length > this.data.length) {
+            this.data.length = (this.length + array.length) * 2;
+        }
+
+        for (var index = 0; index < array.length; index++) {
+            var item = (array.data || array)[index];
+            var pos = this.data.indexOf(item);
+
+            if (pos === -1 ||pos >= this.length) {
+                this.data[this.length++] = item;
+            }
+        }
+    };
+    
     BABYLON.Tools.SmartArray.prototype.indexOf = function (value) {
         var position = this.data.indexOf(value);
         

+ 24 - 26
Babylon/babylon.engine.js

@@ -44,10 +44,6 @@
         // Cache
         this._loadedTexturesCache = [];
         this._activeTexturesCache = [];
-        this._buffersCache = {
-            vertexBuffer: null,
-            indexBuffer: null
-        };
         this._currentEffect = null;
         this._currentState = {
             culling: null
@@ -252,7 +248,6 @@
         this._gl.bindBuffer(this._gl.ARRAY_BUFFER, vbo);
         this._gl.bufferData(this._gl.ARRAY_BUFFER, new Float32Array(vertices), this._gl.STATIC_DRAW);
         this._gl.bindBuffer(this._gl.ARRAY_BUFFER, null);
-        this._buffersCache.vertexBuffer = null;
         vbo.references = 1;
         return vbo;
     };
@@ -262,7 +257,6 @@
         this._gl.bindBuffer(this._gl.ARRAY_BUFFER, vbo);
         this._gl.bufferData(this._gl.ARRAY_BUFFER, capacity, this._gl.DYNAMIC_DRAW);
         this._gl.bindBuffer(this._gl.ARRAY_BUFFER, null);
-        this._buffersCache.vertexBuffer = null;
         vbo.references = 1;
         return vbo;
     };
@@ -278,32 +272,42 @@
         this._gl.bindBuffer(this._gl.ELEMENT_ARRAY_BUFFER, vbo);
         this._gl.bufferData(this._gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), this._gl.STATIC_DRAW);
         this._gl.bindBuffer(this._gl.ELEMENT_ARRAY_BUFFER, null);
-        this._buffersCache.indexBuffer = null;
         vbo.references = 1;
         vbo.is32Bits = is32Bits;
         return vbo;
     };
 
     BABYLON.Engine.prototype.bindBuffers = function (vertexBuffer, indexBuffer, vertexDeclaration, vertexStrideSize, effect) {
-        if (this._buffersCache.vertexBuffer != vertexBuffer) {
-            this._gl.bindBuffer(this._gl.ARRAY_BUFFER, vertexBuffer);
-            this._buffersCache.vertexBuffer = vertexBuffer;
+        this._gl.bindBuffer(this._gl.ARRAY_BUFFER, vertexBuffer);
 
-            var offset = 0;
-            for (var index = 0; index < vertexDeclaration.length; index++) {
-                var order = effect.getAttribute(index);
+        var offset = 0;
+        for (var index = 0; index < vertexDeclaration.length; index++) {
+            var order = effect.getAttribute(index);
 
-                if (order >= 0) {
-                    this._gl.vertexAttribPointer(order, vertexDeclaration[index], this._gl.FLOAT, false, vertexStrideSize, offset);
-                }
-                offset += vertexDeclaration[index] * 4;
+            if (order >= 0) {
+                this._gl.vertexAttribPointer(order, vertexDeclaration[index], this._gl.FLOAT, false, vertexStrideSize, offset);
             }
+            offset += vertexDeclaration[index] * 4;
         }
 
-        if (this._buffersCache.indexBuffer != indexBuffer) {
-            this._gl.bindBuffer(this._gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
-            this._buffersCache.indexBuffer = indexBuffer;
+        this._gl.bindBuffer(this._gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+    };
+    
+    BABYLON.Engine.prototype.bindMultiBuffers = function (vertexBuffers, indexBuffer, effect) {
+        var attributes = effect.getAttributesNames();
+        
+        for (var index = 0; index < attributes.length; index++) {
+            var order = effect.getAttribute(index);
+
+            if (order >= 0) {
+                var vertexBuffer = vertexBuffers[attributes[index]];
+                var stride = vertexBuffer.getStrideSize();
+                this._gl.bindBuffer(this._gl.ARRAY_BUFFER, vertexBuffer._buffer);
+                this._gl.vertexAttribPointer(order, stride, this._gl.FLOAT, false, stride * 4, 0);
+            }
         }
+
+        this._gl.bindBuffer(this._gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
     };
 
     BABYLON.Engine.prototype._releaseBuffer = function (buffer) {
@@ -387,8 +391,6 @@
         if (!effect || !effect.getAttributesCount() || this._currentEffect === effect) {
             return;
         }
-        this._buffersCache.vertexBuffer = null;
-
         // Use program
         this._gl.useProgram(effect.getProgram());
 
@@ -533,10 +535,6 @@
         this._currentState = {
             culling: null
         };
-        this._buffersCache = {
-            vertexBuffer: null,
-            indexBuffer: null
-        };
     };
 
     var getExponantOfTwo = function (value, max) {

+ 132 - 43
Babylon/babylon.scene.js

@@ -17,13 +17,15 @@
         this._renderTargetsDuration = 0;
         this._renderDuration = 0;
 
+        this._renderId = 0;
+
         this._toBeDisposed = new BABYLON.Tools.SmartArray(256);
 
         this._onReadyCallbacks = [];
         this._pendingData = [];
 
         this._onBeforeRenderCallbacks = [];
-        
+
         // Fog
         this.fogMode = BABYLON.Scene.FOGMODE_NONE;
         this.fogColor = new BABYLON.Color3(0.2, 0.2, 0.3);
@@ -40,7 +42,7 @@
 
         // Meshes
         this.meshes = [];
-        
+
         // Internal smart arrays
         this._activeMeshes = new BABYLON.Tools.SmartArray(256);
         this._opaqueSubMeshes = new BABYLON.Tools.SmartArray(256);
@@ -74,10 +76,10 @@
 
         // Animations
         this._activeAnimatables = [];
-        
+
         // Matrices
         this._transformMatrix = BABYLON.Matrix.Zero();
-        
+
         // Internals
         this._scaledPosition = BABYLON.Vector3.Zero();
         this._scaledVelocity = BABYLON.Vector3.Zero();
@@ -144,7 +146,7 @@
         return true;
     };
 
-    BABYLON.Scene.prototype.getWaitingItemsCount = function() {
+    BABYLON.Scene.prototype.getWaitingItemsCount = function () {
         return this._pendingData.length;
     };
 
@@ -160,11 +162,11 @@
         }
         this._onReadyCallbacks.push(func);
     };
-    
+
     BABYLON.Scene.prototype.registerBeforeRender = function (func) {
         this._onBeforeRenderCallbacks.push(func);
     };
-    
+
     BABYLON.Scene.prototype.unregisterBeforeRender = function (func) {
         var index = this._onBeforeRenderCallbacks.indexOf(func);
 
@@ -274,7 +276,7 @@
 
         return null;
     };
-    
+
     BABYLON.Scene.prototype.getLightByID = function (id) {
         for (var index = 0; index < this.lights.length; index++) {
             if (this.lights[index].id == id) {
@@ -320,6 +322,34 @@
         return (this._activeMeshes.indexOf(mesh) !== -1);
     };
 
+    BABYLON.Scene.prototype._evaluateSubMesh = function (subMesh, mesh) {
+        if (mesh.subMeshes.length == 1 || subMesh.isInFrustrum(this._frustumPlanes)) {
+            var material = subMesh.getMaterial();
+
+            if (material) {
+                // Render targets
+                if (material.getRenderTargetTextures) {
+                    if (this._processedMaterials.indexOf(material) === -1) {
+                        this._processedMaterials.push(material);
+
+                        this._renderTargets.concat(material.getRenderTargetTextures());
+                    }
+                }
+
+                // Dispatch
+                if (material.needAlphaBlending() || mesh.visibility < 1.0) { // Transparent
+                    if (material.alpha > 0 || mesh.visibility < 1.0) {
+                        this._transparentSubMeshes.push(subMesh); // Opaque
+                    }
+                } else if (material.needAlphaTesting()) { // Alpha test
+                    this._alphaTestSubMeshes.push(subMesh);
+                } else {
+                    this._opaqueSubMeshes.push(subMesh);
+                }
+            }
+        }
+    };
+
     BABYLON.Scene.prototype._evaluateActiveMeshes = function () {
         this._activeMeshes.reset();
         this._opaqueSubMeshes.reset();
@@ -339,49 +369,68 @@
         this._activeVertices = 0;
 
         // meshes
-        for (var meshIndex = 0; meshIndex < this.meshes.length; meshIndex++) {
-            var mesh = this.meshes[meshIndex];
+        if (this._selectionOctree) { // Octree
+            var selection = this._selectionOctree.select(this._frustumPlanes);
+            this._renderId++;
 
-            this._totalVertices += mesh.getTotalVertices();
-            
-            if (!mesh.isReady()) {
-                continue;
-            }
+            for (var blockIndex = 0; blockIndex < selection.length; blockIndex++) {
+                var block = selection.data[blockIndex];
 
-            mesh.computeWorldMatrix();
+                for (var meshIndex = 0; meshIndex < block.meshes.length; meshIndex++) {
+                    var mesh = block.meshes[meshIndex];
 
-            if (mesh.isEnabled() && mesh.isVisible && mesh.visibility > 0 && mesh.isInFrustrum(this._frustumPlanes)) {
-                for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
-                    var subMesh = mesh.subMeshes[subIndex];
+                    if (Math.abs(mesh._renderId) !== this._renderId) {                        
+                        this._totalVertices += mesh.getTotalVertices();
 
-                    if (mesh.subMeshes.length == 1 || subMesh.isInFrustrum(this._frustumPlanes)) {
-                        var material = subMesh.getMaterial();
+                        if (!mesh.isReady()) {
+                            continue;
+                        }
 
-                        if (this._activeMeshes.indexOf(mesh) === -1) {
+                        mesh.computeWorldMatrix();
+                        mesh._renderId = 0;
+                    }
+                    
+                    if (mesh._renderId === this._renderId || (mesh._renderId === 0 && mesh.isEnabled() && mesh.isVisible && mesh.visibility > 0 && mesh.isInFrustrum(this._frustumPlanes))) {
+                        if (mesh._renderId === 0) {
                             this._activeMeshes.push(mesh);
                         }
+                        mesh._renderId = this._renderId;
 
-                        if (material) {
-                            // Render targets
-                            if (material.getRenderTargetTextures) {
-                                if (this._processedMaterials.indexOf(material) === -1) {
-                                    this._processedMaterials.push(material);
+                        var subMeshes = block.subMeshes[meshIndex];
+                        for (var subIndex = 0; subIndex < subMeshes.length; subIndex++) {
+                            var subMesh = subMeshes[subIndex];
 
-                                    this._renderTargets.concat(material.getRenderTargetTextures());
-                                }
+                            if (subMesh._renderId === this._renderId) {
+                                continue;
                             }
+                            subMesh._renderId = this._renderId;
 
-                            // Dispatch
-                            if (material.needAlphaBlending() || mesh.visibility < 1.0) { // Transparent
-                                if (material.alpha > 0 || mesh.visibility < 1.0) {
-                                    this._transparentSubMeshes.push(subMesh); // Opaque
-                                }
-                            } else if (material.needAlphaTesting()) { // Alpha test
-                                this._alphaTestSubMeshes.push(subMesh);
-                            } else {
-                                this._opaqueSubMeshes.push(subMesh);
-                            }
+                            this._evaluateSubMesh(subMesh, mesh);
                         }
+                    } else {
+                        mesh._renderId = -this._renderId;
+                    }
+                }
+            }
+        } else { // Full scene traversal
+            for (var meshIndex = 0; meshIndex < this.meshes.length; meshIndex++) {
+                var mesh = this.meshes[meshIndex];
+
+                this._totalVertices += mesh.getTotalVertices();
+
+                if (!mesh.isReady()) {
+                    continue;
+                }
+
+                mesh.computeWorldMatrix();
+
+                if (mesh.isEnabled() && mesh.isVisible && mesh.visibility > 0 && mesh.isInFrustrum(this._frustumPlanes)) {
+                    this._activeMeshes.push(mesh);
+
+                    for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
+                        var subMesh = mesh.subMeshes[subIndex];
+
+                        this._evaluateSubMesh(subMesh, mesh);
                     }
                 }
             }
@@ -467,7 +516,7 @@
         if (this.beforeRender) {
             this.beforeRender();
         }
-        
+
         for (var callbackIndex = 0; callbackIndex < this._onBeforeRenderCallbacks.length; callbackIndex++) {
             this._onBeforeRenderCallbacks[callbackIndex]();
         }
@@ -496,7 +545,7 @@
                 this._renderTargets.push(shadowGenerator.getShadowMap());
             }
         }
-        
+
         // Render targets
         var beforeRenderTargetDate = new Date();
         for (var renderIndex = 0; renderIndex < this._renderTargets.length; renderIndex++) {
@@ -555,7 +604,7 @@
 
         // Cleaning
         for (var index = 0; index < this._toBeDisposed.length; index++) {
-            this._toBeDisposed[index].dispose();
+            this._toBeDisposed.data[index].dispose();
             this._toBeDisposed[index] = null;
         }
 
@@ -574,7 +623,7 @@
         for (index = 0; index < this.cameras.length; index++) {
             this.cameras[index].detachControl(canvas);
         }
-        
+
         // Release lights
         while (this.lights.length) {
             this.lights[0].dispose(true);
@@ -666,6 +715,46 @@
         this._collideWithWorld(position, velocity, collider, maximumRetry, finalPosition);
     };
 
+    // Octrees
+    BABYLON.Scene.prototype.createOrUpdateSelectionOctree = function () {
+        if (!this._selectionOctree) {
+            this._selectionOctree = new BABYLON.Octree();
+        }
+
+        // World limits
+        var checkExtends = function (v, min, max) {
+            if (v.x < min.x)
+                min.x = v.x;
+            if (v.y < min.y)
+                min.y = v.y;
+            if (v.z < min.z)
+                min.z = v.z;
+
+            if (v.x > max.x)
+                max.x = v.x;
+            if (v.y > max.y)
+                max.y = v.y;
+            if (v.z > max.z)
+                max.z = v.z;
+        };
+
+        var min = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
+        var max = new BABYLON.Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
+        for (var index = 0; index < this.meshes.length; index++) {
+            var mesh = this.meshes[index];
+
+            mesh.computeWorldMatrix();
+            var minBox = mesh.getBoundingInfo().boundingBox.minimumWorld;
+            var maxBox = mesh.getBoundingInfo().boundingBox.maximumWorld;
+
+            checkExtends(minBox, min, max);
+            checkExtends(maxBox, min, max);
+        }
+
+        // Update octree
+        this._selectionOctree.update(min, max, this.meshes);
+    };
+
     // Picking
     BABYLON.Scene.prototype.createPickingRay = function (x, y, world) {
         var engine = this._engine;

+ 40 - 25
Exporters/Blender/io_export_babylon.py

@@ -310,24 +310,28 @@ class Export_babylon(bpy.types.Operator, ExportHelper):
 		Export_babylon.mesh_triangulate(mesh)
 		
 		# Getting vertices and indices
-		vertices=",\"vertices\":["
+		positions=",\"positions\":["
+		normals=",\"normals\":["
 		indices=",\"indices\":["	
 		hasUV = True;
 		hasUV2 = True;
 		hasVertexColor = True
 		
 		if len(mesh.tessface_uv_textures) > 0:
-			UVmap=mesh.tessface_uv_textures[0].data	
+			UVmap=mesh.tessface_uv_textures[0].data
+			uvs=",\"uvs\":["	
 		else:
 			hasUV = False
 			
 		if len(mesh.tessface_uv_textures) > 1:
 			UV2map=mesh.tessface_uv_textures[1].data
+			uvs2=",\"uvs2\":["	
 		else:
 			hasUV2 = False
 
 		if len(mesh.vertex_colors) > 0:
 			Colormap = mesh.tessface_vertex_colors.active.data
+			colors=",\"colors\":["	
 		else:
 			hasVertexColor = False
 			
@@ -418,24 +422,18 @@ class Export_babylon(bpy.types.Operator, ExportHelper):
 						alreadySavedVertices[vertex_index]=True
 						if hasUV:
 							vertices_UVs[vertex_index].append(vertex_UV)
+							uvs+="%.4f,%.4f,"%(vertex_UV[0], vertex_UV[1])
 						if hasUV2:
 							vertices_UV2s[vertex_index].append(vertex_UV2)
+							uvs2+="%.4f,%.4f,"%(vertex_UV2[0], vertex_UV2[1])
 						if hasVertexColor:	
 							vertices_Colors[vertex_index].append(vertex_Color)
+							colors+="%.4f,%.4f,%.4f,"%(vertex_Color.r,vertex_Color.g,vertex_Color.b)
 
 						vertices_indices[vertex_index].append(index)
 						
-						vertices+="%.4f,%.4f,%.4f,"%(position.x,position.z,position.y)				
-						vertices+="%.4f,%.4f,%.4f,"%(normal.x,normal.z,normal.y)
-
-						if hasUV:
-							vertices+="%.4f,%.4f,"%(vertex_UV[0], vertex_UV[1])
-							
-						if hasUV2:
-							vertices+="%.4f,%.4f,"%(vertex_UV2[0], vertex_UV2[1])
-
-						if hasVertexColor:	
-							vertices+="%.4f,%.4f,%.4f,"%(vertex_Color.r,vertex_Color.g,vertex_Color.b)
+						positions+="%.4f,%.4f,%.4f,"%(position.x,position.z,position.y)				
+						normals+="%.4f,%.4f,%.4f,"%(normal.x,normal.z,normal.y)						
 						
 						verticesCount += 1
 					indices+="%i,"%(index)
@@ -444,11 +442,25 @@ class Export_babylon(bpy.types.Operator, ExportHelper):
 			subMeshes[materialIndex].verticesCount = verticesCount - subMeshes[materialIndex].verticesStart
 			subMeshes[materialIndex].indexCount = indicesCount - subMeshes[materialIndex].indexStart
 				
-		vertices=vertices.rstrip(',')
+		positions=positions.rstrip(',')
+		normals=normals.rstrip(',')
 		indices=indices.rstrip(',')
 			
-		vertices+="]\n"
+		positions+="]\n"
+		normals+="]\n"
 		indices+="]\n"	
+
+		if hasUV:
+			uvs=uvs.rstrip(',')
+			uvs+="]\n"
+
+		if hasUV2:
+			uvs2=uvs.rstrip(',')
+			uvs2+="]\n"
+
+		if hasVertexColor:
+			colors=uvs.rstrip(',')
+			colors+="]\n"
 				
 		# Writing mesh		
 		file_handler.write("{")
@@ -486,16 +498,19 @@ class Export_babylon(bpy.types.Operator, ExportHelper):
 		Export_babylon.write_bool(file_handler, "checkCollisions", object.data.checkCollisions)
 		Export_babylon.write_int(file_handler, "billboardMode", billboardMode)
 		Export_babylon.write_bool(file_handler, "receiveShadows", object.data.receiveShadows)
-		
-		if hasUV and hasUV2:
-			Export_babylon.write_int(file_handler, "uvCount", 2)
-		elif hasUV:
-			Export_babylon.write_int(file_handler, "uvCount", 1)
-		else:
-			Export_babylon.write_int(file_handler, "uvCount", 0)
-		
-		Export_babylon.write_bool(file_handler, "hasVertexColor", hasVertexColor)
-		file_handler.write(vertices)	
+				
+		file_handler.write(positions)
+		file_handler.write(normals)
+
+		if hasUV:
+			file_handler.write(uvs)
+
+		if hasUV2:
+			file_handler.write(uvs2)
+
+		if hasVertexColor:
+			file_handler.write(colors)
+
 		file_handler.write(indices)	
 		
 		# Sub meshes

File diff suppressed because it is too large
+ 9 - 5
Samples/Scenes/Blender/blender.babylon


+ 1 - 1
Samples/Scenes/Customs/charting.js

@@ -54,7 +54,7 @@
     //background.material.reflectionTexture.renderList.push(ground);
     
     var shadowGenerator = new BABYLON.ShadowGenerator(1024, light);
-
+    
     var createSeries = function (series) {
         var margin = 2;
         var offset = playgroundSize / (series.length) - margin;

File diff suppressed because it is too large
+ 1 - 1
Samples/Scenes/Espilit/espilit.babylon


File diff suppressed because it is too large
+ 1 - 1
Samples/Scenes/Flat2009/Flat2009.babylon


File diff suppressed because it is too large
+ 1 - 1
Samples/Scenes/Heart/Heart.babylon


File diff suppressed because it is too large
+ 1 - 1
Samples/Scenes/SpaceDek/SpaceDek.babylon


File diff suppressed because it is too large
+ 1 - 1
Samples/Scenes/Spaceship/Spaceship.babylon


File diff suppressed because it is too large
+ 1 - 1
Samples/Scenes/TheCar/TheCar.babylon


File diff suppressed because it is too large
+ 1 - 1
Samples/Scenes/Viper/Viper.babylon


File diff suppressed because it is too large
+ 1 - 1
Samples/Scenes/WCafe/WCafe.babylon


File diff suppressed because it is too large
+ 3 - 3
Samples/Scenes/WorldMonger/babylon.js


+ 14 - 15
Samples/Scenes/WorldMonger/elevationControl.js

@@ -119,13 +119,14 @@
         if (this._facesOfVertices == null) {
             this._facesOfVertices = [];
 
-            this._groundVertices = this._ground.getVertices();
+            this._groundVerticesPositions = this._ground.getVerticesData(BABYLON.VertexBuffer.PositionKind).getData();
+            this._groundVerticesNormals = this._ground.getVerticesData(BABYLON.VertexBuffer.NormalKind).getData();
             this._groundIndices = this._ground.getIndices();
 
             this._groundPositions = [];
             var index;
-            for (index = 0; index < this._groundVertices.length; index += this._ground.getFloatVertexStrideSize()) {
-                this._groundPositions.push(new BABYLON.Vector3(this._groundVertices[index], this._groundVertices[index + 1], this._groundVertices[index + 2]));
+            for (index = 0; index < this._groundVerticesPositions.length; index += 3) {
+                this._groundPositions.push(new BABYLON.Vector3(this._groundVerticesPositions[index], this._groundVerticesPositions[index + 1], this._groundVerticesPositions[index + 2]));
             }
 
             this._groundFacesNormals = [];
@@ -212,7 +213,6 @@
         }
 
         // Elevate vertices
-        var stride = this._ground.getFloatVertexStrideSize();
         for (var selectedVertice in this._selectedVertices) {
             var position = this._groundPositions[selectedVertice];
             var distance = this._selectedVertices[selectedVertice];
@@ -229,23 +229,24 @@
             else if (position.y < this.heightMin)
                 position.y = this.heightMin;
 
-            this._groundVertices[selectedVertice * stride + 1] = position.y;
+            this._groundVerticesPositions[selectedVertice * 3 + 1] = position.y;
 
             this._updateSubdivisions(selectedVertice);
         }
 
         // Normals
-        this._reComputeNormals()
+        this._reComputeNormals();
 
         // Update vertex buffer
-        this._ground.updateVertices(this._groundVertices);
+        this._ground.updateVerticesData(BABYLON.VertexBuffer.PositionKind, this._groundVerticesPositions);
+        this._ground.updateVerticesData(BABYLON.VertexBuffer.NormalKind,this._groundVerticesNormals);        
     };
 
     WORLDMONGER.ElevationControl.prototype._reComputeNormals = function () {
         var faces = [];
         var face;
 
-        for (selectedVertice in this._selectedVertices) {
+        for (var selectedVertice in this._selectedVertices) {
             var faceOfVertices = this._facesOfVertices[selectedVertice];
             for (var index = 0; index < faceOfVertices.length; index++) {
                 faces[faceOfVertices[index]] = true;
@@ -264,7 +265,7 @@
         }
     };
 
-    WORLDMONGER.ElevationControl.prototype._computeNormal = function (vertexIndex) {
+    WORLDMONGER.ElevationControl.prototype._computeNormal = function(vertexIndex) {
         var faces = this._facesOfVertices[vertexIndex];
 
         var normal = BABYLON.Vector3.Zero();
@@ -274,12 +275,10 @@
 
         normal = BABYLON.Vector3.Normalize(normal.scale(1.0 / faces.length));
 
-        var stride = this._ground.getFloatVertexStrideSize();
-
-        this._groundVertices[vertexIndex * stride + 3] = normal.x;
-        this._groundVertices[vertexIndex * stride + 4] = normal.y;
-        this._groundVertices[vertexIndex * stride + 5] = normal.z;
-    }
+        this._groundVerticesNormals[vertexIndex * 3] = normal.x;
+        this._groundVerticesNormals[vertexIndex * 3 + 1] = normal.y;
+        this._groundVerticesNormals[vertexIndex * 3 + 2] = normal.z;
+    };
 
     WORLDMONGER.ElevationControl.prototype._updateSubdivisions = function (vertexIndex) {
         for (var index = 0; index < this._subdivisionsOfVertices[vertexIndex].length; index++) {

File diff suppressed because it is too large
+ 2 - 2
Samples/babylon.js


+ 6 - 1
Samples/index.html

@@ -34,6 +34,7 @@
     <script src="Babylon/Cameras/babylon.touchCamera.js"></script>
     <script src="Babylon/Cameras/babylon.arcRotateCamera.js"></script>
     <script src="Babylon/babylon.scene.js"></script>
+    <script src="Babylon/Mesh/babylon.vertexBuffer.js"></script>
     <script src="Babylon/Mesh/babylon.mesh.js"></script>
     <script src="Babylon/Mesh/babylon.subMesh.js"></script>
     <script src="Babylon/Materials/textures/babylon.baseTexture.js"></script>
@@ -54,7 +55,9 @@
     <script src="Babylon/Particles/babylon.particle.js"></script>
     <script src="Babylon/Particles/babylon.particleSystem.js"></script>
     <script src="Babylon/Animations/babylon.animation.js"></script>
-    <script src="Babylon/Animations/babylon.animatable.js"></script>-->
+    <script src="Babylon/Animations/babylon.animatable.js"></script>
+    <script src="Babylon/Culling/Octrees/babylon.octree.js"></script>
+    <script src="Babylon/Culling/Octrees/babylon.octreeBlock.js"></script>-->
     <script src="babylon.js"></script>
     <script src="Scenes/Customs/test.js"></script>
     <script src="Scenes/Customs/lights_test.js"></script>
@@ -133,6 +136,7 @@
                                     <li>Frustum clipping</li>
                                     <li>Sub-meshes clipping</li>
                                     <li>Hardware scaling</li>
+                                    <li>Selection octrees</li>
                                 </ul>
                             </li>
                             <li>
@@ -150,6 +154,7 @@
                                     <li>Up to 4 lights (points, directionals, spots, hemispherics)</li>
                                     <li>Custom materials</li>
                                     <li>Skybox</li>
+                                    <li>Vertex color</li>
                                 </ul>
                             </li>
                             <li>

+ 4 - 1
Samples/index.js

@@ -5,7 +5,9 @@
     var demos = [
         { title: "WORLDMONGER", url: "Scenes/Worldmonger/index.html", screenshot: "worldmonger.jpg", size: "8.5 MB", big: true },
         { title: "HEART", scene: "Heart", screenshot: "heart.jpg", size: "14 MB", },
-        { title: "ESPILIT", scene: "Espilit", screenshot: "espilit.jpg", size: "50 MB" },
+        { title: "ESPILIT", scene: "Espilit", screenshot: "espilit.jpg", size: "50 MB", onload: function() {
+            scene.createOrUpdateSelectionOctree();
+        } },
         { title: "WINDOWS CAFE", scene: "WCafe", screenshot: "wcafe.jpg", size: "28 MB" },
         {
             title: "FLAT 2009",
@@ -15,6 +17,7 @@
             onload: function () {
                 var ecran = scene.getMeshByName("Ecran");
                 ecran.material.diffuseTexture = new BABYLON.VideoTexture("video", ["Scenes/Flat2009/babylonjs.mp4", "Scenes/Flat2009/babylonjs.webm"], 256, scene, true);
+                scene.createOrUpdateSelectionOctree();
             }
         },
         { title: "THE CAR", scene: "TheCar", screenshot: "thecar.jpg", size: "100 MB" },

File diff suppressed because it is too large
+ 0 - 13
babylon.1.2.1.js


File diff suppressed because it is too large
+ 13 - 0
babylon.1.3.0.js


+ 1 - 0
readme.md

@@ -14,6 +14,7 @@ Official web site: [www.babylonjs.com](http://www.babylonjs.com/)
  - Frustum clipping
  - Sub-meshes clipping
  - Hardware scaling
+ - Selection octrees
 - Standard material is a per pixel material that supports:
  - Diffuse lightning and texture
  - Ambient lightning and texture

+ 47 - 41
what's new.txt

@@ -1,42 +1,48 @@
-1.2.1:
- - Support for PointerLock ()
- - StandardMaterial now supports per-vertex color
- - Blender exporter supports per-vertex color
-1.2.0:
- - Major rework of the API to remove GC pressure.
- - FreeCamera: Support for QWERTY keyboards
- - New 3D charting demo
-1.1.0:
- - Shadow Maps and Variance Shadow Maps
- - Shadows Maps and animations are now exported from Blender
- - Hand.js is no longer required for ArcRotateCamera
- - ArcRotateCamera support pinch/zoom gesture on IE
-1.0.10:
- - Using typed arrays for Matrix
- - Improving IE11 support
- - Support for new mesh primitives : Torus and cylinder
-1.0.9:
- - Orthographic camera
-1.0.8:
- - Adding keyboard support to ArcRotateCamera
- - Starting to use git tag
-1.0.7:
- - New demo: Worldmonger
- - Improved IE shaders
-1.0.6:
- - Dynamic meshes
- - Skybox
- - Support for high-DPI displays
- - Height maps
-1.0.5:
- - Adding color tint for sprites and layers
-1.0.4:
- - Various optimizations
- - Fog
- - TypeScript support
-1.0.3:
- - Video textures
- - Normal map (bump) 
-1.0.2:
- - Spot lights
+Changes list
+============
+
+- 1.3.0:
+ - Selection octrees
+ - Breaking changes: Meshes now use multi vertex buffers (one for each attribute) instead of a big one. This is for more flexibility. The .babylon file format has changed accordingly (no more .vertices property on meshes but .positions, .normals, .colors, .uvs, .uvs2)
+- 1.2.1:
+ - Support for PointerLock ()
+ - StandardMaterial now supports per-vertex color
+ - Blender exporter supports per-vertex color
+- 1.2.0:
+ - Major rework of the API to remove GC pressure.
+ - FreeCamera: Support for QWERTY keyboards
+ - New 3D charting demo
+- 1.1.0:
+ - Shadow Maps and Variance Shadow Maps
+ - Shadows Maps and animations are now exported from Blender
+ - Hand.js is no longer required for ArcRotateCamera
+ - ArcRotateCamera support pinch/zoom gesture on IE
+- 1.0.10:
+ - Using typed arrays for Matrix
+ - Improving IE11 support
+ - Support for new mesh primitives : Torus and cylinder
+- 1.0.9:
+ - Orthographic camera
+- 1.0.8:
+ - Adding keyboard support to ArcRotateCamera
+ - Starting to use git tag
+- 1.0.7:
+ - New demo: Worldmonger
+ - Improved IE shaders
+- 1.0.6:
+ - Dynamic meshes
+ - Skybox
+ - Support for high-DPI displays
+ - Height maps
+- 1.0.5:
+ - Adding color tint for sprites and layers
+- 1.0.4:
+ - Various optimizations
+ - Fog
+ - TypeScript support
+- 1.0.3:
+ - Video textures
+ - Normal map (bump) 
+- 1.0.2:
+ - Spot lights
  - Hemispheric lights