Babylon 学习 -- 项目初始化

资源

官方文档
官方文档(react)

工具、库

  • vite : 脚手架
  • @babylonjs/core : babylon 基础库
  • babylonjs-loaders : babylon 模型加载库

code

  • init

yarn create vite

cd <project_name>

yarn add @babylonjs/core babylonjs-loaders

  • 创建场景(Scene)组件

import { Engine, EngineOptions, Scene, SceneOptions ,SceneLoader} from "@babylonjs/core";
import { GLTFFileLoader } from 'babylonjs-loaders'
import { useEffect, useRef } from "react";

type SceneComponentPropsType = {
    className?: string
    
    antialias?: boolean
    engineOptions?: EngineOptions
    adaptToDeviceRatio?: boolean
    sceneOptions?: SceneOptions
    onRender?: (scene: Scene) => void
    onSceneReady:(scene: Scene) => void
}

export default (props: SceneComponentPropsType) => {
    const reactCanvas = useRef(null);
    const { antialias, engineOptions, adaptToDeviceRatio, sceneOptions, onRender, onSceneReady, ...rest } = props;
    
    // 很重要, 否则加载外部模型会报错,其他格式如 obj 等也需要注册plugin
    SceneLoader.RegisterPlugin(new GLTFFileLoader());
    useEffect(() => {
        if (reactCanvas.current) {
            const engine = new Engine(reactCanvas.current, 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);
                }
            };
        }
    }, [reactCanvas]);

    return <canvas ref={reactCanvas} {...rest} />;
};

  • 创建镜头、灯光、模型

import React from "react";
import { FreeCamera, Vector3, HemisphericLight, MeshBuilder } from "@babylonjs/core";
import SceneComponent from "./SceneComponent"; // uses above component in same directory
// import SceneComponent from 'babylonjs-hook'; // if you install 'babylonjs-hook' NPM.
import "./App.css";

let box;

const onSceneReady = (scene) => {
  // 创建镜头
  var camera = new FreeCamera("camera1", new Vector3(0, 5, -10), scene);

  // 镜头接受输入端控制
  const canvas = scene.getEngine().getRenderingCanvas();
  camera.attachControl(canvas, true);

  // 创建灯光
  var light = new HemisphericLight("light", new Vector3(0, 1, 0), scene);

  // 创建 box 模型
  box = MeshBuilder.CreateBox("box", { size: 2 }, scene);
};

/**
 * 定义渲染使box沿y轴旋转
 */
const onRender = (scene) => {
  if (box !== undefined) {
    var deltaTimeInMillis = scene.getEngine().getDeltaTime();

    const rpm = 10;
    box.rotation.y += (rpm / 60) * Math.PI * 2 * (deltaTimeInMillis / 1000);
  }
};

export default () => (
  <div>
    <SceneComponent antialias onSceneReady={onSceneReady} onRender={onRender} id="my-canvas" />
  </div>
);


虽然官方例子中没有提到模型加载,如果直接使用 SceneLoader 加载模型会报错,所以上文中提到 引入 babylonjs-loaders 并添加加载插件

posted @ 2021-11-23 13:38  辣椒鱼儿酱  阅读(411)  评论(0编辑  收藏  举报