能否使用双精度(或长整数)在3d空间中准确表示太阳系?


15

我想知道如何在3D游戏中最好地管理坐标,该游戏的目的是真实地模拟整个太阳系,但能够处理“飞船”中的最小移动(即:也许我们可以认为1厘米是最小的)框架的可接受运动)。是否支持64位双精度(或64位long),还是遇到溢出问题?如果没有,那么应该使用多头还是双头,或者如果是,那么,您认为哪种方法最适合在3D游戏中模拟太阳系中的位置?(即:仅根据要运输的距离一次将系统中的一部分保留在显示器中,或以某种方式在不同的坐标空间中表示该系统等)


您定位的语言是:C / C ++?Java的?还有吗
洛朗·库维杜

4
@lorancou:无关紧要,他明确指定的大小long
DeadMG

@DeadMG在C / C ++中可以是32位。64位更像是long long。但是,是的,如果您愿意,可以称之为挑剔。
洛朗·库维杜

只需使用BigInteger。大多数语言都有它的一些变体-大小无限制的整数值(用法是O(log(n)))
ashes999 2012年

如果游戏在计算上不太繁重,那可能是一个答案。
劳伦·库维杜

Answers:


11

关于整数,已经有了一个很好的答案,但我觉得不应消除浮点数。在他的回答中,Byte56选择了去做冥王星最大轨道的选项,可能是从这张excel表中选出的,所以我会坚持下去。

这使太阳系的边界位于:

7,376,000,000公里= 7.376x10 ^ 9厘米= 7.376x10 ^ 14厘米≈7.4x10 ^ 14厘米

双精度浮点数优惠15个显著小数最大精度。因此,您很幸运:如果您的原点位于太阳的中心,并且在冥王星周围使用一个位置,则可以表示所有厘米,例如在C ++中:

printf("%.0Lf\n", 7.4e14);
printf("%.0Lf\n", 7.4e14 + 1.0);
printf("%.0Lf\n", 7.4e14 + 2.0);

Output:
-------
740000000000000
740000000000001
740000000000002

因此,如果您可以将游戏限制在冥王星的轨道上,那么恭喜您!您已经具有足够的精度,可以使用双精度来表示它。

请注意,这足以在模拟中表示它,但不要期望能够毫不费力地渲染它。您必须将其转换为32位浮点数,或者更改原点,以便在接近的对象上获得足够的精度,并且可能必须依靠一些Z缓冲区和相机平截头体欺骗才能使所有这些内容正确渲染。

现在,如果您希望宇航员访问更大的奥尔特云中的一些彗星,那就结束了。在10 ^ 16厘米左右,您开始失去精度:

printf("%.0Lf\n", 1.0e16);
printf("%.0Lf\n", 1.0e16 + 1.0);
printf("%.0Lf\n", 1.0e16 + 2.0);

Output:
-------
10000000000000000
10000000000000000 <-- oops
10000000000000002

当然,情况还会进一步恶化。

因此,在这种情况下,您可能想尝试一些更高级的解决方案。我建议您看一下Peter Freeze在Game Programming Gems 4中的文章:“ 2.3解决大世界坐标系中的精度问题”。IIRC,他建议一个可能适合您需求的系统,它实际上是多种不同的坐标空间。

那只是一些提示,您可能必须使用自己的一些配方才能运行此程序。已经实施了此类工作的人可能会为您提供更多帮助。例如,为什么不向Kerbal Space Program背后的家伙发送电子邮件呢?

祝您比赛顺利!


1
这个答案很好,因为它更容易映射到OpenGL和DirectX等使用的3d浮点空间中,并且具有良好的引用。因此,我将其标记为答案:)
尼古拉斯·希尔

酷:)作为奖励,因为这都是非常近似的,所以您会在Bruce Dawson的博客中找到更多有关浮子的更深入的信息:randomascii.wordpress.com/2012/05/20/…
Laurent Couvidou 2012年

17

假设冥王星位于太阳系的“边缘”(尽管有人说距太阳只有3光年)。冥王星的最大轨道距离太阳约73.76亿公里。那是7.37600×10 ^ 14厘米。将直径翻倍即可得到1,475,200,000,000,000厘米。这完全在64位长的最大大小之内。由于太阳系的高度与其直径相比可以忽略不计,因此我们可以忽略这一点。

所以是的,您可以使用长来表示您在太阳系中的位置。实际上,您可以使用带符号的多头(不带符号的双倍)进行多达9.75光年的仓位。

请注意,查找距离并非如此。您可以找到的最大距离是您可以到达的最大距离的平方根。这可以通过使用详细程度系统来查找距离来克服。您可以做一些简单的检查来猜测距离有多远(比较它们的x值和y值),然后对大距离使用1,000,000公里的增量,对小距离使用厘米的增量。

当然有一个问题,您真的要吗?99.999%的太阳系完全没有兴趣的空白空间。如果您准确地表示了太阳系,那么我希望您不能准确地表示物理。绕过太阳系需要很长时间。大多数人保持兴趣的时间太长了。

为何还要具有如此高的精度,除非您还要以该精度对太阳系中的物体建模?那就是您遇到麻烦的地方。太阳的体积为1.40900×10 ^ 18立方公里。在立方厘米尺度上,使用单个位表示“已占用”该空间将占用1.4×10 ^ 33位或1.6×10 ^ 23 GB。我认为您没有那么多RAM。


3
相当漂亮。简短版:浮动精度是您最少的担心。
aaaaaaaaaaaaaa's

1
溢出整数,甚至是64位。宇宙飞船绕冥王星运行。尝试计算从飞船到太阳的距离。平方。繁荣。
洛朗·库维杜

3
我强烈不同意最后一段中的主张-OP的问题按原样是完全合理的,并且不必期望实际上在每个(立方)厘米中都有项目来关心位置精度为1cm。
史蒂文·斯塔德尼基

1
@StevenStadnicki足够公平,但是即使在千米规模上,每立方千米1位仍为164,029,188 GB。这类似于在汽车速度表中要求原子精度。那只是比需要的更加准确。
MichaelHouse

1
好吧,去非盟或光年的规模太不精确了。因为我们在谈论太阳系。光年或秒差距对于较大的物体(例如大星云)会更好。
MichaelHouse

2

您可以使用BigInteger,无论您的编程语言如何称呼它。这是一个无限制的整数;它可以很好地扩展-通常使用log(n)存储大小为整数的整数n

Java和C#拥有它;我敢肯定其他语言也可以。如果没有,您可以对其进行反编译并重新实现,而不会遇到太多麻烦。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.