🙄
Babylon.jsをはじめよう
概要
AEC and Related Tech Advent Calendar 2021の3日目の内容です。
babylon.jsをはじめてさわってみたという記事です。Web系の3Dといえば、three.jsが有名ですが、Unityなどゲームエンジンに慣れた人におすすめなbabylon.jsについてハンズオンします。babylon.jsには、playgroundがあり、中身をみることができますが、ステップバイステップのチュートリアルが用意されていないため、断片的にプログラムがみれますが、特徴がわかりにくくなっています。今回は、その特徴や利点がわかるように説明ができれば思います。
環境
- vs codeなどお好きなテクストエディタ
- babylon.d.tsのダウンロード
https://raw.githubusercontent.com/BabylonJS/Babylon.js/master/dist/preview release/babylon.d.ts
Three.jsとBabylon.js
Three.jsのサイトでは、ステップバイステップで学ぶオフィシャルリソースが多くあったり、ビデオチュートリアルも豊富で学習リソースは豊富にあるため、学習コストが低いです。
ただし、WebGLに知識が乏しい人にとっては、設定が冗長で簡単にパッとつくるには下ごしらえのコードを多めに書かなければなりません。理解できていれば問題にないのかもしれませんが、WebGLの知識が乏しいと書き忘れや、処理の難しさを感じます。
// create a geometry
const geometry = new THREE.BoxBufferGeometry( 2, 2, 2 );
// create a default (white) Basic material
const material = new THREE.MeshBasicMaterial();
// create a Mesh containing the geometry and material
const mesh = new THREE.Mesh( geometry, material );
// add the mesh to the scene
scene.add( mesh );
// create the renderer
const renderer = new THREE.WebGLRenderer();
renderer.setSize( container.clientWidth, container.clientHeight ); renderer.setPixelRatio( window.devicePixelRatio );
// add the automatically created <canvas> element to the page container.appendChild( renderer.domElement );
// render, or 'create a still image', of the scene
renderer.render( scene, camera );
同じシリンダーを作った時の書き方の違い
var geometry = new THREE.CylinderGeometry( 5, 5, 20, 32 );
var material = new THREE.MeshBasicMaterial( {color: 0xffff00} );
var cylinder = new THREE.Mesh( geometry, material );
scene.add( cylinder );
var cone = BABYLON.MeshBuilder.CreateCylinder("cone", {diameterTop: 0, tessellation: 4}, scene);
実際に書いてみよう!
Html設定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BabylonJS Demo</title>
<script src="https://cdn.babylonjs.com/babylon.js"></script>
<style>
#canvas{
width:100%;
height:100%;
}
</style>
</head>
<body>
<canvas id ="canvas"></canvas>
<script src="js/main.js" type="module"></script>
</body>
</html>
main.jsを書く
キャンバスを設定
// get a canvas
const canvas = document.getElementById("canvas");
// create BabylonJs engine
const engine = new BABYLON.Engine(canvas, true);
Sceneの作り方
/Create Scene Function
function createScene(){
// create scene
const scene = new BABYLON.Scene(engine);
// color
scene.clearColor - new BABYLON.Color3.White();
return scene;
}
カメラの設定
// create camera
const camera = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(0,0,-10),scene);
camera.attachControl(canvas,true);
// create light
const ligth = new BABYLON.HemisphericLight('light', new BABYLON.Vector3(0,1,0),scene);
ジオメトリ
const box = BABYLON.MeshBuilder.CreateBox("box", {size: 1}, scene);
box.rotation.z = 3;
box.rotation.x = 3;
// rotate
box.rotation.y = BABYLON.Tools.ToRadians(45);
// create mesh
const ground = BABYLON.MeshBuilder.CreateGround("ground", {width:10, height:10},scene);
// create sphere
const sphere = BABYLON.MeshBuilder.CreateSphere("sphere", {diameter: 1 ,segments:32}, scene);
sphere.position = new BABYLON.Vector3(3,0,0);
sphere.scaling = new BABYLON.Vector3(1,2,1);
// create plane
const plane = BABYLON.MeshBuilder.CreatePlane("plane", {size: 1}, scene);
plane.position = new BABYLON.Vector3(-3,0,0);
// create a line
const points = [
new BABYLON.Vector3(2,0,0),
new BABYLON.Vector3(0,1,1),
new BABYLON.Vector3(0,1,0),
];
const lines = BABYLON.MeshBuilder.CreateLines("lines", {points}, scene);
// create sounds
//const sound = new BABYLON.Sound("sound", "url to sound file", scene);
//Leave time for the sound file to load before playing it
//sound.play();
return scene;
material
//create materials
const material1 = new BABYLON.StandardMaterial('material', scene);
material1.diffuseColor = new BABYLON.Color3(1,0,0);
material1.emissiveColor = new BABYLON.Color3(0.5,0.5,0);
box.material = material1;
const material2 = new BABYLON.StandardMaterial('material2', scene);
material2.diffuseColor = new BABYLON.Color3(1,0,1);
sphere.material = material2;
const material3 = new BABYLON.StandardMaterial('material3', scene);
material3.diffuseTexture = new BABYLON.Texture('assets/image.png')
plane.material = material3;
アニメーション
const animationBox = new BABYLON.Animation("wheelAnimation", "rotation.y", 30, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);
const wheelKeys = [];
//At the animation key 0, the value of rotation.y is 0
wheelKeys.push({
frame: 0,
value: 0
});
//At the animation key 30, (after 1 sec since animation fps = 30) the value of rotation.y is 2PI for a complete rotation
wheelKeys.push({
frame: 30,
value: 2 * Math.PI
});
//Link this animation to a wheel
box.animations = [];
box.animations.push(animationBox);
//set the keys
animationBox.setKeys(wheelKeys);
scene.beginAnimation(box, 0, 30, true);
パノラマビュー
パノラマビューを表示するのも、PhotoDomeを使えば、簡単に実装できます。こういう手軽さが良さなのかなと感じています。
var createScene = function () {
var scene = new BABYLON.Scene(engine);
var camera = new BABYLON.ArcRotateCamera("Camera", -Math.PI / 2, Math.PI / 2, 5, BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas, true);
camera.inputs.attached.mousewheel.detachControl(canvas);
var dome = new BABYLON.PhotoDome(
"testdome",
"./textures/360photo.jpg",
{
resolution: 32,
size: 1000
},
scene
);
return scene;
};
TAECのワークショップの動画
参考
Discussion