【Three.js】物体を回転、並行移動、スケールする方法(デモあり)

2023年11月18日WebGL & Three.js

Three.jsを使って物体を回転、並行移動、スケールする方法を紹介します。
デモもあるので、一度確認してみてください。

Three.jsを使って物体を回転、並行移動、スケールするデモ

サンプルコード

  const scene = new THREE.Scene();
  const camera = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
  );

  const renderer = new THREE.WebGLRenderer();
  renderer.setSize(window.innerWidth, window.innerHeight);

  document.body.appendChild(renderer.domElement);

  const geometry = new THREE.TorusGeometry(10, 3, 200, 20);

  const material = new THREE.MeshBasicMaterial({
    color: 0x00fff0,
    wireframe: true,
  });

  const mesh = new THREE.Mesh(geometry, material);
  scene.add(mesh);

  // 軸のヘルパーを出す処理
  // 引数には軸の長さを設定する
  const axis = new THREE.AxesHelper(20);
  scene.add(axis);

  camera.position.z = 30;

  const control = new OrbitControls(camera, renderer.domElement);

  let animateType;
  function animate() {
    requestAnimationFrame(animate);

    control.update();
    switch (type) {
      case "回転":
        // 回転
        // mesh.rotation.x += 0.01;
        // mesh.rotation.y += 0.01;
        // 上と全く同じ
        mesh.rotateX(0.01);
        mesh.rotateY(0.01);
        break;

      case "並行移動":
        // 並行移動
        // パフォーマンスがよくない
        // 引数分だけ物体を動かす
        // geometry.translate(0.01, 0, 0.01);
        // 元のある座標から物体を数値分ずらして置く
        mesh.position.x += 0.02;
        mesh.position.z += 0.02;
        break;

      case "スケール":
        // スケール
        // geometry.scale(1.01, 1.01, 1);
        mesh.scale.x += 0.01;
        mesh.scale.y += 0.01;
        break;
      default:
        console.warn("Unknown geometry type: " + type);
        return;
    }

    renderer.render(scene, camera);
  }

  animate();

以下それぞれの解説です。
もしThree.jsの基本的な操作の一連の流れを知らないという場合は、Three.jsの基本的な操作の一連の流れがとても短くまとめた記事なので参考にしてみてください。
具体的なコードとデモが見たい場合は、【WebGL&Three.js入門】Three.jsの一番シンプルなサンプルコードのチュートリアルの解説でデモもみれる状態にしているので参考にしてみてください。

回転させる

        // mesh.rotation.x += 0.01;
        // mesh.rotation.y += 0.01;
        // 上と全く同じ
        mesh.rotateX(0.01);
        mesh.rotateY(0.01);

meshのrotateXを使ってもいいし、rotationでxにアクセスしてもいいです。
最終的にはrotationのxの値を変更しているので、同じことをしています。

並行移動させる

// geometry.translate(0.01, 0, 0.01);
        // 元のある座標から物体を数値分ずらして置く
        mesh.position.x += 0.02;
        mesh.position.z += 0.02;

geometryを使う方法と、meshのpositionの数値を変更する方法があります。
geometryを使う方法は、引数分だけ物体を動かすため、あまりパフォーマンスがよくありません。
methのpositionを動かす方は、元の座標から指定した数値分ずらして置くという処理になり、こちらの方がパフォーマンス的にはいいです。

スケールさせる

// geometry.scale(1.01, 1.01, 1);
        mesh.scale.x += 0.01;
        mesh.scale.y += 0.01;

これも上と同様で、geometryのscaleを使う方法とmeshのscaleを使う方法があります。

geometry.scale()を使用すると、そのジオメトリの頂点の位置が変更され、ジオメトリが拡大縮小されます。こちらはオブジェクトの形状が変化します。
meshのscale.set()を使用すると、オブジェクトの位置は変更されず、表示されるスケールが変更されます。こちらはオブジェクトのサイズが変更されるだけで、オブジェクトの形状は変化しません。
パフォーマンスの観点ではgeometry.scaleは負荷が重く、scale.setはそれに比べると軽い処理になります。
そのため、特段理由がない限りは、requestAnimationFrame内などではmeshのscale.setを使う方が良いです。

余談: 軸を表示する

  const axis = new THREE.AxesHelper(20);
  scene.add(axis);

AxesHelperをインスタンス化することで、x,y,zの軸を表示させることができます。
引数には、軸の長さをとります。