2012-02-23 116 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 2012-02-23 11:00:24