Three.jsでdat.guiとOrbitControlsを同時に使う場合はdomElementを第二引数に指定してあげる


このエントリーをはてなブックマークに追加

初めてのThree.js 第2版をやってみてる

Three.jsを使っててなんとなくわかってきたが

細かいところをしっかりと勉強する時にこの本は丁寧に説明が書かれているので良さそう

で、第1章の

  • 1.7 実験をもっと簡単にするためにdat.GUIを利用

のところ、個人的にThree.jsを使用する時は常にOrbitControlsでカメラを動かしていたいので勝手に追加していたのだが

dat.GUIでパラメータを変更していると、どうもカメラも一緒に動いてしまうという挙動が起こってて

少し気持ち悪かったのを解決したのでメモ


new THREE.OrbitControls する時第二引数に renderer.domElement を指定してあげる

下記リンク先を参考にしたらうまくいった(使用しているのが正確にはTrackballControlsですが基本的に一緒だった)

three.js + Web Font + GPGPU Vol.1 (準備編) | Blog | Takumi Hasegawa

OrbitControlsを使用する際は、外部ライブラリとして OrbitControls.js を読み込んだ後

javascript側では例えば var orbitControls = new THREE.OrbitControls(camera) みたいに、カメラオブジェクトを引数で指定すると思うが

このままだとdat.guiのパラメータ変更するためにマウスドラッグアンドドロップするとカメラも動いてしまう

ので、以下の様に第二引数にrenderer.domElementも指定してあげる

var orbitControls = new THREE.OrbitControls(camera, renderer.domElement);

これだけ、でちゃんと下のようにdat.gui操作時はdat.guiのパラメータだけが動くようになってくれる

公式exampleのspotlightソースコードを見ても、第二引数にちゃんと

renderer.domElementが指定されている(var controls = new THREE.OrbitControls( camera, renderer.domElement );のとこ)


というわけで、初めてのThree.jsのsampleコード 05-control-gui.html

に、<script type="text/javascript" src="../libs/OrbitControls.js"></script>を追加して(書籍の 9.2.4 THREE.OrbitControlを参照)

下記ソースコードにすればひとまず動きます(js部分のみ抜粋、14行目あたりのorbitControlsを追加しただけ)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
function init() {
var stats = initStats();
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
///////// sampleコード通りに第二引数に1.0を指定したらなぜか背景が黄色になってしまったので無くした
renderer.setClearColor(new THREE.Color(0xEEEEEE));
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMapEnabled = true;
// OrbitControls, 第二引数にrenderer.domElementを指定しないとdat.GUI操作時にcameraも動いてしまう
var orbitControls = new THREE.OrbitControls(camera, renderer.domElement);
var planeGeometry = new THREE.PlaneGeometry(60, 20, 1, 1);
var planeMaterial = new THREE.MeshLambertMaterial({color: 0xffffff});
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.receiveShadow = true;
// rotate and position the plane
plane.rotation.x = -0.5 * Math.PI;
plane.position.x = 15;
plane.position.y = 0;
plane.position.z = 0;
// add the plane to the scene
scene.add(plane);
// create a cube
var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
var cubeMaterial = new THREE.MeshLambertMaterial({color: 0xff0000});
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.castShadow = true;
// position the cube
cube.position.x = -4;
cube.position.y = 3;
cube.position.z = 0;
// add the cube to the scene
scene.add(cube);
var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
var sphereMaterial = new THREE.MeshLambertMaterial({color: 0x7777ff});
var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
// position the sphere
sphere.position.x = 20;
sphere.position.y = 0;
sphere.position.z = 2;
sphere.castShadow = true;
// add the sphere to the scene
scene.add(sphere);
// position and point the camera to the center of the scene
camera.position.x = -30;
camera.position.y = 40;
camera.position.z = 30;
camera.lookAt(scene.position);
// add subtle ambient lighting
var ambientLight = new THREE.AmbientLight(0x0c0c0c);
scene.add(ambientLight);
// add spotlight for the shadows
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-40, 60, -10);
spotLight.castShadow = true;
scene.add(spotLight);
// add the output of the renderer to the html element
document.getElementById("WebGL-output").appendChild(renderer.domElement);
// call the render function
var step = 0;
var controls = new function () {
this.rotationSpeed = 0.02;
this.bouncingSpeed = 0.03;
};
var gui = new dat.GUI();
gui.add(controls, 'rotationSpeed', 0, 0.5);
gui.add(controls, 'bouncingSpeed', 0, 0.5);
render();
function render() {
stats.update();
// rotate the cube around its axes
cube.rotation.x += controls.rotationSpeed;
cube.rotation.y += controls.rotationSpeed;
cube.rotation.z += controls.rotationSpeed;
// bounce the sphere up and down
step += controls.bouncingSpeed;
sphere.position.x = 20 + ( 10 * (Math.cos(step)));
sphere.position.y = 2 + ( 10 * Math.abs(Math.sin(step)));
// render using requestAnimationFrame
requestAnimationFrame(render);
renderer.render(scene, camera);
}
function initStats() {
var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms
// Align top-left
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.getElementById("Stats-output").appendChild(stats.domElement);
return stats;
}
}
window.onload = init;


renderer.setClearColorの第二引数が 1.0 なせいで背景が黄色になってしまう

おまけだが、大元のソースコード

renderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0));の部分、第二引数に 1.0 を指定しているが

なぜかこのままブラウザで確認すると背景が黄色になってしまうので

1.0を消して renderer.setClearColor(new THREE.Color(0xEEEEEE));のようにしてあげた(先程記載したコードもそうした)

これでちゃんと背景が白に近い灰色になるはず


ひとまず、なんでそうなるかなかなかまだ理解できてないけどこれで解決した


このエントリーをはてなブックマークに追加