|
@@ -57,6 +57,8 @@ module BABYLON {
|
|
|
private _teleportationAllowed: boolean = false;
|
|
|
private _rotationAllowed: boolean = true;
|
|
|
private _teleportationRequestInitiated = false;
|
|
|
+ private _teleportationBackRequestInitiated = false;
|
|
|
+ private teleportBackwardsVector = new Vector3(0, -1, -1);
|
|
|
private _rotationRightAsked = false;
|
|
|
private _rotationLeftAsked = false;
|
|
|
private _teleportationCircle: Mesh;
|
|
@@ -122,6 +124,14 @@ module BABYLON {
|
|
|
this._leftLaserPointer.isVisible = false;
|
|
|
}
|
|
|
}
|
|
|
+ else {
|
|
|
+ if(this._rightLaserPointer) {
|
|
|
+ this._rightLaserPointer.isVisible = true;
|
|
|
+ }
|
|
|
+ else if (this._leftLaserPointer) {
|
|
|
+ this._leftLaserPointer.isVisible = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
public get deviceOrientationCamera(): Nullable<DeviceOrientationCamera> {
|
|
@@ -150,24 +160,37 @@ module BABYLON {
|
|
|
this._scene = scene;
|
|
|
this._canvas = scene.getEngine().getRenderingCanvas();
|
|
|
|
|
|
- this._defaultHeight = webVROptions.defaultHeight || 1.7;
|
|
|
-
|
|
|
+ // Parse options
|
|
|
if (webVROptions.createFallbackVRDeviceOrientationFreeCamera === undefined) {
|
|
|
webVROptions.createFallbackVRDeviceOrientationFreeCamera = true;
|
|
|
}
|
|
|
-
|
|
|
if (webVROptions.createDeviceOrientationCamera === undefined) {
|
|
|
webVROptions.createDeviceOrientationCamera = true;
|
|
|
}
|
|
|
-
|
|
|
- if (!this._scene.activeCamera || webVROptions.createDeviceOrientationCamera) {
|
|
|
- if (!this._scene.activeCamera || isNaN(this._scene.activeCamera.position.x)) {
|
|
|
- this._position = new BABYLON.Vector3(0, this._defaultHeight, 0);
|
|
|
- this._deviceOrientationCamera = new BABYLON.DeviceOrientationCamera("deviceOrientationVRHelper", this._position.clone(), scene);
|
|
|
+ if (webVROptions.useCustomVRButton) {
|
|
|
+ this._useCustomVRButton = true;
|
|
|
+ if (webVROptions.customVRButton) {
|
|
|
+ this._btnVR = webVROptions.customVRButton;
|
|
|
}
|
|
|
- else {
|
|
|
- this._position = this._scene.activeCamera.position.clone();
|
|
|
- this._deviceOrientationCamera = new BABYLON.DeviceOrientationCamera("deviceOrientationVRHelper", this._position.clone(), scene);
|
|
|
+ }
|
|
|
+ if (webVROptions.rayLength) {
|
|
|
+ this._rayLength = webVROptions.rayLength
|
|
|
+ }
|
|
|
+ this._defaultHeight = webVROptions.defaultHeight || 1.7;
|
|
|
+
|
|
|
+ // Set position
|
|
|
+ if(this._scene.activeCamera){
|
|
|
+ this._position = this._scene.activeCamera.position.clone();
|
|
|
+ }else{
|
|
|
+ this._position = new BABYLON.Vector3(0, this._defaultHeight, 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Set non-vr camera
|
|
|
+ if(webVROptions.createDeviceOrientationCamera || !this._scene.activeCamera){
|
|
|
+ this._deviceOrientationCamera = new BABYLON.DeviceOrientationCamera("deviceOrientationVRHelper", this._position.clone(), scene);
|
|
|
+
|
|
|
+ // Copy data from existing camera
|
|
|
+ if(this._scene.activeCamera){
|
|
|
this._deviceOrientationCamera.minZ = this._scene.activeCamera.minZ;
|
|
|
this._deviceOrientationCamera.maxZ = this._scene.activeCamera.maxZ;
|
|
|
// Set rotation from previous camera
|
|
@@ -181,29 +204,22 @@ module BABYLON {
|
|
|
this._deviceOrientationCamera.rotation = targetCamera.rotation.clone();
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
this._scene.activeCamera = this._deviceOrientationCamera;
|
|
|
if (this._canvas) {
|
|
|
this._scene.activeCamera.attachControl(this._canvas);
|
|
|
}
|
|
|
- }
|
|
|
- else {
|
|
|
+ }else{
|
|
|
this._existingCamera = this._scene.activeCamera;
|
|
|
- this._position = this._scene.activeCamera.position.clone();
|
|
|
}
|
|
|
|
|
|
- if (webVROptions) {
|
|
|
- if (webVROptions.useCustomVRButton) {
|
|
|
- this._useCustomVRButton = true;
|
|
|
- if (webVROptions.customVRButton) {
|
|
|
- this._btnVR = webVROptions.customVRButton;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (webVROptions.rayLength) {
|
|
|
- this._rayLength = webVROptions.rayLength
|
|
|
- }
|
|
|
+ // Create VR cameras
|
|
|
+ if (webVROptions.createFallbackVRDeviceOrientationFreeCamera) {
|
|
|
+ this._vrDeviceOrientationCamera = new BABYLON.VRDeviceOrientationFreeCamera("VRDeviceOrientationVRHelper", this._position, this._scene);
|
|
|
}
|
|
|
+ this._webVRCamera = new BABYLON.WebVRFreeCamera("WebVRHelper", this._position, this._scene, webVROptions);
|
|
|
|
|
|
+ // Create default button
|
|
|
if (!this._useCustomVRButton) {
|
|
|
this._btnVR = <HTMLButtonElement>document.createElement("BUTTON");
|
|
|
this._btnVR.className = "babylonVRicon";
|
|
@@ -219,50 +235,42 @@ module BABYLON {
|
|
|
var style = document.createElement('style');
|
|
|
style.appendChild(document.createTextNode(css));
|
|
|
document.getElementsByTagName('head')[0].appendChild(style);
|
|
|
- }
|
|
|
-
|
|
|
- if (this._canvas) {
|
|
|
- if (!this._useCustomVRButton) {
|
|
|
- this._btnVR.style.top = this._canvas.offsetTop + this._canvas.offsetHeight - 70 + "px";
|
|
|
- this._btnVR.style.left = this._canvas.offsetLeft + this._canvas.offsetWidth - 100 + "px";
|
|
|
- }
|
|
|
- if (this._btnVR) {
|
|
|
- this._btnVR.addEventListener("click", () => {
|
|
|
- if(!this.isInVRMode){
|
|
|
- this.enterVR();
|
|
|
- }else{
|
|
|
- this.exitVR();
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
|
|
|
- window.addEventListener("resize", () => {
|
|
|
- if (this._canvas && !this._useCustomVRButton) {
|
|
|
- this._btnVR.style.top = this._canvas.offsetTop + this._canvas.offsetHeight - 70 + "px";
|
|
|
- this._btnVR.style.left = this._canvas.offsetLeft + this._canvas.offsetWidth - 100 + "px";
|
|
|
- }
|
|
|
+ this.moveButtonToBottomRight();
|
|
|
+ }
|
|
|
|
|
|
- if (this._fullscreenVRpresenting && this._webVRready) {
|
|
|
+ // VR button click event
|
|
|
+ if (this._btnVR) {
|
|
|
+ this._btnVR.addEventListener("click", () => {
|
|
|
+ if (!this.isInVRMode) {
|
|
|
+ this.enterVR();
|
|
|
+ } else {
|
|
|
this.exitVR();
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
|
|
|
+ // Window events
|
|
|
+ window.addEventListener("resize", () => {
|
|
|
+ this.moveButtonToBottomRight();
|
|
|
+ if (this._fullscreenVRpresenting && this._webVRready) {
|
|
|
+ this.exitVR();
|
|
|
+ }
|
|
|
+ });
|
|
|
document.addEventListener("fullscreenchange", () => { this._onFullscreenChange() }, false);
|
|
|
document.addEventListener("mozfullscreenchange", () => { this._onFullscreenChange() }, false);
|
|
|
document.addEventListener("webkitfullscreenchange", () => { this._onFullscreenChange() }, false);
|
|
|
document.addEventListener("msfullscreenchange", () => { this._onFullscreenChange() }, false);
|
|
|
|
|
|
- this._scene.getEngine().onVRDisplayChangedObservable.add((e) => {
|
|
|
- if (!this._useCustomVRButton && !this._btnVRDisplayed && e.vrDisplay) {
|
|
|
- document.body.appendChild(this._btnVR);
|
|
|
- this._btnVRDisplayed = true;
|
|
|
- }
|
|
|
- })
|
|
|
-
|
|
|
- if (!this._useCustomVRButton && !this._btnVRDisplayed && webVROptions.createFallbackVRDeviceOrientationFreeCamera) {
|
|
|
- document.body.appendChild(this._btnVR);
|
|
|
- this._btnVRDisplayed = true;
|
|
|
+ // Display vr button when headset is connected
|
|
|
+ if (webVROptions.createFallbackVRDeviceOrientationFreeCamera) {
|
|
|
+ this.displayVRButton();
|
|
|
+ }else{
|
|
|
+ this._scene.getEngine().onVRDisplayChangedObservable.add((e) => {
|
|
|
+ if (e.vrDisplay) {
|
|
|
+ this.displayVRButton();
|
|
|
+ }
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
// Exiting VR mode using 'ESC' key on desktop
|
|
@@ -294,17 +302,12 @@ module BABYLON {
|
|
|
this._webVRrequesting = false;
|
|
|
this.updateButtonVisibility();
|
|
|
};
|
|
|
-
|
|
|
scene.getEngine().onVRDisplayChangedObservable.add(this._onVRDisplayChanged);
|
|
|
scene.getEngine().onVRRequestPresentStart.add(this._onVRRequestPresentStart);
|
|
|
scene.getEngine().onVRRequestPresentComplete.add(this._onVRRequestPresentComplete);
|
|
|
window.addEventListener('vrdisplaypresentchange', this._onVrDisplayPresentChange);
|
|
|
|
|
|
- // Create the cameras
|
|
|
- if (webVROptions.createFallbackVRDeviceOrientationFreeCamera) {
|
|
|
- this._vrDeviceOrientationCamera = new BABYLON.VRDeviceOrientationFreeCamera("VRDeviceOrientationVRHelper", this._position, this._scene);
|
|
|
- }
|
|
|
- this._webVRCamera = new BABYLON.WebVRFreeCamera("WebVRHelper", this._position, this._scene, webVROptions);
|
|
|
+ // Gamepad connection events
|
|
|
this._webVRCamera.onControllerMeshLoadedObservable.add((webVRController) => this._onDefaultMeshLoaded(webVRController));
|
|
|
this._scene.gamepadManager.onGamepadConnectedObservable.add((pad) => this._onNewGamepadConnected(pad));
|
|
|
this._scene.gamepadManager.onGamepadDisconnectedObservable.add((pad) => this._onNewGamepadDisconnected(pad));
|
|
@@ -395,6 +398,20 @@ module BABYLON {
|
|
|
this.updateButtonVisibility();
|
|
|
}
|
|
|
|
|
|
+ private moveButtonToBottomRight(){
|
|
|
+ if (this._canvas && !this._useCustomVRButton) {
|
|
|
+ this._btnVR.style.top = this._canvas.offsetTop + this._canvas.offsetHeight - 70 + "px";
|
|
|
+ this._btnVR.style.left = this._canvas.offsetLeft + this._canvas.offsetWidth - 100 + "px";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private displayVRButton(){
|
|
|
+ if (!this._useCustomVRButton && !this._btnVRDisplayed) {
|
|
|
+ document.body.appendChild(this._btnVR);
|
|
|
+ this._btnVRDisplayed = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private updateButtonVisibility() {
|
|
|
if (!this._btnVR || this._useCustomVRButton) {
|
|
|
return;
|
|
@@ -414,10 +431,6 @@ module BABYLON {
|
|
|
* Otherwise, will use the fullscreen API.
|
|
|
*/
|
|
|
public enterVR() {
|
|
|
- if (this._scene.activeCamera) {
|
|
|
- this._position = this._scene.activeCamera.position.clone();
|
|
|
- }
|
|
|
-
|
|
|
if (this.onEnteringVR) {
|
|
|
try {
|
|
|
this.onEnteringVR.notifyObservers(this);
|
|
@@ -426,6 +439,11 @@ module BABYLON {
|
|
|
Tools.Warn("Error in your custom logic onEnteringVR: " + err);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ if (this._scene.activeCamera) {
|
|
|
+ this._position = this._scene.activeCamera.position.clone();
|
|
|
+ }
|
|
|
+
|
|
|
if (this._webVRrequesting)
|
|
|
return;
|
|
|
|
|
@@ -617,23 +635,12 @@ module BABYLON {
|
|
|
if (gamepad.leftStick) {
|
|
|
gamepad.onleftstickchanged((stickValues) => {
|
|
|
if (this._teleportationEnabled) {
|
|
|
+ this._checkTeleportBackwards(stickValues);
|
|
|
// Listening to classic/xbox gamepad only if no VR controller is active
|
|
|
if ((!this._leftLaserPointer && !this._rightLaserPointer) ||
|
|
|
((this._leftLaserPointer && !this._leftLaserPointer.isVisible) &&
|
|
|
(this._rightLaserPointer && !this._rightLaserPointer.isVisible))) {
|
|
|
- if (!this._teleportationRequestInitiated) {
|
|
|
- if (stickValues.y < -this._padSensibilityUp) {
|
|
|
- this._teleportationRequestInitiated = true;
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- if (stickValues.y > -this._padSensibilityDown) {
|
|
|
- if (this._teleportationAllowed) {
|
|
|
- this._teleportCamera();
|
|
|
- }
|
|
|
- this._teleportationRequestInitiated = false;
|
|
|
- }
|
|
|
- }
|
|
|
+ this._checkTeleportWithRay(stickValues);
|
|
|
}
|
|
|
}
|
|
|
});
|
|
@@ -641,50 +648,19 @@ module BABYLON {
|
|
|
if (gamepad.rightStick) {
|
|
|
gamepad.onrightstickchanged((stickValues) => {
|
|
|
if (this._teleportationEnabled) {
|
|
|
- if (!this._rotationLeftAsked) {
|
|
|
- if (stickValues.x < -this._padSensibilityUp) {
|
|
|
- this._rotationLeftAsked = true;
|
|
|
- if (this._rotationAllowed) {
|
|
|
- this._rotateCamera(false);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- if (stickValues.x > -this._padSensibilityDown) {
|
|
|
- this._rotationLeftAsked = false;
|
|
|
- }
|
|
|
- }
|
|
|
- if (!this._rotationRightAsked) {
|
|
|
- if (stickValues.x > this._padSensibilityUp) {
|
|
|
- this._rotationRightAsked = true;
|
|
|
- if (this._rotationAllowed) {
|
|
|
- this._rotateCamera(true);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- if (stickValues.x < this._padSensibilityDown) {
|
|
|
- this._rotationRightAsked = false;
|
|
|
- }
|
|
|
- }
|
|
|
+ this._checkRotate(stickValues);
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
if (gamepad.type === BABYLON.Gamepad.XBOX) {
|
|
|
(<Xbox360Pad>gamepad).onbuttondown((buttonPressed: Xbox360Button) => {
|
|
|
if (this._interactionsEnabled && buttonPressed === Xbox360Button.A) {
|
|
|
- this._pointerDownOnMeshAsked = true;
|
|
|
- if (this._currentMeshSelected && this._currentHit) {
|
|
|
- this._scene.simulatePointerDown(this._currentHit);
|
|
|
- }
|
|
|
+ this._selectionPointerDown();
|
|
|
}
|
|
|
});
|
|
|
(<Xbox360Pad>gamepad).onbuttonup((buttonPressed: Xbox360Button) => {
|
|
|
if (this._interactionsEnabled && buttonPressed === Xbox360Button.A) {
|
|
|
- if (this._currentMeshSelected && this._currentHit) {
|
|
|
- this._scene.simulatePointerUp(this._currentHit);
|
|
|
- }
|
|
|
- this._pointerDownOnMeshAsked = false;
|
|
|
+ this._selectionPointerUp();
|
|
|
}
|
|
|
});
|
|
|
}
|
|
@@ -763,21 +739,130 @@ module BABYLON {
|
|
|
webVRController.onTriggerStateChangedObservable.add((stateObject) => {
|
|
|
if (!this._pointerDownOnMeshAsked) {
|
|
|
if (stateObject.value > this._padSensibilityUp) {
|
|
|
- this._pointerDownOnMeshAsked = true;
|
|
|
- if (this._currentMeshSelected && this._currentHit) {
|
|
|
- this._scene.simulatePointerDown(this._currentHit);
|
|
|
+ this._selectionPointerDown();
|
|
|
+ }
|
|
|
+ } else if (stateObject.value < this._padSensibilityDown) {
|
|
|
+ this._selectionPointerUp();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private _checkTeleportWithRay(stateObject: StickValues, webVRController:Nullable<WebVRController> = null){
|
|
|
+ if (!this._teleportationRequestInitiated) {
|
|
|
+ if (stateObject.y < -this._padSensibilityUp) {
|
|
|
+ if(webVRController){
|
|
|
+ // If laser pointer wasn't enabled yet
|
|
|
+ if (this._displayLaserPointer && webVRController.hand === "left" && this._leftLaserPointer) {
|
|
|
+ this._leftLaserPointer.isVisible = true;
|
|
|
+ if (this._rightLaserPointer) {
|
|
|
+ this._rightLaserPointer.isVisible = false;
|
|
|
+ }
|
|
|
+ } else if (this._displayLaserPointer && this._rightLaserPointer) {
|
|
|
+ this._rightLaserPointer.isVisible = true;
|
|
|
+ if (this._leftLaserPointer) {
|
|
|
+ this._leftLaserPointer.isVisible = false;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- else if (stateObject.value < this._padSensibilityDown) {
|
|
|
- if (this._currentMeshSelected && this._currentHit) {
|
|
|
- this._scene.simulatePointerUp(this._currentHit);
|
|
|
+ this._teleportationRequestInitiated = true;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // Listening to the proper controller values changes to confirm teleportation
|
|
|
+ if (webVRController == null
|
|
|
+ ||(webVRController.hand === "left" && this._leftLaserPointer && this._leftLaserPointer.isVisible)
|
|
|
+ || (webVRController.hand === "right" && this._rightLaserPointer && this._rightLaserPointer.isVisible)) {
|
|
|
+ if (stateObject.y > -this._padSensibilityDown) {
|
|
|
+ if (this._teleportationAllowed) {
|
|
|
+ this._teleportationAllowed = false;
|
|
|
+ this._teleportCamera();
|
|
|
}
|
|
|
- this._pointerDownOnMeshAsked = false;
|
|
|
+ this._teleportationRequestInitiated = false;
|
|
|
}
|
|
|
- });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ private _selectionPointerDown(){
|
|
|
+ this._pointerDownOnMeshAsked = true;
|
|
|
+ if (this._currentMeshSelected && this._currentHit) {
|
|
|
+ this._scene.simulatePointerDown(this._currentHit);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ private _selectionPointerUp(){
|
|
|
+ if (this._currentMeshSelected && this._currentHit) {
|
|
|
+ this._scene.simulatePointerUp(this._currentHit);
|
|
|
+ }
|
|
|
+ this._pointerDownOnMeshAsked = false;
|
|
|
+ }
|
|
|
+ private _checkRotate(stateObject: StickValues){
|
|
|
+ if (!this._rotationLeftAsked) {
|
|
|
+ if (stateObject.x < -this._padSensibilityUp) {
|
|
|
+ this._rotationLeftAsked = true;
|
|
|
+ if (this._rotationAllowed) {
|
|
|
+ this._rotateCamera(false);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (stateObject.x > -this._padSensibilityDown) {
|
|
|
+ this._rotationLeftAsked = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!this._rotationRightAsked) {
|
|
|
+ if (stateObject.x > this._padSensibilityUp) {
|
|
|
+ this._rotationRightAsked = true;
|
|
|
+ if (this._rotationAllowed) {
|
|
|
+ this._rotateCamera(true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (stateObject.x < this._padSensibilityDown) {
|
|
|
+ this._rotationRightAsked = false;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
+ private _checkTeleportBackwards(stateObject: StickValues){
|
|
|
+ // Teleport backwards
|
|
|
+ if(stateObject.y > this._padSensibilityUp) {
|
|
|
+ if(!this._teleportationBackRequestInitiated){
|
|
|
+ if(!this.currentVRCamera){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Get rotation and position of the current camera
|
|
|
+ var rotation = Quaternion.FromRotationMatrix(this.currentVRCamera.getWorldMatrix().getRotationMatrix());
|
|
|
+ var position = this.currentVRCamera.position;
|
|
|
+
|
|
|
+ // If the camera has device position, use that instead
|
|
|
+ if((<WebVRFreeCamera>this.currentVRCamera).devicePosition && (<WebVRFreeCamera>this.currentVRCamera).deviceRotationQuaternion){
|
|
|
+ rotation = (<WebVRFreeCamera>this.currentVRCamera).deviceRotationQuaternion;
|
|
|
+ position = (<WebVRFreeCamera>this.currentVRCamera).devicePosition;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Get matrix with only the y rotation of the device rotation
|
|
|
+ rotation.toEulerAnglesToRef(this._workingVector);
|
|
|
+ this._workingVector.z = 0;
|
|
|
+ this._workingVector.x = 0;
|
|
|
+ Quaternion.RotationYawPitchRollToRef(this._workingVector.y, this._workingVector.x, this._workingVector.z, this._workingQuaternion);
|
|
|
+ this._workingQuaternion.toRotationMatrix(this._workingMatrix);
|
|
|
+
|
|
|
+ // Rotate backwards ray by device rotation to cast at the ground behind the user
|
|
|
+ Vector3.TransformCoordinatesToRef(this.teleportBackwardsVector, this._workingMatrix, this._workingVector);
|
|
|
+
|
|
|
+ // Teleport if ray hit the ground and is not to far away eg. backwards off a cliff
|
|
|
+ var ray = new BABYLON.Ray(position, this._workingVector);
|
|
|
+ var hit = this._scene.pickWithRay(ray, this._raySelectionPredicate);
|
|
|
+ if(hit && hit.pickedPoint && hit.pickedMesh &&this._isTeleportationFloor(hit.pickedMesh) && hit.distance < 5){
|
|
|
+ this._teleportCamera(hit.pickedPoint);
|
|
|
+ }
|
|
|
+
|
|
|
+ this._teleportationBackRequestInitiated = true;
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ this._teleportationBackRequestInitiated = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
private _enableTeleportationOnController(webVRController: WebVRController) {
|
|
|
var controllerMesh = webVRController.mesh;
|
|
@@ -795,64 +880,9 @@ module BABYLON {
|
|
|
this._teleportationEnabledOnRightController = true;
|
|
|
}
|
|
|
webVRController.onPadValuesChangedObservable.add((stateObject) => {
|
|
|
- if (!this._teleportationRequestInitiated) {
|
|
|
- if (stateObject.y < -this._padSensibilityUp) {
|
|
|
- // If laser pointer wasn't enabled yet
|
|
|
- if (this._displayLaserPointer && webVRController.hand === "left" && this._leftLaserPointer) {
|
|
|
- this._leftLaserPointer.isVisible = true;
|
|
|
- if (this._rightLaserPointer) {
|
|
|
- this._rightLaserPointer.isVisible = false;
|
|
|
- }
|
|
|
- }
|
|
|
- else if (this._displayLaserPointer && this._rightLaserPointer) {
|
|
|
- this._rightLaserPointer.isVisible = true;
|
|
|
- if (this._leftLaserPointer) {
|
|
|
- this._leftLaserPointer.isVisible = false;
|
|
|
- }
|
|
|
- }
|
|
|
- this._teleportationRequestInitiated = true;
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- // Listening to the proper controller values changes to confirm teleportation
|
|
|
- if ((webVRController.hand === "left" && this._leftLaserPointer && this._leftLaserPointer.isVisible)
|
|
|
- || (webVRController.hand === "right" && this._rightLaserPointer && this._rightLaserPointer.isVisible)) {
|
|
|
- if (stateObject.y > -this._padSensibilityDown) {
|
|
|
- if (this._teleportationAllowed) {
|
|
|
- this._teleportationAllowed = false;
|
|
|
- this._teleportCamera();
|
|
|
- }
|
|
|
- this._teleportationRequestInitiated = false;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- if (!this._rotationLeftAsked) {
|
|
|
- if (stateObject.x < -this._padSensibilityUp) {
|
|
|
- this._rotationLeftAsked = true;
|
|
|
- if (this._rotationAllowed) {
|
|
|
- this._rotateCamera(false);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- if (stateObject.x > -this._padSensibilityDown) {
|
|
|
- this._rotationLeftAsked = false;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (!this._rotationRightAsked) {
|
|
|
- if (stateObject.x > this._padSensibilityUp) {
|
|
|
- this._rotationRightAsked = true;
|
|
|
- if (this._rotationAllowed) {
|
|
|
- this._rotateCamera(true);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- if (stateObject.x < this._padSensibilityDown) {
|
|
|
- this._rotationRightAsked = false;
|
|
|
- }
|
|
|
- }
|
|
|
+ this._checkTeleportBackwards(stateObject);
|
|
|
+ this._checkTeleportWithRay(stateObject, webVRController);
|
|
|
+ this._checkRotate(stateObject)
|
|
|
});
|
|
|
}
|
|
|
}
|
|
@@ -1056,21 +1086,27 @@ module BABYLON {
|
|
|
}
|
|
|
}
|
|
|
private _workingVector = Vector3.Zero();
|
|
|
- private _teleportCamera() {
|
|
|
+ private _workingQuaternion = Quaternion.Identity();
|
|
|
+ private _workingMatrix = Matrix.Identity();
|
|
|
+ private _teleportCamera(location:Nullable<Vector3> = null) {
|
|
|
if (!(this.currentVRCamera instanceof FreeCamera)) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // Teleport the hmd to where the user is looking by moving the anchor to where they are looking minus the
|
|
|
- // offset of the headset from the anchor. Then add the helper's position to account for user's height offset
|
|
|
- if (this.webVRCamera.leftCamera) {
|
|
|
- this._workingVector.copyFrom(this.webVRCamera.leftCamera.globalPosition);
|
|
|
- this._workingVector.subtractInPlace(this.webVRCamera.position);
|
|
|
- this._haloCenter.subtractToRef(this._workingVector, this._workingVector);
|
|
|
- } else {
|
|
|
- this._workingVector.copyFrom(this._haloCenter);
|
|
|
+ if(!location){
|
|
|
+ // Teleport the hmd to where the user is looking by moving the anchor to where they are looking minus the
|
|
|
+ // offset of the headset from the anchor.
|
|
|
+ if (this.webVRCamera.leftCamera) {
|
|
|
+ this._workingVector.copyFrom(this.webVRCamera.leftCamera.globalPosition);
|
|
|
+ this._workingVector.subtractInPlace(this.webVRCamera.position);
|
|
|
+ this._haloCenter.subtractToRef(this._workingVector, this._workingVector);
|
|
|
+ } else {
|
|
|
+ this._workingVector.copyFrom(this._haloCenter);
|
|
|
+ }
|
|
|
+ location = this._workingVector;
|
|
|
}
|
|
|
- this._workingVector.y += this._defaultHeight;
|
|
|
+ // Add height to account for user's height offset
|
|
|
+ location.y += this._defaultHeight;
|
|
|
|
|
|
// Create animation from the camera's position to the new location
|
|
|
this.currentVRCamera.animations = [];
|
|
@@ -1081,7 +1117,7 @@ module BABYLON {
|
|
|
},
|
|
|
{
|
|
|
frame: 11,
|
|
|
- value: this._workingVector
|
|
|
+ value: location
|
|
|
}
|
|
|
];
|
|
|
|