- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
procedure rayxtriangle(Xa,Ya,Za, {Точка отправления луча}
X1,Y1,Z1,X2,Y2,Z2,X3,Y3,Z3 : real; {Координаты полигона (триангла)}
Vx,Vy,Vz : real;{Вектор направления луча} Var Xc,Yc,Zc : real;{Точка пересечения}
bol : boolean {Для проверки пересечения триангла});
Var A,B,C,D : real;
k : real;
ac1,ac2,ac3 : real;
begin
A:=(Y2-Y1)*(Z3-Z1)-(Z2-Z1)*(Y3-Y1); //Вычисляем вектор нормали к треугольному полигону (векторное произведение)
B:=(Z2-Z1)*(X3-X1)-(X2-X1)*(Z3-Z1);
C:=(X2-X1)*(Y3-Y1)-(Y2-Y1)*(X3-X1);
D:=-A*X1-B*Y1-C*Z1;
k:=-(A*Xa+B*Ya+C*Za+D)/(A*Vx+B*Vy+C*Vz); //поскольку вектора луча (Vx Vy Vz) и вектор с даной
//точки к точке пересечения (Xc-Xa, Yc-Ya, Zc-Za) - колинеарны
//ето соотношение выведено мною, обьяснение было раньше (в предыдущем ответе)
Xc:=k*Vx+Xa; //Вычисляем точку пересечения луча с полигоном
Yc:=k*Vy+Ya;
Zc:=k*Vz+Za;
//здесь проверяем лежыт ли даная точка в треугольном полигоне
//ac1,ac2,ac3 арккосинусы углов между векторами с точки пересечения (Xc Yc Zc)
//к вершинам треугольника (из скалярного произведения)
//Для других полигонов (4,5,6... и т.д. угольных) надо побольше вычислений
ac1:=arccos(((x1-xc)*(x2-xc)+(y1-yc)*(y2-yc)+(z1-zc)*(z2-zc))/(sqrt(sqr(x1-xc)+sqr(y1-yc)+sqr(z1-zc))*sqrt(sqr(x2-xc)+sqr(y2-yc)+sqr(z2-zc))));
ac2:=arccos(((x2-xc)*(x3-xc)+(y2-yc)*(y3-yc)+(z2-zc)*(z3-zc))/(sqrt(sqr(x2-xc)+sqr(y2-yc)+sqr(z2-zc))*sqrt(sqr(x3-xc)+sqr(y3-yc)+sqr(z3-zc))));
ac3:=arccos(((x3-xc)*(x1-xc)+(y3-yc)*(y1-yc)+(z3-zc)*(z1-zc))/(sqrt(sqr(x3-xc)+sqr(y3-yc)+sqr(z3-zc))*sqrt(sqr(x1-xc)+sqr(y1-yc)+sqr(z1-zc))));
if (ac1+ac2+ac3=pi) then bol:=true else bol:=false; //Если сума етих углов=360 градусов значит точка в треугольнике
//Если точка пересечения найдена тогда bol=true и ее координаты Xc Yc Zc
end;
А всё потому, что векторную алгебру надо знать, любить и уважать, ибо иначе такая хрень выходит.
Источник: http://www.gamedev.ru/code/forum/?id=148128