是的。
不要蛮力,直接去你想要的瓷砖。
前提是您有:
Tile toMorton(Point3D location)
在给定其真实位置的情况下提供 Tile的函数
Point3D fromMorton(Tile t)
提供 Tile 真实世界坐标的函数(我相信两者都可以从维基百科获得)
这些都是简单的实时操作。
天真的方法
只需转换为真实世界,在那里偏移,然后回到莫顿空间:
Tile originalTile = ...
Point3D originalLocation = fromMorton(original);
Point3D offsetLocation = new Point3D(offsetLocation.x + 1, offsetLocation.y, offsetLocation.y);
Tile offsetTile = toMorton(offsetLocation)
这只需要一些算术运算,因此应该已经适用于实时(比暴力破解更适用)。
优化方法
在 Google 上快速搜索“morton 代码社区”后,我找到了来自volumeseoffun的一篇写得很好的博客文章。
我将在这里提供最好的部分:
对于具有莫顿位置 p 的给定 (x,y,z);如果我们想要查看 (x+1,y,z),那么 p 必须增加的量 Δp 仅取决于 x,并且与 y 和 z 无关。同样的逻辑也适用于查看 y 和 z。
这意味着我们不需要toMorton
/fromMorton
所有三个坐标
此外(尽管博客及其来源都没有支持它)似乎可以通过查找表预先计算所述偏移量。这为您正在寻找的实时功能提供了额外的加速。鉴于 Morton 算法定义明确且可重复,对我来说这是有道理的,所以我相信这个假设。
只需预先计算偏移表,然后从一个起始图块开始,使用该表将您的图块偏移到它的真实邻居:
int[] offsetX = [ ... compute once ... ]
int[] offsetY = [ ... compute once ... ]
int[] offsetZ = [ ... compute once ... ]
Tile[] allTiles = ... // Init 3D world
public Tile neighbour(Tile original, Direction dir){
switch(dir){
case DIR_X_PLUS: return allTiles[original.chunkID + offsetX[original.chunkID];
case DIR_X_MINUS: return allTiles[original.chunkID - offsetX[original.chunkID];
case DIR_Y_PLUS: return allTiles[original.chunkID + offsetY[original.chunkID];
[... etc...]
default: return original;
}
}
希望这可以帮助。