Проблемы с простым raytracer в C++

В основном он проверяет наличие столкновений с массивом треугольников и рисует изображение, основываясь на цвете треугольника, в который он попадает. Я думаю, что моя проблема заключается в обнаружении столкновений. Код здесь:

for (int i = 0; i < triangles.size(); i++){
    vec3 v0 = triangles[i].v0;
    vec3 v1 = triangles[i].v1;
    vec3 v2 = triangles[i].v2;
    vec3 e1 = v1 - v0;
    vec3 e2 = v2 - v0;
    vec3 b = start - v0;
    mat3 A(-dir, e1, e2);
    vec3 x = glm::inverse(A) * b;

    if (x.x > 0 && x.y > 0 && (x.x + x.y < 1) && (x.z - start.z>= 0)){
        return true;
    }
}

... где "dir" - это направление луча, исходящего из камеры, вычисляемое как "x - SCREEN_WIDTH / 2, y - SCREEN_HEIGHT / 2, focalLength". SCREEN_WIDTH, SCREEN_HEIGHT и focalLength являются константами. Старт - это положение камеры, установленное на 0,0,0.

То, в чем я не уверен, так это то, что на самом деле х и что я должен проверить, прежде чем возвращать true. Предполагается, что "xx > 0 && xy > 0 && (xx + xy <1)" проверяет, попадает ли луч не только в ту же плоскость, но и внутри треугольника, и в последнюю часть ("xz - start.z>=" 0", тот, в котором я менее всего уверен), если столкновение произошло перед камерой.

Я получаю изображения, но как бы я ни старался, это никогда не правильно. Предполагается, что это классическая модель TestModel для комнаты с разноцветными стенами и двумя формами. Я думаю, что ближе всего я получаю четыре из пяти правильных стен, при этом отсутствует одна дальняя и часть одной из фигур на другой стороне.

1 ответ

Я не знаком с формулировкой матрицы для пересечения треугольника - это звучит довольно дорого.

Мой собственный код ниже, где мой e1 а также e2 эквивалентны вашим - то есть они представляют векторы ребер из v0 в v1 а также v2 соответственно:

// NB: triangles are assumed to be in world space
vector3 pvec = vector3::cross(ray.direction(), e2);
double det = e1.dot(pvec);
if (::fabs(det) < math::epsilon) return 0;

double invDet = 1.0 / det;
vector3 tvec(p0, ray.origin());

double u = tvec.dot(pvec) * invDet;
if (u < 0 || u > 1) return 0;

vector3 qvec = vector3::cross(tvec, e1);
double v = ray.direction().dot(qvec) * invDet;
if (v < 0 || u + v > 1) return 0;

double t = e2.dot(qvec) * invDet;
if (t > math::epsilon) {        // avoid self intersection
    // hit found at distance "t"
}

Я подозреваю, что проблема в вашем расчете вектора луча, который должен быть нормализован.

Другие вопросы по тегам