Kaynağa Gözat

Merge remote-tracking branch 'BabylonJS/master'

MackeyK24 8 yıl önce
ebeveyn
işleme
7d5e2007b5
33 değiştirilmiş dosya ile 4995 ekleme ve 4062 silme
  1. 0 10
      Exporters/Blender/zip_media.xml
  2. 2 2
      Playground/frame.js
  3. 10 1
      Tools/Gulp/gulpfile.js
  4. 2 1
      Tools/Gulp/package.json
  5. 5 0
      Tools/Gulp/readme.md
  6. 1 0
      assets/meshes/Cat.babylon
  7. 21 4
      canvas2D/src/Engine/babylon.canvas2d.ts
  8. 297 24
      canvas2D/src/Engine/babylon.text2d.ts
  9. 23 23
      dist/preview release/babylon.core.js
  10. 3606 3601
      dist/preview release/babylon.d.ts
  11. 27 27
      dist/preview release/babylon.js
  12. 228 157
      dist/preview release/babylon.max.js
  13. 27 27
      dist/preview release/babylon.noworker.js
  14. 49 1
      dist/preview release/canvas2D/babylon.canvas2d.d.ts
  15. 315 50
      dist/preview release/canvas2D/babylon.canvas2d.js
  16. 8 8
      dist/preview release/canvas2D/babylon.canvas2d.min.js
  17. 4 4
      dist/preview release/inspector/babylon.inspector.bundle.js
  18. 31 0
      dist/preview release/inspector/babylon.inspector.css
  19. 23 0
      dist/preview release/inspector/babylon.inspector.d.ts
  20. 142 0
      dist/preview release/inspector/babylon.inspector.js
  21. 3 3
      dist/preview release/inspector/babylon.inspector.min.js
  22. 17 4
      dist/preview release/what's new.md
  23. 9 5
      src/Cameras/babylon.camera.ts
  24. 44 34
      src/Culling/babylon.ray.ts
  25. 1 1
      src/Math/babylon.math.ts
  26. 51 15
      src/Mesh/babylon.geometry.ts
  27. 25 23
      src/Mesh/babylon.groundMesh.ts
  28. 13 7
      src/Mesh/babylon.mesh.ts
  29. 1 0
      src/Mesh/babylon.meshBuilder.ts
  30. 3 4
      src/Particles/babylon.solidParticleSystem.ts
  31. 1 1
      src/Shaders/ShadersInclude/fogVertex.fx
  32. 1 1
      src/Shaders/sprites.vertex.fx
  33. 5 24
      src/babylon.engine.ts

+ 0 - 10
Exporters/Blender/zip_media.xml

@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project name="zipper">
-	<property name="version" value="5.2"/>
-	
-	<!-- this target assumes it is run from Babylon.js/Exporters/Blender directory.  -->
-    <target name="make-zip">
-    	<zip destfile="Blender2Babylon-${version}.zip" basedir="src" level="9"></zip>
-    </target>
-
-</project>

+ 2 - 2
Playground/frame.js

@@ -1,5 +1,5 @@
 (function () {
 (function () {
-    var snippetUrl = "http://babylonjs-api.azurewebsites.net/api/snippet";
+    var snippetUrl = "//babylonjs-api.azurewebsites.net/api/snippet";
     var currentSnippetToken;
     var currentSnippetToken;
     var engine;
     var engine;
     var fpsLabel = document.getElementById("fpsLabel");
     var fpsLabel = document.getElementById("fpsLabel");
@@ -149,7 +149,7 @@
                 xmlHttp.open("GET", snippetUrl + "/" + hash.replace("#", "/"));
                 xmlHttp.open("GET", snippetUrl + "/" + hash.replace("#", "/"));
                 xmlHttp.send();
                 xmlHttp.send();
 
 
-                document.getElementById("link").href = "http://www.babylonjs-playground.com/#" + hash;
+                document.getElementById("link").href = "//www.babylonjs-playground.com/#" + hash;
             } catch (e) {
             } catch (e) {
 
 
             }
             }

+ 10 - 1
Tools/Gulp/gulpfile.js

@@ -21,6 +21,8 @@ var path = require('path');
 var sass = require('gulp-sass');
 var sass = require('gulp-sass');
 var webpack = require('webpack-stream');
 var webpack = require('webpack-stream');
 
 
+var zip = require('gulp-zip');
+
 var config = require("./config.json");
 var config = require("./config.json");
 var customConfig = require("./custom.config.json");
 var customConfig = require("./custom.config.json");
 
 
@@ -380,4 +382,11 @@ gulp.task('webserver', function () {
  * Combine Webserver and Watch as long as vscode does not handle multi tasks.
  * Combine Webserver and Watch as long as vscode does not handle multi tasks.
  */
  */
 gulp.task('run', ['watch', 'webserver'], function () {
 gulp.task('run', ['watch', 'webserver'], function () {
-});
+});
+
+
+gulp.task("zip-blender" , function() {
+    return gulp.src('../../Exporters/Blender/src/**')
+    .pipe(zip('Blender2Babylon-5.2.zip'))
+    .pipe(gulp.dest('../../Exporters/Blender'));
+});

+ 2 - 1
Tools/Gulp/package.json

@@ -31,7 +31,8 @@
     "css-loader": "^0.25.0",
     "css-loader": "^0.25.0",
     "style-loader": "^0.13.1",
     "style-loader": "^0.13.1",
     "exports-loader": "^0.6.3",
     "exports-loader": "^0.6.3",
-    "imports-loader": "^0.7.0"
+    "imports-loader": "^0.7.0",
+    "gulp-zip": "~3.2.0"
   },
   },
   "scripts": {
   "scripts": {
     "install": "npm --prefix ../../Playground/ install ../../Playground/ && gulp typescript-compile && gulp typescript-libraries && gulp deployLocalDev"
     "install": "npm --prefix ../../Playground/ install ../../Playground/ && gulp typescript-compile && gulp typescript-libraries && gulp deployLocalDev"

+ 5 - 0
Tools/Gulp/readme.md

@@ -89,3 +89,8 @@ Be aware that all js files content will be overwritten.
 ### Compile all the typscript and the library
 ### Compile all the typscript and the library
 ```
 ```
 gulp typescript-all
 gulp typescript-all
+```
+### Zip individual Blender python files for distribute-able
+```
+gulp zip-blender
+```

Dosya farkı çok büyük olduğundan ihmal edildi
+ 1 - 0
assets/meshes/Cat.babylon


+ 21 - 4
canvas2D/src/Engine/babylon.canvas2d.ts

@@ -344,7 +344,7 @@
 
 
         /**
         /**
          * If you set your own WorldSpaceNode to display the Canvas2D you have to provide your own implementation of this method which computes the local position in the Canvas based on the given 3D World one.
          * If you set your own WorldSpaceNode to display the Canvas2D you have to provide your own implementation of this method which computes the local position in the Canvas based on the given 3D World one.
-         * Beware that you have to take under consideration the origin in your calculations! Good luck!
+         * Beware that you have to take under consideration the origin and unitScaleFactor in your calculations! Good luck!
          */
          */
         public worldSpaceToNodeLocal = (worldPos: Vector3): Vector2 => {
         public worldSpaceToNodeLocal = (worldPos: Vector3): Vector2 => {
             let node = this._worldSpaceNode;
             let node = this._worldSpaceNode;
@@ -354,11 +354,14 @@
 
 
             let mtx = node.getWorldMatrix().clone();
             let mtx = node.getWorldMatrix().clone();
             mtx.invert();
             mtx.invert();
+            let usf = this.unitScaleFactor;
             let v = Vector3.TransformCoordinates(worldPos, mtx);
             let v = Vector3.TransformCoordinates(worldPos, mtx);
             let res = new Vector2(v.x, v.y);
             let res = new Vector2(v.x, v.y);
             let size = this.actualSize;
             let size = this.actualSize;
-            res.x += size.width * 0.5;  // res is centered, make it relative to bottom/left
-            res.y += size.height * 0.5;
+            res.x += (size.width/usf) * 0.5;  // res is centered, make it relative to bottom/left
+            res.y += (size.height/usf) * 0.5;
+            res.x *= usf; // multiply by the unitScaleFactor, which defines if the canvas is nth time bigger than the original world plane
+            res.y *= usf;
             return res;
             return res;
         }
         }
 
 
@@ -599,10 +602,14 @@
 
 
         // Based on the previousIntersectionList and the actualInstersectionList we can determined which primitives are being hover state or loosing it
         // Based on the previousIntersectionList and the actualInstersectionList we can determined which primitives are being hover state or loosing it
         private _updateOverStatus(force: boolean) {
         private _updateOverStatus(force: boolean) {
-            if ((!force && (this.scene.getRenderId() === this._hoverStatusRenderId)) || !this._previousIntersectionList || !this._actualIntersectionList) {
+            if ((!force && (this.scene.getRenderId() === this._hoverStatusRenderId)) || !this._actualIntersectionList) {
                 return;
                 return;
             }
             }
 
 
+            if (this._previousIntersectionList == null) {
+                this._previousIntersectionList = [];
+            }
+
             // Detect a change of over
             // Detect a change of over
             let prevPrim = this._previousOverPrimitive ? this._previousOverPrimitive.prim : null;
             let prevPrim = this._previousOverPrimitive ? this._previousOverPrimitive.prim : null;
             let actualPrim = this._actualOverPrimitive ? this._actualOverPrimitive.prim : null;
             let actualPrim = this._actualOverPrimitive ? this._actualOverPrimitive.prim : null;
@@ -1061,6 +1068,10 @@
             return this.__engineData;
             return this.__engineData;
         }
         }
 
 
+        public get unitScaleFactor(): number {
+            return this._unitScaleFactor;
+        }
+
         public createCanvasProfileInfoCanvas(): Canvas2D {
         public createCanvasProfileInfoCanvas(): Canvas2D {
             if (this._profilingCanvas) {
             if (this._profilingCanvas) {
                 return this._profilingCanvas;
                 return this._profilingCanvas;
@@ -1227,6 +1238,7 @@
         private _beforeRenderObserver: Observer<Scene>;
         private _beforeRenderObserver: Observer<Scene>;
         private _afterRenderObserver: Observer<Scene>;
         private _afterRenderObserver: Observer<Scene>;
         private _supprtInstancedArray: boolean;
         private _supprtInstancedArray: boolean;
+        protected _unitScaleFactor: number;
         private _trackedGroups: Array<Group2D>;
         private _trackedGroups: Array<Group2D>;
         protected _trackNode: Node;
         protected _trackNode: Node;
         protected _trackNodeOffset :Vector3;
         protected _trackNodeOffset :Vector3;
@@ -1811,6 +1823,8 @@
             super(scene, settings);
             super(scene, settings);
             Prim2DBase._isCanvasInit = false;
             Prim2DBase._isCanvasInit = false;
 
 
+            this._unitScaleFactor = (settings.unitScaleFactor != null) ? settings.unitScaleFactor : 1;
+
             this._renderableData._useMipMap = true;
             this._renderableData._useMipMap = true;
             this._renderableData._anisotropicLevel = 8;
             this._renderableData._anisotropicLevel = 8;
 
 
@@ -1857,6 +1871,9 @@
                 mtl.specularColor = new Color3(0, 0, 0);
                 mtl.specularColor = new Color3(0, 0, 0);
                 mtl.disableLighting = true;
                 mtl.disableLighting = true;
                 mtl.useAlphaFromDiffuseTexture = true;
                 mtl.useAlphaFromDiffuseTexture = true;
+                if (settings && settings.sideOrientation) {
+                    mtl.backFaceCulling = (settings.sideOrientation === Mesh.DEFAULTSIDE || settings.sideOrientation === Mesh.FRONTSIDE);
+                }
                 plane.position = settings && settings.worldPosition || Vector3.Zero();
                 plane.position = settings && settings.worldPosition || Vector3.Zero();
                 plane.rotationQuaternion = settings && settings.worldRotation || Quaternion.Identity();
                 plane.rotationQuaternion = settings && settings.worldRotation || Quaternion.Identity();
                 plane.material = mtl;
                 plane.material = mtl;

+ 297 - 24
canvas2D/src/Engine/babylon.text2d.ts

@@ -148,6 +148,37 @@
         public static fontSuperSampleProperty: Prim2DPropInfo;
         public static fontSuperSampleProperty: Prim2DPropInfo;
         public static fontSignedDistanceFieldProperty: Prim2DPropInfo;
         public static fontSignedDistanceFieldProperty: Prim2DPropInfo;
 
 
+        /**
+         * Alignment is made relative to the left edge of the Content Area. Valid for horizontal alignment only.
+         */
+        public static get AlignLeft(): number { return Text2D._AlignLeft; }
+
+        /**
+         * Alignment is made relative to the top edge of the Content Area. Valid for vertical alignment only.
+         */
+        public static get AlignTop(): number { return Text2D._AlignTop; }
+
+        /**
+         * Alignment is made relative to the right edge of the Content Area. Valid for horizontal alignment only.
+         */
+        public static get AlignRight(): number { return Text2D._AlignRight; }
+
+        /**
+         * Alignment is made relative to the bottom edge of the Content Area. Valid for vertical alignment only.
+         */
+        public static get AlignBottom(): number { return Text2D._AlignBottom; }
+
+        /**
+         * Alignment is made to center the text from equal distance to the opposite edges of the Content Area
+         */
+        public static get AlignCenter(): number { return Text2D._AlignCenter; }
+
+        private static _AlignLeft = 1;
+        private static _AlignTop = 1;   // Same as left
+        private static _AlignRight = 2;
+        private static _AlignBottom = 2;   // Same as right
+        private static _AlignCenter = 3;
+
         @modelLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 1, pi => Text2D.fontProperty = pi, false, true)
         @modelLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 1, pi => Text2D.fontProperty = pi, false, true)
         /**
         /**
          * Get/set the font name to use, using HTML CSS notation.
          * Get/set the font name to use, using HTML CSS notation.
@@ -304,6 +335,18 @@
         }
         }
 
 
         /**
         /**
+         * You can get/set the text alignment through this property
+         */
+        public get textAlignment(): string {
+            return this._textAlignment;
+        }
+
+        public set textAlignment(value: string) {
+            this._textAlignment = value;
+            this._setTextAlignmentfromString(value);
+        }
+
+        /**
          * Create a Text primitive
          * Create a Text primitive
          * @param text the text to display
          * @param text the text to display
          * @param settings a combination of settings, possible ones are
          * @param settings a combination of settings, possible ones are
@@ -340,6 +383,10 @@
          * - paddingRight: right padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
          * - paddingRight: right padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
          * - paddingBottom: bottom padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
          * - paddingBottom: bottom padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
          * - padding: top, left, right and bottom padding formatted as a single string (see PrimitiveThickness.fromString)
          * - padding: top, left, right and bottom padding formatted as a single string (see PrimitiveThickness.fromString)
+         * - textAlignmentH: align text horizontally (Text2D.AlignLeft, Text2D.AlignCenter, Text2D.AlignRight)
+         * - textAlignmentV: align text vertically (Text2D.AlignTop, Text2D.AlignCenter, Text2D.AlignBottom)
+         * - textAlignment: a string defining the text alignment, text can be: [<h:|horizontal:><left|right|center>], [<v:|vertical:><top|bottom|center>]
+         * - wordWrap: if true the text will wrap inside content area
          */
          */
         constructor(text: string, settings?: {
         constructor(text: string, settings?: {
 
 
@@ -381,6 +428,10 @@
             paddingRight            ?: number | string,
             paddingRight            ?: number | string,
             paddingBottom           ?: number | string,
             paddingBottom           ?: number | string,
             padding                 ?: string,
             padding                 ?: string,
+            textAlignmentH          ?: number,
+            textAlignmentV          ?: number,
+            textAlignment           ?: string,
+            wordWrap                ?: boolean
         }) {
         }) {
 
 
             if (!settings) {
             if (!settings) {
@@ -404,7 +455,11 @@
             this._textSize           = null;
             this._textSize           = null;
             this.text                = text;
             this.text                = text;
             this.size                = (settings.size==null) ? null : settings.size;
             this.size                = (settings.size==null) ? null : settings.size;
-
+            this.textAlignmentH      = (settings.textAlignmentH==null) ? Text2D.AlignLeft : settings.textAlignmentH;
+            this.textAlignmentV      = (settings.textAlignmentV==null) ? Text2D.AlignTop : settings.textAlignmentV;
+            this.textAlignment       = (settings.textAlignment==null) ? "" : settings.textAlignment;
+            this._wordWrap           = (settings.wordWrap==null) ? false : settings.wordWrap;
+            
             this._updateRenderMode();
             this._updateRenderMode();
         }
         }
 
 
@@ -490,56 +545,206 @@
             }
             }
 
 
             if (part.id === Text2D.TEXT2D_MAINPARTID) {
             if (part.id === Text2D.TEXT2D_MAINPARTID) {
+
                 let d = <Text2DInstanceData>part;
                 let d = <Text2DInstanceData>part;
                 let texture = this.fontTexture;
                 let texture = this.fontTexture;
                 let superSampleFactor = texture.isSuperSampled ? 0.5 : 1;
                 let superSampleFactor = texture.isSuperSampled ? 0.5 : 1;
                 let ts = texture.getSize();
                 let ts = texture.getSize();
                 let offset = Vector2.Zero();
                 let offset = Vector2.Zero();
                 let lh = this.fontTexture.lineHeight;
                 let lh = this.fontTexture.lineHeight;
-                offset.y = ((this.textSize.height/lh)-1) * lh;  // Origin is bottom, not top, so the offset is starting with a y that is the top location of the text
-                let charxpos = 0;
+
                 d.dataElementCount = this._charCount;
                 d.dataElementCount = this._charCount;
                 d.curElement = 0;
                 d.curElement = 0;
-                for (let char of this.text) {
+
+                let lineLengths = [];
+                let charWidths = [];
+                let charsPerLine = [];
+                let numCharsCurrenLine = 0;
+                let contentAreaWidth = this.contentArea.width;
+                let contentAreaHeight = this.contentArea.height;
+                let numCharsCurrentWord = 0;
+                let widthCurrentWord = 0;
+                let numWordsPerLine = 0;
+                let text = this.text;
+                let tabWidth = this._tabulationSize * texture.spaceWidth;
+
+                for (let i = 0; i < text.length; i++) {
+                    let char = text[i];
+                    numCharsCurrenLine++;
+                   
+                    charWidths[i] = 0;
 
 
                     // Line feed
                     // Line feed
-                    if (char === "\n") {
+                    if (this._isWhiteSpaceCharVert(char)) {
+                        lineLengths.push(offset.x);
+                        charsPerLine.push(numCharsCurrenLine - 1);
+                        numCharsCurrenLine = 1;
                         offset.x = 0;
                         offset.x = 0;
-                        offset.y -= texture.lineHeight;
+
+                        if (widthCurrentWord > 0) {
+                            numWordsPerLine++;
+                        }
+
+                        numWordsPerLine = 0;
+                        numCharsCurrentWord = 0;
+                        widthCurrentWord = 0;
+                        
+                        continue;
                     }
                     }
 
 
-                    // Tabulation ?
+                    let ci = texture.getChar(char);
+                    let charWidth = 0;
+
                     if (char === "\t") {
                     if (char === "\t") {
-                        let nextPos = charxpos + this._tabulationSize;
-                        nextPos = nextPos - (nextPos % this._tabulationSize);
+                        charWidth = tabWidth;
+                    }else{
+                        charWidth = ci.charWidth;
+                    }
 
 
-                        offset.x += (nextPos - charxpos) * texture.spaceWidth;
-                        charxpos = nextPos;
-                        continue;
+                    offset.x += charWidth;
+                    charWidths[i] = charWidth;
+
+                    if (this._isWhiteSpaceCharHoriz(char)) {
+                        if (widthCurrentWord > 0) {
+                            numWordsPerLine++;
+                        }
+                        numCharsCurrentWord = 0;
+                        widthCurrentWord = 0;
+                    }else {
+                        widthCurrentWord += ci.charWidth;
+                        numCharsCurrentWord++;
                     }
                     }
 
 
-                    if (char < " ") {
-                        continue;
+                    if (this._wordWrap && numWordsPerLine > 0 && offset.x > contentAreaWidth) {
+                        lineLengths.push(offset.x - widthCurrentWord);
+                        numCharsCurrenLine -= numCharsCurrentWord;
+                        let j = i - numCharsCurrentWord;
+                        //skip white space at the end of this line
+                        while (this._isWhiteSpaceCharHoriz(text[j])) {
+                            lineLengths[lineLengths.length - 1] -= charWidths[j];
+                            j--;
+                        }
+
+                        charsPerLine.push(numCharsCurrenLine);
+
+                        if(this._isWhiteSpaceCharHoriz(text[i])){
+                            
+                            //skip white space at the beginning of next line
+                            let numSpaces = 0;
+                            while (this._isWhiteSpaceCharHoriz(text[i+numSpaces])) {
+                                numSpaces++;
+                                charWidths[i+numSpaces] = 0;
+                            }
+                           
+                            i += numSpaces-1;
+                            
+                            offset.x = 0;
+                            numCharsCurrenLine = numSpaces-1;
+                        }else{
+                            numCharsCurrenLine = numCharsCurrentWord;
+                            offset.x = widthCurrentWord;
+                        }
+                        
+                        numWordsPerLine = 0;
                     }
                     }
+                }
+                lineLengths.push(offset.x);
+                charsPerLine.push(numCharsCurrenLine);
+
+                //skip white space at the end
+                let i = text.length - 1;
+                while (this._isWhiteSpaceCharHoriz(text[i])) {
+                    lineLengths[lineLengths.length - 1] -= charWidths[i];
+                    i--;
+                }
 
 
-                    this.updateInstanceDataPart(d, offset);
+                let charNum = 0;
+                let maxLineLen = 0;
+                let alignH = this.textAlignmentH;
+                let alignV = this.textAlignmentV;
 
 
-                    let ci = texture.getChar(char);
-                    offset.x += ci.charWidth;
+                offset.x = 0;
 
 
-                    d.topLeftUV = ci.topLeftUV;
-                    let suv = ci.bottomRightUV.subtract(ci.topLeftUV);
-                    d.sizeUV = suv;
-                    d.textureSize = new Vector2(ts.width, ts.height);
-                    d.color = this.defaultFontColor;
-                    d.superSampleFactor = superSampleFactor;
+                if (alignH == Text2D.AlignRight || alignH == Text2D.AlignCenter) {
+                    for (let i = 0; i < lineLengths.length; i++) {
+                        if (lineLengths[i] > maxLineLen) {
+                            maxLineLen = lineLengths[i];
+                        }
+                    }
+                }
 
 
-                    ++d.curElement;
+                let textHeight = lineLengths.length * lh;
+                let offsetX = this.padding.leftPixels;
+                
+                if (alignH == Text2D.AlignRight) {
+                    offsetX += contentAreaWidth - maxLineLen;
+                } else if (alignH == Text2D.AlignCenter) {
+                    offsetX += (contentAreaWidth - maxLineLen) * .5;
                 }
                 }
+
+                offset.x += offsetX;
+
+                offset.y += contentAreaHeight + textHeight - lh;
+                offset.y += this.padding.bottomPixels;
+
+                if (alignV == Text2D.AlignBottom) {
+                    offset.y -= contentAreaHeight;
+                }else if (alignV == Text2D.AlignCenter) {
+                    offset.y -= (contentAreaHeight - textHeight) * .5 + lineLengths.length * lh;
+                }else {
+                    offset.y -= lineLengths.length * lh;
+                }
+
+                for (let i = 0; i < lineLengths.length; i++) {
+                    let numChars = charsPerLine[i];
+                    let lineLength = lineLengths[i];
+
+                    if (alignH == Text2D.AlignRight) {
+                        offset.x += maxLineLen - lineLength;
+                    }else if (alignH == Text2D.AlignCenter) {
+                        offset.x += (maxLineLen - lineLength) * .5;
+                    }
+
+                    for (let j = 0; j < numChars; j++) {
+                        let char = text[charNum];
+                        let charWidth = charWidths[charNum];
+
+                        this.updateInstanceDataPart(d, offset);
+                        offset.x += charWidth;
+
+                        if (!this._isWhiteSpaceCharHoriz(char)) {
+                            let ci = texture.getChar(char);
+                            d.topLeftUV = ci.topLeftUV;
+                            let suv = ci.bottomRightUV.subtract(ci.topLeftUV);
+                            d.sizeUV = suv;
+                            d.textureSize = new BABYLON.Vector2(ts.width, ts.height);
+                            d.color = this.defaultFontColor;
+                            d.superSampleFactor = superSampleFactor;
+                            ++d.curElement;
+                        }
+                        charNum++;
+                    }
+
+                    offset.x = offsetX;
+                    offset.y -= texture.lineHeight;
+                }
+
             }
             }
             return true;
             return true;
         }
         }
 
 
+        private _isWhiteSpaceCharHoriz(char): boolean {
+            if(char === " " || char === "\t"){
+                return true;
+            }
+        }
+
+        private _isWhiteSpaceCharVert(char): boolean {
+            if(char === "\n" || char === "\r"){
+                return true;
+            }
+        }
+
         private _updateCharCount() {
         private _updateCharCount() {
             let count = 0;
             let count = 0;
             for (let char of this._text) {
             for (let char of this._text) {
@@ -551,6 +756,68 @@
             this._charCount = count;
             this._charCount = count;
         }
         }
 
 
+        private _setTextAlignmentfromString(value: string) {
+            let m = value.trim().split(",");
+
+            for (let v of m) {
+                v = v.toLocaleLowerCase().trim();
+
+                // Horizontal
+                let i = v.indexOf("h:");
+                if (i === -1) {
+                    i = v.indexOf("horizontal:");
+                }
+
+                if (i !== -1) {
+                    v = v.substr(v.indexOf(":") + 1);
+                    this._setTextAlignmentHorizontal(v);
+                    continue;
+                }
+
+                // Vertical
+                i = v.indexOf("v:");
+                if (i === -1) {
+                    i = v.indexOf("vertical:");
+                }
+
+                if (i !== -1) {
+                    v = v.substr(v.indexOf(":") + 1);
+                    this._setTextAlignmentVertical(v);
+                    continue;
+                }
+            }
+        }
+
+        private _setTextAlignmentHorizontal(text: string) {
+            let v = text.trim().toLocaleLowerCase();
+            switch (v) {
+                case "left":
+                    this.textAlignmentH = Text2D.AlignLeft;
+                    return;
+                case "right":
+                    this.textAlignmentH = Text2D.AlignRight;
+                    return;
+                case "center":
+                    this.textAlignmentH = Text2D.AlignCenter;
+                    return;
+            }
+        }
+
+        private _setTextAlignmentVertical(text: string) {
+            let v = text.trim().toLocaleLowerCase();
+            switch (v) {
+                case "top":
+                    this.textAlignmentV = Text2D.AlignTop;
+                    return;
+                case "bottom":
+                    this.textAlignmentV = Text2D.AlignBottom;
+                    return;
+                case "center":
+                    this.textAlignmentV = Text2D.AlignCenter;
+                    return;
+            }
+        }
+
         protected _useTextureAlpha(): boolean {
         protected _useTextureAlpha(): boolean {
             return this._fontSDF;
             return this._fontSDF;
         }
         }
@@ -568,5 +835,11 @@
         private _defaultFontColor: Color4;
         private _defaultFontColor: Color4;
         private _text: string;
         private _text: string;
         private _textSize: Size;
         private _textSize: Size;
+        private _wordWrap: boolean;
+        private _textAlignment: string;
+
+        public textAlignmentH: number;
+        public textAlignmentV: number;
+        
     }
     }
 }
 }

Dosya farkı çok büyük olduğundan ihmal edildi
+ 23 - 23
dist/preview release/babylon.core.js


Dosya farkı çok büyük olduğundan ihmal edildi
+ 3606 - 3601
dist/preview release/babylon.d.ts


Dosya farkı çok büyük olduğundan ihmal edildi
+ 27 - 27
dist/preview release/babylon.js


Dosya farkı çok büyük olduğundan ihmal edildi
+ 228 - 157
dist/preview release/babylon.max.js


Dosya farkı çok büyük olduğundan ihmal edildi
+ 27 - 27
dist/preview release/babylon.noworker.js


+ 49 - 1
dist/preview release/canvas2D/babylon.canvas2d.d.ts

@@ -3281,6 +3281,31 @@ declare module BABYLON {
         static sizeProperty: Prim2DPropInfo;
         static sizeProperty: Prim2DPropInfo;
         static fontSuperSampleProperty: Prim2DPropInfo;
         static fontSuperSampleProperty: Prim2DPropInfo;
         static fontSignedDistanceFieldProperty: Prim2DPropInfo;
         static fontSignedDistanceFieldProperty: Prim2DPropInfo;
+        /**
+         * Alignment is made relative to the left edge of the Content Area. Valid for horizontal alignment only.
+         */
+        static readonly AlignLeft: number;
+        /**
+         * Alignment is made relative to the top edge of the Content Area. Valid for vertical alignment only.
+         */
+        static readonly AlignTop: number;
+        /**
+         * Alignment is made relative to the right edge of the Content Area. Valid for horizontal alignment only.
+         */
+        static readonly AlignRight: number;
+        /**
+         * Alignment is made relative to the bottom edge of the Content Area. Valid for vertical alignment only.
+         */
+        static readonly AlignBottom: number;
+        /**
+         * Alignment is made to center the text from equal distance to the opposite edges of the Content Area
+         */
+        static readonly AlignCenter: number;
+        private static _AlignLeft;
+        private static _AlignTop;
+        private static _AlignRight;
+        private static _AlignBottom;
+        private static _AlignCenter;
         fontName: string;
         fontName: string;
         defaultFontColor: Color4;
         defaultFontColor: Color4;
         text: string;
         text: string;
@@ -3303,6 +3328,10 @@ declare module BABYLON {
         dispose(): boolean;
         dispose(): boolean;
         protected updateLevelBoundingInfo(): boolean;
         protected updateLevelBoundingInfo(): boolean;
         /**
         /**
+         * You can get/set the text alignment through this property
+         */
+        textAlignment: string;
+        /**
          * Create a Text primitive
          * Create a Text primitive
          * @param text the text to display
          * @param text the text to display
          * @param settings a combination of settings, possible ones are
          * @param settings a combination of settings, possible ones are
@@ -3339,6 +3368,10 @@ declare module BABYLON {
          * - paddingRight: right padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
          * - paddingRight: right padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
          * - paddingBottom: bottom padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
          * - paddingBottom: bottom padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
          * - padding: top, left, right and bottom padding formatted as a single string (see PrimitiveThickness.fromString)
          * - padding: top, left, right and bottom padding formatted as a single string (see PrimitiveThickness.fromString)
+         * - textAlignmentH: align text horizontally (Text2D.AlignLeft, Text2D.AlignCenter, Text2D.AlignRight)
+         * - textAlignmentV: align text vertically (Text2D.AlignTop, Text2D.AlignCenter, Text2D.AlignBottom)
+         * - textAlignment: a string defining the text alignment, text can be: [<h:|horizontal:><left|right|center>], [<v:|vertical:><top|bottom|center>]
+         * - wordWrap: if true the text will wrap inside content area
          */
          */
         constructor(text: string, settings?: {
         constructor(text: string, settings?: {
             parent?: Prim2DBase;
             parent?: Prim2DBase;
@@ -3379,6 +3412,10 @@ declare module BABYLON {
             paddingRight?: number | string;
             paddingRight?: number | string;
             paddingBottom?: number | string;
             paddingBottom?: number | string;
             padding?: string;
             padding?: string;
+            textAlignmentH?: number;
+            textAlignmentV?: number;
+            textAlignment?: string;
+            wordWrap?: boolean;
         });
         });
         protected levelIntersect(intersectInfo: IntersectInfo2D): boolean;
         protected levelIntersect(intersectInfo: IntersectInfo2D): boolean;
         protected createModelRenderCache(modelKey: string): ModelRenderCache;
         protected createModelRenderCache(modelKey: string): ModelRenderCache;
@@ -3388,7 +3425,12 @@ declare module BABYLON {
         protected afterRefreshForLayoutConstruction(part: InstanceDataBase, obj: any): void;
         protected afterRefreshForLayoutConstruction(part: InstanceDataBase, obj: any): void;
         protected getUsedShaderCategories(dataPart: InstanceDataBase): string[];
         protected getUsedShaderCategories(dataPart: InstanceDataBase): string[];
         protected refreshInstanceDataPart(part: InstanceDataBase): boolean;
         protected refreshInstanceDataPart(part: InstanceDataBase): boolean;
+        private _isWhiteSpaceCharHoriz(char);
+        private _isWhiteSpaceCharVert(char);
         private _updateCharCount();
         private _updateCharCount();
+        private _setTextAlignmentfromString(value);
+        private _setTextAlignmentHorizontal(text);
+        private _setTextAlignmentVertical(text);
         protected _useTextureAlpha(): boolean;
         protected _useTextureAlpha(): boolean;
         protected _shouldUseAlphaFromTexture(): boolean;
         protected _shouldUseAlphaFromTexture(): boolean;
         private _fontTexture;
         private _fontTexture;
@@ -3400,6 +3442,10 @@ declare module BABYLON {
         private _defaultFontColor;
         private _defaultFontColor;
         private _text;
         private _text;
         private _textSize;
         private _textSize;
+        private _wordWrap;
+        private _textAlignment;
+        textAlignmentH: number;
+        textAlignmentV: number;
     }
     }
 }
 }
 
 
@@ -3680,7 +3726,7 @@ declare module BABYLON {
         private _setupInteraction(enable);
         private _setupInteraction(enable);
         /**
         /**
          * If you set your own WorldSpaceNode to display the Canvas2D you have to provide your own implementation of this method which computes the local position in the Canvas based on the given 3D World one.
          * If you set your own WorldSpaceNode to display the Canvas2D you have to provide your own implementation of this method which computes the local position in the Canvas based on the given 3D World one.
-         * Beware that you have to take under consideration the origin in your calculations! Good luck!
+         * Beware that you have to take under consideration the origin and unitScaleFactor in your calculations! Good luck!
          */
          */
         worldSpaceToNodeLocal: (worldPos: Vector3) => Vector2;
         worldSpaceToNodeLocal: (worldPos: Vector3) => Vector2;
         /**
         /**
@@ -3795,6 +3841,7 @@ declare module BABYLON {
          * @returns {}
          * @returns {}
          */
          */
         readonly _engineData: Canvas2DEngineBoundData;
         readonly _engineData: Canvas2DEngineBoundData;
+        readonly unitScaleFactor: number;
         createCanvasProfileInfoCanvas(): Canvas2D;
         createCanvasProfileInfoCanvas(): Canvas2D;
         /**
         /**
          * Instanced Array will be create if there's at least this number of parts/prim that can fit into it
          * Instanced Array will be create if there's at least this number of parts/prim that can fit into it
@@ -3846,6 +3893,7 @@ declare module BABYLON {
         private _beforeRenderObserver;
         private _beforeRenderObserver;
         private _afterRenderObserver;
         private _afterRenderObserver;
         private _supprtInstancedArray;
         private _supprtInstancedArray;
+        protected _unitScaleFactor: number;
         private _trackedGroups;
         private _trackedGroups;
         protected _trackNode: Node;
         protected _trackNode: Node;
         protected _trackNodeOffset: Vector3;
         protected _trackNodeOffset: Vector3;

+ 315 - 50
dist/preview release/canvas2D/babylon.canvas2d.js

@@ -2084,7 +2084,7 @@ var BABYLON;
          * This layout must be used as a Singleton through the CanvasLayoutEngine.Singleton property.
          * This layout must be used as a Singleton through the CanvasLayoutEngine.Singleton property.
          */
          */
         function CanvasLayoutEngine() {
         function CanvasLayoutEngine() {
-            return _super.apply(this, arguments) || this;
+            return _super !== null && _super.apply(this, arguments) || this;
         }
         }
         // A very simple (no) layout computing...
         // A very simple (no) layout computing...
         // The Canvas and its direct children gets the Canvas' size as Layout Area
         // The Canvas and its direct children gets the Canvas' size as Layout Area
@@ -4872,7 +4872,7 @@ var BABYLON;
     var Prim2DBase = Prim2DBase_1 = (function (_super) {
     var Prim2DBase = Prim2DBase_1 = (function (_super) {
         __extends(Prim2DBase, _super);
         __extends(Prim2DBase, _super);
         function Prim2DBase(settings) {
         function Prim2DBase(settings) {
-            var _this;
+            var _this = this;
             // Avoid checking every time if the object exists
             // Avoid checking every time if the object exists
             if (settings == null) {
             if (settings == null) {
                 settings = {};
                 settings = {};
@@ -8536,7 +8536,7 @@ var BABYLON;
     var Shape2DInstanceData = (function (_super) {
     var Shape2DInstanceData = (function (_super) {
         __extends(Shape2DInstanceData, _super);
         __extends(Shape2DInstanceData, _super);
         function Shape2DInstanceData() {
         function Shape2DInstanceData() {
-            return _super.apply(this, arguments) || this;
+            return _super !== null && _super.apply(this, arguments) || this;
         }
         }
         Object.defineProperty(Shape2DInstanceData.prototype, "fillSolidColor", {
         Object.defineProperty(Shape2DInstanceData.prototype, "fillSolidColor", {
             // FILL ATTRIBUTES
             // FILL ATTRIBUTES
@@ -8706,7 +8706,7 @@ var BABYLON;
          * - padding: top, left, right and bottom padding formatted as a single string (see PrimitiveThickness.fromString)
          * - padding: top, left, right and bottom padding formatted as a single string (see PrimitiveThickness.fromString)
          */
          */
         function Group2D(settings) {
         function Group2D(settings) {
-            var _this;
+            var _this = this;
             if (settings == null) {
             if (settings == null) {
                 settings = {};
                 settings = {};
             }
             }
@@ -9831,7 +9831,7 @@ var BABYLON;
          * - padding: top, left, right and bottom padding formatted as a single string (see PrimitiveThickness.fromString)
          * - padding: top, left, right and bottom padding formatted as a single string (see PrimitiveThickness.fromString)
          */
          */
         function Rectangle2D(settings) {
         function Rectangle2D(settings) {
-            var _this;
+            var _this = this;
             // Avoid checking every time if the object exists
             // Avoid checking every time if the object exists
             if (settings == null) {
             if (settings == null) {
                 settings = {};
                 settings = {};
@@ -10294,7 +10294,7 @@ var BABYLON;
          * - padding: top, left, right and bottom padding formatted as a single string (see PrimitiveThickness.fromString)
          * - padding: top, left, right and bottom padding formatted as a single string (see PrimitiveThickness.fromString)
          */
          */
         function Ellipse2D(settings) {
         function Ellipse2D(settings) {
-            var _this;
+            var _this = this;
             // Avoid checking every time if the object exists
             // Avoid checking every time if the object exists
             if (settings == null) {
             if (settings == null) {
                 settings = {};
                 settings = {};
@@ -10474,7 +10474,7 @@ var BABYLON;
     var Sprite2DRenderCache = (function (_super) {
     var Sprite2DRenderCache = (function (_super) {
         __extends(Sprite2DRenderCache, _super);
         __extends(Sprite2DRenderCache, _super);
         function Sprite2DRenderCache() {
         function Sprite2DRenderCache() {
-            var _this = _super.apply(this, arguments) || this;
+            var _this = _super !== null && _super.apply(this, arguments) || this;
             _this.effectsReady = false;
             _this.effectsReady = false;
             _this.vb = null;
             _this.vb = null;
             _this.ib = null;
             _this.ib = null;
@@ -10591,7 +10591,7 @@ var BABYLON;
          * - padding: top, left, right and bottom padding formatted as a single string (see PrimitiveThickness.fromString)
          * - padding: top, left, right and bottom padding formatted as a single string (see PrimitiveThickness.fromString)
          */
          */
         function Sprite2D(texture, settings) {
         function Sprite2D(texture, settings) {
-            var _this;
+            var _this = this;
             if (!settings) {
             if (!settings) {
                 settings = {};
                 settings = {};
             }
             }
@@ -11244,7 +11244,7 @@ var BABYLON;
     var Text2DRenderCache = (function (_super) {
     var Text2DRenderCache = (function (_super) {
         __extends(Text2DRenderCache, _super);
         __extends(Text2DRenderCache, _super);
         function Text2DRenderCache() {
         function Text2DRenderCache() {
-            var _this = _super.apply(this, arguments) || this;
+            var _this = _super !== null && _super.apply(this, arguments) || this;
             _this.effectsReady = false;
             _this.effectsReady = false;
             _this.vb = null;
             _this.vb = null;
             _this.ib = null;
             _this.ib = null;
@@ -11430,9 +11430,13 @@ var BABYLON;
          * - paddingRight: right padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
          * - paddingRight: right padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
          * - paddingBottom: bottom padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
          * - paddingBottom: bottom padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
          * - padding: top, left, right and bottom padding formatted as a single string (see PrimitiveThickness.fromString)
          * - padding: top, left, right and bottom padding formatted as a single string (see PrimitiveThickness.fromString)
+         * - textAlignmentH: align text horizontally (Text2D.AlignLeft, Text2D.AlignCenter, Text2D.AlignRight)
+         * - textAlignmentV: align text vertically (Text2D.AlignTop, Text2D.AlignCenter, Text2D.AlignBottom)
+         * - textAlignment: a string defining the text alignment, text can be: [<h:|horizontal:><left|right|center>], [<v:|vertical:><top|bottom|center>]
+         * - wordWrap: if true the text will wrap inside content area
          */
          */
         function Text2D(text, settings) {
         function Text2D(text, settings) {
-            var _this;
+            var _this = this;
             if (!settings) {
             if (!settings) {
                 settings = {};
                 settings = {};
             }
             }
@@ -11453,9 +11457,53 @@ var BABYLON;
             _this._textSize = null;
             _this._textSize = null;
             _this.text = text;
             _this.text = text;
             _this.size = (settings.size == null) ? null : settings.size;
             _this.size = (settings.size == null) ? null : settings.size;
+            _this.textAlignmentH = (settings.textAlignmentH == null) ? Text2D_1.AlignLeft : settings.textAlignmentH;
+            _this.textAlignmentV = (settings.textAlignmentV == null) ? Text2D_1.AlignTop : settings.textAlignmentV;
+            _this.textAlignment = (settings.textAlignment == null) ? "" : settings.textAlignment;
+            _this._wordWrap = (settings.wordWrap == null) ? false : settings.wordWrap;
             _this._updateRenderMode();
             _this._updateRenderMode();
             return _this;
             return _this;
         }
         }
+        Object.defineProperty(Text2D, "AlignLeft", {
+            /**
+             * Alignment is made relative to the left edge of the Content Area. Valid for horizontal alignment only.
+             */
+            get: function () { return Text2D_1._AlignLeft; },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Text2D, "AlignTop", {
+            /**
+             * Alignment is made relative to the top edge of the Content Area. Valid for vertical alignment only.
+             */
+            get: function () { return Text2D_1._AlignTop; },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Text2D, "AlignRight", {
+            /**
+             * Alignment is made relative to the right edge of the Content Area. Valid for horizontal alignment only.
+             */
+            get: function () { return Text2D_1._AlignRight; },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Text2D, "AlignBottom", {
+            /**
+             * Alignment is made relative to the bottom edge of the Content Area. Valid for vertical alignment only.
+             */
+            get: function () { return Text2D_1._AlignBottom; },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Text2D, "AlignCenter", {
+            /**
+             * Alignment is made to center the text from equal distance to the opposite edges of the Content Area
+             */
+            get: function () { return Text2D_1._AlignCenter; },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(Text2D.prototype, "fontName", {
         Object.defineProperty(Text2D.prototype, "fontName", {
             get: function () {
             get: function () {
                 return this._fontName;
                 return this._fontName;
@@ -11601,6 +11649,20 @@ var BABYLON;
             BABYLON.BoundingInfo2D.CreateFromSizeToRef(this.actualSize, this._levelBoundingInfo);
             BABYLON.BoundingInfo2D.CreateFromSizeToRef(this.actualSize, this._levelBoundingInfo);
             return true;
             return true;
         };
         };
+        Object.defineProperty(Text2D.prototype, "textAlignment", {
+            /**
+             * You can get/set the text alignment through this property
+             */
+            get: function () {
+                return this._textAlignment;
+            },
+            set: function (value) {
+                this._textAlignment = value;
+                this._setTextAlignmentfromString(value);
+            },
+            enumerable: true,
+            configurable: true
+        });
         Text2D.prototype.levelIntersect = function (intersectInfo) {
         Text2D.prototype.levelIntersect = function (intersectInfo) {
             // For now I can't do something better that boundingInfo is a hit, detecting an intersection on a particular letter would be possible, but do we really need it? Not for now...
             // For now I can't do something better that boundingInfo is a hit, detecting an intersection on a particular letter would be possible, but do we really need it? Not for now...
             return true;
             return true;
@@ -11673,42 +11735,168 @@ var BABYLON;
                 var ts = texture.getSize();
                 var ts = texture.getSize();
                 var offset = BABYLON.Vector2.Zero();
                 var offset = BABYLON.Vector2.Zero();
                 var lh = this.fontTexture.lineHeight;
                 var lh = this.fontTexture.lineHeight;
-                offset.y = ((this.textSize.height / lh) - 1) * lh; // Origin is bottom, not top, so the offset is starting with a y that is the top location of the text
-                var charxpos = 0;
                 d.dataElementCount = this._charCount;
                 d.dataElementCount = this._charCount;
                 d.curElement = 0;
                 d.curElement = 0;
-                for (var _i = 0, _a = this.text; _i < _a.length; _i++) {
-                    var char = _a[_i];
+                var lineLengths = [];
+                var charWidths = [];
+                var charsPerLine = [];
+                var numCharsCurrenLine = 0;
+                var contentAreaWidth = this.contentArea.width;
+                var contentAreaHeight = this.contentArea.height;
+                var numCharsCurrentWord = 0;
+                var widthCurrentWord = 0;
+                var numWordsPerLine = 0;
+                var text = this.text;
+                var tabWidth = this._tabulationSize * texture.spaceWidth;
+                for (var i_1 = 0; i_1 < text.length; i_1++) {
+                    var char = text[i_1];
+                    numCharsCurrenLine++;
+                    charWidths[i_1] = 0;
                     // Line feed
                     // Line feed
-                    if (char === "\n") {
+                    if (this._isWhiteSpaceCharVert(char)) {
+                        lineLengths.push(offset.x);
+                        charsPerLine.push(numCharsCurrenLine - 1);
+                        numCharsCurrenLine = 1;
                         offset.x = 0;
                         offset.x = 0;
-                        offset.y -= texture.lineHeight;
+                        if (widthCurrentWord > 0) {
+                            numWordsPerLine++;
+                        }
+                        numWordsPerLine = 0;
+                        numCharsCurrentWord = 0;
+                        widthCurrentWord = 0;
+                        continue;
                     }
                     }
-                    // Tabulation ?
+                    var ci = texture.getChar(char);
+                    var charWidth = 0;
                     if (char === "\t") {
                     if (char === "\t") {
-                        var nextPos = charxpos + this._tabulationSize;
-                        nextPos = nextPos - (nextPos % this._tabulationSize);
-                        offset.x += (nextPos - charxpos) * texture.spaceWidth;
-                        charxpos = nextPos;
-                        continue;
+                        charWidth = tabWidth;
                     }
                     }
-                    if (char < " ") {
-                        continue;
+                    else {
+                        charWidth = ci.charWidth;
                     }
                     }
-                    this.updateInstanceDataPart(d, offset);
-                    var ci = texture.getChar(char);
-                    offset.x += ci.charWidth;
-                    d.topLeftUV = ci.topLeftUV;
-                    var suv = ci.bottomRightUV.subtract(ci.topLeftUV);
-                    d.sizeUV = suv;
-                    d.textureSize = new BABYLON.Vector2(ts.width, ts.height);
-                    d.color = this.defaultFontColor;
-                    d.superSampleFactor = superSampleFactor;
-                    ++d.curElement;
+                    offset.x += charWidth;
+                    charWidths[i_1] = charWidth;
+                    if (this._isWhiteSpaceCharHoriz(char)) {
+                        if (widthCurrentWord > 0) {
+                            numWordsPerLine++;
+                        }
+                        numCharsCurrentWord = 0;
+                        widthCurrentWord = 0;
+                    }
+                    else {
+                        widthCurrentWord += ci.charWidth;
+                        numCharsCurrentWord++;
+                    }
+                    if (this._wordWrap && numWordsPerLine > 0 && offset.x > contentAreaWidth) {
+                        lineLengths.push(offset.x - widthCurrentWord);
+                        numCharsCurrenLine -= numCharsCurrentWord;
+                        var j = i_1 - numCharsCurrentWord;
+                        //skip white space at the end of this line
+                        while (this._isWhiteSpaceCharHoriz(text[j])) {
+                            lineLengths[lineLengths.length - 1] -= charWidths[j];
+                            j--;
+                        }
+                        charsPerLine.push(numCharsCurrenLine);
+                        if (this._isWhiteSpaceCharHoriz(text[i_1])) {
+                            //skip white space at the beginning of next line
+                            var numSpaces = 0;
+                            while (this._isWhiteSpaceCharHoriz(text[i_1 + numSpaces])) {
+                                numSpaces++;
+                                charWidths[i_1 + numSpaces] = 0;
+                            }
+                            i_1 += numSpaces - 1;
+                            offset.x = 0;
+                            numCharsCurrenLine = numSpaces - 1;
+                        }
+                        else {
+                            numCharsCurrenLine = numCharsCurrentWord;
+                            offset.x = widthCurrentWord;
+                        }
+                        numWordsPerLine = 0;
+                    }
+                }
+                lineLengths.push(offset.x);
+                charsPerLine.push(numCharsCurrenLine);
+                //skip white space at the end
+                var i = text.length - 1;
+                while (this._isWhiteSpaceCharHoriz(text[i])) {
+                    lineLengths[lineLengths.length - 1] -= charWidths[i];
+                    i--;
+                }
+                var charNum = 0;
+                var maxLineLen = 0;
+                var alignH = this.textAlignmentH;
+                var alignV = this.textAlignmentV;
+                offset.x = 0;
+                if (alignH == Text2D_1.AlignRight || alignH == Text2D_1.AlignCenter) {
+                    for (var i_2 = 0; i_2 < lineLengths.length; i_2++) {
+                        if (lineLengths[i_2] > maxLineLen) {
+                            maxLineLen = lineLengths[i_2];
+                        }
+                    }
+                }
+                var textHeight = lineLengths.length * lh;
+                var offsetX = this.padding.leftPixels;
+                if (alignH == Text2D_1.AlignRight) {
+                    offsetX += contentAreaWidth - maxLineLen;
+                }
+                else if (alignH == Text2D_1.AlignCenter) {
+                    offsetX += (contentAreaWidth - maxLineLen) * .5;
+                }
+                offset.x += offsetX;
+                offset.y += contentAreaHeight + textHeight - lh;
+                offset.y += this.padding.bottomPixels;
+                if (alignV == Text2D_1.AlignBottom) {
+                    offset.y -= contentAreaHeight;
+                }
+                else if (alignV == Text2D_1.AlignCenter) {
+                    offset.y -= (contentAreaHeight - textHeight) * .5 + lineLengths.length * lh;
+                }
+                else {
+                    offset.y -= lineLengths.length * lh;
+                }
+                for (var i_3 = 0; i_3 < lineLengths.length; i_3++) {
+                    var numChars = charsPerLine[i_3];
+                    var lineLength = lineLengths[i_3];
+                    if (alignH == Text2D_1.AlignRight) {
+                        offset.x += maxLineLen - lineLength;
+                    }
+                    else if (alignH == Text2D_1.AlignCenter) {
+                        offset.x += (maxLineLen - lineLength) * .5;
+                    }
+                    for (var j = 0; j < numChars; j++) {
+                        var char = text[charNum];
+                        var charWidth = charWidths[charNum];
+                        this.updateInstanceDataPart(d, offset);
+                        offset.x += charWidth;
+                        if (!this._isWhiteSpaceCharHoriz(char)) {
+                            var ci = texture.getChar(char);
+                            d.topLeftUV = ci.topLeftUV;
+                            var suv = ci.bottomRightUV.subtract(ci.topLeftUV);
+                            d.sizeUV = suv;
+                            d.textureSize = new BABYLON.Vector2(ts.width, ts.height);
+                            d.color = this.defaultFontColor;
+                            d.superSampleFactor = superSampleFactor;
+                            ++d.curElement;
+                        }
+                        charNum++;
+                    }
+                    offset.x = offsetX;
+                    offset.y -= texture.lineHeight;
                 }
                 }
             }
             }
             return true;
             return true;
         };
         };
+        Text2D.prototype._isWhiteSpaceCharHoriz = function (char) {
+            if (char === " " || char === "\t") {
+                return true;
+            }
+        };
+        Text2D.prototype._isWhiteSpaceCharVert = function (char) {
+            if (char === "\n" || char === "\r") {
+                return true;
+            }
+        };
         Text2D.prototype._updateCharCount = function () {
         Text2D.prototype._updateCharCount = function () {
             var count = 0;
             var count = 0;
             for (var _i = 0, _a = this._text; _i < _a.length; _i++) {
             for (var _i = 0, _a = this._text; _i < _a.length; _i++) {
@@ -11720,6 +11908,61 @@ var BABYLON;
             }
             }
             this._charCount = count;
             this._charCount = count;
         };
         };
+        Text2D.prototype._setTextAlignmentfromString = function (value) {
+            var m = value.trim().split(",");
+            for (var _i = 0, m_1 = m; _i < m_1.length; _i++) {
+                var v = m_1[_i];
+                v = v.toLocaleLowerCase().trim();
+                // Horizontal
+                var i = v.indexOf("h:");
+                if (i === -1) {
+                    i = v.indexOf("horizontal:");
+                }
+                if (i !== -1) {
+                    v = v.substr(v.indexOf(":") + 1);
+                    this._setTextAlignmentHorizontal(v);
+                    continue;
+                }
+                // Vertical
+                i = v.indexOf("v:");
+                if (i === -1) {
+                    i = v.indexOf("vertical:");
+                }
+                if (i !== -1) {
+                    v = v.substr(v.indexOf(":") + 1);
+                    this._setTextAlignmentVertical(v);
+                    continue;
+                }
+            }
+        };
+        Text2D.prototype._setTextAlignmentHorizontal = function (text) {
+            var v = text.trim().toLocaleLowerCase();
+            switch (v) {
+                case "left":
+                    this.textAlignmentH = Text2D_1.AlignLeft;
+                    return;
+                case "right":
+                    this.textAlignmentH = Text2D_1.AlignRight;
+                    return;
+                case "center":
+                    this.textAlignmentH = Text2D_1.AlignCenter;
+                    return;
+            }
+        };
+        Text2D.prototype._setTextAlignmentVertical = function (text) {
+            var v = text.trim().toLocaleLowerCase();
+            switch (v) {
+                case "top":
+                    this.textAlignmentV = Text2D_1.AlignTop;
+                    return;
+                case "bottom":
+                    this.textAlignmentV = Text2D_1.AlignBottom;
+                    return;
+                case "center":
+                    this.textAlignmentV = Text2D_1.AlignCenter;
+                    return;
+            }
+        };
         Text2D.prototype._useTextureAlpha = function () {
         Text2D.prototype._useTextureAlpha = function () {
             return this._fontSDF;
             return this._fontSDF;
         };
         };
@@ -11730,6 +11973,11 @@ var BABYLON;
     }(BABYLON.RenderablePrim2D));
     }(BABYLON.RenderablePrim2D));
     Text2D.TEXT2D_MAINPARTID = 1;
     Text2D.TEXT2D_MAINPARTID = 1;
     Text2D.TEXT2D_CATEGORY_SDF = "SignedDistanceField";
     Text2D.TEXT2D_CATEGORY_SDF = "SignedDistanceField";
+    Text2D._AlignLeft = 1;
+    Text2D._AlignTop = 1; // Same as left
+    Text2D._AlignRight = 2;
+    Text2D._AlignBottom = 2; // Same as right
+    Text2D._AlignCenter = 3;
     __decorate([
     __decorate([
         BABYLON.modelLevelProperty(BABYLON.RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 1, function (pi) { return Text2D_1.fontProperty = pi; }, false, true)
         BABYLON.modelLevelProperty(BABYLON.RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 1, function (pi) { return Text2D_1.fontProperty = pi; }, false, true)
     ], Text2D.prototype, "fontName", null);
     ], Text2D.prototype, "fontName", null);
@@ -11969,7 +12217,7 @@ var BABYLON;
          * - padding: top, left, right and bottom padding formatted as a single string (see PrimitiveThickness.fromString)
          * - padding: top, left, right and bottom padding formatted as a single string (see PrimitiveThickness.fromString)
          */
          */
         function Lines2D(points, settings) {
         function Lines2D(points, settings) {
-            var _this;
+            var _this = this;
             if (!settings) {
             if (!settings) {
                 settings = {};
                 settings = {};
             }
             }
@@ -12978,7 +13226,7 @@ var BABYLON;
             var _this = _super.call(this, settings) || this;
             var _this = _super.call(this, settings) || this;
             /**
             /**
              * If you set your own WorldSpaceNode to display the Canvas2D you have to provide your own implementation of this method which computes the local position in the Canvas based on the given 3D World one.
              * If you set your own WorldSpaceNode to display the Canvas2D you have to provide your own implementation of this method which computes the local position in the Canvas based on the given 3D World one.
-             * Beware that you have to take under consideration the origin in your calculations! Good luck!
+             * Beware that you have to take under consideration the origin and unitScaleFactor in your calculations! Good luck!
              */
              */
             _this.worldSpaceToNodeLocal = function (worldPos) {
             _this.worldSpaceToNodeLocal = function (worldPos) {
                 var node = _this._worldSpaceNode;
                 var node = _this._worldSpaceNode;
@@ -12987,11 +13235,14 @@ var BABYLON;
                 }
                 }
                 var mtx = node.getWorldMatrix().clone();
                 var mtx = node.getWorldMatrix().clone();
                 mtx.invert();
                 mtx.invert();
+                var usf = _this.unitScaleFactor;
                 var v = BABYLON.Vector3.TransformCoordinates(worldPos, mtx);
                 var v = BABYLON.Vector3.TransformCoordinates(worldPos, mtx);
                 var res = new BABYLON.Vector2(v.x, v.y);
                 var res = new BABYLON.Vector2(v.x, v.y);
                 var size = _this.actualSize;
                 var size = _this.actualSize;
-                res.x += size.width * 0.5; // res is centered, make it relative to bottom/left
-                res.y += size.height * 0.5;
+                res.x += (size.width / usf) * 0.5; // res is centered, make it relative to bottom/left
+                res.y += (size.height / usf) * 0.5;
+                res.x *= usf; // multiply by the unitScaleFactor, which defines if the canvas is nth time bigger than the original world plane
+                res.y *= usf;
                 return res;
                 return res;
             };
             };
             /**
             /**
@@ -13469,9 +13720,12 @@ var BABYLON;
         };
         };
         // Based on the previousIntersectionList and the actualInstersectionList we can determined which primitives are being hover state or loosing it
         // Based on the previousIntersectionList and the actualInstersectionList we can determined which primitives are being hover state or loosing it
         Canvas2D.prototype._updateOverStatus = function (force) {
         Canvas2D.prototype._updateOverStatus = function (force) {
-            if ((!force && (this.scene.getRenderId() === this._hoverStatusRenderId)) || !this._previousIntersectionList || !this._actualIntersectionList) {
+            if ((!force && (this.scene.getRenderId() === this._hoverStatusRenderId)) || !this._actualIntersectionList) {
                 return;
                 return;
             }
             }
+            if (this._previousIntersectionList == null) {
+                this._previousIntersectionList = [];
+            }
             // Detect a change of over
             // Detect a change of over
             var prevPrim = this._previousOverPrimitive ? this._previousOverPrimitive.prim : null;
             var prevPrim = this._previousOverPrimitive ? this._previousOverPrimitive.prim : null;
             var actualPrim = this._actualOverPrimitive ? this._actualOverPrimitive.prim : null;
             var actualPrim = this._actualOverPrimitive ? this._actualOverPrimitive.prim : null;
@@ -13941,6 +14195,13 @@ var BABYLON;
             enumerable: true,
             enumerable: true,
             configurable: true
             configurable: true
         });
         });
+        Object.defineProperty(Canvas2D.prototype, "unitScaleFactor", {
+            get: function () {
+                return this._unitScaleFactor;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Canvas2D.prototype.createCanvasProfileInfoCanvas = function () {
         Canvas2D.prototype.createCanvasProfileInfoCanvas = function () {
             if (this._profilingCanvas) {
             if (this._profilingCanvas) {
                 return this._profilingCanvas;
                 return this._profilingCanvas;
@@ -14525,7 +14786,7 @@ var BABYLON;
          * - padding: top, left, right and bottom padding formatted as a single string (see PrimitiveThickness.fromString)
          * - padding: top, left, right and bottom padding formatted as a single string (see PrimitiveThickness.fromString)
          */
          */
         function WorldSpaceCanvas2D(scene, size, settings) {
         function WorldSpaceCanvas2D(scene, size, settings) {
-            var _this;
+            var _this = this;
             BABYLON.Prim2DBase._isCanvasInit = true;
             BABYLON.Prim2DBase._isCanvasInit = true;
             var s = settings;
             var s = settings;
             s.isScreenSpace = false;
             s.isScreenSpace = false;
@@ -14541,6 +14802,7 @@ var BABYLON;
             }
             }
             _this = _super.call(this, scene, settings) || this;
             _this = _super.call(this, scene, settings) || this;
             BABYLON.Prim2DBase._isCanvasInit = false;
             BABYLON.Prim2DBase._isCanvasInit = false;
+            _this._unitScaleFactor = (settings.unitScaleFactor != null) ? settings.unitScaleFactor : 1;
             _this._renderableData._useMipMap = true;
             _this._renderableData._useMipMap = true;
             _this._renderableData._anisotropicLevel = 8;
             _this._renderableData._anisotropicLevel = 8;
             //if (cachingStrategy === Canvas2D.CACHESTRATEGY_DONTCACHE) {
             //if (cachingStrategy === Canvas2D.CACHESTRATEGY_DONTCACHE) {
@@ -14582,6 +14844,9 @@ var BABYLON;
                 mtl.specularColor = new BABYLON.Color3(0, 0, 0);
                 mtl.specularColor = new BABYLON.Color3(0, 0, 0);
                 mtl.disableLighting = true;
                 mtl.disableLighting = true;
                 mtl.useAlphaFromDiffuseTexture = true;
                 mtl.useAlphaFromDiffuseTexture = true;
+                if (settings && settings.sideOrientation) {
+                    mtl.backFaceCulling = (settings.sideOrientation === BABYLON.Mesh.DEFAULTSIDE || settings.sideOrientation === BABYLON.Mesh.FRONTSIDE);
+                }
                 plane.position = settings && settings.worldPosition || BABYLON.Vector3.Zero();
                 plane.position = settings && settings.worldPosition || BABYLON.Vector3.Zero();
                 plane.rotationQuaternion = settings && settings.worldRotation || BABYLON.Quaternion.Identity();
                 plane.rotationQuaternion = settings && settings.worldRotation || BABYLON.Quaternion.Identity();
                 plane.material = mtl;
                 plane.material = mtl;
@@ -14649,7 +14914,7 @@ var BABYLON;
          * - padding: top, left, right and bottom padding formatted as a single string (see BABYLON.PrimitiveThickness.fromString)
          * - padding: top, left, right and bottom padding formatted as a single string (see BABYLON.PrimitiveThickness.fromString)
          */
          */
         function ScreenSpaceCanvas2D(scene, settings) {
         function ScreenSpaceCanvas2D(scene, settings) {
-            var _this;
+            var _this = this;
             BABYLON.Prim2DBase._isCanvasInit = true;
             BABYLON.Prim2DBase._isCanvasInit = true;
             _this = _super.call(this, scene, settings) || this;
             _this = _super.call(this, scene, settings) || this;
             return _this;
             return _this;
@@ -15633,7 +15898,7 @@ var BABYLON;
     var StackPanel = StackPanel_1 = (function (_super) {
     var StackPanel = StackPanel_1 = (function (_super) {
         __extends(StackPanel, _super);
         __extends(StackPanel, _super);
         function StackPanel(settings) {
         function StackPanel(settings) {
-            var _this;
+            var _this = this;
             if (!settings) {
             if (!settings) {
                 settings = {};
                 settings = {};
             }
             }
@@ -15696,7 +15961,7 @@ var BABYLON;
     var DefaultStackPanelRenderingTemplate = DefaultStackPanelRenderingTemplate_1 = (function (_super) {
     var DefaultStackPanelRenderingTemplate = DefaultStackPanelRenderingTemplate_1 = (function (_super) {
         __extends(DefaultStackPanelRenderingTemplate, _super);
         __extends(DefaultStackPanelRenderingTemplate, _super);
         function DefaultStackPanelRenderingTemplate() {
         function DefaultStackPanelRenderingTemplate() {
-            return _super.apply(this, arguments) || this;
+            return _super !== null && _super.apply(this, arguments) || this;
         }
         }
         DefaultStackPanelRenderingTemplate.prototype.createVisualTree = function (owner, visualPlaceholder) {
         DefaultStackPanelRenderingTemplate.prototype.createVisualTree = function (owner, visualPlaceholder) {
             return { root: visualPlaceholder, contentPlaceholder: visualPlaceholder };
             return { root: visualPlaceholder, contentPlaceholder: visualPlaceholder };
@@ -15825,7 +16090,7 @@ var BABYLON;
     var ContentControl = ContentControl_1 = (function (_super) {
     var ContentControl = ContentControl_1 = (function (_super) {
         __extends(ContentControl, _super);
         __extends(ContentControl, _super);
         function ContentControl(settings) {
         function ContentControl(settings) {
-            var _this;
+            var _this = this;
             if (!settings) {
             if (!settings) {
                 settings = {};
                 settings = {};
             }
             }
@@ -15980,7 +16245,7 @@ var BABYLON;
     var Window = Window_1 = (function (_super) {
     var Window = Window_1 = (function (_super) {
         __extends(Window, _super);
         __extends(Window, _super);
         function Window(scene, settings) {
         function Window(scene, settings) {
-            var _this;
+            var _this = this;
             if (!settings) {
             if (!settings) {
                 settings = {};
                 settings = {};
             }
             }
@@ -16165,7 +16430,7 @@ var BABYLON;
     var DefaultWindowRenderingTemplate = DefaultWindowRenderingTemplate_1 = (function (_super) {
     var DefaultWindowRenderingTemplate = DefaultWindowRenderingTemplate_1 = (function (_super) {
         __extends(DefaultWindowRenderingTemplate, _super);
         __extends(DefaultWindowRenderingTemplate, _super);
         function DefaultWindowRenderingTemplate() {
         function DefaultWindowRenderingTemplate() {
-            return _super.apply(this, arguments) || this;
+            return _super !== null && _super.apply(this, arguments) || this;
         }
         }
         DefaultWindowRenderingTemplate.prototype.createVisualTree = function (owner, visualPlaceholder) {
         DefaultWindowRenderingTemplate.prototype.createVisualTree = function (owner, visualPlaceholder) {
             var r = new BABYLON.Rectangle2D({ parent: visualPlaceholder, fill: "#808080FF" });
             var r = new BABYLON.Rectangle2D({ parent: visualPlaceholder, fill: "#808080FF" });
@@ -16196,7 +16461,7 @@ var BABYLON;
     var Label = Label_1 = (function (_super) {
     var Label = Label_1 = (function (_super) {
         __extends(Label, _super);
         __extends(Label, _super);
         function Label(settings) {
         function Label(settings) {
-            var _this;
+            var _this = this;
             if (!settings) {
             if (!settings) {
                 settings = {};
                 settings = {};
             }
             }
@@ -16243,7 +16508,7 @@ var BABYLON;
     var DefaultLabelRenderingTemplate = DefaultLabelRenderingTemplate_1 = (function (_super) {
     var DefaultLabelRenderingTemplate = DefaultLabelRenderingTemplate_1 = (function (_super) {
         __extends(DefaultLabelRenderingTemplate, _super);
         __extends(DefaultLabelRenderingTemplate, _super);
         function DefaultLabelRenderingTemplate() {
         function DefaultLabelRenderingTemplate() {
-            return _super.apply(this, arguments) || this;
+            return _super !== null && _super.apply(this, arguments) || this;
         }
         }
         DefaultLabelRenderingTemplate.prototype.createVisualTree = function (owner, visualPlaceholder) {
         DefaultLabelRenderingTemplate.prototype.createVisualTree = function (owner, visualPlaceholder) {
             var r = new BABYLON.Text2D("", { parent: visualPlaceholder });
             var r = new BABYLON.Text2D("", { parent: visualPlaceholder });
@@ -16276,7 +16541,7 @@ var BABYLON;
     var Button = Button_1 = (function (_super) {
     var Button = Button_1 = (function (_super) {
         __extends(Button, _super);
         __extends(Button, _super);
         function Button(settings) {
         function Button(settings) {
-            var _this;
+            var _this = this;
             if (!settings) {
             if (!settings) {
                 settings = {};
                 settings = {};
             }
             }
@@ -16430,7 +16695,7 @@ var BABYLON;
     var DefaultButtonRenderingTemplate = DefaultButtonRenderingTemplate_1 = (function (_super) {
     var DefaultButtonRenderingTemplate = DefaultButtonRenderingTemplate_1 = (function (_super) {
         __extends(DefaultButtonRenderingTemplate, _super);
         __extends(DefaultButtonRenderingTemplate, _super);
         function DefaultButtonRenderingTemplate() {
         function DefaultButtonRenderingTemplate() {
-            return _super.apply(this, arguments) || this;
+            return _super !== null && _super.apply(this, arguments) || this;
         }
         }
         DefaultButtonRenderingTemplate.prototype.createVisualTree = function (owner, visualPlaceholder) {
         DefaultButtonRenderingTemplate.prototype.createVisualTree = function (owner, visualPlaceholder) {
             this._rect = new BABYLON.Rectangle2D({ parent: visualPlaceholder, fill: "#FF8080FF", border: "#FF8080FF", roundRadius: 10, borderThickness: 2 });
             this._rect = new BABYLON.Rectangle2D({ parent: visualPlaceholder, fill: "#FF8080FF", border: "#FF8080FF", roundRadius: 10, borderThickness: 2 });

Dosya farkı çok büyük olduğundan ihmal edildi
+ 8 - 8
dist/preview release/canvas2D/babylon.canvas2d.min.js


Dosya farkı çok büyük olduğundan ihmal edildi
+ 4 - 4
dist/preview release/inspector/babylon.inspector.bundle.js


+ 31 - 0
dist/preview release/inspector/babylon.inspector.css

@@ -28,6 +28,8 @@
     display: flex;
     display: flex;
     flex-direction: column;
     flex-direction: column;
     flex-shrink: 0; }
     flex-shrink: 0; }
+    .insp-wrapper .insp-right-panel.popupmode {
+      width: 100% !important; }
     .insp-wrapper .insp-right-panel .top-panel {
     .insp-wrapper .insp-right-panel .top-panel {
       width: 100%;
       width: 100%;
       height: 100%;
       height: 100%;
@@ -167,6 +169,35 @@
       text-transform: uppercase;
       text-transform: uppercase;
       line-height: 25px;
       line-height: 25px;
       margin-bottom: 10px; }
       margin-bottom: 10px; }
+  .insp-wrapper .tab-panel .console-panel {
+    min-height: 100px;
+    user-select: text;
+    box-sizing: border-box;
+    padding: 0 15px; }
+    .insp-wrapper .tab-panel .console-panel .console-panel-title {
+      height: 25px;
+      border-bottom: 1px solid #383838;
+      text-transform: uppercase;
+      line-height: 25px;
+      margin-bottom: 10px; }
+    .insp-wrapper .tab-panel .console-panel .console-panel-content {
+      overflow-y: auto;
+      overflow-x: hidden;
+      height: calc(100% - 30px); }
+    .insp-wrapper .tab-panel .console-panel .defaut-line, .insp-wrapper .tab-panel .console-panel .log, .insp-wrapper .tab-panel .console-panel .warn, .insp-wrapper .tab-panel .console-panel .error, .insp-wrapper .tab-panel .console-panel .object {
+      word-wrap: break-word;
+      padding: 3px 0 3px 5px; }
+    .insp-wrapper .tab-panel .console-panel .caller {
+      padding: 3px 0 3px 0;
+      color: #349ccd; }
+    .insp-wrapper .tab-panel .console-panel .log {
+      color: white; }
+    .insp-wrapper .tab-panel .console-panel .warn {
+      color: orange; }
+    .insp-wrapper .tab-panel .console-panel .error {
+      color: orangered; }
+    .insp-wrapper .tab-panel .console-panel .object {
+      color: #5db0d7; }
   .insp-wrapper .tab-panel.stats-panel {
   .insp-wrapper .tab-panel.stats-panel {
     overflow-y: auto; }
     overflow-y: auto; }
   .insp-wrapper .tab-panel .stats-fps {
   .insp-wrapper .tab-panel .stats-fps {

+ 23 - 0
dist/preview release/inspector/babylon.inspector.d.ts

@@ -707,6 +707,29 @@ declare module INSPECTOR {
 }
 }
 
 
 declare module INSPECTOR {
 declare module INSPECTOR {
+    /**
+     * The console tab will have two features :
+     * - hook all console.log call and display them in this panel (and in the browser console as well)
+     * - display all Babylon logs (called with Tools.Log...)
+     */
+    class ConsoleTab extends Tab {
+        private _inspector;
+        private _consolePanelContent;
+        private _bjsPanelContent;
+        private _oldConsoleLog;
+        private _oldConsoleWarn;
+        private _oldConsoleError;
+        constructor(tabbar: TabBar, insp: Inspector);
+        /** Overrides super.dispose */
+        dispose(): void;
+        private _message(type, message, caller);
+        private _addConsoleLog(...params);
+        private _addConsoleWarn(...params);
+        private _addConsoleError(...params);
+    }
+}
+
+declare module INSPECTOR {
     class StatsTab extends Tab {
     class StatsTab extends Tab {
         private _inspector;
         private _inspector;
         /**
         /**

+ 142 - 0
dist/preview release/inspector/babylon.inspector.js

@@ -108,6 +108,7 @@ var INSPECTOR;
                 this._buildInspector(inspector);
                 this._buildInspector(inspector);
                 // Send resize event to the window
                 // Send resize event to the window
                 INSPECTOR.Helpers.SEND_EVENT('resize');
                 INSPECTOR.Helpers.SEND_EVENT('resize');
+                this._tabbar.updateWidth();
             }
             }
             // Refresh the inspector if the browser is not edge
             // Refresh the inspector if the browser is not edge
             if (!INSPECTOR.Helpers.IsBrowserEdge()) {
             if (!INSPECTOR.Helpers.IsBrowserEdge()) {
@@ -219,6 +220,7 @@ var INSPECTOR;
          * Set 'firstTime' to true if there is no inspector created beforehands
          * Set 'firstTime' to true if there is no inspector created beforehands
          */
          */
         Inspector.prototype.openPopup = function (firstTime) {
         Inspector.prototype.openPopup = function (firstTime) {
+            var _this = this;
             if (INSPECTOR.Helpers.IsBrowserEdge()) {
             if (INSPECTOR.Helpers.IsBrowserEdge()) {
                 console.warn('Inspector - Popup mode is disabled in Edge, as the popup DOM cannot be updated from the main window for security reasons');
                 console.warn('Inspector - Popup mode is disabled in Edge, as the popup DOM cannot be updated from the main window for security reasons');
             }
             }
@@ -251,10 +253,16 @@ var INSPECTOR;
                 this._c2diwrapper = INSPECTOR.Helpers.CreateDiv('insp-wrapper', popup.document.body);
                 this._c2diwrapper = INSPECTOR.Helpers.CreateDiv('insp-wrapper', popup.document.body);
                 // add inspector     
                 // add inspector     
                 var inspector = INSPECTOR.Helpers.CreateDiv('insp-right-panel', this._c2diwrapper);
                 var inspector = INSPECTOR.Helpers.CreateDiv('insp-right-panel', this._c2diwrapper);
+                inspector.classList.add('popupmode');
                 // and build it in the popup  
                 // and build it in the popup  
                 this._buildInspector(inspector);
                 this._buildInspector(inspector);
                 // Rebuild it
                 // Rebuild it
                 this.refresh();
                 this.refresh();
+                popup.addEventListener('resize', function () {
+                    if (_this._tabbar) {
+                        _this._tabbar.updateWidth();
+                    }
+                });
             }
             }
         };
         };
         return Inspector;
         return Inspector;
@@ -2665,6 +2673,139 @@ var __extends = (this && this.__extends) || function (d, b) {
 };
 };
 var INSPECTOR;
 var INSPECTOR;
 (function (INSPECTOR) {
 (function (INSPECTOR) {
+    /**
+     * The console tab will have two features :
+     * - hook all console.log call and display them in this panel (and in the browser console as well)
+     * - display all Babylon logs (called with Tools.Log...)
+     */
+    var ConsoleTab = (function (_super) {
+        __extends(ConsoleTab, _super);
+        function ConsoleTab(tabbar, insp) {
+            var _this = _super.call(this, tabbar, 'Console') || this;
+            _this._inspector = insp;
+            // Build the shaders panel : a div that will contains the shaders tree and both shaders panels
+            _this._panel = INSPECTOR.Helpers.CreateDiv('tab-panel');
+            var consolePanel = INSPECTOR.Helpers.CreateDiv('console-panel');
+            var bjsPanel = INSPECTOR.Helpers.CreateDiv('console-panel');
+            _this._panel.appendChild(consolePanel);
+            _this._panel.appendChild(bjsPanel);
+            Split([consolePanel, bjsPanel], {
+                blockDrag: _this._inspector.popupMode,
+                sizes: [50, 50],
+                direction: 'vertical'
+            });
+            // Titles
+            var title = INSPECTOR.Helpers.CreateDiv('console-panel-title', consolePanel);
+            title.textContent = 'Console logs';
+            title = INSPECTOR.Helpers.CreateDiv('console-panel-title', bjsPanel);
+            title.textContent = 'Babylon.js logs';
+            // Contents
+            _this._consolePanelContent = INSPECTOR.Helpers.CreateDiv('console-panel-content', consolePanel);
+            _this._bjsPanelContent = INSPECTOR.Helpers.CreateDiv('console-panel-content', bjsPanel);
+            // save old console.log
+            _this._oldConsoleLog = console.log;
+            _this._oldConsoleWarn = console.warn;
+            _this._oldConsoleError = console.error;
+            console.log = _this._addConsoleLog.bind(_this);
+            console.warn = _this._addConsoleWarn.bind(_this);
+            console.error = _this._addConsoleError.bind(_this);
+            // Bjs logs
+            _this._bjsPanelContent.innerHTML = BABYLON.Tools.LogCache;
+            BABYLON.Tools.OnNewCacheEntry = function (entry) {
+                _this._bjsPanelContent.innerHTML += entry;
+            };
+            return _this;
+            // Testing
+            //console.log("This is a console.log message");
+            // console.log("That's right, console.log calls are hooked to be written in this window");
+            // console.log("Object are also stringify-ed", {width:10, height:30, shape:'rectangular'});
+            // console.warn("This is a console.warn message");
+            // console.error("This is a console.error message");
+            // BABYLON.Tools.Log("This is a message");
+            // BABYLON.Tools.Warn("This is a warning");
+            // BABYLON.Tools.Error("This is a error");
+        }
+        /** Overrides super.dispose */
+        ConsoleTab.prototype.dispose = function () {
+            console.log = this._oldConsoleLog;
+            console.warn = this._oldConsoleWarn;
+            console.error = this._oldConsoleError;
+        };
+        ConsoleTab.prototype._message = function (type, message, caller) {
+            var callerLine = INSPECTOR.Helpers.CreateDiv('caller', this._consolePanelContent);
+            callerLine.textContent = caller;
+            var line = INSPECTOR.Helpers.CreateDiv(type, this._consolePanelContent);
+            if (typeof message === "string") {
+                line.textContent += message;
+            }
+            else {
+                line.textContent += JSON.stringify(message);
+                line.classList.add('object');
+            }
+        };
+        ConsoleTab.prototype._addConsoleLog = function () {
+            var params = [];
+            for (var _i = 0; _i < arguments.length; _i++) {
+                params[_i] = arguments[_i];
+            }
+            // Get caller name if not null
+            var callerFunc = this._addConsoleLog.caller;
+            var caller = callerFunc == null ? "Window" : "Function " + callerFunc['name'] + ": ";
+            for (var i = 0; i < params.length; i++) {
+                this._message('log', params[i], caller);
+                // Write again in console does not work on edge, as the console object                 
+                // is not instantiate if debugger tools is not open
+                if (!INSPECTOR.Helpers.IsBrowserEdge()) {
+                    this._oldConsoleLog(params[i]);
+                }
+            }
+        };
+        ConsoleTab.prototype._addConsoleWarn = function () {
+            var params = [];
+            for (var _i = 0; _i < arguments.length; _i++) {
+                params[_i] = arguments[_i];
+            }
+            // Get caller name if not null
+            var callerFunc = this._addConsoleLog.caller;
+            var caller = callerFunc == null ? "Window" : callerFunc['name'];
+            for (var i = 0; i < params.length; i++) {
+                this._message('warn', params[i], caller);
+                // Write again in console does not work on edge, as the console object 
+                // is not instantiate if debugger tools is not open
+                if (!INSPECTOR.Helpers.IsBrowserEdge()) {
+                    this._oldConsoleWarn(params[i]);
+                }
+            }
+        };
+        ConsoleTab.prototype._addConsoleError = function () {
+            var params = [];
+            for (var _i = 0; _i < arguments.length; _i++) {
+                params[_i] = arguments[_i];
+            }
+            // Get caller name if not null
+            var callerFunc = this._addConsoleLog.caller;
+            var caller = callerFunc == null ? "Window" : callerFunc['name'];
+            for (var i = 0; i < params.length; i++) {
+                this._message('error', params[i], caller);
+                // Write again in console does not work on edge, as the console object 
+                // is not instantiate if debugger tools is not open
+                if (!INSPECTOR.Helpers.IsBrowserEdge()) {
+                    this._oldConsoleError(params[i]);
+                }
+            }
+        };
+        return ConsoleTab;
+    }(INSPECTOR.Tab));
+    INSPECTOR.ConsoleTab = ConsoleTab;
+})(INSPECTOR || (INSPECTOR = {}));
+
+var __extends = (this && this.__extends) || function (d, b) {
+    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+    function __() { this.constructor = d; }
+    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+};
+var INSPECTOR;
+(function (INSPECTOR) {
     var StatsTab = (function (_super) {
     var StatsTab = (function (_super) {
         __extends(StatsTab, _super);
         __extends(StatsTab, _super);
         function StatsTab(tabbar, insp) {
         function StatsTab(tabbar, insp) {
@@ -2957,6 +3098,7 @@ var INSPECTOR;
             _this._visibleTabs = [];
             _this._visibleTabs = [];
             _this._inspector = inspector;
             _this._inspector = inspector;
             _this._tabs.push(new INSPECTOR.SceneTab(_this, _this._inspector));
             _this._tabs.push(new INSPECTOR.SceneTab(_this, _this._inspector));
+            _this._tabs.push(new INSPECTOR.ConsoleTab(_this, _this._inspector));
             _this._tabs.push(new INSPECTOR.StatsTab(_this, _this._inspector));
             _this._tabs.push(new INSPECTOR.StatsTab(_this, _this._inspector));
             _this._meshTab = new INSPECTOR.MeshTab(_this, _this._inspector);
             _this._meshTab = new INSPECTOR.MeshTab(_this, _this._inspector);
             _this._tabs.push(_this._meshTab);
             _this._tabs.push(_this._meshTab);

Dosya farkı çok büyük olduğundan ihmal edildi
+ 3 - 3
dist/preview release/inspector/babylon.inspector.min.js


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

@@ -12,26 +12,39 @@
  - Multi-platform Compressed Textures for Desktops & Mobile Devices with fall back.  Batch (dos) scripts to convert entire directories of .jpg's & .png's ([jcpalmer](https://github.com/Palmer-JC))
  - Multi-platform Compressed Textures for Desktops & Mobile Devices with fall back.  Batch (dos) scripts to convert entire directories of .jpg's & .png's ([jcpalmer](https://github.com/Palmer-JC))
 
 
 ### Updates
 ### Updates
- - Added addChild, removeChild, setParent to AbstractMesh.  ([abow](https://github.com/abow))
- - `Effect.getVertexShaderSource()` and `Effect.getFragmentShaderSource()` now returns the effective shader code (including evaluation of #define) ([deltakosh](https://github.com/deltakosh))
-
+- `VertexBuffer.updatable` is now serialized ([deltakosh](https://github.com/deltakosh))
+- Added intersectsMeshes to Ray ([abow](https://github.com/abow))
+- New RayHelper class for easily viewing and attaching a ray to a mesh.  [Demo](http://www.babylonjs-playground.com/#ZHDBJ#34) - ([abow](https://github.com/abow))
+- `Mesh.applyDisplacementMap` now accepts uvScale and uvOffset parameter ([deltakosh](https://github.com/deltakosh))
+- Added addChild, removeChild, setParent to AbstractMesh ([abow](https://github.com/abow))
+- `Effect.getVertexShaderSource()` and `Effect.getFragmentShaderSource()` now returns the effective shader code (including evaluation of #define) ([deltakosh](https://github.com/deltakosh))
+- GroundMesh : `getHeightAtCoordinates()`, `getNormalAtCoordinates()` and `getNormalAtCoordinatesToRef()` can now work with rotated grounds ([jerome](https://github.com/jbousquie))  
+- `GroundMesh`, `facetData` and `SolidParticleSystem` improvement in normal computations ([jerome](https://github.com/jbousquie))   
+ 
 ### Canvas2D
 ### Canvas2D
 
 
 #### Major Updates
 #### Major Updates
+ - Added text alignment and word wrap to Text2D ([abow](https://github.com/abow))
  - Support of [Scale9Sprite](http://doc.babylonjs.com/overviews/Canvas2D_Sprite2D#scale9sprite-feature) feature in Sprite2D ([nockawa](https://github.com/nockawa))
  - Support of [Scale9Sprite](http://doc.babylonjs.com/overviews/Canvas2D_Sprite2D#scale9sprite-feature) feature in Sprite2D ([nockawa](https://github.com/nockawa))
  - Support of [AtlasPicture](http://doc.babylonjs.com/overviews/Canvas2D_AtlasPicture) to store many pictures into a bit one, with the possibility to create one/many Sprite2D out of it. ([nockawa](https://github.com/nockawa))
  - Support of [AtlasPicture](http://doc.babylonjs.com/overviews/Canvas2D_AtlasPicture) to store many pictures into a bit one, with the possibility to create one/many Sprite2D out of it. ([nockawa](https://github.com/nockawa))
  - Support of BMFont with the BitmaptFontTexture class, Text2D has now a bitmapFontTexture setting in the constructor to display text using a BitmapFontTexture ([nockawa](https://github.com/nockawa))
  - Support of BMFont with the BitmaptFontTexture class, Text2D has now a bitmapFontTexture setting in the constructor to display text using a BitmapFontTexture ([nockawa](https://github.com/nockawa))
 
 
 #### Minor Updates
 #### Minor Updates
+ - WorldSpaceCanvas: TrackNode feature, a WSC can follow a Scene Node with an optional billboarding feature (always facing the camera)[Demo](http://babylonjs-playground.com/#1KYG17#1)
+ - WorldSpaceCanvas: new setting unitScaleFactor to generated a bigger canvas than the world space mesh size. If you create a WSC with a size of 200;100 and a uSF of 3, the 3D Plane displaying the canvas will be 200;100 of scene units, the WSC will be 600;300 of pixels units.
+
+#### Bug Fixing
  - Fix Rotation issue when the Parent's Primitive hadn't a identity scale. ([nockawa](https://github.com/nockawa))
  - Fix Rotation issue when the Parent's Primitive hadn't a identity scale. ([nockawa](https://github.com/nockawa))
  - Primitive's position computed from TrackedNode are now hidden when the node is out of the Viewing Frustum ([nockawa](https://github.com/nockawa))
  - Primitive's position computed from TrackedNode are now hidden when the node is out of the Viewing Frustum ([nockawa](https://github.com/nockawa))
- - WorldSpaceCanvas: TrackNode feature, a WSC can follow a Scene Node with an optional billboarding feature (always facing the camera)[Demo](http://babylonjs-playground.com/#1KYG17#1)
+ - WorldSpaceCanvas: sideOrientation is finally working, you can try Mesh.DOUBLESIDE to make you Canvas visible on both sides. ([nockawa](https://github.com/nockawa))
+
 
 
 ### Exporters
 ### Exporters
     
     
 ### API doc
 ### API doc
 
 
 ### Bug fixes
 ### Bug fixes
+ - Fixed an issue with Mesh.attachToBone when a mesh is moving and an animation is changed ([abow](https://github.com/abow))
  - Fixed an issue withaspect ratio when using CreateScreenshot ([deltakosh](https://github.com/deltakosh))
  - Fixed an issue withaspect ratio when using CreateScreenshot ([deltakosh](https://github.com/deltakosh))
 
 
 ### Breaking changes
 ### Breaking changes

+ 9 - 5
src/Cameras/babylon.camera.ts

@@ -403,6 +403,10 @@
                 this._markSyncedWithParent();
                 this._markSyncedWithParent();
             }
             }
 
 
+            if (this._cameraRigParams.vrPreViewMatrix) {
+                this._computedViewMatrix.multiplyToRef(this._cameraRigParams.vrPreViewMatrix, this._computedViewMatrix);
+            }
+
             this._currentRenderId = this.getScene().getRenderId();
             this._currentRenderId = this.getScene().getRenderId();
 
 
             return this._computedViewMatrix;
             return this._computedViewMatrix;
@@ -425,11 +429,11 @@
                 this._projectionMatrix = projection;
                 this._projectionMatrix = projection;
             }
             }
         };
         };
-        
+
         public unfreezeProjectionMatrix(): void {
         public unfreezeProjectionMatrix(): void {
             this._doNotComputeProjectionMatrix = false;
             this._doNotComputeProjectionMatrix = false;
         };
         };
-        
+
         public getProjectionMatrix(force?: boolean): Matrix {
         public getProjectionMatrix(force?: boolean): Matrix {
             if (this._doNotComputeProjectionMatrix || (!force && this._isSynchronizedProjectionMatrix())) {
             if (this._doNotComputeProjectionMatrix || (!force && this._isSynchronizedProjectionMatrix())) {
                 return this._projectionMatrix;
                 return this._projectionMatrix;
@@ -707,15 +711,15 @@
             return SerializationHelper.Clone(Camera.GetConstructorFromName(this.getClassName(), name, this.getScene(), this.interaxialDistance, this.isStereoscopicSideBySide), this);
             return SerializationHelper.Clone(Camera.GetConstructorFromName(this.getClassName(), name, this.getScene(), this.interaxialDistance, this.isStereoscopicSideBySide), this);
         }
         }
 
 
-        public getDirection(localAxis:Vector3): Vector3 {
+        public getDirection(localAxis: Vector3): Vector3 {
             var result = Vector3.Zero();
             var result = Vector3.Zero();
 
 
             this.getDirectionToRef(localAxis, result);
             this.getDirectionToRef(localAxis, result);
-            
+
             return result;
             return result;
         }
         }
 
 
-        public getDirectionToRef(localAxis:Vector3, result:Vector3): void {
+        public getDirectionToRef(localAxis: Vector3, result: Vector3): void {
             Vector3.TransformNormalToRef(localAxis, this.getWorldMatrix(), result);
             Vector3.TransformNormalToRef(localAxis, this.getWorldMatrix(), result);
         }
         }
 
 

+ 44 - 34
src/Culling/babylon.ray.ts

@@ -6,12 +6,8 @@
         private _tvec: Vector3;
         private _tvec: Vector3;
         private _qvec: Vector3;
         private _qvec: Vector3;
 
 
-        private _renderPoints: Vector3[];
-        private _renderLine: LinesMesh;
-        private _renderFunction: () => void;
-        private _scene: Scene;
-        private _show = false;
         private _tmpRay: Ray;
         private _tmpRay: Ray;
+        private _rayHelper: RayHelper;
 
 
         constructor(public origin: Vector3, public direction: Vector3, public length: number = Number.MAX_VALUE) {
         constructor(public origin: Vector3, public direction: Vector3, public length: number = Number.MAX_VALUE) {
         }
         }
@@ -216,52 +212,66 @@
 
 
         }
         }
 
 
-        public show(scene:Scene, color:Color3): void{
-
-            if(!this._show){
+        public intersectsMeshes(meshes:Array<AbstractMesh>, fastCheck?: boolean, results?:Array<PickingInfo>): Array<PickingInfo> {
 
 
-                this._renderFunction = this._render.bind(this);
-                this._show = true;
-                this._scene = scene;
-                this._renderPoints = [this.origin, this.origin.add(this.direction.scale(this.length))];
-                this._renderLine = Mesh.CreateLines("ray", this._renderPoints, scene, true);
+            if(results){
+                results.length = 0;
+            }else{
+                results = [];
+            }
 
 
-                this._scene.registerBeforeRender(this._renderFunction);
+            for(var i = 0; i < meshes.length; i++){
+                var pickInfo = this.intersectsMesh(meshes[i], fastCheck);
 
 
+                if(pickInfo.hit){
+                    results.push(pickInfo);
+                }
             }
             }
 
 
-            if (color) {
-                this._renderLine.color.copyFrom(color);
-            }
+            results.sort(this._comparePickingInfo);
+
+            return results;
 
 
         }
         }
 
 
-        public hide(): void{
+        private _comparePickingInfo(pickingInfoA:PickingInfo, pickingInfoB:PickingInfo): number{
 
 
-            if(this._show){
-                this._show = false;
-                this._scene.unregisterBeforeRender(this._renderFunction);
-                this._scene = null;
+            if(pickingInfoA.distance < pickingInfoB.distance){
+                return -1;
+            }else if(pickingInfoA.distance > pickingInfoB.distance){
+                return 1;
+            }else{
+                return 0;
             }
             }
 
 
-            if(this._renderLine){
-                this._renderLine.dispose();
-                this._renderLine = null;
-                this._renderPoints = null;
+        }
+
+        /**
+         *  @Deprecated. Use new RayHelper.show() instead.
+         * */
+        public show(scene:Scene, color:Color3): void{
+
+            console.warn('Ray.show() has been deprecated.  Use new RayHelper.show() instead.');
+
+            if(!this._rayHelper){
+                this._rayHelper = new RayHelper(this);
             }
             }
+            
+            this._rayHelper.show(scene, color);
 
 
         }
         }
 
 
-        private _render(): void {
+        /**
+         *  @Deprecated. Use new RayHelper.hide() instead.
+         * */
+        public hide(): void{
 
 
-            var point = this._renderPoints[1];
-            var len = Math.min(this.length, 1000000);
-            
-            point.copyFrom(this.direction);
-            point.scaleInPlace(len);
-            point.addInPlace(this.origin);
+            console.warn('Ray.hide() has been deprecated.  Use new RayHelper.hide() instead.');
 
 
-            Mesh.CreateLines("ray", this._renderPoints, this._scene, true, this._renderLine);
+            if(this._rayHelper){
+                this._rayHelper.hide();
+                this._rayHelper = null;
+            }
 
 
         }
         }
 
 

+ 1 - 1
src/Math/babylon.math.ts

@@ -1790,7 +1790,7 @@
             return r;
             return r;
         }
         }
 
 
-        public substract(otherSize: Size): Size {
+        public subtract(otherSize: Size): Size {
             let r = new Size(this.width - otherSize.width, this.height - otherSize.height);
             let r = new Size(this.width - otherSize.width, this.height - otherSize.height);
             return r;
             return r;
         }
         }

+ 51 - 15
src/Mesh/babylon.geometry.ts

@@ -290,6 +290,8 @@
                 this._engine._releaseBuffer(this._indexBuffer);
                 this._engine._releaseBuffer(this._indexBuffer);
             }
             }
 
 
+            this._disposeVertexArrayObjects();
+
             this._indices = indices;
             this._indices = indices;
             if (this._meshes.length !== 0 && this._indices) {
             if (this._meshes.length !== 0 && this._indices) {
                 this._indexBuffer = this._engine.createIndexBuffer(this._indices);
                 this._indexBuffer = this._engine.createIndexBuffer(this._indices);
@@ -614,47 +616,80 @@
 
 
             if (this.isVerticesDataPresent(VertexBuffer.PositionKind)) {
             if (this.isVerticesDataPresent(VertexBuffer.PositionKind)) {
                 serializationObject.positions = this.getVerticesData(VertexBuffer.PositionKind);
                 serializationObject.positions = this.getVerticesData(VertexBuffer.PositionKind);
+                if (this.getVertexBuffer(VertexBuffer.PositionKind).isUpdatable) {
+                    serializationObject.positions._updatable = true;
+                }
             }
             }
 
 
             if (this.isVerticesDataPresent(VertexBuffer.NormalKind)) {
             if (this.isVerticesDataPresent(VertexBuffer.NormalKind)) {
                 serializationObject.normals = this.getVerticesData(VertexBuffer.NormalKind);
                 serializationObject.normals = this.getVerticesData(VertexBuffer.NormalKind);
+                if (this.getVertexBuffer(VertexBuffer.NormalKind).isUpdatable) {
+                    serializationObject.normals._updatable = true;
+                }
             }
             }
 
 
             if (this.isVerticesDataPresent(VertexBuffer.UVKind)) {
             if (this.isVerticesDataPresent(VertexBuffer.UVKind)) {
                 serializationObject.uvs = this.getVerticesData(VertexBuffer.UVKind);
                 serializationObject.uvs = this.getVerticesData(VertexBuffer.UVKind);
+                if (this.getVertexBuffer(VertexBuffer.UVKind).isUpdatable) {
+                    serializationObject.uvs._updatable = true;
+                }
             }
             }
 
 
             if (this.isVerticesDataPresent(VertexBuffer.UV2Kind)) {
             if (this.isVerticesDataPresent(VertexBuffer.UV2Kind)) {
                 serializationObject.uv2s = this.getVerticesData(VertexBuffer.UV2Kind);
                 serializationObject.uv2s = this.getVerticesData(VertexBuffer.UV2Kind);
+                if (this.getVertexBuffer(VertexBuffer.UV2Kind).isUpdatable) {
+                    serializationObject.uv2s._updatable = true;
+                }
             }
             }
 
 
             if (this.isVerticesDataPresent(VertexBuffer.UV3Kind)) {
             if (this.isVerticesDataPresent(VertexBuffer.UV3Kind)) {
                 serializationObject.uv3s = this.getVerticesData(VertexBuffer.UV3Kind);
                 serializationObject.uv3s = this.getVerticesData(VertexBuffer.UV3Kind);
+                if (this.getVertexBuffer(VertexBuffer.UV3Kind).isUpdatable) {
+                    serializationObject.uv3s._updatable = true;
+                }
             }
             }
 
 
             if (this.isVerticesDataPresent(VertexBuffer.UV4Kind)) {
             if (this.isVerticesDataPresent(VertexBuffer.UV4Kind)) {
                 serializationObject.uv4s = this.getVerticesData(VertexBuffer.UV4Kind);
                 serializationObject.uv4s = this.getVerticesData(VertexBuffer.UV4Kind);
+                if (this.getVertexBuffer(VertexBuffer.UV4Kind).isUpdatable) {
+                    serializationObject.uv4s._updatable = true;
+                }
             }
             }
 
 
             if (this.isVerticesDataPresent(VertexBuffer.UV5Kind)) {
             if (this.isVerticesDataPresent(VertexBuffer.UV5Kind)) {
                 serializationObject.uv5s = this.getVerticesData(VertexBuffer.UV5Kind);
                 serializationObject.uv5s = this.getVerticesData(VertexBuffer.UV5Kind);
+                if (this.getVertexBuffer(VertexBuffer.UV5Kind).isUpdatable) {
+                    serializationObject.uv5s._updatable = true;
+                }
             }
             }
 
 
             if (this.isVerticesDataPresent(VertexBuffer.UV6Kind)) {
             if (this.isVerticesDataPresent(VertexBuffer.UV6Kind)) {
                 serializationObject.uv6s = this.getVerticesData(VertexBuffer.UV6Kind);
                 serializationObject.uv6s = this.getVerticesData(VertexBuffer.UV6Kind);
+                if (this.getVertexBuffer(VertexBuffer.UV6Kind).isUpdatable) {
+                    serializationObject.uv6s._updatable = true;
+                }
             }
             }
 
 
             if (this.isVerticesDataPresent(VertexBuffer.ColorKind)) {
             if (this.isVerticesDataPresent(VertexBuffer.ColorKind)) {
                 serializationObject.colors = this.getVerticesData(VertexBuffer.ColorKind);
                 serializationObject.colors = this.getVerticesData(VertexBuffer.ColorKind);
+                if (this.getVertexBuffer(VertexBuffer.ColorKind).isUpdatable) {
+                    serializationObject.colors._updatable = true;
+                }
             }
             }
 
 
             if (this.isVerticesDataPresent(VertexBuffer.MatricesIndicesKind)) {
             if (this.isVerticesDataPresent(VertexBuffer.MatricesIndicesKind)) {
                 serializationObject.matricesIndices = this.getVerticesData(VertexBuffer.MatricesIndicesKind);
                 serializationObject.matricesIndices = this.getVerticesData(VertexBuffer.MatricesIndicesKind);
                 serializationObject.matricesIndices._isExpanded = true;
                 serializationObject.matricesIndices._isExpanded = true;
+                if (this.getVertexBuffer(VertexBuffer.MatricesIndicesKind).isUpdatable) {
+                    serializationObject.matricesIndices._updatable = true;
+                }
             }
             }
 
 
             if (this.isVerticesDataPresent(VertexBuffer.MatricesWeightsKind)) {
             if (this.isVerticesDataPresent(VertexBuffer.MatricesWeightsKind)) {
                 serializationObject.matricesWeights = this.getVerticesData(VertexBuffer.MatricesWeightsKind);
                 serializationObject.matricesWeights = this.getVerticesData(VertexBuffer.MatricesWeightsKind);
+                if (this.getVertexBuffer(VertexBuffer.MatricesWeightsKind).isUpdatable) {
+                    serializationObject.matricesWeights._updatable = true;
+                }
             }
             }
 
 
             serializationObject.indices = this.getIndices();
             serializationObject.indices = this.getIndices();
@@ -772,35 +807,36 @@
                     }
                     }
                 }
                 }
             } else if (parsedGeometry.positions && parsedGeometry.normals && parsedGeometry.indices) {
             } else if (parsedGeometry.positions && parsedGeometry.normals && parsedGeometry.indices) {
-                mesh.setVerticesData(VertexBuffer.PositionKind, parsedGeometry.positions, false);
-                mesh.setVerticesData(VertexBuffer.NormalKind, parsedGeometry.normals, false);
+                mesh.setVerticesData(VertexBuffer.PositionKind, parsedGeometry.positions, parsedGeometry.positions._updatable);
+
+                mesh.setVerticesData(VertexBuffer.NormalKind, parsedGeometry.normals, parsedGeometry.normals._updatable);
 
 
                 if (parsedGeometry.uvs) {
                 if (parsedGeometry.uvs) {
-                    mesh.setVerticesData(VertexBuffer.UVKind, parsedGeometry.uvs, false);
+                    mesh.setVerticesData(VertexBuffer.UVKind, parsedGeometry.uvs, parsedGeometry.uvs._updatable);
                 }
                 }
 
 
                 if (parsedGeometry.uvs2) {
                 if (parsedGeometry.uvs2) {
-                    mesh.setVerticesData(VertexBuffer.UV2Kind, parsedGeometry.uvs2, false);
+                    mesh.setVerticesData(VertexBuffer.UV2Kind, parsedGeometry.uvs2, parsedGeometry.uvs2._updatable);
                 }
                 }
 
 
                 if (parsedGeometry.uvs3) {
                 if (parsedGeometry.uvs3) {
-                    mesh.setVerticesData(VertexBuffer.UV3Kind, parsedGeometry.uvs3, false);
+                    mesh.setVerticesData(VertexBuffer.UV3Kind, parsedGeometry.uvs3, parsedGeometry.uvs3._updatable);
                 }
                 }
 
 
                 if (parsedGeometry.uvs4) {
                 if (parsedGeometry.uvs4) {
-                    mesh.setVerticesData(VertexBuffer.UV4Kind, parsedGeometry.uvs4, false);
+                    mesh.setVerticesData(VertexBuffer.UV4Kind, parsedGeometry.uvs4, parsedGeometry.uvs4._updatable);
                 }
                 }
 
 
                 if (parsedGeometry.uvs5) {
                 if (parsedGeometry.uvs5) {
-                    mesh.setVerticesData(VertexBuffer.UV5Kind, parsedGeometry.uvs5, false);
+                    mesh.setVerticesData(VertexBuffer.UV5Kind, parsedGeometry.uvs5, parsedGeometry.uvs5._updatable);
                 }
                 }
 
 
                 if (parsedGeometry.uvs6) {
                 if (parsedGeometry.uvs6) {
-                    mesh.setVerticesData(VertexBuffer.UV6Kind, parsedGeometry.uvs6, false);
+                    mesh.setVerticesData(VertexBuffer.UV6Kind, parsedGeometry.uvs6, parsedGeometry.uvs6._updatable);
                 }
                 }
 
 
                 if (parsedGeometry.colors) {
                 if (parsedGeometry.colors) {
-                    mesh.setVerticesData(VertexBuffer.ColorKind, Color4.CheckColors4(parsedGeometry.colors, parsedGeometry.positions.length / 3), false);
+                    mesh.setVerticesData(VertexBuffer.ColorKind, Color4.CheckColors4(parsedGeometry.colors, parsedGeometry.positions.length / 3), parsedGeometry.colors._updatable);
                 }
                 }
 
 
                 if (parsedGeometry.matricesIndices) {
                 if (parsedGeometry.matricesIndices) {
@@ -816,10 +852,10 @@
                             floatIndices.push(matricesIndex >> 24);
                             floatIndices.push(matricesIndex >> 24);
                         }
                         }
 
 
-                        mesh.setVerticesData(VertexBuffer.MatricesIndicesKind, floatIndices, false);
+                        mesh.setVerticesData(VertexBuffer.MatricesIndicesKind, floatIndices, parsedGeometry.matricesIndices._updatable);
                     } else {
                     } else {
                         delete parsedGeometry.matricesIndices._isExpanded;
                         delete parsedGeometry.matricesIndices._isExpanded;
-                        mesh.setVerticesData(VertexBuffer.MatricesIndicesKind, parsedGeometry.matricesIndices, false);
+                        mesh.setVerticesData(VertexBuffer.MatricesIndicesKind, parsedGeometry.matricesIndices, parsedGeometry.matricesIndices._updatable);
                     }
                     }
                 }
                 }
 
 
@@ -836,19 +872,19 @@
                             floatIndices.push(matricesIndex >> 24);
                             floatIndices.push(matricesIndex >> 24);
                         }
                         }
 
 
-                        mesh.setVerticesData(VertexBuffer.MatricesIndicesExtraKind, floatIndices, false);
+                        mesh.setVerticesData(VertexBuffer.MatricesIndicesExtraKind, floatIndices, parsedGeometry.matricesIndicesExtra._updatable);
                     } else {
                     } else {
                         delete parsedGeometry.matricesIndices._isExpanded;
                         delete parsedGeometry.matricesIndices._isExpanded;
-                        mesh.setVerticesData(VertexBuffer.MatricesIndicesExtraKind, parsedGeometry.matricesIndicesExtra, false);
+                        mesh.setVerticesData(VertexBuffer.MatricesIndicesExtraKind, parsedGeometry.matricesIndicesExtra, parsedGeometry.matricesIndicesExtra._updatable);
                     }
                     }
                 }
                 }
 
 
                 if (parsedGeometry.matricesWeights) {
                 if (parsedGeometry.matricesWeights) {
-                    mesh.setVerticesData(VertexBuffer.MatricesWeightsKind, parsedGeometry.matricesWeights, false);
+                    mesh.setVerticesData(VertexBuffer.MatricesWeightsKind, parsedGeometry.matricesWeights, parsedGeometry.matricesWeights._updatable);
                 }
                 }
 
 
                 if (parsedGeometry.matricesWeightsExtra) {
                 if (parsedGeometry.matricesWeightsExtra) {
-                    mesh.setVerticesData(VertexBuffer.MatricesWeightsExtraKind, parsedGeometry.matricesWeightsExtra, false);
+                    mesh.setVerticesData(VertexBuffer.MatricesWeightsExtraKind, parsedGeometry.matricesWeightsExtra, parsedGeometry.matricesWeights._updatable);
                 }
                 }
 
 
                 mesh.setIndices(parsedGeometry.indices);
                 mesh.setIndices(parsedGeometry.indices);

+ 25 - 23
src/Mesh/babylon.groundMesh.ts

@@ -45,14 +45,15 @@
          * Returns a height (y) value in the Worl system :
          * Returns a height (y) value in the Worl system :
          * the ground altitude at the coordinates (x, z) expressed in the World system.
          * the ground altitude at the coordinates (x, z) expressed in the World system.
          * Returns the ground y position if (x, z) are outside the ground surface.
          * Returns the ground y position if (x, z) are outside the ground surface.
-         * Not pertinent if the ground is rotated.
          */
          */
         public getHeightAtCoordinates(x: number, z: number): number {
         public getHeightAtCoordinates(x: number, z: number): number {
-            // express x and y in the ground local system
-            x -= this.position.x;
-            z -= this.position.z;
-            x /= this.scaling.x;
-            z /= this.scaling.z;
+            var world = this.getWorldMatrix();
+            var invMat = Tmp.Matrix[5];
+            world.invertToRef(invMat);
+            var tmpVect = Tmp.Vector3[8];
+            Vector3.TransformCoordinatesFromFloatsToRef(x, 0.0, z, invMat, tmpVect); // transform x,z in the mesh local space
+            x = tmpVect.x;
+            z = tmpVect.z;
             if (x < this._minX || x > this._maxX || z < this._minZ || z > this._maxZ) {
             if (x < this._minX || x > this._maxX || z < this._minZ || z > this._maxZ) {
                 return this.position.y;
                 return this.position.y;
             }
             }
@@ -63,17 +64,17 @@
             var facet = this._getFacetAt(x, z);
             var facet = this._getFacetAt(x, z);
             var y = -(facet.x * x + facet.z * z + facet.w) / facet.y;
             var y = -(facet.x * x + facet.z * z + facet.w) / facet.y;
             // return y in the World system
             // return y in the World system
-            return y * this.scaling.y + this.position.y;
+            Vector3.TransformCoordinatesFromFloatsToRef(0.0, y, 0.0, world, tmpVect);
+            return tmpVect.y;
         }
         }
 
 
         /**
         /**
          * Returns a normalized vector (Vector3) orthogonal to the ground
          * Returns a normalized vector (Vector3) orthogonal to the ground
          * at the ground coordinates (x, z) expressed in the World system.
          * at the ground coordinates (x, z) expressed in the World system.
-         * Returns Vector3(0, 1, 0) if (x, z) are outside the ground surface.
-         * Not pertinent if the ground is rotated.
+         * Returns Vector3(0.0, 1.0, 0.0) if (x, z) are outside the ground surface.
          */
          */
         public getNormalAtCoordinates(x: number, z: number): Vector3 {
         public getNormalAtCoordinates(x: number, z: number): Vector3 {
-            var normal = new Vector3(0, 1, 0);
+            var normal = new Vector3(0.0, 1.0, 0.0);
             this.getNormalAtCoordinatesToRef(x, z, normal);
             this.getNormalAtCoordinatesToRef(x, z, normal);
             return normal;
             return normal;
         }
         }
@@ -81,26 +82,27 @@
         /**
         /**
          * Updates the Vector3 passed a reference with a normalized vector orthogonal to the ground
          * Updates the Vector3 passed a reference with a normalized vector orthogonal to the ground
          * at the ground coordinates (x, z) expressed in the World system.
          * at the ground coordinates (x, z) expressed in the World system.
-         * Doesn't uptade the reference Vector3 if (x, z) are outside the ground surface.
-         * Not pertinent if the ground is rotated.
+         * Doesn't uptade the reference Vector3 if (x, z) are outside the ground surface.  
+         * Returns the GroundMesh.  
          */
          */
-        public getNormalAtCoordinatesToRef(x: number, z: number, ref: Vector3): void {
-            // express x and y in the ground local system
-            x -= this.position.x;
-            z -= this.position.z;
-            x /= this.scaling.x;
-            z /= this.scaling.z;
+        public getNormalAtCoordinatesToRef(x: number, z: number, ref: Vector3): GroundMesh {
+            var world = this.getWorldMatrix();
+            var tmpMat = Tmp.Matrix[5];
+            world.invertToRef(tmpMat);
+            var tmpVect = Tmp.Vector3[8];
+            Vector3.TransformCoordinatesFromFloatsToRef(x, 0.0, z, tmpMat, tmpVect); // transform x,z in the mesh local space
+            x = tmpVect.x;
+            z = tmpVect.z;
             if (x < this._minX || x > this._maxX || z < this._minZ || z > this._maxZ) {
             if (x < this._minX || x > this._maxX || z < this._minZ || z > this._maxZ) {
-                return;
+                return this;
             }
             }
             if (!this._heightQuads || this._heightQuads.length == 0) {
             if (!this._heightQuads || this._heightQuads.length == 0) {
                 this._initHeightQuads();
                 this._initHeightQuads();
                 this._computeHeightQuads();
                 this._computeHeightQuads();
             }
             }
             var facet = this._getFacetAt(x, z);
             var facet = this._getFacetAt(x, z);
-            ref.x = facet.x;
-            ref.y = facet.y;
-            ref.z = facet.z;
+            Vector3.TransformNormalFromFloatsToRef(facet.x, facet.y, facet.z, world, ref);
+            return this;
         }
         }
 
 
         /**
         /**
@@ -143,7 +145,7 @@
             this._heightQuads = new Array();
             this._heightQuads = new Array();
             for (var row = 0; row < subdivisionsY; row++) {
             for (var row = 0; row < subdivisionsY; row++) {
                 for (var col = 0; col < subdivisionsX; col++) {
                 for (var col = 0; col < subdivisionsX; col++) {
-                    var quad = { slope: BABYLON.Vector2.Zero(), facet1: new BABYLON.Vector4(0, 0, 0, 0), facet2: new BABYLON.Vector4(0, 0, 0, 0) };
+                    var quad = { slope: BABYLON.Vector2.Zero(), facet1: new BABYLON.Vector4(0.0, 0.0, 0.0, 0.0), facet2: new BABYLON.Vector4(0.0, 0.0, 0.0, 0.0) };
                     this._heightQuads[row * subdivisionsX + col] = quad;
                     this._heightQuads[row * subdivisionsX + col] = quad;
                 }
                 }
             }
             }

+ 13 - 7
src/Mesh/babylon.mesh.ts

@@ -1440,8 +1440,10 @@
          * The parameter `url` is a string, the URL from the image file is to be downloaded.  
          * The parameter `url` is a string, the URL from the image file is to be downloaded.  
          * The parameters `minHeight` and `maxHeight` are the lower and upper limits of the displacement.
          * The parameters `minHeight` and `maxHeight` are the lower and upper limits of the displacement.
          * The parameter `onSuccess` is an optional Javascript function to be called just after the mesh is modified. It is passed the modified mesh and must return nothing.
          * The parameter `onSuccess` is an optional Javascript function to be called just after the mesh is modified. It is passed the modified mesh and must return nothing.
+         * The parameter `uvOffset` is an optional vector2 used to offset UV.
+         * The parameter `uvScale` is an optional vector2 used to scale UV.
          */
          */
-        public applyDisplacementMap(url: string, minHeight: number, maxHeight: number, onSuccess?: (mesh: Mesh) => void): void {
+        public applyDisplacementMap(url: string, minHeight: number, maxHeight: number, onSuccess?: (mesh: Mesh) => void, uvOffset?: Vector2, uvScale?: Vector2): void {
             var scene = this.getScene();
             var scene = this.getScene();
 
 
             var onload = img => {
             var onload = img => {
@@ -1459,7 +1461,7 @@
                 //Cast is due to wrong definition in lib.d.ts from ts 1.3 - https://github.com/Microsoft/TypeScript/issues/949
                 //Cast is due to wrong definition in lib.d.ts from ts 1.3 - https://github.com/Microsoft/TypeScript/issues/949
                 var buffer = <Uint8Array>(<any>context.getImageData(0, 0, heightMapWidth, heightMapHeight).data);
                 var buffer = <Uint8Array>(<any>context.getImageData(0, 0, heightMapWidth, heightMapHeight).data);
 
 
-                this.applyDisplacementMapFromBuffer(buffer, heightMapWidth, heightMapHeight, minHeight, maxHeight);
+                this.applyDisplacementMapFromBuffer(buffer, heightMapWidth, heightMapHeight, minHeight, maxHeight, uvOffset, uvScale);
                 //execute success callback, if set
                 //execute success callback, if set
                 if (onSuccess) {
                 if (onSuccess) {
                     onSuccess(this);
                     onSuccess(this);
@@ -1477,8 +1479,10 @@
          * The parameter `buffer` is a `Uint8Array` buffer containing series of `Uint8` lower than 255, the red, green, blue and alpha values of each successive pixel.
          * The parameter `buffer` is a `Uint8Array` buffer containing series of `Uint8` lower than 255, the red, green, blue and alpha values of each successive pixel.
          * The parameters `heightMapWidth` and `heightMapHeight` are positive integers to set the width and height of the buffer image.     
          * The parameters `heightMapWidth` and `heightMapHeight` are positive integers to set the width and height of the buffer image.     
          * The parameters `minHeight` and `maxHeight` are the lower and upper limits of the displacement.
          * The parameters `minHeight` and `maxHeight` are the lower and upper limits of the displacement.
+         * The parameter `uvOffset` is an optional vector2 used to offset UV.
+         * The parameter `uvScale` is an optional vector2 used to scale UV.
          */
          */
-        public applyDisplacementMapFromBuffer(buffer: Uint8Array, heightMapWidth: number, heightMapHeight: number, minHeight: number, maxHeight: number): void {
+        public applyDisplacementMapFromBuffer(buffer: Uint8Array, heightMapWidth: number, heightMapHeight: number, minHeight: number, maxHeight: number, uvOffset?: Vector2, uvScale?: Vector2): void {
             if (!this.isVerticesDataPresent(VertexBuffer.PositionKind)
             if (!this.isVerticesDataPresent(VertexBuffer.PositionKind)
                 || !this.isVerticesDataPresent(VertexBuffer.NormalKind)
                 || !this.isVerticesDataPresent(VertexBuffer.NormalKind)
                 || !this.isVerticesDataPresent(VertexBuffer.UVKind)) {
                 || !this.isVerticesDataPresent(VertexBuffer.UVKind)) {
@@ -1493,14 +1497,17 @@
             var normal = Vector3.Zero();
             var normal = Vector3.Zero();
             var uv = Vector2.Zero();
             var uv = Vector2.Zero();
 
 
+            uvOffset = uvOffset || Vector2.Zero();
+            uvScale = uvScale || new Vector2(1, 1);
+
             for (var index = 0; index < positions.length; index += 3) {
             for (var index = 0; index < positions.length; index += 3) {
                 Vector3.FromArrayToRef(positions, index, position);
                 Vector3.FromArrayToRef(positions, index, position);
                 Vector3.FromArrayToRef(normals, index, normal);
                 Vector3.FromArrayToRef(normals, index, normal);
                 Vector2.FromArrayToRef(uvs, (index / 3) * 2, uv);
                 Vector2.FromArrayToRef(uvs, (index / 3) * 2, uv);
 
 
                 // Compute height
                 // Compute height
-                var u = ((Math.abs(uv.x) * heightMapWidth) % heightMapWidth) | 0;
-                var v = ((Math.abs(uv.y) * heightMapHeight) % heightMapHeight) | 0;
+                var u = ((Math.abs(uv.x * uvScale.x + uvOffset.x) * heightMapWidth) % heightMapWidth) | 0;
+                var v = ((Math.abs(uv.y * uvScale.y + uvOffset.y) * heightMapHeight) % heightMapHeight) | 0;
 
 
                 var pos = (u + v * heightMapWidth) * 4;
                 var pos = (u + v * heightMapWidth) * 4;
                 var r = buffer[pos] / 255.0;
                 var r = buffer[pos] / 255.0;
@@ -1930,8 +1937,7 @@
          */
          */
         public getFacetNormalToRef(i: number, ref: Vector3) {
         public getFacetNormalToRef(i: number, ref: Vector3) {
             var localNorm = (this.getFacetLocalNormals())[i];
             var localNorm = (this.getFacetLocalNormals())[i];
-            (this.getWorldMatrix()).getRotationMatrixToRef(Tmp.Matrix[0]);
-            Vector3.TransformCoordinatesToRef(localNorm, Tmp.Matrix[0], ref);
+            Vector3.TransformNormalToRef(localNorm, this.getWorldMatrix(), ref);
             return this;
             return this;
         }
         }
         /** 
         /** 

+ 1 - 0
src/Mesh/babylon.meshBuilder.ts

@@ -954,6 +954,7 @@
 
 
                 // Get normal
                 // Get normal
                 result.normal = new Vector3(normals[vertexId * 3], normals[vertexId * 3 + 1], normals[vertexId * 3 + 2]);
                 result.normal = new Vector3(normals[vertexId * 3], normals[vertexId * 3 + 1], normals[vertexId * 3 + 2]);
+                result.normal = Vector3.TransformNormal(result.normal, transformMatrix);
 
 
                 return result;
                 return result;
             }; // Inspired by https://github.com/mrdoob/three.js/blob/eee231960882f6f3b6113405f524956145148146/examples/js/geometries/DecalGeometry.js
             }; // Inspired by https://github.com/mrdoob/three.js/blob/eee231960882f6f3b6113405f524956145148146/examples/js/geometries/DecalGeometry.js

+ 3 - 4
src/Particles/babylon.solidParticleSystem.ts

@@ -663,10 +663,9 @@
                             this._normal.y = this._fixedNormal32[idx + 1];
                             this._normal.y = this._fixedNormal32[idx + 1];
                             this._normal.z = this._fixedNormal32[idx + 2];
                             this._normal.z = this._fixedNormal32[idx + 2];
 
 
-                            this._w = (this._normal.x * this._rotMatrix.m[3]) + (this._normal.y * this._rotMatrix.m[7]) + (this._normal.z * this._rotMatrix.m[11]) + this._rotMatrix.m[15];
-                            this._rotated.x = ((this._normal.x * this._rotMatrix.m[0]) + (this._normal.y * this._rotMatrix.m[4]) + (this._normal.z * this._rotMatrix.m[8]) + this._rotMatrix.m[12]) / this._w;
-                            this._rotated.y = ((this._normal.x * this._rotMatrix.m[1]) + (this._normal.y * this._rotMatrix.m[5]) + (this._normal.z * this._rotMatrix.m[9]) + this._rotMatrix.m[13]) / this._w;
-                            this._rotated.z = ((this._normal.x * this._rotMatrix.m[2]) + (this._normal.y * this._rotMatrix.m[6]) + (this._normal.z * this._rotMatrix.m[10]) + this._rotMatrix.m[14]) / this._w;
+                            this._rotated.x = ((this._normal.x * this._rotMatrix.m[0]) + (this._normal.y * this._rotMatrix.m[4]) + (this._normal.z * this._rotMatrix.m[8]) + this._rotMatrix.m[12]);
+                            this._rotated.y = ((this._normal.x * this._rotMatrix.m[1]) + (this._normal.y * this._rotMatrix.m[5]) + (this._normal.z * this._rotMatrix.m[9]) + this._rotMatrix.m[13]);
+                            this._rotated.z = ((this._normal.x * this._rotMatrix.m[2]) + (this._normal.y * this._rotMatrix.m[6]) + (this._normal.z * this._rotMatrix.m[10]) + this._rotMatrix.m[14]);
 
 
                             this._normals32[idx] = this._cam_axisX.x * this._rotated.x + this._cam_axisY.x * this._rotated.y + this._cam_axisZ.x * this._rotated.z;
                             this._normals32[idx] = this._cam_axisX.x * this._rotated.x + this._cam_axisY.x * this._rotated.y + this._cam_axisZ.x * this._rotated.z;
                             this._normals32[idx + 1] = this._cam_axisX.y * this._rotated.x + this._cam_axisY.y * this._rotated.y + this._cam_axisZ.y * this._rotated.z;
                             this._normals32[idx + 1] = this._cam_axisX.y * this._rotated.x + this._cam_axisY.y * this._rotated.y + this._cam_axisZ.y * this._rotated.z;

+ 1 - 1
src/Shaders/ShadersInclude/fogVertex.fx

@@ -1,3 +1,3 @@
 #ifdef FOG
 #ifdef FOG
-fFogDistance = (view * worldPos).z;
+fFogDistance = abs((view * worldPos).z);
 #endif
 #endif

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

@@ -46,6 +46,6 @@ void main(void) {
 
 
 	// Fog
 	// Fog
 #ifdef FOG
 #ifdef FOG
-	fFogDistance = viewPos.z;
+	fFogDistance = abs(viewPos.z);
 #endif
 #endif
 }
 }

+ 5 - 24
src/babylon.engine.ts

@@ -2023,29 +2023,6 @@
             this.bindArrayBuffer(null);
             this.bindArrayBuffer(null);
         }
         }
 
 
-        public setSamplingMode(texture: WebGLTexture, samplingMode: number): void {
-            var gl = this._gl;
-
-            this._bindTextureDirectly(gl.TEXTURE_2D, texture);
-
-            var magFilter = gl.NEAREST;
-            var minFilter = gl.NEAREST;
-
-            if (samplingMode === Texture.BILINEAR_SAMPLINGMODE) {
-                magFilter = gl.LINEAR;
-                minFilter = gl.LINEAR;
-            } else if (samplingMode === Texture.TRILINEAR_SAMPLINGMODE) {
-                magFilter = gl.LINEAR;
-                minFilter = gl.LINEAR_MIPMAP_LINEAR;
-            }
-
-            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter);
-            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter);
-
-            this._bindTextureDirectly(gl.TEXTURE_2D, null);
-
-            texture.samplingMode = samplingMode;
-        }
         /**
         /**
          * Set the compressed texture format to use, based on the formats you have, and the formats
          * Set the compressed texture format to use, based on the formats you have, and the formats
          * supported by the hardware / browser.
          * supported by the hardware / browser.
@@ -2315,7 +2292,7 @@
 
 
         public updateTextureSamplingMode(samplingMode: number, texture: WebGLTexture): void {
         public updateTextureSamplingMode(samplingMode: number, texture: WebGLTexture): void {
             var filters = getSamplingParameters(samplingMode, texture.generateMipMaps, this._gl);
             var filters = getSamplingParameters(samplingMode, texture.generateMipMaps, this._gl);
-
+ 
             if (texture.isCube) {
             if (texture.isCube) {
                 this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, texture);
                 this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, texture);
 
 
@@ -2329,6 +2306,8 @@
                 this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MIN_FILTER, filters.min);
                 this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MIN_FILTER, filters.min);
                 this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
                 this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
             }
             }
+
+             texture.samplingMode = samplingMode;
         }
         }
 
 
         public updateDynamicTexture(texture: WebGLTexture, canvas: HTMLCanvasElement, invertY: boolean, premulAlpha: boolean = false): void {
         public updateDynamicTexture(texture: WebGLTexture, canvas: HTMLCanvasElement, invertY: boolean, premulAlpha: boolean = false): void {
@@ -3157,6 +3136,7 @@
                 for (var i = 0; i < this._caps.maxVertexAttribs; i++) {
                 for (var i = 0; i < this._caps.maxVertexAttribs; i++) {
                     this._gl.disableVertexAttribArray(i);
                     this._gl.disableVertexAttribArray(i);
                     this._vertexAttribArraysEnabled[i] = false;
                     this._vertexAttribArraysEnabled[i] = false;
+                    this._currentBufferPointers[i] = null;
                 }
                 }
                 return;
                 return;
             }
             }
@@ -3168,6 +3148,7 @@
 
 
                 this._gl.disableVertexAttribArray(i);
                 this._gl.disableVertexAttribArray(i);
                 this._vertexAttribArraysEnabled[i] = false;
                 this._vertexAttribArraysEnabled[i] = false;
+                this._currentBufferPointers[i] = null;
             }
             }
         }
         }