Как использовать webVR-polyfill по умолчанию на chrome? - PullRequest
1 голос
/ 25 февраля 2020

Информация об устройстве: Android 9; HUAIWEI COL-AL10; Chrome 80.0.3987.99

Я работаю над применением A-Frame к моему HMD на основе мобильного телефона с моей индивидуальной ориентацией камеры и искажением.

Однако после того, как я изменил искажающее устройство карты (CardboardDistorter. prototype.computeMeshVertices_ в строке 63069 в рамке. js) и запустите сэмплы, искажение все еще использует искажение картбад. В то время как я изменил тот же самый искажатель в webvr-polyfill js, новое искажение работает для меня. И когда я использую другие телефоны для тестирования своей демонстрации в режиме «a-frame», новое искажение также работает ...... Похоже, что «a-frame» рассматривает мой телефон как собственное VR-устройство, поэтому оно запускает службу Google VR в бэкэнде ... .

Как включить новое искажение, которое я изменил в CardboardDistorter? Мне нужно запустить WebVR-polyfill ПРЯМО на моем телефоне. Недавно я создал несколько игр VR для единства, основанных на Google VR. Может быть, они сделали мой телефон «родным устройством Google VR»?

картонное искажение: картонное искажение

мой тестовое искажение (при использовании полифилла оно должно отображаться так): новое искажение

Вот мое новое искажение для теста:

 CardboardDistorter.prototype.computeMeshVertices_ = function (width, height, deviceInfo) {
  var vertices = new Float32Array(2 * width * height * 5);
  var lensFrustum = deviceInfo.getLeftEyeVisibleTanAngles();
  var noLensFrustum = deviceInfo.getLeftEyeNoLensTanAngles();
  var viewport = deviceInfo.getLeftEyeVisibleScreenRect(noLensFrustum);
  var vidx = 0;
  for (var e = 0; e < 2; e++) {
    for (var j = 0; j < height; j++) {
      for (var i = 0; i < width; i++, vidx++) {
        var u = i / (width - 1);
        var v = j / (height - 1);
        var s = u;
        var t = v;
        var x = lerp(lensFrustum[0], lensFrustum[2], u);
        var y = lerp(lensFrustum[3], lensFrustum[1], v);
        var d = Math.sqrt(x * x + y * y);
        var r = deviceInfo.distortion.distortInverse(d);
        var p = x * r / d;
        var q = y * r / d;
        // test distortion
        u = u - 0.5;
        v = v - 0.5;
        u = u * (v + 0.7);
        v = v * 0.7;
        u = u + 0.5;
        v = v + 0.5;
        //u = (p - noLensFrustum[0]) / (noLensFrustum[2] - noLensFrustum[0]);
        //v = (q - noLensFrustum[3]) / (noLensFrustum[1] - noLensFrustum[3]);
        u = (viewport.x + u * viewport.width - 0.5) * 2.0;
        v = (viewport.y + v * viewport.height - 0.5) * 2.0;
        vertices[vidx * 5 + 0] = u;
        vertices[vidx * 5 + 1] = v;
        vertices[vidx * 5 + 2] = s;
        vertices[vidx * 5 + 3] = t;
        vertices[vidx * 5 + 4] = e;
      }
    }
    var w = lensFrustum[2] - lensFrustum[0];
    lensFrustum[0] = -(w + lensFrustum[0]);
    lensFrustum[2] = w - lensFrustum[2];
    w = noLensFrustum[2] - noLensFrustum[0];
    noLensFrustum[0] = -(w + noLensFrustum[0]);
    noLensFrustum[2] = w - noLensFrustum[2];
    viewport.x = 1 - (viewport.x + viewport.width);
  }
  return vertices;
};

Вот что я пробовал : Строка 3511

function shouldUseNative() {
  return false;
}

Строка 80341

window.hasNativeWebVRImplementation = false;
window.hasNativeWebXRImplementation = false;

[ОБНОВЛЕНИЕ] Я считаю, что A-Frame 0.9.2 напрямую использует polyfill, а с 1.0.0 он использует собственный сервис Google VR для display.

enterVR: {
      value: function (useAR) {
        var self = this;
        var vrDisplay;
        var vrManager = self.renderer.xr;

        // Don't enter VR if already in VR.
        if (this.is('vr-mode')) { return Promise.resolve('Already in VR.'); }

        // Has VR.
        if (this.checkHeadsetConnected() || this.isMobile) {
          vrDisplay = utils.device.getVRDisplay();
          vrManager.enabled = true;
          vrManager.setDevice(vrDisplay);

          if (this.hasWebXR) {
            // XR API.
            if (this.xrSession) {
              this.xrSession.removeEventListener('end', this.exitVRBound);
            }
            navigator.xr.requestSession(useAR ? 'immersive-ar' : 'immersive-vr', {
              requiredFeatures: ['local-floor'],
              optionalFeatures: ['bounded-floor']
            }).then(function requestSuccess (xrSession) {
              self.xrSession = xrSession;
              vrManager.setSession(xrSession);
              xrSession.addEventListener('end', self.exitVRBound);
              if (useAR) {
                self.addState('ar-mode');
              }
              enterVRSuccess();
            });
          } else {
            vrDisplay = utils.device.getVRDisplay();
            vrManager.setDevice(vrDisplay);
            if (vrDisplay.isPresenting &&
                !window.hasNativeWebVRImplementation) {
              enterVRSuccess();
              return Promise.resolve();
            }
            var rendererSystem = this.getAttribute('renderer');
            var presentationAttributes = {
              highRefreshRate: rendererSystem.highRefreshRate,
              foveationLevel: rendererSystem.foveationLevel
            };

            return vrDisplay.requestPresent([{
              source: this.canvas,
              attributes: presentationAttributes
            }]).then(enterVRSuccess, enterVRFailure);
          }
          return Promise.resolve();
        }

        // No VR.
        enterVRSuccess();
        return Promise.resolve();

        // Callback that happens on enter VR success or enter fullscreen (any API).
        function enterVRSuccess () {
          // vrdisplaypresentchange fires only once when the first requestPresent is completed;
          // the first requestPresent could be called from ondisplayactivate and there is no way
          // to setup everything from there. Thus, we need to emulate another vrdisplaypresentchange
          // for the actual requestPresent. Need to make sure there are no issues with firing the
          // vrdisplaypresentchange multiple times.
          var event;
          if (window.hasNativeWebVRImplementation && !window.hasNativeWebXRImplementation) {
            event = new CustomEvent('vrdisplaypresentchange', {detail: {display: utils.device.getVRDisplay()}});
            window.dispatchEvent(event);
          }

          self.addState('vr-mode');
          self.emit('enter-vr', {target: self});
          // Lock to landscape orientation on mobile.
          if (!isWebXRAvailable && self.isMobile && screen.orientation && screen.orientation.lock) {
            screen.orientation.lock('landscape');
          }
          self.addFullScreenStyles();

          // On mobile, the polyfill handles fullscreen.
          // TODO: 07/16 Chromium builds break when `requestFullscreen`ing on a canvas
          // that we are also `requestPresent`ing. Until then, don't fullscreen if headset
          // connected.
          if (!self.isMobile && !self.checkHeadsetConnected()) {
            requestFullscreen(self.canvas);
          }

          self.renderer.setAnimationLoop(self.render);
          self.resize();
        }

        function enterVRFailure (err) {
          if (err && err.message) {
            throw new Error('Failed to enter VR mode (`requestPresent`): ' + err.message);
          } else {
            throw new Error('Failed to enter VR mode (`requestPresent`).');
          }
        }
      },
      writable: true
    },

Я обнаружил, что в 0.9.2 this.hasXR = false и в 1.0.0 this.hasXR = true. Поэтому в 1.0.0 я устанавливаю это значение в false, а затем в else {} говорится, что vrDisplay.isPresenting не определен. Похоже, что vrDisplay = utils.device.getVRDisplay (); не может получить правильное значение, как в 0.9.2. Затем я нахожу этот код:

function getVRDisplay () { return vrDisplay; }

Для правильного возврата vrDisplay я попытался изменить приведенные выше коды:

if (false) {
  var updateEnterInterfaces = function () {
    var sceneEl = document.querySelector('a-scene');
    if (sceneEl.hasLoaded) {
      sceneEl.components['vr-mode-ui'].updateEnterInterfaces();
    } else {
      sceneEl.addEventListener('loaded', updateEnterInterfaces);
    }
  };
  var errorHandler = function (err) {
    error('WebXR session support error: ' + err.message);
  };
  if (navigator.xr.isSessionSupported) {
    // Current WebXR spec uses a boolean-returning isSessionSupported promise
    navigator.xr.isSessionSupported('immersive-vr').then(function (supported) {
      supportsVRSession = supported;
      updateEnterInterfaces();
    }).catch(errorHandler);

    navigator.xr.isSessionSupported('immersive-ar').then(function (supported) {
      supportsARSession = supported;
      updateEnterInterfaces();
    }).catch(function () {});
  } else if (navigator.xr.supportsSession) {
    // Fallback for implementations that haven't updated to the new spec yet,
    // the old version used supportsSession which is rejected for missing
    // support.
    navigator.xr.supportsSession('immersive-vr').then(function () {
      supportsVRSession = true;
      updateEnterInterfaces();
    }).catch(errorHandler);
    navigator.xr.supportsSession('immersive-ar').then(function () {
      supportsARSession = true;
      updateEnterInterfaces();
    }).catch(function () {});
  } else {
    error('WebXR has neither isSessionSupported or supportsSession?!');
  }
} else {
  console.log('navigator.getVRDisplays',!!navigator.getVRDisplays);
  if (navigator.getVRDisplays) {

    navigator.getVRDisplays().then(function (displays) {
      console.log('displays[0]',displays[0]);
      var sceneEl = document.querySelector('a-scene');
      vrDisplay = displays.length && displays[0];
      console.log(vrDisplay);
      if (sceneEl) { sceneEl.emit('displayconnected', {vrDisplay: vrDisplay}); }
    });
  }
}

Тогда vrDisplay имеет правильное значение (CardboardVRDisplay). Однако, таким образом, когда я вхожу в режим VR, экран становится черным. После сравнения vrDisplay между 0.9.2 и 1.0.0 я обнаружил, что искажение vrDisplay равно нулю в 1.0.0.

Я думаю, что ключевой момент - vrDisplay = utils.device.getVRDisplay () в Введите VR , но я не знаю, как решить эту проблему, надеюсь, кто-нибудь сможет увидеть этот вопрос и помочь этому бедному новичку ie ..

...