vue3中使用three.js加载外部模型

文章目录

  • 前言
  • 一、vue3中下载与安装three.js
  • 二、使用步骤
    • 1.准备容器
    • 2.引入
    • 3.基本配置
    • 4.点击事件
  • 三、注意事项
  • 四、总结
  • 五、完整代码
  • 五、实现效果


前言

主要介绍如何在vue3中使用three.js加载 gltf、glb 模型。(学习参考);
使用技术包括vue3,element plus,three.js;


提示:以下是本篇文章正文内容,下面案例可供参考

一、vue3中下载与安装three.js

依次使用npm安装three插件,包括three依赖、轨道插件
代码如下(示例):

npm install three
npm install three-orbit-controls

二、使用步骤

1.准备容器

<div id="my-three"></div>

2.引入

import {ref, onMounted} from 'vue'
import * as THREE from 'three'
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls'
import {GLTFLoader} from 'three/examples/jsm/loaders/GLTFLoader'; //gltf

3.基本配置

  1. 创建场景、相机、光源
const width = window.innerWidth, height = window.innerHeight;
const scene = new THREE.Scene();
const renderer = new THREE.WebGLRenderer()
const loader = new GLTFLoader();
const camera = new THREE.PerspectiveCamera(45, width / height, 1, 1000);
const controls = new OrbitControls(camera, renderer.domElement)

function init() {
 //光源
 const ambient = new THREE.AmbientLight(0xffffff, 0.4);
 scene.add(ambient);
 const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);//光源,color:灯光颜色,intensity:光照强度
 directionalLight.position.set(400, 200, 300);
 scene.add(directionalLight);

//设置相机位置
 camera.position.set(300, 300, 300);
//设置相机方向
 camera.lookAt(0, 0, 0);

//辅助坐标轴
 const axesHelper = new THREE.AxesHelper(200);//参数200标示坐标系大小,可以根据场景大小去设置
 scene.add(axesHelper);
 scene.background = new THREE.Color(0xeaeaea);

 renderer.setPixelRatio(window.devicePixelRatio);
 renderer.antialias = true;
}
  1. 添加模型(引入gltf、glb文件)
function gltfModel1() {
  // glb
  loader.load("../../../../public/工厂.glb",
      function (gltf) {
        scene.add(gltf.scene)
      },
      function (xhr) {
        const percent = Math.floor((xhr.loaded / xhr.total) * 100); // 计算加载进度百分比
        // console.log(`模型加载进度:${percent}%`);
      }
  )

}
  1. 渲染
function renderModel() {
  //渲染
  renderer.setSize(width, height)//设置渲染区尺寸
  renderer.render(scene, camera)//执行渲染操作、指定场景、相机作为参数
// renderer.setClearColor(0x00ff00); // 设置背景颜色为绿色
  renderer.toneMapping = THREE.ACESFilmicToneMapping;
// 设置曝光度
  renderer.toneMappingExposure = 1.5; // 适当调整曝光度

  controls.minPolarAngle = Math.PI / 4; // 最小极角为 45 度
  controls.maxPolarAngle = Math.PI / 2; // 最大极角为 90 度
}

function render() {
  renderer.render(scene, camera);
  controls.update()
  requestAnimationFrame(render);
}
  1. 画布跟随窗口变化
window.onresize = function () {
  renderer.setSize(window.innerWidth, window.innerHeight);
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
};

4.点击事件

// 交互事件
addEventListener('dblclick', onMouseDblclick, false)
function onMouseDblclick(event) {
  let intersects = getIntersects(event);

  if (intersects.length !== 0 && intersects[0].object instanceof THREE.Mesh) {

    const selectedObject = intersects[0].object;
    let selectedObjects = [];
    selectedObjects.push(selectedObject);
    console.log(selectedObjects)

  }
}
//获取与射线相交的对象数组
function getIntersects(event) {
  let rayCaster = new THREE.Raycaster();
  let mouse = new THREE.Vector2();

  //通过鼠标点击位置,计算出raycaster所需点的位置,以屏幕为中心点,范围-1到1
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; //这里为什么是-号,没有就无法点中

  //通过鼠标点击的位置(二维坐标)和当前相机的矩阵计算出射线位置
  rayCaster.setFromCamera(mouse, camera);
  return rayCaster.intersectObjects(scene.children);
}

三、注意事项

  1. 这里的glb、gltf文件可去免费网站下载即可;(找不到私信我发你)
  2. 下载的glb、gltf文件,在vue3中 必须 放在public文件下方,否则可能导致模型不显示,并报错找不到模型信息;
  3. 加载glb、gltf文件后,无报错,并可以打印出模型信息,但看不见模型在哪。可能是模型太小的缘故,考虑添加以下代码到加载模型代码中:
function gltfModel1() {
  // glb
  loader.load("../../../../public/工厂.glb",
      function (gltf) {
                  const model = gltf.scene;
            model.scale.set(10, 9, 9); // 将模型放大两倍
            model.position.set(86, -10, 40); // 将模型位置设置为长方形模型的中心点
            model.rotation.set(0, 0, 0); // 可以根据需要调整模型的旋转
            
        scene.add(model)
        
      },
      function (xhr) {
        const percent = Math.floor((xhr.loaded / xhr.total) * 100); // 计算加载进度百分比
        // console.log(`模型加载进度:${percent}%`);
      }
  )

}
  1. 点击事件是通过全局双击监听,这里只是监听选中的最近的模型;为了之后点击高亮和点击后显示文本信息做准备,不需要删除其代码即可,不影响运行。

四、总结

以上就是今天要讲的内容,本文仅仅简单介绍了three.js的使用和如何加载模型;本人也是初学者小白,如有错误请指出,会及时修改;文章太长,其余部分空闲时间补上。。。
关于gltf、glb文件压缩:关于gltf、glb文件压缩
关于gltf、glb文件模型切换:关于gltf、glb文件模型切换
关于描边、高亮效果:描边、高亮效果
关于gltf、glb文件模型点击后显示文本详情:待补充。。。

五、完整代码

<template>
    <div id="my-three"></div>
</template>

<script setup>
import {ref, onMounted} from 'vue'
import * as THREE from 'three'
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls'
import {GLTFLoader} from 'three/examples/jsm/loaders/GLTFLoader'; //gltf

const {proxy} = getCurrentInstance();
onMounted(() => {
  document.getElementById('my-three')?.appendChild(renderer.domElement)
  init()
  renderModel()
  gltfModel1()
  render()
})


const width = window.innerWidth, height = window.innerHeight;
const scene = new THREE.Scene();
const renderer = new THREE.WebGLRenderer()
const loader = new GLTFLoader();
const camera = new THREE.PerspectiveCamera(45, width / height, 1, 1000);
const controls = new OrbitControls(camera, renderer.domElement)


function init() {
  //光源
  const ambient = new THREE.AmbientLight(0xffffff, 0.4);
  scene.add(ambient);
  const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);//光源,color:灯光颜色,intensity:光照强度
  directionalLight.position.set(400, 200, 300);
  scene.add(directionalLight);

//设置相机位置
  camera.position.set(300, 300, 300);
//设置相机方向
  camera.lookAt(0, 0, 0);

//辅助坐标轴
  const axesHelper = new THREE.AxesHelper(200);//参数200标示坐标系大小,可以根据场景大小去设置
  scene.add(axesHelper);
  scene.background = new THREE.Color(0xeaeaea);

  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.antialias = true;
}

function gltfModel1() {
  // glb
  loader.load("../../../../public/工厂.glb",
      function (gltf) {
        scene.add(gltf.scene)
      },
      function (xhr) {
        const percent = Math.floor((xhr.loaded / xhr.total) * 100); // 计算加载进度百分比
        // console.log(`模型加载进度:${percent}%`);
      }
  )

}



function renderModel() {
  //渲染
  renderer.setSize(width, height)//设置渲染区尺寸
  renderer.render(scene, camera)//执行渲染操作、指定场景、相机作为参数
// renderer.setClearColor(0x00ff00); // 设置背景颜色为绿色
  renderer.toneMapping = THREE.ACESFilmicToneMapping;
// 设置曝光度
  renderer.toneMappingExposure = 1.5; // 适当调整曝光度

  controls.minPolarAngle = Math.PI / 4; // 最小极角为 45 度
  controls.maxPolarAngle = Math.PI / 2; // 最大极角为 90 度
}

function render() {
  renderer.render(scene, camera);
  controls.update()
  requestAnimationFrame(render);
}



// 画布跟随窗口变化
window.onresize = function () {
  renderer.setSize(window.innerWidth, window.innerHeight);
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
};


// 交互事件
addEventListener('dblclick', onMouseDblclick, false)
function onMouseDblclick(event) {
  let intersects = getIntersects(event);

  if (intersects.length !== 0 && intersects[0].object instanceof THREE.Mesh) {

    const selectedObject = intersects[0].object;
    let selectedObjects = [];
    selectedObjects.push(selectedObject);
    console.log(selectedObjects)
    // outlinePass.selectedObjects = selectedObjects;

  }
}
//获取与射线相交的对象数组
function getIntersects(event) {
  let rayCaster = new THREE.Raycaster();
  let mouse = new THREE.Vector2();

  //通过鼠标点击位置,计算出raycaster所需点的位置,以屏幕为中心点,范围-1到1
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; //这里为什么是-号,没有就无法点中

  //通过鼠标点击的位置(二维坐标)和当前相机的矩阵计算出射线位置
  rayCaster.setFromCamera(mouse, camera);
  return rayCaster.intersectObjects(scene.children);
}

</script>

<style scoped lang="scss">

</style>

五、实现效果

你可能感兴趣的:(javascript,vue,3d)