はりうすブログ (のすけのメモ)

湘南にある小さな会社 代表 ”のすけ”のブログです

babylon.js ステップ6 カメラ

babylon.jsにはよく使われる2つのカメラがあります。

一つは1人称視点のユニバーサルカメラ(the Universal Camera)、

もう一つはアークカメラ(Arc Rotate Camera)です。


まずカメラのコントロールを可能にしましょう

camera.attachControl(canvas, true);

ユニバーサルカメラ Universal Camera

ユニバーサルカメラはキーボード、タッチ、ゲームパッドに対応したカメラです。

これはFreeCamera,Touch Camera, Gamepad Cameraの上位互換です。

ユニバーサルカメラを使うとFPSっぽい一人称視点を得られます。

それぞれの入力方法のデフォルト設定は次の通り

  1. キーボード・・・上下左右キー
  1. マウス・・・視点を回転
  1. タッチ操作・・・上下左右にスワイプ
  1. ゲームパッド・・・デバイス次第

コード

// Parameters : name, position, scene
    var camera = new BABYLON.UniversalCamera("UniversalCamera", new BABYLON.Vector3(0, 0, -10), scene);

// Targets the camera to a particular position. In this case the scene origin
    camera.setTarget(BABYLON.Vector3.Zero());

// Attach the camera to the canvas
    camera.attachControl(canvas, true);

操作例はこちら:
https://www.babylonjs-playground.com/#SRZRWV

アーク回転カメラ(Arc Rotate Camera)

このカメラは常に所定のターゲット位置を指し、ターゲットを回転の中心としてそのターゲットを中心に回転できます
カーソルとマウス、またはタッチイベントで制御できます。

このカメラは、その目標位置を周回するカメラ、またはより想像力で地球を周回するスパイ衛星と考えてください。ターゲット(地球)に対するその位置は、アルファ(ラジアン)縦回転、ベータ(ラジアン)緯度回転、および ターゲット位置からの距離の半径の3つのパラメーターで設定できます。

f:id:hollywis:20200620014150j:plain

コード

// Parameters: alpha, beta, radius, target position, scene
    var camera = new BABYLON.ArcRotateCamera("Camera", 0, 0, 10, new BABYLON.Vector3(0, 0, 0), scene);

// Positions the camera overwriting alpha, beta, radius
    camera.setPosition(new BABYLON.Vector3(0, 0, 20));

// This attaches the camera to the canvas
    camera.attachControl(canvas, true);

操作例:
https://www.babylonjs-playground.com/#SRZRWV#1

フォローカメラ(FollowCamera)

実際に触ってもらった方が早いため例を見てください。

ターゲットとなるメッシュを追随するように設定出来ます

操作例:
https://www.babylonjs-playground.com/#SRZRWV#6

コード

// Parameters: name, position, scene
var camera = new BABYLON.FollowCamera("FollowCam", new BABYLON.Vector3(0, 10, -10), scene);

// The goal distance of camera from target
camera.radius = 30;

// The goal height of camera above local origin (centre) of target
camera.heightOffset = 10;

// The goal rotation of camera around local origin (centre) of target in x y plane
camera.rotationOffset = 0;

// Acceleration of camera in moving from current to goal position
camera.cameraAcceleration = 0.005

// The speed at which acceleration is halted
camera.maxCameraSpeed = 10

// This attaches the camera to the canvas
camera.attachControl(canvas, true);

// NOTE:: SET CAMERA TARGET AFTER THE TARGET'S CREATION AND NOTE CHANGE FROM BABYLONJS V 2.5
// targetMesh created here.
camera.target = targetMesh;   // version 2.4 and earlier
camera.lockedTarget = targetMesh; //version 2.5 onwards

その他のカメラ

バイス回転カメラ(Device Orientation Camera)
・・・デバイスの方向を取得して反映する

例はこちら
https://www.babylonjs-playground.com/#SRZRWV#3



バーチャルジョイスティックカメラ(Virtual Joysticks Camera)

画面上にジョイスティックを表示する

例はこちら
www.youtube.com




WebVR Free Camera

Use the WebVR Camera - Babylon.js Documentation


飛行カメラ(FlyCamera)

WSADキーで動きます

// Parameters: name, position, scene
var camera = new BABYLON.FlyCamera("FlyCamera", new BABYLON.Vector3(0, 5, -10), scene);

// Airplane like rotation, with faster roll correction and banked-turns.
// Default is 100. A higher number means slower correction.
camera.rollCorrect = 10;
// Default is false.
camera.bankedTurn = true;
// Defaults to 90° in radians in how far banking will roll the camera.
camera.bankedTurnLimit = Math.PI / 2;
// How much of the Yawing (turning) will affect the Rolling (banked-turn.)
// Less than 1 will reduce the Rolling, and more than 1 will increase it.
camera.bankedTurnMultiplier = 1;

// This attaches the camera to the canvas
camera.attachControl(canvas, true);

まとめ

様々なコントロール可能なカメラがbabylon.jsにはあり

ユニバーサルカメラとアーク回転カメラが2大カメラです。

さらに、拡張としてバーチャルジョイスティックを画面上に表示させるなど、十分な操作方法が提供されています

次回はライトの設定です

babylon.js ステップ5 マテリアル

マテリアルを使用すると、メッシュを色とテクスチャで覆うことができます。

なお、メッシュを表示するには光が必要です。

拡散マテリアル(Diffuse)と鏡面マテリアル(Specular)では、光源を作成する必要があります。

いきましょう!

f:id:hollywis:20200619152808p:plain

まずは、StandardMaterialでいきます。

var myMaterial = new BABYLON.StandardMaterial("myMaterial", scene);

myMaterial.diffuseColor = new BABYLON.Color3(1, 0, 1);
myMaterial.specularColor = new BABYLON.Color3(0.5, 0.6, 0.87);
myMaterial.emissiveColor = new BABYLON.Color3(1, 1, 1);
myMaterial.ambientColor = new BABYLON.Color3(0.23, 0.98, 0.53);

mesh.material = myMaterial;


BABYLON.Color3はそれぞれ、赤、緑、青を0~1の間で設定します。0がなし、1が一番強い状態です。

  • diffuseColorは拡散色(光に対して反射する基本の色)
  • specularColorは鏡面反射(ハイライト的な反射)
  • emissiveColorは影の色(そのメッシュ自身がその色で反射する)
  • ambientColor 環境光の反射。シーンのアンビエントカラーが設定されている場合にのみ適用される

そして、定義してマテリアルは、mesh.materialでマテリアルを設定していきます

myMaterial.alpha = 0.5;

aplhaで透明度を変えられる

テクスチャ

メッシュに対して、画像を張れる.

f:id:hollywis:20200619152557p:plain

var myMaterial = new BABYLON.StandardMaterial("myMaterial", scene);

myMaterial.diffuseTexture = new BABYLON.Texture("PATH TO IMAGE", scene);
myMaterial.specularTexture = new BABYLON.Texture("PATH TO IMAGE", scene);
myMaterial.emissiveTexture = new BABYLON.Texture("PATH TO IMAGE", scene);
myMaterial.ambientTexture = new BABYLON.Texture("PATH TO IMAGE", scene);

mesh.material = myMaterial;

ワイヤーフレーム

マテリアルに対して、ワイヤーフレーム表示

f:id:hollywis:20200619153209p:plain

myMaterial.wireframe = true;

まとめ

メッシュに対して、設定できるマテリアルについて紹介しました。

色マテリアルの場合は、まず光Lightをシーンに設定した上で

それぞれ、拡散光、鏡面反射、自身の発光、環境光を設定出来ました。

また、画像テクスチャを貼ることも出来ます。

そして、ワイヤフレーム表示もマテリアルで行いました。

次はカメラです。

hollywis.hatenablog.com

babylon.js ステップ4 位置、回転、スケーリング

babylon.js やってみようシリーズのステップ4

位置、回転、スケーリングのお話です

位置の話

babylon.jsには2つの座標系があります

  • ワールド座標系
  • ローカル座標系

ワールド座標系

ワールド座標系の原点は変わりません。

通常、メッシュが作成されると、その中心はワールド軸の原点に配置されます。

移動しても、ワールド座標系はそのワールドの中心(原点)を元に判断されます

ローカル座標系

ローカル軸はメッシュの場所によって動きます。

でもローカル軸の原点は、ワールド座標における位置に関係なく、常にメッシュの作成された中心にあります。

初期状態

ワールド座標とローカル座標は一致しますが

メッシュが動くとズレることになります。

f:id:hollywis:20200619144019j:plain

配置

mesh(メッシュ)に対して positionで位置を設定出来ます

mesh.position = new BABYLON.Vector3(2, 3, 4);

例えばワールド軸にしたがって、2,3,4の位置に配置します

この意味は

obj.position.x  =  2;
obj.position.y  =  3;
obj.position.z  =  4;

です。

f:id:hollywis:20200619144327j:plain

赤がX軸、緑の線がY軸、青がZ軸

回転

meshに対して rotationで回転させることが出来ます

mesh.rotation = new BABYLON.Vector3(alpha, beta, gamma);

回転もVector3型でメッシュに設定します。

alpha、beta、およびgammaはラジアンで設定します。

mesh.rotation.x  =  alpha; //rotation around x axis
mesh.rotation.y  =  beta;  //rotation around y axis
mesh.rotation.z  =  gamma; //rotation around z axis

これも同じ意味になります。


また、addRotationを使ってmesh(メッシュ)を連鎖的に回転させることも出来ます

mesh.addRotation(Math.PI/2, 0, 0).addRotation(0, Math.PI/2, 0).addRotation(0, 0, Math.PI/2);

スケーリング

meshに対して scalingで大きさを設定出来ます

mesh.scaling = new BABYLON.Vector3(scale_x, scale_y, scale_z);

または、個別に

mesh.scaling.y = 5;

とか出来ます。

y軸に対してスケーリングした物を、z軸を中心に回転させたらこんな感じです。

f:id:hollywis:20200619145855j:plain

まとめ

メッシュに対して、position, rotation, scalingを設定することで

それぞれ、位置、回転、大きさを制御できることがわかりました

次回はマテリアルです

hollywis.hatenablog.com

babylon.js ステップ3 線Lineを使ったいろいろな形状を表示

いろいろな形状シリーズです。

いきましょう!

	//Array of points to construct lines
	var myPoints = [
		new BABYLON.Vector3(0, 0, 0),
		new BABYLON.Vector3(0, 1, 1),
		new BABYLON.Vector3(0, 1, 0)
	];
	
	//Create lines 
	var lines = BABYLON.MeshBuilder.CreateLines("lines", {points: myPoints}, scene); 

BABYLON.Vector3型で繋いでいきます

f:id:hollywis:20200619142450p:plain


Babylon.js Playground

螺旋

f:id:hollywis:20200619142758p:plain

 //Array of points to construct a spiral with lines
 var myPoints = [];

    var deltaTheta = 0.1;
    var deltaY = 0.005;

    var radius = 1;
    var theta = 0;
    var Y = 0;
    for (var i = 0; i<400; i++) {
        myPoints.push(new BABYLON.Vector3(radius * Math.cos(theta), Y, radius * Math.sin(theta)));
        theta += deltaTheta;
        Y += deltaY
    }
	
 //Create lines 
 var lines = BABYLON.MeshBuilder.CreateLines("lines", {points: myPoints}, scene); 

線400個を螺旋状に繋いでグルグルな物も作れます

まとめ

線です。

簡単です。螺旋を描くには座標計算にオイラー角が必要なので、その辺りは難しいですが

線自体は簡単ですね。

hollywis.hatenablog.com

babylon.js ステップ2 いろいろなプリミティブを表示

早速いきます

BABYLON.MeshBuilderを使っていろいろ作っていきます

Three.jsならジオメトリを作って、マテリアルを設定してメッシュを作るのですが、babylonは一行です。

球体

f:id:hollywis:20200619140955p:plain

  // Add and manipulate meshes in the scene
    var sphere = BABYLON.MeshBuilder.CreateSphere("sphere", {diameterX: 1, diameterY: 0.75, diameterZ: 0.25}, scene);

diameterとは直径のことです。x,y,x好きなサイズに出来ます

Babylon.js Playground

f:id:hollywis:20200619141013p:plain

    // Add and manipulate meshes in the scene
    var box = BABYLON.MeshBuilder.CreateBox("box", {height: 1, width: 0.75, depth: 0.25}, scene);

height高さ, width横幅, depth奥行きを設定出来ます

https://www.babylonjs-playground.com/#K6M44R

Plane平面

f:id:hollywis:20200619141024p:plain

       // Add and manipulate meshes in the scene
    var plane = BABYLON.MeshBuilder.CreatePlane("plane", {height:2, width: 1}, scene);

箱の奥行きないバージョンですね


www.babylonjs-playground.com

地面Ground

Three.jsには無いプリミティブ

f:id:hollywis:20200619141230p:plain

    // Add and manipulate meshes in the scene
    var ground = BABYLON.MeshBuilder.CreateGround("ground", {height: 1.5, width: 2.5, subdivisions: 4}, scene);

subdivisionsとはsquare(正方形)の数です。これは4個ですね

Babylon.js Playground

まとめ

プリミティブには球体、箱、平面、そして地面がありました。

どれも1行でシーンに追加出来て、Three.jsよりシンプルです。

Three.jsには無かった、地面Groundが気になる所です

次回は、その他の数学的な形状です

hollywis.hatenablog.com

Three.jsに物理法則を導入できるPhysijs を入れてみたいけど、、

前回の記事で、Three.jsはゲームに使えない的なことを言ってしまったのですが。。


実は、物理法則を簡単にいれる方法があったっぽい。

それが、外部ライブラリPhysijsだ!!


特徴はこうだ!

  • オブジェクトが重力の影響を受け、お互いに衝突するようになる
  • シーン内の物体の摩擦係数と反発係数を触れる!
  • Physijs がサポートしているさまざまな形状がある
  • 単純な形状を組み合わせた合成形状もある
  • ハイトフィールドを使用した複雑な形状もできる
  • オブジェクトの動きの制限する点制約、ヒンジ制約、スライダー制約、コーンツイスト制

約、自由度制約

  • 左右の音量がカメラの位置に基づいて決定される音源

何と盛り沢山な!!



いこう

と思ったらいろいろメンテされてないらしい

qiita.com

ふむふむ。3年くらいメンテされてないとな、、、

Three.jsは結構頻繁にバージョンアップするので、これは厳しいのかなぁ


f:id:hollywis:20200619133908p:plain

比較的に新しいのはOimo.js(お芋ドットジェイエス)。お芋かぁ...


とりあえず、次回!

babylon.jsで3D表現の初めの一歩

f:id:hollywis:20200619121440p:plain

こんにちは

どうしても3Dでゲームっぽい物をWeb上で作りたくて、ここ数ヶ月Three.jsを勉強していたのですが、、

どうやらゲームを作るにはbabylon.jsの方が良さそうです。

なぜ、Three.jsではダメなのか?

それは純粋な3D表現ツールだからです。

  • キャラクターが簡単には歩いたりはしない
  • 地面もただの平面オブジェクト
  • 重力は自前でプログラミング

などなど。


何ていうか・・・・全て自作が前提なのです。

Unityであるように、重力を付与するモジュールとか無いです。

誰かが作ってるかもしれないけれど、公式では無いです。

これがとても辛いです。(あったら御免なさい。教えていただきたいです)



ぽぽん!とゲーム作りたい!


じゃあUnityやりなさいよ!!


という話なのですが、どうやらWeb上では動作が遅いらしく家庭用ゲーム機とかPCやスマホにインストールする形式じゃ無いと辛いらしいです(未検証)


あとは、JSで動かしたいんだ!!既存のWebサービスにシームレスに組み込みたいんだ!という話です。


そこで検討したのが、babylon.js(バビロンジェイエス)名前が、人類の愚かさの象徴であるバベルの塔を作り出したバビロンということで、全然いけてないのがとても気になるのですが。。。

f:id:hollywis:20200619113925j:plain
バベルの塔

果たして、これは目的の物なのか、、


頑張って検証していきます。


www.babylonjs.com


f:id:hollywis:20200619114011p:plain

執筆時点の最新版は4.1です。

Microsoftのエンジニアが作った物らしく、フリーで使えますし、定期的にアップデートもされており、良さげです。

Microsoftと言えばマインクラフト!!

きっとマインクラフトみたいな物も、簡単に作れるんじゃないかと予想していますw

f:id:hollywis:20200619114348j:plain


ただ、babylon.jsにも、一つも問題が。。。。


それは、、、


babylonには日本語のドキュメントが一切ない!! 書籍もない!!


ということです。

Three.jsには素晴らしい書籍がありました。


初めてのThree.js 第2版 ―WebGLのためのJavaScript 3Dライブラリ

初めてのThree.js 第2版 ―WebGLのためのJavaScript 3Dライブラリ

  • 作者:Jos Dirksen
  • 発売日: 2016/07/23
  • メディア: 単行本(ソフトカバー)


ですが、babylon.jsにはありません。

なので、このブログで説明しつつ、頑張って使っていきたいと思います。




それでは使っていきましょう。

なお、Three.jsがある程度使える方を前提に買いていきます!

もし、分からない場合は、コチラのThree.jsの書籍を買って、基本的なWebにおける3D表現のお作法を学んだ方がいいかもしれません。

初めてのThree.js 第2版 ―WebGLのためのJavaScript 3Dライブラリ

初めてのThree.js 第2版 ―WebGLのためのJavaScript 3Dライブラリ

  • 作者:Jos Dirksen
  • 発売日: 2016/07/23
  • メディア: 単行本(ソフトカバー)

まず球体を置いてみる

コード全容

まずは、コード全容です

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">

    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <title>Babylon Template</title>

        <style>
            html, body {
                overflow: hidden;
                width: 100%;
                height: 100%;
                margin: 0;
                padding: 0;
            }

            #renderCanvas {
                width: 100%;
                height: 100%;
                touch-action: none;
            }
        </style>

        <script src="https://preview.babylonjs.com/babylon.js"></script>
        <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
        <script src="https://code.jquery.com/pep/0.4.3/pep.js"></script>
    </head>

   <body>

    <canvas id="renderCanvas" touch-action="none"></canvas> <!-- touch-action="none" for best results from PEP -->

    <script>
        var canvas = document.getElementById("renderCanvas"); // Get the canvas element
        var engine = new BABYLON.Engine(canvas, true); // Generate the BABYLON 3D engine

        /******* Add the create scene function ******/
        var createScene = function () {

            // Create the scene space
            var scene = new BABYLON.Scene(engine);

            // Add a camera to the scene and attach it to the canvas
            var camera = new BABYLON.ArcRotateCamera("Camera", Math.PI / 2, Math.PI / 2, 2, new BABYLON.Vector3(0,0,5), scene);
            camera.attachControl(canvas, true);

            // Add lights to the scene
            var light1 = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(1, 1, 0), scene);
            var light2 = new BABYLON.PointLight("light2", new BABYLON.Vector3(0, 1, -1), scene);

            // Add and manipulate meshes in the scene
            var sphere = BABYLON.MeshBuilder.CreateSphere("sphere", {diameter:2}, scene);

            return scene;
        };
        /******* End of the create scene function ******/

        var scene = createScene(); //Call the createScene function

        // Register a render loop to repeatedly render the scene
        engine.runRenderLoop(function () {
                scene.render();
        });

        // Watch for browser/canvas resize events
        window.addEventListener("resize", function () {
                engine.resize();
        });
    </script>

   </body>

</html>

解説

まず、この部分

<canvas id="renderCanvas" touch-action="none"></canvas>

これはcanvasタグをidを付けて置いているだけです。


<style>
            html, body {
                overflow: hidden;
                width: 100%;
                height: 100%;
                margin: 0;
                padding: 0;
            }

            #renderCanvas {
                width: 100%;
                height: 100%;
                touch-action: none;
            }
        </style>

スタイルシートで全画面表示しています。

<script src="https://preview.babylonjs.com/babylon.js"></script>
        <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
        <script src="https://code.jquery.com/pep/0.4.3/pep.js"></script>

babylon.jsと、babylonjs.loaders.min.jsの本体とローダの読み込み。

そして、スマホでタップを取り扱いたい場合はpep.jsも読み込んであげます。

        var canvas = document.getElementById("renderCanvas"); // Get the canvas element
        var engine = new BABYLON.Engine(canvas, true); // Generate the BABYLON 3D engine

キャンバス要素をID指定で取得して、それをバビロン3Dエンジンに紐付けます!

この3Dエンジンにいろいろ、要素を追加していくことになります。


/******* Add the create scene function ******/
        var createScene = function () {

            // Create the scene space
            var scene = new BABYLON.Scene(engine);

            // Add a camera to the scene and attach it to the canvas
            var camera = new BABYLON.ArcRotateCamera("Camera", Math.PI / 2, Math.PI / 2, 2, new BABYLON.Vector3(0,0,5), scene);
            camera.attachControl(canvas, true);

            // Add lights to the scene
            var light1 = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(1, 1, 0), scene);
            var light2 = new BABYLON.PointLight("light2", new BABYLON.Vector3(0, 1, -1), scene);

            // Add and manipulate meshes in the scene
            var sphere = BABYLON.MeshBuilder.CreateSphere("sphere", {diameter:2}, scene);

            return scene;
        };
        /******* End of the create scene function ******/

        var scene = createScene(); //Call the createScene function

3D表現では、シーンという概念を扱います。

一つの画面表現をシーンとして扱うのですね。

で、

var scene = new BABYLON.Scene(engine);

でシーンを新しく作ります。もちろんバビロン3Dエンジンを使います。

// Add a camera to the scene and attach it to the canvas
            var camera = new BABYLON.ArcRotateCamera("Camera", Math.PI / 2, Math.PI / 2, 2, new BABYLON.Vector3(0,0,5), scene);
            camera.attachControl(canvas, true);

次に、カメラの追加です。

今回は、「ArcRotateCamera」です。球形に回転するカメラですね。

場所はVector3型でz軸に5個進んだところに配置です。(手前に5歩って感じでしょうか)

そのほかにも、いろいろカメラがあるっぽいですが。それは別の記事で

// Add lights to the scene
            var light1 = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(1, 1, 0), scene);
            var light2 = new BABYLON.PointLight("light2", new BABYLON.Vector3(0, 1, -1), scene);

ライトの追加です。2個追加してますね。

一つは、「HemisphericLight」ヘミソフィックライト(環境光)ですね。
場所はVector3型でx軸(左)に1, y軸(上)に1, z軸に0の場所に配置です。

もう一つは「PointLight」スポットライトみたいなやつでしょうか。
場所はVector3型で上奥に設置してますね。

// Add and manipulate meshes in the scene
            var sphere = BABYLON.MeshBuilder.CreateSphere("sphere", {diameter:2}, scene);

球体(sphere)のプリミティブの配置です。

 var scene = createScene(); //Call the createScene function

でこの関数を実行していると。

        // Register a render loop to repeatedly render the scene
        engine.runRenderLoop(function () {
                scene.render();
        });

で、このエンジンを使ってレンダリングするわけですが

それをループさせてシーンの描画を繰り返します。

そうすることでアニメーションとか、カメラの位置変更が常に反映されるようになります。

        // Watch for browser/canvas resize events
        window.addEventListener("resize", function () {
                engine.resize();
        });

おまけで、ウィンドウサイズのリサイズ対応ですね。

Three.jsなら自前で各所をbabylonならengine.resize();で一撃です。便利

整理

  1. まずライブラリを読み込む
  2. HTMLにcanvasを作っておく
  3. 3Dエンジンを起動!
  4. canvasと3Dエンジンを紐付け
  5. シーン作成!!
  6. シーンには「カメラ」と「ライト」と「物体」をVector3型で設置!!
  7. ループ処理を設置
  8. リサイズ対応も書いとく

この順番を覚えておきましょう!

Three.jsよりちょっとだけシンプルかな。

感想

いけそう!

Three.jsを学んだあとなら、babylon.jsは簡単そうな気がする

どんどんブログにあげていこうと思います



追記:Three.jsでもPointerLockカメラというのがあって

それを使えばマイクラフト的な視点のカメラはできるっぽい。

https://threejs.org/examples/#misc_controls_pointerlock


あとは、Physijsというライブラリを使うと物理演算を導入することができるっぽい!!

この辺りも検証したい

hollywis.hatenablog.com