浏览代码

Merge branch 'master' of https://github.com/BabylonJS/Babylon.js

Jaskar 8 年之前
父节点
当前提交
0dcf20f685
共有 57 个文件被更改,包括 12299 次插入9681 次删除
  1. 1 0
      .gitignore
  2. 8185 7639
      Playground/babylon.d.txt
  3. 2 0
      Playground/debug.html
  4. 2 0
      Playground/frame.html
  5. 2 0
      Playground/index.html
  6. 0 0
      Playground/scenes/StanfordBunny.obj
  7. 4 2
      Tools/Gulp/config.json
  8. 386 361
      dist/preview release/babylon.d.ts
  9. 38 38
      dist/preview release/babylon.js
  10. 239 121
      dist/preview release/babylon.max.js
  11. 386 361
      dist/preview release/babylon.module.d.ts
  12. 39 39
      dist/preview release/babylon.worker.js
  13. 244 1
      dist/preview release/gui/babylon.gui.d.ts
  14. 1340 8
      dist/preview release/gui/babylon.gui.js
  15. 1 1
      dist/preview release/gui/babylon.gui.min.js
  16. 247 247
      dist/preview release/inspector/babylon.inspector.bundle.js
  17. 1 1
      dist/preview release/inspector/babylon.inspector.min.js
  18. 2 2
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  19. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  20. 2 2
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  21. 20 0
      gui/readme.md
  22. 0 95
      gui/src/advancedDynamicTexture.js
  23. 97 22
      gui/src/advancedDynamicTexture.ts
  24. 41 0
      gui/src/controls/button.ts
  25. 0 74
      gui/src/controls/container.js
  26. 38 11
      gui/src/controls/container.ts
  27. 0 62
      gui/src/controls/contentControl.js
  28. 0 51
      gui/src/controls/contentControl.ts
  29. 0 180
      gui/src/controls/control.js
  30. 373 18
      gui/src/controls/control.ts
  31. 89 0
      gui/src/controls/image.ts
  32. 0 73
      gui/src/controls/rectangle.js
  33. 70 3
      gui/src/controls/rectangle.ts
  34. 0 89
      gui/src/controls/textBlock.js
  35. 108 31
      gui/src/controls/textBlock.ts
  36. 0 22
      gui/src/measure.js
  37. 30 2
      gui/src/measure.ts
  38. 78 0
      gui/src/valueAndUnit.ts
  39. 1 1
      localDev/index.html
  40. 46 23
      src/Animations/babylon.animation.ts
  41. 12 10
      src/Cameras/Inputs/babylon.arcRotateCameraGamepadInput.ts
  42. 9 4
      src/Cameras/Inputs/babylon.freeCameraGamepadInput.ts
  43. 19 39
      src/Cameras/VR/babylon.webVRCamera.ts
  44. 7 0
      src/Debug/babylon.skeletonViewer.ts
  45. 2 1
      src/Materials/Textures/babylon.baseTexture.ts
  46. 1 0
      src/Materials/Textures/babylon.texture.ts
  47. 2 2
      src/Materials/babylon.pushMaterial.ts
  48. 2 1
      src/Materials/babylon.standardMaterial.ts
  49. 43 4
      src/Math/babylon.math.ts
  50. 2 2
      src/Mesh/babylon.geometry.ts
  51. 14 13
      src/Mesh/babylon.mesh.ts
  52. 20 20
      src/Mesh/babylon.mesh.vertexData.ts
  53. 2 0
      src/Morph/babylon.morphTarget.ts
  54. 1 1
      src/Physics/Plugins/babylon.cannonJSPlugin.ts
  55. 1 1
      src/Rendering/babylon.boundingBoxRenderer.ts
  56. 38 1
      src/babylon.engine.ts
  57. 11 1
      src/babylon.scene.ts

+ 1 - 0
.gitignore

@@ -24,6 +24,7 @@ postProcessLibrary/src/**/*.js
 canvas2D/src/**/*.js
 inspector/src/**/*.js
 serializers/src/**/*.js
+gui/src/**/*.js
 
 # Build results
 [Dd]ebug/

文件差异内容过多而无法显示
+ 8185 - 7639
Playground/babylon.d.txt


+ 2 - 0
Playground/debug.html

@@ -50,6 +50,8 @@
     <script src="https://preview.babylonjs.com/loaders/babylon.objFileLoader.js"></script>
     <script src="https://preview.babylonjs.com/loaders/babylon.stlFileLoader.js"></script>
 
+    <script src="https://preview.babylonjs.com/gui/babylon.gui.js"></script>
+
     <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js"></script>
 
     <script src="https://rawgit.com/BabylonJS/Extensions/master/CompoundShader/src/babylonx.CompoundShader.js"></script>

+ 2 - 0
Playground/frame.html

@@ -38,6 +38,8 @@
     <script src="https://preview.babylonjs.com/loaders/babylon.glTFFileLoader.js"></script>
     <script src="https://preview.babylonjs.com/loaders/babylon.objFileLoader.js"></script>
     <script src="https://preview.babylonjs.com/loaders/babylon.stlFileLoader.js"></script>
+
+    <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
     
     <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js"></script>
     <script src="https://rawgit.com/BabylonJS/Extensions/master/CompoundShader/src/babylonx.CompoundShader.js"></script>

+ 2 - 0
Playground/index.html

@@ -50,6 +50,8 @@
     <script src="https://preview.babylonjs.com/loaders/babylon.objFileLoader.js"></script>
     <script src="https://preview.babylonjs.com/loaders/babylon.stlFileLoader.js"></script>
 
+    <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
+
     <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js"></script>
 
     <script src="https://rawgit.com/BabylonJS/Extensions/master/CompoundShader/src/babylonx.CompoundShader.js"></script>

Playground/Scenes/StanfordBunny.obj → Playground/scenes/StanfordBunny.obj


+ 4 - 2
Tools/Gulp/config.json

@@ -1217,11 +1217,13 @@
                 "files": [
                     "../../gui/src/advancedDynamicTexture.ts",
                     "../../gui/src/measure.ts",
+                    "../../gui/src/valueAndUnit.ts",
                     "../../gui/src/controls/control.ts",
-                    "../../gui/src/controls/contentControl.ts",
                     "../../gui/src/controls/container.ts",
                     "../../gui/src/controls/rectangle.ts",
-                    "../../gui/src/controls/textBlock.ts"
+                    "../../gui/src/controls/textBlock.ts",
+                    "../../gui/src/controls/image.ts",
+                    "../../gui/src/controls/button.ts"
                 ],
                 "output": "babylon.gui.js"
             }

+ 386 - 361
dist/preview release/babylon.d.ts

@@ -337,6 +337,8 @@ declare module BABYLON {
          * @param {number} height - the new canvas' height
          */
         setSize(width: number, height: number): void;
+        isVRDevicePresent(callback: (result: boolean) => void): void;
+        getVRDevice(name: string, callback: (device) => void): void;
         initWebVR(): void;
         enableVR(vrDevice: any): void;
         disableVR(): void;
@@ -1575,6 +1577,7 @@ declare module BABYLON {
         animationTimeScale: number;
         _cachedMaterial: Material;
         _cachedEffect: Effect;
+        _cachedVisibility: number;
         private _renderId;
         private _executeWhenReadyTimeoutId;
         private _intermediateRendering;
@@ -1637,6 +1640,8 @@ declare module BABYLON {
         readonly pointerY: number;
         getCachedMaterial(): Material;
         getCachedEffect(): Effect;
+        getCachedVisibility(): number;
+        isCachedMaterialValid(material: Material, effect: Effect, visibility?: number): boolean;
         getBoundingBoxRenderer(): BoundingBoxRenderer;
         getOutlineRenderer(): OutlineRenderer;
         getEngine(): Engine;
@@ -3432,9 +3437,13 @@ declare module BABYLON {
         getEasingFunction(): IEasingFunction;
         setEasingFunction(easingFunction: EasingFunction): void;
         floatInterpolateFunction(startValue: number, endValue: number, gradient: number): number;
+        floatInterpolateFunctionWithTangents(startValue: number, outTangent: number, endValue: number, inTangent: number, gradient: number): number;
         quaternionInterpolateFunction(startValue: Quaternion, endValue: Quaternion, gradient: number): Quaternion;
+        quaternionInterpolateFunctionWithTangents(startValue: Quaternion, outTangent: Quaternion, endValue: Quaternion, inTangent: Quaternion, gradient: number): Quaternion;
         vector3InterpolateFunction(startValue: Vector3, endValue: Vector3, gradient: number): Vector3;
+        vector3InterpolateFunctionWithTangents(startValue: Vector3, outTangent: Vector3, endValue: Vector3, inTangent: Vector3, gradient: number): Vector3;
         vector2InterpolateFunction(startValue: Vector2, endValue: Vector2, gradient: number): Vector2;
+        vector2InterpolateFunctionWithTangents(startValue: Vector2, outTangent: Vector2, endValue: Vector2, inTangent: Vector2, gradient: number): Vector2;
         sizeInterpolateFunction(startValue: Size, endValue: Size, gradient: number): Size;
         color3InterpolateFunction(startValue: Color3, endValue: Color3, gradient: number): Color3;
         matrixInterpolateFunction(startValue: Matrix, endValue: Matrix, gradient: number): Matrix;
@@ -4201,6 +4210,249 @@ declare module BABYLON {
 }
 
 declare module BABYLON {
+    class Collider {
+        radius: Vector3;
+        retry: number;
+        velocity: Vector3;
+        basePoint: Vector3;
+        epsilon: number;
+        collisionFound: boolean;
+        velocityWorldLength: number;
+        basePointWorld: Vector3;
+        velocityWorld: Vector3;
+        normalizedVelocity: Vector3;
+        initialVelocity: Vector3;
+        initialPosition: Vector3;
+        nearestDistance: number;
+        intersectionPoint: Vector3;
+        collidedMesh: AbstractMesh;
+        private _collisionPoint;
+        private _planeIntersectionPoint;
+        private _tempVector;
+        private _tempVector2;
+        private _tempVector3;
+        private _tempVector4;
+        private _edge;
+        private _baseToVertex;
+        private _destinationPoint;
+        private _slidePlaneNormal;
+        private _displacementVector;
+        private _collisionMask;
+        collisionMask: number;
+        _initialize(source: Vector3, dir: Vector3, e: number): void;
+        _checkPointInTriangle(point: Vector3, pa: Vector3, pb: Vector3, pc: Vector3, n: Vector3): boolean;
+        _canDoCollision(sphereCenter: Vector3, sphereRadius: number, vecMin: Vector3, vecMax: Vector3): boolean;
+        _testTriangle(faceIndex: number, trianglePlaneArray: Array<Plane>, p1: Vector3, p2: Vector3, p3: Vector3, hasMaterial: boolean): void;
+        _collide(trianglePlaneArray: Array<Plane>, pts: Vector3[], indices: IndicesArray, indexStart: number, indexEnd: number, decal: number, hasMaterial: boolean): void;
+        _getResponse(pos: Vector3, vel: Vector3): void;
+    }
+}
+
+declare module BABYLON {
+    var CollisionWorker: string;
+    interface ICollisionCoordinator {
+        getNewPosition(position: Vector3, velocity: Vector3, collider: Collider, maximumRetry: number, excludedMesh: AbstractMesh, onNewPosition: (collisionIndex: number, newPosition: Vector3, collidedMesh?: AbstractMesh) => void, collisionIndex: number): void;
+        init(scene: Scene): void;
+        destroy(): void;
+        onMeshAdded(mesh: AbstractMesh): any;
+        onMeshUpdated(mesh: AbstractMesh): any;
+        onMeshRemoved(mesh: AbstractMesh): any;
+        onGeometryAdded(geometry: Geometry): any;
+        onGeometryUpdated(geometry: Geometry): any;
+        onGeometryDeleted(geometry: Geometry): any;
+    }
+    interface SerializedMesh {
+        id: string;
+        name: string;
+        uniqueId: number;
+        geometryId: string;
+        sphereCenter: Array<number>;
+        sphereRadius: number;
+        boxMinimum: Array<number>;
+        boxMaximum: Array<number>;
+        worldMatrixFromCache: any;
+        subMeshes: Array<SerializedSubMesh>;
+        checkCollisions: boolean;
+    }
+    interface SerializedSubMesh {
+        position: number;
+        verticesStart: number;
+        verticesCount: number;
+        indexStart: number;
+        indexCount: number;
+        hasMaterial: boolean;
+        sphereCenter: Array<number>;
+        sphereRadius: number;
+        boxMinimum: Array<number>;
+        boxMaximum: Array<number>;
+    }
+    interface SerializedGeometry {
+        id: string;
+        positions: Float32Array;
+        indices: Uint32Array;
+        normals: Float32Array;
+    }
+    interface BabylonMessage {
+        taskType: WorkerTaskType;
+        payload: InitPayload | CollidePayload | UpdatePayload;
+    }
+    interface SerializedColliderToWorker {
+        position: Array<number>;
+        velocity: Array<number>;
+        radius: Array<number>;
+    }
+    enum WorkerTaskType {
+        INIT = 0,
+        UPDATE = 1,
+        COLLIDE = 2,
+    }
+    interface WorkerReply {
+        error: WorkerReplyType;
+        taskType: WorkerTaskType;
+        payload?: any;
+    }
+    interface CollisionReplyPayload {
+        newPosition: Array<number>;
+        collisionId: number;
+        collidedMeshUniqueId: number;
+    }
+    interface InitPayload {
+    }
+    interface CollidePayload {
+        collisionId: number;
+        collider: SerializedColliderToWorker;
+        maximumRetry: number;
+        excludedMeshUniqueId?: number;
+    }
+    interface UpdatePayload {
+        updatedMeshes: {
+            [n: number]: SerializedMesh;
+        };
+        updatedGeometries: {
+            [s: string]: SerializedGeometry;
+        };
+        removedMeshes: Array<number>;
+        removedGeometries: Array<string>;
+    }
+    enum WorkerReplyType {
+        SUCCESS = 0,
+        UNKNOWN_ERROR = 1,
+    }
+    class CollisionCoordinatorWorker implements ICollisionCoordinator {
+        private _scene;
+        private _scaledPosition;
+        private _scaledVelocity;
+        private _collisionsCallbackArray;
+        private _init;
+        private _runningUpdated;
+        private _runningCollisionTask;
+        private _worker;
+        private _addUpdateMeshesList;
+        private _addUpdateGeometriesList;
+        private _toRemoveMeshesArray;
+        private _toRemoveGeometryArray;
+        constructor();
+        static SerializeMesh: (mesh: AbstractMesh) => SerializedMesh;
+        static SerializeGeometry: (geometry: Geometry) => SerializedGeometry;
+        getNewPosition(position: Vector3, velocity: Vector3, collider: Collider, maximumRetry: number, excludedMesh: AbstractMesh, onNewPosition: (collisionIndex: number, newPosition: Vector3, collidedMesh?: AbstractMesh) => void, collisionIndex: number): void;
+        init(scene: Scene): void;
+        destroy(): void;
+        onMeshAdded(mesh: AbstractMesh): void;
+        onMeshUpdated: (mesh: AbstractMesh) => void;
+        onMeshRemoved(mesh: AbstractMesh): void;
+        onGeometryAdded(geometry: Geometry): void;
+        onGeometryUpdated: (geometry: Geometry) => void;
+        onGeometryDeleted(geometry: Geometry): void;
+        private _afterRender;
+        private _onMessageFromWorker;
+    }
+    class CollisionCoordinatorLegacy implements ICollisionCoordinator {
+        private _scene;
+        private _scaledPosition;
+        private _scaledVelocity;
+        private _finalPosition;
+        getNewPosition(position: Vector3, velocity: Vector3, collider: Collider, maximumRetry: number, excludedMesh: AbstractMesh, onNewPosition: (collisionIndex: number, newPosition: Vector3, collidedMesh?: AbstractMesh) => void, collisionIndex: number): void;
+        init(scene: Scene): void;
+        destroy(): void;
+        onMeshAdded(mesh: AbstractMesh): void;
+        onMeshUpdated(mesh: AbstractMesh): void;
+        onMeshRemoved(mesh: AbstractMesh): void;
+        onGeometryAdded(geometry: Geometry): void;
+        onGeometryUpdated(geometry: Geometry): void;
+        onGeometryDeleted(geometry: Geometry): void;
+        private _collideWithWorld(position, velocity, collider, maximumRetry, finalPosition, excludedMesh?);
+    }
+}
+
+declare module BABYLON {
+    var WorkerIncluded: boolean;
+    class CollisionCache {
+        private _meshes;
+        private _geometries;
+        getMeshes(): {
+            [n: number]: SerializedMesh;
+        };
+        getGeometries(): {
+            [s: number]: SerializedGeometry;
+        };
+        getMesh(id: any): SerializedMesh;
+        addMesh(mesh: SerializedMesh): void;
+        removeMesh(uniqueId: number): void;
+        getGeometry(id: string): SerializedGeometry;
+        addGeometry(geometry: SerializedGeometry): void;
+        removeGeometry(id: string): void;
+    }
+    class CollideWorker {
+        collider: Collider;
+        private _collisionCache;
+        private finalPosition;
+        private collisionsScalingMatrix;
+        private collisionTranformationMatrix;
+        constructor(collider: Collider, _collisionCache: CollisionCache, finalPosition: Vector3);
+        collideWithWorld(position: Vector3, velocity: Vector3, maximumRetry: number, excludedMeshUniqueId?: number): void;
+        private checkCollision(mesh);
+        private processCollisionsForSubMeshes(transformMatrix, mesh);
+        private collideForSubMesh(subMesh, transformMatrix, meshGeometry);
+        private checkSubmeshCollision(subMesh);
+    }
+    interface ICollisionDetector {
+        onInit(payload: InitPayload): void;
+        onUpdate(payload: UpdatePayload): void;
+        onCollision(payload: CollidePayload): void;
+    }
+    class CollisionDetectorTransferable implements ICollisionDetector {
+        private _collisionCache;
+        onInit(payload: InitPayload): void;
+        onUpdate(payload: UpdatePayload): void;
+        onCollision(payload: CollidePayload): void;
+    }
+}
+
+declare module BABYLON {
+    class IntersectionInfo {
+        bu: number;
+        bv: number;
+        distance: number;
+        faceId: number;
+        subMeshId: number;
+        constructor(bu: number, bv: number, distance: number);
+    }
+    class PickingInfo {
+        hit: boolean;
+        distance: number;
+        pickedPoint: Vector3;
+        pickedMesh: AbstractMesh;
+        bu: number;
+        bv: number;
+        faceId: number;
+        subMeshId: number;
+        pickedSprite: Sprite;
+        getNormal(useWorldCoordinates?: boolean, useVerticesNormals?: boolean): Vector3;
+        getTextureCoordinates(): Vector2;
+    }
+}
+
+declare module BABYLON {
     class BoundingBox implements ICullable {
         minimum: Vector3;
         maximum: Vector3;
@@ -4860,272 +5112,29 @@ declare module BABYLON {
     }
 }
 
-declare module BABYLON {
-    class TouchCamera extends FreeCamera {
-        touchAngularSensibility: number;
-        touchMoveSensibility: number;
-        constructor(name: string, position: Vector3, scene: Scene);
-        getClassName(): string;
-        _setupInputs(): void;
-    }
-}
-
-declare module BABYLON {
-    class UniversalCamera extends TouchCamera {
-        gamepadAngularSensibility: number;
-        gamepadMoveSensibility: number;
-        constructor(name: string, position: Vector3, scene: Scene);
-        getClassName(): string;
-    }
-}
-
-declare module BABYLON {
-    class VirtualJoysticksCamera extends FreeCamera {
-        constructor(name: string, position: Vector3, scene: Scene);
-        getClassName(): string;
-    }
-}
-
-declare module BABYLON {
-    class Collider {
-        radius: Vector3;
-        retry: number;
-        velocity: Vector3;
-        basePoint: Vector3;
-        epsilon: number;
-        collisionFound: boolean;
-        velocityWorldLength: number;
-        basePointWorld: Vector3;
-        velocityWorld: Vector3;
-        normalizedVelocity: Vector3;
-        initialVelocity: Vector3;
-        initialPosition: Vector3;
-        nearestDistance: number;
-        intersectionPoint: Vector3;
-        collidedMesh: AbstractMesh;
-        private _collisionPoint;
-        private _planeIntersectionPoint;
-        private _tempVector;
-        private _tempVector2;
-        private _tempVector3;
-        private _tempVector4;
-        private _edge;
-        private _baseToVertex;
-        private _destinationPoint;
-        private _slidePlaneNormal;
-        private _displacementVector;
-        private _collisionMask;
-        collisionMask: number;
-        _initialize(source: Vector3, dir: Vector3, e: number): void;
-        _checkPointInTriangle(point: Vector3, pa: Vector3, pb: Vector3, pc: Vector3, n: Vector3): boolean;
-        _canDoCollision(sphereCenter: Vector3, sphereRadius: number, vecMin: Vector3, vecMax: Vector3): boolean;
-        _testTriangle(faceIndex: number, trianglePlaneArray: Array<Plane>, p1: Vector3, p2: Vector3, p3: Vector3, hasMaterial: boolean): void;
-        _collide(trianglePlaneArray: Array<Plane>, pts: Vector3[], indices: IndicesArray, indexStart: number, indexEnd: number, decal: number, hasMaterial: boolean): void;
-        _getResponse(pos: Vector3, vel: Vector3): void;
-    }
-}
-
-declare module BABYLON {
-    var CollisionWorker: string;
-    interface ICollisionCoordinator {
-        getNewPosition(position: Vector3, velocity: Vector3, collider: Collider, maximumRetry: number, excludedMesh: AbstractMesh, onNewPosition: (collisionIndex: number, newPosition: Vector3, collidedMesh?: AbstractMesh) => void, collisionIndex: number): void;
-        init(scene: Scene): void;
-        destroy(): void;
-        onMeshAdded(mesh: AbstractMesh): any;
-        onMeshUpdated(mesh: AbstractMesh): any;
-        onMeshRemoved(mesh: AbstractMesh): any;
-        onGeometryAdded(geometry: Geometry): any;
-        onGeometryUpdated(geometry: Geometry): any;
-        onGeometryDeleted(geometry: Geometry): any;
-    }
-    interface SerializedMesh {
-        id: string;
-        name: string;
-        uniqueId: number;
-        geometryId: string;
-        sphereCenter: Array<number>;
-        sphereRadius: number;
-        boxMinimum: Array<number>;
-        boxMaximum: Array<number>;
-        worldMatrixFromCache: any;
-        subMeshes: Array<SerializedSubMesh>;
-        checkCollisions: boolean;
-    }
-    interface SerializedSubMesh {
-        position: number;
-        verticesStart: number;
-        verticesCount: number;
-        indexStart: number;
-        indexCount: number;
-        hasMaterial: boolean;
-        sphereCenter: Array<number>;
-        sphereRadius: number;
-        boxMinimum: Array<number>;
-        boxMaximum: Array<number>;
-    }
-    interface SerializedGeometry {
-        id: string;
-        positions: Float32Array;
-        indices: Uint32Array;
-        normals: Float32Array;
-    }
-    interface BabylonMessage {
-        taskType: WorkerTaskType;
-        payload: InitPayload | CollidePayload | UpdatePayload;
-    }
-    interface SerializedColliderToWorker {
-        position: Array<number>;
-        velocity: Array<number>;
-        radius: Array<number>;
-    }
-    enum WorkerTaskType {
-        INIT = 0,
-        UPDATE = 1,
-        COLLIDE = 2,
-    }
-    interface WorkerReply {
-        error: WorkerReplyType;
-        taskType: WorkerTaskType;
-        payload?: any;
-    }
-    interface CollisionReplyPayload {
-        newPosition: Array<number>;
-        collisionId: number;
-        collidedMeshUniqueId: number;
-    }
-    interface InitPayload {
-    }
-    interface CollidePayload {
-        collisionId: number;
-        collider: SerializedColliderToWorker;
-        maximumRetry: number;
-        excludedMeshUniqueId?: number;
-    }
-    interface UpdatePayload {
-        updatedMeshes: {
-            [n: number]: SerializedMesh;
-        };
-        updatedGeometries: {
-            [s: string]: SerializedGeometry;
-        };
-        removedMeshes: Array<number>;
-        removedGeometries: Array<string>;
-    }
-    enum WorkerReplyType {
-        SUCCESS = 0,
-        UNKNOWN_ERROR = 1,
-    }
-    class CollisionCoordinatorWorker implements ICollisionCoordinator {
-        private _scene;
-        private _scaledPosition;
-        private _scaledVelocity;
-        private _collisionsCallbackArray;
-        private _init;
-        private _runningUpdated;
-        private _runningCollisionTask;
-        private _worker;
-        private _addUpdateMeshesList;
-        private _addUpdateGeometriesList;
-        private _toRemoveMeshesArray;
-        private _toRemoveGeometryArray;
-        constructor();
-        static SerializeMesh: (mesh: AbstractMesh) => SerializedMesh;
-        static SerializeGeometry: (geometry: Geometry) => SerializedGeometry;
-        getNewPosition(position: Vector3, velocity: Vector3, collider: Collider, maximumRetry: number, excludedMesh: AbstractMesh, onNewPosition: (collisionIndex: number, newPosition: Vector3, collidedMesh?: AbstractMesh) => void, collisionIndex: number): void;
-        init(scene: Scene): void;
-        destroy(): void;
-        onMeshAdded(mesh: AbstractMesh): void;
-        onMeshUpdated: (mesh: AbstractMesh) => void;
-        onMeshRemoved(mesh: AbstractMesh): void;
-        onGeometryAdded(geometry: Geometry): void;
-        onGeometryUpdated: (geometry: Geometry) => void;
-        onGeometryDeleted(geometry: Geometry): void;
-        private _afterRender;
-        private _onMessageFromWorker;
-    }
-    class CollisionCoordinatorLegacy implements ICollisionCoordinator {
-        private _scene;
-        private _scaledPosition;
-        private _scaledVelocity;
-        private _finalPosition;
-        getNewPosition(position: Vector3, velocity: Vector3, collider: Collider, maximumRetry: number, excludedMesh: AbstractMesh, onNewPosition: (collisionIndex: number, newPosition: Vector3, collidedMesh?: AbstractMesh) => void, collisionIndex: number): void;
-        init(scene: Scene): void;
-        destroy(): void;
-        onMeshAdded(mesh: AbstractMesh): void;
-        onMeshUpdated(mesh: AbstractMesh): void;
-        onMeshRemoved(mesh: AbstractMesh): void;
-        onGeometryAdded(geometry: Geometry): void;
-        onGeometryUpdated(geometry: Geometry): void;
-        onGeometryDeleted(geometry: Geometry): void;
-        private _collideWithWorld(position, velocity, collider, maximumRetry, finalPosition, excludedMesh?);
+declare module BABYLON {
+    class TouchCamera extends FreeCamera {
+        touchAngularSensibility: number;
+        touchMoveSensibility: number;
+        constructor(name: string, position: Vector3, scene: Scene);
+        getClassName(): string;
+        _setupInputs(): void;
     }
 }
 
 declare module BABYLON {
-    var WorkerIncluded: boolean;
-    class CollisionCache {
-        private _meshes;
-        private _geometries;
-        getMeshes(): {
-            [n: number]: SerializedMesh;
-        };
-        getGeometries(): {
-            [s: number]: SerializedGeometry;
-        };
-        getMesh(id: any): SerializedMesh;
-        addMesh(mesh: SerializedMesh): void;
-        removeMesh(uniqueId: number): void;
-        getGeometry(id: string): SerializedGeometry;
-        addGeometry(geometry: SerializedGeometry): void;
-        removeGeometry(id: string): void;
-    }
-    class CollideWorker {
-        collider: Collider;
-        private _collisionCache;
-        private finalPosition;
-        private collisionsScalingMatrix;
-        private collisionTranformationMatrix;
-        constructor(collider: Collider, _collisionCache: CollisionCache, finalPosition: Vector3);
-        collideWithWorld(position: Vector3, velocity: Vector3, maximumRetry: number, excludedMeshUniqueId?: number): void;
-        private checkCollision(mesh);
-        private processCollisionsForSubMeshes(transformMatrix, mesh);
-        private collideForSubMesh(subMesh, transformMatrix, meshGeometry);
-        private checkSubmeshCollision(subMesh);
-    }
-    interface ICollisionDetector {
-        onInit(payload: InitPayload): void;
-        onUpdate(payload: UpdatePayload): void;
-        onCollision(payload: CollidePayload): void;
-    }
-    class CollisionDetectorTransferable implements ICollisionDetector {
-        private _collisionCache;
-        onInit(payload: InitPayload): void;
-        onUpdate(payload: UpdatePayload): void;
-        onCollision(payload: CollidePayload): void;
+    class UniversalCamera extends TouchCamera {
+        gamepadAngularSensibility: number;
+        gamepadMoveSensibility: number;
+        constructor(name: string, position: Vector3, scene: Scene);
+        getClassName(): string;
     }
 }
 
 declare module BABYLON {
-    class IntersectionInfo {
-        bu: number;
-        bv: number;
-        distance: number;
-        faceId: number;
-        subMeshId: number;
-        constructor(bu: number, bv: number, distance: number);
-    }
-    class PickingInfo {
-        hit: boolean;
-        distance: number;
-        pickedPoint: Vector3;
-        pickedMesh: AbstractMesh;
-        bu: number;
-        bv: number;
-        faceId: number;
-        subMeshId: number;
-        pickedSprite: Sprite;
-        getNormal(useWorldCoordinates?: boolean, useVerticesNormals?: boolean): Vector3;
-        getTextureCoordinates(): Vector2;
+    class VirtualJoysticksCamera extends FreeCamera {
+        constructor(name: string, position: Vector3, scene: Scene);
+        getClassName(): string;
     }
 }
 
@@ -6753,7 +6762,7 @@ declare module BABYLON {
         bindOnlyWorldMatrix(world: Matrix): void;
         bind(world: Matrix, mesh?: Mesh): void;
         protected _afterBind(mesh: Mesh, effect?: Effect): void;
-        protected _mustRebind(scene: Scene, effect: Effect): boolean;
+        protected _mustRebind(scene: Scene, effect: Effect, visibility?: number): boolean;
         markAsDirty(flag: number): void;
         protected _markAllSubMeshesAsDirty(func: (defines: MaterialDefines) => void): void;
         protected _markAllSubMeshesAsTexturesDirty(): void;
@@ -7313,6 +7322,16 @@ declare module BABYLON {
          */
         static Clamp(value: number, min?: number, max?: number): number;
     }
+    class Scalar {
+        /**
+         * Creates a new scalar with values linearly interpolated of "amount" between the start scalar and the end scalar.
+         */
+        static Lerp(start: number, end: number, amount: number): number;
+        /**
+         * Returns a new scalar located for "amount" (float) on the Hermite spline defined by the scalars "value1", "value3", "tangent1", "tangent2".
+         */
+        static Hermite(value1: number, tangent1: number, value2: number, tangent2: number, amount: number): number;
+    }
     class Color3 {
         r: number;
         g: number;
@@ -7742,7 +7761,7 @@ declare module BABYLON {
          */
         static Clamp(value: Vector2, min: Vector2, max: Vector2): Vector2;
         /**
-         * Returns a new Vecto2 located for "amount" (float) on the Hermite spline defined by the vectors "value1", "value3", "tangent1", "tangent2".
+         * Returns a new Vector2 located for "amount" (float) on the Hermite spline defined by the vectors "value1", "value3", "tangent1", "tangent2".
          */
         static Hermite(value1: Vector2, tangent1: Vector2, value2: Vector2, tangent2: Vector2, amount: number): Vector2;
         /**
@@ -8590,6 +8609,10 @@ declare module BABYLON {
         static RotationQuaternionFromAxisToRef(axis1: Vector3, axis2: Vector3, axis3: Vector3, ref: Quaternion): void;
         static Slerp(left: Quaternion, right: Quaternion, amount: number): Quaternion;
         static SlerpToRef(left: Quaternion, right: Quaternion, amount: number, result: Quaternion): void;
+        /**
+         * Returns a new Quaternion located for "amount" (float) on the Hermite interpolation spline defined by the vectors "value1", "tangent1", "value2", "tangent2".
+         */
+        static Hermite(value1: Quaternion, tangent1: Quaternion, value2: Quaternion, tangent2: Quaternion, amount: number): Quaternion;
     }
     class Matrix {
         private static _tempQuaternion;
@@ -9298,68 +9321,6 @@ declare module BABYLON {
 }
 
 declare module BABYLON {
-    class MorphTarget {
-        name: string;
-        private _positions;
-        private _normals;
-        private _tangents;
-        private _influence;
-        onInfluenceChanged: Observable<boolean>;
-        influence: number;
-        constructor(name: string, influence?: number);
-        readonly hasNormals: boolean;
-        readonly hasTangents: boolean;
-        setPositions(data: Float32Array | number[]): void;
-        getPositions(): Float32Array;
-        setNormals(data: Float32Array | number[]): void;
-        getNormals(): Float32Array;
-        setTangents(data: Float32Array | number[]): void;
-        getTangents(): Float32Array;
-        /**
-         * Serializes the current target into a Serialization object.
-         * Returns the serialized object.
-         */
-        serialize(): any;
-        static Parse(serializationObject: any): MorphTarget;
-        static FromMesh(mesh: AbstractMesh, name?: string, influence?: number): MorphTarget;
-    }
-}
-
-declare module BABYLON {
-    class MorphTargetManager {
-        private _targets;
-        private _targetObservable;
-        private _activeTargets;
-        private _scene;
-        private _influences;
-        private _supportsNormals;
-        private _supportsTangents;
-        private _vertexCount;
-        private _uniqueId;
-        constructor(scene?: Scene);
-        readonly uniqueId: number;
-        readonly vertexCount: number;
-        readonly supportsNormals: boolean;
-        readonly supportsTangents: boolean;
-        readonly numTargets: number;
-        readonly numInfluencers: number;
-        readonly influences: Float32Array;
-        getActiveTarget(index: number): MorphTarget;
-        getTarget(index: number): MorphTarget;
-        addTarget(target: MorphTarget): void;
-        removeTarget(target: MorphTarget): void;
-        /**
-         * Serializes the current manager into a Serialization object.
-         * Returns the serialized object.
-         */
-        serialize(): any;
-        private _onInfluenceChanged(needUpdate);
-        private _syncActiveTargets(needUpdate);
-        static Parse(serializationObject: any, scene: Scene): MorphTargetManager;
-    }
-}
-
-declare module BABYLON {
     class AbstractMesh extends Node implements IDisposable, ICullable, IGetSetVerticesData {
         private static _BILLBOARDMODE_NONE;
         private static _BILLBOARDMODE_X;
@@ -10129,7 +10090,7 @@ declare module BABYLON {
         private updateBoundingInfo(updateExtends, data);
         _bind(effect: Effect, indexToBind?: WebGLBuffer): void;
         getTotalVertices(): number;
-        getVerticesData(kind: string, copyWhenShared?: boolean): number[] | Float32Array;
+        getVerticesData(kind: string, copyWhenShared?: boolean, forceCopy?: boolean): number[] | Float32Array;
         getVertexBuffer(kind: string): VertexBuffer;
         getVertexBuffers(): {
             [key: string]: VertexBuffer;
@@ -10672,6 +10633,7 @@ declare module BABYLON {
         /**
          * Returns an array of integers or floats, or a Float32Array, depending on the requested `kind` (positions, indices, normals, etc).
          * If `copywhenShared` is true (default false) and if the mesh geometry is shared among some other meshes, the returned array is a copy of the internal one.
+         * You can force the copy with forceCopy === true
          * Returns null if the mesh has no geometry or no vertex buffer.
          * Possible `kind` values :
          * - BABYLON.VertexBuffer.PositionKind
@@ -10687,7 +10649,7 @@ declare module BABYLON {
          * - BABYLON.VertexBuffer.MatricesWeightsKind
          * - BABYLON.VertexBuffer.MatricesWeightsExtraKind
          */
-        getVerticesData(kind: string, copyWhenShared?: boolean): number[] | Float32Array;
+        getVerticesData(kind: string, copyWhenShared?: boolean, forceCopy?: boolean): number[] | Float32Array;
         /**
          * Returns the mesh VertexBuffer object from the requested `kind` : positions, indices, normals, etc.
          * Returns `undefined` if the mesh has no geometry.
@@ -11084,7 +11046,7 @@ declare module BABYLON {
          * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
-        static CreateRibbon(name: string, pathArray: Vector3[][], closeArray: boolean, closePath: boolean, offset: number, scene: Scene, updatable?: boolean, sideOrientation?: number, instance?: Mesh): Mesh;
+        static CreateRibbon(name: string, pathArray: Vector3[][], closeArray: boolean, closePath: boolean, offset: number, scene?: Scene, updatable?: boolean, sideOrientation?: number, instance?: Mesh): Mesh;
         /**
          * Creates a plane polygonal mesh.  By default, this is a disc.
          * Please consider using the same method from the MeshBuilder class instead.
@@ -11094,7 +11056,7 @@ declare module BABYLON {
          * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
-        static CreateDisc(name: string, radius: number, tessellation: number, scene: Scene, updatable?: boolean, sideOrientation?: number): Mesh;
+        static CreateDisc(name: string, radius: number, tessellation: number, scene?: Scene, updatable?: boolean, sideOrientation?: number): Mesh;
         /**
          * Creates a box mesh.
          * Please consider using the same method from the MeshBuilder class instead.
@@ -11103,7 +11065,7 @@ declare module BABYLON {
          * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
-        static CreateBox(name: string, size: number, scene: Scene, updatable?: boolean, sideOrientation?: number): Mesh;
+        static CreateBox(name: string, size: number, scene?: Scene, updatable?: boolean, sideOrientation?: number): Mesh;
         /**
          * Creates a sphere mesh.
          * Please consider using the same method from the MeshBuilder class instead.
@@ -11126,7 +11088,7 @@ declare module BABYLON {
          * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
-        static CreateCylinder(name: string, height: number, diameterTop: number, diameterBottom: number, tessellation: number, subdivisions: any, scene: Scene, updatable?: any, sideOrientation?: number): Mesh;
+        static CreateCylinder(name: string, height: number, diameterTop: number, diameterBottom: number, tessellation: number, subdivisions: any, scene?: Scene, updatable?: any, sideOrientation?: number): Mesh;
         /**
          * Creates a torus mesh.
          * Please consider using the same method from the MeshBuilder class instead.
@@ -11137,7 +11099,7 @@ declare module BABYLON {
          * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
-        static CreateTorus(name: string, diameter: number, thickness: number, tessellation: number, scene: Scene, updatable?: boolean, sideOrientation?: number): Mesh;
+        static CreateTorus(name: string, diameter: number, thickness: number, tessellation: number, scene?: Scene, updatable?: boolean, sideOrientation?: number): Mesh;
         /**
          * Creates a torus knot mesh.
          * Please consider using the same method from the MeshBuilder class instead.
@@ -11149,7 +11111,7 @@ declare module BABYLON {
          * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
-        static CreateTorusKnot(name: string, radius: number, tube: number, radialSegments: number, tubularSegments: number, p: number, q: number, scene: Scene, updatable?: boolean, sideOrientation?: number): Mesh;
+        static CreateTorusKnot(name: string, radius: number, tube: number, radialSegments: number, tubularSegments: number, p: number, q: number, scene?: Scene, updatable?: boolean, sideOrientation?: number): Mesh;
         /**
          * Creates a line mesh.
          * Please consider using the same method from the MeshBuilder class instead.
@@ -11160,7 +11122,7 @@ declare module BABYLON {
          * When updating an instance, remember that only point positions can change, not the number of points.
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
-        static CreateLines(name: string, points: Vector3[], scene: Scene, updatable?: boolean, instance?: LinesMesh): LinesMesh;
+        static CreateLines(name: string, points: Vector3[], scene?: Scene, updatable?: boolean, instance?: LinesMesh): LinesMesh;
         /**
          * Creates a dashed line mesh.
          * Please consider using the same method from the MeshBuilder class instead.
@@ -11174,7 +11136,7 @@ declare module BABYLON {
          * When updating an instance, remember that only point positions can change, not the number of points.
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
-        static CreateDashedLines(name: string, points: Vector3[], dashSize: number, gapSize: number, dashNb: number, scene: Scene, updatable?: boolean, instance?: LinesMesh): LinesMesh;
+        static CreateDashedLines(name: string, points: Vector3[], dashSize: number, gapSize: number, dashNb: number, scene?: Scene, updatable?: boolean, instance?: LinesMesh): LinesMesh;
         /**
          * Creates an extruded shape mesh.
          * The extrusion is a parametric shape :  http://doc.babylonjs.com/tutorials/Parametric_Shapes.  It has no predefined shape. Its final shape will depend on the input parameters.
@@ -11193,7 +11155,7 @@ declare module BABYLON {
          * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
-        static ExtrudeShape(name: string, shape: Vector3[], path: Vector3[], scale: number, rotation: number, cap: number, scene: Scene, updatable?: boolean, sideOrientation?: number, instance?: Mesh): Mesh;
+        static ExtrudeShape(name: string, shape: Vector3[], path: Vector3[], scale: number, rotation: number, cap: number, scene?: Scene, updatable?: boolean, sideOrientation?: number, instance?: Mesh): Mesh;
         /**
          * Creates an custom extruded shape mesh.
          * The custom extrusion is a parametric shape :  http://doc.babylonjs.com/tutorials/Parametric_Shapes.  It has no predefined shape. Its final shape will depend on the input parameters.
@@ -11258,7 +11220,7 @@ declare module BABYLON {
          * The parameter `subdivisions` (positive integer) sets the number of subdivisions per side.
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
-        static CreateGround(name: string, width: number, height: number, subdivisions: number, scene: Scene, updatable?: boolean): Mesh;
+        static CreateGround(name: string, width: number, height: number, subdivisions: number, scene?: Scene, updatable?: boolean): Mesh;
         /**
          * Creates a tiled ground mesh.
          * Please consider using the same method from the MeshBuilder class instead.
@@ -11418,7 +11380,7 @@ declare module BABYLON {
     type IndicesArray = number[] | Int32Array | Uint32Array | Uint16Array;
     interface IGetSetVerticesData {
         isVerticesDataPresent(kind: string): boolean;
-        getVerticesData(kind: string, copyWhenShared?: boolean): number[] | Float32Array;
+        getVerticesData(kind: string, copyWhenShared?: boolean, forceCopy?: boolean): number[] | Float32Array;
         getIndices(copyWhenShared?: boolean): IndicesArray;
         setVerticesData(kind: string, data: number[] | Float32Array, updatable?: boolean): void;
         updateVerticesData(kind: string, data: number[] | Float32Array, updateExtends?: boolean, makeItUnique?: boolean): void;
@@ -11484,12 +11446,12 @@ declare module BABYLON {
         /**
          * Returns the object VertexData associated to the passed mesh.
          */
-        static ExtractFromMesh(mesh: Mesh, copyWhenShared?: boolean): VertexData;
+        static ExtractFromMesh(mesh: Mesh, copyWhenShared?: boolean, forceCopy?: boolean): VertexData;
         /**
          * Returns the object VertexData associated to the passed geometry.
          */
-        static ExtractFromGeometry(geometry: Geometry, copyWhenShared?: boolean): VertexData;
-        private static _ExtractFrom(meshOrGeometry, copyWhenShared?);
+        static ExtractFromGeometry(geometry: Geometry, copyWhenShared?: boolean, forceCopy?: boolean): VertexData;
+        private static _ExtractFrom(meshOrGeometry, copyWhenShared?, forceCopy?);
         /**
          * Creates the vertexData of the Ribbon.
          */
@@ -12580,6 +12542,69 @@ declare module BABYLON {
 }
 
 declare module BABYLON {
+    class MorphTarget {
+        name: string;
+        animations: Animation[];
+        private _positions;
+        private _normals;
+        private _tangents;
+        private _influence;
+        onInfluenceChanged: Observable<boolean>;
+        influence: number;
+        constructor(name: string, influence?: number);
+        readonly hasNormals: boolean;
+        readonly hasTangents: boolean;
+        setPositions(data: Float32Array | number[]): void;
+        getPositions(): Float32Array;
+        setNormals(data: Float32Array | number[]): void;
+        getNormals(): Float32Array;
+        setTangents(data: Float32Array | number[]): void;
+        getTangents(): Float32Array;
+        /**
+         * Serializes the current target into a Serialization object.
+         * Returns the serialized object.
+         */
+        serialize(): any;
+        static Parse(serializationObject: any): MorphTarget;
+        static FromMesh(mesh: AbstractMesh, name?: string, influence?: number): MorphTarget;
+    }
+}
+
+declare module BABYLON {
+    class MorphTargetManager {
+        private _targets;
+        private _targetObservable;
+        private _activeTargets;
+        private _scene;
+        private _influences;
+        private _supportsNormals;
+        private _supportsTangents;
+        private _vertexCount;
+        private _uniqueId;
+        constructor(scene?: Scene);
+        readonly uniqueId: number;
+        readonly vertexCount: number;
+        readonly supportsNormals: boolean;
+        readonly supportsTangents: boolean;
+        readonly numTargets: number;
+        readonly numInfluencers: number;
+        readonly influences: Float32Array;
+        getActiveTarget(index: number): MorphTarget;
+        getTarget(index: number): MorphTarget;
+        addTarget(target: MorphTarget): void;
+        removeTarget(target: MorphTarget): void;
+        /**
+         * Serializes the current manager into a Serialization object.
+         * Returns the serialized object.
+         */
+        serialize(): any;
+        private _onInfluenceChanged(needUpdate);
+        private _syncActiveTargets(needUpdate);
+        static Parse(serializationObject: any, scene: Scene): MorphTargetManager;
+    }
+}
+
+declare module BABYLON {
     class Particle {
         position: Vector3;
         direction: Vector3;
@@ -13397,6 +13422,29 @@ declare module BABYLON {
 }
 
 declare module BABYLON {
+    class ReflectionProbe {
+        name: string;
+        private _scene;
+        private _renderTargetTexture;
+        private _projectionMatrix;
+        private _viewMatrix;
+        private _target;
+        private _add;
+        private _attachedMesh;
+        invertYAxis: boolean;
+        position: Vector3;
+        constructor(name: string, size: number, scene: Scene, generateMipMaps?: boolean);
+        samples: number;
+        refreshRate: number;
+        getScene(): Scene;
+        readonly cubeTexture: RenderTargetTexture;
+        readonly renderList: AbstractMesh[];
+        attachToMesh(mesh: AbstractMesh): void;
+        dispose(): void;
+    }
+}
+
+declare module BABYLON {
     class AnaglyphPostProcess extends PostProcess {
         private _passedProcess;
         constructor(name: string, options: number | PostProcessOptions, rigCameras: Camera[], samplingMode?: number, engine?: Engine, reusable?: boolean);
@@ -14322,29 +14370,6 @@ declare module BABYLON {
 }
 
 declare module BABYLON {
-    class ReflectionProbe {
-        name: string;
-        private _scene;
-        private _renderTargetTexture;
-        private _projectionMatrix;
-        private _viewMatrix;
-        private _target;
-        private _add;
-        private _attachedMesh;
-        invertYAxis: boolean;
-        position: Vector3;
-        constructor(name: string, size: number, scene: Scene, generateMipMaps?: boolean);
-        samples: number;
-        refreshRate: number;
-        getScene(): Scene;
-        readonly cubeTexture: RenderTargetTexture;
-        readonly renderList: AbstractMesh[];
-        attachToMesh(mesh: AbstractMesh): void;
-        dispose(): void;
-    }
-}
-
-declare module BABYLON {
     class Sprite {
         name: string;
         position: Vector3;

文件差异内容过多而无法显示
+ 38 - 38
dist/preview release/babylon.js


+ 239 - 121
dist/preview release/babylon.max.js

@@ -63,6 +63,30 @@ var __extends = (this && this.__extends) || (function () {
         return MathTools;
     }());
     BABYLON.MathTools = MathTools;
+    var Scalar = (function () {
+        function Scalar() {
+        }
+        /**
+         * Creates a new scalar with values linearly interpolated of "amount" between the start scalar and the end scalar.
+         */
+        Scalar.Lerp = function (start, end, amount) {
+            return start + ((end - start) * amount);
+        };
+        /**
+         * Returns a new scalar located for "amount" (float) on the Hermite spline defined by the scalars "value1", "value3", "tangent1", "tangent2".
+         */
+        Scalar.Hermite = function (value1, tangent1, value2, tangent2, amount) {
+            var squared = amount * amount;
+            var cubed = amount * squared;
+            var part1 = ((2.0 * cubed) - (3.0 * squared)) + 1.0;
+            var part2 = (-2.0 * cubed) + (3.0 * squared);
+            var part3 = (cubed - (2.0 * squared)) + amount;
+            var part4 = cubed - squared;
+            return (((value1 * part1) + (value2 * part2)) + (tangent1 * part3)) + (tangent2 * part4);
+        };
+        return Scalar;
+    }());
+    BABYLON.Scalar = Scalar;
     var Color3 = (function () {
         /**
          * Creates a new Color3 object from red, green, blue values, all between 0 and 1.
@@ -859,7 +883,7 @@ var __extends = (this && this.__extends) || (function () {
             return new Vector2(x, y);
         };
         /**
-         * Returns a new Vecto2 located for "amount" (float) on the Hermite spline defined by the vectors "value1", "value3", "tangent1", "tangent2".
+         * Returns a new Vector2 located for "amount" (float) on the Hermite spline defined by the vectors "value1", "value3", "tangent1", "tangent2".
          */
         Vector2.Hermite = function (value1, tangent1, value2, tangent2, amount) {
             var squared = amount * amount;
@@ -2661,6 +2685,22 @@ var __extends = (this && this.__extends) || (function () {
             result.z = (num3 * left.z) + (num2 * right.z);
             result.w = (num3 * left.w) + (num2 * right.w);
         };
+        /**
+         * Returns a new Quaternion located for "amount" (float) on the Hermite interpolation spline defined by the vectors "value1", "tangent1", "value2", "tangent2".
+         */
+        Quaternion.Hermite = function (value1, tangent1, value2, tangent2, amount) {
+            var squared = amount * amount;
+            var cubed = amount * squared;
+            var part1 = ((2.0 * cubed) - (3.0 * squared)) + 1.0;
+            var part2 = (-2.0 * cubed) + (3.0 * squared);
+            var part3 = (cubed - (2.0 * squared)) + amount;
+            var part4 = cubed - squared;
+            var x = (((value1.x * part1) + (value2.x * part2)) + (tangent1.x * part3)) + (tangent2.x * part4);
+            var y = (((value1.y * part1) + (value2.y * part2)) + (tangent1.y * part3)) + (tangent2.y * part4);
+            var z = (((value1.z * part1) + (value2.z * part2)) + (tangent1.z * part3)) + (tangent2.z * part4);
+            var w = (((value1.w * part1) + (value2.w * part2)) + (tangent1.w * part3)) + (tangent2.w * part4);
+            return new Quaternion(x, y, z, w);
+        };
         return Quaternion;
     }());
     BABYLON.Quaternion = Quaternion;
@@ -7020,6 +7060,11 @@ var BABYLON;
             // To enable/disable IDB support and avoid XHR on .manifest
             this.enableOfflineSupport = BABYLON.Database;
             this.scenes = new Array();
+            // Observables
+            /**
+             * Observable event triggered each time the rendering canvas is resized
+             */
+            this.onResizeObservable = new BABYLON.Observable();
             this._windowIsBackground = false;
             this._webGLVersion = 1.0;
             this._badOS = false;
@@ -7908,6 +7953,9 @@ var BABYLON;
          * @param {number} height - the new canvas' height
          */
         Engine.prototype.setSize = function (width, height) {
+            if (this._renderingCanvas.width === width && this._renderingCanvas.height === height) {
+                return;
+            }
             this._renderingCanvas.width = width;
             this._renderingCanvas.height = height;
             for (var index = 0; index < this.scenes.length; index++) {
@@ -7917,8 +7965,49 @@ var BABYLON;
                     cam._currentRenderId = 0;
                 }
             }
+            if (this.onResizeObservable.hasObservers) {
+                this.onResizeObservable.notifyObservers(this);
+            }
         };
         //WebVR functions
+        Engine.prototype.isVRDevicePresent = function (callback) {
+            this.getVRDevice(null, function (device) {
+                callback(device !== null);
+            });
+        };
+        Engine.prototype.getVRDevice = function (name, callback) {
+            if (!this.vrDisplaysPromise) {
+                callback(null);
+                return;
+            }
+            this.vrDisplaysPromise.then(function (devices) {
+                if (devices.length > 0) {
+                    if (name) {
+                        var found = devices.some(function (device) {
+                            if (device.displayName === name) {
+                                callback(device);
+                                return true;
+                            }
+                            else {
+                                return false;
+                            }
+                        });
+                        if (!found) {
+                            BABYLON.Tools.Warn("Display " + name + " was not found. Using " + devices[0].displayName);
+                            callback(devices[0]);
+                        }
+                    }
+                    else {
+                        //choose the first one
+                        callback(devices[0]);
+                    }
+                }
+                else {
+                    BABYLON.Tools.Error("No WebVR devices found!");
+                    callback(null);
+                }
+            });
+        };
         Engine.prototype.initWebVR = function () {
             if (!this.vrDisplaysPromise) {
                 this._getVRDisplays();
@@ -12691,7 +12780,7 @@ var BABYLON;
             _this._excludedMeshesIds = new Array();
             _this._includedOnlyMeshesIds = new Array();
             _this.getScene().addLight(_this);
-            _this._uniformBuffer = new BABYLON.UniformBuffer(scene.getEngine());
+            _this._uniformBuffer = new BABYLON.UniformBuffer(_this.getScene().getEngine());
             _this._buildUniformLayout();
             _this.includedOnlyMeshes = new Array();
             _this.excludedMeshes = new Array();
@@ -15097,6 +15186,13 @@ var BABYLON;
         Scene.prototype.getCachedEffect = function () {
             return this._cachedEffect;
         };
+        Scene.prototype.getCachedVisibility = function () {
+            return this._cachedVisibility;
+        };
+        Scene.prototype.isCachedMaterialValid = function (material, effect, visibility) {
+            if (visibility === void 0) { visibility = 0; }
+            return this._cachedEffect !== effect || this._cachedMaterial !== material || this._cachedVisibility !== visibility;
+        };
         Scene.prototype.getBoundingBoxRenderer = function () {
             if (!this._boundingBoxRenderer) {
                 this._boundingBoxRenderer = new BABYLON.BoundingBoxRenderer(this);
@@ -15727,6 +15823,7 @@ var BABYLON;
         Scene.prototype.resetCachedMaterial = function () {
             this._cachedMaterial = null;
             this._cachedEffect = null;
+            this._cachedVisibility = null;
         };
         Scene.prototype.registerBeforeRender = function (func) {
             this.onBeforeRenderObservable.add(func);
@@ -17989,7 +18086,8 @@ var BABYLON;
         };
         BaseTexture.prototype.isReady = function () {
             if (this.delayLoadState === BABYLON.Engine.DELAYLOADSTATE_NOTLOADED) {
-                return true;
+                this.delayLoad();
+                return false;
             }
             if (this._texture) {
                 return this._texture.isReady;
@@ -18157,6 +18255,7 @@ var BABYLON;
             _this._buffer = buffer;
             _this._deleteBuffer = deleteBuffer;
             _this._format = format;
+            scene = _this.getScene();
             if (!url) {
                 return _this;
             }
@@ -18825,6 +18924,7 @@ var BABYLON;
         /**
          * Returns an array of integers or floats, or a Float32Array, depending on the requested `kind` (positions, indices, normals, etc).
          * If `copywhenShared` is true (default false) and if the mesh geometry is shared among some other meshes, the returned array is a copy of the internal one.
+         * You can force the copy with forceCopy === true
          * Returns null if the mesh has no geometry or no vertex buffer.
          * Possible `kind` values :
          * - BABYLON.VertexBuffer.PositionKind
@@ -18840,11 +18940,11 @@ var BABYLON;
          * - BABYLON.VertexBuffer.MatricesWeightsKind
          * - BABYLON.VertexBuffer.MatricesWeightsExtraKind
          */
-        Mesh.prototype.getVerticesData = function (kind, copyWhenShared) {
+        Mesh.prototype.getVerticesData = function (kind, copyWhenShared, forceCopy) {
             if (!this._geometry) {
                 return null;
             }
-            return this._geometry.getVerticesData(kind, copyWhenShared);
+            return this._geometry.getVerticesData(kind, copyWhenShared, forceCopy);
         };
         /**
          * Returns the mesh VertexBuffer object from the requested `kind` : positions, indices, normals, etc.
@@ -21118,7 +21218,7 @@ var BABYLON;
             for (index = 0; index < meshes.length; index++) {
                 if (meshes[index]) {
                     meshes[index].computeWorldMatrix(true);
-                    otherVertexData = BABYLON.VertexData.ExtractFromMesh(meshes[index], true);
+                    otherVertexData = BABYLON.VertexData.ExtractFromMesh(meshes[index], false, true);
                     otherVertexData.transform(meshes[index].getWorldMatrix());
                     if (vertexData) {
                         vertexData.merge(otherVertexData);
@@ -23694,8 +23794,9 @@ var BABYLON;
             _super.prototype._afterBind.call(this, mesh);
             this.getScene()._cachedEffect = effect;
         };
-        PushMaterial.prototype._mustRebind = function (scene, effect) {
-            return scene.getCachedEffect() !== effect || scene.getCachedMaterial() !== this;
+        PushMaterial.prototype._mustRebind = function (scene, effect, visibility) {
+            if (visibility === void 0) { visibility = 0; }
+            return scene.isCachedMaterialValid(this, effect, visibility);
         };
         PushMaterial.prototype.markAsDirty = function (flag) {
             if (flag & BABYLON.Material.TextureDirtyFlag) {
@@ -24092,58 +24193,58 @@ var BABYLON;
         /**
          * Returns the object VertexData associated to the passed mesh.
          */
-        VertexData.ExtractFromMesh = function (mesh, copyWhenShared) {
-            return VertexData._ExtractFrom(mesh, copyWhenShared);
+        VertexData.ExtractFromMesh = function (mesh, copyWhenShared, forceCopy) {
+            return VertexData._ExtractFrom(mesh, copyWhenShared, forceCopy);
         };
         /**
          * Returns the object VertexData associated to the passed geometry.
          */
-        VertexData.ExtractFromGeometry = function (geometry, copyWhenShared) {
-            return VertexData._ExtractFrom(geometry, copyWhenShared);
+        VertexData.ExtractFromGeometry = function (geometry, copyWhenShared, forceCopy) {
+            return VertexData._ExtractFrom(geometry, copyWhenShared, forceCopy);
         };
-        VertexData._ExtractFrom = function (meshOrGeometry, copyWhenShared) {
+        VertexData._ExtractFrom = function (meshOrGeometry, copyWhenShared, forceCopy) {
             var result = new VertexData();
             if (meshOrGeometry.isVerticesDataPresent(BABYLON.VertexBuffer.PositionKind)) {
-                result.positions = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.PositionKind, copyWhenShared);
+                result.positions = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.PositionKind, copyWhenShared, forceCopy);
             }
             if (meshOrGeometry.isVerticesDataPresent(BABYLON.VertexBuffer.NormalKind)) {
-                result.normals = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.NormalKind, copyWhenShared);
+                result.normals = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.NormalKind, copyWhenShared, forceCopy);
             }
             if (meshOrGeometry.isVerticesDataPresent(BABYLON.VertexBuffer.TangentKind)) {
-                result.tangents = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.TangentKind, copyWhenShared);
+                result.tangents = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.TangentKind, copyWhenShared, forceCopy);
             }
             if (meshOrGeometry.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)) {
-                result.uvs = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.UVKind, copyWhenShared);
+                result.uvs = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.UVKind, copyWhenShared, forceCopy);
             }
             if (meshOrGeometry.isVerticesDataPresent(BABYLON.VertexBuffer.UV2Kind)) {
-                result.uvs2 = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.UV2Kind, copyWhenShared);
+                result.uvs2 = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.UV2Kind, copyWhenShared, forceCopy);
             }
             if (meshOrGeometry.isVerticesDataPresent(BABYLON.VertexBuffer.UV3Kind)) {
-                result.uvs3 = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.UV3Kind, copyWhenShared);
+                result.uvs3 = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.UV3Kind, copyWhenShared, forceCopy);
             }
             if (meshOrGeometry.isVerticesDataPresent(BABYLON.VertexBuffer.UV4Kind)) {
-                result.uvs4 = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.UV4Kind, copyWhenShared);
+                result.uvs4 = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.UV4Kind, copyWhenShared, forceCopy);
             }
             if (meshOrGeometry.isVerticesDataPresent(BABYLON.VertexBuffer.UV5Kind)) {
-                result.uvs5 = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.UV5Kind, copyWhenShared);
+                result.uvs5 = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.UV5Kind, copyWhenShared, forceCopy);
             }
             if (meshOrGeometry.isVerticesDataPresent(BABYLON.VertexBuffer.UV6Kind)) {
-                result.uvs6 = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.UV6Kind, copyWhenShared);
+                result.uvs6 = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.UV6Kind, copyWhenShared, forceCopy);
             }
             if (meshOrGeometry.isVerticesDataPresent(BABYLON.VertexBuffer.ColorKind)) {
-                result.colors = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.ColorKind, copyWhenShared);
+                result.colors = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.ColorKind, copyWhenShared, forceCopy);
             }
             if (meshOrGeometry.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind)) {
-                result.matricesIndices = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.MatricesIndicesKind, copyWhenShared);
+                result.matricesIndices = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.MatricesIndicesKind, copyWhenShared, forceCopy);
             }
             if (meshOrGeometry.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)) {
-                result.matricesWeights = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.MatricesWeightsKind, copyWhenShared);
+                result.matricesWeights = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.MatricesWeightsKind, copyWhenShared, forceCopy);
             }
             if (meshOrGeometry.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesExtraKind)) {
-                result.matricesIndicesExtra = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.MatricesIndicesExtraKind, copyWhenShared);
+                result.matricesIndicesExtra = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.MatricesIndicesExtraKind, copyWhenShared, forceCopy);
             }
             if (meshOrGeometry.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsExtraKind)) {
-                result.matricesWeightsExtra = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.MatricesWeightsExtraKind, copyWhenShared);
+                result.matricesWeightsExtra = meshOrGeometry.getVerticesData(BABYLON.VertexBuffer.MatricesWeightsExtraKind, copyWhenShared, forceCopy);
             }
             result.indices = meshOrGeometry.getIndices(copyWhenShared);
             return result;
@@ -26029,13 +26130,13 @@ var BABYLON;
             }
             return this._totalVertices;
         };
-        Geometry.prototype.getVerticesData = function (kind, copyWhenShared) {
+        Geometry.prototype.getVerticesData = function (kind, copyWhenShared, forceCopy) {
             var vertexBuffer = this.getVertexBuffer(kind);
             if (!vertexBuffer) {
                 return null;
             }
             var orig = vertexBuffer.getData();
-            if (!copyWhenShared || this._meshes.length === 1) {
+            if (!forceCopy && (!copyWhenShared || this._meshes.length === 1)) {
                 return orig;
             }
             else {
@@ -27752,7 +27853,7 @@ var BABYLON;
             this.bindOnlyWorldMatrix(world);
             // Bones
             BABYLON.MaterialHelper.BindBonesParameters(mesh, effect);
-            if (this._mustRebind(scene, effect)) {
+            if (this._mustRebind(scene, effect, mesh.visibility)) {
                 this._uniformBuffer.bindToEffect(effect, "Material");
                 this.bindViewProjection(effect);
                 if (!this._uniformBuffer.useUbo || !this.isFrozen || !this._uniformBuffer.isSync) {
@@ -31823,7 +31924,7 @@ var BABYLON;
         function HemisphericLight(name, direction, scene) {
             var _this = _super.call(this, name, scene) || this;
             _this.groundColor = new BABYLON.Color3(0.0, 0.0, 0.0);
-            _this.direction = direction;
+            _this.direction = direction || BABYLON.Vector3.Up();
             return _this;
         }
         HemisphericLight.prototype._buildUniformLayout = function () {
@@ -32650,17 +32751,29 @@ var BABYLON;
             this._easingFunction = easingFunction;
         };
         Animation.prototype.floatInterpolateFunction = function (startValue, endValue, gradient) {
-            return startValue + (endValue - startValue) * gradient;
+            return BABYLON.Scalar.Lerp(startValue, endValue, gradient);
+        };
+        Animation.prototype.floatInterpolateFunctionWithTangents = function (startValue, outTangent, endValue, inTangent, gradient) {
+            return BABYLON.Scalar.Hermite(startValue, outTangent, endValue, inTangent, gradient);
         };
         Animation.prototype.quaternionInterpolateFunction = function (startValue, endValue, gradient) {
             return BABYLON.Quaternion.Slerp(startValue, endValue, gradient);
         };
+        Animation.prototype.quaternionInterpolateFunctionWithTangents = function (startValue, outTangent, endValue, inTangent, gradient) {
+            return BABYLON.Quaternion.Hermite(startValue, outTangent, endValue, inTangent, gradient).normalize();
+        };
         Animation.prototype.vector3InterpolateFunction = function (startValue, endValue, gradient) {
             return BABYLON.Vector3.Lerp(startValue, endValue, gradient);
         };
+        Animation.prototype.vector3InterpolateFunctionWithTangents = function (startValue, outTangent, endValue, inTangent, gradient) {
+            return BABYLON.Vector3.Hermite(startValue, outTangent, endValue, inTangent, gradient);
+        };
         Animation.prototype.vector2InterpolateFunction = function (startValue, endValue, gradient) {
             return BABYLON.Vector2.Lerp(startValue, endValue, gradient);
         };
+        Animation.prototype.vector2InterpolateFunctionWithTangents = function (startValue, outTangent, endValue, inTangent, gradient) {
+            return BABYLON.Vector2.Hermite(startValue, outTangent, endValue, inTangent, gradient);
+        };
         Animation.prototype.sizeInterpolateFunction = function (startValue, endValue, gradient) {
             return BABYLON.Size.Lerp(startValue, endValue, gradient);
         };
@@ -32702,18 +32815,22 @@ var BABYLON;
             }
             this.currentFrame = currentFrame;
             // Try to get a hash to find the right key
-            var startKey = Math.max(0, Math.min(this._keys.length - 1, Math.floor(this._keys.length * (currentFrame - this._keys[0].frame) / (this._keys[this._keys.length - 1].frame - this._keys[0].frame)) - 1));
-            if (this._keys[startKey].frame >= currentFrame) {
-                while (startKey - 1 >= 0 && this._keys[startKey].frame >= currentFrame) {
-                    startKey--;
-                }
-            }
-            for (var key = startKey; key < this._keys.length; key++) {
-                if (this._keys[key + 1].frame >= currentFrame) {
-                    var startValue = this._getKeyValue(this._keys[key].value);
-                    var endValue = this._getKeyValue(this._keys[key + 1].value);
+            var startKeyIndex = Math.max(0, Math.min(this._keys.length - 1, Math.floor(this._keys.length * (currentFrame - this._keys[0].frame) / (this._keys[this._keys.length - 1].frame - this._keys[0].frame)) - 1));
+            if (this._keys[startKeyIndex].frame >= currentFrame) {
+                while (startKeyIndex - 1 >= 0 && this._keys[startKeyIndex].frame >= currentFrame) {
+                    startKeyIndex--;
+                }
+            }
+            for (var key = startKeyIndex; key < this._keys.length; key++) {
+                var endKey = this._keys[key + 1];
+                if (endKey.frame >= currentFrame) {
+                    var startKey = this._keys[key];
+                    var startValue = this._getKeyValue(startKey.value);
+                    var endValue = this._getKeyValue(endKey.value);
+                    var useTangent = startKey.outTangent !== undefined && endKey.inTangent !== undefined;
+                    var frameDelta = endKey.frame - startKey.frame;
                     // gradient : percent of currentFrame between the frame inf and the frame sup
-                    var gradient = (currentFrame - this._keys[key].frame) / (this._keys[key + 1].frame - this._keys[key].frame);
+                    var gradient = (currentFrame - startKey.frame) / frameDelta;
                     // check for easingFunction and correction of gradient
                     if (this._easingFunction != null) {
                         gradient = this._easingFunction.ease(gradient);
@@ -32721,44 +32838,45 @@ var BABYLON;
                     switch (this.dataType) {
                         // Float
                         case Animation.ANIMATIONTYPE_FLOAT:
+                            var floatValue = useTangent ? this.floatInterpolateFunctionWithTangents(startValue, startKey.outTangent * frameDelta, endValue, endKey.inTangent * frameDelta, gradient) : this.floatInterpolateFunction(startValue, endValue, gradient);
                             switch (loopMode) {
                                 case Animation.ANIMATIONLOOPMODE_CYCLE:
                                 case Animation.ANIMATIONLOOPMODE_CONSTANT:
-                                    return this.floatInterpolateFunction(startValue, endValue, gradient);
+                                    return floatValue;
                                 case Animation.ANIMATIONLOOPMODE_RELATIVE:
-                                    return offsetValue * repeatCount + this.floatInterpolateFunction(startValue, endValue, gradient);
+                                    return offsetValue * repeatCount + floatValue;
                             }
                             break;
                         // Quaternion
                         case Animation.ANIMATIONTYPE_QUATERNION:
-                            var quaternion = null;
+                            var quatValue = useTangent ? this.quaternionInterpolateFunctionWithTangents(startValue, startKey.outTangent.scale(frameDelta), endValue, endKey.inTangent.scale(frameDelta), gradient) : this.quaternionInterpolateFunction(startValue, endValue, gradient);
                             switch (loopMode) {
                                 case Animation.ANIMATIONLOOPMODE_CYCLE:
                                 case Animation.ANIMATIONLOOPMODE_CONSTANT:
-                                    quaternion = this.quaternionInterpolateFunction(startValue, endValue, gradient);
-                                    break;
+                                    return quatValue;
                                 case Animation.ANIMATIONLOOPMODE_RELATIVE:
-                                    quaternion = this.quaternionInterpolateFunction(startValue, endValue, gradient).add(offsetValue.scale(repeatCount));
-                                    break;
+                                    return quatValue.add(offsetValue.scale(repeatCount));
                             }
-                            return quaternion;
+                            return quatValue;
                         // Vector3
                         case Animation.ANIMATIONTYPE_VECTOR3:
+                            var vec3Value = useTangent ? this.vector3InterpolateFunctionWithTangents(startValue, startKey.outTangent.scale(frameDelta), endValue, endKey.inTangent.scale(frameDelta), gradient) : this.vector3InterpolateFunction(startValue, endValue, gradient);
                             switch (loopMode) {
                                 case Animation.ANIMATIONLOOPMODE_CYCLE:
                                 case Animation.ANIMATIONLOOPMODE_CONSTANT:
-                                    return this.vector3InterpolateFunction(startValue, endValue, gradient);
+                                    return vec3Value;
                                 case Animation.ANIMATIONLOOPMODE_RELATIVE:
-                                    return this.vector3InterpolateFunction(startValue, endValue, gradient).add(offsetValue.scale(repeatCount));
+                                    return vec3Value.add(offsetValue.scale(repeatCount));
                             }
                         // Vector2
                         case Animation.ANIMATIONTYPE_VECTOR2:
+                            var vec2Value = useTangent ? this.vector2InterpolateFunctionWithTangents(startValue, startKey.outTangent.scale(frameDelta), endValue, endKey.inTangent.scale(frameDelta), gradient) : this.vector2InterpolateFunction(startValue, endValue, gradient);
                             switch (loopMode) {
                                 case Animation.ANIMATIONLOOPMODE_CYCLE:
                                 case Animation.ANIMATIONLOOPMODE_CONSTANT:
-                                    return this.vector2InterpolateFunction(startValue, endValue, gradient);
+                                    return vec2Value;
                                 case Animation.ANIMATIONLOOPMODE_RELATIVE:
-                                    return this.vector2InterpolateFunction(startValue, endValue, gradient).add(offsetValue.scale(repeatCount));
+                                    return vec2Value.add(offsetValue.scale(repeatCount));
                             }
                         // Size
                         case Animation.ANIMATIONTYPE_SIZE:
@@ -41576,20 +41694,21 @@ var BABYLON;
             if (format === void 0) { format = BABYLON.Engine.TEXTUREFORMAT_RGBA; }
             var _this = _super.call(this, null, scene, !generateMipMaps, undefined, samplingMode, undefined, undefined, undefined, undefined, format) || this;
             _this.name = name;
+            var engine = _this.getScene().getEngine();
             _this.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
             _this.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
             _this._generateMipMaps = generateMipMaps;
             if (options.getContext) {
                 _this._canvas = options;
-                _this._texture = scene.getEngine().createDynamicTexture(options.width, options.height, generateMipMaps, samplingMode);
+                _this._texture = engine.createDynamicTexture(options.width, options.height, generateMipMaps, samplingMode);
             }
             else {
                 _this._canvas = document.createElement("canvas");
                 if (options.width) {
-                    _this._texture = scene.getEngine().createDynamicTexture(options.width, options.height, generateMipMaps, samplingMode);
+                    _this._texture = engine.createDynamicTexture(options.width, options.height, generateMipMaps, samplingMode);
                 }
                 else {
-                    _this._texture = scene.getEngine().createDynamicTexture(options, options, generateMipMaps, samplingMode);
+                    _this._texture = engine.createDynamicTexture(options, options, generateMipMaps, samplingMode);
                 }
             }
             var textureSize = _this.getSize();
@@ -41605,15 +41724,24 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
-        DynamicTexture.prototype.scale = function (ratio) {
-            var textureSize = this.getSize();
-            textureSize.width *= ratio;
-            textureSize.height *= ratio;
+        DynamicTexture.prototype._recreate = function (textureSize) {
             this._canvas.width = textureSize.width;
             this._canvas.height = textureSize.height;
             this.releaseInternalTexture();
             this._texture = this.getScene().getEngine().createDynamicTexture(textureSize.width, textureSize.height, this._generateMipMaps, this._samplingMode);
         };
+        DynamicTexture.prototype.scale = function (ratio) {
+            var textureSize = this.getSize();
+            textureSize.width *= ratio;
+            textureSize.height *= ratio;
+            this._recreate(textureSize);
+        };
+        DynamicTexture.prototype.scaleTo = function (width, height) {
+            var textureSize = this.getSize();
+            textureSize.width = width;
+            textureSize.height = height;
+            this._recreate(textureSize);
+        };
         DynamicTexture.prototype.getContext = function () {
             return this._context;
         };
@@ -45360,10 +45488,15 @@ var BABYLON;
                 LSValues.x = Math.abs(normalizedLX) > 0.005 ? 0 + normalizedLX : 0;
                 LSValues.y = Math.abs(normalizedLY) > 0.005 ? 0 + normalizedLY : 0;
                 var RSValues = this.gamepad.rightStick;
-                var normalizedRX = RSValues.x / this.gamepadAngularSensibility;
-                var normalizedRY = RSValues.y / this.gamepadAngularSensibility;
-                RSValues.x = Math.abs(normalizedRX) > 0.001 ? 0 + normalizedRX : 0;
-                RSValues.y = Math.abs(normalizedRY) > 0.001 ? 0 + normalizedRY : 0;
+                if (RSValues) {
+                    var normalizedRX = RSValues.x / this.gamepadAngularSensibility;
+                    var normalizedRY = RSValues.y / this.gamepadAngularSensibility;
+                    RSValues.x = Math.abs(normalizedRX) > 0.001 ? 0 + normalizedRX : 0;
+                    RSValues.y = Math.abs(normalizedRY) > 0.001 ? 0 + normalizedRY : 0;
+                }
+                else {
+                    RSValues = { x: 0, y: 0 };
+                }
                 if (!camera.rotationQuaternion) {
                     BABYLON.Matrix.RotationYawPitchRollToRef(camera.rotation.y, camera.rotation.x, 0, this._cameraTransform);
                 }
@@ -45429,20 +45562,22 @@ var BABYLON;
             if (this.gamepad) {
                 var camera = this.camera;
                 var RSValues = this.gamepad.rightStick;
-                if (RSValues.x != 0) {
-                    var normalizedRX = RSValues.x / this.gamepadRotationSensibility;
-                    if (normalizedRX != 0 && Math.abs(normalizedRX) > 0.005) {
-                        camera.inertialAlphaOffset += normalizedRX;
+                if (RSValues) {
+                    if (RSValues.x != 0) {
+                        var normalizedRX = RSValues.x / this.gamepadRotationSensibility;
+                        if (normalizedRX != 0 && Math.abs(normalizedRX) > 0.005) {
+                            camera.inertialAlphaOffset += normalizedRX;
+                        }
                     }
-                }
-                if (RSValues.y != 0) {
-                    var normalizedRY = RSValues.y / this.gamepadRotationSensibility;
-                    if (normalizedRY != 0 && Math.abs(normalizedRY) > 0.005) {
-                        camera.inertialBetaOffset += normalizedRY;
+                    if (RSValues.y != 0) {
+                        var normalizedRY = RSValues.y / this.gamepadRotationSensibility;
+                        if (normalizedRY != 0 && Math.abs(normalizedRY) > 0.005) {
+                            camera.inertialBetaOffset += normalizedRY;
+                        }
                     }
                 }
                 var LSValues = this.gamepad.leftStick;
-                if (LSValues.y != 0) {
+                if (LSValues && LSValues.y != 0) {
                     var normalizedLY = LSValues.y / this.gamepadMoveSensibility;
                     if (normalizedLY != 0 && Math.abs(normalizedLY) > 0.005) {
                         this.camera.inertialRadiusOffset -= normalizedLY;
@@ -55363,7 +55498,7 @@ var BABYLON;
             this._fixedTimeStep = timeStep;
         };
         CannonJSPlugin.prototype.executeStep = function (delta, impostors) {
-            this.world.step(this._fixedTimeStep, this._useDeltaForWorldStep ? delta * 1000 : 0, 3);
+            this.world.step(this._fixedTimeStep, this._useDeltaForWorldStep ? delta : 0, 3);
         };
         CannonJSPlugin.prototype.applyImpulse = function (impostor, force, contactPoint) {
             var worldPoint = new CANNON.Vec3(contactPoint.x, contactPoint.y, contactPoint.z);
@@ -56727,6 +56862,7 @@ var BABYLON;
             };
             SkeletonViewer.prototype._getLinesForBonesWithLength = function (bones, meshMat) {
                 var len = bones.length;
+                var meshPos = this.mesh.position;
                 for (var i = 0; i < len; i++) {
                     var bone = bones[i];
                     var points = this._debugLines[i];
@@ -56736,11 +56872,14 @@ var BABYLON;
                     }
                     this._getBonePosition(points[0], bone, meshMat);
                     this._getBonePosition(points[1], bone, meshMat, 0, bone.length, 0);
+                    points[0].subtractInPlace(meshPos);
+                    points[1].subtractInPlace(meshPos);
                 }
             };
             SkeletonViewer.prototype._getLinesForBonesNoLength = function (bones, meshMat) {
                 var len = bones.length;
                 var boneNum = 0;
+                var meshPos = this.mesh.position;
                 for (var i = len - 1; i >= 0; i--) {
                     var childBone = bones[i];
                     var parentBone = childBone.getParent();
@@ -56754,6 +56893,8 @@ var BABYLON;
                     }
                     childBone.getAbsolutePositionToRef(this.mesh, points[0]);
                     parentBone.getAbsolutePositionToRef(this.mesh, points[1]);
+                    points[0].subtractInPlace(meshPos);
+                    points[1].subtractInPlace(meshPos);
                     boneNum++;
                 }
             };
@@ -56774,6 +56915,7 @@ var BABYLON;
                 else {
                     BABYLON.MeshBuilder.CreateLineSystem(null, { lines: this._debugLines, updatable: true, instance: this._debugMesh }, this._scene);
                 }
+                this._debugMesh.position.copyFrom(this.mesh.position);
                 this._debugMesh.color = this.color;
             };
             SkeletonViewer.prototype.dispose = function () {
@@ -57088,7 +57230,7 @@ var BABYLON;
             }
             this._colorShader = new BABYLON.ShaderMaterial("colorShader", this._scene, "color", {
                 attributes: [BABYLON.VertexBuffer.PositionKind],
-                uniforms: ["worldViewProjection", "color"]
+                uniforms: ["world", "viewProjection", "color"]
             });
             var engine = this._scene.getEngine();
             var boxdata = BABYLON.VertexData.CreateBox(1.0);
@@ -57167,6 +57309,7 @@ var BABYLON;
         function MorphTarget(name, influence) {
             if (influence === void 0) { influence = 0; }
             this.name = name;
+            this.animations = new Array();
             this.onInfluenceChanged = new BABYLON.Observable();
             this.influence = influence;
         }
@@ -58963,51 +59106,26 @@ var BABYLON;
             }
             //enable VR
             _this.getEngine().initWebVR();
-            if (!_this.getEngine().vrDisplaysPromise) {
-                BABYLON.Tools.Error("WebVR is not enabled on your browser");
+            //check specs version
+            if (!window.VRFrameData) {
+                _this._specsVersion = 1.0;
+                _this._frameData = {};
             }
             else {
-                //check specs version
-                if (!window.VRFrameData) {
-                    _this._specsVersion = 1.0;
-                    _this._frameData = {};
-                }
-                else {
-                    _this._frameData = new VRFrameData();
-                }
-                _this.getEngine().vrDisplaysPromise.then(function (devices) {
-                    if (devices.length > 0) {
-                        _this._vrEnabled = true;
-                        if (_this.webVROptions.displayName) {
-                            var found = devices.some(function (device) {
-                                if (device.displayName === _this.webVROptions.displayName) {
-                                    _this._vrDevice = device;
-                                    return true;
-                                }
-                                else {
-                                    return false;
-                                }
-                            });
-                            if (!found) {
-                                _this._vrDevice = devices[0];
-                                BABYLON.Tools.Warn("Display " + _this.webVROptions.displayName + " was not found. Using " + _this._vrDevice.displayName);
-                            }
-                        }
-                        else {
-                            //choose the first one
-                            _this._vrDevice = devices[0];
-                        }
-                        //reset the rig parameters.
-                        _this.setCameraRigMode(BABYLON.Camera.RIG_MODE_WEBVR, { parentCamera: _this, vrDisplay: _this._vrDevice, frameData: _this._frameData, specs: _this._specsVersion });
-                        if (_this._attached) {
-                            _this.getEngine().enableVR(_this._vrDevice);
-                        }
-                    }
-                    else {
-                        BABYLON.Tools.Error("No WebVR devices found!");
-                    }
-                });
+                _this._frameData = new VRFrameData();
             }
+            _this.getEngine().getVRDevice(_this.webVROptions.displayName, function (device) {
+                if (!device) {
+                    return;
+                }
+                _this._vrEnabled = true;
+                _this._vrDevice = device;
+                //reset the rig parameters.
+                _this.setCameraRigMode(BABYLON.Camera.RIG_MODE_WEBVR, { parentCamera: _this, vrDisplay: _this._vrDevice, frameData: _this._frameData, specs: _this._specsVersion });
+                if (_this._attached) {
+                    _this.getEngine().enableVR(_this._vrDevice);
+                }
+            });
             // try to attach the controllers, if found.
             _this.initControllers();
             /**
@@ -63292,7 +63410,7 @@ var BABYLON;
             this.color = color === undefined ? new BABYLON.Color4(1, 1, 1, 1) : color;
             this._scene = scene || BABYLON.Engine.LastCreatedScene;
             this._scene.layers.push(this);
-            var engine = scene.getEngine();
+            var engine = this._scene.getEngine();
             // VBO
             var vertices = [];
             vertices.push(1, 1);

+ 386 - 361
dist/preview release/babylon.module.d.ts

@@ -337,6 +337,8 @@ declare module BABYLON {
          * @param {number} height - the new canvas' height
          */
         setSize(width: number, height: number): void;
+        isVRDevicePresent(callback: (result: boolean) => void): void;
+        getVRDevice(name: string, callback: (device) => void): void;
         initWebVR(): void;
         enableVR(vrDevice: any): void;
         disableVR(): void;
@@ -1575,6 +1577,7 @@ declare module BABYLON {
         animationTimeScale: number;
         _cachedMaterial: Material;
         _cachedEffect: Effect;
+        _cachedVisibility: number;
         private _renderId;
         private _executeWhenReadyTimeoutId;
         private _intermediateRendering;
@@ -1637,6 +1640,8 @@ declare module BABYLON {
         readonly pointerY: number;
         getCachedMaterial(): Material;
         getCachedEffect(): Effect;
+        getCachedVisibility(): number;
+        isCachedMaterialValid(material: Material, effect: Effect, visibility?: number): boolean;
         getBoundingBoxRenderer(): BoundingBoxRenderer;
         getOutlineRenderer(): OutlineRenderer;
         getEngine(): Engine;
@@ -3432,9 +3437,13 @@ declare module BABYLON {
         getEasingFunction(): IEasingFunction;
         setEasingFunction(easingFunction: EasingFunction): void;
         floatInterpolateFunction(startValue: number, endValue: number, gradient: number): number;
+        floatInterpolateFunctionWithTangents(startValue: number, outTangent: number, endValue: number, inTangent: number, gradient: number): number;
         quaternionInterpolateFunction(startValue: Quaternion, endValue: Quaternion, gradient: number): Quaternion;
+        quaternionInterpolateFunctionWithTangents(startValue: Quaternion, outTangent: Quaternion, endValue: Quaternion, inTangent: Quaternion, gradient: number): Quaternion;
         vector3InterpolateFunction(startValue: Vector3, endValue: Vector3, gradient: number): Vector3;
+        vector3InterpolateFunctionWithTangents(startValue: Vector3, outTangent: Vector3, endValue: Vector3, inTangent: Vector3, gradient: number): Vector3;
         vector2InterpolateFunction(startValue: Vector2, endValue: Vector2, gradient: number): Vector2;
+        vector2InterpolateFunctionWithTangents(startValue: Vector2, outTangent: Vector2, endValue: Vector2, inTangent: Vector2, gradient: number): Vector2;
         sizeInterpolateFunction(startValue: Size, endValue: Size, gradient: number): Size;
         color3InterpolateFunction(startValue: Color3, endValue: Color3, gradient: number): Color3;
         matrixInterpolateFunction(startValue: Matrix, endValue: Matrix, gradient: number): Matrix;
@@ -4201,6 +4210,249 @@ declare module BABYLON {
 }
 
 declare module BABYLON {
+    class Collider {
+        radius: Vector3;
+        retry: number;
+        velocity: Vector3;
+        basePoint: Vector3;
+        epsilon: number;
+        collisionFound: boolean;
+        velocityWorldLength: number;
+        basePointWorld: Vector3;
+        velocityWorld: Vector3;
+        normalizedVelocity: Vector3;
+        initialVelocity: Vector3;
+        initialPosition: Vector3;
+        nearestDistance: number;
+        intersectionPoint: Vector3;
+        collidedMesh: AbstractMesh;
+        private _collisionPoint;
+        private _planeIntersectionPoint;
+        private _tempVector;
+        private _tempVector2;
+        private _tempVector3;
+        private _tempVector4;
+        private _edge;
+        private _baseToVertex;
+        private _destinationPoint;
+        private _slidePlaneNormal;
+        private _displacementVector;
+        private _collisionMask;
+        collisionMask: number;
+        _initialize(source: Vector3, dir: Vector3, e: number): void;
+        _checkPointInTriangle(point: Vector3, pa: Vector3, pb: Vector3, pc: Vector3, n: Vector3): boolean;
+        _canDoCollision(sphereCenter: Vector3, sphereRadius: number, vecMin: Vector3, vecMax: Vector3): boolean;
+        _testTriangle(faceIndex: number, trianglePlaneArray: Array<Plane>, p1: Vector3, p2: Vector3, p3: Vector3, hasMaterial: boolean): void;
+        _collide(trianglePlaneArray: Array<Plane>, pts: Vector3[], indices: IndicesArray, indexStart: number, indexEnd: number, decal: number, hasMaterial: boolean): void;
+        _getResponse(pos: Vector3, vel: Vector3): void;
+    }
+}
+
+declare module BABYLON {
+    var CollisionWorker: string;
+    interface ICollisionCoordinator {
+        getNewPosition(position: Vector3, velocity: Vector3, collider: Collider, maximumRetry: number, excludedMesh: AbstractMesh, onNewPosition: (collisionIndex: number, newPosition: Vector3, collidedMesh?: AbstractMesh) => void, collisionIndex: number): void;
+        init(scene: Scene): void;
+        destroy(): void;
+        onMeshAdded(mesh: AbstractMesh): any;
+        onMeshUpdated(mesh: AbstractMesh): any;
+        onMeshRemoved(mesh: AbstractMesh): any;
+        onGeometryAdded(geometry: Geometry): any;
+        onGeometryUpdated(geometry: Geometry): any;
+        onGeometryDeleted(geometry: Geometry): any;
+    }
+    interface SerializedMesh {
+        id: string;
+        name: string;
+        uniqueId: number;
+        geometryId: string;
+        sphereCenter: Array<number>;
+        sphereRadius: number;
+        boxMinimum: Array<number>;
+        boxMaximum: Array<number>;
+        worldMatrixFromCache: any;
+        subMeshes: Array<SerializedSubMesh>;
+        checkCollisions: boolean;
+    }
+    interface SerializedSubMesh {
+        position: number;
+        verticesStart: number;
+        verticesCount: number;
+        indexStart: number;
+        indexCount: number;
+        hasMaterial: boolean;
+        sphereCenter: Array<number>;
+        sphereRadius: number;
+        boxMinimum: Array<number>;
+        boxMaximum: Array<number>;
+    }
+    interface SerializedGeometry {
+        id: string;
+        positions: Float32Array;
+        indices: Uint32Array;
+        normals: Float32Array;
+    }
+    interface BabylonMessage {
+        taskType: WorkerTaskType;
+        payload: InitPayload | CollidePayload | UpdatePayload;
+    }
+    interface SerializedColliderToWorker {
+        position: Array<number>;
+        velocity: Array<number>;
+        radius: Array<number>;
+    }
+    enum WorkerTaskType {
+        INIT = 0,
+        UPDATE = 1,
+        COLLIDE = 2,
+    }
+    interface WorkerReply {
+        error: WorkerReplyType;
+        taskType: WorkerTaskType;
+        payload?: any;
+    }
+    interface CollisionReplyPayload {
+        newPosition: Array<number>;
+        collisionId: number;
+        collidedMeshUniqueId: number;
+    }
+    interface InitPayload {
+    }
+    interface CollidePayload {
+        collisionId: number;
+        collider: SerializedColliderToWorker;
+        maximumRetry: number;
+        excludedMeshUniqueId?: number;
+    }
+    interface UpdatePayload {
+        updatedMeshes: {
+            [n: number]: SerializedMesh;
+        };
+        updatedGeometries: {
+            [s: string]: SerializedGeometry;
+        };
+        removedMeshes: Array<number>;
+        removedGeometries: Array<string>;
+    }
+    enum WorkerReplyType {
+        SUCCESS = 0,
+        UNKNOWN_ERROR = 1,
+    }
+    class CollisionCoordinatorWorker implements ICollisionCoordinator {
+        private _scene;
+        private _scaledPosition;
+        private _scaledVelocity;
+        private _collisionsCallbackArray;
+        private _init;
+        private _runningUpdated;
+        private _runningCollisionTask;
+        private _worker;
+        private _addUpdateMeshesList;
+        private _addUpdateGeometriesList;
+        private _toRemoveMeshesArray;
+        private _toRemoveGeometryArray;
+        constructor();
+        static SerializeMesh: (mesh: AbstractMesh) => SerializedMesh;
+        static SerializeGeometry: (geometry: Geometry) => SerializedGeometry;
+        getNewPosition(position: Vector3, velocity: Vector3, collider: Collider, maximumRetry: number, excludedMesh: AbstractMesh, onNewPosition: (collisionIndex: number, newPosition: Vector3, collidedMesh?: AbstractMesh) => void, collisionIndex: number): void;
+        init(scene: Scene): void;
+        destroy(): void;
+        onMeshAdded(mesh: AbstractMesh): void;
+        onMeshUpdated: (mesh: AbstractMesh) => void;
+        onMeshRemoved(mesh: AbstractMesh): void;
+        onGeometryAdded(geometry: Geometry): void;
+        onGeometryUpdated: (geometry: Geometry) => void;
+        onGeometryDeleted(geometry: Geometry): void;
+        private _afterRender;
+        private _onMessageFromWorker;
+    }
+    class CollisionCoordinatorLegacy implements ICollisionCoordinator {
+        private _scene;
+        private _scaledPosition;
+        private _scaledVelocity;
+        private _finalPosition;
+        getNewPosition(position: Vector3, velocity: Vector3, collider: Collider, maximumRetry: number, excludedMesh: AbstractMesh, onNewPosition: (collisionIndex: number, newPosition: Vector3, collidedMesh?: AbstractMesh) => void, collisionIndex: number): void;
+        init(scene: Scene): void;
+        destroy(): void;
+        onMeshAdded(mesh: AbstractMesh): void;
+        onMeshUpdated(mesh: AbstractMesh): void;
+        onMeshRemoved(mesh: AbstractMesh): void;
+        onGeometryAdded(geometry: Geometry): void;
+        onGeometryUpdated(geometry: Geometry): void;
+        onGeometryDeleted(geometry: Geometry): void;
+        private _collideWithWorld(position, velocity, collider, maximumRetry, finalPosition, excludedMesh?);
+    }
+}
+
+declare module BABYLON {
+    var WorkerIncluded: boolean;
+    class CollisionCache {
+        private _meshes;
+        private _geometries;
+        getMeshes(): {
+            [n: number]: SerializedMesh;
+        };
+        getGeometries(): {
+            [s: number]: SerializedGeometry;
+        };
+        getMesh(id: any): SerializedMesh;
+        addMesh(mesh: SerializedMesh): void;
+        removeMesh(uniqueId: number): void;
+        getGeometry(id: string): SerializedGeometry;
+        addGeometry(geometry: SerializedGeometry): void;
+        removeGeometry(id: string): void;
+    }
+    class CollideWorker {
+        collider: Collider;
+        private _collisionCache;
+        private finalPosition;
+        private collisionsScalingMatrix;
+        private collisionTranformationMatrix;
+        constructor(collider: Collider, _collisionCache: CollisionCache, finalPosition: Vector3);
+        collideWithWorld(position: Vector3, velocity: Vector3, maximumRetry: number, excludedMeshUniqueId?: number): void;
+        private checkCollision(mesh);
+        private processCollisionsForSubMeshes(transformMatrix, mesh);
+        private collideForSubMesh(subMesh, transformMatrix, meshGeometry);
+        private checkSubmeshCollision(subMesh);
+    }
+    interface ICollisionDetector {
+        onInit(payload: InitPayload): void;
+        onUpdate(payload: UpdatePayload): void;
+        onCollision(payload: CollidePayload): void;
+    }
+    class CollisionDetectorTransferable implements ICollisionDetector {
+        private _collisionCache;
+        onInit(payload: InitPayload): void;
+        onUpdate(payload: UpdatePayload): void;
+        onCollision(payload: CollidePayload): void;
+    }
+}
+
+declare module BABYLON {
+    class IntersectionInfo {
+        bu: number;
+        bv: number;
+        distance: number;
+        faceId: number;
+        subMeshId: number;
+        constructor(bu: number, bv: number, distance: number);
+    }
+    class PickingInfo {
+        hit: boolean;
+        distance: number;
+        pickedPoint: Vector3;
+        pickedMesh: AbstractMesh;
+        bu: number;
+        bv: number;
+        faceId: number;
+        subMeshId: number;
+        pickedSprite: Sprite;
+        getNormal(useWorldCoordinates?: boolean, useVerticesNormals?: boolean): Vector3;
+        getTextureCoordinates(): Vector2;
+    }
+}
+
+declare module BABYLON {
     class BoundingBox implements ICullable {
         minimum: Vector3;
         maximum: Vector3;
@@ -4860,272 +5112,29 @@ declare module BABYLON {
     }
 }
 
-declare module BABYLON {
-    class TouchCamera extends FreeCamera {
-        touchAngularSensibility: number;
-        touchMoveSensibility: number;
-        constructor(name: string, position: Vector3, scene: Scene);
-        getClassName(): string;
-        _setupInputs(): void;
-    }
-}
-
-declare module BABYLON {
-    class UniversalCamera extends TouchCamera {
-        gamepadAngularSensibility: number;
-        gamepadMoveSensibility: number;
-        constructor(name: string, position: Vector3, scene: Scene);
-        getClassName(): string;
-    }
-}
-
-declare module BABYLON {
-    class VirtualJoysticksCamera extends FreeCamera {
-        constructor(name: string, position: Vector3, scene: Scene);
-        getClassName(): string;
-    }
-}
-
-declare module BABYLON {
-    class Collider {
-        radius: Vector3;
-        retry: number;
-        velocity: Vector3;
-        basePoint: Vector3;
-        epsilon: number;
-        collisionFound: boolean;
-        velocityWorldLength: number;
-        basePointWorld: Vector3;
-        velocityWorld: Vector3;
-        normalizedVelocity: Vector3;
-        initialVelocity: Vector3;
-        initialPosition: Vector3;
-        nearestDistance: number;
-        intersectionPoint: Vector3;
-        collidedMesh: AbstractMesh;
-        private _collisionPoint;
-        private _planeIntersectionPoint;
-        private _tempVector;
-        private _tempVector2;
-        private _tempVector3;
-        private _tempVector4;
-        private _edge;
-        private _baseToVertex;
-        private _destinationPoint;
-        private _slidePlaneNormal;
-        private _displacementVector;
-        private _collisionMask;
-        collisionMask: number;
-        _initialize(source: Vector3, dir: Vector3, e: number): void;
-        _checkPointInTriangle(point: Vector3, pa: Vector3, pb: Vector3, pc: Vector3, n: Vector3): boolean;
-        _canDoCollision(sphereCenter: Vector3, sphereRadius: number, vecMin: Vector3, vecMax: Vector3): boolean;
-        _testTriangle(faceIndex: number, trianglePlaneArray: Array<Plane>, p1: Vector3, p2: Vector3, p3: Vector3, hasMaterial: boolean): void;
-        _collide(trianglePlaneArray: Array<Plane>, pts: Vector3[], indices: IndicesArray, indexStart: number, indexEnd: number, decal: number, hasMaterial: boolean): void;
-        _getResponse(pos: Vector3, vel: Vector3): void;
-    }
-}
-
-declare module BABYLON {
-    var CollisionWorker: string;
-    interface ICollisionCoordinator {
-        getNewPosition(position: Vector3, velocity: Vector3, collider: Collider, maximumRetry: number, excludedMesh: AbstractMesh, onNewPosition: (collisionIndex: number, newPosition: Vector3, collidedMesh?: AbstractMesh) => void, collisionIndex: number): void;
-        init(scene: Scene): void;
-        destroy(): void;
-        onMeshAdded(mesh: AbstractMesh): any;
-        onMeshUpdated(mesh: AbstractMesh): any;
-        onMeshRemoved(mesh: AbstractMesh): any;
-        onGeometryAdded(geometry: Geometry): any;
-        onGeometryUpdated(geometry: Geometry): any;
-        onGeometryDeleted(geometry: Geometry): any;
-    }
-    interface SerializedMesh {
-        id: string;
-        name: string;
-        uniqueId: number;
-        geometryId: string;
-        sphereCenter: Array<number>;
-        sphereRadius: number;
-        boxMinimum: Array<number>;
-        boxMaximum: Array<number>;
-        worldMatrixFromCache: any;
-        subMeshes: Array<SerializedSubMesh>;
-        checkCollisions: boolean;
-    }
-    interface SerializedSubMesh {
-        position: number;
-        verticesStart: number;
-        verticesCount: number;
-        indexStart: number;
-        indexCount: number;
-        hasMaterial: boolean;
-        sphereCenter: Array<number>;
-        sphereRadius: number;
-        boxMinimum: Array<number>;
-        boxMaximum: Array<number>;
-    }
-    interface SerializedGeometry {
-        id: string;
-        positions: Float32Array;
-        indices: Uint32Array;
-        normals: Float32Array;
-    }
-    interface BabylonMessage {
-        taskType: WorkerTaskType;
-        payload: InitPayload | CollidePayload | UpdatePayload;
-    }
-    interface SerializedColliderToWorker {
-        position: Array<number>;
-        velocity: Array<number>;
-        radius: Array<number>;
-    }
-    enum WorkerTaskType {
-        INIT = 0,
-        UPDATE = 1,
-        COLLIDE = 2,
-    }
-    interface WorkerReply {
-        error: WorkerReplyType;
-        taskType: WorkerTaskType;
-        payload?: any;
-    }
-    interface CollisionReplyPayload {
-        newPosition: Array<number>;
-        collisionId: number;
-        collidedMeshUniqueId: number;
-    }
-    interface InitPayload {
-    }
-    interface CollidePayload {
-        collisionId: number;
-        collider: SerializedColliderToWorker;
-        maximumRetry: number;
-        excludedMeshUniqueId?: number;
-    }
-    interface UpdatePayload {
-        updatedMeshes: {
-            [n: number]: SerializedMesh;
-        };
-        updatedGeometries: {
-            [s: string]: SerializedGeometry;
-        };
-        removedMeshes: Array<number>;
-        removedGeometries: Array<string>;
-    }
-    enum WorkerReplyType {
-        SUCCESS = 0,
-        UNKNOWN_ERROR = 1,
-    }
-    class CollisionCoordinatorWorker implements ICollisionCoordinator {
-        private _scene;
-        private _scaledPosition;
-        private _scaledVelocity;
-        private _collisionsCallbackArray;
-        private _init;
-        private _runningUpdated;
-        private _runningCollisionTask;
-        private _worker;
-        private _addUpdateMeshesList;
-        private _addUpdateGeometriesList;
-        private _toRemoveMeshesArray;
-        private _toRemoveGeometryArray;
-        constructor();
-        static SerializeMesh: (mesh: AbstractMesh) => SerializedMesh;
-        static SerializeGeometry: (geometry: Geometry) => SerializedGeometry;
-        getNewPosition(position: Vector3, velocity: Vector3, collider: Collider, maximumRetry: number, excludedMesh: AbstractMesh, onNewPosition: (collisionIndex: number, newPosition: Vector3, collidedMesh?: AbstractMesh) => void, collisionIndex: number): void;
-        init(scene: Scene): void;
-        destroy(): void;
-        onMeshAdded(mesh: AbstractMesh): void;
-        onMeshUpdated: (mesh: AbstractMesh) => void;
-        onMeshRemoved(mesh: AbstractMesh): void;
-        onGeometryAdded(geometry: Geometry): void;
-        onGeometryUpdated: (geometry: Geometry) => void;
-        onGeometryDeleted(geometry: Geometry): void;
-        private _afterRender;
-        private _onMessageFromWorker;
-    }
-    class CollisionCoordinatorLegacy implements ICollisionCoordinator {
-        private _scene;
-        private _scaledPosition;
-        private _scaledVelocity;
-        private _finalPosition;
-        getNewPosition(position: Vector3, velocity: Vector3, collider: Collider, maximumRetry: number, excludedMesh: AbstractMesh, onNewPosition: (collisionIndex: number, newPosition: Vector3, collidedMesh?: AbstractMesh) => void, collisionIndex: number): void;
-        init(scene: Scene): void;
-        destroy(): void;
-        onMeshAdded(mesh: AbstractMesh): void;
-        onMeshUpdated(mesh: AbstractMesh): void;
-        onMeshRemoved(mesh: AbstractMesh): void;
-        onGeometryAdded(geometry: Geometry): void;
-        onGeometryUpdated(geometry: Geometry): void;
-        onGeometryDeleted(geometry: Geometry): void;
-        private _collideWithWorld(position, velocity, collider, maximumRetry, finalPosition, excludedMesh?);
+declare module BABYLON {
+    class TouchCamera extends FreeCamera {
+        touchAngularSensibility: number;
+        touchMoveSensibility: number;
+        constructor(name: string, position: Vector3, scene: Scene);
+        getClassName(): string;
+        _setupInputs(): void;
     }
 }
 
 declare module BABYLON {
-    var WorkerIncluded: boolean;
-    class CollisionCache {
-        private _meshes;
-        private _geometries;
-        getMeshes(): {
-            [n: number]: SerializedMesh;
-        };
-        getGeometries(): {
-            [s: number]: SerializedGeometry;
-        };
-        getMesh(id: any): SerializedMesh;
-        addMesh(mesh: SerializedMesh): void;
-        removeMesh(uniqueId: number): void;
-        getGeometry(id: string): SerializedGeometry;
-        addGeometry(geometry: SerializedGeometry): void;
-        removeGeometry(id: string): void;
-    }
-    class CollideWorker {
-        collider: Collider;
-        private _collisionCache;
-        private finalPosition;
-        private collisionsScalingMatrix;
-        private collisionTranformationMatrix;
-        constructor(collider: Collider, _collisionCache: CollisionCache, finalPosition: Vector3);
-        collideWithWorld(position: Vector3, velocity: Vector3, maximumRetry: number, excludedMeshUniqueId?: number): void;
-        private checkCollision(mesh);
-        private processCollisionsForSubMeshes(transformMatrix, mesh);
-        private collideForSubMesh(subMesh, transformMatrix, meshGeometry);
-        private checkSubmeshCollision(subMesh);
-    }
-    interface ICollisionDetector {
-        onInit(payload: InitPayload): void;
-        onUpdate(payload: UpdatePayload): void;
-        onCollision(payload: CollidePayload): void;
-    }
-    class CollisionDetectorTransferable implements ICollisionDetector {
-        private _collisionCache;
-        onInit(payload: InitPayload): void;
-        onUpdate(payload: UpdatePayload): void;
-        onCollision(payload: CollidePayload): void;
+    class UniversalCamera extends TouchCamera {
+        gamepadAngularSensibility: number;
+        gamepadMoveSensibility: number;
+        constructor(name: string, position: Vector3, scene: Scene);
+        getClassName(): string;
     }
 }
 
 declare module BABYLON {
-    class IntersectionInfo {
-        bu: number;
-        bv: number;
-        distance: number;
-        faceId: number;
-        subMeshId: number;
-        constructor(bu: number, bv: number, distance: number);
-    }
-    class PickingInfo {
-        hit: boolean;
-        distance: number;
-        pickedPoint: Vector3;
-        pickedMesh: AbstractMesh;
-        bu: number;
-        bv: number;
-        faceId: number;
-        subMeshId: number;
-        pickedSprite: Sprite;
-        getNormal(useWorldCoordinates?: boolean, useVerticesNormals?: boolean): Vector3;
-        getTextureCoordinates(): Vector2;
+    class VirtualJoysticksCamera extends FreeCamera {
+        constructor(name: string, position: Vector3, scene: Scene);
+        getClassName(): string;
     }
 }
 
@@ -6753,7 +6762,7 @@ declare module BABYLON {
         bindOnlyWorldMatrix(world: Matrix): void;
         bind(world: Matrix, mesh?: Mesh): void;
         protected _afterBind(mesh: Mesh, effect?: Effect): void;
-        protected _mustRebind(scene: Scene, effect: Effect): boolean;
+        protected _mustRebind(scene: Scene, effect: Effect, visibility?: number): boolean;
         markAsDirty(flag: number): void;
         protected _markAllSubMeshesAsDirty(func: (defines: MaterialDefines) => void): void;
         protected _markAllSubMeshesAsTexturesDirty(): void;
@@ -7313,6 +7322,16 @@ declare module BABYLON {
          */
         static Clamp(value: number, min?: number, max?: number): number;
     }
+    class Scalar {
+        /**
+         * Creates a new scalar with values linearly interpolated of "amount" between the start scalar and the end scalar.
+         */
+        static Lerp(start: number, end: number, amount: number): number;
+        /**
+         * Returns a new scalar located for "amount" (float) on the Hermite spline defined by the scalars "value1", "value3", "tangent1", "tangent2".
+         */
+        static Hermite(value1: number, tangent1: number, value2: number, tangent2: number, amount: number): number;
+    }
     class Color3 {
         r: number;
         g: number;
@@ -7742,7 +7761,7 @@ declare module BABYLON {
          */
         static Clamp(value: Vector2, min: Vector2, max: Vector2): Vector2;
         /**
-         * Returns a new Vecto2 located for "amount" (float) on the Hermite spline defined by the vectors "value1", "value3", "tangent1", "tangent2".
+         * Returns a new Vector2 located for "amount" (float) on the Hermite spline defined by the vectors "value1", "value3", "tangent1", "tangent2".
          */
         static Hermite(value1: Vector2, tangent1: Vector2, value2: Vector2, tangent2: Vector2, amount: number): Vector2;
         /**
@@ -8590,6 +8609,10 @@ declare module BABYLON {
         static RotationQuaternionFromAxisToRef(axis1: Vector3, axis2: Vector3, axis3: Vector3, ref: Quaternion): void;
         static Slerp(left: Quaternion, right: Quaternion, amount: number): Quaternion;
         static SlerpToRef(left: Quaternion, right: Quaternion, amount: number, result: Quaternion): void;
+        /**
+         * Returns a new Quaternion located for "amount" (float) on the Hermite interpolation spline defined by the vectors "value1", "tangent1", "value2", "tangent2".
+         */
+        static Hermite(value1: Quaternion, tangent1: Quaternion, value2: Quaternion, tangent2: Quaternion, amount: number): Quaternion;
     }
     class Matrix {
         private static _tempQuaternion;
@@ -9298,68 +9321,6 @@ declare module BABYLON {
 }
 
 declare module BABYLON {
-    class MorphTarget {
-        name: string;
-        private _positions;
-        private _normals;
-        private _tangents;
-        private _influence;
-        onInfluenceChanged: Observable<boolean>;
-        influence: number;
-        constructor(name: string, influence?: number);
-        readonly hasNormals: boolean;
-        readonly hasTangents: boolean;
-        setPositions(data: Float32Array | number[]): void;
-        getPositions(): Float32Array;
-        setNormals(data: Float32Array | number[]): void;
-        getNormals(): Float32Array;
-        setTangents(data: Float32Array | number[]): void;
-        getTangents(): Float32Array;
-        /**
-         * Serializes the current target into a Serialization object.
-         * Returns the serialized object.
-         */
-        serialize(): any;
-        static Parse(serializationObject: any): MorphTarget;
-        static FromMesh(mesh: AbstractMesh, name?: string, influence?: number): MorphTarget;
-    }
-}
-
-declare module BABYLON {
-    class MorphTargetManager {
-        private _targets;
-        private _targetObservable;
-        private _activeTargets;
-        private _scene;
-        private _influences;
-        private _supportsNormals;
-        private _supportsTangents;
-        private _vertexCount;
-        private _uniqueId;
-        constructor(scene?: Scene);
-        readonly uniqueId: number;
-        readonly vertexCount: number;
-        readonly supportsNormals: boolean;
-        readonly supportsTangents: boolean;
-        readonly numTargets: number;
-        readonly numInfluencers: number;
-        readonly influences: Float32Array;
-        getActiveTarget(index: number): MorphTarget;
-        getTarget(index: number): MorphTarget;
-        addTarget(target: MorphTarget): void;
-        removeTarget(target: MorphTarget): void;
-        /**
-         * Serializes the current manager into a Serialization object.
-         * Returns the serialized object.
-         */
-        serialize(): any;
-        private _onInfluenceChanged(needUpdate);
-        private _syncActiveTargets(needUpdate);
-        static Parse(serializationObject: any, scene: Scene): MorphTargetManager;
-    }
-}
-
-declare module BABYLON {
     class AbstractMesh extends Node implements IDisposable, ICullable, IGetSetVerticesData {
         private static _BILLBOARDMODE_NONE;
         private static _BILLBOARDMODE_X;
@@ -10129,7 +10090,7 @@ declare module BABYLON {
         private updateBoundingInfo(updateExtends, data);
         _bind(effect: Effect, indexToBind?: WebGLBuffer): void;
         getTotalVertices(): number;
-        getVerticesData(kind: string, copyWhenShared?: boolean): number[] | Float32Array;
+        getVerticesData(kind: string, copyWhenShared?: boolean, forceCopy?: boolean): number[] | Float32Array;
         getVertexBuffer(kind: string): VertexBuffer;
         getVertexBuffers(): {
             [key: string]: VertexBuffer;
@@ -10672,6 +10633,7 @@ declare module BABYLON {
         /**
          * Returns an array of integers or floats, or a Float32Array, depending on the requested `kind` (positions, indices, normals, etc).
          * If `copywhenShared` is true (default false) and if the mesh geometry is shared among some other meshes, the returned array is a copy of the internal one.
+         * You can force the copy with forceCopy === true
          * Returns null if the mesh has no geometry or no vertex buffer.
          * Possible `kind` values :
          * - BABYLON.VertexBuffer.PositionKind
@@ -10687,7 +10649,7 @@ declare module BABYLON {
          * - BABYLON.VertexBuffer.MatricesWeightsKind
          * - BABYLON.VertexBuffer.MatricesWeightsExtraKind
          */
-        getVerticesData(kind: string, copyWhenShared?: boolean): number[] | Float32Array;
+        getVerticesData(kind: string, copyWhenShared?: boolean, forceCopy?: boolean): number[] | Float32Array;
         /**
          * Returns the mesh VertexBuffer object from the requested `kind` : positions, indices, normals, etc.
          * Returns `undefined` if the mesh has no geometry.
@@ -11084,7 +11046,7 @@ declare module BABYLON {
          * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
-        static CreateRibbon(name: string, pathArray: Vector3[][], closeArray: boolean, closePath: boolean, offset: number, scene: Scene, updatable?: boolean, sideOrientation?: number, instance?: Mesh): Mesh;
+        static CreateRibbon(name: string, pathArray: Vector3[][], closeArray: boolean, closePath: boolean, offset: number, scene?: Scene, updatable?: boolean, sideOrientation?: number, instance?: Mesh): Mesh;
         /**
          * Creates a plane polygonal mesh.  By default, this is a disc.
          * Please consider using the same method from the MeshBuilder class instead.
@@ -11094,7 +11056,7 @@ declare module BABYLON {
          * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
-        static CreateDisc(name: string, radius: number, tessellation: number, scene: Scene, updatable?: boolean, sideOrientation?: number): Mesh;
+        static CreateDisc(name: string, radius: number, tessellation: number, scene?: Scene, updatable?: boolean, sideOrientation?: number): Mesh;
         /**
          * Creates a box mesh.
          * Please consider using the same method from the MeshBuilder class instead.
@@ -11103,7 +11065,7 @@ declare module BABYLON {
          * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
-        static CreateBox(name: string, size: number, scene: Scene, updatable?: boolean, sideOrientation?: number): Mesh;
+        static CreateBox(name: string, size: number, scene?: Scene, updatable?: boolean, sideOrientation?: number): Mesh;
         /**
          * Creates a sphere mesh.
          * Please consider using the same method from the MeshBuilder class instead.
@@ -11126,7 +11088,7 @@ declare module BABYLON {
          * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
-        static CreateCylinder(name: string, height: number, diameterTop: number, diameterBottom: number, tessellation: number, subdivisions: any, scene: Scene, updatable?: any, sideOrientation?: number): Mesh;
+        static CreateCylinder(name: string, height: number, diameterTop: number, diameterBottom: number, tessellation: number, subdivisions: any, scene?: Scene, updatable?: any, sideOrientation?: number): Mesh;
         /**
          * Creates a torus mesh.
          * Please consider using the same method from the MeshBuilder class instead.
@@ -11137,7 +11099,7 @@ declare module BABYLON {
          * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
-        static CreateTorus(name: string, diameter: number, thickness: number, tessellation: number, scene: Scene, updatable?: boolean, sideOrientation?: number): Mesh;
+        static CreateTorus(name: string, diameter: number, thickness: number, tessellation: number, scene?: Scene, updatable?: boolean, sideOrientation?: number): Mesh;
         /**
          * Creates a torus knot mesh.
          * Please consider using the same method from the MeshBuilder class instead.
@@ -11149,7 +11111,7 @@ declare module BABYLON {
          * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
-        static CreateTorusKnot(name: string, radius: number, tube: number, radialSegments: number, tubularSegments: number, p: number, q: number, scene: Scene, updatable?: boolean, sideOrientation?: number): Mesh;
+        static CreateTorusKnot(name: string, radius: number, tube: number, radialSegments: number, tubularSegments: number, p: number, q: number, scene?: Scene, updatable?: boolean, sideOrientation?: number): Mesh;
         /**
          * Creates a line mesh.
          * Please consider using the same method from the MeshBuilder class instead.
@@ -11160,7 +11122,7 @@ declare module BABYLON {
          * When updating an instance, remember that only point positions can change, not the number of points.
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
-        static CreateLines(name: string, points: Vector3[], scene: Scene, updatable?: boolean, instance?: LinesMesh): LinesMesh;
+        static CreateLines(name: string, points: Vector3[], scene?: Scene, updatable?: boolean, instance?: LinesMesh): LinesMesh;
         /**
          * Creates a dashed line mesh.
          * Please consider using the same method from the MeshBuilder class instead.
@@ -11174,7 +11136,7 @@ declare module BABYLON {
          * When updating an instance, remember that only point positions can change, not the number of points.
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
-        static CreateDashedLines(name: string, points: Vector3[], dashSize: number, gapSize: number, dashNb: number, scene: Scene, updatable?: boolean, instance?: LinesMesh): LinesMesh;
+        static CreateDashedLines(name: string, points: Vector3[], dashSize: number, gapSize: number, dashNb: number, scene?: Scene, updatable?: boolean, instance?: LinesMesh): LinesMesh;
         /**
          * Creates an extruded shape mesh.
          * The extrusion is a parametric shape :  http://doc.babylonjs.com/tutorials/Parametric_Shapes.  It has no predefined shape. Its final shape will depend on the input parameters.
@@ -11193,7 +11155,7 @@ declare module BABYLON {
          * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
-        static ExtrudeShape(name: string, shape: Vector3[], path: Vector3[], scale: number, rotation: number, cap: number, scene: Scene, updatable?: boolean, sideOrientation?: number, instance?: Mesh): Mesh;
+        static ExtrudeShape(name: string, shape: Vector3[], path: Vector3[], scale: number, rotation: number, cap: number, scene?: Scene, updatable?: boolean, sideOrientation?: number, instance?: Mesh): Mesh;
         /**
          * Creates an custom extruded shape mesh.
          * The custom extrusion is a parametric shape :  http://doc.babylonjs.com/tutorials/Parametric_Shapes.  It has no predefined shape. Its final shape will depend on the input parameters.
@@ -11258,7 +11220,7 @@ declare module BABYLON {
          * The parameter `subdivisions` (positive integer) sets the number of subdivisions per side.
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
-        static CreateGround(name: string, width: number, height: number, subdivisions: number, scene: Scene, updatable?: boolean): Mesh;
+        static CreateGround(name: string, width: number, height: number, subdivisions: number, scene?: Scene, updatable?: boolean): Mesh;
         /**
          * Creates a tiled ground mesh.
          * Please consider using the same method from the MeshBuilder class instead.
@@ -11418,7 +11380,7 @@ declare module BABYLON {
     type IndicesArray = number[] | Int32Array | Uint32Array | Uint16Array;
     interface IGetSetVerticesData {
         isVerticesDataPresent(kind: string): boolean;
-        getVerticesData(kind: string, copyWhenShared?: boolean): number[] | Float32Array;
+        getVerticesData(kind: string, copyWhenShared?: boolean, forceCopy?: boolean): number[] | Float32Array;
         getIndices(copyWhenShared?: boolean): IndicesArray;
         setVerticesData(kind: string, data: number[] | Float32Array, updatable?: boolean): void;
         updateVerticesData(kind: string, data: number[] | Float32Array, updateExtends?: boolean, makeItUnique?: boolean): void;
@@ -11484,12 +11446,12 @@ declare module BABYLON {
         /**
          * Returns the object VertexData associated to the passed mesh.
          */
-        static ExtractFromMesh(mesh: Mesh, copyWhenShared?: boolean): VertexData;
+        static ExtractFromMesh(mesh: Mesh, copyWhenShared?: boolean, forceCopy?: boolean): VertexData;
         /**
          * Returns the object VertexData associated to the passed geometry.
          */
-        static ExtractFromGeometry(geometry: Geometry, copyWhenShared?: boolean): VertexData;
-        private static _ExtractFrom(meshOrGeometry, copyWhenShared?);
+        static ExtractFromGeometry(geometry: Geometry, copyWhenShared?: boolean, forceCopy?: boolean): VertexData;
+        private static _ExtractFrom(meshOrGeometry, copyWhenShared?, forceCopy?);
         /**
          * Creates the vertexData of the Ribbon.
          */
@@ -12580,6 +12542,69 @@ declare module BABYLON {
 }
 
 declare module BABYLON {
+    class MorphTarget {
+        name: string;
+        animations: Animation[];
+        private _positions;
+        private _normals;
+        private _tangents;
+        private _influence;
+        onInfluenceChanged: Observable<boolean>;
+        influence: number;
+        constructor(name: string, influence?: number);
+        readonly hasNormals: boolean;
+        readonly hasTangents: boolean;
+        setPositions(data: Float32Array | number[]): void;
+        getPositions(): Float32Array;
+        setNormals(data: Float32Array | number[]): void;
+        getNormals(): Float32Array;
+        setTangents(data: Float32Array | number[]): void;
+        getTangents(): Float32Array;
+        /**
+         * Serializes the current target into a Serialization object.
+         * Returns the serialized object.
+         */
+        serialize(): any;
+        static Parse(serializationObject: any): MorphTarget;
+        static FromMesh(mesh: AbstractMesh, name?: string, influence?: number): MorphTarget;
+    }
+}
+
+declare module BABYLON {
+    class MorphTargetManager {
+        private _targets;
+        private _targetObservable;
+        private _activeTargets;
+        private _scene;
+        private _influences;
+        private _supportsNormals;
+        private _supportsTangents;
+        private _vertexCount;
+        private _uniqueId;
+        constructor(scene?: Scene);
+        readonly uniqueId: number;
+        readonly vertexCount: number;
+        readonly supportsNormals: boolean;
+        readonly supportsTangents: boolean;
+        readonly numTargets: number;
+        readonly numInfluencers: number;
+        readonly influences: Float32Array;
+        getActiveTarget(index: number): MorphTarget;
+        getTarget(index: number): MorphTarget;
+        addTarget(target: MorphTarget): void;
+        removeTarget(target: MorphTarget): void;
+        /**
+         * Serializes the current manager into a Serialization object.
+         * Returns the serialized object.
+         */
+        serialize(): any;
+        private _onInfluenceChanged(needUpdate);
+        private _syncActiveTargets(needUpdate);
+        static Parse(serializationObject: any, scene: Scene): MorphTargetManager;
+    }
+}
+
+declare module BABYLON {
     class Particle {
         position: Vector3;
         direction: Vector3;
@@ -13397,6 +13422,29 @@ declare module BABYLON {
 }
 
 declare module BABYLON {
+    class ReflectionProbe {
+        name: string;
+        private _scene;
+        private _renderTargetTexture;
+        private _projectionMatrix;
+        private _viewMatrix;
+        private _target;
+        private _add;
+        private _attachedMesh;
+        invertYAxis: boolean;
+        position: Vector3;
+        constructor(name: string, size: number, scene: Scene, generateMipMaps?: boolean);
+        samples: number;
+        refreshRate: number;
+        getScene(): Scene;
+        readonly cubeTexture: RenderTargetTexture;
+        readonly renderList: AbstractMesh[];
+        attachToMesh(mesh: AbstractMesh): void;
+        dispose(): void;
+    }
+}
+
+declare module BABYLON {
     class AnaglyphPostProcess extends PostProcess {
         private _passedProcess;
         constructor(name: string, options: number | PostProcessOptions, rigCameras: Camera[], samplingMode?: number, engine?: Engine, reusable?: boolean);
@@ -14322,29 +14370,6 @@ declare module BABYLON {
 }
 
 declare module BABYLON {
-    class ReflectionProbe {
-        name: string;
-        private _scene;
-        private _renderTargetTexture;
-        private _projectionMatrix;
-        private _viewMatrix;
-        private _target;
-        private _add;
-        private _attachedMesh;
-        invertYAxis: boolean;
-        position: Vector3;
-        constructor(name: string, size: number, scene: Scene, generateMipMaps?: boolean);
-        samples: number;
-        refreshRate: number;
-        getScene(): Scene;
-        readonly cubeTexture: RenderTargetTexture;
-        readonly renderList: AbstractMesh[];
-        attachToMesh(mesh: AbstractMesh): void;
-        dispose(): void;
-    }
-}
-
-declare module BABYLON {
     class Sprite {
         name: string;
         position: Vector3;

文件差异内容过多而无法显示
+ 39 - 39
dist/preview release/babylon.worker.js


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

@@ -1,5 +1,248 @@
 /// <reference path="../../dist/preview release/babylon.d.ts" />
-declare module BABYLON {
+declare module BABYLON.GUI {
     class AdvancedDynamicTexture extends DynamicTexture {
+        private _isDirty;
+        private _renderObserver;
+        private _resizeObserver;
+        private _pointerMoveObserver;
+        private _background;
+        private _rootContainer;
+        _lastControlOver: Control;
+        background: string;
+        constructor(name: string, width: number, height: number, scene: Scene, generateMipMaps?: boolean, samplingMode?: number);
+        markAsDirty(): void;
+        addControl(control: Control): AdvancedDynamicTexture;
+        removeControl(control: Control): AdvancedDynamicTexture;
+        dispose(): void;
+        private _onResize();
+        private _checkUpdate();
+        private _render();
+        private _doPicking(x, y, type);
+        attach(): void;
+        static CreateForMesh(mesh: AbstractMesh, width?: number, height?: number): AdvancedDynamicTexture;
+        static CreateFullscreenUI(name: string, foreground: boolean, scene: Scene): AdvancedDynamicTexture;
+    }
+}
+
+/// <reference path="../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GUI {
+    class Measure {
+        left: number;
+        top: number;
+        width: number;
+        height: number;
+        constructor(left: number, top: number, width: number, height: number);
+        copyFrom(other: Measure): void;
+        isEqualsTo(other: Measure): boolean;
+        static Empty(): Measure;
+    }
+}
+
+/// <reference path="../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GUI {
+    class ValueAndUnit {
+        value: number;
+        unit: number;
+        negativeValueAllowed: boolean;
+        constructor(value?: number, unit?: number, negativeValueAllowed?: boolean);
+        readonly isPercentage: boolean;
+        readonly isPixel: boolean;
+        toString(): string;
+        fromString(source: string): boolean;
+        private static _Regex;
+        private static _UNITMODE_PERCENTAGE;
+        private static _UNITMODE_PIXEL;
+        static readonly UNITMODE_PERCENTAGE: number;
+        static readonly UNITMODE_PIXEL: number;
+    }
+}
+
+/// <reference path="../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GUI {
+    class Control {
+        name: string;
+        private _zIndex;
+        _root: Container;
+        _host: AdvancedDynamicTexture;
+        _currentMeasure: Measure;
+        private _fontFamily;
+        private _fontSize;
+        private _font;
+        private _width;
+        private _height;
+        private _lastMeasuredFont;
+        protected _fontOffset: {
+            ascent: number;
+            height: number;
+            descent: number;
+        };
+        private _color;
+        private _horizontalAlignment;
+        private _verticalAlignment;
+        private _isDirty;
+        private _cachedParentMeasure;
+        private _marginLeft;
+        private _marginRight;
+        private _marginTop;
+        private _marginBottom;
+        private _left;
+        private _top;
+        /**
+        * An event triggered when the pointer move over the control.
+        * @type {BABYLON.Observable}
+        */
+        onPointerMoveObservable: Observable<Control>;
+        /**
+        * An event triggered when the pointer move out of the control.
+        * @type {BABYLON.Observable}
+        */
+        onPointerOutObservable: Observable<Control>;
+        /**
+        * An event triggered when the pointer taps the control
+        * @type {BABYLON.Observable}
+        */
+        onPointerDownObservable: Observable<Control>;
+        /**
+        * An event triggered when pointer up
+        * @type {BABYLON.Observable}
+        */
+        onPointerUpObservable: Observable<Control>;
+        horizontalAlignment: number;
+        verticalAlignment: number;
+        width: string;
+        height: string;
+        fontFamily: string;
+        fontSize: number;
+        color: string;
+        zIndex: number;
+        readonly isDirty: boolean;
+        marginLeft: string;
+        marginRight: string;
+        marginTop: string;
+        marginBottom: string;
+        left: string;
+        top: string;
+        constructor(name: string);
+        protected _markAsDirty(): void;
+        _link(root: Container, host: AdvancedDynamicTexture): void;
+        protected applyStates(context: CanvasRenderingContext2D): void;
+        protected _processMeasures(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+        protected _clip(context: CanvasRenderingContext2D): void;
+        protected _measure(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+        protected _computeAlignment(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+        protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+        _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+        protected _contains(x: number, y: number): boolean;
+        _processPicking(x: number, y: number, type: number): boolean;
+        protected _processObservables(type: number): boolean;
+        private _prepareFont();
+        private static _HORIZONTAL_ALIGNMENT_LEFT;
+        private static _HORIZONTAL_ALIGNMENT_RIGHT;
+        private static _HORIZONTAL_ALIGNMENT_CENTER;
+        private static _VERTICAL_ALIGNMENT_TOP;
+        private static _VERTICAL_ALIGNMENT_BOTTOM;
+        private static _VERTICAL_ALIGNMENT_CENTER;
+        static readonly HORIZONTAL_ALIGNMENT_LEFT: number;
+        static readonly HORIZONTAL_ALIGNMENT_RIGHT: number;
+        static readonly HORIZONTAL_ALIGNMENT_CENTER: number;
+        static readonly VERTICAL_ALIGNMENT_TOP: number;
+        static readonly VERTICAL_ALIGNMENT_BOTTOM: number;
+        static readonly VERTICAL_ALIGNMENT_CENTER: number;
+        private static _FontHeightSizes;
+        static _GetFontOffset(font: string): {
+            ascent: number;
+            height: number;
+            descent: number;
+        };
+    }
+}
+
+/// <reference path="../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GUI {
+    class Container extends Control {
+        name: string;
+        private _children;
+        protected _measureForChildren: Measure;
+        constructor(name: string);
+        addControl(control: Control): Container;
+        removeControl(control: Control): Container;
+        _reOrderControl(control: Control): void;
+        protected _localDraw(context: CanvasRenderingContext2D): void;
+        _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+        _processPicking(x: number, y: number, type: number): boolean;
+        protected _clipForChildren(context: CanvasRenderingContext2D): void;
+        protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+    }
+}
+
+/// <reference path="../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GUI {
+    class Rectangle extends Container {
+        name: string;
+        private _thickness;
+        private _background;
+        private _cornerRadius;
+        thickness: number;
+        cornerRadius: number;
+        background: string;
+        constructor(name: string);
+        protected _localDraw(context: CanvasRenderingContext2D): void;
+        protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+        private _drawRoundedRect(context, offset?);
+        protected _clipForChildren(context: CanvasRenderingContext2D): void;
+    }
+}
+
+/// <reference path="../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GUI {
+    class TextBlock extends Control {
+        name: string;
+        private _text;
+        private _textY;
+        private _textWrapping;
+        private _textHorizontalAlignment;
+        private _textVerticalAlignment;
+        private _lines;
+        private _totalHeight;
+        textWrapping: boolean;
+        text: string;
+        textHorizontalAlignment: number;
+        textVerticalAlignment: number;
+        constructor(name: string, text: string);
+        private _drawText(text, textWidth, y, context);
+        _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+        protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+        protected _renderLines(context: CanvasRenderingContext2D): void;
+    }
+}
+
+/// <reference path="../../../dist/preview release/babylon.d.ts" />
+declare var DOMImage: new (width?: number, height?: number) => HTMLImageElement;
+declare module BABYLON.GUI {
+    class Image extends Control {
+        name: string;
+        private _domImage;
+        private _imageWidth;
+        private _imageHeight;
+        private _loaded;
+        private _stretch;
+        stretch: number;
+        constructor(name: string, url: string);
+        _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+        private static _STRETCH_NONE;
+        private static _STRETCH_FILL;
+        private static _STRETCH_UNIFORM;
+        static readonly STRETCH_NONE: number;
+        static readonly STRETCH_FILL: number;
+        static readonly STRETCH_UNIFORM: number;
+    }
+}
+
+/// <reference path="../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GUI {
+    class Button extends Rectangle {
+        name: string;
+        constructor(name: string);
+        static CreateImageButton(name: string, text: string, imageUrl: string): Button;
     }
 }

文件差异内容过多而无法显示
+ 1340 - 8
dist/preview release/gui/babylon.gui.js


文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js


文件差异内容过多而无法显示
+ 247 - 247
dist/preview release/inspector/babylon.inspector.bundle.js


文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/inspector/babylon.inspector.min.js


文件差异内容过多而无法显示
+ 2 - 2
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


文件差异内容过多而无法显示
+ 2 - 2
dist/preview release/loaders/babylon.glTFFileLoader.min.js


+ 20 - 0
gui/readme.md

@@ -0,0 +1,20 @@
+# Babylon.js GUI library
+
+The Babylon.js GUI library is an extension you can use to generate interactive user interface on top of the DynamicTexture.
+
+## How to use it
+
+- unit mode (Default to percentage)
+
+## Features
+* Flixible containers and controls
+* Horizontal and vertical alignment
+* Proportional or pixel constant size modes
+* Text wrapping
+
+==> ideas
+* lines (with cap)
+* ellipse
+* button
+* interactions
+* rotate / scale

+ 0 - 95
gui/src/advancedDynamicTexture.js

@@ -1,95 +0,0 @@
-/// <reference path="../../dist/preview release/babylon.d.ts"/>
-var __extends = (this && this.__extends) || (function () {
-    var extendStatics = Object.setPrototypeOf ||
-        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
-        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
-    return function (d, b) {
-        extendStatics(d, b);
-        function __() { this.constructor = d; }
-        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
-    };
-})();
-var BABYLON;
-(function (BABYLON) {
-    var GUI;
-    (function (GUI) {
-        var AdvancedDynamicTexture = (function (_super) {
-            __extends(AdvancedDynamicTexture, _super);
-            function AdvancedDynamicTexture(name, scene) {
-                var _this = _super.call(this, name, {}, scene, false, BABYLON.Texture.NEAREST_SAMPLINGMODE, BABYLON.Engine.TEXTUREFORMAT_RGBA) || this;
-                _this._dirty = false;
-                _this._rootContainer = new GUI.Container("root");
-                _this._resizeObserver = _this.getScene().getEngine().onResizeObservable.add(function () { return _this._markAsDirty(); });
-                _this._renderObserver = _this.getScene().onBeforeRenderObservable.add(function () { return _this._checkUpdate(); });
-                return _this;
-            }
-            Object.defineProperty(AdvancedDynamicTexture.prototype, "background", {
-                get: function () {
-                    return this._background;
-                },
-                set: function (value) {
-                    if (this._background === value) {
-                        return;
-                    }
-                    this._background = value;
-                    this._markAsDirty();
-                },
-                enumerable: true,
-                configurable: true
-            });
-            AdvancedDynamicTexture.prototype.addControl = function (control) {
-                control._setRoot(this._rootContainer);
-                this._rootContainer.addControl(control);
-                return this;
-            };
-            AdvancedDynamicTexture.prototype.removeControl = function (control) {
-                this._rootContainer.removeControl(control);
-                return this;
-            };
-            AdvancedDynamicTexture.prototype.dispose = function () {
-                this.getScene().onBeforeRenderObservable.remove(this._renderObserver);
-                this.getScene().getEngine().onResizeObservable.remove(this._resizeObserver);
-                _super.prototype.dispose.call(this);
-            };
-            AdvancedDynamicTexture.prototype._markAsDirty = function () {
-                this._dirty = true;
-            };
-            AdvancedDynamicTexture.prototype._checkUpdate = function () {
-                if (!this._dirty) {
-                    return;
-                }
-                this._dirty = false;
-                this._render();
-                this.update();
-            };
-            AdvancedDynamicTexture.prototype._render = function () {
-                // Check size
-                var engine = this.getScene().getEngine();
-                var textureSize = this.getSize();
-                var renderWidth = engine.getRenderWidth();
-                var renderHeight = engine.getRenderHeight();
-                if (textureSize.width !== renderWidth || textureSize.height !== renderHeight) {
-                    this.scaleTo(renderWidth, renderHeight);
-                }
-                // Clear
-                var context = this.getContext();
-                if (this._background) {
-                    context.save();
-                    context.fillStyle = this._background;
-                    context.fillRect(0, 0, renderWidth, renderHeight);
-                    context.restore();
-                }
-                else {
-                    this.clear();
-                }
-                // Render
-                var measure = new GUI.Measure(0, 0, renderWidth, renderHeight);
-                this._rootContainer._draw(measure, context);
-            };
-            return AdvancedDynamicTexture;
-        }(BABYLON.DynamicTexture));
-        GUI.AdvancedDynamicTexture = AdvancedDynamicTexture;
-    })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
-})(BABYLON || (BABYLON = {}));
-
-//# sourceMappingURL=advancedDynamicTexture.js.map

+ 97 - 22
gui/src/advancedDynamicTexture.ts

@@ -2,11 +2,13 @@
 
 module BABYLON.GUI {
     export class AdvancedDynamicTexture extends DynamicTexture {
-        private _dirty = false;
+        private _isDirty = false;
         private _renderObserver: Observer<Scene>;
         private _resizeObserver: Observer<Engine>;
+        private _pointerMoveObserver: Observer<PointerInfo>;
         private _background: string;
         private _rootContainer = new Container("root");
+        public _lastControlOver: Control;
 
         public get background(): string {
             return this._background;
@@ -18,18 +20,29 @@ module BABYLON.GUI {
             }
 
             this._background = value;
-            this._markAsDirty();
+            this.markAsDirty();
         }
-        
-        constructor(name: string, scene: Scene) {
-            super(name, {}, scene, false, Texture.NEAREST_SAMPLINGMODE, Engine.TEXTUREFORMAT_RGBA);
+       
+        constructor(name: string, width = 0, height = 0, scene: Scene, generateMipMaps = false, samplingMode = Texture.NEAREST_SAMPLINGMODE) {
+            super(name, {width: width, height: height}, scene, generateMipMaps, samplingMode, Engine.TEXTUREFORMAT_RGBA);
 
-            this._resizeObserver = this.getScene().getEngine().onResizeObservable.add(() => this._markAsDirty());
             this._renderObserver = this.getScene().onBeforeRenderObservable.add(() => this._checkUpdate());
+
+            this._rootContainer._link(null, this);
+
+            this.hasAlpha = true;
+
+            if (!width || !height) {
+                this._resizeObserver = this.getScene().getEngine().onResizeObservable.add(() => this._onResize());
+                this._onResize();
+            }
+        }
+
+        public markAsDirty() {
+            this._isDirty = true;
         }
 
         public addControl(control: Control): AdvancedDynamicTexture {
-            control._setRoot(this._rootContainer);
             this._rootContainer.addControl(control);
 
             return this;
@@ -42,50 +55,112 @@ module BABYLON.GUI {
 
         public dispose() {
             this.getScene().onBeforeRenderObservable.remove(this._renderObserver);
-            this.getScene().getEngine().onResizeObservable.remove(this._resizeObserver);
+
+            if (this._resizeObserver) {
+                this.getScene().getEngine().onResizeObservable.remove(this._resizeObserver);
+            }
+
+            if (this._pointerMoveObserver) {
+                this.getScene().onPointerObservable.remove(this._pointerMoveObserver);
+            }
 
             super.dispose();
         }
 
-        public _markAsDirty() {
-            this._dirty = true;
+        private _onResize(): void {
+            // Check size
+            var engine = this.getScene().getEngine();
+            var textureSize = this.getSize();
+            var renderWidth = engine.getRenderWidth();
+            var renderHeight = engine.getRenderHeight();
+
+            if (textureSize.width !== renderWidth || textureSize.height !== renderHeight) {
+                this.scaleTo(renderWidth, renderHeight);
+                this.markAsDirty();
+            }
         }
 
         private _checkUpdate(): void {
-            if (!this._dirty) {
+            if (!this._isDirty && !this._rootContainer.isDirty) {
                 return;
             }
-            this._dirty = false;
+            this._isDirty = false;
 
             this._render();
             this.update();
         }
 
         private _render(): void {
-            // Check size
-            var engine = this.getScene().getEngine();
             var textureSize = this.getSize();
-            var renderWidth = engine.getRenderWidth();
-            var renderHeight = engine.getRenderHeight();
-
-            if (textureSize.width !== renderWidth || textureSize.height !== renderHeight) {
-                this.scaleTo(renderWidth, renderHeight);
-            }
+            var renderWidth = textureSize.width;
+            var renderHeight = textureSize.height;
 
             // Clear
             var context = this.getContext();
+            context.clearRect(0, 0, renderWidth, renderHeight);
             if (this._background) {
                 context.save();
                 context.fillStyle = this._background;
                 context.fillRect(0, 0, renderWidth, renderHeight);
                 context.restore();
-            } else {
-                this.clear();
             }
 
             // Render
             var measure = new Measure(0, 0, renderWidth, renderHeight);
             this._rootContainer._draw(measure, context);
         }
+
+        private _doPicking(x: number, y: number, type: number): void {
+            if (!this._rootContainer._processPicking(x, y, type)) {
+
+                if (type === BABYLON.PointerEventTypes.POINTERMOVE) {
+                    if (this._lastControlOver && this._lastControlOver.onPointerOutObservable.hasObservers()) {
+                        this._lastControlOver.onPointerOutObservable.notifyObservers(this._lastControlOver);
+                    }
+                    
+                    this._lastControlOver = null;
+                }
+            }
+        }
+
+        public attach(): void {
+            var scene = this.getScene();
+            this._pointerMoveObserver = scene.onPointerObservable.add((pi, state) => {
+                if (pi.type !== BABYLON.PointerEventTypes.POINTERMOVE 
+                    && pi.type !== BABYLON.PointerEventTypes.POINTERUP
+                    && pi.type !== BABYLON.PointerEventTypes.POINTERDOWN) {
+                    return;
+                }
+
+                this._doPicking(scene.pointerX, scene.pointerY, pi.type);
+            });
+        }
+
+        // Statics
+        public static CreateForMesh(mesh: AbstractMesh, width = 1024, height = 1024): AdvancedDynamicTexture {
+            var result = new AdvancedDynamicTexture(mesh.name + " AdvancedDynamicTexture", width, height, mesh.getScene(), true, Texture.TRILINEAR_SAMPLINGMODE);
+
+            var material = new BABYLON.StandardMaterial("AdvancedDynamicTextureMaterial", mesh.getScene());
+            material.backFaceCulling = false;
+            material.emissiveTexture = result;
+            material.opacityTexture = result;
+
+            mesh.material = material;
+
+            return result;
+        }
+
+        public static CreateFullscreenUI(name: string, foreground: boolean = true, scene: Scene): AdvancedDynamicTexture {
+            var result = new AdvancedDynamicTexture(name, 0, 0, scene);
+
+            // Display
+            var layer = new BABYLON.Layer(name + "_layer", null, scene, !foreground);
+            layer.texture = result;
+
+            // Attach
+            result.attach();
+
+            return result;
+        }
     }    
 }

+ 41 - 0
gui/src/controls/button.ts

@@ -0,0 +1,41 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON.GUI {
+    export class Button extends Rectangle {      
+        constructor(public name: string) {
+            super(name);
+        }
+
+        // While being a container, the button behaves like a control.
+        public _processPicking(x: number, y: number, type: number): boolean {
+            if (!this._contains(x, y)) {
+                return false;
+            }
+
+            this._processObservables(type);
+
+            return true;
+        }
+
+        // Statics
+        public static CreateImageButton(name: string, text: string, imageUrl: string): Button {
+            var result = new Button(name);
+
+            // Adding text
+            var textBlock = new BABYLON.GUI.TextBlock(name + "_button", text);
+            textBlock.textWrapping = true;
+            textBlock.textHorizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER;
+            textBlock.marginLeft = "20%";
+            result.addControl(textBlock);   
+
+            // Adding image
+            var iconImage = new BABYLON.GUI.Image(name + "_icon", imageUrl);
+            iconImage.width = "20%";
+            iconImage.stretch = BABYLON.GUI.Image.STRETCH_UNIFORM;
+            iconImage.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
+            result.addControl(iconImage);            
+
+            return result;
+        }
+    }    
+}

+ 0 - 74
gui/src/controls/container.js

@@ -1,74 +0,0 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
-var __extends = (this && this.__extends) || (function () {
-    var extendStatics = Object.setPrototypeOf ||
-        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
-        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
-    return function (d, b) {
-        extendStatics(d, b);
-        function __() { this.constructor = d; }
-        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
-    };
-})();
-var BABYLON;
-(function (BABYLON) {
-    var GUI;
-    (function (GUI) {
-        var Container = (function (_super) {
-            __extends(Container, _super);
-            function Container(name) {
-                var _this = _super.call(this, name) || this;
-                _this.name = name;
-                _this._children = new Array();
-                return _this;
-            }
-            Container.prototype.addControl = function (control) {
-                var index = this._children.indexOf(control);
-                if (index !== -1) {
-                    return this;
-                }
-                control._setRoot(this);
-                this._reOrderControl(control);
-                this._markAsDirty();
-                return this;
-            };
-            Container.prototype.removeControl = function (control) {
-                var index = this._children.indexOf(control);
-                if (index !== -1) {
-                    this._children.splice(index, 1);
-                }
-                this._markAsDirty();
-                return this;
-            };
-            Container.prototype._reOrderControl = function (control) {
-                this.removeControl(control);
-                for (var index = 0; index < this._children.length; index++) {
-                    if (this._children[index].zIndex > control.zIndex) {
-                        this._children.splice(index, 0, control);
-                        return;
-                    }
-                }
-                this._children.push(control);
-                this._markAsDirty();
-            };
-            Container.prototype._draw = function (parentMeasure, context) {
-                this._currentMeasure = parentMeasure.copy();
-                context.save();
-                if (this.font) {
-                    context.font = this.font;
-                }
-                if (this.color) {
-                    context.fillStyle = this.color;
-                }
-                for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
-                    var child = _a[_i];
-                    child._draw(this._currentMeasure, context);
-                }
-                context.restore();
-            };
-            return Container;
-        }(GUI.Control));
-        GUI.Container = Container;
-    })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
-})(BABYLON || (BABYLON = {}));
-
-//# sourceMappingURL=container.js.map

+ 38 - 11
gui/src/controls/container.ts

@@ -3,6 +3,7 @@
 module BABYLON.GUI {
     export class Container extends Control {
         private _children = new Array<Control>();
+        protected _measureForChildren = Measure.Empty();     
 
         constructor(public name: string) {
             super(name);
@@ -14,7 +15,7 @@ module BABYLON.GUI {
             if (index !== -1) {
                 return this;
             }
-            control._setRoot(this);
+            control._link(this, this._host);
 
             this._reOrderControl(control);
 
@@ -48,23 +49,49 @@ module BABYLON.GUI {
             this._markAsDirty();
         }
 
-        public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
-            this._currentMeasure = parentMeasure.copy();
+        protected _localDraw(context: CanvasRenderingContext2D): void {
+            // Implemented by child to be injected inside main draw
+        }
 
+        public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
             context.save();
-            
-            if (this.font) {
-                context.font = this.font;
-            }
+            super._processMeasures(parentMeasure, context);
+           
+            this.applyStates(context);
 
-            if (this.color) {
-                context.fillStyle = this.color;
-            }
+            this._localDraw(context);
 
+            this._clipForChildren(context);
             for (var child of this._children) {
-                child._draw(this._currentMeasure, context);
+                child._draw(this._measureForChildren, context);
             }
             context.restore();
         }
+
+        public _processPicking(x: number, y: number, type: number): boolean {
+            if (!super._contains(x, y)) {
+                return false;
+            }
+
+            // Checking backwards to pick closest first
+            for (var index = this._children.length - 1; index >= 0; index--) {
+                var child = this._children[index];
+                if (child._processPicking(x, y, type)) {
+                    return true;
+                }
+            }
+
+            return this._processObservables(type);
+        }
+
+        protected _clipForChildren(context: CanvasRenderingContext2D): void {
+            // DO nothing
+        }
+
+        protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {  
+            super._additionalProcessing(parentMeasure, context);
+
+            this._measureForChildren.copyFrom(this._currentMeasure);
+        }
     }    
 }

+ 0 - 62
gui/src/controls/contentControl.js

@@ -1,62 +0,0 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
-var __extends = (this && this.__extends) || (function () {
-    var extendStatics = Object.setPrototypeOf ||
-        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
-        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
-    return function (d, b) {
-        extendStatics(d, b);
-        function __() { this.constructor = d; }
-        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
-    };
-})();
-var BABYLON;
-(function (BABYLON) {
-    var GUI;
-    (function (GUI) {
-        var ContentControl = (function (_super) {
-            __extends(ContentControl, _super);
-            function ContentControl(name) {
-                var _this = _super.call(this, name) || this;
-                _this.name = name;
-                return _this;
-            }
-            Object.defineProperty(ContentControl.prototype, "child", {
-                get: function () {
-                    return this._child;
-                },
-                set: function (control) {
-                    if (this._child === control) {
-                        return;
-                    }
-                    this._child = control;
-                    control._setRoot(this._root);
-                    this._markAsDirty();
-                },
-                enumerable: true,
-                configurable: true
-            });
-            ContentControl.prototype._localDraw = function (context) {
-                // Implemented by child to be injected inside main draw
-            };
-            ContentControl.prototype._draw = function (parentMeasure, context) {
-                this._currentMeasure = parentMeasure.copy();
-                context.save();
-                if (this.font) {
-                    context.font = this.font;
-                }
-                if (this.color) {
-                    context.fillStyle = this.color;
-                }
-                this._localDraw(context);
-                if (this._child) {
-                    this._child._draw(this._currentMeasure, context);
-                }
-                context.restore();
-            };
-            return ContentControl;
-        }(GUI.Control));
-        GUI.ContentControl = ContentControl;
-    })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
-})(BABYLON || (BABYLON = {}));
-
-//# sourceMappingURL=contentControl.js.map

+ 0 - 51
gui/src/controls/contentControl.ts

@@ -1,51 +0,0 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
-
-module BABYLON.GUI {
-    export class ContentControl extends Control {
-        private _child: Control;       
-
-        public get child(): Control {
-            return this._child;
-        }
-
-        public set child(control: Control) {
-            if (this._child === control) {
-                return;
-            }
-
-            this._child = control;
-            control._setRoot(this._root);
-
-            this._markAsDirty();
-        }
-
-        constructor(public name: string) {
-            super(name);
-        }
-
-        protected _localDraw(context: CanvasRenderingContext2D): void {
-            // Implemented by child to be injected inside main draw
-        }
-
-        public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
-            this._currentMeasure = parentMeasure.copy();
-
-            context.save();
-            
-            if (this.font) {
-                context.font = this.font;
-            }
-
-            if (this.color) {
-                context.fillStyle = this.color;
-            }
-
-            this._localDraw(context);
-
-            if (this._child) {
-                this._child._draw(this._currentMeasure, context);
-            }
-            context.restore();
-        }
-    }    
-}

+ 0 - 180
gui/src/controls/control.js

@@ -1,180 +0,0 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
-var BABYLON;
-(function (BABYLON) {
-    var GUI;
-    (function (GUI) {
-        var Control = (function () {
-            function Control(name) {
-                this.name = name;
-                this._zIndex = 0;
-                this._horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
-                this._verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
-            }
-            Object.defineProperty(Control.prototype, "horizontalAlignment", {
-                get: function () {
-                    return this._horizontalAlignment;
-                },
-                set: function (value) {
-                    if (this._horizontalAlignment === value) {
-                        return;
-                    }
-                    this._horizontalAlignment = value;
-                    this._markAsDirty();
-                },
-                enumerable: true,
-                configurable: true
-            });
-            Object.defineProperty(Control.prototype, "verticalAlignment", {
-                get: function () {
-                    return this._verticalAlignment;
-                },
-                set: function (value) {
-                    if (this._verticalAlignment === value) {
-                        return;
-                    }
-                    this._verticalAlignment = value;
-                    this._markAsDirty();
-                },
-                enumerable: true,
-                configurable: true
-            });
-            Object.defineProperty(Control.prototype, "font", {
-                get: function () {
-                    return this._font;
-                },
-                set: function (value) {
-                    if (this._font === value) {
-                        return;
-                    }
-                    this._font = value;
-                    this._fontHeight = Control._GetFontHeight(this._font);
-                    this._markAsDirty();
-                },
-                enumerable: true,
-                configurable: true
-            });
-            Object.defineProperty(Control.prototype, "color", {
-                get: function () {
-                    return this._color;
-                },
-                set: function (value) {
-                    if (this._color === value) {
-                        return;
-                    }
-                    this._color = value;
-                    this._markAsDirty();
-                },
-                enumerable: true,
-                configurable: true
-            });
-            Object.defineProperty(Control.prototype, "zIndex", {
-                get: function () {
-                    return this._zIndex;
-                },
-                set: function (value) {
-                    if (this.zIndex === value) {
-                        return;
-                    }
-                    this._zIndex = value;
-                    this._root._reOrderControl(this);
-                },
-                enumerable: true,
-                configurable: true
-            });
-            Control.prototype._markAsDirty = function () {
-                if (!this._root) {
-                    return; // Not yet connected
-                }
-                this._root._markAsDirty();
-            };
-            Control.prototype._setRoot = function (root) {
-                this._root = root;
-            };
-            Control.prototype._draw = function (parentMeasure, context) {
-                this._currentMeasure = parentMeasure.copy();
-                // Do nothing
-            };
-            Object.defineProperty(Control, "HORIZONTAL_ALIGNMENT_LEFT", {
-                get: function () {
-                    return Control._HORIZONTAL_ALIGNMENT_LEFT;
-                },
-                enumerable: true,
-                configurable: true
-            });
-            Object.defineProperty(Control, "HORIZONTAL_ALIGNMENT_RIGHT", {
-                get: function () {
-                    return Control._HORIZONTAL_ALIGNMENT_RIGHT;
-                },
-                enumerable: true,
-                configurable: true
-            });
-            Object.defineProperty(Control, "HORIZONTAL_ALIGNMENT_CENTER", {
-                get: function () {
-                    return Control._HORIZONTAL_ALIGNMENT_CENTER;
-                },
-                enumerable: true,
-                configurable: true
-            });
-            Object.defineProperty(Control, "VERTICAL_ALIGNMENT_TOP", {
-                get: function () {
-                    return Control._VERTICAL_ALIGNMENT_TOP;
-                },
-                enumerable: true,
-                configurable: true
-            });
-            Object.defineProperty(Control, "VERTICAL_ALIGNMENT_BOTTOM", {
-                get: function () {
-                    return Control._VERTICAL_ALIGNMENT_BOTTOM;
-                },
-                enumerable: true,
-                configurable: true
-            });
-            Object.defineProperty(Control, "VERTICAL_ALIGNMENT_CENTER", {
-                get: function () {
-                    return Control._VERTICAL_ALIGNMENT_CENTER;
-                },
-                enumerable: true,
-                configurable: true
-            });
-            Control._GetFontHeight = function (font) {
-                if (Control._FontHeightSizes[font]) {
-                    return Control._FontHeightSizes[font];
-                }
-                var text = document.createElement("span");
-                text.innerHTML = "Hg";
-                text.style.font = font;
-                var block = document.createElement("div");
-                block.style.display = "inline-block";
-                block.style.width = "1px";
-                block.style.height = "0px";
-                block.style.verticalAlign = "bottom";
-                var div = document.createElement("div");
-                div.appendChild(text);
-                div.appendChild(block);
-                document.body.appendChild(div);
-                var fontHeight = 0;
-                try {
-                    fontHeight = block.getBoundingClientRect().top - text.getBoundingClientRect().top;
-                }
-                finally {
-                    div.remove();
-                }
-                Control._FontHeightSizes[font] = fontHeight;
-                return fontHeight;
-            };
-            ;
-            return Control;
-        }());
-        // Statics
-        Control._HORIZONTAL_ALIGNMENT_LEFT = 0;
-        Control._HORIZONTAL_ALIGNMENT_RIGHT = 1;
-        Control._HORIZONTAL_ALIGNMENT_CENTER = 2;
-        Control._VERTICAL_ALIGNMENT_TOP = 0;
-        Control._VERTICAL_ALIGNMENT_BOTTOM = 1;
-        Control._VERTICAL_ALIGNMENT_CENTER = 2;
-        Control._FontHeightSizes = {};
-        GUI.Control = Control;
-    })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
-})(BABYLON || (BABYLON = {}));
-
-//# sourceMappingURL=control.js.map

+ 373 - 18
gui/src/controls/control.ts

@@ -4,14 +4,53 @@ module BABYLON.GUI {
     export class Control {        
         private _zIndex = 0;
         public _root: Container;
-        public _currentMeasure: Measure;
+        public _host: AdvancedDynamicTexture;
+        public _currentMeasure = Measure.Empty();
+        private _fontFamily: string;
+        private _fontSize = 18;
         private _font: string;
+        private _width = new ValueAndUnit(1, ValueAndUnit.UNITMODE_PERCENTAGE, false);
+        private _height = new ValueAndUnit(1, ValueAndUnit.UNITMODE_PERCENTAGE, false);
         private _lastMeasuredFont: string;
-        protected _fontHeight: number;
+        protected _fontOffset: {ascent: number, height: number, descent: number};
         private _color: string;
         private _horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
         private _verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
+        private _isDirty = true;
+        private _cachedParentMeasure = Measure.Empty();
+        private _marginLeft = new ValueAndUnit(0);
+        private _marginRight = new ValueAndUnit(0);
+        private _marginTop = new ValueAndUnit(0);
+        private _marginBottom = new ValueAndUnit(0);        
+        private _left = new ValueAndUnit(0);
+        private _top = new ValueAndUnit(0);
         
+        // Properties
+
+        /**
+        * An event triggered when the pointer move over the control.
+        * @type {BABYLON.Observable}
+        */
+        public onPointerMoveObservable = new Observable<Control>();
+
+        /**
+        * An event triggered when the pointer move out of the control.
+        * @type {BABYLON.Observable}
+        */
+        public onPointerOutObservable = new Observable<Control>();        
+
+        /**
+        * An event triggered when the pointer taps the control
+        * @type {BABYLON.Observable}
+        */
+        public onPointerDownObservable = new Observable<Control>();     
+
+        /**
+        * An event triggered when pointer up
+        * @type {BABYLON.Observable}
+        */
+        public onPointerUpObservable = new Observable<Control>();     
+
         public get horizontalAlignment(): number {
             return this._horizontalAlignment;
         }
@@ -38,18 +77,58 @@ module BABYLON.GUI {
             this._markAsDirty();
         } 
 
-        public get font(): string {
-            return this._font;
+        public get width(): string {
+            return this._width.toString();
         }
 
-        public set font(value: string) {
-            if (this._font === value) {
+        public set width(value: string) {
+            if (this._width.toString() === value) {
                 return;
             }
 
-            this._font = value;
-            this._fontHeight = Control._GetFontHeight(this._font);
-            this._markAsDirty();
+            if (this._width.fromString(value)) {
+                this._markAsDirty();
+            }
+        }
+
+        public get height(): string {
+            return this._height.toString();
+        }
+
+        public set height(value: string) {
+            if (this._height.toString() === value) {
+                return;
+            }
+
+            if (this._height.fromString(value)) {
+                this._markAsDirty();
+            }
+        }   
+
+        public get fontFamily(): string {
+            return this._fontFamily;
+        }
+
+        public set fontFamily(value: string) {
+            if (this._fontFamily === value) {
+                return;
+            }
+
+            this._fontFamily = value;
+            this._prepareFont();
+        }
+
+        public get fontSize(): number {
+            return this._fontSize;
+        }
+
+        public set fontSize(value: number) {
+            if (this._fontSize === value) {
+                return;
+            }
+
+            this._fontSize = value;
+            this._prepareFont();
         }
 
         public get color(): string {
@@ -78,29 +157,302 @@ module BABYLON.GUI {
             this._root._reOrderControl(this);
         }
 
+        public get isDirty(): boolean {
+            return this._isDirty;
+        }
+        
+        public get marginLeft(): string {
+            return this._marginLeft.toString();
+        }
+
+        public set marginLeft(value: string) {
+            if (this._marginLeft.fromString(value)) {
+                this._markAsDirty();
+            }
+        }    
+
+        public get marginRight(): string {
+            return this._marginRight.toString();
+        }
+
+        public set marginRight(value: string) {
+            if (this._marginRight.fromString(value)) {
+                this._markAsDirty();
+            }
+        }
+
+        public get marginTop(): string {
+            return this._marginTop.toString();
+        }
+
+        public set marginTop(value: string) {
+            if (this._marginTop.fromString(value)) {
+                this._markAsDirty();
+            }
+        }
+
+        public get marginBottom(): string {
+            return this._marginBottom.toString();
+        }
+
+        public set marginBottom(value: string) {
+            if (this._marginBottom.fromString(value)) {
+                this._markAsDirty();
+            }
+        }     
+
+        public get left(): string {
+            return this._left.toString();
+        }
+
+        public set left(value: string) {
+            if (this._left.fromString(value)) {
+                this._markAsDirty();
+            }
+        }  
+
+        public get top(): string {
+            return this._top.toString();
+        }
+
+        public set top(value: string) {
+            if (this._top.fromString(value)) {
+                this._markAsDirty();
+            }
+        }                   
+
+        // Functions
         constructor(public name: string) {
+            this.fontFamily = "Arial";
         }
 
-        protected _markAsDirty(): void {
-            if (!this._root) {
+        protected _markAsDirty(): void {            
+            this._isDirty = true;
+
+            if (!this._host) {
                 return; // Not yet connected
             }
-            this._root._markAsDirty();
+            this._host.markAsDirty();
         }
 
-        public _setRoot(root: Container): void {
+        public _link(root: Container, host: AdvancedDynamicTexture): void {
             this._root = root;
+            this._host = host;
+        }
+
+        protected applyStates(context: CanvasRenderingContext2D): void {
+            if (this._font) {
+                context.font = this._font;
+            }
+
+            if (this._color) {
+                context.fillStyle = this._color;
+            }
+        }
+
+        protected _processMeasures(parentMeasure: Measure, context: CanvasRenderingContext2D) {     
+            if (this._isDirty || !this._cachedParentMeasure.isEqualsTo(parentMeasure)) {
+                this._currentMeasure.copyFrom(parentMeasure);
+
+                this._measure(parentMeasure, context);
+                this._computeAlignment(parentMeasure, context);
+
+                // Convert to int values
+                this._currentMeasure.left = this._currentMeasure.left | 0;
+                this._currentMeasure.top = this._currentMeasure.top | 0;
+                this._currentMeasure.width = this._currentMeasure.width | 0;
+                this._currentMeasure.height = this._currentMeasure.height | 0;
+
+                // Let children add more features
+                this._additionalProcessing(parentMeasure, context);
+
+                this._isDirty = false;
+                this._cachedParentMeasure.copyFrom(parentMeasure);
+            }      
+                        
+            // Clip
+            this._clip(context);
+            context.clip();
+        }
+
+        protected _clip( context: CanvasRenderingContext2D) {
+            context.beginPath();
+            context.rect(this._currentMeasure.left ,this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
+        }
+
+        protected _measure(parentMeasure: Measure, context: CanvasRenderingContext2D): void {  
+            // Width / Height
+            if (this._width.isPixel) {
+                this._currentMeasure.width = this._width.value;
+            } else {
+                this._currentMeasure.width *= this._width.value; 
+            }
+
+            if (this._height.isPixel) {
+                this._currentMeasure.height = this._height.value;
+            } else {
+                this._currentMeasure.height *= this._height.value; 
+            }
+        }
+
+        protected _computeAlignment(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+            var width = this._currentMeasure.width;
+            var height = this._currentMeasure.height;
+
+            var parentWidth = parentMeasure.width;
+            var parentHeight = parentMeasure.height;
+
+            // Left / top
+            var x = 0;
+            var y = 0;
+
+            switch (this.horizontalAlignment) {
+                case Control.HORIZONTAL_ALIGNMENT_LEFT:
+                    x = 0
+                    break;
+                case Control.HORIZONTAL_ALIGNMENT_RIGHT:
+                    x = parentWidth - width;
+                    break;
+                case Control.HORIZONTAL_ALIGNMENT_CENTER:
+                    x = (parentWidth - width) / 2;
+                    break;
+            }
+
+            switch (this.verticalAlignment) {
+                case Control.VERTICAL_ALIGNMENT_TOP:
+                    y = 0;
+                    break;
+                case Control.VERTICAL_ALIGNMENT_BOTTOM:
+                    y = parentHeight - height;
+                    break;
+                case Control.VERTICAL_ALIGNMENT_CENTER:
+                    y = (parentHeight - height) / 2;
+                    break;
+            }
+            
+            if (this._marginLeft.isPixel) {
+                this._currentMeasure.left += this._marginLeft.value;
+                this._currentMeasure.width -= this._marginRight.value;
+            } else {
+                this._currentMeasure.left += parentWidth * this._marginLeft.value;
+                this._currentMeasure.width -= parentWidth * this._marginLeft.value;
+            }
+
+            if (this._marginRight.isPixel) {
+                this._currentMeasure.width -= this._marginRight.value;
+            } else {
+                this._currentMeasure.width -= parentWidth * this._marginRight.value;
+            }
+
+            if (this._marginTop.isPixel) {
+                this._currentMeasure.top += this._marginTop.value;
+                this._currentMeasure.height -= this._marginTop.value;
+            } else {
+                this._currentMeasure.top += parentHeight * this._marginTop.value;
+                this._currentMeasure.height -= parentHeight * this._marginTop.value;
+            }
+
+            if (this._marginBottom.isPixel) {
+                this._currentMeasure.height -= this._marginBottom.value;
+            } else {
+                this._currentMeasure.height -= parentHeight * this._marginBottom.value;
+            }            
+
+            if (this._left.isPixel) {
+                this._currentMeasure.left += this._left.value;
+            } else {
+                this._currentMeasure.left += parentWidth * this._left.value;
+            }
+
+            if (this._top.isPixel) {
+                this._currentMeasure.top += this._top.value;
+            } else {
+                this._currentMeasure.top += parentHeight * this._top.value;
+            }
+
+            this._currentMeasure.left += x;
+            this._currentMeasure.top += y;            
+        }
+
+        protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+            // Do nothing
         }
 
         public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
-            this._currentMeasure = parentMeasure.copy();
             // Do nothing
         }
 
+        protected _contains(x: number, y: number) : boolean {
+            if (x < this._currentMeasure.left) {
+                return false;
+            }
+
+            if (x > this._currentMeasure.left + this._currentMeasure.width) {
+                return false;
+            }
+
+            if (y < this._currentMeasure.top) {
+                return false;
+            }
+
+            if (y > this._currentMeasure.top + this._currentMeasure.height) {
+                return false;
+            } 
+
+            return true;
+        }
+
+        public _processPicking(x: number, y: number, type: number): boolean {
+            if (!this._contains(x, y)) {
+                return false;
+            }
+
+            this._processObservables(type);
+
+            return true;
+        }
+
+        protected _processObservables(type: number): boolean {
+            if (type === BABYLON.PointerEventTypes.POINTERMOVE && this.onPointerMoveObservable.hasObservers()) {
+                this.onPointerMoveObservable.notifyObservers(this);
+
+                var previousControlOver = this._host._lastControlOver;
+                if (previousControlOver && previousControlOver !== this && previousControlOver.onPointerOutObservable.hasObservers()) {
+                    previousControlOver.onPointerOutObservable.notifyObservers(previousControlOver);
+                }
+                this._host._lastControlOver = this;
+                return true;
+            }
+
+            if (type === BABYLON.PointerEventTypes.POINTERDOWN && this.onPointerDownObservable.hasObservers()) {
+                this.onPointerDownObservable.notifyObservers(this);
+                return true;
+            }
+
+            if (type === BABYLON.PointerEventTypes.POINTERUP && this.onPointerUpObservable.hasObservers()) {
+                this.onPointerUpObservable.notifyObservers(this);
+                return true;
+            }
+        
+            return false;
+        }
+
+        private _prepareFont() {
+            if (!this._fontFamily) {
+                return;
+            }
+
+            this._font = this._fontSize + "px " + this._fontFamily;
+        
+            this._fontOffset = Control._GetFontOffset(this._font);
+            this._markAsDirty();
+        }
+
         // Statics
         private static _HORIZONTAL_ALIGNMENT_LEFT = 0;
         private static _HORIZONTAL_ALIGNMENT_RIGHT = 1;
         private static _HORIZONTAL_ALIGNMENT_CENTER = 2;
+        
         private static _VERTICAL_ALIGNMENT_TOP = 0;
         private static _VERTICAL_ALIGNMENT_BOTTOM = 1;
         private static _VERTICAL_ALIGNMENT_CENTER = 2;
@@ -131,7 +483,7 @@ module BABYLON.GUI {
 
         private static _FontHeightSizes = {};
 
-        public static _GetFontHeight(font: string): number {
+        public static _GetFontOffset(font: string): {ascent: number, height: number, descent: number} {
 
             if (Control._FontHeightSizes[font]) {
                 return Control._FontHeightSizes[font];
@@ -153,16 +505,19 @@ module BABYLON.GUI {
 
             document.body.appendChild(div);
 
+            var fontAscent = 0;
             var fontHeight = 0;
             try {
                 fontHeight = block.getBoundingClientRect().top - text.getBoundingClientRect().top;
+                block.style.verticalAlign = "baseline";
+                fontAscent = block.getBoundingClientRect().top - text.getBoundingClientRect().top;
             } finally {
                 div.remove();
             }
+            var result = { ascent: fontAscent, height: fontHeight, descent: fontHeight - fontAscent };
+            Control._FontHeightSizes[font] = result;
 
-            Control._FontHeightSizes[font] = fontHeight;
-
-            return fontHeight;
+            return result;
         };
     }    
 }

+ 89 - 0
gui/src/controls/image.ts

@@ -0,0 +1,89 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+
+var DOMImage = Image;
+
+module BABYLON.GUI {
+    export class Image extends Control {
+        private _domImage: HTMLImageElement;
+        private _imageWidth: number;
+        private _imageHeight: number;
+        private _loaded = false;
+        private _stretch = Image.STRETCH_FILL;
+
+        public get stretch(): number {
+            return this._stretch;
+        }
+
+        public set stretch(value: number) {
+            if (this._stretch === value) {
+                return;
+            }
+
+            this._stretch = value;
+
+            this._markAsDirty();
+        }
+
+        constructor(public name: string, url: string) {
+            super(name);
+
+            this._domImage = new DOMImage();
+            
+            this._domImage.onload = () => {
+                this._imageWidth = this._domImage.width;
+                this._imageHeight = this._domImage.height;
+                this._loaded = true;
+                this._markAsDirty();
+            }
+            
+            this._domImage.src = url;
+        }
+
+        public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+            context.save();
+
+            this.applyStates(context);
+            super._processMeasures(parentMeasure, context);
+
+            if (this._loaded) {
+                switch (this._stretch) {
+                    case Image.STRETCH_NONE:
+                        context.drawImage(this._domImage, this._currentMeasure.left, this._currentMeasure.top);
+                        break;
+                    case Image.STRETCH_FILL:
+                        context.drawImage(this._domImage, 0, 0, this._imageWidth, this._imageHeight, 
+                                                          this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
+                        break;
+                    case Image.STRETCH_UNIFORM:
+                        var hRatio = this._currentMeasure.width  / this._imageWidth;
+                        var vRatio =  this._currentMeasure.height / this._imageHeight;
+                        var ratio = Math.min(hRatio, vRatio);
+                        var centerX = (this._currentMeasure.width - this._imageWidth * ratio) / 2;
+                        var centerY = (this._currentMeasure.height - this._imageHeight * ratio) / 2; 
+
+                        context.drawImage(this._domImage, 0, 0, this._imageWidth, this._imageHeight,
+                                                          this._currentMeasure.left + centerX, this._currentMeasure.top + centerY, this._imageWidth * ratio, this._imageHeight * ratio);
+                        break;
+                }
+            }
+            context.restore();
+        }
+
+        // Static
+        private static _STRETCH_NONE = 0;
+        private static _STRETCH_FILL = 1;
+        private static _STRETCH_UNIFORM = 2;
+
+        public static get STRETCH_NONE(): number {
+            return Image._STRETCH_NONE;
+        }
+
+        public static get STRETCH_FILL(): number {
+            return Image._STRETCH_FILL;
+        }       
+
+        public static get STRETCH_UNIFORM(): number {
+            return Image._STRETCH_UNIFORM;
+        }              
+    }    
+}

+ 0 - 73
gui/src/controls/rectangle.js

@@ -1,73 +0,0 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
-var __extends = (this && this.__extends) || (function () {
-    var extendStatics = Object.setPrototypeOf ||
-        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
-        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
-    return function (d, b) {
-        extendStatics(d, b);
-        function __() { this.constructor = d; }
-        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
-    };
-})();
-var BABYLON;
-(function (BABYLON) {
-    var GUI;
-    (function (GUI) {
-        var Rectangle = (function (_super) {
-            __extends(Rectangle, _super);
-            function Rectangle(name) {
-                var _this = _super.call(this, name) || this;
-                _this.name = name;
-                _this._thickness = 1;
-                return _this;
-            }
-            Object.defineProperty(Rectangle.prototype, "thickness", {
-                get: function () {
-                    return this._thickness;
-                },
-                set: function (value) {
-                    if (this._thickness === value) {
-                        return;
-                    }
-                    this._thickness = value;
-                    this._markAsDirty();
-                },
-                enumerable: true,
-                configurable: true
-            });
-            Object.defineProperty(Rectangle.prototype, "background", {
-                get: function () {
-                    return this._background;
-                },
-                set: function (value) {
-                    if (this._background === value) {
-                        return;
-                    }
-                    this._background = value;
-                    this._markAsDirty();
-                },
-                enumerable: true,
-                configurable: true
-            });
-            Rectangle.prototype._localDraw = function (context) {
-                context.save();
-                if (this._background) {
-                    context.fillStyle = this._background;
-                    context.fillRect(this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
-                }
-                if (this._thickness) {
-                    if (this.color) {
-                        context.strokeStyle = this.color;
-                    }
-                    context.lineWidth = this._thickness;
-                    context.strokeRect(this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
-                }
-                context.restore();
-            };
-            return Rectangle;
-        }(GUI.ContentControl));
-        GUI.Rectangle = Rectangle;
-    })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
-})(BABYLON || (BABYLON = {}));
-
-//# sourceMappingURL=rectangle.js.map

+ 70 - 3
gui/src/controls/rectangle.ts

@@ -1,9 +1,10 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts"/>
 
 module BABYLON.GUI {
-    export class Rectangle extends ContentControl {
+    export class Rectangle extends Container {
         private _thickness = 1;
         private _background: string;
+        private _cornerRadius = 0;
         
         public get thickness(): number {
             return this._thickness;
@@ -17,7 +18,23 @@ module BABYLON.GUI {
             this._thickness = value;
             this._markAsDirty();
         }   
+        
+        public get cornerRadius(): number {
+            return this._cornerRadius;
+        }
+
+        public set cornerRadius(value: number) {
+            if (value < 0) {
+                value = 0;
+            }
 
+            if (this._cornerRadius === value) {
+                return;
+            }
+
+            this._cornerRadius = value;
+            this._markAsDirty();
+        }   
        
         public get background(): string {
             return this._background;
@@ -41,7 +58,13 @@ module BABYLON.GUI {
 
             if (this._background) {
                 context.fillStyle = this._background;
-                context.fillRect(this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
+
+                if (this._cornerRadius) {
+                    this._drawRoundedRect(context, this._thickness / 2);
+                    context.fill();
+                } else {
+                    context.fillRect(this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
+                }
             }
 
             if (this._thickness) {
@@ -49,10 +72,54 @@ module BABYLON.GUI {
                     context.strokeStyle = this.color;
                 }
                 context.lineWidth = this._thickness;
-                context.strokeRect(this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
+
+                if (this._cornerRadius) {
+                    this._drawRoundedRect(context, this._thickness / 2);
+                    context.stroke();
+                } else {                
+                    context.strokeRect(this._currentMeasure.left + this._thickness / 2, this._currentMeasure.top + this._thickness / 2, 
+                                       this._currentMeasure.width - this._thickness, this._currentMeasure.height - this._thickness);
+                }
             }
         
             context.restore();
         }
+
+        protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {  
+            super._additionalProcessing(parentMeasure, context);
+
+            this._measureForChildren.width -= 2 * this._thickness;
+            this._measureForChildren.height -= 2 * this._thickness;
+            this._measureForChildren.left += this._thickness;
+            this._measureForChildren.top += this._thickness;            
+        }
+
+        private _drawRoundedRect(context: CanvasRenderingContext2D, offset: number = 0): void {
+            var x = this._currentMeasure.left + offset;
+            var y = this._currentMeasure.top + offset;
+            var width = this._currentMeasure.width - offset * 2;
+            var height = this._currentMeasure.height - offset * 2;
+
+            var radius = Math.min(height / 2 - 2, Math.min(width / 2 - 2, this._cornerRadius));
+
+            context.beginPath();
+            context.moveTo(x + radius, y);
+            context.lineTo(x + width - radius, y);
+            context.quadraticCurveTo(x + width, y, x + width, y + radius);
+            context.lineTo(x + width, y + height - radius);
+            context.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
+            context.lineTo(x + radius, y + height);
+            context.quadraticCurveTo(x, y + height, x, y + height - radius);
+            context.lineTo(x, y + radius);
+            context.quadraticCurveTo(x, y, x + radius, y);
+            context.closePath();
+        } 
+
+        protected _clipForChildren(context: CanvasRenderingContext2D) {
+            if (this._cornerRadius) {
+                this._drawRoundedRect(context, this._thickness);
+                context.clip();
+            }
+        }
     }    
 }

+ 0 - 89
gui/src/controls/textBlock.js

@@ -1,89 +0,0 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
-var __extends = (this && this.__extends) || (function () {
-    var extendStatics = Object.setPrototypeOf ||
-        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
-        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
-    return function (d, b) {
-        extendStatics(d, b);
-        function __() { this.constructor = d; }
-        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
-    };
-})();
-var BABYLON;
-(function (BABYLON) {
-    var GUI;
-    (function (GUI) {
-        var TextBlock = (function (_super) {
-            __extends(TextBlock, _super);
-            function TextBlock(name, text) {
-                var _this = _super.call(this, name) || this;
-                _this.name = name;
-                _this.text = text;
-                return _this;
-            }
-            Object.defineProperty(TextBlock.prototype, "text", {
-                get: function () {
-                    return this._text;
-                },
-                set: function (value) {
-                    if (this._text === value) {
-                        return;
-                    }
-                    this._text = value;
-                    this._markAsDirty();
-                },
-                enumerable: true,
-                configurable: true
-            });
-            TextBlock.prototype._draw = function (parentMeasure, context) {
-                context.save();
-                if (this.font) {
-                    context.font = this.font;
-                }
-                if (this.color) {
-                    context.fillStyle = this.color;
-                }
-                this._prepare(parentMeasure, context);
-                context.fillText(this.text, this._currentMeasure.left, this._currentMeasure.top);
-                context.restore();
-            };
-            TextBlock.prototype._prepare = function (parentMeasure, context) {
-                var width = parentMeasure.width;
-                var height = parentMeasure.height;
-                var x = 0;
-                var y = 0;
-                var textSize = context.measureText(this.text);
-                switch (this.horizontalAlignment) {
-                    case GUI.Control.HORIZONTAL_ALIGNMENT_LEFT:
-                        x = 0;
-                        break;
-                    case GUI.Control.HORIZONTAL_ALIGNMENT_RIGHT:
-                        x = width - textSize.width;
-                        break;
-                    case GUI.Control.HORIZONTAL_ALIGNMENT_CENTER:
-                        x = (width - textSize.width) / 2;
-                        break;
-                }
-                if (!this._fontHeight) {
-                    this._fontHeight = GUI.Control._GetFontHeight(context.font);
-                }
-                switch (this.verticalAlignment) {
-                    case GUI.Control.VERTICAL_ALIGNMENT_TOP:
-                        y = this._fontHeight;
-                        break;
-                    case GUI.Control.VERTICAL_ALIGNMENT_BOTTOM:
-                        y = height;
-                        break;
-                    case GUI.Control.VERTICAL_ALIGNMENT_CENTER:
-                        y = (height / 2) + this._fontHeight;
-                        break;
-                }
-                this._currentMeasure = new GUI.Measure(parentMeasure.left + x, parentMeasure.top + y, width, height);
-            };
-            return TextBlock;
-        }(GUI.Control));
-        GUI.TextBlock = TextBlock;
-    })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
-})(BABYLON || (BABYLON = {}));
-
-//# sourceMappingURL=textBlock.js.map

+ 108 - 31
gui/src/controls/textBlock.ts

@@ -3,6 +3,25 @@
 module BABYLON.GUI {
     export class TextBlock extends Control {
         private _text: string;
+        private _textY: number;
+        private _textWrapping = false;
+        private _textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
+        private _textVerticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
+
+        private _lines: any[];
+        private _totalHeight: number;
+
+        public get textWrapping(): boolean {
+            return this._textWrapping;
+        }
+
+        public set textWrapping(value: boolean) {
+            if (this._textWrapping === value) {
+                return;
+            }
+            this._textWrapping = value;
+            this._markAsDirty();
+        }
 
         public get text(): string {
             return this._text;
@@ -16,66 +35,124 @@ module BABYLON.GUI {
             this._markAsDirty();
         }
 
-        constructor(public name: string, text: string) {
-            super(name);
-
-            this.text = text;
+        public get textHorizontalAlignment(): number {
+            return this._textHorizontalAlignment;
         }
 
-        public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
-            context.save();
-            if (this.font) {
-                context.font = this.font;
+        public set textHorizontalAlignment(value: number) {
+            if (this._textHorizontalAlignment === value) {
+                return;
             }
 
-            if (this.color) {
-                context.fillStyle = this.color;
+            this._textHorizontalAlignment = value;
+            this._markAsDirty();
+        } 
+
+        public get textVerticalAlignment(): number {
+            return this._textVerticalAlignment;
+        }
+
+        public set textVerticalAlignment(value: number) {
+            if (this._textVerticalAlignment === value) {
+                return;
             }
 
-            this._prepare(parentMeasure, context)
+            this._textVerticalAlignment = value;
+            this._markAsDirty();
+        } 
 
-            context.fillText(this.text, this._currentMeasure.left, this._currentMeasure.top);
+        constructor(public name: string, text: string) {
+            super(name);
 
-            context.restore();
+            this.text = text;
         }
 
-        private _prepare(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
-            var width = parentMeasure.width;
-            var height = parentMeasure.height;
-
+        private _drawText(text: string, textWidth: number, y: number, context: CanvasRenderingContext2D): void {
+            var width = this._currentMeasure.width;
             var x = 0;
-            var y = 0;
-
-            var textSize = context.measureText(this.text);
-            switch (this.horizontalAlignment) {
+            switch (this._textHorizontalAlignment) {
                 case Control.HORIZONTAL_ALIGNMENT_LEFT:
                     x = 0
                     break;
                 case Control.HORIZONTAL_ALIGNMENT_RIGHT:
-                    x = width - textSize.width;
+                    x = width - textWidth;
                     break;
                 case Control.HORIZONTAL_ALIGNMENT_CENTER:
-                    x = (width - textSize.width) / 2;
+                    x = (width - textWidth) / 2;
                     break;
             }
 
-            if (!this._fontHeight) {
-                this._fontHeight = Control._GetFontHeight(context.font);
+            context.fillText(text, this._currentMeasure.left + x, y);
+        }      
+
+        public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+            context.save();
+
+            this.applyStates(context);
+            super._processMeasures(parentMeasure, context);
+            
+            // Render lines
+            this._renderLines(context);
+
+            context.restore();
+        }
+
+        protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+            this._lines = [];
+
+            if (this._textWrapping) {
+                var words = this.text.split(' ');
+                var line = '';
+
+                var width = this._currentMeasure.width;
+                var lineWidth = 0;
+
+                for(var n = 0; n < words.length; n++) {
+                    var testLine = line + words[n] + ' ';
+                    var metrics = context.measureText(testLine);
+                    var testWidth = metrics.width;
+                    if (testWidth > width && n > 0) {
+                        this._lines.push({text: line, width: lineWidth});
+                        line = words[n] + ' ';
+                        lineWidth = context.measureText(line).width;
+                    }
+                    else {
+                        lineWidth = testWidth;
+                        line = testLine;
+                    }
+                }
+                this._lines.push({text: line, width: lineWidth});
+            } else {
+                this._lines.push({text: this.text, width: context.measureText(this.text).width});
             }
+        }
 
-            switch (this.verticalAlignment) {
+        protected _renderLines(context: CanvasRenderingContext2D): void {
+            var width = this._currentMeasure.width;
+            var height = this._currentMeasure.height;
+            
+            if (!this._fontOffset) {
+                this._fontOffset = Control._GetFontOffset(context.font);
+            }
+            var rootY = 0;
+            switch (this._textVerticalAlignment) {
                 case Control.VERTICAL_ALIGNMENT_TOP:
-                    y = this._fontHeight;
+                    rootY = this._fontOffset.ascent;
                     break;
                 case Control.VERTICAL_ALIGNMENT_BOTTOM:
-                    y = height;
+                    rootY = height - this._fontOffset.height * (this._lines.length - 1) - this._fontOffset.descent;
                     break;
                 case Control.VERTICAL_ALIGNMENT_CENTER:
-                    y = (height /2) + this._fontHeight;
+                    rootY = this._fontOffset.ascent + (height - this._fontOffset.height * this._lines.length) / 2;
                     break;
             }
-            
-            this._currentMeasure = new Measure(parentMeasure.left + x, parentMeasure.top + y, width, height);
+
+            rootY += this._currentMeasure.top;
+
+            for (var line of this._lines) {
+                this._drawText(line.text, line.width, rootY, context);
+                rootY += this._fontOffset.height;
+            }       
         }
     }    
 }

+ 0 - 22
gui/src/measure.js

@@ -1,22 +0,0 @@
-/// <reference path="../../dist/preview release/babylon.d.ts"/>
-var BABYLON;
-(function (BABYLON) {
-    var GUI;
-    (function (GUI) {
-        var Measure = (function () {
-            function Measure(left, top, width, height) {
-                this.left = left;
-                this.top = top;
-                this.width = width;
-                this.height = height;
-            }
-            Measure.prototype.copy = function () {
-                return new Measure(this.left, this.top, this.width, this.height);
-            };
-            return Measure;
-        }());
-        GUI.Measure = Measure;
-    })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
-})(BABYLON || (BABYLON = {}));
-
-//# sourceMappingURL=measure.js.map

+ 30 - 2
gui/src/measure.ts

@@ -6,8 +6,36 @@ module BABYLON.GUI {
 
         }
 
-        public copy(): Measure {
-            return new Measure(this.left, this.top,  this.width, this.height);
+        public copyFrom(other: Measure): void {
+            this.left = other.left;
+            this.top = other.top;
+            this.width = other.width;
+            this.height = other.height;
+        }
+
+        public isEqualsTo(other: Measure): boolean {
+
+            if (this.left !== other.left) {
+                return false;
+            }
+
+            if (this.top !== other.top) {
+                return false;
+            }
+
+            if (this.width !== other.width) {
+                return false;
+            }
+
+            if (this.height !== other.height) {
+                return false;
+            }
+
+            return true;
+        }
+
+        public static Empty(): Measure {
+            return new Measure(0, 0, 0, 0);
         }
     }    
 }

+ 78 - 0
gui/src/valueAndUnit.ts

@@ -0,0 +1,78 @@
+/// <reference path="../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON.GUI {
+    export class ValueAndUnit {
+        public constructor(public value = 1, public unit = ValueAndUnit.UNITMODE_PERCENTAGE, public negativeValueAllowed = true) {
+        }
+
+        public get isPercentage(): boolean {
+            return this.unit === ValueAndUnit.UNITMODE_PERCENTAGE;
+        }
+
+        public get isPixel(): boolean {
+            return this.unit === ValueAndUnit.UNITMODE_PIXEL;
+        }
+
+        public toString(): string {
+            switch (this.unit) {
+                case ValueAndUnit.UNITMODE_PERCENTAGE:
+                    return this.unit + "%";
+                case ValueAndUnit.UNITMODE_PIXEL:
+                    return this.unit + "px";
+            }
+
+            return this.unit.toString();
+        }
+
+        public fromString(source: string): boolean {
+            var match = ValueAndUnit._Regex.exec(source);
+
+            if (!match || match.length === 0) {
+                return false;
+            }
+
+            var sourceValue = parseFloat(match[1]);
+            var sourceUnit = this.unit;
+
+            if (!this.negativeValueAllowed) {
+                if (sourceValue < 0) {
+                    sourceValue = 0;
+                }
+            }
+            
+            if (match.length === 4) {
+                switch(match[3]) {
+                    case "px":
+                        sourceUnit = ValueAndUnit.UNITMODE_PIXEL;
+                        break;
+                    case "%":
+                        sourceUnit = ValueAndUnit.UNITMODE_PERCENTAGE;
+                        sourceValue /= 100.0;
+                        break;
+                }
+            }
+
+            if (sourceValue === this.value && sourceUnit === this.unit) {
+                return false;
+            }
+
+            this.value = sourceValue;
+            this.unit = sourceUnit;
+
+            return true;
+        }
+
+        // Static
+        private static _Regex = /(^-?\d*(\.\d+)?)(%|px)?/;
+        private static _UNITMODE_PERCENTAGE = 0;
+        private static _UNITMODE_PIXEL = 1;
+
+        public static get UNITMODE_PERCENTAGE(): number {
+            return ValueAndUnit._UNITMODE_PERCENTAGE;
+        }
+
+        public static get UNITMODE_PIXEL(): number {
+            return ValueAndUnit._UNITMODE_PIXEL;
+        }
+    }    
+}

+ 1 - 1
localDev/index.html

@@ -30,7 +30,7 @@
 			font-size: 16px;
 			color: white;
 			top: 15px;
-			left: 10px;
+			right: 10px;
 			width: 60px;
 			height: 20px;
 		}

+ 46 - 23
src/Animations/babylon.animation.ts

@@ -89,7 +89,7 @@
     }
 
     export class Animation {
-        private _keys: Array<{frame:number, value: any}>;
+        private _keys: Array<{frame:number, value: any, inTangent?: any, outTangent?: any}>;
         private _offsetsCache = {};
         private _highLimitsCache = {};
         private _stopped = false;
@@ -278,21 +278,37 @@
         }
 
         public floatInterpolateFunction(startValue: number, endValue: number, gradient: number): number {
-            return startValue + (endValue - startValue) * gradient;
+            return Scalar.Lerp(startValue, endValue, gradient);
+        }
+
+        public floatInterpolateFunctionWithTangents(startValue: number, outTangent: number, endValue: number, inTangent: number, gradient: number): number {
+            return Scalar.Hermite(startValue, outTangent, endValue, inTangent, gradient);
         }
 
         public quaternionInterpolateFunction(startValue: Quaternion, endValue: Quaternion, gradient: number): Quaternion {
             return Quaternion.Slerp(startValue, endValue, gradient);
         }
 
+        public quaternionInterpolateFunctionWithTangents(startValue: Quaternion, outTangent: Quaternion, endValue: Quaternion, inTangent: Quaternion, gradient: number): Quaternion {
+            return Quaternion.Hermite(startValue, outTangent, endValue, inTangent, gradient).normalize();
+        }
+
         public vector3InterpolateFunction(startValue: Vector3, endValue: Vector3, gradient: number): Vector3 {
             return Vector3.Lerp(startValue, endValue, gradient);
         }
 
+        public vector3InterpolateFunctionWithTangents(startValue: Vector3, outTangent: Vector3, endValue: Vector3, inTangent: Vector3, gradient: number): Vector3 {
+            return Vector3.Hermite(startValue, outTangent, endValue, inTangent, gradient);
+        }
+
         public vector2InterpolateFunction(startValue: Vector2, endValue: Vector2, gradient: number): Vector2 {
             return Vector2.Lerp(startValue, endValue, gradient);
         }
 
+        public vector2InterpolateFunctionWithTangents(startValue: Vector2, outTangent: Vector2, endValue: Vector2, inTangent: Vector2, gradient: number): Vector2 {
+            return Vector2.Hermite(startValue, outTangent, endValue, inTangent, gradient);
+        }
+
         public sizeInterpolateFunction(startValue: Size, endValue: Size, gradient: number): Size {
             return Size.Lerp(startValue, endValue, gradient);
         }
@@ -347,22 +363,28 @@
             this.currentFrame = currentFrame;
 
             // Try to get a hash to find the right key
-            var startKey = Math.max(0, Math.min(this._keys.length - 1, Math.floor(this._keys.length * (currentFrame - this._keys[0].frame) / (this._keys[this._keys.length - 1].frame - this._keys[0].frame)) - 1));
+            var startKeyIndex = Math.max(0, Math.min(this._keys.length - 1, Math.floor(this._keys.length * (currentFrame - this._keys[0].frame) / (this._keys[this._keys.length - 1].frame - this._keys[0].frame)) - 1));
 
-            if (this._keys[startKey].frame >= currentFrame) {
-                while (startKey - 1 >= 0 && this._keys[startKey].frame >= currentFrame) {
-                    startKey--;
+            if (this._keys[startKeyIndex].frame >= currentFrame) {
+                while (startKeyIndex - 1 >= 0 && this._keys[startKeyIndex].frame >= currentFrame) {
+                    startKeyIndex--;
                 }
             }
 
-            for (var key = startKey; key < this._keys.length; key++) {
-                if (this._keys[key + 1].frame >= currentFrame) {
+            for (var key = startKeyIndex; key < this._keys.length; key++) {
+                var endKey = this._keys[key + 1];
+
+                if (endKey.frame >= currentFrame) {
+
+                    var startKey = this._keys[key];
+                    var startValue = this._getKeyValue(startKey.value);
+                    var endValue = this._getKeyValue(endKey.value);
 
-                    var startValue = this._getKeyValue(this._keys[key].value);
-                    var endValue = this._getKeyValue(this._keys[key + 1].value);
+                    var useTangent = startKey.outTangent !== undefined && endKey.inTangent !== undefined;
+                    var frameDelta = endKey.frame - startKey.frame;
 
                     // gradient : percent of currentFrame between the frame inf and the frame sup
-                    var gradient = (currentFrame - this._keys[key].frame) / (this._keys[key + 1].frame - this._keys[key].frame);
+                    var gradient = (currentFrame - startKey.frame) / frameDelta;
 
                     // check for easingFunction and correction of gradient
                     if (this._easingFunction != null) {
@@ -372,45 +394,46 @@
                     switch (this.dataType) {
                         // Float
                         case Animation.ANIMATIONTYPE_FLOAT:
+                            var floatValue = useTangent ? this.floatInterpolateFunctionWithTangents(startValue, startKey.outTangent * frameDelta, endValue, endKey.inTangent * frameDelta, gradient) : this.floatInterpolateFunction(startValue, endValue, gradient);
                             switch (loopMode) {
                                 case Animation.ANIMATIONLOOPMODE_CYCLE:
                                 case Animation.ANIMATIONLOOPMODE_CONSTANT:
-                                    return this.floatInterpolateFunction(startValue, endValue, gradient);
+                                    return floatValue;
                                 case Animation.ANIMATIONLOOPMODE_RELATIVE:
-                                    return offsetValue * repeatCount + this.floatInterpolateFunction(startValue, endValue, gradient);
+                                    return offsetValue * repeatCount + floatValue;
                             }
                             break;
                         // Quaternion
                         case Animation.ANIMATIONTYPE_QUATERNION:
-                            var quaternion = null;
+                            var quatValue = useTangent ? this.quaternionInterpolateFunctionWithTangents(startValue, startKey.outTangent.scale(frameDelta), endValue, endKey.inTangent.scale(frameDelta), gradient) : this.quaternionInterpolateFunction(startValue, endValue, gradient);
                             switch (loopMode) {
                                 case Animation.ANIMATIONLOOPMODE_CYCLE:
                                 case Animation.ANIMATIONLOOPMODE_CONSTANT:
-                                    quaternion = this.quaternionInterpolateFunction(startValue, endValue, gradient);
-                                    break;
+                                    return quatValue;
                                 case Animation.ANIMATIONLOOPMODE_RELATIVE:
-                                    quaternion = this.quaternionInterpolateFunction(startValue, endValue, gradient).add(offsetValue.scale(repeatCount));
-                                    break;
+                                    return quatValue.add(offsetValue.scale(repeatCount));
                             }
 
-                            return quaternion;
+                            return quatValue;
                         // Vector3
                         case Animation.ANIMATIONTYPE_VECTOR3:
+                            var vec3Value = useTangent ? this.vector3InterpolateFunctionWithTangents(startValue, startKey.outTangent.scale(frameDelta), endValue, endKey.inTangent.scale(frameDelta), gradient) : this.vector3InterpolateFunction(startValue, endValue, gradient);
                             switch (loopMode) {
                                 case Animation.ANIMATIONLOOPMODE_CYCLE:
                                 case Animation.ANIMATIONLOOPMODE_CONSTANT:
-                                    return this.vector3InterpolateFunction(startValue, endValue, gradient);
+                                    return vec3Value;
                                 case Animation.ANIMATIONLOOPMODE_RELATIVE:
-                                    return this.vector3InterpolateFunction(startValue, endValue, gradient).add(offsetValue.scale(repeatCount));
+                                    return vec3Value.add(offsetValue.scale(repeatCount));
                             }
                         // Vector2
                         case Animation.ANIMATIONTYPE_VECTOR2:
+                            var vec2Value = useTangent ? this.vector2InterpolateFunctionWithTangents(startValue, startKey.outTangent.scale(frameDelta), endValue, endKey.inTangent.scale(frameDelta), gradient) : this.vector2InterpolateFunction(startValue, endValue, gradient);
                             switch (loopMode) {
                                 case Animation.ANIMATIONLOOPMODE_CYCLE:
                                 case Animation.ANIMATIONLOOPMODE_CONSTANT:
-                                    return this.vector2InterpolateFunction(startValue, endValue, gradient);
+                                    return vec2Value;
                                 case Animation.ANIMATIONLOOPMODE_RELATIVE:
-                                    return this.vector2InterpolateFunction(startValue, endValue, gradient).add(offsetValue.scale(repeatCount));
+                                    return vec2Value.add(offsetValue.scale(repeatCount));
                             }
                         // Size
                         case Animation.ANIMATIONTYPE_SIZE:

+ 12 - 10
src/Cameras/Inputs/babylon.arcRotateCameraGamepadInput.ts

@@ -27,22 +27,24 @@ module BABYLON {
                 var camera = this.camera;
                 var RSValues = this.gamepad.rightStick;
 
-                if (RSValues.x != 0) {
-                    var normalizedRX = RSValues.x / this.gamepadRotationSensibility;
-                    if (normalizedRX != 0 && Math.abs(normalizedRX) > 0.005) {
-                        camera.inertialAlphaOffset += normalizedRX;
+                if (RSValues) {
+                    if (RSValues.x != 0) {
+                        var normalizedRX = RSValues.x / this.gamepadRotationSensibility;
+                        if (normalizedRX != 0 && Math.abs(normalizedRX) > 0.005) {
+                            camera.inertialAlphaOffset += normalizedRX;
+                        }
                     }
-                }
 
-                if (RSValues.y != 0) {
-                    var normalizedRY = RSValues.y / this.gamepadRotationSensibility;
-                    if (normalizedRY != 0 && Math.abs(normalizedRY) > 0.005) {
-                        camera.inertialBetaOffset += normalizedRY;
+                    if (RSValues.y != 0) {
+                        var normalizedRY = RSValues.y / this.gamepadRotationSensibility;
+                        if (normalizedRY != 0 && Math.abs(normalizedRY) > 0.005) {
+                            camera.inertialBetaOffset += normalizedRY;
+                        }
                     }
                 }
 
                 var LSValues = this.gamepad.leftStick;
-                if (LSValues.y != 0) {
+                if (LSValues && LSValues.y != 0) {
                     var normalizedLY = LSValues.y / this.gamepadMoveSensibility;
                     if (normalizedLY != 0 && Math.abs(normalizedLY) > 0.005) {
                         this.camera.inertialRadiusOffset -= normalizedLY;

+ 9 - 4
src/Cameras/Inputs/babylon.freeCameraGamepadInput.ts

@@ -38,10 +38,15 @@ module BABYLON {
                 LSValues.y = Math.abs(normalizedLY) > 0.005 ? 0 + normalizedLY : 0;
 
                 var RSValues = this.gamepad.rightStick;
-                var normalizedRX = RSValues.x / this.gamepadAngularSensibility;
-                var normalizedRY = RSValues.y / this.gamepadAngularSensibility;
-                RSValues.x = Math.abs(normalizedRX) > 0.001 ? 0 + normalizedRX : 0;
-                RSValues.y = Math.abs(normalizedRY) > 0.001 ? 0 + normalizedRY : 0;
+                if (RSValues) {
+                    var normalizedRX = RSValues.x / this.gamepadAngularSensibility;
+                    var normalizedRY = RSValues.y / this.gamepadAngularSensibility;
+                    RSValues.x = Math.abs(normalizedRX) > 0.001 ? 0 + normalizedRX : 0;
+                    RSValues.y = Math.abs(normalizedRY) > 0.001 ? 0 + normalizedRY : 0;
+                }
+                else {
+                    RSValues = {x:0, y:0};
+                }
 
                 if (!camera.rotationQuaternion) {
                     Matrix.RotationYawPitchRollToRef(camera.rotation.y, camera.rotation.x, 0, this._cameraTransform);

+ 19 - 39
src/Cameras/VR/babylon.webVRCamera.ts

@@ -96,50 +96,30 @@ module BABYLON {
             //enable VR
             this.getEngine().initWebVR();
 
-            if (!this.getEngine().vrDisplaysPromise) {
-                Tools.Error("WebVR is not enabled on your browser");
+            //check specs version
+            if (!window.VRFrameData) {
+                this._specsVersion = 1.0;
+                this._frameData = {
+                };
             } else {
-                //check specs version
-                if (!window.VRFrameData) {
-                    this._specsVersion = 1.0;
-                    this._frameData = {
-                    };
-                } else {
-                    this._frameData = new VRFrameData();
+                this._frameData = new VRFrameData();
+            }
+
+            this.getEngine().getVRDevice(this.webVROptions.displayName, device => {
+                if (!device) {
+                    return;
                 }
 
-                this.getEngine().vrDisplaysPromise.then((devices) => {
-                    if (devices.length > 0) {
-                        this._vrEnabled = true;
-                        if (this.webVROptions.displayName) {
-                            var found = devices.some(device => {
-                                if (device.displayName === this.webVROptions.displayName) {
-                                    this._vrDevice = device;
-                                    return true;
-                                } else {
-                                    return false;
-                                }
-                            });
-                            if (!found) {
-                                this._vrDevice = devices[0];
-                                Tools.Warn("Display " + this.webVROptions.displayName + " was not found. Using " + this._vrDevice.displayName);
-                            }
-                        } else {
-                            //choose the first one
-                            this._vrDevice = devices[0];
-                        }
+                this._vrEnabled = true;               
+                this._vrDevice = device;
 
-                        //reset the rig parameters.
-                        this.setCameraRigMode(Camera.RIG_MODE_WEBVR, { parentCamera: this, vrDisplay: this._vrDevice, frameData: this._frameData, specs: this._specsVersion });
+                //reset the rig parameters.
+                this.setCameraRigMode(Camera.RIG_MODE_WEBVR, { parentCamera: this, vrDisplay: this._vrDevice, frameData: this._frameData, specs: this._specsVersion });
 
-                        if (this._attached) {
-                            this.getEngine().enableVR(this._vrDevice)
-                        }
-                    } else {
-                        Tools.Error("No WebVR devices found!");
-                    }
-                });
-            }
+                if (this._attached) {
+                    this.getEngine().enableVR(this._vrDevice)
+                }
+            });                
 
             // try to attach the controllers, if found.
             this.initControllers();

+ 7 - 0
src/Debug/babylon.skeletonViewer.ts

@@ -64,6 +64,7 @@
 
         private _getLinesForBonesWithLength(bones: Bone[], meshMat: Matrix): void {
             var len = bones.length;
+            var meshPos = this.mesh.position;
             for (var i = 0; i < len; i++) {
                 var bone = bones[i];
                 var points = this._debugLines[i];
@@ -73,12 +74,15 @@
                 }
                 this._getBonePosition(points[0], bone, meshMat);
                 this._getBonePosition(points[1], bone, meshMat, 0, bone.length, 0);
+                points[0].subtractInPlace(meshPos);
+                points[1].subtractInPlace(meshPos);
             }
         }
 
         private _getLinesForBonesNoLength(bones: Bone[], meshMat: Matrix): void {
             var len = bones.length;
             var boneNum = 0;
+            var meshPos = this.mesh.position;
             for (var i = len - 1; i >= 0; i--) {
                 var childBone = bones[i];
                 var parentBone = childBone.getParent();
@@ -92,6 +96,8 @@
                 }
                 childBone.getAbsolutePositionToRef(this.mesh, points[0]);
                 parentBone.getAbsolutePositionToRef(this.mesh, points[1]);
+                points[0].subtractInPlace(meshPos);
+                points[1].subtractInPlace(meshPos);
                 boneNum++;
             }
         }
@@ -113,6 +119,7 @@
             } else {
                 BABYLON.MeshBuilder.CreateLineSystem(null, { lines: this._debugLines, updatable: true, instance: this._debugMesh }, this._scene);
             }
+            this._debugMesh.position.copyFrom(this.mesh.position);
             this._debugMesh.color = this.color;
         }
 

+ 2 - 1
src/Materials/Textures/babylon.baseTexture.ts

@@ -112,7 +112,8 @@
 
         public isReady(): boolean {
             if (this.delayLoadState === Engine.DELAYLOADSTATE_NOTLOADED) {
-                return true;
+                this.delayLoad();
+                return false;
             }
 
             if (this._texture) {

+ 1 - 0
src/Materials/Textures/babylon.texture.ts

@@ -86,6 +86,7 @@
             this._deleteBuffer = deleteBuffer;
             this._format = format;
 
+            scene = this.getScene();
             if (!url) {
                 return;
             }

+ 2 - 2
src/Materials/babylon.pushMaterial.ts

@@ -41,8 +41,8 @@
             this.getScene()._cachedEffect = effect;
         }
 
-        protected _mustRebind(scene: Scene, effect: Effect) {
-            return scene.getCachedEffect() !== effect || scene.getCachedMaterial() !== this;
+        protected _mustRebind(scene: Scene, effect: Effect, visibility: number = 0) {
+            return scene.isCachedMaterialValid(this, effect, visibility);
         }
 
         public markAsDirty(flag: number): void {

+ 2 - 1
src/Materials/babylon.standardMaterial.ts

@@ -821,7 +821,7 @@ module BABYLON {
 
             // Bones
             MaterialHelper.BindBonesParameters(mesh, effect);
-            if (this._mustRebind(scene, effect)) {
+            if (this._mustRebind(scene, effect, mesh.visibility)) {
                 this._uniformBuffer.bindToEffect(effect, "Material");
                 
                 this.bindViewProjection(effect);
@@ -918,6 +918,7 @@ module BABYLON {
                         this._uniformBuffer.updateColor4("vSpecularColor", this.specularColor, this.specularPower);
                     }
                     this._uniformBuffer.updateColor3("vEmissiveColor", this.emissiveColor);
+
                     // Diffuse
                     this._uniformBuffer.updateColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
                 }

+ 43 - 4
src/Math/babylon.math.ts

@@ -53,6 +53,30 @@
     }
 
 
+    export class Scalar {
+        /**
+         * Creates a new scalar with values linearly interpolated of "amount" between the start scalar and the end scalar.
+         */
+        public static Lerp(start: number, end: number, amount: number): number {
+            return start + ((end - start) * amount);
+        }
+
+        /**
+         * Returns a new scalar located for "amount" (float) on the Hermite spline defined by the scalars "value1", "value3", "tangent1", "tangent2".
+         */
+        public static Hermite(value1: number, tangent1: number, value2: number, tangent2: number, amount: number): number {
+            var squared = amount * amount;
+            var cubed = amount * squared;
+            var part1 = ((2.0 * cubed) - (3.0 * squared)) + 1.0;
+            var part2 = (-2.0 * cubed) + (3.0 * squared);
+            var part3 = (cubed - (2.0 * squared)) + amount;
+            var part4 = cubed - squared;
+
+            return (((value1 * part1) + (value2 * part2)) + (tangent1 * part3)) + (tangent2 * part4);
+        }
+    }
+
+
     export class Color3 {
         /**
          * Creates a new Color3 object from red, green, blue values, all between 0 and 1.  
@@ -899,7 +923,7 @@
         }
 
         /**
-         * Returns a new Vecto2 located for "amount" (float) on the Hermite spline defined by the vectors "value1", "value3", "tangent1", "tangent2".  
+         * Returns a new Vector2 located for "amount" (float) on the Hermite spline defined by the vectors "value1", "value3", "tangent1", "tangent2".
          */
         public static Hermite(value1: Vector2, tangent1: Vector2, value2: Vector2, tangent2: Vector2, amount: number): Vector2 {
             var squared = amount * amount;
@@ -1586,7 +1610,7 @@
         }
 
         /**
-         * Returns a new Vector3 located for "amount" (float) on the Hermite interpolation spline defined by the vectors "value1", "tangent1", "value2", "tangent2".  
+         * Returns a new Vector3 located for "amount" (float) on the Hermite interpolation spline defined by the vectors "value1", "tangent1", "value2", "tangent2".
          */
         public static Hermite(value1: Vector3, tangent1: Vector3, value2: Vector3, tangent2: Vector3, amount: number): Vector3 {
             var squared = amount * amount;
@@ -2813,13 +2837,11 @@
         }
 
         public static Slerp(left: Quaternion, right: Quaternion, amount: number): Quaternion {
-
             var result = Quaternion.Identity();
 
             Quaternion.SlerpToRef(left, right, amount, result);
 
             return result;
-
         }
 
         public static SlerpToRef(left: Quaternion, right: Quaternion, amount: number, result: Quaternion): void {
@@ -2849,7 +2871,24 @@
             result.y = (num3 * left.y) + (num2 * right.y);
             result.z = (num3 * left.z) + (num2 * right.z);
             result.w = (num3 * left.w) + (num2 * right.w);
+        }
+
+        /**
+         * Returns a new Quaternion located for "amount" (float) on the Hermite interpolation spline defined by the vectors "value1", "tangent1", "value2", "tangent2".
+         */
+        public static Hermite(value1: Quaternion, tangent1: Quaternion, value2: Quaternion, tangent2: Quaternion, amount: number): Quaternion {
+            var squared = amount * amount;
+            var cubed = amount * squared;
+            var part1 = ((2.0 * cubed) - (3.0 * squared)) + 1.0;
+            var part2 = (-2.0 * cubed) + (3.0 * squared);
+            var part3 = (cubed - (2.0 * squared)) + amount;
+            var part4 = cubed - squared;
 
+            var x = (((value1.x * part1) + (value2.x * part2)) + (tangent1.x * part3)) + (tangent2.x * part4);
+            var y = (((value1.y * part1) + (value2.y * part2)) + (tangent1.y * part3)) + (tangent2.y * part4);
+            var z = (((value1.z * part1) + (value2.z * part2)) + (tangent1.z * part3)) + (tangent2.z * part4);
+            var w = (((value1.w * part1) + (value2.w * part2)) + (tangent1.w * part3)) + (tangent2.w * part4);
+            return new Quaternion(x, y, z, w);
         }
     }
 

+ 2 - 2
src/Mesh/babylon.geometry.ts

@@ -234,13 +234,13 @@
             return this._totalVertices;
         }
 
-        public getVerticesData(kind: string, copyWhenShared?: boolean): number[] | Float32Array {
+        public getVerticesData(kind: string, copyWhenShared?: boolean, forceCopy?: boolean): number[] | Float32Array {
             var vertexBuffer = this.getVertexBuffer(kind);
             if (!vertexBuffer) {
                 return null;
             }
             var orig = vertexBuffer.getData();
-            if (!copyWhenShared || this._meshes.length === 1) {
+            if (!forceCopy && (!copyWhenShared || this._meshes.length === 1)) {
                 return orig;
             } else {
                 var len = orig.length;

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

@@ -389,6 +389,7 @@
         /**
          * Returns an array of integers or floats, or a Float32Array, depending on the requested `kind` (positions, indices, normals, etc).  
          * If `copywhenShared` is true (default false) and if the mesh geometry is shared among some other meshes, the returned array is a copy of the internal one.
+         * You can force the copy with forceCopy === true
          * Returns null if the mesh has no geometry or no vertex buffer.    
          * Possible `kind` values :
          * - BABYLON.VertexBuffer.PositionKind
@@ -404,11 +405,11 @@
          * - BABYLON.VertexBuffer.MatricesWeightsKind
          * - BABYLON.VertexBuffer.MatricesWeightsExtraKind 
          */
-        public getVerticesData(kind: string, copyWhenShared?: boolean): number[] | Float32Array {
+        public getVerticesData(kind: string, copyWhenShared?: boolean, forceCopy?: boolean): number[] | Float32Array {
             if (!this._geometry) {
                 return null;
             }
-            return this._geometry.getVerticesData(kind, copyWhenShared);
+            return this._geometry.getVerticesData(kind, copyWhenShared, forceCopy);
         }
 
         /**
@@ -2311,7 +2312,7 @@
          * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation    
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.  
          */
-        public static CreateRibbon(name: string, pathArray: Vector3[][], closeArray: boolean, closePath: boolean, offset: number, scene: Scene, updatable?: boolean, sideOrientation?: number, instance?: Mesh): Mesh {
+        public static CreateRibbon(name: string, pathArray: Vector3[][], closeArray: boolean, closePath: boolean, offset: number, scene?: Scene, updatable?: boolean, sideOrientation?: number, instance?: Mesh): Mesh {
             return MeshBuilder.CreateRibbon(name, {
                 pathArray: pathArray,
                 closeArray: closeArray,
@@ -2331,7 +2332,7 @@
          * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation    
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.  
          */
-        public static CreateDisc(name: string, radius: number, tessellation: number, scene: Scene, updatable?: boolean, sideOrientation?: number): Mesh {
+        public static CreateDisc(name: string, radius: number, tessellation: number, scene?: Scene, updatable?: boolean, sideOrientation?: number): Mesh {
             var options = {
                 radius: radius,
                 tessellation: tessellation,
@@ -2349,7 +2350,7 @@
          * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation    
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.  
          */
-        public static CreateBox(name: string, size: number, scene: Scene, updatable?: boolean, sideOrientation?: number): Mesh {
+        public static CreateBox(name: string, size: number, scene?: Scene, updatable?: boolean, sideOrientation?: number): Mesh {
             var options = {
                 size: size,
                 sideOrientation: sideOrientation,
@@ -2392,7 +2393,7 @@
          * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation    
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.  
          */
-        public static CreateCylinder(name: string, height: number, diameterTop: number, diameterBottom: number, tessellation: number, subdivisions: any, scene: Scene, updatable?: any, sideOrientation?: number): Mesh {
+        public static CreateCylinder(name: string, height: number, diameterTop: number, diameterBottom: number, tessellation: number, subdivisions: any, scene?: Scene, updatable?: any, sideOrientation?: number): Mesh {
             if (scene === undefined || !(scene instanceof Scene)) {
                 if (scene !== undefined) {
                     sideOrientation = updatable || Mesh.DEFAULTSIDE;
@@ -2426,7 +2427,7 @@
          * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation    
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.  
          */
-        public static CreateTorus(name: string, diameter: number, thickness: number, tessellation: number, scene: Scene, updatable?: boolean, sideOrientation?: number): Mesh {
+        public static CreateTorus(name: string, diameter: number, thickness: number, tessellation: number, scene?: Scene, updatable?: boolean, sideOrientation?: number): Mesh {
             var options = {
                 diameter: diameter,
                 thickness: thickness,
@@ -2448,7 +2449,7 @@
          * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation    
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.  
          */
-        public static CreateTorusKnot(name: string, radius: number, tube: number, radialSegments: number, tubularSegments: number, p: number, q: number, scene: Scene, updatable?: boolean, sideOrientation?: number): Mesh {
+        public static CreateTorusKnot(name: string, radius: number, tube: number, radialSegments: number, tubularSegments: number, p: number, q: number, scene?: Scene, updatable?: boolean, sideOrientation?: number): Mesh {
             var options = {
                 radius: radius,
                 tube: tube,
@@ -2473,7 +2474,7 @@
          * When updating an instance, remember that only point positions can change, not the number of points.      
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.  
          */
-        public static CreateLines(name: string, points: Vector3[], scene: Scene, updatable?: boolean, instance?: LinesMesh): LinesMesh {
+        public static CreateLines(name: string, points: Vector3[], scene?: Scene, updatable?: boolean, instance?: LinesMesh): LinesMesh {
             var options = {
                 points: points,
                 updatable: updatable,
@@ -2495,7 +2496,7 @@
          * When updating an instance, remember that only point positions can change, not the number of points.      
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.  
          */
-        public static CreateDashedLines(name: string, points: Vector3[], dashSize: number, gapSize: number, dashNb: number, scene: Scene, updatable?: boolean, instance?: LinesMesh): LinesMesh {
+        public static CreateDashedLines(name: string, points: Vector3[], dashSize: number, gapSize: number, dashNb: number, scene?: Scene, updatable?: boolean, instance?: LinesMesh): LinesMesh {
             var options = {
                 points: points,
                 dashSize: dashSize,
@@ -2525,7 +2526,7 @@
          * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation    
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.  
          */
-        public static ExtrudeShape(name: string, shape: Vector3[], path: Vector3[], scale: number, rotation: number, cap: number, scene: Scene, updatable?: boolean, sideOrientation?: number, instance?: Mesh): Mesh {
+        public static ExtrudeShape(name: string, shape: Vector3[], path: Vector3[], scale: number, rotation: number, cap: number, scene?: Scene, updatable?: boolean, sideOrientation?: number, instance?: Mesh): Mesh {
             var options = {
                 shape: shape,
                 path: path,
@@ -2640,7 +2641,7 @@
          * The parameter `subdivisions` (positive integer) sets the number of subdivisions per side.       
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.  
          */
-        public static CreateGround(name: string, width: number, height: number, subdivisions: number, scene: Scene, updatable?: boolean): Mesh {
+        public static CreateGround(name: string, width: number, height: number, subdivisions: number, scene?: Scene, updatable?: boolean): Mesh {
             var options = {
                 width: width,
                 height: height,
@@ -2997,7 +2998,7 @@
             for (index = 0; index < meshes.length; index++) {
                 if (meshes[index]) {
                     meshes[index].computeWorldMatrix(true);
-                    otherVertexData = VertexData.ExtractFromMesh(meshes[index], true);
+                    otherVertexData = VertexData.ExtractFromMesh(meshes[index], false, true);
                     otherVertexData.transform(meshes[index].getWorldMatrix());
 
                     if (vertexData) {

+ 20 - 20
src/Mesh/babylon.mesh.vertexData.ts

@@ -4,7 +4,7 @@
     export interface IGetSetVerticesData
     {
         isVerticesDataPresent(kind: string): boolean;
-        getVerticesData(kind: string, copyWhenShared?: boolean): number[] | Float32Array;
+        getVerticesData(kind: string, copyWhenShared?: boolean, forceCopy?: boolean): number[] | Float32Array;
         getIndices(copyWhenShared?: boolean): IndicesArray;
         setVerticesData(kind: string, data: number[] | Float32Array, updatable?: boolean): void;
         updateVerticesData(kind: string, data: number[] | Float32Array, updateExtends?: boolean, makeItUnique?: boolean): void;
@@ -427,74 +427,74 @@
         /**
          * Returns the object VertexData associated to the passed mesh.  
          */
-        public static ExtractFromMesh(mesh: Mesh, copyWhenShared?: boolean): VertexData {
-            return VertexData._ExtractFrom(mesh, copyWhenShared);
+        public static ExtractFromMesh(mesh: Mesh, copyWhenShared?: boolean, forceCopy?: boolean): VertexData {
+            return VertexData._ExtractFrom(mesh, copyWhenShared, forceCopy);
         }
 
         /**
          * Returns the object VertexData associated to the passed geometry.  
          */
-        public static ExtractFromGeometry(geometry: Geometry, copyWhenShared?: boolean): VertexData {
-            return VertexData._ExtractFrom(geometry, copyWhenShared);
+        public static ExtractFromGeometry(geometry: Geometry, copyWhenShared?: boolean, forceCopy?: boolean): VertexData {
+            return VertexData._ExtractFrom(geometry, copyWhenShared, forceCopy);
         }
 
-        private static _ExtractFrom(meshOrGeometry: IGetSetVerticesData, copyWhenShared?: boolean): VertexData {
+        private static _ExtractFrom(meshOrGeometry: IGetSetVerticesData, copyWhenShared?: boolean, forceCopy?: boolean): VertexData {
             var result = new VertexData();
 
             if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.PositionKind)) {
-                result.positions = meshOrGeometry.getVerticesData(VertexBuffer.PositionKind, copyWhenShared);
+                result.positions = meshOrGeometry.getVerticesData(VertexBuffer.PositionKind, copyWhenShared, forceCopy);
             }
 
             if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.NormalKind)) {
-                result.normals = meshOrGeometry.getVerticesData(VertexBuffer.NormalKind, copyWhenShared);
+                result.normals = meshOrGeometry.getVerticesData(VertexBuffer.NormalKind, copyWhenShared, forceCopy);
             }
 
             if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.TangentKind)) {
-                result.tangents = meshOrGeometry.getVerticesData(VertexBuffer.TangentKind, copyWhenShared);
+                result.tangents = meshOrGeometry.getVerticesData(VertexBuffer.TangentKind, copyWhenShared, forceCopy);
             }
 
             if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.UVKind)) {
-                result.uvs = meshOrGeometry.getVerticesData(VertexBuffer.UVKind, copyWhenShared);
+                result.uvs = meshOrGeometry.getVerticesData(VertexBuffer.UVKind, copyWhenShared, forceCopy);
             }
 
             if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.UV2Kind)) {
-                result.uvs2 = meshOrGeometry.getVerticesData(VertexBuffer.UV2Kind, copyWhenShared);
+                result.uvs2 = meshOrGeometry.getVerticesData(VertexBuffer.UV2Kind, copyWhenShared, forceCopy);
             }
 
             if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.UV3Kind)) {
-                result.uvs3 = meshOrGeometry.getVerticesData(VertexBuffer.UV3Kind, copyWhenShared);
+                result.uvs3 = meshOrGeometry.getVerticesData(VertexBuffer.UV3Kind, copyWhenShared, forceCopy);
             }
 
             if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.UV4Kind)) {
-                result.uvs4 = meshOrGeometry.getVerticesData(VertexBuffer.UV4Kind, copyWhenShared);
+                result.uvs4 = meshOrGeometry.getVerticesData(VertexBuffer.UV4Kind, copyWhenShared, forceCopy);
             }
 
             if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.UV5Kind)) {
-                result.uvs5 = meshOrGeometry.getVerticesData(VertexBuffer.UV5Kind, copyWhenShared);
+                result.uvs5 = meshOrGeometry.getVerticesData(VertexBuffer.UV5Kind, copyWhenShared, forceCopy);
             }
 
             if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.UV6Kind)) {
-                result.uvs6 = meshOrGeometry.getVerticesData(VertexBuffer.UV6Kind, copyWhenShared);
+                result.uvs6 = meshOrGeometry.getVerticesData(VertexBuffer.UV6Kind, copyWhenShared, forceCopy);
             }
 
             if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.ColorKind)) {
-                result.colors = meshOrGeometry.getVerticesData(VertexBuffer.ColorKind, copyWhenShared);
+                result.colors = meshOrGeometry.getVerticesData(VertexBuffer.ColorKind, copyWhenShared, forceCopy);
             }
 
             if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.MatricesIndicesKind)) {
-                result.matricesIndices = meshOrGeometry.getVerticesData(VertexBuffer.MatricesIndicesKind, copyWhenShared);
+                result.matricesIndices = meshOrGeometry.getVerticesData(VertexBuffer.MatricesIndicesKind, copyWhenShared, forceCopy);
             }
 
             if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.MatricesWeightsKind)) {
-                result.matricesWeights = meshOrGeometry.getVerticesData(VertexBuffer.MatricesWeightsKind, copyWhenShared);
+                result.matricesWeights = meshOrGeometry.getVerticesData(VertexBuffer.MatricesWeightsKind, copyWhenShared, forceCopy);
             }
 
             if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.MatricesIndicesExtraKind)) {
-                result.matricesIndicesExtra = meshOrGeometry.getVerticesData(VertexBuffer.MatricesIndicesExtraKind, copyWhenShared);
+                result.matricesIndicesExtra = meshOrGeometry.getVerticesData(VertexBuffer.MatricesIndicesExtraKind, copyWhenShared, forceCopy);
             }
 
             if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.MatricesWeightsExtraKind)) {
-                result.matricesWeightsExtra = meshOrGeometry.getVerticesData(VertexBuffer.MatricesWeightsExtraKind, copyWhenShared);
+                result.matricesWeightsExtra = meshOrGeometry.getVerticesData(VertexBuffer.MatricesWeightsExtraKind, copyWhenShared, forceCopy);
             }
 
             result.indices = meshOrGeometry.getIndices(copyWhenShared);

+ 2 - 0
src/Morph/babylon.morphTarget.ts

@@ -1,5 +1,7 @@
 module BABYLON {
     export class MorphTarget {
+        public animations = new Array<Animation>();
+
         private _positions: Float32Array;
         private _normals: Float32Array;
         private _tangents: Float32Array;

+ 1 - 1
src/Physics/Plugins/babylon.cannonJSPlugin.ts

@@ -29,7 +29,7 @@
         }
 
         public executeStep(delta: number, impostors: Array<PhysicsImpostor>): void {
-            this.world.step(this._fixedTimeStep, this._useDeltaForWorldStep ? delta * 1000 : 0, 3);
+            this.world.step(this._fixedTimeStep, this._useDeltaForWorldStep ? delta : 0, 3);
         }
 
         public applyImpulse(impostor: PhysicsImpostor, force: Vector3, contactPoint: Vector3) {

+ 1 - 1
src/Rendering/babylon.boundingBoxRenderer.ts

@@ -22,7 +22,7 @@
             this._colorShader = new ShaderMaterial("colorShader", this._scene, "color",
                 {
                     attributes: [VertexBuffer.PositionKind],
-                    uniforms: ["worldViewProjection", "color"]
+                    uniforms: ["world", "viewProjection", "color"]
                 });
 
 

+ 38 - 1
src/babylon.engine.ts

@@ -1199,8 +1199,45 @@
 
 
         //WebVR functions
+        public isVRDevicePresent(callback: (result: boolean) => void) {
+            this.getVRDevice(null, (device) => {
+                callback(device !== null);
+            });
+        }
+
+        public getVRDevice(name: string, callback: (device) => void) {
+            if (!this.vrDisplaysPromise) {
+                callback(null);
+                return;
+            }
+
+            this.vrDisplaysPromise.then((devices) => {
+                if (devices.length > 0) {
+                    if (name) {
+                        var found = devices.some(device => {
+                            if (device.displayName === name) {
+                                callback(device);
+                                return true;
+                            } else {
+                                return false;
+                            }
+                        });
+                        if (!found) {
+                            Tools.Warn("Display " + name + " was not found. Using " + devices[0].displayName);
+                            callback(devices[0]);
+                        }
+                    } else {
+                        //choose the first one
+                        callback(devices[0]);
+                    }
+                } else {
+                    Tools.Error("No WebVR devices found!");
+                    callback(null);
+                }
+            });            
+        }
 
-        public initWebVR() {
+        public initWebVR(): void {
             if (!this.vrDisplaysPromise) {
                 this._getVRDisplays();
             }

+ 11 - 1
src/babylon.scene.ts

@@ -658,6 +658,7 @@
 
         public _cachedMaterial: Material;
         public _cachedEffect: Effect;
+        public _cachedVisibility: number;
 
         private _renderId = 0;
         private _executeWhenReadyTimeoutId = -1;
@@ -812,10 +813,18 @@
             return this._cachedMaterial;
         }
 
-         public getCachedEffect(): Effect {
+        public getCachedEffect(): Effect {
             return this._cachedEffect;
         }
 
+        public getCachedVisibility(): number {
+            return this._cachedVisibility;
+        }
+
+        public isCachedMaterialValid(material: Material, effect: Effect, visibility: number = 0) {
+            return this._cachedEffect !== effect || this._cachedMaterial !== material || this._cachedVisibility !== visibility;
+        }
+
         public getBoundingBoxRenderer(): BoundingBoxRenderer {
             if (!this._boundingBoxRenderer) {
                 this._boundingBoxRenderer = new BoundingBoxRenderer(this);
@@ -1508,6 +1517,7 @@
         public resetCachedMaterial(): void {
             this._cachedMaterial = null;
             this._cachedEffect = null;
+            this._cachedVisibility = null;
         }
 
         public registerBeforeRender(func: () => void): void {