mmu*_*phy 9 c++ algorithm physics game-physics
这个问题有一个主要问题,还有一个小问题.我相信我在研究中的任何一个问题都是正确的,但不是两者都有.
对于我的物理循环,我做的第一件事就是对我TotalForce的刚体物体施加一个引力.然后我用我TotalForce和我检查碰撞Velocity.我TotalForce会(0, 0, 0)在每次物理循环后重置,虽然我会保留我的velocity.
我熟悉在仅使用速度时在移动球体和静态平面之间进行碰撞检查.但是,如果我还有其他力量velocity,比如重力怎么办?我把其他力量放进去TotalForces(现在我只有引力).为了弥补这一点,当我确定球体当前没有与飞机重叠时,我这样做了
Vector3 forces = (sphereTotalForces + sphereVelocity);
Vector3 forcesDT = forces * fElapsedTime;
float denom = Vec3Dot(&plane->GetNormal(), &forces);
Run Code Online (Sandbox Code Playgroud)
然而,这可能是我认为假设是静止接触的问题.我认为休息接触是通过计算的
denom * dist == 0.0f
Run Code Online (Sandbox Code Playgroud)
哪里dist是
float dist = Vec3Dot(&plane->GetNormal(), &spherePosition) - plane->d;
Run Code Online (Sandbox Code Playgroud)
(作为参考,denom * dist > 0.0f球体远离飞机的明显意义)
但是,这永远不会成真.即使看起来有"休息接触".这是由于我forces上面的计算总是至少有-9.8(我的重力).y.当朝向法线为(denom0,1,0 )的平面移动时,将产生-9.8的ay .
我的问题是
1)我是否正确计算了我的前两个代码片段中提到的休息联系方式?
如果是这样,
2)我的"其他力量"如引力如何使用?我使用TotalForces不正确吗?
作为参考,我的时间步长是
mAcceleration = mTotalForces / mMass;
mVelocity += mAcceleration * fElapsedTime;
Vector3 translation = (mVelocity * fElapsedTime);
Run Code Online (Sandbox Code Playgroud)
编辑
由于某些建议的更改似乎会改变我的碰撞代码,因此我会检测碰撞状态
if(fabs(dist) <= sphereRadius)
{ // There already is a collision }
else
{
Vector3 forces = (sphereTotalForces + sphereVelocity);
float denom = Vec3Dot(&plane->GetNormal(), &forces);
// Resting contact
if(dist == 0) { }
// Sphere is moving away from plane
else if(denom * dist > 0.0f) { }
// There will eventually be a collision
else
{
float fIntersectionTime = (sphereRadius - dist) / denom;
float r;
if(dist > 0.0f)
r = sphereRadius;
else
r = -sphereRadius;
Vector3 collisionPosition = spherePosition + fIntersectionTime * sphereVelocity - r * planeNormal;
}
}
Run Code Online (Sandbox Code Playgroud)
您应该使用if(fabs(dist) < 0.0001f) { /* collided */ }This is 来计算浮点精度。在大多数角度或接触情况下,您肯定不会得到精确的 0.0f。
如果为负值dist,则实际上是在物体穿过平面时将物体移回平面表面所需的实际量。sphere.position = sphere.position - plane.Normal * fabs(dist);
将其移回表面后,您可以选择使其沿平面法线的相反方向反弹;或者只是留在飞机上。
parallel_vec = Vec3.dot(plane.normal, -sphere.velocity);
perpendicular_vec = sphere.velocity - parallel_vec;
bounce_velocity = parallel - perpendicular_vec;
totalforce = external_force + velocity除非所有东西都有单位质量,否则你不能盲目地做。
编辑:
Vector3 planeToSphere = sphere.point - plane.point;
float dist = Vector3.dot(plane.normal, planeToSphere) - plane.radius;
if(dist < 0)
{
// collided.
}
如果这是你不知道的部分,我建议你先学习更多的数学。
注意:抱歉,格式混乱......我无法将其标记为代码块。
编辑2:根据我对你的代码的理解,你要么错误地命名你的变量,要么正如我之前提到的,你需要修改你的数学和物理理论。这条线没有做任何有用的事情。
float denom = Vec3Dot(&plane->GetNormal(), &forces);
在任何时候,球体上的力可以是任何方向,与行进方向无关。因此 denom 本质上是计算平面方向上的力的大小,但不会告诉您球是否会撞击平面。例如,重力向下,但球可以具有向上的速度并撞击上方的平面。有了这个,你需要Vec3Dot(plane.normal, velocity)改为。
另外,马克·法里斯和格哈德·鲍威尔已经为您提供了线性运动学的物理方程,您可以使用它们直接计算未来的位置、速度和撞击时间。
例如s = 0.5 * (u + v) * t;给出未来时间 t 之后的位移。将该位移与距平面的距离进行比较,即可得知球体是否会撞击平面。所以,我再次建议您先阅读http://en.wikipedia.org/wiki/Linear_motion和简单的内容,然后再阅读http://en.wikipedia.org/wiki/Kinematics。
还有另一种方法,如果您期望或假设没有其他力作用在球体上,那么您可以进行射线/平面碰撞测试来找到它撞击平面的时间 t,在这种情况下,请阅读http://en .wikipedia.org/wiki/Line-plane_intersection。