Пересечение луча и квадрата / прямоугольника в 3D

Hei. Делают игру и ищут лучевое пересечение на квадрат или прямоугольник только в трехмерном пространстве. Ищите в Интернете и находите множество решений, но ничего, что я могу понять, имеют сценарий пересечения строк и строк в 2D, но я не могу вычислить его, чтобы сделать его 3D. Не важно, с какой стороны он пересекает квадрат или прямоугольник, но он должен иметь возможность извлекать точку вектора пересечения, чтобы впоследствии можно было проверять расстояние до места, если оно произошло до или после других пересечений на одном и том же пересечении лучей.

Любые примеры в python или других подобных языках сценариев будут высоко оценены

Edit : Dont знать, должны изменить 2D, чтобы показать exaple, но сделал новое и опубликовать оба.

//this is the exaple it test a ray onto a plane then look to se if that point is in the rectangle and saves it to test for distanse later list Faces; //triangle faces list Points; // vector FindPoint(){ //calcute the point of intersection onto the plane and returns it //if it can intersect //else return ZERO_VECTOR } integer point-in-quadrilateral(){ //return 1 if the point is in the rectangular on the plane //else return 0 } default{ state_entry(){ integer n = (Faces != []); //return number of elements integer x = 0; while(x < n){ vector intersection = FindPoint( FromList(Faces, x) ); //take out a element and runs it trough the function if(intersection != ZERO_VECTOR){ integer test = point-in-quadrilateral( FromList(Faces, x) ); //find out if the point is in rectangular if(test == 1){ //if so Points += intersection; //save the point } } ++x; } float first; //the distanse to the box intersection integer l = (Points != []); integer d; while(d < l){ if(Dist( FromList(Points, d) ) < first) //if the new distanse is less then first return 0; //then end script ++d; } } } //this is the 2D version vector lineIntersection(vector one, vector two, vector three, vector four){ float bx = two.x - one.x; float by = two.y - one.y; float dx = four.x - three.x; float dy = four.y - three.y; float b_dot_d_perp = bx*dy - by*dx; if(b_dot_d_perp == 0.0) { return ZERO_VECTOR; } float cx = three.x-one.x; float cy = three.y-one.y; float t = (cx*dy - cy*dx) / b_dot_d_perp; if(LineSeg){ //if true tests for line segment if((t < 0.0) || (t > 1.0)){ return ZERO_VECTOR; } float u = (cx * by - cy * bx) / b_dot_d_perp; if((u < 0.0) || (u > 1.0)) { return ZERO_VECTOR; } } return <one.x+t*bx, one.y+t*by, 0.0>; 

}

Создайте векторное уравнение для строки в R3, затем решите для пересечения этой линии в плоскости прямоугольника, с которой вы его тестируете. После этого достаточно просто проверить, находится ли эта точка решения в пределах границ.

параметр t решения можно найти с помощью:

 t = (a * (x0 - rx) + b * (y0 - ry) + c * (x0 - rz)) / (a * vx + b * vy + c * vz) 

где:

 a(x - x0) + b(y - y0) + c(z - z0) = 0 

– это уравнение плоскости, на которой находится ваш прямоугольник

а также:

 <x, y, z> = <rx + vx * t, ry + vy * t, rz + vz * t> 

– векторное уравнение рассматриваемой линии.

Обратите внимание, что:

 <rx, ry, rz> 

– начальная точка векторного уравнения и

 <vx, vy, vz> 

– вектор направления указанного уравнения

После этого включение параметра t в ваше векторное уравнение даст вам возможность проверить расстояние.

введите описание изображения здесь

Решение очень просто, когда вы определяете луч с точкой (= вектор) и вектором направления, а прямоугольник с точкой (= вектор) и двумя векторами, представляющими стороны.

Предположим, что луч определяется как R0 + t * D , где R0 – начало луча, D – единичный вектор, представляющий его направление, а t – его длина.

Прямоугольник может быть представлен угловой точкой P0 и двумя векторами S1 и S2 которые должны представлять стороны (их длина равна длине сторон). Вам понадобится другой вектор N нормальный к его поверхности, который равен единичному вектору вдоль поперечного произведения S1 и S2 .

Теперь предположим, что луч пересекает прямой в точке Р. Тогда направление луча D должно сделать ненулевой угол с нормалью N Это можно проверить, проверив DN < 0 .

Чтобы найти точку пересечения, предположим, что P = R0 + a * D (точка должна быть на луче). Вам нужно найти значение a now.Find вектор P0P . Это должно быть перпендикулярно N , что означает P0P.N = 0 которое сводится к a = ((P0 - R0).N) / (DN) .

Теперь вам нужно проверить, находится ли точка внутри прямоугольника или нет. Для этого возьмите проекцию Q1 P0P вдоль S1 и Q2 P0P вдоль S2 . Условие для того, чтобы точка находилась внутри, равна 0 <= length(Q1) <= length(S1) и 0 <= length(Q2) <= length(S2) .

Этот метод подходит для любых типов параллелограммов, а не только для прямоугольников.

Вы не говорите, выравнивается ли квадрат / прямоугольник в 3D с координатными осями или нет. Предполагая, что 3D-прямоугольник R ориентирован произвольно в пространстве, здесь есть один метод. Сначала рассмотрим ваш луч r плоскостью, содержащей R. Это может быть достигнуто за счет применения масштабного коэффициента s для умножения r и размещения его на плоскости R и решения для s . Это дает вам точку p на плоскости. Проецируем плоскость и R и p на одну из координатных плоскостей { xy , yz , zx }. Вам нужно избегать проецирования перпендикулярно нормальному вектору на плоскость, что всегда возможно. А затем решить задачу «в-четырехугольник» в плоскости проекции.

Прежде чем начать, проверьте, находится ли ваш сегмент линии в 3D-плоскости R , и если да, обрабатывайте это отдельно.