소스 검색

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

gleborgne 9 년 전
부모
커밋
941086263a
49개의 변경된 파일31034개의 추가작업 그리고 15822개의 파일을 삭제
  1. 12512 0
      dist/preview release/Oimo.js
  2. 20 20
      dist/preview release/babylon.core.js
  3. 1630 1384
      dist/preview release/babylon.d.ts
  4. 27 26
      dist/preview release/babylon.js
  5. 710 348
      dist/preview release/babylon.max.js
  6. 23 22
      dist/preview release/babylon.noworker.js
  7. 1 0
      dist/preview release/what's new.md
  8. 1 1
      materialsLibrary/dist/babylon.gridMaterial.js
  9. 1 1
      materialsLibrary/dist/babylon.gridMaterial.min.js
  10. 12 1
      materialsLibrary/materials/grid/legacygrid.fragment.fx
  11. 15053 13541
      materialsLibrary/test/refs/babylon.max.js
  12. 8 6
      src/Cameras/Inputs/babylon.arcrotatecamera.input.gamepad.js
  13. 4 2
      src/Cameras/Inputs/babylon.arcrotatecamera.input.gamepad.ts
  14. 4 5
      src/Cameras/Inputs/babylon.arcrotatecamera.input.keyboard.js
  15. 6 8
      src/Cameras/Inputs/babylon.arcrotatecamera.input.mousewheel.js
  16. 127 131
      src/Cameras/Inputs/babylon.arcrotatecamera.input.pointers.js
  17. 2 3
      src/Cameras/Inputs/babylon.freecamera.input.deviceorientation.js
  18. 8 6
      src/Cameras/Inputs/babylon.freecamera.input.gamepad.js
  19. 4 2
      src/Cameras/Inputs/babylon.freecamera.input.gamepad.ts
  20. 4 5
      src/Cameras/Inputs/babylon.freecamera.input.keyboard.js
  21. 15 26
      src/Cameras/Inputs/babylon.freecamera.input.mouse.js
  22. 12 12
      src/Cameras/Inputs/babylon.freecamera.input.mouse.ts
  23. 2 18
      src/Cameras/Inputs/babylon.freecamera.input.touch.js
  24. 16 14
      src/Cameras/Inputs/babylon.freecamera.input.virtualjoystick.js
  25. 22 12
      src/Cameras/Inputs/babylon.freecamera.input.vrdeviceorientation.js
  26. 1 1
      src/Cameras/babylon.arcRotateCamera.js
  27. 0 6
      src/Cameras/babylon.arcRotateCameraInputsManager.js
  28. 10 10
      src/Cameras/babylon.arcRotateCameraInputsManager.ts
  29. 1 0
      src/Cameras/babylon.camera.js
  30. 2 0
      src/Cameras/babylon.camera.ts
  31. 14 11
      src/Cameras/babylon.cameraInputsManager.js
  32. 5 3
      src/Cameras/babylon.cameraInputsManager.ts
  33. 0 6
      src/Cameras/babylon.freeCameraInputsManager.js
  34. 17 17
      src/Cameras/babylon.freeCameraInputsManager.ts
  35. 1 0
      src/Lights/babylon.light.js
  36. 2 0
      src/Lights/babylon.light.ts
  37. 27 10
      src/Materials/Textures/babylon.videoTexture.js
  38. 27 10
      src/Materials/Textures/babylon.videoTexture.ts
  39. 8 10
      src/Mesh/babylon.abstractMesh.js
  40. 9 10
      src/Mesh/babylon.abstractMesh.ts
  41. 186 45
      src/Mesh/babylon.meshBuilder.js
  42. 188 49
      src/Mesh/babylon.meshBuilder.ts
  43. 39 0
      src/Physics/Plugins/babylon.cannonJSPlugin.js
  44. 30 0
      src/Physics/Plugins/babylon.oimoJSPlugin.js
  45. 18 0
      src/Physics/babylon.physicsEngine.js
  46. 19 8
      src/Physics/babylon.physicsImpostor.js
  47. 102 1
      src/Physics/babylon.physicsJoint.js
  48. 48 15
      src/babylon.node.js
  49. 56 16
      src/babylon.node.ts

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 12512 - 0
dist/preview release/Oimo.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 20 - 20
dist/preview release/babylon.core.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1630 - 1384
dist/preview release/babylon.d.ts


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 27 - 26
dist/preview release/babylon.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 710 - 348
dist/preview release/babylon.max.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 23 - 22
dist/preview release/babylon.noworker.js


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

@@ -10,6 +10,7 @@
     - New debuger tool: SkeletonViewer. See [demo here](Demo available here: http://www.babylonjs-playground.com/#1BZJVJ#8) (Adam & [deltakosh](https://github.com/deltakosh))
     - Added Camera Inputs Manager to manage camera inputs (mouse, touch, keyboard, gamepad, ...) in a composable way, without relying on class inheritance [gleborgne](https://github.com/gleborgne)
   - **Updates**
+    - Added node._children to track children hierarchy ([deltakosh](https://github.com/deltakosh))
     - Added Camera.ForceAttachControlToAlwaysPreventDefault to help embedding Babylon.js in iFrames ([deltakosh](https://github.com/deltakosh))
     - Support for Layer.alphaTest ([deltakosh](https://github.com/deltakosh))
     - New scene.pointerDownPredicate, scene.pointerMovePredicate, scene.pointerUpPredicate to define your own predicates for meshes picking selection ([deltakosh](https://github.com/deltakosh))

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 1
materialsLibrary/dist/babylon.gridMaterial.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 1
materialsLibrary/dist/babylon.gridMaterial.min.js


+ 12 - 1
materialsLibrary/materials/grid/legacygrid.fragment.fx

@@ -1,3 +1,14 @@
-void main(void) {
+uniform vec3 mainColor;
+uniform vec4 gridControl;
+
+void main(void) {
     gl_FragColor = vec4(1, 1, 1, 0.1);
+    
+    #ifdef TRANSPARENT
+        // Min opacity as if there were no lines.
+        gl_FragColor = vec4(mainColor.rgb, 0.08);
+    #else
+        // Apply the color.
+        gl_FragColor = vec4(mainColor.rgb, 1.0);
+    #endif
 }

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 15053 - 13541
materialsLibrary/test/refs/babylon.max.js


+ 8 - 6
src/Cameras/Inputs/babylon.arcrotatecamera.input.gamepad.js

@@ -8,16 +8,18 @@ var BABYLON;
 (function (BABYLON) {
     var ArcRotateCameraGamepadInput = (function () {
         function ArcRotateCameraGamepadInput() {
-            var _this = this;
             this.gamepadRotationSensibility = 80;
             this.gamepadMoveSensibility = 40;
-            this._gamepads = new BABYLON.Gamepads(function (gamepad) { _this._onNewGameConnected(gamepad); });
         }
-        ArcRotateCameraGamepadInput.prototype.attachCamera = function (camera) {
-            this.camera = camera;
+        ArcRotateCameraGamepadInput.prototype.attachControl = function (element, noPreventDefault) {
+            var _this = this;
+            this._gamepads = new BABYLON.Gamepads(function (gamepad) { _this._onNewGameConnected(gamepad); });
         };
-        ArcRotateCameraGamepadInput.prototype.detach = function () {
-            this._gamepads.dispose();
+        ArcRotateCameraGamepadInput.prototype.detachControl = function (element) {
+            if (this._gamepads) {
+                this._gamepads.dispose();
+            }
+            this.gamepad = null;
         };
         ArcRotateCameraGamepadInput.prototype.checkInputs = function () {
             if (this.gamepad) {

+ 4 - 2
src/Cameras/Inputs/babylon.arcrotatecamera.input.gamepad.ts

@@ -15,8 +15,10 @@ module BABYLON {
             this._gamepads = new Gamepads((gamepad: Gamepad) => { this._onNewGameConnected(gamepad); });
         }
         
-        detachControl(element : HTMLElement) {
-            this._gamepads.dispose();
+        detachControl(element: HTMLElement) {
+            if (this._gamepads) {
+                this._gamepads.dispose();
+            }
             this.gamepad = null;
         }
 

+ 4 - 5
src/Cameras/Inputs/babylon.arcrotatecamera.input.keyboard.js

@@ -14,9 +14,8 @@ var BABYLON;
             this.keysLeft = [37];
             this.keysRight = [39];
         }
-        ArcRotateCameraKeyboardMoveInput.prototype.attachCamera = function (camera) {
+        ArcRotateCameraKeyboardMoveInput.prototype.attachControl = function (element, noPreventDefault) {
             var _this = this;
-            this.camera = camera;
             this._onKeyDown = function (evt) {
                 if (_this.keysUp.indexOf(evt.keyCode) !== -1 ||
                     _this.keysDown.indexOf(evt.keyCode) !== -1 ||
@@ -27,7 +26,7 @@ var BABYLON;
                         _this._keys.push(evt.keyCode);
                     }
                     if (evt.preventDefault) {
-                        if (!camera._noPreventDefault) {
+                        if (!noPreventDefault) {
                             evt.preventDefault();
                         }
                     }
@@ -43,7 +42,7 @@ var BABYLON;
                         _this._keys.splice(index, 1);
                     }
                     if (evt.preventDefault) {
-                        if (!camera._noPreventDefault) {
+                        if (!noPreventDefault) {
                             evt.preventDefault();
                         }
                     }
@@ -58,7 +57,7 @@ var BABYLON;
                 { name: "blur", handler: this._onLostFocus }
             ]);
         };
-        ArcRotateCameraKeyboardMoveInput.prototype.detach = function () {
+        ArcRotateCameraKeyboardMoveInput.prototype.detachControl = function (element) {
             BABYLON.Tools.UnregisterTopRootEvents([
                 { name: "keydown", handler: this._onKeyDown },
                 { name: "keyup", handler: this._onKeyUp },

+ 6 - 8
src/Cameras/Inputs/babylon.arcrotatecamera.input.mousewheel.js

@@ -10,12 +10,8 @@ var BABYLON;
         function ArcRotateCameraMouseWheelInput() {
             this.wheelPrecision = 3.0;
         }
-        ArcRotateCameraMouseWheelInput.prototype.attachCamera = function (camera) {
-            this.camera = camera;
-        };
-        ArcRotateCameraMouseWheelInput.prototype.attachElement = function (element) {
+        ArcRotateCameraMouseWheelInput.prototype.attachControl = function (element, noPreventDefault) {
             var _this = this;
-            this.attachedElement = element;
             this._wheel = function (event) {
                 var delta = 0;
                 if (event.wheelDelta) {
@@ -35,9 +31,11 @@ var BABYLON;
             element.addEventListener('mousewheel', this._wheel, false);
             element.addEventListener('DOMMouseScroll', this._wheel, false);
         };
-        ArcRotateCameraMouseWheelInput.prototype.detach = function () {
-            this.attachedElement.removeEventListener('mousewheel', this._wheel);
-            this.attachedElement.removeEventListener('DOMMouseScroll', this._wheel);
+        ArcRotateCameraMouseWheelInput.prototype.detachControl = function (element) {
+            if (this._wheel && element) {
+                element.removeEventListener('mousewheel', this._wheel);
+                element.removeEventListener('DOMMouseScroll', this._wheel);
+            }
         };
         ArcRotateCameraMouseWheelInput.prototype.getTypeName = function () {
             return "ArcRotateCameraMouseWheelInput";

+ 127 - 131
src/Cameras/Inputs/babylon.arcrotatecamera.input.pointers.js

@@ -17,153 +17,149 @@ var BABYLON;
             this.pinchPrecision = 6.0;
             this.panningSensibility = 50.0;
         }
-        ArcRotateCameraPointersInput.prototype.attachCamera = function (camera) {
-            this.camera = camera;
-        };
-        ArcRotateCameraPointersInput.prototype.attachElement = function (element, noPreventDefault) {
+        ArcRotateCameraPointersInput.prototype.attachControl = function (element, noPreventDefault) {
             var _this = this;
-            this.attachedElement = element;
             var engine = this.camera.getEngine();
             var cacheSoloPointer; // cache pointer object for better perf on camera rotation
             var pointers = new BABYLON.SmartCollection();
             var previousPinchDistance = 0;
-            if (this._onPointerDown === undefined) {
-                if (!this.camera._useCtrlForPanning) {
-                    element.addEventListener("contextmenu", this._onContextMenu, false);
+            if (!this.camera._useCtrlForPanning) {
+                element.addEventListener("contextmenu", this._onContextMenu, false);
+            }
+            this._onLostFocus = function () {
+                //this._keys = [];
+                pointers.empty();
+                previousPinchDistance = 0;
+                cacheSoloPointer = null;
+            };
+            this._onKeyDown = function (evt) {
+                _this._isCtrlPushed = evt.ctrlKey;
+            };
+            this._onKeyUp = function (evt) {
+                _this._isCtrlPushed = evt.ctrlKey;
+            };
+            this._onPointerDown = function (evt) {
+                // Manage panning with right click
+                _this._isRightClick = evt.button === 2;
+                // manage pointers
+                pointers.add(evt.pointerId, { x: evt.clientX, y: evt.clientY, type: evt.pointerType });
+                cacheSoloPointer = pointers.item(evt.pointerId);
+                if (!noPreventDefault) {
+                    evt.preventDefault();
                 }
-                this._onLostFocus = function () {
-                    //this._keys = [];
-                    pointers.empty();
-                    previousPinchDistance = 0;
-                    cacheSoloPointer = null;
-                };
-                this._onKeyDown = function (evt) {
-                    _this._isCtrlPushed = evt.ctrlKey;
-                };
-                this._onKeyUp = function (evt) {
-                    _this._isCtrlPushed = evt.ctrlKey;
-                };
-                this._onPointerDown = function (evt) {
-                    // Manage panning with right click
-                    _this._isRightClick = evt.button === 2;
-                    // manage pointers
-                    pointers.add(evt.pointerId, { x: evt.clientX, y: evt.clientY, type: evt.pointerType });
-                    cacheSoloPointer = pointers.item(evt.pointerId);
-                    if (!noPreventDefault) {
-                        evt.preventDefault();
-                    }
-                };
-                this._onPointerUp = function (evt) {
-                    cacheSoloPointer = null;
-                    previousPinchDistance = 0;
-                    //would be better to use pointers.remove(evt.pointerId) for multitouch gestures, 
-                    //but emptying completly pointers collection is required to fix a bug on iPhone : 
-                    //when changing orientation while pinching camera, one pointer stay pressed forever if we don't release all pointers  
-                    //will be ok to put back pointers.remove(evt.pointerId); when iPhone bug corrected
-                    pointers.empty();
-                    if (!noPreventDefault) {
-                        evt.preventDefault();
-                    }
-                };
-                this._onContextMenu = function (evt) {
+            };
+            this._onPointerUp = function (evt) {
+                cacheSoloPointer = null;
+                previousPinchDistance = 0;
+                //would be better to use pointers.remove(evt.pointerId) for multitouch gestures, 
+                //but emptying completly pointers collection is required to fix a bug on iPhone : 
+                //when changing orientation while pinching camera, one pointer stay pressed forever if we don't release all pointers  
+                //will be ok to put back pointers.remove(evt.pointerId); when iPhone bug corrected
+                pointers.empty();
+                if (!noPreventDefault) {
                     evt.preventDefault();
-                };
-                this._onPointerMove = function (evt) {
-                    if (!noPreventDefault) {
-                        evt.preventDefault();
-                    }
-                    switch (pointers.count) {
-                        case 1:
-                            if (_this.panningSensibility !== 0 && ((_this._isCtrlPushed && _this.camera._useCtrlForPanning) || (!_this.camera._useCtrlForPanning && _this._isRightClick))) {
-                                _this.camera.inertialPanningX += -(evt.clientX - cacheSoloPointer.x) / _this.panningSensibility;
-                                _this.camera.inertialPanningY += (evt.clientY - cacheSoloPointer.y) / _this.panningSensibility;
-                            }
-                            else {
-                                var offsetX = evt.clientX - cacheSoloPointer.x;
-                                var offsetY = evt.clientY - cacheSoloPointer.y;
-                                _this.camera.inertialAlphaOffset -= offsetX / _this.angularSensibilityX;
-                                _this.camera.inertialBetaOffset -= offsetY / _this.angularSensibilityY;
-                            }
-                            cacheSoloPointer.x = evt.clientX;
-                            cacheSoloPointer.y = evt.clientY;
-                            break;
-                        case 2:
-                            //if (noPreventDefault) { evt.preventDefault(); } //if pinch gesture, could be usefull to force preventDefault to avoid html page scroll/zoom in some mobile browsers
+                }
+            };
+            this._onContextMenu = function (evt) {
+                evt.preventDefault();
+            };
+            this._onPointerMove = function (evt) {
+                if (!noPreventDefault) {
+                    evt.preventDefault();
+                }
+                switch (pointers.count) {
+                    case 1:
+                        if (_this.panningSensibility !== 0 && ((_this._isCtrlPushed && _this.camera._useCtrlForPanning) || (!_this.camera._useCtrlForPanning && _this._isRightClick))) {
+                            _this.camera.inertialPanningX += -(evt.clientX - cacheSoloPointer.x) / _this.panningSensibility;
+                            _this.camera.inertialPanningY += (evt.clientY - cacheSoloPointer.y) / _this.panningSensibility;
+                        }
+                        else {
+                            var offsetX = evt.clientX - cacheSoloPointer.x;
+                            var offsetY = evt.clientY - cacheSoloPointer.y;
+                            _this.camera.inertialAlphaOffset -= offsetX / _this.angularSensibilityX;
+                            _this.camera.inertialBetaOffset -= offsetY / _this.angularSensibilityY;
+                        }
+                        cacheSoloPointer.x = evt.clientX;
+                        cacheSoloPointer.y = evt.clientY;
+                        break;
+                    case 2:
+                        //if (noPreventDefault) { evt.preventDefault(); } //if pinch gesture, could be usefull to force preventDefault to avoid html page scroll/zoom in some mobile browsers
+                        pointers.item(evt.pointerId).x = evt.clientX;
+                        pointers.item(evt.pointerId).y = evt.clientY;
+                        var direction = _this.pinchInwards ? 1 : -1;
+                        var distX = pointers.getItemByIndex(0).x - pointers.getItemByIndex(1).x;
+                        var distY = pointers.getItemByIndex(0).y - pointers.getItemByIndex(1).y;
+                        var pinchSquaredDistance = (distX * distX) + (distY * distY);
+                        if (previousPinchDistance === 0) {
+                            previousPinchDistance = pinchSquaredDistance;
+                            return;
+                        }
+                        if (pinchSquaredDistance !== previousPinchDistance) {
+                            _this.camera.inertialRadiusOffset += (pinchSquaredDistance - previousPinchDistance) / (_this.pinchPrecision * ((_this.angularSensibilityX + _this.angularSensibilityY) / 2) * direction);
+                            previousPinchDistance = pinchSquaredDistance;
+                        }
+                        break;
+                    default:
+                        if (pointers.item(evt.pointerId)) {
                             pointers.item(evt.pointerId).x = evt.clientX;
                             pointers.item(evt.pointerId).y = evt.clientY;
-                            var direction = _this.pinchInwards ? 1 : -1;
-                            var distX = pointers.getItemByIndex(0).x - pointers.getItemByIndex(1).x;
-                            var distY = pointers.getItemByIndex(0).y - pointers.getItemByIndex(1).y;
-                            var pinchSquaredDistance = (distX * distX) + (distY * distY);
-                            if (previousPinchDistance === 0) {
-                                previousPinchDistance = pinchSquaredDistance;
-                                return;
-                            }
-                            if (pinchSquaredDistance !== previousPinchDistance) {
-                                _this.camera.inertialRadiusOffset += (pinchSquaredDistance - previousPinchDistance) / (_this.pinchPrecision * ((_this.angularSensibilityX + _this.angularSensibilityY) / 2) * direction);
-                                previousPinchDistance = pinchSquaredDistance;
-                            }
-                            break;
-                        default:
-                            if (pointers.item(evt.pointerId)) {
-                                pointers.item(evt.pointerId).x = evt.clientX;
-                                pointers.item(evt.pointerId).y = evt.clientY;
-                            }
-                    }
-                };
-                this._onMouseMove = function (evt) {
-                    if (!engine.isPointerLock) {
-                        return;
-                    }
-                    var offsetX = evt.movementX || evt.mozMovementX || evt.webkitMovementX || evt.msMovementX || 0;
-                    var offsetY = evt.movementY || evt.mozMovementY || evt.webkitMovementY || evt.msMovementY || 0;
-                    _this.camera.inertialAlphaOffset -= offsetX / _this.angularSensibilityX;
-                    _this.camera.inertialBetaOffset -= offsetY / _this.angularSensibilityY;
-                    if (!noPreventDefault) {
-                        evt.preventDefault();
-                    }
-                };
-                this._onGestureStart = function (e) {
-                    if (window.MSGesture === undefined) {
-                        return;
-                    }
-                    if (!_this._MSGestureHandler) {
-                        _this._MSGestureHandler = new MSGesture();
-                        _this._MSGestureHandler.target = element;
-                    }
-                    _this._MSGestureHandler.addPointer(e.pointerId);
-                };
-                this._onGesture = function (e) {
-                    _this.camera.radius *= e.scale;
-                    if (e.preventDefault) {
-                        if (!noPreventDefault) {
-                            e.stopPropagation();
-                            e.preventDefault();
                         }
+                }
+            };
+            this._onMouseMove = function (evt) {
+                if (!engine.isPointerLock) {
+                    return;
+                }
+                var offsetX = evt.movementX || evt.mozMovementX || evt.webkitMovementX || evt.msMovementX || 0;
+                var offsetY = evt.movementY || evt.mozMovementY || evt.webkitMovementY || evt.msMovementY || 0;
+                _this.camera.inertialAlphaOffset -= offsetX / _this.angularSensibilityX;
+                _this.camera.inertialBetaOffset -= offsetY / _this.angularSensibilityY;
+                if (!noPreventDefault) {
+                    evt.preventDefault();
+                }
+            };
+            this._onGestureStart = function (e) {
+                if (window.MSGesture === undefined) {
+                    return;
+                }
+                if (!_this._MSGestureHandler) {
+                    _this._MSGestureHandler = new MSGesture();
+                    _this._MSGestureHandler.target = element;
+                }
+                _this._MSGestureHandler.addPointer(e.pointerId);
+            };
+            this._onGesture = function (e) {
+                _this.camera.radius *= e.scale;
+                if (e.preventDefault) {
+                    if (!noPreventDefault) {
+                        e.stopPropagation();
+                        e.preventDefault();
                     }
-                };
-            }
-            this.attachedElement.addEventListener(eventPrefix + "down", this._onPointerDown, false);
-            this.attachedElement.addEventListener(eventPrefix + "up", this._onPointerUp, false);
-            this.attachedElement.addEventListener(eventPrefix + "out", this._onPointerUp, false);
-            this.attachedElement.addEventListener(eventPrefix + "move", this._onPointerMove, false);
-            this.attachedElement.addEventListener("mousemove", this._onMouseMove, false);
-            this.attachedElement.addEventListener("MSPointerDown", this._onGestureStart, false);
-            this.attachedElement.addEventListener("MSGestureChange", this._onGesture, false);
+                }
+            };
+            element.addEventListener(eventPrefix + "down", this._onPointerDown, false);
+            element.addEventListener(eventPrefix + "up", this._onPointerUp, false);
+            element.addEventListener(eventPrefix + "out", this._onPointerUp, false);
+            element.addEventListener(eventPrefix + "move", this._onPointerMove, false);
+            element.addEventListener("mousemove", this._onMouseMove, false);
+            element.addEventListener("MSPointerDown", this._onGestureStart, false);
+            element.addEventListener("MSGestureChange", this._onGesture, false);
             BABYLON.Tools.RegisterTopRootEvents([
                 { name: "blur", handler: this._onLostFocus }
             ]);
         };
-        ArcRotateCameraPointersInput.prototype.detach = function () {
+        ArcRotateCameraPointersInput.prototype.detachControl = function (element) {
             this._MSGestureHandler = null;
-            this.attachedElement.removeEventListener("contextmenu", this._onContextMenu);
-            this.attachedElement.removeEventListener(eventPrefix + "down", this._onPointerDown);
-            this.attachedElement.removeEventListener(eventPrefix + "up", this._onPointerUp);
-            this.attachedElement.removeEventListener(eventPrefix + "out", this._onPointerUp);
-            this.attachedElement.removeEventListener(eventPrefix + "move", this._onPointerMove);
-            this.attachedElement.removeEventListener("mousemove", this._onMouseMove);
-            this.attachedElement.removeEventListener("MSPointerDown", this._onGestureStart);
-            this.attachedElement.removeEventListener("MSGestureChange", this._onGesture);
+            if (element && this._onPointerDown) {
+                element.removeEventListener("contextmenu", this._onContextMenu);
+                element.removeEventListener(eventPrefix + "down", this._onPointerDown);
+                element.removeEventListener(eventPrefix + "up", this._onPointerUp);
+                element.removeEventListener(eventPrefix + "out", this._onPointerUp);
+                element.removeEventListener(eventPrefix + "move", this._onPointerMove);
+                element.removeEventListener("mousemove", this._onMouseMove);
+                element.removeEventListener("MSPointerDown", this._onGestureStart);
+                element.removeEventListener("MSGestureChange", this._onGesture);
+            }
             BABYLON.Tools.UnregisterTopRootEvents([
                 { name: "blur", handler: this._onLostFocus }
             ]);

+ 2 - 3
src/Cameras/Inputs/babylon.freecamera.input.deviceorientation.js

@@ -19,8 +19,7 @@ var BABYLON;
             this._resetOrientationGamma = this.resetOrientationGamma.bind(this);
             this._orientationChanged = this.orientationChanged.bind(this);
         }
-        FreeCameraDeviceOrientationInput.prototype.attachCamera = function (camera) {
-            this.camera = camera;
+        FreeCameraDeviceOrientationInput.prototype.attachControl = function (element, noPreventDefault) {
             window.addEventListener("resize", this._resetOrientationGamma, false);
             window.addEventListener("deviceorientation", this._orientationChanged);
         };
@@ -37,7 +36,7 @@ var BABYLON;
             this._offsetY = (this._initialOrientationBeta - this._orientationBeta);
             this._offsetX = (this._initialOrientationGamma - this._orientationGamma);
         };
-        FreeCameraDeviceOrientationInput.prototype.detach = function () {
+        FreeCameraDeviceOrientationInput.prototype.detachControl = function (element) {
             window.removeEventListener("resize", this._resetOrientationGamma);
             window.removeEventListener("deviceorientation", this._orientationChanged);
             this._orientationGamma = 0;

+ 8 - 6
src/Cameras/Inputs/babylon.freecamera.input.gamepad.js

@@ -8,16 +8,18 @@ var BABYLON;
 (function (BABYLON) {
     var FreeCameraGamepadInput = (function () {
         function FreeCameraGamepadInput() {
-            var _this = this;
             this.gamepadAngularSensibility = 200;
             this.gamepadMoveSensibility = 40;
-            this._gamepads = new BABYLON.Gamepads(function (gamepad) { _this._onNewGameConnected(gamepad); });
         }
-        FreeCameraGamepadInput.prototype.attachCamera = function (camera) {
-            this.camera = camera;
+        FreeCameraGamepadInput.prototype.attachControl = function (element, noPreventDefault) {
+            var _this = this;
+            this._gamepads = new BABYLON.Gamepads(function (gamepad) { _this._onNewGameConnected(gamepad); });
         };
-        FreeCameraGamepadInput.prototype.detach = function () {
-            this._gamepads.dispose();
+        FreeCameraGamepadInput.prototype.detachControl = function (element) {
+            if (this._gamepads) {
+                this._gamepads.dispose();
+            }
+            this.gamepad = null;
         };
         FreeCameraGamepadInput.prototype.checkInputs = function () {
             if (this.gamepad) {

+ 4 - 2
src/Cameras/Inputs/babylon.freecamera.input.gamepad.ts

@@ -15,8 +15,10 @@ module BABYLON {
             this._gamepads = new Gamepads((gamepad: Gamepad) => { this._onNewGameConnected(gamepad); });
         }
         
-        detachControl(element : HTMLElement){
-            this._gamepads.dispose();
+        detachControl(element: HTMLElement) {
+            if (this._gamepads) {
+                this._gamepads.dispose();
+            }
             this.gamepad = null;
         }
         

+ 4 - 5
src/Cameras/Inputs/babylon.freecamera.input.keyboard.js

@@ -14,9 +14,8 @@ var BABYLON;
             this.keysLeft = [37];
             this.keysRight = [39];
         }
-        FreeCameraKeyboardMoveInput.prototype.attachCamera = function (camera) {
+        FreeCameraKeyboardMoveInput.prototype.attachControl = function (element, noPreventDefault) {
             var _this = this;
-            this.camera = camera;
             if (this._onKeyDown === undefined) {
                 this._onKeyDown = function (evt) {
                     if (_this.keysUp.indexOf(evt.keyCode) !== -1 ||
@@ -27,7 +26,7 @@ var BABYLON;
                         if (index === -1) {
                             _this._keys.push(evt.keyCode);
                         }
-                        if (!camera._noPreventDefault) {
+                        if (!noPreventDefault) {
                             evt.preventDefault();
                         }
                     }
@@ -41,7 +40,7 @@ var BABYLON;
                         if (index >= 0) {
                             _this._keys.splice(index, 1);
                         }
-                        if (!camera._noPreventDefault) {
+                        if (!noPreventDefault) {
                             evt.preventDefault();
                         }
                     }
@@ -53,7 +52,7 @@ var BABYLON;
                 ]);
             }
         };
-        FreeCameraKeyboardMoveInput.prototype.detach = function () {
+        FreeCameraKeyboardMoveInput.prototype.detachControl = function (element) {
             BABYLON.Tools.UnregisterTopRootEvents([
                 { name: "keydown", handler: this._onKeyDown },
                 { name: "keyup", handler: this._onKeyUp },

+ 15 - 26
src/Cameras/Inputs/babylon.freecamera.input.mouse.js

@@ -10,18 +10,13 @@ var BABYLON;
         function FreeCameraMouseInput() {
             this.angularSensibility = 2000.0;
         }
-        FreeCameraMouseInput.prototype.attachCamera = function (camera) {
-            this.camera = camera;
-        };
-        FreeCameraMouseInput.prototype.attachElement = function (element, noPreventDefault) {
+        FreeCameraMouseInput.prototype.attachControl = function (element, noPreventDefault) {
             var _this = this;
-            var previousPosition;
-            this.attachedElement = element;
             if (this._onMouseDown === undefined) {
                 var camera = this.camera;
                 var engine = this.camera.getEngine();
                 this._onMouseDown = function (evt) {
-                    previousPosition = {
+                    _this.previousPosition = {
                         x: evt.clientX,
                         y: evt.clientY
                     };
@@ -30,26 +25,26 @@ var BABYLON;
                     }
                 };
                 this._onMouseUp = function (evt) {
-                    previousPosition = null;
+                    _this.previousPosition = null;
                     if (!noPreventDefault) {
                         evt.preventDefault();
                     }
                 };
                 this._onMouseOut = function (evt) {
-                    previousPosition = null;
+                    _this.previousPosition = null;
                     if (!noPreventDefault) {
                         evt.preventDefault();
                     }
                 };
                 this._onMouseMove = function (evt) {
-                    if (!previousPosition && !engine.isPointerLock) {
+                    if (!_this.previousPosition && !engine.isPointerLock) {
                         return;
                     }
                     var offsetX;
                     var offsetY;
                     if (!engine.isPointerLock) {
-                        offsetX = evt.clientX - previousPosition.x;
-                        offsetY = evt.clientY - previousPosition.y;
+                        offsetX = evt.clientX - _this.previousPosition.x;
+                        offsetY = evt.clientY - _this.previousPosition.y;
                     }
                     else {
                         offsetX = evt.movementX || evt.mozMovementX || evt.webkitMovementX || evt.msMovementX || 0;
@@ -57,7 +52,7 @@ var BABYLON;
                     }
                     camera.cameraRotation.y += offsetX / _this.angularSensibility;
                     camera.cameraRotation.x += offsetY / _this.angularSensibility;
-                    previousPosition = {
+                    _this.previousPosition = {
                         x: evt.clientX,
                         y: evt.clientY
                     };
@@ -71,19 +66,13 @@ var BABYLON;
             element.addEventListener("mouseout", this._onMouseOut, false);
             element.addEventListener("mousemove", this._onMouseMove, false);
         };
-        FreeCameraMouseInput.prototype.detachElement = function (element) {
-            if (this.attachedElement !== element) {
-                return;
-            }
-            element.removeEventListener("mousedown", this._onMouseDown);
-            element.removeEventListener("mouseup", this._onMouseUp);
-            element.removeEventListener("mouseout", this._onMouseOut);
-            element.removeEventListener("mousemove", this._onMouseMove);
-            this.attachedElement = null;
-        };
-        FreeCameraMouseInput.prototype.detach = function () {
-            if (this.attachedElement) {
-                this.detachElement(this.attachedElement);
+        FreeCameraMouseInput.prototype.detachControl = function (element) {
+            if (this._onMouseDown && element) {
+                this.previousPosition = null;
+                element.removeEventListener("mousedown", this._onMouseDown);
+                element.removeEventListener("mouseup", this._onMouseUp);
+                element.removeEventListener("mouseout", this._onMouseOut);
+                element.removeEventListener("mousemove", this._onMouseMove);
             }
         };
         FreeCameraMouseInput.prototype.getTypeName = function () {

+ 12 - 12
src/Cameras/Inputs/babylon.freecamera.input.mouse.ts

@@ -9,16 +9,15 @@ module BABYLON {
         private _onMouseUp: (e: MouseEvent) => any;
         private _onMouseOut: (e: MouseEvent) => any;
         private _onMouseMove: (e: MouseEvent) => any;
-        
-        attachControl(element: HTMLElement, noPreventDefault?: boolean){     
-            var previousPosition;
-                
+        private previousPosition: { x: number, y: number };
+
+        attachControl(element: HTMLElement, noPreventDefault?: boolean){                     
             if (this._onMouseDown === undefined) {
                 var camera = this.camera;
                 var engine = this.camera.getEngine();
                 
                 this._onMouseDown = evt => {
-                    previousPosition = {
+                    this.previousPosition = {
                         x: evt.clientX,
                         y: evt.clientY
                     };
@@ -29,14 +28,14 @@ module BABYLON {
                 };
 
                 this._onMouseUp = evt => {
-                    previousPosition = null;
+                    this.previousPosition = null;
                     if (!noPreventDefault) {
                         evt.preventDefault();
                     }
                 };
 
                 this._onMouseOut = evt => {
-                    previousPosition = null;
+                    this.previousPosition = null;
                     
                     if (!noPreventDefault) {
                         evt.preventDefault();
@@ -44,7 +43,7 @@ module BABYLON {
                 };
 
                 this._onMouseMove = evt => {
-                    if (!previousPosition && !engine.isPointerLock) {
+                    if (!this.previousPosition && !engine.isPointerLock) {
                         return;
                     }
 
@@ -52,8 +51,8 @@ module BABYLON {
                     var offsetY;
 
                     if (!engine.isPointerLock) {
-                        offsetX = evt.clientX - previousPosition.x;
-                        offsetY = evt.clientY - previousPosition.y;
+                        offsetX = evt.clientX - this.previousPosition.x;
+                        offsetY = evt.clientY - this.previousPosition.y;
                     } else {
                         offsetX = evt.movementX || evt.mozMovementX || evt.webkitMovementX || evt.msMovementX || 0;
                         offsetY = evt.movementY || evt.mozMovementY || evt.webkitMovementY || evt.msMovementY || 0;
@@ -62,7 +61,7 @@ module BABYLON {
                     camera.cameraRotation.y += offsetX / this.angularSensibility;
                     camera.cameraRotation.x += offsetY / this.angularSensibility;
 
-                    previousPosition = {
+                    this.previousPosition = {
                         x: evt.clientX,
                         y: evt.clientY
                     };
@@ -81,7 +80,8 @@ module BABYLON {
         }
         
         detachControl(element : HTMLElement){   
-            if (this._onMouseDown && element){
+            if (this._onMouseDown && element) {
+                this.previousPosition = null;
                 element.removeEventListener("mousedown", this._onMouseDown);
                 element.removeEventListener("mouseup", this._onMouseUp);
                 element.removeEventListener("mouseout", this._onMouseOut);

+ 2 - 18
src/Cameras/Inputs/babylon.freecamera.input.touch.js

@@ -15,16 +15,9 @@ var BABYLON;
             this.touchAngularSensibility = 200000.0;
             this.touchMoveSensibility = 250.0;
         }
-        FreeCameraTouchInput.prototype.attachCamera = function (camera) {
-            this.camera = camera;
-        };
-        FreeCameraTouchInput.prototype.attachElement = function (element, noPreventDefault) {
+        FreeCameraTouchInput.prototype.attachControl = function (element, noPreventDefault) {
             var _this = this;
             var previousPosition;
-            if (this._attachedElement) {
-                return;
-            }
-            this._attachedElement = element;
             if (this._onPointerDown === undefined) {
                 this._onLostFocus = function (evt) {
                     _this._offsetX = null;
@@ -89,16 +82,12 @@ var BABYLON;
             element.addEventListener("pointerout", this._onPointerUp);
             element.addEventListener("pointermove", this._onPointerMove);
         };
-        FreeCameraTouchInput.prototype.detachElement = function (element) {
-            if (this._attachedElement !== element) {
-                return;
-            }
+        FreeCameraTouchInput.prototype.detachControl = function (element) {
             element.removeEventListener("blur", this._onLostFocus);
             element.removeEventListener("pointerdown", this._onPointerDown);
             element.removeEventListener("pointerup", this._onPointerUp);
             element.removeEventListener("pointerout", this._onPointerUp);
             element.removeEventListener("pointermove", this._onPointerMove);
-            this._attachedElement = null;
         };
         FreeCameraTouchInput.prototype.checkInputs = function () {
             if (this._offsetX) {
@@ -115,11 +104,6 @@ var BABYLON;
                 }
             }
         };
-        FreeCameraTouchInput.prototype.detach = function () {
-            if (this._attachedElement) {
-                this.detachElement(this._attachedElement);
-            }
-        };
         FreeCameraTouchInput.prototype.getTypeName = function () {
             return "FreeCameraTouchInput";
         };

+ 16 - 14
src/Cameras/Inputs/babylon.freecamera.input.virtualjoystick.js

@@ -10,21 +10,22 @@ var BABYLON;
             return this._rightjoystick;
         };
         FreeCameraVirtualJoystickInput.prototype.checkInputs = function () {
-            var camera = this.camera;
-            var speed = camera._computeLocalCameraSpeed() * 50;
-            var cameraTransform = BABYLON.Matrix.RotationYawPitchRoll(camera.rotation.y, camera.rotation.x, 0);
-            var deltaTransform = BABYLON.Vector3.TransformCoordinates(new BABYLON.Vector3(this._leftjoystick.deltaPosition.x * speed, this._leftjoystick.deltaPosition.y * speed, this._leftjoystick.deltaPosition.z * speed), cameraTransform);
-            camera.cameraDirection = camera.cameraDirection.add(deltaTransform);
-            camera.cameraRotation = camera.cameraRotation.addVector3(this._rightjoystick.deltaPosition);
-            if (!this._leftjoystick.pressed) {
-                this._leftjoystick.deltaPosition = this._leftjoystick.deltaPosition.scale(0.9);
-            }
-            if (!this._rightjoystick.pressed) {
-                this._rightjoystick.deltaPosition = this._rightjoystick.deltaPosition.scale(0.9);
+            if (this._leftjoystick) {
+                var camera = this.camera;
+                var speed = camera._computeLocalCameraSpeed() * 50;
+                var cameraTransform = BABYLON.Matrix.RotationYawPitchRoll(camera.rotation.y, camera.rotation.x, 0);
+                var deltaTransform = BABYLON.Vector3.TransformCoordinates(new BABYLON.Vector3(this._leftjoystick.deltaPosition.x * speed, this._leftjoystick.deltaPosition.y * speed, this._leftjoystick.deltaPosition.z * speed), cameraTransform);
+                camera.cameraDirection = camera.cameraDirection.add(deltaTransform);
+                camera.cameraRotation = camera.cameraRotation.addVector3(this._rightjoystick.deltaPosition);
+                if (!this._leftjoystick.pressed) {
+                    this._leftjoystick.deltaPosition = this._leftjoystick.deltaPosition.scale(0.9);
+                }
+                if (!this._rightjoystick.pressed) {
+                    this._rightjoystick.deltaPosition = this._rightjoystick.deltaPosition.scale(0.9);
+                }
             }
         };
-        FreeCameraVirtualJoystickInput.prototype.attachCamera = function (camera) {
-            this.camera = camera;
+        FreeCameraVirtualJoystickInput.prototype.attachControl = function (element, noPreventDefault) {
             this._leftjoystick = new BABYLON.VirtualJoystick(true);
             this._leftjoystick.setAxisForUpDown(BABYLON.JoystickAxis.Z);
             this._leftjoystick.setAxisForLeftRight(BABYLON.JoystickAxis.X);
@@ -36,8 +37,9 @@ var BABYLON;
             this._rightjoystick.setJoystickSensibility(0.05);
             this._rightjoystick.setJoystickColor("yellow");
         };
-        FreeCameraVirtualJoystickInput.prototype.detach = function () {
+        FreeCameraVirtualJoystickInput.prototype.detachControl = function (element) {
             this._leftjoystick.releaseCanvas();
+            this._rightjoystick.releaseCanvas();
         };
         FreeCameraVirtualJoystickInput.prototype.getTypeName = function () {
             return "FreeCameraVirtualJoystickInput";

+ 22 - 12
src/Cameras/Inputs/babylon.freecamera.input.vrdeviceorientation.js

@@ -2,13 +2,16 @@ var BABYLON;
 (function (BABYLON) {
     var FreeCameraVRDeviceOrientationInput = (function () {
         function FreeCameraVRDeviceOrientationInput() {
+            this.alphaCorrection = 1;
+            this.betaCorrection = 1;
+            this.gammaCorrection = 1;
             this._alpha = 0;
             this._beta = 0;
             this._gamma = 0;
+            this._dirty = false;
             this._deviceOrientationHandler = this._onOrientationEvent.bind(this);
         }
-        FreeCameraVRDeviceOrientationInput.prototype.attachCamera = function (camera) {
-            this.camera = camera;
+        FreeCameraVRDeviceOrientationInput.prototype.attachControl = function (element, noPreventDefault) {
             window.addEventListener("deviceorientation", this._deviceOrientationHandler);
         };
         FreeCameraVRDeviceOrientationInput.prototype._onOrientationEvent = function (evt) {
@@ -16,18 +19,25 @@ var BABYLON;
             this._alpha = +evt.alpha | 0;
             this._beta = +evt.beta | 0;
             this._gamma = +evt.gamma | 0;
-            if (this._gamma < 0) {
-                this._gamma = 90 + this._gamma;
-            }
-            else {
-                // Incline it in the correct angle.
-                this._gamma = 270 - this._gamma;
+            this._dirty = true;
+        };
+        FreeCameraVRDeviceOrientationInput.prototype.checkInputs = function () {
+            if (this._dirty) {
+                this._dirty = false;
+                var rotationX = this._gamma;
+                if (rotationX < 0) {
+                    rotationX = 90 + rotationX;
+                }
+                else {
+                    // Incline it in the correct angle.
+                    rotationX = 270 - rotationX;
+                }
+                this.camera.rotation.x = this.gammaCorrection * rotationX / 180.0 * Math.PI;
+                this.camera.rotation.y = this.alphaCorrection * -this._alpha / 180.0 * Math.PI;
+                this.camera.rotation.z = this.betaCorrection * this._beta / 180.0 * Math.PI;
             }
-            camera.rotation.x = this._gamma / 180.0 * Math.PI;
-            camera.rotation.y = -this._alpha / 180.0 * Math.PI;
-            camera.rotation.z = this._beta / 180.0 * Math.PI;
         };
-        FreeCameraVRDeviceOrientationInput.prototype.detach = function () {
+        FreeCameraVRDeviceOrientationInput.prototype.detachControl = function (element) {
             window.removeEventListener("deviceorientation", this._deviceOrientationHandler);
         };
         FreeCameraVRDeviceOrientationInput.prototype.getTypeName = function () {

+ 1 - 1
src/Cameras/babylon.arcRotateCamera.js

@@ -262,7 +262,7 @@ var BABYLON;
                 return;
             }
             this._attachedElement = element;
-            this._noPreventDefault = noPreventDefault;
+            this._noPreventDefault = BABYLON.Camera.ForceAttachControlToAlwaysPreventDefault ? false : noPreventDefault;
             this._useCtrlForPanning = useCtrlForPanning;
             this.inputs.attachElement(element, noPreventDefault);
             this._reset = function () {

+ 0 - 6
src/Cameras/babylon.arcRotateCameraInputsManager.js

@@ -10,12 +10,6 @@ var BABYLON;
         function ArcRotateCameraInputsManager(camera) {
             _super.call(this, camera);
         }
-        ArcRotateCameraInputsManager.prototype.add = function (input) {
-            _super.prototype.add.call(this, input);
-            if (this.camera._attachedElement && input.attachElement) {
-                input.attachElement(this.camera._attachedElement, this.camera._noPreventDefault);
-            }
-        };
         ArcRotateCameraInputsManager.prototype.addMouseWheel = function () {
             this.add(new BABYLON.ArcRotateCameraMouseWheelInput());
             return this;

+ 10 - 10
src/Cameras/babylon.arcRotateCameraInputsManager.ts

@@ -1,25 +1,25 @@
 module BABYLON {
     export class ArcRotateCameraInputsManager extends CameraInputsManager<ArcRotateCamera> {
-        constructor(camera : ArcRotateCamera){
-            super(camera);    
+        constructor(camera: ArcRotateCamera) {
+            super(camera);
         }
-        
-        public addMouseWheel(){
+
+        public addMouseWheel(): ArcRotateCameraInputsManager {
             this.add(new ArcRotateCameraMouseWheelInput());
             return this;
         }
-        
-        public addPointers(){
+
+        public addPointers(): ArcRotateCameraInputsManager {
             this.add(new ArcRotateCameraPointersInput());
             return this;
         }
-        
-        public addKeyboard(){
+
+        public addKeyboard(): ArcRotateCameraInputsManager {
             this.add(new ArcRotateCameraKeyboardMoveInput());
             return this;
         }
-        
-        public addGamepad(){
+
+        public addGamepad(): ArcRotateCameraInputsManager {
             this.add(new ArcRotateCameraGamepadInput());
             return this;
         }

+ 1 - 0
src/Cameras/babylon.camera.js

@@ -368,6 +368,7 @@ var BABYLON;
             for (var i = 0; i < this._postProcessesTakenIndices.length; ++i) {
                 this._postProcesses[this._postProcessesTakenIndices[i]].dispose(this);
             }
+            _super.prototype.dispose.call(this);
         };
         // ---- Camera rigs section ----
         Camera.prototype.setCameraRigMode = function (mode, rigParams) {

+ 2 - 0
src/Cameras/babylon.camera.ts

@@ -455,6 +455,8 @@
             for (var i = 0; i < this._postProcessesTakenIndices.length; ++i) {
                 this._postProcesses[this._postProcessesTakenIndices[i]].dispose(this);
             }
+
+            super.dispose();
         }
         
         // ---- Camera rigs section ----

+ 14 - 11
src/Cameras/babylon.cameraInputsManager.js

@@ -14,18 +14,21 @@ var BABYLON;
                 return;
             }
             this.attached[type] = input;
-            input.attachCamera(this.camera);
+            input.camera = this.camera;
             //for checkInputs, we are dynamically creating a function
             //the goal is to avoid the performance penalty of looping for inputs in the render loop
             if (input.checkInputs) {
                 this.checkInputs = this._addCheckInputs(input.checkInputs.bind(input));
             }
+            if (this.attachedElement) {
+                input.attachControl(this.attachedElement);
+            }
         };
         CameraInputsManager.prototype.remove = function (inputToRemove) {
             for (var cam in this.attached) {
                 var input = this.attached[cam];
-                if (input == inputToRemove) {
-                    input.detach();
+                if (input === inputToRemove) {
+                    input.detachControl(this.attachedElement);
                     delete this.attached[cam];
                 }
             }
@@ -33,8 +36,8 @@ var BABYLON;
         CameraInputsManager.prototype.removeByType = function (inputType) {
             for (var cam in this.attached) {
                 var input = this.attached[cam];
-                if (input.getTypeName() == inputType) {
-                    input.detach();
+                if (input.getTypeName() === inputType) {
+                    input.detachControl(this.attachedElement);
                     delete this.attached[cam];
                 }
             }
@@ -47,17 +50,16 @@ var BABYLON;
             };
         };
         CameraInputsManager.prototype.attachElement = function (element, noPreventDefault) {
+            this.attachedElement = element;
             for (var cam in this.attached) {
                 var input = this.attached[cam];
-                if (input.attachElement)
-                    this.attached[cam].attachElement(element, noPreventDefault);
+                this.attached[cam].attachControl(element, noPreventDefault);
             }
         };
         CameraInputsManager.prototype.detachElement = function (element) {
             for (var cam in this.attached) {
                 var input = this.attached[cam];
-                if (input.detachElement)
-                    this.attached[cam].detachElement(element);
+                this.attached[cam].detachControl(element);
             }
         };
         CameraInputsManager.prototype.rebuildInputCheck = function (element) {
@@ -70,10 +72,11 @@ var BABYLON;
             }
         };
         CameraInputsManager.prototype.clear = function () {
-            for (var cam in this.attached) {
-                this.attached[cam].detach();
+            if (this.attachedElement) {
+                this.detachElement(this.attachedElement);
             }
             this.attached = {};
+            this.attachedElement = null;
             this.checkInputs = function () { };
         };
         CameraInputsManager.prototype.serialize = function (serializedCamera) {

+ 5 - 3
src/Cameras/babylon.cameraInputsManager.ts

@@ -53,7 +53,7 @@ module BABYLON {
         public remove(inputToRemove: ICameraInput<TCamera>) {
             for (var cam in this.attached) {
                 var input = this.attached[cam];
-                if (input == inputToRemove) {
+                if (input === inputToRemove) {
                     input.detachControl(this.attachedElement);
                     delete this.attached[cam];
                     this.rebuildInputCheck();
@@ -64,7 +64,7 @@ module BABYLON {
         public removeByType(inputType: string) {
             for (var cam in this.attached) {
                 var input = this.attached[cam];
-                if (input.getTypeName() == inputType) {
+                if (input.getTypeName() === inputType) {
                     input.detachControl(this.attachedElement);
                     delete this.attached[cam];
                     this.rebuildInputCheck();
@@ -123,7 +123,9 @@ module BABYLON {
         }
 
         public clear() {
-            this.detachElement(this.attachedElement);
+            if (this.attachedElement) {
+                this.detachElement(this.attachedElement);
+            }
             this.attached = {};
             this.attachedElement = null;
             this.checkInputs = () => { };

+ 0 - 6
src/Cameras/babylon.freeCameraInputsManager.js

@@ -10,12 +10,6 @@ var BABYLON;
         function FreeCameraInputsManager(camera) {
             _super.call(this, camera);
         }
-        FreeCameraInputsManager.prototype.add = function (input) {
-            _super.prototype.add.call(this, input);
-            if (this.camera._attachedElement && input.attachElement) {
-                input.attachElement(this.camera._attachedElement, this.camera._noPreventDefault);
-            }
-        };
         FreeCameraInputsManager.prototype.addKeyboard = function () {
             this.add(new BABYLON.FreeCameraKeyboardMoveInput());
             return this;

+ 17 - 17
src/Cameras/babylon.freeCameraInputsManager.ts

@@ -1,40 +1,40 @@
 module BABYLON {
     export class FreeCameraInputsManager extends CameraInputsManager<FreeCamera> {
-        constructor(camera : FreeCamera){
-            super(camera);    
-        }        
-        
-        addKeyboard(){
+        constructor(camera: FreeCamera) {
+            super(camera);
+        }
+
+        addKeyboard(): FreeCameraInputsManager {
             this.add(new FreeCameraKeyboardMoveInput());
             return this;
         }
-        
-        addMouse(){
+
+        addMouse(): FreeCameraInputsManager {
             this.add(new FreeCameraMouseInput());
             return this;
         }
-        
-        addGamepad(){
+
+        addGamepad(): FreeCameraInputsManager {
             this.add(new FreeCameraGamepadInput());
             return this;
         }
-        
-        addDeviceOrientation(){
+
+        addDeviceOrientation(): FreeCameraInputsManager {
             this.add(new FreeCameraDeviceOrientationInput());
             return this;
         }
-        
-        addVRDeviceOrientation(){
+
+        addVRDeviceOrientation(): FreeCameraInputsManager {
             this.add(new FreeCameraVRDeviceOrientationInput());
             return this;
         }
-        
-        addTouch(){
+
+        addTouch(): FreeCameraInputsManager {
             this.add(new FreeCameraTouchInput());
             return this;
         }
-        
-        addVirtualJoystick(){
+
+        addVirtualJoystick(): FreeCameraInputsManager {
             this.add(new FreeCameraVirtualJoystickInput());
             return this;
         }

+ 1 - 0
src/Lights/babylon.light.js

@@ -95,6 +95,7 @@ var BABYLON;
             this.getScene().stopAnimation(this);
             // Remove from scene
             this.getScene().removeLight(this);
+            _super.prototype.dispose.call(this);
         };
         Light.prototype.getTypeID = function () {
             return 0;

+ 2 - 0
src/Lights/babylon.light.ts

@@ -141,6 +141,8 @@
 
             // Remove from scene
             this.getScene().removeLight(this);
+
+            super.dispose();
         }
 
         public getTypeID(): number {

+ 27 - 10
src/Materials/Textures/babylon.videoTexture.js

@@ -7,17 +7,33 @@ var BABYLON;
 (function (BABYLON) {
     var VideoTexture = (function (_super) {
         __extends(VideoTexture, _super);
-        function VideoTexture(name, urls, scene, generateMipMaps, invertY, samplingMode) {
+        /**
+        * Creates a video texture.
+        * Sample : https://doc.babylonjs.com/tutorials/01._Advanced_Texturing
+        * @param urlsOrVideo can be used to provide an array of urls or an already setup HTML video element.
+        * @param scene is obviously the current scene.
+        * @param generateMipMaps can be used to turn on mipmaps (Can be expensive for videoTextures because they are often updated).
+        * @param invertY is false by default but can be used to invert video on Y axis
+        * @param samplingMode controls the sampling method and is set to TRILINEAR_SAMPLINGMODE by default
+        */
+        function VideoTexture(name, urlsOrVideo, scene, generateMipMaps, invertY, samplingMode) {
             var _this = this;
             if (generateMipMaps === void 0) { generateMipMaps = false; }
             if (invertY === void 0) { invertY = false; }
             if (samplingMode === void 0) { samplingMode = BABYLON.Texture.TRILINEAR_SAMPLINGMODE; }
             _super.call(this, null, scene, !generateMipMaps, invertY);
             this._autoLaunch = true;
+            var urls;
             this.name = name;
-            this.video = document.createElement("video");
-            this.video.autoplay = false;
-            this.video.loop = true;
+            if (urlsOrVideo instanceof HTMLVideoElement) {
+                this.video = urlsOrVideo;
+            }
+            else {
+                urls = urlsOrVideo;
+                this.video = document.createElement("video");
+                this.video.autoplay = false;
+                this.video.loop = true;
+            }
             this.video.addEventListener("canplaythrough", function () {
                 if (BABYLON.Tools.IsExponentOfTwo(_this.video.videoWidth) && BABYLON.Tools.IsExponentOfTwo(_this.video.videoHeight)) {
                     _this.wrapU = BABYLON.Texture.WRAP_ADDRESSMODE;
@@ -31,12 +47,13 @@ var BABYLON;
                 _this._texture = scene.getEngine().createDynamicTexture(_this.video.videoWidth, _this.video.videoHeight, generateMipMaps, samplingMode, false);
                 _this._texture.isReady = true;
             });
-            urls.forEach(function (url) {
-                //Backwards-compatibility for typescript 1. from 1.3 it should say "SOURCE". see here - https://github.com/Microsoft/TypeScript/issues/1850
-                var source = document.createElement("source");
-                source.src = url;
-                _this.video.appendChild(source);
-            });
+            if (urls) {
+                urls.forEach(function (url) {
+                    var source = document.createElement("source");
+                    source.src = url;
+                    _this.video.appendChild(source);
+                });
+            }
             this._lastUpdate = BABYLON.Tools.Now;
         }
         VideoTexture.prototype.update = function () {

+ 27 - 10
src/Materials/Textures/babylon.videoTexture.ts

@@ -5,14 +5,30 @@
         private _autoLaunch = true;
         private _lastUpdate: number;
 
-        constructor(name: string, urls: string[], scene: Scene, generateMipMaps = false, invertY = false, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE) {
+        /**
+        * Creates a video texture.  
+        * Sample : https://doc.babylonjs.com/tutorials/01._Advanced_Texturing  
+        * @param urlsOrVideo can be used to provide an array of urls or an already setup HTML video element.
+        * @param scene is obviously the current scene.   
+        * @param generateMipMaps can be used to turn on mipmaps (Can be expensive for videoTextures because they are often updated).
+        * @param invertY is false by default but can be used to invert video on Y axis
+        * @param samplingMode controls the sampling method and is set to TRILINEAR_SAMPLINGMODE by default
+        */
+        constructor(name: string, urlsOrVideo: string[] | HTMLVideoElement, scene: Scene, generateMipMaps = false, invertY = false, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE) {
             super(null, scene, !generateMipMaps, invertY);
 
+            var urls: string[];
             this.name = name;
 
-            this.video = document.createElement("video");
-            this.video.autoplay = false;
-            this.video.loop = true;
+            if (urlsOrVideo instanceof HTMLVideoElement) {
+                this.video = <any>urlsOrVideo;
+            } else {
+                urls = <any>urlsOrVideo;
+
+                this.video = document.createElement("video");
+                this.video.autoplay = false;
+                this.video.loop = true;
+            }
 
             this.video.addEventListener("canplaythrough", () => {
                 if (Tools.IsExponentOfTwo(this.video.videoWidth) && Tools.IsExponentOfTwo(this.video.videoHeight)) {
@@ -28,12 +44,13 @@
                 this._texture.isReady = true;
             });
 
-            urls.forEach(url => {
-                //Backwards-compatibility for typescript 1. from 1.3 it should say "SOURCE". see here - https://github.com/Microsoft/TypeScript/issues/1850
-                var source = <HTMLSourceElement> document.createElement("source");
-                source.src = url;
-                this.video.appendChild(source);
-            });
+            if (urls) {
+                urls.forEach(url => {
+                    var source = document.createElement("source");
+                    source.src = url;
+                    this.video.appendChild(source);
+                });
+            }
 
             this._lastUpdate = Tools.Now;
         }

+ 8 - 10
src/Mesh/babylon.abstractMesh.js

@@ -946,22 +946,20 @@ var BABYLON;
                     }
                 }
                 // Children
-                var objects = this.getScene().meshes.slice(0);
+                var objects = this.getDescendants(true);
                 for (index = 0; index < objects.length; index++) {
-                    if (objects[index].parent === this) {
-                        objects[index].dispose();
-                    }
+                    objects[index].dispose();
                 }
             }
             else {
-                for (index = 0; index < this.getScene().meshes.length; index++) {
-                    var obj = this.getScene().meshes[index];
-                    if (obj.parent === this) {
-                        obj.parent = null;
-                        obj.computeWorldMatrix(true);
-                    }
+                var childMeshes = this.getChildMeshes(true);
+                for (index = 0; childMeshes.length; index++) {
+                    var child = childMeshes[index];
+                    child.parent = null;
+                    child.computeWorldMatrix(true);
                 }
             }
+            _super.prototype.dispose.call(this);
             this._onAfterWorldMatrixUpdate = [];
             this._isDisposed = true;
             // Callback

+ 9 - 10
src/Mesh/babylon.abstractMesh.ts

@@ -1112,22 +1112,21 @@
                 }
 
                 // Children
-                var objects = this.getScene().meshes.slice(0);
+                var objects = this.getDescendants(true);
                 for (index = 0; index < objects.length; index++) {
-                    if (objects[index].parent === this) {
-                        objects[index].dispose();
-                    }
+                    objects[index].dispose();
                 }
             } else {
-                for (index = 0; index < this.getScene().meshes.length; index++) {
-                    var obj = this.getScene().meshes[index];
-                    if (obj.parent === this) {
-                        obj.parent = null;
-                        obj.computeWorldMatrix(true);
-                    }
+                var childMeshes = this.getChildMeshes(true);
+                for (index = 0; childMeshes.length; index++) {
+                    var child = childMeshes[index];
+                    child.parent = null;
+                    child.computeWorldMatrix(true);
                 }
             }
 
+            super.dispose();
+
             this._onAfterWorldMatrixUpdate = [];
 
             this._isDisposed = true;

+ 186 - 45
src/Mesh/babylon.meshBuilder.js

@@ -6,13 +6,13 @@ var BABYLON;
         /**
          * Creates a box mesh.
          * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#box
-         * The parameter "size" sets the size (float) of each box side (default 1).
-         * You can set some different box dimensions by using the parameters "width", "height" and "depth" (all by default have the same value than "size").
-         * You can set different colors and different images to each box side by using the parameters "faceColors" (an array of 6 Color3 elements) and "faceUV" (an array of 6 Vector4 elements).
+         * The parameter `size` sets the size (float) of each box side (default 1).
+         * You can set some different box dimensions by using the parameters `width`, `height` and `depth` (all by default have the same value than `size`).
+         * You can set different colors and different images to each box side by using the parameters `faceColors` (an array of 6 `Color3` elements) and `faceUV` (an array of 6 `Vector4` elements).
          * Please read this tutorial : http://doc.babylonjs.com/tutorials/CreateBox_Per_Face_Textures_And_Colors
          * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
          * 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.
+         * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
         MeshBuilder.CreateBox = function (name, options, scene) {
             var box = new BABYLON.Mesh(name, scene);
@@ -23,14 +23,14 @@ var BABYLON;
         /**
          * Creates a sphere mesh.
          * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#sphere
-         * The parameter "diameter" sets the diameter size (float) of the sphere (default 1).
-         * You can set some different sphere dimensions, for instance to build an ellipsoid, by using the parameters "diameterX", "diameterY" and "diameterZ" (all by default have the same value than "diameter").
-         * The parameter "segments" sets the sphere number of horizontal stripes (positive integer, default 32).
-         * You can create an unclosed sphere with the parameter "arc" (positive float, default 1), valued between 0 and 1, what is the ratio of the circumference (latitude) : 2 x PI x ratio
-         * You can create an unclosed sphere on its height with the parameter "slice" (positive float, default1), valued between 0 and 1, what is the height ratio (longitude).
+         * The parameter `diameter` sets the diameter size (float) of the sphere (default 1).
+         * You can set some different sphere dimensions, for instance to build an ellipsoid, by using the parameters `diameterX`, `diameterY` and `diameterZ` (all by default have the same value than `diameter`).
+         * The parameter `segments` sets the sphere number of horizontal stripes (positive integer, default 32).
+         * You can create an unclosed sphere with the parameter `arc` (positive float, default 1), valued between 0 and 1, what is the ratio of the circumference (latitude) : 2 x PI x ratio
+         * You can create an unclosed sphere on its height with the parameter `slice` (positive float, default1), valued between 0 and 1, what is the height ratio (longitude).
          * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
          * 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.
+         * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
         MeshBuilder.CreateSphere = function (name, options, scene) {
             var sphere = new BABYLON.Mesh(name, scene);
@@ -41,12 +41,12 @@ var BABYLON;
         /**
          * Creates a plane polygonal mesh.  By default, this is a disc.
          * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#disc
-         * The parameter "radius" sets the radius size (float) of the polygon (default 0.5).
-         * The parameter "tessellation" sets the number of polygon sides (positive integer, default 64). So a tessellation valued to 3 will build a triangle, to 4 a square, etc.
-         * You can create an unclosed polygon with the parameter "arc" (positive float, default 1), valued between 0 and 1, what is the ratio of the circumference : 2 x PI x ratio
+         * The parameter `radius` sets the radius size (float) of the polygon (default 0.5).
+         * The parameter `tessellation` sets the number of polygon sides (positive integer, default 64). So a tessellation valued to 3 will build a triangle, to 4 a square, etc.
+         * You can create an unclosed polygon with the parameter `arc` (positive float, default 1), valued between 0 and 1, what is the ratio of the circumference : 2 x PI x ratio
          * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
          * 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.
+         * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
         MeshBuilder.CreateDisc = function (name, options, scene) {
             var disc = new BABYLON.Mesh(name, scene);
@@ -57,13 +57,13 @@ var BABYLON;
         /**
          * Creates a sphere based upon an icosahedron with 20 triangular faces which can be subdivided.
          * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#icosphere
-         * The parameter "radius" sets the radius size (float) of the icosphere (default 1).
-         * You can set some different icosphere dimensions, for instance to build an ellipsoid, by using the parameters "radiusX", "radiusY" and "radiusZ" (all by default have the same value than "radius").
-         * The parameter "subdivisions" sets the number of subdivisions (postive integer, default 4). The more subdivisions, the more faces on the icosphere whatever its size.
-         * The parameter "flat" (boolean, default true) gives each side its own normals. Set it to false to get a smooth continuous light reflection on the surface.
+         * The parameter `radius` sets the radius size (float) of the icosphere (default 1).
+         * You can set some different icosphere dimensions, for instance to build an ellipsoid, by using the parameters `radiusX`, `radiusY` and `radiusZ` (all by default have the same value than `radius`).
+         * The parameter `subdivisions` sets the number of subdivisions (postive integer, default 4). The more subdivisions, the more faces on the icosphere whatever its size.
+         * The parameter `flat` (boolean, default true) gives each side its own normals. Set it to false to get a smooth continuous light reflection on the surface.
          * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
          * 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.
+         * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
         MeshBuilder.CreateIcoSphere = function (name, options, scene) {
             var sphere = new BABYLON.Mesh(name, scene);
@@ -77,13 +77,13 @@ var BABYLON;
          * The ribbon 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.
          *
          * Please read this full tutorial to understand how to design a ribbon : http://doc.babylonjs.com/tutorials/Ribbon_Tutorial
-         * The parameter "pathArray" is a required array of paths, what are each an array of successive Vector3. The pathArray parameter depicts the ribbon geometry.
-         * The parameter "closeArray" (boolean, default false) creates a seam between the first and the last paths of the path array.
-         * The parameter "closePath" (boolean, default false) creates a seam between the first and the last points of each path of the path array.
-         * The parameter "instance" is an instance of an existing Ribbon object to be updated with the passed "pathArray" parameter : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#ribbon
+         * The parameter `pathArray` is a required array of paths, what are each an array of successive Vector3. The pathArray parameter depicts the ribbon geometry.
+         * The parameter `closeArray` (boolean, default false) creates a seam between the first and the last paths of the path array.
+         * The parameter `closePath` (boolean, default false) creates a seam between the first and the last points of each path of the path array.
+         * The optional parameter èinstance` is an instance of an existing Ribbon object to be updated with the passed `pathArray` parameter : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#ribbon
          * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
          * 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.
+         * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
         MeshBuilder.CreateRibbon = function (name, options, scene) {
             var pathArray = options.pathArray;
@@ -168,25 +168,25 @@ var BABYLON;
         /**
          * Creates a cylinder or a cone mesh.
          * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#cylinder-or-cone
-         * The parameter "height" sets the height size (float) of the cylinder/cone (float, default 2).
-         * The parameter "diameter" sets the diameter of the top and bottom cap at once (float, default 1).
-         * The parameters "diameterTop" and "diameterBottom" overwrite the parameter "diameter" and set respectively the top cap and bottom cap diameter (floats, default 1). The parameter "diameterBottom" can't be zero.
-         * The parameter "tessellation" sets the number of cylinder sides (positive integer, default 24). Set it to 3 to get a prism for instance.
-         * The parameter "subdivisions" sets the number of rings along the cylinder height (positive integer, default 1).
-         * The parameter "hasRings" (boolean, default false) makes the subdivisions independent from each other, so they become different faces.
-         * The parameter "enclose"  (boolean, default false) adds two extra faces per subdivision to a sliced cylinder to close it around its height axis.
-         * The parameter "arc" (float, default 1) is the ratio (max 1) to apply to the circumference to slice the cylinder.
-         * You can set different colors and different images to each box side by using the parameters "faceColors" (an array of n Color3 elements) and "faceUV" (an array of n Vector4 elements).
+         * The parameter `height` sets the height size (float) of the cylinder/cone (float, default 2).
+         * The parameter `diameter` sets the diameter of the top and bottom cap at once (float, default 1).
+         * The parameters `diameterTop` and `diameterBottom` overwrite the parameter `diameter` and set respectively the top cap and bottom cap diameter (floats, default 1). The parameter "diameterBottom" can't be zero.
+         * The parameter `tessellation` sets the number of cylinder sides (positive integer, default 24). Set it to 3 to get a prism for instance.
+         * The parameter `subdivisions` sets the number of rings along the cylinder height (positive integer, default 1).
+         * The parameter `hasRings` (boolean, default false) makes the subdivisions independent from each other, so they become different faces.
+         * The parameter `enclose`  (boolean, default false) adds two extra faces per subdivision to a sliced cylinder to close it around its height axis.
+         * The parameter `arc` (float, default 1) is the ratio (max 1) to apply to the circumference to slice the cylinder.
+         * You can set different colors and different images to each box side by using the parameters `faceColors` (an array of n `Color3` elements) and `faceUV` (an array of n `Vector4` elements).
          * The value of n is the number of cylinder faces. If the cylinder has only 1 subdivisions, n equals : top face + cylinder surface + bottom face = 3
          * Now, if the cylinder has 5 independent subdivisions (hasRings = true), n equals : top face + 5 stripe surfaces + bottom face = 2 + 5 = 7
          * Finally, if the cylinder has 5 independent subdivisions and is enclose, n equals : top face + 5 x (stripe surface + 2 closing faces) + bottom face = 2 + 5 * 3 = 17
          * Each array (color or UVs) is always ordered the same way : the first element is the bottom cap, the last element is the top cap. The other elements are each a ring surface.
-         * If enclose is false, a ring surface is one element.
-         * If enclose true, a ring surface is 3 successive elements in the array : the tubular surface, then the two closing faces.
+         * If `enclose` is false, a ring surface is one element.
+         * If `enclose` is true, a ring surface is 3 successive elements in the array : the tubular surface, then the two closing faces.
          * Example how to set colors and textures on a sliced cylinder : http://www.html5gamedevs.com/topic/17945-creating-a-closed-slice-of-a-cylinder/#comment-106379
          * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
          * 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.
+         * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
         MeshBuilder.CreateCylinder = function (name, options, scene) {
             var cylinder = new BABYLON.Mesh(name, scene);
@@ -197,12 +197,12 @@ var BABYLON;
         /**
          * Creates a torus mesh.
          * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#torus
-         * The parameter "diameter" sets the diameter size (float) of the torus (default 1).
-         * The parameter "thickness" sets the diameter size of the tube of the torus (float, default 0.5).
-         * The parameter "tessellation" sets the number of torus sides (postive integer, default 16).
+         * The parameter `diameter` sets the diameter size (float) of the torus (default 1).
+         * The parameter `thickness` sets the diameter size of the tube of the torus (float, default 0.5).
+         * The parameter `tessellation` sets the number of torus sides (postive integer, default 16).
          * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
          * 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.
+         * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
         MeshBuilder.CreateTorus = function (name, options, scene) {
             var torus = new BABYLON.Mesh(name, scene);
@@ -213,13 +213,13 @@ var BABYLON;
         /**
          * Creates a torus knot mesh.
          * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#torus-knot
-         * The parameter "radius" sets the global radius size (float) of the torus knot (default 2).
-         * The parameter "radialSegments" sets the number of sides on each tube segments (positive integer, default 32).
-         * The parameter "tubularSegments" sets the number of tubes to decompose the knot into (positive integer, default 32).
-         * The parameters "p" and "q" are the number of windings on each axis (positive integers, default 2 and 3).
+         * The parameter `radius` sets the global radius size (float) of the torus knot (default 2).
+         * The parameter `radialSegments` sets the number of sides on each tube segments (positive integer, default 32).
+         * The parameter `tubularSegments` sets the number of tubes to decompose the knot into (positive integer, default 32).
+         * The parameters `p` and `q` are the number of windings on each axis (positive integers, default 2 and 3).
          * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
          * 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.
+         * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
         MeshBuilder.CreateTorusKnot = function (name, options, scene) {
             var torusKnot = new BABYLON.Mesh(name, scene);
@@ -227,6 +227,18 @@ var BABYLON;
             vertexData.applyToMesh(torusKnot, options.updatable);
             return torusKnot;
         };
+        /**
+         * Creates a line system mesh.
+         * A line system is a pool of many lines gathered in a single mesh.
+         * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#linesystem
+         * A line system mesh is considered as a parametric shape since it has no predefined original shape. Its shape is determined by the passed array of lines as an input parameter.
+         * Like every other parametric shape, it is dynamically updatable by passing an existing instance of LineSystem to this static function.
+         * The parameter `lines` is an array of lines, each line being an array of successive Vector3.
+         * The optional parameter `instance` is an instance of an existing LineSystem object to be updated with the passed `lines` parameter. The way to update it is the same than for
+         * updating a simple Line mesh, you just need to update every line in the `lines` array : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#lines-and-dashedlines
+         * When updating an instance, remember that only line point positions can change, not the number of points, neither the number of lines.
+         * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
+         */
         MeshBuilder.CreateLineSystem = function (name, options, scene) {
             var instance = options.instance;
             var lines = options.lines;
@@ -252,10 +264,33 @@ var BABYLON;
             vertexData.applyToMesh(lineSystem, options.updatable);
             return lineSystem;
         };
+        /**
+         * Creates a line mesh.
+         * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#lines
+         * A line mesh is considered as a parametric shape since it has no predefined original shape. Its shape is determined by the passed array of points as an input parameter.
+         * Like every other parametric shape, it is dynamically updatable by passing an existing instance of LineMesh to this static function.
+         * The parameter `points` is an array successive Vector3.
+         * The optional parameter `instance` is an instance of an existing LineMesh object to be updated with the passed `points` parameter : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#lines-and-dashedlines
+         * 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.
+         */
         MeshBuilder.CreateLines = function (name, options, scene) {
             var lines = MeshBuilder.CreateLineSystem(name, { lines: [options.points], updatable: options.updatable, instance: options.instance }, scene);
             return lines;
         };
+        /**
+         * Creates a dashed line mesh.
+         * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#dashed-lines
+         * A dashed line mesh is considered as a parametric shape since it has no predefined original shape. Its shape is determined by the passed array of points as an input parameter.
+         * Like every other parametric shape, it is dynamically updatable by passing an existing instance of LineMesh to this static function.
+         * The parameter `points` is an array successive Vector3.
+         * The parameter `dashNb` is the intended total number of dashes (positive integer, default 200).
+         * The parameter `dashSize` is the size of the dashes relatively the dash number (positive float, default 3).
+         * The parameter `gapSize` is the size of the gap between two successive dashes relatively the dash number (positive float, default 1).
+         * The optional parameter `instance` is an instance of an existing LineMesh object to be updated with the passed `points` parameter : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#lines-and-dashedlines
+         * 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.
+         */
         MeshBuilder.CreateDashedLines = function (name, options, scene) {
             var points = options.points;
             var instance = options.instance;
@@ -315,6 +350,24 @@ var BABYLON;
             dashedLines.gapSize = gapSize;
             return dashedLines;
         };
+        /**
+         * 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.
+         * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#extruded-shapes
+         *
+         * Please read this full tutorial to understand how to design an extruded shape : http://doc.babylonjs.com/tutorials/Parametric_Shapes#extrusion
+         * The parameter `shape` is a required array of successive Vector3. This array depicts the shape to be extruded in its local space : the shape must be designed in the xOy plane and will be
+         * extruded along the Z axis.
+         * The parameter `path` is a required array of successive Vector3. This is the axis curve the shape is extruded along.
+         * The parameter `rotation` (float, default 0 radians) is the angle value to rotate the shape each step (each path point), from the former step (so rotation added each step) along the curve.
+         * The parameter `scale` (float, default 1) is the value to scale the shape.
+         * The parameter `cap` sets the way the extruded shape is capped. Possible values : BABYLON.Mesh.NO_CAP (default), BABYLON.Mesh.CAP_START, BABYLON.Mesh.CAP_END, BABYLON.Mesh.CAP_ALL
+         * The optional parameter `instance` is an instance of an existing ExtrudedShape object to be updated with the passed `shape`, `path`, `scale` or `rotation` parameters : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#extruded-shape
+         * Remember you can only change the shape or path point positions, not their number when updating an extruded shape.
+         * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
+         * 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.
+         */
         MeshBuilder.ExtrudeShape = function (name, options, scene) {
             var path = options.path;
             var shape = options.shape;
@@ -326,6 +379,36 @@ var BABYLON;
             var instance = options.instance;
             return MeshBuilder._ExtrudeShapeGeneric(name, shape, path, scale, rotation, null, null, false, false, cap, false, scene, updatable, sideOrientation, instance);
         };
+        /**
+         * 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.
+         * tuto :http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#custom-extruded-shapes
+         *
+         * Please read this full tutorial to understand how to design a custom extruded shape : http://doc.babylonjs.com/tutorials/Parametric_Shapes#extrusion
+         * The parameter `shape` is a required array of successive Vector3. This array depicts the shape to be extruded in its local space : the shape must be designed in the xOy plane and will be
+         * extruded along the Z axis.
+         * The parameter `path` is a required array of successive Vector3. This is the axis curve the shape is extruded along.
+         * The parameter `rotationFunction` (JS function) is a custom Javascript function called on each path point. This function is passed the position i of the point in the path
+         * and the distance of this point from the begining of the path :
+         * ```rotationFunction = function(i, distance) {
+         *  // do things
+         *  return rotationValue; }```
+         * It must returns a float value that will be the rotation in radians applied to the shape on each path point.
+         * The parameter `scaleFunction` (JS function) is a custom Javascript function called on each path point. This function is passed the position i of the point in the path
+         * and the distance of this point from the begining of the path :
+         * ````scaleFunction = function(i, distance) {
+         *   // do things
+         *  return scaleValue;}```
+         * It must returns a float value that will be the scale value applied to the shape on each path point.
+         * The parameter `ribbonClosePath` (boolean, default false) forces the extrusion underlying ribbon to close all the paths in its `pathArray`.
+         * The parameter `ribbonCloseArray` (boolean, default false) forces the extrusion underlying ribbon to close its `pathArray`.
+         * The parameter `cap` sets the way the extruded shape is capped. Possible values : BABYLON.Mesh.NO_CAP (default), BABYLON.Mesh.CAP_START, BABYLON.Mesh.CAP_END, BABYLON.Mesh.CAP_ALL
+         * The optional parameter `instance` is an instance of an existing ExtrudedShape object to be updated with the passed `shape`, `path`, `scale` or `rotation` parameters : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#extruded-shape
+         * Remember you can only change the shape or path point positions, not their number when updating an extruded shape.
+         * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
+         * 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.
+         */
         MeshBuilder.ExtrudeShapeCustom = function (name, options, scene) {
             var path = options.path;
             var shape = options.shape;
@@ -339,6 +422,22 @@ var BABYLON;
             var instance = options.instance;
             return MeshBuilder._ExtrudeShapeGeneric(name, shape, path, null, null, scaleFunction, rotationFunction, ribbonCloseArray, ribbonClosePath, cap, true, scene, updatable, sideOrientation, instance);
         };
+        /**
+         * Creates lathe mesh.
+         * The lathe is a shape with a symetry axis : a 2D model shape is rotated around this axis to design the lathe.
+         * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#lathe
+         *
+         * The parameter "shape" is a required array of successive Vector3. This array depicts the shape to be rotated in its local space : the shape must be designed in the xOy plane and will be
+         * rotated around the Y axis. It's usually a 2D shape, so the Vector3 z coordinates are often set to zero.
+         * The parameter "radius" (positive float, default 1) is the radius value of the lathe.
+         * The parameter "tessellation" (positive integer, default 64) is the side number of the lathe.
+         * The parameter "arc" (positive float, default 1) is the ratio of the lathe. 0.5 builds for instance half a lathe, so an opened shape.
+         * The parameter "closed" (boolean, default true) opens/closes the lathe circumference. This should be set to false when used with the parameter "arc".
+         * The parameter "cap" sets the way the extruded shape is capped. Possible values : BABYLON.Mesh.NO_CAP (default), BABYLON.Mesh.CAP_START, BABYLON.Mesh.CAP_END, BABYLON.Mesh.CAP_ALL
+         * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
+         * 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.
+         */
         MeshBuilder.CreateLathe = function (name, options, scene) {
             var arc = (options.arc <= 0 || options.arc > 1) ? 1.0 : options.arc || 1.0;
             var closed = (options.closed === undefined) ? true : options.closed;
@@ -376,6 +475,16 @@ var BABYLON;
             var lathe = MeshBuilder.CreateRibbon(name, { pathArray: paths, closeArray: closed, sideOrientation: sideOrientation, updatable: updatable }, scene);
             return lathe;
         };
+        /**
+         * Creates a plane mesh.
+         * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#plane
+         * The parameter `size` sets the size (float) of both sides of the plane at once (default 1).
+         * You can set some different plane dimensions by using the parameters `width` and `height` (both by default have the same value than `size`).
+         * The parameter `sourcePlane` is a `Plane` instance. It builds a mesh plane from a Math plane.
+         * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
+         * 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.
+         */
         MeshBuilder.CreatePlane = function (name, options, scene) {
             var plane = new BABYLON.Mesh(name, scene);
             var vertexData = BABYLON.VertexData.CreatePlane(options);
@@ -388,6 +497,13 @@ var BABYLON;
             }
             return plane;
         };
+        /**
+         * Creates a ground mesh.
+         * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#plane
+         * The parameters `width` and `height` (floats, default 1) set the width and height sizes of the ground.
+         * 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.
+         */
         MeshBuilder.CreateGround = function (name, options, scene) {
             var ground = new BABYLON.GroundMesh(name, scene);
             ground._setReady(false);
@@ -403,12 +519,37 @@ var BABYLON;
             ground._setReady(true);
             return ground;
         };
+        /**
+         * Creates a tiled ground mesh.
+         * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#tiled-ground
+         * The parameters `xmin` and `xmax` (floats, default -1 and 1) set the ground minimum and maximum X coordinates.
+         * The parameters `zmin` and `zmax` (floats, default -1 and 1) set the ground minimum and maximum Z coordinates.
+         * The parameter `subdivisions` is a javascript object `{w: positive integer, h: positive integer}` (default `{w: 6, h: 6}`). `w` and `h` are the
+         * numbers of subdivisions on the ground width and height. Each subdivision is called a tile.
+         * The parameter `precision` is a javascript object `{w: positive integer, h: positive integer}` (default `{w: 2, h: 2}`). `w` and `h` are the
+         * numbers of subdivisions on the ground width and height of each tile.
+         * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
+         */
         MeshBuilder.CreateTiledGround = function (name, options, scene) {
             var tiledGround = new BABYLON.Mesh(name, scene);
             var vertexData = BABYLON.VertexData.CreateTiledGround(options);
             vertexData.applyToMesh(tiledGround, options.updatable);
             return tiledGround;
         };
+        /**
+         * Creates a ground mesh from a height map.
+         * tuto : http://doc.babylonjs.com/tutorials/14._Height_Map
+         * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#ground-from-a-height-map
+         * The parameter `url` sets the URL of the height map image resource.
+         * The parameters `width` and `height` (positive floats, default 10) set the ground width and height sizes.
+         * The parameter `subdivisions` (positive integer, default 1) sets the number of subdivision per side.
+         * The parameter `minHeight` (float, default 0) is the minimum altitude on the ground.
+         * The parameter `maxHeight` (float, default 1) is the maximum altitude on the ground.
+         * The parameter `onReady` is a javascript callback function that will be called  once the mesh is just built (the height map download can last some time).
+         * This function is passed the newly built mesh : ```function(mesh) { // do things
+         * return; }```
+         * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
+         */
         MeshBuilder.CreateGroundFromHeightMap = function (name, url, options, scene) {
             var width = options.width || 10;
             var height = options.height || 10;

+ 188 - 49
src/Mesh/babylon.meshBuilder.ts

@@ -3,13 +3,13 @@
         /**
          * Creates a box mesh.  
          * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#box  
-         * The parameter "size" sets the size (float) of each box side (default 1).  
-         * You can set some different box dimensions by using the parameters "width", "height" and "depth" (all by default have the same value than "size").  
-         * You can set different colors and different images to each box side by using the parameters "faceColors" (an array of 6 Color3 elements) and "faceUV" (an array of 6 Vector4 elements).
+         * The parameter `size` sets the size (float) of each box side (default 1).  
+         * You can set some different box dimensions by using the parameters `width`, `height` and `depth` (all by default have the same value than `size`).  
+         * You can set different colors and different images to each box side by using the parameters `faceColors` (an array of 6 `Color3` elements) and `faceUV` (an array of 6 `Vector4` elements).
          * Please read this tutorial : http://doc.babylonjs.com/tutorials/CreateBox_Per_Face_Textures_And_Colors  
          * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE  
          * 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.  
+         * 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, options: { size?: number, width?: number, height?: number, depth?: number, faceUV?: Vector4[], faceColors?: Color4[], sideOrientation?: number, updatable?: boolean }, scene: Scene): Mesh {
             var box = new Mesh(name, scene);
@@ -23,14 +23,14 @@
         /**
          * Creates a sphere mesh.  
          * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#sphere  
-         * The parameter "diameter" sets the diameter size (float) of the sphere (default 1).  
-         * You can set some different sphere dimensions, for instance to build an ellipsoid, by using the parameters "diameterX", "diameterY" and "diameterZ" (all by default have the same value than "diameter").  
-         * The parameter "segments" sets the sphere number of horizontal stripes (positive integer, default 32).  
-         * You can create an unclosed sphere with the parameter "arc" (positive float, default 1), valued between 0 and 1, what is the ratio of the circumference (latitude) : 2 x PI x ratio  
-         * You can create an unclosed sphere on its height with the parameter "slice" (positive float, default1), valued between 0 and 1, what is the height ratio (longitude).  
+         * The parameter `diameter` sets the diameter size (float) of the sphere (default 1).  
+         * You can set some different sphere dimensions, for instance to build an ellipsoid, by using the parameters `diameterX`, `diameterY` and `diameterZ` (all by default have the same value than `diameter`).  
+         * The parameter `segments` sets the sphere number of horizontal stripes (positive integer, default 32).  
+         * You can create an unclosed sphere with the parameter `arc` (positive float, default 1), valued between 0 and 1, what is the ratio of the circumference (latitude) : 2 x PI x ratio  
+         * You can create an unclosed sphere on its height with the parameter `slice` (positive float, default1), valued between 0 and 1, what is the height ratio (longitude).  
          * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE  
          * 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.  
+         * 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 CreateSphere(name: string, options: { segments?: number, diameter?: number, diameterX?: number, diameterY?: number, diameterZ?: number, arc?: number, slice?: number, sideOrientation?: number, updatable?: boolean }, scene: any): Mesh {
             var sphere = new Mesh(name, scene);
@@ -44,12 +44,12 @@
         /**
          * Creates a plane polygonal mesh.  By default, this is a disc.   
          * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#disc   
-         * The parameter "radius" sets the radius size (float) of the polygon (default 0.5).  
-         * The parameter "tessellation" sets the number of polygon sides (positive integer, default 64). So a tessellation valued to 3 will build a triangle, to 4 a square, etc.  
-         * You can create an unclosed polygon with the parameter "arc" (positive float, default 1), valued between 0 and 1, what is the ratio of the circumference : 2 x PI x ratio  
+         * The parameter `radius` sets the radius size (float) of the polygon (default 0.5).  
+         * The parameter `tessellation` sets the number of polygon sides (positive integer, default 64). So a tessellation valued to 3 will build a triangle, to 4 a square, etc.  
+         * You can create an unclosed polygon with the parameter `arc` (positive float, default 1), valued between 0 and 1, what is the ratio of the circumference : 2 x PI x ratio  
          * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE  
          * 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.  
+         * 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, options: { radius?: number, tessellation?: number, arc?: number, updatable?: boolean, sideOrientation?: number }, scene: Scene): Mesh {
             var disc = new Mesh(name, scene);
@@ -63,13 +63,13 @@
         /**
          * Creates a sphere based upon an icosahedron with 20 triangular faces which can be subdivided.   
          * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#icosphere     
-         * The parameter "radius" sets the radius size (float) of the icosphere (default 1).  
-         * You can set some different icosphere dimensions, for instance to build an ellipsoid, by using the parameters "radiusX", "radiusY" and "radiusZ" (all by default have the same value than "radius").  
-         * The parameter "subdivisions" sets the number of subdivisions (postive integer, default 4). The more subdivisions, the more faces on the icosphere whatever its size.    
-         * The parameter "flat" (boolean, default true) gives each side its own normals. Set it to false to get a smooth continuous light reflection on the surface.  
+         * The parameter `radius` sets the radius size (float) of the icosphere (default 1).  
+         * You can set some different icosphere dimensions, for instance to build an ellipsoid, by using the parameters `radiusX`, `radiusY` and `radiusZ` (all by default have the same value than `radius`).  
+         * The parameter `subdivisions` sets the number of subdivisions (postive integer, default 4). The more subdivisions, the more faces on the icosphere whatever its size.    
+         * The parameter `flat` (boolean, default true) gives each side its own normals. Set it to false to get a smooth continuous light reflection on the surface.  
          * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE  
          * 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.  
+         * 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 CreateIcoSphere(name: string, options: { radius?: number, radiusX?: number, radiusY?: number, radiusZ?: number, flat?: boolean, subdivisions?: number, sideOrientation?: number, updatable?: boolean }, scene: Scene): Mesh {
             var sphere = new Mesh(name, scene);
@@ -82,16 +82,16 @@
 
         /**
          * Creates a ribbon mesh.    
-         * The ribbon 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.  
+         * The ribbon 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.    
          *
          * Please read this full tutorial to understand how to design a ribbon : http://doc.babylonjs.com/tutorials/Ribbon_Tutorial    
-         * The parameter "pathArray" is a required array of paths, what are each an array of successive Vector3. The pathArray parameter depicts the ribbon geometry.    
-         * The parameter "closeArray" (boolean, default false) creates a seam between the first and the last paths of the path array.  
-         * The parameter "closePath" (boolean, default false) creates a seam between the first and the last points of each path of the path array.  
-         * The parameter "instance" is an instance of an existing Ribbon object to be updated with the passed "pathArray" parameter : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#ribbon   
+         * The parameter `pathArray` is a required array of paths, what are each an array of successive Vector3. The pathArray parameter depicts the ribbon geometry.    
+         * The parameter `closeArray` (boolean, default false) creates a seam between the first and the last paths of the path array.  
+         * The parameter `closePath` (boolean, default false) creates a seam between the first and the last points of each path of the path array.  
+         * The optional parameter èinstance` is an instance of an existing Ribbon object to be updated with the passed `pathArray` parameter : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#ribbon   
          * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE  
          * 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.  
+         * 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, options: { pathArray: Vector3[][], closeArray?: boolean, closePath?: boolean, offset?: number, updatable?: boolean, sideOrientation?: number, instance?: Mesh }, scene?: Scene): Mesh {
             var pathArray = options.pathArray;
@@ -185,25 +185,25 @@
         /**
          * Creates a cylinder or a cone mesh.   
          * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#cylinder-or-cone    
-         * The parameter "height" sets the height size (float) of the cylinder/cone (float, default 2).  
-         * The parameter "diameter" sets the diameter of the top and bottom cap at once (float, default 1).  
-         * The parameters "diameterTop" and "diameterBottom" overwrite the parameter "diameter" and set respectively the top cap and bottom cap diameter (floats, default 1). The parameter "diameterBottom" can't be zero.  
-         * The parameter "tessellation" sets the number of cylinder sides (positive integer, default 24). Set it to 3 to get a prism for instance.
-         * The parameter "subdivisions" sets the number of rings along the cylinder height (positive integer, default 1).   
-         * The parameter "hasRings" (boolean, default false) makes the subdivisions independent from each other, so they become different faces.  
-         * The parameter "enclose"  (boolean, default false) adds two extra faces per subdivision to a sliced cylinder to close it around its height axis.  
-         * The parameter "arc" (float, default 1) is the ratio (max 1) to apply to the circumference to slice the cylinder.   
-         * You can set different colors and different images to each box side by using the parameters "faceColors" (an array of n Color3 elements) and "faceUV" (an array of n Vector4 elements).   
+         * The parameter `height` sets the height size (float) of the cylinder/cone (float, default 2).  
+         * The parameter `diameter` sets the diameter of the top and bottom cap at once (float, default 1).  
+         * The parameters `diameterTop` and `diameterBottom` overwrite the parameter `diameter` and set respectively the top cap and bottom cap diameter (floats, default 1). The parameter "diameterBottom" can't be zero.  
+         * The parameter `tessellation` sets the number of cylinder sides (positive integer, default 24). Set it to 3 to get a prism for instance.
+         * The parameter `subdivisions` sets the number of rings along the cylinder height (positive integer, default 1).   
+         * The parameter `hasRings` (boolean, default false) makes the subdivisions independent from each other, so they become different faces.  
+         * The parameter `enclose`  (boolean, default false) adds two extra faces per subdivision to a sliced cylinder to close it around its height axis.  
+         * The parameter `arc` (float, default 1) is the ratio (max 1) to apply to the circumference to slice the cylinder.   
+         * You can set different colors and different images to each box side by using the parameters `faceColors` (an array of n `Color3` elements) and `faceUV` (an array of n `Vector4` elements).   
          * The value of n is the number of cylinder faces. If the cylinder has only 1 subdivisions, n equals : top face + cylinder surface + bottom face = 3   
          * Now, if the cylinder has 5 independent subdivisions (hasRings = true), n equals : top face + 5 stripe surfaces + bottom face = 2 + 5 = 7   
          * Finally, if the cylinder has 5 independent subdivisions and is enclose, n equals : top face + 5 x (stripe surface + 2 closing faces) + bottom face = 2 + 5 * 3 = 17    
          * Each array (color or UVs) is always ordered the same way : the first element is the bottom cap, the last element is the top cap. The other elements are each a ring surface.    
-         * If enclose is false, a ring surface is one element.   
-         * If enclose true, a ring surface is 3 successive elements in the array : the tubular surface, then the two closing faces.    
+         * If `enclose` is false, a ring surface is one element.   
+         * If `enclose` is true, a ring surface is 3 successive elements in the array : the tubular surface, then the two closing faces.    
          * Example how to set colors and textures on a sliced cylinder : http://www.html5gamedevs.com/topic/17945-creating-a-closed-slice-of-a-cylinder/#comment-106379  
          * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE  
          * 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.  
+         * 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, options: { height?: number, diameterTop?: number, diameterBottom?: number, diameter?: number, tessellation?: number, subdivisions?: number, arc?: number, faceColors?: Color4[], faceUV?: Vector4[], updatable?: boolean, hasRings?: boolean, enclose?: boolean, sideOrientation?: number }, scene: any): Mesh {
             var cylinder = new Mesh(name, scene);
@@ -217,12 +217,12 @@
         /**
          * Creates a torus mesh.   
          * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#torus       
-         * The parameter "diameter" sets the diameter size (float) of the torus (default 1).  
-         * The parameter "thickness" sets the diameter size of the tube of the torus (float, default 0.5).  
-         * The parameter "tessellation" sets the number of torus sides (postive integer, default 16).  
+         * The parameter `diameter` sets the diameter size (float) of the torus (default 1).  
+         * The parameter `thickness` sets the diameter size of the tube of the torus (float, default 0.5).  
+         * The parameter `tessellation` sets the number of torus sides (postive integer, default 16).  
          * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE  
          * 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.  
+         * 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, options: { diameter?: number, thickness?: number, tessellation?: number, updatable?: boolean, sideOrientation?: number }, scene: any): Mesh {
             var torus = new Mesh(name, scene);
@@ -236,13 +236,13 @@
         /**
          * Creates a torus knot mesh.   
          * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#torus-knot         
-         * The parameter "radius" sets the global radius size (float) of the torus knot (default 2).  
-         * The parameter "radialSegments" sets the number of sides on each tube segments (positive integer, default 32).  
-         * The parameter "tubularSegments" sets the number of tubes to decompose the knot into (positive integer, default 32).  
-         * The parameters "p" and "q" are the number of windings on each axis (positive integers, default 2 and 3).    
+         * The parameter `radius` sets the global radius size (float) of the torus knot (default 2).  
+         * The parameter `radialSegments` sets the number of sides on each tube segments (positive integer, default 32).  
+         * The parameter `tubularSegments` sets the number of tubes to decompose the knot into (positive integer, default 32).  
+         * The parameters `p` and `q` are the number of windings on each axis (positive integers, default 2 and 3).    
          * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE  
          * 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.  
+         * 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, options: { radius?: number, tube?: number, radialSegments?: number, tubularSegments?: number, p?: number, q?: number, updatable?: boolean, sideOrientation?: number }, scene: any): Mesh {
             var torusKnot = new Mesh(name, scene);
@@ -253,6 +253,18 @@
             return torusKnot;
         }
 
+        /**
+         * Creates a line system mesh.  
+         * A line system is a pool of many lines gathered in a single mesh.  
+         * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#linesystem  
+         * A line system mesh is considered as a parametric shape since it has no predefined original shape. Its shape is determined by the passed array of lines as an input parameter.  
+         * Like every other parametric shape, it is dynamically updatable by passing an existing instance of LineSystem to this static function.  
+         * The parameter `lines` is an array of lines, each line being an array of successive Vector3.   
+         * The optional parameter `instance` is an instance of an existing LineSystem object to be updated with the passed `lines` parameter. The way to update it is the same than for 
+         * updating a simple Line mesh, you just need to update every line in the `lines` array : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#lines-and-dashedlines   
+         * When updating an instance, remember that only line point positions can change, not the number of points, neither the number of lines.      
+         * 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 CreateLineSystem(name: string, options: { lines: Vector3[][], updatable: boolean, instance?: LinesMesh }, scene: Scene): LinesMesh {
             var instance = options.instance;
             var lines = options.lines;
@@ -281,11 +293,34 @@
             return lineSystem;
         }
 
+        /**
+         * Creates a line mesh.  
+         * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#lines  
+         * A line mesh is considered as a parametric shape since it has no predefined original shape. Its shape is determined by the passed array of points as an input parameter.  
+         * Like every other parametric shape, it is dynamically updatable by passing an existing instance of LineMesh to this static function.  
+         * The parameter `points` is an array successive Vector3.   
+         * The optional parameter `instance` is an instance of an existing LineMesh object to be updated with the passed `points` parameter : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#lines-and-dashedlines    
+         * 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, options: { points: Vector3[], updatable?: boolean, instance?: LinesMesh }, scene: Scene): LinesMesh {
             var lines = MeshBuilder.CreateLineSystem(name, { lines: [options.points], updatable: options.updatable, instance: options.instance }, scene);
             return lines;
         }
 
+        /**
+         * Creates a dashed line mesh.  
+         * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#dashed-lines  
+         * A dashed line mesh is considered as a parametric shape since it has no predefined original shape. Its shape is determined by the passed array of points as an input parameter.  
+         * Like every other parametric shape, it is dynamically updatable by passing an existing instance of LineMesh to this static function.  
+         * The parameter `points` is an array successive Vector3.  
+         * The parameter `dashNb` is the intended total number of dashes (positive integer, default 200).    
+         * The parameter `dashSize` is the size of the dashes relatively the dash number (positive float, default 3).  
+         * The parameter `gapSize` is the size of the gap between two successive dashes relatively the dash number (positive float, default 1).  
+         * The optional parameter `instance` is an instance of an existing LineMesh object to be updated with the passed `points` parameter : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#lines-and-dashedlines    
+         * 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, options: { points: Vector3[], dashSize?: number, gapSize?: number, dashNb?: number, updatable?: boolean, instance?: LinesMesh }, scene: Scene): LinesMesh {
             var points = options.points;
             var instance = options.instance;
@@ -347,6 +382,24 @@
             return dashedLines;
         }
 
+        /**
+         * 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.  
+         * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#extruded-shapes    
+         *
+         * Please read this full tutorial to understand how to design an extruded shape : http://doc.babylonjs.com/tutorials/Parametric_Shapes#extrusion     
+         * The parameter `shape` is a required array of successive Vector3. This array depicts the shape to be extruded in its local space : the shape must be designed in the xOy plane and will be
+         * extruded along the Z axis.    
+         * The parameter `path` is a required array of successive Vector3. This is the axis curve the shape is extruded along.      
+         * The parameter `rotation` (float, default 0 radians) is the angle value to rotate the shape each step (each path point), from the former step (so rotation added each step) along the curve.    
+         * The parameter `scale` (float, default 1) is the value to scale the shape.  
+         * The parameter `cap` sets the way the extruded shape is capped. Possible values : BABYLON.Mesh.NO_CAP (default), BABYLON.Mesh.CAP_START, BABYLON.Mesh.CAP_END, BABYLON.Mesh.CAP_ALL      
+         * The optional parameter `instance` is an instance of an existing ExtrudedShape object to be updated with the passed `shape`, `path`, `scale` or `rotation` parameters : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#extruded-shape  
+         * Remember you can only change the shape or path point positions, not their number when updating an extruded shape.       
+         * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE  
+         * 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, options: { shape: Vector3[], path: Vector3[], scale?: number, rotation?: number, cap?: number, updatable?: boolean, sideOrientation?: number, instance?: Mesh }, scene: Scene): Mesh {
             var path = options.path;
             var shape = options.shape;
@@ -360,6 +413,36 @@
             return MeshBuilder._ExtrudeShapeGeneric(name, shape, path, scale, rotation, null, null, false, false, cap, false, scene, updatable, sideOrientation, instance);
         }
 
+        /**
+         * 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.  
+         * tuto :http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#custom-extruded-shapes     
+         *
+         * Please read this full tutorial to understand how to design a custom extruded shape : http://doc.babylonjs.com/tutorials/Parametric_Shapes#extrusion     
+         * The parameter `shape` is a required array of successive Vector3. This array depicts the shape to be extruded in its local space : the shape must be designed in the xOy plane and will be
+         * extruded along the Z axis.    
+         * The parameter `path` is a required array of successive Vector3. This is the axis curve the shape is extruded along.      
+         * The parameter `rotationFunction` (JS function) is a custom Javascript function called on each path point. This function is passed the position i of the point in the path 
+         * and the distance of this point from the begining of the path : 
+         * ```rotationFunction = function(i, distance) {
+         *  // do things
+         *  return rotationValue; }```  
+         * It must returns a float value that will be the rotation in radians applied to the shape on each path point.      
+         * The parameter `scaleFunction` (JS function) is a custom Javascript function called on each path point. This function is passed the position i of the point in the path 
+         * and the distance of this point from the begining of the path : 
+         * ````scaleFunction = function(i, distance) {
+         *   // do things
+         *  return scaleValue;}```  
+         * It must returns a float value that will be the scale value applied to the shape on each path point.   
+         * The parameter `ribbonClosePath` (boolean, default false) forces the extrusion underlying ribbon to close all the paths in its `pathArray`.  
+         * The parameter `ribbonCloseArray` (boolean, default false) forces the extrusion underlying ribbon to close its `pathArray`.
+         * The parameter `cap` sets the way the extruded shape is capped. Possible values : BABYLON.Mesh.NO_CAP (default), BABYLON.Mesh.CAP_START, BABYLON.Mesh.CAP_END, BABYLON.Mesh.CAP_ALL        
+         * The optional parameter `instance` is an instance of an existing ExtrudedShape object to be updated with the passed `shape`, `path`, `scale` or `rotation` parameters : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#extruded-shape  
+         * Remember you can only change the shape or path point positions, not their number when updating an extruded shape.       
+         * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE  
+         * 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 ExtrudeShapeCustom(name: string, options: { shape: Vector3[], path: Vector3[], scaleFunction?: any, rotationFunction?: any, ribbonCloseArray?: boolean, ribbonClosePath?: boolean, cap?: number, updatable?: boolean, sideOrientation?: number, instance?: Mesh }, scene: Scene): Mesh {
             var path = options.path;
             var shape = options.shape;
@@ -374,6 +457,22 @@
             return MeshBuilder._ExtrudeShapeGeneric(name, shape, path, null, null, scaleFunction, rotationFunction, ribbonCloseArray, ribbonClosePath, cap, true, scene, updatable, sideOrientation, instance);
         }
 
+        /**
+         * Creates lathe mesh.  
+         * The lathe is a shape with a symetry axis : a 2D model shape is rotated around this axis to design the lathe.      
+         * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#lathe  
+         *
+         * The parameter "shape" is a required array of successive Vector3. This array depicts the shape to be rotated in its local space : the shape must be designed in the xOy plane and will be
+         * rotated around the Y axis. It's usually a 2D shape, so the Vector3 z coordinates are often set to zero.    
+         * The parameter "radius" (positive float, default 1) is the radius value of the lathe.        
+         * The parameter "tessellation" (positive integer, default 64) is the side number of the lathe.      
+         * The parameter "arc" (positive float, default 1) is the ratio of the lathe. 0.5 builds for instance half a lathe, so an opened shape.  
+         * The parameter "closed" (boolean, default true) opens/closes the lathe circumference. This should be set to false when used with the parameter "arc".        
+         * The parameter "cap" sets the way the extruded shape is capped. Possible values : BABYLON.Mesh.NO_CAP (default), BABYLON.Mesh.CAP_START, BABYLON.Mesh.CAP_END, BABYLON.Mesh.CAP_ALL          
+         * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE  
+         * 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 CreateLathe(name: string, options: { shape: Vector3[], radius?: number, tessellation?: number, arc?: number, closed?: boolean, updatable?: boolean, sideOrientation?: number, cap?: number }, scene: Scene): Mesh {
             var arc: number = (options.arc <= 0 || options.arc > 1) ? 1.0 : options.arc || 1.0;
             var closed: boolean = (options.closed === undefined) ? true : options.closed;
@@ -413,6 +512,16 @@
             return lathe;
         }
 
+        /**
+         * Creates a plane mesh.  
+         * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#plane  
+         * The parameter `size` sets the size (float) of both sides of the plane at once (default 1).  
+         * You can set some different plane dimensions by using the parameters `width` and `height` (both by default have the same value than `size`).
+         * The parameter `sourcePlane` is a `Plane` instance. It builds a mesh plane from a Math plane.    
+         * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE  
+         * 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 CreatePlane(name: string, options: { size?: number, width?: number, height?: number, sideOrientation?: number, updatable?: boolean, sourcePlane?: Plane }, scene: Scene): Mesh {
             var plane = new Mesh(name, scene);
 
@@ -432,6 +541,13 @@
             return plane;
         }
 
+        /**
+         * Creates a ground mesh.  
+         * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#plane  
+         * The parameters `width` and `height` (floats, default 1) set the width and height sizes of the ground.    
+         * 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, options: { width?: number, height?: number, subdivisions?: number, updatable?: boolean }, scene: any): Mesh {
             var ground = new GroundMesh(name, scene);
             ground._setReady(false);
@@ -452,6 +568,17 @@
             return ground;
         }
 
+        /**
+         * Creates a tiled ground mesh.  
+         * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#tiled-ground    
+         * The parameters `xmin` and `xmax` (floats, default -1 and 1) set the ground minimum and maximum X coordinates.     
+         * The parameters `zmin` and `zmax` (floats, default -1 and 1) set the ground minimum and maximum Z coordinates.   
+         * The parameter `subdivisions` is a javascript object `{w: positive integer, h: positive integer}` (default `{w: 6, h: 6}`). `w` and `h` are the
+         * numbers of subdivisions on the ground width and height. Each subdivision is called a tile.    
+         * The parameter `precision` is a javascript object `{w: positive integer, h: positive integer}` (default `{w: 2, h: 2}`). `w` and `h` are the
+         * numbers of subdivisions on the ground width and height of each tile.  
+         * 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 CreateTiledGround(name: string, options: { xmin: number, zmin: number, xmax: number, zmax: number, subdivisions?: { w: number; h: number; }, precision?: { w: number; h: number; }, updatable?: boolean }, scene: Scene): Mesh {
             var tiledGround = new Mesh(name, scene);
 
@@ -462,6 +589,20 @@
             return tiledGround;
         }
 
+        /**
+         * Creates a ground mesh from a height map.    
+         * tuto : http://doc.babylonjs.com/tutorials/14._Height_Map   
+         * tuto : http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#ground-from-a-height-map  
+         * The parameter `url` sets the URL of the height map image resource.  
+         * The parameters `width` and `height` (positive floats, default 10) set the ground width and height sizes.     
+         * The parameter `subdivisions` (positive integer, default 1) sets the number of subdivision per side.  
+         * The parameter `minHeight` (float, default 0) is the minimum altitude on the ground.     
+         * The parameter `maxHeight` (float, default 1) is the maximum altitude on the ground.   
+         * The parameter `onReady` is a javascript callback function that will be called  once the mesh is just built (the height map download can last some time).  
+         * This function is passed the newly built mesh : ```function(mesh) { // do things
+         * return; }```
+         * 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 CreateGroundFromHeightMap(name: string, url: string, options: { width?: number, height?: number, subdivisions?: number, minHeight?: number, maxHeight?: number, updatable?: boolean, onReady?: (mesh: GroundMesh) => void }, scene: Scene): GroundMesh {
             var width = options.width || 10;
             var height = options.height || 10;
@@ -924,6 +1065,4 @@
             return extrudedGeneric;
         }
     }
-}
-
-
+}

+ 39 - 0
src/Physics/Plugins/babylon.cannonJSPlugin.js

@@ -162,6 +162,7 @@ var BABYLON;
             }*/
             switch (impostorJoint.joint.type) {
                 case BABYLON.PhysicsJoint.HingeJoint:
+                case BABYLON.PhysicsJoint.Hinge2Joint:
                     constraint = new CANNON.HingeConstraint(mainBody, connectedBody, constraintData);
                     break;
                 case BABYLON.PhysicsJoint.DistanceJoint:
@@ -371,6 +372,18 @@ var BABYLON;
         CannonJSPlugin.prototype.setAngularVelocity = function (impostor, velocity) {
             impostor.physicsBody.angularVelocity.copy(velocity);
         };
+        CannonJSPlugin.prototype.getLinearVelocity = function (impostor) {
+            var v = impostor.physicsBody.velocity;
+            if (!v)
+                return null;
+            return new BABYLON.Vector3(v.x, v.y, v.z);
+        };
+        CannonJSPlugin.prototype.getAngularVelocity = function (impostor) {
+            var v = impostor.physicsBody.angularVelocity;
+            if (!v)
+                return null;
+            return new BABYLON.Vector3(v.x, v.y, v.z);
+        };
         CannonJSPlugin.prototype.setBodyMass = function (impostor, mass) {
             impostor.physicsBody.mass = mass;
             impostor.physicsBody.updateMassProperties();
@@ -381,6 +394,32 @@ var BABYLON;
         CannonJSPlugin.prototype.wakeUpBody = function (impostor) {
             impostor.physicsBody.wakeUp();
         };
+        CannonJSPlugin.prototype.updateDistanceJoint = function (joint, maxDistance, minDistance) {
+            joint.physicsJoint.distance = maxDistance;
+        };
+        CannonJSPlugin.prototype.enableMotor = function (joint, motorIndex) {
+            if (!motorIndex) {
+                joint.physicsJoint.enableMotor();
+            }
+        };
+        CannonJSPlugin.prototype.disableMotor = function (joint, motorIndex) {
+            if (!motorIndex) {
+                joint.physicsJoint.disableMotor();
+            }
+        };
+        CannonJSPlugin.prototype.setMotor = function (joint, speed, maxForce, motorIndex) {
+            if (!motorIndex) {
+                joint.physicsJoint.enableMotor();
+                joint.physicsJoint.setMotorSpeed(speed);
+                if (maxForce) {
+                    this.setLimit(joint, maxForce);
+                }
+            }
+        };
+        CannonJSPlugin.prototype.setLimit = function (joint, upperLimit, lowerLimit) {
+            joint.physicsJoint.motorEquation.maxForce = upperLimit;
+            joint.physicsJoint.motorEquation.minForce = lowerLimit || -upperLimit;
+        };
         CannonJSPlugin.prototype.dispose = function () {
             //nothing to do, actually.
         };

+ 30 - 0
src/Physics/Plugins/babylon.oimoJSPlugin.js

@@ -264,6 +264,18 @@ var BABYLON;
         OimoJSPlugin.prototype.setAngularVelocity = function (impostor, velocity) {
             impostor.physicsBody.angularVelocity.init(velocity.x, velocity.y, velocity.z);
         };
+        OimoJSPlugin.prototype.getLinearVelocity = function (impostor) {
+            var v = impostor.physicsBody.linearVelocity;
+            if (!v)
+                return null;
+            return new BABYLON.Vector3(v.x, v.y, v.z);
+        };
+        OimoJSPlugin.prototype.getAngularVelocity = function (impostor) {
+            var v = impostor.physicsBody.angularVelocity;
+            if (!v)
+                return null;
+            return new BABYLON.Vector3(v.x, v.y, v.z);
+        };
         OimoJSPlugin.prototype.setBodyMass = function (impostor, mass) {
             var staticBody = mass === 0;
             //this will actually set the body's density and not its mass.
@@ -277,6 +289,24 @@ var BABYLON;
         OimoJSPlugin.prototype.wakeUpBody = function (impostor) {
             impostor.physicsBody.awake();
         };
+        OimoJSPlugin.prototype.updateDistanceJoint = function (joint, maxDistance, minDistance) {
+            joint.physicsJoint.limitMotoe.upperLimit = maxDistance;
+            if (minDistance !== void 0) {
+                joint.physicsJoint.limitMotoe.lowerLimit = minDistance;
+            }
+        };
+        OimoJSPlugin.prototype.setMotor = function (joint, force, maxForce, motorIndex) {
+            var motor = motorIndex ? joint.physicsJoint.rotationalLimitMotor2 : joint.physicsJoint.rotationalLimitMotor1 || joint.physicsJoint.limitMotor;
+            if (motor) {
+                motor.setMotor(force, maxForce);
+            }
+        };
+        OimoJSPlugin.prototype.setLimit = function (joint, upperLimit, lowerLimit, motorIndex) {
+            var motor = motorIndex ? joint.physicsJoint.rotationalLimitMotor2 : joint.physicsJoint.rotationalLimitMotor1 || joint.physicsJoint.limitMotor;
+            if (motor) {
+                motor.setLimit(upperLimit, lowerLimit || -upperLimit);
+            }
+        };
         OimoJSPlugin.prototype.dispose = function () {
             this.world.clear();
         };

+ 18 - 0
src/Physics/babylon.physicsEngine.js

@@ -24,6 +24,7 @@ var BABYLON;
          * default is 1/60.
          * To slow it down, enter 1/600 for example.
          * To speed it up, 1/30
+         * @param {number} newTimeStep the new timestep to apply to this world.
          */
         PhysicsEngine.prototype.setTimeStep = function (newTimeStep) {
             if (newTimeStep === void 0) { newTimeStep = 1 / 60; }
@@ -38,6 +39,11 @@ var BABYLON;
         PhysicsEngine.prototype.getPhysicsPluginName = function () {
             return this._physicsPlugin.name;
         };
+        /**
+         * Adding a new impostor for the impostor tracking.
+         * This will be done by the impostor itself.
+         * @param {PhysicsImpostor} impostor the impostor to add
+         */
         PhysicsEngine.prototype.addImpostor = function (impostor) {
             this._impostors.push(impostor);
             //if no parent, generate the body
@@ -45,6 +51,11 @@ var BABYLON;
                 this._physicsPlugin.generatePhysicsBody(impostor);
             }
         };
+        /**
+         * Remove an impostor from the engine.
+         * This impostor and its mesh will not longer be updated by the physics engine.
+         * @param {PhysicsImpostor} impostor the impostor to remove
+         */
         PhysicsEngine.prototype.removeImpostor = function (impostor) {
             var index = this._impostors.indexOf(impostor);
             if (index > -1) {
@@ -56,12 +67,19 @@ var BABYLON;
                 }
             }
         };
+        /**
+         * Add a joint to the physics engine
+         * @param {PhysicsImpostor} mainImpostor the main impostor to which the joint is added.
+         * @param {PhysicsImpostor} connectedImpostor the impostor that is connected to the main impostor using this joint
+         * @param {PhysicsJoint} the joint that will connect both impostors.
+         */
         PhysicsEngine.prototype.addJoint = function (mainImpostor, connectedImpostor, joint) {
             var impostorJoint = {
                 mainImpostor: mainImpostor,
                 connectedImpostor: connectedImpostor,
                 joint: joint
             };
+            joint.physicsPlugin = this._physicsPlugin;
             this._joints.push(impostorJoint);
             this._physicsPlugin.generateJoint(impostorJoint);
         };

+ 19 - 8
src/Physics/babylon.physicsImpostor.js

@@ -55,15 +55,20 @@ var BABYLON;
                     });
                 }
             };
-            //default options params
-            this._options.mass = (_options.mass === void 0) ? 0 : _options.mass;
-            this._options.friction = (_options.friction === void 0) ? 0.2 : _options.friction;
-            this._options.restitution = (_options.restitution === void 0) ? 0.2 : _options.restitution;
             this._physicsEngine = this._mesh.getScene().getPhysicsEngine();
-            this._joints = [];
-            //If the mesh has a parent, don't initialize the physicsBody. Instead wait for the parent to do that.
-            if (!this._mesh.parent) {
-                this._init();
+            if (!this._physicsEngine) {
+                BABYLON.Tools.Error("Physics not enabled. Please use scene.enablePhysics(...) before creating impostors.");
+            }
+            else {
+                //default options params
+                this._options.mass = (_options.mass === void 0) ? 0 : _options.mass;
+                this._options.friction = (_options.friction === void 0) ? 0.2 : _options.friction;
+                this._options.restitution = (_options.restitution === void 0) ? 0.2 : _options.restitution;
+                this._joints = [];
+                //If the mesh has a parent, don't initialize the physicsBody. Instead wait for the parent to do that.
+                if (!this._mesh.parent) {
+                    this._init();
+                }
             }
         }
         /**
@@ -165,12 +170,18 @@ var BABYLON;
             }
             this._physicsEngine.getPhysicsPlugin().setBodyMass(this, mass);
         };
+        PhysicsImpostor.prototype.getLinearVelocity = function () {
+            return this._physicsEngine.getPhysicsPlugin().getLinearVelocity(this);
+        };
         /**
          * Set the body's linear velocity.
          */
         PhysicsImpostor.prototype.setLinearVelocity = function (velocity) {
             this._physicsEngine.getPhysicsPlugin().setLinearVelocity(this, velocity);
         };
+        PhysicsImpostor.prototype.getAngularVelocity = function () {
+            return this._physicsEngine.getPhysicsPlugin().getAngularVelocity(this);
+        };
         /**
          * Set the body's linear velocity.
          */

+ 102 - 1
src/Physics/babylon.physicsJoint.js

@@ -1,5 +1,14 @@
+var __extends = (this && this.__extends) || function (d, b) {
+    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+    function __() { this.constructor = d; }
+    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+};
 var BABYLON;
 (function (BABYLON) {
+    /**
+     * This is a holder class for the physics joint created by the physics plugin.
+     * It holds a set of functions to control the underlying joint.
+     */
     var PhysicsJoint = (function () {
         function PhysicsJoint(type, jointData) {
             this.type = type;
@@ -18,6 +27,21 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(PhysicsJoint.prototype, "physicsPlugin", {
+            set: function (physicsPlugin) {
+                this._physicsPlugin = physicsPlugin;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        /**
+         * Execute a function that is physics-plugin specific.
+         * @param {Function} func the function that will be executed.
+         *                        It accepts two parameters: the physics world and the physics joint.
+         */
+        PhysicsJoint.prototype.executeNativeFunction = function (func) {
+            func(this._physicsPlugin.world, this._physicsJoint);
+        };
         //TODO check if the native joints are the same
         //Joint Types
         PhysicsJoint.DistanceJoint = 0;
@@ -29,7 +53,7 @@ var BABYLON;
         PhysicsJoint.PrismaticJoint = 5;
         //ENERGY FTW! (compare with this - http://ode-wiki.org/wiki/index.php?title=Manual:_Joint_Types_and_Functions)
         PhysicsJoint.UniversalJoint = 6;
-        PhysicsJoint.Hinge2Joint = 7;
+        PhysicsJoint.Hinge2Joint = PhysicsJoint.WheelJoint;
         //Cannon
         //Similar to a Ball-Joint. Different in params
         //TODO check!!
@@ -39,4 +63,81 @@ var BABYLON;
         return PhysicsJoint;
     })();
     BABYLON.PhysicsJoint = PhysicsJoint;
+    /**
+     * A class representing a physics distance joint.
+     */
+    var DistanceJoint = (function (_super) {
+        __extends(DistanceJoint, _super);
+        function DistanceJoint(jointData) {
+            _super.call(this, PhysicsJoint.DistanceJoint, jointData);
+        }
+        /**
+         * Update the predefined distance.
+         */
+        DistanceJoint.prototype.updateDistance = function (maxDistance, minDistance) {
+            this._physicsPlugin.updateDistanceJoint(this, maxDistance, minDistance);
+        };
+        return DistanceJoint;
+    })(PhysicsJoint);
+    BABYLON.DistanceJoint = DistanceJoint;
+    /**
+     * This class represents a single hinge physics joint
+     */
+    var HingeJoint = (function (_super) {
+        __extends(HingeJoint, _super);
+        function HingeJoint(jointData) {
+            _super.call(this, PhysicsJoint.HingeJoint, jointData);
+        }
+        /**
+         * Set the motor values.
+         * Attention, this function is plugin specific. Engines won't react 100% the same.
+         * @param {number} force the force to apply
+         * @param {number} maxForce max force for this motor.
+         */
+        HingeJoint.prototype.setMotor = function (force, maxForce) {
+            this._physicsPlugin.setMotor(this, force, maxForce);
+        };
+        /**
+         * Set the motor's limits.
+         * Attention, this function is plugin specific. Engines won't react 100% the same.
+         */
+        HingeJoint.prototype.setLimit = function (upperLimit, lowerLimit) {
+            this._physicsPlugin.setLimit(this, upperLimit, lowerLimit);
+        };
+        return HingeJoint;
+    })(PhysicsJoint);
+    BABYLON.HingeJoint = HingeJoint;
+    /**
+     * This class represents a dual hinge physics joint (same as wheel joint)
+     */
+    var Hinge2Joint = (function (_super) {
+        __extends(Hinge2Joint, _super);
+        function Hinge2Joint(jointData) {
+            _super.call(this, PhysicsJoint.Hinge2Joint, jointData);
+        }
+        /**
+         * Set the motor values.
+         * Attention, this function is plugin specific. Engines won't react 100% the same.
+         * @param {number} force the force to apply
+         * @param {number} maxForce max force for this motor.
+         * @param {motorIndex} the motor's index, 0 or 1.
+         */
+        Hinge2Joint.prototype.setMotor = function (force, maxForce, motorIndex) {
+            if (motorIndex === void 0) { motorIndex = 0; }
+            this._physicsPlugin.setMotor(this, force, maxForce, motorIndex);
+        };
+        /**
+         * Set the motor limits.
+         * Attention, this function is plugin specific. Engines won't react 100% the same.
+         * @param {number} upperLimit the upper limit
+         * @param {number} lowerLimit lower limit
+         * @param {motorIndex} the motor's index, 0 or 1.
+         */
+        Hinge2Joint.prototype.setLimit = function (upperLimit, lowerLimit, motorIndex) {
+            if (motorIndex === void 0) { motorIndex = 0; }
+            this._physicsPlugin.setLimit(this, upperLimit, lowerLimit, motorIndex);
+        };
+        return Hinge2Joint;
+    })(PhysicsJoint);
+    BABYLON.Hinge2Joint = Hinge2Joint;
 })(BABYLON || (BABYLON = {}));

+ 48 - 15
src/babylon.node.js

@@ -29,6 +29,31 @@ var BABYLON;
             this._scene = scene;
             this._initCache();
         }
+        Object.defineProperty(Node.prototype, "parent", {
+            get: function () {
+                return this._parentNode;
+            },
+            set: function (parent) {
+                if (this._parentNode === parent) {
+                    return;
+                }
+                if (this._parentNode) {
+                    var index = this._parentNode._children.indexOf(this);
+                    if (index !== -1) {
+                        this._parentNode._children.splice(index, 1);
+                    }
+                }
+                this._parentNode = parent;
+                if (this._parentNode) {
+                    if (!this._parentNode._children) {
+                        this._parentNode._children = new Array();
+                    }
+                    this._parentNode._children.push(this);
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
         Node.prototype.getScene = function () {
             return this._scene;
         };
@@ -132,32 +157,35 @@ var BABYLON;
             return false;
         };
         /**
-         * Evaluate a list of nodes and determine if they should be considered as descendants considering the given criterias
-         * @param {BABYLON.Node[]} list the input array of nodes to evaluate
+         * Evaluate the list of children and determine if they should be considered as descendants considering the given criterias
          * @param {BABYLON.Node[]} results the result array containing the nodes matching the given criterias
-         * @param {boolean} directDecendantsOnly if true only direct descendants of 'this' will be considered, if false direct and also indirect (children of children, an so on in a recursive manner) descendants of 'this' will be considered.
+         * @param {boolean} directDescendantsOnly if true only direct descendants of 'this' will be considered, if false direct and also indirect (children of children, an so on in a recursive manner) descendants of 'this' will be considered.
          * @param predicate: an optional predicate that will be called on every evaluated children, the predicate must return true for a given child to be part of the result, otherwise it will be ignored.
          */
-        Node.prototype._getDescendants = function (list, results, directDecendantsOnly, predicate) {
-            if (directDecendantsOnly === void 0) { directDecendantsOnly = false; }
-            for (var index = 0; index < list.length; index++) {
-                var item = list[index];
-                if (((directDecendantsOnly && item.parent === this) || (!directDecendantsOnly && item.isDescendantOf(this))) && (!predicate || predicate(item))) {
+        Node.prototype._getDescendants = function (results, directDescendantsOnly, predicate) {
+            if (directDescendantsOnly === void 0) { directDescendantsOnly = false; }
+            if (!this._children) {
+                return;
+            }
+            for (var index = 0; index < this._children.length; index++) {
+                var item = this._children[index];
+                if (!predicate || predicate(item)) {
                     results.push(item);
                 }
+                if (!directDescendantsOnly) {
+                    item._getDescendants(results, false, predicate);
+                }
             }
         };
         /**
-         * Will return all nodes that have this node as parent.
-         * @param {boolean} directDecendantsOnly if true only direct descendants of 'this' will be considered, if false direct and also indirect (children of children, an so on in a recursive manner) descendants of 'this' will be considered.
+         * Will return all nodes that have this node as ascendant.
+         * @param {boolean} directDescendantsOnly if true only direct descendants of 'this' will be considered, if false direct and also indirect (children of children, an so on in a recursive manner) descendants of 'this' will be considered.
          * @param predicate: an optional predicate that will be called on every evaluated children, the predicate must return true for a given child to be part of the result, otherwise it will be ignored.
          * @return {BABYLON.Node[]} all children nodes of all types.
          */
-        Node.prototype.getDescendants = function (directDecendantsOnly, predicate) {
+        Node.prototype.getDescendants = function (directDescendantsOnly, predicate) {
             var results = [];
-            this._getDescendants(this._scene.meshes, results, directDecendantsOnly, predicate);
-            this._getDescendants(this._scene.lights, results, directDecendantsOnly, predicate);
-            this._getDescendants(this._scene.cameras, results, directDecendantsOnly, predicate);
+            this._getDescendants(results, directDescendantsOnly, predicate);
             return results;
         };
         /**
@@ -173,7 +201,9 @@ var BABYLON;
          */
         Node.prototype.getChildMeshes = function (directDecendantsOnly, predicate) {
             var results = [];
-            this._getDescendants(this._scene.meshes, results, directDecendantsOnly, predicate);
+            this._getDescendants(results, directDecendantsOnly, function (node) {
+                return ((!predicate || predicate(node)) && (node instanceof BABYLON.AbstractMesh));
+            });
             return results;
         };
         Node.prototype._setReady = function (state) {
@@ -239,6 +269,9 @@ var BABYLON;
             }
             return serializationRanges;
         };
+        Node.prototype.dispose = function () {
+            this.parent = null;
+        };
         Node.ParseAnimationRanges = function (node, parsedNode, scene) {
             if (parsedNode.ranges) {
                 for (var index = 0; index < parsedNode.ranges.length; index++) {

+ 56 - 16
src/babylon.node.ts

@@ -4,8 +4,6 @@
      * Node is the basic class for all scene objects (Mesh, Light Camera).
      */
     export class Node {
-        public parent: Node;
-
         @serialize()
         public name: string;
 
@@ -34,6 +32,35 @@
         private _scene: Scene;
         public _cache;
 
+        private _parentNode: Node;
+        private _children: Node[];
+
+        public set parent(parent: Node) {
+            if (this._parentNode === parent) {
+                return;
+            }
+
+            if (this._parentNode) {
+                var index = this._parentNode._children.indexOf(this);
+                if (index !== -1) {
+                    this._parentNode._children.splice(index, 1);
+                }
+            }
+
+            this._parentNode = parent;
+
+            if (this._parentNode) {
+                if (!this._parentNode._children) {
+                    this._parentNode._children = new Array<Node>();
+                }
+                this._parentNode._children.push(this);
+            }
+        }
+
+        public get parent(): Node {
+            return this._parentNode;
+        }
+
         /**
          * @constructor
          * @param {string} name - the name and id to be given to this node
@@ -177,32 +204,39 @@
         }
 
         /**
-         * Evaluate a list of nodes and determine if they should be considered as descendants considering the given criterias
-         * @param {BABYLON.Node[]} list the input array of nodes to evaluate
+         * Evaluate the list of children and determine if they should be considered as descendants considering the given criterias
          * @param {BABYLON.Node[]} results the result array containing the nodes matching the given criterias
-         * @param {boolean} directDecendantsOnly if true only direct descendants of 'this' will be considered, if false direct and also indirect (children of children, an so on in a recursive manner) descendants of 'this' will be considered.
+         * @param {boolean} directDescendantsOnly if true only direct descendants of 'this' will be considered, if false direct and also indirect (children of children, an so on in a recursive manner) descendants of 'this' will be considered.
          * @param predicate: an optional predicate that will be called on every evaluated children, the predicate must return true for a given child to be part of the result, otherwise it will be ignored.
          */
-        public _getDescendants(list: Node[], results: Node[], directDecendantsOnly: boolean = false, predicate?: (node: Node) => boolean): void {
-            for (var index = 0; index < list.length; index++) {
-                var item = list[index];
-                if (((directDecendantsOnly && item.parent === this) || (!directDecendantsOnly && item.isDescendantOf(this))) && (!predicate || predicate(item))) {
+        public _getDescendants(results: Node[], directDescendantsOnly: boolean = false, predicate?: (node: Node) => boolean): void {
+            if (!this._children) {
+                return;
+            }
+
+            for (var index = 0; index < this._children.length; index++) {
+                var item = this._children[index];
+
+                if (!predicate || predicate(item)) {
                     results.push(item);
                 }
+
+                if (!directDescendantsOnly) {
+                    item._getDescendants(results, false, predicate);
+                }
             }
         }
 
         /**
-         * Will return all nodes that have this node as parent.
-         * @param {boolean} directDecendantsOnly if true only direct descendants of 'this' will be considered, if false direct and also indirect (children of children, an so on in a recursive manner) descendants of 'this' will be considered.
+         * Will return all nodes that have this node as ascendant.
+         * @param {boolean} directDescendantsOnly if true only direct descendants of 'this' will be considered, if false direct and also indirect (children of children, an so on in a recursive manner) descendants of 'this' will be considered.
          * @param predicate: an optional predicate that will be called on every evaluated children, the predicate must return true for a given child to be part of the result, otherwise it will be ignored.
          * @return {BABYLON.Node[]} all children nodes of all types.
          */
-        public getDescendants(directDecendantsOnly?: boolean, predicate?: (node: Node) => boolean): Node[] {
+        public getDescendants(directDescendantsOnly?: boolean, predicate?: (node: Node) => boolean): Node[] {
             var results = [];
-            this._getDescendants(this._scene.meshes, results, directDecendantsOnly, predicate);
-            this._getDescendants(this._scene.lights, results, directDecendantsOnly, predicate);
-            this._getDescendants(this._scene.cameras, results, directDecendantsOnly, predicate);
+
+            this._getDescendants(results, directDescendantsOnly, predicate);
 
             return results;
         }
@@ -221,7 +255,9 @@
          */
         public getChildMeshes(directDecendantsOnly?: boolean, predicate?: (node: Node) => boolean): AbstractMesh[] {
             var results: Array<AbstractMesh> = [];
-            this._getDescendants(this._scene.meshes, results, directDecendantsOnly, predicate);
+            this._getDescendants(results, directDecendantsOnly, (node: Node) => {
+                return ((!predicate || predicate(node)) && (node instanceof AbstractMesh));
+            });
             return results;
         }
 
@@ -300,6 +336,10 @@
             return serializationRanges;
         }
 
+        public dispose(): void {
+            this.parent = null;
+        }
+
         public static ParseAnimationRanges(node: Node, parsedNode: any, scene: Scene): void {
             if (parsedNode.ranges) {
                 for (var index = 0; index < parsedNode.ranges.length; index++) {