Browse Source

updating repo

Adam Bowman 9 years ago
parent
commit
2aa52b708c
67 changed files with 6562 additions and 4630 deletions
  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)
         {
             bool needToDelete = false;
-            var useJPG = !texture2D.alphaIsTransparency;
 
             // Convert unsupported file extensions
             if (texturePath.EndsWith(".psd") || texturePath.EndsWith(".tif") || texturePath.EndsWith(".exr"))
@@ -112,11 +111,8 @@ namespace Unity3D2Babylon
                     textureImporter.grayscaleToAlpha = false;
 
                     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);
 
                     if (isLightmap)
@@ -130,12 +126,22 @@ namespace Unity3D2Babylon
                         }
                         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.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;
 
@@ -154,6 +160,14 @@ namespace Unity3D2Babylon
                     Debug.LogException(ex);
                 }
             }
+            else if (texture2D.alphaIsTransparency || texturePath.EndsWith(".png"))
+            {
+                babylonTexture.hasAlpha = true;
+            }
+            else
+            {
+                babylonTexture.hasAlpha = false;
+            }
 
             var textureName = Path.GetFileName(texturePath);
             babylonTexture.name = textureName;
@@ -594,8 +608,6 @@ namespace Unity3D2Babylon
             var texture2D = texture as Texture2D;
             if (texture2D)
             {
-                babylonTexture.hasAlpha = texture2D.alphaIsTransparency;
-
                 CopyTexture(texturePath, texture2D, babylonTexture, isLightmap);
             }
             else

+ 2 - 2
Tools/Gulp/config.json

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

+ 1 - 1
Tools/Gulp/package.json

@@ -8,7 +8,7 @@
   "license": "(Apache-2.0)",
   "devDependencies": {
     "gulp": "^3.8.11",
-    "gulp-uglify": "~1.2.0",
+    "gulp-uglify": "~1.5.3",
     "gulp-sourcemaps": "~1.5.2",
     "typescript": "^1.7.5",
     "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@"
+}

File diff suppressed because it is too large
+ 26 - 34
dist/preview release/babylon.core.js


File diff suppressed because it is too large
+ 834 - 376
dist/preview release/babylon.d.ts


File diff suppressed because it is too large
+ 42 - 53
dist/preview release/babylon.js


File diff suppressed because it is too large
+ 3652 - 3394
dist/preview release/babylon.max.js


File diff suppressed because it is too large
+ 42 - 53
dist/preview release/babylon.noworker.js


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

@@ -1,7 +1,7 @@
 # 2.5.0:
 
 ### Major updates
-    
+- Babylon.js now supports right handed system with ```scene.useRightHandedSystem = true``` ([deltakosh](https://github.com/deltakosh))    
 ### Updates
 - Cube textures are now cached by texture cache ([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 INSTANCES = false;
         public SPECULARTERM = false;
+        public LOGARITHMICDEPTH = false;
+        public FRESNELSEPARATE = false;
+        public BUMPSUPERIMPOSE = false;
+        public BUMPAFFECTSREFLECTION = false;
+
 
         constructor() {
             super();
@@ -68,7 +73,23 @@ module BABYLON {
         @serialize()
 		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()
 		public waterColor: Color3 = new Color3(0.1, 0.1, 0.6);
@@ -78,6 +99,16 @@ module BABYLON {
         @serialize()
 		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
         */
         @serialize()
@@ -106,8 +137,10 @@ module BABYLON {
 
         private _defines = new WaterMaterialDefines();
         private _cachedDefines = new WaterMaterialDefines();
-		
-		/**
+
+        private _useLogarithmicDepth: boolean;
+
+        /**
 		* Constructor
 		*/
 		constructor(name: string, scene: Scene, public renderTargetSize: Vector2 = new Vector2(512, 512)) {
@@ -116,7 +149,16 @@ module BABYLON {
 			// Create render targets
 			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
         public get refractionTexture(): RenderTargetTexture {
             return this._refractionRTT;
@@ -228,6 +270,22 @@ module BABYLON {
                 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
             if (scene.fogEnabled && mesh && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE && this.fogEnabled) {
                 this._defines.FOG = true;
@@ -284,6 +342,10 @@ module BABYLON {
                     fallbacks.addFallback(1, "FOG");
                 }
 
+                if (this._defines.LOGARITHMICDEPTH) {
+                    fallbacks.addFallback(0, "LOGARITHMICDEPTH");
+                }
+
                 MaterialHelper.HandleFallbacksForShadows(this._defines, fallbacks, this.maxSimultaneousLights);
              
                 if (this._defines.NUM_BONE_INFLUENCERS > 0) {
@@ -320,9 +382,11 @@ module BABYLON {
                     "vNormalInfos", 
                     "mBones",
                     "vClipPlane", "normalMatrix",
+                    "logarithmicDepthConstant",
+
                     // Water
                     "worldReflectionViewProjection", "windDirection", "waveLength", "time", "windForce",
-                    "cameraPosition", "bumpHeight", "waveHeight", "waterColor", "colorBlendFactor", "waveSpeed"
+                    "cameraPosition", "bumpHeight", "waveHeight", "waterColor", "waterColor2", "colorBlendFactor", "colorBlendFactor2", "waveSpeed"
                 ]
                 var samplers = ["normalSampler",
                     // Water
@@ -403,7 +467,10 @@ module BABYLON {
 
             // Fog
             MaterialHelper.BindFogParameters(scene, mesh, this._effect);
-            
+
+            // Log. depth
+            MaterialHelper.BindLogDepth(this._defines, this._effect, scene);
+
             // Water
             if (StandardMaterial.ReflectionTextureEnabled) {
                 this._effect.setTexture("refractionSampler", this._refractionRTT);
@@ -422,6 +489,8 @@ module BABYLON {
             this._effect.setFloat("bumpHeight", this.bumpHeight);
 			this._effect.setColor4("waterColor", this.waterColor, 1.0);
 			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);
 
             super.bind(world, mesh);
@@ -430,8 +499,13 @@ module BABYLON {
 		private _createRenderTargets(scene: Scene, renderTargetSize: Vector2): void {
 			// Render targets
 			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.wrapU = BABYLON.Texture.MIRROR_ADDRESSMODE;
+            this._reflectionRTT.wrapV = BABYLON.Texture.MIRROR_ADDRESSMODE;
+
 			scene.customRenderTargets.push(this._refractionRTT);
 			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;
 
 // Constants
@@ -28,6 +32,7 @@ varying vec4 vColor;
 // Samplers
 #ifdef BUMP
 varying vec2 vNormalUV;
+varying vec2 vNormalUV2;
 uniform sampler2D normalSampler;
 uniform vec2 vNormalInfos;
 #endif
@@ -43,14 +48,20 @@ uniform vec3 cameraPosition;
 uniform vec4 waterColor;
 uniform float colorBlendFactor;
 
+uniform vec4 waterColor2;
+uniform float colorBlendFactor2;
+
 uniform float bumpHeight;
 
+uniform float time;
+
 // Water varyings
 varying vec3 vRefractionMapTexCoord;
 varying vec3 vReflectionMapTexCoord;
 varying vec3 vPosition;
 
 #include<clipPlaneFragmentDeclaration>
+#include<logDepthDeclaration>
 
 // Fog
 #include<fogFragmentDeclaration>
@@ -69,7 +80,11 @@ void main(void) {
 	float alpha = vDiffuseColor.a;
 
 #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;
 
 #ifdef ALPHATEST
@@ -88,63 +103,130 @@ void main(void) {
 
 	// Bump
 #ifdef NORMAL
-	vec3 normalW = normalize(vNormalW);
 	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
 	vec3 normalW = vec3(1.0, 1.0, 1.0);
 	vec2 perturbation = bumpHeight * (vec2(1.0, 1.0) - 0.5);
 #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;
-	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>
 	
 	gl_FragColor = color;
-}
+}

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

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

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

@@ -44,29 +44,60 @@ window.prepareWater = function() {
 	});
 	
 	// 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() {
-		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() {
-		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() {
-		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() {
-		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;
 }

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

@@ -7,10 +7,19 @@ var BABYLON;
             this.canUseWebAudio = false;
             this.WarnedWebAudioUnsupported = false;
             this.unlocked = false;
+            this.isMP3supported = false;
+            this.isOGGsupported = false;
             if (typeof window.AudioContext !== 'undefined' || typeof window.webkitAudioContext !== 'undefined') {
                 window.AudioContext = window.AudioContext || window.webkitAudioContext;
                 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)) {
                 this._unlockiOSaudio();
             }

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

@@ -10,6 +10,9 @@
         public unlocked: boolean = false;
         public onAudioUnlocked: () => any;
 
+        public isMP3supported: boolean = false;
+        public isOGGsupported: boolean = false;
+
         public get audioContext(): AudioContext {
             if (!this._audioContextInitialized) {
                 this._initializeAudioContext();
@@ -23,6 +26,16 @@
                 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)) {
                 this._unlockiOSaudio();
             }

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

@@ -37,6 +37,7 @@ var BABYLON;
             this._coneOuterAngle = 360;
             this._coneOuterGain = 0;
             this._isOutputConnected = false;
+            this._urlType = "Unknown";
             this.name = name;
             this._scene = scene;
             this._readyToPlayCallback = readyToPlayCallback;
@@ -74,41 +75,83 @@ var BABYLON;
                     this._createSpatialParameters();
                 }
                 this._scene.mainSoundTrack.AddSound(this);
+                var validParameter = true;
                 // if no parameter is passed, you need to call setAudioBuffer yourself to prepare the sound
                 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 {
-                        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) {
                     _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) {
             if (BABYLON.Engine.audioEngine.canUseWebAudio) {

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

@@ -43,6 +43,7 @@
         private _registerFunc: (connectedMesh: AbstractMesh) => any;
         private _isOutputConnected = false;
         private _htmlAudioElement: HTMLAudioElement;
+        private _urlType: string = "Unknown";
 
         /**
         * Create a sound and attach it to a scene
@@ -90,42 +91,83 @@
                     this._createSpatialParameters();
                 }
                 this._scene.mainSoundTrack.AddSound(this);
+                var validParameter = true;
                 // if no parameter is passed, you need to call setAudioBuffer yourself to prepare the sound
                 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 {
-                        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;
                 if (this.autoplay) { this.play(); }
                 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 {

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

@@ -22,12 +22,12 @@ var BABYLON;
     BABYLON.VRDeviceOrientationFreeCamera = VRDeviceOrientationFreeCamera;
     var VRDeviceOrientationArcRotateCamera = (function (_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 (vrCameraMetrics === void 0) { vrCameraMetrics = BABYLON.VRCameraMetrics.GetDefault(); }
             _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();
         }
         VRDeviceOrientationArcRotateCamera.prototype.getTypeName = function () {

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

@@ -16,12 +16,11 @@ module BABYLON {
 
     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);
 
-            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();
         }

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

@@ -407,7 +407,12 @@ var BABYLON;
                     up = up.clone();
                     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[13] += this.targetScreenOffset.y;
             }

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

@@ -431,7 +431,11 @@
                     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[13] += this.targetScreenOffset.y;
             }

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

@@ -348,16 +348,27 @@ var BABYLON;
             }
             this._refreshFrustumPlanes = true;
             var engine = this.getEngine();
+            var scene = this.getScene();
             if (this.mode === Camera.PERSPECTIVE_CAMERA) {
                 if (this.minZ <= 0) {
                     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;
             }
             var halfWidth = engine.getRenderWidth() / 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;
         };
         Camera.prototype.getTranformationMatrix = function () {

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

@@ -417,18 +417,49 @@
             this._refreshFrustumPlanes = true;
 
             var engine = this.getEngine();
+            var scene = this.getScene();
             if (this.mode === Camera.PERSPECTIVE_CAMERA) {
                 if (this.minZ <= 0) {
                     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;
             }
 
             var halfWidth = engine.getRenderWidth() / 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;
         }
 

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

@@ -185,7 +185,12 @@ var BABYLON;
             else {
                 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;
         };
         /**
@@ -228,8 +233,14 @@ var BABYLON;
                     break;
                 case BABYLON.Camera.RIG_MODE_VR:
                 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);
                     camRight.position.copyFrom(this.position);
                     break;

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

@@ -227,7 +227,12 @@
                 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;
         }
 
@@ -275,8 +280,13 @@
 
                 case Camera.RIG_MODE_VR:
                 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);
                     camRight.position.copyFrom(this.position);
 

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

@@ -120,6 +120,10 @@ var BABYLON;
                         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);
             }
             var engine = scene.getEngine();
@@ -859,6 +863,20 @@ var BABYLON;
             enumerable: 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", {
             /**
              * 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 worldMtx = node.getWorldMatrix();
                 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 () {
             this._initPerfMetrics();
-            this._updateTrackedNodes();
             this._updateCanvasState(false);
+            this._updateTrackedNodes();
             // Nothing to do is the Canvas is not visible
             if (this.isVisible === false) {
                 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);
             }
 
@@ -950,6 +955,14 @@
             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
          * @returns {} 
@@ -1159,8 +1172,9 @@
                 let worldMtx = node.getWorldMatrix();
 
                 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._updateTrackedNodes();
-
             this._updateCanvasState(false);
 
+            this._updateTrackedNodes();
+
             // Nothing to do is the Canvas is not visible
             if (this.isVisible === false) {
                 return;

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

@@ -299,6 +299,15 @@ var BABYLON;
             var a = this.actualScale;
             var sw = Math.ceil(s.width * a.x);
             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
             // 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) {

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

@@ -361,6 +361,16 @@
             let sw = Math.ceil(s.width * a.x);
             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
             // 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) {

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

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

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

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

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

@@ -339,7 +339,7 @@ var BABYLON;
         });
         Object.defineProperty(RenderablePrim2D.prototype, "isTransparent", {
             get: function () {
-                return (this._opacity < 1) || this._shouldUseAlphaFromTexture() || this._isPrimTransparent();
+                return (this.actualOpacity < 1) || this._shouldUseAlphaFromTexture() || this._isPrimTransparent();
             },
             enumerable: true,
             configurable: true
@@ -392,14 +392,17 @@ var BABYLON;
                 if (gii.hasOpaqueData) {
                     var od = gii.opaqueData[0];
                     usedCount += od._partData.usedElementCount;
+                    gii.opaqueDirty = true;
                 }
                 if (gii.hasAlphaTestData) {
                     var atd = gii.alphaTestData[0];
                     usedCount += atd._partData.usedElementCount;
+                    gii.alphaTestDirty = true;
                 }
                 if (gii.hasTransparentData) {
                     var td = gii.transparentData[0];
                     usedCount += td._partData.usedElementCount;
+                    gii.transparentDirty = true;
                 }
                 if (usedCount === 0 && gii.modelRenderCache != null) {
                     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.
          */
         public get isTransparent(): boolean {
-            return (this._opacity<1) || this._shouldUseAlphaFromTexture() || this._isPrimTransparent();
+            return (this.actualOpacity<1) || this._shouldUseAlphaFromTexture() || this._isPrimTransparent();
         }
 
         public get renderMode(): number {
@@ -424,14 +424,17 @@
                 if (gii.hasOpaqueData) {
                     let od = gii.opaqueData[0];
                     usedCount += od._partData.usedElementCount;
+                    gii.opaqueDirty = true;
                 }
                 if (gii.hasAlphaTestData) {
                     let atd = gii.alphaTestData[0];
                     usedCount += atd._partData.usedElementCount;
+                    gii.alphaTestDirty = true;
                 }
                 if (gii.hasTransparentData) {
                     let td = gii.transparentData[0];
                     usedCount += td._partData.usedElementCount;
+                    gii.transparentDirty = true;
                 }
 
                 if (usedCount === 0 && gii.modelRenderCache!=null) {

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

@@ -277,20 +277,14 @@ var BABYLON;
             }
             return false;
         };
-        SmartPropertyPrim.prototype.markAsDirty = function (propertyName) {
+        SmartPropertyPrim.prototype._triggerPropertyChanged = function (propInfo, newValue) {
             if (this.isDisposed) {
                 return;
             }
-            var i = propertyName.indexOf(".");
-            if (i !== -1) {
-                propertyName = propertyName.substr(0, i);
-            }
-            var propInfo = this.propDic.get(propertyName);
             if (!propInfo) {
                 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 () {
             this._setFlags(SmartPropertyPrim.flagLevelBoundingInfoDirty);

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

@@ -316,25 +316,16 @@
             return false;
         }
 
-        private static propChangedInfo = new PropertyChangedInfo();
-
-        public markAsDirty(propertyName: string) {
+        protected _triggerPropertyChanged(propInfo: Prim2DPropInfo, newValue: any) {
             if (this.isDisposed) {
                 return;
             }
 
-            let i = propertyName.indexOf(".");
-            if (i !== -1) {
-                propertyName = propertyName.substr(0, i);
-            }
-
-            var propInfo = this.propDic.get(propertyName);
             if (!propInfo) {
                 return;
             }
 
-            var newValue = this[propertyName];
-            this._handlePropChanged(undefined, newValue, propertyName, propInfo, propInfo.typeLevelCompare);
+            this._handlePropChanged(undefined, newValue, propInfo.name, propInfo, propInfo.typeLevelCompare);
         }
 
         protected _boundingBoxDirty() {
@@ -361,6 +352,7 @@
             }
         }
 
+        private static propChangedInfo = new PropertyChangedInfo();
         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 (propInfo.dirtyBoundingInfo) {

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

@@ -23,12 +23,50 @@ var BABYLON;
             this.includedOnlyMeshes = new Array();
             this.excludedMeshes = new Array();
             this.excludeWithLayerMask = 0;
+            this.lightmapMode = 0;
             // PBR Properties.
             this.radius = 0.00001;
             this._excludedMeshesIds = new Array();
             this._includedOnlyMeshesIds = new Array();
             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
          */
@@ -167,6 +205,10 @@ var BABYLON;
             }
             return light;
         };
+        //lightmapMode Consts
+        Light._LIGHTMAP_DEFAULT = 0;
+        Light._LIGHTMAP_SPECULAR = 1;
+        Light._LIGHTMAP_SHADOWSONLY = 2;
         __decorate([
             BABYLON.serializeAsColor3()
         ], Light.prototype, "diffuse", void 0);
@@ -187,6 +229,9 @@ var BABYLON;
         ], Light.prototype, "excludeWithLayerMask", void 0);
         __decorate([
             BABYLON.serialize()
+        ], Light.prototype, "lightmapMode", void 0);
+        __decorate([
+            BABYLON.serialize()
         ], Light.prototype, "radius", void 0);
         return Light;
     })(BABYLON.Node);

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

@@ -21,6 +21,40 @@
     }
 
     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()
         public diffuse = new Color3(1.0, 1.0, 1.0);
 
@@ -42,6 +76,9 @@
         @serialize()
         public excludeWithLayerMask = 0;
 
+        @serialize()
+        public lightmapMode = 0;
+
         // PBR Properties.
         @serialize()
         public radius = 0.00001;

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

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

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

@@ -114,7 +114,7 @@
         public backFaceCulling = true;
 
         @serialize()
-        public sideOrientation = Material.CounterClockWiseSideOrientation;
+        public sideOrientation: number;
 
         public onCompiled: (effect: Effect) => void;
         public onError: (effect: Effect, errors: string) => void;
@@ -209,6 +209,12 @@
 
             this._scene = scene;
 
+            if (scene.useRightHandedSystem) {
+                this.sideOrientation = Material.ClockWiseSideOrientation;
+            } else {
+                this.sideOrientation = Material.CounterClockWiseSideOrientation;
+            }
+
             if (!doNotAdd) {
                 scene.materials.push(this);
             }
@@ -267,9 +273,10 @@
 
         public _preBind(): void {
             var engine = this._scene.getEngine();
+            var reverse = this.sideOrientation === Material.ClockWiseSideOrientation;
 
             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 {

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

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

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

@@ -5,6 +5,7 @@
             var needNormals = false;
             var needRebuild = false;
             var needShadows = false;
+            var lightmapMode = false;
 
             for (var index = 0; index < scene.lights.length; 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++;
                 if (lightIndex === maxSimultaneousLights)
                     break;
@@ -117,6 +132,13 @@
                 defines["SHADOWFULLFLOAT"] = true;
             }
 
+            if (defines["LIGHTMAPEXCLUDED"] === undefined) {
+                needRebuild = true;
+            }
+            if (lightmapMode) {
+                defines["LIGHTMAPEXCLUDED"] = true;
+            }
+
             if (needRebuild) {
                 defines.rebuild();
             }

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

@@ -4,207 +4,182 @@ var BABYLON;
         function SIMDVector3() {
         }
         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) {
-            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;
     })();
-    BABYLON.SIMDVector3 = SIMDVector3;
     var SIMDMatrix = (function () {
         function SIMDMatrix() {
         }
         SIMDMatrix.prototype.multiplyToArraySIMD = function (other, result, offset) {
-            if (offset === void 0) { offset = 0; }
             var tm = this.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) {
             var src = this.m;
             var dest = other.m;
-            var row0, row1, row2, row3;
-            var tmp1;
-            var minor0, minor1, minor2, minor3;
-            var det;
             // 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
-            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
-            //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
-            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
             // 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
-            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;
         };
         SIMDMatrix.LookAtLHToRefSIMD = function (eyeRef, targetRef, upRef, result) {
             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);
-            var f = SIMD.float32x4.sub(center, eye);
+            var f = SIMD.Float32x4.sub(center, eye);
             // 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.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);
-            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);
-            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);
-            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);
-            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;
     })();
-    BABYLON.SIMDMatrix = SIMDMatrix;
     var previousMultiplyToArray = BABYLON.Matrix.prototype.multiplyToArray;
     var previousInvertToRef = BABYLON.Matrix.prototype.invertToRef;
     var previousLookAtLHToRef = BABYLON.Matrix.LookAtLHToRef;
@@ -230,36 +205,32 @@ var BABYLON;
             SIMDHelper._isEnabled = false;
         };
         SIMDHelper.EnableSIMD = function () {
-            if (window.SIMD === undefined) {
+            if (self.SIMD === undefined) {
                 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
             BABYLON.Matrix.prototype.multiplyToArray = SIMDMatrix.prototype.multiplyToArraySIMD;
             BABYLON.Matrix.prototype.invertToRef = SIMDMatrix.prototype.invertToRefSIMD;
             BABYLON.Matrix.LookAtLHToRef = SIMDMatrix.LookAtLHToRefSIMD;
             BABYLON.Vector3.TransformCoordinatesToRef = SIMDVector3.TransformCoordinatesToRefSIMD;
             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 = false;

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

@@ -1,255 +1,221 @@
 module BABYLON {
 
-    declare var SIMD;
+    declare var SIMD: SIMD;
 
-    export class SIMDVector3 {
+    class SIMDVector3 {
         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 {
-            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 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 {
-            var src = (<any>this).m;
+            var src: Float32Array = (<any>this).m;
             var dest = other.m;
-            var row0, row1, row2, row3;
-            var tmp1;
-            var minor0, minor1, minor2, minor3;
-            var det;
 
             // 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
 
-            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
 
-            //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
-            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
             // 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
-            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);
         }
 
         public static LookAtLHToRefSIMD(eyeRef: Vector3, targetRef: Vector3, upRef: Vector3, result: Matrix): void {
             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);
-            var f = SIMD.float32x4.sub(center, eye);
+            var f = SIMD.Float32x4.sub(center, eye);
             // 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.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);
-            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);
-            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);
-            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);
-            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 {
             // 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;
         }
 
         public static EnableSIMD(): void {
-            if (window.SIMD === undefined) {
+            if (self.SIMD === undefined) {
                 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
-            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;
         }
     }
 }
-
-

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

@@ -2258,6 +2258,32 @@ var BABYLON;
             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.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) {
             var matrix = Matrix.Zero();
             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[5] = 2.0 / (top - bottom);
             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[12] = (left + right) / (left - right);
             result.m[13] = (top + bottom) / (bottom - top);
-            result.m[14] = znear / (znear - zfar);
+            result.m[14] = -znear / (zfar - znear);
             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) {
             var matrix = Matrix.Zero();
             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[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[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);
         };
         Matrix.PerspectiveFovWebVRToRef = function (fov, znear, zfar, result, isVerticalFovFixed) {

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

@@ -737,7 +737,6 @@
     export class Vector3 {
 
         constructor(public x: number, public y: number, public z: number) {
-
         }
 
         public toString(): string {
@@ -757,7 +756,7 @@
 
         // Operators
         public asArray(): number[] {
-            var result = [];
+            var result: number[] = [];
 
             this.toArray(result, 0);
 
@@ -2828,6 +2827,43 @@
                 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 {
             var matrix = Matrix.Zero();
 
@@ -2861,14 +2897,27 @@
             result.m[1] = result.m[2] = result.m[3] = 0;
             result.m[5] = 2.0 / (top - bottom);
             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[12] = (left + right) / (left - right);
             result.m[13] = (top + bottom) / (bottom - top);
-            result.m[14] = znear / (znear - zfar);
+            result.m[14] = -znear / (zfar - znear);
             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 {
             var matrix = Matrix.Zero();
 
@@ -2914,13 +2963,48 @@
 
             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[10] = zfar / (zfar - znear);
             result.m[11] = 1.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);
         }
 
-        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 downTan = Math.tan(fov.downDegrees * 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) {
                     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
             if (this._edgesRenderer) {

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

@@ -1162,6 +1162,16 @@
                 if (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

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

@@ -505,13 +505,14 @@ var BABYLON;
             }
             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 () {
-            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) {
             var scene = mesh.getScene();

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

@@ -632,13 +632,14 @@
             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 {
-            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 {

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

@@ -14,15 +14,30 @@ var BABYLON;
         }
         Object.defineProperty(GroundMesh.prototype, "subdivisions", {
             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,
             configurable: true
         });
         GroundMesh.prototype.optimize = function (chunksCount, octreeBlocksSize) {
             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);
         };
         /**
@@ -98,9 +113,11 @@ var BABYLON;
         // Returns the element "facet" from the heightQuads array relative to (x, z) local coordinates
         GroundMesh.prototype._getFacetAt = function (x, z) {
             // 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;
             if (z < quad.slope.x * x + quad.slope.y) {
                 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
         // facet2 :  Vector4(a, b, c, d) = second facet 3D plane equation : ax + by + cz + d = 0
         GroundMesh.prototype._initHeightQuads = function () {
+            var subdivisionsX = this._subdivisionsX;
+            var subdivisionsY = this._subdivisionsY;
             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) };
-                    this._heightQuads[row * this._subdivisions + col] = quad;
+                    this._heightQuads[row * subdivisionsX + col] = quad;
                 }
             }
         };
@@ -146,11 +165,13 @@ var BABYLON;
             var h = 0;
             var d1 = 0; // facet plane equation : ax + by + cz + d = 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;
-                    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.y = positions[j + i + 1];
                     v1.z = positions[j + i + 2];
@@ -180,7 +201,7 @@ var BABYLON;
                     norm2.normalize();
                     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);
-                    var quad = this._heightQuads[row * this._subdivisions + col];
+                    var quad = this._heightQuads[row * subdivisionsX + col];
                     quad.slope.copyFromFloats(cd, h);
                     quad.facet1.copyFromFloats(norm1.x, norm1.y, norm1.z, d1);
                     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) {
                 return;
             }
+            var oldGeometry = this._geometry;
             var geometry = this._geometry.copy(BABYLON.Geometry.RandomId());
+            oldGeometry.releaseForMesh(this, true);
             geometry.applyToMesh(this);
         };
         /**

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

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

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

@@ -988,24 +988,25 @@ var BABYLON;
             var row, col;
             var width = options.width || 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);
                     positions.push(position.x, position.y, position.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

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

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

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

@@ -307,9 +307,9 @@ var BABYLON;
             impostor.physicsBody.awake();
         };
         OimoJSPlugin.prototype.updateDistanceJoint = function (joint, maxDistance, minDistance) {
-            joint.physicsJoint.limitMotoe.upperLimit = maxDistance;
+            joint.physicsJoint.limitMotor.upperLimit = maxDistance;
             if (minDistance !== void 0) {
-                joint.physicsJoint.limitMotoe.lowerLimit = minDistance;
+                joint.physicsJoint.limitMotor.lowerLimit = minDistance;
             }
         };
         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) {
-            joint.physicsJoint.limitMotoe.upperLimit = maxDistance;
+            joint.physicsJoint.limitMotor.upperLimit = maxDistance;
             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}
-	#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 SHADOWVSM{X}
 			shadow = computeShadowWithVSM(vPositionFromLight{X}, shadowSampler{X}, shadowsInfo{X}.z, shadowsInfo{X}.x);
@@ -32,8 +36,17 @@
 	#else
 		shadow = 1.;
 	#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

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

@@ -1,15 +1,19 @@
 #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
     
     #ifdef SHADOW{X}
@@ -34,17 +38,27 @@
         notShadowLevel = 1.;
     #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

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

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

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

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

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

@@ -639,6 +639,17 @@ var BABYLON;
             }
             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", {
             get: function () {
                 return Tools._NoneLogLevel;

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

@@ -750,6 +750,18 @@
             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
         private static _NoneLogLevel = 0;
         private static _MessageLogLevel = 1;

+ 1 - 1
src/babylon.engine.ts

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

+ 437 - 0
src/babylon.mixins.ts

@@ -19,6 +19,13 @@ interface Window {
     AudioContext: AudioContext;
     webkitAudioContext: AudioContext;
     PointerEvent: any;
+    Math: Math;
+    Uint8Array: Uint8ArrayConstructor;
+    Float32Array: Float32ArrayConstructor;
+}
+
+interface AudioContext extends EventTarget {
+    decodeAudioData(audioData: ArrayBuffer, successCallback: DecodeSuccessCallback, errorCallback?: any): void;
 }
 
 interface HTMLURL {
@@ -110,4 +117,434 @@ interface Screen {
 
 interface HTMLMediaElement {
     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.animationsEnabled = true;
             this.constantlyUpdateMeshUnderPointer = false;
+            this.useRightHandedSystem = false;
             this.hoverCursor = "pointer";
             // Events
             /**

+ 1 - 0
src/babylon.scene.ts

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