目錄
機(jī)房效果展示
可能出現(xià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模型顯示場景的設(shè)置
總結(jié)
?文章來源地址http://www.zghlxwxcb.cn/news/detail-447028.html
機(jī)房效果展示
機(jī)房正面圖:
機(jī)房背面圖:
機(jī)房:
機(jī)柜內(nèi)部(因?yàn)檫€處于測試階段,都先使用相同材質(zhì)):
橋架和風(fēng)管:
操作中心:
UPS間外部:
UPS間內(nèi)部:
blender中機(jī)房建模效果圖
渲染模式下機(jī)房模型效果圖(可以看到blender中一部分模型是不透明的,但在Three.js中是透明的,為了得到玻璃材質(zhì)效果,需要在Three.js中單獨(dú)進(jìn)行處理,下文會(huì)提到如何解決Three.js中玻璃材質(zhì)問題):
?文章來源:http://www.zghlxwxcb.cn/news/detail-447028.html
可能出現(xiàn)的問題及解決方法
在作者的不懈努力下,終于在翻遍各大技術(shù)論壇以及Blender和Three.js的官方文檔后,成功根據(jù)機(jī)房的cad圖紙轉(zhuǎn)化為上圖所示的機(jī)房效果,可以說把所有能踩的坑都踩了一遍。
接下來,我將從 Three. js服務(wù)器運(yùn)行環(huán)境搭建及文件配置, Blender模型材質(zhì)處理,Blender導(dǎo)出glTF格式模型和 Three. js模型顯示的場景設(shè)置,依次對(duì)可能出現(xiàn)的問題及解決辦法進(jìn)行說明。
Three. js服務(wù)器運(yùn)行環(huán)境搭建及文件配置
在研究 Three. js的3D模型導(dǎo)入時(shí),經(jīng)常會(huì)出現(xiàn)報(bào)錯(cuò)問題,一般都是因?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的官方文檔中找到問題產(chǎn)生的原因:
所以,要想成功地從外面導(dǎo)入模型,我們就必須在本地運(yùn)行服務(wù)器。但如果你繼續(xù)往下看,你就會(huì)發(fā)現(xiàn),官方對(duì)你能用哪些軟件包來創(chuàng)建一個(gè)服務(wù)器進(jìn)行了簡略的描述,卻沒有給出具體的解決方案(你不知道服務(wù)器代碼是如何編寫的)。
本地服務(wù)器的建立方法多種多樣,如果你對(duì)這方面有所了解,那你可以使用你熟悉的方法來建立本地服務(wù)器,可能你會(huì)問那我直接使用云服務(wù)器如何?我的答案是可以,但是考慮到個(gè)人購買的云服務(wù)器的上行帶寬(你從服務(wù)器上下載文件的最大速度)是如此的低,加載一個(gè)80mb的模型大概在10分鐘左右,所以為了方便和開發(fā)效率起見,在本地搭建一個(gè)服務(wù)器用于測試模型,再將測試完成后的模型放入云服務(wù)器中,才是你最好的解決方案。
使用Node.js搭建本地服務(wù)器
我這里將介紹如何使用Node.js來搭建本地服務(wù)器,需要使用express包,具體的原理和下載流程我就不進(jìn)行贅述了,感興趣的話可以自行搜索。下圖是我進(jìn)行模型測試的文件目錄結(jié)構(gòu):
?
?其中express.js就是用來運(yùn)行本地服務(wù)器的腳本文件,內(nèi)容如下:
var express = require('express');
var app = express();
app.use(express.static('./public'));
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è)簡單的本地服務(wù)器,是因?yàn)閑xpress將功能進(jìn)行了封裝,如果想了解其中運(yùn)行的流程,可以閱讀以下代碼(僅有post功能),其中的MINEType字典可以解釋前面瀏覽器報(bào)錯(cuò)的原因。
var http = require("http")
var url = require("url")
var fs = require('fs')
var path = require('path')
var queryString = require('querystring')
var MINEType = {
".html": "text/html",
".css": "text/css",
".gif": "image/gif",
".jpg": "image/jpeg",
".jpeg": "image/jpeg",
".png": "image/png",
".js": "application/x-javascript"
}
var server = http.createServer(function(request, response) {
response.writeHead(200, { "content-type": "text/html;charset=UTF-8" });
var pathname = url.parse(request.url).pathname
if (request.method.toLocaleLowerCase() === 'post' && pathname === '/postMethod') {
let postdata = ''
request.addListener('data', function(chunk) {
postdata += chunk
})
request.addListener('end', function() {
postdata = queryString.parse(postdata)
console.log(postdata)
})
}
if (pathname === "/") {
pathname = "/index.html"
} else if (pathname.indexOf(".") === -1) {
pathname += "/index.html"
}
fs.readFile("./public" + pathname, function(err, data) {
if (err) {
response.end("404")
return
}
response.writeHead(200, { "content-type": MINEType[path.extname(pathname)] });
response.end(data)
})
})
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 "../".
翻譯過來就是:未捕獲TypeError:未能解析模塊說明符“three”。相對(duì)引用必須以"/"或"./",或者"../"開頭。具體原因也同樣自行搜索,我在這就不進(jìn)行贅述。
解決方法其實(shí)已經(jīng)出現(xiàn)在報(bào)錯(cuò)中了,只要相對(duì)引用以"/"或"./",或者"../"開頭就好。僅模型加載為例,文件的開頭一般是這樣的:
import * as THREE from 'three'
//導(dǎo)入控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js"
//模型加載
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js"
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js"
很明顯不滿足以"/"或"./",或者"../"開頭,這里還是以我的文件目錄結(jié)構(gòu)為例:
?可以看到我將three單獨(dú)從node-modules中提出來放到public文件夾中,同時(shí)將three/build/three.module.js也放到public文件夾中,這是因?yàn)榇罱ǔ鰜淼姆?wù)器是比較簡單的一種,只對(duì)服務(wù)器的當(dāng)前目錄支持比較好。這樣,文件的開頭可以修改為:
import * as THREE from "./three.module.js";
import { GLTFLoader } from "./three/examples/jsm/loaders/GLTFLoader.js"
import { OrbitControls } from "./three/examples/jsm/controls/OrbitControls.js"
import { DRACOLoader } from "./three/examples/jsm/loaders/DRACOLoader.js"
到這里還只是處理了main.js文件的相對(duì)引用問題,引用過的腳本文件也得進(jìn)行相應(yīng)的修改,以GLTFLoader.js文件為例,它的開頭為:
import {
AnimationClip,
Bone,
Box3,
BufferAttribute,
BufferGeometry,
ClampToEdgeWrapping,
Color,
DirectionalLight,
DoubleSide,
FileLoader,
FrontSide,
Group,
ImageBitmapLoader,
InstancedMesh,
InterleavedBuffer,
InterleavedBufferAttribute,
Interpolant,
InterpolateDiscrete,
InterpolateLinear,
Line,
LineBasicMaterial,
LineLoop,
LineSegments,
LinearFilter,
LinearMipmapLinearFilter,
LinearMipmapNearestFilter,
Loader,
LoaderUtils,
Material,
MathUtils,
Matrix4,
Mesh,
MeshBasicMaterial,
MeshPhysicalMaterial,
MeshStandardMaterial,
MirroredRepeatWrapping,
NearestFilter,
NearestMipmapLinearFilter,
NearestMipmapNearestFilter,
NumberKeyframeTrack,
Object3D,
OrthographicCamera,
PerspectiveCamera,
PointLight,
Points,
PointsMaterial,
PropertyBinding,
Quaternion,
QuaternionKeyframeTrack,
RepeatWrapping,
Skeleton,
SkinnedMesh,
Sphere,
SpotLight,
Texture,
TextureLoader,
TriangleFanDrawMode,
TriangleStripDrawMode,
Vector2,
Vector3,
VectorKeyframeTrack,
sRGBEncoding
} from 'three';
import { toTrianglesDrawMode } from '../utils/BufferGeometryUtils.js';
需改成:
import {
AnimationClip,
Bone,
Box3,
BufferAttribute,
BufferGeometry,
ClampToEdgeWrapping,
Color,
DirectionalLight,
DoubleSide,
FileLoader,
FrontSide,
Group,
ImageBitmapLoader,
InstancedMesh,
InterleavedBuffer,
InterleavedBufferAttribute,
Interpolant,
InterpolateDiscrete,
InterpolateLinear,
Line,
LineBasicMaterial,
LineLoop,
LineSegments,
LinearFilter,
LinearMipmapLinearFilter,
LinearMipmapNearestFilter,
Loader,
LoaderUtils,
Material,
MathUtils,
Matrix4,
Mesh,
MeshBasicMaterial,
MeshPhysicalMaterial,
MeshStandardMaterial,
MirroredRepeatWrapping,
NearestFilter,
NearestMipmapLinearFilter,
NearestMipmapNearestFilter,
NumberKeyframeTrack,
Object3D,
OrthographicCamera,
PerspectiveCamera,
PointLight,
Points,
PointsMaterial,
PropertyBinding,
Quaternion,
QuaternionKeyframeTrack,
RepeatWrapping,
Skeleton,
SkinnedMesh,
Sphere,
SpotLight,
Texture,
TextureLoader,
TriangleFanDrawMode,
TriangleStripDrawMode,
Vector2,
Vector3,
VectorKeyframeTrack,
sRGBEncoding
} from '../../../../three.module.js';
import { toTrianglesDrawMode } from '../utils/BufferGeometryUtils.js';
同理,在GLTFLoader.js文件又增加了BufferGeometryUtils.js文件需要修改,上圖的import { toTrianglesDrawMode } from '../utils/BufferGeometryUtils.js';為已經(jīng)修改過的路徑。在完成所有需要導(dǎo)入的腳本文件的修改后,包括修改引用文件的引用文件!??!就可以正常顯示模型了。
Blender材質(zhì)處理
Blender導(dǎo)出GLTF模型出現(xiàn)材質(zhì)丟失
在我完成前面的操作后,并且導(dǎo)入了一個(gè)從網(wǎng)絡(luò)上找到的glb格式模型并且可以正常顯示后,就開始Blender的建模,下圖是我第一次機(jī)房建模在Blender中的效果圖:
?看著還不錯(cuò)吧,連玻璃都一并做好了,只需要將模型以GLTF格式導(dǎo)出就大功告成,模型導(dǎo)出也不過如此,就在我導(dǎo)出模型放入Three.js后在瀏覽器上進(jìn)行顯示后,卻得到下圖的效果:
雖然很黑,但很明顯不是光線的問題,那只能是材質(zhì)丟失的問題。經(jīng)過一番查詢,終于在Blender官方文檔中得到答案
?GLTF文件只支持原理性BSDF材質(zhì),其他的著色器和材質(zhì)都不支持,因此得在Blender中手動(dòng)更改著色器并重新鏈接圖片才可以導(dǎo)出我們需要的模型。
玻璃材質(zhì)為例,在上圖可以看到,玻璃材質(zhì)是實(shí)現(xiàn)是以透明BSDF實(shí)現(xiàn)的,并不是原理化BSDF。因此需要將所有不是以原理化BSDF為著色器的材質(zhì)重新進(jìn)行鏈接。下圖為可以正常導(dǎo)出的材質(zhì):
關(guān)于如何獲取材質(zhì)圖片,以及Blender材質(zhì)的詳細(xì)細(xì)節(jié)如何就不屬于本文的討論的范圍,感興趣的話,可以搜索Blender材質(zhì)節(jié)點(diǎn)進(jìn)行相關(guān)的了解。
Three.js玻璃材質(zhì)制作
既然只能通過原理化BDSF作為著色器,那么玻璃材質(zhì)又該如何進(jìn)行處理?以Blender中的猴頭模型為例:
為猴頭新建材質(zhì)后,初始設(shè)置如下圖:
進(jìn)行如下設(shè)置,將糙度設(shè)置為0,透射設(shè)置為1,Alpha設(shè)置為0.1。
?
?我們想要的玻璃材質(zhì)就做好了,甚至不需要我們特地去尋找材質(zhì),不過你還記得前面機(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的論壇中也有人遇到了相同的問題,問題鏈接:https://discourse.threejs.org/t/meshphysicalmaterial-with-r145-and-later/47092
并且在下面的評(píng)論中也給出了問題的解決,回答鏈接:https://github.com/mrdoob/three.js/issues/25274
?
?大概意思就是片段著色器無法在> r144版本中編譯,而我們的瀏覽器是r144以上的版本。在一番閱讀后,發(fā)現(xiàn)原文作者要我們進(jìn)行一些代碼的修改,不過在我打開代碼文件時(shí),發(fā)現(xiàn)正在使用的three代碼已經(jīng)是被官方修改過了的,并且將模型放入官方的編輯器中也是能夠成功顯示的。
總之,我在這里已經(jīng)找到的問題產(chǎn)生的原因以及可能的解決方案,不斷嘗試的過程中,均以失敗告終,于是我開始思考另一種解決方法,?既然不能使用Blender的著色器,那么就使用Three.js中的材質(zhì)渲染。所以就先在Three.js中先編寫玻璃材質(zhì)如下:
const glassMaterial = new THREE.MeshPhysicalMaterial({
color: 0xffffff,
side: THREE.DoubleSide,
transparent: true,
opacity: 0.1,
depthWrith: false
})
?之后在Blender為需要添加玻璃材質(zhì)的模型的命名中包含“玻璃”兩字。
?之后,在Three代碼中添加判斷,如果模型名字包含“玻璃”就將它的材質(zhì)設(shè)為已經(jīng)編寫好的玻璃材質(zhì)即可,因此就不需要在Blender中提前為玻璃部分的模型設(shè)置材質(zhì),設(shè)置了也會(huì)被后續(xù)的代碼進(jìn)行材質(zhì)的覆蓋。
if (child.isMesh && child.name.includes("玻璃")) {
child.material = glassMaterial
}
?Blender導(dǎo)出glTF格式模型
在完成上述模型的搭建及材質(zhì)處理后,就需要將模型進(jìn)行導(dǎo)出,在導(dǎo)出的時(shí)候要注意要使用鼠標(biāo)將模型全選。
?點(diǎn)擊“文件”,然后點(diǎn)擊“導(dǎo)出”,選擇“glTF2.0”。
?點(diǎn)開右邊的“數(shù)據(jù)”,勾選“壓縮”即可。
這樣就足夠滿足學(xué)習(xí)的需要了,當(dāng)然,里面還有一些個(gè)性化的選擇,不過這就不在本文的討論范圍了。?
Three. js模型顯示場景的設(shè)置
你可能在第一次導(dǎo)入模型時(shí)候發(fā)現(xiàn),Three.js模型顯示全黑。
?這是由于你的場景中沒有光,于是你說要有光,你就在你的文件中添加了如下代碼:
scene.add(new THREE.AmbientLight(0x666666))
const light1 = new THREE.DirectionalLight(0xffffff, 1)
light1.position.set(0, 0, 10)
scene.add(light1)
const light2 = new THREE.DirectionalLight(0xffffff, 1)
light1.position.set(0, 0, -10)
scene.add(light2)
const light3 = new THREE.DirectionalLight(0xffffff, 1)
light1.position.set(10, 0, 0)
scene.add(light3)
const light4 = new THREE.DirectionalLight(0xffffff, 1)
light1.position.set(-10, 0, 0)
scene.add(light4)
這里你可以只寫其中一個(gè)或者兩個(gè)都寫上,這里只是給你提供了一種解決問題的最簡單方法。打光也是一門很有價(jià)值的課程,打光對(duì)模型的展示效果有很大的影響,其重要性不亞于調(diào)整材質(zhì)。
總結(jié)
最后感謝你的閱讀,這里本文所能提供的就像造房子的劣質(zhì)腳手架,當(dāng)你在造好房子后,就應(yīng)該把它拆掉,在它的基礎(chǔ)上繼續(xù)學(xué)習(xí),這樣才能收獲更多。如果你遇到了在本文中沒有出現(xiàn)的問題,歡迎評(píng)論或者私信我。
?
?
?
?
到了這里,關(guān)于Blender Three.js 智慧3D機(jī)房開發(fā) 模型創(chuàng)建與導(dǎo)入中的常見問題與解決方案的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!