2011-11-03 3 views
2

나는 광선 (총에서 나온 총알을 나타냄)과 적 주위의 구 사이의 교차를 감지하는 작업 알고리즘을 얻으려고 노력했습니다. 내가 구 위치로 적의 위치를 ​​사용마우스를 ray-sphere 충돌 감지

//// 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; 
    } 

내가 가진 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

교차로를 해결하기 위해 Cramer의 규칙을 사용하는 것처럼 보입니다. 대체를 고려하십시오. 다항식의 근은 교점을 알려줍니다.

우리가 원하는 것은 원 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 

짧게. Cramer의 규칙이 미분 방정식에서 유용 할 때 컬럼이 함수와 미분을 나타낼 때만 발견했습니다. 보통 Wronskian을 찾을 때.