0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WebXRを利用して、スマートフォンなどのデバイス位置の検出

Posted at

さっそくコード

index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>posDetect</title>
  </head>
  <body>
    <canvas class="output-canvas"></canvas>

    <!-- <button class="green button" type="button">Start Game</button> -->
    <button id="xrStartButton" class="blue button use-webxr" type="button">
      Start(VR mode)
    </button>

    <script src="/libs/gl-matrix.js"></script>
    <script>
      const outputCanvas = document.querySelector('.output-canvas');
      const gl = outputCanvas.getContext('webgl');
      const viewerStartPosition = glMatrix.vec3.fromValues(0, 0, -10);
      const viewerStartOrientation = glMatrix.vec3.fromValues(0, 0, 1.0);

      let xrSession = null;
      let usingXR = false;
      let xrStartButton = document.getElementById('xrStartButton');
      let worldRefSpace;
      let viewerRefSpace;
      let animationFrameRequestID;

      window.addEventListener('load', (event) => {
        console.log('window loaded');
        xrStartButton.addEventListener('click', handleStartButtonClick);
      });

      outputCanvas.addEventListener('webglcontextlost', (event) => {
        /* The context has been lost but can be restored */
        event.canceled = true;
      });

      /* When the GL context is reconnected, reload the resources for the
      current scene. */
      outputCanvas.addEventListener('webglcontextrestored', (event) => {
        // loadSceneResources(currentScene);
      });

      function XRRenderingLoop(currentFrameTime, frame) {
        // ループ
        animationFrameRequestID =
          xrSession.requestAnimationFrame(XRRenderingLoop);

        // デバイスの位置取得
        const pose = frame.getViewerPose(viewerRefSpace);
        if (!pose) return;
        console.log(pose.transform.position);
      }

      async function onStartedXRSession(xrSession) {
        xrStartButton.style.visibility = 'hidden';

        try {
          await gl.makeXRCompatible();

          const xrWebGLLayer = new XRWebGLLayer(xrSession, gl);
          xrSession.updateRenderState({ baseLayer: xrWebGLLayer });

          worldRefSpace = await xrSession.requestReferenceSpace('local');
          if (worldRefSpace) {
            viewerRefSpace = worldRefSpace.getOffsetReferenceSpace(
              new XRRigidTransform(viewerStartPosition, viewerStartOrientation)
            );
            // loopスタート
            animationFrameRequestID =
              xrSession.requestAnimationFrame(XRRenderingLoop);
          }
        } catch (err) {
          console.error(err);
          xrSession.end();
        }
      }

      async function handleStartButtonClick(event) {
        if (event.target.classList.contains('use-webxr') && navigator.xr) {
          try {
            xrSession = await navigator.xr.requestSession('immersive-vr'); //immersive-ar
            await onStartedXRSession(xrSession);
            usingXR = true;
          } catch (err) {
            xrSession = null;
            usingXR = false;
          }
        }
      }
    </script>
  </body>
</html>

p5xr使うとすっごい短縮できる

p5xr.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>p5</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.10.0/p5.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/p5.xr/dist/p5xr.js"></script>
    <style>
      html,
      body {
        margin: 0;
        padding: 0;
      }
    </style>
  </head>
  <body>
    <script>
      async function preload() {
        createARCanvas();
        // createVRCanvas();
      }

      function setup() {}

      function draw() {
        const viewer = getViewer();
        console.log(viewer.pose.transform.position);
      }
    </script>
  </body>
</html>

開発方法Tips

Chromeの拡張機能でエミュレーターがあった
https://chromewebstore.google.com/detail/immersive-web-emulator/cgffilbpcibhmcfbgggfhfolhkfbhmik

いくつかあるけど上記のものは対応機能が多かったのでこれを使ってます

実行方法

localhostでデバッグをやるならいいのですが、同じLAN内のスマートフォンだとhttpsじゃないとだ

以前の記事から
https://qiita.com/ono-honeycomb/items/359a254fd4c859692472

$ openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem
$ http-server -S -C cert.pem

いろいろ試してみたい!

部屋内でスマートフォンがどこにいて、どこに向けているかってのが検出できそうなので、
部屋のどこの壁の位置にかざしているかだったり、部屋に設置されているどの物を見ているかだったり、ユーザーの首からぶら下げてもらって、ユーザーがどの位置にいるかっていうのを検出したりいろいろできそうです

他の検出方法

  • ネイティブアプリでもよさそう
  • UWBとかの別機器
    • RTKとか
  • 壁に測域センサ
    • かざすならNFCでも?
  • Kinect的なのでも
    • Femtoとか
    • 今単眼のカメラでも人検出できちゃうのでそれでも
  • スマートフォンにQRコード貼っちゃってもいいのか
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?