Переглянути джерело

Merge https://github.com/BabylonJS/Babylon.js

Conflicts:
	Babylon/Materials/textures/babylon.texture.js
	Babylon/Materials/textures/babylon.texture.ts
	Babylon/babylon.engine.js
	Babylon/babylon.engine.ts
julien-moreau 11 роки тому
батько
коміт
d54cb710e8
100 змінених файлів з 1926 додано та 489 видалено
  1. 1 0
      Babylon/.gitignore
  2. 4 0
      Babylon/Actions/babylon.action.js
  3. 5 0
      Babylon/Actions/babylon.action.ts
  4. 95 0
      Babylon/Cameras/babylon.arcRotateCamera.js
  5. 95 1
      Babylon/Cameras/babylon.arcRotateCamera.ts
  6. 2 2
      Babylon/Cameras/babylon.camera.js
  7. 3 5
      Babylon/Cameras/babylon.camera.ts
  8. 1 1
      Babylon/Cameras/babylon.oculusCamera.ts
  9. 37 0
      Babylon/Cameras/babylon.vrDeviceOrientationCamera.js
  10. 29 0
      Babylon/Cameras/babylon.vrDeviceOrientationCamera.ts
  11. 80 0
      Babylon/Cameras/babylon.webVRCamera.js
  12. 76 0
      Babylon/Cameras/babylon.webVRCamera.ts
  13. 1 1
      Babylon/LensFlare/babylon.lensFlareSystem.js
  14. 1 1
      Babylon/LensFlare/babylon.lensFlareSystem.ts
  15. 1 1
      Babylon/Lights/Shadows/babylon.shadowGenerator.js
  16. 1 1
      Babylon/Lights/Shadows/babylon.shadowGenerator.ts
  17. 1 1
      Babylon/Lights/babylon.light.js
  18. 1 1
      Babylon/Lights/babylon.light.ts
  19. 142 23
      Babylon/Loading/Plugins/babylon.babylonFileLoader.js
  20. 185 54
      Babylon/Loading/Plugins/babylon.babylonFileLoader.ts
  21. 13 0
      Babylon/Materials/babylon.effect.js
  22. 13 0
      Babylon/Materials/babylon.effect.ts
  23. 2 2
      Babylon/Materials/babylon.shaderMaterial.ts
  24. 57 15
      Babylon/Materials/babylon.standardMaterial.js
  25. 62 15
      Babylon/Materials/babylon.standardMaterial.ts
  26. 1 0
      Babylon/Materials/textures/babylon.renderTargetTexture.ts
  27. 10 0
      Babylon/Materials/textures/babylon.texture.js
  28. 8 0
      Babylon/Materials/textures/babylon.texture.ts
  29. 53 1
      Babylon/Math/babylon.math.js
  30. 54 2
      Babylon/Math/babylon.math.ts
  31. 2 1
      Babylon/Mesh/babylon.abstractMesh.js
  32. 2 1
      Babylon/Mesh/babylon.abstractMesh.ts
  33. 10 0
      Babylon/Mesh/babylon.geometry.js
  34. 10 0
      Babylon/Mesh/babylon.geometry.ts
  35. 25 2
      Babylon/Mesh/babylon.mesh.js
  36. 29 2
      Babylon/Mesh/babylon.mesh.ts
  37. 11 0
      Babylon/Mesh/babylon.vertexBuffer.js
  38. 11 0
      Babylon/Mesh/babylon.vertexBuffer.ts
  39. 9 13
      Babylon/Particles/babylon.particleSystem.js
  40. 9 13
      Babylon/Particles/babylon.particleSystem.ts
  41. 23 6
      Babylon/Physics/Plugins/babylon.cannonJSPlugin.js
  42. 37 9
      Babylon/Physics/Plugins/babylon.oimoJSPlugin.js
  43. 17 14
      Babylon/Physics/Plugins/babylon.oimoJSPlugin.ts
  44. 10 65
      Babylon/PostProcess/RenderPipeline/babylon.postProcessRenderEffect.js
  45. 12 67
      Babylon/PostProcess/RenderPipeline/babylon.postProcessRenderEffect.ts
  46. 10 4
      Babylon/PostProcess/RenderPipeline/babylon.postProcessRenderPipeline.js
  47. 8 6
      Babylon/PostProcess/RenderPipeline/babylon.postProcessRenderPipeline.ts
  48. 7 7
      Babylon/PostProcess/RenderPipeline/babylon.postProcessRenderPipelineManager.js
  49. 14 14
      Babylon/PostProcess/RenderPipeline/babylon.postProcessRenderPipelineManager.ts
  50. 7 2
      Babylon/PostProcess/babylon.postProcess.js
  51. 8 2
      Babylon/PostProcess/babylon.postProcess.ts
  52. 6 1
      Babylon/PostProcess/babylon.postProcessManager.js
  53. 6 1
      Babylon/PostProcess/babylon.postProcessManager.ts
  54. 1 1
      Babylon/Shaders/anaglyph.fragment.fx
  55. 1 1
      Babylon/Shaders/blackAndWhite.fragment.fx
  56. 1 1
      Babylon/Shaders/blur.fragment.fx
  57. 1 1
      Babylon/Shaders/color.fragment.fx
  58. 1 1
      Babylon/Shaders/color.vertex.fx
  59. 1 1
      Babylon/Shaders/convolution.fragment.fx
  60. 44 8
      Babylon/Shaders/default.fragment.fx
  61. 1 1
      Babylon/Shaders/default.vertex.fx
  62. 1 1
      Babylon/Shaders/displayPass.fragment.fx
  63. 1 1
      Babylon/Shaders/filter.fragment.fx
  64. 1 1
      Babylon/Shaders/fxaa.fragment.fx
  65. 1 1
      Babylon/Shaders/layer.fragment.fx
  66. 1 1
      Babylon/Shaders/layer.vertex.fx
  67. 54 1
      Babylon/Shaders/legacydefault.fragment.fx
  68. 1 1
      Babylon/Shaders/legacydefault.vertex.fx
  69. 1 1
      Babylon/Shaders/lensFlare.fragment.fx
  70. 1 1
      Babylon/Shaders/lensFlare.vertex.fx
  71. 1 3
      Babylon/Shaders/oculusDistortionCorrection.fragment.fx
  72. 1 1
      Babylon/Shaders/outline.fragment.fx
  73. 1 1
      Babylon/Shaders/outline.vertex.fx
  74. 1 1
      Babylon/Shaders/particles.fragment.fx
  75. 1 1
      Babylon/Shaders/particles.vertex.fx
  76. 1 1
      Babylon/Shaders/pass.fragment.fx
  77. 1 1
      Babylon/Shaders/postprocess.vertex.fx
  78. 1 1
      Babylon/Shaders/refraction.fragment.fx
  79. 1 1
      Babylon/Shaders/shadowMap.fragment.fx
  80. 1 1
      Babylon/Shaders/shadowMap.vertex.fx
  81. 1 1
      Babylon/Shaders/sprites.fragment.fx
  82. 1 1
      Babylon/Shaders/sprites.vertex.fx
  83. 1 1
      Babylon/Sprites/babylon.sprite.ts
  84. 86 0
      Babylon/Tools/babylon.assetsManager.js
  85. 84 0
      Babylon/Tools/babylon.assetsManager.ts
  86. 1 7
      Babylon/Tools/babylon.database.js
  87. 1 7
      Babylon/Tools/babylon.database.ts
  88. 28 0
      Babylon/Tools/babylon.sceneSerializer.js
  89. 28 0
      Babylon/Tools/babylon.sceneSerializer.ts
  90. 13 0
      Babylon/Tools/babylon.tools.js
  91. 1 1
      Babylon/Tools/babylon.tools.tga.js
  92. 1 1
      Babylon/Tools/babylon.tools.tga.ts
  93. 14 1
      Babylon/Tools/babylon.tools.ts
  94. 67 29
      Babylon/babylon.engine.js
  95. 70 30
      Babylon/babylon.engine.ts
  96. 10 0
      Babylon/babylon.mixins.ts
  97. 2 0
      Babylon/babylon.node.ts
  98. 37 7
      Babylon/babylon.scene.js
  99. 40 10
      Babylon/babylon.scene.ts
  100. 0 0
      Exporters/3ds Max/BabylonExport.Entities/BabylonExport.Entities.csproj

+ 1 - 0
Babylon/.gitignore

@@ -0,0 +1 @@
+*.d.ts

+ 4 - 0
Babylon/Actions/babylon.action.js

@@ -45,6 +45,10 @@
             this._nextActiveAction.execute(evt);
 
             if (this._nextActiveAction._child) {
+                if (!this._nextActiveAction._child._actionManager) {
+                    this._nextActiveAction._child._actionManager = this._actionManager;
+                }
+
                 this._nextActiveAction = this._nextActiveAction._child;
             } else {
                 this._nextActiveAction = this;

+ 5 - 0
Babylon/Actions/babylon.action.ts

@@ -53,6 +53,11 @@
             this._nextActiveAction.execute(evt);
 
             if (this._nextActiveAction._child) {
+
+                if (!this._nextActiveAction._child._actionManager) {
+                    this._nextActiveAction._child._actionManager = this._actionManager;
+                }
+
                 this._nextActiveAction = this._nextActiveAction._child;
             } else {
                 this._nextActiveAction = this;

+ 95 - 0
Babylon/Cameras/babylon.arcRotateCamera.js

@@ -40,6 +40,10 @@ var BABYLON;
             this._previousPosition = BABYLON.Vector3.Zero();
             this._collisionVelocity = BABYLON.Vector3.Zero();
             this._newPosition = BABYLON.Vector3.Zero();
+            // Pinch
+            // value for pinch step scaling
+            // set to 20 by default
+            this.pinchPrecision = 20;
 
             this.getViewMatrix();
         }
@@ -81,6 +85,13 @@ var BABYLON;
             var previousPosition;
             var pointerId;
 
+            // to know if pinch started
+            var pinchStarted = false;
+
+            // two pinch point on X
+            // that will use for find if user action is pinch open or pinch close
+            var pinchPointX1, pinchPointX2;
+
             if (this._attachedElement) {
                 return;
             }
@@ -123,6 +134,11 @@ var BABYLON;
                         return;
                     }
 
+                    // return pinch is started
+                    if (pinchStarted) {
+                        return;
+                    }
+
                     var offsetX = evt.clientX - previousPosition.x;
                     var offsetY = evt.clientY - previousPosition.y;
 
@@ -144,6 +160,11 @@ var BABYLON;
                         return;
                     }
 
+                    // return pinch is started
+                    if (pinchStarted) {
+                        return;
+                    }
+
                     var offsetX = evt.movementX || evt.mozMovementX || evt.webkitMovementX || evt.msMovementX || 0;
                     var offsetY = evt.movementY || evt.mozMovementY || evt.webkitMovementY || evt.msMovementY || 0;
 
@@ -242,6 +263,70 @@ var BABYLON;
                     previousPosition = null;
                     pointerId = null;
                 };
+
+                this._touchStart = function (event) {
+                    if (event.touches.length == 2) {
+                        //-- start pinch if two fingers on the screen
+                        pinchStarted = true;
+                        _this._pinchStart(event);
+                    }
+                };
+                this._touchMove = function (event) {
+                    if (pinchStarted) {
+                        //-- make scaling
+                        _this._pinchMove(event);
+                    }
+                };
+                this._touchEnd = function (event) {
+                    if (pinchStarted) {
+                        //-- end of pinch
+                        _this._pinchEnd(event);
+                    }
+                };
+
+                this._pinchStart = function (event) {
+                    // save origin touch point
+                    pinchPointX1 = event.touches[0].clientX;
+                    pinchPointX2 = event.touches[1].clientX;
+
+                    // block the camera
+                    // if not it rotate around target during pinch
+                    pinchStarted = true;
+                };
+                this._pinchMove = function (event) {
+                    // variable for new camera's radius
+                    var delta = 0;
+
+                    // variables to know if pinch open or pinch close
+                    var direction = 1;
+                    var distanceXOrigine, distanceXNow;
+
+                    if (event.touches.length != 2)
+                        return;
+
+                    // calculate absolute distances of the two fingers
+                    distanceXOrigine = Math.abs(pinchPointX1 - pinchPointX2);
+                    distanceXNow = Math.abs(event.touches[0].clientX - event.touches[1].clientX);
+
+                    // if distanceXNow < distanceXOrigine -> pinch close so direction = -1
+                    if (distanceXNow < distanceXOrigine) {
+                        direction = -1;
+                    }
+
+                    // calculate new radius
+                    delta = (_this.pinchPrecision / (_this.wheelPrecision * 40)) * direction;
+
+                    // set new radius
+                    _this.inertialRadiusOffset += delta;
+
+                    // save origin touch point
+                    pinchPointX1 = event.touches[0].clientX;
+                    pinchPointX2 = event.touches[1].clientX;
+                };
+                this._pinchEnd = function (event) {
+                    // cancel pinch and deblock camera rotation
+                    pinchStarted = false;
+                };
             }
 
             element.addEventListener(eventPrefix + "down", this._onPointerDown, false);
@@ -254,6 +339,11 @@ var BABYLON;
             element.addEventListener('mousewheel', this._wheel, false);
             element.addEventListener('DOMMouseScroll', this._wheel, false);
 
+            // pinch
+            element.addEventListener('touchstart', this._touchStart, false);
+            element.addEventListener('touchmove', this._touchMove, false);
+            element.addEventListener('touchend', this._touchEnd, false);
+
             BABYLON.Tools.RegisterTopRootEvents([
                 { name: "keydown", handler: this._onKeyDown },
                 { name: "keyup", handler: this._onKeyUp },
@@ -276,6 +366,11 @@ var BABYLON;
             element.removeEventListener('mousewheel', this._wheel);
             element.removeEventListener('DOMMouseScroll', this._wheel);
 
+            // pinch
+            element.removeEventListener('touchstart', this._touchStart);
+            element.removeEventListener('touchmove', this._touchMove);
+            element.removeEventListener('touchend', this._touchEnd);
+
             BABYLON.Tools.UnregisterTopRootEvents([
                 { name: "keydown", handler: this._onKeyDown },
                 { name: "keyup", handler: this._onKeyUp },

+ 95 - 1
Babylon/Cameras/babylon.arcRotateCamera.ts

@@ -48,6 +48,19 @@
         private _previousBeta: number;
         private _previousRadius: number;
 
+        // Pinch
+        // value for pinch step scaling
+        // set to 20 by default
+        public pinchPrecision = 20;
+        // Event for pinch
+        private _touchStart: (e: any) => void;
+        private _touchMove: (e: any) => void;
+        private _touchEnd: (e: any) => void;
+        // Method for pinch
+        private _pinchStart: (e: any) => void;
+        private _pinchMove: (e: any) => void;
+        private _pinchEnd: (e: any) => void;
+
         constructor(name: string, public alpha: number, public beta: number, public radius: number, public target: any, scene: Scene) {
             super(name, BABYLON.Vector3.Zero(), scene);
 
@@ -93,6 +106,11 @@
         public attachControl(element: HTMLElement, noPreventDefault?: boolean): void {
             var previousPosition;
             var pointerId;
+            // to know if pinch started
+            var pinchStarted = false;
+            // two pinch point on X
+            // that will use for find if user action is pinch open or pinch close
+            var pinchPointX1, pinchPointX2;
 
             if (this._attachedElement) {
                 return;
@@ -138,6 +156,11 @@
                         return;
                     }
 
+                    // return pinch is started
+                    if (pinchStarted) {
+                        return;
+                    }
+
                     var offsetX = evt.clientX - previousPosition.x;
                     var offsetY = evt.clientY - previousPosition.y;
 
@@ -159,6 +182,11 @@
                         return;
                     }
 
+                    // return pinch is started
+                    if (pinchStarted) {
+                        return;
+                    }
+
                     var offsetX = evt.movementX || evt.mozMovementX || evt.webkitMovementX || evt.msMovementX || 0;
                     var offsetY = evt.movementY || evt.mozMovementY || evt.webkitMovementY || evt.msMovementY || 0;
 
@@ -264,6 +292,64 @@
                     previousPosition = null;
                     pointerId = null;
                 };
+
+                this._touchStart = event => {
+                    if (event.touches.length == 2) {
+                        //-- start pinch if two fingers on the screen
+                        pinchStarted = true;
+                        this._pinchStart(event);
+                    }
+                };
+                this._touchMove = event => {
+                    if (pinchStarted) {
+                        //-- make scaling
+                        this._pinchMove(event);
+                    }
+                };
+                this._touchEnd = event => {
+                    if (pinchStarted) {
+                        //-- end of pinch
+                        this._pinchEnd(event);
+                    }
+                };
+
+                this._pinchStart = event => {
+                    // save origin touch point
+                    pinchPointX1 = event.touches[0].clientX;
+                    pinchPointX2 = event.touches[1].clientX;
+                    // block the camera 
+                    // if not it rotate around target during pinch
+                    pinchStarted = true;
+                };
+                this._pinchMove = event => {
+                    // variable for new camera's radius
+                    var delta = 0;
+                    // variables to know if pinch open or pinch close
+                    var direction = 1;
+                    var distanceXOrigine, distanceXNow;
+
+                    if (event.touches.length != 2)
+                        return;
+                    // calculate absolute distances of the two fingers
+                    distanceXOrigine = Math.abs(pinchPointX1 - pinchPointX2);
+                    distanceXNow = Math.abs(event.touches[0].clientX - event.touches[1].clientX);
+
+                    // if distanceXNow < distanceXOrigine -> pinch close so direction = -1
+                    if (distanceXNow < distanceXOrigine) {
+                        direction = -1;
+                    }
+                    // calculate new radius
+                    delta = (this.pinchPrecision / (this.wheelPrecision * 40)) * direction;
+                    // set new radius
+                    this.inertialRadiusOffset += delta;
+                    // save origin touch point
+                    pinchPointX1 = event.touches[0].clientX;
+                    pinchPointX2 = event.touches[1].clientX;
+                };
+                this._pinchEnd = event => {
+                    // cancel pinch and deblock camera rotation
+                    pinchStarted = false;
+                };
             }
 
             element.addEventListener(eventPrefix + "down", this._onPointerDown, false);
@@ -275,6 +361,10 @@
             element.addEventListener("MSGestureChange", this._onGesture, false);
             element.addEventListener('mousewheel', this._wheel, false);
             element.addEventListener('DOMMouseScroll', this._wheel, false);
+            // pinch
+            element.addEventListener('touchstart', this._touchStart, false);
+            element.addEventListener('touchmove', this._touchMove, false);
+            element.addEventListener('touchend', this._touchEnd, false);
 
             Tools.RegisterTopRootEvents([
                 { name: "keydown", handler: this._onKeyDown },
@@ -297,6 +387,10 @@
             element.removeEventListener("MSGestureChange", this._onGesture);
             element.removeEventListener('mousewheel', this._wheel);
             element.removeEventListener('DOMMouseScroll', this._wheel);
+            // pinch
+            element.removeEventListener('touchstart', this._touchStart);
+            element.removeEventListener('touchmove', this._touchMove);
+            element.removeEventListener('touchend', this._touchEnd);
 
             Tools.UnregisterTopRootEvents([
                 { name: "keydown", handler: this._onKeyDown },
@@ -455,4 +549,4 @@
             this.maxZ = distance * 2;
         }
     }
-} 
+} 

+ 2 - 2
Babylon/Cameras/babylon.camera.js

@@ -18,8 +18,8 @@ var BABYLON;
             this.orthoBottom = null;
             this.orthoTop = null;
             this.fov = 0.8;
-            this.minZ = 0.1;
-            this.maxZ = 1000.0;
+            this.minZ = 1.0;
+            this.maxZ = 10000.0;
             this.inertia = 0.9;
             this.mode = Camera.PERSPECTIVE_CAMERA;
             this.isIntermediate = false;

+ 3 - 5
Babylon/Cameras/babylon.camera.ts

@@ -11,8 +11,8 @@
         public orthoBottom = null;
         public orthoTop = null;
         public fov = 0.8;
-        public minZ = 0.1;
-        public maxZ = 1000.0;
+        public minZ = 1.0;
+        public maxZ = 10000.0;
         public inertia = 0.9;
         public mode = Camera.PERSPECTIVE_CAMERA;
         public isIntermediate = false;
@@ -24,9 +24,7 @@
         public _projectionMatrix = new BABYLON.Matrix();
         private _worldMatrix: Matrix;
         public _postProcesses = new Array<PostProcess>();
-        public _postProcessesTakenIndices = [];
-        
-        public _waitingParentId: string;
+        public _postProcessesTakenIndices = [];               
 
         constructor(name: string, public position: Vector3, scene: Scene) {
             super(name, scene);

+ 1 - 1
Babylon/Cameras/babylon.oculusCamera.ts

@@ -103,7 +103,7 @@
         }
 
         // Oculus events
-        private _onOrientationEvent(evt: DeviceOrientationEvent): void {
+        public _onOrientationEvent(evt: DeviceOrientationEvent): void {
             var yaw = evt.alpha / 180 * Math.PI;
             var pitch = evt.beta / 180 * Math.PI;
             var roll = evt.gamma / 180 * Math.PI;

+ 37 - 0
Babylon/Cameras/babylon.vrDeviceOrientationCamera.js

@@ -0,0 +1,37 @@
+var __extends = this.__extends || function (d, b) {
+    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+    function __() { this.constructor = d; }
+    __.prototype = b.prototype;
+    d.prototype = new __();
+};
+var BABYLON;
+(function (BABYLON) {
+    var VRDeviceOrientationCamera = (function (_super) {
+        __extends(VRDeviceOrientationCamera, _super);
+        function VRDeviceOrientationCamera(name, position, scene) {
+            _super.call(this, name, position, scene);
+            this._alpha = 0;
+            this._beta = 0;
+            this._gamma = 0;
+        }
+        VRDeviceOrientationCamera.prototype._onOrientationEvent = function (evt) {
+            this._alpha = +evt.alpha | 0;
+            this._beta = +evt.beta | 0;
+            this._gamma = +evt.gamma | 0;
+
+            if (this._gamma < 0) {
+                this._gamma = 90 + this._gamma;
+            } else {
+                // Incline it in the correct angle.
+                this._gamma = 270 - this._gamma;
+            }
+
+            this.rotation.x = this._gamma / 180.0 * Math.PI;
+            this.rotation.y = -this._alpha / 180.0 * Math.PI;
+            this.rotation.z = this._beta / 180.0 * Math.PI;
+        };
+        return VRDeviceOrientationCamera;
+    })(BABYLON.OculusCamera);
+    BABYLON.VRDeviceOrientationCamera = VRDeviceOrientationCamera;
+})(BABYLON || (BABYLON = {}));
+//# sourceMappingURL=babylon.vrDeviceOrientationCamera.js.map

+ 29 - 0
Babylon/Cameras/babylon.vrDeviceOrientationCamera.ts

@@ -0,0 +1,29 @@
+module BABYLON {
+	export class VRDeviceOrientationCamera extends BABYLON.OculusCamera {
+		public _alpha = 0;
+		public _beta = 0;
+		public _gamma = 0;
+	
+		constructor(name: string, position: Vector3, scene: Scene) {
+			super(name, position, scene);
+		}
+
+        public _onOrientationEvent(evt: DeviceOrientationEvent): void {
+            this._alpha = +evt.alpha|0;
+            this._beta = +evt.beta|0;
+            this._gamma = +evt.gamma|0;
+
+            if (this._gamma < 0) {
+            	this._gamma = 90 + this._gamma;
+            }
+            else {
+				// Incline it in the correct angle.
+            	this._gamma = 270 - this._gamma;
+            }
+
+            this.rotation.x = this._gamma / 180.0 * Math.PI;   
+			this.rotation.y = -this._alpha / 180.0 * Math.PI;	
+			this.rotation.z	= this._beta / 180.0 * Math.PI;		
+        }
+	}
+}

+ 80 - 0
Babylon/Cameras/babylon.webVRCamera.js

@@ -0,0 +1,80 @@
+var __extends = this.__extends || function (d, b) {
+    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+    function __() { this.constructor = d; }
+    __.prototype = b.prototype;
+    d.prototype = new __();
+};
+var BABYLON;
+(function (BABYLON) {
+    var WebVRCamera = (function (_super) {
+        __extends(WebVRCamera, _super);
+        function WebVRCamera(name, position, scene) {
+            _super.call(this, name, position, scene);
+            this._hmdDevice = null;
+            this._sensorDevice = null;
+            this._cacheState = null;
+            this._cacheQuaternion = new BABYLON.Quaternion();
+            this._cacheRotation = BABYLON.Vector3.Zero();
+            this._vrEnabled = false;
+            this._getWebVRDevices = this._getWebVRDevices.bind(this);
+        }
+        WebVRCamera.prototype._getWebVRDevices = function (devices) {
+            var size = devices.length;
+            var i = 0;
+
+            // Reset devices.
+            this._sensorDevice = null;
+            this._hmdDevice = null;
+
+            while (i < size && this._hmdDevice === null) {
+                if (devices[i] instanceof HMDVRDevice) {
+                    this._hmdDevice = devices[i];
+                }
+                i++;
+            }
+
+            i = 0;
+
+            while (i < size && this._sensorDevice === null) {
+                if (devices[i] instanceof PositionSensorVRDevice && (!this._hmdDevice || devices[i].hardwareUnitId === this._hmdDevice.hardwareUnitId)) {
+                    this._sensorDevice = devices[i];
+                }
+                i++;
+            }
+
+            this._vrEnabled = this._sensorDevice && this._hmdDevice ? true : false;
+        };
+
+        WebVRCamera.prototype._update = function () {
+            if (this._vrEnabled) {
+                this._cacheState = this._sensorDevice.getState();
+                this._cacheQuaternion.copyFromFloats(this._cacheState.orientation.x, this._cacheState.orientation.y, this._cacheState.orientation.z, this._cacheState.orientation.w);
+                this._cacheQuaternion.toEulerAnglesToRef(this._cacheRotation);
+
+                this.rotation.x = -this._cacheRotation.z;
+                this.rotation.y = -this._cacheRotation.y;
+                this.rotation.z = this._cacheRotation.x;
+            }
+
+            _super.prototype._update.call(this);
+        };
+
+        WebVRCamera.prototype.attachControl = function (element, noPreventDefault) {
+            _super.prototype.attachControl.call(this, element, noPreventDefault);
+
+            if (navigator.getVRDevices) {
+                navigator.getVRDevices().then(this._getWebVRDevices);
+            } else if (navigator.mozGetVRDevices) {
+                navigator.mozGetVRDevices(this._getWebVRDevices);
+            }
+        };
+
+        WebVRCamera.prototype.detachControl = function (element) {
+            _super.prototype.detachControl.call(this, element);
+            this._vrEnabled = false;
+        };
+        return WebVRCamera;
+    })(BABYLON.OculusCamera);
+    BABYLON.WebVRCamera = WebVRCamera;
+})(BABYLON || (BABYLON = {}));
+//# sourceMappingURL=babylon.webVRCamera.js.map

+ 76 - 0
Babylon/Cameras/babylon.webVRCamera.ts

@@ -0,0 +1,76 @@
+declare var HMDVRDevice;
+declare var PositionSensorVRDevice;
+
+module BABYLON {
+    export class WebVRCamera extends BABYLON.OculusCamera {
+        public _hmdDevice = null;
+        public _sensorDevice = null;
+        public _cacheState = null;
+        public _cacheQuaternion = new BABYLON.Quaternion();
+        public _cacheRotation = BABYLON.Vector3.Zero();
+        public _vrEnabled = false;
+
+        constructor(name: string, position: Vector3, scene: Scene) {
+            super(name, position, scene);
+            this._getWebVRDevices = this._getWebVRDevices.bind(this);
+        }
+
+        private _getWebVRDevices(devices: Array<any>): void {
+            var size = devices.length;
+            var i = 0;
+
+            // Reset devices.
+            this._sensorDevice = null;
+            this._hmdDevice = null;
+
+            // Search for a HmdDevice.
+            while (i < size && this._hmdDevice === null) {
+                if (devices[i] instanceof HMDVRDevice) {
+                    this._hmdDevice = devices[i];
+                }
+                i++;
+            }
+
+            i = 0;
+
+            while (i < size && this._sensorDevice === null) {
+                if (devices[i] instanceof PositionSensorVRDevice && (!this._hmdDevice || devices[i].hardwareUnitId === this._hmdDevice.hardwareUnitId)) {
+                    this._sensorDevice = devices[i];
+                }
+                i++;
+            }
+
+            this._vrEnabled = this._sensorDevice && this._hmdDevice ? true : false;
+        }
+
+        public _update(): void {
+            if (this._vrEnabled) {
+                this._cacheState = this._sensorDevice.getState();
+                this._cacheQuaternion.copyFromFloats(this._cacheState.orientation.x, this._cacheState.orientation.y, this._cacheState.orientation.z, this._cacheState.orientation.w);
+                this._cacheQuaternion.toEulerAnglesToRef(this._cacheRotation);
+
+                this.rotation.x = -this._cacheRotation.z;
+                this.rotation.y = -this._cacheRotation.y;
+                this.rotation.z = this._cacheRotation.x;
+            }
+
+            super._update();
+        }
+
+        public attachControl(element: HTMLElement, noPreventDefault?: boolean): void {
+            super.attachControl(element, noPreventDefault);
+
+            if (navigator.getVRDevices) {
+                navigator.getVRDevices().then(this._getWebVRDevices);
+            }
+            else if (navigator.mozGetVRDevices) {
+                navigator.mozGetVRDevices(this._getWebVRDevices);
+            }
+        }
+
+        public detachControl(element: HTMLElement): void {
+            super.detachControl(element);
+            this._vrEnabled = false;
+        }
+    }
+}

+ 1 - 1
Babylon/LensFlare/babylon.lensFlareSystem.js

@@ -13,7 +13,7 @@
             scene.lensFlareSystems.push(this);
 
             this.meshesSelectionPredicate = function (m) {
-                return m.material && m.isVisible && m.isEnabled() && m.checkCollisions && ((m.layerMask & scene.activeCamera.layerMask) != 0);
+                return m.material && m.isVisible && m.isEnabled() && m.isBlocker && ((m.layerMask & scene.activeCamera.layerMask) != 0);
             };
 
             // VBO

+ 1 - 1
Babylon/LensFlare/babylon.lensFlareSystem.ts

@@ -21,7 +21,7 @@
             this._emitter = emitter;
             scene.lensFlareSystems.push(this);
 
-            this.meshesSelectionPredicate = m => m.material && m.isVisible && m.isEnabled() && m.checkCollisions && ((m.layerMask & scene.activeCamera.layerMask) != 0);
+            this.meshesSelectionPredicate = m => m.material && m.isVisible && m.isEnabled() && m.isBlocker && ((m.layerMask & scene.activeCamera.layerMask) != 0);
 
             // VBO
             var vertices = [];

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

@@ -38,7 +38,7 @@
                     return;
                 }
 
-                var hardwareInstancedRendering = (engine.getCaps().instancedArrays !== null) && (batch.visibleInstances !== null);
+                var hardwareInstancedRendering = (engine.getCaps().instancedArrays !== null) && (batch.visibleInstances[subMesh._id] !== null);
 
                 if (_this.isReady(subMesh, hardwareInstancedRendering)) {
                     engine.enableEffect(_this._effect);

+ 1 - 1
Babylon/Lights/Shadows/babylon.shadowGenerator.ts

@@ -77,7 +77,7 @@
                     return;
                 }
 
-                var hardwareInstancedRendering = (engine.getCaps().instancedArrays !== null) && (batch.visibleInstances !== null);
+                var hardwareInstancedRendering = (engine.getCaps().instancedArrays !== null) && (batch.visibleInstances[subMesh._id] !== null);
 
                 if (this.isReady(subMesh, hardwareInstancedRendering)) {
                     engine.enableEffect(this._effect);

+ 1 - 1
Babylon/Lights/babylon.light.js

@@ -41,7 +41,7 @@ var BABYLON;
                 return false;
             }
 
-            if (this.includedOnlyMeshes.length > 0 && this.excludedMeshes.indexOf(mesh) !== -1) {
+            if (this.excludedMeshes.length > 0 && this.excludedMeshes.indexOf(mesh) !== -1) {
                 return false;
             }
 

+ 1 - 1
Babylon/Lights/babylon.light.ts

@@ -38,7 +38,7 @@
                 return false;
             }
 
-            if (this.includedOnlyMeshes.length > 0 && this.excludedMeshes.indexOf(mesh) !== -1) {
+            if (this.excludedMeshes.length > 0 && this.excludedMeshes.indexOf(mesh) !== -1) {
                 return false;
             }
 

+ 142 - 23
Babylon/Loading/Plugins/babylon.babylonFileLoader.js

@@ -91,6 +91,8 @@
             fresnelParameters.isEnabled = parsedFresnelParameters.isEnabled;
             fresnelParameters.leftColor = BABYLON.Color3.FromArray(parsedFresnelParameters.leftColor);
             fresnelParameters.rightColor = BABYLON.Color3.FromArray(parsedFresnelParameters.rightColor);
+            fresnelParameters.bias = parsedFresnelParameters.bias;
+            fresnelParameters.power = parsedFresnelParameters.power || 1.0;
 
             return fresnelParameters;
         };
@@ -145,6 +147,10 @@
                 material.emissiveTexture = loadTexture(rootUrl, parsedMaterial.emissiveTexture, scene);
             }
 
+            if (parsedMaterial.emissiveFresnelParameters) {
+                material.emissiveFresnelParameters = parseFresnelParameters(parsedMaterial.emissiveFresnelParameters);
+            }
+
             if (parsedMaterial.specularTexture) {
                 material.specularTexture = loadTexture(rootUrl, parsedMaterial.specularTexture, scene);
             }
@@ -348,7 +354,54 @@
         };
 
         var parseCamera = function (parsedCamera, scene) {
-            var camera = new BABYLON.FreeCamera(parsedCamera.name, BABYLON.Vector3.FromArray(parsedCamera.position), scene);
+            var camera;
+            var position = BABYLON.Vector3.FromArray(parsedCamera.position);
+            var lockedTargetMesh = (parsedCamera.lockedTargetId) ? scene.getLastMeshByID(parsedCamera.lockedTargetId) : null;
+
+            if (parsedCamera.type === "AnaglyphArcRotateCamera" || parsedCamera.type === "ArcRotateCamera") {
+                var alpha = parsedCamera.alpha;
+                var beta = parsedCamera.beta;
+                var radius = parsedCamera.radius;
+                if (parsedCamera.type === "AnaglyphArcRotateCamera") {
+                    var eye_space = parsedCamera.eye_space;
+                    camera = new BABYLON.AnaglyphArcRotateCamera(parsedCamera.name, alpha, beta, radius, lockedTargetMesh, eye_space, scene);
+                } else {
+                    camera = new BABYLON.ArcRotateCamera(parsedCamera.name, alpha, beta, radius, lockedTargetMesh, scene);
+                }
+            } else if (parsedCamera.type === "AnaglyphFreeCamera") {
+                var eye_space = parsedCamera.eye_space;
+                camera = new BABYLON.AnaglyphFreeCamera(parsedCamera.name, position, eye_space, scene);
+            } else if (parsedCamera.type === "DeviceOrientationCamera") {
+                camera = new BABYLON.DeviceOrientationCamera(parsedCamera.name, position, scene);
+            } else if (parsedCamera.type === "FollowCamera") {
+                camera = new BABYLON.FollowCamera(parsedCamera.name, position, scene);
+                camera.heightOffset = parsedCamera.heightOffset;
+                camera.radius = parsedCamera.radius;
+                camera.rotationOffset = parsedCamera.rotationOffset;
+                if (lockedTargetMesh)
+                    camera.target = lockedTargetMesh;
+            } else if (parsedCamera.type === "GamepadCamera") {
+                camera = new BABYLON.GamepadCamera(parsedCamera.name, position, scene);
+            } else if (parsedCamera.type === "OculusCamera") {
+                camera = new BABYLON.OculusCamera(parsedCamera.name, position, scene);
+            } else if (parsedCamera.type === "TouchCamera") {
+                camera = new BABYLON.TouchCamera(parsedCamera.name, position, scene);
+            } else if (parsedCamera.type === "VirtualJoysticksCamera") {
+                camera = new BABYLON.VirtualJoysticksCamera(parsedCamera.name, position, scene);
+            } else if (parsedCamera.type === "WebVRCamera") {
+                camera = new BABYLON.WebVRCamera(parsedCamera.name, position, scene);
+            } else if (parsedCamera.type === "VRDeviceOrientationCamera") {
+                camera = new BABYLON.VRDeviceOrientationCamera(parsedCamera.name, position, scene);
+            } else {
+                // Free Camera is the default value
+                camera = new BABYLON.FreeCamera(parsedCamera.name, position, scene);
+            }
+
+            // Test for lockedTargetMesh & FreeCamera outside of if-else-if nest, since things like GamepadCamera extend FreeCamera
+            if (lockedTargetMesh && camera instanceof BABYLON.FreeCamera) {
+                camera.lockedTarget = lockedTargetMesh;
+            }
+
             camera.id = parsedCamera.id;
 
             BABYLON.Tags.AddTagsTo(camera, parsedCamera.tags);
@@ -365,11 +418,6 @@
                 camera.rotation = BABYLON.Vector3.FromArray(parsedCamera.rotation);
             }
 
-            // Locked target
-            if (parsedCamera.lockedTargetId) {
-                camera._waitingLockedTargetId = parsedCamera.lockedTargetId;
-            }
-
             camera.fov = parsedCamera.fov;
             camera.minZ = parsedCamera.minZ;
             camera.maxZ = parsedCamera.maxZ;
@@ -593,7 +641,7 @@
 
             // Parent
             if (parsedMesh.parentId) {
-                mesh.parent = scene.getLastEntryByID(parsedMesh.parentId);
+                mesh._waitingParentId = parsedMesh.parentId;
             }
 
             // Geometry
@@ -602,6 +650,10 @@
                 mesh.delayLoadingFile = rootUrl + parsedMesh.delayLoadingFile;
                 mesh._boundingInfo = new BABYLON.BoundingInfo(BABYLON.Vector3.FromArray(parsedMesh.boundingBoxMinimum), BABYLON.Vector3.FromArray(parsedMesh.boundingBoxMaximum));
 
+                if (parsedMesh._binaryInfo) {
+                    mesh._binaryInfo = parsedMesh._binaryInfo;
+                }
+
                 mesh._delayInfo = [];
                 if (parsedMesh.hasUVs) {
                     mesh._delayInfo.push(BABYLON.VertexBuffer.UVKind);
@@ -787,6 +839,65 @@
                 if (geometry) {
                     geometry.applyToMesh(mesh);
                 }
+            } else if (parsedGeometry instanceof ArrayBuffer) {
+                var binaryInfo = mesh._binaryInfo;
+
+                if (binaryInfo.positionsAttrDesc && binaryInfo.positionsAttrDesc.count > 0) {
+                    var positionsData = new Float32Array(parsedGeometry, binaryInfo.positionsAttrDesc.offset, binaryInfo.positionsAttrDesc.count);
+                    mesh.setVerticesData(BABYLON.VertexBuffer.PositionKind, positionsData, false);
+                }
+
+                if (binaryInfo.normalsAttrDesc && binaryInfo.normalsAttrDesc.count > 0) {
+                    var normalsData = new Float32Array(parsedGeometry, binaryInfo.normalsAttrDesc.offset, binaryInfo.normalsAttrDesc.count);
+                    mesh.setVerticesData(BABYLON.VertexBuffer.NormalKind, normalsData, false);
+                }
+
+                if (binaryInfo.uvsAttrDesc && binaryInfo.uvsAttrDesc.count > 0) {
+                    var uvsData = new Float32Array(parsedGeometry, binaryInfo.uvsAttrDesc.offset, binaryInfo.uvsAttrDesc.count);
+                    mesh.setVerticesData(BABYLON.VertexBuffer.UVKind, uvsData, false);
+                }
+
+                if (binaryInfo.uvs2AttrDesc && binaryInfo.uvs2AttrDesc.count > 0) {
+                    var uvs2Data = new Float32Array(parsedGeometry, binaryInfo.uvs2AttrDesc.offset, binaryInfo.uvs2AttrDesc.count);
+                    mesh.setVerticesData(BABYLON.VertexBuffer.UV2Kind, uvs2Data, false);
+                }
+
+                if (binaryInfo.colorsAttrDesc && binaryInfo.colorsAttrDesc.count > 0) {
+                    var colorsData = new Float32Array(parsedGeometry, binaryInfo.colorsAttrDesc.offset, binaryInfo.colorsAttrDesc.count);
+                    mesh.setVerticesData(BABYLON.VertexBuffer.ColorKind, colorsData, false);
+                }
+
+                if (binaryInfo.matricesIndicesAttrDesc && binaryInfo.matricesIndicesAttrDesc.count > 0) {
+                    var matricesIndicesData = new Int32Array(parsedGeometry, binaryInfo.matricesIndicesAttrDesc.offset, binaryInfo.matricesIndicesAttrDesc.count);
+                    mesh.setVerticesData(BABYLON.VertexBuffer.MatricesIndicesKind, matricesIndicesData, false);
+                }
+
+                if (binaryInfo.matricesWeightsAttrDesc && binaryInfo.matricesWeightsAttrDesc.count > 0) {
+                    var matricesWeightsData = new Float32Array(parsedGeometry, binaryInfo.matricesWeightsAttrDesc.offset, binaryInfo.matricesWeightsAttrDesc.count);
+                    mesh.setVerticesData(BABYLON.VertexBuffer.MatricesWeightsKind, matricesWeightsData, false);
+                }
+
+                if (binaryInfo.indicesAttrDesc && binaryInfo.indicesAttrDesc.count > 0) {
+                    var indicesData = new Int32Array(parsedGeometry, binaryInfo.indicesAttrDesc.offset, binaryInfo.indicesAttrDesc.count);
+                    mesh.setIndices(indicesData);
+                }
+
+                if (binaryInfo.subMeshesAttrDesc && binaryInfo.subMeshesAttrDesc.count > 0) {
+                    var subMeshesData = new Int32Array(parsedGeometry, binaryInfo.subMeshesAttrDesc.offset, binaryInfo.subMeshesAttrDesc.count * 5);
+
+                    mesh.subMeshes = [];
+                    for (var i = 0; i < binaryInfo.subMeshesAttrDesc.count; i++) {
+                        var materialIndex = subMeshesData[(i * 5) + 0];
+                        var verticesStart = subMeshesData[(i * 5) + 1];
+                        var verticesCount = subMeshesData[(i * 5) + 2];
+                        var indexStart = subMeshesData[(i * 5) + 3];
+                        var indexCount = subMeshesData[(i * 5) + 4];
+
+                        var subMesh = new BABYLON.SubMesh(materialIndex, verticesStart, verticesCount, indexStart, indexCount, mesh);
+                    }
+                }
+
+                return;
             } else if (parsedGeometry.positions && parsedGeometry.normals && parsedGeometry.indices) {
                 mesh.setVerticesData(BABYLON.VertexBuffer.PositionKind, parsedGeometry.positions, false);
                 mesh.setVerticesData(BABYLON.VertexBuffer.NormalKind, parsedGeometry.normals, false);
@@ -921,6 +1032,14 @@
                     }
                 }
 
+                for (index = 0; index < scene.meshes.length; index++) {
+                    var currentMesh = scene.meshes[index];
+                    if (currentMesh._waitingParentId) {
+                        currentMesh.parent = scene.getLastEntryByID(currentMesh._waitingParentId);
+                        currentMesh._waitingParentId = undefined;
+                    }
+                }
+
                 // Particles
                 if (parsedData.particleSystems) {
                     for (index = 0; index < parsedData.particleSystems.length; index++) {
@@ -958,15 +1077,6 @@
                     parseLight(parsedLight, scene);
                 }
 
-                for (index = 0; index < parsedData.cameras.length; index++) {
-                    var parsedCamera = parsedData.cameras[index];
-                    parseCamera(parsedCamera, scene);
-                }
-
-                if (parsedData.activeCameraID) {
-                    scene.setActiveCameraByID(parsedData.activeCameraID);
-                }
-
                 // Materials
                 if (parsedData.materials) {
                     for (index = 0; index < parsedData.materials.length; index++) {
@@ -1071,19 +1181,28 @@
                     parseMesh(parsedMesh, scene, rootUrl);
                 }
 
+                for (index = 0; index < parsedData.cameras.length; index++) {
+                    var parsedCamera = parsedData.cameras[index];
+                    parseCamera(parsedCamera, scene);
+                }
+
+                if (parsedData.activeCameraID) {
+                    scene.setActiveCameraByID(parsedData.activeCameraID);
+                }
+
                 for (index = 0; index < scene.cameras.length; index++) {
                     var camera = scene.cameras[index];
                     if (camera._waitingParentId) {
                         camera.parent = scene.getLastEntryByID(camera._waitingParentId);
-                        delete camera._waitingParentId;
+                        camera._waitingParentId = undefined;
                     }
+                }
 
-                    if (camera instanceof BABYLON.FreeCamera) {
-                        var freecamera = camera;
-                        if (freecamera._waitingLockedTargetId) {
-                            freecamera.lockedTarget = scene.getLastEntryByID(freecamera._waitingLockedTargetId);
-                            delete freecamera._waitingLockedTargetId;
-                        }
+                for (index = 0; index < scene.meshes.length; index++) {
+                    var mesh = scene.meshes[index];
+                    if (mesh._waitingParentId) {
+                        mesh.parent = scene.getLastEntryByID(mesh._waitingParentId);
+                        mesh._waitingParentId = undefined;
                     }
                 }
 

+ 185 - 54
Babylon/Loading/Plugins/babylon.babylonFileLoader.ts

@@ -90,6 +90,8 @@
         fresnelParameters.isEnabled = parsedFresnelParameters.isEnabled;
         fresnelParameters.leftColor = BABYLON.Color3.FromArray(parsedFresnelParameters.leftColor);
         fresnelParameters.rightColor = BABYLON.Color3.FromArray(parsedFresnelParameters.rightColor);
+        fresnelParameters.bias = parsedFresnelParameters.bias;
+        fresnelParameters.power = parsedFresnelParameters.power || 1.0;
 
         return fresnelParameters;
     }
@@ -144,6 +146,10 @@
             material.emissiveTexture = loadTexture(rootUrl, parsedMaterial.emissiveTexture, scene);
         }
 
+        if (parsedMaterial.emissiveFresnelParameters) {
+            material.emissiveFresnelParameters = parseFresnelParameters(parsedMaterial.emissiveFresnelParameters);
+        }
+
         if (parsedMaterial.specularTexture) {
             material.specularTexture = loadTexture(rootUrl, parsedMaterial.specularTexture, scene);
         }
@@ -263,19 +269,19 @@
             var data;
 
             switch (dataType) {
-            case BABYLON.Animation.ANIMATIONTYPE_FLOAT:
-                data = key.values[0];
-                break;
-            case BABYLON.Animation.ANIMATIONTYPE_QUATERNION:
-                data = BABYLON.Quaternion.FromArray(key.values);
-                break;
-            case BABYLON.Animation.ANIMATIONTYPE_MATRIX:
-                data = BABYLON.Matrix.FromArray(key.values);
-                break;
-            case BABYLON.Animation.ANIMATIONTYPE_VECTOR3:
-            default:
-                data = BABYLON.Vector3.FromArray(key.values);
-                break;
+                case BABYLON.Animation.ANIMATIONTYPE_FLOAT:
+                    data = key.values[0];
+                    break;
+                case BABYLON.Animation.ANIMATIONTYPE_QUATERNION:
+                    data = BABYLON.Quaternion.FromArray(key.values);
+                    break;
+                case BABYLON.Animation.ANIMATIONTYPE_MATRIX:
+                    data = BABYLON.Matrix.FromArray(key.values);
+                    break;
+                case BABYLON.Animation.ANIMATIONTYPE_VECTOR3:
+                default:
+                    data = BABYLON.Vector3.FromArray(key.values);
+                    break;
             }
 
             keys.push({
@@ -293,20 +299,20 @@
         var light;
 
         switch (parsedLight.type) {
-        case 0:
-            light = new BABYLON.PointLight(parsedLight.name, BABYLON.Vector3.FromArray(parsedLight.position), scene);
-            break;
-        case 1:
-            light = new BABYLON.DirectionalLight(parsedLight.name, BABYLON.Vector3.FromArray(parsedLight.direction), scene);
-            light.position = BABYLON.Vector3.FromArray(parsedLight.position);
-            break;
-        case 2:
-            light = new BABYLON.SpotLight(parsedLight.name, BABYLON.Vector3.FromArray(parsedLight.position), BABYLON.Vector3.FromArray(parsedLight.direction), parsedLight.angle, parsedLight.exponent, scene);
-            break;
-        case 3:
-            light = new BABYLON.HemisphericLight(parsedLight.name, BABYLON.Vector3.FromArray(parsedLight.direction), scene);
-            light.groundColor = BABYLON.Color3.FromArray(parsedLight.groundColor);
-            break;
+            case 0:
+                light = new BABYLON.PointLight(parsedLight.name, BABYLON.Vector3.FromArray(parsedLight.position), scene);
+                break;
+            case 1:
+                light = new BABYLON.DirectionalLight(parsedLight.name, BABYLON.Vector3.FromArray(parsedLight.direction), scene);
+                light.position = BABYLON.Vector3.FromArray(parsedLight.position);
+                break;
+            case 2:
+                light = new BABYLON.SpotLight(parsedLight.name, BABYLON.Vector3.FromArray(parsedLight.position), BABYLON.Vector3.FromArray(parsedLight.direction), parsedLight.angle, parsedLight.exponent, scene);
+                break;
+            case 3:
+                light = new BABYLON.HemisphericLight(parsedLight.name, BABYLON.Vector3.FromArray(parsedLight.direction), scene);
+                light.groundColor = BABYLON.Color3.FromArray(parsedLight.groundColor);
+                break;
         }
 
         light.id = parsedLight.id;
@@ -346,8 +352,65 @@
         }
     };
 
-    var parseCamera = (parsedCamera, scene) => {
-        var camera = new BABYLON.FreeCamera(parsedCamera.name, BABYLON.Vector3.FromArray(parsedCamera.position), scene);
+    var parseCamera = (parsedCamera, scene: Scene) => {
+        var camera;
+        var position = Vector3.FromArray(parsedCamera.position);
+        var lockedTargetMesh = (parsedCamera.lockedTargetId) ? scene.getLastMeshByID(parsedCamera.lockedTargetId) : null;
+
+        if (parsedCamera.type === "AnaglyphArcRotateCamera" || parsedCamera.type === "ArcRotateCamera") {
+            var alpha = parsedCamera.alpha;
+            var beta = parsedCamera.beta;
+            var radius = parsedCamera.radius;
+            if (parsedCamera.type === "AnaglyphArcRotateCamera") {
+                var eye_space = parsedCamera.eye_space;
+                camera = new AnaglyphArcRotateCamera(parsedCamera.name, alpha, beta, radius, lockedTargetMesh, eye_space, scene);
+            } else {
+                camera = new ArcRotateCamera(parsedCamera.name, alpha, beta, radius, lockedTargetMesh, scene);
+            }
+
+        } else if (parsedCamera.type === "AnaglyphFreeCamera") {
+            var eye_space = parsedCamera.eye_space;
+            camera = new AnaglyphFreeCamera(parsedCamera.name, position, eye_space, scene);
+
+        } else if (parsedCamera.type === "DeviceOrientationCamera") {
+            camera = new DeviceOrientationCamera(parsedCamera.name, position, scene);
+
+        } else if (parsedCamera.type === "FollowCamera") {
+            camera = new FollowCamera(parsedCamera.name, position, scene);
+            camera.heightOffset = parsedCamera.heightOffset;
+            camera.radius = parsedCamera.radius;
+            camera.rotationOffset = parsedCamera.rotationOffset;
+            if (lockedTargetMesh)
+                (<FollowCamera>camera).target = lockedTargetMesh;
+
+        } else if (parsedCamera.type === "GamepadCamera") {
+            camera = new GamepadCamera(parsedCamera.name, position, scene);
+
+        } else if (parsedCamera.type === "OculusCamera") {
+            camera = new OculusCamera(parsedCamera.name, position, scene);
+
+        } else if (parsedCamera.type === "TouchCamera") {
+            camera = new TouchCamera(parsedCamera.name, position, scene);
+
+        } else if (parsedCamera.type === "VirtualJoysticksCamera") {
+            camera = new VirtualJoysticksCamera(parsedCamera.name, position, scene);
+
+        } else if (parsedCamera.type === "WebVRCamera") {
+            camera = new WebVRCamera(parsedCamera.name, position, scene);
+
+        } else if (parsedCamera.type === "VRDeviceOrientationCamera") {
+            camera = new VRDeviceOrientationCamera(parsedCamera.name, position, scene);
+
+        } else {
+            // Free Camera is the default value
+            camera = new FreeCamera(parsedCamera.name, position, scene);
+        }
+
+        // Test for lockedTargetMesh & FreeCamera outside of if-else-if nest, since things like GamepadCamera extend FreeCamera
+        if (lockedTargetMesh && camera instanceof FreeCamera) {
+            (<FreeCamera>camera).lockedTarget = lockedTargetMesh;
+        }
+
         camera.id = parsedCamera.id;
 
         BABYLON.Tags.AddTagsTo(camera, parsedCamera.tags);
@@ -364,11 +427,6 @@
             camera.rotation = BABYLON.Vector3.FromArray(parsedCamera.rotation);
         }
 
-        // Locked target
-        if (parsedCamera.lockedTargetId) {
-            camera._waitingLockedTargetId = parsedCamera.lockedTargetId;
-        }
-
         camera.fov = parsedCamera.fov;
         camera.minZ = parsedCamera.minZ;
         camera.maxZ = parsedCamera.maxZ;
@@ -592,7 +650,7 @@
 
         // Parent
         if (parsedMesh.parentId) {
-            mesh.parent = scene.getLastEntryByID(parsedMesh.parentId);
+            mesh._waitingParentId = parsedMesh.parentId;
         }
 
         // Geometry
@@ -601,6 +659,10 @@
             mesh.delayLoadingFile = rootUrl + parsedMesh.delayLoadingFile;
             mesh._boundingInfo = new BABYLON.BoundingInfo(BABYLON.Vector3.FromArray(parsedMesh.boundingBoxMinimum), BABYLON.Vector3.FromArray(parsedMesh.boundingBoxMaximum));
 
+            if (parsedMesh._binaryInfo) {
+                mesh._binaryInfo = parsedMesh._binaryInfo;
+            }
+
             mesh._delayInfo = [];
             if (parsedMesh.hasUVs) {
                 mesh._delayInfo.push(BABYLON.VertexBuffer.UVKind);
@@ -788,6 +850,67 @@
             if (geometry) {
                 geometry.applyToMesh(mesh);
             }
+        } else if (parsedGeometry instanceof ArrayBuffer) {
+
+            var binaryInfo = mesh._binaryInfo;
+
+            if (binaryInfo.positionsAttrDesc && binaryInfo.positionsAttrDesc.count > 0) {
+                var positionsData = new Float32Array(parsedGeometry, binaryInfo.positionsAttrDesc.offset, binaryInfo.positionsAttrDesc.count);
+                mesh.setVerticesData(BABYLON.VertexBuffer.PositionKind, positionsData, false);
+            }
+
+            if (binaryInfo.normalsAttrDesc && binaryInfo.normalsAttrDesc.count > 0) {
+                var normalsData = new Float32Array(parsedGeometry, binaryInfo.normalsAttrDesc.offset, binaryInfo.normalsAttrDesc.count);
+                mesh.setVerticesData(BABYLON.VertexBuffer.NormalKind, normalsData, false);
+            }
+
+            if (binaryInfo.uvsAttrDesc && binaryInfo.uvsAttrDesc.count > 0) {
+                var uvsData = new Float32Array(parsedGeometry, binaryInfo.uvsAttrDesc.offset, binaryInfo.uvsAttrDesc.count);
+                mesh.setVerticesData(BABYLON.VertexBuffer.UVKind, uvsData, false);
+            }
+
+            if (binaryInfo.uvs2AttrDesc && binaryInfo.uvs2AttrDesc.count > 0) {
+                var uvs2Data = new Float32Array(parsedGeometry, binaryInfo.uvs2AttrDesc.offset, binaryInfo.uvs2AttrDesc.count);
+                mesh.setVerticesData(BABYLON.VertexBuffer.UV2Kind, uvs2Data, false);
+            }
+
+            if (binaryInfo.colorsAttrDesc && binaryInfo.colorsAttrDesc.count > 0) {
+                var colorsData = new Float32Array(parsedGeometry, binaryInfo.colorsAttrDesc.offset, binaryInfo.colorsAttrDesc.count);
+                mesh.setVerticesData(BABYLON.VertexBuffer.ColorKind, colorsData, false);
+            }
+
+            if (binaryInfo.matricesIndicesAttrDesc && binaryInfo.matricesIndicesAttrDesc.count > 0) {
+                var matricesIndicesData = new Int32Array(parsedGeometry, binaryInfo.matricesIndicesAttrDesc.offset, binaryInfo.matricesIndicesAttrDesc.count);
+                mesh.setVerticesData(BABYLON.VertexBuffer.MatricesIndicesKind, matricesIndicesData, false);
+            }
+
+            if (binaryInfo.matricesWeightsAttrDesc && binaryInfo.matricesWeightsAttrDesc.count > 0) {
+                var matricesWeightsData = new Float32Array(parsedGeometry, binaryInfo.matricesWeightsAttrDesc.offset, binaryInfo.matricesWeightsAttrDesc.count);
+                mesh.setVerticesData(BABYLON.VertexBuffer.MatricesWeightsKind, matricesWeightsData, false);
+            }
+
+            if (binaryInfo.indicesAttrDesc && binaryInfo.indicesAttrDesc.count > 0) {
+                var indicesData = new Int32Array(parsedGeometry, binaryInfo.indicesAttrDesc.offset, binaryInfo.indicesAttrDesc.count);
+                mesh.setIndices(indicesData);
+            }
+
+            if (binaryInfo.subMeshesAttrDesc && binaryInfo.subMeshesAttrDesc.count > 0) {
+                var subMeshesData = new Int32Array(parsedGeometry, binaryInfo.subMeshesAttrDesc.offset, binaryInfo.subMeshesAttrDesc.count * 5);
+
+                mesh.subMeshes = [];
+                for (var i = 0; i < binaryInfo.subMeshesAttrDesc.count; i++) {
+                    var materialIndex = subMeshesData[(i * 5) + 0];
+                    var verticesStart = subMeshesData[(i * 5) + 1];
+                    var verticesCount = subMeshesData[(i * 5) + 2];
+                    var indexStart = subMeshesData[(i * 5) + 3];
+                    var indexCount = subMeshesData[(i * 5) + 4];
+
+                    var subMesh = new BABYLON.SubMesh(materialIndex, verticesStart, verticesCount, indexStart, indexCount, mesh);
+                }
+            }
+
+            return;
+
         } else if (parsedGeometry.positions && parsedGeometry.normals && parsedGeometry.indices) {
             mesh.setVerticesData(BABYLON.VertexBuffer.PositionKind, parsedGeometry.positions, false);
             mesh.setVerticesData(BABYLON.VertexBuffer.NormalKind, parsedGeometry.normals, false);
@@ -922,6 +1045,15 @@
                 }
             }
 
+            // Connecting parents
+            for (index = 0; index < scene.meshes.length; index++) {
+                var currentMesh = scene.meshes[index];
+                if (currentMesh._waitingParentId) {
+                    currentMesh.parent = scene.getLastEntryByID(currentMesh._waitingParentId);
+                    currentMesh._waitingParentId = undefined;
+                }
+            }
+
             // Particles
             if (parsedData.particleSystems) {
                 for (index = 0; index < parsedData.particleSystems.length; index++) {
@@ -960,16 +1092,6 @@
                 parseLight(parsedLight, scene);
             }
 
-            // Cameras
-            for (index = 0; index < parsedData.cameras.length; index++) {
-                var parsedCamera = parsedData.cameras[index];
-                parseCamera(parsedCamera, scene);
-            }
-
-            if (parsedData.activeCameraID) {
-                scene.setActiveCameraByID(parsedData.activeCameraID);
-            }
-
             // Materials
             if (parsedData.materials) {
                 for (index = 0; index < parsedData.materials.length; index++) {
@@ -1075,21 +1197,30 @@
                 parseMesh(parsedMesh, scene, rootUrl);
             }
 
-            // Connecting cameras parents and locked target
+            // Cameras
+            for (index = 0; index < parsedData.cameras.length; index++) {
+                var parsedCamera = parsedData.cameras[index];
+                parseCamera(parsedCamera, scene);
+            }
+
+            if (parsedData.activeCameraID) {
+                scene.setActiveCameraByID(parsedData.activeCameraID);
+            }
+
+            // Connecting parents
             for (index = 0; index < scene.cameras.length; index++) {
                 var camera = scene.cameras[index];
                 if (camera._waitingParentId) {
                     camera.parent = scene.getLastEntryByID(camera._waitingParentId);
-                    delete camera._waitingParentId;
+                    camera._waitingParentId = undefined;
                 }
+            }
 
-                if (camera instanceof BABYLON.FreeCamera) {
-                    var freecamera = <FreeCamera>camera;
-                    if (freecamera._waitingLockedTargetId)
-                    {
-                        freecamera.lockedTarget = scene.getLastEntryByID(freecamera._waitingLockedTargetId);
-                        delete freecamera._waitingLockedTargetId;
-                    }
+            for (index = 0; index < scene.meshes.length; index++) {
+                var mesh = scene.meshes[index];
+                if (mesh._waitingParentId) {
+                    mesh.parent = scene.getLastEntryByID(mesh._waitingParentId);
+                    mesh._waitingParentId = undefined;
                 }
             }
 

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

@@ -66,12 +66,20 @@
 
             if (baseName.vertexElement) {
                 vertexSource = document.getElementById(baseName.vertexElement);
+
+                if (!vertexSource) {
+                    vertexSource = baseName.vertexElement;
+                }
             } else {
                 vertexSource = baseName.vertex || baseName;
             }
 
             if (baseName.fragmentElement) {
                 fragmentSource = document.getElementById(baseName.fragmentElement);
+
+                if (!fragmentSource) {
+                    fragmentSource = baseName.fragmentElement;
+                }
             } else {
                 fragmentSource = baseName.fragment || baseName;
             }
@@ -166,6 +174,11 @@
                 return;
             }
 
+            if (BABYLON.Effect.ShadersStore[fragment + "FragmentShader"]) {
+                callback(BABYLON.Effect.ShadersStore[fragment + "FragmentShader"]);
+                return;
+            }
+
             var fragmentShaderUrl;
 
             if (fragment[0] === ".") {

+ 13 - 0
Babylon/Materials/babylon.effect.ts

@@ -74,12 +74,20 @@
 
             if (baseName.vertexElement) {
                 vertexSource = document.getElementById(baseName.vertexElement);
+
+                if (!vertexSource) {
+                    vertexSource = baseName.vertexElement;
+                }
             } else {
                 vertexSource = baseName.vertex || baseName;
             }
 
             if (baseName.fragmentElement) {
                 fragmentSource = document.getElementById(baseName.fragmentElement);
+
+                if (!fragmentSource) {
+                    fragmentSource = baseName.fragmentElement;
+                }
             } else {
                 fragmentSource = baseName.fragment || baseName;
             }
@@ -175,6 +183,11 @@
                 return;
             }
 
+            if (BABYLON.Effect.ShadersStore[fragment + "FragmentShader"]) {
+                callback(BABYLON.Effect.ShadersStore[fragment + "FragmentShader"]);
+                return;
+            }
+
             var fragmentShaderUrl;
 
             if (fragment[0] === ".") {

+ 2 - 2
Babylon/Materials/babylon.shaderMaterial.ts

@@ -1,6 +1,6 @@
 module BABYLON {
     export class ShaderMaterial extends Material {
-        private _shaderPath: string;
+        private _shaderPath: any;
         private _options: any;
         private _textures = new Array<Texture>();
         private _floats = new Array<number>();
@@ -12,7 +12,7 @@
         private _matrices = new Array<Matrix>();
         private _cachedWorldViewMatrix = new BABYLON.Matrix();
 
-        constructor(name: string, scene: Scene, shaderPath: string, options) {
+        constructor(name: string, scene: Scene, shaderPath: any, options: any) {
             super(name, scene);
             this._shaderPath = shaderPath;
 

+ 57 - 15
Babylon/Materials/babylon.standardMaterial.js

@@ -11,8 +11,10 @@ var BABYLON;
     var FresnelParameters = (function () {
         function FresnelParameters() {
             this.isEnabled = true;
-            this.leftColor = BABYLON.Color3.Black();
-            this.rightColor = BABYLON.Color3.White();
+            this.leftColor = BABYLON.Color3.White();
+            this.rightColor = BABYLON.Color3.Black();
+            this.bias = 0;
+            this.power = 1;
         }
         return FresnelParameters;
     })();
@@ -29,11 +31,11 @@ var BABYLON;
             this.specularPower = 64;
             this.emissiveColor = new BABYLON.Color3(0, 0, 0);
             this.useAlphaFromDiffuseTexture = false;
+            this.useSpecularOverAlpha = true;
             this._cachedDefines = null;
             this._renderTargets = new BABYLON.SmartArray(16);
             this._worldViewProjectionMatrix = BABYLON.Matrix.Zero();
             this._globalAmbientColor = new BABYLON.Color3(0, 0, 0);
-            this._baseColor = new BABYLON.Color3();
             this._scaledDiffuse = new BABYLON.Color3();
             this._scaledSpecular = new BABYLON.Color3();
 
@@ -48,7 +50,7 @@ var BABYLON;
             };
         }
         StandardMaterial.prototype.needAlphaBlending = function () {
-            return (this.alpha < 1.0) || (this.opacityTexture != null) || this._shouldUseAlphaFromDiffuseTexture();
+            return (this.alpha < 1.0) || (this.opacityTexture != null) || this._shouldUseAlphaFromDiffuseTexture() || this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled;
         };
 
         StandardMaterial.prototype.needAlphaTesting = function () {
@@ -150,6 +152,11 @@ var BABYLON;
             }
 
             // Effect
+            if (this.useSpecularOverAlpha) {
+                defines.push("#define SPECULAROVERALPHA");
+                fallbacks.addFallback(0, "SPECULAROVERALPHA");
+            }
+
             if (scene.clipPlane) {
                 defines.push("#define CLIPPLANE");
             }
@@ -261,11 +268,35 @@ var BABYLON;
             }
 
             // Fresnel
-            if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled) {
+            if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled || this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled || this.emissiveFresnelParameters && this.emissiveFresnelParameters.isEnabled || this.reflectionFresnelParameters && this.reflectionFresnelParameters.isEnabled) {
+                var fresnelRank = 1;
+
+                if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled) {
+                    defines.push("#define DIFFUSEFRESNEL");
+                    fallbacks.addFallback(fresnelRank, "DIFFUSEFRESNEL");
+                    fresnelRank++;
+                }
+
+                if (this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled) {
+                    defines.push("#define OPACITYFRESNEL");
+                    fallbacks.addFallback(fresnelRank, "OPACITYFRESNEL");
+                    fresnelRank++;
+                }
+
+                if (this.reflectionFresnelParameters && this.reflectionFresnelParameters.isEnabled) {
+                    defines.push("#define REFLECTIONFRESNEL");
+                    fallbacks.addFallback(fresnelRank, "REFLECTIONFRESNEL");
+                    fresnelRank++;
+                }
+
+                if (this.emissiveFresnelParameters && this.emissiveFresnelParameters.isEnabled) {
+                    defines.push("#define EMISSIVEFRESNEL");
+                    fallbacks.addFallback(fresnelRank, "EMISSIVEFRESNEL");
+                    fresnelRank++;
+                }
+
                 defines.push("#define FRESNEL");
-                defines.push("#define DIFFUSEFRESNEL");
-                fallbacks.addFallback(1, "FRESNEL");
-                fallbacks.addFallback(1, "DIFFUSEFRESNEL");
+                fallbacks.addFallback(fresnelRank - 1, "FRESNEL");
             }
 
             // Attribs
@@ -324,7 +355,7 @@ var BABYLON;
                     "mBones",
                     "vClipPlane", "diffuseMatrix", "ambientMatrix", "opacityMatrix", "reflectionMatrix", "emissiveMatrix", "specularMatrix", "bumpMatrix",
                     "darkness0", "darkness1", "darkness2", "darkness3",
-                    "diffuseLeftColor", "diffuseRightColor"
+                    "diffuseLeftColor", "diffuseRightColor", "opacityParts", "reflectionLeftColor", "reflectionRightColor", "emissiveLeftColor", "emissiveRightColor"
                 ], [
                     "diffuseSampler", "ambientSampler", "opacitySampler", "reflectionCubeSampler", "reflection2DSampler", "emissiveSampler", "specularSampler", "bumpSampler",
                     "shadowSampler0", "shadowSampler1", "shadowSampler2", "shadowSampler3"
@@ -351,7 +382,6 @@ var BABYLON;
 
         StandardMaterial.prototype.bind = function (world, mesh) {
             var scene = this.getScene();
-            this._baseColor.copyFrom(this.diffuseColor);
 
             // Matrices
             this.bindOnlyWorldMatrix(world);
@@ -364,8 +394,22 @@ var BABYLON;
 
             // Fresnel
             if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled) {
-                this._effect.setColor3("diffuseLeftColor", this.diffuseFresnelParameters.leftColor);
-                this._effect.setColor3("diffuseRightColor", this.diffuseFresnelParameters.rightColor);
+                this._effect.setColor4("diffuseLeftColor", this.diffuseFresnelParameters.leftColor, this.diffuseFresnelParameters.power);
+                this._effect.setColor4("diffuseRightColor", this.diffuseFresnelParameters.rightColor, this.diffuseFresnelParameters.bias);
+            }
+
+            if (this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled) {
+                this._effect.setColor4("opacityParts", new BABYLON.Color3(this.opacityFresnelParameters.leftColor.toLuminance(), this.opacityFresnelParameters.rightColor.toLuminance(), this.opacityFresnelParameters.bias), this.opacityFresnelParameters.power);
+            }
+
+            if (this.reflectionFresnelParameters && this.reflectionFresnelParameters.isEnabled) {
+                this._effect.setColor4("reflectionLeftColor", this.reflectionFresnelParameters.leftColor, this.reflectionFresnelParameters.power);
+                this._effect.setColor4("reflectionRightColor", this.reflectionFresnelParameters.rightColor, this.reflectionFresnelParameters.bias);
+            }
+
+            if (this.emissiveFresnelParameters && this.emissiveFresnelParameters.isEnabled) {
+                this._effect.setColor4("emissiveLeftColor", this.emissiveFresnelParameters.leftColor, this.emissiveFresnelParameters.power);
+                this._effect.setColor4("emissiveRightColor", this.emissiveFresnelParameters.rightColor, this.emissiveFresnelParameters.bias);
             }
 
             // Textures
@@ -374,8 +418,6 @@ var BABYLON;
 
                 this._effect.setFloat2("vDiffuseInfos", this.diffuseTexture.coordinatesIndex, this.diffuseTexture.level);
                 this._effect.setMatrix("diffuseMatrix", this.diffuseTexture.getTextureMatrix());
-
-                this._baseColor.copyFromFloats(1, 1, 1);
             }
 
             if (this.ambientTexture && BABYLON.StandardMaterial.AmbientTextureEnabled) {
@@ -429,7 +471,7 @@ var BABYLON;
 
             this._effect.setVector3("vEyePosition", scene.activeCamera.position);
             this._effect.setColor3("vAmbientColor", this._globalAmbientColor);
-            this._effect.setColor4("vDiffuseColor", this._baseColor, this.alpha * mesh.visibility);
+            this._effect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
             this._effect.setColor4("vSpecularColor", this.specularColor, this.specularPower);
             this._effect.setColor3("vEmissiveColor", this.emissiveColor);
 

+ 62 - 15
Babylon/Materials/babylon.standardMaterial.ts

@@ -3,8 +3,10 @@
 
     export class FresnelParameters {
         public isEnabled = true;
-        public leftColor = Color3.Black();
-        public rightColor = Color3.White();
+        public leftColor = Color3.White();
+        public rightColor = Color3.Black();
+        public bias = 0;
+        public power = 1;
     }
 
     export class StandardMaterial extends Material {
@@ -22,16 +24,17 @@
         public specularPower = 64;
         public emissiveColor = new BABYLON.Color3(0, 0, 0);
         public useAlphaFromDiffuseTexture = false;
+        public useSpecularOverAlpha = true;
 
         public diffuseFresnelParameters: FresnelParameters;
         public opacityFresnelParameters: FresnelParameters;
         public reflectionFresnelParameters: FresnelParameters;
+        public emissiveFresnelParameters: FresnelParameters;
 
         private _cachedDefines = null;
         private _renderTargets = new BABYLON.SmartArray<RenderTargetTexture>(16);
         private _worldViewProjectionMatrix = BABYLON.Matrix.Zero();
         private _globalAmbientColor = new BABYLON.Color3(0, 0, 0);
-        private _baseColor = new BABYLON.Color3();
         private _scaledDiffuse = new BABYLON.Color3();
         private _scaledSpecular = new BABYLON.Color3();
         private _renderId: number;
@@ -51,7 +54,7 @@
         }
 
         public needAlphaBlending(): boolean {
-            return (this.alpha < 1.0) || (this.opacityTexture != null) || this._shouldUseAlphaFromDiffuseTexture();
+            return (this.alpha < 1.0) || (this.opacityTexture != null) || this._shouldUseAlphaFromDiffuseTexture() || this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled;
         }
 
         public needAlphaTesting(): boolean {
@@ -153,6 +156,11 @@
             }
 
             // Effect
+            if (this.useSpecularOverAlpha) {
+                defines.push("#define SPECULAROVERALPHA");
+                fallbacks.addFallback(0, "SPECULAROVERALPHA");
+            }
+
             if (scene.clipPlane) {
                 defines.push("#define CLIPPLANE");
             }
@@ -264,11 +272,39 @@
             }
 
             // Fresnel
-            if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled) {
+            if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled ||
+                this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled ||
+                this.emissiveFresnelParameters && this.emissiveFresnelParameters.isEnabled ||
+                this.reflectionFresnelParameters && this.reflectionFresnelParameters.isEnabled) {
+
+                var fresnelRank = 1;
+
+                if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled) {
+                    defines.push("#define DIFFUSEFRESNEL");
+                    fallbacks.addFallback(fresnelRank, "DIFFUSEFRESNEL");
+                    fresnelRank++;
+                }
+
+                if (this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled) {
+                    defines.push("#define OPACITYFRESNEL");
+                    fallbacks.addFallback(fresnelRank, "OPACITYFRESNEL");
+                    fresnelRank++;
+                }
+
+                if (this.reflectionFresnelParameters && this.reflectionFresnelParameters.isEnabled) {
+                    defines.push("#define REFLECTIONFRESNEL");
+                    fallbacks.addFallback(fresnelRank, "REFLECTIONFRESNEL");
+                    fresnelRank++;
+                }
+
+                if (this.emissiveFresnelParameters && this.emissiveFresnelParameters.isEnabled) {
+                    defines.push("#define EMISSIVEFRESNEL");
+                    fallbacks.addFallback(fresnelRank, "EMISSIVEFRESNEL");
+                    fresnelRank++;
+                }
+
                 defines.push("#define FRESNEL");
-                defines.push("#define DIFFUSEFRESNEL");
-                fallbacks.addFallback(1, "FRESNEL");
-                fallbacks.addFallback(1, "DIFFUSEFRESNEL");
+                fallbacks.addFallback(fresnelRank - 1, "FRESNEL");
             }
 
 
@@ -329,7 +365,7 @@
                         "mBones",
                         "vClipPlane", "diffuseMatrix", "ambientMatrix", "opacityMatrix", "reflectionMatrix", "emissiveMatrix", "specularMatrix", "bumpMatrix",
                         "darkness0", "darkness1", "darkness2", "darkness3",
-                        "diffuseLeftColor", "diffuseRightColor"
+                        "diffuseLeftColor", "diffuseRightColor", "opacityParts", "reflectionLeftColor", "reflectionRightColor", "emissiveLeftColor", "emissiveRightColor"
                     ],
                     ["diffuseSampler", "ambientSampler", "opacitySampler", "reflectionCubeSampler", "reflection2DSampler", "emissiveSampler", "specularSampler", "bumpSampler",
                         "shadowSampler0", "shadowSampler1", "shadowSampler2", "shadowSampler3"
@@ -358,7 +394,6 @@
 
         public bind(world: Matrix, mesh: Mesh): void {
             var scene = this.getScene();
-            this._baseColor.copyFrom(this.diffuseColor);
 
             // Matrices        
             this.bindOnlyWorldMatrix(world);
@@ -371,8 +406,22 @@
 
             // Fresnel
             if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled) {
-                this._effect.setColor3("diffuseLeftColor", this.diffuseFresnelParameters.leftColor);
-                this._effect.setColor3("diffuseRightColor", this.diffuseFresnelParameters.rightColor);
+                this._effect.setColor4("diffuseLeftColor", this.diffuseFresnelParameters.leftColor, this.diffuseFresnelParameters.power);
+                this._effect.setColor4("diffuseRightColor", this.diffuseFresnelParameters.rightColor, this.diffuseFresnelParameters.bias);
+            }
+
+            if (this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled) {
+                this._effect.setColor4("opacityParts", new BABYLON.Color3(this.opacityFresnelParameters.leftColor.toLuminance(), this.opacityFresnelParameters.rightColor.toLuminance(), this.opacityFresnelParameters.bias), this.opacityFresnelParameters.power);
+            }
+
+            if (this.reflectionFresnelParameters && this.reflectionFresnelParameters.isEnabled) {
+                this._effect.setColor4("reflectionLeftColor", this.reflectionFresnelParameters.leftColor, this.reflectionFresnelParameters.power);
+                this._effect.setColor4("reflectionRightColor", this.reflectionFresnelParameters.rightColor, this.reflectionFresnelParameters.bias);
+            }
+
+            if (this.emissiveFresnelParameters && this.emissiveFresnelParameters.isEnabled) {
+                this._effect.setColor4("emissiveLeftColor", this.emissiveFresnelParameters.leftColor, this.emissiveFresnelParameters.power);
+                this._effect.setColor4("emissiveRightColor", this.emissiveFresnelParameters.rightColor, this.emissiveFresnelParameters.bias);
             }
 
             // Textures        
@@ -381,8 +430,6 @@
 
                 this._effect.setFloat2("vDiffuseInfos", this.diffuseTexture.coordinatesIndex, this.diffuseTexture.level);
                 this._effect.setMatrix("diffuseMatrix", this.diffuseTexture.getTextureMatrix());
-
-                this._baseColor.copyFromFloats(1, 1, 1);
             }
 
             if (this.ambientTexture && BABYLON.StandardMaterial.AmbientTextureEnabled) {
@@ -436,7 +483,7 @@
 
             this._effect.setVector3("vEyePosition", scene.activeCamera.position);
             this._effect.setColor3("vAmbientColor", this._globalAmbientColor);
-            this._effect.setColor4("vDiffuseColor", this._baseColor, this.alpha * mesh.visibility);
+            this._effect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
             this._effect.setColor4("vSpecularColor", this.specularColor, this.specularPower);
             this._effect.setColor3("vEmissiveColor", this.emissiveColor);
 

+ 1 - 0
Babylon/Materials/textures/babylon.renderTargetTexture.ts

@@ -6,6 +6,7 @@
         public coordinatesMode = BABYLON.Texture.PROJECTION_MODE;
         public onBeforeRender: () => void;
         public onAfterRender: () => void;
+        public activeCamera: Camera;
         public customRenderFunction: (opaqueSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, beforeTransparents?: () => void) => void;
 
         private _size: number;

+ 10 - 0
Babylon/Materials/textures/babylon.texture.js

@@ -8,8 +8,14 @@ var BABYLON;
 (function (BABYLON) {
     var Texture = (function (_super) {
         __extends(Texture, _super);
+<<<<<<< HEAD
         function Texture(url, scene, noMipmap, invertY, samplingMode, buffer, deleteBuffer) {
+=======
+        function Texture(url, scene, noMipmap, invertY, samplingMode, onLoad, onError) {
+>>>>>>> 08f8d5bd302ffec3b0c263e3d9b3a73544899aa5
             if (typeof samplingMode === "undefined") { samplingMode = Texture.TRILINEAR_SAMPLINGMODE; }
+            if (typeof onLoad === "undefined") { onLoad = null; }
+            if (typeof onError === "undefined") { onError = null; }
             _super.call(this, scene);
             this.uOffset = 0;
             this.vOffset = 0;
@@ -35,10 +41,14 @@ var BABYLON;
 
             if (!this._texture) {
                 if (!scene.useDelayedTextureLoading) {
+<<<<<<< HEAD
                     this._texture = scene.getEngine().createTexture(url, noMipmap, invertY, scene, this._samplingMode, this._buffer);
                     if (deleteBuffer) {
                         delete this._buffer;
                     }
+=======
+                    this._texture = scene.getEngine().createTexture(url, noMipmap, invertY, scene, this._samplingMode, onLoad, onError);
+>>>>>>> 08f8d5bd302ffec3b0c263e3d9b3a73544899aa5
                 } else {
                     this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NOTLOADED;
                 }

+ 8 - 0
Babylon/Materials/textures/babylon.texture.ts

@@ -47,7 +47,11 @@
         private _buffer: any;
         private _deleteBuffer: boolean;
 
+<<<<<<< HEAD
         constructor(url: string, scene: Scene, noMipmap?: boolean, invertY?: boolean, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE, buffer: any = null, deleteBuffer: boolean = false) {
+=======
+        constructor(url: string, scene: Scene, noMipmap?: boolean, invertY?: boolean, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE, onLoad: () => void = null, onError: () => void = null) {
+>>>>>>> 08f8d5bd302ffec3b0c263e3d9b3a73544899aa5
             super(scene);
 
             this.name = url;
@@ -68,10 +72,14 @@
 
             if (!this._texture) {
                 if (!scene.useDelayedTextureLoading) {
+<<<<<<< HEAD
                     this._texture = scene.getEngine().createTexture(url, noMipmap, invertY, scene, this._samplingMode, this._buffer);
                     if (deleteBuffer) {
                         delete this._buffer;
                     }
+=======
+                    this._texture = scene.getEngine().createTexture(url, noMipmap, invertY, scene, this._samplingMode, onLoad, onError);
+>>>>>>> 08f8d5bd302ffec3b0c263e3d9b3a73544899aa5
                 } else {
                     this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NOTLOADED;
                 }

+ 53 - 1
Babylon/Math/babylon.math.js

@@ -37,6 +37,10 @@
             return result;
         };
 
+        Color3.prototype.toLuminance = function () {
+            return this.r * 0.3 + this.g * 0.59 + this.b * 0.11;
+        };
+
         Color3.prototype.multiply = function (otherColor) {
             return new Color3(this.r * otherColor.r, this.g * otherColor.g, this.b * otherColor.b);
         };
@@ -289,6 +293,33 @@
             return new Vector2(this.x - otherVector.x, this.y - otherVector.y);
         };
 
+        Vector2.prototype.multiplyInPlace = function (otherVector) {
+            this.x *= otherVector.x;
+            this.y *= otherVector.y;
+        };
+
+        Vector2.prototype.multiply = function (otherVector) {
+            return new Vector2(this.x * otherVector.x, this.y * otherVector.y);
+        };
+
+        Vector2.prototype.multiplyToRef = function (otherVector, result) {
+            result.x = this.x * otherVector.x;
+            result.y = this.y * otherVector.y;
+        };
+
+        Vector2.prototype.multiplyByFloats = function (x, y) {
+            return new Vector2(this.x * x, this.y * y);
+        };
+
+        Vector2.prototype.divide = function (otherVector) {
+            return new Vector2(this.x / otherVector.x, this.y / otherVector.y);
+        };
+
+        Vector2.prototype.divideToRef = function (otherVector, result) {
+            result.x = this.x / otherVector.x;
+            result.y = this.y / otherVector.y;
+        };
+
         Vector2.prototype.negate = function () {
             return new Vector2(-this.x, -this.y);
         };
@@ -890,6 +921,13 @@
             this.w = other.w;
         };
 
+        Quaternion.prototype.copyFromFloats = function (x, y, z, w) {
+            this.x = x;
+            this.y = y;
+            this.z = z;
+            this.w = w;
+        };
+
         Quaternion.prototype.add = function (other) {
             return new Quaternion(this.x + other.x, this.y + other.y, this.z + other.z, this.w + other.w);
         };
@@ -930,6 +968,14 @@
         };
 
         Quaternion.prototype.toEulerAngles = function () {
+            var result = Vector3.Zero();
+
+            this.toEulerAnglesToRef(result);
+
+            return result;
+        };
+
+        Quaternion.prototype.toEulerAnglesToRef = function (result) {
             var qx = this.x;
             var qy = this.y;
             var qz = this.z;
@@ -952,7 +998,9 @@
                 roll = 0;
             }
 
-            return new Vector3(pitch, yaw, roll);
+            result.x = pitch;
+            result.y = yaw;
+            result.z = roll;
         };
 
         Quaternion.prototype.toRotationMatrix = function (result) {
@@ -1034,6 +1082,10 @@
         };
 
         // Statics
+        Quaternion.Inverse = function (q) {
+            return new Quaternion(-q.x, -q.y, -q.z, q.w);
+        };
+
         Quaternion.RotationAxis = function (axis, angle) {
             var result = new Quaternion();
             var sin = Math.sin(angle / 2);

+ 54 - 2
Babylon/Math/babylon.math.ts

@@ -30,6 +30,10 @@
             return result;
         }
 
+        public toLuminance(): number {
+            return this.r * 0.3 + this.g * 0.59 + this.b * 0.11;
+        }
+
         public multiply(otherColor: Color3): Color3 {
             return new Color3(this.r * otherColor.r, this.g * otherColor.g, this.b * otherColor.b);
         }
@@ -255,6 +259,33 @@
             return new Vector2(this.x - otherVector.x, this.y - otherVector.y);
         }
 
+        public multiplyInPlace(otherVector: Vector2): void {
+            this.x *= otherVector.x;
+            this.y *= otherVector.y;
+        }
+
+        public multiply(otherVector: Vector2): Vector2 {
+            return new Vector2(this.x * otherVector.x, this.y * otherVector.y);
+        }
+
+        public multiplyToRef(otherVector: Vector2, result: Vector2): void {
+            result.x = this.x * otherVector.x;
+            result.y = this.y * otherVector.y;
+        }
+
+        public multiplyByFloats(x: number, y: number): Vector2 {
+            return new Vector2(this.x * x, this.y * y);
+        }
+
+        public divide(otherVector: Vector2): Vector2 {
+            return new Vector2(this.x / otherVector.x, this.y / otherVector.y);
+        }
+
+        public divideToRef(otherVector: Vector2, result: Vector2): void {
+            result.x = this.x / otherVector.x;
+            result.y = this.y / otherVector.y;
+        }
+
         public negate(): Vector2 {
             return new Vector2(-this.x, -this.y);
         }
@@ -854,6 +885,13 @@
             this.z = other.z;
             this.w = other.w;
         }
+		
+		public copyFromFloats(x: number, y: number, z: number, w: number): void {
+            this.x = x;
+            this.y = y;
+            this.z = z;
+            this.w = w;
+        }
 
         public add(other: Quaternion): Quaternion {
             return new Quaternion(this.x + other.x, this.y + other.y, this.z + other.z, this.w + other.w);
@@ -893,8 +931,16 @@
             this.z *= length;
             this.w *= length;
         }
+		
+		public toEulerAngles(): Vector3 {
+            var result = Vector3.Zero();
+
+            this.toEulerAnglesToRef(result);
 
-        public toEulerAngles(): Vector3 {
+            return result;
+        }
+
+        public toEulerAnglesToRef(result: Vector3): void {
             var qx = this.x;
             var qy = this.y;
             var qz = this.z;
@@ -917,7 +963,9 @@
                 roll = 0;
             }
 
-            return new Vector3(pitch, yaw, roll);
+            result.x = pitch;
+            result.y = yaw;
+            result.z = roll;
         }
 
         public toRotationMatrix(result: Matrix): void {
@@ -1002,6 +1050,10 @@
         }
 
         // Statics
+        public static Inverse(q: Quaternion): Quaternion {
+			return new Quaternion(-q.x, -q.y, -q.z, q.w);
+        }
+
         public static RotationAxis(axis: Vector3, angle: number): Quaternion {
             var result = new Quaternion();
             var sin = Math.sin(angle / 2);

+ 2 - 1
Babylon/Mesh/babylon.abstractMesh.js

@@ -23,6 +23,7 @@ var BABYLON;
             this.showSubMeshesBoundingBox = false;
             this.onDispose = null;
             this.checkCollisions = false;
+            this.isBlocker = false;
             this.renderingGroupId = 0;
             this.receiveShadows = false;
             this.renderOutline = false;
@@ -345,7 +346,7 @@ var BABYLON;
             this._localPivotScaling.multiplyToRef(this._localRotation, this._localPivotScalingRotation);
 
             // Billboarding
-            if (this.billboardMode !== AbstractMesh.BILLBOARDMODE_NONE) {
+            if (this.billboardMode !== AbstractMesh.BILLBOARDMODE_NONE && this.getScene().activeCamera) {
                 var localPosition = this.position.clone();
                 var zero = this.getScene().activeCamera.position.clone();
 

+ 2 - 1
Babylon/Mesh/babylon.abstractMesh.ts

@@ -41,6 +41,7 @@
         public showSubMeshesBoundingBox = false;
         public onDispose = null;
         public checkCollisions = false;
+        public isBlocker = false;
         public skeleton: Skeleton;
         public renderingGroupId = 0;
         public material: Material;
@@ -339,7 +340,7 @@
             this._localPivotScaling.multiplyToRef(this._localRotation, this._localPivotScalingRotation);
 
             // Billboarding
-            if (this.billboardMode !== AbstractMesh.BILLBOARDMODE_NONE) {
+            if (this.billboardMode !== AbstractMesh.BILLBOARDMODE_NONE && this.getScene().activeCamera) {
                 var localPosition = this.position.clone();
                 var zero = this.getScene().activeCamera.position.clone();
 

+ 10 - 0
Babylon/Mesh/babylon.geometry.js

@@ -74,6 +74,16 @@ var BABYLON;
             }
         };
 
+        Geometry.prototype.updateVerticesDataDirectly = function (kind, data) {
+            var vertexBuffer = this.getVertexBuffer(kind);
+
+            if (!vertexBuffer) {
+                return;
+            }
+
+            vertexBuffer.updateDirectly(data);
+        };
+
         Geometry.prototype.updateVerticesData = function (kind, data, updateExtends) {
             var vertexBuffer = this.getVertexBuffer(kind);
 

+ 10 - 0
Babylon/Mesh/babylon.geometry.ts

@@ -83,6 +83,16 @@
             }
         }
 
+        public updateVerticesDataDirectly(kind: string, data: Float32Array): void {
+            var vertexBuffer = this.getVertexBuffer(kind);
+
+            if (!vertexBuffer) {
+                return;
+            }
+
+            vertexBuffer.updateDirectly(data);
+        }
+
         public updateVerticesData(kind: string, data: number[], updateExtends?: boolean): void {
             var vertexBuffer = this.getVertexBuffer(kind);
 

+ 25 - 2
Babylon/Mesh/babylon.mesh.js

@@ -212,6 +212,18 @@ var BABYLON;
             }
         };
 
+        Mesh.prototype.updateVerticesDataDirectly = function (kind, data, makeItUnique) {
+            if (!this._geometry) {
+                return;
+            }
+            if (!makeItUnique) {
+                this._geometry.updateVerticesDataDirectly(kind, data);
+            } else {
+                this.makeGeometryUnique();
+                this.updateVerticesDataDirectly(kind, data, false);
+            }
+        };
+
         Mesh.prototype.makeGeometryUnique = function () {
             if (!this._geometry) {
                 return;
@@ -514,12 +526,19 @@ var BABYLON;
 
                 scene._addPendingData(that);
 
+                var getBinaryData = (this.delayLoadingFile.indexOf(".babylonbinarymeshdata") !== -1) ? true : false;
+
                 BABYLON.Tools.LoadFile(this.delayLoadingFile, function (data) {
-                    _this._delayLoadingFunction(JSON.parse(data), _this);
+                    if (data instanceof ArrayBuffer) {
+                        _this._delayLoadingFunction(data, _this);
+                    } else {
+                        _this._delayLoadingFunction(JSON.parse(data), _this);
+                    }
+
                     _this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_LOADED;
                     scene._removePendingData(_this);
                 }, function () {
-                }, scene.database);
+                }, scene.database, getBinaryData);
             }
         };
 
@@ -563,6 +582,10 @@ var BABYLON;
                 results.push(this.material);
             }
 
+            if (this.skeleton) {
+                results.push(this.skeleton);
+            }
+
             return results;
         };
 

+ 29 - 2
Babylon/Mesh/babylon.mesh.ts

@@ -10,6 +10,7 @@
         public delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NONE;
         public instances = new Array<InstancedMesh>();
         public delayLoadingFile: string;
+        public _binaryInfo: any;
 
         // Private
         public _geometry: Geometry;
@@ -215,6 +216,19 @@
             }
         }
 
+        public updateVerticesDataDirectly(kind: string, data: Float32Array, makeItUnique?: boolean): void {
+            if (!this._geometry) {
+                return;
+            }
+            if (!makeItUnique) {
+                this._geometry.updateVerticesDataDirectly(kind, data);
+            }
+            else {
+                this.makeGeometryUnique();
+                this.updateVerticesDataDirectly(kind, data, false);
+            }
+        }
+
         public makeGeometryUnique() {
             if (!this._geometry) {
                 return;
@@ -518,11 +532,20 @@
 
                 scene._addPendingData(that);
 
+                var getBinaryData = (this.delayLoadingFile.indexOf(".babylonbinarymeshdata") !== -1) ? true : false;
+
                 BABYLON.Tools.LoadFile(this.delayLoadingFile, data => {
-                    this._delayLoadingFunction(JSON.parse(data), this);
+
+                    if (data instanceof ArrayBuffer) {
+                        this._delayLoadingFunction(data, this);
+                    }
+                    else {
+                        this._delayLoadingFunction(JSON.parse(data), this);
+                    }
+
                     this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_LOADED;
                     scene._removePendingData(this);
-                }, () => { }, scene.database);
+                }, () => { }, scene.database, getBinaryData);
             }
         }
 
@@ -566,6 +589,10 @@
                 results.push(this.material);
             }
 
+            if (this.skeleton) {
+                results.push(this.skeleton);
+            }
+
             return results;
         }
 

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

@@ -85,6 +85,17 @@
             this.create(data);
         };
 
+        VertexBuffer.prototype.updateDirectly = function (data) {
+            if (!this._buffer) {
+                return;
+            }
+
+            if (this._updatable) {
+                this._engine.updateDynamicVertexBuffer(this._buffer, data);
+                this._data = null;
+            }
+        };
+
         VertexBuffer.prototype.dispose = function () {
             if (!this._buffer) {
                 return;

+ 11 - 0
Babylon/Mesh/babylon.vertexBuffer.ts

@@ -94,6 +94,17 @@
             this.create(data);
         }
 
+        public updateDirectly(data: Float32Array): void {
+            if (!this._buffer) {
+                return;
+            }
+
+            if (this._updatable) { // update buffer
+                this._engine.updateDynamicVertexBuffer(this._buffer, data);
+                this._data = null;
+            }
+        }
+
         public dispose(): void {
             if (!this._buffer) {
                 return;

+ 9 - 13
Babylon/Particles/babylon.particleSystem.js

@@ -11,10 +11,9 @@
     };
 
     var ParticleSystem = (function () {
-        function ParticleSystem(name, capacity, scene, fragmentElement) {
+        function ParticleSystem(name, capacity, scene, customEffect) {
             var _this = this;
             this.name = name;
-            this.fragmentElement = fragmentElement;
             this.renderingGroupId = 0;
             this.emitter = null;
             this.emitRate = 10;
@@ -59,6 +58,8 @@
 
             this._scene = scene;
 
+            this._customEffect = customEffect;
+
             scene.particleSystems.push(this);
 
             // VBO
@@ -205,6 +206,11 @@
         };
 
         ParticleSystem.prototype._getEffect = function () {
+            if (this._customEffect) {
+                return this._customEffect;
+            }
+            ;
+
             var defines = [];
 
             if (this._scene.clipPlane) {
@@ -215,18 +221,8 @@
             var join = defines.join("\n");
             if (this._cachedDefines != join) {
                 this._cachedDefines = join;
-                var baseName;
-
-                if (this.fragmentElement) {
-                    baseName = {
-                        vertex: "particles",
-                        fragmentElement: this.fragmentElement
-                    };
-                } else {
-                    baseName = "particles";
-                }
 
-                this._effect = this._scene.getEngine().createEffect(baseName, ["position", "color", "options"], ["invView", "view", "projection", "vClipPlane", "textureMask"], ["diffuseSampler"], join);
+                this._effect = this._scene.getEngine().createEffect("particles", ["position", "color", "options"], ["invView", "view", "projection", "vClipPlane", "textureMask"], ["diffuseSampler"], join);
             }
 
             return this._effect;

+ 9 - 13
Babylon/Particles/babylon.particleSystem.ts

@@ -67,6 +67,7 @@
         private _indexBuffer: WebGLBuffer;
         private _vertices: Float32Array;
         private _effect: Effect;
+        private _customEffect: Effect;
         private _cachedDefines: string;
 
         private _scaledColorStep = new BABYLON.Color4(0, 0, 0, 0);
@@ -81,12 +82,14 @@
         private _actualFrame = 0;
         private _scaledUpdateSpeed: number;
 
-        constructor(public name: string, capacity: number, scene: Scene, public fragmentElement?: string) {
+        constructor(public name: string, capacity: number, scene: Scene, customEffect?: Effect) {
             this.id = name;
             this._capacity = capacity;
 
             this._scene = scene;
 
+            this._customEffect = customEffect;
+
             scene.particleSystems.push(this);
 
             // VBO
@@ -235,6 +238,10 @@
         }
 
         private _getEffect(): Effect {
+            if (this._customEffect) {
+                return this._customEffect;
+            };
+
             var defines = [];
 
             if (this._scene.clipPlane) {
@@ -245,20 +252,9 @@
             var join = defines.join("\n");
             if (this._cachedDefines != join) {
                 this._cachedDefines = join;
-                var baseName;
-
-                if (this.fragmentElement) {
-                    baseName = {
-                        vertex: "particles",
-                        fragmentElement: this.fragmentElement
-                    }
-                } else {
-                    baseName = "particles";
-                }
-
 
                 this._effect = this._scene.getEngine().createEffect(
-                    baseName,
+                    "particles",
                     ["position", "color", "options"],
                     ["invView", "view", "projection", "vClipPlane", "textureMask"],
                     ["diffuseSampler"], join);

+ 23 - 6
Babylon/Physics/Plugins/babylon.cannonJSPlugin.js

@@ -9,7 +9,9 @@
                     var registeredMesh = this._registeredMeshes[index];
                     if (registeredMesh.mesh === mesh || registeredMesh.mesh === mesh.parent) {
                         var body = registeredMesh.body.body;
-                        body.position.set(mesh.position.x, mesh.position.z, mesh.position.y);
+
+                        var center = mesh.getBoundingInfo().boundingBox.center;
+                        body.position.set(center.x, center.z, center.y);
 
                         body.quaternion.x = mesh.rotationQuaternion.x;
                         body.quaternion.z = mesh.rotationQuaternion.y;
@@ -41,9 +43,19 @@
                     continue;
                 }
 
-                registeredMesh.mesh.position.x = registeredMesh.body.position.x;
-                registeredMesh.mesh.position.y = registeredMesh.body.position.z;
-                registeredMesh.mesh.position.z = registeredMesh.body.position.y;
+                // Body position
+                var bodyX = registeredMesh.body.position.x, bodyY = registeredMesh.body.position.y, bodyZ = registeredMesh.body.position.z;
+
+                var deltaPos = registeredMesh.delta;
+                if (deltaPos) {
+                    registeredMesh.mesh.position.x = bodyX + deltaPos.x;
+                    registeredMesh.mesh.position.y = bodyZ + deltaPos.y;
+                    registeredMesh.mesh.position.z = bodyY + deltaPos.z;
+                } else {
+                    registeredMesh.mesh.position.x = bodyX;
+                    registeredMesh.mesh.position.y = bodyZ;
+                    registeredMesh.mesh.position.z = bodyY;
+                }
 
                 if (!registeredMesh.mesh.rotationQuaternion) {
                     registeredMesh.mesh.rotationQuaternion = new BABYLON.Quaternion(0, 0, 0, 1);
@@ -184,6 +196,10 @@
                 mesh.rotationQuaternion = new BABYLON.Quaternion(0, 0, 0, 1);
             }
 
+            // The delta between the mesh position and the mesh bounding box center
+            var bbox = mesh.getBoundingInfo().boundingBox;
+            var deltaPosition = mesh.position.subtract(bbox.center);
+
             var material = this._addMaterial(friction, restitution);
             var body = new CANNON.RigidBody(mass, shape, material);
 
@@ -194,10 +210,10 @@
                 body.quaternion.w = -initialRotation.w;
             }
 
-            body.position.set(mesh.position.x, mesh.position.z, mesh.position.y);
+            body.position.set(bbox.center.x, bbox.center.z, bbox.center.y);
             this._world.add(body);
 
-            this._registeredMeshes.push({ mesh: mesh, body: body, material: material });
+            this._registeredMeshes.push({ mesh: mesh, body: body, material: material, delta: deltaPosition });
 
             return body;
         };
@@ -231,6 +247,7 @@
 
                 if (registeredMesh.body === body) {
                     registeredMesh.body = null;
+                    registeredMesh.delta = 0;
                 }
             }
         };

+ 37 - 9
Babylon/Physics/Plugins/babylon.oimoJSPlugin.js

@@ -12,7 +12,9 @@ var BABYLON;
                     var registeredMesh = this._registeredMeshes[index];
                     if (registeredMesh.mesh === mesh || registeredMesh.mesh === mesh.parent) {
                         var body = registeredMesh.body.body;
-                        body.setPosition(mesh.position.x, mesh.position.y, mesh.position.z);
+
+                        var center = mesh.getBoundingInfo().boundingBox.center;
+                        body.setPosition(center.x, center.y, center.z);
                         body.setOrientation(mesh.rotation.x, mesh.rotation.y, mesh.rotation.z);
                         return;
                     }
@@ -59,10 +61,14 @@ var BABYLON;
                     var radiusZ = bbox.maximumWorld.z - bbox.minimumWorld.z;
 
                     var size = Math.max(this._checkWithEpsilon(radiusX), this._checkWithEpsilon(radiusY), this._checkWithEpsilon(radiusZ)) / 2;
+
+                    // The delta between the mesh position and the mesh bounding box center
+                    var deltaPosition = mesh.position.subtract(bbox.center);
+
                     body = new OIMO.Body({
                         type: 'sphere',
                         size: [size],
-                        pos: [mesh.position.x, mesh.position.y, mesh.position.z],
+                        pos: [bbox.center.x, bbox.center.y, bbox.center.z],
                         rot: [mesh.rotation.x / OIMO.TO_RAD, mesh.rotation.y / OIMO.TO_RAD, mesh.rotation.z / OIMO.TO_RAD],
                         move: options.mass != 0,
                         config: [options.mass, options.friction, options.restitution],
@@ -70,7 +76,8 @@ var BABYLON;
                     });
                     this._registeredMeshes.push({
                         mesh: mesh,
-                        body: body
+                        body: body,
+                        delta: deltaPosition
                     });
                     break;
 
@@ -83,10 +90,14 @@ var BABYLON;
                     var sizeX = this._checkWithEpsilon(box.x);
                     var sizeY = this._checkWithEpsilon(box.y);
                     var sizeZ = this._checkWithEpsilon(box.z);
+
+                    // The delta between the mesh position and the mesh boudning box center
+                    var deltaPosition = mesh.position.subtract(bbox.center);
+
                     body = new OIMO.Body({
                         type: 'box',
                         size: [sizeX, sizeY, sizeZ],
-                        pos: [mesh.position.x, mesh.position.y, mesh.position.z],
+                        pos: [bbox.center.x, bbox.center.y, bbox.center.z],
                         rot: [mesh.rotation.x / OIMO.TO_RAD, mesh.rotation.y / OIMO.TO_RAD, mesh.rotation.z / OIMO.TO_RAD],
                         move: options.mass != 0,
                         config: [options.mass, options.friction, options.restitution],
@@ -95,7 +106,8 @@ var BABYLON;
 
                     this._registeredMeshes.push({
                         mesh: mesh,
-                        body: body
+                        body: body,
+                        delta: deltaPosition
                     });
                     break;
             }
@@ -204,7 +216,11 @@ var BABYLON;
             for (var index = 0; index < this._registeredMeshes.length; index++) {
                 var registeredMesh = this._registeredMeshes[index];
                 if (registeredMesh.mesh === mesh || registeredMesh.mesh === mesh.parent) {
-                    registeredMesh.body.body.applyImpulse(contactPoint.scale(OIMO.INV_SCALE), force.scale(OIMO.INV_SCALE));
+                    // Get object mass to have a behaviour similar to cannon.js
+                    var mass = registeredMesh.body.body.massInfo.mass;
+
+                    // The force is scaled with the mass of object
+                    registeredMesh.body.body.applyImpulse(contactPoint.scale(OIMO.INV_SCALE), force.scale(OIMO.INV_SCALE * mass));
                     return;
                 }
             }
@@ -273,6 +289,8 @@ var BABYLON;
             while (i--) {
                 var body = this._registeredMeshes[i].body.body;
                 var mesh = this._registeredMeshes[i].mesh;
+                var delta = this._registeredMeshes[i].delta;
+
                 if (!body.sleeping) {
                     if (body.shapes.next) {
                         var parentShape = this._getLastShape(body);
@@ -288,9 +306,19 @@ var BABYLON;
                     } else {
                         m = body.getMatrix();
                         mtx = BABYLON.Matrix.FromArray(m);
-                        mesh.position.x = mtx.m[12];
-                        mesh.position.y = mtx.m[13];
-                        mesh.position.z = mtx.m[14];
+
+                        // Body position
+                        var bodyX = mtx.m[12], bodyY = mtx.m[13], bodyZ = mtx.m[14];
+
+                        if (!delta) {
+                            mesh.position.x = bodyX;
+                            mesh.position.y = bodyY;
+                            mesh.position.z = bodyZ;
+                        } else {
+                            mesh.position.x = bodyX + delta.x;
+                            mesh.position.y = bodyY + delta.y;
+                            mesh.position.z = bodyZ + delta.z;
+                        }
 
                         if (!mesh.rotationQuaternion) {
                             mesh.rotationQuaternion = new BABYLON.Quaternion(0, 0, 0, 1);

+ 17 - 14
Babylon/Physics/Plugins/babylon.oimoJSPlugin.ts

@@ -8,7 +8,7 @@ module BABYLON {
         private _checkWithEpsilon(value: number): number {
             return value < BABYLON.PhysicsEngine.Epsilon ? BABYLON.PhysicsEngine.Epsilon : value;
         }
-        
+
         public initialize(iterations?: number): void {
             this._world = new OIMO.World();
             this._world.clear();
@@ -34,7 +34,7 @@ module BABYLON {
                     var size = Math.max(
                         this._checkWithEpsilon(radiusX),
                         this._checkWithEpsilon(radiusY),
-                        this._checkWithEpsilon(radiusZ))/2;
+                        this._checkWithEpsilon(radiusZ)) / 2;
 
                     // The delta between the mesh position and the mesh bounding box center
                     var deltaPosition = mesh.position.subtract(bbox.center);
@@ -49,9 +49,9 @@ module BABYLON {
                         world: this._world
                     });
                     this._registeredMeshes.push({
-                        mesh:       mesh,
-                        body:       body,
-                        delta:  deltaPosition
+                        mesh: mesh,
+                        body: body,
+                        delta: deltaPosition
                     });
                     break;
 
@@ -79,9 +79,9 @@ module BABYLON {
                     });
 
                     this._registeredMeshes.push({
-                        mesh:   mesh,
-                        body:   body,
-                        delta:  deltaPosition
+                        mesh: mesh,
+                        body: body,
+                        delta: deltaPosition
                     });
                     break;
 
@@ -138,7 +138,7 @@ module BABYLON {
                     var size = Math.max(
                         this._checkWithEpsilon(radiusX),
                         this._checkWithEpsilon(radiusY),
-                        this._checkWithEpsilon(radiusZ))/2;
+                        this._checkWithEpsilon(radiusZ)) / 2;
                     bodyParameters = {
                         type: 'sphere',
                         /* bug with oimo : sphere needs 3 sizes in this case */
@@ -229,13 +229,16 @@ module BABYLON {
             for (var index = 0; index < this._registeredMeshes.length; index++) {
                 var registeredMesh = this._registeredMeshes[index];
                 if (registeredMesh.mesh === mesh || registeredMesh.mesh === mesh.parent) {
-                    registeredMesh.body.body.applyImpulse(contactPoint.scale(OIMO.INV_SCALE), force.scale(OIMO.INV_SCALE));
+                    // Get object mass to have a behaviour similar to cannon.js
+                    var mass = registeredMesh.body.body.massInfo.mass;
+                    // The force is scaled with the mass of object
+                    registeredMesh.body.body.applyImpulse(contactPoint.scale(OIMO.INV_SCALE), force.scale(OIMO.INV_SCALE * mass));
                     return;
                 }
             }
         }
 
-        public createLink (mesh1: AbstractMesh, mesh2: AbstractMesh, pivot1: Vector3, pivot2: Vector3, options?: any): boolean {
+        public createLink(mesh1: AbstractMesh, mesh2: AbstractMesh, pivot1: Vector3, pivot2: Vector3, options?: any): boolean {
             var body1 = null,
                 body2 = null;
             for (var index = 0; index < this._registeredMeshes.length; index++) {
@@ -301,7 +304,7 @@ module BABYLON {
 
                 var body = this._registeredMeshes[i].body.body;
                 var mesh = this._registeredMeshes[i].mesh;
-                var delta  = this._registeredMeshes[i].delta;
+                var delta = this._registeredMeshes[i].delta;
 
                 if (!body.sleeping) {
 
@@ -326,7 +329,7 @@ module BABYLON {
                             bodyY = mtx.m[13],
                             bodyZ = mtx.m[14];
 
-                        if (delta) {
+                        if (!delta) {
                             mesh.position.x = bodyX;
                             mesh.position.y = bodyY;
                             mesh.position.z = bodyZ;
@@ -345,4 +348,4 @@ module BABYLON {
             }
         }
     }
-}
+}

+ 10 - 65
Babylon/PostProcess/RenderPipeline/babylon.postProcessRenderEffect.js

@@ -1,14 +1,13 @@
 var BABYLON;
 (function (BABYLON) {
     var PostProcessRenderEffect = (function () {
-        function PostProcessRenderEffect(engine, name, postProcessType, ratio, samplingMode, singleInstance) {
+        function PostProcessRenderEffect(engine, name, getPostProcess, singleInstance) {
             this._engine = engine;
             this._name = name;
-            this._postProcessType = postProcessType;
-            this._ratio = ratio || 1.0;
-            this._samplingMode = samplingMode || null;
             this._singleInstance = singleInstance || true;
 
+            this._getPostProcess = getPostProcess;
+
             this._cameras = [];
 
             this._postProcesses = [];
@@ -16,64 +15,7 @@ var BABYLON;
 
             this._renderPasses = [];
             this._renderEffectAsPasses = [];
-
-            this.parameters = function (effect) {
-            };
         }
-        PostProcessRenderEffect._GetInstance = function (engine, postProcessType, ratio, samplingMode) {
-            var postProcess;
-            var instance;
-            var args = [];
-
-            var parameters = PostProcessRenderEffect._GetParametersNames(postProcessType);
-            for (var i = 0; i < parameters.length; i++) {
-                switch (parameters[i]) {
-                    case "name":
-                        args[i] = postProcessType.toString();
-                        break;
-                    case "ratio":
-                        args[i] = ratio;
-                        break;
-                    case "camera":
-                        args[i] = null;
-                        break;
-                    case "samplingMode":
-                        args[i] = samplingMode;
-                        break;
-                    case "engine":
-                        args[i] = engine;
-                        break;
-                    case "reusable":
-                        args[i] = true;
-                        break;
-                    default:
-                        args[i] = null;
-                        break;
-                }
-            }
-
-            postProcess = function () {
-            };
-            postProcess.prototype = postProcessType.prototype;
-
-            instance = new postProcess();
-            postProcessType.apply(instance, args);
-
-            return instance;
-        };
-
-        PostProcessRenderEffect._GetParametersNames = function (func) {
-            var commentsRegex = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
-            var functWithoutComments = func.toString().replace(commentsRegex, '');
-
-            var parameters = functWithoutComments.slice(functWithoutComments.indexOf('(') + 1, functWithoutComments.indexOf(')')).match(/([^\s,]+)/g);
-
-            if (parameters === null)
-                parameters = [];
-
-            return parameters;
-        };
-
         PostProcessRenderEffect.prototype._update = function () {
             for (var renderPassName in this._renderPasses) {
                 this._renderPasses[renderPassName]._update();
@@ -127,11 +69,11 @@ var BABYLON;
                     cameraKey = cameraName;
                 }
 
-                this._postProcesses[cameraKey] = this._postProcesses[cameraKey] || PostProcessRenderEffect._GetInstance(this._engine, this._postProcessType, this._ratio, this._samplingMode);
+                this._postProcesses[cameraKey] = this._postProcesses[cameraKey] || this._getPostProcess();
 
                 var index = camera.attachPostProcess(this._postProcesses[cameraKey]);
 
-                if (this._indicesForCamera[cameraName] === null) {
+                if (!this._indicesForCamera[cameraName]) {
                     this._indicesForCamera[cameraName] = [];
                 }
 
@@ -214,8 +156,11 @@ var BABYLON;
         PostProcessRenderEffect.prototype._linkParameters = function () {
             var _this = this;
             for (var index in this._postProcesses) {
-                this._postProcesses[index].onApply = function (effect) {
-                    _this.parameters(effect);
+                if (this.applyParameters) {
+                    this.applyParameters(this._postProcesses[index]);
+                }
+
+                this._postProcesses[index].onBeforeRender = function (effect) {
                     _this._linkTextures(effect);
                 };
             }

+ 12 - 67
Babylon/PostProcess/RenderPipeline/babylon.postProcessRenderEffect.ts

@@ -3,10 +3,8 @@ module BABYLON {
         private _engine: Engine;
 
         private _postProcesses: PostProcess[];
-        private _postProcessType; //The type must inherit from PostProcess (example: BABYLON.BlackAndWhitePostProcess, like this without quotes).
+        private _getPostProcess: () => PostProcess;
 
-        private _ratio: number;
-        private _samplingMode: number;
         private _singleInstance: boolean;
 
         private _cameras: Camera[];
@@ -18,16 +16,15 @@ module BABYLON {
         // private
         public _name: string;
 
-        public parameters: (effect: Effect) => void;
+        public applyParameters: (postProcess: PostProcess) => void;
 
-        constructor(engine: Engine, name: string, postProcessType, ratio?: number, samplingMode?: number, singleInstance?: boolean) {
+        constructor(engine: Engine, name: string, getPostProcess: () => PostProcess, singleInstance?: boolean) {
             this._engine = engine;
             this._name = name;
-            this._postProcessType = postProcessType;
-            this._ratio = ratio || 1.0;
-            this._samplingMode = samplingMode || null;
             this._singleInstance = singleInstance || true;
 
+            this._getPostProcess = getPostProcess;
+
             this._cameras = [];
 
             this._postProcesses = [];
@@ -35,61 +32,6 @@ module BABYLON {
 
             this._renderPasses = [];
             this._renderEffectAsPasses = [];
-
-            this.parameters = (effect: Effect) => { };
-        }
-
-        private static _GetInstance(engine: Engine, postProcessType, ratio: number, samplingMode: number): PostProcess {
-            var postProcess;
-            var instance;
-            var args = [];
-
-            var parameters = PostProcessRenderEffect._GetParametersNames(postProcessType);
-            for (var i = 0; i < parameters.length; i++) {
-                switch (parameters[i]) {
-                    case "name":
-                        args[i] = postProcessType.toString();
-                        break;
-                    case "ratio":
-                        args[i] = ratio;
-                        break;
-                    case "camera":
-                        args[i] = null;
-                        break;
-                    case "samplingMode":
-                        args[i] = samplingMode;
-                        break;
-                    case "engine":
-                        args[i] = engine;
-                        break;
-                    case "reusable":
-                        args[i] = true;
-                        break;
-                    default:
-                        args[i] = null;
-                        break;
-                }
-            }
-
-            postProcess = function () { };
-            postProcess.prototype = postProcessType.prototype;
-
-            instance = new postProcess();
-            postProcessType.apply(instance, args);
-
-            return instance;
-        }
-
-        private static _GetParametersNames(func): string[] {
-            var commentsRegex = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
-            var functWithoutComments = func.toString().replace(commentsRegex, '');
-
-            var parameters = functWithoutComments.slice(functWithoutComments.indexOf('(') + 1, functWithoutComments.indexOf(')')).match(/([^\s,]+)/g);
-
-            if (parameters === null)
-                parameters = [];
-
-            return parameters;
         }
 
         public _update(): void {
@@ -149,11 +91,11 @@ module BABYLON {
                     cameraKey = cameraName;
                 }
 
-                this._postProcesses[cameraKey] = this._postProcesses[cameraKey] || PostProcessRenderEffect._GetInstance(this._engine, this._postProcessType, this._ratio, this._samplingMode);
+                this._postProcesses[cameraKey] = this._postProcesses[cameraKey] || this._getPostProcess();
 
                 var index = camera.attachPostProcess(this._postProcesses[cameraKey]);
 
-                if (this._indicesForCamera[cameraName] === null) {
+                if (!this._indicesForCamera[cameraName]) {
                     this._indicesForCamera[cameraName] = [];
                 }
 
@@ -245,8 +187,11 @@ module BABYLON {
 
         private _linkParameters(): void {
             for (var index in this._postProcesses) {
-                this._postProcesses[index].onApply = (effect: Effect) => {
-                    this.parameters(effect);
+                if (this.applyParameters) {
+                    this.applyParameters(this._postProcesses[index]);
+                }
+
+                this._postProcesses[index].onBeforeRender = (effect: Effect) => {
                     this._linkTextures(effect);
                 };
             }

+ 10 - 4
Babylon/PostProcess/RenderPipeline/babylon.postProcessRenderPipeline.js

@@ -21,7 +21,7 @@ var BABYLON;
                 return;
             }
 
-            renderEffects.enable(BABYLON.Tools.MakeArray(cameras || this._cameras));
+            renderEffects._enable(BABYLON.Tools.MakeArray(cameras || this._cameras));
         };
 
         PostProcessRenderPipeline.prototype._disableEffect = function (renderEffectName, cameras) {
@@ -31,7 +31,7 @@ var BABYLON;
                 return;
             }
 
-            renderEffects.disable(BABYLON.Tools.MakeArray(cameras || this._cameras));
+            renderEffects._disable(BABYLON.Tools.MakeArray(cameras || this._cameras));
         };
 
         PostProcessRenderPipeline.prototype._attachCameras = function (cameras, unique) {
@@ -72,6 +72,7 @@ var BABYLON;
         };
 
         PostProcessRenderPipeline.prototype._enableDisplayOnlyPass = function (passName, cameras) {
+            var _this = this;
             var _cam = BABYLON.Tools.MakeArray(cameras || this._cameras);
 
             var pass = null;
@@ -98,7 +99,9 @@ var BABYLON;
                 var camera = _cam[i];
                 var cameraName = camera.name;
 
-                this._renderEffectsForIsolatedPass[cameraName] = this._renderEffectsForIsolatedPass[cameraName] || new BABYLON.PostProcessRenderEffect(this._engine, PostProcessRenderPipeline.PASS_EFFECT_NAME, "BABYLON.DisplayPassPostProcess", 1.0, null, null);
+                this._renderEffectsForIsolatedPass[cameraName] = this._renderEffectsForIsolatedPass[cameraName] || new BABYLON.PostProcessRenderEffect(this._engine, PostProcessRenderPipeline.PASS_EFFECT_NAME, function () {
+                    return new BABYLON.DisplayPassPostProcess(PostProcessRenderPipeline.PASS_EFFECT_NAME, 1.0, null, null, _this._engine, true);
+                });
                 this._renderEffectsForIsolatedPass[cameraName].emptyPasses();
                 this._renderEffectsForIsolatedPass[cameraName].addPass(pass);
                 this._renderEffectsForIsolatedPass[cameraName]._attachCameras(camera);
@@ -106,13 +109,16 @@ var BABYLON;
         };
 
         PostProcessRenderPipeline.prototype._disableDisplayOnlyPass = function (cameras) {
+            var _this = this;
             var _cam = BABYLON.Tools.MakeArray(cameras || this._cameras);
 
             for (var i = 0; i < _cam.length; i++) {
                 var camera = _cam[i];
                 var cameraName = camera.name;
 
-                this._renderEffectsForIsolatedPass[cameraName] = this._renderEffectsForIsolatedPass[cameraName] || new BABYLON.PostProcessRenderEffect(this._engine, PostProcessRenderPipeline.PASS_EFFECT_NAME, "BABYLON.DisplayPassPostProcess", 1.0, null, null);
+                this._renderEffectsForIsolatedPass[cameraName] = this._renderEffectsForIsolatedPass[cameraName] || new BABYLON.PostProcessRenderEffect(this._engine, PostProcessRenderPipeline.PASS_EFFECT_NAME, function () {
+                    return new BABYLON.DisplayPassPostProcess(PostProcessRenderPipeline.PASS_EFFECT_NAME, 1.0, null, null, _this._engine, true);
+                });
                 this._renderEffectsForIsolatedPass[cameraName]._disable(camera);
             }
 

+ 8 - 6
Babylon/PostProcess/RenderPipeline/babylon.postProcessRenderPipeline.ts

@@ -32,25 +32,25 @@ module BABYLON {
         public _enableEffect(renderEffectName: string, cameras: Camera);
         public _enableEffect(renderEffectName: string, cameras: Camera[]);
         public _enableEffect(renderEffectName: string, cameras: any): void {
-            var renderEffects = this._renderEffects[renderEffectName];
+            var renderEffects: PostProcessRenderEffect = this._renderEffects[renderEffectName];
 
             if (!renderEffects) {
                 return;
             }
 
-            renderEffects.enable(Tools.MakeArray(cameras || this._cameras));
+            renderEffects._enable(Tools.MakeArray(cameras || this._cameras));
         }
 
         public _disableEffect(renderEffectName: string, cameras: Camera);
         public _disableEffect(renderEffectName: string, cameras: Camera[]);
         public _disableEffect(renderEffectName: string, cameras): void {
-            var renderEffects = this._renderEffects[renderEffectName];
+            var renderEffects: PostProcessRenderEffect = this._renderEffects[renderEffectName];
 
             if (!renderEffects) {
                 return;
             }
 
-            renderEffects.disable(Tools.MakeArray(cameras || this._cameras));
+            renderEffects._disable(Tools.MakeArray(cameras || this._cameras));
         }
 
         public _attachCameras(cameras: Camera, unique: boolean);
@@ -124,7 +124,8 @@ module BABYLON {
                 var camera = _cam[i];
                 var cameraName = camera.name;
 
-                this._renderEffectsForIsolatedPass[cameraName] = this._renderEffectsForIsolatedPass[cameraName] || new PostProcessRenderEffect(this._engine, PostProcessRenderPipeline.PASS_EFFECT_NAME, "BABYLON.DisplayPassPostProcess", 1.0, null, null);
+                this._renderEffectsForIsolatedPass[cameraName] = this._renderEffectsForIsolatedPass[cameraName] || new PostProcessRenderEffect(this._engine, PostProcessRenderPipeline.PASS_EFFECT_NAME,
+                    () => {return new DisplayPassPostProcess(PostProcessRenderPipeline.PASS_EFFECT_NAME, 1.0, null, null, this._engine, true) });
                 this._renderEffectsForIsolatedPass[cameraName].emptyPasses();
                 this._renderEffectsForIsolatedPass[cameraName].addPass(pass);
                 this._renderEffectsForIsolatedPass[cameraName]._attachCameras(camera);
@@ -140,7 +141,8 @@ module BABYLON {
                 var camera = _cam[i];
                 var cameraName = camera.name;
 
-                this._renderEffectsForIsolatedPass[cameraName] = this._renderEffectsForIsolatedPass[cameraName] || new PostProcessRenderEffect(this._engine, PostProcessRenderPipeline.PASS_EFFECT_NAME, "BABYLON.DisplayPassPostProcess", 1.0, null, null);
+                this._renderEffectsForIsolatedPass[cameraName] = this._renderEffectsForIsolatedPass[cameraName] || new PostProcessRenderEffect(this._engine, PostProcessRenderPipeline.PASS_EFFECT_NAME, 
+                                    () => {return new DisplayPassPostProcess(PostProcessRenderPipeline.PASS_EFFECT_NAME, 1.0, null, null, this._engine, true) });
                 this._renderEffectsForIsolatedPass[cameraName]._disable(camera);
             }
 

+ 7 - 7
Babylon/PostProcess/RenderPipeline/babylon.postProcessRenderPipelineManager.js

@@ -2,7 +2,7 @@ var BABYLON;
 (function (BABYLON) {
     var PostProcessRenderPipelineManager = (function () {
         function PostProcessRenderPipelineManager() {
-            this._renderPipelines = [];
+            this._renderPipelines = new Array();
         }
         PostProcessRenderPipelineManager.prototype.addPipeline = function (renderPipeline) {
             this._renderPipelines[renderPipeline._name] = renderPipeline;
@@ -15,7 +15,7 @@ var BABYLON;
                 return;
             }
 
-            renderPipeline.attachCameras(cameras, unique);
+            renderPipeline._attachCameras(cameras, unique);
         };
 
         PostProcessRenderPipelineManager.prototype.detachCamerasFromRenderPipeline = function (renderPipelineName, cameras) {
@@ -25,7 +25,7 @@ var BABYLON;
                 return;
             }
 
-            renderPipeline.detachCameras(cameras);
+            renderPipeline._detachCameras(cameras);
         };
 
         PostProcessRenderPipelineManager.prototype.enableEffectInPipeline = function (renderPipelineName, renderEffectName, cameras) {
@@ -35,7 +35,7 @@ var BABYLON;
                 return;
             }
 
-            renderPipeline.enableEffect(renderEffectName, cameras);
+            renderPipeline._enableEffect(renderEffectName, cameras);
         };
 
         PostProcessRenderPipelineManager.prototype.disableEffectInPipeline = function (renderPipelineName, renderEffectName, cameras) {
@@ -45,7 +45,7 @@ var BABYLON;
                 return;
             }
 
-            renderPipeline.disableEffect(renderEffectName, cameras);
+            renderPipeline._disableEffect(renderEffectName, cameras);
         };
 
         PostProcessRenderPipelineManager.prototype.enableDisplayOnlyPassInPipeline = function (renderPipelineName, passName, cameras) {
@@ -55,7 +55,7 @@ var BABYLON;
                 return;
             }
 
-            renderPipeline.enableDisplayOnlyPass(passName, cameras);
+            renderPipeline._enableDisplayOnlyPass(passName, cameras);
         };
 
         PostProcessRenderPipelineManager.prototype.disableDisplayOnlyPassInPipeline = function (renderPipelineName, cameras) {
@@ -65,7 +65,7 @@ var BABYLON;
                 return;
             }
 
-            renderPipeline.disableDisplayOnlyPass(cameras);
+            renderPipeline._disableDisplayOnlyPass(cameras);
         };
 
         PostProcessRenderPipelineManager.prototype.update = function () {

+ 14 - 14
Babylon/PostProcess/RenderPipeline/babylon.postProcessRenderPipelineManager.ts

@@ -1,9 +1,9 @@
 module BABYLON {
     export class PostProcessRenderPipelineManager {
-        private _renderPipelines: PostProcessRenderPipeline[];
+        private _renderPipelines: Array<PostProcessRenderPipeline>;
 
         constructor() {
-            this._renderPipelines = [];
+            this._renderPipelines = new Array<PostProcessRenderPipeline>();
         }
 
         public addPipeline(renderPipeline: PostProcessRenderPipeline): void {
@@ -13,73 +13,73 @@ module BABYLON {
         public attachCamerasToRenderPipeline(renderPipelineName: string, cameras: Camera, unique?: boolean);
         public attachCamerasToRenderPipeline(renderPipelineName: string, cameras: Camera[], unique?: boolean);
         public attachCamerasToRenderPipeline(renderPipelineName: string, cameras: any, unique?: boolean): void {
-            var renderPipeline = this._renderPipelines[renderPipelineName];
+            var renderPipeline: PostProcessRenderPipeline = this._renderPipelines[renderPipelineName];
 
             if (!renderPipeline) {
                 return;
             }
 
-            renderPipeline.attachCameras(cameras, unique);
+            renderPipeline._attachCameras(cameras, unique);
         }
 
         public detachCamerasFromRenderPipeline(renderPipelineName: string, cameras: Camera);
         public detachCamerasFromRenderPipeline(renderPipelineName: string, cameras: Camera[]);
         public detachCamerasFromRenderPipeline(renderPipelineName: string, cameras: any): void {
-            var renderPipeline = this._renderPipelines[renderPipelineName];
+            var renderPipeline: PostProcessRenderPipeline = this._renderPipelines[renderPipelineName];
 
             if (!renderPipeline) {
                 return;
             }
 
-            renderPipeline.detachCameras(cameras);
+            renderPipeline._detachCameras(cameras);
         }
 
         public enableEffectInPipeline(renderPipelineName: string, renderEffectName: string, cameras: Camera);
         public enableEffectInPipeline(renderPipelineName: string, renderEffectName: string, cameras: Camera[]);
         public enableEffectInPipeline(renderPipelineName: string, renderEffectName: string, cameras: any): void {
-            var renderPipeline = this._renderPipelines[renderPipelineName];
+            var renderPipeline: PostProcessRenderPipeline = this._renderPipelines[renderPipelineName];
 
             if (!renderPipeline) {
                 return;
             }
 
-            renderPipeline.enableEffect(renderEffectName, cameras);
+            renderPipeline._enableEffect(renderEffectName, cameras);
         }
 
         public disableEffectInPipeline(renderPipelineName: string, renderEffectName: string, cameras: Camera);
         public disableEffectInPipeline(renderPipelineName: string, renderEffectName: string, cameras: Camera[]);
         public disableEffectInPipeline(renderPipelineName: string, renderEffectName: string, cameras: any): void {
-            var renderPipeline = this._renderPipelines[renderPipelineName];
+            var renderPipeline: PostProcessRenderPipeline = this._renderPipelines[renderPipelineName];
 
             if (!renderPipeline) {
                 return;
             }
 
-            renderPipeline.disableEffect(renderEffectName, cameras);
+            renderPipeline._disableEffect(renderEffectName, cameras);
         }
 
         public enableDisplayOnlyPassInPipeline(renderPipelineName: string, passName: string, cameras: Camera);
         public enableDisplayOnlyPassInPipeline(renderPipelineName: string, passName: string, cameras: Camera[]);
         public enableDisplayOnlyPassInPipeline(renderPipelineName: string, passName: string, cameras: any): void {
-            var renderPipeline = this._renderPipelines[renderPipelineName];
+            var renderPipeline: PostProcessRenderPipeline = this._renderPipelines[renderPipelineName];
 
             if (!renderPipeline) {
                 return;
             }
 
-            renderPipeline.enableDisplayOnlyPass(passName, cameras);
+            renderPipeline._enableDisplayOnlyPass(passName, cameras);
         }
 
         public disableDisplayOnlyPassInPipeline(renderPipelineName: string, cameras: Camera);
         public disableDisplayOnlyPassInPipeline(renderPipelineName: string, cameras: Camera[]);
         public disableDisplayOnlyPassInPipeline(renderPipelineName: string, cameras: any): void {
-            var renderPipeline = this._renderPipelines[renderPipelineName];
+            var renderPipeline: PostProcessRenderPipeline = this._renderPipelines[renderPipelineName];
 
             if (!renderPipeline) {
                 return;
             }
 
-            renderPipeline.disableDisplayOnlyPass(cameras);
+            renderPipeline._disableDisplayOnlyPass(cameras);
         }
 
         public update(): void {

+ 7 - 2
Babylon/PostProcess/babylon.postProcess.js

@@ -34,8 +34,13 @@
             camera = camera || this._camera;
 
             var scene = camera.getScene();
-            var desiredWidth = (sourceTexture ? sourceTexture._width : this._engine.getRenderingCanvas().width) * this._renderRatio;
-            var desiredHeight = (sourceTexture ? sourceTexture._height : this._engine.getRenderingCanvas().height) * this._renderRatio;
+            var maxSize = camera.getEngine().getCaps().maxTextureSize;
+            var desiredWidth = ((sourceTexture ? sourceTexture._width : this._engine.getRenderingCanvas().width) * this._renderRatio) | 0;
+            var desiredHeight = ((sourceTexture ? sourceTexture._height : this._engine.getRenderingCanvas().height) * this._renderRatio) | 0;
+
+            desiredWidth = BABYLON.Tools.GetExponantOfTwo(desiredWidth, maxSize);
+            desiredHeight = BABYLON.Tools.GetExponantOfTwo(desiredHeight, maxSize);
+
             if (this.width !== desiredWidth || this.height !== desiredHeight) {
                 if (this._textures.length > 0) {
                     for (var i = 0; i < this._textures.length; i++) {

+ 8 - 2
Babylon/PostProcess/babylon.postProcess.ts

@@ -1,6 +1,7 @@
 module BABYLON {
     export class PostProcess {
         public onApply: (Effect) => void;
+        public onBeforeRender: (Effect) => void;
         public onSizeChanged: () => void;
         public onActivate: (Camera) => void;
         public width = -1;
@@ -48,8 +49,13 @@
             camera = camera || this._camera;
 
             var scene = camera.getScene();
-            var desiredWidth =  (sourceTexture ? sourceTexture._width : this._engine.getRenderingCanvas().width) * this._renderRatio;
-            var desiredHeight = (sourceTexture ? sourceTexture._height : this._engine.getRenderingCanvas().height) * this._renderRatio;
+            var maxSize = camera.getEngine().getCaps().maxTextureSize;
+            var desiredWidth = ((sourceTexture ? sourceTexture._width : this._engine.getRenderingCanvas().width) * this._renderRatio) | 0;
+            var desiredHeight = ((sourceTexture ? sourceTexture._height : this._engine.getRenderingCanvas().height) * this._renderRatio) | 0;
+
+            desiredWidth = Tools.GetExponantOfTwo(desiredWidth, maxSize);
+            desiredHeight = Tools.GetExponantOfTwo(desiredHeight, maxSize);
+
             if (this.width !== desiredWidth || this.height !== desiredHeight) {
                 if (this._textures.length > 0) {
                     for (var i = 0; i < this._textures.length; i++) {

+ 6 - 1
Babylon/PostProcess/babylon.postProcessManager.js

@@ -64,9 +64,14 @@
                     break;
                 }
 
-                var effect = postProcesses[postProcessesTakenIndices[index]].apply();
+                var pp = postProcesses[postProcessesTakenIndices[index]];
+                var effect = pp.apply();
 
                 if (effect) {
+                    if (pp.onBeforeRender) {
+                        pp.onBeforeRender(effect);
+                    }
+
                     // VBOs
                     engine.bindBuffers(this._vertexBuffer, this._indexBuffer, this._vertexDeclaration, this._vertexStrideSize, effect);
 

+ 6 - 1
Babylon/PostProcess/babylon.postProcessManager.ts

@@ -68,9 +68,14 @@
                     break;
                 }
 
-                var effect = postProcesses[postProcessesTakenIndices[index]].apply();
+                var pp = postProcesses[postProcessesTakenIndices[index]];
+                var effect = pp.apply();
 
                 if (effect) {
+                    if (pp.onBeforeRender) {
+                        pp.onBeforeRender(effect);
+                    }
+
                     // VBOs
                     engine.bindBuffers(this._vertexBuffer, this._indexBuffer, this._vertexDeclaration, this._vertexStrideSize, effect);
 

+ 1 - 1
Babylon/Shaders/anaglyph.fragment.fx

@@ -1,5 +1,5 @@
 #ifdef GL_ES
-precision mediump float;
+precision highp float;
 #endif
 
 // Samplers

+ 1 - 1
Babylon/Shaders/blackAndWhite.fragment.fx

@@ -1,5 +1,5 @@
 #ifdef GL_ES
-precision mediump float;
+precision highp float;
 #endif
 
 // Samplers

+ 1 - 1
Babylon/Shaders/blur.fragment.fx

@@ -1,5 +1,5 @@
 #ifdef GL_ES
-precision mediump float;
+precision highp float;
 #endif
 
 // Samplers

+ 1 - 1
Babylon/Shaders/color.fragment.fx

@@ -1,4 +1,4 @@
-precision mediump float;
+precision highp float;
 
 uniform vec4 color;
 

+ 1 - 1
Babylon/Shaders/color.vertex.fx

@@ -1,4 +1,4 @@
-precision mediump float;
+precision highp float;
 
 // Attributes
 attribute vec3 position;

+ 1 - 1
Babylon/Shaders/convolution.fragment.fx

@@ -1,5 +1,5 @@
 #ifdef GL_ES
-precision mediump float;
+precision highp float;
 #endif
 
 // Samplers

+ 44 - 8
Babylon/Shaders/default.fragment.fx

@@ -1,5 +1,5 @@
 #ifdef GL_ES
-precision mediump float;
+precision highp float;
 #endif
 
 #define MAP_EXPLICIT	0.
@@ -126,16 +126,30 @@ uniform sampler2D specularSampler;
 
 // Fresnel
 #ifdef FRESNEL
-float computeFresnelTerm(vec3 viewDirection, vec3 worldNormal)
+float computeFresnelTerm(vec3 viewDirection, vec3 worldNormal, float bias, float power)
 {
-	float fresnelTerm = dot(viewDirection, worldNormal);
-	return clamp(1.0 - fresnelTerm, 0., 1.);
+	float fresnelTerm = pow(bias + abs(dot(viewDirection, worldNormal)), power);
+	return clamp(fresnelTerm, 0., 1.);
 }
 #endif
 
 #ifdef DIFFUSEFRESNEL
-uniform vec3 diffuseLeftColor;
-uniform vec3 diffuseRightColor;
+uniform vec4 diffuseLeftColor;
+uniform vec4 diffuseRightColor;
+#endif
+
+#ifdef OPACITYFRESNEL
+uniform vec4 opacityParts;
+#endif
+
+#ifdef REFLECTIONFRESNEL
+uniform vec4 reflectionLeftColor;
+uniform vec4 reflectionRightColor;
+#endif
+
+#ifdef EMISSIVEFRESNEL
+uniform vec4 emissiveLeftColor;
+uniform vec4 emissiveRightColor;
 #endif
 
 // Reflection
@@ -627,6 +641,12 @@ void main(void) {
 
 		reflectionColor = texture2D(reflection2DSampler, coords).rgb * vReflectionInfos.y * shadow;
 	}
+
+#ifdef REFLECTIONFRESNEL
+	float reflectionFresnelTerm = computeFresnelTerm(viewDirectionW, normalW, reflectionRightColor.a, reflectionLeftColor.a);
+
+	reflectionColor *= reflectionLeftColor.rgb * (1.0 - reflectionFresnelTerm) + reflectionFresnelTerm * reflectionRightColor.rgb;
+#endif
 #endif
 
 #ifdef OPACITY
@@ -639,7 +659,12 @@ void main(void) {
 	alpha *= opacityMap.a * vOpacityInfos.y;
 #endif
 
+#endif
+
+#ifdef OPACITYFRESNEL
+	float opacityFresnelTerm = computeFresnelTerm(viewDirectionW, normalW, opacityParts.z, opacityParts.w);
 
+	alpha += opacityParts.x * (1.0 - opacityFresnelTerm) + opacityFresnelTerm * opacityParts.y;
 #endif
 
 	// Emissive
@@ -648,6 +673,12 @@ void main(void) {
 	emissiveColor += texture2D(emissiveSampler, vEmissiveUV).rgb * vEmissiveInfos.y;
 #endif
 
+#ifdef EMISSIVEFRESNEL
+	float emissiveFresnelTerm = computeFresnelTerm(viewDirectionW, normalW, emissiveRightColor.a, emissiveLeftColor.a);
+
+	emissiveColor *= emissiveLeftColor.rgb * (1.0 - emissiveFresnelTerm) + emissiveFresnelTerm * emissiveRightColor.rgb;
+#endif
+
 	// Specular map
 	vec3 specularColor = vSpecularColor.rgb;
 #ifdef SPECULAR
@@ -656,14 +687,19 @@ void main(void) {
 
 	// Fresnel
 #ifdef DIFFUSEFRESNEL
-	float diffuseFresnelTerm = computeFresnelTerm(viewDirectionW, normalW);
-	diffuseBase *= diffuseLeftColor * (1.0 - diffuseFresnelTerm) + diffuseFresnelTerm * diffuseRightColor;
+	float diffuseFresnelTerm = computeFresnelTerm(viewDirectionW, normalW, diffuseRightColor.a, diffuseLeftColor.a);
+
+	diffuseBase *= diffuseLeftColor.rgb * (1.0 - diffuseFresnelTerm) + diffuseFresnelTerm * diffuseRightColor.rgb;
 #endif
 
 	// Composition
 	vec3 finalDiffuse = clamp(diffuseBase * diffuseColor + emissiveColor + vAmbientColor, 0.0, 1.0) * baseColor.rgb;
 	vec3 finalSpecular = specularBase * specularColor;
 
+#ifdef SPECULAROVERALPHA
+	alpha = clamp(alpha + dot(finalSpecular, vec3(0.3, 0.59, 0.11)), 0., 1.);
+#endif
+
 	vec4 color = vec4(finalDiffuse * baseAmbientColor + finalSpecular + reflectionColor, alpha);
 
 #ifdef FOG

+ 1 - 1
Babylon/Shaders/default.vertex.fx

@@ -1,5 +1,5 @@
 #ifdef GL_ES
-precision mediump float;
+precision highp float;
 #endif
 
 // Attributes

+ 1 - 1
Babylon/Shaders/displayPass.fragment.fx

@@ -1,5 +1,5 @@
 #ifdef GL_ES
-precision mediump float;
+precision highp float;
 #endif
 
 // Samplers

+ 1 - 1
Babylon/Shaders/filter.fragment.fx

@@ -1,5 +1,5 @@
 #ifdef GL_ES
-precision mediump float;
+precision highp float;
 #endif
 
 // Samplers

+ 1 - 1
Babylon/Shaders/fxaa.fragment.fx

@@ -1,5 +1,5 @@
 #ifdef GL_ES
-precision mediump float;
+precision highp float;
 #endif
 
 #define FXAA_REDUCE_MIN   (1.0/128.0)

+ 1 - 1
Babylon/Shaders/layer.fragment.fx

@@ -1,5 +1,5 @@
 #ifdef GL_ES
-precision mediump float;
+precision highp float;
 #endif
 
 // Samplers

+ 1 - 1
Babylon/Shaders/layer.vertex.fx

@@ -1,5 +1,5 @@
 #ifdef GL_ES
-precision mediump float;
+precision highp float;
 #endif
 
 // Attributes

+ 54 - 1
Babylon/Shaders/legacydefault.fragment.fx

@@ -1,5 +1,5 @@
 #ifdef GL_ES
-precision mediump float;
+precision highp float;
 #endif
 
 #define MAP_PROJECTION	4.
@@ -122,6 +122,34 @@ uniform vec2 vSpecularInfos;
 uniform sampler2D specularSampler;
 #endif
 
+// Fresnel
+#ifdef FRESNEL
+float computeFresnelTerm(vec3 viewDirection, vec3 worldNormal, float bias, float power)
+{
+	float fresnelTerm = pow(bias + abs(dot(viewDirection, worldNormal)), power);
+	return clamp(fresnelTerm, 0., 1.);
+}
+#endif
+
+#ifdef DIFFUSEFRESNEL
+uniform vec4 diffuseLeftColor;
+uniform vec4 diffuseRightColor;
+#endif
+
+#ifdef OPACITYFRESNEL
+uniform vec4 opacityParts;
+#endif
+
+#ifdef REFLECTIONFRESNEL
+uniform vec4 reflectionLeftColor;
+uniform vec4 reflectionRightColor;
+#endif
+
+#ifdef EMISSIVEFRESNEL
+uniform vec4 emissiveLeftColor;
+uniform vec4 emissiveRightColor;
+#endif
+
 // Shadows
 #ifdef SHADOWS
 
@@ -467,6 +495,12 @@ void main(void) {
 
 		reflectionColor = texture2D(reflection2DSampler, coords).rgb * vReflectionInfos.y;
 	}
+
+#ifdef REFLECTIONFRESNEL
+	float reflectionFresnelTerm = computeFresnelTerm(viewDirectionW, normalW, reflectionRightColor.a, reflectionLeftColor.a);
+
+	reflectionColor *= reflectionLeftColor.rgb * (1.0 - reflectionFresnelTerm) + reflectionFresnelTerm * reflectionRightColor.rgb;
+#endif
 #endif
 
 	// Alpha
@@ -482,18 +516,37 @@ void main(void) {
 #endif
 #endif
 
+#ifdef OPACITYFRESNEL
+	float opacityFresnelTerm = computeFresnelTerm(viewDirectionW, normalW, opacityParts.z, opacityParts.w);
+
+	alpha += opacityParts.x * (1.0 - opacityFresnelTerm) + opacityFresnelTerm * opacityParts.y;
+#endif
+
 	// Emissive
 	vec3 emissiveColor = vEmissiveColor;
 #ifdef EMISSIVE
 	emissiveColor += texture2D(emissiveSampler, vEmissiveUV).rgb * vEmissiveInfos.y;
 #endif
 
+#ifdef EMISSIVEFRESNEL
+	float emissiveFresnelTerm = computeFresnelTerm(viewDirectionW, normalW, emissiveRightColor.a, emissiveLeftColor.a);
+
+	emissiveColor *= emissiveLeftColor.rgb * (1.0 - emissiveFresnelTerm) + emissiveFresnelTerm * emissiveRightColor.rgb;
+#endif
+
 	// Specular map
 	vec3 specularColor = vSpecularColor.rgb;
 #ifdef SPECULAR
 	specularColor = texture2D(specularSampler, vSpecularUV).rgb * vSpecularInfos.y;
 #endif
 
+	// Fresnel
+#ifdef DIFFUSEFRESNEL
+	float diffuseFresnelTerm = computeFresnelTerm(viewDirectionW, normalW, diffuseRightColor.a, diffuseLeftColor.a);
+
+	diffuseBase *= diffuseLeftColor.rgb * (1.0 - diffuseFresnelTerm) + diffuseFresnelTerm * diffuseRightColor.rgb;
+#endif
+
 	// Composition
 	vec3 finalDiffuse = clamp(diffuseBase * diffuseColor + emissiveColor + vAmbientColor, 0.0, 1.0) * baseColor.rgb;
 	vec3 finalSpecular = specularBase * specularColor;

+ 1 - 1
Babylon/Shaders/legacydefault.vertex.fx

@@ -1,5 +1,5 @@
 #ifdef GL_ES
-precision mediump float;
+precision highp float;
 #endif
 
 #define MAP_EXPLICIT	0.

+ 1 - 1
Babylon/Shaders/lensFlare.fragment.fx

@@ -1,5 +1,5 @@
 #ifdef GL_ES
-precision mediump float;
+precision highp float;
 #endif
 
 // Samplers

+ 1 - 1
Babylon/Shaders/lensFlare.vertex.fx

@@ -1,5 +1,5 @@
 #ifdef GL_ES
-precision mediump float;
+precision highp float;
 #endif
 
 // Attributes

+ 1 - 3
Babylon/Shaders/oculusDistortionCorrection.fragment.fx

@@ -1,5 +1,5 @@
 #ifdef GL_ES
-precision mediump float;
+precision highp float;
 #endif
 
 // Samplers
@@ -18,8 +18,6 @@ vec2 HmdWarp(vec2 in01) {
 	return LensCenter + Scale * rvector;
 }
 
-
-
 void main(void)
 {
 	vec2 tc = HmdWarp(vUV);

+ 1 - 1
Babylon/Shaders/outline.fragment.fx

@@ -1,4 +1,4 @@
-precision mediump float;
+precision highp float;
 
 uniform vec3 color;
 

+ 1 - 1
Babylon/Shaders/outline.vertex.fx

@@ -1,5 +1,5 @@
 #ifdef GL_ES
-precision mediump float;
+precision highp float;
 #endif
 
 // Attribute

+ 1 - 1
Babylon/Shaders/particles.fragment.fx

@@ -1,5 +1,5 @@
 #ifdef GL_ES
-precision mediump float;
+precision highp float;
 #endif
 
 // Samplers

+ 1 - 1
Babylon/Shaders/particles.vertex.fx

@@ -1,5 +1,5 @@
 #ifdef GL_ES
-precision mediump float;
+precision highp float;
 #endif
 
 // Attributes

+ 1 - 1
Babylon/Shaders/pass.fragment.fx

@@ -1,5 +1,5 @@
 #ifdef GL_ES
-precision mediump float;
+precision highp float;
 #endif
 
 // Samplers

+ 1 - 1
Babylon/Shaders/postprocess.vertex.fx

@@ -1,5 +1,5 @@
 #ifdef GL_ES
-precision mediump float;
+precision highp float;
 #endif
 
 // Attributes

+ 1 - 1
Babylon/Shaders/refraction.fragment.fx

@@ -1,5 +1,5 @@
 #ifdef GL_ES
-precision mediump float;
+precision highp float;
 #endif
 
 // Samplers

+ 1 - 1
Babylon/Shaders/shadowMap.fragment.fx

@@ -1,5 +1,5 @@
 #ifdef GL_ES
-precision mediump float;
+precision highp float;
 #endif
 
 vec4 pack(float depth)

+ 1 - 1
Babylon/Shaders/shadowMap.vertex.fx

@@ -1,5 +1,5 @@
 #ifdef GL_ES
-precision mediump float;
+precision highp float;
 #endif
 
 // Attribute

+ 1 - 1
Babylon/Shaders/sprites.fragment.fx

@@ -1,5 +1,5 @@
 #ifdef GL_ES
-precision mediump float;
+precision highp float;
 #endif
 
 uniform bool alphaTest;

+ 1 - 1
Babylon/Shaders/sprites.vertex.fx

@@ -1,5 +1,5 @@
 #ifdef GL_ES
-precision mediump float;
+precision highp float;
 #endif
 
 // Attributes

+ 1 - 1
Babylon/Sprites/babylon.sprite.ts

@@ -7,7 +7,7 @@
         public cellIndex = 0;
         public invertU = 0;
         public invertV = 0;
-        public disposeWhenFinishedAnimating: () => void;
+        public disposeWhenFinishedAnimating: boolean;
         public animations = new Array<Animation>();
 
         private _animationStarted = false;

+ 86 - 0
Babylon/Tools/babylon.assetsManager.js

@@ -92,6 +92,77 @@
     })();
     BABYLON.BinaryFileAssetTask = BinaryFileAssetTask;
 
+    var ImageAssetTask = (function () {
+        function ImageAssetTask(name, url) {
+            this.name = name;
+            this.url = url;
+            this.isCompleted = false;
+        }
+        ImageAssetTask.prototype.run = function (scene, onSuccess, onError) {
+            var _this = this;
+            var img = new Image();
+
+            img.onload = function () {
+                _this.image = img;
+                _this.isCompleted = true;
+
+                if (_this.onSuccess) {
+                    _this.onSuccess(_this);
+                }
+
+                onSuccess();
+            };
+
+            img.onerror = function () {
+                if (_this.onError) {
+                    _this.onError(_this);
+                }
+
+                onError();
+            };
+
+            img.src = this.url;
+        };
+        return ImageAssetTask;
+    })();
+    BABYLON.ImageAssetTask = ImageAssetTask;
+
+    var TextureAssetTask = (function () {
+        function TextureAssetTask(name, url, noMipmap, invertY, samplingMode) {
+            if (typeof samplingMode === "undefined") { samplingMode = BABYLON.Texture.TRILINEAR_SAMPLINGMODE; }
+            this.name = name;
+            this.url = url;
+            this.noMipmap = noMipmap;
+            this.invertY = invertY;
+            this.samplingMode = samplingMode;
+            this.isCompleted = false;
+        }
+        TextureAssetTask.prototype.run = function (scene, onSuccess, onError) {
+            var _this = this;
+            var onload = function () {
+                _this.isCompleted = true;
+
+                if (_this.onSuccess) {
+                    _this.onSuccess(_this);
+                }
+
+                onSuccess();
+            };
+
+            var onerror = function () {
+                if (_this.onError) {
+                    _this.onError(_this);
+                }
+
+                onError();
+            };
+
+            this.texture = new BABYLON.Texture(this.url, scene, this.noMipmap, this.invertY, this.samplingMode, onload, onError);
+        };
+        return TextureAssetTask;
+    })();
+    BABYLON.TextureAssetTask = TextureAssetTask;
+
     var AssetsManager = (function () {
         function AssetsManager(scene) {
             this._tasks = new Array();
@@ -120,6 +191,21 @@
             return task;
         };
 
+        AssetsManager.prototype.addImageTask = function (taskName, url) {
+            var task = new ImageAssetTask(taskName, url);
+            this._tasks.push(task);
+
+            return task;
+        };
+
+        AssetsManager.prototype.addTextureTask = function (taskName, url, noMipmap, invertY, samplingMode) {
+            if (typeof samplingMode === "undefined") { samplingMode = BABYLON.Texture.TRILINEAR_SAMPLINGMODE; }
+            var task = new TextureAssetTask(taskName, url, noMipmap, invertY, samplingMode);
+            this._tasks.push(task);
+
+            return task;
+        };
+
         AssetsManager.prototype._decreaseWaitingTasksCount = function () {
             this._waitingTasksCount--;
 

+ 84 - 0
Babylon/Tools/babylon.assetsManager.ts

@@ -107,6 +107,76 @@
         }
     }
 
+    export class ImageAssetTask implements IAssetTask {
+        public onSuccess: (task: IAssetTask) => void;
+        public onError: (task: IAssetTask) => void;
+
+        public isCompleted = false;
+        public image: HTMLImageElement;
+
+        constructor(public name: string, public url: string) {
+        }
+
+        public run(scene: Scene, onSuccess: () => void, onError: () => void) {
+            var img = new Image();
+
+            img.onload = () => {
+                this.image = img;
+                this.isCompleted = true;
+
+                if (this.onSuccess) {
+                    this.onSuccess(this);
+                }
+
+                onSuccess();
+            };
+
+            img.onerror = () => {
+                if (this.onError) {
+                    this.onError(this);
+                }
+
+                onError();
+            };
+
+            img.src = this.url;
+        }
+    }
+
+    export class TextureAssetTask implements IAssetTask {
+        public onSuccess: (task: IAssetTask) => void;
+        public onError: (task: IAssetTask) => void;
+
+        public isCompleted = false;
+        public texture: Texture;
+
+        constructor(public name: string, public url: string, public noMipmap?: boolean, public invertY?: boolean, public samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE) {
+        }
+
+        public run(scene: Scene, onSuccess: () => void, onError: () => void) {
+
+            var onload = () => {
+                this.isCompleted = true;
+
+                if (this.onSuccess) {
+                    this.onSuccess(this);
+                }
+
+                onSuccess();
+            };
+
+            var onerror = () => {
+                if (this.onError) {
+                    this.onError(this);
+                }
+
+                onError();
+            };
+
+            this.texture = new BABYLON.Texture(this.url, scene, this.noMipmap, this.invertY, this.samplingMode, onload, onError);
+        }
+    }
+
     export class AssetsManager {
         private _tasks = new Array<IAssetTask>();
         private _scene: Scene;
@@ -144,6 +214,20 @@
             return task;
         }
 
+        public addImageTask(taskName: string, url: string): IAssetTask {
+            var task = new ImageAssetTask(taskName, url);
+            this._tasks.push(task);
+
+            return task;
+        }
+
+        public addTextureTask(taskName: string, url: string, noMipmap?: boolean, invertY?: boolean, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE): IAssetTask {
+            var task = new TextureAssetTask(taskName, url, noMipmap, invertY, samplingMode);
+            this._tasks.push(task);
+
+            return task;
+        }
+
         private _decreaseWaitingTasksCount(): void {
             this._waitingTasksCount--;
 

+ 1 - 7
Babylon/Tools/babylon.database.js

@@ -1,4 +1,4 @@
-var BABYLON;
+var BABYLON;
 (function (BABYLON) {
     var Database = (function () {
         function Database(urlToScene, callbackManifestChecked) {
@@ -106,12 +106,6 @@
                     request.onupgradeneeded = function (event) {
                         _this.db = (event.target).result;
                         try  {
-                            if (event.oldVersion > 0) {
-                                _this.db.deleteObjectStore("scenes");
-                                _this.db.deleteObjectStore("versions");
-                                _this.db.deleteObjectStore("textures");
-                            }
-
                             var scenesStore = _this.db.createObjectStore("scenes", { keyPath: "sceneUrl" });
                             var versionsStore = _this.db.createObjectStore("versions", { keyPath: "sceneUrl" });
                             var texturesStore = _this.db.createObjectStore("textures", { keyPath: "textureUrl" });

+ 1 - 7
Babylon/Tools/babylon.database.ts

@@ -136,13 +136,7 @@ module BABYLON {
                     // Initialization of the DB. Creating Scenes & Textures stores
                     request.onupgradeneeded = (event: IDBVersionChangeEvent) => {
                         this.db = (<any>(event.target)).result;
-                        try {
-                            if (event.oldVersion > 0) {
-                                this.db.deleteObjectStore("scenes");
-                                this.db.deleteObjectStore("versions");
-                                this.db.deleteObjectStore("textures");
-                            }
-                            
+                        try {                            
                             var scenesStore = this.db.createObjectStore("scenes", { keyPath: "sceneUrl" });
                             var versionsStore = this.db.createObjectStore("versions", { keyPath: "sceneUrl" });
                             var texturesStore = this.db.createObjectStore("textures", { keyPath: "textureUrl" });

+ 28 - 0
Babylon/Tools/babylon.sceneSerializer.js

@@ -40,6 +40,18 @@
         return serializationObject;
     };
 
+    var serializeFresnelParameter = function (fresnelParameter) {
+        var serializationObject = {};
+
+        serializationObject.isEnabled = fresnelParameter.isEnabled;
+        serializationObject.leftColor = fresnelParameter.leftColor;
+        serializationObject.rightColor = fresnelParameter.rightColor;
+        serializationObject.bias = fresnelParameter.bias;
+        serializationObject.power = fresnelParameter.power;
+
+        return serializationObject;
+    };
+
     var serializeCamera = function (camera) {
         var serializationObject = {};
         serializationObject.name = camera.name;
@@ -172,6 +184,10 @@
             serializationObject.diffuseTexture = serializeTexture(material.diffuseTexture);
         }
 
+        if (material.diffuseFresnelParameters) {
+            serializationObject.diffuseFresnelParameters = serializeFresnelParameter(material.diffuseFresnelParameters);
+        }
+
         if (material.ambientTexture) {
             serializationObject.ambientTexture = serializeTexture(material.ambientTexture);
         }
@@ -180,14 +196,26 @@
             serializationObject.opacityTexture = serializeTexture(material.opacityTexture);
         }
 
+        if (material.opacityFresnelParameters) {
+            serializationObject.opacityFresnelParameters = serializeFresnelParameter(material.opacityFresnelParameters);
+        }
+
         if (material.reflectionTexture) {
             serializationObject.reflectionTexture = serializeTexture(material.reflectionTexture);
         }
 
+        if (material.reflectionFresnelParameters) {
+            serializationObject.reflectionFresnelParameters = serializeFresnelParameter(material.reflectionFresnelParameters);
+        }
+
         if (material.emissiveTexture) {
             serializationObject.emissiveTexture = serializeTexture(material.emissiveTexture);
         }
 
+        if (material.emissiveFresnelParameters) {
+            serializationObject.emissiveFresnelParameters = serializeFresnelParameter(material.emissiveFresnelParameters);
+        }
+
         if (material.specularTexture) {
             serializationObject.specularTexture = serializeTexture(material.specularTexture);
         }

+ 28 - 0
Babylon/Tools/babylon.sceneSerializer.ts

@@ -40,6 +40,18 @@
         return serializationObject;
     };
 
+    var serializeFresnelParameter = (fresnelParameter: FresnelParameters): any => {
+        var serializationObject: any = {};
+
+        serializationObject.isEnabled = fresnelParameter.isEnabled;
+        serializationObject.leftColor = fresnelParameter.leftColor;
+        serializationObject.rightColor = fresnelParameter.rightColor;
+        serializationObject.bias = fresnelParameter.bias;
+        serializationObject.power = fresnelParameter.power;
+
+        return serializationObject;
+    }
+
     var serializeCamera = (camera: FreeCamera): any => {
         var serializationObject:any = {};
         serializationObject.name = camera.name;
@@ -172,6 +184,10 @@
             serializationObject.diffuseTexture = serializeTexture(material.diffuseTexture);
         }
 
+        if (material.diffuseFresnelParameters) {
+            serializationObject.diffuseFresnelParameters = serializeFresnelParameter(material.diffuseFresnelParameters);
+        }
+
         if (material.ambientTexture) {
             serializationObject.ambientTexture = serializeTexture(material.ambientTexture);
         }
@@ -180,14 +196,26 @@
             serializationObject.opacityTexture = serializeTexture(material.opacityTexture);
         }
 
+        if (material.opacityFresnelParameters) {
+            serializationObject.opacityFresnelParameters = serializeFresnelParameter(material.opacityFresnelParameters);
+        }
+
         if (material.reflectionTexture) {
             serializationObject.reflectionTexture = serializeTexture(material.reflectionTexture);
         }
 
+        if (material.reflectionFresnelParameters) {
+            serializationObject.reflectionFresnelParameters = serializeFresnelParameter(material.reflectionFresnelParameters);
+        }
+
         if (material.emissiveTexture) {
             serializationObject.emissiveTexture = serializeTexture(material.emissiveTexture);
         }
 
+        if (material.emissiveFresnelParameters) {
+            serializationObject.emissiveFresnelParameters = serializeFresnelParameter(material.emissiveFresnelParameters);
+        }
+
         if (material.specularTexture) {
             serializationObject.specularTexture = serializeTexture(material.specularTexture);
         }

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

@@ -652,6 +652,19 @@
         });
         Tools.BaseUrl = "";
 
+        Tools.GetExponantOfTwo = function (value, max) {
+            var count = 1;
+
+            do {
+                count *= 2;
+            } while(count < value);
+
+            if (count > max)
+                count = max;
+
+            return count;
+        };
+
         Tools._NoneLogLevel = 0;
         Tools._MessageLogLevel = 1;
         Tools._WarningLogLevel = 2;

+ 1 - 1
Babylon/Tools/babylon.tools.tga.js

@@ -98,7 +98,7 @@ var BABYLON;
                     var localOffset = 0;
                     var pixels = new Uint8Array(pixel_size);
 
-                    while (offset < pixel_total) {
+                    while (offset < pixel_total && localOffset < pixel_total) {
                         c = data[offset++];
                         count = (c & 0x7f) + 1;
 

+ 1 - 1
Babylon/Tools/babylon.tools.tga.ts

@@ -111,7 +111,7 @@ module BABYLON.Internals {
                 var localOffset = 0;
                 var pixels = new Uint8Array(pixel_size);
 
-                while (offset < pixel_total) {
+                while (offset < pixel_total && localOffset < pixel_total) {
                     c = data[offset++];
                     count = (c & 0x7f) + 1;
 

+ 14 - 1
Babylon/Tools/babylon.tools.ts

@@ -36,6 +36,19 @@
     export class Tools {
         public static BaseUrl = "";
 
+        public static GetExponantOfTwo = (value: number, max: number): number => {
+            var count = 1;
+
+            do {
+                count *= 2;
+            } while (count < value);
+
+            if (count > max)
+                count = max;
+
+            return count;
+        };
+
         public static GetFilename(path: string): string {
             var index = path.lastIndexOf("/");
             if (index < 0)
@@ -267,7 +280,7 @@
             else {
                 // Caching all files
                 if (database && database.enableSceneOffline) {
-                    database.openAsync(loadFromIndexedDB, noIndexedDB);                    
+                    database.openAsync(loadFromIndexedDB, noIndexedDB);
                 }
                 else {
                     noIndexedDB();

+ 67 - 29
Babylon/babylon.engine.js

@@ -10,7 +10,7 @@
         }
         Object.defineProperty(_DepthCullingState.prototype, "isDirty", {
             get: function () {
-                return this._isDepthTestDirty || this._isDepthMaskDirty || this._isCullFaceDirty || this._isCullDirty;
+                return this._isDepthFuncDirty || this._isDepthTestDirty || this._isDepthMaskDirty || this._isCullFaceDirty || this._isCullDirty;
             },
             enumerable: true,
             configurable: true
@@ -289,24 +289,11 @@
         };
     };
 
-    var getExponantOfTwo = function (value, max) {
-        var count = 1;
-
-        do {
-            count *= 2;
-        } while(count < value);
-
-        if (count > max)
-            count = max;
-
-        return count;
-    };
-
     var prepareWebGLTexture = function (texture, gl, scene, width, height, invertY, noMipmap, isCompressed, processFunction, samplingMode) {
         if (typeof samplingMode === "undefined") { samplingMode = BABYLON.Texture.TRILINEAR_SAMPLINGMODE; }
         var engine = scene.getEngine();
-        var potWidth = getExponantOfTwo(width, engine.getCaps().maxTextureSize);
-        var potHeight = getExponantOfTwo(height, engine.getCaps().maxTextureSize);
+        var potWidth = BABYLON.Tools.GetExponantOfTwo(width, engine.getCaps().maxTextureSize);
+        var potHeight = BABYLON.Tools.GetExponantOfTwo(height, engine.getCaps().maxTextureSize);
 
         gl.bindTexture(gl.TEXTURE_2D, texture);
         gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, invertY === undefined ? 1 : (invertY ? 1 : 0));
@@ -656,6 +643,8 @@
         };
 
         Engine.prototype.clear = function (color, backBuffer, depthStencil) {
+            this.applyStates();
+
             this._gl.clearColor(color.r, color.g, color.b, color.a !== undefined ? color.a : 1.0);
             if (this._depthCullingState.depthMask) {
                 this._gl.clearDepth(1.0);
@@ -889,10 +878,14 @@
             }
         };
 
-        Engine.prototype.draw = function (useTriangles, indexStart, indexCount, instancesCount) {
-            // Apply states
+        Engine.prototype.applyStates = function () {
             this._depthCullingState.apply(this._gl);
             this._alphaState.apply(this._gl);
+        };
+
+        Engine.prototype.draw = function (useTriangles, indexStart, indexCount, instancesCount) {
+            // Apply states
+            this.applyStates();
 
             // Render
             if (instancesCount) {
@@ -929,6 +922,16 @@
             return effect;
         };
 
+        Engine.prototype.createEffectForParticles = function (fragmentName, uniformsNames, samplers, defines, fallbacks, onCompiled, onError) {
+            if (typeof uniformsNames === "undefined") { uniformsNames = []; }
+            if (typeof samplers === "undefined") { samplers = []; }
+            if (typeof defines === "undefined") { defines = ""; }
+            return this.createEffect({
+                vertex: "particles",
+                fragmentElement: fragmentName
+            }, ["position", "color", "options"], ["view", "projection"].concat(uniformsNames), ["diffuseSampler"].concat(samplers), defines, fallbacks, onCompiled, onError);
+        };
+
         Engine.prototype.createShaderProgram = function (vertexCode, fragmentCode, defines) {
             var vertexShader = compileShader(this._gl, vertexCode, "vertex", defines);
             var fragmentShader = compileShader(this._gl, fragmentCode, "fragment", defines);
@@ -1170,9 +1173,15 @@
             gl.bindTexture(gl.TEXTURE_2D, null);
         };
 
+<<<<<<< HEAD
         Engine.prototype.createTexture = function (url, noMipmap, invertY, scene, samplingMode, buffer) {
+=======
+        Engine.prototype.createTexture = function (url, noMipmap, invertY, scene, samplingMode, onLoad, onError) {
+>>>>>>> 08f8d5bd302ffec3b0c263e3d9b3a73544899aa5
             var _this = this;
             if (typeof samplingMode === "undefined") { samplingMode = BABYLON.Texture.TRILINEAR_SAMPLINGMODE; }
+            if (typeof onLoad === "undefined") { onLoad = null; }
+            if (typeof onError === "undefined") { onError = null; }
             var texture = this._gl.createTexture();
             var extension;
             var fromData = false;
@@ -1200,6 +1209,14 @@
             texture.references = 1;
             this._loadedTexturesCache.push(texture);
 
+            var onerror = function () {
+                scene._removePendingData(texture);
+
+                if (onError) {
+                    onError();
+                }
+            };
+
             if (isTGA) {
                 var callback = function (arrayBuffer) {
                     var data = new Uint8Array(arrayBuffer);
@@ -1208,7 +1225,12 @@
 
                     prepareWebGLTexture(texture, _this._gl, scene, header.width, header.height, invertY, noMipmap, false, function () {
                         BABYLON.Internals.TGATools.UploadContent(_this._gl, data);
+
+                        if (onLoad) {
+                            onLoad();
+                        }
                     }, samplingMode);
+<<<<<<< HEAD
                 };
 
                 if (!(fromData instanceof Array))
@@ -1216,15 +1238,22 @@
                 else
                     callback(buffer);
 
+=======
+                }, onerror, scene.database, true);
+>>>>>>> 08f8d5bd302ffec3b0c263e3d9b3a73544899aa5
             } else if (isDDS) {
                 var callback = function (data) {
                     var info = BABYLON.Internals.DDSTools.GetDDSInfo(data);
 
                     var loadMipmap = (info.isRGB || info.isLuminance || info.mipmapCount > 1) && !noMipmap && ((info.width >> (info.mipmapCount - 1)) == 1);
                     prepareWebGLTexture(texture, _this._gl, scene, info.width, info.height, invertY, !loadMipmap, info.isFourCC, function () {
-                        console.log("loading " + url);
                         BABYLON.Internals.DDSTools.UploadDDSLevels(_this._gl, _this.getCaps().s3tc, data, info, loadMipmap, 1);
+
+                        if (onLoad) {
+                            onLoad();
+                        }
                     }, samplingMode);
+<<<<<<< HEAD
                 };
 
                 if (!(fromData instanceof Array))
@@ -1232,6 +1261,9 @@
                 else
                     callback(buffer);
 
+=======
+                }, onerror, scene.database, true);
+>>>>>>> 08f8d5bd302ffec3b0c263e3d9b3a73544899aa5
             } else {
                 var onload = function (img) {
                     prepareWebGLTexture(texture, _this._gl, scene, img.width, img.height, invertY, noMipmap, false, function (potWidth, potHeight) {
@@ -1244,11 +1276,11 @@
                         }
 
                         _this._gl.texImage2D(_this._gl.TEXTURE_2D, 0, _this._gl.RGBA, _this._gl.RGBA, _this._gl.UNSIGNED_BYTE, isPot ? img : _this._workingCanvas);
-                    }, samplingMode);
-                };
 
-                var onerror = function () {
-                    scene._removePendingData(texture);
+                        if (onLoad) {
+                            onLoad();
+                        }
+                    }, samplingMode);
                 };
 
                 if (!(fromData instanceof Array))
@@ -1263,8 +1295,8 @@
         Engine.prototype.createDynamicTexture = function (width, height, generateMipMaps, samplingMode) {
             var texture = this._gl.createTexture();
 
-            width = getExponantOfTwo(width, this._caps.maxTextureSize);
-            height = getExponantOfTwo(height, this._caps.maxTextureSize);
+            width = BABYLON.Tools.GetExponantOfTwo(width, this._caps.maxTextureSize);
+            height = BABYLON.Tools.GetExponantOfTwo(height, this._caps.maxTextureSize);
 
             this._gl.bindTexture(this._gl.TEXTURE_2D, texture);
 
@@ -1437,10 +1469,10 @@
                     texture._width = info.width;
                     texture._height = info.height;
                     texture.isReady = true;
-                });
+                }, null, null, true);
             } else {
                 cascadeLoad(rootUrl, 0, [], scene, function (imgs) {
-                    var width = getExponantOfTwo(imgs[0].width, _this._caps.maxCubemapTextureSize);
+                    var width = BABYLON.Tools.GetExponantOfTwo(imgs[0].width, _this._caps.maxCubemapTextureSize);
                     var height = width;
 
                     _this._workingCanvas.width = width;
@@ -1696,13 +1728,18 @@
             imgBack.style.marginLeft = "-50px";
             imgBack.style.marginTop = "-50px";
             imgBack.style.transition = "transform 1.0s ease";
+            imgBack.style.webkitTransition = "-webkit-transform 1.0s ease";
 
             var deg = 360;
 
-            imgBack.addEventListener("transitionend", function () {
+            var onTransitionEnd = function () {
                 deg += 360;
                 imgBack.style.transform = "rotateZ(" + deg + "deg)";
-            });
+                imgBack.style.webkitTransform = "rotateZ(" + deg + "deg)";
+            };
+
+            imgBack.addEventListener("transitionend", onTransitionEnd);
+            imgBack.addEventListener("webkitTransitionEnd", onTransitionEnd);
 
             this._loadingDiv.appendChild(imgBack);
 
@@ -1737,6 +1774,7 @@
             setTimeout(function () {
                 _this._loadingDiv.style.opacity = "1";
                 imgBack.style.transform = "rotateZ(360deg)";
+                imgBack.style.webkitTransform = "rotateZ(360deg)";
             }, 0);
         };
 

+ 70 - 30
Babylon/babylon.engine.ts

@@ -14,7 +14,7 @@
         
 
         public get isDirty(): boolean {
-            return this._isDepthTestDirty || this._isDepthMaskDirty || this._isCullFaceDirty || this._isCullDirty;
+            return this._isDepthFuncDirty || this._isDepthTestDirty || this._isDepthMaskDirty || this._isCullFaceDirty || this._isCullDirty;
         }
 
         public get cullFace(): number {
@@ -264,24 +264,11 @@
         }
     }
 
-    var getExponantOfTwo = (value: number, max: number): number => {
-        var count = 1;
-
-        do {
-            count *= 2;
-        } while (count < value);
-
-        if (count > max)
-            count = max;
-
-        return count;
-    };
-
     var prepareWebGLTexture = (texture: WebGLTexture, gl: WebGLRenderingContext, scene: Scene, width: number, height: number, invertY: boolean, noMipmap: boolean, isCompressed: boolean,
         processFunction: (width: number, height: number) => void, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE) => {
         var engine = scene.getEngine();
-        var potWidth = getExponantOfTwo(width, engine.getCaps().maxTextureSize);
-        var potHeight = getExponantOfTwo(height, engine.getCaps().maxTextureSize);
+        var potWidth = Tools.GetExponantOfTwo(width, engine.getCaps().maxTextureSize);
+        var potHeight = Tools.GetExponantOfTwo(height, engine.getCaps().maxTextureSize);
 
         gl.bindTexture(gl.TEXTURE_2D, texture);
         gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, invertY === undefined ? 1 : (invertY ? 1 : 0));
@@ -663,6 +650,8 @@
         }
 
         public clear(color: any, backBuffer: boolean, depthStencil: boolean): void {
+            this.applyStates();
+
             this._gl.clearColor(color.r, color.g, color.b, color.a !== undefined ? color.a : 1.0);
             if (this._depthCullingState.depthMask) {
                 this._gl.clearDepth(1.0);
@@ -896,10 +885,14 @@
             }
         }
 
-        public draw(useTriangles: boolean, indexStart: number, indexCount: number, instancesCount?: number): void {
-            // Apply states
+        public applyStates() {
             this._depthCullingState.apply(this._gl);
             this._alphaState.apply(this._gl);
+        }
+
+        public draw(useTriangles: boolean, indexStart: number, indexCount: number, instancesCount?: number): void {
+            // Apply states
+            this.applyStates();
             
             // Render
             if (instancesCount) {
@@ -937,6 +930,19 @@
             return effect;
         }
 
+        public createEffectForParticles(fragmentName: string, uniformsNames: string[]= [], samplers: string[] = [], defines = "", fallbacks?: EffectFallbacks,
+            onCompiled?: (effect: Effect) => void, onError?: (effect: Effect, errors: string) => void): Effect {
+
+            return this.createEffect(
+                {
+                    vertex: "particles",
+                    fragmentElement: fragmentName
+                },
+                ["position", "color", "options"],
+                ["view", "projection"].concat(uniformsNames),
+                ["diffuseSampler"].concat(samplers), defines, fallbacks, onCompiled, onError);
+        }
+
         public createShaderProgram(vertexCode: string, fragmentCode: string, defines: string): WebGLProgram {
             var vertexShader = compileShader(this._gl, vertexCode, "vertex", defines);
             var fragmentShader = compileShader(this._gl, fragmentCode, "fragment", defines);
@@ -1179,7 +1185,11 @@
             gl.bindTexture(gl.TEXTURE_2D, null);
         }
 
+<<<<<<< HEAD
         public createTexture(url: string, noMipmap: boolean, invertY: boolean, scene: Scene, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE, buffer: any = null): WebGLTexture {
+=======
+        public createTexture(url: string, noMipmap: boolean, invertY: boolean, scene: Scene, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE, onLoad: () => void = null, onError: () => void = null): WebGLTexture {
+>>>>>>> 08f8d5bd302ffec3b0c263e3d9b3a73544899aa5
             var texture = this._gl.createTexture();
 
             var extension: string;
@@ -1206,6 +1216,14 @@
             texture.references = 1;
             this._loadedTexturesCache.push(texture);
 
+            var onerror = () => {
+                scene._removePendingData(texture);
+
+                if (onError) {
+                    onError();
+                }
+            };
+
             if (isTGA) {
                 var callback = (arrayBuffer) => {
                     var data = new Uint8Array(arrayBuffer);
@@ -1214,7 +1232,12 @@
 
                     prepareWebGLTexture(texture, this._gl, scene, header.width, header.height, invertY, noMipmap, false, () => {
                         Internals.TGATools.UploadContent(this._gl, data);
+
+                        if (onLoad) {
+                            onLoad();
+                        }
                     }, samplingMode);
+<<<<<<< HEAD
                 };
 
                 if (!(fromData instanceof Array))
@@ -1224,15 +1247,23 @@
                 else
                     callback(buffer);
 
+=======
+                }, onerror, scene.database, true);
+>>>>>>> 08f8d5bd302ffec3b0c263e3d9b3a73544899aa5
             } else if (isDDS) {
                 var callback = (data) => {
                     var info = BABYLON.Internals.DDSTools.GetDDSInfo(data);
 
                     var loadMipmap = (info.isRGB || info.isLuminance || info.mipmapCount > 1) && !noMipmap && ((info.width >> (info.mipmapCount - 1)) == 1);
                     prepareWebGLTexture(texture, this._gl, scene, info.width, info.height, invertY, !loadMipmap, info.isFourCC, () => {
-                        console.log("loading " + url);
+
                         Internals.DDSTools.UploadDDSLevels(this._gl, this.getCaps().s3tc, data, info, loadMipmap, 1);
+
+                        if (onLoad) {
+                            onLoad();
+                        }
                     }, samplingMode);
+<<<<<<< HEAD
                 }
 
                 if (!(fromData instanceof Array))
@@ -1242,6 +1273,9 @@
                 else
                     callback(buffer);
 
+=======
+                }, onerror, scene.database, true);
+>>>>>>> 08f8d5bd302ffec3b0c263e3d9b3a73544899aa5
             } else {
                 var onload = (img) => {
                     prepareWebGLTexture(texture, this._gl, scene, img.width, img.height, invertY, noMipmap, false, (potWidth, potHeight) => {
@@ -1255,12 +1289,12 @@
 
                         this._gl.texImage2D(this._gl.TEXTURE_2D, 0, this._gl.RGBA, this._gl.RGBA, this._gl.UNSIGNED_BYTE, isPot ? img : this._workingCanvas);
 
+                        if (onLoad) {
+                            onLoad();
+                        }
                     }, samplingMode);
                 };
 
-                var onerror = () => {
-                    scene._removePendingData(texture);
-                };
 
                 if (!(fromData instanceof Array))
                     BABYLON.Tools.LoadImage(url, onload, onerror, scene.database);
@@ -1274,8 +1308,8 @@
         public createDynamicTexture(width: number, height: number, generateMipMaps: boolean, samplingMode: number): WebGLTexture {
             var texture = this._gl.createTexture();
 
-            width = getExponantOfTwo(width, this._caps.maxTextureSize);
-            height = getExponantOfTwo(height, this._caps.maxTextureSize);
+            width = Tools.GetExponantOfTwo(width, this._caps.maxTextureSize);
+            height = Tools.GetExponantOfTwo(height, this._caps.maxTextureSize);
 
             this._gl.bindTexture(this._gl.TEXTURE_2D, texture);
 
@@ -1445,10 +1479,10 @@
                     texture._width = info.width;
                     texture._height = info.height;
                     texture.isReady = true;
-                });
+                }, null, null, true);
             } else {
                 cascadeLoad(rootUrl, 0, [], scene, imgs => {
-                    var width = getExponantOfTwo(imgs[0].width, this._caps.maxCubemapTextureSize);
+                    var width = Tools.GetExponantOfTwo(imgs[0].width, this._caps.maxCubemapTextureSize);
                     var height = width;
 
                     this._workingCanvas.width = width;
@@ -1707,13 +1741,18 @@
             imgBack.style.marginLeft = "-50px";
             imgBack.style.marginTop = "-50px";
             imgBack.style.transition = "transform 1.0s ease";
+            imgBack.style.webkitTransition = "-webkit-transform 1.0s ease";
 
             var deg = 360;
 
-            imgBack.addEventListener("transitionend", () => {
+            var onTransitionEnd = () => {
                 deg += 360;
-                imgBack.style.transform = "rotateZ(" + deg + "deg)";
-            });
+                imgBack.style.transform = "rotateZ(" + deg + "deg)"; 
+                imgBack.style.webkitTransform = "rotateZ(" + deg + "deg)";
+            }
+
+            imgBack.addEventListener("transitionend", onTransitionEnd);
+            imgBack.addEventListener("webkitTransitionEnd", onTransitionEnd);
 
             this._loadingDiv.appendChild(imgBack);
 
@@ -1748,6 +1787,7 @@
             setTimeout(() => {
                 this._loadingDiv.style.opacity = "1";
                 imgBack.style.transform = "rotateZ(360deg)";
+                imgBack.style.webkitTransform = "rotateZ(360deg)";
             }, 0);
         }
 
@@ -1804,4 +1844,4 @@
             }
         }
     }
-} 
+}

+ 10 - 0
Babylon/babylon.mixins.ts

@@ -78,4 +78,14 @@ interface MouseEvent {
     webkitMovementY: number;
     msMovementX: number;
     msMovementY: number;
+}
+
+interface MSStyleCSSProperties {
+    webkitTransform: string;
+    webkitTransition: string;
+}
+
+interface Navigator {
+    getVRDevices: () => any;
+    mozGetVRDevices: (any) => any;
 }

+ 2 - 0
Babylon/babylon.node.ts

@@ -14,6 +14,8 @@
         private _isReady = true;
         public _currentRenderId = -1;
 
+        public _waitingParentId: string;
+
         private _scene: Scene;
         public _cache;
 

+ 37 - 7
Babylon/babylon.scene.js

@@ -818,16 +818,11 @@
                 skeleton.prepare();
             }
 
-            for (var customIndex = 0; customIndex < this.customRenderTargets.length; customIndex++) {
-                var renderTarget = this.customRenderTargets[customIndex];
-                this._renderTargets.push(renderTarget);
-            }
-
             // Render targets
             var beforeRenderTargetDate = new Date().getTime();
             if (this.renderTargetsEnabled) {
                 for (var renderIndex = 0; renderIndex < this._renderTargets.length; renderIndex++) {
-                    renderTarget = this._renderTargets.data[renderIndex];
+                    var renderTarget = this._renderTargets.data[renderIndex];
                     if (renderTarget._shouldRender()) {
                         this._renderId++;
                         renderTarget.render();
@@ -839,7 +834,7 @@
             if (this._renderTargets.length > 0) {
                 engine.restoreDefaultFramebuffer();
             }
-            this._renderTargetsDuration = new Date().getTime() - beforeRenderTargetDate;
+            this._renderTargetsDuration += new Date().getTime() - beforeRenderTargetDate;
 
             // Prepare Frame
             this.postProcessManager._prepareFrame();
@@ -980,6 +975,37 @@
                 this._physicsEngine._runOneStep(deltaTime / 1000.0);
             }
 
+            // Customs render targets
+            var beforeRenderTargetDate = new Date().getTime();
+            var engine = this.getEngine();
+            if (this.renderTargetsEnabled) {
+                for (var customIndex = 0; customIndex < this.customRenderTargets.length; customIndex++) {
+                    var renderTarget = this.customRenderTargets[customIndex];
+                    if (renderTarget._shouldRender()) {
+                        this._renderId++;
+
+                        this.activeCamera = renderTarget.activeCamera || this.activeCamera;
+
+                        if (!this.activeCamera)
+                            throw new Error("Active camera not set");
+
+                        // Viewport
+                        engine.setViewport(this.activeCamera.viewport);
+
+                        // Camera
+                        this.updateTransformMatrix();
+
+                        renderTarget.render();
+                    }
+                }
+                this._renderId++;
+            }
+
+            if (this.customRenderTargets.length > 0) {
+                engine.restoreDefaultFramebuffer();
+            }
+            this._renderTargetsDuration += new Date().getTime() - beforeRenderTargetDate;
+
             // Clear
             this._engine.clear(this.clearColor, this.autoClear || this.forceWireframe, true);
 
@@ -1003,6 +1029,10 @@
                     this._processSubCameras(this.activeCameras[cameraIndex]);
                 }
             } else {
+                if (!this.activeCamera) {
+                    throw new Error("No camera defined");
+                }
+
                 this._processSubCameras(this.activeCamera);
             }
 

+ 40 - 10
Babylon/babylon.scene.ts

@@ -15,7 +15,7 @@
 
         // Members
         public autoClear = true;
-        public clearColor = new BABYLON.Color3(0.2, 0.2, 0.3);
+        public clearColor: any = new BABYLON.Color3(0.2, 0.2, 0.3);
         public ambientColor = new BABYLON.Color3(0, 0, 0);
         public beforeRender: () => void;
         public afterRender: () => void;
@@ -161,7 +161,7 @@
 
         private _selectionOctree: Octree<AbstractMesh>;
 
-        private _pointerOverMesh: AbstractMesh;      
+        private _pointerOverMesh: AbstractMesh;
 
         // Constructor
         constructor(engine: Engine) {
@@ -894,17 +894,11 @@
                 skeleton.prepare();
             }
 
-            // Customs render targets registration
-            for (var customIndex = 0; customIndex < this.customRenderTargets.length; customIndex++) {
-                var renderTarget = this.customRenderTargets[customIndex];
-                this._renderTargets.push(renderTarget);
-            }
-
             // Render targets
             var beforeRenderTargetDate = new Date().getTime();
             if (this.renderTargetsEnabled) {
                 for (var renderIndex = 0; renderIndex < this._renderTargets.length; renderIndex++) {
-                    renderTarget = this._renderTargets.data[renderIndex];
+                    var renderTarget = this._renderTargets.data[renderIndex];
                     if (renderTarget._shouldRender()) {
                         this._renderId++;
                         renderTarget.render();
@@ -916,7 +910,7 @@
             if (this._renderTargets.length > 0) { // Restore back buffer
                 engine.restoreDefaultFramebuffer();
             }
-            this._renderTargetsDuration = new Date().getTime() - beforeRenderTargetDate;
+            this._renderTargetsDuration += new Date().getTime() - beforeRenderTargetDate;
 
             // Prepare Frame
             this.postProcessManager._prepareFrame();
@@ -1060,6 +1054,38 @@
                 this._physicsEngine._runOneStep(deltaTime / 1000.0);
             }
 
+            // Customs render targets
+            var beforeRenderTargetDate = new Date().getTime();
+            var engine = this.getEngine();
+            if (this.renderTargetsEnabled) {
+                for (var customIndex = 0; customIndex < this.customRenderTargets.length; customIndex++) {
+                    var renderTarget = this.customRenderTargets[customIndex];
+                    if (renderTarget._shouldRender()) {
+                        this._renderId++;
+
+                        this.activeCamera = renderTarget.activeCamera || this.activeCamera;
+
+                        if (!this.activeCamera)
+                            throw new Error("Active camera not set");
+
+                        // Viewport
+                        engine.setViewport(this.activeCamera.viewport);
+
+                        // Camera
+                        this.updateTransformMatrix();
+
+                        renderTarget.render();
+                    }
+                }
+                this._renderId++;
+            }
+
+            if (this.customRenderTargets.length > 0) { // Restore back buffer
+                engine.restoreDefaultFramebuffer();
+            }
+            this._renderTargetsDuration += new Date().getTime() - beforeRenderTargetDate;
+
+
             // Clear
             this._engine.clear(this.clearColor, this.autoClear || this.forceWireframe, true);
 
@@ -1084,6 +1110,10 @@
                     this._processSubCameras(this.activeCameras[cameraIndex]);
                 }
             } else {
+                if (!this.activeCamera) {
+                    throw new Error("No camera defined");
+                }
+
                 this._processSubCameras(this.activeCamera);
             }
 

+ 0 - 0
Exporters/3ds Max/BabylonExport.Entities/BabylonExport.Entities.csproj


Деякі файли не було показано, через те що забагато файлів було змінено