2012-02-23 33 views
9

Tôi đã gặp sự cố với các thuật toán không chính xác trong thuật toán truyền tia để phát hiện các lần truy cập chuột trong một hộp. Tôi hoàn toàn thua lỗ như thế nào để sửa lỗi này đúng cách và nó đã làm tôi thất vọng trong nhiều tuần.Chọn đối tượng bằng cách đúc ray

Vấn đề là đơn giản nhất được mô tả với một hình ảnh (hộp xoay quanh [0, 0, -30]):

screen shot of problem

Các đường màu đen đại diện cho hitbox thực tế đó được vẽ và hộp màu xanh lá cây tượng trưng cho những gì thực sự xuất hiện để có được hit. Chú ý nó bù đắp như thế nào (có vẻ như sẽ lớn hơn nếu hộp được thêm từ nguồn gốc) và nhỏ hơn một chút so với hitbox được vẽ.

Dưới đây là một số mã có liên quan,

ray hộp dàn diễn viên:

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; 
} 

chuột để ray:

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; 
} 

Tôi đã thử vẽ tia thực tế như một và dường như giao cắt hộp được vẽ chính xác.

Tôi đã khắc phục vấn đề một phần bằng cách tận dụng tất cả các điểm và nguồn gốc/hướng tia theo vị trí hộp, nhưng tôi không biết tại sao nó hoạt động và kích thước của hộp kiểm vẫn không chính xác.

Bất kỳ ý tưởng/phương pháp thay thế nào? Tôi có mã khác để cung cấp nếu cần.

Trả lời

10

Bạn đang giả định hướng sai. Chính xác sẽ là:

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

Nếu không trừ các điểm giao nhau gần và xa, hướng của bạn sẽ bị tắt.

+0

CẢM ƠN BẠN! Điều này đã được chính xác nó, rất nhiều đánh giá cao :) – sler

Các vấn đề liên quan