こんな感じでサッカーボールを表示してみました。
はじめに
ARIの土井です。前回【Babylon.js】Playgroundで遊んでみようという記事を書きました。今回はReactを使って実際にWebページに3Dモデルを表示してみたいと思います。
※ Reactの実行環境は、Web上で利用できる統合開発環境のCodeSandboxを使用しました。
準備
まず、https://codesandbox.io/s/ にアクセスしてSatrt from a template
からReact
をクリックします。
以下のようにReactのテンプレートから生成されたサンプルページが表示されます。
Dependencies
から@babylonjs/core
パッケージをインストールしておきます。
手順
ここからReactのテンプレートで生成されたディレクトリを以下のような構成にしていきます。
public/
└ index.html
src/
├ assets/
│ └ soccerBall.babylon
├ components/
│ └ SceneComponent.js
├ App.js
├ index.js
└ styles.css
package.json
SceneComponent.jsの作成
Babylon.jsの公式ドキュメントの通り、SceneComponent.js
を新規で作成します。src
フォルダの配下にcomponents
フォルダを新規作成して、SceneComponent.js
を作成します。
import { useEffect, useRef } from "react";
import { Engine, Scene } from "@babylonjs/core";
export default ({
antialias,
engineOptions,
adaptToDeviceRatio,
sceneOptions,
onRender,
onSceneReady,
...rest
}) => {
const reactCanvas = useRef(null);
// set up basic engine and scene
useEffect(() => {
const { current: canvas } = reactCanvas;
if (!canvas) return;
const engine = new Engine(
canvas,
antialias,
engineOptions,
adaptToDeviceRatio
);
const scene = new Scene(engine, sceneOptions);
if (scene.isReady()) {
onSceneReady(scene);
} else {
scene.onReadyObservable.addOnce((scene) => onSceneReady(scene));
}
engine.runRenderLoop(() => {
if (typeof onRender === "function") onRender(scene);
scene.render();
});
const resize = () => {
scene.getEngine().resize();
};
if (window) {
window.addEventListener("resize", resize);
}
return () => {
scene.getEngine().dispose();
if (window) {
window.removeEventListener("resize", resize);
}
};
}, [
antialias,
engineOptions,
adaptToDeviceRatio,
sceneOptions,
onRender,
onSceneReady
]);
return <canvas ref={reactCanvas} {...rest} />;
};
.babylonファイルの作成
前回の記事で作成した.glb
ファイルを、.babylon
ファイルに変換します。
CodeSandboxに匿名投稿する際はファイルのアップロードができません。そのため今回はバイナリファイルである.glb
を、.babylon
というJSON形式に変換し、JSONの文字列をコピペでCodeSandBoxに反映するという方法をとりました。
.glb
形式のファイル.babylon
に変換するには、Babylon.jsが提供してくれているBabylon.js Sandboxを使用します。
まず、Babylon.js Sandboxにアクセスして、.glb
ファイルをアップロードします。
次に、サッカーボールのノード名をプログラムからアクセスしやすくするために変更しておきます。Properties
> Name
で SoccerBall
と入力します。
Tools
> SCENE EXPORT
> Export to Babylon
をクリックすると、scene.babylon
という名前でダウンロードできます。
ダウンロードしたファイル内のJSON文字列をsrc/assets/SoccerBall.babylon
にコピペで貼り付けます。
App.jsの修正
Reactのテンプレートから生成されたApp.js
を以下に置き換えます。
import * as BABYLON from "@babylonjs/core";
import SceneComponent from "./components/SceneComponent";
import SoccerBallAsset from "./assets/SoccerBall.babylon";
import "./styles.css";
const onSceneReady = (scene) => {
// カメラの作成, 回転
const camera = new BABYLON.ArcRotateCamera("camera", -2.5, 2, 1.5, new BABYLON.Vector3(0, 0, 0), scene);
camera.useAutoRotationBehavior = true;
camera.autoRotationBehavior.idleRotationSpeed *= 5;
camera.attachControl(SceneComponent, true);
// ライトの作成
const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);
light.intensity = 1.0;
// SoccerBall.babylonからノードの読み込み
const assetsManager = new BABYLON.AssetsManager(scene);
assetsManager.addMeshTask("task", "SoccerBall", SoccerBallAsset); //scene.babylonのノード名SoccerBallを追加
assetsManager.load();
};
export default function App() {
return (
<SceneComponent antialias onSceneReady={onSceneReady} id="my-canvas" />
);
}
SceneComponent
のプロパティとして渡すonSceneReady
関数を作成します。この関数内でカメラやライト、3Dモデルなどを定義していきます。基本的にimport * as BABYLON from "@babylonjs/core";
とすれば、あとはPlaygroundのcreateScene
関数の内容を記載していけば良いのですが以下の点に注意してください。
- Playgroundで定義している
var scene = new BABYLON.Scene(engine);
は、SceneComponent.js
側で定義しているので不要 - Playgroundで参照している
canvas
要素は、SceneComponent
に置き換える- 上記のコードでいうと、
camera.attachControl(SceneComponent, true);
の部分になります。
- 上記のコードでいうと、
まとめ
今回はReactを使ってBabylon.jsの3Dモデルを表示してみました。これからもBabylon.js関連の記事を書いていこうと思います。