three.js 利用uv和ThreeBSP制作一個(gè)快遞柜功能
最近有three網(wǎng)友,問我要不要學(xué)習(xí)blender,其實(shí)我感覺學(xué)習(xí)一下也無妨,不過花大量時(shí)間精通,尚可不必,術(shù)業(yè)有專攻給別人留一條路吧,哈哈。那我我們就是用ThreeBSP和uv貼圖的知識(shí)來制作一個(gè)定制化的快遞柜,先上圖,在線案例請(qǐng)點(diǎn)擊原文。

下面我們來講解一下這樣一個(gè)柜子的制作。
1. 主角是一個(gè)JSON
這樣一個(gè)快遞柜的核心是JSON數(shù)據(jù)的創(chuàng)建,有了jSON數(shù)據(jù),我們就可以通過循環(huán)遍歷出柜子,柜門和uv映射關(guān)系。那面下面來看看我們的JSON數(shù)據(jù)(部分代碼)。
var doorArray = [ [94, 10, -176, 196, false], [94, 10, -76, 196, false], [94, 10, 76, 196, false], [94, 10, 176, 196, false], [46, 15, 0, 186, false], [46, 60, 0, 147, false], [46, 21, 0, 105.5, true], [46, 10, 0, 89, true], [46, 10, 0, 78, true], [46, 20, 0, 62, true], [46, 20, 0, 41, true], [46, 20, 0, 20, true] ]
他是以一個(gè)數(shù)組的形式表現(xiàn)的,每一個(gè)數(shù)組代表一個(gè)柜子數(shù)據(jù),每一個(gè)數(shù)組中的第一項(xiàng)為當(dāng)前柜子寬度,第二項(xiàng)為高度,第三項(xiàng)為中心x位置,第四項(xiàng)而中心y位置,第五項(xiàng)為柜子是否能打開(因?yàn)橛械牡胤綖椴僮髅姘宓龋?/p>
2. ThreeBSP繪制柜子的整體架構(gòu)。
說完核心,我們?cè)诳纯垂褡拥恼w框架。下面是柜子的側(cè)面圖,通過側(cè)面圖我們可以很清晰的看出我們做了什么

其實(shí)加的不多,就是在上面加了一個(gè)檐,下面加了兩個(gè)底座,還有就是在每個(gè)小快遞柜中掏出一個(gè)洞。
我們看代碼
var texture = new THREE.TextureLoader().load('/static/images/base/cabinet.jpg')
let pubMate = new THREE.MeshNormalMaterial();
let frameGeom = new THREE.BoxGeometry(450, 200, 50);
let frameMesh = new THREE.Mesh(frameGeom, pubMate);
frameMesh.position.y = 106;
let footShape = new THREE.Shape();
footShape.moveTo(0, 2);
footShape.lineTo(8, -2);
footShape.lineTo(8, -4);
footShape.lineTo(0, -4);
footShape.lineTo(0, 0);
footShape.lineTo(-12, 0);
footShape.lineTo(-12, 2);
footShape.lineTo(0, 2);
let footExtrudeSettings = {
steps: 5,
depth: 450,
bevelEnabled: false
};
let footGeom = new THREE.ExtrudeGeometry(footShape, footExtrudeSettings);
let footMesh = new THREE.Mesh(footGeom, pubMate);
let footMesh1 = footMesh.clone();
footMesh1.rotation.y = -Math.PI / 2;
footMesh1.position.x = 225;
footMesh1.position.y = 4;
footMesh1.position.z = 25;
let footMesh2 = footMesh.clone();
footMesh2.rotation.y = Math.PI / 2;
footMesh2.position.x = -225;
footMesh2.position.y = 4;
footMesh2.position.z = -25;
let headGeom = new THREE.BoxGeometry(450, 5, 20);
let headMesh = new THREE.Mesh(headGeom, pubMate);
headMesh.position.z = 23;
headMesh.position.y = 206 - 2.5;
let framebsp = new ThreeBSP(frameMesh);
let foot1bsp = new ThreeBSP(footMesh1);
let foot2bsp = new ThreeBSP(footMesh2);
let headbsp = new ThreeBSP(headMesh);
res = framebsp.union(foot1bsp).union(foot2bsp).union(headbsp);
for(var i=0; i<doorArray.length; i++) {
let geom = new THREE.BoxGeometry(doorArray[i][0]-1, doorArray[i][1]-1, 50);
let mesh = new THREE.Mesh(geom, pubMate);
mesh.position.set(doorArray[i][2], doorArray[i][3], 4)
let meshbsp = new ThreeBSP(mesh);
res = res.subtract(meshbsp);
}
let cabinetGeom = res.toGeometry();
let cabinetMate = new THREE.MeshPhongMaterial({color: 0xD8C513, specular: 0xD8C513, shininess: 10});
let cabinetMesh = new THREE.Mesh(cabinetGeom, cabinetMate);
cabinetMesh.position.y = 106;
scene.add(cabinetMesh);這里就是在框架BoxGeometry的基礎(chǔ)上加了兩個(gè)底座ExtrudeGeometry,和一個(gè)檐BoxGeometry,然后遍歷減去小柜子。掌握好各自的空間位置,制作其實(shí)并不難。
3. 柜子的統(tǒng)一貼圖
將一張圖作為貼圖,貼到所有的mesh上,如最上面圖的效果,因?yàn)樯瞎?jié)課已經(jīng)大致的說了關(guān)于uv的一點(diǎn)知識(shí)。
for(var i=0; i<doorArray.length; i++) {
let a0 = doorArray[i][0];
let a1 = doorArray[i][1];
let a2 = doorArray[i][2];
let a3 = doorArray[i][3];
let x1 = ((a2 - a0 / 2) + 223) / 446;
let x2 = ((a2 + a0 / 2) + 223) / 446;
let y1 = ((a3 - a1 / 2) - 10) / 191;
let y2 = ((a3 + a1 / 2) - 10) / 191;
doorMesh.geometry.faceVertexUvs[0][8] = [new THREE.Vector2(x1, y2), new THREE.Vector2(x1, y1), new THREE.Vector2(x2, y2)];
doorMesh.geometry.faceVertexUvs[0][9] = [new THREE.Vector2(x1, y1), new THREE.Vector2(x2, y1), new THREE.Vector2(x2, y2)];
}上面已經(jīng)說過,這里的a0是柜子的寬,a1是柜子的高,a2是柜子中心x的坐標(biāo)值,a3是柜子中心y的坐標(biāo)值。因?yàn)楣褡诱wx的范圍是[-223, 223],y的范圍的[10, 201]。經(jīng)過換算x1是紋理x坐標(biāo)的最小值,x2是紋理x坐標(biāo)的最大值,y1是紋理y坐標(biāo)的最小值,y2是紋理y坐標(biāo)的最大值,最后設(shè)置數(shù)組索引為8和9小三角面的uv映射(因?yàn)槲覀円O(shè)置的面為長(zhǎng)方體的左面,就是8和9控制的面)。
最后加上一點(diǎn)點(diǎn)開柜子的動(dòng)畫就大功告成了。
轉(zhuǎn)載請(qǐng)注明地址:郭先生的博客
到此這篇關(guān)于three.js 利用uv和ThreeBSP制作一個(gè)快遞柜功能的文章就介紹到這了,更多相關(guān)three.js 制作快遞柜內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- three.js如何實(shí)現(xiàn)3D動(dòng)態(tài)文字效果
- three.js 實(shí)現(xiàn)露珠滴落動(dòng)畫效果的示例代碼
- three.js中多線程的使用及性能測(cè)試詳解
- three.js顯示中文字體與tween應(yīng)用詳析
- 微信小游戲中three.js離屏畫布的示例代碼
- three.js著色器材質(zhì)的內(nèi)置變量示例詳解
- vue頁面引入three.js實(shí)現(xiàn)3d動(dòng)畫場(chǎng)景操作
- three.js 制作動(dòng)態(tài)二維碼的示例代碼
- three.js 將圖片馬賽克化的示例代碼
- 如何用threejs實(shí)現(xiàn)實(shí)時(shí)多邊形折射
相關(guān)文章
script不刷新頁面的聯(lián)動(dòng)前后代碼
如何實(shí)現(xiàn)script不刷新頁面的聯(lián)動(dòng),在本文有個(gè)不錯(cuò)的示例或許對(duì)大家有所幫助2013-09-09
JavaScript交換變量的常用方法小結(jié)【4種方法】
這篇文章主要介紹了JavaScript交換變量的常用方法,結(jié)合實(shí)例形式總結(jié)分析了JavaScript交換變量的4種實(shí)現(xiàn)方法與操作注意事項(xiàng),需要的朋友可以參考下2020-05-05
js實(shí)現(xiàn)遍歷含有input的table實(shí)例
這篇文章主要介紹了js實(shí)現(xiàn)遍歷含有input的table方法,結(jié)合實(shí)例形式分析了jsp讀取數(shù)據(jù)庫動(dòng)態(tài)生成table及JavaScript遍歷table的相關(guān)技巧,需要的朋友可以參考下2015-12-12
javascript實(shí)現(xiàn)雙端隊(duì)列
這篇文章主要為大家詳細(xì)介紹了使用javascript實(shí)現(xiàn)雙端隊(duì)列,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11

