浏览代码

xr support

Nikolay Suslov 4 年之前
父节点
当前提交
7bcdd5515e

+ 26 - 1
public/app.js

@@ -55,6 +55,7 @@ class App {
     //client routes
     page('/', this.HandleIndex);
     page('/setup', this.HandleSetupIndex);
+    page('/debug', this.HandleDebugIndex);
     page('/settings', this.HandleSettingsIndex);
     page('/profile', this.HandleUserIndex);
     page('/worlds', this.HandleIndex);
@@ -89,7 +90,9 @@ class App {
         'dbhost': window.location.origin + '/gun', // 'https://' + window.location.hostname + ':8080/gun', //'http://localhost:8080/gun',
         'reflector': 'https://' + window.location.hostname + ':3002',
         'webrtc': false,
-        'language': 'en'
+        'language': 'en',
+        'd3DoF': false,
+        'd6DoF': false
       }
       localStorage.setItem('lcs_config', JSON.stringify(config));
     }
@@ -114,6 +117,16 @@ class App {
       localStorage.setItem('lcs_config', JSON.stringify(config));
     }
 
+    if (!config.d3DoF) {
+      config.d3DoF = false;
+      localStorage.setItem('lcs_config', JSON.stringify(config));
+    }
+
+    if (!config.d6DoF) {
+      config.d6DoF = false;
+      localStorage.setItem('lcs_config', JSON.stringify(config));
+    }
+
     this.config = config;
 
     let webrtcConnection = this.config.webrtc;
@@ -447,6 +460,18 @@ class App {
 
   }
 
+  HandleDebugIndex() {
+
+    window._app.hideProgressBar();
+    window._app.hideUIControl();
+
+    let el = document.createElement("div");
+    el.setAttribute("id", "appGUI");
+    document.body.appendChild(el);
+
+    _cellWidgets.debugGUI();
+
+  }
 
   HandleSettingsIndex() {
 

+ 24 - 0
public/defaults/proxy/vwf.example.com/aframe/hand-controls.vwf.yaml

@@ -0,0 +1,24 @@
+# https://aframe.io/docs/master/components/hand-controls.html
+# Copyright 2017 Krestianstvo.org project
+---
+extends: http://vwf.example.com/aframe/aentity.vwf
+type: "handcontrols"
+properties:
+methods:
+    initialize:
+    updateController:
+    createSimpleController:
+    createControllerFromGLTF:
+        parameters:
+            - modelSrc
+    createController:
+        parameters:
+            - modelSrc
+    updateVRControl:
+        parameters:
+            - position
+            - rotation
+    triggerdown:
+    triggerup:
+scripts:
+- source: "http://vwf.example.com/aframe/handcontrols.js"

+ 232 - 1
public/lib/widgets.js

@@ -714,8 +714,224 @@ Copyright (c) 2014-2018 Nikolai Suslov and the Krestianstvo.org project contribu
             
         }
 
+        debugGUI() {
+
+            let self = this;
+
+            let debug6DoF = {
+                $cell: true,
+                $components: [
+                  {
+                    $type: "p",
+                    class: "mdc-typography--headline5",
+                    $text: "Debug 6DoF mode (for using with WebXR emulator)"
+                  },
+                  {
+                    $type: 'p'
+                  },
+                  _app.widgets.switch({
+                    'id': 'forceDebug6DoF',
+                    'init': function () {
+                      this._switch = new mdc.switchControl.MDCSwitch(this);
+                      let config = localStorage.getItem('lcs_config');
+                      this._switch.checked = JSON.parse(config).d6DoF;
+                      
+                     // this._replaceSwitch = this._switch;
+                      
+                    },
+                    'onchange': function (e) {
+    
+                        if (this._switch) {
+                            let chkAttr = this._switch.checked;//this.getAttribute('checked');
+                            if (chkAttr) {
+                                let config = JSON.parse(localStorage.getItem('lcs_config'));
+                                config.d6DoF = true;
+                                localStorage.setItem('lcs_config', JSON.stringify(config));
+                                //this._switch.checked = false;
+                            } else {
+                                let config = JSON.parse(localStorage.getItem('lcs_config'));
+                                config.d6DoF = false;
+                                localStorage.setItem('lcs_config', JSON.stringify(config));
+                            }
+                        }
+                    }
+                  }
+                  ),
+                  {
+                    $type: 'label',
+                    for: 'input-forceDebug6DoF',
+                    $text: 'On / Off'
+                  }
+    
+                ]
+              }
+
+              let debug3DoF = {
+                $cell: true,
+                $components: [
+                  {
+                    $type: "p",
+                    class: "mdc-typography--headline5",
+                    $text: "Debug 3DoF mode (for using with WebXR emulator)"
+                  },
+                  {
+                    $type: 'p'
+                  },
+                  _app.widgets.switch({
+                    'id': 'forceDebug3DoF',
+                    'init': function () {
+                      this._switch = new mdc.switchControl.MDCSwitch(this);
+                      let config = localStorage.getItem('lcs_config');
+                      this._switch.checked = JSON.parse(config).d3DoF;
+                      
+                     // this._replaceSwitch = this._switch;
+                      
+                    },
+                    'onchange': function (e) {
+    
+                        if (this._switch) {
+                            let chkAttr = this._switch.checked;//this.getAttribute('checked');
+                            if (chkAttr) {
+                                let config = JSON.parse(localStorage.getItem('lcs_config'));
+                                config.d3DoF = true;
+                                localStorage.setItem('lcs_config', JSON.stringify(config));
+                                //this._switch.checked = false;
+                            } else {
+                                let config = JSON.parse(localStorage.getItem('lcs_config'));
+                                config.d3DoF = false;
+                                localStorage.setItem('lcs_config', JSON.stringify(config));
+                            }
+                        }
+                    }
+                  }
+                  ),
+                  {
+                    $type: 'label',
+                    for: 'input-forceDebug3DoF',
+                    $text: 'On / Off'
+                  }
+    
+                ]
+              }
+
+
+              let allGUI =
+              {
+                  $type: "div",
+                  id: "allGUI",
+                  //style:"background-color: #efefef",
+                  class: "mdc-layout-grid mdc-layout-grid--align-left",
+                  _d3DoF: null,
+                  _d6DoF: null,
+                  _initData: function () {
+          
+                      let config = JSON.parse(localStorage.getItem('lcs_config'));
+          
+                      if (config.d3DoF) {
+                          this._d3DoF = config.d3DoF
+                      }
+                      if (config.d6DoF) {
+                          this._d6DoF =config.d6DoF
+                      }
+                    
+                      this._refresh();
+                 },
+                  $init: function () {
+                      this._initData();
+                  },
+                  _refresh: function () {
+          
+                      this.$components = [
+                          {
+                              $type: "div",
+                              class: "mdc-layout-grid__inner",
+                              $components: [
+                                  {
+                                      $type: "div",
+                                      class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
+                                      $components: [
+                                      {
+                                          $type: "h4",
+                                          class: "mdc-typography--headline4",
+                                          $text: "Debug settings"
+                                      }
+                                  ]
+                                  },
+                                 { 
+                                  $type: "div",
+                                  class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
+                                  $components: [debug6DoF ]
+                                 },
+                                 { 
+                                  $type: "div",
+                                  class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
+                                  $components: [_app.widgets.divider]
+                                 },
+                                 { 
+                                  $type: "div",
+                                  class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
+                                  $components: [debug3DoF]
+                                 },
+                                  {
+                                      $type: "div",
+                                      class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
+                                      $components: [
+                                        //   window._app.widgets.buttonRaised(
+                                        //       {
+                                        //           "label": 'Update',
+                                        //           "onclick": function (e) {
+                                        //               e.preventDefault();
+          
+                                        //               let config = JSON.parse(localStorage.getItem('lcs_config'));
+          
+                                        //               config.reflector = this._refHostField.value;
+                                        //               config.dbhost = this._dbHostField.value;
+                                        //               config.luminaryPath = this._lpathField.value;
+                                        //               config.luminaryGlobalHBPath = this._hbpathField.value;
+          
+                                        //               localStorage.setItem('lcs_config', JSON.stringify(config));
+                                        //               window.location.reload(true);
+                                        //           }
+                                        //       }),
+                                              {
+                                                $type: 'span',
+                                                $text: " "
+                                              },
+                                              {
+                                                $type: "button",
+                                                class: "mdc-button mdc-button--raised",
+                                                $text: "Close",
+                                                onclick: function (e) {
+                                                      window.history.back();
+                                                    //window.location.pathname = '/'
+                                                }
+                                              }
+                                      ]
+                                  }
+          
+                              ]
+                          }
+                      ]
+                  }
+          
+              }
+          
+              document.querySelector("#appGUI").$cell({
+                  id: "appGUI",
+                  $cell: true,
+                  $type: "div",
+                  $components: [allGUI]
+              }
+              );
+
+
+
+            }
+
         reflectorGUI() {
 
+            let self = this;
+
             let webrtcConnection = {
                 $cell: true,
                 $components: [
@@ -881,6 +1097,7 @@ Copyright (c) 2014-2018 Nikolai Suslov and the Krestianstvo.org project contribu
                 _lpathField: null,
                 _hbpath: null,
                 _hbpathField: null,
+                //_debug: null,
                 _initData: function () {
                     this._reflectorHost = '';
                     this._dbHost = '';
@@ -899,6 +1116,9 @@ Copyright (c) 2014-2018 Nikolai Suslov and the Krestianstvo.org project contribu
                     if (config.luminaryGlobalHBPath) {
                         this._hbpath = config.luminaryGlobalHBPath
                     }
+                    // if (config.debug) {
+                    //     this._debug = config.debug
+                    // }
 
                 },
                 $init: function () {
@@ -1052,6 +1272,16 @@ Copyright (c) 2014-2018 Nikolai Suslov and the Krestianstvo.org project contribu
                                 class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
                                 $components: [luminaryGlobalHB ]
                                },
+                               { 
+                                $type: "div",
+                                class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
+                                $components: [_app.widgets.divider]
+                               },
+                            //    { 
+                            //     $type: "div",
+                            //     class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
+                            //     $components: [debugGUI]
+                            //    },
                                 {
                                     $type: "div",
                                     class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
@@ -1082,7 +1312,8 @@ Copyright (c) 2014-2018 Nikolai Suslov and the Krestianstvo.org project contribu
                                               class: "mdc-button mdc-button--raised",
                                               $text: "Close",
                                               onclick: function (e) {
-                                                  window.location.pathname = '/'
+                                                    window.history.back();
+                                                  //window.location.pathname = '/'
                                               }
                                             }
                                     ]

+ 30 - 13
public/vwf/model/aframe/addon/aframe-components.js

@@ -15,21 +15,31 @@ AFRAME.registerComponent('scene-utils', {
 
         const sceneEnterVR = (e) => {
 
+            let driver = vwf.views["vwf/view/aframe"];
             //vwf_view.kernel.callMethod(vwf.application(), "enterVR");
             let avatarEl = document.querySelector('#avatarControlParent');
             let avatarID = 'avatar-' + vwf_view.kernel.moniker();
-            if (AFRAME.utils.device.isMobileVR()) {
+
+            //if(AFRAME.utils.device.checkHeadsetConnected())
+
+            driver.hmd = true;
+
+            if (driver.threeDoFMobile|| _app.config.d3DoF ) {
+                driver.threeDoF = true;
 
                  vwf_view.kernel.callMethod(avatarID, "updateYPositionForXR", [0.0]);
                 //avatarEl.setAttribute('position', '0 1.6 0');
                 // if (AFRAME.utils.device.isGearVR()){  
                 // }
 
-            } else if (AFRAME.utils.device.isMobile()) {
-                avatarEl.setAttribute('position', '0 0 0')
-            } else {
-                avatarEl.setAttribute('position', '0 0 0'); //'0 1.6 0'
+            } else if (driver.sixDoFMobile || driver.sixDoFDesktop || _app.config.d6DoF ) {
+                driver.sixDoF = true;
             }
+            // else if (AFRAME.utils.device.isMobile()) {
+            //     avatarEl.setAttribute('position', '0 0 0')
+            // } else {
+            //     avatarEl.setAttribute('position', '0 0 0'); //'0 1.6 0'
+            // }
 
             // if (!AFRAME.utils.device.isGearVR() && !AFRAME.utils.device.isMobile()) {
             //     avatarEl.setAttribute('position', '0 1.6 0');
@@ -39,20 +49,27 @@ AFRAME.registerComponent('scene-utils', {
 
         const sceneExitVR = (e) => {
 
+            let driver = vwf.views["vwf/view/aframe"];
             //vwf_view.kernel.callMethod(vwf.application(), "exitVR");
             let avatarEl = document.querySelector('#avatarControlParent');
             let avatarID = 'avatar-' + vwf_view.kernel.moniker();
 
-            if (AFRAME.utils.device.isMobileVR()) {
+            driver.hmd = false;
+
+            if (driver.threeDoFMobile|| _app.config.d3DoF ) {
+                driver.threeDoF = false;
                 //avatarEl.setAttribute('position', '0 0 0');
 
                 vwf_view.kernel.callMethod(avatarID, "updateYPositionForXR", [-1.6]);
 
-            } else if (AFRAME.utils.device.isMobile()) {
-                avatarEl.setAttribute('position', '0 1.6 0');
-            } else {
-                avatarEl.setAttribute('position', '0 0 0');
+            } else if (driver.sixDoFMobile || driver.sixDoFDesktop || _app.config.d6DoF ) {
+                driver.sixDoF = false;
             }
+            // else if (AFRAME.utils.device.isMobile()) {
+            //     avatarEl.setAttribute('position', '0 1.6 0');
+            // } else {
+            //     avatarEl.setAttribute('position', '0 0 0');
+            // }
 
         }
 
@@ -510,12 +527,12 @@ AFRAME.registerComponent('wmrvrcontrol', {
     init: function () {
         var self = this;
         this.hand = this.data.hand;
-        var controllerID = 'wrmr-' + this.hand + '-' + vwf_view.kernel.moniker();
+        var controllerID = 'wmrvr-' + this.hand + '-' + vwf_view.kernel.moniker();
         //this.gearel = document.querySelector('#gearvrcontrol');
-        this.el.addEventListener('triggerdown', function (event) {
+        this.el.addEventListener('pointdown', function (event) { //pointdown 'triggerdown'
             vwf_view.kernel.callMethod(controllerID, "triggerdown", []);
         });
-        this.el.addEventListener('triggerup', function (event) {
+        this.el.addEventListener('pointup', function (event) { //pointup 'triggerup'
             vwf_view.kernel.callMethod(controllerID, "triggerup", []);
         });
     },

+ 65 - 37
public/vwf/view/aframe.js

@@ -50,11 +50,23 @@ define(["module", "vwf/view"], function (module, view) {
                 this.rootSelector = options;
             }
 
-            this.gearvr = options.gearvr !== undefined ? options.gearvr : false;
-            this.wmrright = options.wmrright !== undefined ? options.wmrright : false;
-            this.wmrleft = options.wmrleft !== undefined ? options.wmrleft : false;
+            // this.gearvr = options.gearvr !== undefined ? options.gearvr : false;
+            // this.wmrright = options.wmrright !== undefined ? options.wmrright : false;
+            // this.wmrleft = options.wmrleft !== undefined ? options.wmrleft : false;
 
             this.xrType = undefined;
+
+            //TODO: FIX detection in better way! (now works for Oculus Browser only)
+
+            this.hmd = false; 
+            this.threeDoF = false;
+            this.sixDoF = false;
+
+            this.threeDoFMobile = AFRAME.utils.device.isMobileVR() && AFRAME.utils.device.checkHeadsetConnected() && !navigator.userAgent.includes('Quest');
+            this.sixDoFMobile = AFRAME.utils.device.checkHeadsetConnected() && navigator.userAgent.includes('Quest');
+            this.sixDoFDesktop = !AFRAME.utils.device.isMobileVR() && AFRAME.utils.device.checkHeadsetConnected();
+
+
         },
 
         createdNode: function (nodeID, childID, childExtendsID, childImplementsIDs,
@@ -79,38 +91,31 @@ define(["module", "vwf/view"], function (module, view) {
 
                 prepairAvatar.then(res => {
 
-                    if (this.gearvr == true) {
                         console.log("CREATE GEARVR HERE!!");
-                        if (AFRAME.utils.device.isMobileVR()) {
+                        if (self.threeDoFMobile || _app.config.d3DoF ) {
                             this.xrType = 'mobileVR';
                             let nodeName = 'gearvr-' + self.kernel.moniker();
                             createGearVRControls();
                             createGearVRController.call(self, childID, nodeName);
                         }
-                    }
-
-
-                    if (this.wmrright == true) {
+                    
                         console.log("CREATE WMR RIGHT HERE!!");
-                        if (!AFRAME.utils.device.isMobileVR()) {
-                            if (AFRAME.utils.device.checkHeadsetConnected()) {
-                                let nodeName = 'wmrvr-right-' + self.kernel.moniker();
+                       // if (!AFRAME.utils.device.isMobileVR()) {
+                            if (self.sixDoFMobile || self.sixDoFDesktop || _app.config.d6DoF  ) {
+
+                                let nodeRight = 'wmrvr-right-' + self.kernel.moniker();
                                 createWMRVRControls('right');
-                                createWMRVR.call(this, childID, nodeName);
-                            }
-                        }
-                    }
+                                createWMRVR.call(this, childID, nodeRight);
 
-                    if (this.wmrleft == true) {
-                        console.log("CREATE WMR LEFT HERE!!");
-                        if (!AFRAME.utils.device.isMobileVR()) {
-                            if (AFRAME.utils.device.checkHeadsetConnected()) {
-                                let nodeName = 'wmrvr-left-' + self.kernel.moniker();
+                                console.log("CREATE WMR LEFT HERE!!");
+                       // if (!AFRAME.utils.device.isMobileVR()) {
+  
+                                let nodeLeft = 'wmrvr-left-' + self.kernel.moniker();
                                 createWMRVRControls('left');
-                                createWMRVR.call(this, childID, nodeName);
+                                createWMRVR.call(this, childID, nodeLeft);
                             }
-                        }
-                    }
+                       // }
+                    
 
                      // console.log(res);
                      createAvatar.call(self, childID);                  
@@ -475,16 +480,22 @@ define(["module", "vwf/view"], function (module, view) {
             updateAvatarPosition();
 
             //update vr controllers
-            if (this.gearvr == true) {
-                updateHandControllerVR('gearvr-', '#gearvrcontrol');
-            }
-            if (this.wmrright == true) {
-                updateHandControllerVR('wmrvr-right-', '#wmrvrcontrolright');
-            }
-            if (this.wmrleft == true) {
-                updateHandControllerVR('wmrvr-left-', '#wmrvrcontrolleft');
+
+            if(self.hmd){
+                if(self.threeDoF )
+                    updateHandControllerVR('gearvr-', '#gearvrcontrol');
+
+                if(this.sixDoF ) {
+                        updateHandControllerVR('wmrvr-right-', '#wmrvrcontrolright');
+                        updateHandControllerVR('wmrvr-left-', '#wmrvrcontrolleft');
+                }
             }
 
+            
+    
+                
+            
+
             //lerpTick ();
         },
 
@@ -654,9 +665,15 @@ define(["module", "vwf/view"], function (module, view) {
         if (el) {
             //let position = el.object3D.getWorldPosition(); //el.getAttribute('position');
 
-            let position = new THREE.Vector3();
-            el.object3D.getWorldPosition(position);
+            var position;
 
+            if((self.hmd && self.sixDoF) || _app.config.d6DoF){
+                position = el.getAttribute('position');
+            } else {
+                position = new THREE.Vector3();
+                el.object3D.getWorldPosition(position);
+            }
+            //let position = el.getAttribute('position');
             let rotation = el.getAttribute('rotation'); //getWorldRotation(el, 'YXZ');
 
             let lastRotation = self.nodes[avatarName].selfTickRotation;
@@ -780,7 +797,7 @@ define(["module", "vwf/view"], function (module, view) {
         avatarEl.setAttribute('id', 'avatarControlParent');
 
 
-        if (AFRAME.utils.device.isMobileVR()) {
+        if (self.d3DoF || _app.config.d3DoF) {
             //avatarEl.setAttribute('gearvr-controls', {}); 
             avatarEl.setAttribute('movement-controls', {});//{'controls': 'gamepad'});
            // avatarEl.setAttribute("gamepad-controls", {});
@@ -1031,10 +1048,12 @@ define(["module", "vwf/view"], function (module, view) {
 
         let gearvr = document.createElement('a-entity');
         gearvr.setAttribute('id', 'gearvrcontrol');
+
         gearvr.setAttribute('gearvr-controls', {
             'hand': 'right',
             'model': true
         });
+    
         // gearvr.setAttribute('gearvr-controls', 'hand', 'right');
 
         gearvr.setAttribute('gearvrcontrol', {});
@@ -1050,8 +1069,17 @@ define(["module", "vwf/view"], function (module, view) {
 
         let wmrvr = document.createElement('a-entity');
         wmrvr.setAttribute('id', 'wmrvrcontrol' + hand);
-        wmrvr.setAttribute('windows-motion-controls', '');
-        wmrvr.setAttribute('windows-motion-controls', 'hand', hand);
+
+        wmrvr.setAttribute('hand-controls', {
+            'hand': hand,
+            'handModelStyle': 'lowPoly',
+            'color': '#ffcccc'
+        });
+
+        // wmrvr.setAttribute('windows-motion-controls', '');
+        // wmrvr.setAttribute('windows-motion-controls', 'hand', hand);
+
+
         wmrvr.setAttribute('wmrvrcontrol', { 'hand': hand });
         avatarControl.appendChild(wmrvr);
     }

+ 6 - 0
public/web/index-app.js

@@ -210,6 +210,12 @@ class IndexApp {
                         class: "mdc-typography--headline3",
                         $text: this._status
                     }
+                    // ,{
+                    //     $type: "div",
+                    //     class: "mdc-typography--headline4",
+                    //     $text: navigator.userAgent
+                    // }
+                    
                 ].concat(gui)
             }
         }