Другие языки программирования и технологии

Как просчитать пересечение луча с трёхмерным объектом из треугольников?

Nps *
Nps *
702
берём треугольник и луч, берём содержащие их плоскость и прямую соответственно, записываем их уравнения в трехмерном пространстве, решаем систему, находим точки пересечения (их будет 0, 1 или бесконечность)

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

проходимся так по всем треугольникам и считаем ближайшую к началу луча точку

ничего особенного, стандартная задачка на линал, хотя мне кажется, что тут можно и какую-то готовую либу заюзать
Денис Спиридонов
Денис Спиридонов
51 164
Лучший ответ
https://cadxfem.org/inf/Fast MinimumStorage RayTriangle Intersection.pdf

/*
`Fast, minimum storage ray-triangle intersection`
Authors:Tomas Möller, Ben Trumbore
*/

inline bool triangleRayTest( const v4f& origin, const v4f& direction, const OxTriangle& triangle, f32 &d, bool backFace )
{

v4f edge1 = triangle.B - triangle.A;
v4f edge2 = triangle.C - triangle.A;

v4f pvec = math::cross( direction, edge2 );
f32 determinant = math::dot( edge1, pvec );

if( !backFace ){
if( determinant < EPSILON )
return false;
}

if( determinant > -EPSILON && determinant < EPSILON )
return false;

f32 inv_det = 1.0f / determinant;

v4f tvec = origin - triangle.A;

f32 u = math::dot( tvec, pvec ) * inv_det;
if( u < 0.f || u > 1.f )
return false;

v4f qvec = math::cross( tvec, edge1 );

f32 v = math::dot( direction, qvec ) * inv_det;
if( v < 0.f || u + v > 1.f )
return false;

d = math::dot(edge2, qvec ) * inv_det;

return true;
}

struct OxTriangle{
v4f A, B, C;
};

Правильнее сначала взять AABB объекта, проверить на пересечение, если есть такое, то уже треугольник за треугольником проверять.
РЦ
Рома Цанга
30 070