ソースを参照

- 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 年 前
コミット
eb9e3e6445
35 ファイル変更769 行追加408 行削除
  1. 41 0
      Babylon/Culling/Octrees/babylon.octree.js
  2. 65 0
      Babylon/Culling/Octrees/babylon.octreeBlock.js
  3. 43 25
      Babylon/Culling/babylon.boundingBox.js
  4. 3 3
      Babylon/Culling/babylon.boundingInfo.js
  5. 3 3
      Babylon/Culling/babylon.boundingSphere.js
  6. 5 0
      Babylon/Materials/babylon.effect.js
  7. 9 14
      Babylon/Materials/babylon.standardMaterial.js
  8. 188 155
      Babylon/Mesh/babylon.mesh.js
  9. 2 3
      Babylon/Mesh/babylon.subMesh.js
  10. 67 0
      Babylon/Mesh/babylon.vertexBuffer.js
  11. 4 0
      Babylon/Tools/babylon.math.js
  12. 17 21
      Babylon/Tools/babylon.sceneLoader.js
  13. 18 0
      Babylon/Tools/babylon.tools.js
  14. 24 26
      Babylon/babylon.engine.js
  15. 132 43
      Babylon/babylon.scene.js
  16. 40 25
      Exporters/Blender/io_export_babylon.py
  17. 9 5
      Samples/Scenes/Blender/blender.babylon
  18. 1 1
      Samples/Scenes/Customs/charting.js
  19. 1 1
      Samples/Scenes/Espilit/espilit.babylon
  20. 1 1
      Samples/Scenes/Flat2009/Flat2009.babylon
  21. 1 1
      Samples/Scenes/Heart/Heart.babylon
  22. 1 1
      Samples/Scenes/SpaceDek/SpaceDek.babylon
  23. 1 1
      Samples/Scenes/Spaceship/Spaceship.babylon
  24. 1 1
      Samples/Scenes/TheCar/TheCar.babylon
  25. 1 1
      Samples/Scenes/Viper/Viper.babylon
  26. 1 1
      Samples/Scenes/WCafe/WCafe.babylon
  27. 3 3
      Samples/Scenes/WorldMonger/babylon.js
  28. 14 15
      Samples/Scenes/WorldMonger/elevationControl.js
  29. 2 2
      Samples/babylon.js
  30. 6 1
      Samples/index.html
  31. 4 1
      Samples/index.js
  32. 0 13
      babylon.1.2.1.js
  33. 13 0
      babylon.1.3.0.js
  34. 1 0
      readme.md
  35. 47 41
      what's new.txt

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

+ 24 - 26
Babylon/babylon.engine.js

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

+ 132 - 43
Babylon/babylon.scene.js

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

+ 40 - 25
Exporters/Blender/io_export_babylon.py

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

ファイルの差分が大きいため隠しています
+ 9 - 5
Samples/Scenes/Blender/blender.babylon


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

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

ファイルの差分が大きいため隠しています
+ 1 - 1
Samples/Scenes/Espilit/espilit.babylon


ファイルの差分が大きいため隠しています
+ 1 - 1
Samples/Scenes/Flat2009/Flat2009.babylon


ファイルの差分が大きいため隠しています
+ 1 - 1
Samples/Scenes/Heart/Heart.babylon


ファイルの差分が大きいため隠しています
+ 1 - 1
Samples/Scenes/SpaceDek/SpaceDek.babylon


ファイルの差分が大きいため隠しています
+ 1 - 1
Samples/Scenes/Spaceship/Spaceship.babylon


ファイルの差分が大きいため隠しています
+ 1 - 1
Samples/Scenes/TheCar/TheCar.babylon


ファイルの差分が大きいため隠しています
+ 1 - 1
Samples/Scenes/Viper/Viper.babylon


ファイルの差分が大きいため隠しています
+ 1 - 1
Samples/Scenes/WCafe/WCafe.babylon


ファイルの差分が大きいため隠しています
+ 3 - 3
Samples/Scenes/WorldMonger/babylon.js


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

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

ファイルの差分が大きいため隠しています
+ 2 - 2
Samples/babylon.js


+ 6 - 1
Samples/index.html

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

+ 4 - 1
Samples/index.js

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

ファイルの差分が大きいため隠しています
+ 0 - 13
babylon.1.2.1.js


ファイルの差分が大きいため隠しています
+ 13 - 0
babylon.1.3.0.js


+ 1 - 0
readme.md

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

+ 47 - 41
what's new.txt

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