jackmiwamiwa devblog

フロントエンドをメインに行ったことをまとめていくサイトになります。

dat.GUIを使用して、開発時の3Dオブジェクトの編集を行いやすくする

今回、THREE.jsを使用した3Dオブジェクトやpixi.jsを使用した2Dオブジェクトなどの開発時に利用したdat.GUIについてのやり方を紹介します。

今回使用するもの

NPM

version: 0.123.0

www.npmjs.com

version: 0.7.7

www.npmjs.com

CDN

https://cdnjs.cloudflare.com/ajax/libs/three.js/r123/three.min.js

https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.7/dat.gui.min.js

完成形

const scene = new THREE.Scene();
scene.background = new THREE.Color( 0x000000 );
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.BoxGeometry();
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const cube = new THREE.Mesh( geometry, material );
scene.add( cube );

camera.position.z = 5;

const datGUIObj = {
  positionZ: 5,
  rotateXSpped: 0.01,
  rotateYSpped: 0.01,
  cubeWireframe: true,
  backColor: {
    red: 0,
    green: 0,
    blue: 0
  },
  cubeColor: {
    red: 0,
    green: 1,
    blue: 0
  }
};

const gui = new dat.GUI();

gui.add(datGUIObj, 'positionZ', 0, 10);
gui.add(datGUIObj, 'rotateXSpped', 0, 0.1);
gui.add(datGUIObj, 'rotateYSpped', 0, 0.1);
gui.add(datGUIObj, 'cubeWireframe');
const backGUI = gui.addFolder('Back Color');
backGUI.add(datGUIObj.backColor, 'red', 0, 1).name('Red').step(0.01)
backGUI.add(datGUIObj.backColor, 'green', 0, 1).name('Green').step(0.01)
backGUI.add(datGUIObj.backColor, 'blue', 0, 1).name('Blue').step(0.01)
const colorGUI = gui.addFolder('Cube Color');
colorGUI.add(datGUIObj.cubeColor, 'red', 0, 1).name('Red').step(0.01)
colorGUI.add(datGUIObj.cubeColor, 'green', 0, 1).name('Green').step(0.01)
colorGUI.add(datGUIObj.cubeColor, 'blue', 0, 1).name('Blue').step(0.01)
colorGUI.open()

const animate = function () {
  requestAnimationFrame( animate );

  cube.material.wireframe = datGUIObj.cubeWireframe;
  scene.background.r = datGUIObj.backColor.red;
  scene.background.g = datGUIObj.backColor.green;
  scene.background.b = datGUIObj.backColor.blue;
  cube.material.color.r = datGUIObj.cubeColor.red;
  cube.material.color.g = datGUIObj.cubeColor.green;
  cube.material.color.b = datGUIObj.cubeColor.blue;
  camera.position.z = datGUIObj.positionZ;
  cube.rotation.x += datGUIObj.rotateXSpped;
  cube.rotation.y += datGUIObj.rotateYSpped;

  renderer.render( scene, camera );
};

animate();

実装手順

1. ベースのプログラムを反映

今回は以下のリンクの一番下にあるコードを使用します。

threejs.org

<!DOCTYPE html>
<html>
    <head>
       <title>My first three.js app</title>
       <style>
            body { margin: 0; }
        </style>
   </head>
    <body>
        <script src="js/three.js"></script>
        <script>
           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.BoxGeometry();
           const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
           const cube = new THREE.Mesh( geometry, material );
           scene.add( cube );

           camera.position.z = 5;

           const animate = function () {
               requestAnimationFrame( animate );

               cube.rotation.x += 0.01;
               cube.rotation.y += 0.01;

               renderer.render( scene, camera );
           };

           animate();
       </script>
    </body>
</html>

上記のコードをコピーすると以下のような状態になります。

f:id:jackswim3411:20201223145516p:plain

2. dat.GUIの反映

// npmでインストールした場合
import * as dat from 'dat.gui';
// これから要素の変更を行うための大枠
const datGUIObj = {}
// ここでdat.GUIのメニューを表示
const gui = new dat.GUI();

これで右上に Close Controlsが表示されます。(現時点ではメニュー項目は一切ないです。)

f:id:jackswim3411:20201223152541p:plain

3. 各種パラメータの追加

回転する速度の調整

const datGUIObj = {
  rotateXSpped: 0.01,
  rotateYSpped: 0.01,
};


gui.add(datGUIObj, 'rotateXSpped', 0, 0.1);
gui.add(datGUIObj, 'rotateYSpped', 0, 0.1);


const animate = function () {
  requestAnimationFrame( animate );

  cube.rotation.x += datGUIObj.rotateXSpped;
  cube.rotation.y += datGUIObj.rotateYSpped;
  renderer.render( scene, camera );
};

カメラの位置の修正

const datGUIObj = {
  positionZ: 5,
};

gui.add(datGUIObj, 'positionZ', 0, 10);

const animate = function () {
  requestAnimationFrame( animate );

  camera.position.z = datGUIObj.positionZ;
  renderer.render( scene, camera );
};

ワイヤーフレームのON, OFF設定

const datGUIObj = {
  cubeWireframe: true,
};

gui.add(datGUIObj, 'cubeWireframe');

const animate = function () {
  requestAnimationFrame( animate );

  cube.material.wireframe = datGUIObj.cubeWireframe;
  renderer.render( scene, camera );
};

色の変更

const datGUIObj = {
  cubeColor: {
    red: 0,
    green: 1,
    blue: 0
  }
};

// dat.GUiを使用して、まとまりを作成したい場合、「gui.addFolder」を使用する
const colorGUI = gui.addFolder('Cube Color');
colorGUI.add(datGUIObj.cubeColor, 'red', 0, 1).name('Red').step(0.01)
colorGUI.add(datGUIObj.cubeColor, 'green', 0, 1).name('Green').step(0.01)
colorGUI.add(datGUIObj.cubeColor, 'blue', 0, 1).name('Blue').step(0.01)
colorGUI.open() // デフォルトで開いておきたい場合

const animate = function () {
  requestAnimationFrame( animate );

  cube.material.color.r = datGUIObj.cubeColor.red;
  cube.material.color.g = datGUIObj.cubeColor.green;
  cube.material.color.b = datGUIObj.cubeColor.blue;
  renderer.render( scene, camera );
};

three.jsで色の変更を行いたい場合、 cube.material.color.rなどで色の情報を取得することができる。 f:id:jackswim3411:20201223180521p:plain

背景色追加・変更

// ここで背景の初期値の設定を行う(設定を行わないと色のオブジェクトを取得することができない)
scene.background = new THREE.Color( 0x000000 );

const datGUIObj = {
  backColor: {
    red: 0,
    green: 0,
    blue: 0
  }
};

const backGUI = gui.addFolder('Back Color');
backGUI.add(datGUIObj.backColor, 'red', 0, 1).name('Red').step(0.01)
backGUI.add(datGUIObj.backColor, 'green', 0, 1).name('Green').step(0.01)
backGUI.add(datGUIObj.backColor, 'blue', 0, 1).name('Blue').step(0.01)

const animate = function () {
  requestAnimationFrame( animate );

  const backGUI = gui.addFolder('Back Color');
  backGUI.add(datGUIObj.backColor, 'red', 0, 1).name('Red').step(0.01)
  backGUI.add(datGUIObj.backColor, 'green', 0, 1).name('Green').step(0.01)
  backGUI.add(datGUIObj.backColor, 'blue', 0, 1).name('Blue').step(0.01)
  renderer.render( scene, camera );
};

詰まった場所

アニメーションフレームワーク内でないとdat.GUI上で変更を行なっても反映されない

three.jsの場合、requestAnimationFrameでループする関数の中に入れないと反応しません。

  • NG例
let changeValue // ここの値をdatGUIで変えたい場合
const Obj = {
  hoge: 'fuga'
}

gui.add(Obj, 'hoge');

changeValue = Obj.hoge
  • OK例
let changeValue // ここの値をdatGUIで変えたい場合
const Obj = {
  hoge: 'fuga'
}

gui.add(Obj, 'hoge'); // gui.addは右上に表示を行うもののため、animationフレームワークの外に出す。

const animate = function () {
  requestAnimationFrame( animate );

  changeValue = Obj.hoge
};

参考リンク

threejs.org

github.com

techblog.kayac.com