2014-12-16 1 views
2

Я пишу проект трассировки лучей с C++ и OpenGL и сталкиваюсь с некоторыми препятствиями с помощью функции пересечения сферы: я проверил несколько источников и математика выглядит правильно, но почему-то для каждого луча метод пересечения возвращает true. Вот код функции пересечения сферы, а также какой-либо другой код для осветления:Ray Tracing - пересечение геометрической сферы - функция пересечения возвращает true для всех лучей, несмотря на отсутствие пересечения

bool intersect(Vertex & origin, Vertex & rayDirection, float intersection) 
{ 
    bool insideSphere = false; 
    Vertex oc = position - origin; 
    float tca = 0.0; 
    float thcSquared = 0.0; 

    if (oc.length() < radius) 
     insideSphere = true; 

    tca = oc.dot(rayDirection); 

    if (tca < 0 && !insideSphere) 
     return false; 

    thcSquared = pow(radius, 2) - pow(oc.length(), 2) + pow(tca, 2); 

    if (thcSquared < 0) 
     return false; 

    insideSphere ? intersection = tca + sqrt(thcSquared) : intersection = tca - sqrt(thcSquared); 

    return true; 
} 

Вот некоторые из контекста функции трассировки лучей, которая вызывает функцию пересечения. FYI моя камера в (0, 0, 0), и что это то, что в моей переменной «происхождения» в трассировки лучей функция:

#define WINDOW_WIDTH 640 
#define WINDOW_HEIGHT 480 

#define WINDOW_METERS_WIDTH 30 
#define WINDOW_METERS_HEIGHT 20 
#define FOCAL_LENGTH 25 


rayDirection.z = FOCAL_LENGTH * -1; 
for (int r = 0; r < WINDOW_HEIGHT; r++) 
{ 
    rayDirection.y = (WINDOW_METERS_HEIGHT/2 * -1) + (r * ((float)WINDOW_METERS_HEIGHT/(float)WINDOW_HEIGHT)); 
    for (int c = 0; c < WINDOW_WIDTH; c++) 
    { 
     intersection = false; 
     t = 0.0; 

     rayDirection.x = (WINDOW_METERS_WIDTH/2 * -1) + (c * ((float)WINDOW_METERS_WIDTH/(float)WINDOW_WIDTH)); 

     rayDirection = rayDirection - origin; 

     for (int i = 0; i < NUM_SPHERES; i++) 
     { 
      if (spheres[i].intersect(CAM_POS, rayDirection, t)) 
      { 
       intersection = true; 
      } 
     } 

Спасибо за взглянуть и дайте мне знать, если есть какие-либо другие код, который может помочь!

+0

Ну, 'intersect()' имеет два 'return true' в нем, который говорит ваш отладчик, продолжает получать удар? – genpfault

+1

Должно быть только одно утверждение «return true»; другой просто присваивает значение «insideSphere» истинное значение. – jdark135

+0

Извините, понимание чтения не выполнено. – genpfault

ответ

2

Кажется, у вас немного математическая математика. Первая часть функции, т.е. до первого return false, в порядке и вернет false, если луч начнется за пределы сферы и не идет к нему. Тем не менее, я думаю, что вы помещаете камеру за пределы своих сфер таким образом, чтобы все сферы были видны, поэтому эта часть никогда не возвращает false.

thcSquared действительно неправильно, и я не знаю, что он должен представлять.

Давайте сделаем пересечение математически. Мы имеем:

  • origin: начало луча, давайте назовем это A
  • rayDirection: направление бесконечного луча, давайте назовем это d.
  • position: центр шара, называется P
  • radius: само за себя, называется r

То, что вы хотите, это точка на обеих сферы и линии, давайте назовем его M:

  • M = A + t * d, потому что он находится на линии
  • |M - P| = r, потому что он находится на зр здесь

Второе уравнение можно изменить как |A + t * d - P|² = r², что дает (A - P)² + 2 * t * (A - P).dot(d) + t²d² = r². Это простое квадратичное уравнение. После того, как вы решили, у вас есть 0, 1 или 2 решения, выберите ближайший к лучу (но положительный).

редактировать: Вы вынуждены использовать другой подход, который я буду подробно здесь:

  1. Вычислить расстояние между центром шара и линией (вызывающей его l). Это делается путем «проецирования» центра на линию. Итак:

    tca = ((P - A) dot d)/|d|, или с вашими именами переменных, tca = (OC dot rd)/|rd|. Проекция H = A + tca * d и l = |H - P|.

  2. Если l > R, тогда верните false, нет пересечения.

  3. Позвоните нам по телефону M с одной точкой пересечения. Треугольник MHP имеют прямой угол, поэтому MH² + HP² = MP², в других терминах thc² + l² = r², поэтому мы теперь имеем thc, расстояние от H до сферы.

  4. Со всем этим, t = tca +- thc, просто возьмите нижний неотрицательный из двух.

В документе вы связаны объяснить это, но не сказать, что он предполагает норму направления луча, чтобы быть 1. Я не вижу нормализации в вашем коде, который может быть, почему ваш код не удается (не проверено).

Примечание стороны: имя Vertex для 3D-вектора действительно выбрано неудачно, что-то вроде Vector3 или vec3 будет намного лучше.

+0

Алгоритм, который мы используем для этот проект основан на алгоритме в слайде 13 в этой презентации: http://www.vis.uky.edu/~ryang/teaching/cs535-2012spr/Lectures/13-RayTracing-II.pdf. Вы, похоже, имеете смысл, и я попробую это, чтобы увидеть, исправляет ли он мою проблему, но в конечном счете и, к сожалению, мне приходится использовать геометрический алгоритм. – jdark135

+0

Также очень согласен с комментарием по имени Vertex; единственная причина, по которой она используется, заключается в том, что она была переработана из более раннего проекта. – jdark135

+0

Хорошо, я увижу ваш алгоритм - может потребоваться некоторое время, так как я должен есть в то же время;) – Synxis