David Catuhe 12 роки тому
батько
коміт
81d707984b

+ 6 - 1
Babylon/Animations/babylon.animatable.js

@@ -1,12 +1,13 @@
 var BABYLON = BABYLON || {};
 
 (function () {
-    BABYLON._Animatable = function (target, from, to, loop, speedRatio) {
+    BABYLON._Animatable = function (target, from, to, loop, speedRatio, onAnimationEnd) {
         this.target = target;
         this.fromFrame = from;
         this.toFrame = to;
         this.loopAnimation = loop;
         this.speedRatio = speedRatio ? speedRatio : 1.0;
+        this.onAnimationEnd = onAnimationEnd;
     };
     
     // Members
@@ -31,6 +32,10 @@
             running = running || isRunning;            
         }
 
+        if (!running && this.onAnimationEnd) {
+            this.onAnimationEnd();
+        }
+
         return running;
     };
 })();

+ 22 - 20
Babylon/Animations/babylon.animation.js

@@ -3,6 +3,7 @@
 (function () {
     BABYLON.Animation = function (name, targetProperty, framePerSecond, dataType, loopMode) {
         this.name = name;
+        this.targetProperty = targetProperty;
         this.targetPropertyPath = targetProperty.split(".");
         this.framePerSecond = framePerSecond;
         this.dataType = dataType;
@@ -96,7 +97,8 @@
         if (!this.targetPropertyPath || this.targetPropertyPath.length < 1) {
             return false;
         }
-        
+
+        var returnValue = true;
         // Adding a start key at frame 0 if missing
         if (this._keys[0].frame != 0) {
             var newKey = {
@@ -120,18 +122,17 @@
         var ratio = delay * (this.framePerSecond * speedRatio) / 1000.0;
 
         if (ratio > range && !loop) { // If we are out of range and not looping get back to caller
-            return false;
-        }
-        
-        // Get max value if required
-        var offsetValue = 0;
-        var highLimitValue = 0;
-        if (this.loopMode != BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE) {
-            var keyOffset = to.toString() + from.toString();
-            if (!this._offsetsCache[keyOffset]) {
-                var fromValue = this._interpolate(from, 0, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);
-                var toValue = this._interpolate(to, 0, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);
-                switch (this.dataType) {
+            returnValue = false;
+        } else {
+            // Get max value if required
+            var offsetValue = 0;
+            var highLimitValue = 0;
+            if (this.loopMode != BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE) {
+                var keyOffset = to.toString() + from.toString();
+                if (!this._offsetsCache[keyOffset]) {
+                    var fromValue = this._interpolate(from, 0, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);
+                    var toValue = this._interpolate(to, 0, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);
+                    switch (this.dataType) {
                     // Float
                     case BABYLON.Animation.ANIMATIONTYPE_FLOAT:
                         this._offsetsCache[keyOffset] = toValue - fromValue;
@@ -145,18 +146,19 @@
                         this._offsetsCache[keyOffset] = toValue.subtract(fromValue);
                     default:
                         break;
+                    }
+
+                    this._highLimitsCache[keyOffset] = toValue;
                 }
 
-                this._highLimitsCache[keyOffset] = toValue;
+                highLimitValue = this._highLimitsCache[keyOffset];
+                offsetValue = this._offsetsCache[keyOffset];
             }
-
-            highLimitValue = this._highLimitsCache[keyOffset];
-            offsetValue = this._offsetsCache[keyOffset];
         }
 
         // Compute value
         var repeatCount = (ratio / range) >> 0;
-        var currentFrame = from + ratio % range;
+        var currentFrame = returnValue ? from + ratio % range : to;
         var currentValue = this._interpolate(currentFrame, repeatCount, this.loopMode, offsetValue, highLimitValue);
 
         // Set value
@@ -173,10 +175,10 @@
         }
         
         if (target.markAsDirty) {
-            target.markAsDirty();
+            target.markAsDirty(this.targetProperty);
         }
 
-        return true;
+        return returnValue;
     };
 
     // Statics

+ 106 - 0
Babylon/Cameras/babylon.deviceOrientationCamera.js

@@ -0,0 +1,106 @@
+var BABYLON = BABYLON || {};
+
+(function () {
+    BABYLON.DeviceOrientationCamera = function (name, position, scene) {
+        this.name = name;
+        this.id = name;
+
+        this._scene = scene;
+        this.position = position;
+        scene.cameras.push(this);
+        this.cameraDirection = new BABYLON.Vector3(0, 0, 0);
+        this.cameraRotation = new BABYLON.Vector2(0, 0);
+        this.rotation = new BABYLON.Vector3(0, 0, 0);
+        this.ellipsoid = new BABYLON.Vector3(0.5, 1, 0.5);
+        this.angularSensibility = 200000.0;
+        this.moveSensibility = 500.0;
+
+        if (!scene.activeCamera) {
+            scene.activeCamera = this;
+        }
+        // Collisions
+        this._collider = new BABYLON.Collider();
+        this._needMoveForGravity = true;
+        
+        // Offset
+        this._offsetX = null;
+        this._offsetY = null;
+        this._orientationGamma = 0;
+        this._orientationBeta = 0;
+        this._initialOrientationGamma = 0;
+        this._initialOrientationBeta = 0;
+        
+        // Animations
+        this.animations = [];
+        
+        // Internals
+        this._cameraRotationMatrix = new BABYLON.Matrix();
+        this._referencePoint = BABYLON.Vector3.Zero();
+        this._currentTarget = BABYLON.Vector3.Zero();
+        this._transformedReferencePoint = BABYLON.Vector3.Zero();
+        this._viewMatrix = BABYLON.Matrix.Zero();
+        this._upVector = BABYLON.Vector3.Up();
+        this._oldPosition = BABYLON.Vector3.Zero();
+        this._diffPosition = BABYLON.Vector3.Zero();
+        this._newPosition = BABYLON.Vector3.Zero();
+    };
+
+    BABYLON.DeviceOrientationCamera.prototype = Object.create(BABYLON.FreeCamera.prototype);
+
+    // Controls
+    BABYLON.DeviceOrientationCamera.prototype.attachControl = function (canvas, noPreventDefault) {
+        if (this._attachedCanvas) {
+            return;
+        }
+        this._attachedCanvas = canvas;
+
+        if (!this._orientationChanged) {
+            this._orientationChanged = function (evt) {
+                
+                if (!this._initialOrientationGamma) {
+                    this._initialOrientationGamma = evt.gamma;
+                    this._initialOrientationBeta = evt.beta;
+                }
+
+                this._orientationGamma = evt.gamma;
+                this._orientationBeta = evt.beta;
+
+                this._offsetY = (this._initialOrientationBeta - this._orientationBeta) * 0.05;
+                this._offsetX = (this._initialOrientationGamma - this._orientationGamma) * -0.05;
+            };
+        }
+
+        window.addEventListener("deviceorientation", this._orientationChanged);
+    };
+
+    BABYLON.DeviceOrientationCamera.prototype.detachControl = function (canvas) {
+        if (this._attachedCanvas != canvas) {
+            return;
+        }
+
+        window.removeEventListener("deviceorientation", this._orientationChanged);
+        
+        this._attachedCanvas = null;
+        this._orientationGamma = 0;
+        this._orientationBeta = 0;
+        this._initialOrientationGamma = 0;
+        this._initialOrientationBeta = 0;
+    };
+    
+    BABYLON.DeviceOrientationCamera.prototype._checkInputs = function () {
+        if (!this._offsetX) {
+            return;
+        }
+        this.cameraRotation.y += this._offsetX / this.angularSensibility;
+
+        if (this._pointerPressed.length > 1) {
+            this.cameraRotation.x += -this._offsetY / this.angularSensibility;
+        } else {
+            var speed = this._computeLocalCameraSpeed();
+            var direction = new BABYLON.Vector3(0, 0, speed * this._offsetY / this.moveSensibility);
+
+            BABYLON.Matrix.RotationYawPitchRollToRef(this.rotation.y, this.rotation.x, 0, this._cameraRotationMatrix);
+            this.cameraDirection.addInPlace(BABYLON.Vector3.TransformCoordinates(direction, this._cameraRotationMatrix));
+        }
+    };
+})();

+ 1 - 0
Babylon/Cameras/babylon.touchCamera.js

@@ -35,6 +35,7 @@
         this._cameraRotationMatrix = new BABYLON.Matrix();
         this._referencePoint = BABYLON.Vector3.Zero();
         this._currentTarget = BABYLON.Vector3.Zero();
+        this._camMatrix = BABYLON.Matrix.Zero();
         this._transformedReferencePoint = BABYLON.Vector3.Zero();
         this._viewMatrix = BABYLON.Matrix.Zero();
         this._upVector = BABYLON.Vector3.Up();

+ 2 - 1
Babylon/Layer/babylon.layer.js

@@ -46,12 +46,13 @@
     BABYLON.Layer.prototype.render = function () {
         // Check
         if (!this._effect.isReady() || !this.texture || !this.texture.isReady())
-            return 0;
+            return;
 
         var engine = this._scene.getEngine();
        
         // Render
         engine.enableEffect(this._effect);
+        engine.setState(false);
 
         // Texture
         this._effect.setTexture("textureSampler", this.texture);

+ 2 - 1
Babylon/Lights/Shadows/babylon.shadowGenerator.js

@@ -11,6 +11,7 @@
         this._shadowMap = new BABYLON.RenderTargetTexture(light.name + "_shadowMap", mapSize, this._scene, false);
         this._shadowMap.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
         this._shadowMap.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
+        this._shadowMap.renderParticles = false;
                 
         // Custom render function
         var that = this;
@@ -39,7 +40,7 @@
             }
         };
 
-        this._shadowMap.customRenderFunction = function (opaqueSubMeshes, alphaTestSubMeshes, transparentSubMeshes, activeMeshes) {
+        this._shadowMap.customRenderFunction = function (opaqueSubMeshes, alphaTestSubMeshes) {
             var index;
             
             for (index = 0; index < opaqueSubMeshes.length; index++) {

+ 3 - 0
Babylon/Materials/textures/babylon.mirrorTexture.js

@@ -12,6 +12,9 @@
         
         // Render list
         this.renderList = [];
+
+        // Rendering groups
+        this._renderingManager = new BABYLON.RenderingManager(scene);
         
         // Internals
         this._transformMatrix = BABYLON.Matrix.Zero();

+ 21 - 40
Babylon/Materials/textures/babylon.renderTargetTexture.js

@@ -5,17 +5,21 @@
         this._scene = scene;
         this._scene.textures.push(this);
 
-        this.name = name;        
+        this.name = name;
 
         this._texture = scene.getEngine().createRenderTargetTexture(size, generateMipMaps);
-        
+
         // Render list
-        this.renderList = [];       
+        this.renderList = [];
+
+        // Rendering groups
+        this._renderingManager = new BABYLON.RenderingManager(scene);
     };
 
     BABYLON.RenderTargetTexture.prototype = Object.create(BABYLON.Texture.prototype);
 
     // Members        
+    BABYLON.RenderTargetTexture.prototype.renderParticles = true;
     BABYLON.RenderTargetTexture.prototype.isRenderTarget = true;
     BABYLON.RenderTargetTexture.prototype.coordinatesMode = BABYLON.Texture.PROJECTION_MODE;
 
@@ -23,11 +27,11 @@
     BABYLON.RenderTargetTexture.prototype.onBeforeRender = null;
     BABYLON.RenderTargetTexture.prototype.onAfterRender = null;
 
-    BABYLON.RenderTargetTexture.prototype.resize = function(size, generateMipMaps) {
+    BABYLON.RenderTargetTexture.prototype.resize = function (size, generateMipMaps) {
         this.releaseInternalTexture();
         this._texture = this._scene.getEngine().createRenderTargetTexture(size, generateMipMaps);
     };
-    
+
     BABYLON.RenderTargetTexture.prototype.render = function () {
         if (this.onBeforeRender) {
             this.onBeforeRender();
@@ -35,7 +39,7 @@
 
         var scene = this._scene;
         var engine = scene.getEngine();
-        
+
         if (this._waitingRenderList) {
             this.renderList = [];
             for (var index = 0; index < this._waitingRenderList.length; index++) {
@@ -49,64 +53,41 @@
         if (!this.renderList || this.renderList.length == 0) {
             return;
         }
-        
-        if (!this._opaqueSubMeshes) {
-            // Smart arrays
-            this._opaqueSubMeshes = new BABYLON.Tools.SmartArray(256);
-            this._transparentSubMeshes = new BABYLON.Tools.SmartArray(256);
-            this._alphaTestSubMeshes = new BABYLON.Tools.SmartArray(256);
-        }
-        
+
         // Bind
         engine.bindFramebuffer(this._texture);
 
         // Clear
         engine.clear(scene.clearColor, true, true);
-        
-        // Dispatch subMeshes
-        this._opaqueSubMeshes.reset();
-        this._transparentSubMeshes.reset();
-        this._alphaTestSubMeshes.reset();
-        
+
+        this._renderingManager.reset();
+
         for (var meshIndex = 0; meshIndex < this.renderList.length; meshIndex++) {
             var mesh = this.renderList[meshIndex];
 
             if (mesh.isEnabled() && mesh.isVisible) {
                 for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
                     var subMesh = mesh.subMeshes[subIndex];
-                    var material = subMesh.getMaterial();
-                    
-                    if (material.needAlphaTesting()) { // Alpha test
-                        this._alphaTestSubMeshes.push(subMesh);
-                    } else if (material.needAlphaBlending()) { // Transparent
-                        if (material.alpha > 0) {
-                            this._transparentSubMeshes.push(subMesh); // Opaque
-                        }
-                    } else {
-                        this._opaqueSubMeshes.push(subMesh);
-                    }
+                    scene._activeVertices += subMesh.verticesCount;
+                    this._renderingManager.dispatch(subMesh);
                 }
             }
         }
-        
+
         // Render
-        if (this.customRenderFunction) {
-            this.customRenderFunction(this._opaqueSubMeshes, this._alphaTestSubMeshes, this._transparentSubMeshes, this.renderList);
-        } else {
-            scene._localRender(this._opaqueSubMeshes, this._alphaTestSubMeshes, this._transparentSubMeshes, this.renderList);
-        }
+        this._renderingManager.render(this.customRenderFunction, null, this.renderList, this.renderParticles);
 
         // Unbind
         engine.unBindFramebuffer(this._texture);
-        
+
         if (this.onAfterRender) {
             this.onAfterRender();
         }
     };
-    
+
     BABYLON.RenderTargetTexture.prototype.clone = function () {
         var textureSize = this.getSize();
-        var newTexture = new BABYLON.DynamicTexture(this.name, textureSize.width, this._scene, this._generateMipMaps);
+        var newTexture = new BABYLON.RenderTargetTexture(this.name, textureSize.width, this._scene, this._generateMipMaps);
 
         // Base texture
         newTexture.hasAlpha = this.hasAlpha;

+ 47 - 4
Babylon/Mesh/babylon.mesh.js

@@ -22,6 +22,8 @@
         this.subMeshes = [];
 
         this._renderId = 0;
+
+        this._onBeforeRenderCallbacks = [];
         
         // Animations
         this.animations = [];
@@ -75,6 +77,8 @@
     BABYLON.Mesh.prototype.onDispose = null;
 
     BABYLON.Mesh.prototype.skeleton = null;
+    
+    BABYLON.Mesh.prototype.renderingGroupId = 0;
 
     // Properties
 
@@ -188,6 +192,29 @@
     };
     
     // Methods
+    BABYLON.Mesh.prototype.markAsDirty = function (property) {
+        if (property === "rotation") {
+            this.rotationQuaternion = null;
+        }
+    };
+    
+    BABYLON.Mesh.prototype.refreshBoundingInfo = function () {
+        var data = this.getVerticesData(BABYLON.VertexBuffer.PositionKind);
+
+        if (!data) {
+            return;
+        }
+
+        var extend = BABYLON.Tools.ExtractMinAndMax(data, 0, this._totalVertices);
+        this._boundingInfo = new BABYLON.BoundingInfo(extend.minimum, extend.maximum);
+
+        for (var index = 0; index < this.subMeshes.length; index++) {
+            this.subMeshes[index].refreshBoundingInfo();
+        }
+        
+        this._updateBoundingInfo();
+    };
+
     BABYLON.Mesh.prototype._updateBoundingInfo = function() {
         if (this._boundingInfo) {
             this._scaleFactor = Math.max(this.scaling.x, this.scaling.y);
@@ -365,12 +392,28 @@
         // Draw order
         engine.draw(useTriangles, useTriangles ? subMesh.indexStart : 0, useTriangles ? subMesh.indexCount : subMesh.linesIndexCount);
     };
+    
+    BABYLON.Mesh.prototype.registerBeforeRender = function (func) {
+        this._onBeforeRenderCallbacks.push(func);
+    };
+
+    BABYLON.Mesh.prototype.unregisterBeforeRender = function (func) {
+        var index = this._onBeforeRenderCallbacks.indexOf(func);
+
+        if (index > -1) {
+            this._onBeforeRenderCallbacks.splice(index, 1);
+        }
+    };
 
     BABYLON.Mesh.prototype.render = function (subMesh) {
         if (!this._vertexBuffers || !this._indexBuffer) {
             return;
         }
-
+        
+        for (var callbackIndex = 0; callbackIndex < this._onBeforeRenderCallbacks.length; callbackIndex++) {
+            this._onBeforeRenderCallbacks[callbackIndex]();
+        }
+        
         // World
         var world = this.getWorldMatrix();
 
@@ -471,7 +514,7 @@
                 BABYLON.SceneLoader._ImportGeometry(JSON.parse(data), that);
                 that.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_LOADED;
                 that._scene._removePendingData(that);
-            });
+            }, function () { }, this._scene.database);
         }
 
         return result;
@@ -507,7 +550,7 @@
     };
 
     // Geometry
-    BABYLON.Mesh.prototype.setLocalTransation = function(vector3) {
+    BABYLON.Mesh.prototype.setLocalTranslation = function(vector3) {
         this.computeWorldMatrix();
         var worldMatrix = this._worldMatrix.clone();
         worldMatrix.setTranslation(BABYLON.Vector3.Zero());
@@ -515,7 +558,7 @@
         this.position = BABYLON.Vector3.TransformCoordinates(vector3, worldMatrix);
     };
     
-    BABYLON.Mesh.prototype.getLocalTransation = function () {
+    BABYLON.Mesh.prototype.getLocalTranslation = function () {
         this.computeWorldMatrix();
         var invWorldMatrix = this._worldMatrix.clone();
         invWorldMatrix.setTranslation(BABYLON.Vector3.Zero());

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

@@ -9,9 +9,8 @@
         this.verticesCount = verticesCount;
         this.indexStart = indexStart;
         this.indexCount = indexCount;
-        
-        var extend = BABYLON.Tools.ExtractMinAndMax(this._mesh.getVerticesData(BABYLON.VertexBuffer.PositionKind), verticesStart, verticesCount);
-        this._boundingInfo = new BABYLON.BoundingInfo(extend.minimum, extend.maximum);
+
+        this.refreshBoundingInfo();
     };
     
     //Properties
@@ -38,6 +37,17 @@
     };
 
     // Methods
+    BABYLON.SubMesh.prototype.refreshBoundingInfo = function () {
+        var data = this._mesh.getVerticesData(BABYLON.VertexBuffer.PositionKind);
+
+        if (!data) {
+            return;
+        }
+
+        var extend = BABYLON.Tools.ExtractMinAndMax(data, this.verticesStart, this.verticesCount);
+        this._boundingInfo = new BABYLON.BoundingInfo(extend.minimum, extend.maximum);
+    };
+
     BABYLON.SubMesh.prototype._checkCollision = function (collider) {
         return this._boundingInfo._checkCollision(collider);
     };

+ 1 - 0
Babylon/Particles/babylon.particleSystem.js

@@ -65,6 +65,7 @@
     };
 
     // Members
+    BABYLON.ParticleSystem.prototype.renderingGroupId = 0;
     BABYLON.ParticleSystem.prototype.emitter = null;
     BABYLON.ParticleSystem.prototype.emitRate = 10;
     BABYLON.ParticleSystem.prototype.manualEmitCount = -1;

+ 82 - 0
Babylon/Rendering/babylon.renderingGroup.js

@@ -0,0 +1,82 @@
+var BABYLON = BABYLON || {};
+
+(function () {
+    BABYLON.RenderingGroup = function (index, scene) {
+        this.index = index;
+        this._scene = scene;
+        
+        this._opaqueSubMeshes = new BABYLON.Tools.SmartArray(256);
+        this._transparentSubMeshes = new BABYLON.Tools.SmartArray(256);
+        this._alphaTestSubMeshes = new BABYLON.Tools.SmartArray(256);
+    };
+
+    // Methods
+    BABYLON.RenderingGroup.prototype.render = function (customRenderFunction, beforeTransparents) {
+        if (customRenderFunction) {
+            customRenderFunction(this._opaqueSubMeshes, this._alphaTestSubMeshes, this._transparentSubMeshes, beforeTransparents);
+            return true;
+        }
+        
+        if (this._opaqueSubMeshes.length === 0 && this._alphaTestSubMeshes.length === 0 && this._transparentSubMeshes === 0) {
+            return false;
+        }
+        var engine = this._scene.getEngine();
+        // Opaque
+        var subIndex;
+        var submesh;
+        for (subIndex = 0; subIndex < this._opaqueSubMeshes.length; subIndex++) {
+            submesh = this._opaqueSubMeshes.data[subIndex];
+            this._activeVertices += submesh.verticesCount;
+
+            submesh.render();
+        }
+
+        // Alpha test
+        engine.setAlphaTesting(true);
+        for (subIndex = 0; subIndex < this._alphaTestSubMeshes.length; subIndex++) {
+            submesh = this._alphaTestSubMeshes.data[subIndex];
+            this._activeVertices += submesh.verticesCount;
+
+            submesh.render();
+        }
+        engine.setAlphaTesting(false);
+
+        if (beforeTransparents) {
+            beforeTransparents();
+        }
+
+        // Transparent
+        engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE);
+        for (subIndex = 0; subIndex < this._transparentSubMeshes.length; subIndex++) {
+            submesh = this._transparentSubMeshes.data[subIndex];
+            this._activeVertices += submesh.verticesCount;
+
+            submesh.render();
+        }
+        engine.setAlphaMode(BABYLON.Engine.ALPHA_DISABLE);
+
+        return true;
+    };
+
+
+    BABYLON.RenderingGroup.prototype.prepare = function () {
+        this._opaqueSubMeshes.reset();
+        this._transparentSubMeshes.reset();
+        this._alphaTestSubMeshes.reset();
+    };
+
+    BABYLON.RenderingGroup.prototype.dispatch = function (subMesh) {
+        var material = subMesh.getMaterial();
+        var mesh = subMesh.getMesh();
+
+        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);
+        }
+    };
+})();

+ 64 - 0
Babylon/Rendering/babylon.renderingManager.js

@@ -0,0 +1,64 @@
+var BABYLON = BABYLON || {};
+
+(function () {
+    BABYLON.RenderingManager = function (scene) {
+        this._scene = scene;
+        this._renderingGroups = [];
+    };
+
+    // Methods
+    BABYLON.RenderingManager.prototype._renderParticles = function (index, activeMeshes) {
+        // Particles
+        var beforeParticlesDate = new Date();
+        for (var particleIndex = 0; particleIndex < this._scene._activeParticleSystems.length; particleIndex++) {
+            var particleSystem = this._scene._activeParticleSystems.data[particleIndex];
+
+            if (particleSystem.renderingGroupId !== index) {
+                continue;
+            }
+
+            if (!particleSystem.emitter.position || !activeMeshes || activeMeshes.indexOf(particleSystem.emitter) !== -1) {
+                this._scene._activeParticles += particleSystem.render();
+            }
+        }
+        this._scene._particlesDuration += new Date() - beforeParticlesDate;
+    };
+
+    BABYLON.RenderingManager.prototype.render = function (customRenderFunction, beforeTransparents, activeMeshes, renderParticles) {
+        for (var index = 0 ; index < BABYLON.RenderingManager.MAX_RENDERINGGROUPS; index++) {
+            var renderingGroup = this._renderingGroups[index];
+            if (index > 0) {
+                this._scene.getEngine().clear(0, false, true);
+            }
+
+            if (renderingGroup && !renderingGroup.render(customRenderFunction, index == 0 ? beforeTransparents  : null)) {
+                this._renderingGroups.splice(index, 1);
+            }
+
+            if (renderParticles) {
+                this._renderParticles(index, activeMeshes);
+            }
+        }
+    };
+
+    BABYLON.RenderingManager.prototype.reset = function () {
+        for (var index in this._renderingGroups) {
+            var renderingGroup = this._renderingGroups[index];
+            renderingGroup.prepare();
+        }
+    };
+
+    BABYLON.RenderingManager.prototype.dispatch = function (subMesh) {
+        var mesh = subMesh.getMesh();
+        var renderingGroupId = mesh.renderingGroupId || 0;
+
+        if (!this._renderingGroups[renderingGroupId]) {
+            this._renderingGroups[renderingGroupId] = new BABYLON.RenderingGroup(renderingGroupId, this._scene);
+        }
+
+        this._renderingGroups[renderingGroupId].dispatch(subMesh);
+    };
+    
+    // Statics
+    BABYLON.RenderingManager.MAX_RENDERINGGROUPS = 4;
+})();

+ 4 - 4
Babylon/Tools/babylon.database.js

@@ -112,7 +112,7 @@
                 request.onupgradeneeded = function (event) {
                     that.db = event.target.result;
                     var scenesStore = that.db.createObjectStore("scenes", { keyPath: "sceneUrl" });
-                    var scenesStore = that.db.createObjectStore("versions", { keyPath: "sceneUrl" });
+                    var versionsStore = that.db.createObjectStore("versions", { keyPath: "sceneUrl" });
                     var texturesStore = that.db.createObjectStore("textures", { keyPath: "textureUrl" });
                 };
             }
@@ -244,7 +244,7 @@
                             // Put the blob into the dabase
                             var addRequest = transaction.objectStore("textures").put(newTexture);
                             addRequest.onsuccess = function (event) {
-
+                                console.log("");
                             };
                             addRequest.onerror = function (event) {
                                 generateBlobUrl();
@@ -363,7 +363,7 @@
                 // Put the scene into the database
                 var addRequest = transaction.objectStore("versions").put(newVersion);
                 addRequest.onsuccess = function (event) {
-
+                    console.log("");
                 };
                 addRequest.onerror = function (event) {
                     console.log("Error in DB add version request in BABYLON.Database.");
@@ -475,7 +475,7 @@
                             // Put the scene into the database
                             var addRequest = transaction.objectStore("scenes").put(newScene);
                             addRequest.onsuccess = function (event) {
-
+                                console.log("");
                             };
                             addRequest.onerror = function (event) {
                                 console.log("Error in DB add scene request in BABYLON.Database.");

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

@@ -868,6 +868,21 @@
         return new BABYLON.Quaternion(this.x * value, this.y * value, this.z * value, this.w * value);
     };
 
+    BABYLON.Quaternion.prototype.multiply = function (q1) {
+        var result = new BABYLON.Quaternion(0, 0, 0, 1.0);
+
+        this.multiplyToRef(q1, result);
+
+        return result;
+    };
+
+    BABYLON.Quaternion.prototype.multiplyToRef = function(q1, result) {
+        result.x = this.x * q1.w + this.y * q1.z - this.z * q1.y + this.w * q1.x;
+        result.y = -this.x * q1.z + this.y * q1.w + this.z * q1.x + this.w * q1.y;
+        result.z = this.x * q1.y - this.y * q1.x + this.z * q1.w + this.w * q1.z;
+        result.w = -this.x * q1.x - this.y * q1.y - this.z * q1.z + this.w * q1.w;
+    };
+
     BABYLON.Quaternion.prototype.length = function () {
         return Math.sqrt((this.x * this.x) + (this.y * this.y) + (this.z * this.z) + (this.w * this.w));
     };

+ 3 - 3
Babylon/Tools/babylon.sceneLoader.js

@@ -277,10 +277,10 @@
         mesh.id = parsedMesh.id;
 
         mesh.position = BABYLON.Vector3.FromArray(parsedMesh.position);
-        if (parsedMesh.rotation.length == 3) {
+        if (parsedMesh.rotation) {
             mesh.rotation = BABYLON.Vector3.FromArray(parsedMesh.rotation);
-        } else {
-            mesh.rotationQuaternion = BABYLON.Quaternion.FromArray(parsedMesh.rotation);
+        } else if (parsedMesh.rotationQuaternion) {
+            mesh.rotationQuaternion = BABYLON.Quaternion.FromArray(parsedMesh.rotationQuaternion);
         }
         mesh.scaling = BABYLON.Vector3.FromArray(parsedMesh.scaling);
         

+ 29 - 78
Babylon/babylon.scene.js

@@ -46,13 +46,13 @@
 
         // Internal smart arrays
         this._activeMeshes = new BABYLON.Tools.SmartArray(256);
-        this._opaqueSubMeshes = new BABYLON.Tools.SmartArray(256);
-        this._transparentSubMeshes = new BABYLON.Tools.SmartArray(256);
-        this._alphaTestSubMeshes = new BABYLON.Tools.SmartArray(256);
         this._processedMaterials = new BABYLON.Tools.SmartArray(256);
         this._renderTargets = new BABYLON.Tools.SmartArray(256);
         this._activeParticleSystems = new BABYLON.Tools.SmartArray(256);
         this._activeSkeletons = new BABYLON.Tools.SmartArray(32);
+        
+        // Rendering groups
+        this._renderingManager = new BABYLON.RenderingManager(this);
 
         // Materials
         this.materials = [];
@@ -230,16 +230,15 @@
     };
 
     // Animations
-    BABYLON.Scene.prototype.beginAnimation = function (target, from, to, loop, speedRatio) {
+    BABYLON.Scene.prototype.beginAnimation = function (target, from, to, loop, speedRatio, onAnimationEnd) {
         if (speedRatio === undefined) {
             speedRatio = 1.0;
         }
-
         // Local animations
         if (target.animations) {
             this.stopAnimation(target);
 
-            var animatable = new BABYLON._Animatable(target, from, to, loop, speedRatio);
+            var animatable = new BABYLON._Animatable(target, from, to, loop, speedRatio, onAnimationEnd);
 
             this._activeAnimatables.push(animatable);
         }
@@ -248,9 +247,10 @@
         if (target.getAnimatables) {
             var animatables = target.getAnimatables();
             for (var index = 0; index < animatables.length; index++) {
-                this.beginAnimation(animatables[index], from, to, loop, speedRatio);
+                this.beginAnimation(animatables[index], from, to, loop, speedRatio, onAnimationEnd);
             }
         }
+
     };
 
     BABYLON.Scene.prototype.stopAnimation = function (target) {
@@ -407,24 +407,15 @@
                 }
 
                 // 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._activeVertices += subMesh.verticesCount;
+                this._renderingManager.dispatch(subMesh);
             }
         }
     };
 
     BABYLON.Scene.prototype._evaluateActiveMeshes = function () {
         this._activeMeshes.reset();
-        this._opaqueSubMeshes.reset();
-        this._transparentSubMeshes.reset();
-        this._alphaTestSubMeshes.reset();
+        this._renderingManager.reset();
         this._processedMaterials.reset();
         this._renderTargets.reset();
         this._activeParticleSystems.reset();
@@ -529,61 +520,6 @@
         this._particlesDuration += new Date() - beforeParticlesDate;
     };
 
-    BABYLON.Scene.prototype._localRender = function (opaqueSubMeshes, alphaTestSubMeshes, transparentSubMeshes, activeMeshes) {
-        var engine = this._engine;
-        // Opaque
-        var subIndex;
-        var submesh;
-        for (subIndex = 0; subIndex < opaqueSubMeshes.length; subIndex++) {
-            submesh = opaqueSubMeshes.data[subIndex];
-            this._activeVertices += submesh.verticesCount;
-
-            submesh.render();
-        }
-
-        // Alpha test
-        engine.setAlphaTesting(true);
-        for (subIndex = 0; subIndex < alphaTestSubMeshes.length; subIndex++) {
-            submesh = alphaTestSubMeshes.data[subIndex];
-            this._activeVertices += submesh.verticesCount;
-
-            submesh.render();
-        }
-        engine.setAlphaTesting(false);
-
-        if (!activeMeshes) {
-            // Sprites
-            var beforeSpritessDate = new Date();
-            for (var index = 0; index < this.spriteManagers.length; index++) {
-                var spriteManager = this.spriteManagers[index];
-
-                spriteManager.render();
-            }
-            this._spritesDuration = new Date() - beforeSpritessDate;
-        }
-
-        // Transparent
-        engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE);
-        for (subIndex = 0; subIndex < transparentSubMeshes.length; subIndex++) {
-            submesh = transparentSubMeshes.data[subIndex];
-            this._activeVertices += submesh.verticesCount;
-
-            submesh.render();
-        }
-        engine.setAlphaMode(BABYLON.Engine.ALPHA_DISABLE);
-
-        // Particles
-        var beforeParticlesDate = new Date();
-        for (var particleIndex = 0; particleIndex < this._activeParticleSystems.length; particleIndex++) {
-            var particleSystem = this._activeParticleSystems.data[particleIndex];
-
-            if (!particleSystem.emitter.position || !activeMeshes || activeMeshes.indexOf(particleSystem.emitter) !== -1) {
-                this._activeParticles += particleSystem.render();
-            }
-        }
-        this._particlesDuration += new Date() - beforeParticlesDate;
-    };
-
     BABYLON.Scene.prototype.render = function () {
         var startDate = new Date();
         this._particlesDuration = 0;
@@ -667,7 +603,17 @@
         }
 
         // Render
-        this._localRender(this._opaqueSubMeshes, this._alphaTestSubMeshes, this._transparentSubMeshes);
+        var that = this;
+        this._renderingManager.render(null, function() {
+            // Sprites
+            var beforeSpritessDate = new Date();
+            for (var index = 0; index < that.spriteManagers.length; index++) {
+                var spriteManager = that.spriteManagers[index];
+
+                spriteManager.render();
+            }
+            that._spritesDuration = new Date() - beforeSpritessDate;
+        }, null, true);
 
         // Foregrounds
         if (this.layers.length) {
@@ -863,7 +809,7 @@
         return BABYLON.Ray.CreateNew(x, y, engine.getRenderWidth() * engine.getHardwareScalingLevel(), engine.getRenderHeight() * engine.getHardwareScalingLevel(), world ? world : BABYLON.Matrix.Identity(), this._viewMatrix, this._projectionMatrix);
     };
 
-    BABYLON.Scene.prototype.pick = function (x, y) {
+    BABYLON.Scene.prototype.pick = function (x, y, predicate) {
         var distance = Number.MAX_VALUE;
         var pickedPoint = null;
         var pickedMesh = null;
@@ -871,9 +817,14 @@
         for (var meshIndex = 0; meshIndex < this.meshes.length; meshIndex++) {
             var mesh = this.meshes[meshIndex];
 
-            if (!mesh.isEnabled() || !mesh.isVisible || !mesh.isPickable) {
-                continue;
+            if (predicate) {
+                if (!predicate(mesh)) {
+                    continue;
+                }
             }
+            else if (!mesh.isEnabled() || !mesh.isVisible || !mesh.isPickable) {
+                continue;
+            }                        
 
             var world = mesh.getWorldMatrix();
             var ray = this.createPickingRay(x, y, world);

+ 1 - 1
Exporters/Blender/io_export_babylon.py

@@ -574,7 +574,7 @@ class Export_babylon(bpy.types.Operator, ExportHelper):
             billboardMode = 0
             
         Export_babylon.write_vector(file_handler, "position", loc)
-        Export_babylon.write_quaternion(file_handler, "rotation", rot)
+        Export_babylon.write_vectorScaled(file_handler, "rotation", rot.to_euler("XYZ"), -1)
         Export_babylon.write_vector(file_handler, "scaling", scale)
         Export_babylon.write_bool(file_handler, "isVisible", object.is_visible(scene))
         Export_babylon.write_bool(file_handler, "isEnabled", True)

+ 3 - 0
Exporters/FBX - OBJ/BabylonExport/BabylonExport.csproj

@@ -200,6 +200,9 @@
     <Compile Include="Tools.cs" />
   </ItemGroup>
   <ItemGroup>
+    <Content Include="generateAll.bat">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </Content>
     <None Include="Exporters\Blender\io_export_babylon.py" />
     <None Include="Refs\xnafx40_redist.msi" />
     <None Include="Test scenes\Chimie\BalanceDM.dds" />

+ 1 - 1
Exporters/FBX - OBJ/BabylonExport/Exporters/Blender/io_export_babylon.py

@@ -574,7 +574,7 @@ class Export_babylon(bpy.types.Operator, ExportHelper):
             billboardMode = 0
             
         Export_babylon.write_vector(file_handler, "position", loc)
-        Export_babylon.write_quaternion(file_handler, "rotation", rot)
+        Export_babylon.write_vectorScaled(file_handler, "rotation", rot.to_euler("XYZ"), -1)
         Export_babylon.write_vector(file_handler, "scaling", scale)
         Export_babylon.write_bool(file_handler, "isVisible", object.is_visible(scene))
         Export_babylon.write_bool(file_handler, "isEnabled", True)

+ 1 - 1
Exporters/FBX - OBJ/BabylonExport/Exporters/MXB/NovaExporter.cs

@@ -331,7 +331,7 @@ namespace BabylonExport.Exporters
             }
 
             // Rotation
-            if (!DumpInterpolator("Rotation animation", "rotation", novaObject.RotationInterpolator, scene, animations))
+            if (!DumpInterpolator("Rotation animation", "rotationQuaternion", novaObject.RotationInterpolator, scene, animations))
             {
                 DumpInterpolator("RotationX animation", "rotation.x", novaObject.RotationXInterpolator, scene,
                     animations, -novaObject.Determinant);

BIN
Exporters/FBX - OBJ/BabylonExporter.zip


Різницю між файлами не показано, бо вона завелика
+ 2 - 2
Samples/babylon.js


+ 19 - 5
Samples/index.html

@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-    <title>Babylon Engine for HTML5</title>
+    <title>Babylon.js</title>
     <script>
         (function (i, s, o, g, r, a, m) {
             i['GoogleAnalyticsObject'] = r; i[r] = i[r] || function () {
@@ -34,6 +34,9 @@
     <script src="Babylon/Cameras/babylon.freeCamera.js"></script>
     <script src="Babylon/Cameras/babylon.touchCamera.js"></script>
     <script src="Babylon/Cameras/babylon.arcRotateCamera.js"></script>
+    <script src="Babylon/Cameras/babylon.deviceOrientationCamera.js"></script>
+    <script src="Babylon/Rendering/babylon.renderingManager.js"></script>
+    <script src="Babylon/Rendering/babylon.renderingGroup.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>
@@ -78,7 +81,7 @@
     <script src="Scenes/Customs/bones.js"></script>
     <script src="index.js"></script>
 </head>
-<body onload="onload();">
+<body>
     <div id="rootDiv">
         <div id="screen1">
             <div id="menuPanel">
@@ -93,6 +96,11 @@
                         FEATURES TESTS
                     </div>
                     <div id="testItems"></div>
+                    <div class="header">
+                        <br />
+                        THIRD-PARTY
+                    </div>
+                    <div id="3rdItems"></div>
                 </div>
             </div>
             <img id="back" src="Assets/BandeauEmbleme.png" />
@@ -144,6 +152,7 @@
                                     <li>Hardware scaling</li>
                                     <li>Selection octrees</li>
                                     <li><b>Offline mode (Assets are saved locally to prevent reloading them)</b></li>
+                                    <li><b>Incremental loading</b></li>
                                 </ul>
                             </li>
                             <li>
@@ -174,6 +183,7 @@
                                     <li>Billboarding</li>
                                     <li>Fullscreen mode</li>
                                     <li>Shadow Maps and Variance Shadow Maps</li>
+                                    <li>Rendering layers</li>
                                 </ul>
                             </li>
                             <li>
@@ -197,15 +207,15 @@
                                 <ul>
                                     <li>Mesh cloning</li>
                                     <li>Dynamic meshes</li>
-                                    <li><b>Height maps</b></li>       
-                                    <li>Bones</li>                             
+                                    <li><b>Height maps</b></li>
+                                    <li>Bones</li>
                                 </ul>
                             </li>
                             <li>
                                 Import:
                                 <ul>
                                     <li>Babylon scene file can be converted from <i>.OBJ</i>, <i>.FBX</i>, <i>.MXB</i></li>
-                                    <li>Exporter for Blender</li>                                    
+                                    <li>Exporter for Blender</li>
                                 </ul>
                             </li>
                         </ul>
@@ -247,6 +257,7 @@
                         </p>
                         <p>
                             <button id="touchCamera">Switch to touch camera</button>
+                            <button id="deviceOrientationCamera">Switch to device orientation camera</button>
                         </p>
                         <p id="extensions"></p>
                     </div>
@@ -260,4 +271,7 @@
         <div id="loadingText" class="loadingText"></div>
     </div>
 </body>
+<script language="javascript">
+    onload();
+</script>
 </html>

Різницю між файлами не показано, бо вона завелика
+ 0 - 13
babylon.1.4.3.js


Різницю між файлами не показано, бо вона завелика
+ 13 - 0
babylon.1.5.0.js


+ 2 - 0
readme.md

@@ -23,6 +23,7 @@ Official web site: [www.babylonjs.com](http://www.babylonjs.com/)
  - Hardware scaling
  - Selection octrees
  - Offline mode (Assets are saved locally to prevent reloading them)
+ - Incremental loading
 - Standard material is a per pixel material that supports:
  - Diffuse lightning and texture
  - Ambient lightning and texture
@@ -45,6 +46,7 @@ Official web site: [www.babylonjs.com](http://www.babylonjs.com/)
  - Billboarding
  - Fullscreen mode
  - Shadow Maps and Variance Shadow Maps
+ - Rendering layers
 -  Textures:
  - Render target textures
  - Dynamic textures (canvas)

+ 10 - 0
what's new.md

@@ -1,5 +1,15 @@
 Changes list
 ============
+- 1.5.0:
+ - **Major updates**
+ - New ```DeviceOrientationCamera``` that supports W3C DeviceOrientations events ([deltakosh](http://www.github.com/deltakosh))
+ - Incremental loading support for meshes and textures ([deltakosh](http://www.github.com/deltakosh))
+ - New API online page to convert .babylon files to .incremental.babylon files ([pierlag](https://github.com/pierlag))
+ - New ```mesh.renderingGroupId``` and ```particleSystem.renderingGroupId``` properties to support rendering layers ([deltakosh](http://www.github.com/deltakosh))
+ - **Updates**
+ - New ```predicate``` parameter for ```scene.pick``` function in order to be able to select pickable meshes ([deltakosh](http://www.github.com/deltakosh)) 
+ - New ```mesh.refreshBoundingInfo()``` method ([deltakosh](http://www.github.com/deltakosh)) 
+ - New ```onAnimationEnd``` parameter for animations ([deltakosh](http://www.github.com/deltakosh)) 
 - 1.4.3:
  - **Updates**
  - New ```mesh.setLocalTranslation``` and ```mesh.getLocalTranslation``` functions ([deltakosh](http://www.github.com/deltakosh))