我有这个简单的euler集成商。为了找到精确的碰撞时间,它也应该处理负dt(我在检测到碰撞时划分帧时间并模拟回来)。
出于某种原因
someBody.update(1.0);
someBody.update(-0.3);
someBody.update(-0.3);
someBody.update(0.6);
给出的结果不同于:
someBody.update(1.0);
可能是因为我使用的是euler而不是RK4或verlet?
以下是集成商的代码:
void Body::update(double dt)
{
if (dt > 0) velocity += acceleration * (dt*dt);
else velocity -= acceleration * (dt*dt);
pos += velocity * dt;
rotation += angularVelocity * dt;
}
非常感谢!
马腾
答案 0 :(得分:3)
原因是数学。让我们关注velocity
变量:
如果你打电话:
someBody.update(1.0)
你会得到:
velocity += acceleration * 1
但如果你打电话:
someBody.update(1.0);
someBody.update(-0.3);
someBody.update(-0.3);
someBody.update(0.6);
你会得到:
velocity += acceleration * (1 - 0.3^2 - 0.32^2 + 0.6^2)
(提供velocity += acceleration * 1.18
)
你应该只有velocity += acceleration * dt;
答案 1 :(得分:0)
怀疑Body :: update中的浮点错误累积。 示例:1 + 2 + 3 + 4 = 10但1.0 + 2.0 + 3.0 + 4.0 =其他。
最简单的解决方法是在每个主要计算步骤后对结果进行舍入。
答案 2 :(得分:0)
谢谢,加速确实是错误的。
我为每个帧使用固定的时间步长。此功能用于运行部分帧的模拟。所以我现在完全忽略了这种说法。这样,帧内的所有内容都会线性发生,加速度仅在帧之间添加。
问题仍然存在。我认为这可能是Magicianeer推出的浮点错误。
虽然我认为这些错误不会如此大幅增加。在大约50帧中,弹跳物体从其全高(100)到大约一半高度。在大约200帧,它仍然在地板上。当我没有在框架内调用多个更新时,一切都很好。
我会尝试将位置保持在帧的末尾,并在进行部分帧模拟后将其放回。这样,错误就不会在多个帧上累加。