2014-04-16 5 views
2
public double intersect(Ray r) 
{ 
    double t; 

    Vector L = r.origin.sub(pos); 

    double a = r.direction.dot(r.direction); 
    double b = 2*(r.direction.dot(L)); 
    double c = (L.dot(L)) - (radius*radius); 

    double disc = b*b - 4*a*c; 

    if (disc < 0) 
     return -1; 

    double distSqrt = Math.sqrt(disc); 
    double q; 

    if (b < 0) 
     q = (-b - distSqrt)/2; 
    else 
     q = (-b + distSqrt)/2; 

    double t0 = q/a; 
    double t1 = c/q; 

    if (t0 > t1) 
    { 
     double temp = t0; 
     t0 = t1; 
     t1 = temp; 
    } 

    if (t1 < 0) 
     return -1; 

    if (t0 < 0) 
     t = t1; 
    else 
     t = t0; 

    return t; 
} 

교차로가없는 경우 -1을 반환해야합니다.광선 구 교차 방법이 작동하지 않습니다.

반지름이 2 인 (5,0,0)에 구가 있습니다. 원점 (0,0,0)과 방향 (5,0,0) .unit이있는 광선을 통과하면 3을 반환합니다. 원점 (0,0,0)과 방향 (5,2,0) .unit이있는 광선을 통과 시키면 3.9를 반환합니다. 광선이 원점 (0,0,0)과 방향 (5,0,1) .unit을 통과 할 때 광선이 교차하더라도 -1을 반환합니다. 방향이 (5,0, -1) .unit 인 경우 t가 3보다 작을 수는 없지만 (5,0,1)과 같은 것을 반환해야하지만 방향은 2.73을 반환합니다. 보고.

답변

0

"원점 (0,0,0) 및 방향 (5,0,1) .unit"예제를 사용하여 해당 코드를 실행하면 3.15979가 반환됩니다. 내가 게시 한 모든 코드가 정확하다는 것을 알 수 있습니다. 실패를 일으키는 다른 구현 중 하나라고 생각합니다. 단위 벡터 계산, Vector.sub() 메서드, Vector.dot() 메서드 등이 될 수 있습니다.

잘못 인쇄 된 부분을 확인하기 위해 인쇄 문을 추가하십시오. 이것이 내가 보통 이런 식으로 디버깅하는 방법입니다.

또한 코드를 C++로 빠르게 변환했습니다 (자바를 모르므로). 원한다면 비교할 수 있습니다. 그것은 잘 작동하는 것 같습니다, 그것은 가능성이 문제가 귀하의 교차 기능을 의미합니다.

내 코드는 여기에 있습니다 : http://codepad.org/xldbJRKo

나는이 조금 도움이되기를 바랍니다!

0

나는 q을 계산하는 데 사용되는 상태를 잘 작성하지 생각 :

if (b < 0) 
    q = (-b - distSqrt)/2; 
else 
    q = (-b + distSqrt)/2; 

을 여기에서, 당신은 b의 부호에 따라 결정하고 있습니다. 두 값을 모두 계산해야합니다. 은 항상 음수가 아니기 때문에 첫 번째 숫자 인 (-b - distSqrt)/2은 항상 q의 더 작은 값을 제공합니다. (-b - distSqrt)/2이 음수 인 경우에만 (-b + distSqrt)/2을 확인해야하는 경우가 있습니다. 이 경우는 광선의 원점이 구 안쪽에있을 때 나타납니다.

그리고 t1 = c/q 것이 필요합니까? q의 양수 값이 작 으면 a이 양수 여야하고 방향이 단위 벡터 인 경우 1이므로 완료됩니다. 내 구현에서

, 내가 계산 이런 식으로했다 :

double Sphere::getIntersection(Ray ray) 
{ 
    Vector v = ray.origin - center; 
    double b = 2 * dot(ray.dir, v); 
    double c = dot(v, v) - radius * radius; 
    double d = b * b - 4 * c; 
    if(d > 0) 
    { 
     double x1 = (-b - sqrt(d))/2; 
     double x2 = (-b + sqrt(d))/2; 
     if(x1 >= 0 && x2 >= 0) return x1; 
     if(x1 < 0 && x2 >= 0) return x2; 
    } 
    return -1; 
} 

을하고 그것을 잘 작동했다.