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]):
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.
CẢM ƠN BẠN! Điều này đã được chính xác nó, rất nhiều đánh giá cao :) – sler