Vue中使用Three.js加载3D模型,实现真实交互3D场景

本文介绍如何在 Vue 组件中使用 Three.js,包括 npm 安装 Three.js 库、Three.js 加载 gltf 模型、添加光源、添加拖拽缩放控制器、添加地平线网格、模型居中等步骤,最后提供完整的 Vue 组件示例,让你可以实现一个真实交互的 3D 场景。

在本文中,我们介绍了如何在 Vue 组件中使用 Three.js,通过 GLTFLoader 模块加载 glTF 格式的 3D 模型,并添加控制器、光源、地平线网格等功能,使得 3D 场景更加真实、交互性更强。在 Vue 组件中创建一个点光源、使用 OrbitControls 模块实现拖拽缩放控制器、使用 GridHelper 模块创建地平线网格,以及将模型居中。通过本文的教程,你可以轻松地创建一个真实交互的 3D 场景。

Three 简介

Three.js 是一款基于 WebGL 的 JavaScript 3D 库,提供了一系列易于使用的 API,使开发者可以快速构建高性能、交互性强的 3D 场景。它是目前最受欢迎的 WebGL 框架之一。

npm 安装 Three

在 Vue 项目中使用 Three.js,需要先安装 Three.js 库。可以通过 npm 进行安装:

npm install three

Three 加载 gltf 模型

glTF(GL Transmission Format)是一种与 Three.js 兼容的 3D 文件格式。Three.js 提供了 GLTFLoader 模块,用于加载 glTF 格式的 3D 模型。

在 Vue 组件中引入 GLTFLoader 模块,并使用它加载 glTF 模型:

import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";

const loader = new GLTFLoader();
loader.load("model.gltf", gltf => {
  scene.add(gltf.scene);
});

image-20230317121142105

没有材质的模型乌漆嘛黑!

添加光源

为了让模型看起来更加真实,我们需要添加光源。Three.js 提供了多种类型的光源,包括环境光、点光源、聚光灯等。

在 Vue 组件中创建一个点光源并添加到场景中:

import { PointLight } from "three";

const light = new PointLight(0xffffbb, 1);
light.position.set(10, 10, 10);
scene.add(light);

image-20230317121302401

添加拖拽缩放控制器

为了方便用户操作模型,我们可以添加拖拽缩放控制器。Three.js 提供了 OrbitControls 模块,用于实现这个功能。

在 Vue 组件中引入 OrbitControls 模块,并创建一个 OrbitControls 实例:

import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";

const controls = new OrbitControls(camera, renderer.domElement);

添加地平线网格

为了更好地展示模型的位置和方向,我们可以添加地平线网格。Three.js 提供了 GridHelper 模块,用于创建网格辅助线。

在 Vue 组件中创建一个地平线网格并添加到场景中:

import { GridHelper } from "three";

const gridHelper = new GridHelper(10, 10);
scene.add(gridHelper);

image-20230317121347061

模型居中

有些情况下,加载的模型可能不是居中的。我们可以通过计算模型的边界框来将其居中。

在 Vue 组件中加载模型后,计算模型的边界框并将其居中:

loader.load("model.gltf", gltf => {
  const bbox = new THREE.Box3().setFromObject(gltf.scene);
  const center = bbox.getCenter(new THREE.Vector3());
  gltf.scene.position.sub(center); // 将模型的中心点移动到场景的中心点
  scene.add(gltf.scene);
});

完整例子

下面是一个完整的Vue组件示例,展示了如何使用Three.js加载glTF模型并添加控制器、光源、地平线网格等功能。

<template>
  <div ref="container"></div>
</template>

<script>
import * as THREE from "three";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";

export default {
  mounted() {
    const container = this.$refs.container;

    // 创建Three.js场景、相机、渲染器
    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);
    const renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(600, 600);
    container.appendChild(renderer.domElement);
    renderer.setClearColor(0x444444, 1.0);
    // 加载GLTF模型
    const loader = new GLTFLoader();
    loader.load(
      "model.gltf",
      gltf => {
        // 将模型放到中间
        const box = new THREE.Box3().setFromObject(gltf.scene);
        const size = box.getSize(new THREE.Vector3()).length();
        const center = box.getCenter(new THREE.Vector3());
        gltf.scene.position.x -= center.x;
        gltf.scene.position.y -= center.y;
        gltf.scene.position.z -= center.z;
        camera.near = size / 100;
        camera.far = size * 100;
        camera.updateProjectionMatrix();
        camera.position.copy(center);
        camera.position.x += size / 2;
        camera.position.y += size / 2;
        camera.position.z += size / 2;
        camera.lookAt(center);
        scene.add(gltf.scene);

        //添加在模型的右上角高三倍设置一个光源 太阳
        const light = new THREE.DirectionalLight(0xffffbb, 1);
        // 模型宽度
        const width = box.max.x - box.min.x;
        // 模型高度
        const height = box.max.y - box.min.y;
        // 模型深度
        const depth = box.max.z - box.min.z;
        light.position.set(width * 3, height * 3, depth * 3);
        scene.add(light);

        //多设置几个光源
        const light3 = new THREE.DirectionalLight(0xffffbb, 1);
        light3.position.set(-width * 3, -height * 3, depth * 3);
        scene.add(light3);

        const light4 = new THREE.DirectionalLight(0xffffbb, 1);
        light4.position.set(width * 3, height * 3, -depth * 3);
        scene.add(light4);
      },
      undefined,
      error => {
        console.error(error);
      }
    );

    // 设置相机位置
    camera.position.z = 5;

    // 添加OrbitControls控制器
    const controls = new OrbitControls(camera, renderer.domElement);
    controls.enableDamping = true;
    controls.dampingFactor = 0.05;
    controls.screenSpacePanning = false;
    controls.minDistance = 1;
    controls.maxDistance = 1000;

    //设置一个地平线网格
    const gridHelper = new THREE.GridHelper(100, 100);
    scene.add(gridHelper);

    // 动画循环
    const animate = function () {
      requestAnimationFrame(animate);
      // 更新OrbitControls控制器状态
      controls.update();
      renderer.render(scene, camera);
    };
    animate();
  },
};
</script>

image-20230317121524101

© 版权声明
THE END
喜欢就支持一下吧
点赞10 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容