使用光线投射的对象拾取

Posted

技术标签:

【中文标题】使用光线投射的对象拾取【英文标题】:Object picking with ray casting 【发布时间】:2012-02-23 02:23:38 【问题描述】:

我的光线投射算法在检测框内的鼠标命中时遇到了不准确的问题。我完全不知道如何正确解决这个问题,而且它已经困扰了我好几个星期了。

这个问题最容易用图片来描述(以 [0, 0, -30] 为中心的框):

黑线代表实际绘制的命中框,绿框代表实际看起来被命中的地方。注意它是如何偏移的(如果框离原点更远,它似乎会变大)并且比绘制的命中框略小。

这是一些相关的代码,

光线盒投射:

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;

我尝试将实际光线绘制为一条线,它似乎与绘制的框正确相交。

我通过减去所有点和光线原点/方向通过盒子位置部分解决了偏移问题,但我不知道为什么会这样,并且命中框的大小仍然不准确。

有什么想法/替代方法吗?如果需要,我还有其他代码可以提供。

【问题讨论】:

【参考方案1】:

你假设一个错误的方向。正确的是:

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

不减去远近交点,你的方向就会偏离。

【讨论】:

谢谢!就是这样,非常感谢:)

以上是关于使用光线投射的对象拾取的主要内容,如果未能解决你的问题,请参考以下文章

正交相机和使用光线投射选择对象

使用光线投射和实例化对象问题检查与多边形碰撞器的碰撞(统一)

为啥我的光线投射会击中错误的对象?

使用光线投射时如何重新着色所有模型的零件?

使用光线投射防止破折号穿过墙壁

统一进行光线投射时出现 NullReferenceException