我在检测鼠标在盒子内的点击时,使用了光线投射算法,但存在不准确的问题。我完全不知道如何正确修复它,这一直困扰着我已经几周了。
问题可以用图片最容易地描述(以[0, 0, -30]为中心的框):
黑色线条表示实际的碰撞盒,绿色盒子表示实际被点击的区域。请注意它的偏移量(如果盒子离原点越远,则似乎越大),并且稍微比绘制的碰撞盒小一些。
以下是一些相关代码, 光线-盒子投射:
问题可以用图片最容易地描述(以[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;
}
我试着将实际的光线绘制成一条线,它似乎正确地与绘制的盒子相交。
我通过将所有点和光线起点/方向减去盒子的位置部分解决了偏移问题,但我不知道为什么它有效,并且击中箱子的大小仍然不准确。
有任何想法/替代方法吗?如果需要,我可以提供其他代码。