Domanda

Ho avuto un problema con le inesattezze nel mio algoritmo di casting Ray per rilevare colpi di mouse all'interno di una scatola. Sono completamente in perdita su come risolverlo correttamente e mi ha infastidito per settimane.

Il problema è più semplice descritto con un'immagine (scatola incentrata su [0, 0, -30]):

screen shot of problem

Le linee nere rappresentano il vero hitbox che viene disegnato e la scatola verde rappresenta ciò che sembra effettivamente essere colpito. Nota come è offset (che sembra diventare più grande se la scatola è più lontano dall'origine) ed è leggermente più piccola del hitbox disegnato.

Ecco un codice pertinente,

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

Ho provato a disegnare il raggio reale come linea e sembra intersecare correttamente la scatola disegnata.

Ho avuto il problema dell'offset in parzialmente risolto minustando tutti i punti e l'origine/direzione Ray dalla posizione delle scatole, ma non ho idea del perché funzionasse e le dimensioni del hitbox sono rimaste imprecise.

Qualche idea/approcci alternativi? Ho un altro codice da fornire se è necessario.

Nessuna soluzione corretta

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top