Raycasting 3D, перекрывающиеся стены, когда игрок находится на определенной высоте - PullRequest
0 голосов
/ 17 февраля 2020

Когда игрок находится на определенной высоте (floor(pos) + [0.5, 0.99]), лучи попадают в неправильные стены и неправильно отображают изображение.

void Player::ray(float cameraX, float cameraY) const
{
    float zOffset = 0.5; //The size of the player is equal to 1/2 block
    Vector3f rayDir(_dir.x + _plane.x * cameraX, _dir.y + _plane.y * cameraX,0.5 * cameraY);
    Vector3f step((rayDir.x < 0) ? -1 : 1, (rayDir.y < 0) ? -1 : 1, (rayDir.z < 0) ? 1 : -1);
    Vector3f coord(std::floor(_pos.x), std::floor(_pos.y), std::floor(_pos.z));
    Vector3f deltaDist(std::abs(1 / rayDir.x), std::abs(1 / rayDir.y), std::abs(1 / rayDir.z));
    Vector3f sideDist;

    sideDist.x = ((rayDir.x < 0) ? _pos.x - coord.x : coord.x + 1.0 - _pos.x) * deltaDist.x;
    sideDist.y = ((rayDir.y < 0) ? _pos.y - coord.y : coord.y + 1.0 - _pos.y) * deltaDist.y;

    //The height of the player is defined by his feet
    sideDist.z = ((rayDir.z < 0) ? coord.z - _pos.z + zOffset: -coord.z + _pos.z - zOffset + 1.0) * deltaDist.z;

    int value = -1;
    while (_map[coord.z][coord.x][coord.y] == 0) {
        if (sideDist.x < sideDist.y) {
            if (sideDist.x < sideDist.z) {
                coord.x += step.x;
                sideDist.x += deltaDist.x;
            } else {
                coord.z += step.z;
                sideDist.z += deltaDist.z;
            }
        } else {
            if (sideDist.y < sideDist.z) {
                coord.y += step.y;
                sideDist.y += deltaDist.y;
            } else {
                coord.z += step.z;
                sideDist.z += deltaDist.z;
            }
        }
        if (coord.z < 0 || coord.z > _map.size() - 1)
            break;

        value = _map[coord.z][coord.x][coord.y];
    }
    return value;
}

void Player::drawProjection() const
{
    for (int x = 0; x < _width; x++) {
        for (int y = 0; y < _height; y++) {
            int value = ray(2 * x / _width - 1, 2 * y / _height - 1);
            //Draw pixel ...
        }
    }
}

Вот результат, который я получаю Obtained result

При изменении входных значений вертикальное отображение будет меняться соответственно:

sideDist.z = ((rayDir.z < 0) ? coord.z - _pos.z + zOffset : -coord.z + _pos.z - zOffset + 1.0) * deltaDist.z;

Часть, где (rayDir.z < 0) ? coord.z - _pos.z + zOffset : ..., кажется, работает нормально (это верхняя часть экрана).

Проблемная часть c составляет rayDir.z > 0. Текущие значения дают самый близкий результат к ожидаемому.

Обратите внимание, что если я изменю zOffset на 1, все будет работать правильно, но игрок всегда будет на 1/2 блока ниже.

Ссылки :

https://lodev.org/cgtutor/raycasting.html

http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.42.3443&rep=rep1&type=pdf#page = 3

...