Babylon.js中文文档基础—第一章—起步

5,050 阅读5分钟

现在让我们一起开始我们的学习。第一步将向您介绍使用Babylon.js创建场景,编写简单模型并将其导出的基础知识。不仅可以使用Babylon.js创建模型,还可以将在其他软件中创建的一系列模型类型导入Babylon.js。我们将展示如何将模型导入场景,并在场景中展示模型。我们将逐步建立一个简单的世界。在旅程的最后,我们将创建一个完善的小村庄场景,展示Babylon.js的功能。

是否想立即试用Babylon.js?每个页面上的示例还通过我们的交互式Playground呈现,您可以在其中编写,查看和尝试代码。可以在Playground上正确地运行的代码,并可以复制粘贴到HTML模板中,用作您的第一个3D Web应用程序。

目录

  • 场景和物体
  • 网页上的第一个模型
  • 导入一个模型和场景
  • 第一个3D Web应用

场景和物体

无论您是要创建整个世界,还是只是将一个模型放到网页中,您都需要一个场景(Scene)来包含该世界或模型,一台用于查看该世界或模型的摄像头(Camera),一个照明它的照明灯(Light),以及至少一个可视对象作为一个对象。所有模型,无论是一个简单的盒子还是复杂的人物角色,都是由三角形或四边形的网格(Mesh)组成的。网格(Mesh)是物体的基本组成单位。

显示网格三角形的线框视图

您可以使用代码直接在Babylon.js中创建大量网格,也可以从其他软件创建的网格中将其作为模型导入。让我们从一个制作一个盒子开始。

所有使用Babylon.js引擎的项目都需要一个带有摄像头(Camera)和灯光(Light)的场景。然后,我们再创建我们的盒子。

const scene = new BABYLON.Scene(engine);
const camera = new BABYLON.ArcRotateCamera("camera", -Math.PI / 2, Math.PI / 2.5, 3, new BABYLON.Vector3(0, 0, 0), scene);
camera.attachControl(canvas, true);
const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);
const box = BABYLON.MeshBuilder.CreateBox("box", {}, scene);

像使用MeshBuilder创建的大多数网格物体一样,创建该线框物体时会将其中心定位在原点,并且需要三个参数。这些是“name","options"和”场景(Scene)“。通过将选项保留为没有属性的空对象{},这个现况物体的宽度,高度和深度默认为单位大小。

为了在Playground上可用,我们需要将它们放在一个名为createScene的函数中,该函数必须返回一个scene。

const createScene =  () => {    
    const scene = new BABYLON.Scene(engine);
    const camera = new BABYLON.ArcRotateCamera("camera", -Math.PI / 2, Math.PI / 2.5, 3, new BABYLON.Vector3(0, 0, 0));
    camera.attachControl(canvas, true);
    const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0));
    const box = BABYLON.MeshBuilder.CreateBox("box", {});
    return scene;
}

第一个场景演示

创建线框物体(Mesh)后,我们可以通过选择“Inspector”,可以保存或导出场景

然后是选择工具,然后选择要导出的类型,.babylon格式或GLB格式。

网页上的第一个模型

如果文件类型是Babylon.js可以识别的文件类型,那么您可以使用< Babylon >元素使用Babylon.js Viewer在网页上显示场景或模型。支持的文件类型包括.babylon,.gltf和glb,建议使用.glb。

使用查看器之前,您需要在< script >元素中将其代码添加到HTML页面中

<script src="https://cdn.babylonjs.com/viewer/babylon.viewer.js"></script>

< bablon >可以自适应容器,将其model属性指向文件路径。

<babylon model="Path to File"></babylon>

Babylon viewer示例

导入一个模型和场景

实际上,将模型放入场景中时,就是将其加载到浏览器中。如您所知,当您将任何内容加载到网站中时,它都是异步的。在对模型执行任何操作之前,您需要知道它们已加载。您可以使用做到这一点ImportMeshAsync的方法SceneLoader,它的形式

BABYLON.SceneLoader.ImportMeshAsync(model name, folder path, file name, scene);

scene参数是可选的,并且默认为当前场景。第一个参数可以是三种类型,具体取决于您是要加载所有模型,还是仅加载一个模型或一系列模型。

BABYLON.SceneLoader.ImportMeshAsync("", "/relative path/", "myFile"); 
//为空表示加载所有模型
BABYLON.SceneLoader.ImportMeshAsync("model1", "/relative path/", "myFile"); 
//加载一个模型
BABYLON.SceneLoader.ImportMeshAsync(["model1", "model2"], "/relative path/", "myFile"); 
//使用数组加载多个模型

以上所有内容仅会加载模型,您将无法以任何方式对其进行操作。您已经设置了Promise对象,但是在实现Promise并提供结果之后,没有采取任何措施。在下面的两个游乐场中,是仅导入命名模型的示例演示。

一次导入一个模型

一次导入多个模型

为了对加载的模型进行操作,我们在Promise之后使用then方法,result是含有模型的所有属性,result.meshes包含所有加载的模型。我们可以使用此数组或其名称来操纵每个网格模型。

BABYLON.SceneLoader.ImportMeshAsync("", "/relative path/", "myFile").then((result) => {
    result.meshes[1].position.x = 20;
    const myMesh_1 = scene.getMeshByName("myMesh_1");
    myMesh1.rotation.y = Math.PI / 2;
});

该示例将导入的模型改变了位置并进行旋转。

加载后操作模型

提醒

不同类型的模型导入的数据的数据结构也不同

  1. 某些软件会使用rotationQuaternion集保存所有网格,除非您先添加该属性,否则无法使用rotation方法

    myMesh.rotationQuaternion = null; //Any version of Babylon.js myMesh.rotation = BABYLON.Vector3(); //babylon.js versions > 4.00

2.以下两种类型是从完全相同的场景导出的,并导入到Babylon.js中。

.babylon 导入的数据结构。

detached_house
ground
semi_house

.glb 导入的数据结构。

_root_ 
   detached_house
           detached_house primitive0
           detached_house primitive1    
   ground    
   semi_house
           semi_house primitive0        
           semi_house primitive1

第一个3D Web应用

导入一个模型示例

<!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://cdn.babylonjs.com/babylon.js"></script>
        <script src="https://cdn.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>
        const canvas = document.getElementById("renderCanvas"); // 获取canvas对象
        const engine = new BABYLON.Engine(canvas, true); // 创建BABYLON 3D 引擎
        // Add your code here matching the playground format
        const createScene = function () {
            const scene = new BABYLON.Scene(engine);  
            BABYLON.SceneLoader.ImportMeshAsync("", "https://assets.babylonjs.com/meshes/", "box.babylon");
            const camera = new BABYLON.ArcRotateCamera("camera", -Math.PI / 2, Math.PI / 2.5, 15, new BABYLON.Vector3(0, 0, 0));
            camera.attachControl(canvas, true);
            const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(1, 1, 0));
            return scene;
        };
        const scene = createScene(); //调用createScene方法
        // 轮询渲染
        engine.runRenderLoop(function () {
                scene.render();
        });
        // 监听浏览器resize事件
        window.addEventListener("resize", function () {
                engine.resize();
        });
    </script>
   </body>
</html>

使用代码创建一个模型示例

<!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://cdn.babylonjs.com/babylon.js"></script>
        <script src="https://cdn.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>
        const canvas = document.getElementById("renderCanvas"); // Get the canvas element        const engine = new BABYLON.Engine(canvas, true); // Generate the BABYLON 3D engine
        // Add your code here matching the playground format
        const createScene = function () {
            const scene = new BABYLON.Scene(engine);  
            BABYLON.MeshBuilder.CreateBox("box", {})
            const camera = new BABYLON.ArcRotateCamera("camera", -Math.PI / 2, Math.PI / 2.5, 15, new BABYLON.Vector3(0, 0, 0));
            camera.attachControl(canvas, true);
            const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(1, 1, 0));
            return scene;
        };
        const 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>