因项目需求 需要自定义搭建3D库房,并配置货架和货物的位置等等。这里贴出部分关键代码
详细代码较多 可参见示例 @跃焱邵隼 下的简单案例 > 3d仓库
const warehouse = new YsWarehouse(app)
// 添加地面
const floorTexture = textureLoader.load("../../images/ysThree/warehouse/floor.jpg")
const floorMaterial = new THREE.MeshBasicMaterial({map: floorTexture,side: THREE.DoubleSide })
floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping
floorTexture.repeat.set(10, 10)
const floor = warehouse.createFloor({
material: floorMaterial,
width: 2600,
height: 1400,
name: '地面'
})
// 添加普通墙
const wallMaterial = [
new THREE.MeshPhongMaterial({color: 0xafc0ca}), //前 0xafc0ca :灰色
new THREE.MeshPhongMaterial({color: 0x9cb2d1}), //后 0x9cb2d1:淡紫
new THREE.MeshPhongMaterial({color: 0xd6e4ec}), //上 0xd6e4ec: 偏白色
new THREE.MeshPhongMaterial({color: 0xd6e4ec}), //下
new THREE.MeshPhongMaterial({color: 0xafc0ca}), //左 0xafc0ca :灰色
new THREE.MeshPhongMaterial({color: 0xafc0ca}), //右
]
const wall1 = warehouse.createCube({
width: 10,
height: 200,
depth: 1400,
name: '墙',
angle: 1,
material: wallMaterial,
position: [-1295, 100, 0]
})
const wall2 = warehouse.createCube({
width: 10,
height: 200,
depth: 1400,
name: '墙',
angle: 0,
material: wallMaterial,
position: [1295, 100, 0]
})
const wall3 = warehouse.createCube({
width: 10,
height: 200,
depth: 2600,
name: '墙',
angle: 1.5,
material: wallMaterial,
position: [0, 100, -700]
})
scene.add(floor,wall1,wall2,wall3)
// 创建墙 并在这个墙上 挖门和窗户
const wall4 = warehouse.createCube({
width: 2600,
height: 200,
depth: 10,
name: '墙',
angle: 0,
position: [0, 100, 700]
})
const window_door = [
warehouse.createCube({
width: 200,
height: 180,
depth: 10,
name: '门1',
angle: 0,
position: [-600, 90, 700]
}),
warehouse.createCube({
width: 200,
height: 180,
depth: 10,
name: '门2',
angle: 0,
position: [600, 90, 700]
}),
warehouse.createCube({
width: 100,
height: 100,
depth: 10,
name: '窗1',
angle: 0,
position: [-900, 90, 700]
}),
warehouse.createCube({
width: 100,
height: 100,
depth: 10,
name: '窗2',
angle: 0,
position: [900, 90, 700]
}),
warehouse.createCube({
width: 100,
height: 100,
depth: 10,
name: '窗3',
angle: 0,
position: [-200, 90, 700]
}),
warehouse.createCube({
width: 100,
height: 100,
depth: 10,
name: '窗4',
angle: 0,
position: [200, 90, 700]
})
]
const wall_window_door_material = new THREE.MeshPhongMaterial({
color: 0x9cb2d1,
specular: 0x9cb2d1,
shininess: 30,
transparent: true,
opacity: 1
})
const wallWithWindow_door = warehouse.createBsp(wall4, window_door, wall_window_door_material)
scene.add(wallWithWindow_door)
//添加门窗 并给他们添加贴图材质
const left_door_material = new THREE.MeshBasicMaterial({
map: textureLoader.load("../../images/ysThree/warehouse/door_left.png"),
transparent:true,
color: 0xffffff
});
const right_door_material = new THREE.MeshBasicMaterial({
map: textureLoader.load("../../images/ysThree/warehouse/door_right.png"),
transparent:true,
color: 0xffffff
});
const window_material = new THREE.MeshBasicMaterial({
map: textureLoader.load("../../images/ysThree/warehouse/window.png"),
transparent:true,
color: 0xffffff
});
const window_door_real = [
warehouse.createCube({
width: 100,
height: 180,
depth: 2,
name: '门_left_1',
angle: 0,
material: left_door_material,
position: [ -700, -10, 0]
}),
warehouse.createCube({
width: 100,
height: 180,
depth: 2,
name: '门_left_2',
angle: 0,
material: right_door_material,
position: [ -500, -10, 0]
}),
warehouse.createCube({
width: 100,
height: 180,
depth: 2,
name: '门_right_1',
angle: 0,
material: left_door_material,
position: [500, -10, 0]
}),
warehouse.createCube({
width: 100,
height: 180,
depth: 2,
name: '门_right_2',
angle: 0,
material: right_door_material,
position: [700, -10, 0]
}),
warehouse.createCube({
width: 100,
height: 100,
depth: 2,
name: '窗1',
angle: 0,
material: window_material,
position: [-900, -10, 0]
}),
warehouse.createCube({
width: 100,
height: 100,
depth: 2,
name: '窗2',
angle: 0,
material: window_material,
position: [900, -10, 0]
}),
warehouse.createCube({
width: 100,
height: 100,
depth: 2,
name: '窗3',
angle: 0,
material: window_material,
position: [-200, -10, 0]
}),
warehouse.createCube({
width: 100,
height: 100,
depth: 2,
name: '窗4',
angle: 0,
material: window_material,
position: [200, -10, 0]
})
]
window_door_real.forEach(e => wallWithWindow_door.add(e))
//添加货架
const data = warehouseData //在data/ysThree/warehouseData.js中
const rackT1 = textureLoader.load(
`../../images/ysThree/warehouse/rack_left.png`
)
const rackT2 = textureLoader.load(
`../../images/ysThree/warehouse/rack_front.png`
)
const rackT3 = textureLoader.load(
`../../images/ysThree/warehouse/rack_bottom.png`
)
const rackMaterial = [
new THREE.MeshBasicMaterial({ map: rackT1, transparent: true, side: THREE.DoubleSide }), // 左 side: THREE.DoubleSide
new THREE.MeshBasicMaterial({ map: rackT1, transparent: true, side: THREE.DoubleSide }), // 右
new THREE.MeshBasicMaterial({ map: rackT2, transparent: true, side: THREE.DoubleSide }), // 前
new THREE.MeshBasicMaterial({ map: rackT2, transparent: true, side: THREE.DoubleSide }), // 后
new THREE.MeshBasicMaterial({
map: rackT3,
transparent: true,
opacity: 0
}), // 上
new THREE.MeshBasicMaterial({ map: rackT3, side: THREE.DoubleSide }) // 下
]
const boxMaterial = new THREE.MeshBasicMaterial({
map: textureLoader.load(`../../images/ysThree/warehouse/crate.gif`)
})
const rackGroupResult = warehouse.initRackGroup({
rack: {
width: 40,
height: 32,
depth: 32
},
box: {
width: 32,
height: 24,
depth: 24
},
rackMaterial: rackMaterial,
boxMaterial: boxMaterial,
data: data
})
const rackGroupList = rackGroupResult.rackGroupList // list
const rackGroupAll = rackGroupResult.rackGroupAll // group
// 初始化拖拽插件
let isDrag = false
let currentDrag
let currentHoverRack
let canDrag = false
function initDragControls(dragObjects, type) {
// 添加平移控件
const transformControls = new THREE.TransformControls(
camera,
renderer.domElement
)
scene.add(transformControls)
// 初始化拖拽控件
const dragControls = new THREE.DragControls(dragObjects, camera, renderer.domElement, type)
// 鼠标略过事件
dragControls.addEventListener('hoveron', function(event) {
if(!canDrag) return
// 让变换控件对象和选中的对象绑定
transformControls.attach(event.object)
// 设置三维坐标轴的大小,这个坐标轴不会随着模型的缩放而缩放
transformControls.setSize(0.000001)
})
// 开始拖拽
dragControls.addEventListener('dragstart', function(event) {
if(!canDrag) return
controls.enabled = false // 拖拽的时候 controls禁止
isDrag = true
currentDrag = event.object
})
// 拖拽结束
dragControls.addEventListener('dragend', function(event) {
if(!canDrag) return
transformControls.detach()
controls.enabled = true
isDrag = false
if(currentDrag.userData.isBox ) {
const dragBox = currentDrag
const dragRack = currentDrag.parent
if(currentHoverRack && currentHoverRack.userData.isEmpty) {
warehouse.addBox(currentHoverRack, {
name: dragBox.name,
displayName: dragBox.userData.displayName,
picList: dragBox.userData.picList
})
dragRack.remove(dragBox)
dragRack.userData.isEmpty = true
currentHoverRack.userData.isEmpty = false
}else {
ys.messageBox({
icon: 'cry',
msg: '当前货架已经有货物了,请重新放置'
})
currentDrag.position.set(0,0,0)
}
}
currentHoverRack = null
})
return dragControls
}
const dragControls = initDragControls(rackGroupList, 1)
dragControls.enabled = false
// 精准放入 box
document.addEventListener('mousemove',function (e) {
const objList = app.getIntersectObject(el,e,rackGroupAll,true).objectList
//如果 开始了拖拽
if(canDrag) {
if(isDrag && currentDrag.userData.isBox) {
const currentHoverList = objList.filter(e => e.object.userData.isRack && e.object.userData.isEmpty)
if(currentHoverList && currentHoverList.length >0) {
currentHoverRack = currentHoverList[0].object
}
}
}
})
document.addEventListener('click',function (e) {
const objList = app.getIntersectObject(el,e,rackGroupAll,true).objectList
//如果 开始了拖拽
if(!canDrag) {
if(objList.length > 0){
console.log(objList[0])
if(objList[0].object.userData.isRack && objList[0].object.userData.isEmpty) { //是空货架孔
ys.messageBox({
msg: '添加一个货架'
})
//dragControls.updateObjects(rackGroupList) 更新后是否需要更新拖拽组
}else if (objList[0].object.userData.isRack && !objList[0].object.userData.isEmpty) { //是箱子
ys.messageBox({
msg: '查看该货架消息,并选择更新'
})
//dragControls.updateObjects(rackGroupList) 更新后是否需要更新拖拽组
}
}
}
})