[程式] Import RealWorld Landscape to UE4

作者: yekdniw (yekdniw)   2020-07-01 12:20:42
網頁版
https://yekdniwue.blogspot.com/2020/06/import-realworld-landscape-toue4.html
簡介
從真實世界地形資料匯入遊戲引擎是蠻常見的需求,
這次剛好有機會在UE4試試看這個功能,
沒想到遇到地形交界處接不起來的問題,
最後找到問題點,所以順便分享作法。
https://www.youtube.com/watch?v=_9ob8FcnYY4
本篇文章使用的流程。
不過過程中有遇到問題,所以寫了這篇文章想要補充不足之處。
以下是簡化版的流程:
下載地形資料並轉換為引擎可匯入的heightmap png檔。
1. 到https://viewer.nationalmap.gov/basic/下載地形資料
2. 到https://github.com/MacroPolo/real-terrain下載python script
3. 解壓縮地形資料檔,放到real-terrain的input資料夾內
4. 如果電腦沒安裝python,安裝python
5. 在命令列輸入python real-terrain.py [檔案名稱].img (註1.)
6. real-terrain的output資料夾內就會有輸出好的png檔。
在UE4匯入地形檔:
1. 創一個新地圖,WorldSettings設定Enable World Composition為true
2. Levels->Create New,產生新的子地圖
3. Models->Landscape->Manage->New Landscape->ImportFromFile
4. Heightmap File選擇前一個步驟6輸出好的png檔
5. 地形匯入完成。
6. 在World Composition視窗調整地圖到想要的位置。
以上是基本流程,不包含太多的細節,一些介面是從哪邊叫出來的就請參考影片。
在我的實驗中,用上面的流程匯入一塊地形檔是不會有任何問題的。
但是當我匯入兩塊地形檔放進UE4後,發現兩塊地形接不上,有嚴重的高低差問題。
修正地形接縫問題
經過一番追查,最後我找到幾個項目要特別處理,才能把地形接起來。
1. 最大高度要一致。
2. height map解析度要符合引擎的規範。
最大高度要一致
以我的範例來說,我有兩張地圖檔49_361跟49_362。
在使用real-terrain轉換的過程,會顯示這個地形檔的最小高度與最大高度
舉例來說
這是49_361的結果
>>> Extracting elevation information from input DEM.
Minimum elevation: 0m
Maximum elevation: 180m
Elevation range: 180m
這是49_362的結果
>>> Extracting elevation information from input DEM.
Minimum elevation: 0m
Maximum elevation: 154m
Elevation range: 154m
real-terrain會將地形最小高度與最大高度normalize為uint16,值域是0到65535,
所以兩張地形分開處理的話,
49_361轉出來的最大值是180m高,49_362轉出來的最大值只有154m,但是值都是65535。
為了解決這個問題,代表在匯入地形的時候,
需要找到所有匯入的地形檔的最大高度與最低高度。
然後用整體最大/最低高度作為基準餐數,提供所有地形檔轉換。
以上面的範例,最低高度就是0m,最大高度就是180m。
強制所有地形檔以預先算好的最高/最低值做轉換
這部份要修改一下python程式碼
使用任何文字編輯器開啟real-terrain.py
找到_find_elevation_range(self):內

self.min_elevation = blabla
self.max_elevation = blabla
改為
self.min_elevation = '0'
self.max_elevation = '180'
然後重新用real-terrain.py轉換地形檔就可以得到相同值域的height map。
Height map解析度要符合引擎的規範
做了上面的步驟,我以為地形要能接上了,結果如下圖1與圖2,
依然沒有接上,觀察了一陣子覺得應該不是高低差問題,而是整個接縫處本來就不連續。
但是原始height map的png檔又是接得起來的(用繪圖軟體將拼起來看)。
所以初步把問題排除是real-terrain產生的圖有問題,將問題範圍限縮到UE4。
圖1. Gap between landscapes without normalize height. (Top view)
圖2. Gap between landscapes without normalize height. (Side view)
後來在搜尋的過程中找到這個頁面
https://docs.unrealengine.com/en-US/Engine/Landscape/TechnicalGuide/index.html#recommendedlandscapesizes
裡面有描述到UE4對height map的圖片是有規範的。
而我從real-terrain輸出的原圖大小是10012*10012,
明顯比UE4最大的8129*8129還要大。
所幸real-terrain也支援圖片的縮放,
所以只要將執行指令改為
python real-terrain.py -s 8129 [檔案名稱].img
就可以了。
在輸出的output資料夾就會多一個_scaled.png檔。
使用這個png檔在UE4匯入後,接縫處終於正常了。如圖3.與圖4.
圖3. Almost no gap after adjust. (Top view)
圖4. Almost no gap after adjust. (Side view)
使用real-terrain輸出多個tile map
我本來的問題其實在前面就結束了,不過有覺得地形有點太大張想要細切。
又看到UE4好像有另一個可以import tiled map的介面,
於是繼續試試看能不能把兩個大地形檔再細切。
這部份其實還是著重在延伸real-terrain的程式。
利用real-terrain輸出tile map
首先先學習如何利用real-terrain輸出tile maps。
一樣要注意UE4的height map圖片規範,這裡就以每個tile是2017*2017為範例。
python real-terrain.py -t 2017 [檔案名稱].img
基本上這個指令就會把地形檔以2017*2017為單位進行分割。
但是可惜的是,原圖10012以2017是沒辦法整除的。最後會留下1944*2017的非正方形圖。
所以我們要先把原圖縮放到2017的倍數,再進行分割。
先縮放再分割
這部份也需要修改python程式碼,因為real-terrain在分割的時候只吃原始圖檔。
現在我們需要先縮放,再對縮放的結果分割。
找到函式_generate_tile(self)的段落,裡面的
img = Image.open(self.output_full)
改成
img = Image.open(self.output_scale)
然後在命令列輸入
python real-terrain.py -s 8068 -t 2017 [檔案名稱].img
就能產生出各個tiled maps。
到UE4的Levels->Import Tiled Landscape選擇剛才所有輸出的tiled png檔。
如圖所示
圖5. Import tiled Landscape from Levels.
會發現UE4除了圖片規範之外,批次匯入tile maps還有命名規則。
如圖所示,命名規則是[檔案名稱]_X[數字]_Y[數字]
圖6. Name rule when import tiled landscape.
符合Import TileMap命名規範
所以回到real-terrain.py,
找到函式_generate_tile(self)的段落,把裡面的
img_slice.save(self.output_tile + "_heightmap_tile_{}-{}.png".format(x, y))
改成
img_slice.save(self.output_tile + "_heightmap_tile_X{}_Y{}.png".format(x, y))
輸出來的圖片應該就是正確的了。
以上就是整個從真實地形檔匯入UE4所遇到的各個問題與解決過程。
簡單列一下重點就是:
1. png檔大小要符合UE4規範
2. 所有地形檔在匯出png的時候要用統一的最大高度/最小高度。
3. 為了達到這個目的,修改real-terrain是必要的。
4. 簡單的方法就是算好最大/最小高度後硬寫在程式碼內,
5. 如果需要更正式的製程的話可能就要修改更多程式碼。
6. 或是使用付費的工具World Machine、World Creator來作。
7. 如果要輸出tiled maps,要修改tile的輸入是scaled的image,
也要修改輸出的命名規則。
註1.
如果跳以下錯誤訊息
ModuleNotFoundError: No module named 'PIL'
可以輸入pip install Pillow 安裝
如果還是跳錯
輸入Python pip install Pillow
參考資料
https://www.youtube.com/watch?v=_9ob8FcnYY4
本篇文章使用的流程。
不過過程中有遇到問題,所以寫了這篇文章想要補充不足之處。
https://viewer.nationalmap.gov/basic/
USGS的下載處,提供多種精細度的資料下載。
https://github.com/MacroPolo/real-terrain
將USGS的地形資料轉換成16 bit PNG heightmap的python程式
支援IMG, ArcGrid以及GeoTIFF檔
也支援圖檔的scale,或是將整個大地圖細切為多個tile。
python程式本身也寫得簡單易懂。
用這支程式可以取代GlobalMapper的部分功能。
https://terraformpro.com/tutorials/
有非常詳細而且完整的產生真實世界地形的圖文說明
裡面的範例還包含地形材質的匯入,鐵道,道路、河流等等的匯入
唯一的可惜之處就是使用了幾個付費軟體
包含GlobalMapper (處理地形資料)與
UE4的plugin Procedural Landscape Ecosystem
鐵道、道路、河流等Vector的匯入仰賴GlobalMapper之外,
也要用該Blog自己寫的plugin匯入進UE4
但是這個Plugin好像只維護到4.19
https://docs.unrealengine.com/en-US/Engine/Landscape/TechnicalGuide/index.html
Unreal對landscape的基本說明。
裡面最重要的就是Recommended Landscape Sizes了,
不管是要用Import TiledLandscape,還是直接Import landscape。
height map都要照這裡面的規範製作。否則會錯誤或是直接無法匯入。
https://www.youtube.com/watch?v=K41WMgJUFEk
使用OpenTopography(地形資料)加上L3DT(heightmap處理),
匯入真實地形到UE4的影片教學。
本篇文章沒有使用到這個流程,不過要拿US以外的地形資料可能要參考這個流程。
作者: sampp1213205 (佛朗Sam哥)   2020-07-01 13:42:00
推一個
作者: Lhmstu (lhmstu)   2020-07-01 14:45:00
推個
作者: biosphere (別)   2020-07-01 22:57:00
推推
作者: coolrobin (泳圈)   2020-07-01 23:56:00
未看先推
作者: rickkcir (多果汁)   2020-07-03 10:48:00

Links booklink

Contact Us: admin [ a t ] ucptt.com