У меня возникла проблема с неточностями в моем алгоритме литья лучей для обнаружения попаданий мыши в ящик. Я совершенно не понимаю, как правильно это исправить, и это беспокоило меня в течение нескольких недель.Сбор объектов с лучевым литьем
Проблемы проще всего описывается с изображением (окно вокруг [0, 0, -30]):
черными линиями представляют собой фактический хитбокс, который втягивается и зеленый прямоугольник представляет что на самом деле похоже на удар. Обратите внимание на то, как он смещается (что, кажется, становится больше, если поле находится дальше от начала) и немного меньше, чем нарисованный 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 все еще оставался неточным.
Любые идеи/альтернативные подходы? У меня есть другой код для поставки, если это необходимо.
СПАСИБО! Это было именно это, очень ценилось :) – sler