/////////////////// UPDATE(先读底)/////////// ///////////
我一直在记录值并搜索确切的问题在哪里,我想我找到了。
我在我的代码
Velocity += Acceleration * Time.deltaTime;
position += Velocity * Time.deltaTime;
现在的加速度约为0,0000000000000009..。随着代码的流动,速度会按照预期的速度增加,浮子没有问题。
但是在开始的时候,地球的初始位置是(0,0,23500f)您可以在最后给出的图表中看到。
现在,当我增加速度时* timedelta(此时类似于0,00000000000000005)到23500的位置,它基本上不添加它。位置仍然是(0,0,23500)而不是(0,0,23500.00000000000005),因此地球不会移动,因此加速度不会改变。
如果我设置初始值将地球的位置设置为0,0,0,然后将加速度设置为0.0000000000000000009,假设其位置为(0,0,23500)
然后“添加”速度* timedelta。
它变成了某种东西例如(0,0,000000000000000000005)并保持增加。当float为0时,添加如此小的值没有问题。但是,如果浮点数是23500,那么它就不会合计较小的值。
我不知道这到底是单位问题还是c#的浮点数。
这就是为什么我无法使其以较小的值起作用。如果我能克服这个问题,我的问题将得到解决。
////////////////////////////// ////////////////////////////////////
我一直在开发n体物理学来模拟我们的太阳系,所以我一直在收集数据以使其尽可能逼真。但是数据大小有问题。我搜寻了互联网的每一个微小部分,却找不到一个能解释人们如何克服这一点的单一解释。 (如果这样的话)所以我在这里尝试射击。
因此,为了保持行星之间的距离,半径和“质量”之比固定,我创建了一个Excel文件来计算所有数据。 (因为为什么有人会在互联网上写“如果地球上有“那个”半径图,那地球的质量将是什么?)
我附上ss。它从根本上“标准化”或换句话说“缩放”行星的每个属性到给定的参考。在这种情况下,我将其称为“地球的半径”。
我是统一工作的,而且你知道,不能统一使用“太大”或“太小的”值。所以我不得不将太阳系缩小很多,
所以我使用牛顿万有引力定律F = GMm / r ^ 2,
很简单,我直接从所有其他物体计算给定物体的a = GM / r ^ 2。
因此,地球引力加速度“朝向太阳”的真实值大约为0,000006 km / s ^ 2,这即使是一个统一的数值也很小,但是可以工作。但是,要获得该值,1我需要将地球半径(比例)设置为6371单位,将太阳设置为696,342!比例,这太大了以致无法统一。
所以我说,让地球的半径为1,以单位为单位。
因此,当半径改变时,一切都改变了,质量,距离...
我保持了行星的密度,并根据具有新半径的新体积。
所有计算都在附件中。
因此,当我将地球半径设为1时,朝着太阳的重力加速度就变成了某种东西像0,0000000000009
太小了当然,Unity不能使用该值。
所以,如果我改为增加地球的半径,那么太阳的质量和半径就会变得可笑地大,然后我再也无法工作
我不知道其他人如何解决这个问题,他们为克服这个问题做了什么,但是从这里我看到,似乎无法对太阳系进行逼真的n体模拟。 (至少要统一)
所以我需要有10个代表才能发布图像-_-,我将改为提供链接。
http://berkaydursun.com/solar_system_simulator/data.PNG
还有一个目录是正在工作的太阳系模拟实验,它具有n体计算,但是具有UNREALISTIC值。
它工作得很好,甚至看起来有点接近真实,但是不,它没有具有正确的比率^^
如果希望http://berkaydursun.com/solar_system_simulator/
编辑,您可以在此处进行测试:哇,我几乎每个段落的开头都是“ So” ^^
#1 楼
我也进行了程序sol系统仿真,因此这里是我的见解:渲染
我使用1:1缩放比例的OpenGL。所有单位均为国际单位制,因此[m,s,kg,...]。问题开始于Z缓冲区。通常,Z缓冲区的位宽为
16/24/32 bit
,与您所需要的相差无几。我正在从0.1m到1000 AU进行渲染,所以该如何克服呢?我确实通过同时结合Z-sorting和Z-buffering的3个平截头进行渲染来管理它(由于透明环,Z-sort是必需的。以及其他效果)。所以首先我渲染最远的部分直到
zfar=1000AU
。天空穹顶投影距离为z=750AU
,然后清除Z缓冲区并渲染对象直到zfar=0.1AU
。然后再次清除Z缓冲区,并渲染最接近zfar=100000 m
的对象。要完成此工作,您必须具有尽可能精确的投影矩阵。
gluPerspective
的余弦不精确,因此需要修复相关元素(花了我很长时间才能发现)。 Z near
的值取决于Z缓冲区的位宽。如果编码正确,则即使缩放10000x
也能很好地工作。我从矿井主视图实时地将该程序用作矿井望远镜:)的对象导航/搜索器。我结合了3D星星,天体,船,真实地面(通过DTM和卫星纹理)。它甚至可以输出红蓝浮雕:)。可以从表面,大气,空间...(不仅限于地球)进行渲染。没有其他第三方库,则使用OpenGL。这是它的外观:您可以看到它在任何高度或缩放情况下都可以正常工作,就像这种大气散射着色器一样完成了大气
模拟
我没有使用n体重力模拟,因为为此,您需要很多非常难以获取的数据(以所需的精度几乎是不可能的)。计算必须非常精确地完成。
我改用开普勒方程,因此请参阅以下内容:
求解开普勒方程
C ++实现。
如果您仍要使用重力模型,请使用NASA的JPL层。我认为他们那里也有C / C ++的源代码,但是它们与矿图使用的参考框架不兼容,因此对我来说是不可用的。
一般而言,开普勒方程的误差较大,但不会随时间增加太多。重力模型更精确,但其误差会随着时间而增加,您需要不断更新天体数据以使其起作用...
[edit1]集成精度
您当前的实现方式是这样的:
// 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
四舍五入仍然存在,但不再累加。您必须选择
max
值,积分本身是安全的,并且附加xxx0+xxx1
也必须是安全的。因此,如果对于一次拆分而言,数字相差太大,则拆分两次或更多次... :
xxx0+=yyy*dt; if (fabs(xxx0>max0))... if (fabs(xxx1>max1))...
[Edit2]星星
恒星的颜色我见过的最好的恒星可视化
恒星BV颜色索引到明显的RGB颜色所有恒星目录都使用BV索引
使用Stelar目录中也有星星名称交叉引用链接
Skybox:组合不同的星星数据
[Edit3]进一步提高Newton D'ALembert积分精度
迭代积分的基本问题是基于当前身体位置施加基于重力的加速度将导致更大的轨道,因为在积分步骤
dt
期间位置发生了一些变化,这在天真的积分中没有考虑。为了解决这个问题,请看这张图片:假设我们的身体处于圆形轨道且处于0度位置。我不是使用基于当前位置的加速度方向,而是使用
0.5*dt
之后的位置。这会增加一点点加速度,从而导致更高的精度(与开普勒轨道相对应)。通过这种调整,我得以成功地从开普勒轨道转换为牛顿D'Alembert用于2体系统。 (下一步是对n体执行此操作)。只有不受潮汐影响和/或卫星影响的2个身体系统才可能与来自太阳系的真实数据进行粗略关联。要构造自己的虚构数据,可以使用开普勒圆轨道和相等重力的等向力:其中
a
是圆轨道半径m
是物体质量,M
是焦点物体质量(太阳)。为了使精度保持在可接受的公差范围内(对我来说),集成步骤dt
应该为:G = 6.67384e-11;
v = sqrt(G*M/a); // orbital speed
T = sqrt((4.0*M_PI*M_PI*a*a*a)/(G*(m+M))); // orbital period
因此要放置新的测试主体,只需将其放在:
dt = 0.000001*T
身体(太阳)位于:
pos = (a,0,0)
vel = (0,sqrt(G*M/a),0)
这会将您的身体置于圆形轨道,以便您可以比较开普勒与牛顿·德阿勒姆伯特,以评估仿真的精度。
评论
但是开普勒方程式是否“假设”存在轨道?就我而言,没有必要绕轨道飞行。一个物体应该能够从另一个质量物体上进行抛射,这是开普勒方程式无法实现的,对吗? -我绝对想在n体内制作。我实际上是在n体中工作,并且要对其进行测试,所以我想以此为基础构建太阳系。问题不在于放纵,而在于难以置信的大质量值和难以置信的小加速度值。好吧,团结并不能说明0,00000000000000009f的值,它基本上会返回0。
– OldBerkay
2015年1月19日15:28
此外,为什么重力模型的误差会随时间增加?通过我进行的伪造的价值颇高的太阳系模拟(链接),它的工作原理非常一致。轨迹模拟器中存在一个问题,但这是因为我为此编写了算法,而不是n体算法。我会尽快修复。
– OldBerkay
2015年1月19日15:29
@BerkayDrsn 1.是的。开普勒方程式不能用于弹弓和非周期性运动。 2.由于连续求和积分误差,重力模型的误差不断增加(它看起来很现实,但是当您将它与真实物体进行比较时,它不匹配)3.我强烈建议不要对这种计算使用统一性,而是自己动手做,但是您需要使用某种更高精度的定点/浮点数和足够小的积分dt步骤。也很可能有一些天文库。 Unity是为游戏设计的,并非用于逼真的模拟
– Spektre
15年1月19日在17:08
我不使用Unity物理,完全不使用刚体。我有自己的物理代码,与您的链接相似。但是问题仍然存在。我最近一直在记录日志,并且我想出了确切的问题在哪里。我有类似Velocity + = Acceleration * Time.deltaTime;位置+ =速度* Time.deltaTime;在代码中,(vector3)加速度现在约为0,0000000000000009 ..随着代码的流动,速度应以适当的速度增加。但是在开始时,地球的初始位置是(0,0,23500)您可以在问题中给出的图表中看到它。
– OldBerkay
15年1月19日在18:37
现在,当我将速度* timedelta加上0,00000000000000005到23500时,基本上不会将其相加。位置仍然是(0,0,23500)而不是(0,0,23500.00000000000005),因此地球不会移动,因此加速度不会改变。我不知道这是单位问题还是C#的浮动问题。我该怎么办?
– OldBerkay
15年1月19日在18:37
#2 楼
正如您所发现的,按比例缩小内容不一定会有所帮助。这是一些有关使用浮点数时要考虑的事项的不错的阅读方法:http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html基本进行模拟第一性原理(牛顿定律)不利于数值精度,因为您不会使数值方法受到重要影响程度的影响,因此最终会在不同尺度上将一大堆不同的影响放在一起,结果精度低。
通常,诸如行星,卫星等星历表之类的东西都不以牛顿定律开头,而是假设轨道是开普勒式的,然后是小的扰动校正。
这里是一种算法(半英制),用于计算行星的位置。
http://ssd.jpl.nasa.gov/txt/aprx_pos_planets.pdf
如果您想进行N体模拟,您似乎需要更高的精度。如果单位制阻止您使用双精度,那么我建议使用普通C#进行计算,然后在完成工作后转换为单精度。
评论
就像我在其他答案中所说的那样,开普勒方程假设人体围绕质量物体绕轨道运行。但就我而言,没有必要拥有一个。例如,身体应该能够从重物上抓弹弓。我不能用开普勒做到这一点,对吗?我严格要使用N体。关于最后一部分,您能告诉我该怎么做吗?
– OldBerkay
2015年1月19日15:43
在我看来,人们可能应该对圆形轨道(行星,卫星)使用开普勒函数,对于加速并具有非圆形轨道的较小物体,标记这些物体并可能切换到具有高频率的高频牛顿函数当它们靠近其他物体然后回到更深空间的开普勒时,采样率(也许是NASA编码)?但是我正在猜测,感谢您的想法!
– Tomachi
19年7月24日在8:45
评论
他们认为,游戏的物理引擎并不是真正地在为现实世界建模。您不能指望应用现实世界的物理公式并获得精确的结果,甚至只是非常接近的结果。一旦理解并接受了这一点,您就会发现通过根据需要调整值和公式来使其看起来可信,这将是制作游戏的更好方法。相反,如果您要进行实际的模拟,则需要实际上尝试模拟现实世界物理的软件,而不是仅仅模拟到看起来似乎熟悉的结果。抱歉,删除了我对PhysX的评论,因为我意识到这个问题与使用游戏引擎物理技术毫无关联。干杯。
也许您可能想看看他们如何在KSP中完成物理学,这是一个链接:github.com/mhoram-kerbin/ksp-physics-documentation/releases(如果我没记错的话,他们正在使用统一性)