<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <title>depthmap-viewer-three</title>
  <style>
    body {
      font-family: sans-serif;
      margin: 0;
    }

    .dropzone {
      box-sizing: border-box;
      display: none;
      position: fixed;
      width: 100%;
      height: 100%;
      left: 0;
      top: 0;
      z-index: 99999;
      background: rgba(#60a7dc, .8);
      border: 11px dashed #60a7dc;
    }
  </style>
  <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script>
  <script type="importmap">
{
"imports": {
  "three": "https://unpkg.com/three@0.154.0/build/three.module.js",
  "three/addons/": "https://unpkg.com/three@0.154.0/examples/jsm/"
}
}
</script>
  <script type="module">
    import * as THREE from 'three';
    import { OrbitControls } from "three/addons/controls/OrbitControls";
    import { GUI } from 'three/addons/libs/lil-gui.module.min.js';

    var rgbBase64Img = window.frameElement?.getAttribute('data-rgb') || "public/images/rgb.png"
    var depthBase64Img = window.frameElement?.getAttribute('data-depth') || "public/images/depth.png"



    let mesh;
    let material;
    let stopAnimation = false;

    const settings = {
      metalness: 0.0,
      roughness: 0.5,
      ambientIntensity: 0.85,
      displacementScale: 100,
      displacementBias: -0.5,
    };
    const meshSettings = {
      rotation: {
        x: 0,
        y: 0,
        z: 0
      }
    }

    // init
    const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
    camera.position.z = 3;

    const scene = new THREE.Scene();

    const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
    scene.add(ambientLight);

    const pointLight = new THREE.PointLight(0xff0000, 0.5);
    pointLight.position.z = 2500;
    scene.add(pointLight);


    const renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.setAnimationLoop(animation);
    // renderer.xr.enabled = true;
    renderer.toneMapping = THREE.ACESFilmicToneMapping;
    renderer.toneMappingExposure = 1;
    renderer.outputEncoding = THREE.sRGBEncoding;
    document.body.appendChild(renderer.domElement);

    // animation
    function animation(time) {
      if (mesh && !stopAnimation) {
        mesh.rotation.x = 0.5 * Math.sin(time / 2000);
        mesh.rotation.y = 0.5 * Math.sin(time / 2000);
        meshSettings.rotation.x = mesh.rotation.x;
        meshSettings.rotation.y = mesh.rotation.y;
      }
      renderer.render(scene, camera);

    }

    function onWindowResize() {

      const aspect = window.innerWidth / window.innerHeight;
      camera.aspect = aspect;
      camera.updateProjectionMatrix();

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

    }
    window.addEventListener('resize', onWindowResize);


    // orbit controls
    const controls = new OrbitControls(camera, renderer.domElement);
    controls.enableZoom = true;
    controls.enableDamping = true;

    async function getCanvasTexture(imageSrc) {
      return new Promise((resolve, reject) => {
        const image = new Image();
        image.src = imageSrc;
        image.onload = () => {
          const ctx = document.createElement('canvas').getContext('2d');
          ctx.canvas.width = image.width;
          ctx.canvas.height = image.height;
          ctx.drawImage(image, 0, 0, image.width, image.height);
          const texture = new THREE.CanvasTexture(ctx.canvas);
          resolve(texture);
        }
      })

    }
    (async () => {
      const rgbTexture = await getCanvasTexture(rgbBase64Img);
      const depthTexture = await getCanvasTexture(depthBase64Img);

      if (mesh) {
        mesh.geometry.dispose();
        mesh.material.dispose();
        scene.remove(mesh);
      }
      // material
      material = new THREE.MeshStandardMaterial({

        color: 0xaaaaaa,
        roughness: settings.roughness,
        metalness: settings.metalness,

        map: rgbTexture,

        displacementMap: depthTexture,
        displacementScale: settings.displacementScale,
        displacementBias: settings.displacementBias,

        side: THREE.DoubleSide

      });
      // generating geometry and add mesh to scene
      const geometry = new THREE.PlaneGeometry(rgbTexture.image.width, rgbTexture.image.height, 512, 512);
      mesh = new THREE.Mesh(geometry, material);
      const scale = 1 / Math.max(rgbTexture.image.width, rgbTexture.image.height);
      mesh.scale.set(scale, scale, scale);
      scene.add(mesh);

    })()



    // setup gui
    const gui = new GUI();
    gui.close();
    const sceneGUI = gui.addFolder('Scene');
    sceneGUI.add(settings, 'metalness').min(0).max(1).onChange(function (value) {
      material.metalness = value;
    });
    sceneGUI.add(settings, 'roughness').min(0).max(1).onChange(function (value) {
      material.roughness = value;
    });
    sceneGUI.add(settings, 'ambientIntensity').min(0).max(1).onChange(function (value) {
      ambientLight.intensity = value;
    });
    sceneGUI.add(settings, 'displacementScale').min(0).max(500.0).onChange(function (value) {
      material.displacementScale = value;
    });
    sceneGUI.add(settings, 'displacementBias').min(-500).max(500).onChange(function (value) {
      material.displacementBias = value;
    });
    const meshGUI = gui.addFolder('Mesh');
    meshGUI.add(meshSettings.rotation, 'x').min(-Math.PI).max(Math.PI).step(0.0001).onChange(function (value) {
      mesh.rotation.x = value;
      stopAnimation = true;
    }).listen()


    meshGUI.add(meshSettings.rotation, 'y').min(-Math.PI).max(Math.PI).step(0.0001).onChange(function (value) {
      mesh.rotation.y = value;
      stopAnimation = true;
    }).listen()


    meshGUI.add(meshSettings.rotation, 'z').min(-Math.PI).max(Math.PI).step(0.0001).onChange(function (value) {
      mesh.rotation.z = value;
      stopAnimation = true;
    }).listen()


  </script>
</head>

<body>
</body>

</html>