three.js 利用uv和ThreeBSP制作一個(gè)快遞柜功能
最近有three網(wǎng)友,問(wèn)我要不要學(xué)習(xí)blender,其實(shí)我感覺(jué)學(xué)習(xí)一下也無(wú)妨,不過(guò)花大量時(shí)間精通,尚可不必,術(shù)業(yè)有專攻給別人留一條路吧,哈哈。那我我們就是用ThreeBSP和uv貼圖的知識(shí)來(lái)制作一個(gè)定制化的快遞柜,先上圖,在線案例請(qǐng)點(diǎn)擊原文。
下面我們來(lái)講解一下這樣一個(gè)柜子的制作。
1. 主角是一個(gè)JSON
這樣一個(gè)快遞柜的核心是JSON數(shù)據(jù)的創(chuàng)建,有了jSON數(shù)據(jù),我們就可以通過(guò)循環(huán)遍歷出柜子,柜門和uv映射關(guān)系。那面下面來(lái)看看我們的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)為柜子是否能打開(kāi)(因?yàn)橛械牡胤綖椴僮髅姘宓龋?/p>
2. ThreeBSP繪制柜子的整體架構(gòu)。
說(shuō)完核心,我們?cè)诳纯垂褡拥恼w框架。下面是柜子的側(cè)面圖,通過(guò)側(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)大致的說(shuō)了關(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)說(shuō)過(guò),這里的a0是柜子的寬,a1是柜子的高,a2是柜子中心x的坐標(biāo)值,a3是柜子中心y的坐標(biāo)值。因?yàn)楣褡诱wx的范圍是[-223, 223],y的范圍的[10, 201]。經(jīng)過(guò)換算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)開(kāi)柜子的動(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頁(yè)面引入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)文章
省市聯(lián)動(dòng)效果的簡(jiǎn)單實(shí)現(xiàn)代碼(推薦)
下面小編就為大家?guī)?lái)一篇省市聯(lián)動(dòng)效果的簡(jiǎn)單實(shí)現(xiàn)代碼(推薦)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-06-06Javasript設(shè)計(jì)模式之鏈?zhǔn)秸{(diào)用詳解
這篇文章主要為大家詳細(xì)介紹了Javasript設(shè)計(jì)模式之鏈?zhǔn)秸{(diào)用的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-04js + css實(shí)現(xiàn)標(biāo)簽內(nèi)容切換功能(實(shí)例講解)
下面小編就為大家?guī)?lái)一篇js + css實(shí)現(xiàn)標(biāo)簽內(nèi)容切換功能(實(shí)例講解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10頁(yè)面調(diào)用單個(gè)swf文件,嵌套出多個(gè)方法。
頁(yè)面調(diào)用單個(gè)swf 文件,嵌套出多個(gè)方法,需要的朋友可以參考下。2011-11-11詳談js使用in和hasOwnProperty獲取對(duì)象屬性的區(qū)別
下面小編就為大家?guī)?lái)一篇詳談js使用in和hasOwnProperty獲取對(duì)象屬性的區(qū)別。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04JavaScript對(duì)象的特性與實(shí)踐應(yīng)用深入詳解
這篇文章主要介紹了JavaScript對(duì)象的特性與實(shí)踐應(yīng)用,結(jié)合實(shí)例形式較為深入的分析了javascript對(duì)象的相關(guān)概念、操作方法及注意事項(xiàng),需要的朋友可以參考下2018-12-12nuxt+axios實(shí)現(xiàn)打包后動(dòng)態(tài)修改請(qǐng)求地址的方法
這篇文章主要介紹了nuxt+axios實(shí)現(xiàn)打包后動(dòng)態(tài)修改請(qǐng)求地址的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04