Three.js day 5 となりました。
昨日 は、星空を作りました。
本日は、カメラを動かします。
#1. 完成版
See the Pen universe by hiroya iizuka (@hiroyaiizuka) on CodePen.
#2. 参考文献
ICS MEDIA
初めてのThree.js
CodeGrid
#3. 分解してみる
❶.
前回までのコードです。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/102/three.min.js"></script>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
</head>
<body>
<canvas class="stage"></canvas>
<script>
function init() {
//レンダラーを作成
const renderer = new THREE.WebGLRenderer({
canvas: document.querySelector(".stage")
});
renderer.setSize(window.innerWidth, window.innerHeight);
//シーンを作成
const scene = new THREE.Scene();
starNight();
function starNight() {
// 形状データを作成
const geometry = new THREE.Geometry();
for (let i = 0; i < 1000; i++) {
const star = new THREE.Vector3();
star.x = THREE.Math.randFloatSpread(3000);
star.y = THREE.Math.randFloatSpread(3000);
star.z = THREE.Math.randFloatSpread(3000);
geometry.vertices.push(star);
}
// マテリアルを作成
const material = new THREE.PointsMaterial({
size: 10,
color: 0xffffff
});
// 星を作成
const star = new THREE.Points(geometry, material);
scene.add(star);
}
//カメラを作成
const camera = new THREE.PerspectiveCamera(
50,
window.innerWidth / window.innerHeight,
0.1,
2000
);
camera.position.set(0, 0, 1000);
camera.lookAt(new THREE.Vector3(0, 0, 0));
//球を作成
const geometry = new THREE.SphereGeometry(100, 32, 32);
const material = new THREE.MeshNormalMaterial();
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
renderScene();
//アニメーション
function renderScene() {
mesh.rotation.x += 2;
requestAnimationFrame(renderScene);
renderer.render(scene, camera);
}
}
window.addEventListener("load", init);
</script>
</body>
</html>
この中心の球を注視しながら、カメラが回転するようにしましょう。
数学の復習をしよう!
カメラの動きを理解するためには、数学の知識が必要です。
テンション下がりますね・・・。
三角関数 を学び直しましょう。
半径がr の円における、円周上の点の座標は
X: r cosθ Y: r sinθ
で計算されました。
しかし、three.js では、θではなく、radian
を使います。
radian ってなんだったでしょうか・・・?汗
###radian とは?
radian とは、円の半径に等しい長さの弧の中心に対する角度 のことです。
例えば、半径が2cm の円があります。
弧の長さもちょうど2cm の時に、半径と、半径で作られる角度のことを、1 radian と言います。
弧の長さと、半径の比がradian と考えるとわかりやすいですね。
弧が長くなって、4cm になると 中心角は 2radian になります。
したがって、 4π cm (円周)になると、中心角は、2π radian になります。
つまり、下の式が成り立ちます。
360 度 = 2π (radian)
180 度 = π (radian)
1 度 = π/180 (radian)
__扇型の中心角を、長さを使って表現できる__のが、radian の特徴というわけですね。
半径がr の弧の場合は
孤の長さ = 2 × π × θ/360
となりますが、
なぜ、こんな面倒な radian を使うのか?
と興味を持たれましたかたは、こちら をご参照ください。
数学って難しいですね・・・
###カメラの位置をradian で表そう!
本題に戻ります。
円周上の座標は
X: r cosθ Y: r sinθ
で表されましたが、これらを、radian に変換すると
(角度 = rot)
X: r cos(rot × π/180)
Y: r sin(rot × π/180)
となります。
πは、Math.PI
で表されるため、Three.js では、以下に変わります。
X: r * Math.cos(rot * Math.PI/180)
Y: r * Math.sin(rot * Math.PI/180)
これで、camera.position.x = ~ と、camera の座標を表せば良いです。
rot(角度) については、アニメーションの設定の中で、徐々に増えていくように設定しましょう。
let rot = 0;
function renderScene() {
rot += 0.5;
const radian = (rot * Math.PI) / 180;
camera.position.x = 1000 * Math.sin(radian);
camera.position.z = 1000 * Math.cos(radian);
camera.lookAt(new THREE.Vector3(0, 0, 0));
requestAnimationFrame(renderScene);
renderer.render(scene, camera);
}
#4. 最終コード
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/102/three.min.js"></script>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
</head>
<body>
<canvas class="stage"></canvas>
<script>
function init() {
let rot = 0;
//レンダラーを作成
const renderer = new THREE.WebGLRenderer({
canvas: document.querySelector(".stage")
});
renderer.setSize(window.innerWidth, window.innerHeight);
//シーンを作成
const scene = new THREE.Scene();
starNight();
function starNight() {
// 形状データを作成
const geometry = new THREE.Geometry();
for (let i = 0; i < 1000; i++) {
const star = new THREE.Vector3();
star.x = THREE.Math.randFloatSpread(3000);
star.y = THREE.Math.randFloatSpread(3000);
star.z = THREE.Math.randFloatSpread(3000);
geometry.vertices.push(star);
}
// マテリアルを作成
const material = new THREE.PointsMaterial({
size: 10,
color: 0xffffff
});
// 物体を作成
const star = new THREE.Points(geometry, material);
scene.add(star);
}
//カメラを作成
const camera = new THREE.PerspectiveCamera(
50,
window.innerWidth / window.innerHeight,
0.1,
2000
);
//球を作成
const geometry = new THREE.SphereGeometry(100, 32, 32);
const material = new THREE.MeshNormalMaterial();
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
renderScene();
//アニメーション
function renderScene() {
//radian の設定
rot += 0.5;
const radian = (rot * Math.PI) / 180;
//カメラのpositioning
camera.position.x = 1000 * Math.sin(radian);
camera.position.z = 1000 * Math.cos(radian);
camera.lookAt(new THREE.Vector3(0, 0, 0));
requestAnimationFrame(renderScene);
renderer.render(scene, camera);
}
}
window.addEventListener("load", init);
</script>
</body>
</html>
See the Pen universe by hiroya iizuka (@hiroyaiizuka) on CodePen.
できました。
綺麗な眺めです。
次回は、インタラクション操作を取り込んでいきます。
それでは、また明日〜