2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

LiveView on Babylon.js でチュートリアルの2章やってみた その1

Posted at

はじめに

この記事はElixirアドベントカレンダー2025のシリーズ2、11日目の記事です

今回はBabylon.jsのチュートリアルの2章をLiveView+Babylon.jsでやっていく記事になります

10日目の続きから進めていきます

下準備

下準備としてLiveViewとHooksの雛形を作っておきます

Homeにリンクを追加

lib/babylon_web/live/home_live.ex
defmodule BabylonWeb.HomeLive do
  use BabylonWeb, :live_view

  def render(assigns) do
    ~H"""
    <Layouts.app flash={@flash}>
      <div class="flex flex-col w-1/2 gap-4">
        <.button navigate={~p"/ch101"}>Chapter1-01</.button>
        <.button navigate={~p"/ch103"}>Chapter1-03</.button>
+       <.button navigate={~p"/ch201"}>Chapter2</.button>
      </div>
    </Layouts.app>
    """
  end
end

2章のLiveViewをルーティングに追加

lib/babylon_web/router.ex
  scope "/", BabylonWeb do
    pipe_through :browser

    live "/", HomeLive
    live "/ch101", Ch101Live
    live "/ch103", Ch103Live
+   live "/ch201", Ch201Live
  end

描画するLiveViewを作成

lib/babylon_web/live/ch201_live.ex
defmodule BabylonWeb.Ch201Live do
  use BabylonWeb, :live_view

  def render(assigns) do
    ~H"""
    <div class="p-4">
      <.header>
        Chapter 2-01
        <:actions><.button navigate={~p"/"}>Back</.button></:actions>
      </.header>
    </div>
    <canvas class="w-screen h-[88vh]" id="renderCanvas" phx-hook="BabylonHook201" phx-update="ignore">
    </canvas>
    """
  end

  def mount(_params, _session, socket) do
    {:ok, socket}
  end
end

hooks

カメラとライトは毎回使うのでutil化

assets/js/util.js
const createAttachment = ({ scene, canvas }) => {
  const camera = new BABYLON.ArcRotateCamera(
    "camera",
    -Math.PI / 2,
    Math.PI / 2.5,
    15,
    new BABYLON.Vector3(0, 0, 0),
    scene
  );
  camera.attachControl(canvas, true);
  new BABYLON.HemisphericLight("light", new BABYLON.Vector3(1, 1, 0), scene);
};

export { createAttachment };
assets/js/BabylonHook201.js
import { createAttachment } from "./util";
const BabylonHook201 = {
  mounted() {
    const canvas = document.getElementById("renderCanvas");
    const engine = new BABYLON.Engine(canvas, true);
    const scene = new BABYLON.Scene(engine);
    createAttachment(scene,canvas)

    engine.runRenderLoop(() => {
      scene.render();
    });

  }
}

export default BabylonHook201
assets/js/hooks.js
import BabylonHook101 from "./BabylonHook101";
import BabylonHook103 from "./BabylonHook103";
+ import BabylonHook201 from "./BabylonHook201";

const Hooks = {
  BabylonHook101: BabylonHook101,
  BabylonHook103: BabylonHook103,
+ BabylonHook201: BabylonHook201,
};

export default Hooks;

chapter 2-01 地面 (Grounding the World)

地面と箱を追加します

箱が [0, 0, 0]で表示すると貫通するので [0, 0.5, 0]にします

assets/js/BabylonHook201.js
const BabylonHook201 = {
  mounted() {
    const canvas = document.getElementById("renderCanvas");
    const engine = new BABYLON.Engine(canvas, true);
    const scene = new BABYLON.Scene(engine);
    createAttachment(scene, canvas);

+   const box = BABYLON.MeshBuilder.CreateBox("box", {});
+   box.position.y = 0.5;
+   const ground = BABYLON.MeshBuilder.CreateGround("ground", {
+     width: 10,
+     height: 10,
+    });

    engine.runRenderLoop(() => {
      scene.render();
    });
  },
};

スクリーンショット 2025-12-06 17.32.01.png

2-02はスキップします

chapter 2-03: メッシュを設置 (Place and Scale a Mesh)

box1は初期値で大きさを設定
box2はscalingで個別に大きさを設定、位置をVectorでまとめて設定
box3はscalingをVectorでまとめて設定し、位置は個別に設定しています

assets/js/BabylonHook203.js
import { createAttachment } from "./util";

const BabylonHook203 = {
  mounted() {
    const canvas = document.getElementById("renderCanvas");
    const engine = new BABYLON.Engine(canvas, true);
    const scene = new BABYLON.Scene(engine);
    createAttachment(scene, canvas);

    const ground = BABYLON.MeshBuilder.CreateGround("ground", {
      width: 10,
      height: 10,
    });

    const box1 = BABYLON.MeshBuilder.CreateBox("box1", {
      width: 2,
      height: 1.5,
      depth: 3,
    });
    box1.position.y = 0.75;

    const box2 = BABYLON.MeshBuilder.CreateBox("box2", {});
    box2.scaling.x = 2;
    box2.scaling.y = 1.5;
    box2.scaling.z = 3;
    box2.position = new BABYLON.Vector3(-3, 0.75, 0);

    const box3 = BABYLON.MeshBuilder.CreateBox("box3", {});
    box3.scaling = new BABYLON.Vector3(2, 1.5, 3);
    box3.position.x = 3;
    box3.position.y = 0.75;
    box3.position.z = 0;

    engine.runRenderLoop(() => {
      scene.render();
    });
  },
};

export default BabylonHook203;

スクリーンショット 2025-12-06 19.01.46.png

ch2-01に以下を追加して回転を試します

   box.position.y = 0.5;
   box.rotation.y = Math.PI / 4;

スクリーンショット 2025-12-06 19.08.19.png

2-04: 基本的な家 (A Basic House)

シリンダーメッシュをtessellation: 3で作成して
z軸に回転させて、屋根っぽく載せます

assets/js/BabylonHook201.js
import { createAttachment } from "./util";

const BabylonHook201 = {
  mounted() {
    const canvas = document.getElementById("renderCanvas");
    const engine = new BABYLON.Engine(canvas, true);
    const scene = new BABYLON.Scene(engine);
    createAttachment(scene, canvas);

    const ground = BABYLON.MeshBuilder.CreateGround("ground", {
      width: 10,
      height: 10,
    });

    const box = BABYLON.MeshBuilder.CreateBox("box", {});
    box.position.y = 0.5;

+   const roof = BABYLON.MeshBuilder.CreateCylinder("roof", {
+     diameter: 1.3,
+     height: 1.2,
+     tessellation: 3,
+   });
+   roof.scaling.x = 0.75;
+   roof.rotation.z = Math.PI / 2;
+   roof.position.y = 1.22;

    engine.runRenderLoop(() => {
      scene.render();
    });
  },
};

export default BabylonHook201;

スクリーンショット 2025-12-06 19.11.07.png

最後に

長くなってきたので一旦ここまで続きはその2で

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?