关于存储大量数字(用于3D坐标)的新方法的想法

时间:2016-04-01 13:41:12

标签: numbers point floating

在创建大型游戏世界时,标准似乎是使用浮点数,特别是双精度浮点数,用于世界坐标。你可以使用一个64位整数,它给你加上或减去9 quintillion范围,(9 x 10 ^ 18),但是你要以毫米为单位进行处理,这不如使用说米。

我们都知道,浮点数越大,它的精确度就越低,数量就越大。在大多数开放世界的游戏中,你并没有真正看到大于6平方公里的地图。 GTA V(6乘12),巫师3(两个独立的地图,大约4乘4),辐射游戏,大致可比,Just Cause游戏,稍大(约20km平方标记),极品飞车游戏,同样,4平方,也许5,Elder Scrolls游戏,大致相同,你明白了。对于双精度浮点数,大多数这些游戏都不是问题。

但是你有游戏和世界特别巨大的案例,我猜这些游戏主要是太空主题游戏,其中的行动发生在太阳系,星系等等。我刚读了reddit上关于如何开发人员表示,转向64位版本的太空工程师游戏可以让他们极大地扩大游戏世界的范围,称他们现在可以填充大约13个天文单位,或大约20亿公里。尽管如此,冥王星在远日或75亿公里之外的距离约为50澳大利亚。这让我想知道像Star Citizen或Elite Dangerous这样的游戏是如何做到的,我猜测无缝拼接不同的地图。

我听说过long double和quad,但是long double似乎不适用于大多数架构和编译器,并且四边形的信息很少。

但是这引出了我的想法话题,我确信每个人在某些时候都有,这就是使用多种数据类型并将它们结合使用。例如,我已经说过,使用64位有符号整数,你可以获得一个高达9 quintillion的整数精度。比方说,你让64位int成为你的米单位。这将为您提供9千万亿公里的世界空间。然后你需要的是一个额外的两个字节,一个16位整数,可以容纳大约65,000个值,并使用这两个字节作为毫米。值2将是2毫米,值25将是2.5厘米,值500将是半米。这样,您的世界坐标就会达到毫米级分辨率。

我相当有信心添加和减去这样的复合数字(让我们称之为em)不会是一个问题,但乘法和除法似乎有点棘手。但是,毕竟说完了之后,通过对两个整数类型执行多个操作(当你将两个数字组合在一起时实际上是四个整数类型)会比使用浮点数算术更快或更有效吗?

1 个答案:

答案 0 :(得分:1)

它被称为fixed point arithmetic。您可以通过以下实现来实现:

public struct BigVector3 {
    const float SCALE = 0.0001; // this controls the fixed point precision.

    public long x;
    public long y;
    public long z;

    public Vector3 GetRelativePos(BigVector3 other) {
        long x = this.x - other.x;
        long y = this.y - other.y;
        long z = this.z - other.z;
        Vector3 v = new Vector3(x*SCALE, y*SCALE, z*SCALE);
        return v;
    }
}

但是最后,你最终还是会转换回某种浮点数,用于渲染,几乎每个主要物理引擎的物理计算等等。

真正的解决方案是增加数字的精确度。 double可以处理任何具有毫米精度的亚太阳系统。任何星系规模的游戏都应该使用相对定位和数学。

如果你真的需要在宇宙尺度上存储精确位置,C#的decimal类型是128位数据类型,它比双精度更精确,它可以存储我们可观察宇宙的比例位置。这应该是任何人都需要的。但是,很少有物理和渲染引擎支持这一点。

编辑:“这让我想知道像Star Citizen或Elite Dangerous这样的游戏如何做到这一点”

这些游戏不需要在如此远的距离上进行准确定位。如果你所乘的太空船比光速快,那么毫米可以忽略不计。顶点位置不准确只能近距离看到。您可以简单地将船舶内部与世界其他地方分开渲染。