Из того, что я понял, вы пытаетесь проверить, проходит ли ray
triangle
.Самая первая ошибка, которую я вижу, состоит в том, что point
:
vec3 point = ray.origin + scalar * ray.dir;
имеет бессмысленное определение.Вы вычисляете пересечение ray
с параллельной плоскостью к triangle
, проходящей через начало координат.Если эта плоскость по какой-то чудесной причине не совпадает с плоскостью triangle
, все последующие вычисления с этим point
не имеют никакого значения.
Чтобы исправить это, вам нужно определить scalar
следующим образом:
float scalar = dot(triangle.normal,triangle.x) - dot(triangle.normal,ray.origin);
scalar /= dot(triangle.normal,ray.dir);
, где triangle.x
- любая точка triangle
.
. После исправления этой проблемы можно будет обсудить, имеют ли смысл другие части вашего кода.
Также, пожалуйста, предоставьте больше информации о деталях кода, т. Е. Соответствующих частях реализации.
Теперь о том, как проверить, пересекает ли луч треугольник.Метод пересечения луча с плоскостью треугольника, а затем проверки, находится ли точка внутри треугольника в двумерной постановке, - не очень хорош с точки зрения устойчивости.Поэтому избегайте этого.
Более простой и прямой метод состоит в том, чтобы вычислить разностные векторы:
vec3 dvec1 = tringle.p1 - ray.origin;
vec3 dvec2 = tringle.p2 - ray.origin;
vec3 dvec3 = tringle.p3 - ray.origin;
и затем проверить, можно ли выразить ray.dir
в виде линейной суммы dvec1
dvec2
и dvec3
с положительными коэффициентами.Это может быть достигнуто путем вычисления обратной матрицы mat3(dvec1,dvec2,dvec3)
и умножения ее на ray.dir
(таким образом, вы получите коэффициенты, необходимые для выражения ray.dir
линейной суммы dvec1
, dvec2
и dvec3
).
Однако матричный метод не является абсолютно стабильным из-за делений.Это может быть улучшено путем реализации логически эквивалентного кода без делений.
vec3 dvec12 = cross_product(dvec1, dvec2);
if(dot(dvec12,dvec3)*dot(dvec12,ray.dir) < 0.) return false;
vec3 dvec23 = cross_product(dvec2, dvec3);
if(dot(dvec23,dvec1)*dot(dvec23,ray.dir) < 0.) return false;
vec3 dvec31 = cross_product(dvec3, dvec1);
if(dot(dvec31,dvec2)*dot(dvec31,ray.dir) < 0.) return false;
return true;
В первом if
мы проверяем, находится ли ray.dir
в той же полуплоскости, что и dvec3
относительносамолет натянут на {dvec1,dvec2}
.Если это не так, ray
не будет пересекать треугольник.
Затем мы повторим эту проверку для других векторов.