我希望在游戏中实现物理引擎,以计算施加力后的物体运动轨迹。该引擎将根据物体的先前状态计算每个状态。当然,这意味着需要在两个时间单位之间进行大量计算,以保证足够精确。
为了更好地做到这一点,我首先想知道使用此方法获取位置与使用运动学方程之间的差异有多大。 因此,我编写了此代码,将模拟和方程所给出的位置(x、y、z)存储在一个文件中。
问题是,对于简单的数字(例如在-9.81重力场中的简单下落),我得到了很好的位置,但对于更大(且相当随机)的数字,我得到了不准确的位置。这是浮点数问题吗?以下是结果,包括相对误差。(注意:标签轴为法语,Temps = 时间)。图表如下:
为了更好地做到这一点,我首先想知道使用此方法获取位置与使用运动学方程之间的差异有多大。 因此,我编写了此代码,将模拟和方程所给出的位置(x、y、z)存储在一个文件中。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "header.h"
Body nouveauCorps(Body body, Vector3 force, double deltaT){
double m = body.mass;
double t = deltaT;
//Newton's second law:
double ax = force.x/m;
double ay = force.y/m;
double az = force.z/m;
body.speedx += ax*t;
body.speedy += ay*t;
body.speedz += az*t;
body.x +=t*body.speedx;
body.y +=t*body.speedy;
body.z +=t*body.speedz;
return body;
}
int main()
{
//Initial conditions:
double posX = 1.4568899;
double posY = 5.6584225;
double posZ = -8.8944444;
double speedX = 0.232323;
double speedY = -1.6565656;
double speedZ = -8.6565656;
double mass = 558.74;
//Force applied:
Vector3 force = {5.8745554, -97887.568, 543.5875};
Body body = {posX, posY, posZ, speedX, speedY, speedZ, mass};
double duration = 10.0;
double pointsPS = 100.0; //Points Per Second
double pointsTot = duration * pointsPS;
char name[20];
sprintf(name, "BN_%fs-%fpts.txt", duration, pointsPS);
remove(name);
FILE* fichier = NULL;
fichier = fopen(name, "w");
for(int i=1; i<=pointsTot; i++){
body = nouveauCorps(body, force, duration/pointsTot);
double t = i/pointsPS;
//Make a table: TIME | POS_X, Y, Z by simulation | POS_X, Y, Z by modele (reference)
fprintf(fichier, "%e \t %e \t %e \t %e \t %e \t %e \t %e\n", t, body.x, body.y, body.z, force.x*(t*t)/2.0/mass + speedX*t + posX, force.y*(t*t)/2.0/mass + speedY*t + posY, force.z*(t*t)/2.0/mass + speedZ*t + posZ);
}
return 0;
}
问题是,对于简单的数字(例如在-9.81重力场中的简单下落),我得到了很好的位置,但对于更大(且相当随机)的数字,我得到了不准确的位置。这是浮点数问题吗?以下是结果,包括相对误差。(注意:标签轴为法语,Temps = 时间)。图表如下:
- 黑色+虚线:根据运动方程计算的值
- 红色:每秒100个数据点
- 橙色:每秒1000个数据点
- 绿色:每秒10000个数据点
pos+=v_old*t+a/2*t^2
公式,可以改善模拟。另一个提示是减小deltaT。如果模拟变得更好,那么肯定是一个模拟问题。 - gezaO(Δt)
,这与您的误差图相吻合(每种情况下它都减少了一个数量级,因为您在每种情况下将步长减小了一个数量级)。这是数值积分的基本问题。 - Kyle