小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Blender Three.js 智慧3D機(jī)房開(kāi)發(fā) 模型創(chuàng)建與導(dǎo)入中的常見(jiàn)問(wèn)題與解決方案

 芥子c1yw3tb42g 2023-08-26 發(fā)布于陜西

目錄

機(jī)房效果展示

可能出現(xiàn)的問(wèn)題及解決方法

Three. js服務(wù)器運(yùn)行環(huán)境搭建及文件配置

使用Node.js搭建本地服務(wù)器

文件配置 

Blender材質(zhì)處理

Blender導(dǎo)出GLTF模型出現(xiàn)材質(zhì)丟失

Three.js玻璃材質(zhì)制作

 Blender導(dǎo)出glTF格式模型

Three. js模型顯示場(chǎng)景的設(shè)置

總結(jié)


機(jī)房效果展示

機(jī)房正面圖:

24172bf3cd1f4c39bd62d850ea9ae816.png

機(jī)房背面圖:

dc2c69d7f9014b0db117c708c60b400d.png

機(jī)房:

a24e1f0355054b288b928726a1bc8ea0.png

機(jī)柜內(nèi)部(因?yàn)檫€處于測(cè)試階段,都先使用相同材質(zhì)):

b432192fc7b941d0a9ec9306ccfb7920.png

橋架和風(fēng)管:

4b5d97dacc324668b20bbd4b7b17019c.png

操作中心:

bd7ba714a646427391eac5d4a832fee8.png

UPS間外部:

7e52979c55294462a1874540f62c2d58.png

UPS間內(nèi)部:

db999a3fc01249ee8066db81f689c90d.png

blender中機(jī)房建模效果圖

1cdb9700f5aa4c2bb98cf7332b59ed36.png

渲染模式下機(jī)房模型效果圖(可以看到blender中一部分模型是不透明的,但在Three.js中是透明的,為了得到玻璃材質(zhì)效果,需要在Three.js中單獨(dú)進(jìn)行處理,下文會(huì)提到如何解決Three.js中玻璃材質(zhì)問(wèn)題):

e40dc8b4ad4343d7aac2f463b96464f1.png

可能出現(xiàn)的問(wèn)題及解決方法

在作者的不懈努力下,終于在翻遍各大技術(shù)論壇以及Blender和Three.js的官方文檔后,成功根據(jù)機(jī)房的cad圖紙轉(zhuǎn)化為上圖所示的機(jī)房效果,可以說(shuō)把所有能踩的坑都踩了一遍。

接下來(lái),我將從 Three. js服務(wù)器運(yùn)行環(huán)境搭建及文件配置, Blender模型材質(zhì)處理,Blender導(dǎo)出glTF格式模型和 Three. js模型顯示的場(chǎng)景設(shè)置,依次對(duì)可能出現(xiàn)的問(wèn)題及解決辦法進(jìn)行說(shuō)明。

Three. js服務(wù)器運(yùn)行環(huán)境搭建及文件配置

在研究 Three. js的3D模型導(dǎo)入時(shí),經(jīng)常會(huì)出現(xiàn)報(bào)錯(cuò)問(wèn)題,一般都是因?yàn)槿鄙僖恍╆P(guān)鍵的前提條件而直接導(dǎo)入模型。通常情況下,瀏覽器將顯示類似于這樣的錯(cuò)誤:

Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of 'text/html'. Strict MIME type checking is enforced for module scripts per HTML spec.

我們可以在Three.js的官方文檔中找到問(wèn)題產(chǎn)生的原因:

36eb9c26d6544e6087018c093a58ec69.png

所以,要想成功地從外面導(dǎo)入模型,我們就必須在本地運(yùn)行服務(wù)器。但如果你繼續(xù)往下看,你就會(huì)發(fā)現(xiàn),官方對(duì)你能用哪些軟件包來(lái)創(chuàng)建一個(gè)服務(wù)器進(jìn)行了簡(jiǎn)略的描述,卻沒(méi)有給出具體的解決方案(你不知道服務(wù)器代碼是如何編寫的)。

本地服務(wù)器的建立方法多種多樣,如果你對(duì)這方面有所了解,那你可以使用你熟悉的方法來(lái)建立本地服務(wù)器,可能你會(huì)問(wèn)那我直接使用云服務(wù)器如何?我的答案是可以,但是考慮到個(gè)人購(gòu)買的云服務(wù)器的上行帶寬(你從服務(wù)器上下載文件的最大速度)是如此的低,加載一個(gè)80mb的模型大概在10分鐘左右,所以為了方便和開(kāi)發(fā)效率起見(jiàn),在本地搭建一個(gè)服務(wù)器用于測(cè)試模型,再將測(cè)試完成后的模型放入云服務(wù)器中,才是你最好的解決方案。

使用Node.js搭建本地服務(wù)器

我這里將介紹如何使用Node.js來(lái)搭建本地服務(wù)器,需要使用express包,具體的原理和下載流程我就不進(jìn)行贅述了,感興趣的話可以自行搜索。下圖是我進(jìn)行模型測(cè)試的文件目錄結(jié)構(gòu):

9655baedd7e74571b1f8ad6f58bb4766.png f62cb9523e514aacb4d339cbbf97a5b5.png

 其中express.js就是用來(lái)運(yùn)行本地服務(wù)器的腳本文件,內(nèi)容如下:

  1. var express = require('express');
  2. var app = express();
  3. app.use(express.static('./public'));
  4. app.listen(3000, '127.0.0.1');

在終端輸入:

node express.js

 這樣你便成功運(yùn)行服務(wù)器,在瀏覽器輸入中輸入http://localhost:3000/后,程序?qū)ublic作為運(yùn)行主目錄,執(zhí)行里面的index.html文件。

當(dāng)然之所以僅僅需要4行就可以搭建出一個(gè)簡(jiǎn)單的本地服務(wù)器,是因?yàn)閑xpress將功能進(jìn)行了封裝,如果想了解其中運(yùn)行的流程,可以閱讀以下代碼(僅有post功能),其中的MINEType字典可以解釋前面瀏覽器報(bào)錯(cuò)的原因。

  1. var http = require('http')
  2. var url = require('url')
  3. var fs = require('fs')
  4. var path = require('path')
  5. var queryString = require('querystring')
  6. var MINEType = {
  7. '.html': 'text/html',
  8. '.css': 'text/css',
  9. '.gif': 'image/gif',
  10. '.jpg': 'image/jpeg',
  11. '.jpeg': 'image/jpeg',
  12. '.png': 'image/png',
  13. '.js': 'application/x-javascript'
  14. }
  15. var server = http.createServer(function(request, response) {
  16. response.writeHead(200, { 'content-type': 'text/html;charset=UTF-8' });
  17. var pathname = url.parse(request.url).pathname
  18. if (request.method.toLocaleLowerCase() === 'post' && pathname === '/postMethod') {
  19. let postdata = ''
  20. request.addListener('data', function(chunk) {
  21. postdata += chunk
  22. })
  23. request.addListener('end', function() {
  24. postdata = queryString.parse(postdata)
  25. console.log(postdata)
  26. })
  27. }
  28. if (pathname === '/') {
  29. pathname = '/index.html'
  30. } else if (pathname.indexOf('.') === -1) {
  31. pathname += '/index.html'
  32. }
  33. fs.readFile('./public' + pathname, function(err, data) {
  34. if (err) {
  35. response.end('404')
  36. return
  37. }
  38. response.writeHead(200, { 'content-type': MINEType[path.extname(pathname)] });
  39. response.end(data)
  40. })
  41. })
  42. server.listen(3000, '127.0.0.1')

文件配置 

在你成功搭建本地服務(wù)器后,你迫不及待將模型進(jìn)行加載,結(jié)果瀏覽器還是出現(xiàn)了報(bào)錯(cuò):

Uncaught TypeError: Failed to resolve module specifier 'three'. Relative references must start with either '/', './', or '../'.

翻譯過(guò)來(lái)就是:未捕獲TypeError:未能解析模塊說(shuō)明符“three”。相對(duì)引用必須以'/'或'./',或者'../'開(kāi)頭。具體原因也同樣自行搜索,我在這就不進(jìn)行贅述。

解決方法其實(shí)已經(jīng)出現(xiàn)在報(bào)錯(cuò)中了,只要相對(duì)引用以'/'或'./',或者'../'開(kāi)頭就好。僅模型加載為例,文件的開(kāi)頭一般是這樣的:

  1. import * as THREE from 'three'
  2. //導(dǎo)入控制器
  3. import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
  4. //模型加載
  5. import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
  6. import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'

很明顯不滿足以'/'或'./',或者'../'開(kāi)頭,這里還是以我的文件目錄結(jié)構(gòu)為例:

ce17204f845441c89141176e98ce2c4e.png

 可以看到我將three單獨(dú)從node-modules中提出來(lái)放到public文件夾中,同時(shí)將three/build/three.module.js也放到public文件夾中,這是因?yàn)榇罱ǔ鰜?lái)的服務(wù)器是比較簡(jiǎn)單的一種,只對(duì)服務(wù)器的當(dāng)前目錄支持比較好。這樣,文件的開(kāi)頭可以修改為:

  1. import * as THREE from './three.module.js';
  2. import { GLTFLoader } from './three/examples/jsm/loaders/GLTFLoader.js'
  3. import { OrbitControls } from './three/examples/jsm/controls/OrbitControls.js'
  4. import { DRACOLoader } from './three/examples/jsm/loaders/DRACOLoader.js'

到這里還只是處理了main.js文件的相對(duì)引用問(wèn)題,引用過(guò)的腳本文件也得進(jìn)行相應(yīng)的修改,以GLTFLoader.js文件為例,它的開(kāi)頭為:

  1. import {
  2. AnimationClip,
  3. Bone,
  4. Box3,
  5. BufferAttribute,
  6. BufferGeometry,
  7. ClampToEdgeWrapping,
  8. Color,
  9. DirectionalLight,
  10. DoubleSide,
  11. FileLoader,
  12. FrontSide,
  13. Group,
  14. ImageBitmapLoader,
  15. InstancedMesh,
  16. InterleavedBuffer,
  17. InterleavedBufferAttribute,
  18. Interpolant,
  19. InterpolateDiscrete,
  20. InterpolateLinear,
  21. Line,
  22. LineBasicMaterial,
  23. LineLoop,
  24. LineSegments,
  25. LinearFilter,
  26. LinearMipmapLinearFilter,
  27. LinearMipmapNearestFilter,
  28. Loader,
  29. LoaderUtils,
  30. Material,
  31. MathUtils,
  32. Matrix4,
  33. Mesh,
  34. MeshBasicMaterial,
  35. MeshPhysicalMaterial,
  36. MeshStandardMaterial,
  37. MirroredRepeatWrapping,
  38. NearestFilter,
  39. NearestMipmapLinearFilter,
  40. NearestMipmapNearestFilter,
  41. NumberKeyframeTrack,
  42. Object3D,
  43. OrthographicCamera,
  44. PerspectiveCamera,
  45. PointLight,
  46. Points,
  47. PointsMaterial,
  48. PropertyBinding,
  49. Quaternion,
  50. QuaternionKeyframeTrack,
  51. RepeatWrapping,
  52. Skeleton,
  53. SkinnedMesh,
  54. Sphere,
  55. SpotLight,
  56. Texture,
  57. TextureLoader,
  58. TriangleFanDrawMode,
  59. TriangleStripDrawMode,
  60. Vector2,
  61. Vector3,
  62. VectorKeyframeTrack,
  63. sRGBEncoding
  64. } from 'three';
  65. import { toTrianglesDrawMode } from '../utils/BufferGeometryUtils.js';

需改成:

  1. import {
  2. AnimationClip,
  3. Bone,
  4. Box3,
  5. BufferAttribute,
  6. BufferGeometry,
  7. ClampToEdgeWrapping,
  8. Color,
  9. DirectionalLight,
  10. DoubleSide,
  11. FileLoader,
  12. FrontSide,
  13. Group,
  14. ImageBitmapLoader,
  15. InstancedMesh,
  16. InterleavedBuffer,
  17. InterleavedBufferAttribute,
  18. Interpolant,
  19. InterpolateDiscrete,
  20. InterpolateLinear,
  21. Line,
  22. LineBasicMaterial,
  23. LineLoop,
  24. LineSegments,
  25. LinearFilter,
  26. LinearMipmapLinearFilter,
  27. LinearMipmapNearestFilter,
  28. Loader,
  29. LoaderUtils,
  30. Material,
  31. MathUtils,
  32. Matrix4,
  33. Mesh,
  34. MeshBasicMaterial,
  35. MeshPhysicalMaterial,
  36. MeshStandardMaterial,
  37. MirroredRepeatWrapping,
  38. NearestFilter,
  39. NearestMipmapLinearFilter,
  40. NearestMipmapNearestFilter,
  41. NumberKeyframeTrack,
  42. Object3D,
  43. OrthographicCamera,
  44. PerspectiveCamera,
  45. PointLight,
  46. Points,
  47. PointsMaterial,
  48. PropertyBinding,
  49. Quaternion,
  50. QuaternionKeyframeTrack,
  51. RepeatWrapping,
  52. Skeleton,
  53. SkinnedMesh,
  54. Sphere,
  55. SpotLight,
  56. Texture,
  57. TextureLoader,
  58. TriangleFanDrawMode,
  59. TriangleStripDrawMode,
  60. Vector2,
  61. Vector3,
  62. VectorKeyframeTrack,
  63. sRGBEncoding
  64. } from '../../../../three.module.js';
  65. import { toTrianglesDrawMode } from '../utils/BufferGeometryUtils.js';

同理,在GLTFLoader.js文件又增加了BufferGeometryUtils.js文件需要修改,上圖的import { toTrianglesDrawMode } from '../utils/BufferGeometryUtils.js';為已經(jīng)修改過(guò)的路徑。在完成所有需要導(dǎo)入的腳本文件的修改后,包括修改引用文件的引用文件?。。【涂梢哉o@示模型了。

Blender材質(zhì)處理

Blender導(dǎo)出GLTF模型出現(xiàn)材質(zhì)丟失

在我完成前面的操作后,并且導(dǎo)入了一個(gè)從網(wǎng)絡(luò)上找到的glb格式模型并且可以正常顯示后,就開(kāi)始Blender的建模,下圖是我第一次機(jī)房建模在Blender中的效果圖:

930500d9ee46403f91ecec335d9c42f3.png

 看著還不錯(cuò)吧,連玻璃都一并做好了,只需要將模型以GLTF格式導(dǎo)出就大功告成,模型導(dǎo)出也不過(guò)如此,就在我導(dǎo)出模型放入Three.js后在瀏覽器上進(jìn)行顯示后,卻得到下圖的效果:

74cbdbb3214840e38e28609780607383.png

雖然很黑,但很明顯不是光線的問(wèn)題,那只能是材質(zhì)丟失的問(wèn)題。經(jīng)過(guò)一番查詢,終于在Blender官方文檔中得到答案

3acdce17cfd147309629e578daa464f6.png

 GLTF文件只支持原理性BSDF材質(zhì),其他的著色器和材質(zhì)都不支持,因此得在Blender中手動(dòng)更改著色器并重新鏈接圖片才可以導(dǎo)出我們需要的模型。

fc85175b2aa34af88d86762b48b0fb08.png

玻璃材質(zhì)為例,在上圖可以看到,玻璃材質(zhì)是實(shí)現(xiàn)是以透明BSDF實(shí)現(xiàn)的,并不是原理化BSDF。因此需要將所有不是以原理化BSDF為著色器的材質(zhì)重新進(jìn)行鏈接。下圖為可以正常導(dǎo)出的材質(zhì):

219a370e2ef7479c8c952ddcf5c1c348.png

關(guān)于如何獲取材質(zhì)圖片,以及Blender材質(zhì)的詳細(xì)細(xì)節(jié)如何就不屬于本文的討論的范圍,感興趣的話,可以搜索Blender材質(zhì)節(jié)點(diǎn)進(jìn)行相關(guān)的了解。

Three.js玻璃材質(zhì)制作

既然只能通過(guò)原理化BDSF作為著色器,那么玻璃材質(zhì)又該如何進(jìn)行處理?以Blender中的猴頭模型為例:

bc8d528458ab487295b8d757606fb229.png

為猴頭新建材質(zhì)后,初始設(shè)置如下圖:

3b972ea7e87e46969d75ee930eaa35e6.png

進(jìn)行如下設(shè)置,將糙度設(shè)置為0,透射設(shè)置為1,Alpha設(shè)置為0.1。

dd142f5efe1846299114d8ec16066d66.png

 826cfce8ce174de6b3180e025ad7b3d3.png

 我們想要的玻璃材質(zhì)就做好了,甚至不需要我們特地去尋找材質(zhì),不過(guò)你還記得前面機(jī)房展示中,玻璃部分在Blender中卻是不透明的嗎?如果將該模型導(dǎo)出,并放到瀏覽器中進(jìn)行展示就會(huì)出現(xiàn)如下報(bào)錯(cuò):

THREE.WebGLProgram: Shader Error 0 - VALIDATE_STATUS false

Program Info Log: Fragment shader is not compiled.

FRAGMENT

ERROR: 0:880: 'isinf' : no matching overloaded function found
ERROR: 0:880: '' : boolean expression expected

 這是由于調(diào)整透射的值導(dǎo)致的,最后我發(fā)現(xiàn)在Three.js的論壇中也有人遇到了相同的問(wèn)題,問(wèn)題鏈接:https://discourse./t/meshphysicalmaterial-with-r145-and-later/47092

c413f7ccf4fa4f1c885c28f73106f6a7.png

并且在下面的評(píng)論中也給出了問(wèn)題的解決,回答鏈接:https://github.com/mrdoob/three.js/issues/25274

 32d5c3b5dc8a40debded2efe1d863771.png

 大概意思就是片段著色器無(wú)法在> r144版本中編譯,而我們的瀏覽器是r144以上的版本。在一番閱讀后,發(fā)現(xiàn)原文作者要我們進(jìn)行一些代碼的修改,不過(guò)在我打開(kāi)代碼文件時(shí),發(fā)現(xiàn)正在使用的three代碼已經(jīng)是被官方修改過(guò)了的,并且將模型放入官方的編輯器中也是能夠成功顯示的。

ae145c4175c9445faf68b5df6dc6182e.png

總之,我在這里已經(jīng)找到的問(wèn)題產(chǎn)生的原因以及可能的解決方案,不斷嘗試的過(guò)程中,均以失敗告終,于是我開(kāi)始思考另一種解決方法, 既然不能使用Blender的著色器,那么就使用Three.js中的材質(zhì)渲染。所以就先在Three.js中先編寫玻璃材質(zhì)如下:

  1. const glassMaterial = new THREE.MeshPhysicalMaterial({
  2. color: 0xffffff,
  3. side: THREE.DoubleSide,
  4. transparent: true,
  5. opacity: 0.1,
  6. depthWrith: false
  7. })

 之后在Blender為需要添加玻璃材質(zhì)的模型的命名中包含“玻璃”兩字。

11a3980a8a764842a5e8025eb7bdc242.png

 之后,在Three代碼中添加判斷,如果模型名字包含“玻璃”就將它的材質(zhì)設(shè)為已經(jīng)編寫好的玻璃材質(zhì)即可,因此就不需要在Blender中提前為玻璃部分的模型設(shè)置材質(zhì),設(shè)置了也會(huì)被后續(xù)的代碼進(jìn)行材質(zhì)的覆蓋。

  1. if (child.isMesh && child.name.includes('玻璃')) {
  2. child.material = glassMaterial
  3. }

 Blender導(dǎo)出glTF格式模型

在完成上述模型的搭建及材質(zhì)處理后,就需要將模型進(jìn)行導(dǎo)出,在導(dǎo)出的時(shí)候要注意要使用鼠標(biāo)將模型全選。

e06a91deefc54d2d99f351dc97e918d8.png

 點(diǎn)擊“文件”,然后點(diǎn)擊“導(dǎo)出”,選擇“glTF2.0”。

b946fdcb13bd4b1eaefef26548f51184.png

 點(diǎn)開(kāi)右邊的“數(shù)據(jù)”,勾選“壓縮”即可。

e42ff00d31d940beb37640825df089e8.png

這樣就足夠滿足學(xué)習(xí)的需要了,當(dāng)然,里面還有一些個(gè)性化的選擇,不過(guò)這就不在本文的討論范圍了。 

Three. js模型顯示場(chǎng)景的設(shè)置

你可能在第一次導(dǎo)入模型時(shí)候發(fā)現(xiàn),Three.js模型顯示全黑。

d39605c059eb448cb4e8528088401bc5.png

 這是由于你的場(chǎng)景中沒(méi)有光,于是你說(shuō)要有光,你就在你的文件中添加了如下代碼:

scene.add(new THREE.AmbientLight(0x666666))
  1. const light1 = new THREE.DirectionalLight(0xffffff, 1)
  2. light1.position.set(0, 0, 10)
  3. scene.add(light1)
  4. const light2 = new THREE.DirectionalLight(0xffffff, 1)
  5. light1.position.set(0, 0, -10)
  6. scene.add(light2)
  7. const light3 = new THREE.DirectionalLight(0xffffff, 1)
  8. light1.position.set(10, 0, 0)
  9. scene.add(light3)
  10. const light4 = new THREE.DirectionalLight(0xffffff, 1)
  11. light1.position.set(-10, 0, 0)
  12. scene.add(light4)

這里你可以只寫其中一個(gè)或者兩個(gè)都寫上,這里只是給你提供了一種解決問(wèn)題的最簡(jiǎn)單方法。打光也是一門很有價(jià)值的課程,打光對(duì)模型的展示效果有很大的影響,其重要性不亞于調(diào)整材質(zhì)。

總結(jié)

最后感謝你的閱讀,這里本文所能提供的就像造房子的劣質(zhì)腳手架,當(dāng)你在造好房子后,就應(yīng)該把它拆掉,在它的基礎(chǔ)上繼續(xù)學(xué)習(xí),這樣才能收獲更多。如果你遇到了在本文中沒(méi)有出現(xiàn)的問(wèn)題,歡迎評(píng)論或者私信我。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多