Когда игрок находится на определенной высоте (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 ...
}
}
}
Вот результат, который я получаю
При изменении входных значений вертикальное отображение будет меняться соответственно:
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