Forráskód Böngészése

Merge pull request #2777 from BabylonJS/master

Nightly
David Catuhe 8 éve
szülő
commit
fc439c0e34
36 módosított fájl, 33036 hozzáadás és 33170 törlés
  1. BIN
      assets/meshes/controllers/wmr/default/left.glb
  2. BIN
      assets/meshes/controllers/wmr/default/right.glb
  3. 7536 7548
      dist/preview release/babylon.d.ts
  4. 42 42
      dist/preview release/babylon.js
  5. 84 117
      dist/preview release/babylon.max.js
  6. 7536 7548
      dist/preview release/babylon.module.d.ts
  7. 43 43
      dist/preview release/babylon.worker.js
  8. 8610 8622
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts
  9. 45 45
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js
  10. 93 122
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js
  11. 8610 8622
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.module.d.ts
  12. 3 3
      dist/preview release/gui/babylon.gui.min.js
  13. 263 263
      dist/preview release/inspector/babylon.inspector.bundle.js
  14. 3 3
      dist/preview release/inspector/babylon.inspector.min.js
  15. 2 2
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  16. 1 0
      dist/preview release/loaders/babylon.glTF2FileLoader.d.ts
  17. 9 5
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  18. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  19. 1 0
      dist/preview release/loaders/babylon.glTFFileLoader.d.ts
  20. 9 5
      dist/preview release/loaders/babylon.glTFFileLoader.js
  21. 3 3
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  22. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js
  23. 1 1
      dist/preview release/materialsLibrary/babylon.customMaterial.min.js
  24. 1 1
      dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js
  25. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.min.js
  26. 1 1
      dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js
  27. 1 1
      dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js
  28. 10 4
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  29. 1 1
      loaders/src/glTF/2.0/babylon.glTFLoaderUtils.ts
  30. 4 0
      src/Cameras/Inputs/babylon.arcRotateCameraPointersInput.ts
  31. 8 0
      src/Cameras/Inputs/babylon.freeCameraMouseInput.ts
  32. 0 5
      src/Cameras/babylon.camera.ts
  33. 12 4
      src/Gamepad/Controllers/babylon.webVRController.ts
  34. 84 150
      src/Gamepad/Controllers/babylon.windowsMotionController.ts
  35. 9 0
      src/babylon.engine.ts
  36. 8 6
      src/babylon.scene.ts

BIN
assets/meshes/controllers/wmr/default/left.glb


BIN
assets/meshes/controllers/wmr/default/right.glb


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 7536 - 7548
dist/preview release/babylon.d.ts


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 42 - 42
dist/preview release/babylon.js


+ 84 - 117
dist/preview release/babylon.max.js

@@ -7629,6 +7629,7 @@ var BABYLON;
              * Observable event triggered each time the canvas receives pointerout event
              */
             this.onCanvasPointerOutObservable = new BABYLON.Observable();
+            this._vrExclusivePointerMode = false;
             // Uniform buffers list
             this.disableUniformBuffers = false;
             this._uniformBuffers = new Array();
@@ -7859,9 +7860,13 @@ var BABYLON;
                 document.addEventListener("mozpointerlockchange", this._onPointerLockChange, false);
                 document.addEventListener("webkitpointerlockchange", this._onPointerLockChange, false);
                 this._onVRDisplayPointerRestricted = function () {
+                    _this._vrExclusivePointerMode = true;
+                    console.log("enter");
                     canvas.requestPointerLock();
                 };
                 this._onVRDisplayPointerUnrestricted = function () {
+                    _this._vrExclusivePointerMode = false;
+                    console.log("exit");
                     document.exitPointerLock();
                 };
                 window.addEventListener('vrdisplaypointerrestricted', this._onVRDisplayPointerRestricted, false);
@@ -8214,6 +8219,13 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(Engine.prototype, "isInVRExclusivePointerMode", {
+            get: function () {
+                return this._vrExclusivePointerMode;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(Engine.prototype, "supportsUniformBuffers", {
             get: function () {
                 return this.webGLVersion > 1 && !this.disableUniformBuffers;
@@ -15215,10 +15227,6 @@ var BABYLON;
             this._cache.renderWidth = engine.getRenderWidth();
             this._cache.renderHeight = engine.getRenderHeight();
         };
-        Camera.prototype._updateFromScene = function () {
-            this.updateCache();
-            this.update();
-        };
         // Synchronized
         Camera.prototype._isSynchronized = function () {
             return this._isSynchronizedViewMatrix() && this._isSynchronizedProjectionMatrix();
@@ -18806,6 +18814,7 @@ var BABYLON;
             // Camera
             this.resetCachedMaterial();
             this._renderId++;
+            this.activeCamera.update();
             this.updateTransformMatrix();
             if (camera._alternateCamera) {
                 this.updateAlternateTransformMatrix(camera._alternateCamera);
@@ -18941,7 +18950,7 @@ var BABYLON;
             // Finalize frame
             this.postProcessManager._finalizeFrame(camera.isIntermediate);
             // Update camera
-            this.activeCamera._updateFromScene();
+            this.activeCamera.updateCache();
             // Reset some special arrays
             this._renderTargets.reset();
             this._alternateRendering = false;
@@ -18953,14 +18962,15 @@ var BABYLON;
                 this._renderForCamera(camera);
                 return;
             }
+            // Update camera
+            this.activeCamera.update();
             // rig cameras
             for (var index = 0; index < camera._rigCameras.length; index++) {
                 this._renderForCamera(camera._rigCameras[index]);
             }
             this.activeCamera = camera;
             this.setTransformMatrix(this.activeCamera.getViewMatrix(), this.activeCamera.getProjectionMatrix());
-            // Update camera
-            this.activeCamera._updateFromScene();
+            this.activeCamera.updateCache();
         };
         Scene.prototype._checkIntersections = function () {
             for (var index = 0; index < this._meshesForIntersections.length; index++) {
@@ -34375,6 +34385,9 @@ var BABYLON;
             if (!this._pointerInput) {
                 this._pointerInput = function (p, s) {
                     var evt = p.event;
+                    if (engine.isInVRExclusivePointerMode) {
+                        return;
+                    }
                     if (!_this.touchEnabled && evt.pointerType === "touch") {
                         return;
                     }
@@ -34436,6 +34449,9 @@ var BABYLON;
                 if (!engine.isPointerLock) {
                     return;
                 }
+                if (engine.isInVRExclusivePointerMode) {
+                    return;
+                }
                 var offsetX = evt.movementX || evt.mozMovementX || evt.webkitMovementX || evt.msMovementX || 0;
                 var offsetY = evt.movementY || evt.mozMovementY || evt.webkitMovementY || evt.msMovementY || 0;
                 if (_this.camera.getScene().useRightHandedSystem) {
@@ -35381,6 +35397,9 @@ var BABYLON;
             var previousMultiTouchPanPosition = { x: 0, y: 0, isPaning: false };
             this._pointerInput = function (p, s) {
                 var evt = p.event;
+                if (engine.isInVRExclusivePointerMode) {
+                    return;
+                }
                 if (p.type !== BABYLON.PointerEventTypes.POINTERMOVE && _this.buttons.indexOf(evt.button) === -1) {
                     return;
                 }
@@ -52101,6 +52120,7 @@ var BABYLON;
         __extends(WebVRController, _super);
         function WebVRController(vrGamepad) {
             var _this = _super.call(this, vrGamepad) || this;
+            // Observables
             _this.onTriggerStateChangedObservable = new BABYLON.Observable();
             _this.onMainButtonStateChangedObservable = new BABYLON.Observable();
             _this.onSecondaryButtonStateChangedObservable = new BABYLON.Observable();
@@ -52173,6 +52193,14 @@ var BABYLON;
             this._changes.changed = this._changes.pressChanged || this._changes.touchChanged || this._changes.valueChanged;
             return this._changes;
         };
+        WebVRController.prototype.dispose = function () {
+            _super.prototype.dispose.call(this);
+            this.onTriggerStateChangedObservable.clear();
+            this.onMainButtonStateChangedObservable.clear();
+            this.onSecondaryButtonStateChangedObservable.clear();
+            this.onPadStateChangedObservable.clear();
+            this.onPadValuesChangedObservable.clear();
+        };
         return WebVRController;
     }(BABYLON.PoseEnabledController));
     BABYLON.WebVRController = WebVRController;
@@ -52451,6 +52479,13 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
+    var LoadedMeshInfo = (function () {
+        function LoadedMeshInfo() {
+            this.buttonMeshes = {};
+            this.axisMeshes = {};
+        }
+        return LoadedMeshInfo;
+    }());
     var WindowsMotionController = (function (_super) {
         __extends(WindowsMotionController, _super);
         function WindowsMotionController(vrGamepad) {
@@ -52488,7 +52523,6 @@ var BABYLON;
             };
             _this.onTrackpadChangedObservable = new BABYLON.Observable();
             _this.controllerType = BABYLON.PoseEnabledControllerType.WINDOWS;
-            _this._parentMeshName = _this.id + " " + _this.hand;
             _this._loadedMeshInfo = null;
             return _this;
         }
@@ -52549,8 +52583,9 @@ var BABYLON;
          */
         WindowsMotionController.prototype.handleButtonChange = function (buttonIdx, state, changes) {
             var buttonName = this._mapping.buttons[buttonIdx];
-            if (!buttonName)
+            if (!buttonName) {
                 return;
+            }
             // Only emit events for buttons that we know how to map from index to name
             var observable = this[this._mapping.buttonObservableNames[buttonName]];
             if (observable) {
@@ -52560,16 +52595,18 @@ var BABYLON;
         };
         WindowsMotionController.prototype.lerpButtonTransform = function (buttonName, buttonValue) {
             // If there is no loaded mesh, there is nothing to transform.
-            if (!this._loadedMeshInfo)
+            if (!this._loadedMeshInfo) {
                 return;
+            }
             var meshInfo = this._loadedMeshInfo.buttonMeshes[buttonName];
             BABYLON.Quaternion.SlerpToRef(meshInfo.unpressed.rotationQuaternion, meshInfo.pressed.rotationQuaternion, buttonValue, meshInfo.value.rotationQuaternion);
             BABYLON.Vector3.LerpToRef(meshInfo.unpressed.position, meshInfo.pressed.position, buttonValue, meshInfo.value.position);
         };
         WindowsMotionController.prototype.lerpAxisTransform = function (axis, axisValue) {
             var meshInfo = this._loadedMeshInfo.axisMeshes[axis];
-            if (!meshInfo)
+            if (!meshInfo) {
                 return;
+            }
             // Convert from gamepad value range (-1 to +1) to lerp range (0 to 1)
             var lerpValue = axisValue * 0.5 + 0.5;
             BABYLON.Quaternion.SlerpToRef(meshInfo.min.rotationQuaternion, meshInfo.max.rotationQuaternion, lerpValue, meshInfo.value.rotationQuaternion);
@@ -52582,73 +52619,36 @@ var BABYLON;
          */
         WindowsMotionController.prototype.initControllerMesh = function (scene, meshLoaded) {
             var _this = this;
-            var parentMesh = scene.getMeshByName(this._parentMeshName);
-            if (parentMesh) {
-                // A mesh with the name we are expecting already exists in the scene, use that.
-                if (!this._loadedMeshInfo) {
-                    // Create our mesh info. Note that this method will always return non-null.
-                    this._loadedMeshInfo = this.createMeshInfo(parentMesh);
-                    this.attachToMesh(this._loadedMeshInfo.rootNode);
-                }
-                if (meshLoaded)
-                    meshLoaded(this._loadedMeshInfo.rootNode);
+            // Determine the device specific folder based on the ID suffix
+            var device = 'default';
+            if (this.id) {
+                var match = this.id.match(WindowsMotionController.GAMEPAD_ID_PATTERN);
+                device = ((match && match[0]) || device);
+            }
+            // Hand
+            var filename;
+            if (this.hand === 'left') {
+                filename = WindowsMotionController.MODEL_LEFT_FILENAME;
             }
             else {
-                // Make a call to load a mesh from CDN
-                this.loadModel(scene)
-                    .then(function (mesh) {
-                    _this.attachToMesh(mesh);
-                    if (meshLoaded)
-                        meshLoaded(mesh);
-                })
-                    .catch(function (message) {
-                    BABYLON.Tools.Warn(message);
-                    // We failed to load our custom models; fall back and attempt to the generic model.
-                    _super.prototype.initControllerMesh.call(_this, scene, meshLoaded);
-                });
+                filename = WindowsMotionController.MODEL_RIGHT_FILENAME;
             }
-        };
-        /**
-         * Starts a load request to get model data from the remote server, then parse it to ensure a valid format.
-         * If the first attempt fails, a second attempt will be made to retrieve a fallback model which is (non specific to the device ID suffix)
-         *
-         * @param scene in which to insert new Meshes
-         * @return A promise that resolves with the mesh that represents the loaded controller model, or rejects with an error message.
-         */
-        WindowsMotionController.prototype.loadModel = function (scene) {
-            var _this = this;
-            var self = this;
-            return new Promise(function (resolve, reject) {
-                // First attempt, use ID Suffix specific URL
-                attemptLoad(_this.createControllerModelUrl(false))
-                    .then(resolve)
-                    .catch(function (message) {
-                    BABYLON.Tools.Warn(message);
-                    // Second attempt, use fallback URL
-                    attemptLoad(_this.createControllerModelUrl(true))
-                        .then(resolve)
-                        .catch(reject);
-                });
+            var path = WindowsMotionController.MODEL_BASE_URL + device + '/';
+            BABYLON.SceneLoader.ImportMesh("", path, filename, scene, function (meshes) {
+                // glTF files successfully loaded from the remote server, now process them to ensure they are in the right format.
+                _this._loadedMeshInfo = _this.processModel(scene, meshes);
+                if (!_this._loadedMeshInfo) {
+                    return;
+                }
+                _this._defaultModel = _this._loadedMeshInfo.rootNode;
+                _this.attachToMesh(_this._defaultModel);
+                if (meshLoaded) {
+                    meshLoaded(_this._defaultModel);
+                }
+            }, null, function (scene, message) {
+                BABYLON.Tools.Log(message);
+                BABYLON.Tools.Warn('Failed to retrieve controller model from the remote server: ' + path + filename);
             });
-            function attemptLoad(controllerSrc) {
-                var _this = this;
-                return new Promise(function (resolve, reject) {
-                    BABYLON.SceneLoader.ImportMesh("" /* all meshes */, controllerSrc.path, controllerSrc.name, scene, function (meshes) {
-                        // glTF files successfully loaded from the remote server, now process them to ensure they are in the right format.
-                        _this._loadedMeshInfo = self.processModel(scene, meshes);
-                        if (_this._loadedMeshInfo) {
-                            // Mesh data processed successfully!
-                            resolve(_this._loadedMeshInfo.rootNode);
-                        }
-                        else {
-                            reject('Failed to parse controller model for device');
-                        }
-                    }, null, function (scene, message) {
-                        BABYLON.Tools.Log(message);
-                        reject('Failed to retrieve controller model from the remote server: ' + controllerSrc.path + controllerSrc.name);
-                    });
-                });
-            }
         };
         /**
          * Takes a list of meshes (as loaded from the glTF file) and finds the root node, as well as nodes that
@@ -52661,7 +52661,7 @@ var BABYLON;
         WindowsMotionController.prototype.processModel = function (scene, meshes) {
             var loadedMeshInfo = null;
             // Create a new mesh to contain the glTF hierarchy
-            var parentMesh = new BABYLON.Mesh(this._parentMeshName, scene);
+            var parentMesh = new BABYLON.Mesh(this.id + " " + this.hand, scene);
             // Find the root node in the loaded glTF scene, and attach it as a child of 'parentMesh'
             var childMesh = null;
             for (var i = 0; i < meshes.length; i++) {
@@ -52690,34 +52690,6 @@ var BABYLON;
             }
             return loadedMeshInfo;
         };
-        /**
-         * Helper function that constructs a URL from the controller ID suffix, for future proofed
-         * art assets.
-         */
-        WindowsMotionController.prototype.createControllerModelUrl = function (forceDefault) {
-            // Determine the device specific folder based on the ID suffix
-            var device = 'default';
-            if (!forceDefault) {
-                if (this.id) {
-                    var match = this.id.match(WindowsMotionController.GAMEPAD_ID_PATTERN);
-                    device = ((match && match[0]) || device);
-                }
-            }
-            // Hand
-            var filename;
-            if (this.hand === 'left')
-                filename = WindowsMotionController.MODEL_LEFT_FILENAME;
-            else if (this.hand === 'right')
-                filename = WindowsMotionController.MODEL_RIGHT_FILENAME;
-            else
-                filename = WindowsMotionController.MODEL_UNIVERSAL_FILENAME;
-            // Final url
-            return {
-                //                path: WindowsMotionController.MODEL_BASE_URL + device + '/',
-                path: WindowsMotionController.MODEL_BASE_URL,
-                name: filename
-            };
-        };
         WindowsMotionController.prototype.createMeshInfo = function (rootNode) {
             var loadedMeshInfo = new LoadedMeshInfo();
             var i;
@@ -52795,27 +52767,22 @@ var BABYLON;
                 return node.getChildMeshes(true, function (n) { return n.name == name; })[0];
             }
         };
-        // TODO: Update with final asset URL's
-        WindowsMotionController.MODEL_BASE_URL = 'http://yoda.blob.core.windows.net/models/';
-        WindowsMotionController.MODEL_LEFT_FILENAME = 'genericvrcontroller.babylon';
-        WindowsMotionController.MODEL_RIGHT_FILENAME = 'genericvrcontroller.babylon';
-        WindowsMotionController.MODEL_UNIVERSAL_FILENAME = 'genericvrcontroller.babylon';
+        WindowsMotionController.prototype.dispose = function () {
+            _super.prototype.dispose.call(this);
+            this.onTrackpadChangedObservable.clear();
+        };
+        WindowsMotionController.MODEL_BASE_URL = 'https://controllers.babylonjs.com/';
+        WindowsMotionController.MODEL_LEFT_FILENAME = 'left.glb';
+        WindowsMotionController.MODEL_RIGHT_FILENAME = 'right.glb';
         WindowsMotionController.MODEL_ROOT_NODE_NAME = 'RootNode';
         WindowsMotionController.GLTF_ROOT_TRANSFORM_NAME = 'root';
         WindowsMotionController.GAMEPAD_ID_PREFIX = 'Spatial Controller (Spatial Interaction Source) ';
         WindowsMotionController.GAMEPAD_ID_PATTERN = /([0-9a-zA-Z]+-[0-9a-zA-Z]+)$/;
-        // TODO: Why do we need to flip the model around? Art asset or BabylonJS specific?
+        // Art assets is backward facing
         WindowsMotionController.ROTATE_OFFSET = [Math.PI, 0, 0]; // x, y, z.
         return WindowsMotionController;
-    }(BABYLON.GenericController));
+    }(BABYLON.WebVRController));
     BABYLON.WindowsMotionController = WindowsMotionController;
-    var LoadedMeshInfo = (function () {
-        function LoadedMeshInfo() {
-            this.buttonMeshes = {};
-            this.axisMeshes = {};
-        }
-        return LoadedMeshInfo;
-    }());
 })(BABYLON || (BABYLON = {}));
 
 //# sourceMappingURL=babylon.windowsMotionController.js.map

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 7536 - 7548
dist/preview release/babylon.module.d.ts


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 43 - 43
dist/preview release/babylon.worker.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 8610 - 8622
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 45 - 45
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js


+ 93 - 122
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js

@@ -7629,6 +7629,7 @@ var BABYLON;
              * Observable event triggered each time the canvas receives pointerout event
              */
             this.onCanvasPointerOutObservable = new BABYLON.Observable();
+            this._vrExclusivePointerMode = false;
             // Uniform buffers list
             this.disableUniformBuffers = false;
             this._uniformBuffers = new Array();
@@ -7859,9 +7860,13 @@ var BABYLON;
                 document.addEventListener("mozpointerlockchange", this._onPointerLockChange, false);
                 document.addEventListener("webkitpointerlockchange", this._onPointerLockChange, false);
                 this._onVRDisplayPointerRestricted = function () {
+                    _this._vrExclusivePointerMode = true;
+                    console.log("enter");
                     canvas.requestPointerLock();
                 };
                 this._onVRDisplayPointerUnrestricted = function () {
+                    _this._vrExclusivePointerMode = false;
+                    console.log("exit");
                     document.exitPointerLock();
                 };
                 window.addEventListener('vrdisplaypointerrestricted', this._onVRDisplayPointerRestricted, false);
@@ -8214,6 +8219,13 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(Engine.prototype, "isInVRExclusivePointerMode", {
+            get: function () {
+                return this._vrExclusivePointerMode;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(Engine.prototype, "supportsUniformBuffers", {
             get: function () {
                 return this.webGLVersion > 1 && !this.disableUniformBuffers;
@@ -15215,10 +15227,6 @@ var BABYLON;
             this._cache.renderWidth = engine.getRenderWidth();
             this._cache.renderHeight = engine.getRenderHeight();
         };
-        Camera.prototype._updateFromScene = function () {
-            this.updateCache();
-            this.update();
-        };
         // Synchronized
         Camera.prototype._isSynchronized = function () {
             return this._isSynchronizedViewMatrix() && this._isSynchronizedProjectionMatrix();
@@ -18806,6 +18814,7 @@ var BABYLON;
             // Camera
             this.resetCachedMaterial();
             this._renderId++;
+            this.activeCamera.update();
             this.updateTransformMatrix();
             if (camera._alternateCamera) {
                 this.updateAlternateTransformMatrix(camera._alternateCamera);
@@ -18941,7 +18950,7 @@ var BABYLON;
             // Finalize frame
             this.postProcessManager._finalizeFrame(camera.isIntermediate);
             // Update camera
-            this.activeCamera._updateFromScene();
+            this.activeCamera.updateCache();
             // Reset some special arrays
             this._renderTargets.reset();
             this._alternateRendering = false;
@@ -18953,14 +18962,15 @@ var BABYLON;
                 this._renderForCamera(camera);
                 return;
             }
+            // Update camera
+            this.activeCamera.update();
             // rig cameras
             for (var index = 0; index < camera._rigCameras.length; index++) {
                 this._renderForCamera(camera._rigCameras[index]);
             }
             this.activeCamera = camera;
             this.setTransformMatrix(this.activeCamera.getViewMatrix(), this.activeCamera.getProjectionMatrix());
-            // Update camera
-            this.activeCamera._updateFromScene();
+            this.activeCamera.updateCache();
         };
         Scene.prototype._checkIntersections = function () {
             for (var index = 0; index < this._meshesForIntersections.length; index++) {
@@ -34375,6 +34385,9 @@ var BABYLON;
             if (!this._pointerInput) {
                 this._pointerInput = function (p, s) {
                     var evt = p.event;
+                    if (engine.isInVRExclusivePointerMode) {
+                        return;
+                    }
                     if (!_this.touchEnabled && evt.pointerType === "touch") {
                         return;
                     }
@@ -34436,6 +34449,9 @@ var BABYLON;
                 if (!engine.isPointerLock) {
                     return;
                 }
+                if (engine.isInVRExclusivePointerMode) {
+                    return;
+                }
                 var offsetX = evt.movementX || evt.mozMovementX || evt.webkitMovementX || evt.msMovementX || 0;
                 var offsetY = evt.movementY || evt.mozMovementY || evt.webkitMovementY || evt.msMovementY || 0;
                 if (_this.camera.getScene().useRightHandedSystem) {
@@ -35381,6 +35397,9 @@ var BABYLON;
             var previousMultiTouchPanPosition = { x: 0, y: 0, isPaning: false };
             this._pointerInput = function (p, s) {
                 var evt = p.event;
+                if (engine.isInVRExclusivePointerMode) {
+                    return;
+                }
                 if (p.type !== BABYLON.PointerEventTypes.POINTERMOVE && _this.buttons.indexOf(evt.button) === -1) {
                     return;
                 }
@@ -52101,6 +52120,7 @@ var BABYLON;
         __extends(WebVRController, _super);
         function WebVRController(vrGamepad) {
             var _this = _super.call(this, vrGamepad) || this;
+            // Observables
             _this.onTriggerStateChangedObservable = new BABYLON.Observable();
             _this.onMainButtonStateChangedObservable = new BABYLON.Observable();
             _this.onSecondaryButtonStateChangedObservable = new BABYLON.Observable();
@@ -52173,6 +52193,14 @@ var BABYLON;
             this._changes.changed = this._changes.pressChanged || this._changes.touchChanged || this._changes.valueChanged;
             return this._changes;
         };
+        WebVRController.prototype.dispose = function () {
+            _super.prototype.dispose.call(this);
+            this.onTriggerStateChangedObservable.clear();
+            this.onMainButtonStateChangedObservable.clear();
+            this.onSecondaryButtonStateChangedObservable.clear();
+            this.onPadStateChangedObservable.clear();
+            this.onPadValuesChangedObservable.clear();
+        };
         return WebVRController;
     }(BABYLON.PoseEnabledController));
     BABYLON.WebVRController = WebVRController;
@@ -52451,6 +52479,13 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
+    var LoadedMeshInfo = (function () {
+        function LoadedMeshInfo() {
+            this.buttonMeshes = {};
+            this.axisMeshes = {};
+        }
+        return LoadedMeshInfo;
+    }());
     var WindowsMotionController = (function (_super) {
         __extends(WindowsMotionController, _super);
         function WindowsMotionController(vrGamepad) {
@@ -52488,7 +52523,6 @@ var BABYLON;
             };
             _this.onTrackpadChangedObservable = new BABYLON.Observable();
             _this.controllerType = BABYLON.PoseEnabledControllerType.WINDOWS;
-            _this._parentMeshName = _this.id + " " + _this.hand;
             _this._loadedMeshInfo = null;
             return _this;
         }
@@ -52549,8 +52583,9 @@ var BABYLON;
          */
         WindowsMotionController.prototype.handleButtonChange = function (buttonIdx, state, changes) {
             var buttonName = this._mapping.buttons[buttonIdx];
-            if (!buttonName)
+            if (!buttonName) {
                 return;
+            }
             // Only emit events for buttons that we know how to map from index to name
             var observable = this[this._mapping.buttonObservableNames[buttonName]];
             if (observable) {
@@ -52560,16 +52595,18 @@ var BABYLON;
         };
         WindowsMotionController.prototype.lerpButtonTransform = function (buttonName, buttonValue) {
             // If there is no loaded mesh, there is nothing to transform.
-            if (!this._loadedMeshInfo)
+            if (!this._loadedMeshInfo) {
                 return;
+            }
             var meshInfo = this._loadedMeshInfo.buttonMeshes[buttonName];
             BABYLON.Quaternion.SlerpToRef(meshInfo.unpressed.rotationQuaternion, meshInfo.pressed.rotationQuaternion, buttonValue, meshInfo.value.rotationQuaternion);
             BABYLON.Vector3.LerpToRef(meshInfo.unpressed.position, meshInfo.pressed.position, buttonValue, meshInfo.value.position);
         };
         WindowsMotionController.prototype.lerpAxisTransform = function (axis, axisValue) {
             var meshInfo = this._loadedMeshInfo.axisMeshes[axis];
-            if (!meshInfo)
+            if (!meshInfo) {
                 return;
+            }
             // Convert from gamepad value range (-1 to +1) to lerp range (0 to 1)
             var lerpValue = axisValue * 0.5 + 0.5;
             BABYLON.Quaternion.SlerpToRef(meshInfo.min.rotationQuaternion, meshInfo.max.rotationQuaternion, lerpValue, meshInfo.value.rotationQuaternion);
@@ -52582,73 +52619,36 @@ var BABYLON;
          */
         WindowsMotionController.prototype.initControllerMesh = function (scene, meshLoaded) {
             var _this = this;
-            var parentMesh = scene.getMeshByName(this._parentMeshName);
-            if (parentMesh) {
-                // A mesh with the name we are expecting already exists in the scene, use that.
-                if (!this._loadedMeshInfo) {
-                    // Create our mesh info. Note that this method will always return non-null.
-                    this._loadedMeshInfo = this.createMeshInfo(parentMesh);
-                    this.attachToMesh(this._loadedMeshInfo.rootNode);
-                }
-                if (meshLoaded)
-                    meshLoaded(this._loadedMeshInfo.rootNode);
+            // Determine the device specific folder based on the ID suffix
+            var device = 'default';
+            if (this.id) {
+                var match = this.id.match(WindowsMotionController.GAMEPAD_ID_PATTERN);
+                device = ((match && match[0]) || device);
+            }
+            // Hand
+            var filename;
+            if (this.hand === 'left') {
+                filename = WindowsMotionController.MODEL_LEFT_FILENAME;
             }
             else {
-                // Make a call to load a mesh from CDN
-                this.loadModel(scene)
-                    .then(function (mesh) {
-                    _this.attachToMesh(mesh);
-                    if (meshLoaded)
-                        meshLoaded(mesh);
-                })
-                    .catch(function (message) {
-                    BABYLON.Tools.Warn(message);
-                    // We failed to load our custom models; fall back and attempt to the generic model.
-                    _super.prototype.initControllerMesh.call(_this, scene, meshLoaded);
-                });
+                filename = WindowsMotionController.MODEL_RIGHT_FILENAME;
             }
-        };
-        /**
-         * Starts a load request to get model data from the remote server, then parse it to ensure a valid format.
-         * If the first attempt fails, a second attempt will be made to retrieve a fallback model which is (non specific to the device ID suffix)
-         *
-         * @param scene in which to insert new Meshes
-         * @return A promise that resolves with the mesh that represents the loaded controller model, or rejects with an error message.
-         */
-        WindowsMotionController.prototype.loadModel = function (scene) {
-            var _this = this;
-            var self = this;
-            return new Promise(function (resolve, reject) {
-                // First attempt, use ID Suffix specific URL
-                attemptLoad(_this.createControllerModelUrl(false))
-                    .then(resolve)
-                    .catch(function (message) {
-                    BABYLON.Tools.Warn(message);
-                    // Second attempt, use fallback URL
-                    attemptLoad(_this.createControllerModelUrl(true))
-                        .then(resolve)
-                        .catch(reject);
-                });
+            var path = WindowsMotionController.MODEL_BASE_URL + device + '/';
+            BABYLON.SceneLoader.ImportMesh("", path, filename, scene, function (meshes) {
+                // glTF files successfully loaded from the remote server, now process them to ensure they are in the right format.
+                _this._loadedMeshInfo = _this.processModel(scene, meshes);
+                if (!_this._loadedMeshInfo) {
+                    return;
+                }
+                _this._defaultModel = _this._loadedMeshInfo.rootNode;
+                _this.attachToMesh(_this._defaultModel);
+                if (meshLoaded) {
+                    meshLoaded(_this._defaultModel);
+                }
+            }, null, function (scene, message) {
+                BABYLON.Tools.Log(message);
+                BABYLON.Tools.Warn('Failed to retrieve controller model from the remote server: ' + path + filename);
             });
-            function attemptLoad(controllerSrc) {
-                var _this = this;
-                return new Promise(function (resolve, reject) {
-                    BABYLON.SceneLoader.ImportMesh("" /* all meshes */, controllerSrc.path, controllerSrc.name, scene, function (meshes) {
-                        // glTF files successfully loaded from the remote server, now process them to ensure they are in the right format.
-                        _this._loadedMeshInfo = self.processModel(scene, meshes);
-                        if (_this._loadedMeshInfo) {
-                            // Mesh data processed successfully!
-                            resolve(_this._loadedMeshInfo.rootNode);
-                        }
-                        else {
-                            reject('Failed to parse controller model for device');
-                        }
-                    }, null, function (scene, message) {
-                        BABYLON.Tools.Log(message);
-                        reject('Failed to retrieve controller model from the remote server: ' + controllerSrc.path + controllerSrc.name);
-                    });
-                });
-            }
         };
         /**
          * Takes a list of meshes (as loaded from the glTF file) and finds the root node, as well as nodes that
@@ -52661,7 +52661,7 @@ var BABYLON;
         WindowsMotionController.prototype.processModel = function (scene, meshes) {
             var loadedMeshInfo = null;
             // Create a new mesh to contain the glTF hierarchy
-            var parentMesh = new BABYLON.Mesh(this._parentMeshName, scene);
+            var parentMesh = new BABYLON.Mesh(this.id + " " + this.hand, scene);
             // Find the root node in the loaded glTF scene, and attach it as a child of 'parentMesh'
             var childMesh = null;
             for (var i = 0; i < meshes.length; i++) {
@@ -52690,34 +52690,6 @@ var BABYLON;
             }
             return loadedMeshInfo;
         };
-        /**
-         * Helper function that constructs a URL from the controller ID suffix, for future proofed
-         * art assets.
-         */
-        WindowsMotionController.prototype.createControllerModelUrl = function (forceDefault) {
-            // Determine the device specific folder based on the ID suffix
-            var device = 'default';
-            if (!forceDefault) {
-                if (this.id) {
-                    var match = this.id.match(WindowsMotionController.GAMEPAD_ID_PATTERN);
-                    device = ((match && match[0]) || device);
-                }
-            }
-            // Hand
-            var filename;
-            if (this.hand === 'left')
-                filename = WindowsMotionController.MODEL_LEFT_FILENAME;
-            else if (this.hand === 'right')
-                filename = WindowsMotionController.MODEL_RIGHT_FILENAME;
-            else
-                filename = WindowsMotionController.MODEL_UNIVERSAL_FILENAME;
-            // Final url
-            return {
-                //                path: WindowsMotionController.MODEL_BASE_URL + device + '/',
-                path: WindowsMotionController.MODEL_BASE_URL,
-                name: filename
-            };
-        };
         WindowsMotionController.prototype.createMeshInfo = function (rootNode) {
             var loadedMeshInfo = new LoadedMeshInfo();
             var i;
@@ -52795,27 +52767,22 @@ var BABYLON;
                 return node.getChildMeshes(true, function (n) { return n.name == name; })[0];
             }
         };
-        // TODO: Update with final asset URL's
-        WindowsMotionController.MODEL_BASE_URL = 'http://yoda.blob.core.windows.net/models/';
-        WindowsMotionController.MODEL_LEFT_FILENAME = 'genericvrcontroller.babylon';
-        WindowsMotionController.MODEL_RIGHT_FILENAME = 'genericvrcontroller.babylon';
-        WindowsMotionController.MODEL_UNIVERSAL_FILENAME = 'genericvrcontroller.babylon';
+        WindowsMotionController.prototype.dispose = function () {
+            _super.prototype.dispose.call(this);
+            this.onTrackpadChangedObservable.clear();
+        };
+        WindowsMotionController.MODEL_BASE_URL = 'https://controllers.babylonjs.com/';
+        WindowsMotionController.MODEL_LEFT_FILENAME = 'left.glb';
+        WindowsMotionController.MODEL_RIGHT_FILENAME = 'right.glb';
         WindowsMotionController.MODEL_ROOT_NODE_NAME = 'RootNode';
         WindowsMotionController.GLTF_ROOT_TRANSFORM_NAME = 'root';
         WindowsMotionController.GAMEPAD_ID_PREFIX = 'Spatial Controller (Spatial Interaction Source) ';
         WindowsMotionController.GAMEPAD_ID_PATTERN = /([0-9a-zA-Z]+-[0-9a-zA-Z]+)$/;
-        // TODO: Why do we need to flip the model around? Art asset or BabylonJS specific?
+        // Art assets is backward facing
         WindowsMotionController.ROTATE_OFFSET = [Math.PI, 0, 0]; // x, y, z.
         return WindowsMotionController;
-    }(BABYLON.GenericController));
+    }(BABYLON.WebVRController));
     BABYLON.WindowsMotionController = WindowsMotionController;
-    var LoadedMeshInfo = (function () {
-        function LoadedMeshInfo() {
-            this.buttonMeshes = {};
-            this.axisMeshes = {};
-        }
-        return LoadedMeshInfo;
-    }());
 })(BABYLON || (BABYLON = {}));
 
 //# sourceMappingURL=babylon.windowsMotionController.js.map
@@ -75132,21 +75099,25 @@ var BABYLON;
                 }
             };
             GLTFLoader.prototype._addRightHandToLeftHandRootTransform = function () {
-                var rootMesh = new BABYLON.Mesh("root", this._babylonScene);
-                rootMesh.scaling = new BABYLON.Vector3(1, 1, -1);
-                rootMesh.rotation.y = Math.PI;
+                this._rootMesh = new BABYLON.Mesh("root", this._babylonScene);
+                this._rootMesh.isVisible = false;
+                this._rootMesh.scaling = new BABYLON.Vector3(1, 1, -1);
+                this._rootMesh.rotation.y = Math.PI;
                 var nodes = this._gltf.nodes;
                 if (nodes) {
                     for (var i = 0; i < nodes.length; i++) {
                         var mesh = nodes[i].babylonMesh;
                         if (mesh && !mesh.parent) {
-                            mesh.parent = rootMesh;
+                            mesh.parent = this._rootMesh;
                         }
                     }
                 }
             };
             GLTFLoader.prototype._getMeshes = function () {
                 var meshes = [];
+                if (this._rootMesh) {
+                    meshes.push(this._rootMesh);
+                }
                 var nodes = this._gltf.nodes;
                 if (nodes) {
                     nodes.forEach(function (node) {
@@ -76090,7 +76061,7 @@ var BABYLON;
             GLTFUtils.GetTextureSamplingMode = function (magFilter, minFilter) {
                 // Set defaults if undefined
                 magFilter = magFilter === undefined ? GLTF2.ETextureMagFilter.LINEAR : magFilter;
-                minFilter = minFilter === undefined ? GLTF2.ETextureMinFilter.LINEAR_MIPMAP_NEAREST : minFilter;
+                minFilter = minFilter === undefined ? GLTF2.ETextureMinFilter.LINEAR_MIPMAP_LINEAR : minFilter;
                 if (magFilter === GLTF2.ETextureMagFilter.LINEAR) {
                     switch (minFilter) {
                         case GLTF2.ETextureMinFilter.NEAREST: return BABYLON.Texture.LINEAR_NEAREST;

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 8610 - 8622
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.module.d.ts


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 3 - 3
dist/preview release/gui/babylon.gui.min.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 263 - 263
dist/preview release/inspector/babylon.inspector.bundle.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 3 - 3
dist/preview release/inspector/babylon.inspector.min.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 2 - 2
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


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

@@ -301,6 +301,7 @@ declare module BABYLON.GLTF2 {
         private _disposed;
         private _blockPendingTracking;
         private _nonBlockingData;
+        private _rootMesh;
         private _renderReadyObservable;
         private _renderPendingCount;
         private _loaderPendingCount;

+ 9 - 5
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -462,21 +462,25 @@ var BABYLON;
                 }
             };
             GLTFLoader.prototype._addRightHandToLeftHandRootTransform = function () {
-                var rootMesh = new BABYLON.Mesh("root", this._babylonScene);
-                rootMesh.scaling = new BABYLON.Vector3(1, 1, -1);
-                rootMesh.rotation.y = Math.PI;
+                this._rootMesh = new BABYLON.Mesh("root", this._babylonScene);
+                this._rootMesh.isVisible = false;
+                this._rootMesh.scaling = new BABYLON.Vector3(1, 1, -1);
+                this._rootMesh.rotation.y = Math.PI;
                 var nodes = this._gltf.nodes;
                 if (nodes) {
                     for (var i = 0; i < nodes.length; i++) {
                         var mesh = nodes[i].babylonMesh;
                         if (mesh && !mesh.parent) {
-                            mesh.parent = rootMesh;
+                            mesh.parent = this._rootMesh;
                         }
                     }
                 }
             };
             GLTFLoader.prototype._getMeshes = function () {
                 var meshes = [];
+                if (this._rootMesh) {
+                    meshes.push(this._rootMesh);
+                }
                 var nodes = this._gltf.nodes;
                 if (nodes) {
                     nodes.forEach(function (node) {
@@ -1420,7 +1424,7 @@ var BABYLON;
             GLTFUtils.GetTextureSamplingMode = function (magFilter, minFilter) {
                 // Set defaults if undefined
                 magFilter = magFilter === undefined ? GLTF2.ETextureMagFilter.LINEAR : magFilter;
-                minFilter = minFilter === undefined ? GLTF2.ETextureMinFilter.LINEAR_MIPMAP_NEAREST : minFilter;
+                minFilter = minFilter === undefined ? GLTF2.ETextureMinFilter.LINEAR_MIPMAP_LINEAR : minFilter;
                 if (magFilter === GLTF2.ETextureMagFilter.LINEAR) {
                     switch (minFilter) {
                         case GLTF2.ETextureMinFilter.NEAREST: return BABYLON.Texture.LINEAR_NEAREST;

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


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

@@ -797,6 +797,7 @@ declare module BABYLON.GLTF2 {
         private _disposed;
         private _blockPendingTracking;
         private _nonBlockingData;
+        private _rootMesh;
         private _renderReadyObservable;
         private _renderPendingCount;
         private _loaderPendingCount;

+ 9 - 5
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -2620,21 +2620,25 @@ var BABYLON;
                 }
             };
             GLTFLoader.prototype._addRightHandToLeftHandRootTransform = function () {
-                var rootMesh = new BABYLON.Mesh("root", this._babylonScene);
-                rootMesh.scaling = new BABYLON.Vector3(1, 1, -1);
-                rootMesh.rotation.y = Math.PI;
+                this._rootMesh = new BABYLON.Mesh("root", this._babylonScene);
+                this._rootMesh.isVisible = false;
+                this._rootMesh.scaling = new BABYLON.Vector3(1, 1, -1);
+                this._rootMesh.rotation.y = Math.PI;
                 var nodes = this._gltf.nodes;
                 if (nodes) {
                     for (var i = 0; i < nodes.length; i++) {
                         var mesh = nodes[i].babylonMesh;
                         if (mesh && !mesh.parent) {
-                            mesh.parent = rootMesh;
+                            mesh.parent = this._rootMesh;
                         }
                     }
                 }
             };
             GLTFLoader.prototype._getMeshes = function () {
                 var meshes = [];
+                if (this._rootMesh) {
+                    meshes.push(this._rootMesh);
+                }
                 var nodes = this._gltf.nodes;
                 if (nodes) {
                     nodes.forEach(function (node) {
@@ -3578,7 +3582,7 @@ var BABYLON;
             GLTFUtils.GetTextureSamplingMode = function (magFilter, minFilter) {
                 // Set defaults if undefined
                 magFilter = magFilter === undefined ? GLTF2.ETextureMagFilter.LINEAR : magFilter;
-                minFilter = minFilter === undefined ? GLTF2.ETextureMinFilter.LINEAR_MIPMAP_NEAREST : minFilter;
+                minFilter = minFilter === undefined ? GLTF2.ETextureMinFilter.LINEAR_MIPMAP_LINEAR : minFilter;
                 if (magFilter === GLTF2.ETextureMagFilter.LINEAR) {
                     switch (minFilter) {
                         case GLTF2.ETextureMinFilter.NEAREST: return BABYLON.Texture.LINEAR_NEAREST;

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 3 - 3
dist/preview release/loaders/babylon.glTFFileLoader.min.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1 - 1
dist/preview release/loaders/babylon.objFileLoader.min.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1 - 1
dist/preview release/materialsLibrary/babylon.customMaterial.min.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1 - 1
dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1 - 1
dist/preview release/materialsLibrary/babylon.waterMaterial.min.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js


+ 10 - 4
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -14,6 +14,7 @@ module BABYLON.GLTF2 {
         private _disposed: boolean = false;
         private _blockPendingTracking: boolean = false;
         private _nonBlockingData: Array<any>;
+        private _rootMesh: Mesh;
 
         // Observable with boolean indicating success or error.
         private _renderReadyObservable = new Observable<GLTFLoader>();
@@ -181,16 +182,17 @@ module BABYLON.GLTF2 {
         }
 
         private _addRightHandToLeftHandRootTransform(): void {
-            var rootMesh = new Mesh("root", this._babylonScene);
-            rootMesh.scaling = new Vector3(1, 1, -1);
-            rootMesh.rotation.y = Math.PI;
+            this._rootMesh = new Mesh("root", this._babylonScene);
+            this._rootMesh.isVisible = false;
+            this._rootMesh.scaling = new Vector3(1, 1, -1);
+            this._rootMesh.rotation.y = Math.PI;
 
             var nodes = this._gltf.nodes;
             if (nodes) {
                 for (var i = 0; i < nodes.length; i++) {
                     var mesh = nodes[i].babylonMesh;
                     if (mesh && !mesh.parent) {
-                        mesh.parent = rootMesh;
+                        mesh.parent = this._rootMesh;
                     }
                 }
             }
@@ -199,6 +201,10 @@ module BABYLON.GLTF2 {
         private _getMeshes(): Mesh[] {
             var meshes = [];
 
+            if (this._rootMesh) {
+                meshes.push(this._rootMesh);
+            }
+
             var nodes = this._gltf.nodes;
             if (nodes) {
                 nodes.forEach(node => {

+ 1 - 1
loaders/src/glTF/2.0/babylon.glTFLoaderUtils.ts

@@ -52,7 +52,7 @@ module BABYLON.GLTF2 {
         public static GetTextureSamplingMode(magFilter: ETextureMagFilter, minFilter: ETextureMinFilter): number {
             // Set defaults if undefined
             magFilter = magFilter === undefined ? ETextureMagFilter.LINEAR : magFilter;
-            minFilter = minFilter === undefined ? ETextureMinFilter.LINEAR_MIPMAP_NEAREST : minFilter;
+            minFilter = minFilter === undefined ? ETextureMinFilter.LINEAR_MIPMAP_LINEAR : minFilter;
 
             if (magFilter === ETextureMagFilter.LINEAR) {
                 switch (minFilter) {

+ 4 - 0
src/Cameras/Inputs/babylon.arcRotateCameraPointersInput.ts

@@ -45,6 +45,10 @@ module BABYLON {
             this._pointerInput = (p, s) => {
                 var evt = <PointerEvent>p.event;
 
+                if (engine.isInVRExclusivePointerMode) {
+                    return;
+                }
+
                 if (p.type !== PointerEventTypes.POINTERMOVE && this.buttons.indexOf(evt.button) === -1) {
                     return;
                 }

+ 8 - 0
src/Cameras/Inputs/babylon.freeCameraMouseInput.ts

@@ -24,6 +24,10 @@ module BABYLON {
                 this._pointerInput = (p, s) => {
                     var evt = <PointerEvent>p.event;
 
+                    if (engine.isInVRExclusivePointerMode) {
+                        return;
+                    }
+
                     if (!this.touchEnabled && evt.pointerType === "touch") {
                         return;
                     }
@@ -95,6 +99,10 @@ module BABYLON {
                     return;
                 }
 
+                if (engine.isInVRExclusivePointerMode) {
+                    return;
+                }
+
                 var offsetX = evt.movementX || evt.mozMovementX || evt.webkitMovementX || evt.msMovementX || 0;
                 var offsetY = evt.movementY || evt.mozMovementY || evt.webkitMovementY || evt.msMovementY || 0;
 

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

@@ -278,11 +278,6 @@
             this._cache.renderHeight = engine.getRenderHeight();
         }
 
-        public _updateFromScene(): void {
-            this.updateCache();
-            this.update();
-        }
-
         // Synchronized
         public _isSynchronized(): boolean {
             return this._isSynchronizedViewMatrix() && this._isSynchronizedProjectionMatrix();

+ 12 - 4
src/Gamepad/Controllers/babylon.webVRController.ts

@@ -4,12 +4,10 @@ module BABYLON {
 
         protected _defaultModel: AbstractMesh;
 
+        // Observables
         public onTriggerStateChangedObservable = new Observable<ExtendedGamepadButton>();
-
         public onMainButtonStateChangedObservable = new Observable<ExtendedGamepadButton>();
-
         public onSecondaryButtonStateChangedObservable = new Observable<ExtendedGamepadButton>();
-
         public onPadStateChangedObservable = new Observable<ExtendedGamepadButton>();
         public onPadValuesChangedObservable = new Observable<StickValues>();
 
@@ -94,6 +92,16 @@ module BABYLON {
             this._changes.changed = this._changes.pressChanged || this._changes.touchChanged || this._changes.valueChanged;
             return this._changes;
         }
+
+        public dispose(): void {
+            super.dispose();
+
+            this.onTriggerStateChangedObservable.clear();
+            this.onMainButtonStateChangedObservable.clear();
+            this.onSecondaryButtonStateChangedObservable.clear();
+            this.onPadStateChangedObservable.clear();
+            this.onPadValuesChangedObservable.clear();
+        }
     }
         
-}
+}

+ 84 - 150
src/Gamepad/Controllers/babylon.windowsMotionController.ts

@@ -1,27 +1,46 @@
-
 module BABYLON {
-    declare var Promise: any;
-    export class WindowsMotionController extends GenericController {
-
-        // TODO: Update with final asset URL's
-        private static readonly MODEL_BASE_URL:string = 'http://yoda.blob.core.windows.net/models/';
-        private static readonly MODEL_LEFT_FILENAME:string = 'genericvrcontroller.babylon';
-        private static readonly MODEL_RIGHT_FILENAME:string = 'genericvrcontroller.babylon';
-        private static readonly MODEL_UNIVERSAL_FILENAME:string = 'genericvrcontroller.babylon';
+
+    class LoadedMeshInfo {
+        public rootNode: AbstractMesh;
+        public pointingPoseNode: AbstractMesh;
+        public holdingPoseNode: AbstractMesh;
+        public buttonMeshes: { [id: string] : IButtonMeshInfo; } = {};
+        public axisMeshes: { [id: number] : IAxisMeshInfo; } = {};
+    }
+
+    interface IMeshInfo {
+        index: number;
+        value: AbstractMesh;
+    }
+
+    interface IButtonMeshInfo extends IMeshInfo {
+        pressed: AbstractMesh;
+        unpressed: AbstractMesh;
+    }
+
+    interface IAxisMeshInfo extends IMeshInfo {
+        min: AbstractMesh;
+        max: AbstractMesh;
+    }
+
+    export class WindowsMotionController extends WebVRController {
+        private static readonly MODEL_BASE_URL:string = 'https://controllers.babylonjs.com/';
+        private static readonly MODEL_LEFT_FILENAME:string = 'left.glb';
+        private static readonly MODEL_RIGHT_FILENAME:string = 'right.glb';
         private static readonly MODEL_ROOT_NODE_NAME:string = 'RootNode';
         private static readonly GLTF_ROOT_TRANSFORM_NAME:string = 'root';
 
         public static readonly GAMEPAD_ID_PREFIX:string = 'Spatial Controller (Spatial Interaction Source) ';
         private static readonly GAMEPAD_ID_PATTERN = /([0-9a-zA-Z]+-[0-9a-zA-Z]+)$/;
 
-        // TODO: Why do we need to flip the model around? Art asset or BabylonJS specific?
+        // Art assets is backward facing
         private static readonly ROTATE_OFFSET:number[] = [Math.PI, 0, 0]; // x, y, z.
 
-        private _parentMeshName: string;
         private _loadedMeshInfo: LoadedMeshInfo;
-        private readonly _mapping : IControllerMappingInfo = {
+        private readonly _mapping = {
             // Semantic button names
             buttons: ['thumbstick', 'trigger', 'grip', 'menu', 'trackpad'],
+            
             // A mapping of the button name to glTF model node name
             // that should be transformed by button value.
             buttonMeshNames: {
@@ -56,27 +75,26 @@ module BABYLON {
         constructor(vrGamepad) {
             super(vrGamepad);
             this.controllerType = PoseEnabledControllerType.WINDOWS;
-            this._parentMeshName = this.id + " " + this.hand;
             this._loadedMeshInfo = null;
         }
         
-        public get onTriggerButtonStateChangedObservable() {
+        public get onTriggerButtonStateChangedObservable(): Observable<ExtendedGamepadButton> {
             return this.onTriggerStateChangedObservable;
         }
 
-        public get onMenuButtonStateChangedObservable() {
+        public get onMenuButtonStateChangedObservable(): Observable<ExtendedGamepadButton> {
             return this.onSecondaryButtonStateChangedObservable;
         }
 
-        public get onGripButtonStateChangedObservable() {
+        public get onGripButtonStateChangedObservable(): Observable<ExtendedGamepadButton> {
             return this.onMainButtonStateChangedObservable;
         }
 
-        public get onThumbstickButtonStateChangedObservable() {
+        public get onThumbstickButtonStateChangedObservable(): Observable<ExtendedGamepadButton> {
             return this.onPadStateChangedObservable;
         }    
 
-        public get onTouchpadButtonStateChangedObservable() {
+        public get onTouchpadButtonStateChangedObservable(): Observable<ExtendedGamepadButton> {
             return this.onTrackpadChangedObservable;
         }
         
@@ -104,7 +122,9 @@ module BABYLON {
          */
         protected handleButtonChange(buttonIdx: number, state: ExtendedGamepadButton, changes: GamepadButtonChanges) {
             let buttonName = this._mapping.buttons[buttonIdx];
-            if (!buttonName) return; 
+            if (!buttonName) {
+                return; 
+            }
 
             // Only emit events for buttons that we know how to map from index to name
             let observable = this[this._mapping.buttonObservableNames[buttonName]];
@@ -118,7 +138,9 @@ module BABYLON {
         protected lerpButtonTransform(buttonName: string, buttonValue: number) {
             
             // If there is no loaded mesh, there is nothing to transform.
-            if (!this._loadedMeshInfo) return;
+            if (!this._loadedMeshInfo) {
+                return;
+            }
 
             var meshInfo = this._loadedMeshInfo.buttonMeshes[buttonName];
             BABYLON.Quaternion.SlerpToRef(
@@ -135,7 +157,9 @@ module BABYLON {
         
         protected lerpAxisTransform(axis:number, axisValue: number) {
             let meshInfo = this._loadedMeshInfo.axisMeshes[axis];
-            if (!meshInfo) return;
+            if (!meshInfo) {
+                return;
+            }
 
             // Convert from gamepad value range (-1 to +1) to lerp range (0 to 1)
             let lerpValue = axisValue * 0.5 + 0.5;
@@ -157,73 +181,42 @@ module BABYLON {
          * @param meshLoaded optional callback function that will be called if the mesh loads successfully.
          */
         public initControllerMesh(scene: Scene, meshLoaded?: (mesh: AbstractMesh) => void) {
-            let parentMesh = scene.getMeshByName(this._parentMeshName);
-            if (parentMesh) {
-                // A mesh with the name we are expecting already exists in the scene, use that.
-                if (!this._loadedMeshInfo) {
-                    // Create our mesh info. Note that this method will always return non-null.
-                    this._loadedMeshInfo = this.createMeshInfo(parentMesh);
-                    
-                    this.attachToMesh(this._loadedMeshInfo.rootNode);
-                }
-                if (meshLoaded) meshLoaded(this._loadedMeshInfo.rootNode);
-            } else {
-                // Make a call to load a mesh from CDN
-                this.loadModel(scene)
-                    .then((mesh) => {
-                        this.attachToMesh(mesh);
-                        if (meshLoaded) meshLoaded(mesh);
-                    })
-                    .catch((message) => {
-                        Tools.Warn(message);
-                        // We failed to load our custom models; fall back and attempt to the generic model.
-                        super.initControllerMesh(scene, meshLoaded);
-                    });
+            // Determine the device specific folder based on the ID suffix
+            let device = 'default';
+            if (this.id) {
+                let match = this.id.match(WindowsMotionController.GAMEPAD_ID_PATTERN);
+                device = ((match && match[0]) || device);
             }
-        }
 
-        /**
-         * Starts a load request to get model data from the remote server, then parse it to ensure a valid format.
-         * If the first attempt fails, a second attempt will be made to retrieve a fallback model which is (non specific to the device ID suffix)
-         * 
-         * @param scene in which to insert new Meshes
-         * @return A promise that resolves with the mesh that represents the loaded controller model, or rejects with an error message.
-         */
-        protected loadModel(scene: Scene) : Promise<AbstractMesh> {
-            var self = this;
-            return new Promise((resolve, reject) => {
-                // First attempt, use ID Suffix specific URL
-                attemptLoad(this.createControllerModelUrl(false))
-                    .then(resolve)
-                    .catch((message) => {
-                        Tools.Warn(message);
-                        // Second attempt, use fallback URL
-                        attemptLoad(this.createControllerModelUrl(true))
-                            .then(resolve)
-                            .catch(reject);
-                    });
-                });
-
-            function attemptLoad(controllerSrc) {
-                return new Promise((resolve, reject) => {
-                        SceneLoader.ImportMesh("" /* all meshes */, controllerSrc.path, controllerSrc.name, scene, (meshes: AbstractMesh[]) => {
-                                // glTF files successfully loaded from the remote server, now process them to ensure they are in the right format.
-                                this._loadedMeshInfo = self.processModel(scene, meshes);
-
-                                if (this._loadedMeshInfo) {
-                                    // Mesh data processed successfully!
-                                    resolve(this._loadedMeshInfo.rootNode);
-                                } else {
-                                    reject('Failed to parse controller model for device');
-                                }
-                            }, 
-                            null, 
-                            (scene: Scene, message: string) => {
-                                Tools.Log(message);
-                                reject('Failed to retrieve controller model from the remote server: ' + controllerSrc.path + controllerSrc.name);
-                            });
-                    });
+            // Hand
+            let filename: string;
+            if (this.hand === 'left') {
+                filename = WindowsMotionController.MODEL_LEFT_FILENAME;
+            }
+            else { // Right is the default if no hand is specified
+                filename = WindowsMotionController.MODEL_RIGHT_FILENAME;
             }
+
+            let path = WindowsMotionController.MODEL_BASE_URL + device + '/';
+
+            SceneLoader.ImportMesh("", path, filename, scene, (meshes: AbstractMesh[]) => {
+                // glTF files successfully loaded from the remote server, now process them to ensure they are in the right format.
+                this._loadedMeshInfo = this.processModel(scene, meshes);
+
+                if (!this._loadedMeshInfo) {
+                    return;
+                }
+
+                this._defaultModel = this._loadedMeshInfo.rootNode;
+                this.attachToMesh(this._defaultModel);
+
+                if (meshLoaded) {
+                    meshLoaded(this._defaultModel);
+                }
+            }, null, (scene: Scene, message: string) => {
+                Tools.Log(message);
+                Tools.Warn('Failed to retrieve controller model from the remote server: ' + path + filename);
+            });
         }
 
         /**
@@ -235,11 +228,10 @@ module BABYLON {
          * @return structured view of the given meshes, with mapping of buttons and axes to meshes that can be transformed.
          */
         private processModel(scene: Scene, meshes: AbstractMesh[]) : LoadedMeshInfo {
-
             let loadedMeshInfo = null;
 
             // Create a new mesh to contain the glTF hierarchy
-            let parentMesh = new BABYLON.Mesh(this._parentMeshName, scene);
+            let parentMesh = new BABYLON.Mesh(this.id + " " + this.hand, scene);
 
             // Find the root node in the loaded glTF scene, and attach it as a child of 'parentMesh'
             let childMesh : AbstractMesh = null;
@@ -269,42 +261,13 @@ module BABYLON {
                 var rotOffset = WindowsMotionController.ROTATE_OFFSET;
                 childMesh.addRotation(rotOffset[0], rotOffset[1], rotOffset[2]);
             } else {
-                Tools.Warn('No node with name '+WindowsMotionController.MODEL_ROOT_NODE_NAME+' in model file.');
+                Tools.Warn('No node with name ' + WindowsMotionController.MODEL_ROOT_NODE_NAME +' in model file.');
             }
 
             return loadedMeshInfo;
         }
-
-        /**
-         * Helper function that constructs a URL from the controller ID suffix, for future proofed
-         * art assets.
-         */
-        private createControllerModelUrl(forceDefault: boolean) : IControllerUrl {
-            // Determine the device specific folder based on the ID suffix
-            var device = 'default';
-            if (!forceDefault) {
-                if (this.id) {
-                    var match = this.id.match(WindowsMotionController.GAMEPAD_ID_PATTERN);
-                    device = ((match && match[0]) || device);
-                }
-            }
-
-            // Hand
-            var filename;
-            if (this.hand === 'left') filename = WindowsMotionController.MODEL_LEFT_FILENAME;
-            else if (this.hand === 'right') filename = WindowsMotionController.MODEL_RIGHT_FILENAME;
-            else filename = WindowsMotionController.MODEL_UNIVERSAL_FILENAME;
-
-            // Final url
-            return {
-//                path: WindowsMotionController.MODEL_BASE_URL + device + '/',
-                path: WindowsMotionController.MODEL_BASE_URL,
-                name: filename
-            };
-        }
         
         private createMeshInfo(rootNode: AbstractMesh) : LoadedMeshInfo {
-
             let loadedMeshInfo = new LoadedMeshInfo();
             var i;
             loadedMeshInfo.rootNode = rootNode;
@@ -388,40 +351,11 @@ module BABYLON {
                 return node.getChildMeshes(true, n => n.name == name)[0];
             }
         }
-    }
-
-    class LoadedMeshInfo {
-        public rootNode: AbstractMesh;
-        public pointingPoseNode: AbstractMesh;
-        public holdingPoseNode: AbstractMesh;
-        public buttonMeshes: { [id: string] : IButtonMeshInfo; } = {};
-        public axisMeshes: { [id: number] : IAxisMeshInfo; } = {};
-    }
 
-    interface IMeshInfo {
-        index: number;
-        value: AbstractMesh;
-    }
+        public dispose(): void {
+            super.dispose();
 
-    interface IButtonMeshInfo extends IMeshInfo {
-        pressed: AbstractMesh;
-        unpressed: AbstractMesh;
-    }
-
-    interface IAxisMeshInfo extends IMeshInfo {
-        min: AbstractMesh;
-        max: AbstractMesh;
-    }
-
-    interface IControllerMappingInfo {
-        buttons: string[];
-        buttonMeshNames: { [id: string ] : string };
-        buttonObservableNames: { [id: string ] : string };
-        axisMeshNames: string[];
-    }
-
-    interface IControllerUrl {
-        path: string;
-        name: string;
+            this.onTrackpadChangedObservable.clear();
+        }
     }
 }

+ 9 - 0
src/babylon.engine.ts

@@ -564,6 +564,11 @@
         private _vrDisplayEnabled;
         private _oldSize: BABYLON.Size;
         private _oldHardwareScaleFactor: number;
+        private _vrExclusivePointerMode = false;
+
+        public get isInVRExclusivePointerMode(): boolean {
+            return this._vrExclusivePointerMode;
+        }
 
         // Uniform buffers list
         public disableUniformBuffers = false;
@@ -941,10 +946,14 @@
                 document.addEventListener("webkitpointerlockchange", this._onPointerLockChange, false);
 
                 this._onVRDisplayPointerRestricted = () => {
+                    this._vrExclusivePointerMode = true;
+                    console.log("enter");
                     canvas.requestPointerLock();
                 }
 
                 this._onVRDisplayPointerUnrestricted = () => {
+                    this._vrExclusivePointerMode = false;
+                    console.log("exit");
                     document.exitPointerLock();
                 }
 

+ 8 - 6
src/babylon.scene.ts

@@ -2829,13 +2829,14 @@
                 throw new Error("Active camera not set");
 
             Tools.StartPerformanceCounter("Rendering camera " + this.activeCamera.name);
-
+           
             // Viewport
             engine.setViewport(this.activeCamera.viewport);
 
             // Camera
             this.resetCachedMaterial();
             this._renderId++;
+            this.activeCamera.update();
             this.updateTransformMatrix();
 
             if (camera._alternateCamera) {
@@ -3005,8 +3006,8 @@
             this.postProcessManager._finalizeFrame(camera.isIntermediate);
 
             // Update camera
-            this.activeCamera._updateFromScene();
-
+            this.activeCamera.updateCache();
+            
             // Reset some special arrays
             this._renderTargets.reset();
 
@@ -3023,6 +3024,9 @@
                 return;
             }
 
+            // Update camera
+            this.activeCamera.update();
+            
             // rig cameras
             for (var index = 0; index < camera._rigCameras.length; index++) {
                 this._renderForCamera(camera._rigCameras[index]);
@@ -3030,9 +3034,7 @@
 
             this.activeCamera = camera;
             this.setTransformMatrix(this.activeCamera.getViewMatrix(), this.activeCamera.getProjectionMatrix());
-
-            // Update camera
-            this.activeCamera._updateFromScene();
+            this.activeCamera.updateCache();
         }
 
         private _checkIntersections(): void {