摘 要: WebGL標(biāo)準(zhǔn)的推出加速了Web3D時(shí)代的到來(lái),在Web3D項(xiàng)目中,三維模型的生成與處理是一個(gè)最核心的問(wèn)題。利用three.js引擎,介紹了Web環(huán)境下的數(shù)據(jù)驅(qū)動(dòng)建模、靜態(tài)三維模型的導(dǎo)入與處理、動(dòng)態(tài)三維模型的導(dǎo)入與解析問(wèn)題。實(shí)驗(yàn)結(jié)果表明:基于WebGL平臺(tái)和three.js引擎的Web3D技術(shù),能夠有效地實(shí)施數(shù)據(jù)可視化,實(shí)現(xiàn)了基于數(shù)據(jù)庫(kù)的參數(shù)化建模,同時(shí)也能兼容大多數(shù)的工業(yè)三維模型,可以支撐完整的Web3D項(xiàng)目。
關(guān)鍵詞: HTML5; WebGL; three.js; 三維模型; 數(shù)據(jù)驅(qū)動(dòng)
中圖分類號(hào): TN710?34; TP391.9 文獻(xiàn)標(biāo)識(shí)碼: A 文章編號(hào): 1004?373X(2015)24?0083?04
Web?oriented 3D model generation and processing technology
ZHENG Hua1, SU Jingfang2
(1. Shijiazhuang Institute of Railway Technology, Shijiazhuang 050061, China; 2. Hebei University of Science and Technology, Shijiazhuang 050018, China)
Abstract: The introduction of WebGL standards accelerated the arrival of the Web3D era. The generation and processing of 3D model is the core in Web3D project. On the basis of the three.js engine, the data drive modeling, importing and processing of static 3D model, and importing and analysis of dynamic 3D model in the Web environment are introduced. The experimental results show that the Web3D technology based on WebGL platform and three.js engine can not only effectively achieve the data visualization and the database?oriented parametric modeling, but also has compatibleness with most of the industrial 3D models and support the whole Web3D project.
Keywords: HTML5; WebGL; three.js; 3D model; data drive
0 引 言
Web自20世紀(jì)90年代初誕生以來(lái),經(jīng)過(guò)20多年的發(fā)展,現(xiàn)在已經(jīng)成為Internet上最重要、最普及的應(yīng)用,從HTML 1.0到2.0,3.0,4.0,XHTML以及現(xiàn)在的HTML 5.0,但至今為止,主流的Web頁(yè)面仍然是二維的,隨著3D技術(shù)的日益普及,下一代Web技術(shù)正朝著3D方向發(fā)展。2013年5月,HTML 5.1正式草案公布,新增了Canvas標(biāo)記,通過(guò)WebGL,允許瀏覽器直接在上面繪制矢量圖形,目前HTML 5和Canvas 2D規(guī)范的制定已經(jīng)完成。three.js是由JavaScript編寫的WebGL第三方庫(kù),是一款運(yùn)行在瀏覽器中的3D引擎,可以用它在Web中創(chuàng)建各種三維場(chǎng)景,比如3D對(duì)象、攝影機(jī)、光、影、紋理、材質(zhì)、動(dòng)畫等。與傳統(tǒng)的Web3D技術(shù)(如Flash3D、Unity3D、Silverlight等)相比,three.js的優(yōu)勢(shì)在于它不需要在瀏覽器中安裝插件,用戶可以通過(guò)JavaScript直接控制Web頁(yè)面上的3D場(chǎng)景,不足之處在于它需要瀏覽器支持WebGL,到目前為止,火狐、谷歌等瀏覽器都支持WebGL,但微軟的IE瀏覽器要11.0以后的版本才支持。
現(xiàn)在,主流的Web仍然是二維的,文本、圖片、聲音、視頻仍然是Web的主要內(nèi)容。通過(guò)與傳統(tǒng)的Web技術(shù)相結(jié)合,three.js可以將二維數(shù)據(jù)以三維方式呈現(xiàn)出來(lái),3D場(chǎng)景漫游將成為Web的主要內(nèi)容,這對(duì)Web的影響是革命性的,本文重點(diǎn)探討基于three.js引擎的各類三維模型的生成與處理技術(shù)。
1 數(shù)據(jù)驅(qū)動(dòng)的三維建模
3D建模是構(gòu)建三維場(chǎng)景的一個(gè)基本問(wèn)題,一般的方法是先建模,然后渲染,最后輸出成某種特定格式的模型或動(dòng)畫。當(dāng)模型有變化時(shí),必須重復(fù)執(zhí)行上述步驟,也就是說(shuō),渲染結(jié)果一旦輸出,就不可修改,無(wú)法實(shí)現(xiàn)實(shí)時(shí)變化。
Web的后臺(tái)主要是數(shù)據(jù),3D只是一種數(shù)據(jù)呈現(xiàn)方式,通過(guò)后臺(tái)的數(shù)據(jù)驅(qū)動(dòng)前臺(tái)的3D場(chǎng)景和動(dòng)畫,即是數(shù)據(jù)驅(qū)動(dòng)的三維建模,其意義在于通過(guò)修改后臺(tái)的數(shù)據(jù),即可觸發(fā)前臺(tái)3D場(chǎng)景的變化。
1.1 數(shù)據(jù)驅(qū)動(dòng)建模的基本原理
與一般的建模不同,Web上的建模涉及帶寬問(wèn)題,模型數(shù)據(jù)需要先從Web服務(wù)器傳輸?shù)娇蛻魴C(jī)上,然后才能進(jìn)行渲染,因此,模型本身不能太大,否則容易引起網(wǎng)頁(yè)不響應(yīng);另外,由于Web是實(shí)時(shí)交互的,因此,模型數(shù)據(jù)要在后臺(tái)以異步方式完成傳輸,如AJAX;由于three.js是基于JavaScript的,模型數(shù)據(jù)的格式最好能與之匹配,如JSON。
綜上所述,Web3D建模過(guò)程的一種合理方式是:先通過(guò)Web服務(wù)器端的技術(shù)(如Asp,Java等)將后臺(tái)數(shù)據(jù)格式轉(zhuǎn)化成JSON格式,再以AJAX的方式將數(shù)據(jù)送往客戶端,然后利用JavaScript調(diào)用three.js中相應(yīng)的API,將數(shù)據(jù)以三維的方式顯示出來(lái),其原理如圖1所示。
圖1 數(shù)據(jù)驅(qū)動(dòng)的三維建模原理圖
1.2 數(shù)據(jù)驅(qū)動(dòng)建模案例
下面的例子展示了一個(gè)基于Access數(shù)據(jù)庫(kù)的數(shù)據(jù)(見圖2)驅(qū)動(dòng)的三維動(dòng)畫,描繪了太陽(yáng)及其鄰近的六大行星的運(yùn)轉(zhuǎn)情況,通過(guò)修改后臺(tái)數(shù)據(jù),可觸發(fā)前臺(tái)頁(yè)面3D場(chǎng)景的實(shí)時(shí)變化,如圖3所示。
圖2 簡(jiǎn)單三維模型數(shù)據(jù)
如圖2所示數(shù)據(jù)定義了模型(各星球)的形狀(球形)、大?。ò霃剑?、坐標(biāo)(距離太陽(yáng)的距離)、外觀(貼圖文件)、運(yùn)動(dòng)方式(自傳和公轉(zhuǎn)的速度及方向)等基本屬性,是一種很普通的關(guān)系數(shù)據(jù)。
在向?yàn)g覽器端傳輸這些數(shù)據(jù)時(shí),為減少數(shù)據(jù)轉(zhuǎn)換的工作,一般采用JSON格式(和JavaScript天然適應(yīng))。另外,由于瀏覽器在渲染三維動(dòng)畫時(shí)比較消耗資源,一般采用AJAX異步通信方式(幾乎所有的瀏覽器都支持)。
接下來(lái)調(diào)用three.js中的SphereGeometry(球體)函數(shù)顯示這些星球即可。最后,為提高Web的交互性,可以加上3D聲音和場(chǎng)景控制(如第一人稱視角)。
圖3 數(shù)據(jù)驅(qū)動(dòng)的Web3D動(dòng)畫效果圖
幾個(gè)關(guān)鍵步驟的代碼如下:
(1) 將模型數(shù)據(jù)格式化成JSON格式
//???Getmodels.asp
<%
sql=\"SELECT * FROM 星球 order by id\"
set conn = Server.CreateObject(\"ADODB.Connection\")
conn_str=\"DBQ=\"+server.mappath(\"star.mdb\")+\";driver={Microsoft Access Driver (*.mdb)};\"
Conn.Open conn_str
set rs=Server.CreateObject(\"ADODB.recordset\")
rs.Open sql,conn
str=\" {star:[\"
do until rs.EOF
str=str \"{\"
for each x in rs.Fields
str=str \"′\" x.name \"′:′\" x.value \"′,\"
next
str= left(str,len(str)?1) +\"},\"
rs.MoveNext
loop
str= left(str,len(str)?1) +\"]}\"
response.write(str)
%>
(2) 通過(guò)AJAX獲取模型數(shù)據(jù)
var obj;
function getstarpara(){
var xmlhttp;
if (window.XMLHttpRequest){xmlhttp=new XMLHttpRequest();}// code for IE7+, Firefox, Chrome, Opera, Safari
else{xmlhttp=new ActiveXObject(\"Microsoft.XMLHTTP\")};// code for IE6
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4 xmlhttp.status==200){
var txt=xmlhttp.responseText;
obj = eval (\"(\" + txt + \")\");
}
}
xmlhttp.open(\"GET\",\"getmodels.asp?k=\"+Math.random(),true);
xmlhttp.send();
}
(3) 通過(guò)three.js引擎生成3D模型
var sun;
var texture = new THREE.MeshPhongMaterial({map: THREE.ImageUtils.loadTexture(′images/′+obj.star[0].tietuwenjian),emissive:0xffffff});
sun = new THREE.Mesh(new THREE.SphereGeometry(Number(obj.star[0].banjing),20,20)) ,texture);
scene.add(sun);
sun.position.set(Number(obj.star[0].juli),0,0);
該方法的局限性在于他只能表示一些基本的、規(guī)則的三維模型,如立方體、球體、錐體等,模型本身所需要的數(shù)據(jù)很少,而且可以方便地通過(guò)關(guān)系數(shù)據(jù)庫(kù)存儲(chǔ),因此,在實(shí)踐中有一定的局限性。
現(xiàn)實(shí)中各類工業(yè)模型一般會(huì)復(fù)雜得多,而且很難直接通過(guò)數(shù)學(xué)函數(shù)來(lái)表達(dá),而且他們一般都使用某種專門的工具建立,具有某種特殊的格式,如Autodesk 3DS Max下的.3ds,Wavefront下的.obj等。
2 復(fù)雜靜態(tài)三維模型的導(dǎo)入及處理
一個(gè)典型的靜態(tài)三維模型中包含了幾何體頂點(diǎn)、貼圖坐標(biāo)點(diǎn)、頂點(diǎn)法線、線、面、曲線、曲面等信息,將這些數(shù)據(jù)以關(guān)系數(shù)據(jù)庫(kù)的方式存儲(chǔ)是不太現(xiàn)實(shí)的,因?yàn)閿?shù)據(jù)量太大且難以控制。更好的處理方式是直接在建模工具中將模型建立好,然后輸出成特定格式的模型文件,直接在Web3D中加以利用。這就涉及到三維模型的導(dǎo)入及處理問(wèn)題。
由于沒(méi)有一個(gè)統(tǒng)一標(biāo)準(zhǔn),過(guò)去用于工業(yè)建模設(shè)計(jì)上的交換格式,例如Autodesk 3DS Max下的.3ds和Wavefront軟件下的.obj,現(xiàn)在成為了最具代表性的兩種主流靜態(tài)模型格式。其中.obj格式由于沒(méi)有專利限制,使用文本存儲(chǔ),而被大家廣泛采納。
Three.js中的OBJLoader()和OBJMTLLoader()類專門用于導(dǎo)入和處理obj格式的模型,下面的代碼導(dǎo)入了一個(gè)挖掘機(jī)的靜態(tài)模型,如圖4所示。首先在建模工具中建立好模型,然后輸出成.obj格式,假設(shè)模型文件命名為“wjj.obj”,導(dǎo)入模型的關(guān)鍵代碼如下:
var obj=′model_obj/wjj.obj′; //模型文件
var mtl=′model_obj/wjj.mtl′; //貼圖文件
var loader = new THREE.OBJMTLLoader();
loader.load(obj,mtl,function(object){
object.position.set(0,0,0);
scene.add( object );
} );
圖4 靜態(tài)模型的導(dǎo)入
靜態(tài)模型本身是靜止的,程序能做的事情只能是改變他的坐標(biāo)位置、旋轉(zhuǎn)角度和顯示比例,通過(guò)改變這些參數(shù),也可以實(shí)現(xiàn)三維動(dòng)畫效果(參考第一個(gè)例子)。
3 復(fù)雜動(dòng)態(tài)三維模型的導(dǎo)入及處理
一個(gè)典型的動(dòng)態(tài)三維模型中包含了頂點(diǎn)、紋理、骨骼、蒙皮、動(dòng)畫等信息,與靜態(tài)模型相比,動(dòng)態(tài)模型需要存儲(chǔ)的信息更多,控制也更復(fù)雜,因此也更加適合用導(dǎo)入的方式來(lái)處理和使用。
隨著硬件和技術(shù)的發(fā)展,三維建模逐漸從靜態(tài)模型向“幀動(dòng)畫”和“骨骼動(dòng)畫”發(fā)展,ID Tech下的.md,Autodesk下的.fbx,以及非盈利性組織Khronos負(fù)責(zé)維護(hù)的.dae格式成為了主流的動(dòng)態(tài)模型格式。各種模型格式之間可以通過(guò)插件互相轉(zhuǎn)換,因此對(duì)于Web開發(fā)者來(lái)說(shuō),并不需要完全弄清每種模型的詳細(xì)格式,選擇當(dāng)前最為流行的一種格式即可。
Dae格式由于其開放性而成為目前應(yīng)用最普遍的一種動(dòng)態(tài)三維模型格式,他使用XML格式存儲(chǔ),結(jié)構(gòu)靈活,運(yùn)用自由度很高,圖5展示了一個(gè)典型的dae文件結(jié)構(gòu)。
圖5 一個(gè)典型的dae文件
對(duì)于動(dòng)態(tài)模型來(lái)說(shuō),將其導(dǎo)入到三維場(chǎng)景的方法和靜態(tài)模型是基本相同的,但動(dòng)畫部分需要程序員通過(guò)JavaScript來(lái)控制,這是難點(diǎn)所在。
Three.js中的ColladaLoader()類專門用于導(dǎo)入和處理dae格式的模型,下面的代碼展示了一個(gè)頂點(diǎn)變形動(dòng)畫模型在導(dǎo)入和處理過(guò)程中的關(guān)鍵代碼:
var md=\"model_dae/wjj.dae\";
var loader = new THREE.ColladaLoader();
loader.load(md, function ( collada ) {
dae = collada.scene;
skin = collada.skins[ 0 ];
dae.position.set(0,0,0);
animate();
} );
function animate() {
var delta = clock.getDelta();
if ( t > 1 ) t = 0;
if ( skin ) {
for ( var i = 0; i < skin.morphTargetInfluences.length; i++ ) {
skin.morphTargetInfluences[i]=0;
}
skin.morphTargetInfluences[Math.floor(t*30)]=1;
t += delta;
}
requestAnimationFrame( animate );
}
在Web3D中,動(dòng)態(tài)模型一般是循環(huán)播放的,three.js通過(guò)requestAnimationFrame函數(shù)實(shí)現(xiàn)動(dòng)畫效果,它很類似于setTimeOut函數(shù),但又略有區(qū)別,一是當(dāng)標(biāo)簽頁(yè)失去焦點(diǎn)時(shí),它就不再運(yùn)行了,二是該函數(shù)目前還是依賴于瀏覽器的,以后可能還有變化。
4 其他三維模型的導(dǎo)入及處理
其他常見的3D模型格式還有:vtk,wrl,utf8,stl,ply,JSON等,這些模型中的大多數(shù)three.js都提供了相應(yīng)的接口,如:CTMLoader,PLYLoade,BinaryLoader,VTKLoader,STLLoader,UTF8Loader,VRMLLoader等,在處理方法上與obj或dae格式大同小異。
5 結(jié) 語(yǔ)
至此,完成了數(shù)據(jù)驅(qū)動(dòng)的三維模型、復(fù)雜的靜態(tài)三維模型和復(fù)雜的動(dòng)態(tài)三維模型的處理工作,大多數(shù)情況下,這三種模型能夠支持一個(gè)完整的3D場(chǎng)景了。與普通的視頻不同,在Web3D中,由于所有的動(dòng)畫都是實(shí)時(shí)渲染的,對(duì)CPU和GPU資源的消耗很嚴(yán)重,對(duì)于大型的3D場(chǎng)景,要有一定的優(yōu)化措施。
(1) 渲染效率問(wèn)題
筆者曾做過(guò)實(shí)驗(yàn),在3D場(chǎng)景中加入一個(gè)半徑為2 000的球體,如果加上燈光和陰影,在一臺(tái)普通PC機(jī)上需要近2 min的時(shí)間才能渲染出來(lái)(FireFox瀏覽器),如果再加上動(dòng)畫,網(wǎng)頁(yè)基本處于“未響應(yīng)”狀態(tài)。造成這種情況的根源在于three.js是以三角形為基礎(chǔ)來(lái)構(gòu)建3D模型的,在一個(gè)半徑為2 000的球體平面上會(huì)有大量的三角形,他們都需要獨(dú)立渲染。因此,在進(jìn)行Web3D開發(fā)時(shí),應(yīng)盡量減少使用弧面模型,如果必須使用,則應(yīng)盡量縮小其尺寸。
(2) 碰撞檢測(cè)問(wèn)題
Three.js沒(méi)有提供碰撞檢測(cè)機(jī)制,即在改變模型的坐標(biāo)時(shí),會(huì)出現(xiàn)一個(gè)模型進(jìn)入另一個(gè)模型內(nèi)部的問(wèn)題,這部分工作需要開發(fā)者自己編程解決,一種簡(jiǎn)單的算法是AABB算法,即沿坐標(biāo)軸方向的包圍盒算法。
參考文獻(xiàn)
[1] 譚文文,丁世勇,李桂英.基于WebGL和HTML5的網(wǎng)頁(yè)3D動(dòng)畫的設(shè)計(jì)與實(shí)現(xiàn)[J].電腦知識(shí)與技術(shù),2011(28):6981?6983.
[2] 蘇雪.基于WebGL標(biāo)準(zhǔn)的家庭娛樂(lè)終端上Web3D渲染的實(shí)現(xiàn)[J].長(zhǎng)江大學(xué)學(xué)報(bào):自然科學(xué)版,2011(12):102?104.
[3] 劉愛(ài)華,韓勇,張小壘,等.基于WebGL技術(shù)的網(wǎng)絡(luò)三維可視化研究與實(shí)現(xiàn)[J].地理空間信息,2012(5):79?81.
[4] 殷周平,吳勇.基于WebGL和AJAX的Web3D應(yīng)用研究:以在線3D協(xié)作交互式設(shè)計(jì)為例[J].安慶師范學(xué)院學(xué)報(bào):自然科學(xué)版,2013(1):58?61.
[5] 霍冬,鄭偉華,盛步云.基于WebGL的機(jī)械產(chǎn)品三維展示技術(shù)研究[J].制造業(yè)自動(dòng)化,2013(18):73?77.
[6] 方路平,李國(guó)鵬,洪文杰,等.基于WebGL的醫(yī)學(xué)圖像三維可視化研究[J].計(jì)算機(jī)系統(tǒng)應(yīng)用,2013(9):25?30.
[7] 韓義.Web3D及Web三維可視化新發(fā)展:以WebGL和O3D為例[J].科技廣場(chǎng),2010(5):81?86.
[8] 方強(qiáng).基于WebGL的3D圖形引擎研究與實(shí)現(xiàn)[D].合肥:安徽大學(xué),2013.
[9] 張麗媛,蘇永生,蘆志強(qiáng).基于WebGL和有限元的碼頭三維設(shè)計(jì)與計(jì)算仿真[J].水運(yùn)工程,2013(12):57?63.