2011-02-15 44 views
4

我想寫一個簡單的物理模擬,其中半球和質量不同的球在完美彈性和無摩擦的環境中彈跳。我寫我自己的代碼下面這個資源:http://www.vobarian.com/collisions/2dcollisions2.pdf,我也測試了從這裏代碼:Ball to Ball Collision - Detection and Handling二維球碰撞問題:沒有能量守恆

問題EDITED

與Rick Goldstein和拉爾夫的幫助下,我已經得到了我的代碼工作(有一個錯字..)。非常感謝你的幫助。不過,我仍然困惑於爲什麼其他算法不適合我。球沿正確的方向反彈,但系統的總能量永遠不會被保存。速度變得越來越快,直到球剛開始在屏幕上的靜態位置閃爍。我實際上想在我的程序中使用這些代碼,因爲它比我寫的更簡潔。

這裏是我寫的功能算法(雖然我沒有從其他來源獲得第一位)。它在氣泡類別:

public void resolveCollision(Bubble b) 
{ 
    // get the minimum translation distance 
    Vector2 delta = (position.subtract(b.position)); 
    float d = delta.getMagnitude(); 
    // minimum translation distance to push balls apart after intersecting 
    Vector2 mtd = delta.multiply(((getRadius() + b.getRadius())-d)/d); 

    // resolve intersection -- 
    // inverse mass quantities 
    float im1 = 1/getMass(); 
    float im2 = 1/b.getMass(); 

    // push-pull them apart based off their mass 
    position = position.add(mtd.multiply(im1/(im1 + im2))); 
    b.position = b.position.subtract(mtd.multiply(im2/(im1 + im2))); 

    //get the unit normal and unit tanget vectors 
    Vector2 uN = b.position.subtract(this.position).normalize(); 
    Vector2 uT = new Vector2(-uN.Y, uN.X); 

    //project ball 1 & 2 's velocities onto the collision axis 
    float v1n = uN.dot(this.velocity); 
    float v1t = uT.dot(this.velocity); 
    float v2n = uN.dot(b.velocity); 
    float v2t = uT.dot(b.velocity); 

    //calculate the post collision normal velocities (tangent velocities don't change) 
    float v1nPost = (v1n*(this.mass-b.mass) + 2*b.mass*v2n)/(this.mass+b.mass); 
    float v2nPost = (v2n*(b.mass-this.mass) + 2*this.mass*v1n)/(this.mass+b.mass); 

    //convert scalar velocities to vectors 
    Vector2 postV1N = uN.multiply(v1nPost); 
    Vector2 postV1T = uT.multiply(v1t); 
    Vector2 postV2N = uN.multiply(v2nPost); 
    Vector2 postV2T = uT.multiply(v2t); 

    //change the balls velocities 
    this.velocity = postV1N.add(postV1T); 
    b.velocity = postV2N.add(postV2T); 
} 

這裏是行不通

public void resolveCollision(Bubble b) 
{ 
    // get the minimum translation distance 
    Vector2 delta = (position.subtract(b.position)); 
    float d = delta.getMagnitude(); 
    // minimum translation distance to push balls apart after intersecting 
    Vector2 mtd = delta.multiply(((getRadius() + b.getRadius())-d)/d); 

    // resolve intersection -- 
    // inverse mass quantities 
    float im1 = 1/getMass(); 
    float im2 = 1/b.getMass(); 

    // push-pull them apart based off their mass 
    position = position.add(mtd.multiply(im1/(im1 + im2))); 
    b.position = b.position.subtract(mtd.multiply(im2/(im1 + im2))); 

    // impact speed 
    Vector2 v = (this.velocity.subtract(b.velocity)); 
    float vn = v.dot(mtd.normalize()); 

    // sphere intersecting but moving away from each other already 
    if (vn > 0.0f) return; 

    // collision impulse (1f is the coefficient of restitution) 
    float i = (-(1.0f + 1f) * vn)/(im1 + im2); 
    Vector2 impulse = mtd.multiply(i); 

    // change in momentum 
    this.velocity = this.velocity.add(impulse.multiply(im1)); 
    b.velocity = b.velocity.subtract(impulse.multiply(im2)); 
} 

我們,如果你發現任何我知道的一個。謝謝

回答

6

在設置v1nPost的行中是否有拼寫錯誤?看起來分母應該是this.mass + b.mass,而不是this.mass * b.mass

而且,因爲你計算thisb之間的碰撞,你檢查,以確保你不是也做bthis之間的相同的碰撞,從而加倍三角洲應用到每一個參與泡沫的碰撞?

+0

雅這是錯字...我一直在電腦前呆了太久,我多次查了一遍數學。謝謝。看看我的編輯雖然,我真的想讓其他算法的工作和它絕對不是同一個問題 – Cbas 2011-02-16 02:51:26

+0

至於你的第二點,我不檢查,看看我是否已經通過氣泡解決了我的循環中的碰撞,但我不認爲這很重要,因爲我在這個resolveCollision方法中做的第一件事是將它們拉開。當循環在碰撞中找到另一個球時,它不會再發生碰撞並且不會再次調用這個方法 – Cbas 2011-02-16 02:56:36

3

我做了第一個猜測:getMass()返回一個整數(或整數)(而不是一個浮點數或雙)?

如果這是真的,比你的問題是1/getMass()將導致一個整數值(並且可能只有1或大多數時間0))。要解決由1.01.0f

這種替換1因爲一般的規則很簡單: 如果你有一個數學運算(+, - ,*,/)所產生的類型將是整數,如果沒有這兩個operants的是浮點數據結構(雙精度或浮點)

無論如何:可能會有第二個問題,可能您的計算結果不準確。那麼你應該使用double而不是float。

+0

這是一個很好的觀點。 getMass()實際上返回一個字節,在我的代碼中,到目前爲止,所有的氣泡的質量都是1.如果質量不同,我發現我會遇到問題。我會改變它,非常感謝。 – Cbas 2011-02-16 03:00:50

1

有看起來奇怪的一部分:

兩個計算:

float v1nPost = (v1n*(this.mass-b.mass) + 2*b.mass*v2n)/(this.mass*b.mass); 
float v2nPost = (v2n*(b.mass-this.mass) + 2*this.mass*v1n)/(this.mass+b.mass); 

是對稱的,除了最後的操作,第一它是在第二*+