numbers - 存储非常大的数字的新方法的想法(对于 3D 坐标)

标签 numbers point floating

创建大型游戏世界时,标准似乎是使用 float ,特别是 double float 作为世界坐标。您可以使用 64 位整数,它为您提供正负 9 千万亿的范围(9 x 10^18),但是您将以毫米为单位进行处理,这不如使用米那么舒服。

我们都知道, float 越大,其精度就越低,并且数字越有可能出现较大偏差。在大多数开放世界游戏中,您实际上看不到大于 6 平方公里的 map 。 GTA V(6 x 12)、巫师 3(两张约 4 x 4 的独立 map )、辐射游戏,大致相当、正当防卫游戏,稍大(大约 20 平方千米)、极品飞车游戏,相同,4 平方厘米,也许5个,上古卷轴游戏,大致相同,你明白了。大多数这些游戏对于 double float 来说不是问题。

但是你也有一些游戏和案例,其中的世界特别巨大,我猜这些游戏大多是太空主题游戏,其中的 Action 发生在太阳系、星系等中。我刚刚在 Reddit 上读到了关于如何开发者表示,游戏《Space Engineers》转向 64 位版本使他们能够极大地扩大游戏世界的范围,并表示现在可以填满约 13 个天文单位,即约 20 亿公里。尽管如此,冥王星距离远日点约 50 个天文单位,即 75 亿公里。这让我想知道像《星际公民》或《精英危险》这样的游戏是如何做到的,我猜想将不同的 map 无缝地拼接在一起。

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

但这让我想到了一个想法,我相信每个人都曾在某个时候有过这样的想法,那就是使用多种数据类型并将它们一起使用。例如,我已经说过,使用 64 位有符号整数,您可以获得高达 9 quintillion 的一个整数精度。举例来说,您让 64 位整数作为米单位。这将为您提供 9 千万亿公里的世界空间。那么您所需要的只是额外的两个字节,一个 16 位整数,可以容纳大约 65,000 个值,并将这两个字节用作毫米。值 2 表示 2 毫米,值 25 表示 2.5 厘米,值 500 表示半米。这样,您的世界坐标就将具有毫米分辨率。

我相当有信心,加减这样的合数(我们称之为 em)不会有问题,但乘法和除法似乎有点棘手。但是,总而言之,通过对两个整数类型(实际上是四个整数类型,当您将两个数字放在一起时)执行多个运算是否会比使用 float 算术更快或更有效?

最佳答案

它的名字是fixed point arithmetic 。您可以通过如下实现来做到这一点:

public struct BigVector3
{
    private 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)
    {
        BigVector3 v = this;
        v.x -= other.x;
        v.y -= other.y;
        v.z -= other.z;

        return (Vector3)v;
    }

    public static implicit operator Vector3(BigVector3 value)
    {
        return new Vector3(value.x * SCALE, value.y * SCALE,  value.z * SCALE);
    }
}

但最终,您仍然最终会转换回某种 float ,以进行渲染、使用几乎所有主要物理引擎计算物理等。

真正的解决方案是提高数字的精度。 double 可以处理任何亚太阳系尺度,精度为毫米。任何银河系规模的游戏都应该真正使用相对定位和数学。

编辑:“这让我想知道像《星际公民》或《精英危险》这样的游戏是如何做到这一点的”

这些游戏不需要在这么远的距离上进行精确定位。如果你乘坐的 spaceship 以超光速飞行,那么一毫米可以忽略不计。而且顶点位置不准确只有近距离才能看到。您只需将船舶内部与世界其他部分分开渲染即可。

关于numbers - 存储非常大的数字的新方法的想法(对于 3D 坐标),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36357879/

相关文章:

html - 在两个部分之间放置一个 div,使其部分位于两个部分之上

javascript - 两个整数 Javascript 之间的相同数字集合

javascript - 如何区分时间字符串和非时间字符串

algorithm - 如何获得描述路径的固定数量的均匀分布的点?

mysql - 有没有办法从 MySQL 的 Envelope(Poly) 中选择 lat1、lat2、lon1、lon2?

geometry - "ray through vertex"检测多边形中的点时的特殊情况

html - 如何使文本可环绕以下 float 元素?

html - CSS - 如何通过 float 摆脱空白的垂直空间

c++ - 在 C++ 中生成正态分布的随机数

algorithm - 两个整数之间加减的最短路径