王曉年, 宋夢(mèng)譞, 丁保青
(同濟(jì)大學(xué)a.電子與信息工程學(xué)院;b.計(jì)算機(jī)與信息技術(shù)國(guó)家級(jí)實(shí)驗(yàn)教學(xué)示范中心,上海 201804)
三維場(chǎng)景建模的目的是獲取物理世界的計(jì)算機(jī)描述,以便在其中實(shí)現(xiàn)各種仿真、測(cè)試和數(shù)字孿生等工作[1-3]。
圖像的三維場(chǎng)景建模[4]方法。可分為:通過提取圖像特征,根據(jù)相機(jī)運(yùn)動(dòng)結(jié)構(gòu)獲取三維信息;通過雙目或深度相機(jī)直接得到場(chǎng)景的深度。這兩類方法都可根據(jù)同步定位和地圖構(gòu)建相關(guān)算法獲得更為準(zhǔn)確的重構(gòu)結(jié)果[5]。理想的圖像建模擁有很高的真實(shí)感,重構(gòu)三維結(jié)果和語義對(duì)象有鴻溝,當(dāng)定位系統(tǒng)有誤差時(shí),所建構(gòu)的模型也存在偏差。
利用激光雷達(dá)生成的點(diǎn)云數(shù)據(jù)進(jìn)行三維場(chǎng)景重建的方法。激光器根據(jù)激光束發(fā)射的角度以及發(fā)射、接收的時(shí)間差能夠得到周圍環(huán)境的三維坐標(biāo)[6-7]。所探測(cè)到的三維點(diǎn)集合構(gòu)成點(diǎn)云數(shù)據(jù),得到周圍場(chǎng)景的模型。該方式具有精度高、不受光照影響等優(yōu)點(diǎn)。缺點(diǎn)是激光器價(jià)格昂貴,且所得點(diǎn)云較圖像過于稀疏,此外得到的三維數(shù)據(jù)中缺少色彩信息。
利用CAD[8-9]進(jìn)行建模的方法??色@得需要建模場(chǎng)景的平面數(shù)據(jù),再結(jié)合建筑物的外形特征和高度信息來進(jìn)行建模。CAD 能夠得到非常準(zhǔn)確的三維模型數(shù)據(jù)。數(shù)據(jù)的獲取和處理都具有很大的挑戰(zhàn),場(chǎng)景的規(guī)劃和建筑物以及裝飾的規(guī)劃屬于不同的部門,出于安全和知識(shí)產(chǎn)權(quán)的壁壘,通常難以獲??;如果對(duì)場(chǎng)景重新測(cè)量,那么測(cè)繪的工作量會(huì)非常大。
二維地理數(shù)據(jù)相較于三維模型數(shù)據(jù)更易獲取,使用二維地圖[10-11]信息實(shí)現(xiàn)三維場(chǎng)景的建??纱蟠蠼档徒5膹?fù)雜度和周期。即可根據(jù)二維地圖上的建筑物、河流、樹木和道路等幾何信息,借助于高度信息和紋理信息自動(dòng)實(shí)現(xiàn)三維建模工作,極大地提高建模效率。
本文將討論如何從二維地圖中導(dǎo)出數(shù)據(jù)以及各種對(duì)象的自動(dòng)生成方法,為三維場(chǎng)景的建模提供新的思路,以降低建模工作量。相較于Carla[12]仿真環(huán)境,本文方法可更好地適應(yīng)地圖信息的修改。區(qū)別于商業(yè)軟件CityEngine[2]和SketchUp[13]的建模方法,本文基于Unity3D[3]平臺(tái)和C#語言,利用免費(fèi)地圖軟件和開放平臺(tái)實(shí)現(xiàn)全自主、全自動(dòng)的三維建模流程和方法。平臺(tái)的開放性可為學(xué)生或科研工作者提供實(shí)驗(yàn)和仿真,所建模型可用于各種仿真環(huán)境,比如用于定位、用于規(guī)劃導(dǎo)航以及SLAM測(cè)試等。這一特點(diǎn)使得本文方法對(duì)新場(chǎng)景的構(gòu)建更方便簡(jiǎn)潔,且對(duì)場(chǎng)景或者道路的動(dòng)態(tài)變化更具適應(yīng)性。
OpenStreetMap[10,14]是一個(gè)免費(fèi)提供全球電子地圖的網(wǎng)站,以拓?fù)浣Y(jié)構(gòu)組織地圖數(shù)據(jù)。數(shù)據(jù)中包括空間數(shù)據(jù)和屬性數(shù)據(jù)。空間數(shù)據(jù)有3 種,分別是結(jié)點(diǎn)(Node)、路徑(Way)和關(guān)系(Relation),Node 和Way用于表示地圖中的點(diǎn)、線數(shù)據(jù);Way 是一個(gè)有序的Node序列,如果該序列首尾Node 相同,則表示區(qū)域,反之則對(duì)應(yīng)的是線段。Relation 把多個(gè)Node 和Way組織起來表示復(fù)雜的圖形。文中根據(jù)地圖數(shù)據(jù)構(gòu)造了MapNode類和MapWay 2 個(gè)類,用以組織所有的Node和Way,部分變量定義如下:
public class MapNode
{
public long id;
public double longitude,latitude;
public float x,y;
public Dictionary <string,string >tags;
public List <MapWay >ways;
……
};
MapNode類中的成員變量包括節(jié)點(diǎn)的id 值;結(jié)點(diǎn)的經(jīng)緯度坐標(biāo)longitude、latitude;結(jié)點(diǎn)的二維坐標(biāo)x、y;結(jié)點(diǎn)的標(biāo)簽值tags 和包括此節(jié)點(diǎn)的路徑的id 值的列表ways。
public class MapWay
{
public long id;
public List <long >nodeIds;
public List <MapNode >nodes;
public Dictionary <string,string >tags;
public List <MapWay >leadTos;
……
}
MapWay中的成員變量包括路徑的id 值;該路徑所包括結(jié)點(diǎn)的id值列表nodeIds;該路徑所包括結(jié)點(diǎn)的列表nodes;路徑的標(biāo)簽值tags以及與該路徑相連接的下一條路徑的列表leadTos。
讀取選定區(qū)域的地圖數(shù)據(jù),構(gòu)建一個(gè)以MapWay為數(shù)據(jù)類型的列表MapWayList,便于后續(xù)對(duì)象的遍歷和查找。MapWayList可以通過成員變量nodes訪問該路徑上的所有MapNode類型的節(jié)點(diǎn)。
游戲?qū)ο笫荱nity3D[11,15]中的基本載體,一個(gè)游戲?qū)ο笊峡梢栽黾佣鄠€(gè)組件,其中比較基礎(chǔ)的包括Transform、Mesh Filter 和Mesh Renderer 等組件,這些組件共同決定了物體呈現(xiàn)在虛擬場(chǎng)景中的樣子。Transform決定了物體在游戲界面中的位姿和尺度。Mesh Filter 決定展現(xiàn)哪一個(gè)Mesh。Mesh Renderer 決定以何種方式渲染Mesh,包括使用哪種材質(zhì)球、是否接受陰影和投影等,二者共同決定了物體的表現(xiàn)形式。Mesh至少包括頂點(diǎn)坐標(biāo)的集合以及三角形頂點(diǎn)索引序列。由于MapWayList 中都是區(qū)域或者路徑的屬性描述,在渲染前必須得到對(duì)象的Mesh 數(shù)據(jù),耳切法就是把多邊形分解為三角形的經(jīng)典方法[9]。
耳切法的基本思想是找出多邊形的耳朵點(diǎn),將其從頂點(diǎn)序列中移除。當(dāng)最后多邊形的頂點(diǎn)序列中只剩下3 個(gè)頂點(diǎn)時(shí),分解完成。圖1 中的陰影部分即為一個(gè)耳朵,其對(duì)應(yīng)頂點(diǎn)0 即為一個(gè)耳朵點(diǎn)。
圖1 多邊形的耳朵示例
為得到更合理的切分結(jié)果,在耳切法的基礎(chǔ)上進(jìn)行了如下處理:
(1)頂點(diǎn)序列預(yù)處理。Unity3D 中三角形頂點(diǎn)的索引順序會(huì)影響三角形呈現(xiàn)的方向。使用矢量叉乘的方法判斷多邊形頂點(diǎn)順序。先計(jì)算相鄰的3 個(gè)頂點(diǎn)構(gòu)成2 個(gè)矢量,2 個(gè)矢量叉乘結(jié)果的正、負(fù)代表序列點(diǎn)所指的方向,當(dāng)叉乘結(jié)果為正時(shí),采用順時(shí)針方向的頂點(diǎn)存儲(chǔ)方式;反之,對(duì)整個(gè)頂點(diǎn)索引序列逆序處理。
(2)凸點(diǎn)的確定。在分割三角形時(shí),耳朵點(diǎn)應(yīng)從凸點(diǎn)中選擇。判斷凸點(diǎn)的方法也采用叉乘檢測(cè)法,即定義凸點(diǎn)為相鄰3 個(gè)點(diǎn)構(gòu)成2 個(gè)矢量叉乘的方向?yàn)檎狞c(diǎn)。
(3)耳朵點(diǎn)移除順序的原則。如果移除耳朵點(diǎn)的順序選取不當(dāng),會(huì)導(dǎo)致多邊形的分割不合理,如圖2(a)所示。耳朵點(diǎn)采用逐層刪除原則,首先移除頂點(diǎn)的內(nèi)角接近90°的點(diǎn);如果有多個(gè)候選解時(shí),優(yōu)先移除可能構(gòu)成三角形內(nèi)角方差較小的那個(gè)頂點(diǎn)。同樣圖形,本文的分割結(jié)果如圖2(b)所示。
圖2 移除耳朵點(diǎn)不同順序?qū)Χ噙呅畏指畹挠绊?/p>
地圖中的元素,包括道路,河流和建筑等都用首尾相接的點(diǎn)和其他屬性描述。首尾相接的點(diǎn)構(gòu)成一個(gè)多邊形區(qū)域,通過上述耳切法可得三角形分割結(jié)果,實(shí)現(xiàn)紋理的貼圖。
建筑物是典型的三維物體,只有對(duì)每個(gè)墻面進(jìn)行渲染,才能展現(xiàn)出逼真的三維效果。遍歷MapWayList,如果tags包括“building”則表示物體為一幢建筑。建筑物高度由建筑物的層數(shù)和層高共同決定。其中層數(shù)可從地圖中建筑的標(biāo)簽讀出。對(duì)于缺失此數(shù)據(jù)的建筑,如果沒有人為設(shè)定則賦予隨機(jī)值,表現(xiàn)為某些建筑物的高度在每一次建模中都會(huì)不同。層高則預(yù)先設(shè)定為固定值。
建筑物的頂面形狀就是地圖中的封閉區(qū)域,由按照逆時(shí)針順序存儲(chǔ)的頂點(diǎn)構(gòu)成;每個(gè)面墻則通過給邊加上高度后形成。墻面部分直接影響重建的視覺效果,由于建筑物每個(gè)面形狀和高度各異,給貼圖帶來一些挑戰(zhàn)。表面貼圖的素材和實(shí)際場(chǎng)景越接近,構(gòu)建的三維場(chǎng)景越真實(shí),真實(shí)的貼圖需要采集和標(biāo)定建筑物不同角度的照片。為讓虛擬建筑物看起來更具多樣性,建筑物的表面采用多種圖片構(gòu)成的紋理庫(kù)作為素材。貼圖時(shí)遵循如下兩個(gè)原則:
(1)宏觀和微觀紋理并存。將圖片中重復(fù)出現(xiàn)的部分視作一個(gè)微觀紋理單元,如圖3 中紅色方框部分所示,該單元對(duì)應(yīng)一層樓的高度和一扇窗戶的寬度。為提高效率,同時(shí)保存宏觀單元,如圖3 中整體紋理所示。貼圖時(shí),可使用多個(gè)微觀單元鋪滿整個(gè)墻面,則貼滿如圖所示墻面需要貼圖10 ×5 次,而宏觀單元僅需一次。
圖3 貼圖實(shí)例
(2)自動(dòng)匹配加人為指定。用戶可指定某個(gè)墻面使用的紋理序號(hào),否則程序自動(dòng)從墻面紋理圖庫(kù)中尋找最適合的紋理圖片,選擇次序如下:首先根據(jù)建筑物層數(shù)和宏觀紋理中的層數(shù)做最優(yōu)匹配,當(dāng)存在多個(gè)選擇時(shí)優(yōu)先選擇寬度更匹配的紋理,如果依然有多個(gè)候選紋理則由程序隨機(jī)決定。貼圖時(shí)對(duì)于不能完全覆蓋的情形,則在宏觀紋理圖像適度變形的前提下用微觀紋理進(jìn)行補(bǔ)充。
地圖文件中沒有地形數(shù)據(jù),但當(dāng)tags 包括“natural”并且標(biāo)簽的value 值為“water”時(shí),表示此物體為一條河流;當(dāng)標(biāo)簽包含“l(fā)anduse”且該標(biāo)簽value值為“grass”時(shí),此數(shù)據(jù)為一片綠地。
道路是相對(duì)標(biāo)準(zhǔn)區(qū)域,正常道路可根據(jù)車道數(shù)、屬性以及道路寬度動(dòng)態(tài)實(shí)現(xiàn)貼圖。對(duì)特殊區(qū)域,比如Y型路口或者環(huán)島等可先三角化然后再貼圖。地圖中沒有指示草地和河流的高度,需要在生成平面的基礎(chǔ)上根據(jù)屬性進(jìn)行調(diào)整。通過將降低位于河流內(nèi)頂點(diǎn)的高度,形成下陷的地形。類似,也可抬高草地區(qū)域內(nèi)每個(gè)頂點(diǎn)的高度形成草地。通過這種方法得到河床的地面如圖4(a)所示。如果現(xiàn)實(shí)中的河床比較平緩,可將所有頂點(diǎn)坐標(biāo)進(jìn)行拉普拉斯平滑處理,經(jīng)過平滑處理后的河床如圖4(b)所示。
圖4 有河床的地形網(wǎng)格
草地的貼圖方法與河流相同。通過法線貼圖,使物體表面呈凹凸不平的逼真效果,貼圖后的河流和草地如圖5 所示。
地圖上沒有標(biāo)記的交通燈,可人為修改地圖。程序也可在道路的交叉處加上偏移后設(shè)定交通燈位置。對(duì)于三維環(huán)境重構(gòu)而言,道路兩旁的行道樹是必不可少的部分。行道樹在地圖中沒有標(biāo)記,人為添加工作量太大。采取如下方法:遍歷MapWayList中的每條數(shù)據(jù),當(dāng)某條數(shù)據(jù)的標(biāo)簽包含“highway”且該標(biāo)簽的value值為“service”時(shí),即對(duì)應(yīng)一條道路,根據(jù)道路的數(shù)據(jù)便可進(jìn)行樹木模型的擺放。
行道樹設(shè)定算法的原則:
(1)同一條id的道路選用一種樹形。
(2)車行道一般會(huì)有2 個(gè)方向,如將每條路的兩側(cè)均放置行道樹,會(huì)造成2 條路中間樹木的重疊和冗余,在本文中只在道路前進(jìn)方向的右側(cè)放置行道樹。
(3)行道樹之間的間隔可改變,可人為設(shè)定。
用上述方法為每條道路計(jì)算出行道樹的位置,隨機(jī)從多個(gè)樹木素材中選出一種放置選取的樹木即完成行道樹的擺放。一條道路的路面紋理和行道樹放置后如圖6 所示。
圖6 路面和行道樹
從OpenStreetMap網(wǎng)站導(dǎo)出某校區(qū)公開的地圖文件,各圖層合并后如圖7 所示。用文中方法自動(dòng)構(gòu)建的部分三維場(chǎng)景如圖8 所示。
圖7 某校區(qū)公開地圖
圖8 自動(dòng)建模的部分場(chǎng)景
本文自動(dòng)建模的方法可即刻根據(jù)OpenStreetMap數(shù)據(jù)構(gòu)建三維場(chǎng)景,并在更換OpenStreetMap數(shù)據(jù)為其他地區(qū)后仍然適用。此方法為測(cè)試系統(tǒng)進(jìn)行場(chǎng)景建??蛇_(dá)到快速適應(yīng)場(chǎng)景變換的效果,也可據(jù)此動(dòng)態(tài)紋理環(huán)境實(shí)現(xiàn)豐富的數(shù)據(jù)信息生成等。所自動(dòng)構(gòu)建的三維場(chǎng)景被大學(xué)生綜合設(shè)計(jì)與實(shí)踐選為基礎(chǔ)平臺(tái)使用,基于此實(shí)現(xiàn)模擬“滴滴”叫車服務(wù),完成路徑規(guī)劃以及實(shí)驗(yàn)仿真。后續(xù)工作中可加入更多智能非玩家角色,使得構(gòu)建環(huán)境具備更廣泛的應(yīng)用場(chǎng)景。