NASAのEarth 3D Modelをthree.jsで使ってみた

![](https://raw.githubusercontent.com/cheer4u-code/earth_3d_model/main/earth_3d_model.png "Earth 3D Model")

NASAのEarth 3D Modelをthree.jsのGLTFLoader()を使って読み込んで表示させてみました。

# わかったこと

three.jsのGLTFLoader()でちゃんと読み込んで表示できること。
Earth 3D Modelのサイズが1000あったので、使ったカメラPerspectiveCameraのfar (区間の終了距離)を大きくする必要があった。または、Earth 3D Modelのスケールで縮小する必要がった。
ライトを当てないと真っ黒になること(なので環境光源を明るめに当てました)。
扁平率が約1/298なので地球楕円体になっていたこと。
経度0度がthree.jsのz軸のマイナス方向だったこと。

作成したものは以下で確認できます。

https://cheer4u-code.github.io/earth_3d_model/


# 作成

GLTFLoader()の使い方は、three.jsのドキュメントを参考にしました。

https://threejs.org/docs/#examples/en/loaders/GLTFLoader

あとは、テキストを表示するのにthree.jsのドキュメントにあった DOM + CSS を使っています。

https://threejs.org/docs/#manual/en/introduction/Creating-text

three.jsのシーンの作成はCreating a sceneを参考にしました。

https://threejs.org/docs/#manual/en/introduction/Creating-a-scene

全ソースコードはこうなりました。

```html:index.html
<!DOCTYPE html>
<html lang="en">

<head>
  <title>Earth 3D Model - Earth_1_12756.glb</title>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <style>
    body {
      margin: 0;
      overflow: hidden;
    }

    #info {
      color: lightgrey;
      position: absolute;
      top: 10px;
      width: 100%;
      z-index: 100;
      display: block;
    }
  </style>
</head>

<body>
  <script type="importmap">
      {
        "imports": {
          "three": "https://unpkg.com/three@0.164.1/build/three.module.js",
          "three/addons/controls/OrbitControls": "https://unpkg.com/three@0.164.1/examples/jsm/controls/OrbitControls.js",
          "three/addons/loaders/GLTFLoader": "https://unpkg.com/three@0.164.1/examples/jsm/loaders/GLTFLoader.js"
        }
      }
    </script>
  <div id="info">
    Earth 3D Model - https://science.nasa.gov/resource/earth-3d-model/
    <div id="automatically_generated">
    </div>
  </div>
  <script type="module">
    import * as THREE from "three";
    import { OrbitControls } from "three/addons/controls/OrbitControls";
    import { GLTFLoader } from "three/addons/loaders/GLTFLoader";

    const renderer = new THREE.WebGLRenderer();
    document.body.appendChild(renderer.domElement);
    const scene = new THREE.Scene();

    // XYZ軸を表示
    const axesHelper = new THREE.AxesHelper(700);
    scene.add(axesHelper);

    // カメラ
    const camera = new THREE.PerspectiveCamera(
      75,
      window.innerWidth / window.innerHeight,
      1,
      10000
    );
    camera.position.set(1000, 100, 100);
    const controls = new OrbitControls(camera, renderer.domElement);

    // 環境光源
    const ambientLight = new THREE.AmbientLight(0xffffff, 5);
    scene.add(ambientLight);

    const automaticallyGenerated = document.getElementById('automatically_generated');
    // GLTFLoader: https://threejs.org/docs/#examples/en/loaders/GLTFLoader
    const loader = new GLTFLoader();
    loader.load(
      // Earth_1_12756.glb: Earth 3D Model https://science.nasa.gov/resource/earth-3d-model/ の読み込み
      "Earth_1_12756.glb",
      // リソースがロードされたときに呼び出される
      function (gltf) {
        scene.add(gltf.scene);
        const boundingBox = new THREE.Box3().setFromObject(gltf.scene);
        const boxSize = boundingBox.getSize(new THREE.Vector3());
        automaticallyGenerated.innerText = `Size of Earth 3D Model: x=${boxSize.x}, y=${boxSize.y}, z=${boxSize.z}`;
      },
      // 読み込み中に呼び出される
      function (xhr) {
        automaticallyGenerated.innerText = Math.round((xhr.loaded / xhr.total) * 100) + "% loaded";
      },
      // 読み込みエラーが発生したときに呼び出される
      function (error) {
        automaticallyGenerated.innerText = error;
      }
    );

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

    function onWindowResize() {
      const width = window.innerWidth;
      const height = window.innerHeight;
      renderer.setPixelRatio(window.devicePixelRatio);
      renderer.setSize(width, height);
      camera.aspect = width / height;
      camera.updateProjectionMatrix();
    }
    onWindowResize();
    window.addEventListener("resize", onWindowResize);
  </script>
</body>

</html>
```

[Earth with Clouds 3D Model](https://science.nasa.gov/resource/earth-with-clouds-3d-model/) を使うと雲つきの地球が表示できました。

![earth_clouds_3d_model.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2527700/6474b159-14d2-aa59-fbe8-4c70325f8bb0.png "Earth with Clouds 3D Model")

最初は表示されなくて、原因がわからず悩みましたが、サイズの問題と分かってからは特に問題なく表示できました。