这节算是给这个车间场景收个尾,等了几天并没有人发设备模型给我,只能自己找了一个凑合用了。加载模型之前,首先要把货架上的料箱合并,以防加载模型之后因模型数量多出现卡顿,方法和之前介绍的合并传送带方法相同,代码如下:
//初始化料箱
initCube(){
let cubeList = [];
const textureLoader = new THREE.TextureLoader();
let texture = textureLoader.load("/static/images/box.png",)
const material = new THREE.MeshBasicMaterial({map: texture});
for(let q=0; q<this.shelfList.length;q++){
for(let i=0;i<this.layerNum;i++){
for(let j=0;j<this.columnNum;j++){
let x = this.shelfList[q].positionX;
let y = this.shelfList[q].positionY + 2 + j * (this.plane.planeLength / 3)
let z = this.shelfList[q].positionZ + i * (this.holder.holderHeight + this.plane.planeHeight)-9
cubeList.push(this.addCube(x - 2, y, z));
cubeList.push(this.addCube(x + 2, y, z));
}
}
}
const bayGeometry = mergeGeometries(cubeList);//合并模型数组
let cubeModelMesh = new THREE.Mesh(bayGeometry, material);//生成一整个新的模型
this.scene.add(cubeModelMesh);
},
//新增料箱
addCube(x,y,z){
let geometry = new THREE.BoxGeometry(3,3,2)
let material = new THREE.MeshBasicMaterial({color: 0x00ff00});
let mesh = new THREE.Mesh(geometry, material);
mesh.position.set(x,y,z);
mesh.updateMatrix();//更新模型变换矩阵
return mesh.geometry.applyMatrix4(mesh.matrix);//启动并应用变换矩阵
},
然后开始替换模型。首先我们下载好模型放到本地,我下载的是gltf的格式,之前用引入人的模型已经导入此组件,不用再次导入了,我们只需要在绘制模型的外面加载模型,并在循环中克隆加载到的模型,并根据模型的大小进行缩放和位置偏移。为了方便查看替换过程,我把for循环分开写了。代码如下:
initMachine(){ // 初始哈设备
this.initPerson(this.begin.x,this.begin.y,this.begin.z);
const loader = new GLTFLoader()
let addressY = this.begin.y
loader.load("/static/models/device/scene.gltf", (gltf) => {
let machine = gltf.scene
machine.scale.set(0.08,0.08,0.8)
machine.rotation.x = Math.PI/2
machine.rotation.y = Math.PI/2
for (let i = 0; i < 5; i++) {
for (let i = 0; i < this.machineList.length; i++) {
let temp = machine.clone();
temp.position.set(this.begin.x+20+45*i,addressY+2,this.begin.z-10)
this.scene.add(temp);//添加到场景中
}
addressY = addressY +60
}
})
for (let i = 0; i < 5; i++) {
for (let i = 0; i < this.machineList.length; i++) {
this.initMachineName(this.begin.x+20+45*i,this.begin.y,10,this.machineList[i])
this.initConveyor(this.begin.x+(this.conveyor.lang/2),this.begin.y,this.begin.z,6,this.conveyor.lang);//前三个参数是xyz,后面两个一个是传送带宽度,一个是传送带长度
this.addWarning(this.begin.x-5,this.begin.y,this.begin.z-9,2,30);//添加警戒线
}
this.begin.y = this.begin.y +60
}
},
这样我们就得到这样的效果
总的来说比之前好看一些了,但是数字孪生的场景是为了模拟真实情况并查看数据的,所以我们要给设备加点数据才行,之前用了精灵组件简单的做了个设备工序名,这里为了显示更复杂的样式引用CSS2DRender,他的好处是可以做一个html的div显示在设备上,样式与原生的方法一样,这样就可以设置好看的标签样式了。
首先我们需要引入两个组件CSS2DRenderer, CSS2DObject,然后我们用js创建一个div,并根据自己的需求做一个好看的div样式和数据,然后把div塞到CSS2DObject中,并设置这个对象的位置,然后加载到场景中。
const earthDiv = document.createElement('div');
earthDiv.className = "label";
earthDiv.innerHTML = "<div style='border:1px #FFFFFF solid;border-radius: 3px;'>" +
"<span style='font-size: 12px;'>"+machine.name+"</span><br/>" +
"<span style='font-size: 12px;'>PASS:100 个</span><br/>" +
"<span style='color:red;font-size: 12px;'>NG:2 个</span>" +
"</div>";
const earthLabel = new CSS2DObject(earthDiv);
earthLabel.position.set(x,y,z);//相对于父级元素的位置
this.scene.add(earthLabel);
this.labelRenderer = new CSS2DRenderer();
this.labelRenderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(this.labelRenderer.domElement)
不过要注意的是这个CSS2DObject需要用CSS2DRenderer才能渲染,所以我们需要再创建CSS2DRenderer渲染器,并放到控制器和动画绘制中,保证CSS2DObject能够正常渲染
this.labelRenderer = new CSS2DRenderer();
this.labelRenderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(this.labelRenderer.domElement)
//设置样式
this.labelRenderer.domElement.style.position = 'fixed';
this.labelRenderer.domElement.style.top = '0px';
this.labelRenderer.domElement.style.left = '0px';
this.labelRenderer.domElement.style.zIndex = '10';//设置层级
this.controls = new OrbitControls(this.camera, this.labelRenderer.domElement);//创建控制器
this.labelRenderer.render(this.scene,this.camera);
我们可以看下效果
我审美有限,大家可以根据需求和选择适合的模型和绘制更美观的标签Label,完整效果如下:
车间视频end
整个生产车间的数字孪生就到这里,需要源码的可以在评论区给我留下邮箱地址,我发给你,如果觉得有哪里不足的地方也可以给我留言,可以根据需求后续再添加章节完善这个场景。