Arnis 原理拆解:一份 OpenStreetMap 数据如何变成 Minecraft 城市
【免费下载链接】arnisGenerate any location from the real world in Minecraft with a high level of detail.项目地址: https://gitcode.com/GitHub_Trending/ar/arnis
Arnis 替你解决一件事:把某个真实地点的街道、建筑和地形起伏,按真实坐标搬进 Minecraft——它读取 OpenStreetMap 要素与高程数据,生成 Java、基岩版、Luanti 三种能直接打开的世界文件。
为什么"照抄"一座城市没那么容易
难点在哪?两个场景就够了。
第一,地球是圆的,方块世界是平的。你在地图上框住一块区域,拿到的是经纬度,Minecraft 只认整数坐标。直接按"经度差 × 常数"线性缩放,小区域没问题;区域一大,偏差就藏不住——赤道附近一度经度约 111 公里,挪到北纬 60 度只剩一半。
第二,数据是拼起来的。街道与建筑轮廓来自 OpenStreetMap,但很多建筑没标层数;Overture Maps 能补上一批带高度的建筑底面;地面起伏又要单独从高程服务下载。三路数据各说各话,坐标体系还不一致,得先对齐到同一张网格上,才谈得上生成。
先框出要生成哪片地
生成之前必须先回答一个问题:生成哪里?
在 GUI 里用矩形工具在地图上拖一个框,背后就是把框的四个角存成min_lat,min_lng,max_lat,max_lat四元组;命令行则直接传--bbox。
没给 bbox 时的回退顺序
如果你喂的是本地 .osm 文件而没写 bbox,程序会按顺序回退:先读文件里的 bounds 元素,再不行就取所有节点坐标的包围范围。框定之后还会估算面积,超过约 250 平方公里就提醒你:这次生成费时间、费内存,而且会把公共的地图服务器压得很辛苦。
bbox 是后面一切的地基——三路数据请求、坐标转换、落盘命名全靠它。
三路数据并行拉取:OSM、Overture 与高程
bbox 定下来之后,原始数据从哪来?三件事同时发生:Overpass API 抓取区域内的节点、道路与建筑轮廓;Overture 请求建筑底面;地面高程数据按瓦片从高程服务下载(带本地缓存,重复生成同一块地不用重新拉)。
这里的取舍在容错上:Overture 挂了只降级——警告一声继续生成,建筑少一些而已;高程挂了直接终止,因为"真实地形"是这个项目的默认卖点,没有它整个生成就没有意义。抓回来的原始 XML 被解析成统一结构,建筑、道路、水体各归各类,等下一步换坐标。
经纬度怎么变成方块坐标
解析出的要素还穿着经纬度的衣服,怎么换成方块世界的整数坐标?转换逻辑集中在src/coordinate_system/transformation.rs,它提供两种模式。
小区域用线性,大区域切 Web Mercator
一种是本地线性模式:把 bbox 内位置按比例映射到 XZ 网格,小范围生成足够准,计算也最便宜。另一种是 Web Mercator 投影(就是大多数在线地图用的、把地球表面展开成平面的数学变换):先把 bbox 四角投影出去,取包围盒再反算坐标。区域偏大或偏北时,它能避免线性缩放在边缘产生的拉伸。
两种模式共享同一个 scale 参数——现实距离到方块数的比例,GUI 和 CLI 都能调。坐标系统一之后,整个生成范围变成一个整数 XZ 包围盒,后续所有处理都发生在这个盒子里。
要素排队:优先级排序与地面改判
所有要素齐了,谁先落块?程序先做一次全局排序:按类型排优先级,建筑、桥梁、道路依次生成,后生成的要素会避让先生成的,避免"马路从楼顶穿过去"这种低级错误。
排序前后还有一次地面"改判":有一层处理专门用 OSM 的水体、陆地标记去修正高程数据里的矛盾——比如卫星数据把一片湖判成了平地,或者桥下被误标成水面,都会被逐格修复。这一步不开调试开关时你完全看不到它,但生成质量很大程度押在这里。你还能通过 JSON 文件描述旋转、平移等操作,或直接给--rotation把整个世界转个角度,让某条街正对着自己。
从道路到摩天楼:要素如何拼装成方块
排队完成后,一个"建筑"要素怎么变成成排的方块?答案在src/element_processing/:每个文件负责一类东西——建筑轮廓被拉伸出楼层并按屋顶类型收尾,道路按等级铺宽度,桥梁分跨河与跨路两种走法,河道与湖泊各有专门处理。
🌳 树跟着气候走,大件结构是预制件
两个细节值得留意。其一是树:assets/tree-packs/按气候分区(热带、寒带、温带等)各存了一套树形结构,生成时按所选区域的坐标判断气候,挑对应树种,所以寒带不会出现椰子树。其二是大型物体——汽车、飞机、起重机、灯塔——都以预制结构文件存在assets/structures/里,生成时整体塞进对应位置,而不是逐方块现算,省时间也更稳定。
分块写入 Anvil、mcworld 与 Luanti
方块都算好了,怎么变成游戏能读的文件?src/world_editor/用一个公共接口对应三个写入器:Java 版的 Anvil 区块格式、基岩版的 .mcworld 打包文件、Luanti 世界。三个版本的方块名不一样,各自有一张映射表兜底,保证同一片"草地"在三端长得一致。
瓦片并行与内存分配器的选择
写入本身是按瓦片并行跑的,这也解释了main.rs里一个不显眼的决定:全局换成了 mimalloc 内存分配器。瓦片并行意味着大量小块内存频繁申请释放,mimalloc 在这种负载下比系统分配器快得多;同时并行线程池被限制在 90% 的 CPU,给系统和前台程序留口气。⛏️
怎么验证生成结果、怎么按需求扩展
怎么确认这次生成没跑偏?几步就够:
- 先用
--mode terrain-only只跑地形,完全不碰地图数据,快得多——确认起伏符合预期,再跑完整的geo-terrain模式。 - 加
--debug,解析出的要素会写进一份文本清单,地面修正前后还会各输出一张对比图,方便核对水陆边界。 - 关心生成速度时开
--benchmark,各阶段耗时会逐项打印。
想按自己需求调:--scale控制比例尺,--overture决定是否合并 Overture 建筑,--rotation转角度,Java 版用--disable-height-limit装高世界数据包(需 1.21.4 以上)。这些选项在 GUI 里都有对应开关,生成前选框、选世界、点开始即可:
想自己跑起来,clone 仓库(https://gitcode.com/GitHub_Trending/ar/arnis)后用 cargo 以 release 模式编译;要新增一类元素的处理,顺着src/element_processing/里现成文件的模式加文件即可——解析、定优先级、落块这三件事,框架都已留好接口。
【免费下载链接】arnisGenerate any location from the real world in Minecraft with a high level of detail.项目地址: https://gitcode.com/GitHub_Trending/ar/arnis
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考