先看一下 效果圖
基礎知識 可以看 我之前寫的 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>