Explorar el Código

Added Material.sideOrientation
First alpha of lightmapTexture property on StdMaterial

David catuhe hace 10 años
padre
commit
c6aae2264e

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 868 - 860
dist/preview release/babylon.d.ts


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 25 - 21
dist/preview release/babylon.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 66 - 14
dist/preview release/babylon.max.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 24 - 20
dist/preview release/babylon.noworker.js


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

@@ -1,6 +1,8 @@
 - 2.3.0:
 - 2.3.0:
   - **Major updates**
   - **Major updates**
+    - New `StandardMaterial.lightmapTexture` which can be controlled with `StandardMaterial.lightmapThreshold`. [Demo here](#NEEDDEMO) ([deltakosh](https://github.com/deltakosh))
   - **Updates**
   - **Updates**
+    - New `Material.sideOrientation` property to define clockwise or counter-clockwise faces selection. [Demo here](http://www.babylonjs-playground.com/#1TZJQY) ([deltakosh](https://github.com/deltakosh))
   - **Bug fixes**
   - **Bug fixes**
   - **Breaking changes**
   - **Breaking changes**
 
 

+ 5 - 1
src/Audio/babylon.sound.js

@@ -35,6 +35,7 @@ var BABYLON;
             this._coneInnerAngle = 360;
             this._coneInnerAngle = 360;
             this._coneOuterAngle = 360;
             this._coneOuterAngle = 360;
             this._coneOuterGain = 0;
             this._coneOuterGain = 0;
+            this._isOutputConnected = false;
             this.name = name;
             this.name = name;
             this._scene = scene;
             this._scene = scene;
             this._readyToPlayCallback = readyToPlayCallback;
             this._readyToPlayCallback = readyToPlayCallback;
@@ -213,8 +214,11 @@ var BABYLON;
         };
         };
         Sound.prototype.connectToSoundTrackAudioNode = function (soundTrackAudioNode) {
         Sound.prototype.connectToSoundTrackAudioNode = function (soundTrackAudioNode) {
             if (BABYLON.Engine.audioEngine.canUseWebAudio) {
             if (BABYLON.Engine.audioEngine.canUseWebAudio) {
-                this._ouputAudioNode.disconnect();
+                if (this._isOutputConnected) {
+                    this._ouputAudioNode.disconnect();
+                }
                 this._ouputAudioNode.connect(soundTrackAudioNode);
                 this._ouputAudioNode.connect(soundTrackAudioNode);
+                this._isOutputConnected = true;
             }
             }
         };
         };
         /**
         /**

+ 5 - 1
src/Audio/babylon.sound.ts

@@ -39,6 +39,7 @@
         private _connectedMesh: AbstractMesh;
         private _connectedMesh: AbstractMesh;
         private _customAttenuationFunction: (currentVolume: number, currentDistance: number, maxDistance: number, refDistance: number, rolloffFactor: number) => number;
         private _customAttenuationFunction: (currentVolume: number, currentDistance: number, maxDistance: number, refDistance: number, rolloffFactor: number) => number;
         private _registerFunc: (connectedMesh: AbstractMesh) => any;
         private _registerFunc: (connectedMesh: AbstractMesh) => any;
+        private _isOutputConnected = false;
 
 
         /**
         /**
         * Create a sound and attach it to a scene
         * Create a sound and attach it to a scene
@@ -233,8 +234,11 @@
 
 
         public connectToSoundTrackAudioNode(soundTrackAudioNode: AudioNode) {
         public connectToSoundTrackAudioNode(soundTrackAudioNode: AudioNode) {
             if (Engine.audioEngine.canUseWebAudio) {
             if (Engine.audioEngine.canUseWebAudio) {
-                this._ouputAudioNode.disconnect();
+                if (this._isOutputConnected) {
+                    this._ouputAudioNode.disconnect();
+                }
                 this._ouputAudioNode.connect(soundTrackAudioNode);
                 this._ouputAudioNode.connect(soundTrackAudioNode);
+                this._isOutputConnected = true;
             }
             }
         }
         }
 
 

+ 1 - 0
src/Debug/babylon.debugLayer.js

@@ -512,6 +512,7 @@ var BABYLON;
                 this._generateCheckBox(this._optionsSubsetDiv, "Opacity", BABYLON.StandardMaterial.OpacityTextureEnabled, function (element) { BABYLON.StandardMaterial.OpacityTextureEnabled = element.checked; });
                 this._generateCheckBox(this._optionsSubsetDiv, "Opacity", BABYLON.StandardMaterial.OpacityTextureEnabled, function (element) { BABYLON.StandardMaterial.OpacityTextureEnabled = element.checked; });
                 this._generateCheckBox(this._optionsSubsetDiv, "Reflection", BABYLON.StandardMaterial.ReflectionTextureEnabled, function (element) { BABYLON.StandardMaterial.ReflectionTextureEnabled = element.checked; });
                 this._generateCheckBox(this._optionsSubsetDiv, "Reflection", BABYLON.StandardMaterial.ReflectionTextureEnabled, function (element) { BABYLON.StandardMaterial.ReflectionTextureEnabled = element.checked; });
                 this._generateCheckBox(this._optionsSubsetDiv, "Fresnel", BABYLON.StandardMaterial.FresnelEnabled, function (element) { BABYLON.StandardMaterial.FresnelEnabled = element.checked; });
                 this._generateCheckBox(this._optionsSubsetDiv, "Fresnel", BABYLON.StandardMaterial.FresnelEnabled, function (element) { BABYLON.StandardMaterial.FresnelEnabled = element.checked; });
+                this._generateCheckBox(this._optionsSubsetDiv, "Lightmap", BABYLON.StandardMaterial.LightmapEnabled, function (element) { BABYLON.StandardMaterial.LightmapEnabled = element.checked; });
                 this._optionsSubsetDiv.appendChild(document.createElement("br"));
                 this._optionsSubsetDiv.appendChild(document.createElement("br"));
                 this._generateTexBox(this._optionsSubsetDiv, "<b>Options:</b>", this.accentColor);
                 this._generateTexBox(this._optionsSubsetDiv, "<b>Options:</b>", this.accentColor);
                 this._generateCheckBox(this._optionsSubsetDiv, "Animations", this._scene.animationsEnabled, function (element) { _this._scene.animationsEnabled = element.checked; });
                 this._generateCheckBox(this._optionsSubsetDiv, "Animations", this._scene.animationsEnabled, function (element) { _this._scene.animationsEnabled = element.checked; });

+ 1 - 0
src/Debug/babylon.debugLayer.ts

@@ -657,6 +657,7 @@
                 this._generateCheckBox(this._optionsSubsetDiv, "Opacity", StandardMaterial.OpacityTextureEnabled, (element) => { StandardMaterial.OpacityTextureEnabled = element.checked });
                 this._generateCheckBox(this._optionsSubsetDiv, "Opacity", StandardMaterial.OpacityTextureEnabled, (element) => { StandardMaterial.OpacityTextureEnabled = element.checked });
                 this._generateCheckBox(this._optionsSubsetDiv, "Reflection", StandardMaterial.ReflectionTextureEnabled, (element) => { StandardMaterial.ReflectionTextureEnabled = element.checked });
                 this._generateCheckBox(this._optionsSubsetDiv, "Reflection", StandardMaterial.ReflectionTextureEnabled, (element) => { StandardMaterial.ReflectionTextureEnabled = element.checked });
                 this._generateCheckBox(this._optionsSubsetDiv, "Fresnel", StandardMaterial.FresnelEnabled, (element) => { StandardMaterial.FresnelEnabled = element.checked });
                 this._generateCheckBox(this._optionsSubsetDiv, "Fresnel", StandardMaterial.FresnelEnabled, (element) => { StandardMaterial.FresnelEnabled = element.checked });
+                this._generateCheckBox(this._optionsSubsetDiv, "Lightmap", StandardMaterial.LightmapEnabled, (element) => { StandardMaterial.LightmapEnabled = element.checked });
                 this._optionsSubsetDiv.appendChild(document.createElement("br"));
                 this._optionsSubsetDiv.appendChild(document.createElement("br"));
                 this._generateTexBox(this._optionsSubsetDiv, "<b>Options:</b>", this.accentColor);
                 this._generateTexBox(this._optionsSubsetDiv, "<b>Options:</b>", this.accentColor);
                 this._generateCheckBox(this._optionsSubsetDiv, "Animations", this._scene.animationsEnabled, (element) => { this._scene.animationsEnabled = element.checked });
                 this._generateCheckBox(this._optionsSubsetDiv, "Animations", this._scene.animationsEnabled, (element) => { this._scene.animationsEnabled = element.checked });

+ 4 - 0
src/Loading/Plugins/babylon.babylonFileLoader.js

@@ -143,6 +143,10 @@ var BABYLON;
             if (parsedMaterial.emissiveTexture) {
             if (parsedMaterial.emissiveTexture) {
                 material.emissiveTexture = loadTexture(rootUrl, parsedMaterial.emissiveTexture, scene);
                 material.emissiveTexture = loadTexture(rootUrl, parsedMaterial.emissiveTexture, scene);
             }
             }
+            if (parsedMaterial.lightmapTexture) {
+                material.lightmapTexture = loadTexture(rootUrl, parsedMaterial.lightmapTexture, scene);
+                material.lightmapThreshold = parsedMaterial.lightmapThreshold;
+            }
             if (parsedMaterial.emissiveFresnelParameters) {
             if (parsedMaterial.emissiveFresnelParameters) {
                 material.emissiveFresnelParameters = parseFresnelParameters(parsedMaterial.emissiveFresnelParameters);
                 material.emissiveFresnelParameters = parseFresnelParameters(parsedMaterial.emissiveFresnelParameters);
             }
             }

+ 5 - 0
src/Loading/Plugins/babylon.babylonFileLoader.ts

@@ -175,6 +175,11 @@
             material.emissiveTexture = loadTexture(rootUrl, parsedMaterial.emissiveTexture, scene);
             material.emissiveTexture = loadTexture(rootUrl, parsedMaterial.emissiveTexture, scene);
         }
         }
 
 
+        if (parsedMaterial.lightmapTexture) {
+            material.lightmapTexture = loadTexture(rootUrl, parsedMaterial.lightmapTexture, scene);
+            material.lightmapThreshold = parsedMaterial.lightmapThreshold;
+        }
+
         if (parsedMaterial.emissiveFresnelParameters) {
         if (parsedMaterial.emissiveFresnelParameters) {
             material.emissiveFresnelParameters = parseFresnelParameters(parsedMaterial.emissiveFresnelParameters);
             material.emissiveFresnelParameters = parseFresnelParameters(parsedMaterial.emissiveFresnelParameters);
         }
         }

+ 18 - 1
src/Materials/babylon.material.js

@@ -8,6 +8,7 @@ var BABYLON;
             this.state = "";
             this.state = "";
             this.alpha = 1.0;
             this.alpha = 1.0;
             this.backFaceCulling = true;
             this.backFaceCulling = true;
+            this.sideOrientation = Material.CounterClockWiseSideOrientation;
             this.alphaMode = BABYLON.Engine.ALPHA_COMBINE;
             this.alphaMode = BABYLON.Engine.ALPHA_COMBINE;
             this.disableDepthWrite = false;
             this.disableDepthWrite = false;
             this._wasPreviouslyReady = false;
             this._wasPreviouslyReady = false;
@@ -41,6 +42,20 @@ var BABYLON;
             enumerable: true,
             enumerable: true,
             configurable: true
             configurable: true
         });
         });
+        Object.defineProperty(Material, "ClockWiseSideOrientation", {
+            get: function () {
+                return Material._ClockWiseSideOrientation;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Material, "CounterClockWiseSideOrientation", {
+            get: function () {
+                return Material._CounterClockWiseSideOrientation;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(Material.prototype, "wireframe", {
         Object.defineProperty(Material.prototype, "wireframe", {
             get: function () {
             get: function () {
                 return this._fillMode === Material.WireFrameFillMode;
                 return this._fillMode === Material.WireFrameFillMode;
@@ -94,7 +109,7 @@ var BABYLON;
         Material.prototype._preBind = function () {
         Material.prototype._preBind = function () {
             var engine = this._scene.getEngine();
             var engine = this._scene.getEngine();
             engine.enableEffect(this._effect);
             engine.enableEffect(this._effect);
-            engine.setState(this.backFaceCulling, this.zOffset);
+            engine.setState(this.backFaceCulling, this.zOffset, false, this.sideOrientation === Material.ClockWiseSideOrientation);
         };
         };
         Material.prototype.bind = function (world, mesh) {
         Material.prototype.bind = function (world, mesh) {
             this._scene._cachedMaterial = this;
             this._scene._cachedMaterial = this;
@@ -135,6 +150,8 @@ var BABYLON;
         Material._TriangleFillMode = 0;
         Material._TriangleFillMode = 0;
         Material._WireFrameFillMode = 1;
         Material._WireFrameFillMode = 1;
         Material._PointFillMode = 2;
         Material._PointFillMode = 2;
+        Material._ClockWiseSideOrientation = 0;
+        Material._CounterClockWiseSideOrientation = 1;
         return Material;
         return Material;
     })();
     })();
     BABYLON.Material = Material;
     BABYLON.Material = Material;

+ 13 - 1
src/Materials/babylon.material.ts

@@ -16,12 +16,24 @@
             return Material._PointFillMode;
             return Material._PointFillMode;
         }
         }
 
 
+        private static _ClockWiseSideOrientation = 0;
+        private static _CounterClockWiseSideOrientation = 1;
+
+        public static get ClockWiseSideOrientation(): number {
+            return Material._ClockWiseSideOrientation;
+        }
+
+        public static get CounterClockWiseSideOrientation(): number {
+            return Material._CounterClockWiseSideOrientation;
+        }
+
         public id: string;
         public id: string;
         public checkReadyOnEveryCall = true;
         public checkReadyOnEveryCall = true;
         public checkReadyOnlyOnce = false;
         public checkReadyOnlyOnce = false;
         public state = "";
         public state = "";
         public alpha = 1.0;
         public alpha = 1.0;
         public backFaceCulling = true;
         public backFaceCulling = true;
+        public sideOrientation = Material.CounterClockWiseSideOrientation;
         public onCompiled: (effect: Effect) => void;
         public onCompiled: (effect: Effect) => void;
         public onError: (effect: Effect, errors: string) => void;
         public onError: (effect: Effect, errors: string) => void;
         public onDispose: () => void;
         public onDispose: () => void;
@@ -105,7 +117,7 @@
             var engine = this._scene.getEngine();
             var engine = this._scene.getEngine();
 
 
             engine.enableEffect(this._effect);
             engine.enableEffect(this._effect);
-            engine.setState(this.backFaceCulling, this.zOffset);
+            engine.setState(this.backFaceCulling, this.zOffset, false, this.sideOrientation === Material.ClockWiseSideOrientation);
         }
         }
 
 
         public bind(world: Matrix, mesh?: Mesh): void {
         public bind(world: Matrix, mesh?: Mesh): void {

+ 20 - 3
src/Materials/babylon.standardMaterial.js

@@ -81,6 +81,7 @@ var BABYLON;
             this.ROUGHNESS = false;
             this.ROUGHNESS = false;
             this.EMISSIVEASILLUMINATION = false;
             this.EMISSIVEASILLUMINATION = false;
             this.REFLECTIONFRESNELFROMSPECULAR = false;
             this.REFLECTIONFRESNELFROMSPECULAR = false;
+            this.LIGHTMAP = false;
             this._keys = Object.keys(this);
             this._keys = Object.keys(this);
         }
         }
         StandardMaterialDefines.prototype.isEqual = function (other) {
         StandardMaterialDefines.prototype.isEqual = function (other) {
@@ -140,6 +141,7 @@ var BABYLON;
             this.useSpecularOverAlpha = true;
             this.useSpecularOverAlpha = true;
             this.fogEnabled = true;
             this.fogEnabled = true;
             this.roughness = 0;
             this.roughness = 0;
+            this.lightmapThreshold = 0;
             this.useGlossinessFromSpecularMapAlpha = false;
             this.useGlossinessFromSpecularMapAlpha = false;
             this._renderTargets = new BABYLON.SmartArray(16);
             this._renderTargets = new BABYLON.SmartArray(16);
             this._worldViewProjectionMatrix = BABYLON.Matrix.Zero();
             this._worldViewProjectionMatrix = BABYLON.Matrix.Zero();
@@ -240,6 +242,15 @@ var BABYLON;
                         this._defines.EMISSIVE = true;
                         this._defines.EMISSIVE = true;
                     }
                     }
                 }
                 }
+                if (this.lightmapTexture && StandardMaterial.LightmapEnabled) {
+                    if (!this.lightmapTexture.isReady()) {
+                        return false;
+                    }
+                    else {
+                        needUVs = true;
+                        this._defines.LIGHTMAP = true;
+                    }
+                }
                 if (this.specularTexture && StandardMaterial.SpecularTextureEnabled) {
                 if (this.specularTexture && StandardMaterial.SpecularTextureEnabled) {
                     if (!this.specularTexture.isReady()) {
                     if (!this.specularTexture.isReady()) {
                         return false;
                         return false;
@@ -499,13 +510,13 @@ var BABYLON;
                     "vLightData2", "vLightDiffuse2", "vLightSpecular2", "vLightDirection2", "vLightGround2", "lightMatrix2",
                     "vLightData2", "vLightDiffuse2", "vLightSpecular2", "vLightDirection2", "vLightGround2", "lightMatrix2",
                     "vLightData3", "vLightDiffuse3", "vLightSpecular3", "vLightDirection3", "vLightGround3", "lightMatrix3",
                     "vLightData3", "vLightDiffuse3", "vLightSpecular3", "vLightDirection3", "vLightGround3", "lightMatrix3",
                     "vFogInfos", "vFogColor", "pointSize",
                     "vFogInfos", "vFogColor", "pointSize",
-                    "vDiffuseInfos", "vAmbientInfos", "vOpacityInfos", "vReflectionInfos", "vEmissiveInfos", "vSpecularInfos", "vBumpInfos",
+                    "vDiffuseInfos", "vAmbientInfos", "vOpacityInfos", "vReflectionInfos", "vEmissiveInfos", "vSpecularInfos", "vBumpInfos", "vLightmapInfos",
                     "mBones",
                     "mBones",
-                    "vClipPlane", "diffuseMatrix", "ambientMatrix", "opacityMatrix", "reflectionMatrix", "emissiveMatrix", "specularMatrix", "bumpMatrix",
+                    "vClipPlane", "diffuseMatrix", "ambientMatrix", "opacityMatrix", "reflectionMatrix", "emissiveMatrix", "specularMatrix", "bumpMatrix", "lightmapMatrix",
                     "shadowsInfo0", "shadowsInfo1", "shadowsInfo2", "shadowsInfo3",
                     "shadowsInfo0", "shadowsInfo1", "shadowsInfo2", "shadowsInfo3",
                     "diffuseLeftColor", "diffuseRightColor", "opacityParts", "reflectionLeftColor", "reflectionRightColor", "emissiveLeftColor", "emissiveRightColor",
                     "diffuseLeftColor", "diffuseRightColor", "opacityParts", "reflectionLeftColor", "reflectionRightColor", "emissiveLeftColor", "emissiveRightColor",
                     "roughness"
                     "roughness"
-                ], ["diffuseSampler", "ambientSampler", "opacitySampler", "reflectionCubeSampler", "reflection2DSampler", "emissiveSampler", "specularSampler", "bumpSampler",
+                ], ["diffuseSampler", "ambientSampler", "opacitySampler", "reflectionCubeSampler", "reflection2DSampler", "emissiveSampler", "specularSampler", "bumpSampler", "lightmapSampler",
                     "shadowSampler0", "shadowSampler1", "shadowSampler2", "shadowSampler3"
                     "shadowSampler0", "shadowSampler1", "shadowSampler2", "shadowSampler3"
                 ], join, fallbacks, this.onCompiled, this.onError);
                 ], join, fallbacks, this.onCompiled, this.onError);
             }
             }
@@ -587,6 +598,11 @@ var BABYLON;
                     this._effect.setFloat2("vEmissiveInfos", this.emissiveTexture.coordinatesIndex, this.emissiveTexture.level);
                     this._effect.setFloat2("vEmissiveInfos", this.emissiveTexture.coordinatesIndex, this.emissiveTexture.level);
                     this._effect.setMatrix("emissiveMatrix", this.emissiveTexture.getTextureMatrix());
                     this._effect.setMatrix("emissiveMatrix", this.emissiveTexture.getTextureMatrix());
                 }
                 }
+                if (this.lightmapTexture && StandardMaterial.LightmapEnabled) {
+                    this._effect.setTexture("lightmapSampler", this.lightmapTexture);
+                    this._effect.setFloat3("vLightmapInfos", this.lightmapTexture.coordinatesIndex, this.lightmapTexture.level, this.lightmapThreshold);
+                    this._effect.setMatrix("lightmapMatrix", this.lightmapTexture.getTextureMatrix());
+                }
                 if (this.specularTexture && StandardMaterial.SpecularTextureEnabled) {
                 if (this.specularTexture && StandardMaterial.SpecularTextureEnabled) {
                     this._effect.setTexture("specularSampler", this.specularTexture);
                     this._effect.setTexture("specularSampler", this.specularTexture);
                     this._effect.setFloat2("vSpecularInfos", this.specularTexture.coordinatesIndex, this.specularTexture.level);
                     this._effect.setFloat2("vSpecularInfos", this.specularTexture.coordinatesIndex, this.specularTexture.level);
@@ -776,6 +792,7 @@ var BABYLON;
         StandardMaterial.SpecularTextureEnabled = true;
         StandardMaterial.SpecularTextureEnabled = true;
         StandardMaterial.BumpTextureEnabled = true;
         StandardMaterial.BumpTextureEnabled = true;
         StandardMaterial.FresnelEnabled = true;
         StandardMaterial.FresnelEnabled = true;
+        StandardMaterial.LightmapEnabled = true;
         return StandardMaterial;
         return StandardMaterial;
     })(BABYLON.Material);
     })(BABYLON.Material);
     BABYLON.StandardMaterial = StandardMaterial;
     BABYLON.StandardMaterial = StandardMaterial;

+ 24 - 3
src/Materials/babylon.standardMaterial.ts

@@ -72,6 +72,7 @@
         public ROUGHNESS = false;
         public ROUGHNESS = false;
         public EMISSIVEASILLUMINATION = false;
         public EMISSIVEASILLUMINATION = false;
         public REFLECTIONFRESNELFROMSPECULAR = false;
         public REFLECTIONFRESNELFROMSPECULAR = false;
+        public LIGHTMAP = false;
 
 
         _keys: string[];
         _keys: string[];
 
 
@@ -139,6 +140,7 @@
         public emissiveTexture: BaseTexture;
         public emissiveTexture: BaseTexture;
         public specularTexture: BaseTexture;
         public specularTexture: BaseTexture;
         public bumpTexture: BaseTexture;
         public bumpTexture: BaseTexture;
+        public lightmapTexture: BaseTexture;
 
 
         public ambientColor = new Color3(0, 0, 0);
         public ambientColor = new Color3(0, 0, 0);
         public diffuseColor = new Color3(1, 1, 1);
         public diffuseColor = new Color3(1, 1, 1);
@@ -153,6 +155,8 @@
 
 
         public roughness = 0;
         public roughness = 0;
 
 
+        public lightmapThreshold = 0;
+
         public diffuseFresnelParameters: FresnelParameters;
         public diffuseFresnelParameters: FresnelParameters;
         public opacityFresnelParameters: FresnelParameters;
         public opacityFresnelParameters: FresnelParameters;
         public reflectionFresnelParameters: FresnelParameters;
         public reflectionFresnelParameters: FresnelParameters;
@@ -280,6 +284,15 @@
                     }
                     }
                 }
                 }
 
 
+                if (this.lightmapTexture && StandardMaterial.LightmapEnabled) {
+                    if (!this.lightmapTexture.isReady()) {
+                        return false;
+                    } else {
+                        needUVs = true;
+                        this._defines.LIGHTMAP = true;
+                    }
+                }
+
                 if (this.specularTexture && StandardMaterial.SpecularTextureEnabled) {
                 if (this.specularTexture && StandardMaterial.SpecularTextureEnabled) {
                     if (!this.specularTexture.isReady()) {
                     if (!this.specularTexture.isReady()) {
                         return false;
                         return false;
@@ -599,14 +612,14 @@
                         "vLightData2", "vLightDiffuse2", "vLightSpecular2", "vLightDirection2", "vLightGround2", "lightMatrix2",
                         "vLightData2", "vLightDiffuse2", "vLightSpecular2", "vLightDirection2", "vLightGround2", "lightMatrix2",
                         "vLightData3", "vLightDiffuse3", "vLightSpecular3", "vLightDirection3", "vLightGround3", "lightMatrix3",
                         "vLightData3", "vLightDiffuse3", "vLightSpecular3", "vLightDirection3", "vLightGround3", "lightMatrix3",
                         "vFogInfos", "vFogColor", "pointSize",
                         "vFogInfos", "vFogColor", "pointSize",
-                        "vDiffuseInfos", "vAmbientInfos", "vOpacityInfos", "vReflectionInfos", "vEmissiveInfos", "vSpecularInfos", "vBumpInfos",
+                        "vDiffuseInfos", "vAmbientInfos", "vOpacityInfos", "vReflectionInfos", "vEmissiveInfos", "vSpecularInfos", "vBumpInfos", "vLightmapInfos",
                         "mBones",
                         "mBones",
-                        "vClipPlane", "diffuseMatrix", "ambientMatrix", "opacityMatrix", "reflectionMatrix", "emissiveMatrix", "specularMatrix", "bumpMatrix",
+                        "vClipPlane", "diffuseMatrix", "ambientMatrix", "opacityMatrix", "reflectionMatrix", "emissiveMatrix", "specularMatrix", "bumpMatrix", "lightmapMatrix",
                         "shadowsInfo0", "shadowsInfo1", "shadowsInfo2", "shadowsInfo3",
                         "shadowsInfo0", "shadowsInfo1", "shadowsInfo2", "shadowsInfo3",
                         "diffuseLeftColor", "diffuseRightColor", "opacityParts", "reflectionLeftColor", "reflectionRightColor", "emissiveLeftColor", "emissiveRightColor",
                         "diffuseLeftColor", "diffuseRightColor", "opacityParts", "reflectionLeftColor", "reflectionRightColor", "emissiveLeftColor", "emissiveRightColor",
                         "roughness"
                         "roughness"
                     ],
                     ],
-                    ["diffuseSampler", "ambientSampler", "opacitySampler", "reflectionCubeSampler", "reflection2DSampler", "emissiveSampler", "specularSampler", "bumpSampler",
+                    ["diffuseSampler", "ambientSampler", "opacitySampler", "reflectionCubeSampler", "reflection2DSampler", "emissiveSampler", "specularSampler", "bumpSampler", "lightmapSampler",
                         "shadowSampler0", "shadowSampler1", "shadowSampler2", "shadowSampler3"
                         "shadowSampler0", "shadowSampler1", "shadowSampler2", "shadowSampler3"
                     ],
                     ],
                     join, fallbacks, this.onCompiled, this.onError);
                     join, fallbacks, this.onCompiled, this.onError);
@@ -712,6 +725,13 @@
                     this._effect.setMatrix("emissiveMatrix", this.emissiveTexture.getTextureMatrix());
                     this._effect.setMatrix("emissiveMatrix", this.emissiveTexture.getTextureMatrix());
                 }
                 }
 
 
+                if (this.lightmapTexture && StandardMaterial.LightmapEnabled) {
+                    this._effect.setTexture("lightmapSampler", this.lightmapTexture);
+
+                    this._effect.setFloat3("vLightmapInfos", this.lightmapTexture.coordinatesIndex, this.lightmapTexture.level, this.lightmapThreshold);
+                    this._effect.setMatrix("lightmapMatrix", this.lightmapTexture.getTextureMatrix());
+                }
+
                 if (this.specularTexture && StandardMaterial.SpecularTextureEnabled) {
                 if (this.specularTexture && StandardMaterial.SpecularTextureEnabled) {
                     this._effect.setTexture("specularSampler", this.specularTexture);
                     this._effect.setTexture("specularSampler", this.specularTexture);
 
 
@@ -943,5 +963,6 @@
         public static SpecularTextureEnabled = true;
         public static SpecularTextureEnabled = true;
         public static BumpTextureEnabled = true;
         public static BumpTextureEnabled = true;
         public static FresnelEnabled = true;
         public static FresnelEnabled = true;
+        public static LightmapEnabled = true;
     }
     }
 } 
 } 

+ 7 - 2
src/Math/babylon.math.js

@@ -2047,9 +2047,14 @@ var BABYLON;
             // Z axis
             // Z axis
             target.subtractToRef(eye, this._zAxis);
             target.subtractToRef(eye, this._zAxis);
             this._zAxis.normalize();
             this._zAxis.normalize();
-            // X axis
+            // X axis            
             Vector3.CrossToRef(up, this._zAxis, this._xAxis);
             Vector3.CrossToRef(up, this._zAxis, this._xAxis);
-            this._xAxis.normalize();
+            if (this._xAxis.lengthSquared() === 0) {
+                this._xAxis.x = 1.0;
+            }
+            else {
+                this._xAxis.normalize();
+            }
             // Y axis
             // Y axis
             Vector3.CrossToRef(this._zAxis, this._xAxis, this._yAxis);
             Vector3.CrossToRef(this._zAxis, this._xAxis, this._yAxis);
             this._yAxis.normalize();
             this._yAxis.normalize();

+ 7 - 2
src/Math/babylon.math.ts

@@ -2578,9 +2578,14 @@
             target.subtractToRef(eye, this._zAxis);
             target.subtractToRef(eye, this._zAxis);
             this._zAxis.normalize();
             this._zAxis.normalize();
 
 
-            // X axis
+            // X axis            
             Vector3.CrossToRef(up, this._zAxis, this._xAxis);
             Vector3.CrossToRef(up, this._zAxis, this._xAxis);
-            this._xAxis.normalize();
+
+            if (this._xAxis.lengthSquared() === 0) {
+                this._xAxis.x = 1.0;
+            } else {
+                this._xAxis.normalize();
+            }
 
 
             // Y axis
             // Y axis
             Vector3.CrossToRef(this._zAxis, this._xAxis, this._yAxis);
             Vector3.CrossToRef(this._zAxis, this._xAxis, this._yAxis);

+ 5 - 4
src/Mesh/babylon.abstractMesh.js

@@ -226,8 +226,9 @@ var BABYLON;
                 this.rotationQuaternion = BABYLON.Quaternion.RotationYawPitchRoll(this.rotation.y, this.rotation.x, this.rotation.z);
                 this.rotationQuaternion = BABYLON.Quaternion.RotationYawPitchRoll(this.rotation.y, this.rotation.x, this.rotation.z);
                 this.rotation = BABYLON.Vector3.Zero();
                 this.rotation = BABYLON.Vector3.Zero();
             }
             }
+            var rotationQuaternion;
             if (!space || space === BABYLON.Space.LOCAL) {
             if (!space || space === BABYLON.Space.LOCAL) {
-                var rotationQuaternion = BABYLON.Quaternion.RotationAxis(axis, amount);
+                rotationQuaternion = BABYLON.Quaternion.RotationAxis(axis, amount);
                 this.rotationQuaternion = this.rotationQuaternion.multiply(rotationQuaternion);
                 this.rotationQuaternion = this.rotationQuaternion.multiply(rotationQuaternion);
             }
             }
             else {
             else {
@@ -445,7 +446,7 @@ var BABYLON;
                     localPosition.addInPlace(this.parent.position);
                     localPosition.addInPlace(this.parent.position);
                     BABYLON.Matrix.TranslationToRef(localPosition.x, localPosition.y, localPosition.z, this._localTranslation);
                     BABYLON.Matrix.TranslationToRef(localPosition.x, localPosition.y, localPosition.z, this._localTranslation);
                 }
                 }
-                if ((this.billboardMode & AbstractMesh.BILLBOARDMODE_ALL) != AbstractMesh.BILLBOARDMODE_ALL) {
+                if ((this.billboardMode & AbstractMesh.BILLBOARDMODE_ALL) !== AbstractMesh.BILLBOARDMODE_ALL) {
                     if (this.billboardMode & AbstractMesh.BILLBOARDMODE_X)
                     if (this.billboardMode & AbstractMesh.BILLBOARDMODE_X)
                         zero.x = localPosition.x + BABYLON.Engine.Epsilon;
                         zero.x = localPosition.x + BABYLON.Engine.Epsilon;
                     if (this.billboardMode & AbstractMesh.BILLBOARDMODE_Y)
                     if (this.billboardMode & AbstractMesh.BILLBOARDMODE_Y)
@@ -568,7 +569,7 @@ var BABYLON;
         AbstractMesh.prototype.setPhysicsState = function (impostor, options) {
         AbstractMesh.prototype.setPhysicsState = function (impostor, options) {
             var physicsEngine = this.getScene().getPhysicsEngine();
             var physicsEngine = this.getScene().getPhysicsEngine();
             if (!physicsEngine) {
             if (!physicsEngine) {
-                return;
+                return null;
             }
             }
             impostor = impostor || BABYLON.PhysicsEngine.NoImpostor;
             impostor = impostor || BABYLON.PhysicsEngine.NoImpostor;
             if (impostor.impostor) {
             if (impostor.impostor) {
@@ -578,7 +579,7 @@ var BABYLON;
             }
             }
             if (impostor === BABYLON.PhysicsEngine.NoImpostor) {
             if (impostor === BABYLON.PhysicsEngine.NoImpostor) {
                 physicsEngine._unregisterMesh(this);
                 physicsEngine._unregisterMesh(this);
-                return;
+                return null;
             }
             }
             if (!options) {
             if (!options) {
                 options = { mass: 0, friction: 0.2, restitution: 0.2 };
                 options = { mass: 0, friction: 0.2, restitution: 0.2 };

+ 5 - 5
src/Mesh/babylon.abstractMesh.ts

@@ -232,9 +232,9 @@
                 this.rotationQuaternion = Quaternion.RotationYawPitchRoll(this.rotation.y, this.rotation.x, this.rotation.z);
                 this.rotationQuaternion = Quaternion.RotationYawPitchRoll(this.rotation.y, this.rotation.x, this.rotation.z);
                 this.rotation = Vector3.Zero();
                 this.rotation = Vector3.Zero();
             }
             }
-
+            var rotationQuaternion: Quaternion;
             if (!space || space === Space.LOCAL) {
             if (!space || space === Space.LOCAL) {
-                var rotationQuaternion = Quaternion.RotationAxis(axis, amount);
+                rotationQuaternion = Quaternion.RotationAxis(axis, amount);
                 this.rotationQuaternion = this.rotationQuaternion.multiply(rotationQuaternion);
                 this.rotationQuaternion = this.rotationQuaternion.multiply(rotationQuaternion);
             }
             }
             else {
             else {
@@ -493,7 +493,7 @@
                     Matrix.TranslationToRef(localPosition.x, localPosition.y, localPosition.z, this._localTranslation);
                     Matrix.TranslationToRef(localPosition.x, localPosition.y, localPosition.z, this._localTranslation);
                 }
                 }
 
 
-                if ((this.billboardMode & AbstractMesh.BILLBOARDMODE_ALL) != AbstractMesh.BILLBOARDMODE_ALL) {
+                if ((this.billboardMode & AbstractMesh.BILLBOARDMODE_ALL) !== AbstractMesh.BILLBOARDMODE_ALL) {
                     if (this.billboardMode & AbstractMesh.BILLBOARDMODE_X)
                     if (this.billboardMode & AbstractMesh.BILLBOARDMODE_X)
                         zero.x = localPosition.x + Engine.Epsilon;
                         zero.x = localPosition.x + Engine.Epsilon;
                     if (this.billboardMode & AbstractMesh.BILLBOARDMODE_Y)
                     if (this.billboardMode & AbstractMesh.BILLBOARDMODE_Y)
@@ -650,7 +650,7 @@
             var physicsEngine = this.getScene().getPhysicsEngine();
             var physicsEngine = this.getScene().getPhysicsEngine();
 
 
             if (!physicsEngine) {
             if (!physicsEngine) {
-                return;
+                return null;
             }
             }
 
 
             impostor = impostor || PhysicsEngine.NoImpostor;
             impostor = impostor || PhysicsEngine.NoImpostor;
@@ -663,7 +663,7 @@
 
 
             if (impostor === PhysicsEngine.NoImpostor) {
             if (impostor === PhysicsEngine.NoImpostor) {
                 physicsEngine._unregisterMesh(this);
                 physicsEngine._unregisterMesh(this);
-                return;
+                return null;
             }
             }
 
 
             if (!options) {
             if (!options) {

+ 20 - 0
src/Shaders/default.fragment.fx

@@ -131,6 +131,12 @@ uniform vec2 vEmissiveInfos;
 uniform sampler2D emissiveSampler;
 uniform sampler2D emissiveSampler;
 #endif
 #endif
 
 
+#ifdef LIGHTMAP
+varying vec2 vLightmapUV;
+uniform vec3 vLightmapInfos;
+uniform sampler2D lightmapSampler;
+#endif
+
 #if defined(SPECULAR) && defined(SPECULARTERM)
 #if defined(SPECULAR) && defined(SPECULARTERM)
 varying vec2 vSpecularUV;
 varying vec2 vSpecularUV;
 uniform vec2 vSpecularInfos;
 uniform vec2 vSpecularInfos;
@@ -812,6 +818,20 @@ void main(void) {
     vec4 color = vec4(finalDiffuse * baseAmbientColor + finalSpecular + reflectionColor, alpha);
     vec4 color = vec4(finalDiffuse * baseAmbientColor + finalSpecular + reflectionColor, alpha);
 #endif
 #endif
 
 
+#ifdef LIGHTMAP
+	vec3 lightmapColor = texture2D(lightmapSampler, vLightmapUV).rgb * vLightmapInfos.y;
+	float lightmapIllum = clamp(dot(lightmapColor, vec3(0.3, 0.59, 0.11)), 0., 1.);
+
+	if (lightmapIllum > vLightmapInfos.z)
+	{
+		color.rgb += lightmapColor;
+	}
+	else
+	{
+		color.rgb *= lightmapColor;
+	}
+#endif
+
 #ifdef FOG
 #ifdef FOG
 	float fog = CalcFogFactor();
 	float fog = CalcFogFactor();
 	color.rgb = fog * color.rgb + (1.0 - fog) * vFogColor;
 	color.rgb = fog * color.rgb + (1.0 - fog) * vFogColor;

+ 17 - 0
src/Shaders/default.vertex.fx

@@ -59,6 +59,12 @@ uniform vec2 vEmissiveInfos;
 uniform mat4 emissiveMatrix;
 uniform mat4 emissiveMatrix;
 #endif
 #endif
 
 
+#ifdef LIGHTMAP
+varying vec2 vLightmapUV;
+uniform vec3 vLightmapInfos;
+uniform mat4 lightmapMatrix;
+#endif
+
 #if defined(SPECULAR) && defined(SPECULARTERM)
 #if defined(SPECULAR) && defined(SPECULARTERM)
 varying vec2 vSpecularUV;
 varying vec2 vSpecularUV;
 uniform vec2 vSpecularInfos;
 uniform vec2 vSpecularInfos;
@@ -208,6 +214,17 @@ void main(void) {
 	}
 	}
 #endif
 #endif
 
 
+#ifdef LIGHTMAP
+	if (vLightmapInfos.x == 0.)
+	{
+		vLightmapUV = vec2(lightmapMatrix * vec4(uv, 1.0, 0.0));
+	}
+	else
+	{
+		vLightmapUV = vec2(lightmapMatrix * vec4(uv2, 1.0, 0.0));
+	}
+#endif
+
 #if defined(SPECULAR) && defined(SPECULARTERM)
 #if defined(SPECULAR) && defined(SPECULARTERM)
 	if (vSpecularInfos.x == 0.)
 	if (vSpecularInfos.x == 0.)
 	{
 	{

+ 4 - 0
src/Tools/babylon.sceneSerializer.js

@@ -236,6 +236,10 @@ var BABYLON;
         if (material.emissiveTexture) {
         if (material.emissiveTexture) {
             serializationObject.emissiveTexture = serializeTexture(material.emissiveTexture);
             serializationObject.emissiveTexture = serializeTexture(material.emissiveTexture);
         }
         }
+        if (material.lightmapTexture) {
+            serializationObject.lightmapTexture = serializeTexture(material.lightmapTexture);
+            serializationObject.lightmapThreshold = material.lightmapThreshold;
+        }
         if (material.emissiveFresnelParameters) {
         if (material.emissiveFresnelParameters) {
             serializationObject.emissiveFresnelParameters = serializeFresnelParameter(material.emissiveFresnelParameters);
             serializationObject.emissiveFresnelParameters = serializeFresnelParameter(material.emissiveFresnelParameters);
         }
         }

+ 5 - 0
src/Tools/babylon.sceneSerializer.ts

@@ -268,6 +268,11 @@
             serializationObject.emissiveTexture = serializeTexture(material.emissiveTexture);
             serializationObject.emissiveTexture = serializeTexture(material.emissiveTexture);
         }
         }
 
 
+        if (material.lightmapTexture) {
+            serializationObject.lightmapTexture = serializeTexture(material.lightmapTexture);
+            serializationObject.lightmapThreshold = material.lightmapThreshold;
+        }
+
         if (material.emissiveFresnelParameters) {
         if (material.emissiveFresnelParameters) {
             serializationObject.emissiveFresnelParameters = serializeFresnelParameter(material.emissiveFresnelParameters);
             serializationObject.emissiveFresnelParameters = serializeFresnelParameter(material.emissiveFresnelParameters);
         }
         }

+ 6 - 3
src/babylon.engine.js

@@ -617,7 +617,7 @@ var BABYLON;
         });
         });
         Object.defineProperty(Engine, "Version", {
         Object.defineProperty(Engine, "Version", {
             get: function () {
             get: function () {
-                return "2.2.0-beta";
+                return "2.3.0-alpha";
             },
             },
             enumerable: true,
             enumerable: true,
             configurable: true
             configurable: true
@@ -1202,12 +1202,15 @@ var BABYLON;
             this._gl.uniform4f(uniform, color3.r, color3.g, color3.b, alpha);
             this._gl.uniform4f(uniform, color3.r, color3.g, color3.b, alpha);
         };
         };
         // States
         // States
-        Engine.prototype.setState = function (culling, zOffset, force) {
+        Engine.prototype.setState = function (culling, zOffset, force, reverseSide) {
             if (zOffset === void 0) { zOffset = 0; }
             if (zOffset === void 0) { zOffset = 0; }
+            if (reverseSide === void 0) { reverseSide = false; }
             // Culling        
             // Culling        
             if (this._depthCullingState.cull !== culling || force) {
             if (this._depthCullingState.cull !== culling || force) {
                 if (culling) {
                 if (culling) {
-                    this._depthCullingState.cullFace = this.cullBackFaces ? this._gl.BACK : this._gl.FRONT;
+                    var showSide = reverseSide ? this._gl.FRONT : this._gl.BACK;
+                    var hideSide = reverseSide ? this._gl.BACK : this._gl.FRONT;
+                    this._depthCullingState.cullFace = this.cullBackFaces ? showSide : hideSide;
                     this._depthCullingState.cull = true;
                     this._depthCullingState.cull = true;
                 }
                 }
                 else {
                 else {

+ 5 - 3
src/babylon.engine.ts

@@ -481,7 +481,7 @@
         }
         }
 
 
         public static get Version(): string {
         public static get Version(): string {
-            return "2.2.0-beta";
+            return "2.3.0-alpha";
         }
         }
 
 
         // Updatable statics so stick with vars here
         // Updatable statics so stick with vars here
@@ -1429,11 +1429,13 @@
         }
         }
 
 
         // States
         // States
-        public setState(culling: boolean, zOffset: number = 0, force?: boolean): void {
+        public setState(culling: boolean, zOffset: number = 0, force?: boolean, reverseSide = false): void {
             // Culling        
             // Culling        
             if (this._depthCullingState.cull !== culling || force) {
             if (this._depthCullingState.cull !== culling || force) {
                 if (culling) {
                 if (culling) {
-                    this._depthCullingState.cullFace = this.cullBackFaces ? this._gl.BACK : this._gl.FRONT;
+                    var showSide = reverseSide ? this._gl.FRONT : this._gl.BACK;
+                    var hideSide = reverseSide ? this._gl.BACK : this._gl.FRONT;
+                    this._depthCullingState.cullFace = this.cullBackFaces ? showSide : hideSide;
                     this._depthCullingState.cull = true;
                     this._depthCullingState.cull = true;
                 } else {
                 } else {
                     this._depthCullingState.cull = false;
                     this._depthCullingState.cull = false;