基于UE4/Unity绘制地图 - 确定展示区域

前言

绘制地图基础元素-线

绘制地图基础元素-面和体

基础知识

在研究清楚如何绘制地图的线面体之后,接下来需要确定需要展示的地图区域了。

地图可以看成是一个巨型的开放世界游戏场景,因此为了便于数据存储和查找,传统的做法是将地球根据墨卡托投影转换为平面地图,再将地图分级分块进行切片,通过索引获取到对应的数据。

image.png

以OSM的地图为例,导出数据是以当前视口的大小,查询对应级别的切片得到的。Google的卫星图、地形图等也都是按照分级分块的规则进行管理。

image.png

基于视口展示

传统的地图展示方式,展示区域的确定通常是与视口绑定的,即地图切片只加载摄像机视锥体与地图所在平面相交的部分,并在摄像机移动时动态进行切片的更替。

image.png

这种方式对于查看全世界全量地图数据的场景非常合适,但对于希望使用游戏引擎构建一个更精细的世界来说,有一些不足:

  • 视锥体动态计算切片的前提是,一定要保证其与地图所在平面一定有四个交点,因此摄像机的FOV(竖直方向的张开角度)不能太大,否则当摄像机俯仰角变化时,视锥体的上下两个面可能与地图所在平面平行,从而导致无法计算切片。
  • 在平行之前,同样也会因为角度问题,导致计算得到的切片数量过大,无法进行加载;或因为设置了一些切片数量的限制,导致看到的世界有所缺失。

因此视椎体动态计算的方式,通常会固定一个较小的FOV,并且限制俯仰角。同时因为性能的限制,对于大俯仰角的情况,通过一些手段进行切片的数量优化。以腾讯的JS API GL为例,为了减少大俯仰角造成切片数量过大带来的性能瓶颈,采用雾化的方式将较远处的场景进行剔除,使得可以无缝衔接查看整个世界。

image.png

UE4和Unity都有能够获得视椎体的接口。以UE4为例,ULocalPlayer中存储了Viewport相关的信息,根据矩阵变换的信息可以得到存储视椎体信息的FConvexVolume。

ULocalPlayer* LocalPlayer = GetWorld()->GetFirstPlayerController()->GetLocalPlayer();

FSceneViewProjectionData ProjectionData;

LocalPlayer->GetProjectionData(LocalPlayer->ViewportClient->Viewport, eSSP_FULL, ProjectionData);
    
FMatrix ViewProjectionMatrix = ProjectionData.ComputeViewProjectionMatrix();
    
FConvexVolume ViewFrustum;
    
GetViewFrustumBounds(ViewFrustum, ViewProjectionMatrix, true);

FConvexVolume的Planes数组中依次存储了左右上下四个平面的方程FPlane,比较特殊的是FPlane是以Xx+Yy+Zz=W的形式存储了(X,Y,Z,W)值。同时,地图所在平面也可以使用一个方程表示,因此,视锥体与地图的一个交点就是三个平面的相交点。(以左上交点为例,将视椎体的左、上平面方程与地图所在平面方程联立,即可得到交点)

其中的联立求交,可以使用矩阵运算快速求得:

image.png

若联立有解,则矩阵可逆,那么行列式不为0可以作为判断有解的快速验证方式。当确定有解后,则可使用逆矩阵快速求解:

image.png

基于行政区划展示

基于视口展示方案理论上完全可行,但对于有高性能显卡支撑的游戏引擎来说远远不够:

  • 地图至少要像GTA那样,目之所及都有元素,不能将远裁剪面如此提前。
  • 摄像机需要自由度,可以随心所欲的进行移动。

因此,比较直接的想法是,如果想展示一个城市,那就一次性渲染出城市的所有数据。

image.png

城市的数据可以借助于现有的服务获取,以腾讯位置服务的WebService API为例,可以通过行政区划服务获取到对应的行政区划点串信息,依托于地图数据的切片存储形式,因此只需要确定这个行政区划点串覆盖的切片集合就可以了。

// 行政区划线点串以连续的经纬度进行表示
"polygon": [ [116.809403,39.61482,116.790175,39.610555,116.780286,39.593196....],]

根据基础知识所说,每一个切片都是一个小正方形,而行政区划点串信息代表的是一个大多边形,因此转化为使用小正方形切片去近似一个多边形的问题。

是不是听起来十分像光栅化

image.png

因此顺着这个思路,借助于光栅化的方式求切片集合:

1、光栅化的基本单位是三角形,因此对于行政区划的多边形,先调用三角剖分算法分解为三角形的集合。
2、对于一个三角形,最经典的方式就是拆为两个更容易绘制的三角形,一个底边平行,一个顶边平行,再使用水平扫线法求得所有的切片。

image.png

具体算法可以参考这篇TriangleRasterization的文章,其中还有Bresenham算法和重心坐标算法等其他光栅化的算法。

获取到所有切片数据后,就可以进行行政区划的展示了。

基于位置的动态展示方法

借助于光栅化算法可以得到切片集合进行渲染展示,但基于行政区划的方式展示也有弊端,即CPU/GPU资源有限,对于几千平方公里的城市可能无法粗暴的直接支持。

和开放大世界游戏一样,比较合理的方式就是随着当前位置动态载入/载出场景,使得感官上构建出一个无缝衔接的大世界。

以UE4为例,Epic提供了World Composition这个利器去支持游戏开发者制作开发大世界游戏,开发者可以方便的并行编辑每个子关卡。运行时根据游戏角色所在的位置,可以异步加载/卸载子关卡,达到无缝衔接的效果。

image.png

而对于不适合使用World Composition的场景,可以退一步使用Level Streaming去进行手动管理,初步的使用方法,可以参考之前的文章,对于Level Streaming的一些初步的学习

基于位置的动态展示方法需要做更多的额外工作去达到完美的沉浸效果,目前这部分依旧还在摸索中,希望有朝一日可以完全解决。这篇文章权当是抛砖引玉,希望给大家带来一些思考。

作者:程序员阿Tu

链接:https://zhuanlan.zhihu.com/p/353203619

来源:知乎

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容