先看一下 效果图
基础知识 可以看 我之前写的 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路径,同时注意 dealMeshMaterial 这个函数是留着 后期做高高亮的
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.oldChildren = _this.dealMeshMaterial(calldata.children)
_this.scene.add(calldata)
}, null, null, null)
})
},
/**
* 留住每个模型的 原材质
*/
dealMeshMaterial (arrs) {
let result = []
for (let i = 0; i < arrs.length; i++) {
let obj = {
'name': arrs[i].name,
'material': arrs[i].material
}
result.push(obj)
}
return result
},
其次 需要更改 .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
点击事件,高亮的原理是 之前先备份一份原 材质 ,在 点击之前先还原 ,最后 通过 new THREE.材质
map 使用原来记录的 材质 map 添加一个高亮颜色就可以了
/**
* 点击事件
*/
mouseClick (event) {
// 还原之前的 点击状态
this.restore(this.scene.children[2].children, this.oldChildren)
// 获取 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);
}
},
restore (arrsNew, arrsOld) {
for (let i = 0; i < arrsNew.length; i++) {
for (let j = 0; j < arrsOld.length; j++) {
if (arrsNew[i].name === arrsOld[j].name) {
arrsNew[i].material = arrsOld[j].material
break
}
}
}
},
/**
* 展示点击内容
*/
showObject (obj, event) {
console.log(obj)
let key = obj.name
let objs = this.cabinetData.filter(item => {
return item.code === key
})
// 显示内容,高亮
if (objs.length > 0) {
let oldOneMaterial = this.oldChildren.filter(item => item.name === key)[0]
obj.material = new THREE.MeshPhongMaterial({
color: 0xff0000,
map: oldOneMaterial.material.map
});
this.texts = objs[0]
// 处理坐标
this.dragTop = event.clientY - 50
this.dragLeft = event.clientX - 100
} else {
this.init()
}
},
将平面 坐标 转换到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
},
下面是 代码
机柜编号: {{texts.code}}
设备类型: {{texts.type}}