Ver código fonte

Added TransformNode class

David Catuhe 7 anos atrás
pai
commit
b80decd966
26 arquivos alterados com 14102 adições e 13768 exclusões
  1. 3793 3761
      dist/preview release/babylon.d.ts
  2. 38 38
      dist/preview release/babylon.js
  3. 670 607
      dist/preview release/babylon.max.js
  4. 3793 3761
      dist/preview release/babylon.module.d.ts
  5. 38 38
      dist/preview release/babylon.worker.js
  6. 2201 2167
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts
  7. 39 39
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js
  8. 631 556
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js
  9. 2201 2167
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.module.d.ts
  10. 1 0
      dist/preview release/gui/babylon.gui.d.ts
  11. 13 0
      dist/preview release/gui/babylon.gui.js
  12. 3 3
      dist/preview release/gui/babylon.gui.min.js
  13. 1 0
      dist/preview release/gui/babylon.gui.module.d.ts
  14. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js
  15. 2 2
      dist/preview release/loaders/babylonjs.loaders.min.js
  16. 6 4
      dist/preview release/materialsLibrary/babylon.customMaterial.d.ts
  17. 17 23
      dist/preview release/materialsLibrary/babylon.customMaterial.js
  18. 2 2
      dist/preview release/materialsLibrary/babylon.customMaterial.min.js
  19. 17 23
      dist/preview release/materialsLibrary/babylonjs.materials.js
  20. 3 3
      dist/preview release/materialsLibrary/babylonjs.materials.min.js
  21. 6 4
      dist/preview release/materialsLibrary/babylonjs.materials.module.d.ts
  22. 1 0
      dist/preview release/what's new.md
  23. 19 566
      src/Mesh/babylon.abstractMesh.ts
  24. 1 0
      src/Mesh/babylon.mesh.ts
  25. 602 0
      src/Mesh/babylon.transformNode.ts
  26. 3 3
      src/Physics/babylon.physicsImpostor.ts

Diferenças do arquivo suprimidas por serem muito extensas
+ 3793 - 3761
dist/preview release/babylon.d.ts


Diferenças do arquivo suprimidas por serem muito extensas
+ 38 - 38
dist/preview release/babylon.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 670 - 607
dist/preview release/babylon.max.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 3793 - 3761
dist/preview release/babylon.module.d.ts


Diferenças do arquivo suprimidas por serem muito extensas
+ 38 - 38
dist/preview release/babylon.worker.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 2201 - 2167
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts


Diferenças do arquivo suprimidas por serem muito extensas
+ 39 - 39
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 631 - 556
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 2201 - 2167
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.module.d.ts


+ 1 - 0
dist/preview release/gui/babylon.gui.d.ts

@@ -36,6 +36,7 @@ declare module BABYLON.GUI {
         readonly layer: Nullable<Layer>;
         readonly rootContainer: Container;
         focusedControl: Nullable<IFocusableControl>;
+        isForeground: boolean;
         constructor(name: string, width: number | undefined, height: number | undefined, scene: Nullable<Scene>, generateMipMaps?: boolean, samplingMode?: number);
         executeOnAllControls(func: (control: Control) => void, container?: Container): void;
         markAsDirty(): void;

+ 13 - 0
dist/preview release/gui/babylon.gui.js

@@ -154,6 +154,19 @@ var BABYLON;
                 enumerable: true,
                 configurable: true
             });
+            Object.defineProperty(AdvancedDynamicTexture.prototype, "isForeground", {
+                get: function () {
+                    return (!this.layer.isBackground);
+                },
+                set: function (value) {
+                    if (this.layer.isBackground === !value) {
+                        return;
+                    }
+                    this.layer.isBackground = !value;
+                },
+                enumerable: true,
+                configurable: true
+            });
             AdvancedDynamicTexture.prototype.executeOnAllControls = function (func, container) {
                 if (!container) {
                     container = this._rootContainer;

Diferenças do arquivo suprimidas por serem muito extensas
+ 3 - 3
dist/preview release/gui/babylon.gui.min.js


+ 1 - 0
dist/preview release/gui/babylon.gui.module.d.ts

@@ -41,6 +41,7 @@ declare module BABYLON.GUI {
         readonly layer: Nullable<Layer>;
         readonly rootContainer: Container;
         focusedControl: Nullable<IFocusableControl>;
+        isForeground: boolean;
         constructor(name: string, width: number | undefined, height: number | undefined, scene: Nullable<Scene>, generateMipMaps?: boolean, samplingMode?: number);
         executeOnAllControls(func: (control: Control) => void, container?: Container): void;
         markAsDirty(): void;

Diferenças do arquivo suprimidas por serem muito extensas
+ 1 - 1
dist/preview release/loaders/babylon.objFileLoader.min.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 2 - 2
dist/preview release/loaders/babylonjs.loaders.min.js


+ 6 - 4
dist/preview release/materialsLibrary/babylon.customMaterial.d.ts

@@ -54,12 +54,15 @@ declare module BABYLON {
         REFRACTION: boolean;
         REFRACTIONMAP_3D: boolean;
         REFLECTIONOVERALPHA: boolean;
+        INVERTNORMALMAPX: boolean;
+        INVERTNORMALMAPY: boolean;
         TWOSIDEDLIGHTING: boolean;
         SHADOWFLOAT: boolean;
         MORPHTARGETS: boolean;
         MORPHTARGETS_NORMAL: boolean;
         MORPHTARGETS_TANGENT: boolean;
         NUM_MORPH_INFLUENCERS: number;
+        USERIGHTHANDEDSYSTEM: boolean;
         IMAGEPROCESSING: boolean;
         VIGNETTE: boolean;
         VIGNETTEBLENDMODEMULTIPLY: boolean;
@@ -68,7 +71,6 @@ declare module BABYLON {
         CONTRAST: boolean;
         COLORCURVES: boolean;
         COLORGRADING: boolean;
-        COLORGRADING3D: boolean;
         SAMPLER3DGREENDEPTH: boolean;
         SAMPLER3DBGRMAP: boolean;
         IMAGEPROCESSINGPOSTPROCESS: boolean;
@@ -175,7 +177,7 @@ declare module BABYLON {
          * Attaches a new image processing configuration to the Standard Material.
          * @param configuration
          */
-        protected _attachImageProcessingConfiguration(configuration: Nullable<ImageProcessingConfiguration>): void;
+        protected _attachImageProcessingConfiguration(configuration: ImageProcessingConfiguration): void;
         /**
          * Gets wether the color curves effect is enabled.
          */
@@ -221,7 +223,7 @@ declare module BABYLON {
         /**
          * Sets the Color Grading 2D Lookup Texture.
          */
-        cameraColorGradingTexture: Nullable<BaseTexture>;
+        cameraColorGradingTexture: BaseTexture;
         customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: StandardMaterialDefines_OldVer) => string;
         protected _renderTargets: SmartArray<RenderTargetTexture>;
         protected _worldViewProjectionMatrix: Matrix;
@@ -293,7 +295,7 @@ declare module BABYLON {
         constructor();
     }
     class StandardShaderVersions {
-        static Ver3_0: string;
+        static Ver3_0: any;
     }
     class CustomMaterial extends StandardMaterial_OldVer {
         static ShaderIndexer: number;

+ 17 - 23
dist/preview release/materialsLibrary/babylon.customMaterial.js

@@ -75,12 +75,15 @@ var BABYLON;
             _this.REFRACTION = false;
             _this.REFRACTIONMAP_3D = false;
             _this.REFLECTIONOVERALPHA = false;
+            _this.INVERTNORMALMAPX = false;
+            _this.INVERTNORMALMAPY = false;
             _this.TWOSIDEDLIGHTING = false;
             _this.SHADOWFLOAT = false;
             _this.MORPHTARGETS = false;
             _this.MORPHTARGETS_NORMAL = false;
             _this.MORPHTARGETS_TANGENT = false;
             _this.NUM_MORPH_INFLUENCERS = 0;
+            _this.USERIGHTHANDEDSYSTEM = false;
             _this.IMAGEPROCESSING = false;
             _this.VIGNETTE = false;
             _this.VIGNETTEBLENDMODEMULTIPLY = false;
@@ -89,7 +92,6 @@ var BABYLON;
             _this.CONTRAST = false;
             _this.COLORCURVES = false;
             _this.COLORGRADING = false;
-            _this.COLORGRADING3D = false;
             _this.SAMPLER3DGREENDEPTH = false;
             _this.SAMPLER3DBGRMAP = false;
             _this.IMAGEPROCESSINGPOSTPROCESS = false;
@@ -496,6 +498,8 @@ var BABYLON;
                         else {
                             defines._needUVs = true;
                             defines.BUMP = true;
+                            defines.INVERTNORMALMAPX = this.invertNormalMapX;
+                            defines.INVERTNORMALMAPY = this.invertNormalMapY;
                             defines.PARALLAX = this._useParallax;
                             defines.PARALLAXOCCLUSION = this._useParallaxOcclusion;
                         }
@@ -564,7 +568,12 @@ var BABYLON;
             // Attribs
             BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true, true);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
+            if (scene._mirroredCameraPosition && defines.BUMP) {
+                defines.INVERTNORMALMAPX = !this.invertNormalMapX;
+                defines.INVERTNORMALMAPY = !this.invertNormalMapY;
+                defines.markAsUnprocessed();
+            }
             // Get correct effect      
             if (defines.isDirty) {
                 defines.markAsProcessed();
@@ -641,7 +650,7 @@ var BABYLON;
                     "mBones",
                     "vClipPlane", "diffuseMatrix", "ambientMatrix", "opacityMatrix", "reflectionMatrix", "emissiveMatrix", "specularMatrix", "bumpMatrix", "lightmapMatrix", "refractionMatrix",
                     "diffuseLeftColor", "diffuseRightColor", "opacityParts", "reflectionLeftColor", "reflectionRightColor", "emissiveLeftColor", "emissiveRightColor", "refractionLeftColor", "refractionRightColor",
-                    "logarithmicDepthConstant", "vTangentSpaceParams"
+                    "logarithmicDepthConstant"
                 ];
                 var samplers = ["diffuseSampler", "ambientSampler", "opacitySampler", "reflectionCubeSampler", "reflection2DSampler", "emissiveSampler", "specularSampler", "bumpSampler", "lightmapSampler", "refractionCubeSampler", "refraction2DSampler"];
                 var uniformBuffers = ["Material", "Scene"];
@@ -671,7 +680,7 @@ var BABYLON;
                 }, engine), defines);
                 this.buildUniformLayout();
             }
-            if (!subMesh.effect || !subMesh.effect.isReady()) {
+            if (!subMesh.effect.isReady()) {
                 return false;
             }
             defines._renderId = scene.getRenderId();
@@ -705,7 +714,6 @@ var BABYLON;
             this._uniformBuffer.addUniform("lightmapMatrix", 16);
             this._uniformBuffer.addUniform("specularMatrix", 16);
             this._uniformBuffer.addUniform("bumpMatrix", 16);
-            this._uniformBuffer.addUniform("vTangentSpaceParams", 2);
             this._uniformBuffer.addUniform("refractionMatrix", 16);
             this._uniformBuffer.addUniform("vRefractionInfos", 4);
             this._uniformBuffer.addUniform("vSpecularColor", 4);
@@ -732,9 +740,6 @@ var BABYLON;
                 return;
             }
             var effect = subMesh.effect;
-            if (!effect) {
-                return;
-            }
             this._activeEffect = effect;
             // Matrices        
             this.bindOnlyWorldMatrix(world);
@@ -799,12 +804,6 @@ var BABYLON;
                         if (this._bumpTexture && scene.getEngine().getCaps().standardDerivatives && StandardMaterial_OldVer.BumpTextureEnabled) {
                             this._uniformBuffer.updateFloat3("vBumpInfos", this._bumpTexture.coordinatesIndex, 1.0 / this._bumpTexture.level, this.parallaxScaleBias);
                             this._uniformBuffer.updateMatrix("bumpMatrix", this._bumpTexture.getTextureMatrix());
-                            if (scene._mirroredCameraPosition) {
-                                this._uniformBuffer.updateFloat2("vTangentSpaceParams", this._invertNormalMapX ? 1.0 : -1.0, this._invertNormalMapY ? 1.0 : -1.0);
-                            }
-                            else {
-                                this._uniformBuffer.updateFloat2("vTangentSpaceParams", this._invertNormalMapX ? -1.0 : 1.0, this._invertNormalMapY ? -1.0 : 1.0);
-                            }
                         }
                         if (this._refractionTexture && StandardMaterial_OldVer.RefractionTextureEnabled) {
                             var depth = 1.0;
@@ -873,7 +872,7 @@ var BABYLON;
                 BABYLON.MaterialHelper.BindClipPlane(effect, scene);
                 // Colors
                 scene.ambientColor.multiplyToRef(this.ambientColor, this._globalAmbientColor);
-                BABYLON.MaterialHelper.BindEyePosition(effect, scene);
+                effect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);
                 effect.setColor3("vAmbientColor", this._globalAmbientColor);
             }
             if (this._mustRebind(scene, effect) || !this.isFrozen) {
@@ -1902,7 +1901,6 @@ vColor=color;\n\
     var StandardShaderVersions = /** @class */ (function () {
         function StandardShaderVersions() {
         }
-        StandardShaderVersions.Ver3_0 = "3.0.0";
         return StandardShaderVersions;
     }());
     BABYLON.StandardShaderVersions = StandardShaderVersions;
@@ -1949,20 +1947,16 @@ vColor=color;\n\
             return arr;
         };
         CustomMaterial.prototype.Builder = function (shaderName, uniforms, uniformBuffers, samplers, defines) {
-            var _this = this;
             if (this._isCreatedShader)
                 return this._createdShaderName;
             this._isCreatedShader = false;
             CustomMaterial.ShaderIndexer++;
-            var name = "custom_" + CustomMaterial.ShaderIndexer;
+            var name = name + "custom_" + CustomMaterial.ShaderIndexer;
             this.ReviewUniform("uniform", uniforms);
             this.ReviewUniform("sampler", samplers);
             var fn_afterBind = this._afterBind;
             this._afterBind = function (m, e) {
-                if (!e) {
-                    return;
-                }
-                _this.AttachAfterBind(m, e);
+                this.AttachAfterBind(m, e);
                 try {
                     fn_afterBind(m, e);
                 }
@@ -2005,7 +1999,7 @@ vColor=color;\n\
                     this._newUniformInstances[kind + "-" + name] = param;
                 }
                 else {
-                    this._newUniformInstances[kind + "-" + name] = param;
+                    this._newSamplerInstances[kind + "-" + name] = param;
                 }
             }
             this._customUniform.push("uniform " + kind + " " + name + ";");

Diferenças do arquivo suprimidas por serem muito extensas
+ 2 - 2
dist/preview release/materialsLibrary/babylon.customMaterial.min.js


+ 17 - 23
dist/preview release/materialsLibrary/babylonjs.materials.js

@@ -4054,12 +4054,15 @@ var BABYLON;
             _this.REFRACTION = false;
             _this.REFRACTIONMAP_3D = false;
             _this.REFLECTIONOVERALPHA = false;
+            _this.INVERTNORMALMAPX = false;
+            _this.INVERTNORMALMAPY = false;
             _this.TWOSIDEDLIGHTING = false;
             _this.SHADOWFLOAT = false;
             _this.MORPHTARGETS = false;
             _this.MORPHTARGETS_NORMAL = false;
             _this.MORPHTARGETS_TANGENT = false;
             _this.NUM_MORPH_INFLUENCERS = 0;
+            _this.USERIGHTHANDEDSYSTEM = false;
             _this.IMAGEPROCESSING = false;
             _this.VIGNETTE = false;
             _this.VIGNETTEBLENDMODEMULTIPLY = false;
@@ -4068,7 +4071,6 @@ var BABYLON;
             _this.CONTRAST = false;
             _this.COLORCURVES = false;
             _this.COLORGRADING = false;
-            _this.COLORGRADING3D = false;
             _this.SAMPLER3DGREENDEPTH = false;
             _this.SAMPLER3DBGRMAP = false;
             _this.IMAGEPROCESSINGPOSTPROCESS = false;
@@ -4475,6 +4477,8 @@ var BABYLON;
                         else {
                             defines._needUVs = true;
                             defines.BUMP = true;
+                            defines.INVERTNORMALMAPX = this.invertNormalMapX;
+                            defines.INVERTNORMALMAPY = this.invertNormalMapY;
                             defines.PARALLAX = this._useParallax;
                             defines.PARALLAXOCCLUSION = this._useParallaxOcclusion;
                         }
@@ -4543,7 +4547,12 @@ var BABYLON;
             // Attribs
             BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true, true);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
+            if (scene._mirroredCameraPosition && defines.BUMP) {
+                defines.INVERTNORMALMAPX = !this.invertNormalMapX;
+                defines.INVERTNORMALMAPY = !this.invertNormalMapY;
+                defines.markAsUnprocessed();
+            }
             // Get correct effect      
             if (defines.isDirty) {
                 defines.markAsProcessed();
@@ -4620,7 +4629,7 @@ var BABYLON;
                     "mBones",
                     "vClipPlane", "diffuseMatrix", "ambientMatrix", "opacityMatrix", "reflectionMatrix", "emissiveMatrix", "specularMatrix", "bumpMatrix", "lightmapMatrix", "refractionMatrix",
                     "diffuseLeftColor", "diffuseRightColor", "opacityParts", "reflectionLeftColor", "reflectionRightColor", "emissiveLeftColor", "emissiveRightColor", "refractionLeftColor", "refractionRightColor",
-                    "logarithmicDepthConstant", "vTangentSpaceParams"
+                    "logarithmicDepthConstant"
                 ];
                 var samplers = ["diffuseSampler", "ambientSampler", "opacitySampler", "reflectionCubeSampler", "reflection2DSampler", "emissiveSampler", "specularSampler", "bumpSampler", "lightmapSampler", "refractionCubeSampler", "refraction2DSampler"];
                 var uniformBuffers = ["Material", "Scene"];
@@ -4650,7 +4659,7 @@ var BABYLON;
                 }, engine), defines);
                 this.buildUniformLayout();
             }
-            if (!subMesh.effect || !subMesh.effect.isReady()) {
+            if (!subMesh.effect.isReady()) {
                 return false;
             }
             defines._renderId = scene.getRenderId();
@@ -4684,7 +4693,6 @@ var BABYLON;
             this._uniformBuffer.addUniform("lightmapMatrix", 16);
             this._uniformBuffer.addUniform("specularMatrix", 16);
             this._uniformBuffer.addUniform("bumpMatrix", 16);
-            this._uniformBuffer.addUniform("vTangentSpaceParams", 2);
             this._uniformBuffer.addUniform("refractionMatrix", 16);
             this._uniformBuffer.addUniform("vRefractionInfos", 4);
             this._uniformBuffer.addUniform("vSpecularColor", 4);
@@ -4711,9 +4719,6 @@ var BABYLON;
                 return;
             }
             var effect = subMesh.effect;
-            if (!effect) {
-                return;
-            }
             this._activeEffect = effect;
             // Matrices        
             this.bindOnlyWorldMatrix(world);
@@ -4778,12 +4783,6 @@ var BABYLON;
                         if (this._bumpTexture && scene.getEngine().getCaps().standardDerivatives && StandardMaterial_OldVer.BumpTextureEnabled) {
                             this._uniformBuffer.updateFloat3("vBumpInfos", this._bumpTexture.coordinatesIndex, 1.0 / this._bumpTexture.level, this.parallaxScaleBias);
                             this._uniformBuffer.updateMatrix("bumpMatrix", this._bumpTexture.getTextureMatrix());
-                            if (scene._mirroredCameraPosition) {
-                                this._uniformBuffer.updateFloat2("vTangentSpaceParams", this._invertNormalMapX ? 1.0 : -1.0, this._invertNormalMapY ? 1.0 : -1.0);
-                            }
-                            else {
-                                this._uniformBuffer.updateFloat2("vTangentSpaceParams", this._invertNormalMapX ? -1.0 : 1.0, this._invertNormalMapY ? -1.0 : 1.0);
-                            }
                         }
                         if (this._refractionTexture && StandardMaterial_OldVer.RefractionTextureEnabled) {
                             var depth = 1.0;
@@ -4852,7 +4851,7 @@ var BABYLON;
                 BABYLON.MaterialHelper.BindClipPlane(effect, scene);
                 // Colors
                 scene.ambientColor.multiplyToRef(this.ambientColor, this._globalAmbientColor);
-                BABYLON.MaterialHelper.BindEyePosition(effect, scene);
+                effect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);
                 effect.setColor3("vAmbientColor", this._globalAmbientColor);
             }
             if (this._mustRebind(scene, effect) || !this.isFrozen) {
@@ -5881,7 +5880,6 @@ vColor=color;\n\
     var StandardShaderVersions = /** @class */ (function () {
         function StandardShaderVersions() {
         }
-        StandardShaderVersions.Ver3_0 = "3.0.0";
         return StandardShaderVersions;
     }());
     BABYLON.StandardShaderVersions = StandardShaderVersions;
@@ -5928,20 +5926,16 @@ vColor=color;\n\
             return arr;
         };
         CustomMaterial.prototype.Builder = function (shaderName, uniforms, uniformBuffers, samplers, defines) {
-            var _this = this;
             if (this._isCreatedShader)
                 return this._createdShaderName;
             this._isCreatedShader = false;
             CustomMaterial.ShaderIndexer++;
-            var name = "custom_" + CustomMaterial.ShaderIndexer;
+            var name = name + "custom_" + CustomMaterial.ShaderIndexer;
             this.ReviewUniform("uniform", uniforms);
             this.ReviewUniform("sampler", samplers);
             var fn_afterBind = this._afterBind;
             this._afterBind = function (m, e) {
-                if (!e) {
-                    return;
-                }
-                _this.AttachAfterBind(m, e);
+                this.AttachAfterBind(m, e);
                 try {
                     fn_afterBind(m, e);
                 }
@@ -5984,7 +5978,7 @@ vColor=color;\n\
                     this._newUniformInstances[kind + "-" + name] = param;
                 }
                 else {
-                    this._newUniformInstances[kind + "-" + name] = param;
+                    this._newSamplerInstances[kind + "-" + name] = param;
                 }
             }
             this._customUniform.push("uniform " + kind + " " + name + ";");

Diferenças do arquivo suprimidas por serem muito extensas
+ 3 - 3
dist/preview release/materialsLibrary/babylonjs.materials.min.js


+ 6 - 4
dist/preview release/materialsLibrary/babylonjs.materials.module.d.ts

@@ -558,12 +558,15 @@ declare module BABYLON {
         REFRACTION: boolean;
         REFRACTIONMAP_3D: boolean;
         REFLECTIONOVERALPHA: boolean;
+        INVERTNORMALMAPX: boolean;
+        INVERTNORMALMAPY: boolean;
         TWOSIDEDLIGHTING: boolean;
         SHADOWFLOAT: boolean;
         MORPHTARGETS: boolean;
         MORPHTARGETS_NORMAL: boolean;
         MORPHTARGETS_TANGENT: boolean;
         NUM_MORPH_INFLUENCERS: number;
+        USERIGHTHANDEDSYSTEM: boolean;
         IMAGEPROCESSING: boolean;
         VIGNETTE: boolean;
         VIGNETTEBLENDMODEMULTIPLY: boolean;
@@ -572,7 +575,6 @@ declare module BABYLON {
         CONTRAST: boolean;
         COLORCURVES: boolean;
         COLORGRADING: boolean;
-        COLORGRADING3D: boolean;
         SAMPLER3DGREENDEPTH: boolean;
         SAMPLER3DBGRMAP: boolean;
         IMAGEPROCESSINGPOSTPROCESS: boolean;
@@ -679,7 +681,7 @@ declare module BABYLON {
          * Attaches a new image processing configuration to the Standard Material.
          * @param configuration
          */
-        protected _attachImageProcessingConfiguration(configuration: Nullable<ImageProcessingConfiguration>): void;
+        protected _attachImageProcessingConfiguration(configuration: ImageProcessingConfiguration): void;
         /**
          * Gets wether the color curves effect is enabled.
          */
@@ -725,7 +727,7 @@ declare module BABYLON {
         /**
          * Sets the Color Grading 2D Lookup Texture.
          */
-        cameraColorGradingTexture: Nullable<BaseTexture>;
+        cameraColorGradingTexture: BaseTexture;
         customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: StandardMaterialDefines_OldVer) => string;
         protected _renderTargets: SmartArray<RenderTargetTexture>;
         protected _worldViewProjectionMatrix: Matrix;
@@ -797,7 +799,7 @@ declare module BABYLON {
         constructor();
     }
     class StandardShaderVersions {
-        static Ver3_0: string;
+        static Ver3_0: any;
     }
     class CustomMaterial extends StandardMaterial_OldVer {
         static ShaderIndexer: number;

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

@@ -22,6 +22,7 @@
 - Complete rework of Unity3D exporter. [Doc here](http://doc.babylonjs.com/resources/intro) ([MackeyK24](https://github.com/MackeyK24))
 
 ## Updates
+- Introduced `TransformNode` class as a parent of `AbstractMesh`. This class was extensively asked by the community to hold only tranformation for a node ([deltakosh](https://github.com/deltakosh))
 - Added `boundingInfo.centerOn` to recreate the bounding info to be centered around a specific point given a specific extend ([deltakosh](https://github.com/deltakosh))
 - Added `mesh.normalizeToUnitCube` to uniformly scales the mesh to fit inside of a unit cube (1 X 1 X 1 units) ([deltakosh](https://github.com/deltakosh))
 - Added `scene.onDataLoadedObservable` which is raised when SceneLoader.Append or SceneLoader.Load or SceneLoader.ImportMesh were successfully executed ([deltakosh](https://github.com/deltakosh))

+ 19 - 566
src/Mesh/babylon.abstractMesh.ts

@@ -1,12 +1,5 @@
 module BABYLON {
-    export class AbstractMesh extends Node implements IDisposable, ICullable, IGetSetVerticesData {
-        // Statics
-        private static _BILLBOARDMODE_NONE = 0;
-        private static _BILLBOARDMODE_X = 1;
-        private static _BILLBOARDMODE_Y = 2;
-        private static _BILLBOARDMODE_Z = 4;
-        private static _BILLBOARDMODE_ALL = 7;
-
+    export class AbstractMesh extends TransformNode implements IDisposable, ICullable, IGetSetVerticesData {
         public static OCCLUSION_TYPE_NONE = 0;
         public static OCCLUSION_TYPE_OPTIMISTIC = 1;
         public static OCCLUSION_TYPE_STRICT = 2;
@@ -14,23 +7,23 @@
         public static OCCLUSION_ALGORITHM_TYPE_CONSERVATIVE = 1;
 
         public static get BILLBOARDMODE_NONE(): number {
-            return AbstractMesh._BILLBOARDMODE_NONE;
+            return TransformNode.BILLBOARDMODE_NONE;
         }
 
         public static get BILLBOARDMODE_X(): number {
-            return AbstractMesh._BILLBOARDMODE_X;
+            return TransformNode.BILLBOARDMODE_X;
         }
 
         public static get BILLBOARDMODE_Y(): number {
-            return AbstractMesh._BILLBOARDMODE_Y;
+            return TransformNode.BILLBOARDMODE_Y;
         }
 
         public static get BILLBOARDMODE_Z(): number {
-            return AbstractMesh._BILLBOARDMODE_Z;
+            return TransformNode.BILLBOARDMODE_Z;
         }
 
         public static get BILLBOARDMODE_ALL(): number {
-            return AbstractMesh._BILLBOARDMODE_ALL;
+            return TransformNode.BILLBOARDMODE_ALL;
         }
 
         // facetData private properties
@@ -110,18 +103,12 @@
             return this._facetDataEnabled;
         }
 
-        // Normal matrix
-        private _nonUniformScaling = false;
-        public get nonUniformScaling(): boolean {
-            return this._nonUniformScaling;
-        }
-
-        public set nonUniformScaling(value: boolean) {
-            if (this._nonUniformScaling === value) {
-                return;
+        public _updateNonUniformScalingState(value: boolean): boolean {
+            if (!super._updateNonUniformScalingState(value)) {
+                return false;
             }
-            this._nonUniformScaling = true;
             this._markSubMeshesAsMiscDirty();
+            return true;
         }
 
         // Events
@@ -155,12 +142,6 @@
         }
 
         /**
-        * An event triggered after the world matrix is updated
-        * @type {BABYLON.Observable}
-        */
-        public onAfterWorldMatrixUpdateObservable = new Observable<AbstractMesh>();
-
-        /**
         * An event triggered when material is changed
         * @type {BABYLON.Observable}
         */
@@ -168,7 +149,6 @@
 
         // Properties
         public definedFacingForward = true; // orientation for POV movement & rotation
-        public position = Vector3.Zero();
 
         /**
         * This property determines the type of occlusion query algorithm to run in WebGl, you can use:
@@ -222,13 +202,8 @@
 
         private _occlusionQuery: Nullable<WebGLQuery>;
 
-        private _rotation = Vector3.Zero();
-        private _rotationQuaternion: Nullable<Quaternion>;
-        private _scaling = Vector3.One();
-        public billboardMode = AbstractMesh.BILLBOARDMODE_NONE;
         public visibility = 1.0;
         public alphaIndex = Number.MAX_VALUE;
-        public infiniteDistance = false;
         public isVisible = true;
         public isPickable = true;
         public showBoundingBox = false;
@@ -345,8 +320,6 @@
             this._markSubMeshesAsMiscDirty();
         }
 
-        public scalingDeterminant = 1;
-
         public useOctreeForRenderingSelection = true;
         public useOctreeForPicking = true;
         public useOctreeForCollisions = true;
@@ -407,27 +380,17 @@
             this._collisionGroup = !isNaN(mask) ? mask : -1;
         }
 
-        // Attach to bone
-        private _meshToBoneReferal: Nullable<AbstractMesh>;
-
         // Edges
         public edgesWidth = 1;
         public edgesColor = new Color4(1, 0, 0, 1);
         public _edgesRenderer: Nullable<EdgesRenderer>;
 
         // Cache
-        private _localWorld = Matrix.Zero();
-        public _worldMatrix = Matrix.Zero();
-        private _absolutePosition = Vector3.Zero();
         private _collisionsTransformMatrix = Matrix.Zero();
         private _collisionsScalingMatrix = Matrix.Zero();
-        private _isDirty = false;
         public _masterMesh: Nullable<AbstractMesh>;
 
         public _boundingInfo: Nullable<BoundingInfo>;
-        private _pivotMatrix = Matrix.Identity();
-        private _pivotMatrixInverse: Matrix;
-        private _postMultiplyPivotMatrix = false;
         public _isDisposed = false;
         public _renderId = 0;
 
@@ -435,12 +398,8 @@
         public _submeshesOctree: Octree<SubMesh>;
         public _intersectionsInProgress = new Array<AbstractMesh>();
 
-        private _isWorldMatrixFrozen = false;
-
         public _unIndexed = false;
 
-        public _poseMatrix: Matrix;
-
         public _lightSources = new Array<Light>();
 
         public get _positions(): Nullable<Vector3[]> {
@@ -612,20 +571,7 @@
             }
         }
 
-        /**
-         * Rotation property : a Vector3 depicting the rotation value in radians around each local axis X, Y, Z. 
-         * If rotation quaternion is set, this Vector3 will (almost always) be the Zero vector!
-         * Default : (0.0, 0.0, 0.0)
-         */
-        public get rotation(): Vector3 {
-            return this._rotation;
-        }
-
-        public set rotation(newRotation: Vector3) {
-            this._rotation = newRotation;
-        }
-
-        /**
+         /**
          * Scaling property : a Vector3 depicting the mesh scaling along each local axis X, Y, Z.  
          * Default : (1.0, 1.0, 1.0)
          */
@@ -633,6 +579,10 @@
             return this._scaling;
         }
 
+        /**
+         * Scaling property : a Vector3 depicting the mesh scaling along each local axis X, Y, Z.  
+         * Default : (1.0, 1.0, 1.0)
+         */
         public set scaling(newScaling: Vector3) {
             this._scaling = newScaling;
             if (this.physicsImpostor) {
@@ -640,23 +590,6 @@
             }
         }
 
-        /**
-         * Rotation Quaternion property : this a Quaternion object depicting the mesh rotation by using a unit quaternion. 
-         * It's null by default.  
-         * If set, only the rotationQuaternion is then used to compute the mesh rotation and its property `.rotation\ is then ignored and set to (0.0, 0.0, 0.0)
-         */
-        public get rotationQuaternion(): Nullable<Quaternion> {
-            return this._rotationQuaternion;
-        }
-
-        public set rotationQuaternion(quaternion: Nullable<Quaternion>) {
-            this._rotationQuaternion = quaternion;
-            //reset the rotation vector. 
-            if (quaternion && this.rotation.length()) {
-                this.rotation.copyFromFloats(0.0, 0.0, 0.0);
-            }
-        }
-
         // Methods
         /**
          * Copies the paramater passed Matrix into the mesh Pose matrix.  
@@ -878,54 +811,7 @@
                 return this._masterMesh.getWorldMatrix();
             }
 
-            if (this._currentRenderId !== this.getScene().getRenderId()) {
-                this.computeWorldMatrix();
-            }
-            return this._worldMatrix;
-        }
-
-        /**
-         * Returns directly the latest state of the mesh World matrix. 
-         * A Matrix is returned.    
-         */
-        public get worldMatrixFromCache(): Matrix {
-            return this._worldMatrix;
-        }
-
-        /**
-         * Returns the current mesh absolute position.
-         * Retuns a Vector3.
-         */
-        public get absolutePosition(): Vector3 {
-            return this._absolutePosition;
-        }
-        /**
-         * Prevents the World matrix to be computed any longer.
-         * Returns the AbstractMesh.  
-         */
-        public freezeWorldMatrix(): AbstractMesh {
-            this._isWorldMatrixFrozen = false;  // no guarantee world is not already frozen, switch off temporarily
-            this.computeWorldMatrix(true);
-            this._isWorldMatrixFrozen = true;
-            return this;
-        }
-
-        /**
-         * Allows back the World matrix computation. 
-         * Returns the AbstractMesh.  
-         */
-        public unfreezeWorldMatrix() {
-            this._isWorldMatrixFrozen = false;
-            this.computeWorldMatrix(true);
-            return this;
-        }
-
-        /**
-         * True if the World matrix has been frozen.  
-         * Returns a boolean.  
-         */
-        public get isWorldMatrixFrozen(): boolean {
-            return this._isWorldMatrixFrozen;
+            return super.getWorldMatrix();
         }
 
         private static _rotationAxisCache = new Quaternion();
@@ -1036,51 +922,7 @@
             return this;
         }
 
-        /**
-         * Retuns the mesh absolute position in the World.  
-         * Returns a Vector3.
-         */
-        public getAbsolutePosition(): Vector3 {
-            this.computeWorldMatrix();
-            return this._absolutePosition;
-        }
-
-        /**
-         * Sets the mesh absolute position in the World from a Vector3 or an Array(3).
-         * Returns the AbstractMesh.  
-         */
-        public setAbsolutePosition(absolutePosition: Vector3): AbstractMesh {
-            if (!absolutePosition) {
-                return this;
-            }
-            var absolutePositionX;
-            var absolutePositionY;
-            var absolutePositionZ;
-            if (absolutePosition.x === undefined) {
-                if (arguments.length < 3) {
-                    return this;
-                }
-                absolutePositionX = arguments[0];
-                absolutePositionY = arguments[1];
-                absolutePositionZ = arguments[2];
-            }
-            else {
-                absolutePositionX = absolutePosition.x;
-                absolutePositionY = absolutePosition.y;
-                absolutePositionZ = absolutePosition.z;
-            }
-            if (this.parent) {
-                var invertParentWorldMatrix = this.parent.getWorldMatrix().clone();
-                invertParentWorldMatrix.invert();
-                var worldPosition = new Vector3(absolutePositionX, absolutePositionY, absolutePositionZ);
-                this.position = Vector3.TransformCoordinates(worldPosition, invertParentWorldMatrix);
-            } else {
-                this.position.x = absolutePositionX;
-                this.position.y = absolutePositionY;
-                this.position.z = absolutePositionZ;
-            }
-            return this;
-        }
+   
 
         // ================================== Point of View Movement =================================
         /**
@@ -1147,30 +989,6 @@
             return new Vector3(flipBack * defForwardMult, twirlClockwise, tiltRight * defForwardMult);
         }
 
-        /**
-         * Sets a new pivot matrix to the mesh.  
-         * Returns the AbstractMesh.
-         */
-        public setPivotMatrix(matrix: Matrix, postMultiplyPivotMatrix = false): AbstractMesh {
-            this._pivotMatrix = matrix.clone();
-            this._cache.pivotMatrixUpdated = true;
-            this._postMultiplyPivotMatrix = postMultiplyPivotMatrix;
-
-            if (this._postMultiplyPivotMatrix) {
-                this._pivotMatrixInverse = Matrix.Invert(matrix);
-            }
-            return this;
-        }
-
-        /**
-         * Returns the mesh pivot matrix.
-         * Default : Identity.  
-         * A Matrix is returned.  
-         */
-        public getPivotMatrix(): Matrix {
-            return this._pivotMatrix;
-        }
-
         public _isSynchronized(): boolean {
             if (this._isDirty) {
                 return false;
@@ -1299,173 +1117,9 @@
             return this;
         }
 
-        /**
-         * Computes the mesh World matrix and returns it.  
-         * If the mesh world matrix is frozen, this computation does nothing more than returning the last frozen values.  
-         * If the parameter `force` is let to `false` (default), the current cached World matrix is returned. 
-         * If the parameter `force`is set to `true`, the actual computation is done.  
-         * Returns the mesh World Matrix.
-         */
-        public computeWorldMatrix(force?: boolean): Matrix {
-            if (this._isWorldMatrixFrozen) {
-                return this._worldMatrix;
-            }
-
-            if (!force && this.isSynchronized(true)) {
-                return this._worldMatrix;
-            }
-
-            this._cache.position.copyFrom(this.position);
-            this._cache.scaling.copyFrom(this.scaling);
-            this._cache.pivotMatrixUpdated = false;
-            this._cache.billboardMode = this.billboardMode;
-            this._currentRenderId = this.getScene().getRenderId();
-            this._isDirty = false;
-
-            // Scaling
-            Matrix.ScalingToRef(this.scaling.x * this.scalingDeterminant, this.scaling.y * this.scalingDeterminant, this.scaling.z * this.scalingDeterminant, Tmp.Matrix[1]);
-
-            // Rotation
-
-            //rotate, if quaternion is set and rotation was used
-            if (this.rotationQuaternion) {
-                var len = this.rotation.length();
-                if (len) {
-                    this.rotationQuaternion.multiplyInPlace(BABYLON.Quaternion.RotationYawPitchRoll(this.rotation.y, this.rotation.x, this.rotation.z))
-                    this.rotation.copyFromFloats(0, 0, 0);
-                }
-            }
-
-            if (this.rotationQuaternion) {
-                this.rotationQuaternion.toRotationMatrix(Tmp.Matrix[0]);
-                this._cache.rotationQuaternion.copyFrom(this.rotationQuaternion);
-            } else {
-                Matrix.RotationYawPitchRollToRef(this.rotation.y, this.rotation.x, this.rotation.z, Tmp.Matrix[0]);
-                this._cache.rotation.copyFrom(this.rotation);
-            }
-
-            // Translation
-            let camera = (<Camera>this.getScene().activeCamera);
-            
-            if (this.infiniteDistance && !this.parent && camera) {
-
-                var cameraWorldMatrix = camera.getWorldMatrix();
-
-                var cameraGlobalPosition = new Vector3(cameraWorldMatrix.m[12], cameraWorldMatrix.m[13], cameraWorldMatrix.m[14]);
-
-                Matrix.TranslationToRef(this.position.x + cameraGlobalPosition.x, this.position.y + cameraGlobalPosition.y,
-                    this.position.z + cameraGlobalPosition.z, Tmp.Matrix[2]);
-            } else {
-                Matrix.TranslationToRef(this.position.x, this.position.y, this.position.z, Tmp.Matrix[2]);
-            }
-
-            // Composing transformations
-            this._pivotMatrix.multiplyToRef(Tmp.Matrix[1], Tmp.Matrix[4]);
-            Tmp.Matrix[4].multiplyToRef(Tmp.Matrix[0], Tmp.Matrix[5]);
-
-            // Billboarding (testing PG:http://www.babylonjs-playground.com/#UJEIL#13)
-            if (this.billboardMode !== AbstractMesh.BILLBOARDMODE_NONE && camera) {
-                if ((this.billboardMode & AbstractMesh.BILLBOARDMODE_ALL) !== AbstractMesh.BILLBOARDMODE_ALL) {
-                    // Need to decompose each rotation here
-                    var currentPosition = Tmp.Vector3[3];
-
-                    if (this.parent && this.parent.getWorldMatrix) {
-                        if (this._meshToBoneReferal) {
-                            this.parent.getWorldMatrix().multiplyToRef(this._meshToBoneReferal.getWorldMatrix(), Tmp.Matrix[6]);
-                            Vector3.TransformCoordinatesToRef(this.position, Tmp.Matrix[6], currentPosition);
-                        } else {
-                            Vector3.TransformCoordinatesToRef(this.position, this.parent.getWorldMatrix(), currentPosition);
-                        }
-                    } else {
-                        currentPosition.copyFrom(this.position);
-                    }
-
-                    currentPosition.subtractInPlace(camera.globalPosition);
-
-                    var finalEuler = Tmp.Vector3[4].copyFromFloats(0, 0, 0);
-                    if ((this.billboardMode & AbstractMesh.BILLBOARDMODE_X) === AbstractMesh.BILLBOARDMODE_X) {
-                        finalEuler.x = Math.atan2(-currentPosition.y, currentPosition.z);
-                    }
-
-                    if ((this.billboardMode & AbstractMesh.BILLBOARDMODE_Y) === AbstractMesh.BILLBOARDMODE_Y) {
-                        finalEuler.y = Math.atan2(currentPosition.x, currentPosition.z);
-                    }
-
-                    if ((this.billboardMode & AbstractMesh.BILLBOARDMODE_Z) === AbstractMesh.BILLBOARDMODE_Z) {
-                        finalEuler.z = Math.atan2(currentPosition.y, currentPosition.x);
-                    }
-
-                    Matrix.RotationYawPitchRollToRef(finalEuler.y, finalEuler.x, finalEuler.z, Tmp.Matrix[0]);
-                } else {
-                    Tmp.Matrix[1].copyFrom(camera.getViewMatrix());
-
-                    Tmp.Matrix[1].setTranslationFromFloats(0, 0, 0);
-                    Tmp.Matrix[1].invertToRef(Tmp.Matrix[0]);
-                }
-
-                Tmp.Matrix[1].copyFrom(Tmp.Matrix[5]);
-                Tmp.Matrix[1].multiplyToRef(Tmp.Matrix[0], Tmp.Matrix[5]);
-            }
-
-            // Local world
-            Tmp.Matrix[5].multiplyToRef(Tmp.Matrix[2], this._localWorld);
-
-            // Parent
-            if (this.parent && this.parent.getWorldMatrix) {
-                if (this.billboardMode !== AbstractMesh.BILLBOARDMODE_NONE) {
-                    if (this._meshToBoneReferal) {
-                        this.parent.getWorldMatrix().multiplyToRef(this._meshToBoneReferal.getWorldMatrix(), Tmp.Matrix[6]);
-                        Tmp.Matrix[5].copyFrom(Tmp.Matrix[6]);
-                    } else {
-                        Tmp.Matrix[5].copyFrom(this.parent.getWorldMatrix());
-                    }
-
-                    this._localWorld.getTranslationToRef(Tmp.Vector3[5]);
-                    Vector3.TransformCoordinatesToRef(Tmp.Vector3[5], Tmp.Matrix[5], Tmp.Vector3[5]);
-                    this._worldMatrix.copyFrom(this._localWorld);
-                    this._worldMatrix.setTranslation(Tmp.Vector3[5]);
-
-                } else {
-                    if (this._meshToBoneReferal) {
-                        this._localWorld.multiplyToRef(this.parent.getWorldMatrix(), Tmp.Matrix[6]);
-                        Tmp.Matrix[6].multiplyToRef(this._meshToBoneReferal.getWorldMatrix(), this._worldMatrix);
-                    } else {
-                        this._localWorld.multiplyToRef(this.parent.getWorldMatrix(), this._worldMatrix);
-                    }
-                }
-                this._markSyncedWithParent();
-            } else {
-                this._worldMatrix.copyFrom(this._localWorld);
-            }
-
-            // Post multiply inverse of pivotMatrix
-            if (this._postMultiplyPivotMatrix) {
-                this._worldMatrix.multiplyToRef(this._pivotMatrixInverse, this._worldMatrix);
-            }
-
-            // Normal matrix
-            if (this.scaling.isNonUniform) {
-                this.nonUniformScaling = true;
-            } else if (this.parent && (<AbstractMesh>this.parent)._nonUniformScaling) {
-                this.nonUniformScaling = (<AbstractMesh>this.parent)._nonUniformScaling;
-            } else {
-                this.nonUniformScaling = false;
-            }
-
+        protected _afterComputeWorldMatrix(): void {
             // Bounding info
             this._updateBoundingInfo();
-
-            // Absolute position
-            this._absolutePosition.copyFromFloats(this._worldMatrix.m[12], this._worldMatrix.m[13], this._worldMatrix.m[14]);
-
-            // Callbacks
-            this.onAfterWorldMatrixUpdateObservable.notifyObservers(this);
-
-            if (!this._poseMatrix) {
-                this._poseMatrix = Matrix.Invert(this._worldMatrix);
-            }
-
-            return this._worldMatrix;
         }
 
         /**
@@ -1489,81 +1143,6 @@
         }
 
         /**
-         * Sets the mesh position in its local space.  
-         * Returns the AbstractMesh.  
-         */
-        public setPositionWithLocalVector(vector3: Vector3): AbstractMesh {
-            this.computeWorldMatrix();
-            this.position = Vector3.TransformNormal(vector3, this._localWorld);
-            return this;
-        }
-
-        /**
-         * Returns the mesh position in the local space from the current World matrix values.
-         * Returns a new Vector3.
-         */
-        public getPositionExpressedInLocalSpace(): Vector3 {
-            this.computeWorldMatrix();
-            var invLocalWorldMatrix = this._localWorld.clone();
-            invLocalWorldMatrix.invert();
-
-            return Vector3.TransformNormal(this.position, invLocalWorldMatrix);
-        }
-
-        /**
-         * Translates the mesh along the passed Vector3 in its local space.  
-         * Returns the AbstractMesh. 
-         */
-        public locallyTranslate(vector3: Vector3): AbstractMesh {
-            this.computeWorldMatrix(true);
-            this.position = Vector3.TransformCoordinates(vector3, this._localWorld);
-            return this;
-        }
-
-        private static _lookAtVectorCache = new Vector3(0, 0, 0);
-        public lookAt(targetPoint: Vector3, yawCor: number = 0, pitchCor: number = 0, rollCor: number = 0, space: Space = Space.LOCAL): AbstractMesh {
-            /// <summary>Orients a mesh towards a target point. Mesh must be drawn facing user.</summary>
-            /// <param name="targetPoint" type="Vector3">The position (must be in same space as current mesh) to look at</param>
-            /// <param name="yawCor" type="Number">optional yaw (y-axis) correction in radians</param>
-            /// <param name="pitchCor" type="Number">optional pitch (x-axis) correction in radians</param>
-            /// <param name="rollCor" type="Number">optional roll (z-axis) correction in radians</param>
-            /// <returns>Mesh oriented towards targetMesh</returns>
-
-            var dv = AbstractMesh._lookAtVectorCache;
-            var pos = space === Space.LOCAL ? this.position : this.getAbsolutePosition();
-            targetPoint.subtractToRef(pos, dv);
-            var yaw = -Math.atan2(dv.z, dv.x) - Math.PI / 2;
-            var len = Math.sqrt(dv.x * dv.x + dv.z * dv.z);
-            var pitch = Math.atan2(dv.y, len);
-            this.rotationQuaternion = this.rotationQuaternion || new Quaternion();
-            Quaternion.RotationYawPitchRollToRef(yaw + yawCor, pitch + pitchCor, rollCor, this.rotationQuaternion);
-            return this;
-        }
-
-        public attachToBone(bone: Bone, affectedMesh: AbstractMesh): AbstractMesh {
-            this._meshToBoneReferal = affectedMesh;
-            this.parent = bone;
-
-            if (bone.getWorldMatrix().determinant() < 0) {
-                this.scalingDeterminant *= -1;
-            }
-            return this;
-        }
-
-        public detachFromBone(): AbstractMesh {
-            if (!this.parent) {
-                return this;
-            }
-
-            if (this.parent.getWorldMatrix().determinant() < 0) {
-                this.scalingDeterminant *= -1;
-            }
-            this._meshToBoneReferal = null;
-            this.parent = null;
-            return this;
-        }
-
-        /**
          * Returns `true` if the mesh is within the frustum defined by the passed array of planes.  
          * A mesh is in the frustum if its bounding box intersects the frustum.  
          * Boolean returned.  
@@ -2055,120 +1634,7 @@
             this._isDisposed = true;
 
             super.dispose();
-        }
-
-        /**
-         * Returns a new Vector3 what is the localAxis, expressed in the mesh local space, rotated like the mesh.  
-         * This Vector3 is expressed in the World space.  
-         */
-        public getDirection(localAxis: Vector3): Vector3 {
-            var result = Vector3.Zero();
-
-            this.getDirectionToRef(localAxis, result);
-
-            return result;
-        }
-
-        /**
-         * Sets the Vector3 "result" as the rotated Vector3 "localAxis" in the same rotation than the mesh.
-         * localAxis is expressed in the mesh local space.
-         * result is computed in the Wordl space from the mesh World matrix.  
-         * Returns the AbstractMesh.  
-         */
-        public getDirectionToRef(localAxis: Vector3, result: Vector3): AbstractMesh {
-            Vector3.TransformNormalToRef(localAxis, this.getWorldMatrix(), result);
-            return this;
-        }
-
-        public setPivotPoint(point: Vector3, space: Space = Space.LOCAL): AbstractMesh {
-
-            if (this.getScene().getRenderId() == 0) {
-                this.computeWorldMatrix(true);
-            }
-
-            var wm = this.getWorldMatrix();
-
-            if (space == Space.WORLD) {
-                var tmat = Tmp.Matrix[0];
-                wm.invertToRef(tmat);
-                point = Vector3.TransformCoordinates(point, tmat);
-            }
-
-            Vector3.TransformCoordinatesToRef(point, wm, this.position);
-            this._pivotMatrix.m[12] = -point.x;
-            this._pivotMatrix.m[13] = -point.y;
-            this._pivotMatrix.m[14] = -point.z;
-            this._cache.pivotMatrixUpdated = true;
-            return this;
-        }
-
-        /**
-         * Returns a new Vector3 set with the mesh pivot point coordinates in the local space.  
-         */
-        public getPivotPoint(): Vector3 {
-            var point = Vector3.Zero();
-            this.getPivotPointToRef(point);
-            return point;
-        }
-
-        /**
-         * Sets the passed Vector3 "result" with the coordinates of the mesh pivot point in the local space.   
-         * Returns the AbstractMesh.   
-         */
-        public getPivotPointToRef(result: Vector3): AbstractMesh {
-            result.x = -this._pivotMatrix.m[12];
-            result.y = -this._pivotMatrix.m[13];
-            result.z = -this._pivotMatrix.m[14];
-            return this;
-        }
-
-        /**
-         * Returns a new Vector3 set with the mesh pivot point World coordinates.  
-         */
-        public getAbsolutePivotPoint(): Vector3 {
-            var point = Vector3.Zero();
-            this.getAbsolutePivotPointToRef(point);
-            return point;
-        }
-
-        /**
-         * Defines the passed mesh as the parent of the current mesh.  
-         * Returns the AbstractMesh.  
-         */
-        public setParent(mesh: Nullable<AbstractMesh>): AbstractMesh {
-            var parent = (<AbstractMesh>mesh);
-
-            if (mesh == null) {
-
-                var rotation = Tmp.Quaternion[0];
-                var position = Tmp.Vector3[0];
-                var scale = Tmp.Vector3[1];
-
-                this.getWorldMatrix().decompose(scale, rotation, position);
-
-                if (this.rotationQuaternion) {
-                    this.rotationQuaternion.copyFrom(rotation);
-                } else {
-                    rotation.toEulerAnglesToRef(this.rotation);
-                }
-
-                this.position.x = position.x;
-                this.position.y = position.y;
-                this.position.z = position.z;
-
-            } else {
-
-                var position = Tmp.Vector3[0];
-                var m1 = Tmp.Matrix[0];
-
-                parent.getWorldMatrix().invertToRef(m1);
-                Vector3.TransformCoordinatesToRef(this.position, m1, position);
-
-                this.position.copyFrom(position);
-            }
-            this.parent = parent;
-            return this;
-        }
+        } 
 
         /**
          * Adds the passed mesh as a child to the current mesh.  
@@ -2188,19 +1654,6 @@
             return this;
         }
 
-        /**
-         * Sets the Vector3 "result" coordinates with the mesh pivot point World coordinates.  
-         * Returns the AbstractMesh.  
-         */
-        public getAbsolutePivotPointToRef(result: Vector3): AbstractMesh {
-            result.x = this._pivotMatrix.m[12];
-            result.y = this._pivotMatrix.m[13];
-            result.z = this._pivotMatrix.m[14];
-            this.getPivotPointToRef(result);
-            Vector3.TransformCoordinatesToRef(result, this.getWorldMatrix(), result);
-            return this;
-        }
-
         // Facet data
         /** 
          *  Initialize the facet data arrays : facetNormals, facetPositions and facetPartitioning.   

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

@@ -912,6 +912,7 @@
         /**
          * Sets the mesh indices.  
          * Expects an array populated with integers or a typed array (Int32Array, Uint32Array, Uint16Array).
+         * Type is Uint16Array by default unless the mesh has more than 65536 vertices.
          * If the mesh has no geometry, a new Geometry object is created and set to the mesh. 
          * This method creates a new index buffer each call.  
          * Returns the Mesh.  

+ 602 - 0
src/Mesh/babylon.transformNode.ts

@@ -0,0 +1,602 @@
+module BABYLON {
+    export class TransformNode extends Node {
+        // Statics
+        public static BILLBOARDMODE_NONE = 0;
+        public static BILLBOARDMODE_X = 1;
+        public static BILLBOARDMODE_Y = 2;
+        public static BILLBOARDMODE_Z = 4;
+        public static BILLBOARDMODE_ALL = 7;
+        
+        // Properties
+        private _rotation = Vector3.Zero();
+        private _rotationQuaternion: Nullable<Quaternion>;
+        protected _scaling = Vector3.One();
+        protected _isDirty = false;
+        private _transformToBoneReferal: Nullable<TransformNode>;
+        
+        public billboardMode = AbstractMesh.BILLBOARDMODE_NONE;
+        public scalingDeterminant = 1;
+        public infiniteDistance = false;
+        public position = Vector3.Zero();
+                        
+        // Cache        
+        public _poseMatrix: Matrix;
+        private _localWorld = Matrix.Zero();
+        public _worldMatrix = Matrix.Zero();
+        private _absolutePosition = Vector3.Zero();
+        private _pivotMatrix = Matrix.Identity();
+        private _pivotMatrixInverse: Matrix;
+        private _postMultiplyPivotMatrix = false;        
+        
+        protected _isWorldMatrixFrozen = false;
+
+        /**
+        * An event triggered after the world matrix is updated
+        * @type {BABYLON.Observable}
+        */
+        public onAfterWorldMatrixUpdateObservable = new Observable<TransformNode>();        
+                
+       /**
+         * Rotation property : a Vector3 depicting the rotation value in radians around each local axis X, Y, Z. 
+         * If rotation quaternion is set, this Vector3 will (almost always) be the Zero vector!
+         * Default : (0.0, 0.0, 0.0)
+         */
+        public get rotation(): Vector3 {
+            return this._rotation;
+        }
+
+        public set rotation(newRotation: Vector3) {
+            this._rotation = newRotation;
+        }
+
+        /**
+         * Scaling property : a Vector3 depicting the mesh scaling along each local axis X, Y, Z.  
+         * Default : (1.0, 1.0, 1.0)
+         */
+        public get scaling(): Vector3 {
+            return this._scaling;
+        }
+
+        /**
+         * Scaling property : a Vector3 depicting the mesh scaling along each local axis X, Y, Z.  
+         * Default : (1.0, 1.0, 1.0)
+        */
+        public set scaling(newScaling: Vector3) {
+            this._scaling = newScaling;
+        }
+
+        /**
+         * Rotation Quaternion property : this a Quaternion object depicting the mesh rotation by using a unit quaternion. 
+         * It's null by default.  
+         * If set, only the rotationQuaternion is then used to compute the mesh rotation and its property `.rotation\ is then ignored and set to (0.0, 0.0, 0.0)
+         */
+        public get rotationQuaternion(): Nullable<Quaternion> {
+            return this._rotationQuaternion;
+        }
+
+        public set rotationQuaternion(quaternion: Nullable<Quaternion>) {
+            this._rotationQuaternion = quaternion;
+            //reset the rotation vector. 
+            if (quaternion && this.rotation.length()) {
+                this.rotation.copyFromFloats(0.0, 0.0, 0.0);
+            }
+        }
+
+        /**
+         * Returns the latest update of the World matrix
+         * Returns a Matrix.  
+         */
+        public getWorldMatrix(): Matrix {
+            if (this._currentRenderId !== this.getScene().getRenderId()) {
+                this.computeWorldMatrix();
+            }
+            return this._worldMatrix;
+        }
+
+        /**
+         * Returns directly the latest state of the mesh World matrix. 
+         * A Matrix is returned.    
+         */
+        public get worldMatrixFromCache(): Matrix {
+            return this._worldMatrix;
+        }
+
+        /**
+         * Returns the current mesh absolute position.
+         * Retuns a Vector3.
+         */
+        public get absolutePosition(): Vector3 {
+            return this._absolutePosition;
+        }
+
+        /**
+         * Sets a new pivot matrix to the mesh.  
+         * Returns the AbstractMesh.
+        */
+        public setPivotMatrix(matrix: Matrix, postMultiplyPivotMatrix = false): TransformNode {
+            this._pivotMatrix = matrix.clone();
+            this._cache.pivotMatrixUpdated = true;
+            this._postMultiplyPivotMatrix = postMultiplyPivotMatrix;
+
+            if (this._postMultiplyPivotMatrix) {
+                this._pivotMatrixInverse = Matrix.Invert(matrix);
+            }
+            return this;
+        }
+
+        /**
+         * Returns the mesh pivot matrix.
+         * Default : Identity.  
+         * A Matrix is returned.  
+         */
+        public getPivotMatrix(): Matrix {
+            return this._pivotMatrix;
+        }
+
+        /**
+         * Prevents the World matrix to be computed any longer.
+         * Returns the AbstractMesh.  
+         */
+        public freezeWorldMatrix(): TransformNode {
+            this._isWorldMatrixFrozen = false;  // no guarantee world is not already frozen, switch off temporarily
+            this.computeWorldMatrix(true);
+            this._isWorldMatrixFrozen = true;
+            return this;
+        }
+
+        /**
+         * Allows back the World matrix computation. 
+         * Returns the AbstractMesh.  
+         */
+        public unfreezeWorldMatrix() {
+            this._isWorldMatrixFrozen = false;
+            this.computeWorldMatrix(true);
+            return this;
+        }
+
+        /**
+         * True if the World matrix has been frozen.  
+         * Returns a boolean.  
+         */
+        public get isWorldMatrixFrozen(): boolean {
+            return this._isWorldMatrixFrozen;
+        }
+
+     /**
+         * Retuns the mesh absolute position in the World.  
+         * Returns a Vector3.
+         */
+        public getAbsolutePosition(): Vector3 {
+            this.computeWorldMatrix();
+            return this._absolutePosition;
+        }
+
+        /**
+         * Sets the mesh absolute position in the World from a Vector3 or an Array(3).
+         * Returns the AbstractMesh.  
+         */
+        public setAbsolutePosition(absolutePosition: Vector3): TransformNode {
+            if (!absolutePosition) {
+                return this;
+            }
+            var absolutePositionX;
+            var absolutePositionY;
+            var absolutePositionZ;
+            if (absolutePosition.x === undefined) {
+                if (arguments.length < 3) {
+                    return this;
+                }
+                absolutePositionX = arguments[0];
+                absolutePositionY = arguments[1];
+                absolutePositionZ = arguments[2];
+            }
+            else {
+                absolutePositionX = absolutePosition.x;
+                absolutePositionY = absolutePosition.y;
+                absolutePositionZ = absolutePosition.z;
+            }
+            if (this.parent) {
+                var invertParentWorldMatrix = this.parent.getWorldMatrix().clone();
+                invertParentWorldMatrix.invert();
+                var worldPosition = new Vector3(absolutePositionX, absolutePositionY, absolutePositionZ);
+                this.position = Vector3.TransformCoordinates(worldPosition, invertParentWorldMatrix);
+            } else {
+                this.position.x = absolutePositionX;
+                this.position.y = absolutePositionY;
+                this.position.z = absolutePositionZ;
+            }
+            return this;
+        }   
+
+      /**
+         * Sets the mesh position in its local space.  
+         * Returns the AbstractMesh.  
+         */
+        public setPositionWithLocalVector(vector3: Vector3): TransformNode {
+            this.computeWorldMatrix();
+            this.position = Vector3.TransformNormal(vector3, this._localWorld);
+            return this;
+        }
+
+        /**
+         * Returns the mesh position in the local space from the current World matrix values.
+         * Returns a new Vector3.
+         */
+        public getPositionExpressedInLocalSpace(): Vector3 {
+            this.computeWorldMatrix();
+            var invLocalWorldMatrix = this._localWorld.clone();
+            invLocalWorldMatrix.invert();
+
+            return Vector3.TransformNormal(this.position, invLocalWorldMatrix);
+        }
+
+        /**
+         * Translates the mesh along the passed Vector3 in its local space.  
+         * Returns the AbstractMesh. 
+         */
+        public locallyTranslate(vector3: Vector3): TransformNode {
+            this.computeWorldMatrix(true);
+            this.position = Vector3.TransformCoordinates(vector3, this._localWorld);
+            return this;
+        }
+
+        private static _lookAtVectorCache = new Vector3(0, 0, 0);
+        public lookAt(targetPoint: Vector3, yawCor: number = 0, pitchCor: number = 0, rollCor: number = 0, space: Space = Space.LOCAL): TransformNode {
+            /// <summary>Orients a mesh towards a target point. Mesh must be drawn facing user.</summary>
+            /// <param name="targetPoint" type="Vector3">The position (must be in same space as current mesh) to look at</param>
+            /// <param name="yawCor" type="Number">optional yaw (y-axis) correction in radians</param>
+            /// <param name="pitchCor" type="Number">optional pitch (x-axis) correction in radians</param>
+            /// <param name="rollCor" type="Number">optional roll (z-axis) correction in radians</param>
+            /// <returns>Mesh oriented towards targetMesh</returns>
+
+            var dv = AbstractMesh._lookAtVectorCache;
+            var pos = space === Space.LOCAL ? this.position : this.getAbsolutePosition();
+            targetPoint.subtractToRef(pos, dv);
+            var yaw = -Math.atan2(dv.z, dv.x) - Math.PI / 2;
+            var len = Math.sqrt(dv.x * dv.x + dv.z * dv.z);
+            var pitch = Math.atan2(dv.y, len);
+            this.rotationQuaternion = this.rotationQuaternion || new Quaternion();
+            Quaternion.RotationYawPitchRollToRef(yaw + yawCor, pitch + pitchCor, rollCor, this.rotationQuaternion);
+            return this;
+        }        
+
+       /**
+         * Returns a new Vector3 what is the localAxis, expressed in the mesh local space, rotated like the mesh.  
+         * This Vector3 is expressed in the World space.  
+         */
+        public getDirection(localAxis: Vector3): Vector3 {
+            var result = Vector3.Zero();
+
+            this.getDirectionToRef(localAxis, result);
+
+            return result;
+        }
+
+        /**
+         * Sets the Vector3 "result" as the rotated Vector3 "localAxis" in the same rotation than the mesh.
+         * localAxis is expressed in the mesh local space.
+         * result is computed in the Wordl space from the mesh World matrix.  
+         * Returns the AbstractMesh.  
+         */
+        public getDirectionToRef(localAxis: Vector3, result: Vector3): TransformNode {
+            Vector3.TransformNormalToRef(localAxis, this.getWorldMatrix(), result);
+            return this;
+        }
+
+        public setPivotPoint(point: Vector3, space: Space = Space.LOCAL): TransformNode {
+            if (this.getScene().getRenderId() == 0) {
+                this.computeWorldMatrix(true);
+            }
+
+            var wm = this.getWorldMatrix();
+
+            if (space == Space.WORLD) {
+                var tmat = Tmp.Matrix[0];
+                wm.invertToRef(tmat);
+                point = Vector3.TransformCoordinates(point, tmat);
+            }
+
+            Vector3.TransformCoordinatesToRef(point, wm, this.position);
+            this._pivotMatrix.m[12] = -point.x;
+            this._pivotMatrix.m[13] = -point.y;
+            this._pivotMatrix.m[14] = -point.z;
+            this._cache.pivotMatrixUpdated = true;
+            return this;
+        }
+
+        /**
+         * Returns a new Vector3 set with the mesh pivot point coordinates in the local space.  
+         */
+        public getPivotPoint(): Vector3 {
+            var point = Vector3.Zero();
+            this.getPivotPointToRef(point);
+            return point;
+        }
+
+        /**
+         * Sets the passed Vector3 "result" with the coordinates of the mesh pivot point in the local space.   
+         * Returns the AbstractMesh.   
+         */
+        public getPivotPointToRef(result: Vector3): TransformNode {
+            result.x = -this._pivotMatrix.m[12];
+            result.y = -this._pivotMatrix.m[13];
+            result.z = -this._pivotMatrix.m[14];
+            return this;
+        }
+
+        /**
+         * Returns a new Vector3 set with the mesh pivot point World coordinates.  
+         */
+        public getAbsolutePivotPoint(): Vector3 {
+            var point = Vector3.Zero();
+            this.getAbsolutePivotPointToRef(point);
+            return point;
+        }
+
+        /**
+         * Sets the Vector3 "result" coordinates with the mesh pivot point World coordinates.  
+         * Returns the AbstractMesh.  
+         */
+        public getAbsolutePivotPointToRef(result: Vector3): TransformNode {
+            result.x = this._pivotMatrix.m[12];
+            result.y = this._pivotMatrix.m[13];
+            result.z = this._pivotMatrix.m[14];
+            this.getPivotPointToRef(result);
+            Vector3.TransformCoordinatesToRef(result, this.getWorldMatrix(), result);
+            return this;
+        }        
+
+        /**
+         * Defines the passed mesh as the parent of the current mesh.  
+         * Returns the AbstractMesh.  
+         */
+        public setParent(mesh: Nullable<AbstractMesh>): TransformNode {
+            var parent = (<AbstractMesh>mesh);
+
+            if (mesh == null) {
+
+                var rotation = Tmp.Quaternion[0];
+                var position = Tmp.Vector3[0];
+                var scale = Tmp.Vector3[1];
+
+                this.getWorldMatrix().decompose(scale, rotation, position);
+
+                if (this.rotationQuaternion) {
+                    this.rotationQuaternion.copyFrom(rotation);
+                } else {
+                    rotation.toEulerAnglesToRef(this.rotation);
+                }
+
+                this.position.x = position.x;
+                this.position.y = position.y;
+                this.position.z = position.z;
+
+            } else {
+
+                var position = Tmp.Vector3[0];
+                var m1 = Tmp.Matrix[0];
+
+                parent.getWorldMatrix().invertToRef(m1);
+                Vector3.TransformCoordinatesToRef(this.position, m1, position);
+
+                this.position.copyFrom(position);
+            }
+            this.parent = parent;
+            return this;
+        }       
+        
+        private _nonUniformScaling = false;
+        public get nonUniformScaling(): boolean {
+            return this._nonUniformScaling;
+        }
+
+        public _updateNonUniformScalingState(value: boolean): boolean {
+            if (this._nonUniformScaling === value) {
+                return false;
+            }
+
+            this._nonUniformScaling = true;
+            return true;
+        }        
+
+        /**
+         * Attach the current TransformNode to another TransformNode associated with a bone
+         * @param bone Bone affecting the TransformNode
+         * @param affectedTransformNode TransformNode associated with the bone 
+         */
+        public attachToBone(bone: Bone, affectedTransformNode: TransformNode): TransformNode {
+            this._transformToBoneReferal = affectedTransformNode;
+            this.parent = bone;
+
+            if (bone.getWorldMatrix().determinant() < 0) {
+                this.scalingDeterminant *= -1;
+            }
+            return this;
+        }
+
+        public detachFromBone(): TransformNode {
+            if (!this.parent) {
+                return this;
+            }
+
+            if (this.parent.getWorldMatrix().determinant() < 0) {
+                this.scalingDeterminant *= -1;
+            }
+            this._transformToBoneReferal = null;
+            this.parent = null;
+            return this;
+        }        
+        
+        /**
+         * Computes the mesh World matrix and returns it.  
+         * If the mesh world matrix is frozen, this computation does nothing more than returning the last frozen values.  
+         * If the parameter `force` is let to `false` (default), the current cached World matrix is returned. 
+         * If the parameter `force`is set to `true`, the actual computation is done.  
+         * Returns the mesh World Matrix.
+         */
+        public computeWorldMatrix(force?: boolean): Matrix {
+            if (this._isWorldMatrixFrozen) {
+                return this._worldMatrix;
+            }
+
+            if (!force && this.isSynchronized(true)) {
+                return this._worldMatrix;
+            }
+
+            this._cache.position.copyFrom(this.position);
+            this._cache.scaling.copyFrom(this.scaling);
+            this._cache.pivotMatrixUpdated = false;
+            this._cache.billboardMode = this.billboardMode;
+            this._currentRenderId = this.getScene().getRenderId();
+            this._isDirty = false;
+
+            // Scaling
+            Matrix.ScalingToRef(this.scaling.x * this.scalingDeterminant, this.scaling.y * this.scalingDeterminant, this.scaling.z * this.scalingDeterminant, Tmp.Matrix[1]);
+
+            // Rotation
+
+            //rotate, if quaternion is set and rotation was used
+            if (this.rotationQuaternion) {
+                var len = this.rotation.length();
+                if (len) {
+                    this.rotationQuaternion.multiplyInPlace(BABYLON.Quaternion.RotationYawPitchRoll(this.rotation.y, this.rotation.x, this.rotation.z))
+                    this.rotation.copyFromFloats(0, 0, 0);
+                }
+            }
+
+            if (this.rotationQuaternion) {
+                this.rotationQuaternion.toRotationMatrix(Tmp.Matrix[0]);
+                this._cache.rotationQuaternion.copyFrom(this.rotationQuaternion);
+            } else {
+                Matrix.RotationYawPitchRollToRef(this.rotation.y, this.rotation.x, this.rotation.z, Tmp.Matrix[0]);
+                this._cache.rotation.copyFrom(this.rotation);
+            }
+
+            // Translation
+            let camera = (<Camera>this.getScene().activeCamera);
+            
+            if (this.infiniteDistance && !this.parent && camera) {
+
+                var cameraWorldMatrix = camera.getWorldMatrix();
+
+                var cameraGlobalPosition = new Vector3(cameraWorldMatrix.m[12], cameraWorldMatrix.m[13], cameraWorldMatrix.m[14]);
+
+                Matrix.TranslationToRef(this.position.x + cameraGlobalPosition.x, this.position.y + cameraGlobalPosition.y,
+                    this.position.z + cameraGlobalPosition.z, Tmp.Matrix[2]);
+            } else {
+                Matrix.TranslationToRef(this.position.x, this.position.y, this.position.z, Tmp.Matrix[2]);
+            }
+
+            // Composing transformations
+            this._pivotMatrix.multiplyToRef(Tmp.Matrix[1], Tmp.Matrix[4]);
+            Tmp.Matrix[4].multiplyToRef(Tmp.Matrix[0], Tmp.Matrix[5]);
+
+            // Billboarding (testing PG:http://www.babylonjs-playground.com/#UJEIL#13)
+            if (this.billboardMode !== AbstractMesh.BILLBOARDMODE_NONE && camera) {
+                if ((this.billboardMode & AbstractMesh.BILLBOARDMODE_ALL) !== AbstractMesh.BILLBOARDMODE_ALL) {
+                    // Need to decompose each rotation here
+                    var currentPosition = Tmp.Vector3[3];
+
+                    if (this.parent && this.parent.getWorldMatrix) {
+                        if (this._transformToBoneReferal) {
+                            this.parent.getWorldMatrix().multiplyToRef(this._transformToBoneReferal.getWorldMatrix(), Tmp.Matrix[6]);
+                            Vector3.TransformCoordinatesToRef(this.position, Tmp.Matrix[6], currentPosition);
+                        } else {
+                            Vector3.TransformCoordinatesToRef(this.position, this.parent.getWorldMatrix(), currentPosition);
+                        }
+                    } else {
+                        currentPosition.copyFrom(this.position);
+                    }
+
+                    currentPosition.subtractInPlace(camera.globalPosition);
+
+                    var finalEuler = Tmp.Vector3[4].copyFromFloats(0, 0, 0);
+                    if ((this.billboardMode & AbstractMesh.BILLBOARDMODE_X) === AbstractMesh.BILLBOARDMODE_X) {
+                        finalEuler.x = Math.atan2(-currentPosition.y, currentPosition.z);
+                    }
+
+                    if ((this.billboardMode & AbstractMesh.BILLBOARDMODE_Y) === AbstractMesh.BILLBOARDMODE_Y) {
+                        finalEuler.y = Math.atan2(currentPosition.x, currentPosition.z);
+                    }
+
+                    if ((this.billboardMode & AbstractMesh.BILLBOARDMODE_Z) === AbstractMesh.BILLBOARDMODE_Z) {
+                        finalEuler.z = Math.atan2(currentPosition.y, currentPosition.x);
+                    }
+
+                    Matrix.RotationYawPitchRollToRef(finalEuler.y, finalEuler.x, finalEuler.z, Tmp.Matrix[0]);
+                } else {
+                    Tmp.Matrix[1].copyFrom(camera.getViewMatrix());
+
+                    Tmp.Matrix[1].setTranslationFromFloats(0, 0, 0);
+                    Tmp.Matrix[1].invertToRef(Tmp.Matrix[0]);
+                }
+
+                Tmp.Matrix[1].copyFrom(Tmp.Matrix[5]);
+                Tmp.Matrix[1].multiplyToRef(Tmp.Matrix[0], Tmp.Matrix[5]);
+            }
+
+            // Local world
+            Tmp.Matrix[5].multiplyToRef(Tmp.Matrix[2], this._localWorld);
+
+            // Parent
+            if (this.parent && this.parent.getWorldMatrix) {
+                if (this.billboardMode !== AbstractMesh.BILLBOARDMODE_NONE) {
+                    if (this._transformToBoneReferal) {
+                        this.parent.getWorldMatrix().multiplyToRef(this._transformToBoneReferal.getWorldMatrix(), Tmp.Matrix[6]);
+                        Tmp.Matrix[5].copyFrom(Tmp.Matrix[6]);
+                    } else {
+                        Tmp.Matrix[5].copyFrom(this.parent.getWorldMatrix());
+                    }
+
+                    this._localWorld.getTranslationToRef(Tmp.Vector3[5]);
+                    Vector3.TransformCoordinatesToRef(Tmp.Vector3[5], Tmp.Matrix[5], Tmp.Vector3[5]);
+                    this._worldMatrix.copyFrom(this._localWorld);
+                    this._worldMatrix.setTranslation(Tmp.Vector3[5]);
+
+                } else {
+                    if (this._transformToBoneReferal) {
+                        this._localWorld.multiplyToRef(this.parent.getWorldMatrix(), Tmp.Matrix[6]);
+                        Tmp.Matrix[6].multiplyToRef(this._transformToBoneReferal.getWorldMatrix(), this._worldMatrix);
+                    } else {
+                        this._localWorld.multiplyToRef(this.parent.getWorldMatrix(), this._worldMatrix);
+                    }
+                }
+                this._markSyncedWithParent();
+            } else {
+                this._worldMatrix.copyFrom(this._localWorld);
+            }
+
+            // Post multiply inverse of pivotMatrix
+            if (this._postMultiplyPivotMatrix) {
+                this._worldMatrix.multiplyToRef(this._pivotMatrixInverse, this._worldMatrix);
+            }
+
+            // Normal matrix
+            if (this.scaling.isNonUniform) {
+                this._updateNonUniformScalingState(true);
+            } else if (this.parent && (<TransformNode>this.parent)._nonUniformScaling) {
+                this._updateNonUniformScalingState((<TransformNode>this.parent)._nonUniformScaling);
+            } else {
+                this._updateNonUniformScalingState(false);
+            }
+
+            this._afterComputeWorldMatrix();
+
+            // Absolute position
+            this._absolutePosition.copyFromFloats(this._worldMatrix.m[12], this._worldMatrix.m[13], this._worldMatrix.m[14]);
+
+            // Callbacks
+            this.onAfterWorldMatrixUpdateObservable.notifyObservers(this);
+
+            if (!this._poseMatrix) {
+                this._poseMatrix = Matrix.Invert(this._worldMatrix);
+            }
+
+            return this._worldMatrix;
+        }   
+
+        protected _afterComputeWorldMatrix(): void {
+
+        }
+    }
+}

+ 3 - 3
src/Physics/babylon.physicsImpostor.ts

@@ -24,9 +24,9 @@ module BABYLON {
         getScene?(): Scene;
         getAbsolutePosition(): Vector3;
         getAbsolutePivotPoint(): Vector3;
-        rotate(axis: Vector3, amount: number, space?: Space): IPhysicsEnabledObject;
-        translate(axis: Vector3, distance: number, space?: Space): IPhysicsEnabledObject;
-        setAbsolutePosition(absolutePosition: Vector3): IPhysicsEnabledObject;
+        rotate(axis: Vector3, amount: number, space?: Space): TransformNode;
+        translate(axis: Vector3, distance: number, space?: Space): TransformNode;
+        setAbsolutePosition(absolutePosition: Vector3): TransformNode;
     }
 
     export class PhysicsImpostor {