cmathraycasting

How can I detect what side the ray has hit a wall in a raycaster game engine?


I've been writing a raycaster since 2 days ago. I am using a simple and fast algorithm for detecting walls using rays. It's C btw. My question is: what check should I use to detect what face of the wall did the ray hit? I've been thinking about checking if the ray Y component is larger than the ray X component, and that would mean that I've hit the left and right faces. Right? I'm not really sure. Full code here:

    double rayAngle, wallX, wallY, rayX, rayY, h, distance, lineHeight, lineOffset, cameraAngle, shadeDistance;
    for (double ray = 0; ray < FOV * RAY_PER_DEG; ray++) // we want to raycast FOV * RAYS_PER_DEG rays
    {
        rayAngle = playerAngle + TO_RADIANS(ray / RAY_PER_DEG - FOV / 2); // set the ray angle derived from the ray index
        wallX = playerX; // set current wall coordinates to player's
        wallY = playerY; //
        rayY = sin(rayAngle) * DISTANCE_COEFFICIENT; // use vector decomposition to determine X and Y components of the ray
        rayX = cos(rayAngle) * DISTANCE_COEFFICIENT; // 
 
        for(distance = 0; distance < MAX_DISTANCE; distance++) // check for ray collision
        {
            wallX = wallX + rayX; // increase wall coordinates
            wallY = wallY + rayY;
 
            if (wallX < mapWidth && wallY < mapHeight &&       // check for wall boundaries
                wallX >= 0 && wallY >= 0 &&
                mapWalls[(int)wallY * mapHeight + (int)wallX]) // check for wall to be present
            {
                break;
            }
        }
 
        // fisheye compensation
        cameraAngle = playerAngle - rayAngle; // determine the camera angle
        WRAP_AROUND_RADIANS(cameraAngle);
        distance = distance * cos(cameraAngle); // adjust distance by x component of camera angle
 
        lineHeight = WALL_HEIGHT * MAX_WALL_HEIGHT / distance;
        lineOffset = WALL_HEIGHT - lineHeight/2; // move the line at middle
 
        // draw the ray on the map
        shadeDistance = 1 / distance;
 
        glLineWidth(1 / RESOLUTION);
        glBegin(GL_LINES);
        glColor3f(shadeDistance * SHADE_COEFFICIENT, 0, 0); // wall
        glVertex2f(ray / RESOLUTION, lineHeight + lineOffset);
        glVertex2f(ray / RESOLUTION, lineOffset);
 
        glColor3f(0, shadeDistance * SHADE_COEFFICIENT, 0); // floor
        glVertex2f(ray / RESOLUTION, lineOffset);
        glVertex2f(ray / RESOLUTION, 0);
        glEnd();
    }

https://pastebin.com/BsNYvXPf Feel free to tell me anything about the code. Edit: I have to know this to implement texture mapping.


Solution

  • Represent ray in parametric coordinates

    x = x0 + dx * t
    y = y0 + dy * t
    

    In your case dx=cos(rayAngle), dy=sin(rayAngle), and (dx,dy) is unit direction vector.

    Check intersections with vertical and horizontal line

     x0 + dx * t1 = wallX
     y0 + dy * t2 = wallY 
    

    get t1, t2

    t1 = (wallX - x0) / dx
    t2 = (wallY - y0) / dy
    

    and smaller value from t1,t2 tells us what wall will be met first.

    increase wall coordinates - do walls move?