Newer
Older
about-Leaflet / avater.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Document</title>
  <style>
    body {
      margin: 0;
      overflow: hidden;
    }
  </style>
</head>
<body>
  <div id="WebGL-output"></div>

  <script type="module">
    import * as THREE from "https://unpkg.com/three@0.126.1/build/three.module.js";
    import { PointerLockControls } from "https://unpkg.com/three@0.126.1/examples/jsm/controls/PointerLockControls.js";
    import { GLTFLoader } from "https://unpkg.com/three@0.126.1/examples/jsm/loaders/GLTFLoader.js";

    let camera;
    let scene;
    let renderer;
    let controls;
    let moveForward = false;
    let moveBackward = false;
    let moveLeft = false;
    let moveRight = false;
    let bChanLoaded = false; // B-chan.glbがロードされたかどうかを示すフラグ
    let classroomModel, blackboardModel, bchanModel;

    function init() {
      // シーンの作成
      scene = new THREE.Scene();
      scene.background = new THREE.Color(0xffffff); // 背景色

      // カメラの作成
      camera = new THREE.PerspectiveCamera(
        45,
        window.innerWidth / window.innerHeight,
        0.1,
        1000
      );
      camera.position.set(1, 5, 5);
      camera.lookAt(new THREE.Vector3(0, 0, 0));

      // ライトの作成
      const light = new THREE.SpotLight(0xffffff, 1.0);
      light.position.set(100, 500, 500);
      scene.add(light);
      light.castShadow = true;

      // モデルの読み込み
      const loader = new GLTFLoader();

      loader.load(
        'https://www.yatex.org/gitbucket/j2311/about-Leaflet/raw/main/class_room_final.glb',
        function (gltf) {
          classroomModel = gltf.scene;
          scene.add(classroomModel);
        },
        function (xhr) {
          console.log((xhr.loaded / xhr.total * 100) + '% loaded');
        },
        function (error) {
          console.error('An error happened', error);
        }
      );

      loader.load(
        'https://www.yatex.org/gitbucket/j2311/about-Leaflet/raw/main/black board.glb',
        function (gltf) {
          blackboardModel = gltf.scene;
          scene.add(blackboardModel);
        },
        function (xhr) {
          console.log((xhr.loaded / xhr.total * 100) + '% loaded');
        },
        function (error) {
          console.error('An error happened', error);
        }
      );

      loader.load(
        'https://www.yatex.org/gitbucket/j2311/about-Leaflet/raw/main/B-chan.glb',
        function (gltf) {
          bchanModel = gltf.scene;
          scene.add(bchanModel);
          bChanLoaded = true; // モデルがロードされたときにフラグを更新
        },
        function (xhr) {
          console.log((xhr.loaded / xhr.total * 100) + '% loaded');
        },
        function (error) {
          console.error('An error happened', error);
        }
      );

      const axesHelper = new THREE.AxesHelper(100);
      scene.add(axesHelper);
      const gridHelper = new THREE.GridHelper(50, 50);
      scene.add(gridHelper);

      // カメラコントロールの作成
      controls = new PointerLockControls(camera, document.body);
      document.addEventListener("click", function () {
        controls.lock();
      });

      // キーボードのキー操作
      document.addEventListener("keydown", handleKeyDown);
      document.addEventListener("keyup", handleKeyUp);

      // オブジェクトの作成と追加
      const geometry = new THREE.SphereGeometry();
      const material = new THREE.MeshBasicMaterial({ color: 0xffff00 });
      const mesh = new THREE.Mesh(geometry, material);
      scene.add(mesh);

      // レンダラーの作成
      renderer = new THREE.WebGLRenderer({
        alpha: true,
        antialias: true,
      });
      renderer.setSize(window.innerWidth, window.innerHeight);
      document.getElementById("WebGL-output").appendChild(renderer.domElement);
    }

    function handleKeyDown(event) {
      switch (event.key) {
        case "w":
        case "ArrowUp":
          moveForward = true;
          break;
        case "s":
        case "ArrowDown":
          moveBackward = true;
          break;
        case "a":
        case "ArrowLeft":
          moveLeft = true;
          break;
        case "d":
        case "ArrowRight":
          moveRight = true;
          break;
        case "g": // Move B-chan.glb forward
        case "ArrowUp":
          if (bChanLoaded) {
            bchanModel.position.z -= 0.5; // 動かす方向を調整
          }
          break;
        case "b": // Move B-chan.glb backward
        case "ArrowDown":
          if (bChanLoaded) {
            bchanModel.position.z += 0.5; // 動かす方向を調整
          }
          break;
        case "h": // Move B-chan.glb left
        case "ArrowLeft":
          if (bChanLoaded) {
            bchanModel.position.x -= 0.5; // 動かす方向を調整
          }
          break;
        case "f": // Move B-chan.glb right
        case "ArrowRight":
          if (bChanLoaded) {
            bchanModel.position.x += 0.5; // 動かす方向を調整
          }
          break;
      }
    }

    function handleKeyUp(event) {
      switch (event.key) {
        case "w":
        case "ArrowUp":
          moveForward = false;
          break;
        case "s":
        case "ArrowDown":
          moveBackward = false;
          break;
        case "a":
        case "ArrowLeft":
          moveLeft = false;
          break;
        case "d":
        case "ArrowRight":
          moveRight = false;
          break;
      }
    }

    function updateCameraPosition() {
      const speed = 5;
      const direction = new THREE.Vector3();
      const { x, y, z } = controls.getObject().position;
      direction.x = Number(moveRight) - Number(moveLeft);
      direction.z = Number(moveBackward) - Number(moveForward);
      direction.normalize();
      const delta = speed * 0.1;
      controls.getObject().translateX(direction.x * delta);
      controls.getObject().translateZ(direction.z * delta);
    }

    function animate() {
      requestAnimationFrame(animate);
      updateCameraPosition();
      renderer.render(scene, camera);
    }

    // クリック時の処理
    document.addEventListener("dblclick", function (event) {
      event.preventDefault();
      const raycaster = new THREE.Raycaster();
      const mouse = new THREE.Vector2();
      // マウス位置の取得
      mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
      mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
      raycaster.setFromCamera(mouse, camera);
      const intersects = raycaster.intersectObjects(scene.children, true);
      if (intersects.length > 0) {
        if (intersects[0].object.name === "blackboard_main") {
          window.open("https://www.yatex.org/gitbucket/j2311/about-Leaflet/pages/hello-template.html");
        }
        console.log(intersects[0]);
      }
    });

    // 初期化とアニメーションの開始
    init();
    animate();
  </script>
</body>
</html>