vue-cli3.0以上 threejs引入obj模型 點擊顯示模型數據

先看一下 效果圖

基礎知識 可以看 我之前寫的 https://blog.csdn.net/www_share8/category_9385409.html

首先 說一下 可能遇到的問題,

第一個可能遇見,vue-cli3.0中沒有 static 所以你的 模型可以引入不了,這個時候 你的 模型需要放到 public文件中

第二個是 引入obj模型,貼圖沒有顯示,問題主要是更改mtl文件中圖片路徑,

上面的是問題  需求就是 引入模型 並點擊模型 在對應的 模型 做展示

首先第一個問題,將模型放入 public中

 data () {
    return {
      baseUrl: process.env.BASE_URL
    }
}

加載模型,注意.load路徑

initObject () {
      let objLoader2 = new OBJLoader2()
      let mtlLoader = new MTLLoader()
      let _this = this
      let urls_mtl = `${this.baseUrl}` + '/webgl/test.mtl'
      let urls_obj = `${this.baseUrl}` + '/webgl/test.obj'

      mtlLoader.load(urls_mtl, function (mtlParseResult) {
        console.log(mtlParseResult)
        objLoader2.setLogging(true, true)

        objLoader2.addMaterials(MtlObjBridge.addMaterialsFromMtlLoader(mtlParseResult))
        objLoader2.load(urls_obj, function (calldata) {
          _this.scene.add(calldata)
        }, null, null, null)
      })
    },

其次 需要更改 .mtl文件,注意 map_ka, map_kb 這個是指定圖片路徑的 

將圖片和 mtl文件放在同一目錄下就  可以直接寫 圖片名字就行

newmtl 02___Default
	Ns 10.0000
	Ni 1.5000
	d 1.0000
	Tr 0.0000
	Tf 1.0000 1.0000 1.0000 
	illum 2
	Ka 0.5882 0.5882 0.5882
	Kd 0.5882 0.5882 0.5882
	Ks 0.0000 0.0000 0.0000
	Ke 0.0000 0.0000 0.0000
	map_Ka _auto_1.png
	map_Kd _auto_1.png

newmtl 01___Default
	Ns 10.0000
	Ni 1.5000
	d 1.0000
	Tr 0.0000
	Tf 1.0000 1.0000 1.0000 
	illum 2
	Ka 0.5882 0.5882 0.5882
	Kd 0.5882 0.5882 0.5882
	Ks 0.0000 0.0000 0.0000
	Ke 0.0000 0.0000 0.0000
	map_Ka _auto_4.png
	map_Kd _auto_4.png

至於 點擊 模型展示

我是直接在 2D平面上展示的  因爲項目需求 沒有要求 在3D模型中展示  ,3D展示的  大家可以參考 我之前寫的 這篇文章  你根據 思路 去寫https://blog.csdn.net/WWW_share8/article/details/102826326

點擊事件

  /**
     * 點擊事件
     */
    mouseClick (event) {
      // 獲取 raycaster 和所有模型相交的數組,其中的元素按照距離排序,越近的越靠前
      let intersects = this.getIntersects(event)
      console.log(intersects)
      // 獲取選中最近的 Mesh 對象
      if (intersects.length != 0 && intersects[0].object instanceof THREE.Mesh) {
        let selectObject = intersects[0].object;
        this.showObject(selectObject, event);
      }
    },

將平面 座標 轉換到3D座標

   /**
     * 將屏幕座標轉換爲3d 座標
     */
    getIntersects (event) {
      event.preventDefault();
      console.log("event.clientX:" + event.clientX)
      console.log("event.clientY:" + event.clientY)

      // 聲明 raycaster 和 mouse 變量
      var raycaster = new THREE.Raycaster();
      var 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, this.camera);

      // 獲取與射線相交的對象數組,其中的元素按照距離排序,越近的越靠前
      var intersects = raycaster.intersectObjects(this.scene.children, true);
      //返回選中的對象
      return intersects;
    },

其次 就是  點擊 事件後 需要  展示 的 內容,因爲 我和做模型的同事那  瞭解到  他可以在mesh中 name屬性 上添加 標記

所以  我只需要獲取name屬性 就可以了

 /**
     * 展示點擊內容
     */
    showObject (obj, event) {
      console.log(obj)
      let key = obj.name
      let objs = this.cabinetData.filter(item => {
        return item.code === key
      })
      // 顯示內容
      this.texts = objs[0]
      // 處理座標
      this.dragTop = event.clientY - 50
      this.dragLeft = event.clientX - 100
    },

下面是  代碼

<template>
  <div id="threes"
       @click="mouseClick">
    <div class="moveText"
         :style="{top:dragTop+'px',left:dragLeft+'px'}">
      <p>機櫃編號: {{texts.code}}</p>
      <p>設備類型: {{texts.type}}</p>
    </div>
  </div>
</template>

<script>
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader.js'
import { OBJLoader2 } from 'three/examples/jsm/loaders/OBJLoader2.js'
import { MtlObjBridge } from 'three/examples/jsm/loaders/obj2/bridge/MtlObjBridge.js'
export default {
  name: 'threes',
  data () {
    return {
      texts: {
        code: '',
        type: ''
      },
      dragTop: -100,
      dragLeft: -200,
      widthBox: '',
      heightBox: '',
      cabinetData: [
        { code: 'Mesh1', type: '交換機' },
        { code: 'Mesh2', type: '路由器' }
      ],
      clock: '',
      renderer: '', // 渲染器
      camera: '', // 相機
      scene: '', // 場景
      light: '', // 光線
      mesh: '', // 網格
      controls: '',//控制
      baseUrl: process.env.BASE_URL
    }
  },
  mounted: function () {
    this.$nextTick(function () {
      this.threeStart()
    })
  },
  methods: {
    /**
     * 初始化渲染器
     */
    initThree () {
      this.widthBox = document.getElementById('threes').clientWidth
      this.heightBox = document.getElementById('threes').clientHeight
      this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true })
      this.renderer.setSize(this.widthBox, this.heightBox)
      document.getElementById('threes').appendChild(this.renderer.domElement)
      this.renderer.setClearAlpha(0.2);
    },

    /**
     * 初始化相機
     */
    initCamera () {
      this.camera = new THREE.PerspectiveCamera(45, this.widthBox / this.heightBox, 0.1, 2000)
      this.camera.position.set(150, 250, 200)
    },

    /**
     * 初始化場景
     */
    initScene () {
      this.scene = new THREE.Scene()
    },

    /**
     * 初始化燈光
     */
    initLight () {
      this.light = new THREE.AmbientLight(0xffffff)
      this.scene.add(this.light)
      let pointLight = new THREE.PointLight(0xe3e3e4)
      pointLight.position.set(300, 150, 350)
      this.scene.add(pointLight)
    },

    /**
     * 初始化模型
     */
    initObject () {
      let objLoader2 = new OBJLoader2()
      let mtlLoader = new MTLLoader()
      let _this = this
      let urls_mtl = `${this.baseUrl}` + '/webgl/test.mtl'
      let urls_obj = `${this.baseUrl}` + '/webgl/test.obj'

      mtlLoader.load(urls_mtl, function (mtlParseResult) {
        console.log(mtlParseResult)
        objLoader2.setLogging(true, true)
        objLoader2.addMaterials(MtlObjBridge.addMaterialsFromMtlLoader(mtlParseResult))
        objLoader2.load(urls_obj, function (calldata) {
          _this.scene.add(calldata)
        }, null, null, null)
      })
    },

    /**
     * 用戶交換事件
     */
    initControls () {
      this.controls = new OrbitControls(this.camera, this.renderer.domElement)
      // 拉近攝像頭
      this.controls.minDistance = 5
      this.controls.maxDistance = 600
      // 垂直旋轉
      this.controls.maxPolarAngle = Math.PI / 2
      this.controls.minPolarAngle = Math.PI / 4

      this.controls.target.set(0, 5, 0)
    },

    /**
     * 控制動畫
     */
    animation () {
      this.controls.update()
      requestAnimationFrame(this.animation)
      this.renderer.render(this.scene, this.camera)
    },

    /**
     * 點擊事件
     */
    mouseClick (event) {
      // 獲取 raycaster 和所有模型相交的數組,其中的元素按照距離排序,越近的越靠前
      let intersects = this.getIntersects(event)
      // 獲取選中最近的 Mesh 對象
      if (intersects.length != 0 && intersects[0].object instanceof THREE.Mesh) {
        let selectObject = intersects[0].object;
        this.showObject(selectObject, event);
      }
    },

    /**
     * 展示點擊內容
     */
    showObject (obj, event) {
      console.log(obj)
      let key = obj.name
      let objs = this.cabinetData.filter(item => {
        return item.code === key
      })
      // 顯示內容
      this.texts = objs[0]
      // 處理座標
      this.dragTop = event.clientY - 50
      this.dragLeft = event.clientX - 100
    },
    /**
     * 將屏幕座標轉換爲3d 座標
     */
    getIntersects (event) {
      event.preventDefault();
      var raycaster = new THREE.Raycaster();
      var mouse = new THREE.Vector2();
      mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
      mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
      raycaster.setFromCamera(mouse, this.camera);
      var intersects = raycaster.intersectObjects(this.scene.children, true);
      return intersects;
    },

    threeStart () {
      this.initThree()
      this.initCamera()
      this.initScene()
      this.initLight()
      this.initObject()
      this.initControls()
      this.animation()
    }
  }

}
</script>

<style lang='less' scoped>
#threes {
  width: 100%;
  height: 100%;
  position: relative;

  .text {
    position: absolute;
    font-size: 40px;
    color: #47fff8;
    left: 40px;
    bottom: 60px;
    cursor: pointer;
    animation: glow-animation 2s linear infinite alternate;
  }
  .moveText {
    position: absolute;
    padding: 10px;
    background: rgba(154, 200, 225, 0.3);

    p {
      font-size: 20px;
      text-align: left;
      color: #fff;
    }
  }

  @keyframes glow-animation {
    0% {
      font-size: 40px;
    }
    50% {
      font-size: 42px;
    }
    100% {
      font-size: 44px;
    }
  }
}
</style>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章