当前位置: 首页 > article >正文

vue3使用three.js加载.obj模型示例

vue3使用three.js加载.obj模型示例

效果:
在这里插入图片描述
在这里插入图片描述
代码:
需要先安装three.js

npm install three
<template>
  <div ref="threeContainer" class="three-container"></div>
</template>

<script>
import * as THREE from 'three'
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
let scene = null // 场景需要定义到全局

const raycaster = new THREE.Raycaster()
const mouse = new THREE.Vector2()

export default {
  name: 'ThreeModel',
  data() {
    return {
      camera: null,
      renderer: null,
      controls: null
    }
  },
  mounted() {
    this.initThree()
    this.loadModel()
    this.initControls()
    this.addBackground()
    this.animate()
  },
  unmounted() {
    this.renderer.domElement.removeEventListener('click', this.onClick)
  },
  methods: {
    /**
     * 创建场景
     */
    initThree() {
      this.scene = new THREE.Scene()
      this.scene.rotation.y = 20.75
      this.scene.rotation.x = 10
      this.scene.rotation.z = 0

      // 创建相机
      this.camera = new THREE.PerspectiveCamera(
        75,
        this.$refs.threeContainer.clientWidth / this.$refs.threeContainer.clientHeight,
        1,
        1000
      )
      this.camera.position.z = 13.9
      this.camera.position.y = -100
      this.camera.position.x = 45

      // 把画面放大一点
      // this.camera.zoom = 1
      // this.camera.updateProjectionMatrix()

      // 创建渲染器
      this.renderer = new THREE.WebGLRenderer()
      this.renderer.setSize(
        this.$refs.threeContainer.clientWidth,
        this.$refs.threeContainer.clientHeight
      )
      this.$refs.threeContainer.appendChild(this.renderer.domElement)

      // 添加光源
      const light = new THREE.DirectionalLight(0xa1a1a1, 1)
      light.position.set(10, 5, 5).normalize()
      this.scene.add(light)

      // 注册点击事件
      this.renderer.domElement.addEventListener('click', this.onClick, false)
    },
    /**
     * 点击事件
     * @param {*} event
     */
    onClick(event) {
      // 将鼠标位置归一化到-1到1的范围(相对于渲染器的尺寸)
      mouse.x = (event.clientX / window.innerWidth) * 2 - 1
      mouse.y = -(event.clientY / window.innerHeight) * 2 + 1

      // 使用相机和鼠标向量来投射射线
      raycaster.setFromCamera(mouse, this.camera)

      // 检查与哪些对象相交,并处理相交的对象
      const intersects = raycaster.intersectObjects(this.scene.children)
      if (intersects.length > 0) {
        intersects.forEach((o) => {
          const intersectedObject = o.object
          // 在这里处理被点击的对象,例如改变颜色、显示信息等
          console.log('点击-on object:', intersectedObject)
          if (intersectedObject.parent.name == 'tank') {
            // 改变颜色
            intersectedObject.material.color.set(0xffffff)
          }
        })
      }
    },
    /**
     * 鼠标互动
     */
    initControls() {
      // 假设你已经有了相机、渲染器和场景
      const controls = new OrbitControls(this.camera, this.renderer.domElement)

      // 设置控制器的属性,例如最小和最大距离、旋转速度等
      controls.minDistance = 1
      controls.maxDistance = 500
      controls.enableDamping = true // 启用阻尼效果,使互动更加流畅
      controls.dampingFactor = 0.25 // 阻尼系数
      controls.screenSpacePanning = true // 是否允许平面移动
      this.controls = controls
    },
    /**
     * 场景增加背景
     */
    addBackground() {
      // 添加纯色为背景
      this.renderer.setClearColor(0xcccccc) // 设置背景颜色为天空色

      // 创建一个新的纹理加载器
      const textureLoader = new THREE.TextureLoader()

      const scene = this.scene

      // 加载图像纹理
      textureLoader.load(
        'http://cdn.yhxweb.cn/3d-sucai/BA_64_D.jpg', // 图像路径
        function (texture) {
          // 设置name
          texture.name = 'background'

          // 创建一个平面几何体(或其他几何体)
          const geometry = new THREE.PlaneGeometry(500, 500) // 假设你的场景宽度和高度是500
          const material = new THREE.MeshBasicMaterial({ map: texture })

          // 创建一个网格并添加到场景中
          const plane = new THREE.Mesh(geometry, material)
          plane.position.z = 0 // 根据你的场景深度调整位置
          scene.add(plane)
        },
        // 可选的加载进度回调函数
        undefined,
        // 可选的加载错误回调函数
        function (err) {
          console.error('An error happened while loading the texture.')
        }
      )
    },
    /**
     * 初始化模型
     */
    loadModel() {
      const loader = new OBJLoader()

      // 加载.obj模型文件
      loader.load(
        'http://cdn.yhxweb.cn/3d-sucai/OBJ_7020.obj', // 替换为你的.obj文件的URL(园林)
        (obj) => {
          // 设置name
          obj.name = 'tank'

          // 设置模型的位置和缩放
          obj.position.set(0, 0, 0)
          obj.scale.set(5, 5, 5)

          // 设置模型的旋转角度

          obj.rotation.x = 1.6
          obj.rotation.y = 2

          // 设置模型颜色
          obj.traverse((child) => {
            console.log('child:', child)

            if (child instanceof THREE.Mesh) {
              child.material.color.set(0xffd4db) // 设置颜色
            }
          })

          // 将加载的模型添加到场景中
          this.scene.add(obj)
        },
        (xhr) => {
          console.log((xhr.loaded / xhr.total) * 100 + '% loaded')
        },
        (error) => {
          console.error('An error happened', error)
        }
      )
    },
    /**
     * 动画
     */
    animate() {
      // 可以在这里添加动画逻辑,例如模型旋转
      // this.scene.rotation.y += 0.002
      // this.scene.rotation.x += 0.001

      // 更新控制器
      this.controls.update()

      this.renderer.render(this.scene, this.camera)
      // console.log(this.scene.rotation.x, this.scene.rotation.y)

      requestAnimationFrame(this.animate)
    }
  }
}
</script>

<style>
.three-container {
  width: 100%;
  height: calc(100vh - 175px);
  overflow: hidden;
}
</style>


http://www.kler.cn/news/335424.html

相关文章:

  • 项目管理-信息技术发展
  • java:缓存 json格式
  • 阿里云域名注册购买和备案
  • 工厂模式与建造者模式的区别
  • 二、Python(项目创建、常见的设置、print函数)
  • SQL Inject-基于报错的信息获取
  • JavaScript中的高阶函数
  • C语言—单链表
  • 什么是reactor以及其三种版本
  • STM32定时器(TIM)
  • jQuery 选择器
  • C++的STL标准模版库容器--list类
  • Linux相关概念和重要知识点(11)(进程调度、Linux内核链表)
  • Hive优化操作(二)
  • 数据结构与算法篇(图)(持续更新迭代)
  • Vue入门-指令学习-v-on
  • 【工具类:FastJsonRedisSerializer】
  • 新技术浪潮下的等保测评:云计算、物联网与大数据的挑战与机遇
  • 【CKA】十四、监控pod的日志
  • 【git】通过配置 `init.defaultBranch`,自定义 Git 初始化时的默认分支名称,避免使用 `master` 并消除相关的警告提示