是否有可能在尺寸和质量上做出逼真的n体太阳系模拟?

重要提示:这个问题与“PhysX” 完全没有关系,它是一个计算机游戏物理系统(对于诸如球类游戏之类的街机游戏中的物理学是有用的); PhysX是Unity3D和其他游戏引擎的内置系统, PhysX在这里完全不相干。

////////////////////更新(先阅读底部)/////////////////////

我一直在logging价值观和确切的问题在哪里,我想我find了。 我在我的代码中有这样的东西

Velocity += Acceleration * Time.deltaTime; position += Velocity * Time.deltaTime; 

加速度现在是0,0000000000000009 .. 随着代码的stream动,速度会随着时间的推移而增加,而浮动则没有问题。 但是在开始时,地球的初始位置是(0,0,23500f)你可以在我最后给出的图表中看到这一点。

那么现在当我加速度* timedelta(这是类似于0,00000000000000005在这一点上)的位置是23500,基本上不会增加​​它。 位置仍然是(0,0,23500)而不是像(0,0,23500.00000000000005)那样,因此地球不移动,因此加速不会改变。

如果我将地球的初始位置设置为0,0,0,则将加速度设置为0.0000000000000000009,以确定其位置是(0,0,23500)然后“加速”速度* timedelta。 它变得像(0,000000000000000000005),并保持增长。 当float为0时,添加这么小的值没有问题。 但是如果浮点数是23500,那么它不会加上小数值。

我不知道这是否是团结的问题或C#的浮动。

这就是为什么我不能使它的价值小的工作。 如果我能克服这个问题,我的问题就解决了。

////////////////////////////////////////////////// /////////////////////////////

我一直在开发n体物理来模拟我们的太阳系,所以我一直在收集数据,使其尽可能现实。 但数据大小有问题。 我search了互联网的每一个小小的一点,我找不到一个解释人们如何克服这一点。 (如果他们这样)所以我试着在这里拍摄。

因此,为了保持行星之间的距离,半径和“质量”的比例固定,我创build了一个excel文件来计算所有的数据。 (因为为什么有人会把“如果有地球的质量是什么”放在互联网上的“半径图”上呢?)我将把ss作为附件。 它基本上“正常化”,换句话说就是“规模化”一个星球上的每一个属性。 在这种情况下,我把这个参考称为“地球半径”。

我是团结一致的工作,你们知道,你们不能一起工作,“太大”或“太小”的价值观。 所以我不得不缩小太阳系,“太多了!”

所以我用牛顿的万有引力定律(F = GMm / r ^ 2)来简单化,我直接从一个其他的物体上计算出一个给定的物体a = GM / r ^ 2。

所以地球引力加速度“朝阳”的实际价值大概在0.006万km / s ^ 2,这个值很小,可以统一起来,但是可以工作。 然而,为了得到这个值,我需要把地球的半径(比例)设置为6371单位,太阳比例为696,342 !,这太大了,以致于统一。

所以我说,让地球半径为1,以统一单位。 所以,当半径变化时,一切都在变化,质量,距离…我保持行星的密度,并计算新的半径新体积的质量。 所有的计算都在附件中。

所以事实是,当我把地球的半径作为1时,对太阳的引力加速度就变成了0000000000000这个可笑的小东西。 当然,Unity并不符合这个价值。

所以,如果我反而增加了地球的半径,那么太阳的质量和半径会变得很大,然后我再也不能使用了。

我不知道其他人怎么解决这个问题,他们是怎样解决这个问题的,但是从我看来,看起来不太可能对太阳系进行现实的n体模拟。 (至less统一)

所以我需要有10个代表张贴图像-_-,我会给链接。 http://berkaydursun.com/solar_system_simulator/data.PNG另外一个目录是工作实验太阳系模拟n体计算,但UNREALISTIC值。 它工作得很好,它甚至看起来接近真实,但不,它没有正确的比例^^你可以在这里testing它,如果你希望http://berkaydursun.com/solar_system_simulator/

编辑:魔兽我几乎开始每个段落“所以”^^

我也编程溶胶系统模拟,所以这里是我的见解:

  1. 翻译

    我使用1:1缩放的OpenGL 。 所有单位都在SI [m,s,kg,…] 。 问题从Z缓冲开始。 通常的Z缓冲位宽是16/24/32 bit ,这是16/24/32 bit你所需要的。 我从0.1米到1000 AU渲染,所以如何克服这个问题?

    我通过结合Z-sortingZ-buffering (通过Z-sort是因为透明环和其他效果是必需的),一次渲染3个frustrums来pipe理它。 所以首先我把最远的部分渲染到zfar=1000AU 。 天空圆顶投射在z=750AU距离处,然后清除Z缓冲区并渲染物体达到zfar=0.1AU 。 然后再次清理Z缓冲区并渲染最近的对象zfar=100000 m

    为了得到这个工作,你必须有尽可能精确的投影matrix。 gluPerspective已经没有任何的cotangens,所以它需要修复有关元素(让我很长时间来发现)。 Z nearZ near Z缓冲区的位宽。 当编码正确,然后这个工程很好,即使在10000x倍的缩放。 我使用这个程序作为我的望远镜的对象的导航/search器:)实时从我的主页视图。 我结合了3D明星,天体,船只,真实的地面(通过DTM和卫星纹理)。 它的能力,甚至红色的青色浮雕输出:)。 可以从表面,大气,空间渲染…(不只是locking到地球)。 没有其他的第三方lib然后使用OpenGL。 以下是它的样子:

    IMGIMGIMGIMGIMG

    正如你所看到的,它可以在任何高度上正常工作,或者放大像大气散射着色器那样的气氛

  2. 模拟

    我不使用n体重力模拟,因为你需要很多非常难以获得的数据(在所需的精度上几乎是不可能的)。 计算必须非常精确

    我使用开普勒方程,所以看看这些:

    • 解开开普勒方程
    • C ++实现 。

    如果你仍然想使用引力模型,那么使用来自NASA的 JPL视野 。 我认为他们也有C / C ++的源代码,但他们使用了不兼容的参考框架与我的地图,所以它是无法使用的。

    一般来说,开普勒方程有较大的误差,但不会随着时间的推移而增加。 重力模型更精确,但其误差随时间而上升,您需要不断更新天体数据才能使其工作…

整合精度

你目前的实现是这样的:

 // object variables double acc[3],vel[3],pos[3]; // timer iteration double dt=timer.interval; for (int i=0;i<3;i++) { vel[i]+=acc[i]*dt; pos[i]+=vel[i]*dt; } 

问题是当你添加非常小和非常大的值,然后他们被转移到相同的指数加法之前,将四舍五入重要的数据为了避免这只是改变它:

 // object variables double vel0[3],pos0[3]; // low double vel1[3],pos1[3]; // high double acc [3],vel [3],pos [3]; // full // timer iteration double dt =timer.interval; double max=10.0; // precision range constant for (int i=0;i<3;i++) { vel0[i]+=acc[i]*dt; if (fabs(vel0[i]>=max)) { vel1[i]+=vel0[i]; vel0[i]=0.0; } vel[i]=vel0[i]+vel1[i]; pos0[i]+=vel[i]*dt; if (fabs(pos0[i]>=max)) { pos1[i]+=pos0[i]; pos0[i]=0.0; } pos[i]=pos0[i]+pos1[i]; } 

现在xxx0被集成到max ,整个事情被添加到xxx1

四舍五入仍然存在,但不再累积。 您必须selectmax ,集成本身是安全的,而且xxx0+xxx1必须是安全的。 所以如果这个数字对于一个分裂来说太不同了,那么分裂两次或者更多…

  • 如: xxx0+=yyy*dt; if (fabs(xxx0>max0))... if (fabs(xxx1>max1))... xxx0+=yyy*dt; if (fabs(xxx0>max0))... if (fabs(xxx1>max1))...

[编辑2]星星

  • 星星的颜色我见过的最好的星星形象
  • Star BV颜色索引到明显的RGB颜色全部星表使用BV索引
  • 使用Stelar目录也是星号交叉引用链接
  • 天空盒:结合不同的星星数据

正如你所发现的,放大缩小的东西不一定有帮助。 这里有一些很好的阅读使用浮点数时要考虑的事情: http : //docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

基本上,根据第一性原理(牛顿定律)进行模拟对于数值的准确性是不利的,因为你不用重力效应的规模来思考数值方法,所以你最终会在不同的尺度上抛出一大堆不同的效应在一起,结果是低精度。

通常行星,卫星星历等事物不是以牛顿定律开始的,他们首先假定轨道是开普勒的,然后是微扰校正。

这是一个计算行星位置的algorithm(半不透明的)。 http://ssd.jpl.nasa.gov/txt/aprx_pos_planets.pdf

如果你想做一个N体模拟,你似乎需要更多的精度。 如果统一阻止你使用双精度,那么我build议用纯C#进行计算,然后在作业完成时转换为单精度。