1
\$\begingroup\$

I'm writing a raycasting engine in C++ and SFML.

I have the wall texturing done and I'm trying to get floor and ceiling texturing right.

I almost got it but the textures are "sliding" when the player moves, as illustrated here:

Display of 'sliding' effect

(Source)

I followed lodev tutorial agian and again but I can't get whats wrong. The code is available at https://github.com/Bazouz660/Raycaster-.git

Any help would be greatly appreciated.

Here is the raycasting algorythm :

Raycaster::Ray Raycaster::castRay(sf::Vector2f playerPosition, float angle, float refAngle, int x)
{
    Ray ray;
    sf::Vector2f rayStart = playerPosition / (float)m_grid.getTileSize();
    sf::Vector2f rayDir = normalize(sf::Vector2f(std::cos(angle), std::sin(angle)));
    sf::Vector2f unitStepSize = {std::sqrt(1 + (rayDir.y / rayDir.x) * (rayDir.y / rayDir.x)),
                                 std::sqrt(1 + (rayDir.x / rayDir.y) * (rayDir.x / rayDir.y))};
    sf::Vector2i mapCheck = {(int)rayStart.x, (int)rayStart.y};
    sf::Vector2f rayLength1D;
    sf::Vector2i step;
    sf::Vector2f intersection;
    sf::Texture *texture = ResourceManager::getInstance().getTexture("wall");
    sf::Image *image = ResourceManager::getInstance().getTextureImage("wall");
    bool tileFound = false;
    float distance = 0.0f;
    float perpWallDist = 0.0f;

    if (rayDir.x < 0)
    {
        step.x = -1;
        rayLength1D.x = (rayStart.x - float(mapCheck.x)) * unitStepSize.x;
    }
    else
    {
        step.x = 1;
        rayLength1D.x = (float(mapCheck.x + 1) - rayStart.x) * unitStepSize.x;
    }
    if (rayDir.y < 0)
    {
        step.y = -1;
        rayLength1D.y = (rayStart.y - float(mapCheck.y)) * unitStepSize.y;
    }
    else
    {
        step.y = 1;
        rayLength1D.y = (float(mapCheck.y + 1) - rayStart.y) * unitStepSize.y;
    }

    while (!tileFound && distance < RENDER_DISTANCE)
    {
        if (rayLength1D.x < rayLength1D.y)
        {
            mapCheck.x += step.x;
            distance = rayLength1D.x;
            rayLength1D.x += unitStepSize.x;
            ray.side = 0;
        }
        else
        {
            mapCheck.y += step.y;
            distance = rayLength1D.y;
            rayLength1D.y += unitStepSize.y;
            ray.side = 1;
        }

        if (mapCheck.x >= 0 && mapCheck.x < m_grid.getWidth() && mapCheck.y >= 0 && mapCheck.y < m_grid.getHeight())
        {
            if (m_grid.getTile(mapCheck.x, mapCheck.y).type != 0)
            {
                tileFound = true;
            }
        }
    }

    if (tileFound)
    {
        intersection = rayStart + rayDir * distance;
    }
    else
        intersection = rayStart;

    float angleFromRef = refAngle - angle;
    if (angleFromRef < 0)
        angleFromRef += 2 * PI;
    if (angleFromRef > 2 * PI)
        angleFromRef -= 2 * PI;

    ray.length = (distance * float(m_grid.getTileSize())) * std::cos(angleFromRef);

    // Calculate distance of perpendicular ray (Euclidean distance would give fisheye effect!)
    if (ray.side == 0)
        perpWallDist = (rayLength1D.x - unitStepSize.x);
    else
        perpWallDist = (rayLength1D.y - unitStepSize.y);

    // calculate value of wallX
    double wallX; // where exactly the wall was hit
    if (ray.side == 0)
        wallX = rayStart.y + perpWallDist * rayDir.y;
    else
        wallX = rayStart.x + perpWallDist * rayDir.x;
    wallX -= floor((wallX));

    // Floor and ceiling casting, bugged rn as the textures slides under the walls

    // Calculate height of line to draw on screen
    int lineHeight = (int)(RESY / (ray.length / m_grid.getTileSize()));

    // calculate lowest and highest pixel to fill in current stripe
    int drawStart = -lineHeight / 2 + RESY / 2;
    if (drawStart < 0)
        drawStart = 0;
    int drawEnd = lineHeight / 2 + RESY / 2;
    if (drawEnd >= RESY)
        drawEnd = RESY - 1;

    // FLOOR CASTING (vertical version, directly after drawing the vertical wall stripe for the current x)
    double floorXWall, floorYWall; // x, y position of the floor texel at the bottom of the wall

    // 4 different wall directions possible
    if (ray.side == 0 && rayDir.x > 0)
    {
        floorXWall = mapCheck.x;
        floorYWall = mapCheck.y + wallX;
    }
    else if (ray.side == 0 && rayDir.x < 0)
    {
        floorXWall = mapCheck.x + 1.0;
        floorYWall = mapCheck.y + wallX;
    }
    else if (ray.side == 1 && rayDir.y > 0)
    {
        floorXWall = mapCheck.x + wallX;
        floorYWall = mapCheck.y;
    }
    else
    {
        floorXWall = mapCheck.x + wallX;
        floorYWall = mapCheck.y + 1.0;
    }

    double distWall, currentDist;

    distWall = (ray.length / m_grid.getTileSize());

    if (drawEnd < 0)
        drawEnd = RESY; // becomes < 0 when the integer overflows

    // draw the floor from drawEnd to the bottom of the screen
    for (int y = drawEnd + 1; y < RESY; y++)
    {
        currentDist = RESY / (2.0 * y - RESY); // you could make a small lookup table for this instead

        double weight = (currentDist) / (distWall);

        double currentFloorX = weight * floorXWall + (1.0 - weight) * (rayStart.x);
        double currentFloorY = weight * floorYWall + (1.0 - weight) * (rayStart.y);

        int floorTexX, floorTexY;
        floorTexX = int(currentFloorX * texture->getSize().x * 1.25) % texture->getSize().x;
        floorTexY = int(currentFloorY * texture->getSize().y * 1.25) % texture->getSize().y;

        // floor
        m_floorGroundImage.setPixel(x, y, image->getPixel(floorTexX, floorTexY));
        // ceiling (symmetrical!)
        m_floorGroundImage.setPixel(x, RESY - y - 1, image->getPixel(floorTexX, floorTexY));
    }

    ray.wallX = wallX;
    ray.color = m_grid.getTile(mapCheck.x, mapCheck.y).color;
    ray.direction = rayDir;
    ray.origin = playerPosition;
    m_zBuffer[x] = ray.length;
    ray.vertices[0].position = ray.origin;
    ray.vertices[0].color = ray.color;
    ray.vertices[1].position = (intersection * float(m_grid.getTileSize()));
    ray.vertices[1].color = ray.color;
    return ray;
}
\$\endgroup\$
0

0

You must log in to answer this question.

Browse other questions tagged .