返回 导航

Vue.js

hangge.com

Vue.js - 集成Babylon.js构建三维可视化场景教程2(加载GLTF模型)

作者:hangge | 2026-06-11 09:40
    前文我演示了如何在 Vue 项目中集成 Babylon.js,并创建了一个包含立方体、球体、圆柱体、地面和光照的基础 3D 场景(点击查看)。在实际工程和数字孪生场景中,我们通常不只是渲染简单的几何体,而是需要加载真实的三维模型(GLTF / GLB 格式)。本文我将接着演示如何在 Vue 中加载 GLTF 模型。

二、加载 GLTF 模型

1,模型准备

我们将需要加载的 GLTF 模型文件放置项目的 public/models/glb 目录下。

2,样例代码

下面代码我使用 Babylon.js 加载这个 glb 格式的变压器模型。
<template>
    <div class="babylon-container">
        <div ref="canvasContainer" class="canvas-container">
            <canvas ref="renderCanvas" class="render-canvas"></canvas>
        </div>

        <!-- 加载状态 -->
        <div v-if="loading" class="loading-overlay">
            <div class="loader">加载中...</div>
        </div>

        <!-- 场景信息 -->
        <div class="scene-info">
            <p>物体数量: {{ objectCount }}</p>
            <p>FPS: {{ fps.toFixed(1) }}</p>
        </div>
    </div>
</template>

<script>
import * as BABYLON from 'babylonjs';
// 注册3D模型加载器
import 'babylonjs-loaders'

export default {
    name: "BabylonScene",
    data() {
        return {
            engine: null,
            scene: null,
            loading: true,
            error: null,
            objectCount: 0,
            fps: 60,
        };
    },
    mounted() {
        this.initBabylon();
    },
    beforeDestroy() {
        // 销毁组件时释放内存,防止内存泄漏
        if (this.engine) {
            this.engine.dispose();
        }
        window.removeEventListener("resize", this.onWindowResize);
    },
    methods: {
        initBabylon() {
            const canvas = this.$refs.renderCanvas;

            // 1. 初始化渲染引擎
            this.engine = new BABYLON.Engine(canvas, true,
                { preserveDrawingBuffer: true, stencil: true });

            // 2. 创建场景
            this.scene = this.createScene(this.engine, canvas);

            // 3. 隐藏加载遮罩
            //this.loading = false;

            // 4. 注册渲染循环
            this.engine.runRenderLoop(() => {
                this.scene.render();
                this.fps = this.engine.getFps();
            });

            // 5. 监听窗口调整大小
            window.addEventListener("resize", this.onWindowResize);

            // 6. 初始化场景统计
            this.updateSceneInfo();
        },

        createScene(engine, canvas) {
            const scene = new BABYLON.Scene(engine);

            // 设置背景颜色
            scene.clearColor = BABYLON.Color3.FromHexString('#aaaaaa').toColor4();

            // 添加摄像头 (ArcRotateCamera 允许用户绕着中心点旋转)
            const camera = new BABYLON.ArcRotateCamera(
                'camera',
                -Math.PI / 2,
                Math.PI / 3,
                7,
                BABYLON.Vector3.Zero(),
                scene
            );
            camera.attachControl(canvas, true);

            // 设置相机控制
            camera.wheelPrecision = 50;
            camera.lowerRadiusLimit = 2;
            camera.upperRadiusLimit = 50;

            // 添加灯光
            const light1 = new BABYLON.HemisphericLight(
                'light1',
                new BABYLON.Vector3(1, 1, 0),
                scene
            );

            const light2 = new BABYLON.DirectionalLight(
                'light2',
                new BABYLON.Vector3(0, -1, 1),
                scene
            );
            light2.position = new BABYLON.Vector3(5, 10, 5)
            light2.intensity = 0.3

            // 添加地面
            const ground = BABYLON.MeshBuilder.CreateGround(
                'ground',
                { width: 15, height: 15 },
                scene
            );
            const groundMaterial = new BABYLON.StandardMaterial('groundMaterial', scene);
            groundMaterial.diffuseColor = new BABYLON.Color3(0.8, 0.8, 0.8);
            ground.material = groundMaterial;

            // 加载 GLTF / GLB 模型
            BABYLON.SceneLoader.ImportMesh(
                null,               // null = 加载全部 mesh
                '/models/glb/',         // 模型目录
                'transformer.glb',         // 文件名
                scene,
                (meshes, particleSystems, skeletons, animationGroups) => {
                    // Babylon 会自动创建一个 __root__ TransformNode
                    const root = meshes[0]
                    // 1设置模型位置(世界坐标)
                    root.position = new BABYLON.Vector3(0, 1, 0)
                    // 2设置模型旋转(弧度制)
                    //root.rotation = new BABYLON.Vector3(0, Math.PI / 2, 0)
                    // 3设置模型缩放
                    root.scaling = new BABYLON.Vector3(1, 1, 1)

                    // 相机自动对准模型
                    camera.zoomOn(scene.meshes)

                    // 更新统计
                    this.$nextTick(() => {
                        this.objectCount = scene.meshes.length
                        this.loading = false
                    })
                }
            )

            return scene;
        },

        // 更新场景信息
        updateSceneInfo() {
            if (this.scene) {
                this.objectCount = this.scene.meshes.length;
            }
        },

        // 窗口大小变化处理
        onWindowResize() {
            if (this.engine) {
                this.engine.resize();
            }
        },
    },
};
</script>

<style scoped>
.babylon-container {
    position: relative;
    width: 100%;
    height: 100%;
}

.canvas-container {
    width: 100%;
    height: 100%;
    overflow: hidden;
}

.render-canvas {
    width: 100%;
    height: 100%;
    display: block;
    outline: none;
}

.loading-overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.7);
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 1000;
}

.loader {
    color: white;
    font-size: 18px;
}

.scene-info {
    position: absolute;
    bottom: 20px;
    left: 20px;
    background: rgba(0, 0, 0, 0.6);
    color: white;
    padding: 10px 15px;
    border-radius: 5px;
    font-size: 14px;
}

.scene-info p {
    margin: 5px 0;
}
</style>

3,运行测试

(1)页面加载后除了会显示地面外,还会加载显示一个变压器 GLTF 模型。

(2)按住鼠标左键拖动可以将视图绕模型旋转,使用滚轮可以缩放视图,按住右键拖动则可平移视角。
评论

全部评论(0)

回到顶部