Babylon 学习 -- 项目初始化
资源
工具、库
- 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 并添加加载插件