🙄

Babylon.jsをはじめよう

2021/12/15に公開

概要

AEC and Related Tech Advent Calendar 2021の3日目の内容です。
https://adventar.org/calendars/6392

babylon.jsをはじめてさわってみたという記事です。Web系の3Dといえば、three.jsが有名ですが、Unityなどゲームエンジンに慣れた人におすすめなbabylon.jsについてハンズオンします。babylon.jsには、playgroundがあり、中身をみることができますが、ステップバイステップのチュートリアルが用意されていないため、断片的にプログラムがみれますが、特徴がわかりにくくなっています。今回は、その特徴や利点がわかるように説明ができれば思います。

環境

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のワークショップの動画

https://youtu.be/N91O2xGRjDE

参考

https://adventar.org/calendars/6392

Babylon.js Playground

Babylon.js Playground

Discussion