2012-05-15 33 views
0

簡版:將球體移動到飛機從未預測未來碰撞

如何正確地將重力添加到我的物理更新中?

詳細版本:

我有其中用於移動球體平面通用碰撞算法(下面貼供參考)的問題將永遠不會打到這裏未來的衝突將被檢測點。我相信這是由於我有我的物理更新。

我已經設置好了,只有當確定會有未來的碰撞時,重力纔會應用到物體上。因此,在將重力應用於物體之前,首先要完成碰撞檢查。然而,由於總是假定永遠不會有未來的碰撞,所以不會有重力不會被施加。設想一個場景,其值爲

spherePosition = (0, 5, 0) 
sphereVelocity = (2, 0, 0) 
sphereRadius = 1 
planeOrigin = (0, 0, 0) 
planeNormal = (0, 1, 0) 

這總是假定球體正在移動平面。因此,重力永遠不會被應用。

我的更新比較簡單,如

mAcceleration = mTotalForces/mMass; 
Vector3 translation = (mVelocity * fElapsedTime) + 0.5 * mAcceleration * pow(fElapsedTime, 2); 
mVelocity += mAcceleration * fElapsedTime; 

所以操作的順序大致是

int collisionResult = checkCollision(sphere, plane); 
if(collisionResult == 2) 
{ 
    sphere.applyGravity(); // Just sets "mAcceleration" to (0, -9.81, 0). Which is then removed by my physics update. 
} 
sphere.update(timeSlice); 

與所有的這樣說,我什麼時候應該在應用重力到我的對象物理更新循環以及如何?如果我在碰撞檢查前應用它,在碰撞檢查過程中,如果我之後要這樣做,如果將來會發生碰撞,應如何調整更新?

碰撞測試基準:

int IntersectMovingSpherePlane(float sphereRadius, const Vector3& sphereCenter, const Vector3& sphereVelocity, const Vector3& planeNormal, 
    const Vector3& planeOrigin, float planeD, float &t, Vector3 &q) 
{ 
    // Compute distance of sphere center to plane 
    float dist = Vec3Dot(&planeNormal, &sphereCenter) - planeD; 
    if (fabs(dist) <= sphereRadius) { 
     // The sphere is already overlapping the plane. Set time of 
     // intersection to zero and q to sphere center 
     t = 0.0f; 
     q = sphereCenter; 
     return 0; 
    } else { 
     float denom = Vec3Dot(&planeNormal, &sphereVelocity); 
     if (denom * dist >= 0.0f) { 
      // No intersection as sphere moving parallel to or away from plane 
      return 1; 
     } else { 
      // Sphere is moving towards the plane 

      // Use +r in computations if sphere in front of plane, else -r 
      float r = dist > 0.0f ? sphereRadius : -sphereRadius; 
      t = (r - dist)/denom; 
      q = sphereCenter + t * sphereVelocity - sphereRadius * planeNormal; 
      return 2; 
     } 
    } 
} 
+0

我不確定你的問題到底是什麼。你確定不要「只有在沒有碰撞的情況下才施加重力」(換句話說:只要物體不接觸就施加重力)。另外,我總是會應用重力,然後只需對座標設置限制或爲飛機下方的物體添加反作用力。 – kritzikratzi

+0

@kritzikratzi:那是我正在做的一部分。問題是,即使我應用重力,由於我的物理更新(我公佈了代碼示例),它並不重要。你將如何「對座標設置限制或爲飛機下方的物體添加反作用力」。 – mmurphy

+0

一個令人厭惡的方式,很好開始,可能是:始終做sphere.applyGravity()。然後做所有你的物理的東西。之後做sphereCenter.y = max(0,sphereCenter.y); 我仍然不確定你要在這裏做什麼。我還沒有聽說過在某些情況下引力適用的世界。 – kritzikratzi

回答

1

在這裏可以最簡單的方法是使重力mTotalForces的一部分。

更多的物理方法是使重力成爲一個單獨的加速度。並加入到`mTotalForces/mMass」之後的最終加速度值。

編輯

Vector3 translation = (mVelocity * fElapsedTime) + 0.5 * mAcceleration * pow(fElapsedTime, 2);

看來這裏你的代碼是勻速運動。但是,如果你想有一個球停止下降後對於這樣的非均勻運動,通常我們只是細分時間框架,並在很短的時間內進行均勻計算,以使運動可以被認爲是均勻的,並且忽略累積誤差。

+0

你能說說你的第二點嗎?我認爲你提到的第一點是最簡單的方法,但是,正如我在這個線程中演示的那樣:http://stackoverflow.com/questions/10393840/determining-resting-contact-between-sphere-and-plane-when-using外力......不幸的是,情況並非如此。無論是哪種情況,我寧願以更「正確」的方式去做。 – mmurphy

+0

您能否解釋「細分時間框架並在很短的時間內進行統一計算,以使運動可以被認爲是統一的,並忽略累積誤差」? – mmurphy

1

將物理添加到系統的正確方法是使用迭代過程,稱爲runge-kutta method(或牛頓,一階runge-kutta)。

基本上,你的模型將有質量與時間演變的粒子。你必須「模型化」的唯一的東西就是每個滴答的每個粒子上施加的力量。用那個,你計算加速度。

如果世界有重力,你必須說每個粒子的加速度都是-g(負向指向下,在這種情況下與質量無關)。

例如,一階龍格 - 庫塔是:

newVelocity = oldVelocity + tickAcceleration*dt 
newPosition = oldPosition + newVelocity*dt 

其中dt爲您選擇適合您蜱的時間步。

通常,爲了避免物體通過其他物體傳遞,您實際上並不計算新的*。你計算一個建議的位置:

proposedVelocity = oldVelocity + tickAcceleration*dt 
proposedPosition = oldPosition + proposedVelocity*dt 

然後計算碰撞條件(你測試每個粒子對其他)。如果粒子碰撞,則應用碰撞方程(例如elastic collision),並相應地更新newPositions/velocity。如果他們沒有相撞,更新新的*與建議*值,

newVelocity = proposedVelocity 
newPosition = proposedPosition 

編輯:

在一個1º逼近,這不要緊,你使用哪一個的碰撞。然而,2°逼近可以首先計算建議的速度和位置。然後檢查舊位置和新位置之間是否發生碰撞,並計算我稱之爲dtCol的碰撞時間。然後,我們可以將時間步分爲兩部分:碰撞前,dtCol和碰撞dt-dtCol之後。第一部分是將建議的數量設置爲

proposedVelocityBeforeCollision = oldVelocity + tickAcceleration*dtCol 
proposedPositionBeforeCollision = oldPosition + proposedVelocityBeforeCollision*dtCol 

這個量恰好在碰撞之前。您現在可以使用那麼然後用碰撞方程來計算提議的VelocityAfterCollision(提出的PositionAfterCollision = proposedPosition)。

之後,您更新新的*量:

newVelocity = proposedVelocityAfterCollision + tickAcceleration*(dt-dtCol) 
newPosition = proposedPosition + newVelocity*(dt-dtCol) 

注意,此過程不會考慮選擇一個以上的碰撞。

希望這會有所幫助。

+0

因此,如果發生碰撞,無視建議的速度和提議的位置?當我正在做我的碰撞檢查(需要速度)時,我應該使用哪種速度? – mmurphy

+0

更新了文字以解釋您提出的問題。 –