Browse Source

Merge remote-tracking branch 'BabylonJS/master'

MackeyK24 8 years ago
parent
commit
639c94ead0
34 changed files with 13602 additions and 12503 deletions
  1. 25 6
      canvas2D/src/Engine/babylon.canvas2d.ts
  2. 55 2
      canvas2D/src/Engine/babylon.fontTexture.ts
  3. 4 3
      canvas2D/src/Engine/babylon.group2d.ts
  4. 35 15
      canvas2D/src/Engine/babylon.prim2dBase.ts
  5. 15 21
      canvas2D/src/Engine/babylon.renderablePrim2d.ts
  6. 32 6
      canvas2D/src/Engine/babylon.text2d.ts
  7. 7 0
      canvas2D/src/shaders/text2d.fragment.fx
  8. 33 0
      contributing.md
  9. 26 26
      dist/preview release/babylon.core.js
  10. 5983 5928
      dist/preview release/babylon.d.ts
  11. 38 37
      dist/preview release/babylon.js
  12. 523 199
      dist/preview release/babylon.max.js
  13. 5983 5928
      dist/preview release/babylon.module.d.ts
  14. 38 37
      dist/preview release/babylon.noworker.js
  15. 13 1
      dist/preview release/canvas2D/babylon.canvas2d.d.ts
  16. 141 45
      dist/preview release/canvas2D/babylon.canvas2d.js
  17. 12 12
      dist/preview release/canvas2D/babylon.canvas2d.min.js
  18. 3 2
      dist/preview release/what's new.md
  19. 3 0
      localDev/index.html
  20. 3 9
      readme.md
  21. 40 5
      src/Bones/babylon.bone.ts
  22. 258 30
      src/Bones/babylon.boneLookController.ts
  23. 1 1
      src/Cameras/babylon.freeCamera.ts
  24. 10 0
      src/Cameras/babylon.targetCamera.ts
  25. 13 0
      src/Materials/Textures/babylon.renderTargetTexture.ts
  26. 1 1
      src/Materials/babylon.material.ts
  27. 33 0
      src/Mesh/babylon.groundMesh.ts
  28. 132 1
      src/Mesh/babylon.mesh.ts
  29. 8 0
      src/Probes/babylon.reflectionProbe.ts
  30. 2 2
      src/Tools/babylon.database.ts
  31. 11 127
      src/Tools/babylon.sceneSerializer.ts
  32. 1 1
      src/Tools/babylon.tools.ts
  33. 107 57
      src/babylon.engine.ts
  34. 13 1
      src/babylon.mixins.ts

+ 25 - 6
canvas2D/src/Engine/babylon.canvas2d.ts

@@ -169,6 +169,8 @@
             this._scene = scene;
             this._scene = scene;
             this._engine = engine;
             this._engine = engine;
             this._renderingSize = new Size(0, 0);
             this._renderingSize = new Size(0, 0);
+            this._curHWScale = 0;
+            this._canvasLevelScale = new Vector3(1, 1, 1);
             this._designSize = settings.designSize || null;
             this._designSize = settings.designSize || null;
             this._designUseHorizAxis = settings.designUseHorizAxis === true;
             this._designUseHorizAxis = settings.designUseHorizAxis === true;
             if (!this._trackedGroups) {
             if (!this._trackedGroups) {
@@ -1292,7 +1294,9 @@
         private _designUseHorizAxis: boolean;
         private _designUseHorizAxis: boolean;
         public  _primitiveCollisionManager: PrimitiveCollisionManagerBase;
         public  _primitiveCollisionManager: PrimitiveCollisionManagerBase;
 
 
-        public _renderingSize: Size;
+        public _canvasLevelScale: Vector3;
+        public  _renderingSize: Size;
+        private _curHWScale;
 
 
         private _drawCallsOpaqueCounter          : PerfCounter;
         private _drawCallsOpaqueCounter          : PerfCounter;
         private _drawCallsAlphaTestCounter       : PerfCounter;
         private _drawCallsAlphaTestCounter       : PerfCounter;
@@ -1458,15 +1462,26 @@
                 return;
                 return;
             }
             }
 
 
+            // Detect a change of HWRendering scale
+            let hwsl = this.engine.getHardwareScalingLevel();
+            let hwslChanged = this._curHWScale !== hwsl;
+            if (hwslChanged) {
+                this._curHWScale = hwsl;
+                for (let child of this.children) {
+                    child._setFlags(SmartPropertyPrim.flagLocalTransformDirty|SmartPropertyPrim.flagGlobalTransformDirty);
+                }
+                this._setLayoutDirty();
+            }
+
             // Detect a change of rendering size
             // Detect a change of rendering size
             let renderingSizeChanged = false;
             let renderingSizeChanged = false;
-            let newWidth = this.engine.getRenderWidth();
+            let newWidth = this.engine.getRenderWidth() * hwsl;
             if (newWidth !== this._renderingSize.width) {
             if (newWidth !== this._renderingSize.width) {
                 renderingSizeChanged = true;
                 renderingSizeChanged = true;
             }
             }
             this._renderingSize.width = newWidth;
             this._renderingSize.width = newWidth;
 
 
-            let newHeight = this.engine.getRenderHeight();
+            let newHeight = this.engine.getRenderHeight() * hwsl;
             if (newHeight !== this._renderingSize.height) {
             if (newHeight !== this._renderingSize.height) {
                 renderingSizeChanged = true;
                 renderingSizeChanged = true;
             }
             }
@@ -1487,17 +1502,21 @@
             if (this._designSize) {
             if (this._designSize) {
                 let scale: number;
                 let scale: number;
                 if (this._designUseHorizAxis) {
                 if (this._designUseHorizAxis) {
-                    scale = this._renderingSize.width / this._designSize.width;
+                    scale = this._renderingSize.width / (this._designSize.width * hwsl);
                 } else {
                 } else {
-                    scale = this._renderingSize.height / this._designSize.height;
+                    scale = this._renderingSize.height / (this._designSize.height * hwsl);
                 }
                 }
                 this.size = this._designSize.clone();
                 this.size = this._designSize.clone();
-                this.scale = scale;
+                this._canvasLevelScale.copyFromFloats(scale, scale, 1);
+            } else if (this._curHWScale !== 1) {
+                let ratio = 1 / this._curHWScale;
+                this._canvasLevelScale.copyFromFloats(ratio, ratio, 1);
             }
             }
 
 
             var context = new PrepareRender2DContext();
             var context = new PrepareRender2DContext();
 
 
             ++this._globalTransformProcessStep;
             ++this._globalTransformProcessStep;
+            this._setFlags(SmartPropertyPrim.flagLocalTransformDirty|SmartPropertyPrim.flagGlobalTransformDirty);
             this.updateCachedStates(false);
             this.updateCachedStates(false);
 
 
             this._prepareGroupRender(context);
             this._prepareGroupRender(context);

+ 55 - 2
canvas2D/src/Engine/babylon.fontTexture.ts

@@ -478,13 +478,50 @@
 
 
             this._currentFreePosition = Vector2.Zero();
             this._currentFreePosition = Vector2.Zero();
 
 
-            // Add the basic ASCII based characters
+            // Add the basic ASCII based characters                                                               
             for (let i = 0x20; i < 0x7F; i++) {
             for (let i = 0x20; i < 0x7F; i++) {
                 var c = String.fromCharCode(i);
                 var c = String.fromCharCode(i);
                 this.getChar(c);
                 this.getChar(c);
             }
             }
 
 
             this.update();
             this.update();
+
+            //this._saveToImage("");
+            
+        }
+
+        private _saveToImage(url: string) {
+            let base64Image = this._canvas.toDataURL("image/png");
+
+            //Creating a link if the browser have the download attribute on the a tag, to automatically start download generated image.
+            if (("download" in document.createElement("a"))) {
+                var a = window.document.createElement("a");
+                a.href = base64Image;
+                var date = new Date();
+                var stringDate = (date.getFullYear() + "-" + (date.getMonth() + 1)).slice(-2) +
+                    "-" +
+                    date.getDate() +
+                    "_" +
+                    date.getHours() +
+                    "-" +
+                    ('0' + date.getMinutes()).slice(-2);
+                a.setAttribute("download", "screenshot_" + stringDate + ".png");
+
+                window.document.body.appendChild(a);
+
+                a.addEventListener("click",
+                    () => {
+                        a.parentElement.removeChild(a);
+                    });
+                a.click();
+
+                //Or opening a new tab with the image if it is not possible to automatically start download.
+            } else {
+                var newWindow = window.open("");
+                var img = newWindow.document.createElement("img");
+                img.src = base64Image;
+                newWindow.document.body.appendChild(img);
+            }
         }
         }
 
 
         /**
         /**
@@ -561,6 +598,20 @@
 
 
                 // Draw the character in the HTML canvas
                 // Draw the character in the HTML canvas
                 this._context.fillText(char, curPosXMargin, curPosYMargin - this._offset);
                 this._context.fillText(char, curPosXMargin, curPosYMargin - this._offset);
+
+                // Premul Alpha manually
+                let id = this._context.getImageData(curPosXMargin, curPosYMargin, width, this._lineHeightSuper);
+                for (let i = 0; i < id.data.length; i += 4) {
+                    let v = id.data[i + 3];
+                    if (v > 0 && v < 255) {
+                        id.data[i + 0] = v;
+                        id.data[i + 1] = v;
+                        id.data[i + 2] = v;
+                        id.data[i + 3] = v;
+                    }
+
+                }
+                this._context.putImageData(id, curPosXMargin, curPosYMargin);
             }
             }
 
 
             // Fill the CharInfo object
             // Fill the CharInfo object
@@ -765,12 +816,14 @@
             ctx.font = font;
             ctx.font = font;
             ctx.fillText(chars, 0, 0);
             ctx.fillText(chars, 0, 0);
             var pixels = ctx.getImageData(0, 0, fontDraw.width, fontDraw.height).data;
             var pixels = ctx.getImageData(0, 0, fontDraw.width, fontDraw.height).data;
+
             var start = -1;
             var start = -1;
             var end = -1;
             var end = -1;
             for (var row = 0; row < fontDraw.height; row++) {
             for (var row = 0; row < fontDraw.height; row++) {
                 for (var column = 0; column < fontDraw.width; column++) {
                 for (var column = 0; column < fontDraw.width; column++) {
                     var index = (row * fontDraw.width + column) * 4;
                     var index = (row * fontDraw.width + column) * 4;
-                    if (pixels[index] === 0) {
+                    let pix = pixels[index];
+                    if (pix === 0) {
                         if (column === fontDraw.width - 1 && start !== -1) {
                         if (column === fontDraw.width - 1 && start !== -1) {
                             end = row;
                             end = row;
                             row = fontDraw.height;
                             row = fontDraw.height;

+ 4 - 3
canvas2D/src/Engine/babylon.group2d.ts

@@ -355,8 +355,9 @@
 
 
             let s = this.actualSize;
             let s = this.actualSize;
             let a = this.actualScale;
             let a = this.actualScale;
-            let sw = Math.ceil(s.width * a.x);
-            let sh = Math.ceil(s.height * a.y);
+            let hwsl = 1/this.owner.engine.getHardwareScalingLevel();
+            let sw = Math.ceil(s.width * a.x * hwsl);
+            let sh = Math.ceil(s.height * a.y * hwsl);
 
 
             // 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.
             // 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!
             // So we set the width/height to the rendering's one because that's what we want for the viewport!
@@ -370,7 +371,7 @@
             if (!this._isCachedGroup) {
             if (!this._isCachedGroup) {
                 // Compute the WebGL viewport's location/size
                 // Compute the WebGL viewport's location/size
                 let t = this._globalTransform.getTranslation();
                 let t = this._globalTransform.getTranslation();
-                let rs = this.owner._renderingSize;
+                let rs = this.owner._renderingSize.multiplyByFloats(hwsl, hwsl);
                 sh = Math.min(sh, rs.height - t.y);
                 sh = Math.min(sh, rs.height - t.y);
                 sw = Math.min(sw, rs.width - t.x);
                 sw = Math.min(sw, rs.width - t.x);
                 let x = t.x;
                 let x = t.x;

+ 35 - 15
canvas2D/src/Engine/babylon.prim2dBase.ts

@@ -2228,6 +2228,7 @@
             this._scale.x = this._scale.y = value;
             this._scale.x = this._scale.y = value;
             this._setFlags(SmartPropertyPrim.flagActualScaleDirty);
             this._setFlags(SmartPropertyPrim.flagActualScaleDirty);
             this._spreadActualScaleDirty();
             this._spreadActualScaleDirty();
+            this._positioningDirty();
         }
         }
 
 
         public get scale(): number {
         public get scale(): number {
@@ -2553,6 +2554,7 @@
             this._scale.x = value;
             this._scale.x = value;
             this._setFlags(SmartPropertyPrim.flagActualScaleDirty);
             this._setFlags(SmartPropertyPrim.flagActualScaleDirty);
             this._spreadActualScaleDirty();
             this._spreadActualScaleDirty();
+            this._positioningDirty();
         }
         }
 
 
         public get scaleX(): number {
         public get scaleX(): number {
@@ -2567,6 +2569,7 @@
             this._scale.y = value;
             this._scale.y = value;
             this._setFlags(SmartPropertyPrim.flagActualScaleDirty);
             this._setFlags(SmartPropertyPrim.flagActualScaleDirty);
             this._spreadActualScaleDirty();
             this._spreadActualScaleDirty();
+            this._positioningDirty();
         }
         }
 
 
         public get scaleY(): number {
         public get scaleY(): number {
@@ -3665,6 +3668,7 @@
         private static _t2: Matrix = new Matrix();
         private static _t2: Matrix = new Matrix();
         private static _v0: Vector2 = Vector2.Zero();   // Must stay with the value 0,0
         private static _v0: Vector2 = Vector2.Zero();   // Must stay with the value 0,0
         private static _v30: Vector3 = Vector3.Zero();   // Must stay with the value 0,0,0
         private static _v30: Vector3 = Vector3.Zero();   // Must stay with the value 0,0,0
+        private static _iv3: Vector3 = new Vector3(1,1,1); // Must stay identity vector
         private static _ts0 = Size.Zero();
         private static _ts0 = Size.Zero();
 
 
         private _updateLocalTransform(): boolean {
         private _updateLocalTransform(): boolean {
@@ -3680,12 +3684,19 @@
                     this._updatePositioning();
                     this._updatePositioning();
                 }
                 }
 
 
+
                 var rot = Quaternion.RotationAxis(new Vector3(0, 0, 1), this._rotation);
                 var rot = Quaternion.RotationAxis(new Vector3(0, 0, 1), this._rotation);
                 var local: Matrix;
                 var local: Matrix;
                 let pos = this._position ? this.position : (this.layoutAreaPos || Prim2DBase._v0);
                 let pos = this._position ? this.position : (this.layoutAreaPos || Prim2DBase._v0);
                 let scale = new Vector3(this._scale.x, this._scale.y, 1);
                 let scale = new Vector3(this._scale.x, this._scale.y, 1);
                 let postScale = this._postScale;
                 let postScale = this._postScale;
-                let globalScale = scale.multiplyByFloats(postScale.x, postScale.y, 1);
+                let canvasScale = Prim2DBase._iv3;
+                let hasCanvasScale = false;
+                if (this._parent instanceof Canvas2D) {
+                    hasCanvasScale = true;
+                    canvasScale = (this._parent as Canvas2D)._canvasLevelScale || Prim2DBase._iv3;
+                }
+                let globalScale = scale.multiplyByFloats(postScale.x*canvasScale.x, postScale.y*canvasScale.y, 1);
 
 
                 if (this._origin.x === 0 && this._origin.y === 0) {
                 if (this._origin.x === 0 && this._origin.y === 0) {
                     // ###MATRIX PART###
                     // ###MATRIX PART###
@@ -3698,31 +3709,39 @@
                     // ###MATRIX PART###
                     // ###MATRIX PART###
                     {
                     {
                         // -Origin offset
                         // -Origin offset
+                        let t0 = Prim2DBase._t0;
+                        let t1 = Prim2DBase._t1;
+                        let t2 = Prim2DBase._t2;
                         let as = Prim2DBase._ts0;
                         let as = Prim2DBase._ts0;
                         as.copyFrom(this.actualSize);
                         as.copyFrom(this.actualSize);
                         as.width /= postScale.x;
                         as.width /= postScale.x;
                         as.height /= postScale.y;
                         as.height /= postScale.y;
-                        Matrix.TranslationToRef((-as.width * this._origin.x), (-as.height * this._origin.y), 0, Prim2DBase._t0);
+                        Matrix.TranslationToRef((-as.width * this._origin.x), (-as.height * this._origin.y), 0, t0);
 
 
                         // -Origin * rotation
                         // -Origin * rotation
-                        rot.toRotationMatrix(Prim2DBase._t1);
-                        Prim2DBase._t0.multiplyToRef(Prim2DBase._t1, Prim2DBase._t2);
+                        rot.toRotationMatrix(t1);
+                        t0.multiplyToRef(t1, t2);
 
 
                         // -Origin * rotation * scale
                         // -Origin * rotation * scale
-                        Matrix.ScalingToRef(this._scale.x, this._scale.y, 1, Prim2DBase._t0);
-                        Prim2DBase._t2.multiplyToRef(Prim2DBase._t0, Prim2DBase._t1);
+                        Matrix.ScalingToRef(this._scale.x, this._scale.y, 1, t0);
+                        t2.multiplyToRef(t0, t1);
 
 
                         // -Origin * rotation * scale * Origin
                         // -Origin * rotation * scale * Origin
-                        Matrix.TranslationToRef((as.width * this._origin.x), (as.height * this._origin.y), 0, Prim2DBase._t2);
-                        Prim2DBase._t1.multiplyToRef(Prim2DBase._t2, Prim2DBase._t0);
+                        Matrix.TranslationToRef((as.width * this._origin.x), (as.height * this._origin.y), 0, t2);
+                        t1.multiplyToRef(t2, t0);
 
 
                         // -Origin * rotation * scale * Origin * postScale
                         // -Origin * rotation * scale * Origin * postScale
-                        Matrix.ScalingToRef(postScale.x, postScale.y, 1, Prim2DBase._t1);
-                        Prim2DBase._t0.multiplyToRef(Prim2DBase._t1, Prim2DBase._t2);
+                        Matrix.ScalingToRef(postScale.x, postScale.y, 1, t1);
+                        t0.multiplyToRef(t1, t2);
 
 
                         // -Origin * rotation * scale * Origin * postScale * Position
                         // -Origin * rotation * scale * Origin * postScale * Position
-                        Matrix.TranslationToRef(pos.x + this._marginOffset.x, pos.y + this._marginOffset.y, 0, Prim2DBase._t0);
-                        Prim2DBase._t2.multiplyToRef(Prim2DBase._t0, this._localTransform);
+                        Matrix.TranslationToRef(pos.x + this._marginOffset.x, pos.y + this._marginOffset.y, 0, t0);
+                        t2.multiplyToRef(t0, this._localTransform);
+
+                        if (hasCanvasScale) {
+                            Matrix.ScalingToRef(canvasScale.x, canvasScale.y, canvasScale.z, Prim2DBase._t1);
+                            this._localTransform.multiplyToRef(Prim2DBase._t1, this._localTransform);
+                        }
 
 
                         this._localLayoutTransform = Matrix.Compose(globalScale, rot, new Vector3(pos.x, pos.y, 0));
                         this._localLayoutTransform = Matrix.Compose(globalScale, rot, new Vector3(pos.x, pos.y, 0));
                     }
                     }
@@ -3799,7 +3818,7 @@
             }
             }
 
 
             // Check if we must update this prim
             // Check if we must update this prim
-            if ((this === <any>this.owner) || (this._globalTransformProcessStep !== this.owner._globalTransformProcessStep) || (this._areSomeFlagsSet(SmartPropertyPrim.flagGlobalTransformDirty))) {
+            if ((this._globalTransformProcessStep !== this.owner._globalTransformProcessStep) || (this._areSomeFlagsSet(SmartPropertyPrim.flagGlobalTransformDirty))) {
                 this.owner.addUpdateGlobalTransformCounter(1);
                 this.owner.addUpdateGlobalTransformCounter(1);
 
 
                 let curVisibleState = this.isVisible;
                 let curVisibleState = this.isVisible;
@@ -3864,6 +3883,8 @@
 
 
         private _updatePositioning() {
         private _updatePositioning() {
             if (!this._isFlagSet(SmartPropertyPrim.flagUsePositioning)) {
             if (!this._isFlagSet(SmartPropertyPrim.flagUsePositioning)) {
+                // Just in case, if may happen and if we don't clear some computation will keep going on forever
+                this._clearFlags(SmartPropertyPrim.flagPositioningDirty);
                 return;
                 return;
             }
             }
 
 
@@ -3891,7 +3912,6 @@
             // Set the flag to avoid re-entrance
             // Set the flag to avoid re-entrance
             this._setFlags(SmartPropertyPrim.flagComputingPositioning);
             this._setFlags(SmartPropertyPrim.flagComputingPositioning);
             try {
             try {
-
                 let isSizeAuto = this.isSizeAuto;
                 let isSizeAuto = this.isSizeAuto;
                 let isVSizeAuto = this.isVerticalSizeAuto;
                 let isVSizeAuto = this.isVerticalSizeAuto;
                 let isHSizeAuto = this.isHorizontalSizeAuto;
                 let isHSizeAuto = this.isHorizontalSizeAuto;
@@ -4008,7 +4028,7 @@
                     //  not yet set and computing alignment would result into a bad size.
                     //  not yet set and computing alignment would result into a bad size.
                     // So we make sure with compute alignment only if the layoutArea is good
                     // So we make sure with compute alignment only if the layoutArea is good
                     if (layoutArea && layoutArea.width >= newSize.width && layoutArea.height >= newSize.height) {
                     if (layoutArea && layoutArea.width >= newSize.width && layoutArea.height >= newSize.height) {
-                        margin.computeWithAlignment(layoutArea, newSize, ma, this.actualScale, mo, Prim2DBase._size2);
+                        margin.computeWithAlignment(layoutArea, newSize, ma, new Vector2(1,1)/*this.actualScale*/, mo, Prim2DBase._size2);
                     } else {
                     } else {
                         mo.copyFromFloats(0, 0, 0, 0);
                         mo.copyFromFloats(0, 0, 0, 0);
                     }
                     }

+ 15 - 21
canvas2D/src/Engine/babylon.renderablePrim2d.ts

@@ -931,7 +931,7 @@
         private static _s = Vector3.Zero();
         private static _s = Vector3.Zero();
         private static _r = Quaternion.Identity();
         private static _r = Quaternion.Identity();
         private static _t = Vector3.Zero();
         private static _t = Vector3.Zero();
-        private static _uV3 = new Vector3(1, 1, 1);
+        private static _iV3 = new Vector3(1, 1, 1); // Must stay identity vector3
         /**
         /**
          * Update the instanceDataBase level properties of a part
          * Update the instanceDataBase level properties of a part
          * @param part the part to update
          * @param part the part to update
@@ -939,12 +939,22 @@
          */
          */
         protected updateInstanceDataPart(part: InstanceDataBase, positionOffset: Vector2 = null) {
         protected updateInstanceDataPart(part: InstanceDataBase, positionOffset: Vector2 = null) {
             let t = this._globalTransform.multiply(this.renderGroup.invGlobalTransform);    // Compute the transformation into the renderGroup's space
             let t = this._globalTransform.multiply(this.renderGroup.invGlobalTransform);    // Compute the transformation into the renderGroup's space
-            let rgScale = this._areSomeFlagsSet(SmartPropertyPrim.flagDontInheritParentScale) ? RenderablePrim2D._uV : this.renderGroup.actualScale;         // We still need to apply the scale of the renderGroup to our rendering, so get it.
+            let scl = RenderablePrim2D._s;
+            let rot = RenderablePrim2D._r;
+            let trn = RenderablePrim2D._t;
+            t.decompose(scl, rot, trn);
+            let pas = this.actualScale;
+            scl.x = pas.x;
+            scl.y = pas.y;
+            scl.z = 1;
+            t = Matrix.Compose(this.applyActualScaleOnTransform() ? scl : RenderablePrim2D._iV3, rot, trn);
+
             let size = (<Size>this.renderGroup.viewportSize);
             let size = (<Size>this.renderGroup.viewportSize);
             let zBias = this.actualZOffset;
             let zBias = this.actualZOffset;
 
 
             let offX = 0;
             let offX = 0;
             let offY = 0;
             let offY = 0;
+
             // If there's an offset, apply the global transformation matrix on it to get a global offset
             // If there's an offset, apply the global transformation matrix on it to get a global offset
             if (positionOffset) {
             if (positionOffset) {
                 offX = positionOffset.x * t.m[0] + positionOffset.y * t.m[4];
                 offX = positionOffset.x * t.m[0] + positionOffset.y * t.m[4];
@@ -960,25 +970,9 @@
             let w = size.width;
             let w = size.width;
             let h = size.height;
             let h = size.height;
             let invZBias = 1 / zBias;
             let invZBias = 1 / zBias;
-            let tx = new Vector4(t.m[0] * rgScale.x * 2 / w, t.m[4] * rgScale.x * 2 / w, 0/*t.m[8]*/, ((t.m[12] + offX) * rgScale.x * 2 / w) - 1);
-            let ty = new Vector4(t.m[1] * rgScale.y * 2 / h, t.m[5] * rgScale.y * 2 / h, 0/*t.m[9]*/, ((t.m[13] + offY) * rgScale.y * 2 / h) - 1);
-
-            //if (!this.applyActualScaleOnTransform()) {
-            //    t.m[0] = tx.x, t.m[4] = tx.y, t.m[12] = tx.w;
-            //    t.m[1] = ty.x, t.m[5] = ty.y, t.m[13] = ty.w;
-            //    let las = this.actualScale;
-            //    t.decompose(RenderablePrim2D._s, RenderablePrim2D._r, RenderablePrim2D._t);
-            //    let scale = new Vector3(RenderablePrim2D._s.x / las.x, RenderablePrim2D._s.y / las.y, 1);
-            //    t = Matrix.Compose(scale, RenderablePrim2D._r, RenderablePrim2D._t);
-            //    tx = new Vector4(t.m[0], t.m[4], 0, t.m[12]);
-            //    ty = new Vector4(t.m[1], t.m[5], 0, t.m[13]);
-            //}
-
-            //tx.x /= w;
-            //tx.y /= w;
-
-            //ty.x /= h;
-            //ty.y /= h;
+            let tx = new Vector4(t.m[0] * 2 / w, t.m[4] * 2 / w, 0, ((t.m[12] + offX) * 2 / w) - 1);
+            let ty = new Vector4(t.m[1] * 2 / h, t.m[5] * 2 / h, 0, ((t.m[13] + offY) * 2 / h) - 1);
+
 
 
             part.transformX = tx;
             part.transformX = tx;
             part.transformY = ty;
             part.transformY = ty;

File diff suppressed because it is too large
+ 32 - 6
canvas2D/src/Engine/babylon.text2d.ts


+ 7 - 0
canvas2D/src/shaders/text2d.fragment.fx

@@ -22,7 +22,14 @@ void main(void) {
 	gl_FragColor = vec4(vColor.xyz*dist, vColor.a);
 	gl_FragColor = vec4(vColor.xyz*dist, vColor.a);
 #else
 #else
 	vec4 color = texture2D(diffuseSampler, vUV);
 	vec4 color = texture2D(diffuseSampler, vUV);
+	if (color.a == 0.0) {
+		discard;
+	}
+#ifdef FontTexture
+	gl_FragColor = vec4(color.xxxx)*vColor;
+#else
 	gl_FragColor = color*vColor;
 	gl_FragColor = color*vColor;
 #endif
 #endif
+#endif
 
 
 }
 }

+ 33 - 0
contributing.md

@@ -0,0 +1,33 @@
+# Contributing to Babylon.js
+
+The foundation of **Babylon.js** is simplicity. 
+
+A developer should be able to quickly and easily learn to use the API. 
+
+Simplicity and a low barrier to entry are must-have features of every API. If you have any second thoughts about the complexity of a design, it is almost always much better to cut the feature from the current release and spend more time to get the design right for the next release. 
+
+You can always add to an API, you cannot ever remove anything from one. If the design does not feel right, and you ship it anyway, you are likely to regret having done so.
+
+That's why many of the guidelines of this document are obvious and serve only one purpose: Simplicity.
+
+## Forum and Github issues
+
+Since the very beginning, Babylon.js relies on a great forum and a tremendous community: http://www.html5gamedevs.com/forum/16-babylonjs/.
+Please use the forum for **ANY questions you may have**.
+
+Please use the Github issues **only** for:
+- Bugs
+- Feature requests
+
+We will try to enforce these rules as we consider the forum is a better place for discussions and learnings.
+
+## Pull requests
+
+We are not complicated people, but we still have some [coding guidelines](http://doc.babylonjs.com/generals/Approved_Naming_Conventions)
+Before submitting your PR, just check that everything goes well by [creating the minified version](http://doc.babylonjs.com/generals/Creating_the_Mini-fied_Version)
+
+Need help contributing, here are some links:
+  - [Gulp](https://github.com/BabylonJS/Babylon.js/tree/master/Tools/Gulp) to build from command line.
+  - [VSCode Editor](https://code.visualstudio.com/), Microsoft Code editor, see [Julian Chenard's post](http://pixelcodr.com/tutos/contribute/contribute.html) a Microsoft code editor.
+  - [Visual Studio](http://doc.babylonjs.com/generals/setup_visualStudio), Microsoft's IDE.
+  - [Forum thread](http://www.html5gamedevs.com/topic/20456-contributing-on-babylonjs/) for assistance from our very helpful family.

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


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


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


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


File diff suppressed because it is too large
+ 5983 - 5928
dist/preview release/babylon.module.d.ts


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


File diff suppressed because it is too large
+ 13 - 1
dist/preview release/canvas2D/babylon.canvas2d.d.ts


File diff suppressed because it is too large
+ 141 - 45
dist/preview release/canvas2D/babylon.canvas2d.js


File diff suppressed because it is too large
+ 12 - 12
dist/preview release/canvas2D/babylon.canvas2d.min.js


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

@@ -1,10 +1,11 @@
-# 2.6.0:
+# 3.0.0:
 
 
 ## Core engine
 ## Core engine
 
 
 ### Major updates
 ### Major updates
- - WebGL2 context support.WebGL2 is initialized instead of WebGL 1 when available ([deltakosh](https://github.com/deltakosh))
+ - WebGL2 context support. WebGL2 is now used instead of WebGL 1 when available. [More info here](http://doc.babylonjs.com/overviews/webgl2) ([deltakosh](https://github.com/deltakosh))
  - Support for [Vertex Array Objects](https://www.opengl.org/registry/specs/ARB/vertex_array_object.txt) ([deltakosh](https://github.com/deltakosh))
  - Support for [Vertex Array Objects](https://www.opengl.org/registry/specs/ARB/vertex_array_object.txt) ([deltakosh](https://github.com/deltakosh))
+ - Support for multisample render targets. [Demo](http://www.babylonjs-playground.com/#12MKMN) ([deltakosh](https://github.com/deltakosh))
  - New Unity 5 Editor Toolkit. Complete pipeline integration [Doc](TODO) - ([MackeyK24](https://github.com/MackeyK24))
  - New Unity 5 Editor Toolkit. Complete pipeline integration [Doc](TODO) - ([MackeyK24](https://github.com/MackeyK24))
  - New DebugLayer. [Doc](TODO) - ([temechon](https://github.com/temechon))
  - New DebugLayer. [Doc](TODO) - ([temechon](https://github.com/temechon))
  - New `VideoTexture.CreateFromWebCam` to generate video texture using WebRTC. [Demo](https://www.babylonjs-playground.com#1R77YT#2) - (Sebastien Vandenberghe)(https://github.com/sebavanmicrosoft) / ([deltakosh](https://github.com/deltakosh))
  - New `VideoTexture.CreateFromWebCam` to generate video texture using WebRTC. [Demo](https://www.babylonjs-playground.com#1R77YT#2) - (Sebastien Vandenberghe)(https://github.com/sebavanmicrosoft) / ([deltakosh](https://github.com/deltakosh))

+ 3 - 0
localDev/index.html

@@ -2,6 +2,9 @@
 <html xmlns="http://www.w3.org/1999/xhtml">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
 <head>
 	<title>Local Development</title>
 	<title>Local Development</title>
+	
+    <script src="https://babylonjs.azurewebsites.net/cannon.js"></script>
+    <script src="https://babylonjs.azurewebsites.net/Oimo.js"></script>
 	<script src="../assets/refs/dat.gui.min.js"></script>
 	<script src="../assets/refs/dat.gui.min.js"></script>
 	<script src="../tools/DevLoader/BabylonLoader.js"></script>
 	<script src="../tools/DevLoader/BabylonLoader.js"></script>
 
 

+ 3 - 9
readme.md

@@ -14,15 +14,9 @@ Getting started? Play directly with the Babylon.js API via our [playground](http
 - http://cdn.babylonjs.com/2-5/babylon.core.js 
 - http://cdn.babylonjs.com/2-5/babylon.core.js 
 
 
 ## Preview release
 ## Preview release
-You can help by testing or contributing to the next version.
-- **2.6-alpha** can be found [here](https://github.com/BabylonJS/Babylon.js/tree/master/dist/preview%20release)
-- We are not complicated people, but we still have some [coding guidelines](http://doc.babylonjs.com/generals/Approved_Naming_Conventions)
-- Before submitting your PR, just check that everything goes well by [creating the minified version](http://doc.babylonjs.com/generals/Creating_the_Mini-fied_Version)
-- Need help contributing, here are some links:
-  - [Gulp](https://github.com/BabylonJS/Babylon.js/tree/master/Tools/Gulp) to build from command line.
-  - [VSCode Editor](https://code.visualstudio.com/), Microsoft Code editor, see [Julian Chenard's post](http://pixelcodr.com/tutos/contribute/contribute.html) a Microsoft code editor.
-  - [Visual Studio](http://doc.babylonjs.com/generals/setup_visualStudio), Microsoft's IDE.
-  - [Forum thread](http://www.html5gamedevs.com/topic/20456-contributing-on-babylonjs/) for assistance from our very helpful family.
+
+**3.0-alpha** can be found [here](https://github.com/BabylonJS/Babylon.js/tree/master/dist/preview%20release)
+If you want to contribute, please read our [contribution guidelines](https://github.com/BabylonJS/Babylon.js/blob/master/contributing.md) first.
 
 
 ## Documentation
 ## Documentation
 - [Documentation](http://doc.babylonjs.com)
 - [Documentation](http://doc.babylonjs.com)

+ 40 - 5
src/Bones/babylon.bone.ts

@@ -203,13 +203,20 @@ module BABYLON {
 
 
             }else{
             }else{
 
 
+                var wm:Matrix;
+
+                //mesh.getWorldMatrix() needs to be called before skeleton.computeAbsoluteTransforms()
+                if(mesh){
+                    wm = mesh.getWorldMatrix();
+                }
+
                 this._skeleton.computeAbsoluteTransforms();
                 this._skeleton.computeAbsoluteTransforms();
                 var tmat = Tmp.Matrix[0];
                 var tmat = Tmp.Matrix[0];
                 var tvec = Tmp.Vector3[0];
                 var tvec = Tmp.Vector3[0];
 
 
                 if (mesh) {
                 if (mesh) {
                     tmat.copyFrom(this._parent.getAbsoluteTransform());
                     tmat.copyFrom(this._parent.getAbsoluteTransform());
-                    tmat.multiplyToRef(mesh.getWorldMatrix(), tmat);
+                    tmat.multiplyToRef(wm, tmat);
                 }else {
                 }else {
                     tmat.copyFrom(this._parent.getAbsoluteTransform());
                     tmat.copyFrom(this._parent.getAbsoluteTransform());
                 }
                 }
@@ -249,6 +256,13 @@ module BABYLON {
 
 
             }else{
             }else{
 
 
+                var wm:Matrix;
+
+                //mesh.getWorldMatrix() needs to be called before skeleton.computeAbsoluteTransforms()
+                if(mesh){
+                    wm = mesh.getWorldMatrix();
+                }
+
                 this._skeleton.computeAbsoluteTransforms();
                 this._skeleton.computeAbsoluteTransforms();
 
 
                 var tmat = Tmp.Matrix[0];
                 var tmat = Tmp.Matrix[0];
@@ -256,7 +270,7 @@ module BABYLON {
 
 
                 if (mesh) {
                 if (mesh) {
                     tmat.copyFrom(this._parent.getAbsoluteTransform());
                     tmat.copyFrom(this._parent.getAbsoluteTransform());
-                    tmat.multiplyToRef(mesh.getWorldMatrix(), tmat);
+                    tmat.multiplyToRef(wm, tmat);
                 }else {
                 }else {
                     tmat.copyFrom(this._parent.getAbsoluteTransform());
                     tmat.copyFrom(this._parent.getAbsoluteTransform());
                 }
                 }
@@ -754,6 +768,13 @@ module BABYLON {
          */
          */
         public getDirectionToRef (localAxis: Vector3, mesh: AbstractMesh, result: Vector3): void {
         public getDirectionToRef (localAxis: Vector3, mesh: AbstractMesh, result: Vector3): void {
 
 
+            var wm:Matrix;
+
+            //mesh.getWorldMatrix() needs to be called before skeleton.computeAbsoluteTransforms()
+            if(mesh){
+                wm = mesh.getWorldMatrix();
+            }
+
             this._skeleton.computeAbsoluteTransforms();
             this._skeleton.computeAbsoluteTransforms();
             
             
             var mat = Tmp.Matrix[0];
             var mat = Tmp.Matrix[0];
@@ -761,7 +782,7 @@ module BABYLON {
             mat.copyFrom(this.getAbsoluteTransform());
             mat.copyFrom(this.getAbsoluteTransform());
 
 
             if(mesh){
             if(mesh){
-                mat.multiplyToRef(mesh.getWorldMatrix(), mat);
+                mat.multiplyToRef(wm, mat);
             }
             }
 
 
             Vector3.TransformNormalToRef(localAxis, mat, result);
             Vector3.TransformNormalToRef(localAxis, mat, result);
@@ -923,13 +944,20 @@ module BABYLON {
          */
          */
         public getAbsolutePositionFromLocalToRef(position:Vector3, mesh:AbstractMesh, result:Vector3): void{
         public getAbsolutePositionFromLocalToRef(position:Vector3, mesh:AbstractMesh, result:Vector3): void{
 
 
+            var wm:Matrix;
+
+            //mesh.getWorldMatrix() needs to be called before skeleton.computeAbsoluteTransforms()
+            if(mesh){
+                wm = mesh.getWorldMatrix();
+            }
+
             this._skeleton.computeAbsoluteTransforms();
             this._skeleton.computeAbsoluteTransforms();
 
 
             var tmat = Tmp.Matrix[0];
             var tmat = Tmp.Matrix[0];
             
             
             if (mesh) {
             if (mesh) {
                 tmat.copyFrom(this.getAbsoluteTransform());
                 tmat.copyFrom(this.getAbsoluteTransform());
-                tmat.multiplyToRef(mesh.getWorldMatrix(), tmat);
+                tmat.multiplyToRef(wm, tmat);
             }else{
             }else{
                 tmat = this.getAbsoluteTransform();
                 tmat = this.getAbsoluteTransform();
             }
             }
@@ -962,6 +990,13 @@ module BABYLON {
          */
          */
         public getLocalPositionFromAbsoluteToRef(position:Vector3, mesh:AbstractMesh, result:Vector3): void{
         public getLocalPositionFromAbsoluteToRef(position:Vector3, mesh:AbstractMesh, result:Vector3): void{
 
 
+            var wm:Matrix;
+
+            //mesh.getWorldMatrix() needs to be called before skeleton.computeAbsoluteTransforms()
+            if(mesh){
+                wm = mesh.getWorldMatrix();
+            }
+
             this._skeleton.computeAbsoluteTransforms();
             this._skeleton.computeAbsoluteTransforms();
 
 
             var tmat = Tmp.Matrix[0];
             var tmat = Tmp.Matrix[0];
@@ -969,7 +1004,7 @@ module BABYLON {
             tmat.copyFrom(this.getAbsoluteTransform());
             tmat.copyFrom(this.getAbsoluteTransform());
             
             
             if (mesh) {
             if (mesh) {
-                tmat.multiplyToRef(mesh.getWorldMatrix(), tmat);
+                tmat.multiplyToRef(wm, tmat);
             }
             }
 
 
             tmat.invert();
             tmat.invert();

+ 258 - 30
src/Bones/babylon.boneLookController.ts

@@ -1,24 +1,116 @@
 module BABYLON {
 module BABYLON {
     export class BoneLookController {
     export class BoneLookController {
 
 
+        private static _tmpVecs: Vector3[] = [Vector3.Zero(), Vector3.Zero(), Vector3.Zero(),Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero()];
+        private static _tmpQuat = Quaternion.Identity();
+        private static _tmpMat1 = Matrix.Identity();
+        private static _tmpMat2 = Matrix.Identity();
+
         public target: Vector3;
         public target: Vector3;
         public mesh: AbstractMesh;
         public mesh: AbstractMesh;
         public bone: Bone;
         public bone: Bone;
         public upAxis: Vector3 = Vector3.Up();
         public upAxis: Vector3 = Vector3.Up();
+        public slerpAmount = 1;
 
 
-        public adjustYaw = 0;
-        public adjustPitch = 0;
-        public adjustRoll = 0;
-        
-        private _tmpVec1 = Vector3.Zero();
-        private _tmpVec2 = Vector3.Zero();
-        private _tmpVec3 = Vector3.Zero();
-        private _tmpVec4 = Vector3.Zero();
-        
-        private _tmpMat1 = Matrix.Identity();
-        private _tmpMat2 = Matrix.Identity();
+        private _adjustRotY = 0;
+        private _adjustRotX = 0;
+        private _adjustRotZ = 0;
+        private _minRotY:number;
+        private _maxRotY:number;
+        private _minRotX:number;
+        private _maxRotX:number;
+        private _minRotYSin:number;
+        private _minRotYCos:number;
+        private _maxRotYSin:number;
+        private _maxRotYCos:number;
+        private _minRotXTan:number;
+        private _maxRotXTan:number;
+        private _minRotZ:number;
+        private _maxRotZ:number;
+        private _minRotZSin:number;
+        private _minRotZCos:number;
+        private _maxRotZSin:number;
+        private _maxRotZCos:number;
+        private _boneQuat:Quaternion = Quaternion.Identity();
+        private _slerping = false;
 
 
-        constructor(mesh: AbstractMesh, bone: Bone, target: Vector3, options?: {adjustYaw?: number, adjustPitch?: number, adjustRoll?: number} ){
+        get minRotationY():number{
+            return this._minRotY - this._adjustRotY;
+        }
+
+        set minRotationY(value:number){
+            this._minRotY = value + this._adjustRotY;
+            this._minRotYSin = Math.sin(this._minRotY);
+            this._minRotYCos = Math.cos(this._minRotY);
+        }
+
+        get maxRoationY():number{
+            return this._maxRotY - this._adjustRotY;
+        }
+
+        set maxRotationY(value:number){
+            this._maxRotY = value + this._adjustRotY;
+            this._maxRotYSin = Math.sin(this._maxRotY);
+            this._maxRotYCos = Math.cos(this._maxRotY);
+        }
+
+        get minRotationX():number{
+            return this._minRotX - this._adjustRotX;
+        }
+
+        set minRotationX(value:number){
+            this._minRotX = value + this._adjustRotX;
+            this._minRotXTan = Math.tan(this._minRotX);
+        }
+
+        get maxRotationX():number{
+            return this._maxRotX - this._adjustRotX;
+        }
+
+        set maxRotationX(value:number){
+            this._maxRotX = value + this._adjustRotX;
+            this._maxRotXTan = Math.tan(this._maxRotX);
+        }
+
+        get minRotationZ():number{
+            return this._minRotZ - this._adjustRotZ;
+        }
+
+        set minRotationZ(value:number){
+            this._minRotZ = value + this._adjustRotZ;
+            this._minRotZSin = Math.sin(this._minRotZ);
+            this._minRotZCos = Math.cos(this._minRotZ);
+        }
+
+        get maxRotationZ():number{
+            return this._maxRotZ - this._adjustRotZ;
+        }
+
+        set maxRotationZ(value:number){
+            this._maxRotZ = value + this._adjustRotZ;
+            this._maxRotZSin = Math.sin(this._maxRotZ);
+            this._maxRotZCos = Math.cos(this._maxRotZ);
+        }
+
+        constructor(mesh: AbstractMesh, 
+                    bone: Bone, 
+                    target: Vector3, 
+                    options?: { 
+                        adjustRotationX?: number, 
+                        adjustRotationY?: number, 
+                        adjustRotationZ?: number, 
+                        slerpAmount?: number, 
+                        maxRotationY?:number, 
+                        minRotationY?:number,
+                        maxRotationX?:number, 
+                        minRotationX?:number,
+                        maxRotationZ?:number, 
+                        minRotationZ?:number,
+                        adjustYaw?: number, 
+                        adjustPitch?: number, 
+                        adjustRoll?: number 
+                    } 
+                    ){
 
 
             this.mesh = mesh;
             this.mesh = mesh;
             this.bone = bone;
             this.bone = bone;
@@ -27,15 +119,55 @@ module BABYLON {
             if(options){
             if(options){
 
 
                 if(options.adjustYaw){
                 if(options.adjustYaw){
-                    this.adjustYaw = options.adjustYaw;
+                    this._adjustRotY = options.adjustYaw;
                 }
                 }
 
 
                 if(options.adjustPitch){
                 if(options.adjustPitch){
-                    this.adjustPitch = options.adjustPitch;
+                    this._adjustRotX = options.adjustPitch;
                 }
                 }
 
 
                 if(options.adjustRoll){
                 if(options.adjustRoll){
-                    this.adjustRoll = options.adjustRoll;
+                    this._adjustRotZ = options.adjustRoll;
+                }
+
+                if(options.adjustRotationY){
+                    this._adjustRotY = options.adjustRotationY;
+                }
+
+                if(options.adjustRotationX){
+                    this._adjustRotX = options.adjustRotationX;
+                }
+
+                if(options.adjustRotationZ){
+                    this._adjustRotZ = options.adjustRotationZ;
+                }
+
+                if(options.maxRotationY != undefined){
+                    this.maxRotationY = options.maxRotationY;
+                }
+
+                if(options.minRotationY != undefined){
+                    this.minRotationY = options.minRotationY;
+                }
+
+                if(options.maxRotationX != undefined){
+                    this.maxRotationX = options.maxRotationX;
+                }
+
+                if(options.minRotationX != undefined){
+                    this.minRotationX = options.minRotationX;
+                }
+
+                if(options.maxRotationZ != undefined){
+                    this.maxRotationZ = options.maxRotationZ;
+                }
+
+                if(options.minRotationZ != undefined){
+                    this.minRotationZ = options.minRotationZ;
+                }
+
+                if(options.slerpAmount != undefined){
+                    this.slerpAmount = options.slerpAmount;
                 }
                 }
 
 
             }
             }
@@ -46,33 +178,129 @@ module BABYLON {
                 
                 
             var bone = this.bone;
             var bone = this.bone;
             var target = this.target;
             var target = this.target;
+            var mat1 = BoneLookController._tmpMat1;
+            var mat2 = BoneLookController._tmpMat2;
 
 
-            var bonePos = this._tmpVec1;
-            var zaxis = this._tmpVec2;
-            var xaxis = this._tmpVec3;
-            var yaxis = this._tmpVec4;
-            var mat1 = this._tmpMat1;
-            var mat2 = this._tmpMat2;
+            var parentBone = bone.getParent();
 
 
-            bone.getAbsolutePositionToRef(this.mesh, bonePos);
+            if(parentBone){
+                if(this._maxRotX != undefined || this._minRotX != undefined){
+                    var localTarget = BoneLookController._tmpVecs[4];
+                    var _tmpVec5 = BoneLookController._tmpVecs[5];
+                    parentBone.getLocalPositionFromAbsoluteToRef(target, this.mesh, localTarget);
+                    bone.getPositionToRef(Space.LOCAL, null, _tmpVec5);
+                    localTarget.x -= _tmpVec5.x;
+                    localTarget.y -= _tmpVec5.y;
+                    localTarget.z -= _tmpVec5.z;
+                    var xzlen = Math.sqrt(localTarget.x*localTarget.x + localTarget.z*localTarget.z);
+                    var rotX = Math.atan2(localTarget.y, xzlen);
+
+                    if(rotX > this._maxRotX){
+                        localTarget.y = this._maxRotXTan*xzlen + _tmpVec5.y;
+                        parentBone.getAbsolutePositionFromLocalToRef(localTarget, this.mesh, localTarget);
+                        target = localTarget;
+                    }else if(rotX < this._minRotX){
+                        localTarget.y = this._minRotXTan*xzlen + _tmpVec5.y;
+                        parentBone.getAbsolutePositionFromLocalToRef(localTarget, this.mesh, localTarget);
+                        target = localTarget;
+                    }
+                }
+
+                if(this._maxRotY != undefined || this._minRotY != undefined){
+                    var localTarget = BoneLookController._tmpVecs[6];
+                    var _tmpVec7 = BoneLookController._tmpVecs[7];
+                    parentBone.getLocalPositionFromAbsoluteToRef(target, this.mesh, localTarget);
+                    bone.getPositionToRef(Space.LOCAL, null, _tmpVec7);
+                    localTarget.x -= _tmpVec7.x;
+                    localTarget.z -= _tmpVec7.z;
+                    var rotY = Math.atan2(localTarget.x, localTarget.z);
+                    
+                    if(rotY > this._maxRotY){
+                        var xzlen = Math.sqrt(localTarget.x*localTarget.x + localTarget.z*localTarget.z);
+                        localTarget.z = this._maxRotYCos*xzlen;
+                        localTarget.x = this._maxRotYSin*xzlen;
+                        parentBone.getAbsolutePositionFromLocalToRef(localTarget, this.mesh, localTarget);
+                        target = localTarget;
+                    }else if(rotY < this._minRotY){
+                        var xzlen = Math.sqrt(localTarget.x*localTarget.x + localTarget.z*localTarget.z);
+                        localTarget.z = this._minRotYCos*xzlen;
+                        localTarget.x = this._minRotYSin*xzlen;
+                        parentBone.getAbsolutePositionFromLocalToRef(localTarget, this.mesh, localTarget);
+                        target = localTarget;
+                    }
+                }
 
 
+                if(this._maxRotZ != undefined || this._minRotZ != undefined){
+                    var localTarget = BoneLookController._tmpVecs[8];
+                    var _tmpVec9 = BoneLookController._tmpVecs[9];
+                    parentBone.getLocalPositionFromAbsoluteToRef(target, this.mesh, localTarget);
+                    bone.getPositionToRef(Space.LOCAL, null, _tmpVec9);
+                    localTarget.x -= _tmpVec9.x;
+                    localTarget.y -= _tmpVec9.y;
+                    var rotZ = Math.atan2(localTarget.y, localTarget.x);
+                    
+                    if(rotZ > this._maxRotZ){
+                        var xylen = Math.sqrt(localTarget.x*localTarget.x + localTarget.y*localTarget.y);
+                        localTarget.x = this._maxRotZCos*xylen;
+                        localTarget.y = this._maxRotZSin*xylen;
+                        parentBone.getAbsolutePositionFromLocalToRef(localTarget, this.mesh, localTarget);
+                        target = localTarget;
+                    }else if(rotZ < this._minRotZ){
+                        var xylen = Math.sqrt(localTarget.x*localTarget.x + localTarget.y*localTarget.y);
+                        localTarget.x = this._minRotZCos*xylen;
+                        localTarget.y = this._minRotZSin*xylen;
+                        parentBone.getAbsolutePositionFromLocalToRef(localTarget, this.mesh, localTarget);
+                        target = localTarget;
+                    }
+                }
+
+
+            }
+
+            var bonePos = BoneLookController._tmpVecs[0];
+            var zaxis = BoneLookController._tmpVecs[1];
+            var xaxis = BoneLookController._tmpVecs[2];
+            var yaxis = BoneLookController._tmpVecs[3];
+            var _tmpQuat = BoneLookController._tmpQuat;
+
+            bone.getAbsolutePositionToRef(this.mesh, bonePos);
             target.subtractToRef(bonePos, zaxis);
             target.subtractToRef(bonePos, zaxis);
             zaxis.normalize();
             zaxis.normalize();
-
-            BABYLON.Vector3.CrossToRef(this.upAxis, zaxis, xaxis);
+            Vector3.CrossToRef(this.upAxis, zaxis, xaxis);
             xaxis.normalize();
             xaxis.normalize();
-
-            BABYLON.Vector3.CrossToRef(zaxis, xaxis, yaxis);
+            Vector3.CrossToRef(zaxis, xaxis, yaxis);
             yaxis.normalize();
             yaxis.normalize();
+            Matrix.FromXYZAxesToRef(xaxis, yaxis, zaxis, mat1);
+
+            if(xaxis.x === 0 && xaxis.y === 0 && xaxis.z === 0){
+                return;
+            }
+
+            if(yaxis.x === 0 && yaxis.y === 0 && yaxis.z === 0){
+                return;
+            }
 
 
-            BABYLON.Matrix.FromXYZAxesToRef(xaxis, yaxis, zaxis, mat1);
+            if(zaxis.x === 0 && zaxis.y === 0 && zaxis.z === 0){
+                return;
+            }
 
 
-            if (this.adjustYaw || this.adjustPitch || this.adjustRoll) {
-                BABYLON.Matrix.RotationYawPitchRollToRef(this.adjustYaw, this.adjustPitch, this.adjustRoll, mat2);
+            if (this._adjustRotY || this._adjustRotX || this._adjustRotZ) {
+                Matrix.RotationYawPitchRollToRef(this._adjustRotY, this._adjustRotX, this._adjustRotZ, mat2);
                 mat2.multiplyToRef(mat1, mat1);
                 mat2.multiplyToRef(mat1, mat1);
             }
             }
 
 
-            this.bone.setRotationMatrix(mat1, BABYLON.Space.WORLD, this.mesh);
+            if (this.slerpAmount < 1) {
+                if (!this._slerping) {
+                    this.bone.getRotationQuaternionToRef(Space.WORLD, this.mesh, this._boneQuat);
+                }
+                Quaternion.FromRotationMatrixToRef(mat1, _tmpQuat);
+                Quaternion.SlerpToRef(this._boneQuat, _tmpQuat, this.slerpAmount, this._boneQuat);
+                this.bone.setRotationQuaternion(this._boneQuat, Space.WORLD, this.mesh);
+                this._slerping = true;
+            } else {
+                this.bone.setRotationMatrix(mat1, Space.WORLD, this.mesh);
+                this._slerping = false;
+            }
 
 
         }
         }
 
 

+ 1 - 1
src/Cameras/babylon.freeCamera.ts

@@ -181,7 +181,7 @@
             if (this.checkCollisions && this.getScene().collisionsEnabled) {
             if (this.checkCollisions && this.getScene().collisionsEnabled) {
                 this._collideWithWorld(this.cameraDirection);
                 this._collideWithWorld(this.cameraDirection);
             } else {
             } else {
-                this.position.addInPlace(this.cameraDirection);
+                super._updatePosition();
             }
             }
         }
         }
 
 

+ 10 - 0
src/Cameras/babylon.targetCamera.ts

@@ -142,6 +142,10 @@ module BABYLON {
             }
             }
         }
         }
 
 
+
+        /**
+         * Return the current target position of the camera. This value is expressed in local space.
+         */
         public getTarget(): Vector3 {
         public getTarget(): Vector3 {
             return this._currentTarget;
             return this._currentTarget;
         }
         }
@@ -151,6 +155,12 @@ module BABYLON {
         }
         }
 
 
         public _updatePosition(): void {
         public _updatePosition(): void {
+            if (this.parent) {
+                this.parent.getWorldMatrix().invertToRef(Tmp.Matrix[0]);
+                Vector3.TransformNormalToRef(this.cameraDirection, Tmp.Matrix[0], Tmp.Vector3[0]);
+                this.position.addInPlace(Tmp.Vector3[0]);
+                return;
+            }
             this.position.addInPlace(this.cameraDirection);
             this.position.addInPlace(this.cameraDirection);
         }
         }
         public _checkInputs(): void {
         public _checkInputs(): void {

+ 13 - 0
src/Materials/Textures/babylon.renderTargetTexture.ts

@@ -99,6 +99,7 @@
         private _currentRefreshId = -1;
         private _currentRefreshId = -1;
         private _refreshRate = 1;
         private _refreshRate = 1;
         private _textureMatrix: Matrix;
         private _textureMatrix: Matrix;
+        private _samples = 1;
         protected _renderTargetOptions: {
         protected _renderTargetOptions: {
             generateMipMaps: boolean,
             generateMipMaps: boolean,
             type: number,
             type: number,
@@ -141,6 +142,18 @@
             this._renderingManager = new RenderingManager(scene);
             this._renderingManager = new RenderingManager(scene);
         }
         }
 
 
+        public get samples(): number {
+            return this._samples;
+        }
+
+        public set samples(value: number) {
+            if (this._samples === value) {
+                return;
+            }
+            
+            this._samples = this.getScene().getEngine().updateRenderTargetTextureSampleCount(this._texture, value);
+        }
+
         public resetRefreshCounter(): void {
         public resetRefreshCounter(): void {
             this._currentRefreshId = -1;
             this._currentRefreshId = -1;
         }
         }

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

@@ -215,7 +215,7 @@
 
 
             this._scene = scene || Engine.LastCreatedScene;
             this._scene = scene || Engine.LastCreatedScene;
 
 
-            if (scene.useRightHandedSystem) {
+            if (this._scene.useRightHandedSystem) {
                 this.sideOrientation = Material.ClockWiseSideOrientation;
                 this.sideOrientation = Material.ClockWiseSideOrientation;
             } else {
             } else {
                 this.sideOrientation = Material.CounterClockWiseSideOrientation;
                 this.sideOrientation = Material.CounterClockWiseSideOrientation;

+ 33 - 0
src/Mesh/babylon.groundMesh.ts

@@ -229,5 +229,38 @@ module BABYLON {
             }
             }
             return this;
             return this;
         }
         }
+
+        public serialize(serializationObject: any): void {
+            super.serialize(serializationObject);
+            serializationObject.subdivisionsX = this._subdivisionsX;
+            serializationObject.subdivisionsY = this._subdivisionsY;
+
+            serializationObject.minX = this._minX;
+            serializationObject.maxX = this._maxX;
+
+            serializationObject.minZ = this._minZ;
+            serializationObject.maxZ = this._maxZ;
+
+            serializationObject.width = this._width;
+            serializationObject.height = this._height;
+        }
+
+        public static Parse(parsedMesh: any, scene: Scene): GroundMesh {
+            var result = new GroundMesh(parsedMesh.name, scene);
+
+            result._subdivisionsX = parsedMesh.subdivisionsX || 1;
+            result._subdivisionsY = parsedMesh.subdivisionsY || 1;
+
+            result._minX = parsedMesh.minX;
+            result._maxX = parsedMesh.maxX;
+
+            result._minZ = parsedMesh.minZ;
+            result._maxZ = parsedMesh.maxZ;
+
+            result._width = parsedMesh.width;
+            result._height = parsedMesh.height;
+
+            return result;
+        }
     }
     }
 }
 }

+ 132 - 1
src/Mesh/babylon.mesh.ts

@@ -1845,6 +1845,137 @@
             return this;
             return this;
         }
         }
 
 
+        public serialize(serializationObject: any): void {
+            serializationObject.name = this.name;
+            serializationObject.id = this.id;
+            serializationObject.type = this.getClassName();
+
+            if (Tags.HasTags(this)) {
+                serializationObject.tags = Tags.GetTags(this);
+            }
+
+            serializationObject.position = this.position.asArray();
+
+            if (this.rotationQuaternion) {
+                serializationObject.rotationQuaternion = this.rotationQuaternion.asArray();
+            } else if (this.rotation) {
+                serializationObject.rotation = this.rotation.asArray();
+            }
+
+            serializationObject.scaling = this.scaling.asArray();
+            serializationObject.localMatrix = this.getPivotMatrix().asArray();
+
+            serializationObject.isEnabled = this.isEnabled();
+            serializationObject.isVisible = this.isVisible;
+            serializationObject.infiniteDistance = this.infiniteDistance;
+            serializationObject.pickable = this.isPickable;
+
+            serializationObject.receiveShadows = this.receiveShadows;
+
+            serializationObject.billboardMode = this.billboardMode;
+            serializationObject.visibility = this.visibility;
+
+            serializationObject.checkCollisions = this.checkCollisions;
+            serializationObject.isBlocker = this.isBlocker;
+
+            // Parent
+            if (this.parent) {
+                serializationObject.parentId = this.parent.id;
+            }
+
+            // Geometry
+            var geometry = this._geometry;
+            if (geometry) {
+                var geometryId = geometry.id;
+                serializationObject.geometryId = geometryId;
+
+                // SubMeshes
+                serializationObject.subMeshes = [];
+                for (var subIndex = 0; subIndex < this.subMeshes.length; subIndex++) {
+                    var subMesh = this.subMeshes[subIndex];
+
+                    serializationObject.subMeshes.push({
+                        materialIndex: subMesh.materialIndex,
+                        verticesStart: subMesh.verticesStart,
+                        verticesCount: subMesh.verticesCount,
+                        indexStart: subMesh.indexStart,
+                        indexCount: subMesh.indexCount
+                    });
+                }
+            }
+
+            // Material
+            if (this.material) {
+                serializationObject.materialId = this.material.id;
+            } else {
+                this.material = null;
+            }
+
+            // Skeleton
+            if (this.skeleton) {
+                serializationObject.skeletonId = this.skeleton.id;
+            }
+
+            // Physics
+            //TODO implement correct serialization for physics impostors.
+            if (this.getPhysicsImpostor()) {
+                serializationObject.physicsMass = this.getPhysicsMass();
+                serializationObject.physicsFriction = this.getPhysicsFriction();
+                serializationObject.physicsRestitution = this.getPhysicsRestitution();
+                serializationObject.physicsImpostor = this.getPhysicsImpostor().type;
+            }
+
+            // Metadata
+            if (this.metadata) {
+                serializationObject.metadata = this.metadata;
+            }
+
+            // Instances
+            serializationObject.instances = [];
+            for (var index = 0; index < this.instances.length; index++) {
+                var instance = this.instances[index];
+                var serializationInstance: any = {
+                    name: instance.name,
+                    position: instance.position.asArray(),
+                    scaling: instance.scaling.asArray()
+                };
+                if (instance.rotationQuaternion) {
+                    serializationInstance.rotationQuaternion = instance.rotationQuaternion.asArray();
+                } else if (instance.rotation) {
+                    serializationInstance.rotation = instance.rotation.asArray();
+                }
+                serializationObject.instances.push(serializationInstance);
+
+                // Animations
+                Animation.AppendSerializedAnimations(instance, serializationInstance);
+                serializationInstance.ranges = instance.serializeAnimationRanges();
+            }
+
+            // Animations
+            Animation.AppendSerializedAnimations(this, serializationObject);
+            serializationObject.ranges = this.serializeAnimationRanges();
+
+            // Layer mask
+            serializationObject.layerMask = this.layerMask;
+
+            // Alpha
+            serializationObject.alphaIndex = this.alphaIndex;
+            serializationObject.hasVertexAlpha = this.hasVertexAlpha;
+            
+            // Overlay
+            serializationObject.overlayAlpha = this.overlayAlpha;
+            serializationObject.overlayColor = this.overlayColor.asArray();
+            serializationObject.renderOverlay = this.renderOverlay;
+
+            // Fog
+            serializationObject.applyFog = this.applyFog;
+
+            // Action Manager
+            if (this.actionManager) {
+                serializationObject.actions = this.actionManager.serialize(this.name);
+            }
+        }
+
         // Statics
         // Statics
         /**
         /**
          * Returns a new Mesh object what is a deep copy of the passed mesh.   
          * Returns a new Mesh object what is a deep copy of the passed mesh.   
@@ -1855,7 +1986,7 @@
             var mesh : Mesh;
             var mesh : Mesh;
 
 
             if (parsedMesh.type && parsedMesh.type === "GroundMesh") {
             if (parsedMesh.type && parsedMesh.type === "GroundMesh") {
-                mesh = new GroundMesh(parsedMesh.name, scene);
+                mesh = GroundMesh.Parse(parsedMesh, scene);
             } else {
             } else {
                 mesh = new Mesh(parsedMesh.name, scene);
                 mesh = new Mesh(parsedMesh.name, scene);
             }
             }

+ 8 - 0
src/Probes/babylon.reflectionProbe.ts

@@ -59,6 +59,14 @@
             this._projectionMatrix = Matrix.PerspectiveFovLH(Math.PI / 2, 1, scene.activeCamera.minZ, scene.activeCamera.maxZ);
             this._projectionMatrix = Matrix.PerspectiveFovLH(Math.PI / 2, 1, scene.activeCamera.minZ, scene.activeCamera.maxZ);
         }
         }
 
 
+        public get samples(): number {
+            return this._renderTargetTexture.samples;
+        }
+
+        public set samples(value: number) {
+            this._renderTargetTexture.samples = value;
+        }
+
         public get refreshRate(): number {
         public get refreshRate(): number {
             return this._renderTargetTexture.refreshRate;
             return this._renderTargetTexture.refreshRate;
         }
         }

+ 2 - 2
src/Tools/babylon.database.ts

@@ -43,7 +43,7 @@ module BABYLON {
         }
         }
 
 
         static ReturnFullUrlLocation = (url: string): string => {
         static ReturnFullUrlLocation = (url: string): string => {
-            if (url.indexOf("http:/") === -1) {
+            if (url.indexOf("http:/") === -1 && url.indexOf("https:/") === -1) {
                 return (Database.parseURL(window.location.href) + url);
                 return (Database.parseURL(window.location.href) + url);
             }
             }
             else {
             else {
@@ -584,4 +584,4 @@ module BABYLON {
             }
             }
         }
         }
     }
     }
-}
+}

+ 11 - 127
src/Tools/babylon.sceneSerializer.ts

@@ -43,138 +43,18 @@
     var serializeMesh = (mesh: Mesh, serializationScene: any): any => {
     var serializeMesh = (mesh: Mesh, serializationScene: any): any => {
         var serializationObject: any = {};
         var serializationObject: any = {};
 
 
-        serializationObject.name = mesh.name;
-        serializationObject.id = mesh.id;
-        serializationObject.type = mesh.getClassName();
-
-        if (Tags.HasTags(mesh)) {
-            serializationObject.tags = Tags.GetTags(mesh);
-        }
-
-        serializationObject.position = mesh.position.asArray();
-
-        if (mesh.rotationQuaternion) {
-            serializationObject.rotationQuaternion = mesh.rotationQuaternion.asArray();
-        } else if (mesh.rotation) {
-            serializationObject.rotation = mesh.rotation.asArray();
-        }
-
-        serializationObject.scaling = mesh.scaling.asArray();
-        serializationObject.localMatrix = mesh.getPivotMatrix().asArray();
-
-        serializationObject.isEnabled = mesh.isEnabled();
-        serializationObject.isVisible = mesh.isVisible;
-        serializationObject.infiniteDistance = mesh.infiniteDistance;
-        serializationObject.pickable = mesh.isPickable;
-
-        serializationObject.receiveShadows = mesh.receiveShadows;
-
-        serializationObject.billboardMode = mesh.billboardMode;
-        serializationObject.visibility = mesh.visibility;
-
-        serializationObject.checkCollisions = mesh.checkCollisions;
-        serializationObject.isBlocker = mesh.isBlocker;
-
-        // Parent
-        if (mesh.parent) {
-            serializationObject.parentId = mesh.parent.id;
-        }
-
-        // Geometry
-        var geometry = mesh._geometry;
+        // Geometry      
+        var geometry = mesh._geometry;      
         if (geometry) {
         if (geometry) {
-            var geometryId = geometry.id;
-            serializationObject.geometryId = geometryId;
-
-            if (!mesh.getScene().getGeometryByID(geometryId)) {
-                // geometry was in the memory but not added to the scene, nevertheless it's better to serialize to be able to reload the mesh with its geometry
+            if (!mesh.getScene().getGeometryByID(geometry.id)) {
+                // Geometry was in the memory but not added to the scene, nevertheless it's better to serialize to be able to reload the mesh with its geometry
                 serializeGeometry(geometry, serializationScene.geometries);
                 serializeGeometry(geometry, serializationScene.geometries);
             }
             }
-
-            // SubMeshes
-            serializationObject.subMeshes = [];
-            for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
-                var subMesh = mesh.subMeshes[subIndex];
-
-                serializationObject.subMeshes.push({
-                    materialIndex: subMesh.materialIndex,
-                    verticesStart: subMesh.verticesStart,
-                    verticesCount: subMesh.verticesCount,
-                    indexStart: subMesh.indexStart,
-                    indexCount: subMesh.indexCount
-                });
-            }
-        }
-
-        // Material
-        if (mesh.material) {
-            serializationObject.materialId = mesh.material.id;
-        } else {
-            mesh.material = null;
         }
         }
 
 
-        // Skeleton
-        if (mesh.skeleton) {
-            serializationObject.skeletonId = mesh.skeleton.id;
-        }
-
-        // Physics
-        //TODO implement correct serialization for physics impostors.
-        if (mesh.getPhysicsImpostor()) {
-            serializationObject.physicsMass = mesh.getPhysicsMass();
-            serializationObject.physicsFriction = mesh.getPhysicsFriction();
-            serializationObject.physicsRestitution = mesh.getPhysicsRestitution();
-            serializationObject.physicsImpostor = mesh.getPhysicsImpostor().type;
-        }
-
-        // Metadata
-        if (mesh.metadata) {
-            serializationObject.metadata = mesh.metadata;
-        }
-
-        // Instances
-        serializationObject.instances = [];
-        for (var index = 0; index < mesh.instances.length; index++) {
-            var instance = mesh.instances[index];
-            var serializationInstance: any = {
-                name: instance.name,
-                position: instance.position.asArray(),
-                scaling: instance.scaling.asArray()
-            };
-            if (instance.rotationQuaternion) {
-                serializationInstance.rotationQuaternion = instance.rotationQuaternion.asArray();
-            } else if (instance.rotation) {
-                serializationInstance.rotation = instance.rotation.asArray();
-            }
-            serializationObject.instances.push(serializationInstance);
-
-            // Animations
-            Animation.AppendSerializedAnimations(instance, serializationInstance);
-            serializationInstance.ranges = instance.serializeAnimationRanges();
-        }
-
-        // Animations
-        Animation.AppendSerializedAnimations(mesh, serializationObject);
-        serializationObject.ranges = mesh.serializeAnimationRanges();
-
-        // Layer mask
-        serializationObject.layerMask = mesh.layerMask;
-
-        // Alpha
-        serializationObject.alphaIndex = mesh.alphaIndex;
-        serializationObject.hasVertexAlpha = mesh.hasVertexAlpha;
-        
-        // Overlay
-        serializationObject.overlayAlpha = mesh.overlayAlpha;
-        serializationObject.overlayColor = mesh.overlayColor.asArray();
-        serializationObject.renderOverlay = mesh.renderOverlay;
-
-        // Fog
-        serializationObject.applyFog = mesh.applyFog;
-
-        // Action Manager
-        if (mesh.actionManager) {
-            serializationObject.actions = mesh.actionManager.serialize(mesh.name);
+        // Custom
+        if (mesh.serialize) {
+            mesh.serialize(serializationObject);
         }
         }
 
 
         return serializationObject;
         return serializationObject;
@@ -236,6 +116,8 @@
         public static Serialize(scene: Scene): any {
         public static Serialize(scene: Scene): any {
             var serializationObject: any = {};
             var serializationObject: any = {};
 
 
+            SceneSerializer.ClearCache();
+
             // Scene
             // Scene
             serializationObject.useDelayedTextureLoading = scene.useDelayedTextureLoading;
             serializationObject.useDelayedTextureLoading = scene.useDelayedTextureLoading;
             serializationObject.autoClear = scene.autoClear;
             serializationObject.autoClear = scene.autoClear;
@@ -402,6 +284,8 @@
         public static SerializeMesh(toSerialize: any /* Mesh || Mesh[] */, withParents: boolean = false, withChildren: boolean = false): any {
         public static SerializeMesh(toSerialize: any /* Mesh || Mesh[] */, withParents: boolean = false, withChildren: boolean = false): any {
             var serializationObject: any = {};
             var serializationObject: any = {};
 
 
+            SceneSerializer.ClearCache();
+
             toSerialize = (toSerialize instanceof Array) ? toSerialize : [toSerialize];
             toSerialize = (toSerialize instanceof Array) ? toSerialize : [toSerialize];
 
 
             if (withParents || withChildren) {
             if (withParents || withChildren) {

+ 1 - 1
src/Tools/babylon.tools.ts

@@ -304,7 +304,7 @@
                     case "function":
                     case "function":
                         var result = Tools.CorsBehavior(url);
                         var result = Tools.CorsBehavior(url);
                         if (result) {
                         if (result) {
-                            return result;
+                            img.crossOrigin = result;
                         }
                         }
                         break;
                         break;
                     case "string":
                     case "string":

+ 107 - 57
src/babylon.engine.ts

@@ -408,7 +408,7 @@
         }
         }
 
 
         public static get Version(): string {
         public static get Version(): string {
-            return "2.6-alpha";
+            return "3.0-alpha";
         }
         }
 
 
         // Updatable statics so stick with vars here
         // Updatable statics so stick with vars here
@@ -1216,10 +1216,9 @@
 
 
         public bindFramebuffer(texture: WebGLTexture, faceIndex?: number, requiredWidth?: number, requiredHeight?: number): void {
         public bindFramebuffer(texture: WebGLTexture, faceIndex?: number, requiredWidth?: number, requiredHeight?: number): void {
             this._currentRenderTarget = texture;
             this._currentRenderTarget = texture;
-            this.bindUnboundFramebuffer(texture._framebuffer);
+            this.bindUnboundFramebuffer(texture._MSAAFramebuffer ? texture._MSAAFramebuffer : texture._framebuffer);
             var gl = this._gl;
             var gl = this._gl;
             if (texture.isCube) {
             if (texture.isCube) {
-
                 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, texture, 0);
                 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, texture, 0);
             }
             }
 
 
@@ -1237,8 +1236,19 @@
 
 
         public unBindFramebuffer(texture: WebGLTexture, disableGenerateMipMaps = false): void {
         public unBindFramebuffer(texture: WebGLTexture, disableGenerateMipMaps = false): void {
             this._currentRenderTarget = null;
             this._currentRenderTarget = null;
+
+            // If MSAA, we need to bitblt back to main texture
+            var gl = this._gl;
+
+            if (texture._MSAAFramebuffer) {
+                gl.bindFramebuffer(gl.READ_FRAMEBUFFER, texture._MSAAFramebuffer);
+                gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, texture._framebuffer);
+                gl.blitFramebuffer( 0, 0, texture._width, texture._height, 
+                                    0, 0, texture._width, texture._height,
+                                    gl.COLOR_BUFFER_BIT, gl.NEAREST);
+            }
+
             if (texture.generateMipMaps && !disableGenerateMipMaps) {
             if (texture.generateMipMaps && !disableGenerateMipMaps) {
-                var gl = this._gl;
                 this._bindTextureDirectly(gl.TEXTURE_2D, texture);
                 this._bindTextureDirectly(gl.TEXTURE_2D, texture);
                 gl.generateMipmap(gl.TEXTURE_2D);
                 gl.generateMipmap(gl.TEXTURE_2D);
                 this._bindTextureDirectly(gl.TEXTURE_2D, null);
                 this._bindTextureDirectly(gl.TEXTURE_2D, null);
@@ -1995,7 +2005,7 @@
                     this._alphaState.alphaBlend = false;
                     this._alphaState.alphaBlend = false;
                     break;
                     break;
                 case Engine.ALPHA_PREMULTIPLIED:
                 case Engine.ALPHA_PREMULTIPLIED:
-                    this._alphaState.setAlphaBlendFunctionParameters(this._gl.ONE, this._gl.ONE_MINUS_SRC_ALPHA, this._gl.ONE, this._gl.ONE_MINUS_SRC_ALPHA);
+                    this._alphaState.setAlphaBlendFunctionParameters(this._gl.ONE, this._gl.ONE_MINUS_SRC_ALPHA, this._gl.ONE, this._gl.ONE);
                     this._alphaState.alphaBlend = true;
                     this._alphaState.alphaBlend = true;
                     break;
                     break;
                 case Engine.ALPHA_COMBINE:
                 case Engine.ALPHA_COMBINE:
@@ -2467,33 +2477,13 @@
 
 
             gl.texImage2D(gl.TEXTURE_2D, 0, this._getRGBABufferInternalSizedFormat(type), width, height, 0, gl.RGBA, this._getWebGLTextureType(type), null);
             gl.texImage2D(gl.TEXTURE_2D, 0, this._getRGBABufferInternalSizedFormat(type), width, height, 0, gl.RGBA, this._getWebGLTextureType(type), null);
 
 
-            var depthStencilBuffer: WebGLRenderbuffer;
-
-            // Create the depth/stencil buffer
-            if (generateStencilBuffer) {
-                depthStencilBuffer = gl.createRenderbuffer();
-                gl.bindRenderbuffer(gl.RENDERBUFFER, depthStencilBuffer);
-                gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height);
-            }
-            else if (generateDepthBuffer) {
-                depthStencilBuffer = gl.createRenderbuffer();
-                gl.bindRenderbuffer(gl.RENDERBUFFER, depthStencilBuffer);
-                gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height);
-            }
-
             // Create the framebuffer
             // Create the framebuffer
             var framebuffer = gl.createFramebuffer();
             var framebuffer = gl.createFramebuffer();
             this.bindUnboundFramebuffer(framebuffer);
             this.bindUnboundFramebuffer(framebuffer);
-
-            // Manage attachments
-            if (generateStencilBuffer) {
-                gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer);
-            }
-            else if (generateDepthBuffer) {
-                gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer);
-            }
             gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
             gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
 
 
+            texture._depthStencilBuffer = this._setupFramebufferDepthAttachments(generateStencilBuffer, generateDepthBuffer, width, height);
+
             if (generateMipMaps) {
             if (generateMipMaps) {
                 this._gl.generateMipmap(this._gl.TEXTURE_2D);
                 this._gl.generateMipmap(this._gl.TEXTURE_2D);
             }
             }
@@ -2504,9 +2494,6 @@
             this.bindUnboundFramebuffer(null);
             this.bindUnboundFramebuffer(null);
 
 
             texture._framebuffer = framebuffer;
             texture._framebuffer = framebuffer;
-            if (generateDepthBuffer) {
-                texture._depthBuffer = depthStencilBuffer;
-            }
             texture._baseWidth = width;
             texture._baseWidth = width;
             texture._baseHeight = height;
             texture._baseHeight = height;
             texture._width = width;
             texture._width = width;
@@ -2516,6 +2503,8 @@
             texture.references = 1;
             texture.references = 1;
             texture.samplingMode = samplingMode;
             texture.samplingMode = samplingMode;
             texture.type = type;
             texture.type = type;
+            texture._generateDepthBuffer = generateDepthBuffer;
+            texture._generateStencilBuffer = generateStencilBuffer;
 
 
             this.resetTextureCache();
             this.resetTextureCache();
 
 
@@ -2524,6 +2513,83 @@
             return texture;
             return texture;
         }
         }
 
 
+        private _setupFramebufferDepthAttachments(generateStencilBuffer: boolean, generateDepthBuffer: boolean, width: number, height: number, samples = 1): WebGLRenderbuffer {
+            var depthStencilBuffer: WebGLRenderbuffer = null;
+            var gl = this._gl;
+
+            // Create the depth/stencil buffer
+            if (generateStencilBuffer) {
+                depthStencilBuffer = gl.createRenderbuffer();
+                gl.bindRenderbuffer(gl.RENDERBUFFER, depthStencilBuffer);
+
+                if (samples > 1) {
+                    gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples, gl.DEPTH_STENCIL, width, height);
+                } else {
+                    gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height);
+                }
+
+                gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer);
+            }
+            else if (generateDepthBuffer) {
+                depthStencilBuffer = gl.createRenderbuffer();
+                gl.bindRenderbuffer(gl.RENDERBUFFER, depthStencilBuffer);
+
+                if (samples > 1) {
+                    gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples, gl.DEPTH_COMPONENT16, width, height);
+                } else {
+                    gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height);
+                }
+
+                gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer);
+            }
+
+            return depthStencilBuffer;
+        }
+
+        public updateRenderTargetTextureSampleCount(texture: WebGLTexture, samples: number) : number {
+            if (this.webGLVersion < 2) {
+                return 1;
+            }
+            var gl = this._gl;
+
+            samples = Math.min(samples, gl.getParameter(gl.MAX_SAMPLES));
+
+            // Dispose previous render buffers
+            if (texture._depthStencilBuffer) {
+                gl.deleteRenderbuffer(texture._depthStencilBuffer);
+            }
+
+            if (texture._MSAAFramebuffer) {
+                gl.deleteFramebuffer(texture._MSAAFramebuffer);
+            }
+
+            if (texture._MSAARenderBuffer) {
+                gl.deleteRenderbuffer(texture._MSAARenderBuffer);
+            }
+
+            if (samples > 1) {
+                texture._MSAAFramebuffer = gl.createFramebuffer();
+                this.bindUnboundFramebuffer(texture._MSAAFramebuffer);
+
+                var colorRenderbuffer = gl.createRenderbuffer();
+                gl.bindRenderbuffer(gl.RENDERBUFFER, colorRenderbuffer);
+                gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples, gl.RGBA8, texture._width, texture._height);
+
+                gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorRenderbuffer);
+
+                texture._MSAARenderBuffer = colorRenderbuffer;
+            } else {
+                this.bindUnboundFramebuffer(texture._framebuffer);
+            }
+
+            texture._depthStencilBuffer = this._setupFramebufferDepthAttachments(texture._generateStencilBuffer, texture._generateDepthBuffer, texture._width, texture._height, samples);
+
+            gl.bindRenderbuffer(gl.RENDERBUFFER, null);
+            this.bindUnboundFramebuffer(null);
+
+            return samples;
+        }
+
         public createRenderTargetCubeTexture(size: number, options?: any): WebGLTexture {
         public createRenderTargetCubeTexture(size: number, options?: any): WebGLTexture {
             var gl = this._gl;
             var gl = this._gl;
 
 
@@ -2563,32 +2629,11 @@
             gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
             gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
             gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
             gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
 
 
-            // Create the depth buffer
-            var depthStencilBuffer: WebGLRenderbuffer;
-
-            // Create the depth/stencil buffer
-            if (generateStencilBuffer) {
-                depthStencilBuffer = gl.createRenderbuffer();
-                gl.bindRenderbuffer(gl.RENDERBUFFER, depthStencilBuffer);
-                gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, size, size);
-            }
-            else if (generateDepthBuffer) {
-                depthStencilBuffer = gl.createRenderbuffer();
-                gl.bindRenderbuffer(gl.RENDERBUFFER, depthStencilBuffer);
-                gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, size, size);
-            }
-
             // Create the framebuffer
             // Create the framebuffer
             var framebuffer = gl.createFramebuffer();
             var framebuffer = gl.createFramebuffer();
             this.bindUnboundFramebuffer(framebuffer);
             this.bindUnboundFramebuffer(framebuffer);
 
 
-            // Manage attachments
-            if (generateStencilBuffer) {
-                gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer);
-            }
-            else if (generateDepthBuffer) {
-                gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer);
-            }
+            texture._depthStencilBuffer = this._setupFramebufferDepthAttachments(generateStencilBuffer, generateDepthBuffer, size, size);
 
 
             // Mipmaps
             // Mipmaps
             if (texture.generateMipMaps) {
             if (texture.generateMipMaps) {
@@ -2602,9 +2647,6 @@
             this.bindUnboundFramebuffer(null);
             this.bindUnboundFramebuffer(null);
 
 
             texture._framebuffer = framebuffer;
             texture._framebuffer = framebuffer;
-            if (generateDepthBuffer) {
-                texture._depthBuffer = depthStencilBuffer;
-            }
             texture._width = size;
             texture._width = size;
             texture._height = size;
             texture._height = size;
             texture.isReady = true;
             texture.isReady = true;
@@ -2918,8 +2960,16 @@
                 gl.deleteFramebuffer(texture._framebuffer);
                 gl.deleteFramebuffer(texture._framebuffer);
             }
             }
 
 
-            if (texture._depthBuffer) {
-                gl.deleteRenderbuffer(texture._depthBuffer);
+            if (texture._depthStencilBuffer) {
+                gl.deleteRenderbuffer(texture._depthStencilBuffer);
+            }
+
+            if (texture._MSAAFramebuffer) {
+                gl.deleteFramebuffer(texture._MSAAFramebuffer);
+            }
+
+            if (texture._MSAARenderBuffer) {
+                gl.deleteRenderbuffer(texture._MSAARenderBuffer);
             }
             }
 
 
             gl.deleteTexture(texture);
             gl.deleteTexture(texture);

+ 13 - 1
src/babylon.mixins.ts

@@ -39,6 +39,14 @@ interface WebGLRenderingContext {
     createVertexArray(): any;
     createVertexArray(): any;
     bindVertexArray(vao: WebGLVertexArrayObject): void;
     bindVertexArray(vao: WebGLVertexArrayObject): void;
     deleteVertexArray(vao: WebGLVertexArrayObject): void;
     deleteVertexArray(vao: WebGLVertexArrayObject): void;
+
+    blitFramebuffer(srcX0 : number, srcY0 : number, srcX1 : number, srcY1 : number, dstX0 : number, dstY0 : number, dstX1 : number, dstY1 : number, mask : number, filter : number) : void;
+    renderbufferStorageMultisample(target : number, samples : number, internalformat : number, width : number, height : number) : void;
+
+    MAX_SAMPLES: number;
+    RGBA8: number;
+    READ_FRAMEBUFFER : number;
+    DRAW_FRAMEBUFFER : number;
 }
 }
 
 
 interface HTMLURL {
 interface HTMLURL {
@@ -91,11 +99,15 @@ interface WebGLTexture {
     _workingCanvas: HTMLCanvasElement;
     _workingCanvas: HTMLCanvasElement;
     _workingContext: CanvasRenderingContext2D;
     _workingContext: CanvasRenderingContext2D;
     _framebuffer: WebGLFramebuffer;
     _framebuffer: WebGLFramebuffer;
-    _depthBuffer: WebGLRenderbuffer;
+    _depthStencilBuffer: WebGLRenderbuffer;
+    _MSAAFramebuffer: WebGLFramebuffer;
+    _MSAARenderBuffer: WebGLRenderbuffer;
     _cachedCoordinatesMode: number;
     _cachedCoordinatesMode: number;
     _cachedWrapU: number;
     _cachedWrapU: number;
     _cachedWrapV: number;
     _cachedWrapV: number;
     _isDisabled: boolean;
     _isDisabled: boolean;
+    _generateStencilBuffer: boolean;
+    _generateDepthBuffer: boolean;
 }
 }
 
 
 interface WebGLBuffer {
 interface WebGLBuffer {