Question

J'ai eu un problème avec des inexactitudes dans mon algorithme de coulée de rayons pour détecter les coups de souris dans une boîte. Je suis complètement à court de savoir comment corriger cela correctement et cela me dérange depuis des semaines.

Le problème est le plus facile décrit avec une image (boîte centrée sur [0, 0, -30]):

screen shot of problem

Les lignes noires représentent la Hitbox réelle qui est dessinée et la boîte verte représente ce qui semble réellement être touché. Remarquez comment il est décalé (qui semble s'agrandir si la boîte est plus éloignée de l'origine) et est légèrement plus petite que la Hitbox dessinée.

Voici un code pertinent,

Ray-Box Cast:

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

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

J'ai essayé de dessiner le rayon réel comme une ligne et il semble couper correctement la boîte dessinée.

J'ai eu le problème de décalage partiellement résolu en insignifiant tous les points et la position d'origine / direction du rayon par la position des boîtes, mais je ne sais pas pourquoi cela a fonctionné et la taille de la hitbox est restée inexacte.

Des idées / approches alternatives? J'ai un autre code à fournir si cela est nécessaire.

Pas de solution correcte

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top