MathgeomGLS

Форк
0
/
Neslib.FastMath.Common.inc 
3230 строк · 73.4 Кб
1
var
2
  PrevFloatingPointExceptions: TArithmeticExceptionMask = DefaultExceptionFlags;
3

4
{$WARN SYMBOL_PLATFORM OFF}
5
procedure DisableFloatingPointExceptions;
6
begin
7
  PrevFloatingPointExceptions := SetExceptionMask(exAllArithmeticExceptions);
8
end;
9

10
procedure RestoreFloatingPointExceptions;
11
begin
12
  SetExceptionMask(PrevFloatingPointExceptions);
13
end;
14
{$WARN SYMBOL_PLATFORM ON}
15

16
{ Vector2 }
17

18
function Vector2: TVector2;
19
begin
20
  Result.Init;
21
end;
22

23
function Vector2(const A: Single): TVector2;
24
begin
25
  Result.Init(A);
26
end;
27

28
function Vector2(const A1, A2: Single): TVector2;
29
begin
30
  Result.Init(A1, A2);
31
end;
32

33
function Vector2(const AVector: TVector3): TVector2;
34
begin
35
  Result.Init(AVector.X, AVector.Y);
36
end;
37

38
function Vector2(const AVector: TVector4): TVector2;
39
begin
40
  Result.Init(AVector.X, AVector.Y);
41
end;
42

43
{ Vector3 }
44

45
function Vector3: TVector3;
46
begin
47
  Result.Init;
48
end;
49

50
function Vector3(const A: Single): TVector3;
51
begin
52
  Result.Init(A);
53
end;
54

55
function Vector3(const A1, A2, A3: Single): TVector3;
56
begin
57
  Result.Init(A1, A2, A3);
58
end;
59

60
function Vector3(const A1: TVector2; const A2: Single): TVector3;
61
begin
62
  Result.Init(A1, A2);
63
end;
64

65
function Vector3(const A1: Single; const A2: TVector2): TVector3;
66
begin
67
  Result.Init(A1, A2);
68
end;
69

70
function Vector3(const AVector: TVector4): TVector3;
71
begin
72
  Result.Init(AVector.X, AVector.Y, AVector.Z);
73
end;
74

75
{ Vector4 }
76

77
function Vector4: TVector4;
78
begin
79
  Result.Init;
80
end;
81

82
function Vector4(const A: Single): TVector4;
83
begin
84
  Result.Init(A);
85
end;
86

87
function Vector4(const A1, A2, A3, A4: Single): TVector4;
88
begin
89
  Result.Init(A1, A2, A3, A4);
90
end;
91

92
function Vector4(const A1: TVector2; const A2, A3: Single): TVector4;
93
begin
94
  Result.Init(A1, A2, A3);
95
end;
96

97
function Vector4(const A1: Single; const A2: TVector2; const A3: Single): TVector4;
98
begin
99
  Result.Init(A1, A2, A3);
100
end;
101

102
function Vector4(const A1, A2: Single; const A3: TVector2): TVector4;
103
begin
104
  Result.Init(A1, A2, A3);
105
end;
106

107
function Vector4(const A1, A2: TVector2): TVector4;
108
begin
109
  Result.Init(A1, A2);
110
end;
111

112
function Vector4(const A1: TVector3; const A2: Single): TVector4;
113
begin
114
  Result.Init(A1, A2);
115
end;
116

117
function Vector4(const A1: Single; const A2: TVector3): TVector4;
118
begin
119
  Result.Init(A1, A2);
120
end;
121

122
{ Quaternion }
123

124
function Quaternion: TQuaternion;
125
begin
126
  Result.Init;
127
end;
128

129
function Quaternion(const AX, AY, AZ, AW: Single): TQuaternion; overload;
130
begin
131
  Result.Init(AX, AY, AZ, AW);
132
end;
133

134
function Quaternion(const AAxis: TVector3; const AAngleRadians: Single): TQuaternion; overload;
135
begin
136
  Result.Init(AAxis, AAngleRadians);
137
end;
138

139
{ Matrix2 }
140

141
function Matrix2: TMatrix2;
142
begin
143
  Result.Init;
144
end;
145

146
function Matrix2(const ADiagonal: Single): TMatrix2;
147
begin
148
  Result.Init(ADiagonal);
149
end;
150

151
function Matrix2(const ARow0, ARow1: TVector2): TMatrix2;
152
begin
153
  Result.Init(ARow0, ARow1);
154
end;
155

156
function Matrix2(const A11, A12, A21, A22: Single): TMatrix2;
157
begin
158
  Result.Init(A11, A12, A21, A22);
159
end;
160

161
function Matrix2(const AMatrix: TMatrix3): TMatrix2;
162
begin
163
  Result.V[0] := Vector2(AMatrix.V[0]);
164
  Result.V[1] := Vector2(AMatrix.V[1]);
165
end;
166

167
function Matrix2(const AMatrix: TMatrix4): TMatrix2;
168
begin
169
  Result.V[0] := Vector2(AMatrix.V[0]);
170
  Result.V[1] := Vector2(AMatrix.V[1]);
171
end;
172

173
{ Matrix3 }
174

175
function Matrix3: TMatrix3;
176
begin
177
  Result.Init;
178
end;
179

180
function Matrix3(const ADiagonal: Single): TMatrix3;
181
begin
182
  Result.Init(ADiagonal);
183
end;
184

185
function Matrix3(const ARow0, ARow1, ARow2: TVector3): TMatrix3;
186
begin
187
  Result.Init(ARow0, ARow1, ARow2);
188
end;
189

190
function Matrix3(const A11, A12, A13, A21, A22, A23, A31, A32, A33: Single): TMatrix3;
191
begin
192
  Result.Init(A11, A12, A13, A21, A22, A23, A31, A32, A33);
193
end;
194

195
function Matrix3(const AMatrix: TMatrix2): TMatrix3;
196
begin
197
  Result.V[0] := Vector3(AMatrix.V[0], 0);
198
  Result.V[1] := Vector3(AMatrix.V[1], 0);
199
  Result.V[2] := Vector3(0, 0, 1);
200
end;
201

202
function Matrix3(const AMatrix: TMatrix4): TMatrix3;
203
begin
204
  Result.V[0] := Vector3(AMatrix.V[0]);
205
  Result.V[1] := Vector3(AMatrix.V[1]);
206
  Result.V[2] := Vector3(AMatrix.V[2]);
207
end;
208

209
{ Matrix4 }
210

211
function Matrix4: TMatrix4;
212
begin
213
  Result.Init;
214
end;
215

216
function Matrix4(const ADiagonal: Single): TMatrix4;
217
begin
218
  Result.Init(ADiagonal);;
219
end;
220

221
function Matrix4(const ARow0, ARow1, ARow2, ARow3: TVector4): TMatrix4;
222
begin
223
  Result.Init(ARow0, ARow1, ARow2, ARow3);
224
end;
225

226
function Matrix4(const A11, A12, A13, A14, A21, A22, A23, A24, A31, A32, A33,
227
  A34, A41, A42, A43, A44: Single): TMatrix4;
228
begin
229
  Result.Init(A11, A12, A13, A14, A21, A22, A23, A24, A31, A32, A33, A34, A41,
230
    A42, A43, A44);
231
end;
232

233
function Matrix4(const AMatrix: TMatrix2): TMatrix4;
234
begin
235
  Result.V[0].Init(AMatrix.V[0], 0, 0);
236
  Result.V[1].Init(AMatrix.V[1], 0, 0);
237
  Result.V[2].Init(0, 0, 1, 0);
238
  Result.V[3].Init(0, 0, 0, 1);
239
end;
240

241
function Matrix4(const AMatrix: TMatrix3): TMatrix4;
242
begin
243
  Result.V[0].Init(AMatrix.V[0], 0);
244
  Result.V[1].Init(AMatrix.V[1], 0);
245
  Result.V[2].Init(AMatrix.V[2], 0);
246
  Result.V[3].Init(0, 0, 0, 1);
247
end;
248

249
{ IVector2 }
250

251
function IVector2: TIVector2;
252
begin
253
  Result.Init;
254
end;
255

256
function IVector2(const A: Integer): TIVector2;
257
begin
258
  Result.Init(A);
259
end;
260

261
function IVector2(const A1, A2: Integer): TIVector2;
262
begin
263
  Result.Init(A1, A2);
264
end;
265

266
{ IVector3 }
267

268
function IVector3: TIVector3;
269
begin
270
  Result.Init;
271
end;
272

273
function IVector3(const A: Integer): TIVector3;
274
begin
275
  Result.Init(A);
276
end;
277

278
function IVector3(const A1, A2, A3: Integer): TIVector3;
279
begin
280
  Result.Init(A1, A2, A3);
281
end;
282

283
{ IVector4 }
284

285
function IVector4: TIVector4;
286
begin
287
  Result.Init;
288
end;
289

290
function IVector4(const A: Integer): TIVector4;
291
begin
292
  Result.Init(A);
293
end;
294

295
function IVector4(const A1, A2, A3, A4: Integer): TIVector4;
296
begin
297
  Result.Init(A1, A2, A3, A4);
298
end;
299

300
{ Angle and Trigonometry Functions }
301

302
function Sin(const ARadians: Single): Single;
303
begin
304
  Result := System.Sin(ARadians);
305
end;
306

307
function Sin(const ARadians: TVector2): TVector2;
308
begin
309
  Result.Init(System.Sin(ARadians.X), System.Sin(ARadians.Y));
310
end;
311

312
function Sin(const ARadians: TVector3): TVector3;
313
begin
314
  Result.Init(System.Sin(ARadians.X), System.Sin(ARadians.Y), System.Sin(ARadians.Z));
315
end;
316

317
function Sin(const ARadians: TVector4): TVector4;
318
begin
319
  Result.Init(System.Sin(ARadians.X), System.Sin(ARadians.Y), System.Sin(ARadians.Z), System.Sin(ARadians.W));
320
end;
321

322
function Cos(const ARadians: Single): Single;
323
begin
324
  Result := System.Cos(ARadians);
325
end;
326

327
function Cos(const ARadians: TVector2): TVector2;
328
begin
329
  Result.Init(System.Cos(ARadians.X), System.Cos(ARadians.Y));
330
end;
331

332
function Cos(const ARadians: TVector3): TVector3;
333
begin
334
  Result.Init(System.Cos(ARadians.X), System.Cos(ARadians.Y), System.Cos(ARadians.Z));
335
end;
336

337
function Cos(const ARadians: TVector4): TVector4;
338
begin
339
  Result.Init(System.Cos(ARadians.X), System.Cos(ARadians.Y), System.Cos(ARadians.Z), System.Cos(ARadians.W));
340
end;
341

342
procedure SinCos(const ARadians: Single; out ASin, ACos: Single);
343
begin
344
  System.Math.SinCos(ARadians, ASin, ACos);
345
end;
346

347
procedure SinCos(const ARadians: TVector2; out ASin, ACos: TVector2);
348
begin
349
  System.Math.SinCos(ARadians.X, ASin.X, ACos.X);
350
  System.Math.SinCos(ARadians.Y, ASin.Y, ACos.Y);
351
end;
352

353
procedure SinCos(const ARadians: TVector3; out ASin, ACos: TVector3);
354
begin
355
  System.Math.SinCos(ARadians.X, ASin.X, ACos.X);
356
  System.Math.SinCos(ARadians.Y, ASin.Y, ACos.Y);
357
  System.Math.SinCos(ARadians.Z, ASin.Z, ACos.Z);
358
end;
359

360
procedure SinCos(const ARadians: TVector4; out ASin, ACos: TVector4);
361
begin
362
  System.Math.SinCos(ARadians.X, ASin.X, ACos.X);
363
  System.Math.SinCos(ARadians.Y, ASin.Y, ACos.Y);
364
  System.Math.SinCos(ARadians.Z, ASin.Z, ACos.Z);
365
  System.Math.SinCos(ARadians.W, ASin.W, ACos.W);
366
end;
367

368
function Tan(const ARadians: Single): Single;
369
begin
370
  Result := System.Tangent(ARadians);
371
end;
372

373
function Tan(const ARadians: TVector2): TVector2;
374
begin
375
  Result.Init(System.Tangent(ARadians.X), System.Tangent(ARadians.Y));
376
end;
377

378
function Tan(const ARadians: TVector3): TVector3;
379
begin
380
  Result.Init(System.Tangent(ARadians.X), System.Tangent(ARadians.Y), System.Tangent(ARadians.Z));
381
end;
382

383
function Tan(const ARadians: TVector4): TVector4;
384
begin
385
  Result.Init(System.Tangent(ARadians.X), System.Tangent(ARadians.Y), System.Tangent(ARadians.Z), System.Tangent(ARadians.W));
386
end;
387

388
function ArcSin(const A: Single): Single;
389
begin
390
  Result := System.Math.ArcSin(A);
391
end;
392

393
function ArcSin(const A: TVector2): TVector2;
394
begin
395
  Result.Init(System.Math.ArcSin(A.X), System.Math.ArcSin(A.Y));
396
end;
397

398
function ArcSin(const A: TVector3): TVector3;
399
begin
400
  Result.Init(System.Math.ArcSin(A.X), System.Math.ArcSin(A.Y), System.Math.ArcSin(A.Z));
401
end;
402

403
function ArcSin(const A: TVector4): TVector4;
404
begin
405
  Result.Init(System.Math.ArcSin(A.X), System.Math.ArcSin(A.Y), System.Math.ArcSin(A.Z), System.Math.ArcSin(A.W));
406
end;
407

408
function ArcCos(const A: Single): Single;
409
begin
410
  Result := System.Math.ArcCos(A);
411
end;
412

413
function ArcCos(const A: TVector2): TVector2;
414
begin
415
  Result.Init(System.Math.ArcCos(A.X), System.Math.ArcCos(A.Y));
416
end;
417

418
function ArcCos(const A: TVector3): TVector3;
419
begin
420
  Result.Init(System.Math.ArcCos(A.X), System.Math.ArcCos(A.Y), System.Math.ArcCos(A.Z));
421
end;
422

423
function ArcCos(const A: TVector4): TVector4;
424
begin
425
  Result.Init(System.Math.ArcCos(A.X), System.Math.ArcCos(A.Y), System.Math.ArcCos(A.Z), System.Math.ArcCos(A.W));
426
end;
427

428
function ArcTan(const A: Single): Single;
429
begin
430
  Result := System.ArcTan(A);
431
end;
432

433
function ArcTan(const A: TVector2): TVector2;
434
begin
435
  Result.Init(System.ArcTan(A.X), System.ArcTan(A.Y));
436
end;
437

438
function ArcTan(const A: TVector3): TVector3;
439
begin
440
  Result.Init(System.ArcTan(A.X), System.ArcTan(A.Y), System.ArcTan(A.Z));
441
end;
442

443
function ArcTan(const A: TVector4): TVector4;
444
begin
445
  Result.Init(System.ArcTan(A.X), System.ArcTan(A.Y), System.ArcTan(A.Z), System.ArcTan(A.W));
446
end;
447

448
function ArcTan2(const Y, X: Single): Single;
449
begin
450
  Result := System.Math.ArcTan2(Y, X);
451
end;
452

453
function ArcTan2(const Y, X: TVector2): TVector2;
454
begin
455
  Result.Init(System.Math.ArcTan2(Y.X, X.X), System.Math.ArcTan2(Y.Y, X.Y));
456
end;
457

458
function ArcTan2(const Y, X: TVector3): TVector3;
459
begin
460
  Result.Init(System.Math.ArcTan2(Y.X, X.X), System.Math.ArcTan2(Y.Y, X.Y), System.Math.ArcTan2(Y.Z, X.Z));
461
end;
462

463
function ArcTan2(const Y, X: TVector4): TVector4;
464
begin
465
  Result.Init(System.Math.ArcTan2(Y.X, X.X), System.Math.ArcTan2(Y.Y, X.Y), System.Math.ArcTan2(Y.Z, X.Z), System.Math.ArcTan2(Y.W, X.W));
466
end;
467

468
function Sinh(const A: Single): Single;
469
begin
470
  Result := System.Math.Sinh(A);
471
end;
472

473
function Sinh(const A: TVector2): TVector2;
474
begin
475
  Result.Init(System.Math.Sinh(A.X), System.Math.Sinh(A.Y));
476
end;
477

478
function Sinh(const A: TVector3): TVector3;
479
begin
480
  Result.Init(System.Math.Sinh(A.X), System.Math.Sinh(A.Y), System.Math.Sinh(A.Z));
481
end;
482

483
function Sinh(const A: TVector4): TVector4;
484
begin
485
  Result.Init(System.Math.Sinh(A.X), System.Math.Sinh(A.Y), System.Math.Sinh(A.Z), System.Math.Sinh(A.W));
486
end;
487

488
function Cosh(const A: Single): Single;
489
begin
490
  Result := System.Math.Cosh(A);
491
end;
492

493
function Cosh(const A: TVector2): TVector2;
494
begin
495
  Result.Init(System.Math.Cosh(A.X), System.Math.Cosh(A.Y));
496
end;
497

498
function Cosh(const A: TVector3): TVector3;
499
begin
500
  Result.Init(System.Math.Cosh(A.X), System.Math.Cosh(A.Y), System.Math.Cosh(A.Z));
501
end;
502

503
function Cosh(const A: TVector4): TVector4;
504
begin
505
  Result.Init(System.Math.Cosh(A.X), System.Math.Cosh(A.Y), System.Math.Cosh(A.Z), System.Math.Cosh(A.W));
506
end;
507

508
function Tanh(const A: Single): Single;
509
begin
510
  Result := System.Math.Tanh(A);
511
end;
512

513
function Tanh(const A: TVector2): TVector2;
514
begin
515
  Result.Init(System.Math.Tanh(A.X), System.Math.Tanh(A.Y));
516
end;
517

518
function Tanh(const A: TVector3): TVector3;
519
begin
520
  Result.Init(System.Math.Tanh(A.X), System.Math.Tanh(A.Y), System.Math.Tanh(A.Z));
521
end;
522

523
function Tanh(const A: TVector4): TVector4;
524
begin
525
  Result.Init(System.Math.Tanh(A.X), System.Math.Tanh(A.Y), System.Math.Tanh(A.Z), System.Math.Tanh(A.W));
526
end;
527

528
function ArcSinh(const A: Single): Single;
529
begin
530
  Result := System.Math.ArcSinh(A);
531
end;
532

533
function ArcSinh(const A: TVector2): TVector2;
534
begin
535
  Result.Init(System.Math.ArcSinh(A.X), System.Math.ArcSinh(A.Y));
536
end;
537

538
function ArcSinh(const A: TVector3): TVector3;
539
begin
540
  Result.Init(System.Math.ArcSinh(A.X), System.Math.ArcSinh(A.Y), System.Math.ArcSinh(A.Z));
541
end;
542

543
function ArcSinh(const A: TVector4): TVector4;
544
begin
545
  Result.Init(System.Math.ArcSinh(A.X), System.Math.ArcSinh(A.Y), System.Math.ArcSinh(A.Z), System.Math.ArcSinh(A.W));
546
end;
547

548
function ArcCosh(const A: Single): Single;
549
begin
550
  Result := System.Math.ArcCosh(A);
551
end;
552

553
function ArcCosh(const A: TVector2): TVector2;
554
begin
555
  Result.Init(System.Math.ArcCosh(A.X), System.Math.ArcCosh(A.Y));
556
end;
557

558
function ArcCosh(const A: TVector3): TVector3;
559
begin
560
  Result.Init(System.Math.ArcCosh(A.X), System.Math.ArcCosh(A.Y), System.Math.ArcCosh(A.Z));
561
end;
562

563
function ArcCosh(const A: TVector4): TVector4;
564
begin
565
  Result.Init(System.Math.ArcCosh(A.X), System.Math.ArcCosh(A.Y), System.Math.ArcCosh(A.Z), System.Math.ArcCosh(A.W));
566
end;
567

568
function ArcTanh(const A: Single): Single;
569
begin
570
  Result := System.Math.ArcTanh(A);
571
end;
572

573
function ArcTanh(const A: TVector2): TVector2;
574
begin
575
  Result.Init(System.Math.ArcTanh(A.X), System.Math.ArcTanh(A.Y));
576
end;
577

578
function ArcTanh(const A: TVector3): TVector3;
579
begin
580
  Result.Init(System.Math.ArcTanh(A.X), System.Math.ArcTanh(A.Y), System.Math.ArcTanh(A.Z));
581
end;
582

583
function ArcTanh(const A: TVector4): TVector4;
584
begin
585
  Result.Init(System.Math.ArcTanh(A.X), System.Math.ArcTanh(A.Y), System.Math.ArcTanh(A.Z), System.Math.ArcTanh(A.W));
586
end;
587

588
{ Exponential Functions }
589

590
function Power(const ABase, AExponent: Single): Single;
591
begin
592
  Result := System.Math.Power(ABase, AExponent);
593
end;
594

595
function Power(const ABase, AExponent: TVector2): TVector2;
596
begin
597
  Result.Init(System.Math.Power(ABase.X, AExponent.X), System.Math.Power(ABase.Y, AExponent.Y));
598
end;
599

600
function Power(const ABase, AExponent: TVector3): TVector3;
601
begin
602
  Result.Init(System.Math.Power(ABase.X, AExponent.X), System.Math.Power(ABase.Y, AExponent.Y), System.Math.Power(ABase.Z, AExponent.Z));
603
end;
604

605
function Power(const ABase, AExponent: TVector4): TVector4;
606
begin
607
  Result.Init(System.Math.Power(ABase.X, AExponent.X), System.Math.Power(ABase.Y, AExponent.Y), System.Math.Power(ABase.Z, AExponent.Z), System.Math.Power(ABase.W, AExponent.W));
608
end;
609

610
function Exp(const A: Single): Single;
611
begin
612
  Result := System.Exp(A);
613
end;
614

615
function Exp(const A: TVector2): TVector2;
616
begin
617
  Result.Init(System.Exp(A.X), System.Exp(A.Y));
618
end;
619

620
function Exp(const A: TVector3): TVector3;
621
begin
622
  Result.Init(System.Exp(A.X), System.Exp(A.Y), System.Exp(A.Z));
623
end;
624

625
function Exp(const A: TVector4): TVector4;
626
begin
627
  Result.Init(System.Exp(A.X), System.Exp(A.Y), System.Exp(A.Z), System.Exp(A.W));
628
end;
629

630
function Ln(const A: Single): Single;
631
begin
632
  Result := System.Ln(A);
633
end;
634

635
function Ln(const A: TVector2): TVector2;
636
begin
637
  Result.Init(System.Ln(A.X), System.Ln(A.Y));
638
end;
639

640
function Ln(const A: TVector3): TVector3;
641
begin
642
  Result.Init(System.Ln(A.X), System.Ln(A.Y), System.Ln(A.Z));
643
end;
644

645
function Ln(const A: TVector4): TVector4;
646
begin
647
  Result.Init(System.Ln(A.X), System.Ln(A.Y), System.Ln(A.Z), System.Ln(A.W));
648
end;
649

650
function Exp2(const A: Single): Single;
651
begin
652
  Result := System.Math.Power(2, A);
653
end;
654

655
function Exp2(const A: TVector2): TVector2;
656
begin
657
  Result.Init(Exp2(A.X), Exp2(A.Y));
658
end;
659

660
function Exp2(const A: TVector3): TVector3;
661
begin
662
  Result.Init(Exp2(A.X), Exp2(A.Y), Exp2(A.Z));
663
end;
664

665
function Exp2(const A: TVector4): TVector4;
666
begin
667
  Result.Init(Exp2(A.X), Exp2(A.Y), Exp2(A.Z), Exp2(A.W));
668
end;
669

670
function Log2(const A: Single): Single;
671
begin
672
  Result := System.Math.Log2(A);
673
end;
674

675
function Log2(const A: TVector2): TVector2;
676
begin
677
  Result.Init(System.Math.Log2(A.X), System.Math.Log2(A.Y));
678
end;
679

680
function Log2(const A: TVector3): TVector3;
681
begin
682
  Result.Init(System.Math.Log2(A.X), System.Math.Log2(A.Y), System.Math.Log2(A.Z));
683
end;
684

685
function Log2(const A: TVector4): TVector4;
686
begin
687
  Result.Init(System.Math.Log2(A.X), System.Math.Log2(A.Y), System.Math.Log2(A.Z), System.Math.Log2(A.W));
688
end;
689

690
{ Fast approximate Functions }
691

692
function FastPower(const ABase, AExponent: Single): Single;
693
begin
694
  Result := FastExp2(AExponent * FastLog2(ABase));
695
end;
696

697
function FastPower(const ABase, AExponent: TVector2): TVector2;
698
begin
699
  Result := FastExp2(AExponent * FastLog2(ABase));
700
end;
701

702
function FastPower(const ABase, AExponent: TVector3): TVector3;
703
begin
704
  Result := FastExp2(AExponent * FastLog2(ABase));
705
end;
706

707
function FastPower(const ABase, AExponent: TVector4): TVector4;
708
begin
709
  Result := FastExp2(AExponent * FastLog2(ABase));
710
end;
711

712
function FastTan(const ARadians: Single): Single;
713
var
714
  S, C: Single;
715
begin
716
  FastSinCos(ARadians, S, C);
717
  Result := S / C;
718
end;
719

720
function FastTan(const ARadians: TVector2): TVector2;
721
var
722
  S, C: TVector2;
723
begin
724
  FastSinCos(ARadians, S, C);
725
  Result := S / C;
726
end;
727

728
function FastTan(const ARadians: TVector3): TVector3;
729
var
730
  S, C: TVector3;
731
begin
732
  FastSinCos(ARadians, S, C);
733
  Result := S / C;
734
end;
735

736
function FastTan(const ARadians: TVector4): TVector4;
737
var
738
  S, C: TVector4;
739
begin
740
  FastSinCos(ARadians, S, C);
741
  Result := S / C;
742
end;
743

744
function FastArcTan2(const Y, X: Single): Single;
745
var
746
  Z: Single;
747
begin
748
  if (X = 0) then
749
  begin
750
    if (Y > 0) then
751
      Exit(0.5 * Pi);
752
    if (Y = 0) then
753
      Exit(0);
754
    Exit(-0.5 * Pi);
755
  end;
756

757
  Z := Y / X;
758
  if (Abs(Z) < 1) then
759
  begin
760
    Result := Z / (1.0 + 0.28 * Z * Z);
761
    if (X < 0) then
762
    begin
763
      if (Y < 0) then
764
        Result := Result - Pi
765
      else
766
        Result := Result + Pi;
767
    end;
768
  end
769
  else
770
  begin
771
    Result := (0.5 * Pi) - Z / (Z * Z + 0.28);
772
    if (Y < 0) then
773
      Result := Result - Pi;
774
  end;
775
end;
776

777
function FastArcTan2(const Y, X: TVector2): TVector2;
778
begin
779
  Result.Init(FastArcTan2(Y.X, X.X), FastArcTan2(Y.Y, X.Y));
780
end;
781

782
function FastArcTan2(const Y, X: TVector3): TVector3;
783
begin
784
  Result.Init(FastArcTan2(Y.X, X.X), FastArcTan2(Y.Y, X.Y), FastArcTan2(Y.Z, X.Z));
785
end;
786

787
function FastArcTan2(const Y, X: TVector4): TVector4;
788
begin
789
  Result.Init(FastArcTan2(Y.X, X.X), FastArcTan2(Y.Y, X.Y), FastArcTan2(Y.Z, X.Z), FastArcTan2(Y.W, X.W));
790
end;
791

792
{ Common functions }
793

794
function Min(const A, B: Single): Single;
795
begin
796
  Result := System.Math.Min(A, B);
797
end;
798

799
function Max(const A, B: Single): Single;
800
begin
801
  Result := System.Math.Max(A, B);
802
end;
803

804
function Mix(const A, B, T: Single): Single;
805
begin
806
//  Result := (A * (1 - T)) + (B * T);
807
  Result := A + (T * (B - A)); // Faster
808
end;
809

810
function Step(const AEdge, A: Single): Single;
811
begin
812
  if (A < AEdge) then
813
    Result := 0
814
  else
815
    Result := 1;
816
end;
817

818
function SmoothStep(const AEdge0, AEdge1, A: Single): Single;
819
var
820
  Temp: Single;
821
begin
822
  Assert(AEdge1 > AEdge0);
823
  if (A < AEdge0) then
824
    Result := 0
825
  else if (A > AEdge1) then
826
    Result := 1
827
  else
828
  begin
829
    Temp := (A - AEdge0) / (AEdge1 - AEdge0);
830
    Result := Temp * Temp * (3 - (2 * Temp));
831
  end;
832
end;
833

834
function FMA(const A, B, C: Single): Single;
835
begin
836
  Result := (A * B) + C;
837
end;
838

839
{ TVector2 }
840

841
function TVector2.AngleTo(const ATarget: TVector2): Single;
842
begin
843
  Result := Neslib.FastMath.ArcTan2(Cross(ATarget), Dot(ATarget));
844
end;
845

846
function TVector2.Clamp(const AMinLength, AMaxLength: Single): TVector2;
847
var
848
  LenSq, EdgeSq: Single;
849
begin
850
  LenSq := GetLengthSquared;
851
  if (LenSq = 0) then
852
    Exit(Self);
853

854
  EdgeSq := AMaxLength * AMaxLength;
855
  if (LenSq > EdgeSq) then
856
    Exit(Self * Sqrt(EdgeSq / LenSq));
857

858
  EdgeSq := AMinLength * AMinLength;
859
  if (LenSq < EdgeSq) then
860
    Exit(Self * Sqrt(EdgeSq / LenSq));
861

862
  Result := Self;
863
end;
864

865
function TVector2.Cross(const AOther: TVector2): Single;
866
begin
867
  Result := (X * AOther.Y) - (Y * AOther.X);
868
end;
869

870
class operator TVector2.Equal(const A, B: TVector2): Boolean;
871
begin
872
  Result := (A.X = B.X) and (A.Y = B.Y);
873
end;
874

875
function TVector2.Equals(const AOther: TVector2; const ATolerance: Single): Boolean;
876
begin
877
  Result := (Abs(X - AOther.X) <= ATolerance)
878
        and (Abs(Y - AOther.Y) <= ATolerance);
879
end;
880

881
function TVector2.GetAngle: Single;
882
begin
883
  Result := Neslib.FastMath.ArcTan2(Y, X)
884
end;
885

886
function TVector2.GetComponent(const AIndex: Integer): Single;
887
begin
888
  Assert((AIndex >= 0) and (AIndex < 2));
889
  Result := C[AIndex];
890
end;
891

892
function TVector2.HasSameDirection(const AOther: TVector2): Boolean;
893
begin
894
  Result := (Dot(AOther) > 0);
895
end;
896

897
function TVector2.HasOppositeDirection(const AOther: TVector2): Boolean;
898
begin
899
  Result := (Dot(AOther) < 0);
900
end;
901

902
class operator TVector2.Implicit(const A: TPointF): TVector2;
903
begin
904
  Result.X := A.X;
905
  Result.Y := A.Y;
906
end;
907

908
class operator TVector2.Implicit(const A: TVector2): TPointF;
909
begin
910
  Result.X := A.X;
911
  Result.Y := A.Y;
912
end;
913

914
procedure TVector2.Init;
915
begin
916
  X := 0;
917
  Y := 0;
918
end;
919

920
procedure TVector2.Init(const A: Single);
921
begin
922
  X := A;
923
  Y := A;
924
end;
925

926
procedure TVector2.Init(const A1, A2: Single);
927
begin
928
  X := A1;
929
  Y := A2;
930
end;
931

932
procedure TVector2.Init(const APoint: TPoint);
933
begin
934
  X := APoint.X;
935
  Y := APoint.Y;
936
end;
937

938
function TVector2.IsCollinear(const AOther: TVector2; const ATolerance: Single): Boolean;
939
begin
940
  Result := IsParallel(AOther, ATolerance) and (Dot(AOther) > 0);
941
end;
942

943
function TVector2.IsCollinearOpposite(const AOther: TVector2; const ATolerance: Single): Boolean;
944
begin
945
  Result := IsParallel(AOther, ATolerance) and (Dot(AOther) < 0);
946
end;
947

948
function TVector2.IsNormalized: Boolean;
949
begin
950
  Result := IsNormalized(0.000000001);
951
end;
952

953
function TVector2.IsNormalized(const AErrorMargin: Single): Boolean;
954
begin
955
  Result := (Abs(LengthSquared - 1.0) < AErrorMargin);
956
end;
957

958
function TVector2.IsParallel(const AOther: TVector2; const ATolerance: Single): Boolean;
959
begin
960
  Result := (Abs(X * AOther.Y - Y * AOther.X) <= ATolerance);
961
end;
962

963
function TVector2.IsPerpendicular(const AOther: TVector2; const ATolerance: Single): Boolean;
964
begin
965
  Result := (Abs(Dot(AOther)) <= ATolerance);
966
end;
967

968
function TVector2.IsZero: Boolean;
969
begin
970
  Result := (X = 0) and (Y = 0);
971
end;
972

973
function TVector2.IsZero(const AErrorMargin: Single): Boolean;
974
begin
975
  Result := (LengthSquared < AErrorMargin);
976
end;
977

978
function TVector2.Lerp(const ATarget: TVector2; const AAlpha: Single): TVector2;
979
begin
980
  Result := Mix(Self, ATarget, AAlpha);
981
end;
982

983
function TVector2.Limit(const AMaxLength: Single): TVector2;
984
begin
985
  Result := LimitSquared(AMaxLength * AMaxLength);
986
end;
987

988
function TVector2.LimitSquared(const AMaxLengthSquared: Single): TVector2;
989
var
990
  LenSq: Single;
991
begin
992
  LenSq := GetLengthSquared;
993
  if (LenSq > AMaxLengthSquared) then
994
    Result := Self * Sqrt(AMaxLengthSquared / LenSq)
995
  else
996
    Result := Self;
997
end;
998

999
class operator TVector2.Negative(const A: TVector2): TVector2;
1000
begin
1001
  Result.X := -A.X;
1002
  Result.Y := -A.Y;
1003
end;
1004

1005
function TVector2.Normalize: TVector2;
1006
begin
1007
  Result := Self / Length;
1008
end;
1009

1010
class operator TVector2.NotEqual(const A, B: TVector2): Boolean;
1011
begin
1012
  Result := (A.X <> B.X) or (A.Y <> B.Y);
1013
end;
1014

1015
procedure TVector2.Offset(const ADeltaX, ADeltaY: Single);
1016
begin
1017
  X := X + ADeltaX;
1018
  Y := Y + ADeltaY;
1019
end;
1020

1021
procedure TVector2.Offset(const ADelta: TVector2);
1022
begin
1023
  Self := Self + ADelta;
1024
end;
1025

1026
function TVector2.Rotate(const ARadians: Single): TVector2;
1027
var
1028
  S, C: Single;
1029
begin
1030
  FastSinCos(ARadians, S, C);
1031
  Result.X := (X * C) - (Y * S);
1032
  Result.Y := (X * S) + (Y * C);
1033
end;
1034

1035
function TVector2.Rotate90CCW: TVector2;
1036
begin
1037
  Result.X := -Y;
1038
  Result.Y := X;
1039
end;
1040

1041
function TVector2.Rotate90CW: TVector2;
1042
begin
1043
  Result.X := Y;
1044
  Result.Y := -X;
1045
end;
1046

1047
procedure TVector2.SetLerp(const ATarget: TVector2; const AAlpha: Single);
1048
begin
1049
  Self := Mix(Self, ATarget, AAlpha);
1050
end;
1051

1052
procedure TVector2.SetNormalized;
1053
begin
1054
  Self := Self / Length;
1055
end;
1056

1057
procedure TVector2.SetRotated90CCW;
1058
begin
1059
  Self := Rotate90CCW;
1060
end;
1061

1062
procedure TVector2.SetRotated90CW;
1063
begin
1064
  Self := Rotate90CW;
1065
end;
1066

1067
procedure TVector2.SetAngle(const AValue: Single);
1068
begin
1069
  X := Length;
1070
  Y := 0;
1071
  SetRotated(AValue);
1072
end;
1073

1074
procedure TVector2.SetClamped(const AMinLength, AMaxLength: Single);
1075
begin
1076
  Self := Clamp(AMinLength, AMaxLength);
1077
end;
1078

1079
procedure TVector2.SetComponent(const AIndex: Integer; const Value: Single);
1080
begin
1081
  Assert((AIndex >= 0) and (AIndex < 2));
1082
  C[AIndex] := Value;
1083
end;
1084

1085
procedure TVector2.SetLength(const AValue: Single);
1086
begin
1087
  SetLengthSquared(AValue * AValue);
1088
end;
1089

1090
procedure TVector2.SetLengthSquared(const AValue: Single);
1091
var
1092
  LenSq: Single;
1093
begin
1094
  LenSq := GetLengthSquared;
1095
  if (LenSq <> 0) and (LenSq <> AValue) then
1096
    Self := Self * Sqrt(AValue / LenSq);
1097
end;
1098

1099
procedure TVector2.SetLimit(const AMaxLength: Single);
1100
begin
1101
  Self := LimitSquared(AMaxLength * AMaxLength);
1102
end;
1103

1104
procedure TVector2.SetLimitSquared(const AMaxLengthSquared: Single);
1105
begin
1106
  Self := LimitSquared(AMaxLengthSquared);
1107
end;
1108

1109
procedure TVector2.SetRotated(const ARadians: Single);
1110
begin
1111
  Self := Rotate(ARadians);
1112
end;
1113

1114
{ _TVector2Helper }
1115

1116
function _TVector2Helper.Floor: TIVector2;
1117
begin
1118
  Result := Neslib.FastMath.Floor(Self);
1119
end;
1120

1121
function _TVector2Helper.Ceiling: TIVector2;
1122
begin
1123
  Result := Neslib.FastMath.Ceil(Self);
1124
end;
1125

1126
function _TVector2Helper.Truncate: TIVector2;
1127
begin
1128
  Result := Neslib.FastMath.Trunc(Self);
1129
end;
1130

1131
function _TVector2Helper.Round: TIVector2;
1132
begin
1133
  Result := Neslib.FastMath.Round(Self);
1134
end;
1135

1136
{ TVector3 }
1137

1138
function TVector3.Clamp(const AMinLength, AMaxLength: Single): TVector3;
1139
var
1140
  LenSq, EdgeSq: Single;
1141
begin
1142
  LenSq := GetLengthSquared;
1143
  if (LenSq = 0) then
1144
    Exit(Self);
1145

1146
  EdgeSq := AMaxLength * AMaxLength;
1147
  if (LenSq > EdgeSq) then
1148
    Exit(Self * Sqrt(EdgeSq / LenSq));
1149

1150
  EdgeSq := AMinLength * AMinLength;
1151
  if (LenSq < EdgeSq) then
1152
    Exit(Self * Sqrt(EdgeSq / LenSq));
1153

1154
  Result := Self;
1155
end;
1156

1157
class operator TVector3.Equal(const A, B: TVector3): Boolean;
1158
begin
1159
  Result := (A.X = B.X) and (A.Y = B.Y) and (A.Z = B.Z);
1160
end;
1161

1162
function TVector3.Equals(const AOther: TVector3; const ATolerance: Single): Boolean;
1163
begin
1164
  Result := (Abs(X - AOther.X) <= ATolerance)
1165
        and (Abs(Y - AOther.Y) <= ATolerance)
1166
        and (Abs(Z - AOther.Z) <= ATolerance);
1167
end;
1168

1169
function TVector3.GetComponent(const AIndex: Integer): Single;
1170
begin
1171
  Assert((AIndex >= 0) and (AIndex < 3));
1172
  Result := C[AIndex];
1173
end;
1174

1175
function TVector3.HasSameDirection(const AOther: TVector3): Boolean;
1176
begin
1177
  Result := (Dot(AOther) > 0);
1178
end;
1179

1180
function TVector3.HasOppositeDirection(const AOther: TVector3): Boolean;
1181
begin
1182
  Result := (Dot(AOther) < 0);
1183
end;
1184

1185
class operator TVector3.Implicit(const A: TPoint3D): TVector3;
1186
begin
1187
  Result.X := A.X;
1188
  Result.Y := A.Y;
1189
  Result.Z := A.Z;
1190
end;
1191

1192
class operator TVector3.Implicit(const A: TVector3): TPoint3D;
1193
begin
1194
  Result.X := A.X;
1195
  Result.Y := A.Y;
1196
  Result.Z := A.Z;
1197
end;
1198

1199
procedure TVector3.Init(const A: Single);
1200
begin
1201
  X := A;
1202
  Y := A;
1203
  Z := A;
1204
end;
1205

1206
procedure TVector3.Init;
1207
begin
1208
  X := 0;
1209
  Y := 0;
1210
  Z := 0;
1211
end;
1212

1213
procedure TVector3.Init(const A1, A2, A3: Single);
1214
begin
1215
  X := A1;
1216
  Y := A2;
1217
  Z := A3;
1218
end;
1219

1220
procedure TVector3.Init(const A1: Single; const A2: TVector2);
1221
begin
1222
  X := A1;
1223
  Y := A2.X;
1224
  Z := A2.Y;
1225
end;
1226

1227
procedure TVector3.Init(const A1: TVector2; const A2: Single);
1228
begin
1229
  X := A1.X;
1230
  Y := A1.Y;
1231
  Z := A2;
1232
end;
1233

1234
function TVector3.IsCollinear(const AOther: TVector3; const ATolerance: Single): Boolean;
1235
begin
1236
  Result := IsParallel(AOther, ATolerance) and (Dot(AOther) > 0);
1237
end;
1238

1239
function TVector3.IsCollinearOpposite(const AOther: TVector3; const ATolerance: Single): Boolean;
1240
begin
1241
  Result := IsParallel(AOther, ATolerance) and (Dot(AOther) < 0);
1242
end;
1243

1244
function TVector3.IsNormalized: Boolean;
1245
begin
1246
  Result := IsNormalized(0.000000001);
1247
end;
1248

1249
function TVector3.IsNormalized(const AErrorMargin: Single): Boolean;
1250
begin
1251
  Result := (Abs(LengthSquared - 1.0) < AErrorMargin);
1252
end;
1253

1254
function TVector3.IsParallel(const AOther: TVector3; const ATolerance: Single): Boolean;
1255
begin
1256
  Result := ((Vector3(Y * AOther.Z - Z * AOther.Y,
1257
                      Z * AOther.X - X * AOther.Z,
1258
                      X * AOther.Y - Y * AOther.X).LengthSquared) <= ATolerance);
1259
end;
1260

1261
function TVector3.IsPerpendicular(const AOther: TVector3; const ATolerance: Single): Boolean;
1262
begin
1263
  Result := (Abs(Dot(AOther)) <= ATolerance);
1264
end;
1265

1266
function TVector3.IsZero: Boolean;
1267
begin
1268
  Result := (X = 0) and (Y = 0) and (Z = 0);
1269
end;
1270

1271
function TVector3.IsZero(const AErrorMargin: Single): Boolean;
1272
begin
1273
  Result := (LengthSquared < AErrorMargin);
1274
end;
1275

1276
function TVector3.Lerp(const ATarget: TVector3; const AAlpha: Single): TVector3;
1277
begin
1278
  Result := Mix(Self, ATarget, AAlpha);
1279
end;
1280

1281
function TVector3.Limit(const AMaxLength: Single): TVector3;
1282
begin
1283
  Result := LimitSquared(AMaxLength * AMaxLength);
1284
end;
1285

1286
function TVector3.LimitSquared(const AMaxLengthSquared: Single): TVector3;
1287
var
1288
  LenSq: Single;
1289
begin
1290
  LenSq := GetLengthSquared;
1291
  if (LenSq > AMaxLengthSquared) then
1292
    Result := Self * Sqrt(AMaxLengthSquared / LenSq)
1293
  else
1294
    Result := Self;
1295
end;
1296

1297
function TVector3.Normalize: TVector3;
1298
begin
1299
  Result := Self / Length;
1300
end;
1301

1302
class operator TVector3.NotEqual(const A, B: TVector3): Boolean;
1303
begin
1304
  Result := (A.X <> B.X) or (A.Y <> B.Y) or (A.Z <> B.Z);
1305
end;
1306

1307
procedure TVector3.Offset(const ADeltaX, ADeltaY, ADeltaZ: Single);
1308
begin
1309
  X := X + ADeltaX;
1310
  Y := Y + ADeltaY;
1311
  Z := Z + ADeltaZ;
1312
end;
1313

1314
procedure TVector3.Offset(const ADelta: TVector3);
1315
begin
1316
  Self := Self + ADelta;
1317
end;
1318

1319
procedure TVector3.SetClamped(const AMinLength, AMaxLength: Single);
1320
begin
1321
  Self := Clamp(AMinLength, AMaxLength);
1322
end;
1323

1324
procedure TVector3.SetComponent(const AIndex: Integer; const Value: Single);
1325
begin
1326
  Assert((AIndex >= 0) and (AIndex < 3));
1327
  C[AIndex] := Value;
1328
end;
1329

1330
procedure TVector3.SetLength(const AValue: Single);
1331
begin
1332
  SetLengthSquared(AValue * AValue);
1333
end;
1334

1335
procedure TVector3.SetLengthSquared(const AValue: Single);
1336
var
1337
  LenSq: Single;
1338
begin
1339
  LenSq := GetLengthSquared;
1340
  if (LenSq <> 0) and (LenSq <> AValue) then
1341
    Self := Self * Sqrt(AValue / LenSq);
1342
end;
1343

1344
procedure TVector3.SetLerp(const ATarget: TVector3; const AAlpha: Single);
1345
begin
1346
  Self := Mix(Self, ATarget, AAlpha);
1347
end;
1348

1349
procedure TVector3.SetLimit(const AMaxLength: Single);
1350
begin
1351
  Self := LimitSquared(AMaxLength * AMaxLength);
1352
end;
1353

1354
procedure TVector3.SetLimitSquared(const AMaxLengthSquared: Single);
1355
begin
1356
  Self := LimitSquared(AMaxLengthSquared);
1357
end;
1358

1359
procedure TVector3.SetNormalized;
1360
begin
1361
  Self := Self / Length;
1362
end;
1363

1364
{ _TVector3Helper }
1365

1366
function _TVector3Helper.Floor: TIVector3;
1367
begin
1368
  Result := Neslib.FastMath.Floor(Self);
1369
end;
1370

1371
function _TVector3Helper.Ceiling: TIVector3;
1372
begin
1373
  Result := Neslib.FastMath.Ceil(Self);
1374
end;
1375

1376
function _TVector3Helper.Truncate: TIVector3;
1377
begin
1378
  Result := Neslib.FastMath.Trunc(Self);
1379
end;
1380

1381
function _TVector3Helper.Round: TIVector3;
1382
begin
1383
  Result := Neslib.FastMath.Round(Self);
1384
end;
1385

1386
{ TVector4 }
1387

1388
function TVector4.Clamp(const AMinLength, AMaxLength: Single): TVector4;
1389
var
1390
  LenSq, EdgeSq: Single;
1391
begin
1392
  LenSq := GetLengthSquared;
1393
  if (LenSq = 0) then
1394
    Exit(Self);
1395

1396
  EdgeSq := AMaxLength * AMaxLength;
1397
  if (LenSq > EdgeSq) then
1398
    Exit(Self * Sqrt(EdgeSq / LenSq));
1399

1400
  EdgeSq := AMinLength * AMinLength;
1401
  if (LenSq < EdgeSq) then
1402
    Exit(Self * Sqrt(EdgeSq / LenSq));
1403

1404
  Result := Self;
1405
end;
1406

1407
class operator TVector4.Equal(const A, B: TVector4): Boolean;
1408
begin
1409
  Result := (A.X = B.X) and (A.Y = B.Y) and (A.Z = B.Z) and (A.W = B.W);
1410
end;
1411

1412
function TVector4.Equals(const AOther: TVector4; const ATolerance: Single): Boolean;
1413
begin
1414
  Result := (Abs(X - AOther.X) <= ATolerance)
1415
        and (Abs(Y - AOther.Y) <= ATolerance)
1416
        and (Abs(Z - AOther.Z) <= ATolerance)
1417
        and (Abs(W - AOther.W) <= ATolerance);
1418
end;
1419

1420
function TVector4.GetComponent(const AIndex: Integer): Single;
1421
begin
1422
  Assert((AIndex >= 0) and (AIndex < 4));
1423
  Result := C[AIndex];
1424
end;
1425

1426
function TVector4.HasSameDirection(const AOther: TVector4): Boolean;
1427
begin
1428
  Result := (((X * AOther.X) + (Y * AOther.Y) + (Z * AOther.Z)) > 0);
1429
end;
1430

1431
function TVector4.HasOppositeDirection(const AOther: TVector4): Boolean;
1432
begin
1433
  Result := (((X * AOther.X) + (Y * AOther.Y) + (Z * AOther.Z)) < 0);
1434
end;
1435

1436
class operator TVector4.Implicit(const A: TVector3D): TVector4;
1437
begin
1438
  Result.X := A.X;
1439
  Result.Y := A.Y;
1440
  Result.Z := A.Z;
1441
  Result.W := A.W;
1442
end;
1443

1444
class operator TVector4.Implicit(const A: TVector4): TVector3D;
1445
begin
1446
  Result.X := A.X;
1447
  Result.Y := A.Y;
1448
  Result.Z := A.Z;
1449
  Result.W := A.W;
1450
end;
1451

1452
procedure TVector4.Init(const A1, A2, A3, A4: Single);
1453
begin
1454
  X := A1;
1455
  Y := A2;
1456
  Z := A3;
1457
  W := A4;
1458
end;
1459

1460
procedure TVector4.Init(const A: Single);
1461
begin
1462
  X := A;
1463
  Y := A;
1464
  Z := A;
1465
  W := A;
1466
end;
1467

1468
procedure TVector4.Init;
1469
begin
1470
  X := 0;
1471
  Y := 0;
1472
  Z := 0;
1473
  W := 0;
1474
end;
1475

1476
procedure TVector4.Init(const A1: TVector2; const A2, A3: Single);
1477
begin
1478
  X := A1.X;
1479
  Y := A1.Y;
1480
  Z := A2;
1481
  W := A3;
1482
end;
1483

1484
procedure TVector4.Init(const A1, A2: TVector2);
1485
begin
1486
  X := A1.X;
1487
  Y := A1.Y;
1488
  Z := A2.X;
1489
  W := A2.Y;
1490
end;
1491

1492
procedure TVector4.Init(const A1, A2: Single; const A3: TVector2);
1493
begin
1494
  X := A1;
1495
  Y := A2;
1496
  Z := A3.X;
1497
  W := A3.Y;
1498
end;
1499

1500
procedure TVector4.Init(const A1: Single; const A2: TVector2; const A3: Single);
1501
begin
1502
  X := A1;
1503
  Y := A2.X;
1504
  Z := A2.Y;
1505
  W := A3;
1506
end;
1507

1508
procedure TVector4.Init(const A1: TVector3; const A2: Single);
1509
begin
1510
  X := A1.X;
1511
  Y := A1.Y;
1512
  Z := A1.Z;
1513
  W := A2;
1514
end;
1515

1516
procedure TVector4.Init(const A1: Single; const A2: TVector3);
1517
begin
1518
  X := A1;
1519
  Y := A2.X;
1520
  Z := A2.Y;
1521
  W := A2.Z;
1522
end;
1523

1524
function TVector4.IsCollinear(const AOther: TVector4; const ATolerance: Single): Boolean;
1525
begin
1526
  Result := IsParallel(AOther, ATolerance) and (HasSameDirection(AOther));
1527
end;
1528

1529
function TVector4.IsCollinearOpposite(const AOther: TVector4; const ATolerance: Single): Boolean;
1530
begin
1531
  Result := IsParallel(AOther, ATolerance) and (HasOppositeDirection(AOther));
1532
end;
1533

1534
function TVector4.IsNormalized: Boolean;
1535
begin
1536
  Result := IsNormalized(0.000000001);
1537
end;
1538

1539
function TVector4.IsNormalized(const AErrorMargin: Single): Boolean;
1540
begin
1541
  Result := (Abs(LengthSquared - 1.0) < AErrorMargin);
1542
end;
1543

1544
function TVector4.IsParallel(const AOther: TVector4; const ATolerance: Single): Boolean;
1545
begin
1546
  Result := ((Vector3(Y * AOther.Z - Z * AOther.Y,
1547
                      Z * AOther.X - X * AOther.Z,
1548
                      X * AOther.Y - Y * AOther.X).LengthSquared) <= ATolerance);
1549
end;
1550

1551
function TVector4.IsPerpendicular(const AOther: TVector4; const ATolerance: Single): Boolean;
1552
begin
1553
  Result := (Abs((X * AOther.X) + (Y * AOther.Y) + (Z * AOther.Z)) <= ATolerance);
1554
end;
1555

1556
function TVector4.IsZero: Boolean;
1557
begin
1558
  Result := (X = 0) and (Y = 0) and (Z = 0) and (W = 0);
1559
end;
1560

1561
function TVector4.IsZero(const AErrorMargin: Single): Boolean;
1562
begin
1563
  Result := (LengthSquared < AErrorMargin);
1564
end;
1565

1566
function TVector4.Lerp(const ATarget: TVector4; const AAlpha: Single): TVector4;
1567
begin
1568
  Result := Mix(Self, ATarget, AAlpha);
1569
end;
1570

1571
function TVector4.Limit(const AMaxLength: Single): TVector4;
1572
begin
1573
  Result := LimitSquared(AMaxLength * AMaxLength);
1574
end;
1575

1576
function TVector4.LimitSquared(const AMaxLengthSquared: Single): TVector4;
1577
var
1578
  LenSq: Single;
1579
begin
1580
  LenSq := GetLengthSquared;
1581
  if (LenSq > AMaxLengthSquared) then
1582
    Result := Self * Sqrt(AMaxLengthSquared / LenSq)
1583
  else
1584
    Result := Self;
1585
end;
1586

1587
function TVector4.Normalize: TVector4;
1588
begin
1589
  Result := Self / Length;
1590
end;
1591

1592
class operator TVector4.NotEqual(const A, B: TVector4): Boolean;
1593
begin
1594
  Result := (A.X <> B.X) or (A.Y <> B.Y) or (A.Z <> B.Z) or (A.W <> B.W);
1595
end;
1596

1597
procedure TVector4.Offset(const ADeltaX, ADeltaY, ADeltaZ, ADeltaW: Single);
1598
begin
1599
  X := X + ADeltaX;
1600
  Y := Y + ADeltaY;
1601
  Z := Z + ADeltaZ;
1602
  W := W + ADeltaW;
1603
end;
1604

1605
procedure TVector4.Offset(const ADelta: TVector4);
1606
begin
1607
  Self := Self + ADelta;
1608
end;
1609

1610
procedure TVector4.SetClamped(const AMinLength, AMaxLength: Single);
1611
begin
1612
  Self := Clamp(AMinLength, AMaxLength);
1613
end;
1614

1615
procedure TVector4.SetComponent(const AIndex: Integer; const Value: Single);
1616
begin
1617
  Assert((AIndex >= 0) and (AIndex < 4));
1618
  C[AIndex] := Value;
1619
end;
1620

1621
procedure TVector4.SetLength(const AValue: Single);
1622
begin
1623
  SetLengthSquared(AValue * AValue);
1624
end;
1625

1626
procedure TVector4.SetLengthSquared(const AValue: Single);
1627
var
1628
  LenSq: Single;
1629
begin
1630
  LenSq := GetLengthSquared;
1631
  if (LenSq <> 0) and (LenSq <> AValue) then
1632
    Self := Self * Sqrt(AValue / LenSq);
1633
end;
1634

1635
procedure TVector4.SetLerp(const ATarget: TVector4; const AAlpha: Single);
1636
begin
1637
  Self := Mix(Self, ATarget, AAlpha);
1638
end;
1639

1640
procedure TVector4.SetLimit(const AMaxLength: Single);
1641
begin
1642
  Self := LimitSquared(AMaxLength * AMaxLength);
1643
end;
1644

1645
procedure TVector4.SetLimitSquared(const AMaxLengthSquared: Single);
1646
begin
1647
  Self := LimitSquared(AMaxLengthSquared);
1648
end;
1649

1650
procedure TVector4.SetNormalized;
1651
begin
1652
  Self := Self / Length;
1653
end;
1654

1655
{ _TVector4Helper }
1656

1657
function _TVector4Helper.Floor: TIVector4;
1658
begin
1659
  Result := Neslib.FastMath.Floor(Self);
1660
end;
1661

1662
function _TVector4Helper.Ceiling: TIVector4;
1663
begin
1664
  Result := Neslib.FastMath.Ceil(Self);
1665
end;
1666

1667
function _TVector4Helper.Truncate: TIVector4;
1668
begin
1669
  Result := Neslib.FastMath.Trunc(Self);
1670
end;
1671

1672
function _TVector4Helper.Round: TIVector4;
1673
begin
1674
  Result := Neslib.FastMath.Round(Self);
1675
end;
1676

1677
{ TQuaternion }
1678

1679
function TQuaternion.Conjugate: TQuaternion;
1680
begin
1681
  Result.X := -X;
1682
  Result.Y := -Y;
1683
  Result.Z := -Z;
1684
  Result.W := W;
1685
end;
1686

1687
class operator TQuaternion.Implicit(const A: TQuaternion3D): TQuaternion;
1688
begin
1689
  Result.X := A.V[0];
1690
  Result.Y := A.V[1];
1691
  Result.Z := A.V[2];
1692
  Result.W := A.V[3];
1693
end;
1694

1695
class operator TQuaternion.Implicit(const A: TQuaternion): TQuaternion3D;
1696
begin
1697
  Result.V[0] := A.X;
1698
  Result.V[1] := A.Y;
1699
  Result.V[2] := A.Z;
1700
  Result.V[3] := A.W;
1701
end;
1702

1703
procedure TQuaternion.Init;
1704
begin
1705
  X := 0;
1706
  Y := 0;
1707
  Z := 0;
1708
  W := 1;
1709
end;
1710

1711
procedure TQuaternion.Init(const AX, AY, AZ, AW: Single);
1712
begin
1713
  X := AX;
1714
  Y := AY;
1715
  Z := AZ;
1716
  W := AW;
1717
end;
1718

1719
procedure TQuaternion.Init(const AAxis: TVector3; const AAngleRadians: Single);
1720
var
1721
  D, S, C: Single;
1722
begin
1723
  D := AAxis.Length;
1724
  if (D = 0) then
1725
  begin
1726
    Init;
1727
    Exit;
1728
  end;
1729

1730
  D := 1 / D;
1731
  FastSinCos(AAngleRadians * 0.5, S, C);
1732
  X := D * AAxis.X * S;
1733
  Y := D * AAxis.Y * S;
1734
  Z := D * AAxis.Z * S;
1735
  W := C;
1736
  SetNormalized;
1737
end;
1738

1739
procedure TQuaternion.Init(const AYaw, APitch, ARoll: Single);
1740
var
1741
  A, S, C: TVector4;
1742
  CYSP, SYCP, CYCP, SYSP: Single;
1743
begin
1744
  A.Init(APitch * 0.5, AYaw * 0.5, ARoll * 0.5, 0);
1745
  FastSinCos(A, S, C);
1746

1747
  CYSP := C.Y * S.X;
1748
  SYCP := S.Y * C.X;
1749
  CYCP := C.Y * C.X;
1750
  SYSP := S.Y * S.X;
1751

1752
  X := (CYSP * C.Z) + (SYCP * S.Z);
1753
  Y := (SYCP * C.Z) - (CYSP * S.Z);
1754
  Z := (CYCP * S.Z) - (SYSP * C.Z);
1755
  W := (CYCP * C.Z) + (SYSP * S.Z);
1756
end;
1757

1758
procedure TQuaternion.Init(const AMatrix: TMatrix4);
1759
var
1760
  Trace, S: double;
1761
begin
1762
  Trace := AMatrix.m11 + AMatrix.m22 + AMatrix.m33;
1763
  if (Trace > EPSILON) then
1764
  begin
1765
    S := 0.5 / Sqrt(Trace + 1.0);
1766
    X := (AMatrix.m23 - AMatrix.m32) * S;
1767
    Y := (AMatrix.m31 - AMatrix.m13) * S;
1768
    Z := (AMatrix.m12 - AMatrix.m21) * S;
1769
    W := 0.25 / S;
1770
  end
1771
  else if (AMatrix.m11 > AMatrix.m22) and (AMatrix.m11 > AMatrix.m33) then
1772
  begin
1773
    S := Sqrt(Neslib.FastMath.Max(EPSILON, 1 + AMatrix.m11 - AMatrix.m22 - AMatrix.m33)) * 2.0;
1774
    X := 0.25 * S;
1775
    Y := (AMatrix.m12 + AMatrix.m21) / S;
1776
    Z := (AMatrix.m31 + AMatrix.m13) / S;
1777
    W := (AMatrix.m23 - AMatrix.m32) / S;
1778
  end
1779
  else if (AMatrix.m22 > AMatrix.m33) then
1780
  begin
1781
    S := Sqrt(Neslib.FastMath.Max(EPSILON, 1 + AMatrix.m22 - AMatrix.m11 - AMatrix.m33)) * 2.0;
1782
    X := (AMatrix.m12 + AMatrix.m21) / S;
1783
    Y := 0.25 * S;
1784
    Z := (AMatrix.m23 + AMatrix.m32) / S;
1785
    W := (AMatrix.m31 - AMatrix.m13) / S;
1786
  end else
1787
  begin
1788
    S := Sqrt(Neslib.FastMath.Max(EPSILON, 1 + AMatrix.m33 - AMatrix.m11 - AMatrix.m22)) * 2.0;
1789
    X := (AMatrix.m31 + AMatrix.m13) / S;
1790
    Y := (AMatrix.m23 + AMatrix.m32) / S;
1791
    Z := 0.25 * S;
1792
    W := (AMatrix.m12 - AMatrix.m21) / S;
1793
  end;
1794
  SetNormalized;
1795
end;
1796

1797
function TQuaternion.IsIdentity: Boolean;
1798
begin
1799
  Result := (X = 0) and (Y = 0) and (Z = 0) and (W = 1);
1800
end;
1801

1802
function TQuaternion.IsIdentity(const AErrorMargin: Single): Boolean;
1803
begin
1804
  Result := (Abs(X) <= AErrorMargin) and (Abs(Y) <= AErrorMargin)
1805
    and (Abs(Z) <= AErrorMargin) and ((Abs(W) - 1) <= AErrorMargin)
1806
end;
1807

1808
function TQuaternion.Normalize: TQuaternion;
1809
begin
1810
  Result := Self * (1 / Length);
1811
end;
1812

1813
procedure TQuaternion.SetConjugate;
1814
begin
1815
  X := -X;
1816
  Y := -Y;
1817
  Z := -Z;
1818
end;
1819

1820
procedure TQuaternion.SetNormalized;
1821
begin
1822
  Self := Self * (1 / Length);
1823
end;
1824

1825
function TQuaternion.ToMatrix: TMatrix4;
1826
var
1827
  Q: TQuaternion;
1828
  XX, XY, XZ, XW, YY, YZ, YW, ZZ, ZW: Single;
1829
begin
1830
  Q := Normalize;
1831
  XX := Q.X * Q.X;
1832
  XY := Q.X * Q.Y;
1833
  XZ := Q.X * Q.Z;
1834
  XW := Q.X * Q.W;
1835
  YY := Q.Y * Q.Y;
1836
  YZ := Q.Y * Q.Z;
1837
  YW := Q.Y * Q.W;
1838
  ZZ := Q.Z * Q.Z;
1839
  ZW := Q.Z * Q.W;
1840

1841
  Result.Init(
1842
    1 - 2 * (YY + ZZ), 2 * (XY + ZW), 2 * (XZ - YW), 0,
1843
    2 * (XY - ZW), 1 - 2 * (XX + ZZ), 2 * (YZ + XW), 0,
1844
    2 * (XZ + YW), 2 * (YZ - XW), 1 - 2 * (XX + YY), 0,
1845
    0, 0, 0, 1);
1846
end;
1847

1848
{ TMatrix2 }
1849

1850
class operator TMatrix2.Divide(const A, B: TMatrix2): TMatrix2;
1851
begin
1852
  Result := A * B.Inverse;
1853
end;
1854

1855
class operator TMatrix2.Divide(const A: TVector2; const B: TMatrix2): TVector2;
1856
begin
1857
  Result := A * B.Inverse;
1858
end;
1859

1860
class operator TMatrix2.Divide(const A: TMatrix2; const B: TVector2): TVector2;
1861
begin
1862
  Result := A.Inverse * B;
1863
end;
1864

1865
function TMatrix2.GetDeterminant: Single;
1866
begin
1867
  Result :=
1868
    + (M[0,0] * M[1,1])
1869
    - (M[1,0] * M[0,1]);
1870
end;
1871

1872
function TMatrix2.Inverse: TMatrix2;
1873
var
1874
  OneOverDeterminant: Single;
1875
begin
1876
  OneOverDeterminant := 1 / Determinant;
1877
  Result.M[0,0] := +M[1,1] * OneOverDeterminant;
1878
  Result.M[0,1] := -M[0,1] * OneOverDeterminant;
1879
  Result.M[1,0] := -M[1,0] * OneOverDeterminant;
1880
  Result.M[1,1] := +M[0,0] * OneOverDeterminant;
1881
end;
1882

1883
procedure TMatrix2.SetInversed;
1884
begin
1885
  Self := Inverse;
1886
end;
1887

1888
class operator TMatrix2.Equal(const A, B: TMatrix2): Boolean;
1889
begin
1890
  Result := (A.V[0] = B.V[0]) and (A.V[1] = B.V[1]);
1891
end;
1892

1893
procedure TMatrix2.Init(const ADiagonal: Single);
1894
begin
1895
  V[0].Init(ADiagonal, 0);
1896
  V[1].Init(0, ADiagonal);
1897
end;
1898

1899
procedure TMatrix2.Init;
1900
begin
1901
  V[0].Init(1, 0);
1902
  V[1].Init(0, 1);
1903
end;
1904

1905
procedure TMatrix2.Init(const A11, A12, A21, A22: Single);
1906
begin
1907
  V[0].Init(A11, A12);
1908
  V[1].Init(A21, A22);
1909
end;
1910

1911
class operator TMatrix2.NotEqual(const A, B: TMatrix2): Boolean;
1912
begin
1913
  Result := (A.V[0] <> B.V[0]) or (A.V[1] <> B.V[1]);
1914
end;
1915

1916
{$IFDEF FM_COLUMN_MAJOR}
1917
function TMatrix2.GetColumn(const AIndex: Integer): TVector2;
1918
begin
1919
  Assert((AIndex >= 0) and (AIndex < 2));
1920
  Result := C[AIndex];
1921
end;
1922

1923
function TMatrix2.GetComponent(const AColumn, ARow: Integer): Single;
1924
begin
1925
  Assert((AColumn >= 0) and (AColumn < 2));
1926
  Assert((ARow >= 0) and (ARow < 2));
1927
  Result := M[AColumn, ARow];
1928
end;
1929

1930
procedure TMatrix2.Init(const AColumn0, AColumn1: TVector2);
1931
begin
1932
  C[0] := AColumn0;
1933
  C[1] := AColumn1;
1934
end;
1935

1936
class operator TMatrix3.Implicit(const A: TMatrix): TMatrix3;
1937
var
1938
  M: TMatrix3 absolute A;
1939
begin
1940
  Result := M.Transpose;
1941
end;
1942

1943
class operator TMatrix3.Implicit(const A: TMatrix3): TMatrix;
1944
var
1945
  M: TMatrix3 absolute Result;
1946
begin
1947
  M := A.Transpose;
1948
end;
1949

1950
procedure TMatrix2.SetColumn(const AIndex: Integer; const Value: TVector2);
1951
begin
1952
  Assert((AIndex >= 0) and (AIndex < 2));
1953
  C[AIndex] := Value;
1954
end;
1955

1956
procedure TMatrix2.SetComponent(const AColumn, ARow: Integer; const Value: Single);
1957
begin
1958
  Assert((AColumn >= 0) and (AColumn < 2));
1959
  Assert((ARow >= 0) and (ARow < 2));
1960
  M[AColumn, ARow] := Value;
1961
end;
1962
{$ELSE}
1963
function TMatrix2.GetComponent(const ARow, AColumn: Integer): Single;
1964
begin
1965
  Assert((ARow >= 0) and (ARow < 2));
1966
  Assert((AColumn >= 0) and (AColumn < 2));
1967
  Result := M[ARow, AColumn];
1968
end;
1969

1970
function TMatrix2.GetRow(const AIndex: Integer): TVector2;
1971
begin
1972
  Assert((AIndex >= 0) and (AIndex < 2));
1973
  Result := R[AIndex];
1974
end;
1975

1976
class operator TMatrix3.Implicit(const A: TMatrix): TMatrix3;
1977
begin
1978
  Move(A, Result, SizeOf(A));
1979
end;
1980

1981
class operator TMatrix3.Implicit(const A: TMatrix3): TMatrix;
1982
begin
1983
  Move(A, Result, SizeOf(A));
1984
end;
1985

1986
procedure TMatrix2.Init(const ARow0, ARow1: TVector2);
1987
begin
1988
  R[0] := ARow0;
1989
  R[1] := ARow1;
1990
end;
1991

1992
procedure TMatrix2.SetComponent(const ARow, AColumn: Integer; const Value: Single);
1993
begin
1994
  Assert((ARow >= 0) and (ARow < 2));
1995
  Assert((AColumn >= 0) and (AColumn < 2));
1996
  M[ARow, AColumn] := Value;
1997
end;
1998

1999
procedure TMatrix2.SetRow(const AIndex: Integer; const Value: TVector2);
2000
begin
2001
  Assert((AIndex >= 0) and (AIndex < 2));
2002
  R[AIndex] := Value;
2003
end;
2004
{$ENDIF}
2005

2006
{ TMatrix3 }
2007

2008
class operator TMatrix3.Divide(const A, B: TMatrix3): TMatrix3;
2009
begin
2010
  Result := A * B.Inverse;
2011
end;
2012

2013
class operator TMatrix3.Divide(const A: TVector3; const B: TMatrix3): TVector3;
2014
begin
2015
  Result := A * B.Inverse;
2016
end;
2017

2018
class operator TMatrix3.Divide(const A: TMatrix3; const B: TVector3): TVector3;
2019
begin
2020
  Result := A.Inverse * B;
2021
end;
2022

2023
function TMatrix3.GetDeterminant: Single;
2024
begin
2025
  Result :=
2026
    + (M[0,0] * ((M[1,1] * M[2,2]) - (M[2,1] * M[1,2])))
2027
    - (M[0,1] * ((M[1,0] * M[2,2]) - (M[2,0] * M[1,2])))
2028
    + (M[0,2] * ((M[1,0] * M[2,1]) - (M[2,0] * M[1,1])));
2029
end;
2030

2031
function TMatrix3.Inverse: TMatrix3;
2032
var
2033
  OneOverDeterminant: Single;
2034
begin
2035
  OneOverDeterminant := 1 / Determinant;
2036
  Result.M[0,0] := + ((M[1,1] * M[2,2]) - (M[2,1] * M[1,2])) * OneOverDeterminant;
2037
  Result.M[1,0] := - ((M[1,0] * M[2,2]) - (M[2,0] * M[1,2])) * OneOverDeterminant;
2038
  Result.M[2,0] := + ((M[1,0] * M[2,1]) - (M[2,0] * M[1,1])) * OneOverDeterminant;
2039
  Result.M[0,1] := - ((M[0,1] * M[2,2]) - (M[2,1] * M[0,2])) * OneOverDeterminant;
2040
  Result.M[1,1] := + ((M[0,0] * M[2,2]) - (M[2,0] * M[0,2])) * OneOverDeterminant;
2041
  Result.M[2,1] := - ((M[0,0] * M[2,1]) - (M[2,0] * M[0,1])) * OneOverDeterminant;
2042
  Result.M[0,2] := + ((M[0,1] * M[1,2]) - (M[1,1] * M[0,2])) * OneOverDeterminant;
2043
  Result.M[1,2] := - ((M[0,0] * M[1,2]) - (M[1,0] * M[0,2])) * OneOverDeterminant;
2044
  Result.M[2,2] := + ((M[0,0] * M[1,1]) - (M[1,0] * M[0,1])) * OneOverDeterminant;
2045
end;
2046

2047
procedure TMatrix3.SetInversed;
2048
begin
2049
  Self := Inverse;
2050
end;
2051

2052
class operator TMatrix3.Equal(const A, B: TMatrix3): Boolean;
2053
begin
2054
  Result := (A.V[0] = B.V[0]) and (A.V[1] = B.V[1]) and (A.V[2] = B.V[2]);
2055
end;
2056

2057
procedure TMatrix3.Init(const ADiagonal: Single);
2058
begin
2059
  V[0].Init(ADiagonal, 0, 0);
2060
  V[1].Init(0, ADiagonal, 0);
2061
  V[2].Init(0, 0, ADiagonal);
2062
end;
2063

2064
procedure TMatrix3.Init;
2065
begin
2066
  V[0].Init(1, 0, 0);
2067
  V[1].Init(0, 1, 0);
2068
  V[2].Init(0, 0, 1);
2069
end;
2070

2071
procedure TMatrix3.Init(const AMatrix: TMatrix2);
2072
begin
2073
  V[0].Init(AMatrix.V[0], 0);
2074
  V[1].Init(AMatrix.V[1], 0);
2075
  V[2].Init(0, 0, 1);
2076
end;
2077

2078
procedure TMatrix3.Init(const A11, A12, A13, A21, A22, A23, A31, A32,
2079
  A33: Single);
2080
begin
2081
  V[0].Init(A11, A12, A13);
2082
  V[1].Init(A21, A22, A23);
2083
  V[2].Init(A31, A32, A33);
2084
end;
2085

2086
procedure TMatrix3.InitScaling(const AScale: Single);
2087
begin
2088
  V[0].Init(AScale, 0, 0);
2089
  V[1].Init(0, AScale, 0);
2090
  V[2].Init(0, 0, 1);
2091
end;
2092

2093
procedure TMatrix3.InitScaling(const AScaleX, AScaleY: Single);
2094
begin
2095
  V[0].Init(AScaleX, 0, 0);
2096
  V[1].Init(0, AScaleY, 0);
2097
  V[2].Init(0, 0, 1);
2098
end;
2099

2100
procedure TMatrix3.InitScaling(const AScale: TVector2);
2101
begin
2102
  V[0].Init(AScale.X, 0, 0);
2103
  V[1].Init(0, AScale.Y, 0);
2104
  V[2].Init(0, 0, 1);
2105
end;
2106

2107
procedure TMatrix3.InitTranslation(const ADeltaX, ADeltaY: Single);
2108
begin
2109
  V[0].Init(1, 0, 0);
2110
  V[1].Init(0, 1, 0);
2111
  V[2].Init(ADeltaX, ADeltaY, 1);
2112
end;
2113

2114
procedure TMatrix3.InitTranslation(const ADelta: TVector2);
2115
begin
2116
  V[0].Init(1, 0, 0);
2117
  V[1].Init(0, 1, 0);
2118
  V[2].Init(ADelta.X, ADelta.Y, 1);
2119
end;
2120

2121
class operator TMatrix3.NotEqual(const A, B: TMatrix3): Boolean;
2122
begin
2123
  Result := (A.V[0] <> B.V[0]) or (A.V[1] <> B.V[1]) or (A.V[2] <> B.V[2]);
2124
end;
2125

2126
{$IFDEF FM_COLUMN_MAJOR}
2127
function TMatrix3.GetColumn(const AIndex: Integer): TVector3;
2128
begin
2129
  Assert((AIndex >= 0) and (AIndex < 3));
2130
  Result := C[AIndex];
2131
end;
2132

2133
function TMatrix3.GetComponent(const AColumn, ARow: Integer): Single;
2134
begin
2135
  Assert((AColumn >= 0) and (AColumn < 3));
2136
  Assert((ARow >= 0) and (ARow < 3));
2137
  Result := M[AColumn, ARow];
2138
end;
2139

2140
procedure TMatrix3.Init(const AColumn0, AColumn1, AColumn2: TVector3);
2141
begin
2142
  C[0] := AColumn0;
2143
  C[1] := AColumn1;
2144
  C[2] := AColumn2;
2145
end;
2146

2147
procedure TMatrix3.InitRotation(const AAngle: Single);
2148
var
2149
  S, C: Single;
2150
begin
2151
  FastSinCos(AAngle, S, C);
2152
  Self.C[0].Init(C, S, 0);
2153
  Self.C[1].Init(-S, C, 0);
2154
  Self.C[2].Init(0, 0, 1);
2155
end;
2156

2157
procedure TMatrix3.SetColumn(const AIndex: Integer; const Value: TVector3);
2158
begin
2159
  Assert((AIndex >= 0) and (AIndex < 3));
2160
  C[AIndex] := Value;
2161
end;
2162

2163
procedure TMatrix3.SetComponent(const AColumn, ARow: Integer; const Value: Single);
2164
begin
2165
  Assert((AColumn >= 0) and (AColumn < 3));
2166
  Assert((ARow >= 0) and (ARow < 3));
2167
  M[AColumn, ARow] := Value;
2168
end;
2169
{$ELSE}
2170
function TMatrix3.GetComponent(const ARow, AColumn: Integer): Single;
2171
begin
2172
  Assert((ARow >= 0) and (ARow < 3));
2173
  Assert((AColumn >= 0) and (AColumn < 3));
2174
  Result := M[ARow, AColumn];
2175
end;
2176

2177
function TMatrix3.GetRow(const AIndex: Integer): TVector3;
2178
begin
2179
  Assert((AIndex >= 0) and (AIndex < 3));
2180
  Result := R[AIndex];
2181
end;
2182

2183
procedure TMatrix3.Init(const ARow0, ARow1, ARow2: TVector3);
2184
begin
2185
  R[0] := ARow0;
2186
  R[1] := ARow1;
2187
  R[2] := ARow2;
2188
end;
2189

2190
procedure TMatrix3.InitRotation(const AAngle: Single);
2191
var
2192
  S, C: Single;
2193
begin
2194
  FastSinCos(AAngle, S, C);
2195
  R[0].Init(C, S, 0);
2196
  R[1].Init(-S, C, 0);
2197
  R[2].Init(0, 0, 1);
2198
end;
2199

2200
procedure TMatrix3.SetComponent(const ARow, AColumn: Integer; const Value: Single);
2201
begin
2202
  Assert((ARow >= 0) and (ARow < 3));
2203
  Assert((AColumn >= 0) and (AColumn < 3));
2204
  M[ARow, AColumn] := Value;
2205
end;
2206

2207
procedure TMatrix3.SetRow(const AIndex: Integer; const Value: TVector3);
2208
begin
2209
  Assert((AIndex >= 0) and (AIndex < 3));
2210
  R[AIndex] := Value;
2211
end;
2212
{$ENDIF}
2213

2214
{ TMatrix4 }
2215

2216
class operator TMatrix4.Divide(const A, B: TMatrix4): TMatrix4;
2217
begin
2218
  Result := A * B.Inverse;
2219
end;
2220

2221
class operator TMatrix4.Divide(const A: TVector4; const B: TMatrix4): TVector4;
2222
begin
2223
  Result := A * B.Inverse;
2224
end;
2225

2226
class operator TMatrix4.Divide(const A: TMatrix4; const B: TVector4): TVector4;
2227
begin
2228
  Result := A.Inverse * B;
2229
end;
2230

2231
function TMatrix4.GetDeterminant: Single;
2232
var
2233
  F00, F01, F02, F03, F04, F05: Single;
2234
  C: TVector4;
2235
begin
2236
  F00 := (M[2,2] * M[3,3]) - (M[3,2] * M[2,3]);
2237
  F01 := (M[2,1] * M[3,3]) - (M[3,1] * M[2,3]);
2238
  F02 := (M[2,1] * M[3,2]) - (M[3,1] * M[2,2]);
2239
  F03 := (M[2,0] * M[3,3]) - (M[3,0] * M[2,3]);
2240
  F04 := (M[2,0] * M[3,2]) - (M[3,0] * M[2,2]);
2241
  F05 := (M[2,0] * M[3,1]) - (M[3,0] * M[2,1]);
2242

2243
  C.X := + ((M[1,1] * F00) - (M[1,2] * F01) + (M[1,3] * F02));
2244
  C.Y := - ((M[1,0] * F00) - (M[1,2] * F03) + (M[1,3] * F04));
2245
  C.Z := + ((M[1,0] * F01) - (M[1,1] * F03) + (M[1,3] * F05));
2246
  C.W := - ((M[1,0] * F02) - (M[1,1] * F04) + (M[1,2] * F05));
2247

2248
  Result := (M[0,0] * C.X) + (M[0,1] * C.Y) + (M[0,2] * C.Z) + (M[0,3] * C.W);
2249
end;
2250

2251
class operator TMatrix4.Equal(const A, B: TMatrix4): Boolean;
2252
begin
2253
  Result := (A.V[0] = B.V[0]) and (A.V[1] = B.V[1]) and (A.V[2] = B.V[2]) and (A.V[3] = B.V[3]);
2254
end;
2255

2256
procedure TMatrix4.Init(const ADiagonal: Single);
2257
begin
2258
  V[0].Init(ADiagonal, 0, 0, 0);
2259
  V[1].Init(0, ADiagonal, 0, 0);
2260
  V[2].Init(0, 0, ADiagonal, 0);
2261
  V[3].Init(0, 0, 0, ADiagonal);
2262
end;
2263

2264
procedure TMatrix4.Init;
2265
begin
2266
  V[0].Init(1, 0, 0, 0);
2267
  V[1].Init(0, 1, 0, 0);
2268
  V[2].Init(0, 0, 1, 0);
2269
  V[3].Init(0, 0, 0, 1);
2270
end;
2271

2272
procedure TMatrix4.Init(const A11, A12, A13, A14, A21, A22, A23, A24, A31, A32,
2273
  A33, A34, A41, A42, A43, A44: Single);
2274
begin
2275
  V[0].Init(A11, A12, A13, A14);
2276
  V[1].Init(A21, A22, A23, A24);
2277
  V[2].Init(A31, A32, A33, A34);
2278
  V[3].Init(A41, A42, A43, A44);
2279
end;
2280

2281
procedure TMatrix4.Init(const AMatrix: TMatrix2);
2282
begin
2283
  V[0].Init(AMatrix.V[0], 0, 0);
2284
  V[1].Init(AMatrix.V[1], 0, 0);
2285
  V[2].Init(0, 0, 1, 0);
2286
  V[3].Init(0, 0, 0, 1);
2287
end;
2288

2289
procedure TMatrix4.Init(const AMatrix: TMatrix3);
2290
begin
2291
  V[0].Init(AMatrix.V[0], 0);
2292
  V[1].Init(AMatrix.V[1], 0);
2293
  V[2].Init(AMatrix.V[2], 0);
2294
  V[3].Init(0, 0, 0, 1);
2295
end;
2296

2297
procedure TMatrix4.InitLookAtLH(const ACameraPosition, ACameraTarget,
2298
  ACameraUp: TVector3);
2299
var
2300
  XAxis, YAxis, ZAxis: TVector3;
2301
begin
2302
  ZAxis := (ACameraTarget - ACameraPosition).Normalize;
2303
  XAxis := ACameraUp.Cross(ZAxis).Normalize;
2304
  YAxis := ZAxis.Cross(XAxis);
2305

2306
  V[0].Init(XAxis.X, YAxis.X, ZAxis.X, 0);
2307
  V[1].Init(XAxis.Y, YAxis.Y, ZAxis.Y, 0);
2308
  V[2].Init(XAxis.Z, YAxis.Z, ZAxis.Z, 0);
2309
  V[3].Init(-XAxis.Dot(ACameraPosition),
2310
            -YAxis.Dot(ACameraPosition),
2311
            -ZAxis.Dot(ACameraPosition), 1);
2312
end;
2313

2314
procedure TMatrix4.InitLookAtRH(const ACameraPosition, ACameraTarget,
2315
  ACameraUp: TVector3);
2316
var
2317
  XAxis, YAxis, ZAxis: TVector3;
2318
begin
2319
  ZAxis := (ACameraPosition - ACameraTarget).Normalize;
2320
  XAxis := ACameraUp.Cross(ZAxis).Normalize;
2321
  YAxis := ZAxis.Cross(XAxis);
2322

2323
  V[0].Init(XAxis.X, YAxis.X, ZAxis.X, 0);
2324
  V[1].Init(XAxis.Y, YAxis.Y, ZAxis.Y, 0);
2325
  V[2].Init(XAxis.Z, YAxis.Z, ZAxis.Z, 0);
2326
  V[3].Init(-XAxis.Dot(ACameraPosition),
2327
            -YAxis.Dot(ACameraPosition),
2328
            -ZAxis.Dot(ACameraPosition), 1);
2329
end;
2330

2331
procedure TMatrix4.InitLookAtDirLH(const ACameraPosition, ACameraDirection,
2332
  ACameraUp: TVector3);
2333
var
2334
  XAxis, YAxis, ZAxis: TVector3;
2335
begin
2336
  ZAxis := -ACameraDirection.Normalize;
2337
  XAxis := ACameraUp.Cross(ZAxis).Normalize;
2338
  YAxis := ZAxis.Cross(XAxis);
2339

2340
  V[0].Init(XAxis.X, YAxis.X, ZAxis.X, 0);
2341
  V[1].Init(XAxis.Y, YAxis.Y, ZAxis.Y, 0);
2342
  V[2].Init(XAxis.Z, YAxis.Z, ZAxis.Z, 0);
2343
  V[3].Init(-XAxis.Dot(ACameraPosition),
2344
            -YAxis.Dot(ACameraPosition),
2345
            -ZAxis.Dot(ACameraPosition), 1);
2346
end;
2347

2348
procedure TMatrix4.InitLookAtDirRH(const ACameraPosition, ACameraDirection,
2349
  ACameraUp: TVector3);
2350
var
2351
  XAxis, YAxis, ZAxis: TVector3;
2352
begin
2353
  ZAxis := ACameraDirection.Normalize;
2354
  XAxis := ACameraUp.Cross(ZAxis).Normalize;
2355
  YAxis := ZAxis.Cross(XAxis);
2356

2357
  V[0].Init(XAxis.X, YAxis.X, ZAxis.X, 0);
2358
  V[1].Init(XAxis.Y, YAxis.Y, ZAxis.Y, 0);
2359
  V[2].Init(XAxis.Z, YAxis.Z, ZAxis.Z, 0);
2360
  V[3].Init(-XAxis.Dot(ACameraPosition),
2361
            -YAxis.Dot(ACameraPosition),
2362
            -ZAxis.Dot(ACameraPosition), 1);
2363
end;
2364

2365
procedure TMatrix4.InitScaling(const AScale: Single);
2366
begin
2367
  V[0].Init(AScale, 0, 0, 0);
2368
  V[1].Init(0, AScale, 0, 0);
2369
  V[2].Init(0, 0, AScale, 0);
2370
  V[3].Init(0, 0, 0, 1);
2371
end;
2372

2373
procedure TMatrix4.InitScaling(const AScaleX, AScaleY, AScaleZ: Single);
2374
begin
2375
  V[0].Init(AScaleX, 0, 0, 0);
2376
  V[1].Init(0, AScaleY, 0, 0);
2377
  V[2].Init(0, 0, AScaleZ, 0);
2378
  V[3].Init(0, 0, 0, 1);
2379
end;
2380

2381
procedure TMatrix4.InitScaling(const AScale: TVector3);
2382
begin
2383
  V[0].Init(AScale.X, 0, 0, 0);
2384
  V[1].Init(0, AScale.Y, 0, 0);
2385
  V[2].Init(0, 0, AScale.Z, 0);
2386
  V[3].Init(0, 0, 0, 1);
2387
end;
2388

2389
procedure TMatrix4.InitTranslation(const ADeltaX, ADeltaY, ADeltaZ: Single);
2390
begin
2391
  V[0].Init(1, 0, 0, 0);
2392
  V[1].Init(0, 1, 0, 0);
2393
  V[2].Init(0, 0, 1, 0);
2394
  V[3].Init(ADeltaX, ADeltaY, ADeltaZ, 1);
2395
end;
2396

2397
procedure TMatrix4.InitTranslation(const ADelta: TVector3);
2398
begin
2399
  V[0].Init(1, 0, 0, 0);
2400
  V[1].Init(0, 1, 0, 0);
2401
  V[2].Init(0, 0, 1, 0);
2402
  V[3].Init(ADelta.X, ADelta.Y, ADelta.Z, 1);
2403
end;
2404

2405
class operator TMatrix4.NotEqual(const A, B: TMatrix4): Boolean;
2406
begin
2407
  Result := (A.V[0] <> B.V[0]) or (A.V[1] <> B.V[1]) or (A.V[2] <> B.V[2]) or (A.V[3] <> B.V[3]);
2408
end;
2409

2410
procedure TMatrix4.InitRotationX(const AAngle: Single);
2411
var
2412
  S, C: Single;
2413
begin
2414
  FastSinCos(AAngle, S, C);
2415
  V[0].Init(1, 0, 0, 0);
2416
  V[1].Init(0, C, S, 0);
2417
  V[2].Init(0, -S, C, 0);
2418
  V[3].Init(0, 0, 0, 1);
2419
end;
2420

2421
procedure TMatrix4.InitRotationY(const AAngle: Single);
2422
var
2423
  S, C: Single;
2424
begin
2425
  FastSinCos(AAngle, S, C);
2426
  V[0].Init(C, 0, -S, 0);
2427
  V[1].Init(0, 1, 0, 0);
2428
  V[2].Init(S, 0, C, 0);
2429
  V[3].Init(0, 0, 0, 1);
2430
end;
2431

2432
procedure TMatrix4.InitRotationZ(const AAngle: Single);
2433
var
2434
  S, C: Single;
2435
begin
2436
  FastSinCos(AAngle, S, C);
2437
  V[0].Init(C, S, 0, 0);
2438
  V[1].Init(-S, C, 0, 0);
2439
  V[2].Init(0, 0, 1, 0);
2440
  V[3].Init(0, 0, 0, 1);
2441
end;
2442

2443
procedure TMatrix4.InitRotation(const AAxis: TVector3; const AAngle: Single);
2444
var
2445
  S, C, C1: Single;
2446
  N: TVector3;
2447
begin
2448
  FastSinCos(AAngle, S, C);
2449
  C1 := 1 - C;
2450
  N := AAxis.Normalize;
2451

2452
  V[0].Init((C1 * N.X * N.X) + C,
2453
            (C1 * N.X * N.Y) + (N.Z * S),
2454
            (C1 * N.Z * N.X) - (N.Y * S), 0);
2455

2456

2457
  V[1].Init((C1 * N.X * N.Y) - (N.Z * S),
2458
            (C1 * N.Y * N.Y) + C,
2459
            (C1 * N.Y * N.Z) + (N.X * S), 0);
2460

2461
  V[2].Init((C1 * N.Z * N.X) + (N.Y * S),
2462
            (C1 * N.Y * N.Z) - (N.X * S),
2463
            (C1 * N.Z * N.Z) + C, 0);
2464

2465
  V[3].Init(0, 0, 0, 1);
2466
end;
2467

2468
procedure TMatrix4.InitRotationYawPitchRoll(const AYaw, APitch, ARoll: Single);
2469
var
2470
  A, S, C: TVector4;
2471
begin
2472
  A.Init(APitch, AYaw, ARoll, 0);
2473
  FastSinCos(A, S, C);
2474

2475
  V[0].Init((C.Y * C.Z) + (S.X * S.Y * S.Z),
2476
            (C.Y * S.X * S.Z) - (C.Z * S.Y),
2477
            -C.X * S.Z, 0);
2478

2479
  V[1].Init(C.X * S.Y,
2480
            C.X * C.Y,
2481
            S.X, 0);
2482

2483
  V[2].Init((C.Y * S.Z) - (C.Z * S.X * S.Y),
2484
           (-C.Z * C.Y * S.X) - (S.Z * S.Y),
2485
             C.X * C.Z, 0);
2486

2487
  V[3].Init(0, 0, 0, 1);
2488
end;
2489

2490
procedure TMatrix4.InitRotationHeadingPitchBank(const AHeading, APitch, ABank: Single);
2491
var
2492
  A, S, C: TVector4;
2493
begin
2494
  A.Init(AHeading, APitch, ABank, 0);
2495
  FastSinCos(A, S, C);
2496

2497
  V[0].Init((C.X * C.Z) + (S.X * S.Y * S.Z),
2498
           (-C.X * S.Z) + (S.X * S.Y * C.Z),
2499
             S.X * C.Y, 0);
2500

2501
  V[1].Init(S.Z * C.Y,
2502
            C.Y * C.Z,
2503
           -S.Y, 0);
2504

2505
  V[2].Init((-S.X * C.Z) + (C.X * S.Y * S.Z),
2506
             (S.Z * S.X) + (C.X * S.Y * C.Z),
2507
              C.X * C.Y, 0);
2508

2509
  V[3].Init(0, 0, 0, 1);
2510
end;
2511

2512
{$IFDEF FM_COLUMN_MAJOR}
2513
function TMatrix4.GetColumn(const AIndex: Integer): TVector4;
2514
begin
2515
  Assert((AIndex >= 0) and (AIndex < 4));
2516
  Result := C[AIndex];
2517
end;
2518

2519
function TMatrix4.GetComponent(const AColumn, ARow: Integer): Single;
2520
begin
2521
  Assert((AColumn >= 0) and (AColumn < 4));
2522
  Assert((ARow >= 0) and (ARow < 4));
2523
  Result := M[AColumn, ARow];
2524
end;
2525

2526
procedure TMatrix4.Init(const AColumn0, AColumn1, AColumn2, AColumn3: TVector4);
2527
begin
2528
  C[0] := AColumn0;
2529
  C[1] := AColumn1;
2530
  C[2] := AColumn2;
2531
  C[3] := AColumn3;
2532
end;
2533

2534
procedure TMatrix4.InitOrthoLH(const AWidth, AHeight, AZNearPlane,
2535
  AZFarPlane: Single);
2536
begin
2537
  C[0].Init(2 / AWidth, 0, 0, 0);
2538
  C[1].Init(0, 2 / AHeight, 0, 0);
2539
  C[2].Init(0, 0, 2 / (AZFarPlane - AZNearPlane), 0);
2540
  C[3].Init(-1, -1, -(AZFarPlane + AZNearPlane) / (AZFarPlane - AZNearPlane), 1);
2541
end;
2542

2543
procedure TMatrix4.InitOrthoRH(const AWidth, AHeight, AZNearPlane,
2544
  AZFarPlane: Single);
2545
begin
2546
  C[0].Init(2 / AWidth, 0, 0, 0);
2547
  C[1].Init(0, 2 / AHeight, 0, 0);
2548
  C[2].Init(0, 0, -2 / (AZFarPlane - AZNearPlane), 0);
2549
  C[3].Init(-1, -1, -(AZFarPlane + AZNearPlane) / (AZFarPlane - AZNearPlane), 1);
2550
end;
2551

2552
procedure TMatrix4.InitOrthoOffCenterLH(const ALeft, ATop, ARight, ABottom,
2553
  AZNearPlane, AZFarPlane: Single);
2554
begin
2555
  C[0].Init(2 / (ARight - ALeft), 0, 0, 0);
2556
  C[1].Init(0, 2 / (ATop - ABottom), 0, 0);
2557
  C[2].Init(0, 0, 2 / (AZFarPlane - AZNearPlane), 0);
2558
  C[3].Init(-(ALeft + ARight) / (ARight - ALeft),
2559
            -(ATop + ABottom) / (ATop - ABottom),
2560
            -(AZFarPlane + AZNearPlane) / (AZFarPlane - AZNearPlane), 1);
2561
end;
2562

2563
procedure TMatrix4.InitOrthoOffCenterRH(const ALeft, ATop, ARight, ABottom,
2564
  AZNearPlane, AZFarPlane: Single);
2565
begin
2566
  C[0].Init(2 / (ARight - ALeft), 0, 0, 0);
2567
  C[1].Init(0, 2 / (ATop - ABottom), 0, 0);
2568
  C[2].Init(0, 0, -2 / (AZFarPlane - AZNearPlane), 0);
2569
  C[3].Init(-(ALeft + ARight) / (ARight - ALeft),
2570
            -(ATop + ABottom) / (ATop - ABottom),
2571
            -(AZFarPlane + AZNearPlane) / (AZFarPlane - AZNearPlane), 1);
2572
end;
2573

2574
procedure TMatrix4.InitPerspectiveFovLH(const AFieldOfView, AAspectRatio,
2575
  ANearPlaneDistance, AFarPlaneDistance: Single; const AHorizontalFOV: Boolean);
2576
var
2577
  XScale, YScale: Single;
2578
begin
2579
  if (AHorizontalFOV) then
2580
  begin
2581
    XScale := 1 / FastTan(0.5 * AFieldOfView);
2582
    YScale := XScale / AAspectRatio;
2583
  end
2584
  else
2585
  begin
2586
    YScale := 1 / FastTan(0.5 * AFieldOfView);
2587
    XScale := YScale / AAspectRatio;
2588
  end;
2589

2590
  C[0].Init(XScale, 0, 0, 0);
2591
  C[1].Init(0, YScale, 0, 0);
2592
  C[2].Init(0, 0, (AFarPlaneDistance + ANearPlaneDistance) / (AFarPlaneDistance - ANearPlaneDistance), 1);
2593
  C[3].Init(0, 0, (-2 * ANearPlaneDistance * AFarPlaneDistance) / (AFarPlaneDistance - ANearPlaneDistance), 0);
2594
end;
2595

2596
procedure TMatrix4.InitPerspectiveFovRH(const AFieldOfView, AAspectRatio,
2597
  ANearPlaneDistance, AFarPlaneDistance: Single; const AHorizontalFOV: Boolean);
2598
var
2599
  XScale, YScale: Single;
2600
begin
2601
  if (AHorizontalFOV) then
2602
  begin
2603
    XScale := 1 / FastTan(0.5 * AFieldOfView);
2604
    YScale := XScale / AAspectRatio;
2605
  end
2606
  else
2607
  begin
2608
    YScale := 1 / FastTan(0.5 * AFieldOfView);
2609
    XScale := YScale / AAspectRatio;
2610
  end;
2611

2612
  C[0].Init(XScale, 0, 0, 0);
2613
  C[1].Init(0, YScale, 0, 0);
2614
  C[2].Init(0, 0, -(AFarPlaneDistance + ANearPlaneDistance) / (AFarPlaneDistance - ANearPlaneDistance), -1);
2615
  C[3].Init(0, 0, (-2 * ANearPlaneDistance * AFarPlaneDistance) / (AFarPlaneDistance - ANearPlaneDistance), 0);
2616
end;
2617

2618
class operator TMatrix4.Implicit(const A: TMatrix3D): TMatrix4;
2619
var
2620
  M: TMatrix4 absolute A;
2621
begin
2622
  Result := M.Transpose;
2623
end;
2624

2625
class operator TMatrix4.Implicit(const A: TMatrix4): TMatrix3D;
2626
var
2627
  M: TMatrix4 absolute Result;
2628
begin
2629
  M := A.Transpose;
2630
end;
2631

2632
procedure TMatrix4.SetComponent(const AColumn, ARow: Integer; const Value: Single);
2633
begin
2634
  Assert((AColumn >= 0) and (AColumn < 4));
2635
  Assert((ARow >= 0) and (ARow < 4));
2636
  M[AColumn, ARow] := Value;
2637
end;
2638

2639
procedure TMatrix4.SetColumn(const AIndex: Integer; const Value: TVector4);
2640
begin
2641
  Assert((AIndex >= 0) and (AIndex < 4));
2642
  C[AIndex] := Value;
2643
end;
2644
{$ELSE}
2645
function TMatrix4.GetComponent(const ARow, AColumn: Integer): Single;
2646
begin
2647
  Assert((ARow >= 0) and (ARow < 4));
2648
  Assert((AColumn >= 0) and (AColumn < 4));
2649
  Result := M[ARow, AColumn];
2650
end;
2651

2652
function TMatrix4.GetRow(const AIndex: Integer): TVector4;
2653
begin
2654
  Assert((AIndex >= 0) and (AIndex < 4));
2655
  Result := R[AIndex];
2656
end;
2657

2658
procedure TMatrix4.Init(const ARow0, ARow1, ARow2, ARow3: TVector4);
2659
begin
2660
  R[0] := ARow0;
2661
  R[1] := ARow1;
2662
  R[2] := ARow2;
2663
  R[3] := ARow3;
2664
end;
2665

2666
procedure TMatrix4.InitOrthoLH(const AWidth, AHeight, AZNearPlane,
2667
  AZFarPlane: Single);
2668
begin
2669
  R[0].Init(2 / AWidth, 0, 0, 0);
2670
  R[1].Init(0, 2 / AHeight, 0, 0);
2671
  R[2].Init(0, 0, 1 / (AZFarPlane - AZNearPlane), 0);
2672
  R[3].Init(0, AZNearPlane / (AZNearPlane - AZFarPlane), 0, 1);
2673
end;
2674

2675
procedure TMatrix4.InitOrthoRH(const AWidth, AHeight, AZNearPlane,
2676
  AZFarPlane: Single);
2677
begin
2678
  R[0].Init(2 / AWidth, 0, 0, 0);
2679
  R[1].Init(0, 2 / AHeight, 0, 0);
2680
  R[2].Init(0, 0, 1 / (AZNearPlane - AZFarPlane), 0);
2681
  R[3].Init(0, AZNearPlane / (AZNearPlane - AZFarPlane), 0, 1);
2682
end;
2683

2684
procedure TMatrix4.InitOrthoOffCenterLH(const ALeft, ATop, ARight, ABottom,
2685
  AZNearPlane, AZFarPlane: Single);
2686
begin
2687
  R[0].Init(2 / (ARight - ALeft), 0, 0, 0);
2688
  R[1].Init(0, 2 / (ATop - ABottom), 0, 0);
2689
  R[2].Init(0, 0, 1 / (AZFarPlane - AZNearPlane), 0);
2690
  R[3].Init((ALeft + ARight) / (ALeft - ARight),
2691
            (ATop + ABottom) / (ABottom - ATop),
2692
            AZNearPlane / (AZNearPlane - AZFarPlane), 1);
2693
end;
2694

2695
procedure TMatrix4.InitOrthoOffCenterRH(const ALeft, ATop, ARight, ABottom,
2696
  AZNearPlane, AZFarPlane: Single);
2697
begin
2698
  R[0].Init(2 / (ARight - ALeft), 0, 0, 0);
2699
  R[1].Init(0, 2 / (ATop - ABottom), 0, 0);
2700
  R[2].Init(0, 0, 1 / (AZNearPlane - AZFarPlane), 0);
2701
  R[3].Init((ALeft + ARight) / (ALeft - ARight),
2702
            (ATop + ABottom) / (ABottom - ATop),
2703
            AZNearPlane / (AZNearPlane - AZFarPlane), 1);
2704
end;
2705

2706
procedure TMatrix4.InitPerspectiveFovLH(const AFieldOfView, AAspectRatio,
2707
  ANearPlaneDistance, AFarPlaneDistance: Single; const AHorizontalFOV: Boolean);
2708
var
2709
  XScale, YScale: Single;
2710
begin
2711
  if (AHorizontalFOV) then
2712
  begin
2713
    XScale := 1 / FastTan(0.5 * AFieldOfView);
2714
    YScale := XScale / AAspectRatio;
2715
  end
2716
  else
2717
  begin
2718
    YScale := 1 / FastTan(0.5 * AFieldOfView);
2719
    XScale := YScale / AAspectRatio;
2720
  end;
2721

2722
  R[0].Init(XScale, 0, 0, 0);
2723
  R[1].Init(0, YScale, 0, 0);
2724
  R[2].Init(0, 0, AFarPlaneDistance / (AFarPlaneDistance - ANearPlaneDistance), 1);
2725
  R[3].Init(0, 0, (-ANearPlaneDistance * AFarPlaneDistance) / (AFarPlaneDistance - ANearPlaneDistance), 0);
2726
end;
2727

2728
procedure TMatrix4.InitPerspectiveFovRH(const AFieldOfView, AAspectRatio,
2729
  ANearPlaneDistance, AFarPlaneDistance: Single; const AHorizontalFOV: Boolean);
2730
var
2731
  XScale, YScale: Single;
2732
begin
2733
  if (AHorizontalFOV) then
2734
  begin
2735
    XScale := 1 / FastTan(0.5 * AFieldOfView);
2736
    YScale := XScale / AAspectRatio;
2737
  end
2738
  else
2739
  begin
2740
    YScale := 1 / FastTan(0.5 * AFieldOfView);
2741
    XScale := YScale / AAspectRatio;
2742
  end;
2743

2744
  R[0].Init(XScale, 0, 0, 0);
2745
  R[1].Init(0, YScale, 0, 0);
2746
  R[2].Init(0, 0, AFarPlaneDistance / (ANearPlaneDistance - AFarPlaneDistance), -1);
2747
  R[3].Init(0, 0, (ANearPlaneDistance * AFarPlaneDistance) / (ANearPlaneDistance - AFarPlaneDistance), 0);
2748
end;
2749

2750
procedure TMatrix4.SetComponent(const ARow, AColumn: Integer; const Value: Single);
2751
begin
2752
  Assert((ARow >= 0) and (ARow < 4));
2753
  Assert((AColumn >= 0) and (AColumn < 4));
2754
  M[ARow, AColumn] := Value;
2755
end;
2756

2757
class operator TMatrix4.Implicit(const A: TMatrix3D): TMatrix4;
2758
begin
2759
  Move(A, Result, SizeOf(TMatrix4));
2760
end;
2761

2762
class operator TMatrix4.Implicit(const A: TMatrix4): TMatrix3D;
2763
begin
2764
  Move(A, Result, SizeOf(TMatrix4));
2765
end;
2766

2767
procedure TMatrix4.SetRow(const AIndex: Integer; const Value: TVector4);
2768
begin
2769
  Assert((AIndex >= 0) and (AIndex < 4));
2770
  R[AIndex] := Value;
2771
end;
2772
{$ENDIF}
2773

2774
{ _TMatrix2Helper }
2775

2776
procedure _TMatrix2Helper.Init(const AMatrix: TMatrix3);
2777
begin
2778
  V[0].Init(AMatrix.V[0].X, AMatrix.V[0].Y);
2779
  V[1].Init(AMatrix.V[1].X, AMatrix.V[1].Y);
2780
end;
2781

2782
procedure _TMatrix2Helper.Init(const AMatrix: TMatrix4);
2783
begin
2784
  V[0].Init(AMatrix.V[0].X, AMatrix.V[0].Y);
2785
  V[1].Init(AMatrix.V[1].X, AMatrix.V[1].Y);
2786
end;
2787

2788
{ _TMatrix3Helper }
2789

2790
procedure _TMatrix3Helper.Init(const AMatrix: TMatrix4);
2791
begin
2792
  V[0].Init(AMatrix.V[0].X, AMatrix.V[0].Y, AMatrix.V[0].Z);
2793
  V[1].Init(AMatrix.V[1].X, AMatrix.V[1].Y, AMatrix.V[1].Z);
2794
  V[2].Init(AMatrix.V[2].X, AMatrix.V[2].Y, AMatrix.V[2].Z);
2795
end;
2796

2797
{ TIVector2 }
2798

2799
class operator TIVector2.Add(const A: TIVector2; const B: Integer): TIVector2;
2800
begin
2801
  Result.X := A.X + B;
2802
  Result.Y := A.Y + B;
2803
end;
2804

2805
class operator TIVector2.Add(const A: Integer; const B: TIVector2): TIVector2;
2806
begin
2807
  Result.X := A + B.X;
2808
  Result.Y := A + B.Y;
2809
end;
2810

2811
class operator TIVector2.Add(const A, B: TIVector2): TIVector2;
2812
begin
2813
  Result.X := A.X + B.X;
2814
  Result.Y := A.Y + B.Y;
2815
end;
2816

2817
class operator TIVector2.Equal(const A, B: TIVector2): Boolean;
2818
begin
2819
  Result := (A.X = B.X) and (A.Y = B.Y);
2820
end;
2821

2822
function TIVector2.GetComponent(const AIndex: Integer): Integer;
2823
begin
2824
  Assert((AIndex >= 0) and (AIndex < 2));
2825
  Result := C[AIndex];
2826
end;
2827

2828
class operator TIVector2.Implicit(const A: TPoint): TIVector2;
2829
begin
2830
  Result.X := A.X;
2831
  Result.Y := A.Y;
2832
end;
2833

2834
class operator TIVector2.Implicit(const A: TIVector2): TPoint;
2835
begin
2836
  Result.X := A.X;
2837
  Result.Y := A.Y;
2838
end;
2839

2840
procedure TIVector2.Init;
2841
begin
2842
  X := 0;
2843
  Y := 0;
2844
end;
2845

2846
procedure TIVector2.Init(const A: Integer);
2847
begin
2848
  X := A;
2849
  Y := A;
2850
end;
2851

2852
procedure TIVector2.Init(const A1, A2: Integer);
2853
begin
2854
  X := A1;
2855
  Y := A2;
2856
end;
2857

2858
class operator TIVector2.IntDivide(const A: TIVector2; const B: Integer): TIVector2;
2859
begin
2860
  Result.X := A.X div B;
2861
  Result.Y := A.Y div B;
2862
end;
2863

2864
class operator TIVector2.IntDivide(const A: Integer; const B: TIVector2): TIVector2;
2865
begin
2866
  Result.X := A div B.X;
2867
  Result.Y := A div B.Y;
2868
end;
2869

2870
class operator TIVector2.IntDivide(const A, B: TIVector2): TIVector2;
2871
begin
2872
  Result.X := A.X div B.X;
2873
  Result.Y := A.Y div B.Y;
2874
end;
2875

2876
function TIVector2.IsZero: Boolean;
2877
begin
2878
  Result := (X = 0) and (Y = 0);
2879
end;
2880

2881
class operator TIVector2.Multiply(const A: TIVector2; const B: Integer): TIVector2;
2882
begin
2883
  Result.X := A.X * B;
2884
  Result.Y := A.Y * B;
2885
end;
2886

2887
class operator TIVector2.Multiply(const A: Integer; const B: TIVector2): TIVector2;
2888
begin
2889
  Result.X := A * B.X;
2890
  Result.Y := A * B.Y;
2891
end;
2892

2893
class operator TIVector2.Multiply(const A, B: TIVector2): TIVector2;
2894
begin
2895
  Result.X := A.X * B.X;
2896
  Result.Y := A.Y * B.Y;
2897
end;
2898

2899
class operator TIVector2.Negative(const A: TIVector2): TIVector2;
2900
begin
2901
  Result.X := -A.X;
2902
  Result.Y := -A.Y;
2903
end;
2904

2905
class operator TIVector2.NotEqual(const A, B: TIVector2): Boolean;
2906
begin
2907
  Result := (A.X <> B.X) or (A.Y <> B.Y);
2908
end;
2909

2910
procedure TIVector2.SetComponent(const AIndex: Integer; const Value: Integer);
2911
begin
2912
  Assert((AIndex >= 0) and (AIndex < 2));
2913
  C[AIndex] := Value;
2914
end;
2915

2916
class operator TIVector2.Subtract(const A: TIVector2; const B: Integer): TIVector2;
2917
begin
2918
  Result.X := A.X - B;
2919
  Result.Y := A.Y - B;
2920
end;
2921

2922
class operator TIVector2.Subtract(const A: Integer; const B: TIVector2): TIVector2;
2923
begin
2924
  Result.X := A - B.X;
2925
  Result.Y := A - B.Y;
2926
end;
2927

2928
class operator TIVector2.Subtract(const A, B: TIVector2): TIVector2;
2929
begin
2930
  Result.X := A.X - B.X;
2931
  Result.Y := A.Y - B.Y;
2932
end;
2933

2934
{ TIVector3 }
2935

2936
class operator TIVector3.Add(const A: TIVector3; const B: Integer): TIVector3;
2937
begin
2938
  Result.X := A.X + B;
2939
  Result.Y := A.Y + B;
2940
  Result.Z := A.Z + B;
2941
end;
2942

2943
class operator TIVector3.Add(const A: Integer; const B: TIVector3): TIVector3;
2944
begin
2945
  Result.X := A + B.X;
2946
  Result.Y := A + B.Y;
2947
  Result.Z := A + B.Z;
2948
end;
2949

2950
class operator TIVector3.Add(const A, B: TIVector3): TIVector3;
2951
begin
2952
  Result.X := A.X + B.X;
2953
  Result.Y := A.Y + B.Y;
2954
  Result.Z := A.Z + B.Z;
2955
end;
2956

2957
class operator TIVector3.Equal(const A, B: TIVector3): Boolean;
2958
begin
2959
  Result := (A.X = B.X) and (A.Y = B.Y) and (A.Z = B.Z);
2960
end;
2961

2962
function TIVector3.GetComponent(const AIndex: Integer): Integer;
2963
begin
2964
  Assert((AIndex >= 0) and (AIndex < 3));
2965
  Result := C[AIndex];
2966
end;
2967

2968
procedure TIVector3.Init(const A: Integer);
2969
begin
2970
  X := A;
2971
  Y := A;
2972
  Z := A;
2973
end;
2974

2975
procedure TIVector3.Init;
2976
begin
2977
  X := 0;
2978
  Y := 0;
2979
  Z := 0;
2980
end;
2981

2982
procedure TIVector3.Init(const A1, A2, A3: Integer);
2983
begin
2984
  X := A1;
2985
  Y := A2;
2986
  Z := A3;
2987
end;
2988

2989
class operator TIVector3.IntDivide(const A: TIVector3; const B: Integer): TIVector3;
2990
begin
2991
  Result.X := A.X div B;
2992
  Result.Y := A.Y div B;
2993
  Result.Z := A.Z div B;
2994
end;
2995

2996
class operator TIVector3.IntDivide(const A: Integer; const B: TIVector3): TIVector3;
2997
begin
2998
  Result.X := A div B.X;
2999
  Result.Y := A div B.Y;
3000
  Result.Z := A div B.Z;
3001
end;
3002

3003
class operator TIVector3.IntDivide(const A, B: TIVector3): TIVector3;
3004
begin
3005
  Result.X := A.X div B.X;
3006
  Result.Y := A.Y div B.Y;
3007
  Result.Z := A.Z div B.Z;
3008
end;
3009

3010
function TIVector3.IsZero: Boolean;
3011
begin
3012
  Result := (X = 0) and (Y = 0) and (Z = 0);
3013
end;
3014

3015
class operator TIVector3.Multiply(const A: TIVector3; const B: Integer): TIVector3;
3016
begin
3017
  Result.X := A.X * B;
3018
  Result.Y := A.Y * B;
3019
  Result.Z := A.Z * B;
3020
end;
3021

3022
class operator TIVector3.Multiply(const A: Integer; const B: TIVector3): TIVector3;
3023
begin
3024
  Result.X := A * B.X;
3025
  Result.Y := A * B.Y;
3026
  Result.Z := A * B.Z;
3027
end;
3028

3029
class operator TIVector3.Multiply(const A, B: TIVector3): TIVector3;
3030
begin
3031
  Result.X := A.X * B.X;
3032
  Result.Y := A.Y * B.Y;
3033
  Result.Z := A.Z * B.Z;
3034
end;
3035

3036
class operator TIVector3.Negative(const A: TIVector3): TIVector3;
3037
begin
3038
  Result.X := -A.X;
3039
  Result.Y := -A.Y;
3040
  Result.Z := -A.Z;
3041
end;
3042

3043
class operator TIVector3.NotEqual(const A, B: TIVector3): Boolean;
3044
begin
3045
  Result := (A.X <> B.X) or (A.Y <> B.Y) or (A.Z <> B.Z);
3046
end;
3047

3048
procedure TIVector3.SetComponent(const AIndex: Integer; const Value: Integer);
3049
begin
3050
  Assert((AIndex >= 0) and (AIndex < 3));
3051
  C[AIndex] := Value;
3052
end;
3053

3054
class operator TIVector3.Subtract(const A: TIVector3; const B: Integer): TIVector3;
3055
begin
3056
  Result.X := A.X - B;
3057
  Result.Y := A.Y - B;
3058
  Result.Z := A.Z - B;
3059
end;
3060

3061
class operator TIVector3.Subtract(const A: Integer; const B: TIVector3): TIVector3;
3062
begin
3063
  Result.X := A - B.X;
3064
  Result.Y := A - B.Y;
3065
  Result.Z := A - B.Z;
3066
end;
3067

3068
class operator TIVector3.Subtract(const A, B: TIVector3): TIVector3;
3069
begin
3070
  Result.X := A.X - B.X;
3071
  Result.Y := A.Y - B.Y;
3072
  Result.Z := A.Z - B.Z;
3073
end;
3074

3075
{ TIVector4 }
3076

3077
class operator TIVector4.Add(const A: TIVector4; const B: Integer): TIVector4;
3078
begin
3079
  Result.X := A.X + B;
3080
  Result.Y := A.Y + B;
3081
  Result.Z := A.Z + B;
3082
  Result.W := A.W + B;
3083
end;
3084

3085
class operator TIVector4.Add(const A: Integer; const B: TIVector4): TIVector4;
3086
begin
3087
  Result.X := A + B.X;
3088
  Result.Y := A + B.Y;
3089
  Result.Z := A + B.Z;
3090
  Result.W := A + B.W;
3091
end;
3092

3093
class operator TIVector4.Add(const A, B: TIVector4): TIVector4;
3094
begin
3095
  Result.X := A.X + B.X;
3096
  Result.Y := A.Y + B.Y;
3097
  Result.Z := A.Z + B.Z;
3098
  Result.W := A.W + B.W;
3099
end;
3100

3101
class operator TIVector4.Equal(const A, B: TIVector4): Boolean;
3102
begin
3103
  Result := (A.X = B.X) and (A.Y = B.Y) and (A.Z = B.Z) and (A.W = B.W);
3104
end;
3105

3106
function TIVector4.GetComponent(const AIndex: Integer): Integer;
3107
begin
3108
  Assert((AIndex >= 0) and (AIndex < 4));
3109
  Result := C[AIndex];
3110
end;
3111

3112
procedure TIVector4.Init(const A1, A2, A3, A4: Integer);
3113
begin
3114
  X := A1;
3115
  Y := A2;
3116
  Z := A3;
3117
  W := A4;
3118
end;
3119

3120
procedure TIVector4.Init(const A: Integer);
3121
begin
3122
  X := A;
3123
  Y := A;
3124
  Z := A;
3125
  W := A;
3126
end;
3127

3128
procedure TIVector4.Init;
3129
begin
3130
  X := 0;
3131
  Y := 0;
3132
  Z := 0;
3133
  W := 0;
3134
end;
3135

3136
class operator TIVector4.IntDivide(const A: TIVector4; const B: Integer): TIVector4;
3137
begin
3138
  Result.X := A.X div B;
3139
  Result.Y := A.Y div B;
3140
  Result.Z := A.Z div B;
3141
  Result.W := A.W div B;
3142
end;
3143

3144
class operator TIVector4.IntDivide(const A: Integer; const B: TIVector4): TIVector4;
3145
begin
3146
  Result.X := A div B.X;
3147
  Result.Y := A div B.Y;
3148
  Result.Z := A div B.Z;
3149
  Result.W := A div B.W;
3150
end;
3151

3152
class operator TIVector4.IntDivide(const A, B: TIVector4): TIVector4;
3153
begin
3154
  Result.X := A.X div B.X;
3155
  Result.Y := A.Y div B.Y;
3156
  Result.Z := A.Z div B.Z;
3157
  Result.W := A.W div B.W;
3158
end;
3159

3160
function TIVector4.IsZero: Boolean;
3161
begin
3162
  Result := (X = 0) and (Y = 0) and (Z = 0) and (W = 0);
3163
end;
3164

3165
class operator TIVector4.Multiply(const A: TIVector4; const B: Integer): TIVector4;
3166
begin
3167
  Result.X := A.X * B;
3168
  Result.Y := A.Y * B;
3169
  Result.Z := A.Z * B;
3170
  Result.W := A.W * B;
3171
end;
3172

3173
class operator TIVector4.Multiply(const A: Integer; const B: TIVector4): TIVector4;
3174
begin
3175
  Result.X := A * B.X;
3176
  Result.Y := A * B.Y;
3177
  Result.Z := A * B.Z;
3178
  Result.W := A * B.W;
3179
end;
3180

3181
class operator TIVector4.Multiply(const A, B: TIVector4): TIVector4;
3182
begin
3183
  Result.X := A.X * B.X;
3184
  Result.Y := A.Y * B.Y;
3185
  Result.Z := A.Z * B.Z;
3186
  Result.W := A.W * B.W;
3187
end;
3188

3189
class operator TIVector4.Negative(const A: TIVector4): TIVector4;
3190
begin
3191
  Result.X := -A.X;
3192
  Result.Y := -A.Y;
3193
  Result.Z := -A.Z;
3194
  Result.W := -A.W;
3195
end;
3196

3197
class operator TIVector4.NotEqual(const A, B: TIVector4): Boolean;
3198
begin
3199
  Result := (A.X <> B.X) or (A.Y <> B.Y) or (A.Z <> B.Z) or (A.W <> B.W);
3200
end;
3201

3202
procedure TIVector4.SetComponent(const AIndex: Integer; const Value: Integer);
3203
begin
3204
  Assert((AIndex >= 0) and (AIndex < 4));
3205
  C[AIndex] := Value;
3206
end;
3207

3208
class operator TIVector4.Subtract(const A: TIVector4; const B: Integer): TIVector4;
3209
begin
3210
  Result.X := A.X - B;
3211
  Result.Y := A.Y - B;
3212
  Result.Z := A.Z - B;
3213
  Result.W := A.W - B;
3214
end;
3215

3216
class operator TIVector4.Subtract(const A: Integer; const B: TIVector4): TIVector4;
3217
begin
3218
  Result.X := A - B.X;
3219
  Result.Y := A - B.Y;
3220
  Result.Z := A - B.Z;
3221
  Result.W := A - B.W;
3222
end;
3223

3224
class operator TIVector4.Subtract(const A, B: TIVector4): TIVector4;
3225
begin
3226
  Result.X := A.X - B.X;
3227
  Result.Y := A.Y - B.Y;
3228
  Result.Z := A.Z - B.Z;
3229
  Result.W := A.W - B.W;
3230
end;
3231

3232

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.