浏览代码

updating repo

Adam Bowman 9 年之前
父节点
当前提交
2aa52b708c
共有 67 个文件被更改,包括 6562 次插入4630 次删除
  1. 22 10
      Exporters/Unity 5/Unity3D2Babylon/SceneBuilder.Materials.cs
  2. 2 2
      Tools/Gulp/config.json
  3. 1 1
      Tools/Gulp/package.json
  4. 41 0
      Tools/Npm/package.json
  5. 26 34
      dist/preview release/babylon.core.js
  6. 834 376
      dist/preview release/babylon.d.ts
  7. 42 53
      dist/preview release/babylon.js
  8. 3652 3394
      dist/preview release/babylon.max.js
  9. 42 53
      dist/preview release/babylon.noworker.js
  10. 1 1
      dist/preview release/what's new.md
  11. 81 7
      materialsLibrary/materials/water/babylon.waterMaterial.ts
  12. 127 45
      materialsLibrary/materials/water/water.fragment.fx
  13. 17 1
      materialsLibrary/materials/water/water.vertex.fx
  14. 46 15
      materialsLibrary/test/add/addwater.js
  15. 9 0
      src/Audio/babylon.audioEngine.js
  16. 13 0
      src/Audio/babylon.audioEngine.ts
  17. 71 28
      src/Audio/babylon.sound.js
  18. 71 29
      src/Audio/babylon.sound.ts
  19. 4 4
      src/Cameras/VR/babylon.vrDeviceOrientationCamera.js
  20. 3 4
      src/Cameras/VR/babylon.vrDeviceOrientationCamera.ts
  21. 6 1
      src/Cameras/babylon.arcRotateCamera.js
  22. 5 1
      src/Cameras/babylon.arcRotateCamera.ts
  23. 13 2
      src/Cameras/babylon.camera.js
  24. 33 2
      src/Cameras/babylon.camera.ts
  25. 14 3
      src/Cameras/babylon.targetCamera.js
  26. 13 3
      src/Cameras/babylon.targetCamera.ts
  27. 22 3
      src/Canvas2d/babylon.canvas2d.js
  28. 18 4
      src/Canvas2d/babylon.canvas2d.ts
  29. 9 0
      src/Canvas2d/babylon.group2d.js
  30. 10 0
      src/Canvas2d/babylon.group2d.ts
  31. 9 7
      src/Canvas2d/babylon.prim2dBase.js
  32. 9 7
      src/Canvas2d/babylon.prim2dBase.ts
  33. 4 1
      src/Canvas2d/babylon.renderablePrim2d.js
  34. 4 1
      src/Canvas2d/babylon.renderablePrim2d.ts
  35. 2 8
      src/Canvas2d/babylon.smartPropertyPrim.js
  36. 3 11
      src/Canvas2d/babylon.smartPropertyPrim.ts
  37. 45 0
      src/Lights/babylon.light.js
  38. 37 0
      src/Lights/babylon.light.ts
  39. 8 2
      src/Materials/babylon.material.js
  40. 9 2
      src/Materials/babylon.material.ts
  41. 20 0
      src/Materials/babylon.materialHelper.js
  42. 22 0
      src/Materials/babylon.materialHelper.ts
  43. 151 180
      src/Math/babylon.math.SIMD.js
  44. 188 229
      src/Math/babylon.math.SIMD.ts
  45. 66 3
      src/Math/babylon.math.js
  46. 90 6
      src/Math/babylon.math.ts
  47. 8 0
      src/Mesh/babylon.abstractMesh.js
  48. 10 0
      src/Mesh/babylon.abstractMesh.ts
  49. 7 6
      src/Mesh/babylon.geometry.js
  50. 7 6
      src/Mesh/babylon.geometry.ts
  51. 35 14
      src/Mesh/babylon.groundMesh.js
  52. 2 0
      src/Mesh/babylon.mesh.js
  53. 4 0
      src/Mesh/babylon.mesh.ts
  54. 14 13
      src/Mesh/babylon.mesh.vertexData.js
  55. 4 2
      src/Mesh/babylon.meshBuilder.js
  56. 2 2
      src/Physics/Plugins/babylon.oimoJSPlugin.js
  57. 2 2
      src/Physics/Plugins/babylon.oimoJSPlugin.ts
  58. 28 15
      src/Shaders/ShadersInclude/lightFragment.fx
  59. 36 22
      src/Shaders/ShadersInclude/pbrLightFunctionsCall.fx
  60. 12 7
      src/Shaders/default.fragment.fx
  61. 13 7
      src/Shaders/pbr.fragment.fx
  62. 11 0
      src/Tools/babylon.tools.js
  63. 12 0
      src/Tools/babylon.tools.ts
  64. 1 1
      src/babylon.engine.ts
  65. 437 0
      src/babylon.mixins.ts
  66. 1 0
      src/babylon.scene.js
  67. 1 0
      src/babylon.scene.ts

+ 22 - 10
Exporters/Unity 5/Unity3D2Babylon/SceneBuilder.Materials.cs

@@ -88,7 +88,6 @@ namespace Unity3D2Babylon
         private void CopyTexture(string texturePath, Texture2D texture2D, BabylonTexture babylonTexture, bool isLightmap = false)
         private void CopyTexture(string texturePath, Texture2D texture2D, BabylonTexture babylonTexture, bool isLightmap = false)
         {
         {
             bool needToDelete = false;
             bool needToDelete = false;
-            var useJPG = !texture2D.alphaIsTransparency;
 
 
             // Convert unsupported file extensions
             // Convert unsupported file extensions
             if (texturePath.EndsWith(".psd") || texturePath.EndsWith(".tif") || texturePath.EndsWith(".exr"))
             if (texturePath.EndsWith(".psd") || texturePath.EndsWith(".tif") || texturePath.EndsWith(".exr"))
@@ -112,11 +111,8 @@ namespace Unity3D2Babylon
                     textureImporter.grayscaleToAlpha = false;
                     textureImporter.grayscaleToAlpha = false;
 
 
                     AssetDatabase.ImportAsset(texturePath);
                     AssetDatabase.ImportAsset(texturePath);
-
-                    texturePath = Path.Combine(Path.GetTempPath(), Path.GetFileName(texturePath));
-                    var extension = useJPG ? ".jpg" : ".png";
-                    texturePath = texturePath.Replace(".psd", extension).Replace(".tif", extension).Replace(".exr", extension);
-
+                    
+                    var usePNG = texture2D.alphaIsTransparency;
                     var tempTexture = new Texture2D(texture2D.width, texture2D.height, TextureFormat.ARGB32, false);
                     var tempTexture = new Texture2D(texture2D.width, texture2D.height, TextureFormat.ARGB32, false);
 
 
                     if (isLightmap)
                     if (isLightmap)
@@ -130,12 +126,22 @@ namespace Unity3D2Babylon
                         }
                         }
                         tempTexture.SetPixels(pixels);
                         tempTexture.SetPixels(pixels);
                     }
                     }
-                    else {
+                    else
+                    {
+                        Color[] pixels = texture2D.GetPixels(0, 0, texture2D.width, texture2D.height);
+                        for (int index = 0; index < pixels.Length; index++)
+                        {
+                            usePNG |= pixels[index].a <= 0.99999f;
+                        }
+                        
                         tempTexture.SetPixels32(texture2D.GetPixels32());
                         tempTexture.SetPixels32(texture2D.GetPixels32());
                     }
                     }
                     tempTexture.Apply();
                     tempTexture.Apply();
 
 
-                    File.WriteAllBytes(texturePath, useJPG ? tempTexture.EncodeToJPG() : tempTexture.EncodeToPNG());
+                    texturePath = Path.Combine(Path.GetTempPath(), Path.GetFileName(texturePath));
+                    var extension = usePNG ? ".png": ".jpg";
+                    texturePath = texturePath.Replace(".psd", extension).Replace(".tif", extension).Replace(".exr", extension);
+                    File.WriteAllBytes(texturePath, usePNG ? tempTexture.EncodeToPNG() : tempTexture.EncodeToJPG());
 
 
                     needToDelete = true;
                     needToDelete = true;
 
 
@@ -154,6 +160,14 @@ namespace Unity3D2Babylon
                     Debug.LogException(ex);
                     Debug.LogException(ex);
                 }
                 }
             }
             }
+            else if (texture2D.alphaIsTransparency || texturePath.EndsWith(".png"))
+            {
+                babylonTexture.hasAlpha = true;
+            }
+            else
+            {
+                babylonTexture.hasAlpha = false;
+            }
 
 
             var textureName = Path.GetFileName(texturePath);
             var textureName = Path.GetFileName(texturePath);
             babylonTexture.name = textureName;
             babylonTexture.name = textureName;
@@ -594,8 +608,6 @@ namespace Unity3D2Babylon
             var texture2D = texture as Texture2D;
             var texture2D = texture as Texture2D;
             if (texture2D)
             if (texture2D)
             {
             {
-                babylonTexture.hasAlpha = texture2D.alphaIsTransparency;
-
                 CopyTexture(texturePath, texture2D, babylonTexture, isLightmap);
                 CopyTexture(texturePath, texture2D, babylonTexture, isLightmap);
             }
             }
             else
             else

+ 2 - 2
Tools/Gulp/config.json

@@ -11,11 +11,11 @@
   "core": {
   "core": {
     "typescript": [
     "typescript": [
       "../../src/**/*.ts",
       "../../src/**/*.ts",
-      "!../../src/**/*.d.ts",
-      "../../external references/**/*.d.ts"
+      "!../../src/**/*.d.ts"
     ],
     ],
     "files": [
     "files": [
       "../../src/Math/babylon.math.js",
       "../../src/Math/babylon.math.js",
+      "../../src/babylon.mixins.js",
       "../../src/Tools/babylon.decorators.js",
       "../../src/Tools/babylon.decorators.js",
       "../../src/Tools/babylon.observable.js",
       "../../src/Tools/babylon.observable.js",
       "../../src/Tools/babylon.database.js",
       "../../src/Tools/babylon.database.js",

+ 1 - 1
Tools/Gulp/package.json

@@ -8,7 +8,7 @@
   "license": "(Apache-2.0)",
   "license": "(Apache-2.0)",
   "devDependencies": {
   "devDependencies": {
     "gulp": "^3.8.11",
     "gulp": "^3.8.11",
-    "gulp-uglify": "~1.2.0",
+    "gulp-uglify": "~1.5.3",
     "gulp-sourcemaps": "~1.5.2",
     "gulp-sourcemaps": "~1.5.2",
     "typescript": "^1.7.5",
     "typescript": "^1.7.5",
     "gulp-typescript": "~2.13.0",
     "gulp-typescript": "~2.13.0",

+ 41 - 0
Tools/Npm/package.json

@@ -0,0 +1,41 @@
+{
+  "author": {
+    "name": "David CATUHE"
+  },
+  "contributors": [
+    "David ROUSSET"
+  ],
+  "name": "babylonjs",
+  "description": "Babylon.js is a JavaScript 3D engine based on webgl.",
+  "version": "2.4.0",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/BabylonJS/Babylon.js.git"
+  },
+  "main": "babylon.js",
+  "files": [
+    "babylon.d.ts",
+    "babylon.js",
+    "babylon.max.js",
+    "babylon.noworker.js",
+    "babylon.core.js",
+    "Oimo.js",
+    "package.json"
+  ],
+  "typings": "babylon.d.ts",
+  "keywords": [
+    "3D",
+    "javascript",
+    "html5",
+    "webgl"
+  ],
+  "license": "Apache-2.0",
+  "dependencies": {},
+  "engines": {
+    "node": "*"
+  },
+  "readme": "Babylon.js is a 3D engine based on webgl and javascript",
+  "readmeFilename": "README.md",
+  "_id": "babylonjs@2.0.2",
+  "_from": "babylonjs@"
+}

文件差异内容过多而无法显示
+ 26 - 34
dist/preview release/babylon.core.js


文件差异内容过多而无法显示
+ 834 - 376
dist/preview release/babylon.d.ts


文件差异内容过多而无法显示
+ 42 - 53
dist/preview release/babylon.js


文件差异内容过多而无法显示
+ 3652 - 3394
dist/preview release/babylon.max.js


文件差异内容过多而无法显示
+ 42 - 53
dist/preview release/babylon.noworker.js


+ 1 - 1
dist/preview release/what's new.md

@@ -1,7 +1,7 @@
 # 2.5.0:
 # 2.5.0:
 
 
 ### Major updates
 ### Major updates
-    
+- Babylon.js now supports right handed system with ```scene.useRightHandedSystem = true``` ([deltakosh](https://github.com/deltakosh))    
 ### Updates
 ### Updates
 - Cube textures are now cached by texture cache ([deltakosh](https://github.com/deltakosh)) 
 - Cube textures are now cached by texture cache ([deltakosh](https://github.com/deltakosh)) 
 - Added onAnimationEnd callback for `sprite.playAnimation` ([deltakosh](https://github.com/deltakosh)) 
 - Added onAnimationEnd callback for `sprite.playAnimation` ([deltakosh](https://github.com/deltakosh)) 

+ 81 - 7
materialsLibrary/materials/water/babylon.waterMaterial.ts

@@ -18,6 +18,11 @@ module BABYLON {
         public BonesPerMesh = 0;
         public BonesPerMesh = 0;
         public INSTANCES = false;
         public INSTANCES = false;
         public SPECULARTERM = false;
         public SPECULARTERM = false;
+        public LOGARITHMICDEPTH = false;
+        public FRESNELSEPARATE = false;
+        public BUMPSUPERIMPOSE = false;
+        public BUMPAFFECTSREFLECTION = false;
+
 
 
         constructor() {
         constructor() {
             super();
             super();
@@ -68,7 +73,23 @@ module BABYLON {
         @serialize()
         @serialize()
 		public bumpHeight: number = 0.4;
 		public bumpHeight: number = 0.4;
         /**
         /**
-        * @param {number}: The water color blended with the reflection and refraction samplers
+         * @param {boolean}: Add a smaller moving bump to less steady waves.
+         */
+        @serialize()
+        public bumpSuperimpose = false;
+        /**
+         * @param {boolean}: Color refraction and reflection differently with .waterColor2 and .colorBlendFactor2. Non-linear (physically correct) fresnel.
+         */
+        @serialize()
+        public fresnelSeparate = false;
+        /**
+         * @param {boolean}: bump Waves modify the reflection.
+         */
+        @serialize()
+        public bumpAffectsReflection = false;
+
+        /**
+        * @param {number}: The water color blended with the refraction (near)
         */
         */
         @serializeAsColor3()
         @serializeAsColor3()
 		public waterColor: Color3 = new Color3(0.1, 0.1, 0.6);
 		public waterColor: Color3 = new Color3(0.1, 0.1, 0.6);
@@ -78,6 +99,16 @@ module BABYLON {
         @serialize()
         @serialize()
 		public colorBlendFactor: number = 0.2;
 		public colorBlendFactor: number = 0.2;
         /**
         /**
+         * @param {number}: The water color blended with the reflection (far)
+         */
+        @serializeAsColor3()
+        public waterColor2: Color3 = new Color3(0.1, 0.1, 0.6);
+        /**
+         * @param {number}: The blend factor related to the water color (reflection, far)
+         */
+        @serialize()
+        public colorBlendFactor2: number = 0.2;
+        /**
         * @param {number}: Represents the maximum length of a wave
         * @param {number}: Represents the maximum length of a wave
         */
         */
         @serialize()
         @serialize()
@@ -106,8 +137,10 @@ module BABYLON {
 
 
         private _defines = new WaterMaterialDefines();
         private _defines = new WaterMaterialDefines();
         private _cachedDefines = new WaterMaterialDefines();
         private _cachedDefines = new WaterMaterialDefines();
-		
-		/**
+
+        private _useLogarithmicDepth: boolean;
+
+        /**
 		* Constructor
 		* Constructor
 		*/
 		*/
 		constructor(name: string, scene: Scene, public renderTargetSize: Vector2 = new Vector2(512, 512)) {
 		constructor(name: string, scene: Scene, public renderTargetSize: Vector2 = new Vector2(512, 512)) {
@@ -116,7 +149,16 @@ module BABYLON {
 			// Create render targets
 			// Create render targets
 			this._createRenderTargets(scene, renderTargetSize);
 			this._createRenderTargets(scene, renderTargetSize);
         }
         }
-		
+
+        @serialize()
+        public get useLogarithmicDepth(): boolean {
+            return this._useLogarithmicDepth;
+        }
+
+        public set useLogarithmicDepth(value: boolean) {
+            this._useLogarithmicDepth = value && this.getScene().getEngine().getCaps().fragmentDepthSupported;
+        }
+
         // Get / Set
         // Get / Set
         public get refractionTexture(): RenderTargetTexture {
         public get refractionTexture(): RenderTargetTexture {
             return this._refractionRTT;
             return this._refractionRTT;
@@ -228,6 +270,22 @@ module BABYLON {
                 this._defines.POINTSIZE = true;
                 this._defines.POINTSIZE = true;
             }
             }
 
 
+            if (this.useLogarithmicDepth) {
+                this._defines.LOGARITHMICDEPTH = true;
+            }
+
+            if (this.fresnelSeparate) {
+                this._defines.FRESNELSEPARATE = true;
+            }
+
+            if (this.bumpSuperimpose) {
+                this._defines.BUMPSUPERIMPOSE = true;
+            }
+
+            if (this.bumpAffectsReflection) {
+                this._defines.BUMPAFFECTSREFLECTION = true;
+            }
+
             // Fog
             // Fog
             if (scene.fogEnabled && mesh && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE && this.fogEnabled) {
             if (scene.fogEnabled && mesh && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE && this.fogEnabled) {
                 this._defines.FOG = true;
                 this._defines.FOG = true;
@@ -284,6 +342,10 @@ module BABYLON {
                     fallbacks.addFallback(1, "FOG");
                     fallbacks.addFallback(1, "FOG");
                 }
                 }
 
 
+                if (this._defines.LOGARITHMICDEPTH) {
+                    fallbacks.addFallback(0, "LOGARITHMICDEPTH");
+                }
+
                 MaterialHelper.HandleFallbacksForShadows(this._defines, fallbacks, this.maxSimultaneousLights);
                 MaterialHelper.HandleFallbacksForShadows(this._defines, fallbacks, this.maxSimultaneousLights);
              
              
                 if (this._defines.NUM_BONE_INFLUENCERS > 0) {
                 if (this._defines.NUM_BONE_INFLUENCERS > 0) {
@@ -320,9 +382,11 @@ module BABYLON {
                     "vNormalInfos", 
                     "vNormalInfos", 
                     "mBones",
                     "mBones",
                     "vClipPlane", "normalMatrix",
                     "vClipPlane", "normalMatrix",
+                    "logarithmicDepthConstant",
+
                     // Water
                     // Water
                     "worldReflectionViewProjection", "windDirection", "waveLength", "time", "windForce",
                     "worldReflectionViewProjection", "windDirection", "waveLength", "time", "windForce",
-                    "cameraPosition", "bumpHeight", "waveHeight", "waterColor", "colorBlendFactor", "waveSpeed"
+                    "cameraPosition", "bumpHeight", "waveHeight", "waterColor", "waterColor2", "colorBlendFactor", "colorBlendFactor2", "waveSpeed"
                 ]
                 ]
                 var samplers = ["normalSampler",
                 var samplers = ["normalSampler",
                     // Water
                     // Water
@@ -403,7 +467,10 @@ module BABYLON {
 
 
             // Fog
             // Fog
             MaterialHelper.BindFogParameters(scene, mesh, this._effect);
             MaterialHelper.BindFogParameters(scene, mesh, this._effect);
-            
+
+            // Log. depth
+            MaterialHelper.BindLogDepth(this._defines, this._effect, scene);
+
             // Water
             // Water
             if (StandardMaterial.ReflectionTextureEnabled) {
             if (StandardMaterial.ReflectionTextureEnabled) {
                 this._effect.setTexture("refractionSampler", this._refractionRTT);
                 this._effect.setTexture("refractionSampler", this._refractionRTT);
@@ -422,6 +489,8 @@ module BABYLON {
             this._effect.setFloat("bumpHeight", this.bumpHeight);
             this._effect.setFloat("bumpHeight", this.bumpHeight);
 			this._effect.setColor4("waterColor", this.waterColor, 1.0);
 			this._effect.setColor4("waterColor", this.waterColor, 1.0);
 			this._effect.setFloat("colorBlendFactor", this.colorBlendFactor);
 			this._effect.setFloat("colorBlendFactor", this.colorBlendFactor);
+            this._effect.setColor4("waterColor2", this.waterColor2, 1.0);
+            this._effect.setFloat("colorBlendFactor2", this.colorBlendFactor2);
             this._effect.setFloat("waveSpeed", this.waveSpeed);
             this._effect.setFloat("waveSpeed", this.waveSpeed);
 
 
             super.bind(world, mesh);
             super.bind(world, mesh);
@@ -430,8 +499,13 @@ module BABYLON {
 		private _createRenderTargets(scene: Scene, renderTargetSize: Vector2): void {
 		private _createRenderTargets(scene: Scene, renderTargetSize: Vector2): void {
 			// Render targets
 			// Render targets
 			this._refractionRTT = new RenderTargetTexture(name + "_refraction", {width: renderTargetSize.x, height: renderTargetSize.y}, scene, false, true);
 			this._refractionRTT = new RenderTargetTexture(name + "_refraction", {width: renderTargetSize.x, height: renderTargetSize.y}, scene, false, true);
+            this._refractionRTT.wrapU = BABYLON.Texture.MIRROR_ADDRESSMODE;
+            this._refractionRTT.wrapV = BABYLON.Texture.MIRROR_ADDRESSMODE;
+
 			this._reflectionRTT = new RenderTargetTexture(name + "_reflection", {width: renderTargetSize.x, height: renderTargetSize.y}, scene, false, true);
 			this._reflectionRTT = new RenderTargetTexture(name + "_reflection", {width: renderTargetSize.x, height: renderTargetSize.y}, scene, false, true);
-			
+            this._reflectionRTT.wrapU = BABYLON.Texture.MIRROR_ADDRESSMODE;
+            this._reflectionRTT.wrapV = BABYLON.Texture.MIRROR_ADDRESSMODE;
+
 			scene.customRenderTargets.push(this._refractionRTT);
 			scene.customRenderTargets.push(this._refractionRTT);
 			scene.customRenderTargets.push(this._reflectionRTT);
 			scene.customRenderTargets.push(this._reflectionRTT);
 			
 			

+ 127 - 45
materialsLibrary/materials/water/water.fragment.fx

@@ -1,3 +1,7 @@
+#ifdef LOGARITHMICDEPTH
+#extension GL_EXT_frag_depth : enable
+#endif
+
 precision highp float;
 precision highp float;
 
 
 // Constants
 // Constants
@@ -28,6 +32,7 @@ varying vec4 vColor;
 // Samplers
 // Samplers
 #ifdef BUMP
 #ifdef BUMP
 varying vec2 vNormalUV;
 varying vec2 vNormalUV;
+varying vec2 vNormalUV2;
 uniform sampler2D normalSampler;
 uniform sampler2D normalSampler;
 uniform vec2 vNormalInfos;
 uniform vec2 vNormalInfos;
 #endif
 #endif
@@ -43,14 +48,20 @@ uniform vec3 cameraPosition;
 uniform vec4 waterColor;
 uniform vec4 waterColor;
 uniform float colorBlendFactor;
 uniform float colorBlendFactor;
 
 
+uniform vec4 waterColor2;
+uniform float colorBlendFactor2;
+
 uniform float bumpHeight;
 uniform float bumpHeight;
 
 
+uniform float time;
+
 // Water varyings
 // Water varyings
 varying vec3 vRefractionMapTexCoord;
 varying vec3 vRefractionMapTexCoord;
 varying vec3 vReflectionMapTexCoord;
 varying vec3 vReflectionMapTexCoord;
 varying vec3 vPosition;
 varying vec3 vPosition;
 
 
 #include<clipPlaneFragmentDeclaration>
 #include<clipPlaneFragmentDeclaration>
+#include<logDepthDeclaration>
 
 
 // Fog
 // Fog
 #include<fogFragmentDeclaration>
 #include<fogFragmentDeclaration>
@@ -69,7 +80,11 @@ void main(void) {
 	float alpha = vDiffuseColor.a;
 	float alpha = vDiffuseColor.a;
 
 
 #ifdef BUMP
 #ifdef BUMP
-	baseColor = texture2D(normalSampler, vNormalUV);
+    #ifdef BUMPSUPERIMPOSE
+    	baseColor = 0.6 * texture2D(normalSampler, vNormalUV) + 0.4 * texture2D(normalSampler,vec2(vNormalUV2.x,vNormalUV2.y));
+    #else
+	    baseColor = texture2D(normalSampler, vNormalUV);
+    #endif
 	vec3 bumpColor = baseColor.rgb;
 	vec3 bumpColor = baseColor.rgb;
 
 
 #ifdef ALPHATEST
 #ifdef ALPHATEST
@@ -88,63 +103,130 @@ void main(void) {
 
 
 	// Bump
 	// Bump
 #ifdef NORMAL
 #ifdef NORMAL
-	vec3 normalW = normalize(vNormalW);
 	vec2 perturbation = bumpHeight * (baseColor.rg - 0.5);
 	vec2 perturbation = bumpHeight * (baseColor.rg - 0.5);
+	#ifdef BUMPAFFECTSREFLECTION
+	    vec3 normalW = normalize(vNormalW + vec3(perturbation.x*8.0,0.0,perturbation.y*8.0));
+	    if (normalW.y<0.0) {
+	        normalW.y = -normalW.y;
+	    }
+    #else
+    	vec3 normalW = normalize(vNormalW);
+	#endif
 #else
 #else
 	vec3 normalW = vec3(1.0, 1.0, 1.0);
 	vec3 normalW = vec3(1.0, 1.0, 1.0);
 	vec2 perturbation = bumpHeight * (vec2(1.0, 1.0) - 0.5);
 	vec2 perturbation = bumpHeight * (vec2(1.0, 1.0) - 0.5);
 #endif
 #endif
 
 
-#ifdef REFLECTION
-	// Water
-	vec3 eyeVector = normalize(vEyePosition - vPosition);
-	
-	vec2 projectedRefractionTexCoords = clamp(vRefractionMapTexCoord.xy / vRefractionMapTexCoord.z + perturbation, 0.0, 1.0);
-	vec4 refractiveColor = texture2D(refractionSampler, projectedRefractionTexCoords);
-	
-	vec2 projectedReflectionTexCoords = clamp(vReflectionMapTexCoord.xy / vReflectionMapTexCoord.z + perturbation, 0.0, 1.0);
-	vec4 reflectiveColor = texture2D(reflectionSampler, projectedReflectionTexCoords);
-	
-	vec3 upVector = vec3(0.0, 1.0, 0.0);
-	
-	float fresnelTerm = max(dot(eyeVector, upVector), 0.0);
-	
-	vec4 combinedColor = refractiveColor * fresnelTerm + reflectiveColor * (1.0 - fresnelTerm);
-	
-	baseColor = colorBlendFactor * waterColor + (1.0 - colorBlendFactor) * combinedColor;
-#endif
+#ifdef FRESNELSEPARATE
+    #ifdef REFLECTION
+        // Water
+        vec3 eyeVector = normalize(vEyePosition - vPosition);
+
+        vec2 projectedRefractionTexCoords = clamp(vRefractionMapTexCoord.xy / vRefractionMapTexCoord.z + perturbation*0.5, 0.0, 1.0);
+        vec4 refractiveColor = texture2D(refractionSampler, projectedRefractionTexCoords);
 
 
-	// Lighting
-	vec3 diffuseBase = vec3(0., 0., 0.);
+        vec2 projectedReflectionTexCoords = clamp(vec2(
+            vReflectionMapTexCoord.x / vReflectionMapTexCoord.z + perturbation.x * 0.3,
+            vReflectionMapTexCoord.y / vReflectionMapTexCoord.z + perturbation.y
+        ),0.0, 1.0);
+
+        vec4 reflectiveColor = texture2D(reflectionSampler, projectedReflectionTexCoords);
+
+        vec3 upVector = vec3(0.0, 1.0, 0.0);
+
+        float fresnelTerm = clamp(abs(pow(dot(eyeVector, upVector),3.0)),0.05,0.65);
+        float IfresnelTerm = 1.0 - fresnelTerm;
+
+        refractiveColor = colorBlendFactor*waterColor + (1.0-colorBlendFactor)*refractiveColor;
+        reflectiveColor = IfresnelTerm*colorBlendFactor2*waterColor + (1.0-colorBlendFactor2*IfresnelTerm)*reflectiveColor;
+
+        vec4 combinedColor = refractiveColor * fresnelTerm + reflectiveColor * IfresnelTerm;
+        baseColor = combinedColor;
+    #endif
+
+    // Lighting
+    vec3 diffuseBase = vec3(0., 0., 0.);
     lightingInfo info;
     lightingInfo info;
-	float shadow = 1.;
-    
-#ifdef SPECULARTERM
-	float glossiness = vSpecularColor.a;
-	vec3 specularBase = vec3(0., 0., 0.);
-    vec3 specularColor = vSpecularColor.rgb;
-#else
-	float glossiness = 0.;
-#endif
-    
-#include<lightFragment>[0..maxSimultaneousLights]
+    float shadow = 1.;
 
 
-#ifdef VERTEXALPHA
-	alpha *= vColor.a;
-#endif
+    #ifdef SPECULARTERM
+        float glossiness = vSpecularColor.a;
+        vec3 specularBase = vec3(0., 0., 0.);
+        vec3 specularColor = vSpecularColor.rgb;
+    #else
+        float glossiness = 0.;
+    #endif
 
 
-#ifdef SPECULARTERM
-	vec3 finalSpecular = specularBase * specularColor;
-#else
-	vec3 finalSpecular = vec3(0.0);
-#endif
+    #include<lightFragment>[0..maxSimultaneousLights]
+
+    vec3 finalDiffuse = clamp(baseColor.rgb, 0.0, 1.0);
+
+    #ifdef VERTEXALPHA
+        alpha *= vColor.a;
+    #endif
+
+    #ifdef SPECULARTERM
+        vec3 finalSpecular = specularBase * specularColor;
+    #else
+        vec3 finalSpecular = vec3(0.0);
+    #endif
+
+
+#else // !FRESNELSEPARATE
+    #ifdef REFLECTION
+        // Water
+        vec3 eyeVector = normalize(vEyePosition - vPosition);
+
+        vec2 projectedRefractionTexCoords = clamp(vRefractionMapTexCoord.xy / vRefractionMapTexCoord.z + perturbation, 0.0, 1.0);
+        vec4 refractiveColor = texture2D(refractionSampler, projectedRefractionTexCoords);
+
+        vec2 projectedReflectionTexCoords = clamp(vReflectionMapTexCoord.xy / vReflectionMapTexCoord.z + perturbation, 0.0, 1.0);
+        vec4 reflectiveColor = texture2D(reflectionSampler, projectedReflectionTexCoords);
+
+        vec3 upVector = vec3(0.0, 1.0, 0.0);
+
+        float fresnelTerm = max(dot(eyeVector, upVector), 0.0);
 
 
-	vec3 finalDiffuse = clamp(diffuseBase * diffuseColor, 0.0, 1.0) * baseColor.rgb;
+        vec4 combinedColor = refractiveColor * fresnelTerm + reflectiveColor * (1.0 - fresnelTerm);
+
+        baseColor = colorBlendFactor * waterColor + (1.0 - colorBlendFactor) * combinedColor;
+    #endif
+
+    // Lighting
+    vec3 diffuseBase = vec3(0., 0., 0.);
+    lightingInfo info;
+    float shadow = 1.;
+
+    #ifdef SPECULARTERM
+        float glossiness = vSpecularColor.a;
+        vec3 specularBase = vec3(0., 0., 0.);
+        vec3 specularColor = vSpecularColor.rgb;
+    #else
+        float glossiness = 0.;
+    #endif
+
+    #include<lightFragment>[0..maxSimultaneousLights]
+
+    vec3 finalDiffuse = clamp(baseColor.rgb, 0.0, 1.0);
+
+
+    #ifdef VERTEXALPHA
+        alpha *= vColor.a;
+    #endif
+
+    #ifdef SPECULARTERM
+        vec3 finalSpecular = specularBase * specularColor;
+    #else
+        vec3 finalSpecular = vec3(0.0);
+    #endif
+
+#endif
 
 
-	// Composition
-	vec4 color = vec4(finalDiffuse + finalSpecular, alpha);
+// Composition
+vec4 color = vec4(finalDiffuse + finalSpecular, alpha);
 
 
+#include<logDepthFragment>
 #include<fogFragment>
 #include<fogFragment>
 	
 	
 	gl_FragColor = color;
 	gl_FragColor = color;
-}
+}

+ 17 - 1
materialsLibrary/materials/water/water.vertex.fx

@@ -25,6 +25,9 @@ uniform mat4 viewProjection;
 
 
 #ifdef BUMP
 #ifdef BUMP
 varying vec2 vNormalUV;
 varying vec2 vNormalUV;
+#ifdef BUMPSUPERIMPOSE
+    varying vec2 vNormalUV2;
+#endif
 uniform mat4 normalMatrix;
 uniform mat4 normalMatrix;
 uniform vec2 vNormalInfos;
 uniform vec2 vNormalInfos;
 #endif
 #endif
@@ -48,6 +51,8 @@ varying vec4 vColor;
 #include<fogVertexDeclaration>
 #include<fogVertexDeclaration>
 #include<shadowsVertexDeclaration>[0..maxSimultaneousLights]
 #include<shadowsVertexDeclaration>[0..maxSimultaneousLights]
 
 
+#include<logDepthDeclaration>
+
 // Water uniforms
 // Water uniforms
 uniform mat4 worldReflectionViewProjection;
 uniform mat4 worldReflectionViewProjection;
 uniform vec2 windDirection;
 uniform vec2 windDirection;
@@ -62,6 +67,8 @@ varying vec3 vPosition;
 varying vec3 vRefractionMapTexCoord;
 varying vec3 vRefractionMapTexCoord;
 varying vec3 vReflectionMapTexCoord;
 varying vec3 vReflectionMapTexCoord;
 
 
+
+
 void main(void) {
 void main(void) {
 
 
     #include<instancesVertex>
     #include<instancesVertex>
@@ -86,10 +93,16 @@ void main(void) {
 	if (vNormalInfos.x == 0.)
 	if (vNormalInfos.x == 0.)
 	{
 	{
 		vNormalUV = vec2(normalMatrix * vec4((uv * 1.0) / waveLength + time * windForce * windDirection, 1.0, 0.0));
 		vNormalUV = vec2(normalMatrix * vec4((uv * 1.0) / waveLength + time * windForce * windDirection, 1.0, 0.0));
+        #ifdef BUMPSUPERIMPOSE
+		    vNormalUV2 = vec2(normalMatrix * vec4((uv * 0.721) / waveLength + time * 1.2 * windForce * windDirection, 1.0, 0.0));
+		#endif
 	}
 	}
 	else
 	else
 	{
 	{
-		vNormalUV = vec2(normalMatrix * vec4((uv2 * 1.0) / waveLength + time * windForce * windDirection, 1.0, 0.0));
+		vNormalUV = vec2(normalMatrix * vec4((uv2 * 1.0) / waveLength + time * windForce * windDirection , 1.0, 0.0));
+        #ifdef BUMPSUPERIMPOSE
+    		vNormalUV2 = vec2(normalMatrix * vec4((uv2 * 0.721) / waveLength + time * 1.2 * windForce * windDirection , 1.0, 0.0));
+    	#endif
 	}
 	}
 #endif
 #endif
 
 
@@ -134,4 +147,7 @@ void main(void) {
 	vReflectionMapTexCoord.y = 0.5 * (worldPos.w + worldPos.y);
 	vReflectionMapTexCoord.y = 0.5 * (worldPos.w + worldPos.y);
 	vReflectionMapTexCoord.z = worldPos.w;
 	vReflectionMapTexCoord.z = worldPos.w;
 #endif
 #endif
+
+#include<logDepthVertex>
+
 }
 }

+ 46 - 15
materialsLibrary/test/add/addwater.js

@@ -44,29 +44,60 @@ window.prepareWater = function() {
 	});
 	});
 	
 	
 	// Specular color
 	// Specular color
-	registerRangeUI("water", "specularColorR", 0, 1, function(value) {
-		water.specularColor.r = value;
+	registerColorPicker("water", "specularColor", "#703605", function(value) {		
+		water.specularColor.r = value.r/255;
+		water.specularColor.g = value.g/255;
+		water.specularColor.b = value.b/255;
 	}, function() {
 	}, function() {
-		return water.specularColor.r;
+		return water.specularColor;
 	});
 	});
-	
-	registerRangeUI("water", "specularColorG", 0, 1, function(value) {
-		water.specularColor.g = value;
+
+	registerRangeUI("water", "specularPower", 0, 512, function(value) {
+		water.specularPower = value;
 	}, function() {
 	}, function() {
-		return water.specularColor.g;
+		return water.specularPower;
 	});
 	});
-	
-	registerRangeUI("water", "specularColorB", 0, 1, function(value) {
-		water.specularColor.b = value;
+
+	// Advanced
+	registerRangeUI("water", "bumpSuperimpose", 0, 1, function(value) {
+		water.bumpSuperimpose = value;
 	}, function() {
 	}, function() {
-		return water.specularColor.b;
+		return water.bumpSuperimpose;
 	});
 	});
-	
-	registerRangeUI("water", "specularPower", 0, 512, function(value) {
-		water.specularPower = value;
+
+	registerRangeUI("water", "fresnelSeparate", 0, 1, function(value) {
+		water.fresnelSeparate  = value;
 	}, function() {
 	}, function() {
-		return water.specularPower;
+		return water.fresnelSeparate ;
 	});
 	});
 		
 		
+	registerRangeUI("water", "bumpAffectsReflection", 0, 1, function(value) {
+		water.bumpAffectsReflection  = value;
+	}, function() {
+		return water.bumpAffectsReflection ;
+	});
+
+	registerRangeUI("water", "colorBlendFactor2", 0, 1, function(value) {
+		water.colorBlendFactor2 = value;
+	}, function() {
+		return water.colorBlendFactor2;
+	});
+
+	registerColorPicker("water", "waterColor", "#703605", function(value) {		
+		water.waterColor.r = value.r/255;
+		water.waterColor.g = value.g/255;
+		water.waterColor.b = value.b/255;
+	}, function() {
+		return water.waterColor;
+	});
+
+	registerColorPicker("water", "waterColor2", "#703605", function(value) {		
+		water.waterColor2.r = value.r/255;
+		water.waterColor2.g = value.g/255;
+		water.waterColor2.b = value.b/255;
+	}, function() {
+		return water.waterColor2;
+	});
+
 	return water;
 	return water;
 }
 }

+ 9 - 0
src/Audio/babylon.audioEngine.js

@@ -7,10 +7,19 @@ var BABYLON;
             this.canUseWebAudio = false;
             this.canUseWebAudio = false;
             this.WarnedWebAudioUnsupported = false;
             this.WarnedWebAudioUnsupported = false;
             this.unlocked = false;
             this.unlocked = false;
+            this.isMP3supported = false;
+            this.isOGGsupported = false;
             if (typeof window.AudioContext !== 'undefined' || typeof window.webkitAudioContext !== 'undefined') {
             if (typeof window.AudioContext !== 'undefined' || typeof window.webkitAudioContext !== 'undefined') {
                 window.AudioContext = window.AudioContext || window.webkitAudioContext;
                 window.AudioContext = window.AudioContext || window.webkitAudioContext;
                 this.canUseWebAudio = true;
                 this.canUseWebAudio = true;
             }
             }
+            var audioElem = document.createElement('audio');
+            if (audioElem && !!audioElem.canPlayType && audioElem.canPlayType('audio/mpeg; codecs="mp3"').replace(/^no$/, '')) {
+                this.isMP3supported = true;
+            }
+            if (audioElem && !!audioElem.canPlayType && audioElem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/, '')) {
+                this.isOGGsupported = true;
+            }
             if (/iPad|iPhone|iPod/.test(navigator.platform)) {
             if (/iPad|iPhone|iPod/.test(navigator.platform)) {
                 this._unlockiOSaudio();
                 this._unlockiOSaudio();
             }
             }

+ 13 - 0
src/Audio/babylon.audioEngine.ts

@@ -10,6 +10,9 @@
         public unlocked: boolean = false;
         public unlocked: boolean = false;
         public onAudioUnlocked: () => any;
         public onAudioUnlocked: () => any;
 
 
+        public isMP3supported: boolean = false;
+        public isOGGsupported: boolean = false;
+
         public get audioContext(): AudioContext {
         public get audioContext(): AudioContext {
             if (!this._audioContextInitialized) {
             if (!this._audioContextInitialized) {
                 this._initializeAudioContext();
                 this._initializeAudioContext();
@@ -23,6 +26,16 @@
                 this.canUseWebAudio = true;
                 this.canUseWebAudio = true;
             }
             }
 
 
+            var audioElem = document.createElement('audio');
+
+            if (audioElem && !!audioElem.canPlayType && audioElem.canPlayType('audio/mpeg; codecs="mp3"').replace(/^no$/, '')) {
+                this.isMP3supported = true;
+            }
+
+            if (audioElem && !!audioElem.canPlayType && audioElem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/, '')) {
+                this.isOGGsupported = true;
+            }
+
             if (/iPad|iPhone|iPod/.test(navigator.platform)) {
             if (/iPad|iPhone|iPod/.test(navigator.platform)) {
                 this._unlockiOSaudio();
                 this._unlockiOSaudio();
             }
             }

+ 71 - 28
src/Audio/babylon.sound.js

@@ -37,6 +37,7 @@ var BABYLON;
             this._coneOuterAngle = 360;
             this._coneOuterAngle = 360;
             this._coneOuterGain = 0;
             this._coneOuterGain = 0;
             this._isOutputConnected = false;
             this._isOutputConnected = false;
+            this._urlType = "Unknown";
             this.name = name;
             this.name = name;
             this._scene = scene;
             this._scene = scene;
             this._readyToPlayCallback = readyToPlayCallback;
             this._readyToPlayCallback = readyToPlayCallback;
@@ -74,41 +75,83 @@ var BABYLON;
                     this._createSpatialParameters();
                     this._createSpatialParameters();
                 }
                 }
                 this._scene.mainSoundTrack.AddSound(this);
                 this._scene.mainSoundTrack.AddSound(this);
+                var validParameter = true;
                 // if no parameter is passed, you need to call setAudioBuffer yourself to prepare the sound
                 // if no parameter is passed, you need to call setAudioBuffer yourself to prepare the sound
                 if (urlOrArrayBuffer) {
                 if (urlOrArrayBuffer) {
-                    // If it's an URL
-                    if (typeof (urlOrArrayBuffer) === "string") {
-                        // Loading sound using XHR2
-                        if (!this._streaming) {
-                            BABYLON.Tools.LoadFile(urlOrArrayBuffer, function (data) { _this._soundLoaded(data); }, null, this._scene.database, true);
-                        }
-                        else {
-                            this._htmlAudioElement = new Audio(urlOrArrayBuffer);
-                            this._htmlAudioElement.controls = false;
-                            this._htmlAudioElement.loop = this.loop;
-                            this._htmlAudioElement.crossOrigin = "anonymous";
-                            this._htmlAudioElement.preload = "auto";
-                            this._htmlAudioElement.addEventListener("canplaythrough", function () {
-                                _this._isReadyToPlay = true;
-                                if (_this.autoplay) {
-                                    _this.play();
+                    if (typeof (urlOrArrayBuffer) === "string")
+                        this._urlType = "String";
+                    if (Array.isArray(urlOrArrayBuffer))
+                        this._urlType = "Array";
+                    if (urlOrArrayBuffer instanceof ArrayBuffer)
+                        this._urlType = "ArrayBuffer";
+                    var urls = [];
+                    var codecSupportedFound = false;
+                    switch (this._urlType) {
+                        case "ArrayBuffer":
+                            if (urlOrArrayBuffer.byteLength > 0) {
+                                codecSupportedFound = true;
+                                this._soundLoaded(urlOrArrayBuffer);
+                            }
+                            break;
+                        case "String":
+                            urls.push(urlOrArrayBuffer);
+                        case "Array":
+                            if (urls.length === 0)
+                                urls = urlOrArrayBuffer;
+                            // If we found a supported format, we load it immediately and stop the loop
+                            for (var i = 0; i < urls.length; i++) {
+                                var url = urls[i];
+                                if (url.indexOf(".mp3", url.length - 4) !== -1 && BABYLON.Engine.audioEngine.isMP3supported) {
+                                    codecSupportedFound = true;
                                 }
                                 }
-                                if (_this._readyToPlayCallback) {
-                                    _this._readyToPlayCallback();
+                                if (url.indexOf(".ogg", url.length - 4) !== -1 && BABYLON.Engine.audioEngine.isOGGsupported) {
+                                    codecSupportedFound = true;
                                 }
                                 }
-                            });
-                            document.body.appendChild(this._htmlAudioElement);
-                        }
+                                if (url.indexOf(".wav", url.length - 4) !== -1) {
+                                    codecSupportedFound = true;
+                                }
+                                if (codecSupportedFound) {
+                                    // Loading sound using XHR2
+                                    if (!this._streaming) {
+                                        BABYLON.Tools.LoadFile(url, function (data) { _this._soundLoaded(data); }, null, this._scene.database, true);
+                                    }
+                                    else {
+                                        this._htmlAudioElement = new Audio(url);
+                                        this._htmlAudioElement.controls = false;
+                                        this._htmlAudioElement.loop = this.loop;
+                                        this._htmlAudioElement.crossOrigin = "anonymous";
+                                        this._htmlAudioElement.preload = "auto";
+                                        this._htmlAudioElement.addEventListener("canplaythrough", function () {
+                                            _this._isReadyToPlay = true;
+                                            if (_this.autoplay) {
+                                                _this.play();
+                                            }
+                                            if (_this._readyToPlayCallback) {
+                                                _this._readyToPlayCallback();
+                                            }
+                                        });
+                                        document.body.appendChild(this._htmlAudioElement);
+                                    }
+                                    break;
+                                }
+                            }
+                            break;
+                        default:
+                            validParameter = false;
+                            break;
+                    }
+                    if (!validParameter) {
+                        BABYLON.Tools.Error("Parameter must be a URL to the sound, an Array of URLs (.mp3 & .ogg) or an ArrayBuffer of the sound.");
                     }
                     }
                     else {
                     else {
-                        if (urlOrArrayBuffer instanceof ArrayBuffer) {
-                            if (urlOrArrayBuffer.byteLength > 0) {
-                                this._soundLoaded(urlOrArrayBuffer);
+                        if (!codecSupportedFound) {
+                            // Simulating a ready to play event to avoid breaking code path
+                            if (this._readyToPlayCallback) {
+                                window.setTimeout(function () {
+                                    _this._readyToPlayCallback();
+                                }, 1000);
                             }
                             }
                         }
                         }
-                        else {
-                            BABYLON.Tools.Error("Parameter must be a URL to the sound or an ArrayBuffer of the sound.");
-                        }
                     }
                     }
                 }
                 }
             }
             }
@@ -175,7 +218,7 @@ var BABYLON;
                 if (_this._readyToPlayCallback) {
                 if (_this._readyToPlayCallback) {
                     _this._readyToPlayCallback();
                     _this._readyToPlayCallback();
                 }
                 }
-            }, function () { BABYLON.Tools.Error("Error while decoding audio data for: " + _this.name); });
+            }, function (err) { BABYLON.Tools.Error("Error while decoding audio data for: " + _this.name + " / Error: " + err); });
         };
         };
         Sound.prototype.setAudioBuffer = function (audioBuffer) {
         Sound.prototype.setAudioBuffer = function (audioBuffer) {
             if (BABYLON.Engine.audioEngine.canUseWebAudio) {
             if (BABYLON.Engine.audioEngine.canUseWebAudio) {

+ 71 - 29
src/Audio/babylon.sound.ts

@@ -43,6 +43,7 @@
         private _registerFunc: (connectedMesh: AbstractMesh) => any;
         private _registerFunc: (connectedMesh: AbstractMesh) => any;
         private _isOutputConnected = false;
         private _isOutputConnected = false;
         private _htmlAudioElement: HTMLAudioElement;
         private _htmlAudioElement: HTMLAudioElement;
+        private _urlType: string = "Unknown";
 
 
         /**
         /**
         * Create a sound and attach it to a scene
         * Create a sound and attach it to a scene
@@ -90,42 +91,83 @@
                     this._createSpatialParameters();
                     this._createSpatialParameters();
                 }
                 }
                 this._scene.mainSoundTrack.AddSound(this);
                 this._scene.mainSoundTrack.AddSound(this);
+                var validParameter = true;
                 // if no parameter is passed, you need to call setAudioBuffer yourself to prepare the sound
                 // if no parameter is passed, you need to call setAudioBuffer yourself to prepare the sound
                 if (urlOrArrayBuffer) {
                 if (urlOrArrayBuffer) {
-                    // If it's an URL
-                    if (typeof (urlOrArrayBuffer) === "string") {
-                        // Loading sound using XHR2
-                        if (!this._streaming) {
-                            Tools.LoadFile(urlOrArrayBuffer, (data) => { this._soundLoaded(data); }, null, this._scene.database, true);
-                        }
-                        // Streaming sound using HTML5 Audio tag
-                        else {
-                            this._htmlAudioElement = new Audio(urlOrArrayBuffer);
-                            this._htmlAudioElement.controls = false;
-                            this._htmlAudioElement.loop = this.loop;
-                            this._htmlAudioElement.crossOrigin = "anonymous";
-                            this._htmlAudioElement.preload = "auto";
-                            this._htmlAudioElement.addEventListener("canplaythrough", () => {
-                                this._isReadyToPlay = true;
-                                if (this.autoplay) {
-                                    this.play();
+                    if (typeof (urlOrArrayBuffer) === "string") this._urlType = "String";
+                    if (Array.isArray(urlOrArrayBuffer)) this._urlType = "Array";
+                    if (urlOrArrayBuffer instanceof ArrayBuffer) this._urlType = "ArrayBuffer";
+
+                    var urls:string[] = [];
+                    var codecSupportedFound = false;
+ 
+                    switch (this._urlType) {
+                        case "ArrayBuffer":
+                            if ((<ArrayBuffer>urlOrArrayBuffer).byteLength > 0) {
+                                codecSupportedFound = true;
+                                this._soundLoaded(urlOrArrayBuffer);
+                            }
+                            break;
+                        case "String":
+                            urls.push(urlOrArrayBuffer);
+                        case "Array":
+                            if (urls.length === 0) urls = urlOrArrayBuffer;
+                            // If we found a supported format, we load it immediately and stop the loop
+                            for (var i = 0; i < urls.length; i++) {
+                                var url = urls[i];
+                                if (url.indexOf(".mp3", url.length - 4) !== -1 && Engine.audioEngine.isMP3supported) {
+                                    codecSupportedFound = true;
                                 }
                                 }
-                                if (this._readyToPlayCallback) {
-                                    this._readyToPlayCallback();
+                                if (url.indexOf(".ogg", url.length - 4) !== -1 && Engine.audioEngine.isOGGsupported) {
+                                    codecSupportedFound = true;
                                 }
                                 }
-                            });
-                            document.body.appendChild(this._htmlAudioElement);
-                        }
+                                if (url.indexOf(".wav", url.length - 4) !== -1) {
+                                    codecSupportedFound = true;
+                                }
+                                if (codecSupportedFound) {
+                                    // Loading sound using XHR2
+                                    if (!this._streaming) {
+                                        Tools.LoadFile(url, (data) => { this._soundLoaded(data); }, null, this._scene.database, true);
+                                    }
+                                    // Streaming sound using HTML5 Audio tag
+                                    else {
+                                        this._htmlAudioElement = new Audio(url);
+                                        this._htmlAudioElement.controls = false;
+                                        this._htmlAudioElement.loop = this.loop;
+                                        this._htmlAudioElement.crossOrigin = "anonymous";
+                                        this._htmlAudioElement.preload = "auto";
+                                        this._htmlAudioElement.addEventListener("canplaythrough", () => {
+                                            this._isReadyToPlay = true;
+                                            if (this.autoplay) {
+                                                this.play();
+                                            }
+                                            if (this._readyToPlayCallback) {
+                                                this._readyToPlayCallback();
+                                            }
+                                        });
+                                        document.body.appendChild(this._htmlAudioElement);
+                                    }
+                                    break;
+                                }
+                            }
+                            break;
+                        default:
+                            validParameter = false;
+                            break;
+                    }
+
+                    if (!validParameter) {
+                        Tools.Error("Parameter must be a URL to the sound, an Array of URLs (.mp3 & .ogg) or an ArrayBuffer of the sound.");
                     }
                     }
                     else {
                     else {
-                        if (urlOrArrayBuffer instanceof ArrayBuffer) {
-                            if ((<ArrayBuffer>urlOrArrayBuffer).byteLength > 0) {
-                                this._soundLoaded(urlOrArrayBuffer);
+                        if (!codecSupportedFound) {
+                            // Simulating a ready to play event to avoid breaking code path
+                            if (this._readyToPlayCallback) {
+                                window.setTimeout(() => {
+                                    this._readyToPlayCallback();
+                                }, 1000);
                             }
                             }
                         }
                         }
-                        else {
-                            Tools.Error("Parameter must be a URL to the sound or an ArrayBuffer of the sound.");
-                        }
                     }
                     }
                 }
                 }
             }
             }
@@ -191,7 +233,7 @@
                 this._isReadyToPlay = true;
                 this._isReadyToPlay = true;
                 if (this.autoplay) { this.play(); }
                 if (this.autoplay) { this.play(); }
                 if (this._readyToPlayCallback) { this._readyToPlayCallback(); }
                 if (this._readyToPlayCallback) { this._readyToPlayCallback(); }
-            }, () => { Tools.Error("Error while decoding audio data for: " + this.name); });
+            }, (err: any) => { Tools.Error("Error while decoding audio data for: " + this.name + " / Error: " + err); });
         }
         }
 
 
         public setAudioBuffer(audioBuffer: AudioBuffer): void {
         public setAudioBuffer(audioBuffer: AudioBuffer): void {

+ 4 - 4
src/Cameras/VR/babylon.vrDeviceOrientationCamera.js

@@ -22,12 +22,12 @@ var BABYLON;
     BABYLON.VRDeviceOrientationFreeCamera = VRDeviceOrientationFreeCamera;
     BABYLON.VRDeviceOrientationFreeCamera = VRDeviceOrientationFreeCamera;
     var VRDeviceOrientationArcRotateCamera = (function (_super) {
     var VRDeviceOrientationArcRotateCamera = (function (_super) {
         __extends(VRDeviceOrientationArcRotateCamera, _super);
         __extends(VRDeviceOrientationArcRotateCamera, _super);
-        function VRDeviceOrientationArcRotateCamera(name, alpha, beta, radius, target, scene, compensateDistortion) {
+        function VRDeviceOrientationArcRotateCamera(name, alpha, beta, radius, target, scene, compensateDistortion, vrCameraMetrics) {
             if (compensateDistortion === void 0) { compensateDistortion = true; }
             if (compensateDistortion === void 0) { compensateDistortion = true; }
+            if (vrCameraMetrics === void 0) { vrCameraMetrics = BABYLON.VRCameraMetrics.GetDefault(); }
             _super.call(this, name, alpha, beta, radius, target, scene);
             _super.call(this, name, alpha, beta, radius, target, scene);
-            var metrics = BABYLON.VRCameraMetrics.GetDefault();
-            metrics.compensateDistortion = compensateDistortion;
-            this.setCameraRigMode(BABYLON.Camera.RIG_MODE_VR, { vrCameraMetrics: metrics });
+            vrCameraMetrics.compensateDistortion = compensateDistortion;
+            this.setCameraRigMode(BABYLON.Camera.RIG_MODE_VR, { vrCameraMetrics: vrCameraMetrics });
             this.inputs.addVRDeviceOrientation();
             this.inputs.addVRDeviceOrientation();
         }
         }
         VRDeviceOrientationArcRotateCamera.prototype.getTypeName = function () {
         VRDeviceOrientationArcRotateCamera.prototype.getTypeName = function () {

+ 3 - 4
src/Cameras/VR/babylon.vrDeviceOrientationCamera.ts

@@ -16,12 +16,11 @@ module BABYLON {
 
 
     export class VRDeviceOrientationArcRotateCamera extends ArcRotateCamera {
     export class VRDeviceOrientationArcRotateCamera extends ArcRotateCamera {
 
 
-        constructor(name: string, alpha: number, beta: number, radius: number, target: Vector3, scene: Scene, compensateDistortion = true) {
+        constructor(name: string, alpha: number, beta: number, radius: number, target: Vector3, scene: Scene, compensateDistortion = true, vrCameraMetrics: VRCameraMetrics = VRCameraMetrics.GetDefault()) {
             super(name, alpha, beta, radius, target, scene);
             super(name, alpha, beta, radius, target, scene);
 
 
-            var metrics = VRCameraMetrics.GetDefault();
-            metrics.compensateDistortion = compensateDistortion;
-            this.setCameraRigMode(Camera.RIG_MODE_VR, { vrCameraMetrics: metrics });
+            vrCameraMetrics.compensateDistortion = compensateDistortion;
+            this.setCameraRigMode(Camera.RIG_MODE_VR, { vrCameraMetrics: vrCameraMetrics });
 
 
             this.inputs.addVRDeviceOrientation();
             this.inputs.addVRDeviceOrientation();
         }
         }

+ 6 - 1
src/Cameras/babylon.arcRotateCamera.js

@@ -407,7 +407,12 @@ var BABYLON;
                     up = up.clone();
                     up = up.clone();
                     up = up.negate();
                     up = up.negate();
                 }
                 }
-                BABYLON.Matrix.LookAtLHToRef(this.position, target, up, this._viewMatrix);
+                if (this.getScene().useRightHandedSystem) {
+                    BABYLON.Matrix.LookAtRHToRef(this.position, target, up, this._viewMatrix);
+                }
+                else {
+                    BABYLON.Matrix.LookAtLHToRef(this.position, target, up, this._viewMatrix);
+                }
                 this._viewMatrix.m[12] += this.targetScreenOffset.x;
                 this._viewMatrix.m[12] += this.targetScreenOffset.x;
                 this._viewMatrix.m[13] += this.targetScreenOffset.y;
                 this._viewMatrix.m[13] += this.targetScreenOffset.y;
             }
             }

+ 5 - 1
src/Cameras/babylon.arcRotateCamera.ts

@@ -431,7 +431,11 @@
                     up = up.negate();
                     up = up.negate();
                 }
                 }
 
 
-                Matrix.LookAtLHToRef(this.position, target, up, this._viewMatrix);
+                if (this.getScene().useRightHandedSystem) {
+                    Matrix.LookAtRHToRef(this.position, target, up, this._viewMatrix);
+                } else {
+                    Matrix.LookAtLHToRef(this.position, target, up, this._viewMatrix);
+                }
                 this._viewMatrix.m[12] += this.targetScreenOffset.x;
                 this._viewMatrix.m[12] += this.targetScreenOffset.x;
                 this._viewMatrix.m[13] += this.targetScreenOffset.y;
                 this._viewMatrix.m[13] += this.targetScreenOffset.y;
             }
             }

+ 13 - 2
src/Cameras/babylon.camera.js

@@ -348,16 +348,27 @@ var BABYLON;
             }
             }
             this._refreshFrustumPlanes = true;
             this._refreshFrustumPlanes = true;
             var engine = this.getEngine();
             var engine = this.getEngine();
+            var scene = this.getScene();
             if (this.mode === Camera.PERSPECTIVE_CAMERA) {
             if (this.mode === Camera.PERSPECTIVE_CAMERA) {
                 if (this.minZ <= 0) {
                 if (this.minZ <= 0) {
                     this.minZ = 0.1;
                     this.minZ = 0.1;
                 }
                 }
-                BABYLON.Matrix.PerspectiveFovLHToRef(this.fov, engine.getAspectRatio(this), this.minZ, this.maxZ, this._projectionMatrix, this.fovMode === Camera.FOVMODE_VERTICAL_FIXED);
+                if (scene.useRightHandedSystem) {
+                    BABYLON.Matrix.PerspectiveFovRHToRef(this.fov, engine.getAspectRatio(this), this.minZ, this.maxZ, this._projectionMatrix, this.fovMode === Camera.FOVMODE_VERTICAL_FIXED);
+                }
+                else {
+                    BABYLON.Matrix.PerspectiveFovLHToRef(this.fov, engine.getAspectRatio(this), this.minZ, this.maxZ, this._projectionMatrix, this.fovMode === Camera.FOVMODE_VERTICAL_FIXED);
+                }
                 return this._projectionMatrix;
                 return this._projectionMatrix;
             }
             }
             var halfWidth = engine.getRenderWidth() / 2.0;
             var halfWidth = engine.getRenderWidth() / 2.0;
             var halfHeight = engine.getRenderHeight() / 2.0;
             var halfHeight = engine.getRenderHeight() / 2.0;
-            BABYLON.Matrix.OrthoOffCenterLHToRef(this.orthoLeft || -halfWidth, this.orthoRight || halfWidth, this.orthoBottom || -halfHeight, this.orthoTop || halfHeight, this.minZ, this.maxZ, this._projectionMatrix);
+            if (scene.useRightHandedSystem) {
+                BABYLON.Matrix.OrthoOffCenterRHToRef(this.orthoLeft || -halfWidth, this.orthoRight || halfWidth, this.orthoBottom || -halfHeight, this.orthoTop || halfHeight, this.minZ, this.maxZ, this._projectionMatrix);
+            }
+            else {
+                BABYLON.Matrix.OrthoOffCenterLHToRef(this.orthoLeft || -halfWidth, this.orthoRight || halfWidth, this.orthoBottom || -halfHeight, this.orthoTop || halfHeight, this.minZ, this.maxZ, this._projectionMatrix);
+            }
             return this._projectionMatrix;
             return this._projectionMatrix;
         };
         };
         Camera.prototype.getTranformationMatrix = function () {
         Camera.prototype.getTranformationMatrix = function () {

+ 33 - 2
src/Cameras/babylon.camera.ts

@@ -417,18 +417,49 @@
             this._refreshFrustumPlanes = true;
             this._refreshFrustumPlanes = true;
 
 
             var engine = this.getEngine();
             var engine = this.getEngine();
+            var scene = this.getScene();
             if (this.mode === Camera.PERSPECTIVE_CAMERA) {
             if (this.mode === Camera.PERSPECTIVE_CAMERA) {
                 if (this.minZ <= 0) {
                 if (this.minZ <= 0) {
                     this.minZ = 0.1;
                     this.minZ = 0.1;
                 }
                 }
 
 
-                Matrix.PerspectiveFovLHToRef(this.fov, engine.getAspectRatio(this), this.minZ, this.maxZ, this._projectionMatrix, this.fovMode === Camera.FOVMODE_VERTICAL_FIXED);
+                if (scene.useRightHandedSystem) {
+                    Matrix.PerspectiveFovRHToRef(this.fov,
+                        engine.getAspectRatio(this),
+                        this.minZ,
+                        this.maxZ,
+                        this._projectionMatrix,
+                        this.fovMode === Camera.FOVMODE_VERTICAL_FIXED);
+                } else {
+                    Matrix.PerspectiveFovLHToRef(this.fov,
+                        engine.getAspectRatio(this),
+                        this.minZ,
+                        this.maxZ,
+                        this._projectionMatrix,
+                        this.fovMode === Camera.FOVMODE_VERTICAL_FIXED);
+                }
                 return this._projectionMatrix;
                 return this._projectionMatrix;
             }
             }
 
 
             var halfWidth = engine.getRenderWidth() / 2.0;
             var halfWidth = engine.getRenderWidth() / 2.0;
             var halfHeight = engine.getRenderHeight() / 2.0;
             var halfHeight = engine.getRenderHeight() / 2.0;
-            Matrix.OrthoOffCenterLHToRef(this.orthoLeft || -halfWidth, this.orthoRight || halfWidth, this.orthoBottom || -halfHeight, this.orthoTop || halfHeight, this.minZ, this.maxZ, this._projectionMatrix);
+            if (scene.useRightHandedSystem) {
+                Matrix.OrthoOffCenterRHToRef(this.orthoLeft || -halfWidth,
+                    this.orthoRight || halfWidth,
+                    this.orthoBottom || -halfHeight,
+                    this.orthoTop || halfHeight,
+                    this.minZ,
+                    this.maxZ,
+                    this._projectionMatrix);
+            } else {
+                Matrix.OrthoOffCenterLHToRef(this.orthoLeft || -halfWidth,
+                    this.orthoRight || halfWidth,
+                    this.orthoBottom || -halfHeight,
+                    this.orthoTop || halfHeight,
+                    this.minZ,
+                    this.maxZ,
+                    this._projectionMatrix);
+            }
             return this._projectionMatrix;
             return this._projectionMatrix;
         }
         }
 
 

+ 14 - 3
src/Cameras/babylon.targetCamera.js

@@ -185,7 +185,12 @@ var BABYLON;
             else {
             else {
                 this._currentTarget.copyFrom(this._getLockedTargetPosition());
                 this._currentTarget.copyFrom(this._getLockedTargetPosition());
             }
             }
-            BABYLON.Matrix.LookAtLHToRef(this.position, this._currentTarget, this.upVector, this._viewMatrix);
+            if (this.getScene().useRightHandedSystem) {
+                BABYLON.Matrix.LookAtRHToRef(this.position, this._currentTarget, this.upVector, this._viewMatrix);
+            }
+            else {
+                BABYLON.Matrix.LookAtLHToRef(this.position, this._currentTarget, this.upVector, this._viewMatrix);
+            }
             return this._viewMatrix;
             return this._viewMatrix;
         };
         };
         /**
         /**
@@ -228,8 +233,14 @@ var BABYLON;
                     break;
                     break;
                 case BABYLON.Camera.RIG_MODE_VR:
                 case BABYLON.Camera.RIG_MODE_VR:
                 case BABYLON.Camera.RIG_MODE_WEBVR:
                 case BABYLON.Camera.RIG_MODE_WEBVR:
-                    camLeft.rotationQuaternion.copyFrom(this.rotationQuaternion);
-                    camRight.rotationQuaternion.copyFrom(this.rotationQuaternion);
+                    if (camLeft.rotationQuaternion) {
+                        camLeft.rotationQuaternion.copyFrom(this.rotationQuaternion);
+                        camRight.rotationQuaternion.copyFrom(this.rotationQuaternion);
+                    }
+                    else {
+                        camLeft.rotation.copyFrom(this.rotation);
+                        camRight.rotation.copyFrom(this.rotation);
+                    }
                     camLeft.position.copyFrom(this.position);
                     camLeft.position.copyFrom(this.position);
                     camRight.position.copyFrom(this.position);
                     camRight.position.copyFrom(this.position);
                     break;
                     break;

+ 13 - 3
src/Cameras/babylon.targetCamera.ts

@@ -227,7 +227,12 @@
                 this._currentTarget.copyFrom(this._getLockedTargetPosition());
                 this._currentTarget.copyFrom(this._getLockedTargetPosition());
             }
             }
 
 
-            Matrix.LookAtLHToRef(this.position, this._currentTarget, this.upVector, this._viewMatrix);
+            if (this.getScene().useRightHandedSystem) {
+                Matrix.LookAtRHToRef(this.position, this._currentTarget, this.upVector, this._viewMatrix);
+            } else {
+                Matrix.LookAtLHToRef(this.position, this._currentTarget, this.upVector, this._viewMatrix);
+            }
+            
             return this._viewMatrix;
             return this._viewMatrix;
         }
         }
 
 
@@ -275,8 +280,13 @@
 
 
                 case Camera.RIG_MODE_VR:
                 case Camera.RIG_MODE_VR:
                 case Camera.RIG_MODE_WEBVR:
                 case Camera.RIG_MODE_WEBVR:
-                    camLeft.rotationQuaternion.copyFrom(this.rotationQuaternion);
-                    camRight.rotationQuaternion.copyFrom(this.rotationQuaternion);
+                    if (camLeft.rotationQuaternion) {
+                        camLeft.rotationQuaternion.copyFrom(this.rotationQuaternion);
+                        camRight.rotationQuaternion.copyFrom(this.rotationQuaternion);
+                    } else {
+                        camLeft.rotation.copyFrom(this.rotation);
+                        camRight.rotation.copyFrom(this.rotation);
+                    }
                     camLeft.position.copyFrom(this.position);
                     camLeft.position.copyFrom(this.position);
                     camRight.position.copyFrom(this.position);
                     camRight.position.copyFrom(this.position);
 
 

+ 22 - 3
src/Canvas2d/babylon.canvas2d.js

@@ -120,6 +120,10 @@ var BABYLON;
                         this.backgroundFill = settings.backgroundFill;
                         this.backgroundFill = settings.backgroundFill;
                     }
                     }
                 }
                 }
+                // Put a handler to resize the background whenever the canvas is resizing
+                this.propertyChanged.add(function (e, s) {
+                    _this._background.size = _this.size;
+                }, BABYLON.Group2D.sizeProperty.flagId);
                 this._background._patchHierarchy(this);
                 this._background._patchHierarchy(this);
             }
             }
             var engine = scene.getEngine();
             var engine = scene.getEngine();
@@ -859,6 +863,20 @@ var BABYLON;
             enumerable: true,
             enumerable: true,
             configurable: true
             configurable: true
         });
         });
+        Object.defineProperty(Canvas2D.prototype, "designSize", {
+            get: function () {
+                return this._designSize;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Canvas2D.prototype, "designSizeUseHorizAxis", {
+            get: function () {
+                return this._designUseHorizAxis;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(Canvas2D.prototype, "_engineData", {
         Object.defineProperty(Canvas2D.prototype, "_engineData", {
             /**
             /**
              * Access the babylon.js' engine bound data, do not invoke this method, it's for internal purpose only
              * Access the babylon.js' engine bound data, do not invoke this method, it's for internal purpose only
@@ -990,8 +1008,9 @@ var BABYLON;
                 var node = group.trackedNode;
                 var node = group.trackedNode;
                 var worldMtx = node.getWorldMatrix();
                 var worldMtx = node.getWorldMatrix();
                 var proj = BABYLON.Vector3.Project(Canvas2D._v, worldMtx, Canvas2D._m, v);
                 var proj = BABYLON.Vector3.Project(Canvas2D._v, worldMtx, Canvas2D._m, v);
-                group.x = Math.round(proj.x);
-                group.y = Math.round(rh - proj.y);
+                var s = this.scale;
+                group.x = Math.round(proj.x / s);
+                group.y = Math.round((rh - proj.y) / s);
             }
             }
         };
         };
         /**
         /**
@@ -1086,8 +1105,8 @@ var BABYLON;
          */
          */
         Canvas2D.prototype._render = function () {
         Canvas2D.prototype._render = function () {
             this._initPerfMetrics();
             this._initPerfMetrics();
-            this._updateTrackedNodes();
             this._updateCanvasState(false);
             this._updateCanvasState(false);
+            this._updateTrackedNodes();
             // Nothing to do is the Canvas is not visible
             // Nothing to do is the Canvas is not visible
             if (this.isVisible === false) {
             if (this.isVisible === false) {
                 return;
                 return;

+ 18 - 4
src/Canvas2d/babylon.canvas2d.ts

@@ -125,6 +125,11 @@
                     }
                     }
                 }
                 }
 
 
+                // Put a handler to resize the background whenever the canvas is resizing
+                this.propertyChanged.add((e, s) => {
+                    this._background.size = this.size;
+                }, Group2D.sizeProperty.flagId);
+
                 this._background._patchHierarchy(this);
                 this._background._patchHierarchy(this);
             }
             }
 
 
@@ -950,6 +955,14 @@
             this._setupInteraction(enable);
             this._setupInteraction(enable);
         }
         }
 
 
+        public get designSize(): Size {
+            return this._designSize;
+        }
+
+        public get designSizeUseHorizAxis(): boolean {
+            return this._designUseHorizAxis;
+        }
+
         /**
         /**
          * Access the babylon.js' engine bound data, do not invoke this method, it's for internal purpose only
          * Access the babylon.js' engine bound data, do not invoke this method, it's for internal purpose only
          * @returns {} 
          * @returns {} 
@@ -1159,8 +1172,9 @@
                 let worldMtx = node.getWorldMatrix();
                 let worldMtx = node.getWorldMatrix();
 
 
                 let proj = Vector3.Project(Canvas2D._v, worldMtx, Canvas2D._m, v);
                 let proj = Vector3.Project(Canvas2D._v, worldMtx, Canvas2D._m, v);
-                group.x = Math.round(proj.x);
-                group.y = Math.round(rh - proj.y);
+                let s = this.scale;
+                group.x = Math.round(proj.x/s);
+                group.y = Math.round((rh - proj.y)/s);
             }
             }
         }
         }
 
 
@@ -1278,10 +1292,10 @@
 
 
             this._initPerfMetrics();
             this._initPerfMetrics();
 
 
-            this._updateTrackedNodes();
-
             this._updateCanvasState(false);
             this._updateCanvasState(false);
 
 
+            this._updateTrackedNodes();
+
             // Nothing to do is the Canvas is not visible
             // Nothing to do is the Canvas is not visible
             if (this.isVisible === false) {
             if (this.isVisible === false) {
                 return;
                 return;

+ 9 - 0
src/Canvas2d/babylon.group2d.js

@@ -299,6 +299,15 @@ var BABYLON;
             var a = this.actualScale;
             var a = this.actualScale;
             var sw = Math.ceil(s.width * a.x);
             var sw = Math.ceil(s.width * a.x);
             var sh = Math.ceil(s.height * a.y);
             var sh = Math.ceil(s.height * a.y);
+            // The dimension must be overridden when using the designSize feature, the ratio is maintain to compute a uniform scale, which is mandatory but if the designSize's ratio is different from the rendering surface's ratio, content will be clipped in some cases.
+            // So we set the width/height to the rendering's one because that's what we want for the viewport!
+            if (this instanceof BABYLON.Canvas2D) {
+                var c = this;
+                if (c.designSize != null) {
+                    sw = this.owner.engine.getRenderWidth();
+                    sh = this.owner.engine.getRenderHeight();
+                }
+            }
             // Setup the size of the rendering viewport
             // Setup the size of the rendering viewport
             // In non cache mode, we're rendering directly to the rendering canvas, in this case we have to detect if the canvas size changed since the previous iteration, if it's the case all primitives must be prepared again because their transformation must be recompute
             // In non cache mode, we're rendering directly to the rendering canvas, in this case we have to detect if the canvas size changed since the previous iteration, if it's the case all primitives must be prepared again because their transformation must be recompute
             if (!this._isCachedGroup) {
             if (!this._isCachedGroup) {

+ 10 - 0
src/Canvas2d/babylon.group2d.ts

@@ -361,6 +361,16 @@
             let sw = Math.ceil(s.width * a.x);
             let sw = Math.ceil(s.width * a.x);
             let sh = Math.ceil(s.height * a.y);
             let sh = Math.ceil(s.height * a.y);
 
 
+            // The dimension must be overridden when using the designSize feature, the ratio is maintain to compute a uniform scale, which is mandatory but if the designSize's ratio is different from the rendering surface's ratio, content will be clipped in some cases.
+            // So we set the width/height to the rendering's one because that's what we want for the viewport!
+            if (this instanceof Canvas2D) {
+                let c = <Canvas2D><any>this;
+                if (c.designSize != null) {
+                    sw = this.owner.engine.getRenderWidth();
+                    sh = this.owner.engine.getRenderHeight();
+                }
+            }
+
             // Setup the size of the rendering viewport
             // Setup the size of the rendering viewport
             // In non cache mode, we're rendering directly to the rendering canvas, in this case we have to detect if the canvas size changed since the previous iteration, if it's the case all primitives must be prepared again because their transformation must be recompute
             // In non cache mode, we're rendering directly to the rendering canvas, in this case we have to detect if the canvas size changed since the previous iteration, if it's the case all primitives must be prepared again because their transformation must be recompute
             if (!this._isCachedGroup) {
             if (!this._isCachedGroup) {

+ 9 - 7
src/Canvas2d/babylon.prim2dBase.js

@@ -1494,7 +1494,7 @@ var BABYLON;
                     return;
                     return;
                 }
                 }
                 this._position = value;
                 this._position = value;
-                this.markAsDirty("actualPosition");
+                this._triggerPropertyChanged(Prim2DBase.actualPositionProperty, value);
             },
             },
             enumerable: true,
             enumerable: true,
             configurable: true
             configurable: true
@@ -1521,8 +1521,8 @@ var BABYLON;
                     return;
                     return;
                 }
                 }
                 this._position.x = value;
                 this._position.x = value;
-                this.markAsDirty("position");
-                this.markAsDirty("actualPosition");
+                this._triggerPropertyChanged(Prim2DBase.positionProperty, value);
+                this._triggerPropertyChanged(Prim2DBase.actualPositionProperty, value);
             },
             },
             enumerable: true,
             enumerable: true,
             configurable: true
             configurable: true
@@ -1549,8 +1549,8 @@ var BABYLON;
                     return;
                     return;
                 }
                 }
                 this._position.y = value;
                 this._position.y = value;
-                this.markAsDirty("position");
-                this.markAsDirty("actualPosition");
+                this._triggerPropertyChanged(Prim2DBase.positionProperty, value);
+                this._triggerPropertyChanged(Prim2DBase.actualPositionProperty, value);
             },
             },
             enumerable: true,
             enumerable: true,
             configurable: true
             configurable: true
@@ -1602,7 +1602,7 @@ var BABYLON;
                     return;
                     return;
                 }
                 }
                 this.size.width = value;
                 this.size.width = value;
-                this.markAsDirty("size");
+                this._triggerPropertyChanged(Prim2DBase.sizeProperty, value);
                 this._positioningDirty();
                 this._positioningDirty();
             },
             },
             enumerable: true,
             enumerable: true,
@@ -1628,7 +1628,7 @@ var BABYLON;
                     return;
                     return;
                 }
                 }
                 this.size.height = value;
                 this.size.height = value;
-                this.markAsDirty("size");
+                this._triggerPropertyChanged(Prim2DBase.sizeProperty, value);
                 this._positioningDirty();
                 this._positioningDirty();
             },
             },
             enumerable: true,
             enumerable: true,
@@ -2501,6 +2501,8 @@ var BABYLON;
             for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
             for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
                 var child = _a[_i];
                 var child = _a[_i];
                 child._setFlags(BABYLON.SmartPropertyPrim.flagActualOpacityDirty);
                 child._setFlags(BABYLON.SmartPropertyPrim.flagActualOpacityDirty);
+                child._updateRenderMode();
+                child.onPrimBecomesDirty();
                 child._spreadActualOpacityChanged();
                 child._spreadActualOpacityChanged();
             }
             }
         };
         };

+ 9 - 7
src/Canvas2d/babylon.prim2dBase.ts

@@ -1725,7 +1725,7 @@
                 return;
                 return;
             }
             }
             this._position = value;
             this._position = value;
-            this.markAsDirty("actualPosition");
+            this._triggerPropertyChanged(Prim2DBase.actualPositionProperty, value);
         }
         }
 
 
         /**
         /**
@@ -1752,8 +1752,8 @@
             }
             }
 
 
             this._position.x = value;
             this._position.x = value;
-            this.markAsDirty("position");
-            this.markAsDirty("actualPosition");
+            this._triggerPropertyChanged(Prim2DBase.positionProperty, value);
+            this._triggerPropertyChanged(Prim2DBase.actualPositionProperty, value);
         }
         }
 
 
         /**
         /**
@@ -1780,8 +1780,8 @@
             }
             }
 
 
             this._position.y = value;
             this._position.y = value;
-            this.markAsDirty("position");
-            this.markAsDirty("actualPosition");
+            this._triggerPropertyChanged(Prim2DBase.positionProperty, value);
+            this._triggerPropertyChanged(Prim2DBase.actualPositionProperty, value);
         }
         }
 
 
         private static boundinbBoxReentrency = false;
         private static boundinbBoxReentrency = false;
@@ -1842,7 +1842,7 @@
             }
             }
 
 
             this.size.width = value;
             this.size.width = value;
-            this.markAsDirty("size");
+            this._triggerPropertyChanged(Prim2DBase.sizeProperty, value);
             this._positioningDirty();
             this._positioningDirty();
         }
         }
 
 
@@ -1868,7 +1868,7 @@
             }
             }
 
 
             this.size.height = value;
             this.size.height = value;
-            this.markAsDirty("size");
+            this._triggerPropertyChanged(Prim2DBase.sizeProperty, value);
             this._positioningDirty();
             this._positioningDirty();
         }
         }
 
 
@@ -2748,6 +2748,8 @@
         protected _spreadActualOpacityChanged() {
         protected _spreadActualOpacityChanged() {
             for (let child of this._children) {
             for (let child of this._children) {
                 child._setFlags(SmartPropertyPrim.flagActualOpacityDirty);
                 child._setFlags(SmartPropertyPrim.flagActualOpacityDirty);
+                child._updateRenderMode();
+                child.onPrimBecomesDirty();
                 child._spreadActualOpacityChanged();
                 child._spreadActualOpacityChanged();
             }
             }
         }
         }

+ 4 - 1
src/Canvas2d/babylon.renderablePrim2d.js

@@ -339,7 +339,7 @@ var BABYLON;
         });
         });
         Object.defineProperty(RenderablePrim2D.prototype, "isTransparent", {
         Object.defineProperty(RenderablePrim2D.prototype, "isTransparent", {
             get: function () {
             get: function () {
-                return (this._opacity < 1) || this._shouldUseAlphaFromTexture() || this._isPrimTransparent();
+                return (this.actualOpacity < 1) || this._shouldUseAlphaFromTexture() || this._isPrimTransparent();
             },
             },
             enumerable: true,
             enumerable: true,
             configurable: true
             configurable: true
@@ -392,14 +392,17 @@ var BABYLON;
                 if (gii.hasOpaqueData) {
                 if (gii.hasOpaqueData) {
                     var od = gii.opaqueData[0];
                     var od = gii.opaqueData[0];
                     usedCount += od._partData.usedElementCount;
                     usedCount += od._partData.usedElementCount;
+                    gii.opaqueDirty = true;
                 }
                 }
                 if (gii.hasAlphaTestData) {
                 if (gii.hasAlphaTestData) {
                     var atd = gii.alphaTestData[0];
                     var atd = gii.alphaTestData[0];
                     usedCount += atd._partData.usedElementCount;
                     usedCount += atd._partData.usedElementCount;
+                    gii.alphaTestDirty = true;
                 }
                 }
                 if (gii.hasTransparentData) {
                 if (gii.hasTransparentData) {
                     var td = gii.transparentData[0];
                     var td = gii.transparentData[0];
                     usedCount += td._partData.usedElementCount;
                     usedCount += td._partData.usedElementCount;
+                    gii.transparentDirty = true;
                 }
                 }
                 if (usedCount === 0 && gii.modelRenderCache != null) {
                 if (usedCount === 0 && gii.modelRenderCache != null) {
                     this.renderGroup._renderableData._renderGroupInstancesInfo.remove(gii.modelRenderCache.modelKey);
                     this.renderGroup._renderableData._renderGroupInstancesInfo.remove(gii.modelRenderCache.modelKey);

+ 4 - 1
src/Canvas2d/babylon.renderablePrim2d.ts

@@ -359,7 +359,7 @@
          * The setter should be used only by implementers of new primitive type.
          * The setter should be used only by implementers of new primitive type.
          */
          */
         public get isTransparent(): boolean {
         public get isTransparent(): boolean {
-            return (this._opacity<1) || this._shouldUseAlphaFromTexture() || this._isPrimTransparent();
+            return (this.actualOpacity<1) || this._shouldUseAlphaFromTexture() || this._isPrimTransparent();
         }
         }
 
 
         public get renderMode(): number {
         public get renderMode(): number {
@@ -424,14 +424,17 @@
                 if (gii.hasOpaqueData) {
                 if (gii.hasOpaqueData) {
                     let od = gii.opaqueData[0];
                     let od = gii.opaqueData[0];
                     usedCount += od._partData.usedElementCount;
                     usedCount += od._partData.usedElementCount;
+                    gii.opaqueDirty = true;
                 }
                 }
                 if (gii.hasAlphaTestData) {
                 if (gii.hasAlphaTestData) {
                     let atd = gii.alphaTestData[0];
                     let atd = gii.alphaTestData[0];
                     usedCount += atd._partData.usedElementCount;
                     usedCount += atd._partData.usedElementCount;
+                    gii.alphaTestDirty = true;
                 }
                 }
                 if (gii.hasTransparentData) {
                 if (gii.hasTransparentData) {
                     let td = gii.transparentData[0];
                     let td = gii.transparentData[0];
                     usedCount += td._partData.usedElementCount;
                     usedCount += td._partData.usedElementCount;
+                    gii.transparentDirty = true;
                 }
                 }
 
 
                 if (usedCount === 0 && gii.modelRenderCache!=null) {
                 if (usedCount === 0 && gii.modelRenderCache!=null) {

+ 2 - 8
src/Canvas2d/babylon.smartPropertyPrim.js

@@ -277,20 +277,14 @@ var BABYLON;
             }
             }
             return false;
             return false;
         };
         };
-        SmartPropertyPrim.prototype.markAsDirty = function (propertyName) {
+        SmartPropertyPrim.prototype._triggerPropertyChanged = function (propInfo, newValue) {
             if (this.isDisposed) {
             if (this.isDisposed) {
                 return;
                 return;
             }
             }
-            var i = propertyName.indexOf(".");
-            if (i !== -1) {
-                propertyName = propertyName.substr(0, i);
-            }
-            var propInfo = this.propDic.get(propertyName);
             if (!propInfo) {
             if (!propInfo) {
                 return;
                 return;
             }
             }
-            var newValue = this[propertyName];
-            this._handlePropChanged(undefined, newValue, propertyName, propInfo, propInfo.typeLevelCompare);
+            this._handlePropChanged(undefined, newValue, propInfo.name, propInfo, propInfo.typeLevelCompare);
         };
         };
         SmartPropertyPrim.prototype._boundingBoxDirty = function () {
         SmartPropertyPrim.prototype._boundingBoxDirty = function () {
             this._setFlags(SmartPropertyPrim.flagLevelBoundingInfoDirty);
             this._setFlags(SmartPropertyPrim.flagLevelBoundingInfoDirty);

+ 3 - 11
src/Canvas2d/babylon.smartPropertyPrim.ts

@@ -316,25 +316,16 @@
             return false;
             return false;
         }
         }
 
 
-        private static propChangedInfo = new PropertyChangedInfo();
-
-        public markAsDirty(propertyName: string) {
+        protected _triggerPropertyChanged(propInfo: Prim2DPropInfo, newValue: any) {
             if (this.isDisposed) {
             if (this.isDisposed) {
                 return;
                 return;
             }
             }
 
 
-            let i = propertyName.indexOf(".");
-            if (i !== -1) {
-                propertyName = propertyName.substr(0, i);
-            }
-
-            var propInfo = this.propDic.get(propertyName);
             if (!propInfo) {
             if (!propInfo) {
                 return;
                 return;
             }
             }
 
 
-            var newValue = this[propertyName];
-            this._handlePropChanged(undefined, newValue, propertyName, propInfo, propInfo.typeLevelCompare);
+            this._handlePropChanged(undefined, newValue, propInfo.name, propInfo, propInfo.typeLevelCompare);
         }
         }
 
 
         protected _boundingBoxDirty() {
         protected _boundingBoxDirty() {
@@ -361,6 +352,7 @@
             }
             }
         }
         }
 
 
+        private static propChangedInfo = new PropertyChangedInfo();
         private _handlePropChanged<T>(curValue: T, newValue: T, propName: string, propInfo: Prim2DPropInfo, typeLevelCompare: boolean) {
         private _handlePropChanged<T>(curValue: T, newValue: T, propName: string, propInfo: Prim2DPropInfo, typeLevelCompare: boolean) {
             // If the property change also dirty the boundingInfo, update the boundingInfo dirty flags
             // If the property change also dirty the boundingInfo, update the boundingInfo dirty flags
             if (propInfo.dirtyBoundingInfo) {
             if (propInfo.dirtyBoundingInfo) {

+ 45 - 0
src/Lights/babylon.light.js

@@ -23,12 +23,50 @@ var BABYLON;
             this.includedOnlyMeshes = new Array();
             this.includedOnlyMeshes = new Array();
             this.excludedMeshes = new Array();
             this.excludedMeshes = new Array();
             this.excludeWithLayerMask = 0;
             this.excludeWithLayerMask = 0;
+            this.lightmapMode = 0;
             // PBR Properties.
             // PBR Properties.
             this.radius = 0.00001;
             this.radius = 0.00001;
             this._excludedMeshesIds = new Array();
             this._excludedMeshesIds = new Array();
             this._includedOnlyMeshesIds = new Array();
             this._includedOnlyMeshesIds = new Array();
             scene.addLight(this);
             scene.addLight(this);
         }
         }
+        Object.defineProperty(Light, "LIGHTMAP_DEFAULT", {
+            /**
+             * If every light affecting the material is in this lightmapMode,
+             * material.lightmapTexture adds or multiplies
+             * (depends on material.useLightmapAsShadowmap)
+             * after every other light calculations.
+             */
+            get: function () {
+                return Light._LIGHTMAP_DEFAULT;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Light, "LIGHTMAP_SPECULAR", {
+            /**
+             * material.lightmapTexture as only diffuse lighting from this light
+             * adds pnly specular lighting from this light
+             * adds dynamic shadows
+             */
+            get: function () {
+                return Light._LIGHTMAP_SPECULAR;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Light, "LIGHTMAP_SHADOWSONLY", {
+            /**
+             * material.lightmapTexture as only lighting
+             * no light calculation from this light
+             * only adds dynamic shadows from this light
+             */
+            get: function () {
+                return Light._LIGHTMAP_SHADOWSONLY;
+            },
+            enumerable: true,
+            configurable: true
+        });
         /**
         /**
          * @param {boolean} fullDetails - support for multiple levels of logging within scene loading
          * @param {boolean} fullDetails - support for multiple levels of logging within scene loading
          */
          */
@@ -167,6 +205,10 @@ var BABYLON;
             }
             }
             return light;
             return light;
         };
         };
+        //lightmapMode Consts
+        Light._LIGHTMAP_DEFAULT = 0;
+        Light._LIGHTMAP_SPECULAR = 1;
+        Light._LIGHTMAP_SHADOWSONLY = 2;
         __decorate([
         __decorate([
             BABYLON.serializeAsColor3()
             BABYLON.serializeAsColor3()
         ], Light.prototype, "diffuse", void 0);
         ], Light.prototype, "diffuse", void 0);
@@ -187,6 +229,9 @@ var BABYLON;
         ], Light.prototype, "excludeWithLayerMask", void 0);
         ], Light.prototype, "excludeWithLayerMask", void 0);
         __decorate([
         __decorate([
             BABYLON.serialize()
             BABYLON.serialize()
+        ], Light.prototype, "lightmapMode", void 0);
+        __decorate([
+            BABYLON.serialize()
         ], Light.prototype, "radius", void 0);
         ], Light.prototype, "radius", void 0);
         return Light;
         return Light;
     })(BABYLON.Node);
     })(BABYLON.Node);

+ 37 - 0
src/Lights/babylon.light.ts

@@ -21,6 +21,40 @@
     }
     }
 
 
     export class Light extends Node {
     export class Light extends Node {
+
+        //lightmapMode Consts
+        private static _LIGHTMAP_DEFAULT = 0;
+        private static _LIGHTMAP_SPECULAR = 1;
+        private static _LIGHTMAP_SHADOWSONLY = 2;
+
+        /**
+         * If every light affecting the material is in this lightmapMode,
+         * material.lightmapTexture adds or multiplies
+         * (depends on material.useLightmapAsShadowmap)
+         * after every other light calculations.
+         */
+        public static get LIGHTMAP_DEFAULT(): number {
+            return Light._LIGHTMAP_DEFAULT;
+        }
+
+        /**
+         * material.lightmapTexture as only diffuse lighting from this light
+         * adds pnly specular lighting from this light
+         * adds dynamic shadows
+         */
+        public static get LIGHTMAP_SPECULAR(): number {
+            return Light._LIGHTMAP_SPECULAR;
+        }
+
+        /**
+         * material.lightmapTexture as only lighting
+         * no light calculation from this light
+         * only adds dynamic shadows from this light
+         */
+        public static get LIGHTMAP_SHADOWSONLY(): number {
+            return Light._LIGHTMAP_SHADOWSONLY;
+        }
+
         @serializeAsColor3()
         @serializeAsColor3()
         public diffuse = new Color3(1.0, 1.0, 1.0);
         public diffuse = new Color3(1.0, 1.0, 1.0);
 
 
@@ -42,6 +76,9 @@
         @serialize()
         @serialize()
         public excludeWithLayerMask = 0;
         public excludeWithLayerMask = 0;
 
 
+        @serialize()
+        public lightmapMode = 0;
+
         // PBR Properties.
         // PBR Properties.
         @serialize()
         @serialize()
         public radius = 0.00001;
         public radius = 0.00001;

+ 8 - 2
src/Materials/babylon.material.js

@@ -71,7 +71,6 @@ var BABYLON;
             this.state = "";
             this.state = "";
             this.alpha = 1.0;
             this.alpha = 1.0;
             this.backFaceCulling = true;
             this.backFaceCulling = true;
-            this.sideOrientation = Material.CounterClockWiseSideOrientation;
             /**
             /**
             * An event triggered when the material is disposed.
             * An event triggered when the material is disposed.
             * @type {BABYLON.Observable}
             * @type {BABYLON.Observable}
@@ -96,6 +95,12 @@ var BABYLON;
             this._fillMode = Material.TriangleFillMode;
             this._fillMode = Material.TriangleFillMode;
             this.id = name;
             this.id = name;
             this._scene = scene;
             this._scene = scene;
+            if (scene.useRightHandedSystem) {
+                this.sideOrientation = Material.ClockWiseSideOrientation;
+            }
+            else {
+                this.sideOrientation = Material.CounterClockWiseSideOrientation;
+            }
             if (!doNotAdd) {
             if (!doNotAdd) {
                 scene.materials.push(this);
                 scene.materials.push(this);
             }
             }
@@ -231,8 +236,9 @@ var BABYLON;
         };
         };
         Material.prototype._preBind = function () {
         Material.prototype._preBind = function () {
             var engine = this._scene.getEngine();
             var engine = this._scene.getEngine();
+            var reverse = this.sideOrientation === Material.ClockWiseSideOrientation;
             engine.enableEffect(this._effect);
             engine.enableEffect(this._effect);
-            engine.setState(this.backFaceCulling, this.zOffset, false, this.sideOrientation === Material.ClockWiseSideOrientation);
+            engine.setState(this.backFaceCulling, this.zOffset, false, reverse);
         };
         };
         Material.prototype.bind = function (world, mesh) {
         Material.prototype.bind = function (world, mesh) {
             this._scene._cachedMaterial = this;
             this._scene._cachedMaterial = this;

+ 9 - 2
src/Materials/babylon.material.ts

@@ -114,7 +114,7 @@
         public backFaceCulling = true;
         public backFaceCulling = true;
 
 
         @serialize()
         @serialize()
-        public sideOrientation = Material.CounterClockWiseSideOrientation;
+        public sideOrientation: number;
 
 
         public onCompiled: (effect: Effect) => void;
         public onCompiled: (effect: Effect) => void;
         public onError: (effect: Effect, errors: string) => void;
         public onError: (effect: Effect, errors: string) => void;
@@ -209,6 +209,12 @@
 
 
             this._scene = scene;
             this._scene = scene;
 
 
+            if (scene.useRightHandedSystem) {
+                this.sideOrientation = Material.ClockWiseSideOrientation;
+            } else {
+                this.sideOrientation = Material.CounterClockWiseSideOrientation;
+            }
+
             if (!doNotAdd) {
             if (!doNotAdd) {
                 scene.materials.push(this);
                 scene.materials.push(this);
             }
             }
@@ -267,9 +273,10 @@
 
 
         public _preBind(): void {
         public _preBind(): void {
             var engine = this._scene.getEngine();
             var engine = this._scene.getEngine();
+            var reverse = this.sideOrientation === Material.ClockWiseSideOrientation;
 
 
             engine.enableEffect(this._effect);
             engine.enableEffect(this._effect);
-            engine.setState(this.backFaceCulling, this.zOffset, false, this.sideOrientation === Material.ClockWiseSideOrientation);
+            engine.setState(this.backFaceCulling, this.zOffset, false, reverse);
         }
         }
 
 
         public bind(world: Matrix, mesh?: Mesh): void {
         public bind(world: Matrix, mesh?: Mesh): void {

+ 20 - 0
src/Materials/babylon.materialHelper.js

@@ -9,6 +9,7 @@ var BABYLON;
             var needNormals = false;
             var needNormals = false;
             var needRebuild = false;
             var needRebuild = false;
             var needShadows = false;
             var needShadows = false;
+            var lightmapMode = false;
             for (var index = 0; index < scene.lights.length; index++) {
             for (var index = 0; index < scene.lights.length; index++) {
                 var light = scene.lights[index];
                 var light = scene.lights[index];
                 if (!light.isEnabled()) {
                 if (!light.isEnabled()) {
@@ -87,6 +88,19 @@ var BABYLON;
                         needShadows = true;
                         needShadows = true;
                     }
                     }
                 }
                 }
+                if (light.lightmapMode != BABYLON.Light.LIGHTMAP_DEFAULT) {
+                    lightmapMode = true;
+                    if (defines["LIGHTMAPEXCLUDED" + lightIndex] === undefined) {
+                        needRebuild = true;
+                    }
+                    if (defines["LIGHTMAPNOSPECULAR" + lightIndex] === undefined) {
+                        needRebuild = true;
+                    }
+                    defines["LIGHTMAPEXCLUDED" + lightIndex] = true;
+                    if (light.lightmapMode == BABYLON.Light.LIGHTMAP_SHADOWSONLY) {
+                        defines["LIGHTMAPNOSPECULAR" + lightIndex] = true;
+                    }
+                }
                 lightIndex++;
                 lightIndex++;
                 if (lightIndex === maxSimultaneousLights)
                 if (lightIndex === maxSimultaneousLights)
                     break;
                     break;
@@ -98,6 +112,12 @@ var BABYLON;
                 }
                 }
                 defines["SHADOWFULLFLOAT"] = true;
                 defines["SHADOWFULLFLOAT"] = true;
             }
             }
+            if (defines["LIGHTMAPEXCLUDED"] === undefined) {
+                needRebuild = true;
+            }
+            if (lightmapMode) {
+                defines["LIGHTMAPEXCLUDED"] = true;
+            }
             if (needRebuild) {
             if (needRebuild) {
                 defines.rebuild();
                 defines.rebuild();
             }
             }

+ 22 - 0
src/Materials/babylon.materialHelper.ts

@@ -5,6 +5,7 @@
             var needNormals = false;
             var needNormals = false;
             var needRebuild = false;
             var needRebuild = false;
             var needShadows = false;
             var needShadows = false;
+            var lightmapMode = false;
 
 
             for (var index = 0; index < scene.lights.length; index++) {
             for (var index = 0; index < scene.lights.length; index++) {
                 var light = scene.lights[index];
                 var light = scene.lights[index];
@@ -103,6 +104,20 @@
                     }
                     }
                 }
                 }
 
 
+                if (light.lightmapMode != Light.LIGHTMAP_DEFAULT ) {
+                    lightmapMode = true;
+                    if (defines["LIGHTMAPEXCLUDED" + lightIndex] === undefined) {
+                        needRebuild = true;
+                    }
+                    if (defines["LIGHTMAPNOSPECULAR" + lightIndex] === undefined) {
+                        needRebuild = true;
+                    }
+                    defines["LIGHTMAPEXCLUDED" + lightIndex] = true;
+                    if (light.lightmapMode == Light.LIGHTMAP_SHADOWSONLY) {
+                        defines["LIGHTMAPNOSPECULAR" + lightIndex] = true;
+                    }
+                }
+
                 lightIndex++;
                 lightIndex++;
                 if (lightIndex === maxSimultaneousLights)
                 if (lightIndex === maxSimultaneousLights)
                     break;
                     break;
@@ -117,6 +132,13 @@
                 defines["SHADOWFULLFLOAT"] = true;
                 defines["SHADOWFULLFLOAT"] = true;
             }
             }
 
 
+            if (defines["LIGHTMAPEXCLUDED"] === undefined) {
+                needRebuild = true;
+            }
+            if (lightmapMode) {
+                defines["LIGHTMAPEXCLUDED"] = true;
+            }
+
             if (needRebuild) {
             if (needRebuild) {
                 defines.rebuild();
                 defines.rebuild();
             }
             }

+ 151 - 180
src/Math/babylon.math.SIMD.js

@@ -4,207 +4,182 @@ var BABYLON;
         function SIMDVector3() {
         function SIMDVector3() {
         }
         }
         SIMDVector3.TransformCoordinatesToRefSIMD = function (vector, transformation, result) {
         SIMDVector3.TransformCoordinatesToRefSIMD = function (vector, transformation, result) {
-            var v = SIMD.float32x4.loadXYZ(vector._data, 0);
-            var m0 = SIMD.float32x4.load(transformation.m, 0);
-            var m1 = SIMD.float32x4.load(transformation.m, 4);
-            var m2 = SIMD.float32x4.load(transformation.m, 8);
-            var m3 = SIMD.float32x4.load(transformation.m, 12);
-            var r = SIMD.float32x4.add(SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(v, 0, 0, 0, 0), m0), SIMD.float32x4.mul(SIMD.float32x4.swizzle(v, 1, 1, 1, 1), m1)), SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(v, 2, 2, 2, 2), m2), m3));
-            r = SIMD.float32x4.div(r, SIMD.float32x4.swizzle(r, 3, 3, 3, 3));
-            SIMD.float32x4.storeXYZ(result._data, 0, r);
+            SIMDVector3.TransformCoordinatesFromFloatsToRefSIMD(vector.x, vector.y, vector.z, transformation, result);
         };
         };
         SIMDVector3.TransformCoordinatesFromFloatsToRefSIMD = function (x, y, z, transformation, result) {
         SIMDVector3.TransformCoordinatesFromFloatsToRefSIMD = function (x, y, z, transformation, result) {
-            var v0 = SIMD.float32x4.splat(x);
-            var v1 = SIMD.float32x4.splat(y);
-            var v2 = SIMD.float32x4.splat(z);
-            var m0 = SIMD.float32x4.load(transformation.m, 0);
-            var m1 = SIMD.float32x4.load(transformation.m, 4);
-            var m2 = SIMD.float32x4.load(transformation.m, 8);
-            var m3 = SIMD.float32x4.load(transformation.m, 12);
-            var r = SIMD.float32x4.add(SIMD.float32x4.add(SIMD.float32x4.mul(v0, m0), SIMD.float32x4.mul(v1, m1)), SIMD.float32x4.add(SIMD.float32x4.mul(v2, m2), m3));
-            r = SIMD.float32x4.div(r, SIMD.float32x4.swizzle(r, 3, 3, 3, 3));
-            SIMD.float32x4.storeXYZ(result._data, 0, r);
+            var m = transformation.m;
+            var m0 = SIMD.Float32x4.load(m, 0);
+            var m1 = SIMD.Float32x4.load(m, 4);
+            var m2 = SIMD.Float32x4.load(m, 8);
+            var m3 = SIMD.Float32x4.load(m, 12);
+            var r = SIMD.Float32x4.add(SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.splat(x), m0), SIMD.Float32x4.mul(SIMD.Float32x4.splat(y), m1)), SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.splat(z), m2), m3));
+            r = SIMD.Float32x4.div(r, SIMD.Float32x4.swizzle(r, 3, 3, 3, 3));
+            result.x = SIMD.Float32x4.extractLane(r, 0);
+            result.y = SIMD.Float32x4.extractLane(r, 1);
+            result.z = SIMD.Float32x4.extractLane(r, 2);
         };
         };
         return SIMDVector3;
         return SIMDVector3;
     })();
     })();
-    BABYLON.SIMDVector3 = SIMDVector3;
     var SIMDMatrix = (function () {
     var SIMDMatrix = (function () {
         function SIMDMatrix() {
         function SIMDMatrix() {
         }
         }
         SIMDMatrix.prototype.multiplyToArraySIMD = function (other, result, offset) {
         SIMDMatrix.prototype.multiplyToArraySIMD = function (other, result, offset) {
-            if (offset === void 0) { offset = 0; }
             var tm = this.m;
             var tm = this.m;
             var om = other.m;
             var om = other.m;
-            var om0 = SIMD.float32x4.load(om, 0);
-            var om1 = SIMD.float32x4.load(om, 4);
-            var om2 = SIMD.float32x4.load(om, 8);
-            var om3 = SIMD.float32x4.load(om, 12);
-            var tm0 = SIMD.float32x4.load(tm, 0);
-            SIMD.float32x4.store(result, offset + 0, SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm0, 0, 0, 0, 0), om0), SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm0, 1, 1, 1, 1), om1), SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm0, 2, 2, 2, 2), om2), SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm0, 3, 3, 3, 3), om3)))));
-            var tm1 = SIMD.float32x4.load(tm, 4);
-            SIMD.float32x4.store(result, offset + 4, SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm1, 0, 0, 0, 0), om0), SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm1, 1, 1, 1, 1), om1), SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm1, 2, 2, 2, 2), om2), SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm1, 3, 3, 3, 3), om3)))));
-            var tm2 = SIMD.float32x4.load(tm, 8);
-            SIMD.float32x4.store(result, offset + 8, SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm2, 0, 0, 0, 0), om0), SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm2, 1, 1, 1, 1), om1), SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm2, 2, 2, 2, 2), om2), SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm2, 3, 3, 3, 3), om3)))));
-            var tm3 = SIMD.float32x4.load(tm, 12);
-            SIMD.float32x4.store(result, offset + 12, SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm3, 0, 0, 0, 0), om0), SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm3, 1, 1, 1, 1), om1), SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm3, 2, 2, 2, 2), om2), SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm3, 3, 3, 3, 3), om3)))));
+            var m0 = SIMD.Float32x4.load(om, 0);
+            var m1 = SIMD.Float32x4.load(om, 4);
+            var m2 = SIMD.Float32x4.load(om, 8);
+            var m3 = SIMD.Float32x4.load(om, 12);
+            for (var i = 0; i < 16; i += 4) {
+                SIMD.Float32x4.store(result, i + offset, SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.splat(tm[i]), m0), SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.splat(tm[i + 1]), m1), SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.splat(tm[i + 2]), m2), SIMD.Float32x4.mul(SIMD.Float32x4.splat(tm[i + 3]), m3)))));
+            }
+            return this;
         };
         };
         SIMDMatrix.prototype.invertToRefSIMD = function (other) {
         SIMDMatrix.prototype.invertToRefSIMD = function (other) {
             var src = this.m;
             var src = this.m;
             var dest = other.m;
             var dest = other.m;
-            var row0, row1, row2, row3;
-            var tmp1;
-            var minor0, minor1, minor2, minor3;
-            var det;
             // Load the 4 rows
             // Load the 4 rows
-            var src0 = SIMD.float32x4.load(src, 0);
-            var src1 = SIMD.float32x4.load(src, 4);
-            var src2 = SIMD.float32x4.load(src, 8);
-            var src3 = SIMD.float32x4.load(src, 12);
+            var src0 = SIMD.Float32x4.load(src, 0);
+            var src1 = SIMD.Float32x4.load(src, 4);
+            var src2 = SIMD.Float32x4.load(src, 8);
+            var src3 = SIMD.Float32x4.load(src, 12);
             // Transpose the source matrix.  Sort of.  Not a true transpose operation
             // Transpose the source matrix.  Sort of.  Not a true transpose operation
-            tmp1 = SIMD.float32x4.shuffle(src0, src1, 0, 1, 4, 5);
-            row1 = SIMD.float32x4.shuffle(src2, src3, 0, 1, 4, 5);
-            row0 = SIMD.float32x4.shuffle(tmp1, row1, 0, 2, 4, 6);
-            row1 = SIMD.float32x4.shuffle(row1, tmp1, 1, 3, 5, 7);
-            tmp1 = SIMD.float32x4.shuffle(src0, src1, 2, 3, 6, 7);
-            row3 = SIMD.float32x4.shuffle(src2, src3, 2, 3, 6, 7);
-            row2 = SIMD.float32x4.shuffle(tmp1, row3, 0, 2, 4, 6);
-            row3 = SIMD.float32x4.shuffle(row3, tmp1, 1, 3, 5, 7);
+            var tmp1 = SIMD.Float32x4.shuffle(src0, src1, 0, 1, 4, 5);
+            var row1 = SIMD.Float32x4.shuffle(src2, src3, 0, 1, 4, 5);
+            var row0 = SIMD.Float32x4.shuffle(tmp1, row1, 0, 2, 4, 6);
+            row1 = SIMD.Float32x4.shuffle(row1, tmp1, 1, 3, 5, 7);
+            tmp1 = SIMD.Float32x4.shuffle(src0, src1, 2, 3, 6, 7);
+            var row3 = SIMD.Float32x4.shuffle(src2, src3, 2, 3, 6, 7);
+            var row2 = SIMD.Float32x4.shuffle(tmp1, row3, 0, 2, 4, 6);
+            row3 = SIMD.Float32x4.shuffle(row3, tmp1, 1, 3, 5, 7);
             // This is a true transposition, but it will lead to an incorrect result
             // This is a true transposition, but it will lead to an incorrect result
-            //tmp1 = SIMD.float32x4.shuffle(src0, src1, 0, 1, 4, 5);
-            //tmp2 = SIMD.float32x4.shuffle(src2, src3, 0, 1, 4, 5);
-            //row0  = SIMD.float32x4.shuffle(tmp1, tmp2, 0, 2, 4, 6);
-            //row1  = SIMD.float32x4.shuffle(tmp1, tmp2, 1, 3, 5, 7);
-            //tmp1 = SIMD.float32x4.shuffle(src0, src1, 2, 3, 6, 7);
-            //tmp2 = SIMD.float32x4.shuffle(src2, src3, 2, 3, 6, 7);
-            //row2  = SIMD.float32x4.shuffle(tmp1, tmp2, 0, 2, 4, 6);
-            //row3  = SIMD.float32x4.shuffle(tmp1, tmp2, 1, 3, 5, 7);
+            //tmp1 = shuffle(src0, src1, 0, 1, 4, 5);
+            //tmp2 = shuffle(src2, src3, 0, 1, 4, 5);
+            //row0  = shuffle(tmp1, tmp2, 0, 2, 4, 6);
+            //row1  = shuffle(tmp1, tmp2, 1, 3, 5, 7);
+            //tmp1 = shuffle(src0, src1, 2, 3, 6, 7);
+            //tmp2 = shuffle(src2, src3, 2, 3, 6, 7);
+            //row2  = shuffle(tmp1, tmp2, 0, 2, 4, 6);
+            //row3  = shuffle(tmp1, tmp2, 1, 3, 5, 7);
             // ----
             // ----
-            tmp1 = SIMD.float32x4.mul(row2, row3);
-            tmp1 = SIMD.float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
-            minor0 = SIMD.float32x4.mul(row1, tmp1);
-            minor1 = SIMD.float32x4.mul(row0, tmp1);
-            tmp1 = SIMD.float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
-            minor0 = SIMD.float32x4.sub(SIMD.float32x4.mul(row1, tmp1), minor0);
-            minor1 = SIMD.float32x4.sub(SIMD.float32x4.mul(row0, tmp1), minor1);
-            minor1 = SIMD.float32x4.swizzle(minor1, 2, 3, 0, 1); // 0x4E = 01001110
+            tmp1 = SIMD.Float32x4.mul(row2, row3);
+            tmp1 = SIMD.Float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
+            var minor0 = SIMD.Float32x4.mul(row1, tmp1);
+            var minor1 = SIMD.Float32x4.mul(row0, tmp1);
+            tmp1 = SIMD.Float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
+            minor0 = SIMD.Float32x4.sub(SIMD.Float32x4.mul(row1, tmp1), minor0);
+            minor1 = SIMD.Float32x4.sub(SIMD.Float32x4.mul(row0, tmp1), minor1);
+            minor1 = SIMD.Float32x4.swizzle(minor1, 2, 3, 0, 1); // 0x4E = 01001110
             // ----
             // ----
-            tmp1 = SIMD.float32x4.mul(row1, row2);
-            tmp1 = SIMD.float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
-            minor0 = SIMD.float32x4.add(SIMD.float32x4.mul(row3, tmp1), minor0);
-            minor3 = SIMD.float32x4.mul(row0, tmp1);
-            tmp1 = SIMD.float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
-            minor0 = SIMD.float32x4.sub(minor0, SIMD.float32x4.mul(row3, tmp1));
-            minor3 = SIMD.float32x4.sub(SIMD.float32x4.mul(row0, tmp1), minor3);
-            minor3 = SIMD.float32x4.swizzle(minor3, 2, 3, 0, 1); // 0x4E = 01001110
+            tmp1 = SIMD.Float32x4.mul(row1, row2);
+            tmp1 = SIMD.Float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
+            minor0 = SIMD.Float32x4.add(SIMD.Float32x4.mul(row3, tmp1), minor0);
+            var minor3 = SIMD.Float32x4.mul(row0, tmp1);
+            tmp1 = SIMD.Float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
+            minor0 = SIMD.Float32x4.sub(minor0, SIMD.Float32x4.mul(row3, tmp1));
+            minor3 = SIMD.Float32x4.sub(SIMD.Float32x4.mul(row0, tmp1), minor3);
+            minor3 = SIMD.Float32x4.swizzle(minor3, 2, 3, 0, 1); // 0x4E = 01001110
             // ----
             // ----
-            tmp1 = SIMD.float32x4.mul(SIMD.float32x4.swizzle(row1, 2, 3, 0, 1), row3); // 0x4E = 01001110
-            tmp1 = SIMD.float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
-            row2 = SIMD.float32x4.swizzle(row2, 2, 3, 0, 1); // 0x4E = 01001110
-            minor0 = SIMD.float32x4.add(SIMD.float32x4.mul(row2, tmp1), minor0);
-            minor2 = SIMD.float32x4.mul(row0, tmp1);
-            tmp1 = SIMD.float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
-            minor0 = SIMD.float32x4.sub(minor0, SIMD.float32x4.mul(row2, tmp1));
-            minor2 = SIMD.float32x4.sub(SIMD.float32x4.mul(row0, tmp1), minor2);
-            minor2 = SIMD.float32x4.swizzle(minor2, 2, 3, 0, 1); // 0x4E = 01001110
+            tmp1 = SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(row1, 2, 3, 0, 1), row3); // 0x4E = 01001110
+            tmp1 = SIMD.Float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
+            row2 = SIMD.Float32x4.swizzle(row2, 2, 3, 0, 1); // 0x4E = 01001110
+            minor0 = SIMD.Float32x4.add(SIMD.Float32x4.mul(row2, tmp1), minor0);
+            var minor2 = SIMD.Float32x4.mul(row0, tmp1);
+            tmp1 = SIMD.Float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
+            minor0 = SIMD.Float32x4.sub(minor0, SIMD.Float32x4.mul(row2, tmp1));
+            minor2 = SIMD.Float32x4.sub(SIMD.Float32x4.mul(row0, tmp1), minor2);
+            minor2 = SIMD.Float32x4.swizzle(minor2, 2, 3, 0, 1); // 0x4E = 01001110
             // ----
             // ----
-            tmp1 = SIMD.float32x4.mul(row0, row1);
-            tmp1 = SIMD.float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
-            minor2 = SIMD.float32x4.add(SIMD.float32x4.mul(row3, tmp1), minor2);
-            minor3 = SIMD.float32x4.sub(SIMD.float32x4.mul(row2, tmp1), minor3);
-            tmp1 = SIMD.float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
-            minor2 = SIMD.float32x4.sub(SIMD.float32x4.mul(row3, tmp1), minor2);
-            minor3 = SIMD.float32x4.sub(minor3, SIMD.float32x4.mul(row2, tmp1));
+            tmp1 = SIMD.Float32x4.mul(row0, row1);
+            tmp1 = SIMD.Float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
+            minor2 = SIMD.Float32x4.add(SIMD.Float32x4.mul(row3, tmp1), minor2);
+            minor3 = SIMD.Float32x4.sub(SIMD.Float32x4.mul(row2, tmp1), minor3);
+            tmp1 = SIMD.Float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
+            minor2 = SIMD.Float32x4.sub(SIMD.Float32x4.mul(row3, tmp1), minor2);
+            minor3 = SIMD.Float32x4.sub(minor3, SIMD.Float32x4.mul(row2, tmp1));
             // ----
             // ----
-            tmp1 = SIMD.float32x4.mul(row0, row3);
-            tmp1 = SIMD.float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
-            minor1 = SIMD.float32x4.sub(minor1, SIMD.float32x4.mul(row2, tmp1));
-            minor2 = SIMD.float32x4.add(SIMD.float32x4.mul(row1, tmp1), minor2);
-            tmp1 = SIMD.float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
-            minor1 = SIMD.float32x4.add(SIMD.float32x4.mul(row2, tmp1), minor1);
-            minor2 = SIMD.float32x4.sub(minor2, SIMD.float32x4.mul(row1, tmp1));
+            tmp1 = SIMD.Float32x4.mul(row0, row3);
+            tmp1 = SIMD.Float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
+            minor1 = SIMD.Float32x4.sub(minor1, SIMD.Float32x4.mul(row2, tmp1));
+            minor2 = SIMD.Float32x4.add(SIMD.Float32x4.mul(row1, tmp1), minor2);
+            tmp1 = SIMD.Float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
+            minor1 = SIMD.Float32x4.add(SIMD.Float32x4.mul(row2, tmp1), minor1);
+            minor2 = SIMD.Float32x4.sub(minor2, SIMD.Float32x4.mul(row1, tmp1));
             // ----
             // ----
-            tmp1 = SIMD.float32x4.mul(row0, row2);
-            tmp1 = SIMD.float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
-            minor1 = SIMD.float32x4.add(SIMD.float32x4.mul(row3, tmp1), minor1);
-            minor3 = SIMD.float32x4.sub(minor3, SIMD.float32x4.mul(row1, tmp1));
-            tmp1 = SIMD.float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
-            minor1 = SIMD.float32x4.sub(minor1, SIMD.float32x4.mul(row3, tmp1));
-            minor3 = SIMD.float32x4.add(SIMD.float32x4.mul(row1, tmp1), minor3);
+            tmp1 = SIMD.Float32x4.mul(row0, row2);
+            tmp1 = SIMD.Float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
+            minor1 = SIMD.Float32x4.add(SIMD.Float32x4.mul(row3, tmp1), minor1);
+            minor3 = SIMD.Float32x4.sub(minor3, SIMD.Float32x4.mul(row1, tmp1));
+            tmp1 = SIMD.Float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
+            minor1 = SIMD.Float32x4.sub(minor1, SIMD.Float32x4.mul(row3, tmp1));
+            minor3 = SIMD.Float32x4.add(SIMD.Float32x4.mul(row1, tmp1), minor3);
             // Compute determinant
             // Compute determinant
-            det = SIMD.float32x4.mul(row0, minor0);
-            det = SIMD.float32x4.add(SIMD.float32x4.swizzle(det, 2, 3, 0, 1), det); // 0x4E = 01001110
-            det = SIMD.float32x4.add(SIMD.float32x4.swizzle(det, 1, 0, 3, 2), det); // 0xB1 = 10110001
-            tmp1 = SIMD.float32x4.reciprocalApproximation(det);
-            det = SIMD.float32x4.sub(SIMD.float32x4.add(tmp1, tmp1), SIMD.float32x4.mul(det, SIMD.float32x4.mul(tmp1, tmp1)));
-            det = SIMD.float32x4.swizzle(det, 0, 0, 0, 0);
+            var det = SIMD.Float32x4.mul(row0, minor0);
+            det = SIMD.Float32x4.add(SIMD.Float32x4.swizzle(det, 2, 3, 0, 1), det); // 0x4E = 01001110
+            det = SIMD.Float32x4.add(SIMD.Float32x4.swizzle(det, 1, 0, 3, 2), det); // 0xB1 = 10110001
+            tmp1 = SIMD.Float32x4.reciprocalApproximation(det);
+            det = SIMD.Float32x4.sub(SIMD.Float32x4.add(tmp1, tmp1), SIMD.Float32x4.mul(det, SIMD.Float32x4.mul(tmp1, tmp1)));
+            det = SIMD.Float32x4.swizzle(det, 0, 0, 0, 0);
             // These shuffles aren't necessary if the faulty transposition is done
             // These shuffles aren't necessary if the faulty transposition is done
             // up at the top of this function.
             // up at the top of this function.
-            //minor0 = SIMD.float32x4.swizzle(minor0, 2, 1, 0, 3);
-            //minor1 = SIMD.float32x4.swizzle(minor1, 2, 1, 0, 3);
-            //minor2 = SIMD.float32x4.swizzle(minor2, 2, 1, 0, 3);
-            //minor3 = SIMD.float32x4.swizzle(minor3, 2, 1, 0, 3);
+            //minor0 =SIMD.Float32x4.swizzle(minor0, 2, 1, 0, 3);
+            //minor1 =SIMD.Float32x4.swizzle(minor1, 2, 1, 0, 3);
+            //minor2 =SIMD.Float32x4.swizzle(minor2, 2, 1, 0, 3);
+            //minor3 =SIMD.Float32x4.swizzle(minor3, 2, 1, 0, 3);
             // Compute final values by multiplying with 1/det
             // Compute final values by multiplying with 1/det
-            minor0 = SIMD.float32x4.mul(det, minor0);
-            minor1 = SIMD.float32x4.mul(det, minor1);
-            minor2 = SIMD.float32x4.mul(det, minor2);
-            minor3 = SIMD.float32x4.mul(det, minor3);
-            SIMD.float32x4.store(dest, 0, minor0);
-            SIMD.float32x4.store(dest, 4, minor1);
-            SIMD.float32x4.store(dest, 8, minor2);
-            SIMD.float32x4.store(dest, 12, minor3);
+            SIMD.Float32x4.store(dest, 0, SIMD.Float32x4.mul(det, minor0));
+            SIMD.Float32x4.store(dest, 4, SIMD.Float32x4.mul(det, minor1));
+            SIMD.Float32x4.store(dest, 8, minor2 = SIMD.Float32x4.mul(det, minor2));
+            SIMD.Float32x4.store(dest, 12, SIMD.Float32x4.mul(det, minor3));
             return this;
             return this;
         };
         };
         SIMDMatrix.LookAtLHToRefSIMD = function (eyeRef, targetRef, upRef, result) {
         SIMDMatrix.LookAtLHToRefSIMD = function (eyeRef, targetRef, upRef, result) {
             var out = result.m;
             var out = result.m;
-            var center = SIMD.float32x4(targetRef.x, targetRef.y, targetRef.z, 0);
-            var eye = SIMD.float32x4(eyeRef.x, eyeRef.y, eyeRef.z, 0);
-            var up = SIMD.float32x4(upRef.x, upRef.y, upRef.z, 0);
+            var center = SIMD.Float32x4(targetRef.x, targetRef.y, targetRef.z, 0.0);
+            var eye = SIMD.Float32x4(eyeRef.x, eyeRef.y, eyeRef.z, 0.0);
+            var up = SIMD.Float32x4(upRef.x, upRef.y, upRef.z, 0.0);
             // cc.kmVec3Subtract(f, pCenter, pEye);
             // cc.kmVec3Subtract(f, pCenter, pEye);
-            var f = SIMD.float32x4.sub(center, eye);
+            var f = SIMD.Float32x4.sub(center, eye);
             // cc.kmVec3Normalize(f, f);    
             // cc.kmVec3Normalize(f, f);    
-            var tmp = SIMD.float32x4.mul(f, f);
-            tmp = SIMD.float32x4.add(tmp, SIMD.float32x4.add(SIMD.float32x4.swizzle(tmp, 1, 2, 0, 3), SIMD.float32x4.swizzle(tmp, 2, 0, 1, 3)));
-            f = SIMD.float32x4.mul(f, SIMD.float32x4.reciprocalSqrtApproximation(tmp));
+            var tmp = SIMD.Float32x4.mul(f, f);
+            tmp = SIMD.Float32x4.add(tmp, SIMD.Float32x4.add(SIMD.Float32x4.swizzle(tmp, 1, 2, 0, 3), SIMD.Float32x4.swizzle(tmp, 2, 0, 1, 3)));
+            f = SIMD.Float32x4.mul(f, SIMD.Float32x4.reciprocalSqrtApproximation(tmp));
             // cc.kmVec3Assign(up, pUp);
             // cc.kmVec3Assign(up, pUp);
             // cc.kmVec3Normalize(up, up);
             // cc.kmVec3Normalize(up, up);
-            tmp = SIMD.float32x4.mul(up, up);
-            tmp = SIMD.float32x4.add(tmp, SIMD.float32x4.add(SIMD.float32x4.swizzle(tmp, 1, 2, 0, 3), SIMD.float32x4.swizzle(tmp, 2, 0, 1, 3)));
-            up = SIMD.float32x4.mul(up, SIMD.float32x4.reciprocalSqrtApproximation(tmp));
+            tmp = SIMD.Float32x4.mul(up, up);
+            tmp = SIMD.Float32x4.add(tmp, SIMD.Float32x4.add(SIMD.Float32x4.swizzle(tmp, 1, 2, 0, 3), SIMD.Float32x4.swizzle(tmp, 2, 0, 1, 3)));
+            up = SIMD.Float32x4.mul(up, SIMD.Float32x4.reciprocalSqrtApproximation(tmp));
             // cc.kmVec3Cross(s, f, up);
             // cc.kmVec3Cross(s, f, up);
-            var s = SIMD.float32x4.sub(SIMD.float32x4.mul(SIMD.float32x4.swizzle(f, 1, 2, 0, 3), SIMD.float32x4.swizzle(up, 2, 0, 1, 3)), SIMD.float32x4.mul(SIMD.float32x4.swizzle(f, 2, 0, 1, 3), SIMD.float32x4.swizzle(up, 1, 2, 0, 3)));
+            var s = SIMD.Float32x4.sub(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(f, 1, 2, 0, 3), SIMD.Float32x4.swizzle(up, 2, 0, 1, 3)), SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(f, 2, 0, 1, 3), SIMD.Float32x4.swizzle(up, 1, 2, 0, 3)));
             // cc.kmVec3Normalize(s, s);
             // cc.kmVec3Normalize(s, s);
-            tmp = SIMD.float32x4.mul(s, s);
-            tmp = SIMD.float32x4.add(tmp, SIMD.float32x4.add(SIMD.float32x4.swizzle(tmp, 1, 2, 0, 3), SIMD.float32x4.swizzle(tmp, 2, 0, 1, 3)));
-            s = SIMD.float32x4.mul(s, SIMD.float32x4.reciprocalSqrtApproximation(tmp));
+            tmp = SIMD.Float32x4.mul(s, s);
+            tmp = SIMD.Float32x4.add(tmp, SIMD.Float32x4.add(SIMD.Float32x4.swizzle(tmp, 1, 2, 0, 3), SIMD.Float32x4.swizzle(tmp, 2, 0, 1, 3)));
+            s = SIMD.Float32x4.mul(s, SIMD.Float32x4.reciprocalSqrtApproximation(tmp));
             // cc.kmVec3Cross(u, s, f);
             // cc.kmVec3Cross(u, s, f);
-            var u = SIMD.float32x4.sub(SIMD.float32x4.mul(SIMD.float32x4.swizzle(s, 1, 2, 0, 3), SIMD.float32x4.swizzle(f, 2, 0, 1, 3)), SIMD.float32x4.mul(SIMD.float32x4.swizzle(s, 2, 0, 1, 3), SIMD.float32x4.swizzle(f, 1, 2, 0, 3)));
+            var u = SIMD.Float32x4.sub(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(s, 1, 2, 0, 3), SIMD.Float32x4.swizzle(f, 2, 0, 1, 3)), SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(s, 2, 0, 1, 3), SIMD.Float32x4.swizzle(f, 1, 2, 0, 3)));
             // cc.kmVec3Normalize(s, s);
             // cc.kmVec3Normalize(s, s);
-            tmp = SIMD.float32x4.mul(s, s);
-            tmp = SIMD.float32x4.add(tmp, SIMD.float32x4.add(SIMD.float32x4.swizzle(tmp, 1, 2, 0, 3), SIMD.float32x4.swizzle(tmp, 2, 0, 1, 3)));
-            s = SIMD.float32x4.mul(s, SIMD.float32x4.reciprocalSqrtApproximation(tmp));
-            var zero = SIMD.float32x4.splat(0.0);
-            s = SIMD.float32x4.neg(s);
-            var tmp01 = SIMD.float32x4.shuffle(s, u, 0, 1, 4, 5);
-            var tmp23 = SIMD.float32x4.shuffle(f, zero, 0, 1, 4, 5);
-            var a0 = SIMD.float32x4.shuffle(tmp01, tmp23, 0, 2, 4, 6);
-            var a1 = SIMD.float32x4.shuffle(tmp01, tmp23, 1, 3, 5, 7);
-            tmp01 = SIMD.float32x4.shuffle(s, u, 2, 3, 6, 7);
-            tmp23 = SIMD.float32x4.shuffle(f, zero, 2, 3, 6, 7);
-            var a2 = SIMD.float32x4.shuffle(tmp01, tmp23, 0, 2, 4, 6);
-            var a3 = SIMD.float32x4(0.0, 0.0, 0.0, 1.0);
-            var b0 = SIMD.float32x4(1.0, 0.0, 0.0, 0.0);
-            var b1 = SIMD.float32x4(0.0, 1.0, 0.0, 0.0);
-            var b2 = SIMD.float32x4(0.0, 0.0, 1.0, 0.0);
-            var b3 = SIMD.float32x4.neg(eye);
-            b3 = SIMD.float32x4.withW(b3, 1.0);
-            SIMD.float32x4.store(out, 0, SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(b0, 0, 0, 0, 0), a0), SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(b0, 1, 1, 1, 1), a1), SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(b0, 2, 2, 2, 2), a2), SIMD.float32x4.mul(SIMD.float32x4.swizzle(b0, 3, 3, 3, 3), a3)))));
-            SIMD.float32x4.store(out, 4, SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(b1, 0, 0, 0, 0), a0), SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(b1, 1, 1, 1, 1), a1), SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(b1, 2, 2, 2, 2), a2), SIMD.float32x4.mul(SIMD.float32x4.swizzle(b1, 3, 3, 3, 3), a3)))));
-            SIMD.float32x4.store(out, 8, SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(b2, 0, 0, 0, 0), a0), SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(b2, 1, 1, 1, 1), a1), SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(b2, 2, 2, 2, 2), a2), SIMD.float32x4.mul(SIMD.float32x4.swizzle(b2, 3, 3, 3, 3), a3)))));
-            SIMD.float32x4.store(out, 12, SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(b3, 0, 0, 0, 0), a0), SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(b3, 1, 1, 1, 1), a1), SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(b3, 2, 2, 2, 2), a2), SIMD.float32x4.mul(SIMD.float32x4.swizzle(b3, 3, 3, 3, 3), a3)))));
+            tmp = SIMD.Float32x4.mul(s, s);
+            tmp = SIMD.Float32x4.add(tmp, SIMD.Float32x4.add(SIMD.Float32x4.swizzle(tmp, 1, 2, 0, 3), SIMD.Float32x4.swizzle(tmp, 2, 0, 1, 3)));
+            s = SIMD.Float32x4.mul(s, SIMD.Float32x4.reciprocalSqrtApproximation(tmp));
+            var zero = SIMD.Float32x4.splat(0.0);
+            s = SIMD.Float32x4.neg(s);
+            var tmp01 = SIMD.Float32x4.shuffle(s, u, 0, 1, 4, 5);
+            var tmp23 = SIMD.Float32x4.shuffle(f, zero, 0, 1, 4, 5);
+            var a0 = SIMD.Float32x4.shuffle(tmp01, tmp23, 0, 2, 4, 6);
+            var a1 = SIMD.Float32x4.shuffle(tmp01, tmp23, 1, 3, 5, 7);
+            var a2 = SIMD.Float32x4.shuffle(SIMD.Float32x4.shuffle(s, u, 2, 3, 6, 7), SIMD.Float32x4.shuffle(f, zero, 2, 3, 6, 7), 0, 2, 4, 6);
+            var a3 = SIMD.Float32x4(0.0, 0.0, 0.0, 1.0);
+            var b = SIMD.Float32x4(1.0, 0.0, 0.0, 0.0);
+            SIMD.Float32x4.store(out, 0, SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 0, 0, 0, 0), a0), SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 1, 1, 1, 1), a1), SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 2, 2, 2, 2), a2), SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 3, 3, 3, 3), a3)))));
+            b = SIMD.Float32x4(0.0, 1.0, 0.0, 0.0);
+            SIMD.Float32x4.store(out, 4, SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 0, 0, 0, 0), a0), SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 1, 1, 1, 1), a1), SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 2, 2, 2, 2), a2), SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 3, 3, 3, 3), a3)))));
+            b = SIMD.Float32x4(0.0, 0.0, 1.0, 0.0);
+            SIMD.Float32x4.store(out, 8, SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 0, 0, 0, 0), a0), SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 1, 1, 1, 1), a1), SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 2, 2, 2, 2), a2), SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 3, 3, 3, 3), a3)))));
+            b = SIMD.Float32x4.replaceLane(SIMD.Float32x4.neg(eye), 3, 1.0);
+            SIMD.Float32x4.store(out, 12, SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 0, 0, 0, 0), a0), SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 1, 1, 1, 1), a1), SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 2, 2, 2, 2), a2), SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 3, 3, 3, 3), a3)))));
         };
         };
         return SIMDMatrix;
         return SIMDMatrix;
     })();
     })();
-    BABYLON.SIMDMatrix = SIMDMatrix;
     var previousMultiplyToArray = BABYLON.Matrix.prototype.multiplyToArray;
     var previousMultiplyToArray = BABYLON.Matrix.prototype.multiplyToArray;
     var previousInvertToRef = BABYLON.Matrix.prototype.invertToRef;
     var previousInvertToRef = BABYLON.Matrix.prototype.invertToRef;
     var previousLookAtLHToRef = BABYLON.Matrix.LookAtLHToRef;
     var previousLookAtLHToRef = BABYLON.Matrix.LookAtLHToRef;
@@ -230,36 +205,32 @@ var BABYLON;
             SIMDHelper._isEnabled = false;
             SIMDHelper._isEnabled = false;
         };
         };
         SIMDHelper.EnableSIMD = function () {
         SIMDHelper.EnableSIMD = function () {
-            if (window.SIMD === undefined) {
+            if (self.SIMD === undefined) {
                 return;
                 return;
             }
             }
+            // check if polyfills needed
+            if (!self.Math.fround) {
+                self.Math.fround = (function (array) { return function (x) {
+                    return array[0] = x, array[0];
+                }; })(new Float32Array(1));
+            }
+            if (!self.Math.imul) {
+                self.Math.imul = function (a, b) {
+                    var ah = (a >>> 16) & 0xffff;
+                    var al = a & 0xffff;
+                    var bh = (b >>> 16) & 0xffff;
+                    var bl = b & 0xffff;
+                    // the shift by 0 fixes the sign on the high part
+                    // the final |0 converts the unsigned value into a signed value
+                    return ((al * bl) + (((ah * bl + al * bh) << 16) >>> 0) | 0);
+                };
+            }
             // Replace functions
             // Replace functions
             BABYLON.Matrix.prototype.multiplyToArray = SIMDMatrix.prototype.multiplyToArraySIMD;
             BABYLON.Matrix.prototype.multiplyToArray = SIMDMatrix.prototype.multiplyToArraySIMD;
             BABYLON.Matrix.prototype.invertToRef = SIMDMatrix.prototype.invertToRefSIMD;
             BABYLON.Matrix.prototype.invertToRef = SIMDMatrix.prototype.invertToRefSIMD;
             BABYLON.Matrix.LookAtLHToRef = SIMDMatrix.LookAtLHToRefSIMD;
             BABYLON.Matrix.LookAtLHToRef = SIMDMatrix.LookAtLHToRefSIMD;
             BABYLON.Vector3.TransformCoordinatesToRef = SIMDVector3.TransformCoordinatesToRefSIMD;
             BABYLON.Vector3.TransformCoordinatesToRef = SIMDVector3.TransformCoordinatesToRefSIMD;
             BABYLON.Vector3.TransformCoordinatesFromFloatsToRef = SIMDVector3.TransformCoordinatesFromFloatsToRefSIMD;
             BABYLON.Vector3.TransformCoordinatesFromFloatsToRef = SIMDVector3.TransformCoordinatesFromFloatsToRefSIMD;
-            Object.defineProperty(BABYLON.Vector3.prototype, "x", {
-                get: function () { return this._data[0]; },
-                set: function (value) {
-                    if (!this._data) {
-                        this._data = new Float32Array(3);
-                    }
-                    this._data[0] = value;
-                }
-            });
-            Object.defineProperty(BABYLON.Vector3.prototype, "y", {
-                get: function () { return this._data[1]; },
-                set: function (value) {
-                    this._data[1] = value;
-                }
-            });
-            Object.defineProperty(BABYLON.Vector3.prototype, "z", {
-                get: function () { return this._data[2]; },
-                set: function (value) {
-                    this._data[2] = value;
-                }
-            });
             SIMDHelper._isEnabled = true;
             SIMDHelper._isEnabled = true;
         };
         };
         SIMDHelper._isEnabled = false;
         SIMDHelper._isEnabled = false;

+ 188 - 229
src/Math/babylon.math.SIMD.ts

@@ -1,255 +1,221 @@
 module BABYLON {
 module BABYLON {
 
 
-    declare var SIMD;
+    declare var SIMD: SIMD;
 
 
-    export class SIMDVector3 {
+    class SIMDVector3 {
         public static TransformCoordinatesToRefSIMD(vector: Vector3, transformation: Matrix, result: Vector3): void {
         public static TransformCoordinatesToRefSIMD(vector: Vector3, transformation: Matrix, result: Vector3): void {
-            var v = SIMD.float32x4.loadXYZ((<any>vector)._data, 0);
-            var m0 = SIMD.float32x4.load(transformation.m, 0);
-            var m1 = SIMD.float32x4.load(transformation.m, 4);
-            var m2 = SIMD.float32x4.load(transformation.m, 8);
-            var m3 = SIMD.float32x4.load(transformation.m, 12);
-            var r = SIMD.float32x4.add(SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(v, 0, 0, 0, 0), m0), SIMD.float32x4.mul(SIMD.float32x4.swizzle(v, 1, 1, 1, 1), m1)), SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(v, 2, 2, 2, 2), m2), m3));
-            r = SIMD.float32x4.div(r, SIMD.float32x4.swizzle(r, 3, 3, 3, 3));
-            SIMD.float32x4.storeXYZ((<any>result)._data, 0, r);
+            SIMDVector3.TransformCoordinatesFromFloatsToRefSIMD(vector.x, vector.y, vector.z, transformation, result);
         }
         }
 
 
         public static TransformCoordinatesFromFloatsToRefSIMD(x: number, y: number, z: number, transformation: Matrix, result: Vector3): void {
         public static TransformCoordinatesFromFloatsToRefSIMD(x: number, y: number, z: number, transformation: Matrix, result: Vector3): void {
-            var v0 = SIMD.float32x4.splat(x);
-            var v1 = SIMD.float32x4.splat(y);
-            var v2 = SIMD.float32x4.splat(z);
-            var m0 = SIMD.float32x4.load(transformation.m, 0);
-            var m1 = SIMD.float32x4.load(transformation.m, 4);
-            var m2 = SIMD.float32x4.load(transformation.m, 8);
-            var m3 = SIMD.float32x4.load(transformation.m, 12);
-            var r = SIMD.float32x4.add(SIMD.float32x4.add(SIMD.float32x4.mul(v0, m0), SIMD.float32x4.mul(v1, m1)), SIMD.float32x4.add(SIMD.float32x4.mul(v2, m2), m3));
-            r = SIMD.float32x4.div(r, SIMD.float32x4.swizzle(r, 3, 3, 3, 3));
-            SIMD.float32x4.storeXYZ((<any>result)._data, 0, r);
+            var m = transformation.m;
+
+            var m0 = SIMD.Float32x4.load(m, 0);
+            var m1 = SIMD.Float32x4.load(m, 4);
+            var m2 = SIMD.Float32x4.load(m, 8);
+            var m3 = SIMD.Float32x4.load(m, 12);
+            var r = SIMD.Float32x4.add(
+                SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.splat(x), m0), SIMD.Float32x4.mul(SIMD.Float32x4.splat(y), m1)),
+                SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.splat(z), m2), m3)
+            );
+            r = SIMD.Float32x4.div(r, SIMD.Float32x4.swizzle(r, 3, 3, 3, 3));
+            result.x = SIMD.Float32x4.extractLane(r, 0);
+            result.y = SIMD.Float32x4.extractLane(r, 1);
+            result.z = SIMD.Float32x4.extractLane(r, 2);
         }
         }
     }
     }
 
 
-    export class SIMDMatrix {
-        public multiplyToArraySIMD(other: Matrix, result: Matrix, offset = 0): void {
-            var tm = (<any>this).m;
+    class SIMDMatrix {
+        public multiplyToArraySIMD(other: Matrix, result: Float32Array, offset: number): Matrix {
+            var tm: Float32Array = (<any>this).m;
             var om = other.m;
             var om = other.m;
-            var om0 = SIMD.float32x4.load(om, 0);
-            var om1 = SIMD.float32x4.load(om, 4);
-            var om2 = SIMD.float32x4.load(om, 8);
-            var om3 = SIMD.float32x4.load(om, 12);
-
-            var tm0 = SIMD.float32x4.load(tm, 0);
-            SIMD.float32x4.store(result, offset + 0, SIMD.float32x4.add(
-                SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm0, 0, 0, 0, 0), om0),
-                SIMD.float32x4.add(
-                    SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm0, 1, 1, 1, 1), om1),
-                    SIMD.float32x4.add(
-                        SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm0, 2, 2, 2, 2), om2),
-                        SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm0, 3, 3, 3, 3), om3)))));
-
-            var tm1 = SIMD.float32x4.load(tm, 4);
-            SIMD.float32x4.store(result, offset + 4, SIMD.float32x4.add(
-                SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm1, 0, 0, 0, 0), om0),
-                SIMD.float32x4.add(
-                    SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm1, 1, 1, 1, 1), om1),
-                    SIMD.float32x4.add(
-                        SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm1, 2, 2, 2, 2), om2),
-                        SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm1, 3, 3, 3, 3), om3)))));
-
-            var tm2 = SIMD.float32x4.load(tm, 8);
-            SIMD.float32x4.store(result, offset + 8, SIMD.float32x4.add(
-                SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm2, 0, 0, 0, 0), om0),
-                SIMD.float32x4.add(
-                    SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm2, 1, 1, 1, 1), om1),
-                    SIMD.float32x4.add(
-                        SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm2, 2, 2, 2, 2), om2),
-                        SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm2, 3, 3, 3, 3), om3)))));
-
-            var tm3 = SIMD.float32x4.load(tm, 12);
-            SIMD.float32x4.store(result, offset + 12, SIMD.float32x4.add(
-                SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm3, 0, 0, 0, 0), om0),
-                SIMD.float32x4.add(
-                    SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm3, 1, 1, 1, 1), om1),
-                    SIMD.float32x4.add(
-                        SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm3, 2, 2, 2, 2), om2),
-                        SIMD.float32x4.mul(SIMD.float32x4.swizzle(tm3, 3, 3, 3, 3), om3)))));
+
+            var m0 = SIMD.Float32x4.load(om, 0);
+            var m1 = SIMD.Float32x4.load(om, 4);
+            var m2 = SIMD.Float32x4.load(om, 8);
+            var m3 = SIMD.Float32x4.load(om, 12);
+
+            for (var i = 0; i < 16; i += 4) {
+                SIMD.Float32x4.store(result, i + offset, SIMD.Float32x4.add(
+                    SIMD.Float32x4.mul(SIMD.Float32x4.splat(tm[i]), m0),
+                    SIMD.Float32x4.add(
+                        SIMD.Float32x4.mul(SIMD.Float32x4.splat(tm[i + 1]), m1),
+                        SIMD.Float32x4.add(
+                            SIMD.Float32x4.mul(SIMD.Float32x4.splat(tm[i + 2]), m2),
+                            SIMD.Float32x4.mul(SIMD.Float32x4.splat(tm[i + 3]), m3)))));
+            }
+
+            return (<any>this);
         }
         }
 
 
         public invertToRefSIMD(other: Matrix): Matrix {
         public invertToRefSIMD(other: Matrix): Matrix {
-            var src = (<any>this).m;
+            var src: Float32Array = (<any>this).m;
             var dest = other.m;
             var dest = other.m;
-            var row0, row1, row2, row3;
-            var tmp1;
-            var minor0, minor1, minor2, minor3;
-            var det;
 
 
             // Load the 4 rows
             // Load the 4 rows
-            var src0 = SIMD.float32x4.load(src, 0);
-            var src1 = SIMD.float32x4.load(src, 4);
-            var src2 = SIMD.float32x4.load(src, 8);
-            var src3 = SIMD.float32x4.load(src, 12);
+            var src0 = SIMD.Float32x4.load(src, 0);
+            var src1 = SIMD.Float32x4.load(src, 4);
+            var src2 = SIMD.Float32x4.load(src, 8);
+            var src3 = SIMD.Float32x4.load(src, 12);
 
 
             // Transpose the source matrix.  Sort of.  Not a true transpose operation
             // Transpose the source matrix.  Sort of.  Not a true transpose operation
 
 
-            tmp1 = SIMD.float32x4.shuffle(src0, src1, 0, 1, 4, 5);
-            row1 = SIMD.float32x4.shuffle(src2, src3, 0, 1, 4, 5);
-            row0 = SIMD.float32x4.shuffle(tmp1, row1, 0, 2, 4, 6);
-            row1 = SIMD.float32x4.shuffle(row1, tmp1, 1, 3, 5, 7);
+            var tmp1 = SIMD.Float32x4.shuffle(src0, src1, 0, 1, 4, 5);
+            var row1 = SIMD.Float32x4.shuffle(src2, src3, 0, 1, 4, 5);
+            var row0 = SIMD.Float32x4.shuffle(tmp1, row1, 0, 2, 4, 6);
+            row1 = SIMD.Float32x4.shuffle(row1, tmp1, 1, 3, 5, 7);
 
 
-            tmp1 = SIMD.float32x4.shuffle(src0, src1, 2, 3, 6, 7);
-            row3 = SIMD.float32x4.shuffle(src2, src3, 2, 3, 6, 7);
-            row2 = SIMD.float32x4.shuffle(tmp1, row3, 0, 2, 4, 6);
-            row3 = SIMD.float32x4.shuffle(row3, tmp1, 1, 3, 5, 7);
+            tmp1 = SIMD.Float32x4.shuffle(src0, src1, 2, 3, 6, 7);
+            var row3 = SIMD.Float32x4.shuffle(src2, src3, 2, 3, 6, 7);
+            var row2 = SIMD.Float32x4.shuffle(tmp1, row3, 0, 2, 4, 6);
+            row3 = SIMD.Float32x4.shuffle(row3, tmp1, 1, 3, 5, 7);
 
 
             // This is a true transposition, but it will lead to an incorrect result
             // This is a true transposition, but it will lead to an incorrect result
 
 
-            //tmp1 = SIMD.float32x4.shuffle(src0, src1, 0, 1, 4, 5);
-            //tmp2 = SIMD.float32x4.shuffle(src2, src3, 0, 1, 4, 5);
-            //row0  = SIMD.float32x4.shuffle(tmp1, tmp2, 0, 2, 4, 6);
-            //row1  = SIMD.float32x4.shuffle(tmp1, tmp2, 1, 3, 5, 7);
+            //tmp1 = shuffle(src0, src1, 0, 1, 4, 5);
+            //tmp2 = shuffle(src2, src3, 0, 1, 4, 5);
+            //row0  = shuffle(tmp1, tmp2, 0, 2, 4, 6);
+            //row1  = shuffle(tmp1, tmp2, 1, 3, 5, 7);
 
 
-            //tmp1 = SIMD.float32x4.shuffle(src0, src1, 2, 3, 6, 7);
-            //tmp2 = SIMD.float32x4.shuffle(src2, src3, 2, 3, 6, 7);
-            //row2  = SIMD.float32x4.shuffle(tmp1, tmp2, 0, 2, 4, 6);
-            //row3  = SIMD.float32x4.shuffle(tmp1, tmp2, 1, 3, 5, 7);
+            //tmp1 = shuffle(src0, src1, 2, 3, 6, 7);
+            //tmp2 = shuffle(src2, src3, 2, 3, 6, 7);
+            //row2  = shuffle(tmp1, tmp2, 0, 2, 4, 6);
+            //row3  = shuffle(tmp1, tmp2, 1, 3, 5, 7);
 
 
             // ----
             // ----
-            tmp1 = SIMD.float32x4.mul(row2, row3);
-            tmp1 = SIMD.float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
-            minor0 = SIMD.float32x4.mul(row1, tmp1);
-            minor1 = SIMD.float32x4.mul(row0, tmp1);
-            tmp1 = SIMD.float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
-            minor0 = SIMD.float32x4.sub(SIMD.float32x4.mul(row1, tmp1), minor0);
-            minor1 = SIMD.float32x4.sub(SIMD.float32x4.mul(row0, tmp1), minor1);
-            minor1 = SIMD.float32x4.swizzle(minor1, 2, 3, 0, 1); // 0x4E = 01001110
+            tmp1 = SIMD.Float32x4.mul(row2, row3);
+            tmp1 = SIMD.Float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
+            var minor0 = SIMD.Float32x4.mul(row1, tmp1);
+            var minor1 = SIMD.Float32x4.mul(row0, tmp1);
+            tmp1 = SIMD.Float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
+            minor0 = SIMD.Float32x4.sub(SIMD.Float32x4.mul(row1, tmp1), minor0);
+            minor1 = SIMD.Float32x4.sub(SIMD.Float32x4.mul(row0, tmp1), minor1);
+            minor1 = SIMD.Float32x4.swizzle(minor1, 2, 3, 0, 1); // 0x4E = 01001110
 
 
             // ----
             // ----
-            tmp1 = SIMD.float32x4.mul(row1, row2);
-            tmp1 = SIMD.float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
-            minor0 = SIMD.float32x4.add(SIMD.float32x4.mul(row3, tmp1), minor0);
-            minor3 = SIMD.float32x4.mul(row0, tmp1);
-            tmp1 = SIMD.float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
-            minor0 = SIMD.float32x4.sub(minor0, SIMD.float32x4.mul(row3, tmp1));
-            minor3 = SIMD.float32x4.sub(SIMD.float32x4.mul(row0, tmp1), minor3);
-            minor3 = SIMD.float32x4.swizzle(minor3, 2, 3, 0, 1); // 0x4E = 01001110
+            tmp1 = SIMD.Float32x4.mul(row1, row2);
+            tmp1 = SIMD.Float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
+            minor0 = SIMD.Float32x4.add(SIMD.Float32x4.mul(row3, tmp1), minor0);
+            var minor3 = SIMD.Float32x4.mul(row0, tmp1);
+            tmp1 = SIMD.Float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
+            minor0 = SIMD.Float32x4.sub(minor0, SIMD.Float32x4.mul(row3, tmp1));
+            minor3 = SIMD.Float32x4.sub(SIMD.Float32x4.mul(row0, tmp1), minor3);
+            minor3 = SIMD.Float32x4.swizzle(minor3, 2, 3, 0, 1); // 0x4E = 01001110
 
 
             // ----
             // ----
-            tmp1 = SIMD.float32x4.mul(SIMD.float32x4.swizzle(row1, 2, 3, 0, 1), row3); // 0x4E = 01001110
-            tmp1 = SIMD.float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
-            row2 = SIMD.float32x4.swizzle(row2, 2, 3, 0, 1);  // 0x4E = 01001110
-            minor0 = SIMD.float32x4.add(SIMD.float32x4.mul(row2, tmp1), minor0);
-            minor2 = SIMD.float32x4.mul(row0, tmp1);
-            tmp1 = SIMD.float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
-            minor0 = SIMD.float32x4.sub(minor0, SIMD.float32x4.mul(row2, tmp1));
-            minor2 = SIMD.float32x4.sub(SIMD.float32x4.mul(row0, tmp1), minor2);
-            minor2 = SIMD.float32x4.swizzle(minor2, 2, 3, 0, 1); // 0x4E = 01001110
+            tmp1 = SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(row1, 2, 3, 0, 1), row3); // 0x4E = 01001110
+            tmp1 = SIMD.Float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
+            row2 = SIMD.Float32x4.swizzle(row2, 2, 3, 0, 1);  // 0x4E = 01001110
+            minor0 = SIMD.Float32x4.add(SIMD.Float32x4.mul(row2, tmp1), minor0);
+            var minor2 = SIMD.Float32x4.mul(row0, tmp1);
+            tmp1 = SIMD.Float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
+            minor0 = SIMD.Float32x4.sub(minor0, SIMD.Float32x4.mul(row2, tmp1));
+            minor2 = SIMD.Float32x4.sub(SIMD.Float32x4.mul(row0, tmp1), minor2);
+            minor2 = SIMD.Float32x4.swizzle(minor2, 2, 3, 0, 1); // 0x4E = 01001110
 
 
             // ----
             // ----
-            tmp1 = SIMD.float32x4.mul(row0, row1);
-            tmp1 = SIMD.float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
-            minor2 = SIMD.float32x4.add(SIMD.float32x4.mul(row3, tmp1), minor2);
-            minor3 = SIMD.float32x4.sub(SIMD.float32x4.mul(row2, tmp1), minor3);
-            tmp1 = SIMD.float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
-            minor2 = SIMD.float32x4.sub(SIMD.float32x4.mul(row3, tmp1), minor2);
-            minor3 = SIMD.float32x4.sub(minor3, SIMD.float32x4.mul(row2, tmp1));
+            tmp1 = SIMD.Float32x4.mul(row0, row1);
+            tmp1 = SIMD.Float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
+            minor2 = SIMD.Float32x4.add(SIMD.Float32x4.mul(row3, tmp1), minor2);
+            minor3 = SIMD.Float32x4.sub(SIMD.Float32x4.mul(row2, tmp1), minor3);
+            tmp1 = SIMD.Float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
+            minor2 = SIMD.Float32x4.sub(SIMD.Float32x4.mul(row3, tmp1), minor2);
+            minor3 = SIMD.Float32x4.sub(minor3, SIMD.Float32x4.mul(row2, tmp1));
 
 
             // ----
             // ----
-            tmp1 = SIMD.float32x4.mul(row0, row3);
-            tmp1 = SIMD.float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
-            minor1 = SIMD.float32x4.sub(minor1, SIMD.float32x4.mul(row2, tmp1));
-            minor2 = SIMD.float32x4.add(SIMD.float32x4.mul(row1, tmp1), minor2);
-            tmp1 = SIMD.float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
-            minor1 = SIMD.float32x4.add(SIMD.float32x4.mul(row2, tmp1), minor1);
-            minor2 = SIMD.float32x4.sub(minor2, SIMD.float32x4.mul(row1, tmp1));
+            tmp1 = SIMD.Float32x4.mul(row0, row3);
+            tmp1 = SIMD.Float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
+            minor1 = SIMD.Float32x4.sub(minor1, SIMD.Float32x4.mul(row2, tmp1));
+            minor2 = SIMD.Float32x4.add(SIMD.Float32x4.mul(row1, tmp1), minor2);
+            tmp1 = SIMD.Float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
+            minor1 = SIMD.Float32x4.add(SIMD.Float32x4.mul(row2, tmp1), minor1);
+            minor2 = SIMD.Float32x4.sub(minor2, SIMD.Float32x4.mul(row1, tmp1));
 
 
             // ----
             // ----
-            tmp1 = SIMD.float32x4.mul(row0, row2);
-            tmp1 = SIMD.float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
-            minor1 = SIMD.float32x4.add(SIMD.float32x4.mul(row3, tmp1), minor1);
-            minor3 = SIMD.float32x4.sub(minor3, SIMD.float32x4.mul(row1, tmp1));
-            tmp1 = SIMD.float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
-            minor1 = SIMD.float32x4.sub(minor1, SIMD.float32x4.mul(row3, tmp1));
-            minor3 = SIMD.float32x4.add(SIMD.float32x4.mul(row1, tmp1), minor3);
+            tmp1 = SIMD.Float32x4.mul(row0, row2);
+            tmp1 = SIMD.Float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
+            minor1 = SIMD.Float32x4.add(SIMD.Float32x4.mul(row3, tmp1), minor1);
+            minor3 = SIMD.Float32x4.sub(minor3, SIMD.Float32x4.mul(row1, tmp1));
+            tmp1 = SIMD.Float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
+            minor1 = SIMD.Float32x4.sub(minor1, SIMD.Float32x4.mul(row3, tmp1));
+            minor3 = SIMD.Float32x4.add(SIMD.Float32x4.mul(row1, tmp1), minor3);
 
 
             // Compute determinant
             // Compute determinant
-            det = SIMD.float32x4.mul(row0, minor0);
-            det = SIMD.float32x4.add(SIMD.float32x4.swizzle(det, 2, 3, 0, 1), det); // 0x4E = 01001110
-            det = SIMD.float32x4.add(SIMD.float32x4.swizzle(det, 1, 0, 3, 2), det); // 0xB1 = 10110001
-            tmp1 = SIMD.float32x4.reciprocalApproximation(det);
-            det = SIMD.float32x4.sub(SIMD.float32x4.add(tmp1, tmp1), SIMD.float32x4.mul(det, SIMD.float32x4.mul(tmp1, tmp1)));
-            det = SIMD.float32x4.swizzle(det, 0, 0, 0, 0);
+            var det = SIMD.Float32x4.mul(row0, minor0);
+            det = SIMD.Float32x4.add(SIMD.Float32x4.swizzle(det, 2, 3, 0, 1), det); // 0x4E = 01001110
+            det = SIMD.Float32x4.add(SIMD.Float32x4.swizzle(det, 1, 0, 3, 2), det); // 0xB1 = 10110001
+            tmp1 = SIMD.Float32x4.reciprocalApproximation(det);
+            det = SIMD.Float32x4.sub(SIMD.Float32x4.add(tmp1, tmp1), SIMD.Float32x4.mul(det, SIMD.Float32x4.mul(tmp1, tmp1)));
+            det = SIMD.Float32x4.swizzle(det, 0, 0, 0, 0);
 
 
             // These shuffles aren't necessary if the faulty transposition is done
             // These shuffles aren't necessary if the faulty transposition is done
             // up at the top of this function.
             // up at the top of this function.
-            //minor0 = SIMD.float32x4.swizzle(minor0, 2, 1, 0, 3);
-            //minor1 = SIMD.float32x4.swizzle(minor1, 2, 1, 0, 3);
-            //minor2 = SIMD.float32x4.swizzle(minor2, 2, 1, 0, 3);
-            //minor3 = SIMD.float32x4.swizzle(minor3, 2, 1, 0, 3);
+            //minor0 =SIMD.Float32x4.swizzle(minor0, 2, 1, 0, 3);
+            //minor1 =SIMD.Float32x4.swizzle(minor1, 2, 1, 0, 3);
+            //minor2 =SIMD.Float32x4.swizzle(minor2, 2, 1, 0, 3);
+            //minor3 =SIMD.Float32x4.swizzle(minor3, 2, 1, 0, 3);
 
 
             // Compute final values by multiplying with 1/det
             // Compute final values by multiplying with 1/det
-            minor0 = SIMD.float32x4.mul(det, minor0);
-            minor1 = SIMD.float32x4.mul(det, minor1);
-            minor2 = SIMD.float32x4.mul(det, minor2);
-            minor3 = SIMD.float32x4.mul(det, minor3);
-
-            SIMD.float32x4.store(dest, 0, minor0);
-            SIMD.float32x4.store(dest, 4, minor1);
-            SIMD.float32x4.store(dest, 8, minor2);
-            SIMD.float32x4.store(dest, 12, minor3);
+            SIMD.Float32x4.store(dest, 0, SIMD.Float32x4.mul(det, minor0));
+            SIMD.Float32x4.store(dest, 4, SIMD.Float32x4.mul(det, minor1));
+            SIMD.Float32x4.store(dest, 8, minor2 = SIMD.Float32x4.mul(det, minor2));
+            SIMD.Float32x4.store(dest, 12, SIMD.Float32x4.mul(det, minor3));
 
 
             return (<any>this);
             return (<any>this);
         }
         }
 
 
         public static LookAtLHToRefSIMD(eyeRef: Vector3, targetRef: Vector3, upRef: Vector3, result: Matrix): void {
         public static LookAtLHToRefSIMD(eyeRef: Vector3, targetRef: Vector3, upRef: Vector3, result: Matrix): void {
             var out = result.m;
             var out = result.m;
-            var center = SIMD.float32x4(targetRef.x, targetRef.y, targetRef.z, 0);
-            var eye = SIMD.float32x4(eyeRef.x, eyeRef.y, eyeRef.z, 0);
-            var up = SIMD.float32x4(upRef.x, upRef.y, upRef.z, 0);
+            var center = SIMD.Float32x4(targetRef.x, targetRef.y, targetRef.z, 0.0);
+            var eye = SIMD.Float32x4(eyeRef.x, eyeRef.y, eyeRef.z, 0.0);
+            var up = SIMD.Float32x4(upRef.x, upRef.y, upRef.z, 0.0);
 
 
             // cc.kmVec3Subtract(f, pCenter, pEye);
             // cc.kmVec3Subtract(f, pCenter, pEye);
-            var f = SIMD.float32x4.sub(center, eye);
+            var f = SIMD.Float32x4.sub(center, eye);
             // cc.kmVec3Normalize(f, f);    
             // cc.kmVec3Normalize(f, f);    
-            var tmp = SIMD.float32x4.mul(f, f);
-            tmp = SIMD.float32x4.add(tmp, SIMD.float32x4.add(SIMD.float32x4.swizzle(tmp, 1, 2, 0, 3), SIMD.float32x4.swizzle(tmp, 2, 0, 1, 3)));
-            f = SIMD.float32x4.mul(f, SIMD.float32x4.reciprocalSqrtApproximation(tmp));
+            var tmp = SIMD.Float32x4.mul(f, f);
+            tmp = SIMD.Float32x4.add(tmp, SIMD.Float32x4.add(SIMD.Float32x4.swizzle(tmp, 1, 2, 0, 3), SIMD.Float32x4.swizzle(tmp, 2, 0, 1, 3)));
+            f = SIMD.Float32x4.mul(f, SIMD.Float32x4.reciprocalSqrtApproximation(tmp));
 
 
             // cc.kmVec3Assign(up, pUp);
             // cc.kmVec3Assign(up, pUp);
             // cc.kmVec3Normalize(up, up);
             // cc.kmVec3Normalize(up, up);
-            tmp = SIMD.float32x4.mul(up, up);
-            tmp = SIMD.float32x4.add(tmp, SIMD.float32x4.add(SIMD.float32x4.swizzle(tmp, 1, 2, 0, 3), SIMD.float32x4.swizzle(tmp, 2, 0, 1, 3)));
-            up = SIMD.float32x4.mul(up, SIMD.float32x4.reciprocalSqrtApproximation(tmp));
+            tmp = SIMD.Float32x4.mul(up, up);
+            tmp = SIMD.Float32x4.add(tmp, SIMD.Float32x4.add(SIMD.Float32x4.swizzle(tmp, 1, 2, 0, 3), SIMD.Float32x4.swizzle(tmp, 2, 0, 1, 3)));
+            up = SIMD.Float32x4.mul(up, SIMD.Float32x4.reciprocalSqrtApproximation(tmp));
             // cc.kmVec3Cross(s, f, up);
             // cc.kmVec3Cross(s, f, up);
-            var s = SIMD.float32x4.sub(SIMD.float32x4.mul(SIMD.float32x4.swizzle(f, 1, 2, 0, 3), SIMD.float32x4.swizzle(up, 2, 0, 1, 3)), SIMD.float32x4.mul(SIMD.float32x4.swizzle(f, 2, 0, 1, 3), SIMD.float32x4.swizzle(up, 1, 2, 0, 3)));
+            var s = SIMD.Float32x4.sub(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(f, 1, 2, 0, 3), SIMD.Float32x4.swizzle(up, 2, 0, 1, 3)), SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(f, 2, 0, 1, 3), SIMD.Float32x4.swizzle(up, 1, 2, 0, 3)));
             // cc.kmVec3Normalize(s, s);
             // cc.kmVec3Normalize(s, s);
-            tmp = SIMD.float32x4.mul(s, s);
-            tmp = SIMD.float32x4.add(tmp, SIMD.float32x4.add(SIMD.float32x4.swizzle(tmp, 1, 2, 0, 3), SIMD.float32x4.swizzle(tmp, 2, 0, 1, 3)));
-            s = SIMD.float32x4.mul(s, SIMD.float32x4.reciprocalSqrtApproximation(tmp));
+            tmp = SIMD.Float32x4.mul(s, s);
+            tmp = SIMD.Float32x4.add(tmp, SIMD.Float32x4.add(SIMD.Float32x4.swizzle(tmp, 1, 2, 0, 3), SIMD.Float32x4.swizzle(tmp, 2, 0, 1, 3)));
+            s = SIMD.Float32x4.mul(s, SIMD.Float32x4.reciprocalSqrtApproximation(tmp));
             // cc.kmVec3Cross(u, s, f);
             // cc.kmVec3Cross(u, s, f);
-            var u = SIMD.float32x4.sub(SIMD.float32x4.mul(SIMD.float32x4.swizzle(s, 1, 2, 0, 3), SIMD.float32x4.swizzle(f, 2, 0, 1, 3)), SIMD.float32x4.mul(SIMD.float32x4.swizzle(s, 2, 0, 1, 3), SIMD.float32x4.swizzle(f, 1, 2, 0, 3)));
+            var u = SIMD.Float32x4.sub(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(s, 1, 2, 0, 3), SIMD.Float32x4.swizzle(f, 2, 0, 1, 3)), SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(s, 2, 0, 1, 3), SIMD.Float32x4.swizzle(f, 1, 2, 0, 3)));
             // cc.kmVec3Normalize(s, s);
             // cc.kmVec3Normalize(s, s);
-            tmp = SIMD.float32x4.mul(s, s);
-            tmp = SIMD.float32x4.add(tmp, SIMD.float32x4.add(SIMD.float32x4.swizzle(tmp, 1, 2, 0, 3), SIMD.float32x4.swizzle(tmp, 2, 0, 1, 3)));
-            s = SIMD.float32x4.mul(s, SIMD.float32x4.reciprocalSqrtApproximation(tmp));
-
-            var zero = SIMD.float32x4.splat(0.0);
-            s = SIMD.float32x4.neg(s);
-            var tmp01 = SIMD.float32x4.shuffle(s, u, 0, 1, 4, 5);
-            var tmp23 = SIMD.float32x4.shuffle(f, zero, 0, 1, 4, 5);
-            var a0 = SIMD.float32x4.shuffle(tmp01, tmp23, 0, 2, 4, 6);
-            var a1 = SIMD.float32x4.shuffle(tmp01, tmp23, 1, 3, 5, 7);
-            tmp01 = SIMD.float32x4.shuffle(s, u, 2, 3, 6, 7);
-            tmp23 = SIMD.float32x4.shuffle(f, zero, 2, 3, 6, 7);
-            var a2 = SIMD.float32x4.shuffle(tmp01, tmp23, 0, 2, 4, 6);
-            var a3 = SIMD.float32x4(0.0, 0.0, 0.0, 1.0);
-            var b0 = SIMD.float32x4(1.0, 0.0, 0.0, 0.0);
-            var b1 = SIMD.float32x4(0.0, 1.0, 0.0, 0.0);
-            var b2 = SIMD.float32x4(0.0, 0.0, 1.0, 0.0);
-            var b3 = SIMD.float32x4.neg(eye);
-            b3 = SIMD.float32x4.withW(b3, 1.0);
-
-            SIMD.float32x4.store(out, 0, SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(b0, 0, 0, 0, 0), a0), SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(b0, 1, 1, 1, 1), a1), SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(b0, 2, 2, 2, 2), a2), SIMD.float32x4.mul(SIMD.float32x4.swizzle(b0, 3, 3, 3, 3), a3)))));
-            SIMD.float32x4.store(out, 4, SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(b1, 0, 0, 0, 0), a0), SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(b1, 1, 1, 1, 1), a1), SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(b1, 2, 2, 2, 2), a2), SIMD.float32x4.mul(SIMD.float32x4.swizzle(b1, 3, 3, 3, 3), a3)))));
-            SIMD.float32x4.store(out, 8, SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(b2, 0, 0, 0, 0), a0), SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(b2, 1, 1, 1, 1), a1), SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(b2, 2, 2, 2, 2), a2), SIMD.float32x4.mul(SIMD.float32x4.swizzle(b2, 3, 3, 3, 3), a3)))));
-            SIMD.float32x4.store(out, 12, SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(b3, 0, 0, 0, 0), a0), SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(b3, 1, 1, 1, 1), a1), SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(b3, 2, 2, 2, 2), a2), SIMD.float32x4.mul(SIMD.float32x4.swizzle(b3, 3, 3, 3, 3), a3)))));
+            tmp = SIMD.Float32x4.mul(s, s);
+            tmp = SIMD.Float32x4.add(tmp, SIMD.Float32x4.add(SIMD.Float32x4.swizzle(tmp, 1, 2, 0, 3), SIMD.Float32x4.swizzle(tmp, 2, 0, 1, 3)));
+            s = SIMD.Float32x4.mul(s, SIMD.Float32x4.reciprocalSqrtApproximation(tmp));
+
+            var zero = SIMD.Float32x4.splat(0.0);
+            s = SIMD.Float32x4.neg(s);
+            var tmp01 = SIMD.Float32x4.shuffle(s, u, 0, 1, 4, 5);
+            var tmp23 = SIMD.Float32x4.shuffle(f, zero, 0, 1, 4, 5);
+            var a0 = SIMD.Float32x4.shuffle(tmp01, tmp23, 0, 2, 4, 6);
+            var a1 = SIMD.Float32x4.shuffle(tmp01, tmp23, 1, 3, 5, 7);
+            var a2 = SIMD.Float32x4.shuffle(SIMD.Float32x4.shuffle(s, u, 2, 3, 6, 7), SIMD.Float32x4.shuffle(f, zero, 2, 3, 6, 7), 0, 2, 4, 6);
+            var a3 = SIMD.Float32x4(0.0, 0.0, 0.0, 1.0);
+
+            var b = SIMD.Float32x4(1.0, 0.0, 0.0, 0.0);
+            SIMD.Float32x4.store(out, 0, SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 0, 0, 0, 0), a0), SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 1, 1, 1, 1), a1), SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 2, 2, 2, 2), a2), SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 3, 3, 3, 3), a3)))));
+
+            b = SIMD.Float32x4(0.0, 1.0, 0.0, 0.0);
+            SIMD.Float32x4.store(out, 4, SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 0, 0, 0, 0), a0), SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 1, 1, 1, 1), a1), SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 2, 2, 2, 2), a2), SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 3, 3, 3, 3), a3)))));
+
+            b = SIMD.Float32x4(0.0, 0.0, 1.0, 0.0);
+            SIMD.Float32x4.store(out, 8, SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 0, 0, 0, 0), a0), SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 1, 1, 1, 1), a1), SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 2, 2, 2, 2), a2), SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 3, 3, 3, 3), a3)))));
+
+            b = SIMD.Float32x4.replaceLane(SIMD.Float32x4.neg(eye), 3, 1.0);
+            SIMD.Float32x4.store(out, 12, SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 0, 0, 0, 0), a0), SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 1, 1, 1, 1), a1), SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 2, 2, 2, 2), a2), SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b, 3, 3, 3, 3), a3)))));
+
         }
         }
     }
     }
 
 
@@ -268,54 +234,47 @@
 
 
         public static DisableSIMD(): void {
         public static DisableSIMD(): void {
             // Replace functions
             // Replace functions
-            Matrix.prototype.multiplyToArray = <any>previousMultiplyToArray;
-            Matrix.prototype.invertToRef = <any>previousInvertToRef;
-            Matrix.LookAtLHToRef = <any>previousLookAtLHToRef;
-            Vector3.TransformCoordinatesToRef = <any>previousTransformCoordinatesToRef;
-            Vector3.TransformCoordinatesFromFloatsToRef = <any>previousTransformCoordinatesFromFloatsToRef;
+            Matrix.prototype.multiplyToArray = previousMultiplyToArray;
+            Matrix.prototype.invertToRef = previousInvertToRef;
+            Matrix.LookAtLHToRef = previousLookAtLHToRef;
+            Vector3.TransformCoordinatesToRef = previousTransformCoordinatesToRef;
+            Vector3.TransformCoordinatesFromFloatsToRef = previousTransformCoordinatesFromFloatsToRef;
 
 
             SIMDHelper._isEnabled = false;
             SIMDHelper._isEnabled = false;
         }
         }
 
 
         public static EnableSIMD(): void {
         public static EnableSIMD(): void {
-            if (window.SIMD === undefined) {
+            if (self.SIMD === undefined) {
                 return;
                 return;
             }
             }
 
 
+            // check if polyfills needed
+            if (!self.Math.fround) {
+                self.Math.fround = (array => x => {
+                    return array[0] = x, array[0];
+                })(new Float32Array(1));
+            }
+
+            if (!self.Math.imul) {
+                self.Math.imul = (a, b) => {
+                    var ah = (a >>> 16) & 0xffff;
+                    var al = a & 0xffff;
+                    var bh = (b >>> 16) & 0xffff;
+                    var bl = b & 0xffff;
+                    // the shift by 0 fixes the sign on the high part
+                    // the final |0 converts the unsigned value into a signed value
+                    return ((al * bl) + (((ah * bl + al * bh) << 16) >>> 0) | 0);
+                };
+            }
+
             // Replace functions
             // Replace functions
-            Matrix.prototype.multiplyToArray = <any>SIMDMatrix.prototype.multiplyToArraySIMD;
-            Matrix.prototype.invertToRef = <any>SIMDMatrix.prototype.invertToRefSIMD;
-            Matrix.LookAtLHToRef = <any>SIMDMatrix.LookAtLHToRefSIMD;
-            Vector3.TransformCoordinatesToRef = <any>SIMDVector3.TransformCoordinatesToRefSIMD;
-            Vector3.TransformCoordinatesFromFloatsToRef = <any>SIMDVector3.TransformCoordinatesFromFloatsToRefSIMD;
-
-            Object.defineProperty(Vector3.prototype, "x", {
-                get() { return this._data[0]; },
-                set(value: number) {
-                    if (!this._data) {
-                        this._data = new Float32Array(3);
-                    }
-                    this._data[0] = value;
-                }
-            });
-
-            Object.defineProperty(Vector3.prototype, "y", {
-                get() { return this._data[1]; },
-                set(value: number) {
-                    this._data[1] = value;
-                }
-            });
-
-            Object.defineProperty(Vector3.prototype, "z", {
-                get() { return this._data[2]; },
-                set(value: number) {
-                    this._data[2] = value;
-                }
-            });
+            Matrix.prototype.multiplyToArray = SIMDMatrix.prototype.multiplyToArraySIMD;
+            Matrix.prototype.invertToRef = SIMDMatrix.prototype.invertToRefSIMD;
+            Matrix.LookAtLHToRef = SIMDMatrix.LookAtLHToRefSIMD;
+            Vector3.TransformCoordinatesToRef = SIMDVector3.TransformCoordinatesToRefSIMD;
+            Vector3.TransformCoordinatesFromFloatsToRef = SIMDVector3.TransformCoordinatesFromFloatsToRefSIMD;
 
 
             SIMDHelper._isEnabled = true;
             SIMDHelper._isEnabled = true;
         }
         }
     }
     }
 }
 }
-
-

+ 66 - 3
src/Math/babylon.math.js

@@ -2258,6 +2258,32 @@ var BABYLON;
             var ez = -Vector3.Dot(this._zAxis, eye);
             var ez = -Vector3.Dot(this._zAxis, eye);
             return Matrix.FromValuesToRef(this._xAxis.x, this._yAxis.x, this._zAxis.x, 0, this._xAxis.y, this._yAxis.y, this._zAxis.y, 0, this._xAxis.z, this._yAxis.z, this._zAxis.z, 0, ex, ey, ez, 1, result);
             return Matrix.FromValuesToRef(this._xAxis.x, this._yAxis.x, this._zAxis.x, 0, this._xAxis.y, this._yAxis.y, this._zAxis.y, 0, this._xAxis.z, this._yAxis.z, this._zAxis.z, 0, ex, ey, ez, 1, result);
         };
         };
+        Matrix.LookAtRH = function (eye, target, up) {
+            var result = Matrix.Zero();
+            Matrix.LookAtRHToRef(eye, target, up, result);
+            return result;
+        };
+        Matrix.LookAtRHToRef = function (eye, target, up, result) {
+            // Z axis
+            eye.subtractToRef(target, this._zAxis);
+            this._zAxis.normalize();
+            // X axis
+            Vector3.CrossToRef(up, this._zAxis, this._xAxis);
+            if (this._xAxis.lengthSquared() === 0) {
+                this._xAxis.x = 1.0;
+            }
+            else {
+                this._xAxis.normalize();
+            }
+            // Y axis
+            Vector3.CrossToRef(this._zAxis, this._xAxis, this._yAxis);
+            this._yAxis.normalize();
+            // Eye angles
+            var ex = -Vector3.Dot(this._xAxis, eye);
+            var ey = -Vector3.Dot(this._yAxis, eye);
+            var ez = -Vector3.Dot(this._zAxis, eye);
+            return Matrix.FromValuesToRef(this._xAxis.x, this._yAxis.x, this._zAxis.x, 0, this._xAxis.y, this._yAxis.y, this._zAxis.y, 0, this._xAxis.z, this._yAxis.z, this._zAxis.z, 0, ex, ey, ez, 1, result);
+        };
         Matrix.OrthoLH = function (width, height, znear, zfar) {
         Matrix.OrthoLH = function (width, height, znear, zfar) {
             var matrix = Matrix.Zero();
             var matrix = Matrix.Zero();
             Matrix.OrthoLHToRef(width, height, znear, zfar, matrix);
             Matrix.OrthoLHToRef(width, height, znear, zfar, matrix);
@@ -2280,13 +2306,22 @@ var BABYLON;
             result.m[1] = result.m[2] = result.m[3] = 0;
             result.m[1] = result.m[2] = result.m[3] = 0;
             result.m[5] = 2.0 / (top - bottom);
             result.m[5] = 2.0 / (top - bottom);
             result.m[4] = result.m[6] = result.m[7] = 0;
             result.m[4] = result.m[6] = result.m[7] = 0;
-            result.m[10] = -1.0 / (znear - zfar);
+            result.m[10] = 1.0 / (zfar - znear);
             result.m[8] = result.m[9] = result.m[11] = 0;
             result.m[8] = result.m[9] = result.m[11] = 0;
             result.m[12] = (left + right) / (left - right);
             result.m[12] = (left + right) / (left - right);
             result.m[13] = (top + bottom) / (bottom - top);
             result.m[13] = (top + bottom) / (bottom - top);
-            result.m[14] = znear / (znear - zfar);
+            result.m[14] = -znear / (zfar - znear);
             result.m[15] = 1.0;
             result.m[15] = 1.0;
         };
         };
+        Matrix.OrthoOffCenterRH = function (left, right, bottom, top, znear, zfar) {
+            var matrix = Matrix.Zero();
+            Matrix.OrthoOffCenterRHToRef(left, right, bottom, top, znear, zfar, matrix);
+            return matrix;
+        };
+        Matrix.OrthoOffCenterRHToRef = function (left, right, bottom, top, znear, zfar, result) {
+            Matrix.OrthoOffCenterLHToRef(left, right, bottom, top, znear, zfar, result);
+            result.m[10] *= -1.0;
+        };
         Matrix.PerspectiveLH = function (width, height, znear, zfar) {
         Matrix.PerspectiveLH = function (width, height, znear, zfar) {
             var matrix = Matrix.Zero();
             var matrix = Matrix.Zero();
             matrix.m[0] = (2.0 * znear) / width;
             matrix.m[0] = (2.0 * znear) / width;
@@ -2323,9 +2358,37 @@ var BABYLON;
             }
             }
             result.m[4] = result.m[6] = result.m[7] = 0.0;
             result.m[4] = result.m[6] = result.m[7] = 0.0;
             result.m[8] = result.m[9] = 0.0;
             result.m[8] = result.m[9] = 0.0;
-            result.m[10] = -zfar / (znear - zfar);
+            result.m[10] = zfar / (zfar - znear);
             result.m[11] = 1.0;
             result.m[11] = 1.0;
             result.m[12] = result.m[13] = result.m[15] = 0.0;
             result.m[12] = result.m[13] = result.m[15] = 0.0;
+            result.m[14] = -(znear * zfar) / (zfar - znear);
+        };
+        Matrix.PerspectiveFovRH = function (fov, aspect, znear, zfar) {
+            var matrix = Matrix.Zero();
+            Matrix.PerspectiveFovRHToRef(fov, aspect, znear, zfar, matrix);
+            return matrix;
+        };
+        Matrix.PerspectiveFovRHToRef = function (fov, aspect, znear, zfar, result, isVerticalFovFixed) {
+            if (isVerticalFovFixed === void 0) { isVerticalFovFixed = true; }
+            var tan = 1.0 / (Math.tan(fov * 0.5));
+            if (isVerticalFovFixed) {
+                result.m[0] = tan / aspect;
+            }
+            else {
+                result.m[0] = tan;
+            }
+            result.m[1] = result.m[2] = result.m[3] = 0.0;
+            if (isVerticalFovFixed) {
+                result.m[5] = tan;
+            }
+            else {
+                result.m[5] = tan * aspect;
+            }
+            result.m[4] = result.m[6] = result.m[7] = 0.0;
+            result.m[8] = result.m[9] = 0.0;
+            result.m[10] = zfar / (znear - zfar);
+            result.m[11] = -1.0;
+            result.m[12] = result.m[13] = result.m[15] = 0.0;
             result.m[14] = (znear * zfar) / (znear - zfar);
             result.m[14] = (znear * zfar) / (znear - zfar);
         };
         };
         Matrix.PerspectiveFovWebVRToRef = function (fov, znear, zfar, result, isVerticalFovFixed) {
         Matrix.PerspectiveFovWebVRToRef = function (fov, znear, zfar, result, isVerticalFovFixed) {

+ 90 - 6
src/Math/babylon.math.ts

@@ -737,7 +737,6 @@
     export class Vector3 {
     export class Vector3 {
 
 
         constructor(public x: number, public y: number, public z: number) {
         constructor(public x: number, public y: number, public z: number) {
-
         }
         }
 
 
         public toString(): string {
         public toString(): string {
@@ -757,7 +756,7 @@
 
 
         // Operators
         // Operators
         public asArray(): number[] {
         public asArray(): number[] {
-            var result = [];
+            var result: number[] = [];
 
 
             this.toArray(result, 0);
             this.toArray(result, 0);
 
 
@@ -2828,6 +2827,43 @@
                 ex, ey, ez, 1, result);
                 ex, ey, ez, 1, result);
         }
         }
 
 
+        public static LookAtRH(eye: Vector3, target: Vector3, up: Vector3): Matrix {
+            var result = Matrix.Zero();
+
+            Matrix.LookAtRHToRef(eye, target, up, result);
+
+            return result;
+        }
+
+        public static LookAtRHToRef(eye: Vector3, target: Vector3, up: Vector3, result: Matrix): void {
+            // Z axis
+            eye.subtractToRef(target, this._zAxis);
+            this._zAxis.normalize();
+
+            // X axis
+            Vector3.CrossToRef(up, this._zAxis, this._xAxis);
+
+            if (this._xAxis.lengthSquared() === 0) {
+                this._xAxis.x = 1.0;
+            } else {
+                this._xAxis.normalize();
+            }
+
+            // Y axis
+            Vector3.CrossToRef(this._zAxis, this._xAxis, this._yAxis);
+            this._yAxis.normalize();
+
+            // Eye angles
+            var ex = -Vector3.Dot(this._xAxis, eye);
+            var ey = -Vector3.Dot(this._yAxis, eye);
+            var ez = -Vector3.Dot(this._zAxis, eye);
+
+            return Matrix.FromValuesToRef(this._xAxis.x, this._yAxis.x, this._zAxis.x, 0,
+                this._xAxis.y, this._yAxis.y, this._zAxis.y, 0,
+                this._xAxis.z, this._yAxis.z, this._zAxis.z, 0,
+                ex, ey, ez, 1, result);
+        }
+
         public static OrthoLH(width: number, height: number, znear: number, zfar: number): Matrix {
         public static OrthoLH(width: number, height: number, znear: number, zfar: number): Matrix {
             var matrix = Matrix.Zero();
             var matrix = Matrix.Zero();
 
 
@@ -2861,14 +2897,27 @@
             result.m[1] = result.m[2] = result.m[3] = 0;
             result.m[1] = result.m[2] = result.m[3] = 0;
             result.m[5] = 2.0 / (top - bottom);
             result.m[5] = 2.0 / (top - bottom);
             result.m[4] = result.m[6] = result.m[7] = 0;
             result.m[4] = result.m[6] = result.m[7] = 0;
-            result.m[10] = -1.0 / (znear - zfar);
+            result.m[10] = 1.0 / (zfar - znear);
             result.m[8] = result.m[9] = result.m[11] = 0;
             result.m[8] = result.m[9] = result.m[11] = 0;
             result.m[12] = (left + right) / (left - right);
             result.m[12] = (left + right) / (left - right);
             result.m[13] = (top + bottom) / (bottom - top);
             result.m[13] = (top + bottom) / (bottom - top);
-            result.m[14] = znear / (znear - zfar);
+            result.m[14] = -znear / (zfar - znear);
             result.m[15] = 1.0;
             result.m[15] = 1.0;
         }
         }
 
 
+        public static OrthoOffCenterRH(left: number, right: number, bottom: number, top: number, znear: number, zfar: number): Matrix {
+            var matrix = Matrix.Zero();
+
+            Matrix.OrthoOffCenterRHToRef(left, right, bottom, top, znear, zfar, matrix);
+
+            return matrix;
+        }
+
+        public static OrthoOffCenterRHToRef(left: number, right, bottom: number, top: number, znear: number, zfar: number, result: Matrix): void {
+            Matrix.OrthoOffCenterLHToRef(left, right, bottom, top, znear, zfar, result);
+            result.m[10] *= -1.0;
+        }
+
         public static PerspectiveLH(width: number, height: number, znear: number, zfar: number): Matrix {
         public static PerspectiveLH(width: number, height: number, znear: number, zfar: number): Matrix {
             var matrix = Matrix.Zero();
             var matrix = Matrix.Zero();
 
 
@@ -2914,13 +2963,48 @@
 
 
             result.m[4] = result.m[6] = result.m[7] = 0.0;
             result.m[4] = result.m[6] = result.m[7] = 0.0;
             result.m[8] = result.m[9] = 0.0;
             result.m[8] = result.m[9] = 0.0;
-            result.m[10] = -zfar / (znear - zfar);
+            result.m[10] = zfar / (zfar - znear);
             result.m[11] = 1.0;
             result.m[11] = 1.0;
             result.m[12] = result.m[13] = result.m[15] = 0.0;
             result.m[12] = result.m[13] = result.m[15] = 0.0;
+            result.m[14] = -(znear * zfar) / (zfar - znear);
+        }
+
+        public static PerspectiveFovRH(fov: number, aspect: number, znear: number, zfar: number): Matrix {
+            var matrix = Matrix.Zero();
+
+            Matrix.PerspectiveFovRHToRef(fov, aspect, znear, zfar, matrix);
+
+            return matrix;
+        }
+
+        public static PerspectiveFovRHToRef(fov: number, aspect: number, znear: number, zfar: number, result: Matrix, isVerticalFovFixed = true): void {
+            var tan = 1.0 / (Math.tan(fov * 0.5));
+
+            if (isVerticalFovFixed) {
+                result.m[0] = tan / aspect;
+            }
+            else {
+                result.m[0] = tan;
+            }
+
+            result.m[1] = result.m[2] = result.m[3] = 0.0;
+
+            if (isVerticalFovFixed) {
+                result.m[5] = tan;
+            }
+            else {
+                result.m[5] = tan * aspect;
+            }
+
+            result.m[4] = result.m[6] = result.m[7] = 0.0;
+            result.m[8] = result.m[9] = 0.0;
+            result.m[10] = zfar / (znear - zfar);
+            result.m[11] = -1.0;
+            result.m[12] = result.m[13] = result.m[15] = 0.0;
             result.m[14] = (znear * zfar) / (znear - zfar);
             result.m[14] = (znear * zfar) / (znear - zfar);
         }
         }
 
 
-        public static PerspectiveFovWebVRToRef(fov, znear: number, zfar: number, result: Matrix, isVerticalFovFixed = true) {
+        public static PerspectiveFovWebVRToRef(fov, znear: number, zfar: number, result: Matrix, isVerticalFovFixed = true): void {
             var upTan = Math.tan(fov.upDegrees * Math.PI / 180.0);
             var upTan = Math.tan(fov.upDegrees * Math.PI / 180.0);
             var downTan = Math.tan(fov.downDegrees * Math.PI / 180.0);
             var downTan = Math.tan(fov.downDegrees * Math.PI / 180.0);
             var leftTan = Math.tan(fov.leftDegrees * Math.PI / 180.0);
             var leftTan = Math.tan(fov.leftDegrees * Math.PI / 180.0);

+ 8 - 0
src/Mesh/babylon.abstractMesh.js

@@ -997,6 +997,14 @@ var BABYLON;
                 if (meshIndex !== -1) {
                 if (meshIndex !== -1) {
                     light.excludedMeshes.splice(meshIndex, 1);
                     light.excludedMeshes.splice(meshIndex, 1);
                 }
                 }
+                // Shadow generators
+                var generator = light.getShadowGenerator();
+                if (generator) {
+                    meshIndex = generator.getShadowMap().renderList.indexOf(_this);
+                    if (meshIndex !== -1) {
+                        generator.getShadowMap().renderList.splice(meshIndex, 1);
+                    }
+                }
             });
             });
             // Edges
             // Edges
             if (this._edgesRenderer) {
             if (this._edgesRenderer) {

+ 10 - 0
src/Mesh/babylon.abstractMesh.ts

@@ -1162,6 +1162,16 @@
                 if (meshIndex !== -1) {
                 if (meshIndex !== -1) {
                     light.excludedMeshes.splice(meshIndex, 1);
                     light.excludedMeshes.splice(meshIndex, 1);
                 }
                 }
+
+                // Shadow generators
+                var generator = light.getShadowGenerator();
+                if (generator) {
+                    meshIndex = generator.getShadowMap().renderList.indexOf(this);
+
+                    if (meshIndex !== -1) {
+                        generator.getShadowMap().renderList.splice(meshIndex, 1);
+                    }
+                }
             });
             });
 
 
             // Edges
             // Edges

+ 7 - 6
src/Mesh/babylon.geometry.js

@@ -505,13 +505,14 @@ var BABYLON;
             }
             }
             return geometry.copy(id);
             return geometry.copy(id);
         };
         };
-        // from http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#answer-2117523
-        // be aware Math.random() could cause collisions
+        /**
+         * You should now use Tools.RandomId(), this method is still here for legacy reasons.
+         * Implementation from http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#answer-2117523
+         * Be aware Math.random() could cause collisions, but:
+         * "All but 6 of the 128 bits of the ID are randomly generated, which means that for any two ids, there's a 1 in 2^^122 (or 5.3x10^^36) chance they'll collide"
+         */
         Geometry.RandomId = function () {
         Geometry.RandomId = function () {
-            return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
-                var r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
-                return v.toString(16);
-            });
+            return BABYLON.Tools.RandomId();
         };
         };
         Geometry.ImportGeometry = function (parsedGeometry, mesh) {
         Geometry.ImportGeometry = function (parsedGeometry, mesh) {
             var scene = mesh.getScene();
             var scene = mesh.getScene();

+ 7 - 6
src/Mesh/babylon.geometry.ts

@@ -632,13 +632,14 @@
             return geometry.copy(id);
             return geometry.copy(id);
         }
         }
 
 
-        // from http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#answer-2117523
-        // be aware Math.random() could cause collisions
+        /**
+         * You should now use Tools.RandomId(), this method is still here for legacy reasons.
+         * Implementation from http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#answer-2117523
+         * Be aware Math.random() could cause collisions, but:
+         * "All but 6 of the 128 bits of the ID are randomly generated, which means that for any two ids, there's a 1 in 2^^122 (or 5.3x10^^36) chance they'll collide"
+         */
         public static RandomId(): string {
         public static RandomId(): string {
-            return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
-                var r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
-                return v.toString(16);
-            });
+            return Tools.RandomId();
         }
         }
 
 
         public static ImportGeometry(parsedGeometry: any, mesh: Mesh): void {
         public static ImportGeometry(parsedGeometry: any, mesh: Mesh): void {

+ 35 - 14
src/Mesh/babylon.groundMesh.js

@@ -14,15 +14,30 @@ var BABYLON;
         }
         }
         Object.defineProperty(GroundMesh.prototype, "subdivisions", {
         Object.defineProperty(GroundMesh.prototype, "subdivisions", {
             get: function () {
             get: function () {
-                return this._subdivisions;
+                return Math.min(this._subdivisionsX, this._subdivisionsY);
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(GroundMesh.prototype, "subdivisionsX", {
+            get: function () {
+                return this._subdivisionsX;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(GroundMesh.prototype, "subdivisionsY", {
+            get: function () {
+                return this._subdivisionsY;
             },
             },
             enumerable: true,
             enumerable: true,
             configurable: true
             configurable: true
         });
         });
         GroundMesh.prototype.optimize = function (chunksCount, octreeBlocksSize) {
         GroundMesh.prototype.optimize = function (chunksCount, octreeBlocksSize) {
             if (octreeBlocksSize === void 0) { octreeBlocksSize = 32; }
             if (octreeBlocksSize === void 0) { octreeBlocksSize = 32; }
-            this._subdivisions = chunksCount;
-            this.subdivide(this._subdivisions);
+            this._subdivisionsX = chunksCount;
+            this._subdivisionsY = chunksCount;
+            this.subdivide(chunksCount);
             this.createOrUpdateSubmeshesOctree(octreeBlocksSize);
             this.createOrUpdateSubmeshesOctree(octreeBlocksSize);
         };
         };
         /**
         /**
@@ -98,9 +113,11 @@ var BABYLON;
         // Returns the element "facet" from the heightQuads array relative to (x, z) local coordinates
         // Returns the element "facet" from the heightQuads array relative to (x, z) local coordinates
         GroundMesh.prototype._getFacetAt = function (x, z) {
         GroundMesh.prototype._getFacetAt = function (x, z) {
             // retrieve col and row from x, z coordinates in the ground local system
             // retrieve col and row from x, z coordinates in the ground local system
-            var col = Math.floor((x + this._maxX) * this._subdivisions / this._width);
-            var row = Math.floor(-(z + this._maxZ) * this._subdivisions / this._height + this._subdivisions);
-            var quad = this._heightQuads[row * this._subdivisions + col];
+            var subdivisionsX = this._subdivisionsX;
+            var subdivisionsY = this._subdivisionsY;
+            var col = Math.floor((x + this._maxX) * this._subdivisionsX / this._width);
+            var row = Math.floor(-(z + this._maxZ) * this._subdivisionsY / this._height + this._subdivisionsY);
+            var quad = this._heightQuads[row * this._subdivisionsX + col];
             var facet;
             var facet;
             if (z < quad.slope.x * x + quad.slope.y) {
             if (z < quad.slope.x * x + quad.slope.y) {
                 facet = quad.facet1;
                 facet = quad.facet1;
@@ -116,11 +133,13 @@ var BABYLON;
         // facet1 : Vector4(a, b, c, d) = first facet 3D plane equation : ax + by + cz + d = 0
         // facet1 : Vector4(a, b, c, d) = first facet 3D plane equation : ax + by + cz + d = 0
         // facet2 :  Vector4(a, b, c, d) = second facet 3D plane equation : ax + by + cz + d = 0
         // facet2 :  Vector4(a, b, c, d) = second facet 3D plane equation : ax + by + cz + d = 0
         GroundMesh.prototype._initHeightQuads = function () {
         GroundMesh.prototype._initHeightQuads = function () {
+            var subdivisionsX = this._subdivisionsX;
+            var subdivisionsY = this._subdivisionsY;
             this._heightQuads = new Array();
             this._heightQuads = new Array();
-            for (var row = 0; row < this._subdivisions; row++) {
-                for (var col = 0; col < this._subdivisions; col++) {
+            for (var row = 0; row < subdivisionsY; row++) {
+                for (var col = 0; col < subdivisionsX; col++) {
                     var quad = { slope: BABYLON.Vector2.Zero(), facet1: new BABYLON.Vector4(0, 0, 0, 0), facet2: new BABYLON.Vector4(0, 0, 0, 0) };
                     var quad = { slope: BABYLON.Vector2.Zero(), facet1: new BABYLON.Vector4(0, 0, 0, 0), facet2: new BABYLON.Vector4(0, 0, 0, 0) };
-                    this._heightQuads[row * this._subdivisions + col] = quad;
+                    this._heightQuads[row * subdivisionsX + col] = quad;
                 }
                 }
             }
             }
         };
         };
@@ -146,11 +165,13 @@ var BABYLON;
             var h = 0;
             var h = 0;
             var d1 = 0; // facet plane equation : ax + by + cz + d = 0
             var d1 = 0; // facet plane equation : ax + by + cz + d = 0
             var d2 = 0;
             var d2 = 0;
-            for (var row = 0; row < this._subdivisions; row++) {
-                for (var col = 0; col < this._subdivisions; col++) {
+            var subdivisionsX = this._subdivisionsX;
+            var subdivisionsY = this._subdivisionsY;
+            for (var row = 0; row < subdivisionsY; row++) {
+                for (var col = 0; col < subdivisionsX; col++) {
                     i = col * 3;
                     i = col * 3;
-                    j = row * (this._subdivisions + 1) * 3;
-                    k = (row + 1) * (this._subdivisions + 1) * 3;
+                    j = row * (subdivisionsX + 1) * 3;
+                    k = (row + 1) * (subdivisionsX + 1) * 3;
                     v1.x = positions[j + i];
                     v1.x = positions[j + i];
                     v1.y = positions[j + i + 1];
                     v1.y = positions[j + i + 1];
                     v1.z = positions[j + i + 2];
                     v1.z = positions[j + i + 2];
@@ -180,7 +201,7 @@ var BABYLON;
                     norm2.normalize();
                     norm2.normalize();
                     d1 = -(norm1.x * v1.x + norm1.y * v1.y + norm1.z * v1.z);
                     d1 = -(norm1.x * v1.x + norm1.y * v1.y + norm1.z * v1.z);
                     d2 = -(norm2.x * v2.x + norm2.y * v2.y + norm2.z * v2.z);
                     d2 = -(norm2.x * v2.x + norm2.y * v2.y + norm2.z * v2.z);
-                    var quad = this._heightQuads[row * this._subdivisions + col];
+                    var quad = this._heightQuads[row * subdivisionsX + col];
                     quad.slope.copyFromFloats(cd, h);
                     quad.slope.copyFromFloats(cd, h);
                     quad.facet1.copyFromFloats(norm1.x, norm1.y, norm1.z, d1);
                     quad.facet1.copyFromFloats(norm1.x, norm1.y, norm1.z, d1);
                     quad.facet2.copyFromFloats(norm2.x, norm2.y, norm2.z, d2);
                     quad.facet2.copyFromFloats(norm2.x, norm2.y, norm2.z, d2);

+ 2 - 0
src/Mesh/babylon.mesh.js

@@ -712,7 +712,9 @@ var BABYLON;
             if (!this._geometry) {
             if (!this._geometry) {
                 return;
                 return;
             }
             }
+            var oldGeometry = this._geometry;
             var geometry = this._geometry.copy(BABYLON.Geometry.RandomId());
             var geometry = this._geometry.copy(BABYLON.Geometry.RandomId());
+            oldGeometry.releaseForMesh(this, true);
             geometry.applyToMesh(this);
             geometry.applyToMesh(this);
         };
         };
         /**
         /**

+ 4 - 0
src/Mesh/babylon.mesh.ts

@@ -755,7 +755,11 @@
             if (!this._geometry) {
             if (!this._geometry) {
                 return;
                 return;
             }
             }
+            var oldGeometry = this._geometry;
+
             var geometry = this._geometry.copy(Geometry.RandomId());
             var geometry = this._geometry.copy(Geometry.RandomId());
+
+			oldGeometry.releaseForMesh(this, true);
             geometry.applyToMesh(this);
             geometry.applyToMesh(this);
         }
         }
 
 

+ 14 - 13
src/Mesh/babylon.mesh.vertexData.js

@@ -988,24 +988,25 @@ var BABYLON;
             var row, col;
             var row, col;
             var width = options.width || 1;
             var width = options.width || 1;
             var height = options.height || 1;
             var height = options.height || 1;
-            var subdivisions = options.subdivisions || 1;
-            for (row = 0; row <= subdivisions; row++) {
-                for (col = 0; col <= subdivisions; col++) {
-                    var position = new BABYLON.Vector3((col * width) / subdivisions - (width / 2.0), 0, ((subdivisions - row) * height) / subdivisions - (height / 2.0));
+            var subdivisionsX = options.subdivisionsX || options.subdivisions || 1;
+            var subdivisionsY = options.subdivisionsY || options.subdivisions || 1;
+            for (row = 0; row <= subdivisionsY; row++) {
+                for (col = 0; col <= subdivisionsX; col++) {
+                    var position = new BABYLON.Vector3((col * width) / subdivisionsX - (width / 2.0), 0, ((subdivisionsY - row) * height) / subdivisionsY - (height / 2.0));
                     var normal = new BABYLON.Vector3(0, 1.0, 0);
                     var normal = new BABYLON.Vector3(0, 1.0, 0);
                     positions.push(position.x, position.y, position.z);
                     positions.push(position.x, position.y, position.z);
                     normals.push(normal.x, normal.y, normal.z);
                     normals.push(normal.x, normal.y, normal.z);
-                    uvs.push(col / subdivisions, 1.0 - row / subdivisions);
+                    uvs.push(col / subdivisionsX, 1.0 - row / subdivisionsX);
                 }
                 }
             }
             }
-            for (row = 0; row < subdivisions; row++) {
-                for (col = 0; col < subdivisions; col++) {
-                    indices.push(col + 1 + (row + 1) * (subdivisions + 1));
-                    indices.push(col + 1 + row * (subdivisions + 1));
-                    indices.push(col + row * (subdivisions + 1));
-                    indices.push(col + (row + 1) * (subdivisions + 1));
-                    indices.push(col + 1 + (row + 1) * (subdivisions + 1));
-                    indices.push(col + row * (subdivisions + 1));
+            for (row = 0; row < subdivisionsY; row++) {
+                for (col = 0; col < subdivisionsX; col++) {
+                    indices.push(col + 1 + (row + 1) * (subdivisionsX + 1));
+                    indices.push(col + 1 + row * (subdivisionsX + 1));
+                    indices.push(col + row * (subdivisionsX + 1));
+                    indices.push(col + (row + 1) * (subdivisionsX + 1));
+                    indices.push(col + 1 + (row + 1) * (subdivisionsX + 1));
+                    indices.push(col + row * (subdivisionsX + 1));
                 }
                 }
             }
             }
             // Result
             // Result

+ 4 - 2
src/Mesh/babylon.meshBuilder.js

@@ -542,7 +542,8 @@ var BABYLON;
         MeshBuilder.CreateGround = function (name, options, scene) {
         MeshBuilder.CreateGround = function (name, options, scene) {
             var ground = new BABYLON.GroundMesh(name, scene);
             var ground = new BABYLON.GroundMesh(name, scene);
             ground._setReady(false);
             ground._setReady(false);
-            ground._subdivisions = options.subdivisions || 1;
+            ground._subdivisionsX = options.subdivisionsX || options.subdivisions || 1;
+            ground._subdivisionsY = options.subdivisionsY || options.subdivisions || 1;
             ground._width = options.width || 1;
             ground._width = options.width || 1;
             ground._height = options.height || 1;
             ground._height = options.height || 1;
             ground._maxX = ground._width / 2;
             ground._maxX = ground._width / 2;
@@ -597,7 +598,8 @@ var BABYLON;
             var updatable = options.updatable;
             var updatable = options.updatable;
             var onReady = options.onReady;
             var onReady = options.onReady;
             var ground = new BABYLON.GroundMesh(name, scene);
             var ground = new BABYLON.GroundMesh(name, scene);
-            ground._subdivisions = subdivisions;
+            ground._subdivisionsX = subdivisions;
+            ground._subdivisionsY = subdivisions;
             ground._width = width;
             ground._width = width;
             ground._height = height;
             ground._height = height;
             ground._maxX = ground._width / 2.0;
             ground._maxX = ground._width / 2.0;

+ 2 - 2
src/Physics/Plugins/babylon.oimoJSPlugin.js

@@ -307,9 +307,9 @@ var BABYLON;
             impostor.physicsBody.awake();
             impostor.physicsBody.awake();
         };
         };
         OimoJSPlugin.prototype.updateDistanceJoint = function (joint, maxDistance, minDistance) {
         OimoJSPlugin.prototype.updateDistanceJoint = function (joint, maxDistance, minDistance) {
-            joint.physicsJoint.limitMotoe.upperLimit = maxDistance;
+            joint.physicsJoint.limitMotor.upperLimit = maxDistance;
             if (minDistance !== void 0) {
             if (minDistance !== void 0) {
-                joint.physicsJoint.limitMotoe.lowerLimit = minDistance;
+                joint.physicsJoint.limitMotor.lowerLimit = minDistance;
             }
             }
         };
         };
         OimoJSPlugin.prototype.setMotor = function (joint, speed, maxForce, motorIndex) {
         OimoJSPlugin.prototype.setMotor = function (joint, speed, maxForce, motorIndex) {

+ 2 - 2
src/Physics/Plugins/babylon.oimoJSPlugin.ts

@@ -365,9 +365,9 @@ module BABYLON {
         }
         }
 
 
         public updateDistanceJoint(joint: IMotorEnabledJoint, maxDistance: number, minDistance?: number) {
         public updateDistanceJoint(joint: IMotorEnabledJoint, maxDistance: number, minDistance?: number) {
-            joint.physicsJoint.limitMotoe.upperLimit = maxDistance;
+            joint.physicsJoint.limitMotor.upperLimit = maxDistance;
             if (minDistance !== void 0) {
             if (minDistance !== void 0) {
-                joint.physicsJoint.limitMotoe.lowerLimit = minDistance;
+                joint.physicsJoint.limitMotor.lowerLimit = minDistance;
             }
             }
         }
         }
 
 

+ 28 - 15
src/Shaders/ShadersInclude/lightFragment.fx

@@ -1,16 +1,20 @@
 #ifdef LIGHT{X}
 #ifdef LIGHT{X}
-	#ifndef SPECULARTERM
-		vec3 vLightSpecular{X} = vec3(0.);
-	#endif
-	#ifdef SPOTLIGHT{X}
-		info = computeSpotLighting(viewDirectionW, normalW, vLightData{X}, vLightDirection{X}, vLightDiffuse{X}.rgb, vLightSpecular{X}, vLightDiffuse{X}.a, glossiness);
-	#endif
-	#ifdef HEMILIGHT{X}
-		info = computeHemisphericLighting(viewDirectionW, normalW, vLightData{X}, vLightDiffuse{X}.rgb, vLightSpecular{X}, vLightGround{X}, glossiness);
-	#endif
-	#if defined(POINTLIGHT{X}) || defined(DIRLIGHT{X})
-		info = computeLighting(viewDirectionW, normalW, vLightData{X}, vLightDiffuse{X}.rgb, vLightSpecular{X}, vLightDiffuse{X}.a, glossiness);
-	#endif
+    #if defined(LIGHTMAP) && defined(LIGHTMAPEXCLUDED{X}) && defined(LIGHTMAPNOSPECULAR{X})
+        //No light calculation
+    #else
+        #ifndef SPECULARTERM
+            vec3 vLightSpecular{X} = vec3(0.);
+        #endif
+        #ifdef SPOTLIGHT{X}
+            info = computeSpotLighting(viewDirectionW, normalW, vLightData{X}, vLightDirection{X}, vLightDiffuse{X}.rgb, vLightSpecular{X}, vLightDiffuse{X}.a, glossiness);
+        #endif
+        #ifdef HEMILIGHT{X}
+            info = computeHemisphericLighting(viewDirectionW, normalW, vLightData{X}, vLightDiffuse{X}.rgb, vLightSpecular{X}, vLightGround{X}, glossiness);
+        #endif
+        #if defined(POINTLIGHT{X}) || defined(DIRLIGHT{X})
+            info = computeLighting(viewDirectionW, normalW, vLightData{X}, vLightDiffuse{X}.rgb, vLightSpecular{X}, vLightDiffuse{X}.a, glossiness);
+        #endif
+    #endif
 	#ifdef SHADOW{X}
 	#ifdef SHADOW{X}
 		#ifdef SHADOWVSM{X}
 		#ifdef SHADOWVSM{X}
 			shadow = computeShadowWithVSM(vPositionFromLight{X}, shadowSampler{X}, shadowsInfo{X}.z, shadowsInfo{X}.x);
 			shadow = computeShadowWithVSM(vPositionFromLight{X}, shadowSampler{X}, shadowsInfo{X}.z, shadowsInfo{X}.x);
@@ -32,8 +36,17 @@
 	#else
 	#else
 		shadow = 1.;
 		shadow = 1.;
 	#endif
 	#endif
-		diffuseBase += info.diffuse * shadow;
-	#ifdef SPECULARTERM
-		specularBase += info.specular * shadow;
+    #if defined(LIGHTMAP) && defined(LIGHTMAPEXCLUDED{X})
+	    diffuseBase += lightmapColor * shadow;
+	    #ifdef SPECULARTERM
+            #ifndef LIGHTMAPNOSPECULAR{X}
+                specularBase += info.specular * shadow * lightmapColor;
+            #endif
+        #endif
+    #else
+	    diffuseBase += info.diffuse * shadow;
+	    #ifdef SPECULARTERM
+		    specularBase += info.specular * shadow;
+	    #endif
 	#endif
 	#endif
 #endif
 #endif

+ 36 - 22
src/Shaders/ShadersInclude/pbrLightFunctionsCall.fx

@@ -1,15 +1,19 @@
 #ifdef LIGHT{X}
 #ifdef LIGHT{X}
-    #ifndef SPECULARTERM
-        vec3 vLightSpecular{X} = vec3(0.0);
-    #endif
-    #ifdef SPOTLIGHT{X}
-        info = computeSpotLighting(viewDirectionW, normalW, vLightData{X}, vLightDirection{X}, vLightDiffuse{X}.rgb, vLightSpecular{X}, vLightDiffuse{X}.a, roughness, NdotV, specularEnvironmentR90, NdotL);
-    #endif
-    #ifdef HEMILIGHT{X}
-        info = computeHemisphericLighting(viewDirectionW, normalW, vLightData{X}, vLightDiffuse{X}.rgb, vLightSpecular{X}, vLightGround{X}, roughness, NdotV, specularEnvironmentR90, NdotL);
-    #endif
-    #if defined(POINTLIGHT{X}) || defined(DIRLIGHT{X})
-        info = computeLighting(viewDirectionW, normalW, vLightData{X}, vLightDiffuse{X}.rgb, vLightSpecular{X}, vLightDiffuse{X}.a, roughness, NdotV, specularEnvironmentR90, NdotL);
+    #if defined(LIGHTMAP) && defined(LIGHTMAPEXCLUDED{X}) && defined(LIGHTMAPNOSPECULAR{X})
+        //No light calculation
+    #else
+        #ifndef SPECULARTERM
+            vec3 vLightSpecular{X} = vec3(0.0);
+        #endif
+        #ifdef SPOTLIGHT{X}
+            info = computeSpotLighting(viewDirectionW, normalW, vLightData{X}, vLightDirection{X}, vLightDiffuse{X}.rgb, vLightSpecular{X}, vLightDiffuse{X}.a, roughness, NdotV, specularEnvironmentR90, NdotL);
+        #endif
+        #ifdef HEMILIGHT{X}
+            info = computeHemisphericLighting(viewDirectionW, normalW, vLightData{X}, vLightDiffuse{X}.rgb, vLightSpecular{X}, vLightGround{X}, roughness, NdotV, specularEnvironmentR90, NdotL);
+        #endif
+        #if defined(POINTLIGHT{X}) || defined(DIRLIGHT{X})
+            info = computeLighting(viewDirectionW, normalW, vLightData{X}, vLightDiffuse{X}.rgb, vLightSpecular{X}, vLightDiffuse{X}.a, roughness, NdotV, specularEnvironmentR90, NdotL);
+        #endif
     #endif
     #endif
     
     
     #ifdef SHADOW{X}
     #ifdef SHADOW{X}
@@ -34,17 +38,27 @@
         notShadowLevel = 1.;
         notShadowLevel = 1.;
     #endif
     #endif
     
     
-    lightDiffuseContribution += info.diffuse * notShadowLevel;
-    
-    #ifdef OVERLOADEDSHADOWVALUES
-        if (NdotL < 0.000000000011)
-        {
-            notShadowLevel = 1.;
-        }
-        shadowedOnlyLightDiffuseContribution *= notShadowLevel;
-    #endif
+    #if defined(LIGHTMAP) && defined(LIGHTMAPEXCLUDED{X})
+	    lightDiffuseContribution += lightmapColor * notShadowLevel;
+	    
+        #ifdef SPECULARTERM
+            #ifndef LIGHTMAPNOSPECULAR{X}
+                lightSpecularContribution += info.specular * notShadowLevel * lightmapColor;
+            #endif
+        #endif
+    #else
+        lightDiffuseContribution += info.diffuse * notShadowLevel;
+        
+        #ifdef OVERLOADEDSHADOWVALUES
+            if (NdotL < 0.000000000011)
+            {
+                notShadowLevel = 1.;
+            }
+            shadowedOnlyLightDiffuseContribution *= notShadowLevel;
+        #endif
 
 
-    #ifdef SPECULARTERM
-        lightSpecularContribution += info.specular * notShadowLevel;
+        #ifdef SPECULARTERM
+            lightSpecularContribution += info.specular * notShadowLevel;
+        #endif
     #endif
     #endif
 #endif
 #endif

+ 12 - 7
src/Shaders/default.fragment.fx

@@ -232,6 +232,10 @@ void main(void) {
 #endif
 #endif
 	float shadow = 1.;
 	float shadow = 1.;
 
 
+#ifdef LIGHTMAP
+	vec3 lightmapColor = texture2D(lightmapSampler, vLightmapUV).rgb * vLightmapInfos.y;
+#endif
+
 #include<lightFragment>[0..maxSimultaneousLights]
 #include<lightFragment>[0..maxSimultaneousLights]
 
 
 	// Refraction
 	// Refraction
@@ -387,14 +391,15 @@ void main(void) {
 	vec4 color = vec4(finalDiffuse * baseAmbientColor + finalSpecular + reflectionColor + refractionColor, alpha);
 	vec4 color = vec4(finalDiffuse * baseAmbientColor + finalSpecular + reflectionColor + refractionColor, alpha);
 #endif
 #endif
 
 
+//Old lightmap calculation method
 #ifdef LIGHTMAP
 #ifdef LIGHTMAP
-	vec3 lightmapColor = texture2D(lightmapSampler, vLightmapUV).rgb * vLightmapInfos.y;
-
-#ifdef USELIGHTMAPASSHADOWMAP
-	color.rgb *= lightmapColor;
-#else
-	color.rgb += lightmapColor;
-#endif
+    #ifndef LIGHTMAPEXCLUDED
+        #ifdef USELIGHTMAPASSHADOWMAP
+            color.rgb *= lightmapColor;
+        #else
+            color.rgb += lightmapColor;
+        #endif
+    #endif
 #endif
 #endif
 
 
 #include<logDepthFragment>
 #include<logDepthFragment>

+ 13 - 7
src/Shaders/pbr.fragment.fx

@@ -289,7 +289,13 @@ void main(void) {
 #ifdef SPECULARTERM
 #ifdef SPECULARTERM
 	vec3 lightSpecularContribution = vec3(0., 0., 0.);
 	vec3 lightSpecularContribution = vec3(0., 0., 0.);
 #endif
 #endif
+	
 	float notShadowLevel = 1.; // 1 - shadowLevel
 	float notShadowLevel = 1.; // 1 - shadowLevel
+
+	#ifdef LIGHTMAP
+  		vec3 lightmapColor = texture2D(lightmapSampler, vLightmapUV).rgb * vLightmapInfos.y;
+  	#endif
+
 	float NdotL = -1.;
 	float NdotL = -1.;
 	lightingInfo info;
 	lightingInfo info;
 
 
@@ -589,13 +595,13 @@ void main(void) {
 #endif
 #endif
 
 
 #ifdef LIGHTMAP
 #ifdef LIGHTMAP
-	vec3 lightmapColor = texture2D(lightmapSampler, vLightmapUV).rgb * vLightmapInfos.y;
-
-#ifdef USELIGHTMAPASSHADOWMAP
-	finalColor.rgb *= lightmapColor;
-#else
-	finalColor.rgb += lightmapColor;
-#endif
+    #ifndef LIGHTMAPEXCLUDED
+        #ifdef USELIGHTMAPASSHADOWMAP
+            finalColor.rgb *= lightmapColor;
+        #else
+            finalColor.rgb += lightmapColor;
+        #endif
+    #endif
 #endif
 #endif
 
 
 	finalColor = max(finalColor, 0.0);
 	finalColor = max(finalColor, 0.0);

+ 11 - 0
src/Tools/babylon.tools.js

@@ -639,6 +639,17 @@ var BABYLON;
             }
             }
             return false;
             return false;
         };
         };
+        /**
+         * Implementation from http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#answer-2117523
+         * Be aware Math.random() could cause collisions, but:
+         * "All but 6 of the 128 bits of the ID are randomly generated, which means that for any two ids, there's a 1 in 2^^122 (or 5.3x10^^36) chance they'll collide"
+         */
+        Tools.RandomId = function () {
+            return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
+                var r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
+                return v.toString(16);
+            });
+        };
         Object.defineProperty(Tools, "NoneLogLevel", {
         Object.defineProperty(Tools, "NoneLogLevel", {
             get: function () {
             get: function () {
                 return Tools._NoneLogLevel;
                 return Tools._NoneLogLevel;

+ 12 - 0
src/Tools/babylon.tools.ts

@@ -750,6 +750,18 @@
             return false;
             return false;
         }
         }
 
 
+        /**
+         * Implementation from http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#answer-2117523
+         * Be aware Math.random() could cause collisions, but:
+         * "All but 6 of the 128 bits of the ID are randomly generated, which means that for any two ids, there's a 1 in 2^^122 (or 5.3x10^^36) chance they'll collide"
+         */
+        public static RandomId(): string {
+            return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
+                var r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
+                return v.toString(16);
+            });
+        }
+
         // Logs
         // Logs
         private static _NoneLogLevel = 0;
         private static _NoneLogLevel = 0;
         private static _MessageLogLevel = 1;
         private static _MessageLogLevel = 1;

+ 1 - 1
src/babylon.engine.ts

@@ -88,7 +88,7 @@
         engine.resetTextureCache();
         engine.resetTextureCache();
         scene._removePendingData(texture);
         scene._removePendingData(texture);
 
 
-        texture.onLoadedCallbacks.forEach(function (callback) {
+        texture.onLoadedCallbacks.forEach(callback => {
             callback();
             callback();
         });
         });
         texture.onLoadedCallbacks = [];
         texture.onLoadedCallbacks = [];

+ 437 - 0
src/babylon.mixins.ts

@@ -19,6 +19,13 @@ interface Window {
     AudioContext: AudioContext;
     AudioContext: AudioContext;
     webkitAudioContext: AudioContext;
     webkitAudioContext: AudioContext;
     PointerEvent: any;
     PointerEvent: any;
+    Math: Math;
+    Uint8Array: Uint8ArrayConstructor;
+    Float32Array: Float32ArrayConstructor;
+}
+
+interface AudioContext extends EventTarget {
+    decodeAudioData(audioData: ArrayBuffer, successCallback: DecodeSuccessCallback, errorCallback?: any): void;
 }
 }
 
 
 interface HTMLURL {
 interface HTMLURL {
@@ -110,4 +117,434 @@ interface Screen {
 
 
 interface HTMLMediaElement {
 interface HTMLMediaElement {
     crossOrigin: string;
     crossOrigin: string;
+}
+
+interface Math {
+    fround(x: number): number;
+    imul(a: number, b: number): number;
+}
+
+interface SIMDglobal {
+    SIMD: SIMD;
+    Math: Math;
+    Uint8Array: Uint8ArrayConstructor;
+    Float32Array: Float32ArrayConstructor;
+}
+
+interface SIMD {
+    Float32x4: SIMD.Float32x4Constructor;
+    Int32x4: SIMD.Int32x4Constructor;
+    Int16x8: SIMD.Int16x8Constructor;
+    Int8x16: SIMD.Int8x16Constructor;
+    Uint32x4: SIMD.Uint32x4Constructor;
+    Uint16x8: SIMD.Uint16x8Constructor;
+    Uint8x16: SIMD.Uint8x16Constructor;
+    Bool32x4: SIMD.Bool32x4Constructor;
+    Bool16x8: SIMD.Bool16x8Constructor;
+    Bool8x16: SIMD.Bool8x16Constructor;
+}
+
+declare namespace SIMD {
+    interface Float32x4 {
+        constructor: Float32x4Constructor;
+        valueOf(): Float32x4;
+        toLocaleString(): string;
+        toString(): string;
+    }
+
+    interface Float32x4Constructor {
+        (s0?: number, s1?: number, s2?: number, s3?: number): Float32x4;
+        prototype: Float32x4;
+        extractLane(simd: SIMD.Float32x4, lane: number): number;
+        swizzle(a: SIMD.Float32x4, l1: number, l2: number, l3: number, l4: number): SIMD.Float32x4;
+        shuffle(a: SIMD.Float32x4, b: SIMD.Float32x4, l1: number, l2: number, l3: number, l4: number): SIMD.Float32x4;
+        check(a: SIMD.Float32x4): SIMD.Float32x4;
+        splat(n: number): SIMD.Float32x4;
+        replaceLane(simd: SIMD.Float32x4, lane: number, value: number): SIMD.Float32x4;
+        select(selector: SIMD.Bool32x4, a: SIMD.Float32x4, b: SIMD.Float32x4): SIMD.Float32x4;
+        equal(a: SIMD.Float32x4, b: SIMD.Float32x4): SIMD.Bool32x4;
+        notEqual(a: SIMD.Float32x4, b: SIMD.Float32x4): SIMD.Bool32x4;
+        lessThan(a: SIMD.Float32x4, b: SIMD.Float32x4): SIMD.Bool32x4;
+        lessThanOrEqual(a: SIMD.Float32x4, b: SIMD.Float32x4): SIMD.Bool32x4;
+        greaterThan(a: SIMD.Float32x4, b: SIMD.Float32x4): SIMD.Bool32x4;
+        greaterThanOrEqual(a: SIMD.Float32x4, b: SIMD.Float32x4): SIMD.Bool32x4;
+        add(a: SIMD.Float32x4, b: SIMD.Float32x4): SIMD.Float32x4;
+        sub(a: SIMD.Float32x4, b: SIMD.Float32x4): SIMD.Float32x4;
+        mul(a: SIMD.Float32x4, b: SIMD.Float32x4): SIMD.Float32x4;
+        div(a: SIMD.Float32x4, b: SIMD.Float32x4): SIMD.Float32x4;
+        neg(a: SIMD.Float32x4): SIMD.Float32x4;
+        abs(a: SIMD.Float32x4): SIMD.Float32x4;
+        min(a: SIMD.Float32x4, b: SIMD.Float32x4): SIMD.Float32x4;
+        max(a: SIMD.Float32x4, b: SIMD.Float32x4): SIMD.Float32x4;
+        minNum(a: SIMD.Float32x4, b: SIMD.Float32x4): SIMD.Float32x4;
+        maxNum(a: SIMD.Float32x4, b: SIMD.Float32x4): SIMD.Float32x4;
+        reciprocalApproximation(a: SIMD.Float32x4): SIMD.Float32x4;
+        reciprocalSqrtApproximation(a: SIMD.Float32x4): SIMD.Float32x4;
+        sqrt(a: SIMD.Float32x4): SIMD.Float32x4;
+        load(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number): SIMD.Float32x4;
+        load1(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number): SIMD.Float32x4;
+        load2(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number): SIMD.Float32x4;
+        load3(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number): SIMD.Float32x4;
+        store(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number, value: SIMD.Float32x4): SIMD.Float32x4;
+        store1(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number, value: SIMD.Float32x4): SIMD.Float32x4;
+        store2(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number, value: SIMD.Float32x4): SIMD.Float32x4;
+        store3(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number, value: SIMD.Float32x4): SIMD.Float32x4;
+        fromInt32x4(value: SIMD.Int32x4): SIMD.Float32x4;
+        fromUint32x4(value: SIMD.Uint32x4): SIMD.Float32x4;
+        fromInt32x4Bits(value: SIMD.Int32x4): SIMD.Float32x4;
+        fromInt16x8Bits(value: SIMD.Int16x8): SIMD.Float32x4;
+        fromInt8x16Bits(value: SIMD.Int8x16): SIMD.Float32x4;
+        fromUint32x4Bits(value: SIMD.Uint32x4): SIMD.Float32x4;
+        fromUint16x8Bits(value: SIMD.Uint16x8): SIMD.Float32x4;
+        fromUint8x16Bits(value: SIMD.Uint8x16): SIMD.Float32x4;
+    }
+
+    interface Int32x4 {
+        constructor: Int32x4Constructor;
+        valueOf(): Int32x4;
+        toLocaleString(): string;
+        toString(): string;
+    }
+
+    interface Int32x4Constructor {
+        (s0?: number, s1?: number, s2?: number, s3?: number): Int32x4;
+        prototype: Int32x4;
+        extractLane(simd: SIMD.Int32x4, lane: number): number;
+        swizzle(a: SIMD.Int32x4, l1: number, l2: number, l3: number, l4: number): SIMD.Int32x4;
+        shuffle(a: SIMD.Int32x4, b: SIMD.Int32x4, l1: number, l2: number, l3: number, l4: number): SIMD.Int32x4;
+        check(a: SIMD.Int32x4): SIMD.Int32x4;
+        splat(n: number): SIMD.Int32x4;
+        replaceLane(simd: SIMD.Int32x4, lane: number, value: number): SIMD.Int32x4;
+        select(selector: SIMD.Bool32x4, a: SIMD.Int32x4, b: SIMD.Int32x4): SIMD.Int32x4;
+        equal(a: SIMD.Int32x4, b: SIMD.Int32x4): SIMD.Bool32x4;
+        notEqual(a: SIMD.Int32x4, b: SIMD.Int32x4): SIMD.Bool32x4;
+        lessThan(a: SIMD.Int32x4, b: SIMD.Int32x4): SIMD.Bool32x4;
+        lessThanOrEqual(a: SIMD.Int32x4, b: SIMD.Int32x4): SIMD.Bool32x4;
+        greaterThan(a: SIMD.Int32x4, b: SIMD.Int32x4): SIMD.Bool32x4;
+        greaterThanOrEqual(a: SIMD.Int32x4, b: SIMD.Int32x4): SIMD.Bool32x4;
+        and(a: SIMD.Int32x4, b: SIMD.Int32x4): SIMD.Int32x4;
+        or(a: SIMD.Int32x4, b: SIMD.Int32x4): SIMD.Int32x4;
+        xor(a: SIMD.Int32x4, b: SIMD.Int32x4): SIMD.Int32x4;
+        not(a: SIMD.Int32x4, b: SIMD.Int32x4): SIMD.Int32x4;
+        add(a: SIMD.Int32x4, b: SIMD.Int32x4): SIMD.Int32x4;
+        sub(a: SIMD.Int32x4, b: SIMD.Int32x4): SIMD.Int32x4;
+        mul(a: SIMD.Int32x4, b: SIMD.Int32x4): SIMD.Int32x4;
+        neg(a: SIMD.Int32x4): SIMD.Int32x4;
+        shiftLeftByScalar(a: SIMD.Int32x4, bits: number): SIMD.Int32x4;
+        shiftRightByScalar(a: SIMD.Int32x4, bits: number): SIMD.Int32x4;
+        load(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number): SIMD.Int32x4;
+        load1(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number): SIMD.Int32x4;
+        load2(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number): SIMD.Int32x4;
+        load3(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number): SIMD.Int32x4;
+        store(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number, value: SIMD.Int32x4): SIMD.Int32x4;
+        store1(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number, value: SIMD.Int32x4): SIMD.Int32x4;
+        store2(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number, value: SIMD.Int32x4): SIMD.Int32x4;
+        store3(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number, value: SIMD.Int32x4): SIMD.Int32x4;
+        fromFloat32x4(value: SIMD.Float32x4): SIMD.Int32x4;
+        fromUint32x4(value: SIMD.Uint32x4): SIMD.Int32x4;
+        fromFloat32x4Bits(value: SIMD.Float32x4): SIMD.Int32x4;
+        fromInt16x8Bits(value: SIMD.Int16x8): SIMD.Int32x4;
+        fromInt8x16Bits(value: SIMD.Int8x16): SIMD.Int32x4;
+        fromUint32x4Bits(value: SIMD.Uint32x4): SIMD.Int32x4;
+        fromUint16x8Bits(value: SIMD.Uint16x8): SIMD.Int32x4;
+        fromUint8x16Bits(value: SIMD.Uint8x16): SIMD.Int32x4;
+    }
+
+    interface Int16x8 {
+        constructor: Int16x8Constructor;
+        valueOf(): Int16x8;
+        toLocaleString(): string;
+        toString(): string;
+    }
+
+    interface Int16x8Constructor {
+        (s0?: number, s1?: number, s2?: number, s3?: number, s4?: number, s5?: number, s6?: number, s7?: number): Int16x8;
+        prototype: Int16x8;
+        extractLane(simd: SIMD.Int16x8, lane: number): number;
+        swizzle(a: SIMD.Int16x8, l1: number, l2: number, l3: number, l4: number, l5: number, l6: number, l7: number, l8: number): SIMD.Int16x8;
+        shuffle(a: SIMD.Int16x8, b: SIMD.Int16x8, l1: number, l2: number, l3: number, l4: number, l5: number, l6: number, l7: number, l8: number): SIMD.Int16x8;
+        check(a: SIMD.Int16x8): SIMD.Int16x8;
+        splat(n: number): SIMD.Int16x8;
+        replaceLane(simd: SIMD.Int16x8, lane: number, value: number): SIMD.Int16x8;
+        select(selector: SIMD.Bool16x8, a: SIMD.Int16x8, b: SIMD.Int16x8): SIMD.Int16x8;
+        equal(a: SIMD.Int16x8, b: SIMD.Int16x8): SIMD.Bool16x8;
+        notEqual(a: SIMD.Int16x8, b: SIMD.Int16x8): SIMD.Bool16x8;
+        lessThan(a: SIMD.Int16x8, b: SIMD.Int16x8): SIMD.Bool16x8;
+        lessThanOrEqual(a: SIMD.Int16x8, b: SIMD.Int16x8): SIMD.Bool16x8;
+        greaterThan(a: SIMD.Int16x8, b: SIMD.Int16x8): SIMD.Bool16x8;
+        greaterThanOrEqual(a: SIMD.Int16x8, b: SIMD.Int16x8): SIMD.Bool16x8;
+        and(a: SIMD.Int16x8, b: SIMD.Int16x8): SIMD.Int16x8;
+        or(a: SIMD.Int16x8, b: SIMD.Int16x8): SIMD.Int16x8;
+        xor(a: SIMD.Int16x8, b: SIMD.Int16x8): SIMD.Int16x8;
+        not(a: SIMD.Int16x8, b: SIMD.Int16x8): SIMD.Int16x8;
+        add(a: SIMD.Int16x8, b: SIMD.Int16x8): SIMD.Int16x8;
+        sub(a: SIMD.Int16x8, b: SIMD.Int16x8): SIMD.Int16x8;
+        mul(a: SIMD.Int16x8, b: SIMD.Int16x8): SIMD.Int16x8;
+        neg(a: SIMD.Int16x8): SIMD.Int16x8;
+        shiftLeftByScalar(a: SIMD.Int16x8, bits: number): SIMD.Int16x8;
+        shiftRightByScalar(a: SIMD.Int16x8, bits: number): SIMD.Int16x8;
+        addSaturate(a: SIMD.Int16x8, b: SIMD.Int16x8): SIMD.Int16x8;
+        subSaturate(a: SIMD.Int16x8, b: SIMD.Int16x8): SIMD.Int16x8;
+        load(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number): SIMD.Int16x8;
+        store(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number, value: SIMD.Int16x8): SIMD.Int16x8;
+        fromUint16x8(value: SIMD.Uint16x8): SIMD.Int16x8;
+        fromFloat32x4Bits(value: SIMD.Float32x4): SIMD.Int16x8;
+        fromInt32x4Bits(value: SIMD.Int32x4): SIMD.Int16x8;
+        fromInt8x16Bits(value: SIMD.Int8x16): SIMD.Int16x8;
+        fromUint32x4Bits(value: SIMD.Uint32x4): SIMD.Int16x8;
+        fromUint16x8Bits(value: SIMD.Uint16x8): SIMD.Int16x8;
+        fromUint8x16Bits(value: SIMD.Uint8x16): SIMD.Int16x8;
+    }
+
+    interface Int8x16 {
+        constructor: Int8x16Constructor;
+        valueOf(): Int8x16;
+        toLocaleString(): string;
+        toString(): string;
+    }
+
+    interface Int8x16Constructor {
+        (s0?: number, s1?: number, s2?: number, s3?: number, s4?: number, s5?: number, s6?: number, s7?: number, s8?: number, s9?: number, s10?: number, s11?: number, s12?: number, s13?: number, s14?: number, s15?: number): Int8x16;
+        prototype: Int8x16;
+        extractLane(simd: SIMD.Int8x16, lane: number): number;
+        swizzle(a: SIMD.Int8x16, l1: number, l2: number, l3: number, l4: number, l5: number, l6: number, l7: number, l8: number, l9: number, l10: number, l11: number, l12: number, l13: number, l14: number, l15: number, l16: number): SIMD.Int8x16;
+        shuffle(a: SIMD.Int8x16, b: SIMD.Int8x16, l1: number, l2: number, l3: number, l4: number, l5: number, l6: number, l7: number, l8: number, l9: number, l10: number, l11: number, l12: number, l13: number, l14: number, l15: number, l16: number): SIMD.Int8x16;
+        check(a: SIMD.Int8x16): SIMD.Int8x16;
+        splat(n: number): SIMD.Int8x16;
+        replaceLane(simd: SIMD.Int8x16, lane: number, value: number): SIMD.Int8x16;
+        select(selector: SIMD.Bool8x16, a: SIMD.Int8x16, b: SIMD.Int8x16): SIMD.Int8x16;
+        equal(a: SIMD.Int8x16, b: SIMD.Int8x16): SIMD.Bool8x16;
+        notEqual(a: SIMD.Int8x16, b: SIMD.Int8x16): SIMD.Bool8x16;
+        lessThan(a: SIMD.Int8x16, b: SIMD.Int8x16): SIMD.Bool8x16;
+        lessThanOrEqual(a: SIMD.Int8x16, b: SIMD.Int8x16): SIMD.Bool8x16;
+        greaterThan(a: SIMD.Int8x16, b: SIMD.Int8x16): SIMD.Bool8x16;
+        greaterThanOrEqual(a: SIMD.Int8x16, b: SIMD.Int8x16): SIMD.Bool8x16;
+        and(a: SIMD.Int8x16, b: SIMD.Int8x16): SIMD.Int8x16;
+        or(a: SIMD.Int8x16, b: SIMD.Int8x16): SIMD.Int8x16;
+        xor(a: SIMD.Int8x16, b: SIMD.Int8x16): SIMD.Int8x16;
+        not(a: SIMD.Int8x16, b: SIMD.Int8x16): SIMD.Int8x16;
+        add(a: SIMD.Int8x16, b: SIMD.Int8x16): SIMD.Int8x16;
+        sub(a: SIMD.Int8x16, b: SIMD.Int8x16): SIMD.Int8x16;
+        mul(a: SIMD.Int8x16, b: SIMD.Int8x16): SIMD.Int8x16;
+        neg(a: SIMD.Int8x16): SIMD.Int8x16;
+        shiftLeftByScalar(a: SIMD.Int8x16, bits: number): SIMD.Int8x16;
+        shiftRightByScalar(a: SIMD.Int8x16, bits: number): SIMD.Int8x16;
+        addSaturate(a: SIMD.Int8x16, b: SIMD.Int8x16): SIMD.Int8x16;
+        subSaturate(a: SIMD.Int8x16, b: SIMD.Int8x16): SIMD.Int8x16;
+        load(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number): SIMD.Int8x16;
+        store(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number, value: SIMD.Int8x16): SIMD.Int8x16;
+        fromUint8x16(value: SIMD.Uint8x16): SIMD.Int8x16;
+        fromFloat32x4Bits(value: SIMD.Float32x4): SIMD.Int8x16;
+        fromInt32x4Bits(value: SIMD.Int32x4): SIMD.Int8x16;
+        fromInt16x8Bits(value: SIMD.Int16x8): SIMD.Int8x16;
+        fromUint32x4Bits(value: SIMD.Uint32x4): SIMD.Int8x16;
+        fromUint16x8Bits(value: SIMD.Uint16x8): SIMD.Int8x16;
+        fromUint8x16Bits(value: SIMD.Uint8x16): SIMD.Int8x16;
+    }
+
+    interface Uint32x4 {
+        constructor: Uint32x4Constructor;
+        valueOf(): Uint32x4;
+        toLocaleString(): string;
+        toString(): string;
+    }
+
+    interface Uint32x4Constructor {
+        (s0?: number, s1?: number, s2?: number, s3?: number): Uint32x4;
+        prototype: Uint32x4;
+        extractLane(simd: SIMD.Uint32x4, lane: number): number;
+        swizzle(a: SIMD.Uint32x4, l1: number, l2: number, l3: number, l4: number): SIMD.Uint32x4;
+        shuffle(a: SIMD.Uint32x4, b: SIMD.Uint32x4, l1: number, l2: number, l3: number, l4: number): SIMD.Uint32x4;
+        check(a: SIMD.Uint32x4): SIMD.Uint32x4;
+        splat(n: number): SIMD.Uint32x4;
+        replaceLane(simd: SIMD.Uint32x4, lane: number, value: number): SIMD.Uint32x4;
+        select(selector: SIMD.Bool32x4, a: SIMD.Uint32x4, b: SIMD.Uint32x4): SIMD.Uint32x4;
+        equal(a: SIMD.Uint32x4, b: SIMD.Uint32x4): SIMD.Bool32x4;
+        notEqual(a: SIMD.Uint32x4, b: SIMD.Uint32x4): SIMD.Bool32x4;
+        lessThan(a: SIMD.Uint32x4, b: SIMD.Uint32x4): SIMD.Bool32x4;
+        lessThanOrEqual(a: SIMD.Uint32x4, b: SIMD.Uint32x4): SIMD.Bool32x4;
+        greaterThan(a: SIMD.Uint32x4, b: SIMD.Uint32x4): SIMD.Bool32x4;
+        greaterThanOrEqual(a: SIMD.Uint32x4, b: SIMD.Uint32x4): SIMD.Bool32x4;
+        and(a: SIMD.Uint32x4, b: SIMD.Uint32x4): SIMD.Uint32x4;
+        or(a: SIMD.Uint32x4, b: SIMD.Uint32x4): SIMD.Uint32x4;
+        xor(a: SIMD.Uint32x4, b: SIMD.Uint32x4): SIMD.Uint32x4;
+        not(a: SIMD.Uint32x4, b: SIMD.Uint32x4): SIMD.Uint32x4;
+        add(a: SIMD.Uint32x4, b: SIMD.Uint32x4): SIMD.Uint32x4;
+        sub(a: SIMD.Uint32x4, b: SIMD.Uint32x4): SIMD.Uint32x4;
+        mul(a: SIMD.Uint32x4, b: SIMD.Uint32x4): SIMD.Uint32x4;
+        shiftLeftByScalar(a: SIMD.Uint32x4, bits: number): SIMD.Uint32x4;
+        shiftRightByScalar(a: SIMD.Uint32x4, bits: number): SIMD.Uint32x4;
+        load(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number): SIMD.Uint32x4;
+        load1(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number): SIMD.Uint32x4;
+        load2(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number): SIMD.Uint32x4;
+        load3(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number): SIMD.Uint32x4;
+        store(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number, value: SIMD.Uint32x4): SIMD.Uint32x4;
+        store1(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number, value: SIMD.Uint32x4): SIMD.Uint32x4;
+        store2(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number, value: SIMD.Uint32x4): SIMD.Uint32x4;
+        store3(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number, value: SIMD.Uint32x4): SIMD.Uint32x4;
+        fromFloat32x4(value: SIMD.Float32x4): SIMD.Uint32x4;
+        fromInt32x4(value: SIMD.Int32x4): SIMD.Uint32x4;
+        fromFloat32x4Bits(value: SIMD.Float32x4): SIMD.Uint32x4;
+        fromInt32x4Bits(value: SIMD.Int32x4): SIMD.Uint32x4;
+        fromInt16x8Bits(value: SIMD.Int16x8): SIMD.Uint32x4;
+        fromInt8x16Bits(value: SIMD.Int8x16): SIMD.Uint32x4;
+        fromUint16x8Bits(value: SIMD.Uint16x8): SIMD.Uint32x4;
+        fromUint8x16Bits(value: SIMD.Uint8x16): SIMD.Uint32x4;
+    }
+
+    interface Uint16x8 {
+        constructor: Uint16x8Constructor;
+        valueOf(): Uint16x8;
+        toLocaleString(): string;
+        toString(): string;
+    }
+
+    interface Uint16x8Constructor {
+        (s0?: number, s1?: number, s2?: number, s3?: number, s4?: number, s5?: number, s6?: number, s7?: number): Uint16x8;
+        prototype: Uint16x8;
+        extractLane(simd: SIMD.Uint16x8, lane: number): number;
+        swizzle(a: SIMD.Uint16x8, l1: number, l2: number, l3: number, l4: number, l5: number, l6: number, l7: number, l8: number): SIMD.Uint16x8;
+        shuffle(a: SIMD.Uint16x8, b: SIMD.Uint16x8, l1: number, l2: number, l3: number, l4: number, l5: number, l6: number, l7: number, l8: number): SIMD.Uint16x8;
+        check(a: SIMD.Uint16x8): SIMD.Uint16x8;
+        splat(n: number): SIMD.Uint16x8;
+        replaceLane(simd: SIMD.Uint16x8, lane: number, value: number): SIMD.Uint16x8;
+        select(selector: SIMD.Bool16x8, a: SIMD.Uint16x8, b: SIMD.Uint16x8): SIMD.Uint16x8;
+        equal(a: SIMD.Uint16x8, b: SIMD.Uint16x8): SIMD.Bool16x8;
+        notEqual(a: SIMD.Uint16x8, b: SIMD.Uint16x8): SIMD.Bool16x8;
+        lessThan(a: SIMD.Uint16x8, b: SIMD.Uint16x8): SIMD.Bool16x8;
+        lessThanOrEqual(a: SIMD.Uint16x8, b: SIMD.Uint16x8): SIMD.Bool16x8;
+        greaterThan(a: SIMD.Uint16x8, b: SIMD.Uint16x8): SIMD.Bool16x8;
+        greaterThanOrEqual(a: SIMD.Uint16x8, b: SIMD.Uint16x8): SIMD.Bool16x8;
+        and(a: SIMD.Uint16x8, b: SIMD.Uint16x8): SIMD.Uint16x8;
+        or(a: SIMD.Uint16x8, b: SIMD.Uint16x8): SIMD.Uint16x8;
+        xor(a: SIMD.Uint16x8, b: SIMD.Uint16x8): SIMD.Uint16x8;
+        not(a: SIMD.Uint16x8, b: SIMD.Uint16x8): SIMD.Uint16x8;
+        add(a: SIMD.Uint16x8, b: SIMD.Uint16x8): SIMD.Uint16x8;
+        sub(a: SIMD.Uint16x8, b: SIMD.Uint16x8): SIMD.Uint16x8;
+        mul(a: SIMD.Uint16x8, b: SIMD.Uint16x8): SIMD.Uint16x8;
+        shiftLeftByScalar(a: SIMD.Uint16x8, bits: number): SIMD.Uint16x8;
+        shiftRightByScalar(a: SIMD.Uint16x8, bits: number): SIMD.Uint16x8;
+        addSaturate(a: SIMD.Uint16x8, b: SIMD.Uint16x8): SIMD.Uint16x8;
+        subSaturate(a: SIMD.Uint16x8, b: SIMD.Uint16x8): SIMD.Uint16x8;
+        load(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number): SIMD.Uint16x8;
+        store(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number, value: SIMD.Uint16x8): SIMD.Uint16x8;
+        fromInt16x8(value: SIMD.Int16x8): SIMD.Uint16x8;
+        fromFloat32x4Bits(value: SIMD.Float32x4): SIMD.Uint16x8;
+        fromInt32x4Bits(value: SIMD.Int32x4): SIMD.Uint16x8;
+        fromInt16x8Bits(value: SIMD.Int16x8): SIMD.Uint16x8;
+        fromInt8x16Bits(value: SIMD.Int8x16): SIMD.Uint16x8;
+        fromUint32x4Bits(value: SIMD.Uint32x4): SIMD.Uint16x8;
+        fromUint8x16Bits(value: SIMD.Uint8x16): SIMD.Uint16x8;
+    }
+
+    interface Uint8x16 {
+        constructor: Uint8x16Constructor;
+        valueOf(): Uint8x16;
+        toLocaleString(): string;
+        toString(): string;
+    }
+
+    interface Uint8x16Constructor {
+        (s0?: number, s1?: number, s2?: number, s3?: number, s4?: number, s5?: number, s6?: number, s7?: number, s8?: number, s9?: number, s10?: number, s11?: number, s12?: number, s13?: number, s14?: number, s15?: number): Uint8x16;
+        prototype: Uint8x16;
+        extractLane(simd: SIMD.Uint8x16, lane: number): number;
+        swizzle(a: SIMD.Uint8x16, l1: number, l2: number, l3: number, l4: number, l5: number, l6: number, l7: number, l8: number, l9: number, l10: number, l11: number, l12: number, l13: number, l14: number, l15: number, l16: number): SIMD.Uint8x16;
+        shuffle(a: SIMD.Uint8x16, b: SIMD.Uint8x16, l1: number, l2: number, l3: number, l4: number, l5: number, l6: number, l7: number, l8: number, l9: number, l10: number, l11: number, l12: number, l13: number, l14: number, l15: number, l16: number): SIMD.Uint8x16;
+        check(a: SIMD.Uint8x16): SIMD.Uint8x16;
+        splat(n: number): SIMD.Uint8x16;
+        replaceLane(simd: SIMD.Uint8x16, lane: number, value: number): SIMD.Uint8x16;
+        select(selector: SIMD.Bool8x16, a: SIMD.Uint8x16, b: SIMD.Uint8x16): SIMD.Uint8x16;
+        equal(a: SIMD.Uint8x16, b: SIMD.Uint8x16): SIMD.Bool8x16;
+        notEqual(a: SIMD.Uint8x16, b: SIMD.Uint8x16): SIMD.Bool8x16;
+        lessThan(a: SIMD.Uint8x16, b: SIMD.Uint8x16): SIMD.Bool8x16;
+        lessThanOrEqual(a: SIMD.Uint8x16, b: SIMD.Uint8x16): SIMD.Bool8x16;
+        greaterThan(a: SIMD.Uint8x16, b: SIMD.Uint8x16): SIMD.Bool8x16;
+        greaterThanOrEqual(a: SIMD.Uint8x16, b: SIMD.Uint8x16): SIMD.Bool8x16;
+        and(a: SIMD.Uint8x16, b: SIMD.Uint8x16): SIMD.Uint8x16;
+        or(a: SIMD.Uint8x16, b: SIMD.Uint8x16): SIMD.Uint8x16;
+        xor(a: SIMD.Uint8x16, b: SIMD.Uint8x16): SIMD.Uint8x16;
+        not(a: SIMD.Uint8x16, b: SIMD.Uint8x16): SIMD.Uint8x16;
+        add(a: SIMD.Uint8x16, b: SIMD.Uint8x16): SIMD.Uint8x16;
+        sub(a: SIMD.Uint8x16, b: SIMD.Uint8x16): SIMD.Uint8x16;
+        mul(a: SIMD.Uint8x16, b: SIMD.Uint8x16): SIMD.Uint8x16;
+        shiftLeftByScalar(a: SIMD.Uint8x16, bits: number): SIMD.Uint8x16;
+        shiftRightByScalar(a: SIMD.Uint8x16, bits: number): SIMD.Uint8x16;
+        addSaturate(a: SIMD.Uint8x16, b: SIMD.Uint8x16): SIMD.Uint8x16;
+        subSaturate(a: SIMD.Uint8x16, b: SIMD.Uint8x16): SIMD.Uint8x16;
+        load(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number): SIMD.Uint8x16;
+        store(tarray: Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array, index: number, value: SIMD.Uint8x16): SIMD.Uint8x16;
+        fromInt8x16(value: SIMD.Int8x16): SIMD.Uint8x16;
+        fromFloat32x4Bits(value: SIMD.Float32x4): SIMD.Uint8x16;
+        fromInt32x4Bits(value: SIMD.Int32x4): SIMD.Uint8x16;
+        fromInt16x8Bits(value: SIMD.Int16x8): SIMD.Uint8x16;
+        fromInt8x16Bits(value: SIMD.Int8x16): SIMD.Uint8x16;
+        fromUint32x4Bits(value: SIMD.Uint32x4): SIMD.Uint8x16;
+        fromUint16x8Bits(value: SIMD.Uint16x8): SIMD.Uint8x16;
+    }
+
+    interface Bool32x4 {
+        constructor: Bool32x4Constructor;
+        valueOf(): Bool32x4;
+        toLocaleString(): string;
+        toString(): string;
+    }
+
+    interface Bool32x4Constructor {
+        (s0?: boolean, s1?: boolean, s2?: boolean, s3?: boolean): Bool32x4;
+        prototype: Bool32x4;
+        extractLane(simd: SIMD.Bool32x4, lane: number): boolean;
+        check(a: SIMD.Bool32x4): SIMD.Bool32x4;
+        splat(n: boolean): SIMD.Bool32x4;
+        replaceLane(simd: SIMD.Bool32x4, lane: number, value: boolean): SIMD.Bool32x4;
+        allTrue(a: SIMD.Bool32x4): boolean;
+        anyTrue(a: SIMD.Bool32x4): boolean;
+        and(a: SIMD.Bool32x4, b: SIMD.Bool32x4): SIMD.Bool32x4;
+        or(a: SIMD.Bool32x4, b: SIMD.Bool32x4): SIMD.Bool32x4;
+        xor(a: SIMD.Bool32x4, b: SIMD.Bool32x4): SIMD.Bool32x4;
+        not(a: SIMD.Bool32x4, b: SIMD.Bool32x4): SIMD.Bool32x4;
+    }
+
+    interface Bool16x8 {
+        constructor: Bool16x8Constructor;
+        valueOf(): Bool16x8;
+        toLocaleString(): string;
+        toString(): string;
+    }
+
+    interface Bool16x8Constructor {
+        (s0?: boolean, s1?: boolean, s2?: boolean, s3?: boolean, s4?: boolean, s5?: boolean, s6?: boolean, s7?: boolean): Bool16x8;
+        prototype: Bool16x8;
+        extractLane(simd: SIMD.Bool16x8, lane: number): boolean;
+        check(a: SIMD.Bool16x8): SIMD.Bool16x8;
+        splat(n: boolean): SIMD.Bool16x8;
+        replaceLane(simd: SIMD.Bool16x8, lane: number, value: boolean): SIMD.Bool16x8;
+        allTrue(a: SIMD.Bool16x8): boolean;
+        anyTrue(a: SIMD.Bool16x8): boolean;
+        and(a: SIMD.Bool16x8, b: SIMD.Bool16x8): SIMD.Bool16x8;
+        or(a: SIMD.Bool16x8, b: SIMD.Bool16x8): SIMD.Bool16x8;
+        xor(a: SIMD.Bool16x8, b: SIMD.Bool16x8): SIMD.Bool16x8;
+        not(a: SIMD.Bool16x8, b: SIMD.Bool16x8): SIMD.Bool16x8;
+    }
+
+    interface Bool8x16 {
+        constructor: Bool8x16Constructor;
+        valueOf(): Bool8x16;
+        toLocaleString(): string;
+        toString(): string;
+    }
+
+    interface Bool8x16Constructor {
+        (s0?: boolean, s1?: boolean, s2?: boolean, s3?: boolean, s4?: boolean, s5?: boolean, s6?: boolean, s7?: boolean, s8?: boolean, s9?: boolean, s10?: boolean, s11?: boolean, s12?: boolean, s13?: boolean, s14?: boolean, s15?: boolean): Bool8x16;
+        prototype: Bool8x16;
+        extractLane(simd: SIMD.Bool8x16, lane: number): boolean;
+        check(a: SIMD.Bool8x16): SIMD.Bool8x16;
+        splat(n: boolean): SIMD.Bool8x16;
+        replaceLane(simd: SIMD.Bool8x16, lane: number, value: boolean): SIMD.Bool8x16;
+        allTrue(a: SIMD.Bool8x16): boolean;
+        anyTrue(a: SIMD.Bool8x16): boolean;
+        and(a: SIMD.Bool8x16, b: SIMD.Bool8x16): SIMD.Bool8x16;
+        or(a: SIMD.Bool8x16, b: SIMD.Bool8x16): SIMD.Bool8x16;
+        xor(a: SIMD.Bool8x16, b: SIMD.Bool8x16): SIMD.Bool8x16;
+        not(a: SIMD.Bool8x16, b: SIMD.Bool8x16): SIMD.Bool8x16;
+    }
 }
 }

+ 1 - 0
src/babylon.scene.js

@@ -105,6 +105,7 @@ var BABYLON;
             this.forceShowBoundingBoxes = false;
             this.forceShowBoundingBoxes = false;
             this.animationsEnabled = true;
             this.animationsEnabled = true;
             this.constantlyUpdateMeshUnderPointer = false;
             this.constantlyUpdateMeshUnderPointer = false;
+            this.useRightHandedSystem = false;
             this.hoverCursor = "pointer";
             this.hoverCursor = "pointer";
             // Events
             // Events
             /**
             /**

+ 1 - 0
src/babylon.scene.ts

@@ -103,6 +103,7 @@
         public clipPlane: Plane;
         public clipPlane: Plane;
         public animationsEnabled = true;
         public animationsEnabled = true;
         public constantlyUpdateMeshUnderPointer = false;
         public constantlyUpdateMeshUnderPointer = false;
+        public useRightHandedSystem = false;
 
 
         public hoverCursor = "pointer";
         public hoverCursor = "pointer";