Различные результаты для одних и тех же вычислений с плавающей точкой

В задании по трассировке лучей, которое я делаю, я должен вычислить смещение по X луча, снимаемого с камеры; расчет смещения происходит следующим образом

FovY дается в качестве входных данных; Я вспомнил, чтобы преобразовать его в радианы в тот момент, когда я прочитал переменную.

OffsetX = tan (FovX / 2) * ((col - (width / 2)) / (width / 2))

FovX = tan(FovY / 2) * aspect = tan(FovY / 2) * (width / height)

Подставляя в исходное уравнение и писать код:

float OffsetX = tan(FovY / 2.0f) * (width / height) * ((col - (width / 2.0f)) / (width / 2.0f));

дал мне неправильное растянутое изображение, и мне потребовались часы, чтобы понять это правильно, после того как выяснилось, что то же самое уравнение работает после его упрощения.

Окончательное переставленное уравнение было:

float OffsetX = tan(FovY / 2.0f) * (2.0f / height) * (col - (width / 2.0f));

Я попробовал отладку, и результаты действительно были разными для обоих уравнений.

Будет ли какая-то ошибка округления? Может кто-нибудь объяснить мне эту причуду?

#include <cmath>
#include <iostream>
#include <cstdint>

using namespace std;

int main()
{
const float PI = 3.1415f;
const uint32_t width = 160, height = 120;
const auto fovy = (30.0f * (PI / 180.0f));
size_t j = 0;
auto alpha = (tan(fovy / 2.0f) * (width / height)) * (((j + 0.5f) - (width / 2.0f)) / (width / 2.0f));
cout << alpha << endl;
alpha = tan(fovy / 2.0f) * (2.0f / height) * ((j + 0.5f) - (width / 2.0f));
cout << alpha << endl;
}

1

Решение

Позвольте мне угадать: ширина и высота являются целыми числами.

Когда вы делаете:

(width / height)

вы получаете целочисленное деление, которое отбрасывает дробную часть результата. Если вы вместо этого сделаете:

((double)width / height)

тогда два результата будут практически одинаковыми.


кроме того, вы можете упростить выражение далее:

tan(FovY / 2.0f) * (2.0f*col - width) / height
6

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]