みかづきブログ・カスタム

基本的にはちょちょいのほいです。

AR.js + Three.jsでつくったマーカー型AR用マーカーの縁の太さを変更する 📷

こちらのサイト でARマーカーを作成とする際、Pattern Ratioを変更するとマーカーにする画像の大きさを変更することができるので、結果として相対的に縁の太さを変更することができます。

jeromeetienne.github.io

ただ、Pattern Ratioを0.5以外に設定した場合は、THREEx.ArToolkitContextのインスタンスを作成する際に渡すパラメーターのpatternRatioを設定値に合わせる必要があるので注意が必要です。

const arToolkitContext = new THREEx.ArToolkitContext({
  cameraParametersUrl: './camera.dat',
  detectionMode: 'mono',
  patternRatio: .9 // 0.1 ~ 0.9で設定、デフォルトは0.5
});

今回は、クエリパラメーターでpatternRatioに渡す値を変更できる デモサイト を作ったので、いろんな縁の太さをマーカーを試してみてください。マーカー画像は、

を設定しています。

develop.kimizuka.org

使い方

patternRatioを0.1に設定したい場合は、

https://develop.kimizuka.org/ar-marker-pattern-ratio/?ratio=0.1

patternRatioを0.9に設定したい場合は、

https://develop.kimizuka.org/ar-marker-pattern-ratio/?ratio=0.9

という感じで使います。

ソースコード

<html>
<head>
  <title>pattern-ratio</title>
  <meta name="viewport" content="width=device-width, viewport-fit=cover, shrink-to-fit=no" />
  <style>
    * {
      margin: 0; padding: 0;
    }

    .wrapper {
      position: relative;
      overflow: hidden;
    }
  </style>
</head>
<body>
  <div class="wrapper">
    <canvas></canvas>
  </div>
  <script src="https://unpkg.com/three@0.127.0/build/three.min.js"></script>
  <script src="https://raw.githack.com/AR-js-org/AR.js/3.3.3/three.js/build/ar.js"></script>
  <script>
    const renderer = new THREE.WebGLRenderer({
      canvas: document.querySelector('canvas'),
      antialias: true,
      alpha: true
    });
    const camera = new THREE.PerspectiveCamera();
    const scene = new THREE.Scene();
    const markerRoot = new THREE.Group();
    const query = convertQueryStringToObject(location.search);
    const patternRatio = Number(query.ratio) || .5;
    const arToolkitContext = new THREEx.ArToolkitContext({
      cameraParametersUrl: './camera.dat',
      detectionMode: 'mono',
      patternRatio
    });
    const arToolkitSource = new THREEx.ArToolkitSource({
      sourceType: 'webcam'
    });
    const arMarkerControl = new THREEx.ArMarkerControls(arToolkitContext, markerRoot, {
      type: 'pattern',
      patternUrl: 'pattern-marker.patt'
    });

    renderer.setSize(window.innerWidth, window.innerHeight);

    window.addEventListener('resize', handleResize, {
      passive: true
    });

    arToolkitContext.init(() => {
      camera.projectionMatrix.copy(arToolkitContext.getProjectionMatrix());
    });

    arToolkitSource.init(() => {
      document.querySelector('.wrapper').appendChild(arToolkitSource.domElement);
      setTimeout(() => handleResize(), 400);
    });

    scene.add(markerRoot);

    const cube = new THREE.Mesh(
      new THREE.BoxGeometry(1, 1, 1),
      new THREE.MeshNormalMaterial()
    );

    cube.position.set(0, .5, 0);

    markerRoot.add(cube);

    renderer.setAnimationLoop((delta) => {
      if (arToolkitSource.ready) {
        arToolkitContext.update(arToolkitSource.domElement);
      }

      renderer.render(scene, camera);
    });

    function handleResize() {
      if (arToolkitSource.ready) {
        arToolkitSource.onResize();
        arToolkitSource.copySizeTo(renderer.domElement);
      }

      renderer.setPixelRatio(window.devicePixelRatio);
    }

    function convertQueryStringToObject(query = '') {
      const obj = {};
      const params = query.split(/[?&]/);

      for (let i = 0; i < params.length; ++i) {
        const array = params[i].split('=');
        const key = decode(array[0]);
        const value = decode(array[1]);

        if (key) {
          obj[key] = value;
        }
      }

      return obj;
    }

    function fixedDecodeURIComponent(str) {
      return decodeURIComponent(str.replace(/[!'()*]/g, unescape));
    }

    function decode(arg) {
      return arg ? fixedDecodeURIComponent(arg) : null;
    }
  </script>
</body>
</html>