曲線的生成算法實現_PCGPlanet1-地形生成算法簡介

2a65bb71897d0a6110e36d5e1fc4d3e1.png

比較常用的地形生成算法有三種:

四叉樹算法,GeoMipmap算法,移動立方體算法

目前市面游戲采用的方案基本都是以這三種算法為基礎實現的,下面依次進行介紹

四叉樹算法

很經典的算法,在沒有GPU的時代就已經出現了,原始算法是純cpu的實現,不過在現在已經可以將其實現為GPU-Driven的形式。

這里主要介紹CPU上的實現,GPU實現將在之后進行單獨的介紹。

a7006b78f91b6a2b56b1dbb3597d6954.png

四叉樹,顧名思義,就是每個根節點最多有四個孩子的樹,其結構能夠很好的表現平面的分化。

a542b4ba39608e3d2fdf079b17d40a7f.png

算法簡介:

初始化時為一個根節點

視點靠近時四分

每個節點對應一個網格

分化公式:

距離/節點邊長>CL CL為自己設置的一個值,CL越大,越容易分化

此外,也可以根據屏幕占比進行分化

f45ced0528f8de9187527f1b04d4db81.png

這里也可以進行一個優化,預處理生成一份陡峭度數據去干預分化,越復雜的地形越易分化,如果地形沒有任何起伏,那么完全不分化也是沒問題的。

下圖展示了動態的分化過程

b1fdf0540c9f02c035642852c1342184.gif

0226e4a7b483706a4a725642e14ce66b.gif

到這里,基本的思路就已經講完了,但還需要解決一個問題,也就是“裂縫”,見下

e157cf84eb7acc15c07bf6242258121b.gif

如上圖所示,由于不同分化層級網格毗鄰處頂點數不一致,采樣精度不同,就會導致漏面的情況

859c471729690f4ae820c3ff81d8c244.png

在經典算法中,是這么解決的:

將網格分為5個部分,其中上下左右四個部分會根據鄰居節點的分化程度去控制網格的生成方式,如下所以,如果鄰居的分化程度較低,則會去掉一些頂點,使邊界頂點正好對齊來保證采樣精度一致。

此外,也要保證相鄰節點的lod層級最多相差1,在根據公式分化后還要依次檢測每個節點的鄰居是否存在分化程度比自身高兩個層級的節點,是的話要強制分化該節點。

5c1fa854c661141264d6f0c9265ae941.png

8908dd604b3aecdfe6cec580291351a9.png

這個算法其實不是很好,目前也沒看到哪個游戲采用這種方式。

解決裂縫的方式還有很多,下面主要介紹三種

1.強制對齊

4f1723ac64d173bb9943ce0cc2f132d1.png

2.向下生成一圈外圍網格

68ffd1a018d2e94a26c70864b7c6f8ea.png

3.邊界處按最密進行分化

29d5881c94dbcdbca7d7e76295d15c5d.png

最后效果如下

ed5905eec11a54af5990edaa4cb4e276.gif

至此,四叉樹算法就介紹完了,之后的實現也是采用的此算法。

此外,unity也是采用的此算法,但老版unity沒有采用GPUInstance,導致dc奇多,新版本雖然進行了優化,但由于unity本身不開源,無法進行定制開發,所以還是不推薦。

下面兩種算法我沒有進行具體的實現,所以只是簡介。

GeoMipmap算法

此算法是虛幻4采用的算法

大致思路為:

將地圖分為固定數量的mesh,每個mesh根據lod生成不同精度的網格

47c46ad35f4834230c3ef6cd1a4f44b4.png

見下圖,lod為0時生成完整網格,lod為1時會把黑色的頂點去掉,用剩余的白色頂點去生成網格,這個過程是完全在GPU進行的。

d0c297049d5880b8677ab5a035b5d3dd.png

移動端的話基本就采用的上面的兩種方式。

下面對比一下兩種方式:

四叉樹算法的網格近多遠少,且能通過GpuInstance進行優化,dc大概在10左右,面數在6w左右。當距離較遠時,極端情況只有一個mesh。由于地形一般包含多種植被,如沼澤,沙漠,森林,且移動端由于性能限制最多也只能采樣3次,所以1個mesh時會不能很好的表現整個地形面貌。但可以通過烘培一個低模,遠處用低模,近處用四叉樹的方式優化。

Geomipmap網格固定,dc固定,大概在40-60左右,頂點數在2w左右。距離較遠時,Mesh數量固定,紋理采樣不受影響。但為了減dc,一般也會烘培一個低模。

最后總結一下,unity建議自己寫四叉樹,虛幻直接用自帶的geomipmap

移動立方體算法

上面的兩種算法都存在一個缺陷,由于是基于二維高度圖,所以不能表現洞穴,地洞地形。

而移動立方體算法則解決了這個問題。無人深空中即采用了此算法。

4e4c1d630fe7ce2acae4bffce4d2c902.png

該算法將場景看成由無限多個立方體組成。

當立方體足夠小時,可以近似將穿過該立方體的面看做標準曲面

曲面方程表示為:

F(x,y,z)=a0+a1x+a2y+a3Z+a4xy+a5yz+a6xz+a7xyz

立方體存在8個頂點,每個頂點都有一個狀態,空氣中,土壤中

由0和1表示。8個頂點可以存在一個int中,如:00011001

如果為邊界,則表示需要生成網格

3a70144b7b0f872817d69b3035ea817b.png

一共有2的8次方,即256種情況

除去對稱的情況,歸納為15種,這里歸為15種只是為了好分析,實際編碼時仍需256種情況單獨考慮。針對每種情況,將網格生成方式存在一個查找表中。

9dc43521ec229220ee332212c3411c16.png

20fabd7956f68af666f104c393562a6a.png

這種算法存在一個二義性問題,如圖所示,假設黑點為在土地中,則下面兩種生成方式均可滿足。

9d12e5c542892475efca22b5f0e45315.png

這里假設某一面所在的平面方程為z=z0,

代入式F(x,y,z)=a0+a1x+a2y+a3Z+a4xy+a5yz+a6xz+a7xyz可以得到:

b0+b1x+b2y+b3xy=C0

兩邊除xy即可得到一個雙曲線方程

897d5d972919e711ff17baf119060e88.png

求出該雙曲線兩條漸近線的交點,根據正負即可決定最終該如何生成。

02a11717a0755f5fcb7ca01c7a74f9e7.png

看起來很簡單,但落實到實現還有巨多坑。

其實現在看來,這個算法生成的地形其實就相當于方塊變小無數倍的“我的世界”,生成的方塊數是奇多的,在無人深空中,基本常態就是百萬量級的頂點,所以在移動端自然就被Pass了。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/271000.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/271000.shtml
英文地址,請注明出處:http://en.pswp.cn/news/271000.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

數據庫安全:數據庫加密技術介紹

數據庫加密是計算機系統對信息進行保護的一種最可靠的方法。它利用密碼技術對信息進行加密,實現信息屏蔽,從而起到保護信息安全的作用。對數據庫中的數據進行加密,可以防止數據在存儲和傳輸過程中失密。常用的數據加密技術按照作用不同分為數…

poj 1201 差分約束

轉自:優YoU http://user.qzone.qq.com/289065406/blog/1307063918 大致題意: 給出數軸上的n個區間[ai,bi],每個區間都是連續的int區間。 現在要在數軸上任意取一堆元素,構成一個元素集合V 要求每個區間[ai&#xff0c…

oracle11 刪除表空間,oracle11g啟動停止服務,修改字符集,導入導出,創建刪除表空間,卸載oracle等...

oracle11g啟動停止服務,修改字符集,導入導出,創建刪除表空間,卸載oracle等1. 【啟動停止服務】//啟動停止監聽 www.2cto.comlsnrctl start;lsnrctl stop;//啟動停止服務sqlplus orcl as sysdba; //登錄>shutdown immediate;>STARTUP;或者ps -ef|grep ora_dbw0_$O…

Java中包裝類型和基本類型的使用場景(阿里開發規范)

基本數據類型和包裝數據類型推薦使用場景 所有的 POJO 類屬性必須使用包裝數據類型RPC 方法的返回值和參數必須使用包裝數據類型所有的局部變量推薦使用基本數據類型

數據庫:整理四個實用的SQLServer腳本函數

今天給大家分享小編自己日常工作積累的四個SQLServer腳本函數 目錄 1、字符串指定字符分割為list 2、數字去掉末尾的0 3、創建表、視圖、函數、存儲過程判斷是否存在 4、金額轉換為大寫 1、字符串指定字符分割為list 功能:主要適用于數據庫字段存儲字段用逗號等分隔…

python排名分析_用Python分析了近幾年胡潤排行榜,我酸了……

10 月 20 日,胡潤研究院發布《2020 胡潤百富榜》,也就是富富富豪排行榜杭州的馬云毫無懸念的再次摘下中國首富桂冠,深圳的馬化騰位列第二榜單被我翻爛了,還是沒有找到我的名字,難道是被遺漏了嗎?&#xff1…

sublime代碼片段

創建方法&#xff1a;Tools > New Snippet 這時你會看到如下示例代碼&#xff1a; <snippet><content><![CDATA[Hello, ${1:this} is a ${2:snippet}.]]></content><!-- Optional: Set a tabTrigger to define how to trigger the snippet -->…

定義DO/DTO/VO等POJO類時,不要設定任何屬性默認值

定義DO/DTO/VO等POJO類時&#xff0c;不要設定任何屬性默認值

php事務 面向對象,關于PHP面向對象的事務腳本模式

下面為大家帶來一篇PHP面向對象之事務腳本模式(詳解)。內容挺不錯的&#xff0c;現在就分享給大家&#xff0c;也給大家做個參考。如下所示&#xff1a;/*事務腳本模式: 類似于thinkphp中的model層&#xff0c;或者說就是操作數據庫的類。個人覺得實踐中使用起來還是挺簡單方便…

分布式數據庫相關概念介紹

1、分布式數據庫的概念分布式數據庫系統&#xff08;Distributed Database System&#xff0c;DDBS&#xff09;是針對面向地理上分散&#xff0c;而管理上有需要不同程度集中管理的需求而提出的一種數據庫管理信息系統。2、分布式數據庫系統組成LDBMS(Local DBMS)&#xff1a;…

社會管理網格化 源碼_為什么說網格化管理是基層社會治理的有效武器

在社會治安綜合治理中網格化管理是當前各地加強基層社會治理的一種有效“武器”。為什么要說網格化管理是基層社會治理的有效“武器”&#xff1f;這就要為大家講講以下幾點了&#xff0c;好讓大家清楚的明白為什么。網格化管理適應當代社會的基本特性。網格化服務管理是當前城…

【Time系列一】datetime的妙用

今天在弄個自動關機小腳本的時候&#xff0c;遇到了時間轉換的問題&#xff0c;也難怪&#xff0c;以前沒學過&#xff0c; 不能怪我不會哦! 首先&#xff0c;先學會打印出當前時間的幾種方式 參考開源社區: http://my.oschina.net/u/1032854/blog/198179#OSC_h1_3 菜鳥編程:…

循環體內,字符串的連接方式,使用StringBuilder的append方法進行擴展

循環體內&#xff0c;字符串的連接方式&#xff0c;使用StringBuilder的append方法進行擴展

JS樹結構操作:查找、遍歷、篩選、樹結構和列表結構相互轉換

經常有同學問樹結構的相關操作&#xff0c;也寫了很多次&#xff0c;在這里總結一下 JS 樹形結構一些操作的實現思路&#xff0c;并給出了簡潔易懂的代碼實現。本文內容結構大概如下&#xff1a;JS樹結構相關操作1遍歷樹結構1. 樹結構介紹JS中樹結構一般是類似于這樣的結構&…

python框架django的使用_Django框架的基本使用,若依框架

Django框架的基本使用&#xff0c;若依框架Django框架的基本使用Django是一個功能強大的web框架框架模式1、MVC和MTV框架MVC&#xff1a;Web服務器開發領域里著名的MVC模式&#xff0c;所謂MVC就是把Web應用分為模型(M)&#xff0c;控制器(C)和視圖(V)三層&#xff0c;結構說明…

初學js

今天開始接觸js&#xff0c;知道了js的功能以及學習的意義&#xff0c; 今天從命名的規范和數值的規則就能看出js是1門非常嚴謹的課程&#xff0c;只有做好細節才能體現出js的強大之處&#xff0c; var是定義一個名字 var name1&#xff1b; 定義了還能賦值&#xff0c;可以是數…

數據庫:SQLServer中GUID用法介紹

今天給大家分享一下SQLServer中生成GUID的用法。一、NEWID用法NEWID()作用是生成無順序的GUID字符串。用法如下&#xff1a;SELECT NEWID() --生成36位的GUIDSELECT REPLACE(newid(), -, ) -- 生成32 位的GUID二、NEWSEQUENTIALID用法1、NEWSEQUENTIALID是什么&#xff1f;在指…

oracle po:默認申請分組,PR自動創建PO采購訂單:強制按照PR行進行分組

有時候&#xff0c;需要實現強制按照PR行來自動創建PO。舉個例子&#xff1a;假設2張PR&#xff0c;同一個物料&#xff0c;同一個需求日期等等的&#xff0c;在合并采購訂單的時候&#xff0c;希望是2個PO行。按照標準功能的處理邏輯&#xff0c;如果是同一個物料需求日期(配置…

cserialport 循環發送信號_C++信號處理

免費C語言教程&#xff1a;阿里云大學——開發者課堂(點擊文章最下方“了解更多”)信號是由操作系統傳給進程的中斷&#xff0c;會提早終止一個程序。在 UNIX、LINUX、Mac OS X 或 Windows 系統上&#xff0c;可以通過按 CtrlC 產生中斷。有些信號不能被程序捕獲&#xff0c;但…