-
Notifications
You must be signed in to change notification settings - Fork 1
/
Unit_Vector.pas
197 lines (150 loc) · 4.4 KB
/
Unit_Vector.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
unit Unit_Vector;
interface
type
TVector2f = record
case Integer of
0: (X, Y: Single);
1: (U, V: Single);
end;
TVector2i = record X,Y: Integer; end;
TVector2d = record X,Y: Double; end;
TVector3f = record X,Y,Z: Single; end;
TVector3d = record X,Y,Z: Double; end;
TVector3i = record X,Y,Z: Integer; end;
TVector4f = record X,Y,Z,W: Single; end;
TVector4d = record X,Y,Z,W: Double; end;
PVector3f = ^TVector3f;
TVertice = record
X,Y,Z: Single;
nx, ny, nz: Single;
end;
TPoly3 = array [0..2] of Integer;
function Vector2i(X, Y: Integer): TVector2i;
function Vector3(X, Y, Z: Single): TVector3f;
function Vector4d(X, Y, Z, W: Single): TVector4d;
function Vertice(X, Y, Z, nx, ny, nz: Single): TVertice;
function Poly3(A,B,C: Integer): TPoly3;
function VectorLengthSqr(const A: TVector3f): Single;
function VectorAdd(const A,B: TVector3f): TVector3f;
function VectorSubtract(const A,B: TVector3f): TVector3f;
function VectorScale(const A: TVector3f; Scale: Single): TVector3f;
function VectorDotProduct(const A,B: TVector3f): Single;
function VectorCrossProduct(const A,B : TVector3f): TVector3f;
function VectorCombine(const A,B: TVector3f; const Coef: Single): TVector3f;
function RayTriangleIntersect(const aRayStart, aRayVector, A, B, C: TVector3f; out aPoint, aNormal: TVector3f): Boolean;
implementation
function Vector2i(X, Y: Integer): TVector2i;
begin
Result.X := X;
Result.Y := Y;
end;
function Vector3(X, Y, Z: Single): TVector3f;
begin
Result.X := X;
Result.Y := Y;
Result.Z := Z;
end;
function Vector4d(X, Y, Z, W: Single): TVector4d;
begin
Result.X := X;
Result.Y := Y;
Result.Z := Z;
Result.W := W;
end;
function Vertice(X, Y, Z, nx, ny, nz: Single): TVertice;
begin
Result.X := X;
Result.Y := Y;
Result.Z := Z;
Result.nx := nx;
Result.ny := ny;
Result.nz := nz;
end;
function Poly3(A,B,C: Integer): TPoly3;
begin
Result[0] := A;
Result[1] := B;
Result[2] := C;
end;
function VectorLengthSqr(const A: TVector3f): Single;
begin
Result := Sqr(A.X) + Sqr(A.Y) + Sqr(A.Z);
end;
function VectorAdd(const A,B: TVector3f): TVector3f;
begin
Result.X := A.X + B.X;
Result.Y := A.Y + B.Y;
Result.Z := A.Z + B.Z;
end;
function VectorSubtract(const A,B: TVector3f): TVector3f;
begin
Result.X := A.X - B.X;
Result.Y := A.Y - B.Y;
Result.Z := A.Z - B.Z;
end;
function VectorScale(const A: TVector3f; Scale: Single): TVector3f;
begin
Result.X := A.X * Scale;
Result.Y := A.Y * Scale;
Result.Z := A.Z * Scale;
end;
function VectorNormalize(const A: TVector3f): TVector3f;
var
Scale: Single;
begin
Scale := Sqrt(VectorLengthSqr(A));
if Scale = 0 then
Scale := 1;
Result.X := A.X / Scale;
Result.Y := A.Y / Scale;
Result.Z := A.Z / Scale;
end;
function VectorDotProduct(const A,B: TVector3f): Single;
begin
Result := A.X * B.X + A.Y * B.Y + A.Z * B.Z;
end;
function VectorCrossProduct(const A,B : TVector3f): TVector3f;
begin
Result.X := A.Y * B.Z - A.Z * B.Y;
Result.Y := A.Z * B.X - A.X * B.Z;
Result.Z := A.X * B.Y - A.Y * B.X;
end;
function VectorCombine(const A,B: TVector3f; const Coef: Single): TVector3f;
begin
Result.X := A.X + B.X * Coef;
Result.Y := A.Y + B.Y * Coef;
Result.Z := A.Z + B.Z * Coef;
end;
function RayTriangleIntersect(const aRayStart, aRayVector, A, B, C: TVector3f; out aPoint, aNormal: TVector3f): Boolean;
var
V1, V2, PV, QV, TV: TVector3f;
T, U, V, Det, InvDet: Single;
begin
Result := False;
V1 := VectorSubtract(B, A);
V2 := VectorSubtract(C, A);
PV := VectorCrossProduct(aRayVector, V2);
Det := VectorDotProduct(V1, PV);
//Skip if Ray is parallel to triangle
if Abs(Det) < 0.00001 then
Exit;
InvDet := 1 / Det;
TV := VectorSubtract(aRayStart, A);
U := VectorDotProduct(TV, PV) * InvDet;
if (U >= 0) and (U <= 1) then
begin
QV := VectorCrossProduct(TV, V1);
V := VectorDotProduct(aRayVector, QV) * InvDet;
if (V >= 0) and (U + V <= 1) then
begin
T := VectorDotProduct(V2, QV) * InvDet;
if T > 0 then
begin
aPoint := VectorCombine(aRayStart, aRayVector, T);
aNormal := VectorNormalize(VectorCrossProduct(V1, V2));
Result := True;
end;
end;
end;
end;
end.