2012-02-23 6 views
9

У меня возникла проблема с неточностями в моем алгоритме литья лучей для обнаружения попаданий мыши в ящик. Я совершенно не понимаю, как правильно это исправить, и это беспокоило меня в течение нескольких недель.Сбор объектов с лучевым литьем

Проблемы проще всего описывается с изображением (окно вокруг [0, 0, -30]):

screen shot of problem

черными линиями представляют собой фактический хитбокс, который втягивается и зеленый прямоугольник представляет что на самом деле похоже на удар. Обратите внимание на то, как он смещается (что, кажется, становится больше, если поле находится дальше от начала) и немного меньше, чем нарисованный hitbox.

Вот некоторые соответствующий код,

лучей коробка литая:

double BBox::checkFaceIntersection(Vector3 points[4], Vector3 normal, Ray3 ray) { 

    double rayDotNorm = ray.direction.dot(normal); 
    if(rayDotNorm == 0) return -1; 

    Vector3 intersect = points[0] - ray.origin; 
    double t = intersect.dot(normal)/rayDotNorm; 
    if(t < 0) return -1; 

    // Check if first point is from under or below polygon 
    bool positive = false; 
    double firstPtDot = ray.direction.dot((ray.origin - points[0]).cross(ray.origin - points[1])); 
    if(firstPtDot > 0) positive = true; 
    else if(firstPtDot < 0) positive = false; 
    else return -1; 

    // Check all signs are the same 
    for(int i = 1; i < 4; i++) { 
     int nextPoint = (i+1) % 4; 
     double rayDotPt = ray.direction.dot((ray.origin - points[i]).cross(ray.origin - points[nextPoint])); 
     if(positive && rayDotPt < 0) { 
      return -1; 
     } 
     else if(!positive && rayDotPt > 0) { 
      return -1; 
     } 
    } 

    return t; 
} 

мышь лучу:

GLint viewport[4]; 
GLdouble modelMatrix[16]; 
GLdouble projectionMatrix[16]; 

glGetIntegerv(GL_VIEWPORT, viewport); 
glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix); 
glGetDoublev(GL_PROJECTION_MATRIX, projectionMatrix); 

GLfloat winY = GLfloat(viewport[3] - mouse_y); 

Ray3 ray; 
double x, y, z; 
gluUnProject((double) mouse_x, winY, 0.0f, // Near 
       modelMatrix, projectionMatrix, viewport, 
       &x, &y, &z); 
ray.origin = Vector3(x, y, z); 

gluUnProject((double) mouse_x, winY, 1.0f, // Far 
       modelMatrix, projectionMatrix, viewport, 
      &x, &y, &z); 
ray.direction = Vector3(x, y, z); 

if(bbox.checkBoxIntersection(ray) != -1) { 
    std::cout << "Hit!" << std::endl; 
} 

Я пытался рисовать фактический луч в виде и кажется, что он правильно пересекает рисованный прямоугольник.

У меня была проблема смещения, частично устраненная, минуя все точки и начало/направление луча по положению в ящиках, но я понятия не имею, почему это сработало, а размер hitbox все еще оставался неточным.

Любые идеи/альтернативные подходы? У меня есть другой код для поставки, если это необходимо.

ответ

10

Вы принимаете неправильное направление. Правильно было бы:

ray.direction = Vector3(far.x - near.x, far.y - near.y, far.z - near.z); 

Без вычитания точек пересечения вблизи и дальности ваше направление будет выключено.

+0

СПАСИБО! Это было именно это, очень ценилось :) – sler

Смежные вопросы