Bladeren bron

- 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 jaren geleden
bovenliggende
commit
eb9e3e6445
35 gewijzigde bestanden met toevoegingen van 769 en 408 verwijderingen
  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 || {};
 var BABYLON = BABYLON || {};
 
 
 (function () {
 (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.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);
         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.minimum = BABYLON.Vector3.Minimize(current, this.minimum);
             this.maximum = BABYLON.Vector3.Maximize(current, this.maximum);
             this.maximum = BABYLON.Vector3.Maximize(current, this.maximum);
         }
         }
-        
+
         // Bounding vectors
         // Bounding vectors
         this.vectors = [];
         this.vectors = [];
 
 
@@ -35,12 +35,12 @@
 
 
         this.vectors.push(this.maximum.clone());
         this.vectors.push(this.maximum.clone());
         this.vectors[7].y = this.minimum.y;
         this.vectors[7].y = this.minimum.y;
-        
+
         // OBB
         // OBB
         this.center = this.maximum.add(this.minimum).scale(0.5);
         this.center = this.maximum.add(this.minimum).scale(0.5);
         this.extends = this.maximum.subtract(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()];
         this.directions = [BABYLON.Vector3.Zero(), BABYLON.Vector3.Zero(), BABYLON.Vector3.Zero()];
-        
+
         // World
         // World
         this.vectorsWorld = [];
         this.vectorsWorld = [];
         for (var index = 0; index < this.vectors.length; index++) {
         for (var index = 0; index < this.vectors.length; index++) {
@@ -49,7 +49,7 @@
         this.minimumWorld = BABYLON.Vector3.Zero();
         this.minimumWorld = BABYLON.Vector3.Zero();
         this.maximumWorld = BABYLON.Vector3.Zero();
         this.maximumWorld = BABYLON.Vector3.Zero();
     };
     };
-    
+
     // Methods
     // Methods
     BABYLON.BoundingBox.prototype._update = function (world) {
     BABYLON.BoundingBox.prototype._update = function (world) {
         BABYLON.Vector3.FromFloatsToRef(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE, this.minimumWorld);
         BABYLON.Vector3.FromFloatsToRef(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE, this.minimumWorld);
@@ -77,29 +77,16 @@
         // OBB
         // OBB
         this.maximumWorld.addToRef(this.minimumWorld, this.center);
         this.maximumWorld.addToRef(this.minimumWorld, this.center);
         this.center.scaleInPlace(0.5);
         this.center.scaleInPlace(0.5);
-        
+
         BABYLON.Vector3.FromArrayToRef(world.m, 0, this.directions[0]);
         BABYLON.Vector3.FromArrayToRef(world.m, 0, this.directions[0]);
         BABYLON.Vector3.FromArrayToRef(world.m, 4, this.directions[1]);
         BABYLON.Vector3.FromArrayToRef(world.m, 4, this.directions[1]);
         BABYLON.Vector3.FromArrayToRef(world.m, 8, this.directions[2]);
         BABYLON.Vector3.FromArrayToRef(world.m, 8, this.directions[2]);
     };
     };
 
 
     BABYLON.BoundingBox.prototype.isInFrustrum = function (frustumPlanes) {
     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) {
     BABYLON.BoundingBox.prototype.intersectsPoint = function (point) {
         if (this.maximumWorld.x < point.x || this.minimumWorld.x > point.x)
         if (this.maximumWorld.x < point.x || this.minimumWorld.x > point.x)
             return false;
             return false;
@@ -112,13 +99,26 @@
 
 
         return true;
         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 vector = BABYLON.Vector3.Clamp(sphere.centerWorld, this.minimumWorld, this.maximumWorld);
         var num = BABYLON.Vector3.DistanceSquared(sphere.centerWorld, vector);
         var num = BABYLON.Vector3.DistanceSquared(sphere.centerWorld, vector);
         return (num <= (sphere.radiusWorld * sphere.radiusWorld));
         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
     // Statics
     BABYLON.BoundingBox.intersects = function (box0, box1) {
     BABYLON.BoundingBox.intersects = function (box0, box1) {
         if (box0.maximumWorld.x < box1.minimumWorld.x || box0.minimumWorld.x > box1.maximumWorld.x)
         if (box0.maximumWorld.x < box1.minimumWorld.x || box0.minimumWorld.x > box1.maximumWorld.x)
@@ -132,4 +132,22 @@
 
 
         return true;
         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 || {};
 var BABYLON = BABYLON || {};
 
 
 (function () {
 (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
     // Methods

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

@@ -1,12 +1,12 @@
 var BABYLON = BABYLON || {};
 var BABYLON = BABYLON || {};
 
 
 (function () {
 (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 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);
         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);
             minimum = BABYLON.Vector3.Minimize(current, minimum);
             maximum = BABYLON.Vector3.Maximize(current, maximum);
             maximum = BABYLON.Vector3.Maximize(current, maximum);

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

@@ -10,6 +10,7 @@
         this._samplers = samplers;
         this._samplers = samplers;
         this._isReady = false;
         this._isReady = false;
         this._compilationError = "";
         this._compilationError = "";
+        this._attributesNames = attributesNames;
 
 
         var that = this;
         var that = this;
 
 
@@ -50,6 +51,10 @@
         return this._program;
         return this._program;
     };
     };
 
 
+    BABYLON.Effect.prototype.getAttributesNames = function () {
+        return this._attributesNames;
+    };
+
     BABYLON.Effect.prototype.getAttribute = function (index) {
     BABYLON.Effect.prototype.getAttribute = function (index) {
         return this._attributes[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._scene.getEngine().getCaps().standardDerivatives && this.bumpTexture) {
             if (!this.bumpTexture.isReady()) {
             if (!this.bumpTexture.isReady()) {
                 return false;
                 return false;
-            } else {                
+            } else {
                 defines.push("#define BUMP");
                 defines.push("#define BUMP");
             }
             }
         }
         }
@@ -169,20 +169,15 @@
 
 
         var attribs = ["position", "normal"];
         var attribs = ["position", "normal"];
         if (mesh) {
         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");
                 attribs.push("color");
                 defines.push("#define VERTEXCOLOR");
                 defines.push("#define VERTEXCOLOR");
             }
             }

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

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

+ 24 - 26
Babylon/babylon.engine.js

@@ -44,10 +44,6 @@
         // Cache
         // Cache
         this._loadedTexturesCache = [];
         this._loadedTexturesCache = [];
         this._activeTexturesCache = [];
         this._activeTexturesCache = [];
-        this._buffersCache = {
-            vertexBuffer: null,
-            indexBuffer: null
-        };
         this._currentEffect = null;
         this._currentEffect = null;
         this._currentState = {
         this._currentState = {
             culling: null
             culling: null
@@ -252,7 +248,6 @@
         this._gl.bindBuffer(this._gl.ARRAY_BUFFER, vbo);
         this._gl.bindBuffer(this._gl.ARRAY_BUFFER, vbo);
         this._gl.bufferData(this._gl.ARRAY_BUFFER, new Float32Array(vertices), this._gl.STATIC_DRAW);
         this._gl.bufferData(this._gl.ARRAY_BUFFER, new Float32Array(vertices), this._gl.STATIC_DRAW);
         this._gl.bindBuffer(this._gl.ARRAY_BUFFER, null);
         this._gl.bindBuffer(this._gl.ARRAY_BUFFER, null);
-        this._buffersCache.vertexBuffer = null;
         vbo.references = 1;
         vbo.references = 1;
         return vbo;
         return vbo;
     };
     };
@@ -262,7 +257,6 @@
         this._gl.bindBuffer(this._gl.ARRAY_BUFFER, vbo);
         this._gl.bindBuffer(this._gl.ARRAY_BUFFER, vbo);
         this._gl.bufferData(this._gl.ARRAY_BUFFER, capacity, this._gl.DYNAMIC_DRAW);
         this._gl.bufferData(this._gl.ARRAY_BUFFER, capacity, this._gl.DYNAMIC_DRAW);
         this._gl.bindBuffer(this._gl.ARRAY_BUFFER, null);
         this._gl.bindBuffer(this._gl.ARRAY_BUFFER, null);
-        this._buffersCache.vertexBuffer = null;
         vbo.references = 1;
         vbo.references = 1;
         return vbo;
         return vbo;
     };
     };
@@ -278,32 +272,42 @@
         this._gl.bindBuffer(this._gl.ELEMENT_ARRAY_BUFFER, vbo);
         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.bufferData(this._gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), this._gl.STATIC_DRAW);
         this._gl.bindBuffer(this._gl.ELEMENT_ARRAY_BUFFER, null);
         this._gl.bindBuffer(this._gl.ELEMENT_ARRAY_BUFFER, null);
-        this._buffersCache.indexBuffer = null;
         vbo.references = 1;
         vbo.references = 1;
         vbo.is32Bits = is32Bits;
         vbo.is32Bits = is32Bits;
         return vbo;
         return vbo;
     };
     };
 
 
     BABYLON.Engine.prototype.bindBuffers = function (vertexBuffer, indexBuffer, vertexDeclaration, vertexStrideSize, effect) {
     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) {
     BABYLON.Engine.prototype._releaseBuffer = function (buffer) {
@@ -387,8 +391,6 @@
         if (!effect || !effect.getAttributesCount() || this._currentEffect === effect) {
         if (!effect || !effect.getAttributesCount() || this._currentEffect === effect) {
             return;
             return;
         }
         }
-        this._buffersCache.vertexBuffer = null;
-
         // Use program
         // Use program
         this._gl.useProgram(effect.getProgram());
         this._gl.useProgram(effect.getProgram());
 
 
@@ -533,10 +535,6 @@
         this._currentState = {
         this._currentState = {
             culling: null
             culling: null
         };
         };
-        this._buffersCache = {
-            vertexBuffer: null,
-            indexBuffer: null
-        };
     };
     };
 
 
     var getExponantOfTwo = function (value, max) {
     var getExponantOfTwo = function (value, max) {

+ 132 - 43
Babylon/babylon.scene.js

@@ -17,13 +17,15 @@
         this._renderTargetsDuration = 0;
         this._renderTargetsDuration = 0;
         this._renderDuration = 0;
         this._renderDuration = 0;
 
 
+        this._renderId = 0;
+
         this._toBeDisposed = new BABYLON.Tools.SmartArray(256);
         this._toBeDisposed = new BABYLON.Tools.SmartArray(256);
 
 
         this._onReadyCallbacks = [];
         this._onReadyCallbacks = [];
         this._pendingData = [];
         this._pendingData = [];
 
 
         this._onBeforeRenderCallbacks = [];
         this._onBeforeRenderCallbacks = [];
-        
+
         // Fog
         // Fog
         this.fogMode = BABYLON.Scene.FOGMODE_NONE;
         this.fogMode = BABYLON.Scene.FOGMODE_NONE;
         this.fogColor = new BABYLON.Color3(0.2, 0.2, 0.3);
         this.fogColor = new BABYLON.Color3(0.2, 0.2, 0.3);
@@ -40,7 +42,7 @@
 
 
         // Meshes
         // Meshes
         this.meshes = [];
         this.meshes = [];
-        
+
         // Internal smart arrays
         // Internal smart arrays
         this._activeMeshes = new BABYLON.Tools.SmartArray(256);
         this._activeMeshes = new BABYLON.Tools.SmartArray(256);
         this._opaqueSubMeshes = new BABYLON.Tools.SmartArray(256);
         this._opaqueSubMeshes = new BABYLON.Tools.SmartArray(256);
@@ -74,10 +76,10 @@
 
 
         // Animations
         // Animations
         this._activeAnimatables = [];
         this._activeAnimatables = [];
-        
+
         // Matrices
         // Matrices
         this._transformMatrix = BABYLON.Matrix.Zero();
         this._transformMatrix = BABYLON.Matrix.Zero();
-        
+
         // Internals
         // Internals
         this._scaledPosition = BABYLON.Vector3.Zero();
         this._scaledPosition = BABYLON.Vector3.Zero();
         this._scaledVelocity = BABYLON.Vector3.Zero();
         this._scaledVelocity = BABYLON.Vector3.Zero();
@@ -144,7 +146,7 @@
         return true;
         return true;
     };
     };
 
 
-    BABYLON.Scene.prototype.getWaitingItemsCount = function() {
+    BABYLON.Scene.prototype.getWaitingItemsCount = function () {
         return this._pendingData.length;
         return this._pendingData.length;
     };
     };
 
 
@@ -160,11 +162,11 @@
         }
         }
         this._onReadyCallbacks.push(func);
         this._onReadyCallbacks.push(func);
     };
     };
-    
+
     BABYLON.Scene.prototype.registerBeforeRender = function (func) {
     BABYLON.Scene.prototype.registerBeforeRender = function (func) {
         this._onBeforeRenderCallbacks.push(func);
         this._onBeforeRenderCallbacks.push(func);
     };
     };
-    
+
     BABYLON.Scene.prototype.unregisterBeforeRender = function (func) {
     BABYLON.Scene.prototype.unregisterBeforeRender = function (func) {
         var index = this._onBeforeRenderCallbacks.indexOf(func);
         var index = this._onBeforeRenderCallbacks.indexOf(func);
 
 
@@ -274,7 +276,7 @@
 
 
         return null;
         return null;
     };
     };
-    
+
     BABYLON.Scene.prototype.getLightByID = function (id) {
     BABYLON.Scene.prototype.getLightByID = function (id) {
         for (var index = 0; index < this.lights.length; index++) {
         for (var index = 0; index < this.lights.length; index++) {
             if (this.lights[index].id == id) {
             if (this.lights[index].id == id) {
@@ -320,6 +322,34 @@
         return (this._activeMeshes.indexOf(mesh) !== -1);
         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 () {
     BABYLON.Scene.prototype._evaluateActiveMeshes = function () {
         this._activeMeshes.reset();
         this._activeMeshes.reset();
         this._opaqueSubMeshes.reset();
         this._opaqueSubMeshes.reset();
@@ -339,49 +369,68 @@
         this._activeVertices = 0;
         this._activeVertices = 0;
 
 
         // meshes
         // 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);
                             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) {
         if (this.beforeRender) {
             this.beforeRender();
             this.beforeRender();
         }
         }
-        
+
         for (var callbackIndex = 0; callbackIndex < this._onBeforeRenderCallbacks.length; callbackIndex++) {
         for (var callbackIndex = 0; callbackIndex < this._onBeforeRenderCallbacks.length; callbackIndex++) {
             this._onBeforeRenderCallbacks[callbackIndex]();
             this._onBeforeRenderCallbacks[callbackIndex]();
         }
         }
@@ -496,7 +545,7 @@
                 this._renderTargets.push(shadowGenerator.getShadowMap());
                 this._renderTargets.push(shadowGenerator.getShadowMap());
             }
             }
         }
         }
-        
+
         // Render targets
         // Render targets
         var beforeRenderTargetDate = new Date();
         var beforeRenderTargetDate = new Date();
         for (var renderIndex = 0; renderIndex < this._renderTargets.length; renderIndex++) {
         for (var renderIndex = 0; renderIndex < this._renderTargets.length; renderIndex++) {
@@ -555,7 +604,7 @@
 
 
         // Cleaning
         // Cleaning
         for (var index = 0; index < this._toBeDisposed.length; index++) {
         for (var index = 0; index < this._toBeDisposed.length; index++) {
-            this._toBeDisposed[index].dispose();
+            this._toBeDisposed.data[index].dispose();
             this._toBeDisposed[index] = null;
             this._toBeDisposed[index] = null;
         }
         }
 
 
@@ -574,7 +623,7 @@
         for (index = 0; index < this.cameras.length; index++) {
         for (index = 0; index < this.cameras.length; index++) {
             this.cameras[index].detachControl(canvas);
             this.cameras[index].detachControl(canvas);
         }
         }
-        
+
         // Release lights
         // Release lights
         while (this.lights.length) {
         while (this.lights.length) {
             this.lights[0].dispose(true);
             this.lights[0].dispose(true);
@@ -666,6 +715,46 @@
         this._collideWithWorld(position, velocity, collider, maximumRetry, finalPosition);
         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
     // Picking
     BABYLON.Scene.prototype.createPickingRay = function (x, y, world) {
     BABYLON.Scene.prototype.createPickingRay = function (x, y, world) {
         var engine = this._engine;
         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)
 		Export_babylon.mesh_triangulate(mesh)
 		
 		
 		# Getting vertices and indices
 		# Getting vertices and indices
-		vertices=",\"vertices\":["
+		positions=",\"positions\":["
+		normals=",\"normals\":["
 		indices=",\"indices\":["	
 		indices=",\"indices\":["	
 		hasUV = True;
 		hasUV = True;
 		hasUV2 = True;
 		hasUV2 = True;
 		hasVertexColor = True
 		hasVertexColor = True
 		
 		
 		if len(mesh.tessface_uv_textures) > 0:
 		if len(mesh.tessface_uv_textures) > 0:
-			UVmap=mesh.tessface_uv_textures[0].data	
+			UVmap=mesh.tessface_uv_textures[0].data
+			uvs=",\"uvs\":["	
 		else:
 		else:
 			hasUV = False
 			hasUV = False
 			
 			
 		if len(mesh.tessface_uv_textures) > 1:
 		if len(mesh.tessface_uv_textures) > 1:
 			UV2map=mesh.tessface_uv_textures[1].data
 			UV2map=mesh.tessface_uv_textures[1].data
+			uvs2=",\"uvs2\":["	
 		else:
 		else:
 			hasUV2 = False
 			hasUV2 = False
 
 
 		if len(mesh.vertex_colors) > 0:
 		if len(mesh.vertex_colors) > 0:
 			Colormap = mesh.tessface_vertex_colors.active.data
 			Colormap = mesh.tessface_vertex_colors.active.data
+			colors=",\"colors\":["	
 		else:
 		else:
 			hasVertexColor = False
 			hasVertexColor = False
 			
 			
@@ -418,24 +422,18 @@ class Export_babylon(bpy.types.Operator, ExportHelper):
 						alreadySavedVertices[vertex_index]=True
 						alreadySavedVertices[vertex_index]=True
 						if hasUV:
 						if hasUV:
 							vertices_UVs[vertex_index].append(vertex_UV)
 							vertices_UVs[vertex_index].append(vertex_UV)
+							uvs+="%.4f,%.4f,"%(vertex_UV[0], vertex_UV[1])
 						if hasUV2:
 						if hasUV2:
 							vertices_UV2s[vertex_index].append(vertex_UV2)
 							vertices_UV2s[vertex_index].append(vertex_UV2)
+							uvs2+="%.4f,%.4f,"%(vertex_UV2[0], vertex_UV2[1])
 						if hasVertexColor:	
 						if hasVertexColor:	
 							vertices_Colors[vertex_index].append(vertex_Color)
 							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_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
 						verticesCount += 1
 					indices+="%i,"%(index)
 					indices+="%i,"%(index)
@@ -444,11 +442,25 @@ class Export_babylon(bpy.types.Operator, ExportHelper):
 			subMeshes[materialIndex].verticesCount = verticesCount - subMeshes[materialIndex].verticesStart
 			subMeshes[materialIndex].verticesCount = verticesCount - subMeshes[materialIndex].verticesStart
 			subMeshes[materialIndex].indexCount = indicesCount - subMeshes[materialIndex].indexStart
 			subMeshes[materialIndex].indexCount = indicesCount - subMeshes[materialIndex].indexStart
 				
 				
-		vertices=vertices.rstrip(',')
+		positions=positions.rstrip(',')
+		normals=normals.rstrip(',')
 		indices=indices.rstrip(',')
 		indices=indices.rstrip(',')
 			
 			
-		vertices+="]\n"
+		positions+="]\n"
+		normals+="]\n"
 		indices+="]\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		
 		# Writing mesh		
 		file_handler.write("{")
 		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_bool(file_handler, "checkCollisions", object.data.checkCollisions)
 		Export_babylon.write_int(file_handler, "billboardMode", billboardMode)
 		Export_babylon.write_int(file_handler, "billboardMode", billboardMode)
 		Export_babylon.write_bool(file_handler, "receiveShadows", object.data.receiveShadows)
 		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)	
 		file_handler.write(indices)	
 		
 		
 		# Sub meshes
 		# 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);
     //background.material.reflectionTexture.renderList.push(ground);
     
     
     var shadowGenerator = new BABYLON.ShadowGenerator(1024, light);
     var shadowGenerator = new BABYLON.ShadowGenerator(1024, light);
-
+    
     var createSeries = function (series) {
     var createSeries = function (series) {
         var margin = 2;
         var margin = 2;
         var offset = playgroundSize / (series.length) - margin;
         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) {
         if (this._facesOfVertices == null) {
             this._facesOfVertices = [];
             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._groundIndices = this._ground.getIndices();
 
 
             this._groundPositions = [];
             this._groundPositions = [];
             var index;
             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 = [];
             this._groundFacesNormals = [];
@@ -212,7 +213,6 @@
         }
         }
 
 
         // Elevate vertices
         // Elevate vertices
-        var stride = this._ground.getFloatVertexStrideSize();
         for (var selectedVertice in this._selectedVertices) {
         for (var selectedVertice in this._selectedVertices) {
             var position = this._groundPositions[selectedVertice];
             var position = this._groundPositions[selectedVertice];
             var distance = this._selectedVertices[selectedVertice];
             var distance = this._selectedVertices[selectedVertice];
@@ -229,23 +229,24 @@
             else if (position.y < this.heightMin)
             else if (position.y < this.heightMin)
                 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);
             this._updateSubdivisions(selectedVertice);
         }
         }
 
 
         // Normals
         // Normals
-        this._reComputeNormals()
+        this._reComputeNormals();
 
 
         // Update vertex buffer
         // 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 () {
     WORLDMONGER.ElevationControl.prototype._reComputeNormals = function () {
         var faces = [];
         var faces = [];
         var face;
         var face;
 
 
-        for (selectedVertice in this._selectedVertices) {
+        for (var selectedVertice in this._selectedVertices) {
             var faceOfVertices = this._facesOfVertices[selectedVertice];
             var faceOfVertices = this._facesOfVertices[selectedVertice];
             for (var index = 0; index < faceOfVertices.length; index++) {
             for (var index = 0; index < faceOfVertices.length; index++) {
                 faces[faceOfVertices[index]] = true;
                 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 faces = this._facesOfVertices[vertexIndex];
 
 
         var normal = BABYLON.Vector3.Zero();
         var normal = BABYLON.Vector3.Zero();
@@ -274,12 +275,10 @@
 
 
         normal = BABYLON.Vector3.Normalize(normal.scale(1.0 / faces.length));
         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) {
     WORLDMONGER.ElevationControl.prototype._updateSubdivisions = function (vertexIndex) {
         for (var index = 0; index < this._subdivisionsOfVertices[vertexIndex].length; index++) {
         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.touchCamera.js"></script>
     <script src="Babylon/Cameras/babylon.arcRotateCamera.js"></script>
     <script src="Babylon/Cameras/babylon.arcRotateCamera.js"></script>
     <script src="Babylon/babylon.scene.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.mesh.js"></script>
     <script src="Babylon/Mesh/babylon.subMesh.js"></script>
     <script src="Babylon/Mesh/babylon.subMesh.js"></script>
     <script src="Babylon/Materials/textures/babylon.baseTexture.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.particle.js"></script>
     <script src="Babylon/Particles/babylon.particleSystem.js"></script>
     <script src="Babylon/Particles/babylon.particleSystem.js"></script>
     <script src="Babylon/Animations/babylon.animation.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="babylon.js"></script>
     <script src="Scenes/Customs/test.js"></script>
     <script src="Scenes/Customs/test.js"></script>
     <script src="Scenes/Customs/lights_test.js"></script>
     <script src="Scenes/Customs/lights_test.js"></script>
@@ -133,6 +136,7 @@
                                     <li>Frustum clipping</li>
                                     <li>Frustum clipping</li>
                                     <li>Sub-meshes clipping</li>
                                     <li>Sub-meshes clipping</li>
                                     <li>Hardware scaling</li>
                                     <li>Hardware scaling</li>
+                                    <li>Selection octrees</li>
                                 </ul>
                                 </ul>
                             </li>
                             </li>
                             <li>
                             <li>
@@ -150,6 +154,7 @@
                                     <li>Up to 4 lights (points, directionals, spots, hemispherics)</li>
                                     <li>Up to 4 lights (points, directionals, spots, hemispherics)</li>
                                     <li>Custom materials</li>
                                     <li>Custom materials</li>
                                     <li>Skybox</li>
                                     <li>Skybox</li>
+                                    <li>Vertex color</li>
                                 </ul>
                                 </ul>
                             </li>
                             </li>
                             <li>
                             <li>

+ 4 - 1
Samples/index.js

@@ -5,7 +5,9 @@
     var demos = [
     var demos = [
         { title: "WORLDMONGER", url: "Scenes/Worldmonger/index.html", screenshot: "worldmonger.jpg", size: "8.5 MB", big: true },
         { 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: "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: "WINDOWS CAFE", scene: "WCafe", screenshot: "wcafe.jpg", size: "28 MB" },
         {
         {
             title: "FLAT 2009",
             title: "FLAT 2009",
@@ -15,6 +17,7 @@
             onload: function () {
             onload: function () {
                 var ecran = scene.getMeshByName("Ecran");
                 var ecran = scene.getMeshByName("Ecran");
                 ecran.material.diffuseTexture = new BABYLON.VideoTexture("video", ["Scenes/Flat2009/babylonjs.mp4", "Scenes/Flat2009/babylonjs.webm"], 256, scene, true);
                 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" },
         { 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
  - Frustum clipping
  - Sub-meshes clipping
  - Sub-meshes clipping
  - Hardware scaling
  - Hardware scaling
+ - Selection octrees
 - Standard material is a per pixel material that supports:
 - Standard material is a per pixel material that supports:
  - Diffuse lightning and texture
  - Diffuse lightning and texture
  - Ambient 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
  - Hemispheric lights