2011-11-03 23 views
2

我一直在試圖找到一個工作算法,檢測射線(代表從槍的子彈)和敵人周圍的球體之間的交集....我嘗試了幾個發現網,但沒有一個似乎能夠正常工作,也許我做錯了什麼......鼠標到射線 - 球體碰撞檢測

這是我目前使用的一個:

//// Ray-sphere intersection. 
    // p=(ray origin position - sphere position), 
    // d=ray direction, 
    // r=sphere radius, 
    // Output: 
    // i1=first intersection distance, 
    // i2=second intersection distance 
    // i1<=i2 
    // i1>=0 
    // returns true if intersection found,false otherwise.// 


    bool Player::RaySphereIntersect(const Vector3 &p, const Vector3 &d, double r,     double &i1, double &i2){ 
double det,b; 
b = -Vector3::dot(p,d); 
det = b*b - Vector3::dot(p,p) + r*r;  
if (det<0){  
    return false; 
} 
det= sqrt(det); 
i1= b - det;  
i2= b + det;  

// intersecting with ray? 
if(i2<0) 
    return false; 
if(i1<0) 
    i1=0; 
return true; 
    } 

如果我用的是敵人的球位置的位置,大致玩家的槍的位置爲射線源,投影的射線方向爲鼠標座標......這是我用來將鼠標座標投影到遠處的OpenGL代碼飛機:

Vector3 projectedMouse(float mx, float my){ 

GLdouble model_view[16]; 
GLint viewport[4]; 
GLdouble projection[16]; 

GLfloat winX, winY, winZ; 
GLdouble dx, dy, dz, bx, by, bz; 

glGetDoublev(GL_MODELVIEW_MATRIX, model_view); 
glGetDoublev(GL_PROJECTION_MATRIX, projection); 
glGetIntegerv(GL_VIEWPORT, viewport); 

winX = (float)mx; 
winY = (float)viewport[3] - (float)my; 

glReadPixels ((int)mx, (int)winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ); 
gluUnProject(winX, winY, 1, model_view, projection, viewport, &dx, &dy, &dz); 

projectedAim = Vector3(dx, dy, dz); 

return projectedAim; 
    } 

這似乎是正確的COS我畫一個線GL與它和它看起來罰款...因此,也許它的交集的代碼,但似乎沒有任何工作....我想這等一個應該返回交叉點距離,但對於任何給定的敵人的位置,但它仍然給了我非常隨機的結果:

double intersectRaySphere(Vector3 rO, Vector3 rV, Vector3 sO, double sR) 
     Vector3 Q = sO-rO; 
     double c = Q.magnitude(); 
     double v = Vector3::dot(Q,rV); 
     double d = sR*sR - (c*c - v*v); 

     // If there was no intersection, return -1 
     if (d < 0.0) return (-1.0f); 

     // Return the distance to the [first] intersecting point 
     return (v - sqrt(d)); 

他們都被稍微修改,以在我使用的庫相匹配的數學函數...任何人都可以發現他們有什麼問題,或者建議他人嗎?這讓我發瘋......

謝謝!

+0

縮小範圍:交叉碼或OpenGL狀態中的問題是否爲讀取/解釋? – genpfault

+0

這是一個確定的交點,因爲一條線正在繪製,因此它的鼠標座標和投影似乎沒問題! – Alex

回答

2

看起來你正在用克拉默法則來解決交集。考慮替代。多項式的根將告訴你交點。

從2D案例開始,我們想要看看位於圓C中心的點P的正交(因此最小)距離是否小於圓C的半徑R的距離。

基本上。我們找到圓心和光線/線之間的最小距離。我們如何做到這一點?有幾種方法。

我們知道最短距離是一條直線,它具有正交斜率(在R2負向收信人)對我們的射線開始於圓圈的中間。然後我們找到我們兩條線的交點。如果我們不得不超過長度R,我們就不在外面,我們也不在乎它有多遠。

http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html

解決兩條線的交叉點,看到它的交集是進一步除R可能不是最有效的方法,但幸運的是鎢有一個更好的方式使用更高級別的數學基本上做同樣的事情。

現在考慮一個R3與射線相交的射線基本上是相同的東西,但「正交」比R2更難取悅,所以我們使用雙交叉產品。並解決參數方程。

http://www.cs.umbc.edu/~olano/435f02/ray-sphere.html

這是一個聰明的方法,如果我們的射線的任何部分滿足我們作爲一個約束球的方程。

float a = Vector3::dot(d,d); 
float b = Vector3::dot(d * 2, p); 
float c = Vector3::dot(p,p) - r*r 
// if the discriminant of the quadratic formula is positive 
// we have at least one intersection 
return (b*b - 4 * a * c) >= 0 

總之。當我的列是函數及其派生詞時,我只發現克拉默法則對微分方程有幫助。通常在找到Wronskian時。