【 THREE.js 】10分でわかる簡単3D表示

WebGL

概要

  • THREE.jsを使って3Dを簡単に表示できます。
  • THREE.js をダウンロード後、examplesの下にline.htmlとして、以下のhtmlをコピーします。
  • 座標軸、点、線分を描くソースコードです。座標の大きさに関係なく表示できます。
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>three.js Sample</title>
  <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <link type="text/css" rel="stylesheet" href="main.css">
  </head>
  <body>

     <script type="module">
       import * as THREE from '../build/three.module.js';
       import { OrbitControls } from './jsm/controls/OrbitControls.js';

       var group, camera, scene, renderer;
       init();
       animate();

       function init() {
         scene = new THREE.Scene();
         renderer = new THREE.WebGLRenderer( { antialias: true } );
         renderer.setPixelRatio( window.devicePixelRatio );
         renderer.setSize( window.innerWidth, window.innerHeight );
         document.body.appendChild( renderer.domElement );

         // camera
         camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.05, 100000 );
         camera.position.set( 0, 0, 5 );
         scene.add( camera );

         // controls
         var controls = new OrbitControls( camera, renderer.domElement );
         scene.add( new THREE.AmbientLight( 0x222222 ) );

         // light
         var light = new THREE.PointLight( 0xffffff, 1 );
         camera.add( light );

         // helper
         var axis = new THREE.AxisHelper(2);
         axis.position.set(0.0,0.0,0.0);
         scene.add( axis );

         // line
         const line_material = new THREE.LineBasicMaterial({ color:0xffffff });
         var line_geometry   = new THREE.Geometry();
         line_geometry.vertices.push(
                 new THREE.Vector3(500,  500, 1000,0),
                 new THREE.Vector3(1000,1000, 1000.0)
         );
         var newline=new THREE.Line(line_geometry, line_material);
         line_geometry.computeBoundingSphere();
         line_geometry.computeBoundingBox();

         var radius = line_geometry.boundingSphere.radius;
         var scale = 1.0 / radius;
         newline.scale.set(scale,scale,scale);

         var center = line_geometry.boundingSphere.center;
         newline.translateX( -center.x * scale);
         newline.translateY( -center.y * scale);
         newline.translateZ( -center.z * scale);
         scene.add(newline);

         // points
         var point_geometry   = new THREE.Geometry();
         point_geometry.vertices = line_geometry.vertices;

         var point_material = new THREE.PointsMaterial( { size: 0.2,color: 0xff0000 } );
         var points = new THREE.Points( point_geometry, point_material );

         points.scale.set(scale,scale,scale);
         points.translateX( -center.x * scale);
         points.translateY( -center.y * scale);
         points.translateZ( -center.z * scale);
         scene.add(points);

         //EventListener
         window.addEventListener( 'resize', onWindowResize, false );
        }

        function onWindowResize() {
          camera.aspect = window.innerWidth / window.innerHeight;
          camera.updateProjectionMatrix();
          renderer.setSize( window.innerWidth, window.innerHeight );
       }

       function animate() {
          requestAnimationFrame( animate );
          render();
       }

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

    </script>
  </body>
</html>

解説

javascriptの始まりと終り

<script type="module">
~ 省略 ~
</script>
  • javascriptの定義と始まりと終りを示します。

インポート

       import * as THREE from '../build/three.module.js';
       import { OrbitControls } from './jsm/controls/OrbitControls.js';
  • THREEのモジュールとOrbitControlsのjsをインポートします。
  • OrbitControlsはマウスなどの制御のプログラムが入っています。

グローバル変数と関数

   var group, camera, scene, renderer;
   init();
   animate();
  • group, camera, scene, rendererはグローバル変数となります。
  • init()とanimate()と関数がCallされます。

function init()

おまじない

     scene = new THREE.Scene();
     renderer = new THREE.WebGLRenderer( { antialias: true } );
     renderer.setPixelRatio( window.devicePixelRatio );
     renderer.setSize( window.innerWidth, window.innerHeight );
     document.body.appendChild( renderer.domElement );

これは、おまじない的なコードです。以後、scene に描画したいものを追加していきます。

カメラ

         // camera
         camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.05, 100000 );
         camera.position.set( 0, 0, 5 );
         scene.add( camera );

PerspectiveCamerの引数は、以下の通りです。

  • 視野角 : 45度
  • アスペクト比(幅/高さ):window.innerWidth / window.innerHeight
  • 視体積の手前の距離(near) : 0.05
  • 視体積 の奥までの距離(far) : 100000

カメラの座標は、+ Z方向の5の方向から眺めます。座標では(0,0,5)です。

LINEの描画

     // line
   // 色
   const line_material = new THREE.LineBasicMaterial({ color:0xffffff });
   // LINEの定義
     var line_geometry   = new THREE.Geometry();
     line_geometry.vertices.push(
             new THREE.Vector3(500,  500, 1000,0),
             new THREE.Vector3(1000,1000, 1000.0)
     );
     var newline=new THREE.Line(line_geometry, line_material);

     //包括球を計算します
     line_geometry.computeBoundingSphere();
     var radius = line_geometry.boundingSphere.radius;
   //描画領域に入るようにスケーリングします
     var scale = 1.0 / radius;
     newline.scale.set(scale,scale,scale);
     //描画領域の中心に物体中心を合わせます
     var center = line_geometry.boundingSphere.center;
     newline.translateX( -center.x * scale);
     newline.translateY( -center.y * scale);
     newline.translateZ( -center.z * scale);
    //シーンに登録します
     scene.add(newline);

点の描画

     // points
     var point_geometry   = new THREE.Geometry();
   //線分の頂点をコピー
     point_geometry.vertices = line_geometry.vertices;
   //点のサイズ、色を定義
     var point_material = new THREE.PointsMaterial( { size: 0.2,color: 0xff0000 } );
     var points = new THREE.Points( point_geometry, point_material );
   //描画領域に入るようにスケーリングします
     points.scale.set(scale,scale,scale);
     //描画領域の中心に物体中心を合わせます
     points.translateX( -center.x * scale);
     points.translateY( -center.y * scale);
     points.translateZ( -center.z * scale);
      //シーンに登録します
     scene.add(points);

リサイズ

         //EventListener
         window.addEventListener( 'resize', onWindowResize, false );

イベントリスナにresizeの関数を登録します。

その他の関数

        function onWindowResize() {
          camera.aspect = window.innerWidth / window.innerHeight;
          camera.updateProjectionMatrix();
          renderer.setSize( window.innerWidth, window.innerHeight );
       }

       function animate() {
          requestAnimationFrame( animate );
          render();
       }

       function render() {
          renderer.render( scene, camera );
       }
  • onWindowResize()は、リサイズによって呼ばれる関数です。
  • animate()は、init()関数の後のCallされる関数です。
  • render()関数は、 animate() よりCallされます。