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

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

在本文中,我们介绍了如何在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模型并添加控制器、光源、地平线网格等功能。

```javascript
<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 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容