MathgeomGLS
3230 строк · 73.4 Кб
1var
2PrevFloatingPointExceptions: TArithmeticExceptionMask = DefaultExceptionFlags;3
4{$WARN SYMBOL_PLATFORM OFF}
5procedure DisableFloatingPointExceptions;6begin
7PrevFloatingPointExceptions := SetExceptionMask(exAllArithmeticExceptions);8end;9
10procedure RestoreFloatingPointExceptions;11begin
12SetExceptionMask(PrevFloatingPointExceptions);13end;14{$WARN SYMBOL_PLATFORM ON}
15
16{ Vector2 }
17
18function Vector2: TVector2;19begin
20Result.Init;21end;22
23function Vector2(const A: Single): TVector2;24begin
25Result.Init(A);26end;27
28function Vector2(const A1, A2: Single): TVector2;29begin
30Result.Init(A1, A2);31end;32
33function Vector2(const AVector: TVector3): TVector2;34begin
35Result.Init(AVector.X, AVector.Y);36end;37
38function Vector2(const AVector: TVector4): TVector2;39begin
40Result.Init(AVector.X, AVector.Y);41end;42
43{ Vector3 }
44
45function Vector3: TVector3;46begin
47Result.Init;48end;49
50function Vector3(const A: Single): TVector3;51begin
52Result.Init(A);53end;54
55function Vector3(const A1, A2, A3: Single): TVector3;56begin
57Result.Init(A1, A2, A3);58end;59
60function Vector3(const A1: TVector2; const A2: Single): TVector3;61begin
62Result.Init(A1, A2);63end;64
65function Vector3(const A1: Single; const A2: TVector2): TVector3;66begin
67Result.Init(A1, A2);68end;69
70function Vector3(const AVector: TVector4): TVector3;71begin
72Result.Init(AVector.X, AVector.Y, AVector.Z);73end;74
75{ Vector4 }
76
77function Vector4: TVector4;78begin
79Result.Init;80end;81
82function Vector4(const A: Single): TVector4;83begin
84Result.Init(A);85end;86
87function Vector4(const A1, A2, A3, A4: Single): TVector4;88begin
89Result.Init(A1, A2, A3, A4);90end;91
92function Vector4(const A1: TVector2; const A2, A3: Single): TVector4;93begin
94Result.Init(A1, A2, A3);95end;96
97function Vector4(const A1: Single; const A2: TVector2; const A3: Single): TVector4;98begin
99Result.Init(A1, A2, A3);100end;101
102function Vector4(const A1, A2: Single; const A3: TVector2): TVector4;103begin
104Result.Init(A1, A2, A3);105end;106
107function Vector4(const A1, A2: TVector2): TVector4;108begin
109Result.Init(A1, A2);110end;111
112function Vector4(const A1: TVector3; const A2: Single): TVector4;113begin
114Result.Init(A1, A2);115end;116
117function Vector4(const A1: Single; const A2: TVector3): TVector4;118begin
119Result.Init(A1, A2);120end;121
122{ Quaternion }
123
124function Quaternion: TQuaternion;125begin
126Result.Init;127end;128
129function Quaternion(const AX, AY, AZ, AW: Single): TQuaternion; overload;130begin
131Result.Init(AX, AY, AZ, AW);132end;133
134function Quaternion(const AAxis: TVector3; const AAngleRadians: Single): TQuaternion; overload;135begin
136Result.Init(AAxis, AAngleRadians);137end;138
139{ Matrix2 }
140
141function Matrix2: TMatrix2;142begin
143Result.Init;144end;145
146function Matrix2(const ADiagonal: Single): TMatrix2;147begin
148Result.Init(ADiagonal);149end;150
151function Matrix2(const ARow0, ARow1: TVector2): TMatrix2;152begin
153Result.Init(ARow0, ARow1);154end;155
156function Matrix2(const A11, A12, A21, A22: Single): TMatrix2;157begin
158Result.Init(A11, A12, A21, A22);159end;160
161function Matrix2(const AMatrix: TMatrix3): TMatrix2;162begin
163Result.V[0] := Vector2(AMatrix.V[0]);164Result.V[1] := Vector2(AMatrix.V[1]);165end;166
167function Matrix2(const AMatrix: TMatrix4): TMatrix2;168begin
169Result.V[0] := Vector2(AMatrix.V[0]);170Result.V[1] := Vector2(AMatrix.V[1]);171end;172
173{ Matrix3 }
174
175function Matrix3: TMatrix3;176begin
177Result.Init;178end;179
180function Matrix3(const ADiagonal: Single): TMatrix3;181begin
182Result.Init(ADiagonal);183end;184
185function Matrix3(const ARow0, ARow1, ARow2: TVector3): TMatrix3;186begin
187Result.Init(ARow0, ARow1, ARow2);188end;189
190function Matrix3(const A11, A12, A13, A21, A22, A23, A31, A32, A33: Single): TMatrix3;191begin
192Result.Init(A11, A12, A13, A21, A22, A23, A31, A32, A33);193end;194
195function Matrix3(const AMatrix: TMatrix2): TMatrix3;196begin
197Result.V[0] := Vector3(AMatrix.V[0], 0);198Result.V[1] := Vector3(AMatrix.V[1], 0);199Result.V[2] := Vector3(0, 0, 1);200end;201
202function Matrix3(const AMatrix: TMatrix4): TMatrix3;203begin
204Result.V[0] := Vector3(AMatrix.V[0]);205Result.V[1] := Vector3(AMatrix.V[1]);206Result.V[2] := Vector3(AMatrix.V[2]);207end;208
209{ Matrix4 }
210
211function Matrix4: TMatrix4;212begin
213Result.Init;214end;215
216function Matrix4(const ADiagonal: Single): TMatrix4;217begin
218Result.Init(ADiagonal);;219end;220
221function Matrix4(const ARow0, ARow1, ARow2, ARow3: TVector4): TMatrix4;222begin
223Result.Init(ARow0, ARow1, ARow2, ARow3);224end;225
226function Matrix4(const A11, A12, A13, A14, A21, A22, A23, A24, A31, A32, A33,227A34, A41, A42, A43, A44: Single): TMatrix4;228begin
229Result.Init(A11, A12, A13, A14, A21, A22, A23, A24, A31, A32, A33, A34, A41,230A42, A43, A44);231end;232
233function Matrix4(const AMatrix: TMatrix2): TMatrix4;234begin
235Result.V[0].Init(AMatrix.V[0], 0, 0);236Result.V[1].Init(AMatrix.V[1], 0, 0);237Result.V[2].Init(0, 0, 1, 0);238Result.V[3].Init(0, 0, 0, 1);239end;240
241function Matrix4(const AMatrix: TMatrix3): TMatrix4;242begin
243Result.V[0].Init(AMatrix.V[0], 0);244Result.V[1].Init(AMatrix.V[1], 0);245Result.V[2].Init(AMatrix.V[2], 0);246Result.V[3].Init(0, 0, 0, 1);247end;248
249{ IVector2 }
250
251function IVector2: TIVector2;252begin
253Result.Init;254end;255
256function IVector2(const A: Integer): TIVector2;257begin
258Result.Init(A);259end;260
261function IVector2(const A1, A2: Integer): TIVector2;262begin
263Result.Init(A1, A2);264end;265
266{ IVector3 }
267
268function IVector3: TIVector3;269begin
270Result.Init;271end;272
273function IVector3(const A: Integer): TIVector3;274begin
275Result.Init(A);276end;277
278function IVector3(const A1, A2, A3: Integer): TIVector3;279begin
280Result.Init(A1, A2, A3);281end;282
283{ IVector4 }
284
285function IVector4: TIVector4;286begin
287Result.Init;288end;289
290function IVector4(const A: Integer): TIVector4;291begin
292Result.Init(A);293end;294
295function IVector4(const A1, A2, A3, A4: Integer): TIVector4;296begin
297Result.Init(A1, A2, A3, A4);298end;299
300{ Angle and Trigonometry Functions }
301
302function Sin(const ARadians: Single): Single;303begin
304Result := System.Sin(ARadians);305end;306
307function Sin(const ARadians: TVector2): TVector2;308begin
309Result.Init(System.Sin(ARadians.X), System.Sin(ARadians.Y));310end;311
312function Sin(const ARadians: TVector3): TVector3;313begin
314Result.Init(System.Sin(ARadians.X), System.Sin(ARadians.Y), System.Sin(ARadians.Z));315end;316
317function Sin(const ARadians: TVector4): TVector4;318begin
319Result.Init(System.Sin(ARadians.X), System.Sin(ARadians.Y), System.Sin(ARadians.Z), System.Sin(ARadians.W));320end;321
322function Cos(const ARadians: Single): Single;323begin
324Result := System.Cos(ARadians);325end;326
327function Cos(const ARadians: TVector2): TVector2;328begin
329Result.Init(System.Cos(ARadians.X), System.Cos(ARadians.Y));330end;331
332function Cos(const ARadians: TVector3): TVector3;333begin
334Result.Init(System.Cos(ARadians.X), System.Cos(ARadians.Y), System.Cos(ARadians.Z));335end;336
337function Cos(const ARadians: TVector4): TVector4;338begin
339Result.Init(System.Cos(ARadians.X), System.Cos(ARadians.Y), System.Cos(ARadians.Z), System.Cos(ARadians.W));340end;341
342procedure SinCos(const ARadians: Single; out ASin, ACos: Single);343begin
344System.Math.SinCos(ARadians, ASin, ACos);345end;346
347procedure SinCos(const ARadians: TVector2; out ASin, ACos: TVector2);348begin
349System.Math.SinCos(ARadians.X, ASin.X, ACos.X);350System.Math.SinCos(ARadians.Y, ASin.Y, ACos.Y);351end;352
353procedure SinCos(const ARadians: TVector3; out ASin, ACos: TVector3);354begin
355System.Math.SinCos(ARadians.X, ASin.X, ACos.X);356System.Math.SinCos(ARadians.Y, ASin.Y, ACos.Y);357System.Math.SinCos(ARadians.Z, ASin.Z, ACos.Z);358end;359
360procedure SinCos(const ARadians: TVector4; out ASin, ACos: TVector4);361begin
362System.Math.SinCos(ARadians.X, ASin.X, ACos.X);363System.Math.SinCos(ARadians.Y, ASin.Y, ACos.Y);364System.Math.SinCos(ARadians.Z, ASin.Z, ACos.Z);365System.Math.SinCos(ARadians.W, ASin.W, ACos.W);366end;367
368function Tan(const ARadians: Single): Single;369begin
370Result := System.Tangent(ARadians);371end;372
373function Tan(const ARadians: TVector2): TVector2;374begin
375Result.Init(System.Tangent(ARadians.X), System.Tangent(ARadians.Y));376end;377
378function Tan(const ARadians: TVector3): TVector3;379begin
380Result.Init(System.Tangent(ARadians.X), System.Tangent(ARadians.Y), System.Tangent(ARadians.Z));381end;382
383function Tan(const ARadians: TVector4): TVector4;384begin
385Result.Init(System.Tangent(ARadians.X), System.Tangent(ARadians.Y), System.Tangent(ARadians.Z), System.Tangent(ARadians.W));386end;387
388function ArcSin(const A: Single): Single;389begin
390Result := System.Math.ArcSin(A);391end;392
393function ArcSin(const A: TVector2): TVector2;394begin
395Result.Init(System.Math.ArcSin(A.X), System.Math.ArcSin(A.Y));396end;397
398function ArcSin(const A: TVector3): TVector3;399begin
400Result.Init(System.Math.ArcSin(A.X), System.Math.ArcSin(A.Y), System.Math.ArcSin(A.Z));401end;402
403function ArcSin(const A: TVector4): TVector4;404begin
405Result.Init(System.Math.ArcSin(A.X), System.Math.ArcSin(A.Y), System.Math.ArcSin(A.Z), System.Math.ArcSin(A.W));406end;407
408function ArcCos(const A: Single): Single;409begin
410Result := System.Math.ArcCos(A);411end;412
413function ArcCos(const A: TVector2): TVector2;414begin
415Result.Init(System.Math.ArcCos(A.X), System.Math.ArcCos(A.Y));416end;417
418function ArcCos(const A: TVector3): TVector3;419begin
420Result.Init(System.Math.ArcCos(A.X), System.Math.ArcCos(A.Y), System.Math.ArcCos(A.Z));421end;422
423function ArcCos(const A: TVector4): TVector4;424begin
425Result.Init(System.Math.ArcCos(A.X), System.Math.ArcCos(A.Y), System.Math.ArcCos(A.Z), System.Math.ArcCos(A.W));426end;427
428function ArcTan(const A: Single): Single;429begin
430Result := System.ArcTan(A);431end;432
433function ArcTan(const A: TVector2): TVector2;434begin
435Result.Init(System.ArcTan(A.X), System.ArcTan(A.Y));436end;437
438function ArcTan(const A: TVector3): TVector3;439begin
440Result.Init(System.ArcTan(A.X), System.ArcTan(A.Y), System.ArcTan(A.Z));441end;442
443function ArcTan(const A: TVector4): TVector4;444begin
445Result.Init(System.ArcTan(A.X), System.ArcTan(A.Y), System.ArcTan(A.Z), System.ArcTan(A.W));446end;447
448function ArcTan2(const Y, X: Single): Single;449begin
450Result := System.Math.ArcTan2(Y, X);451end;452
453function ArcTan2(const Y, X: TVector2): TVector2;454begin
455Result.Init(System.Math.ArcTan2(Y.X, X.X), System.Math.ArcTan2(Y.Y, X.Y));456end;457
458function ArcTan2(const Y, X: TVector3): TVector3;459begin
460Result.Init(System.Math.ArcTan2(Y.X, X.X), System.Math.ArcTan2(Y.Y, X.Y), System.Math.ArcTan2(Y.Z, X.Z));461end;462
463function ArcTan2(const Y, X: TVector4): TVector4;464begin
465Result.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));466end;467
468function Sinh(const A: Single): Single;469begin
470Result := System.Math.Sinh(A);471end;472
473function Sinh(const A: TVector2): TVector2;474begin
475Result.Init(System.Math.Sinh(A.X), System.Math.Sinh(A.Y));476end;477
478function Sinh(const A: TVector3): TVector3;479begin
480Result.Init(System.Math.Sinh(A.X), System.Math.Sinh(A.Y), System.Math.Sinh(A.Z));481end;482
483function Sinh(const A: TVector4): TVector4;484begin
485Result.Init(System.Math.Sinh(A.X), System.Math.Sinh(A.Y), System.Math.Sinh(A.Z), System.Math.Sinh(A.W));486end;487
488function Cosh(const A: Single): Single;489begin
490Result := System.Math.Cosh(A);491end;492
493function Cosh(const A: TVector2): TVector2;494begin
495Result.Init(System.Math.Cosh(A.X), System.Math.Cosh(A.Y));496end;497
498function Cosh(const A: TVector3): TVector3;499begin
500Result.Init(System.Math.Cosh(A.X), System.Math.Cosh(A.Y), System.Math.Cosh(A.Z));501end;502
503function Cosh(const A: TVector4): TVector4;504begin
505Result.Init(System.Math.Cosh(A.X), System.Math.Cosh(A.Y), System.Math.Cosh(A.Z), System.Math.Cosh(A.W));506end;507
508function Tanh(const A: Single): Single;509begin
510Result := System.Math.Tanh(A);511end;512
513function Tanh(const A: TVector2): TVector2;514begin
515Result.Init(System.Math.Tanh(A.X), System.Math.Tanh(A.Y));516end;517
518function Tanh(const A: TVector3): TVector3;519begin
520Result.Init(System.Math.Tanh(A.X), System.Math.Tanh(A.Y), System.Math.Tanh(A.Z));521end;522
523function Tanh(const A: TVector4): TVector4;524begin
525Result.Init(System.Math.Tanh(A.X), System.Math.Tanh(A.Y), System.Math.Tanh(A.Z), System.Math.Tanh(A.W));526end;527
528function ArcSinh(const A: Single): Single;529begin
530Result := System.Math.ArcSinh(A);531end;532
533function ArcSinh(const A: TVector2): TVector2;534begin
535Result.Init(System.Math.ArcSinh(A.X), System.Math.ArcSinh(A.Y));536end;537
538function ArcSinh(const A: TVector3): TVector3;539begin
540Result.Init(System.Math.ArcSinh(A.X), System.Math.ArcSinh(A.Y), System.Math.ArcSinh(A.Z));541end;542
543function ArcSinh(const A: TVector4): TVector4;544begin
545Result.Init(System.Math.ArcSinh(A.X), System.Math.ArcSinh(A.Y), System.Math.ArcSinh(A.Z), System.Math.ArcSinh(A.W));546end;547
548function ArcCosh(const A: Single): Single;549begin
550Result := System.Math.ArcCosh(A);551end;552
553function ArcCosh(const A: TVector2): TVector2;554begin
555Result.Init(System.Math.ArcCosh(A.X), System.Math.ArcCosh(A.Y));556end;557
558function ArcCosh(const A: TVector3): TVector3;559begin
560Result.Init(System.Math.ArcCosh(A.X), System.Math.ArcCosh(A.Y), System.Math.ArcCosh(A.Z));561end;562
563function ArcCosh(const A: TVector4): TVector4;564begin
565Result.Init(System.Math.ArcCosh(A.X), System.Math.ArcCosh(A.Y), System.Math.ArcCosh(A.Z), System.Math.ArcCosh(A.W));566end;567
568function ArcTanh(const A: Single): Single;569begin
570Result := System.Math.ArcTanh(A);571end;572
573function ArcTanh(const A: TVector2): TVector2;574begin
575Result.Init(System.Math.ArcTanh(A.X), System.Math.ArcTanh(A.Y));576end;577
578function ArcTanh(const A: TVector3): TVector3;579begin
580Result.Init(System.Math.ArcTanh(A.X), System.Math.ArcTanh(A.Y), System.Math.ArcTanh(A.Z));581end;582
583function ArcTanh(const A: TVector4): TVector4;584begin
585Result.Init(System.Math.ArcTanh(A.X), System.Math.ArcTanh(A.Y), System.Math.ArcTanh(A.Z), System.Math.ArcTanh(A.W));586end;587
588{ Exponential Functions }
589
590function Power(const ABase, AExponent: Single): Single;591begin
592Result := System.Math.Power(ABase, AExponent);593end;594
595function Power(const ABase, AExponent: TVector2): TVector2;596begin
597Result.Init(System.Math.Power(ABase.X, AExponent.X), System.Math.Power(ABase.Y, AExponent.Y));598end;599
600function Power(const ABase, AExponent: TVector3): TVector3;601begin
602Result.Init(System.Math.Power(ABase.X, AExponent.X), System.Math.Power(ABase.Y, AExponent.Y), System.Math.Power(ABase.Z, AExponent.Z));603end;604
605function Power(const ABase, AExponent: TVector4): TVector4;606begin
607Result.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));608end;609
610function Exp(const A: Single): Single;611begin
612Result := System.Exp(A);613end;614
615function Exp(const A: TVector2): TVector2;616begin
617Result.Init(System.Exp(A.X), System.Exp(A.Y));618end;619
620function Exp(const A: TVector3): TVector3;621begin
622Result.Init(System.Exp(A.X), System.Exp(A.Y), System.Exp(A.Z));623end;624
625function Exp(const A: TVector4): TVector4;626begin
627Result.Init(System.Exp(A.X), System.Exp(A.Y), System.Exp(A.Z), System.Exp(A.W));628end;629
630function Ln(const A: Single): Single;631begin
632Result := System.Ln(A);633end;634
635function Ln(const A: TVector2): TVector2;636begin
637Result.Init(System.Ln(A.X), System.Ln(A.Y));638end;639
640function Ln(const A: TVector3): TVector3;641begin
642Result.Init(System.Ln(A.X), System.Ln(A.Y), System.Ln(A.Z));643end;644
645function Ln(const A: TVector4): TVector4;646begin
647Result.Init(System.Ln(A.X), System.Ln(A.Y), System.Ln(A.Z), System.Ln(A.W));648end;649
650function Exp2(const A: Single): Single;651begin
652Result := System.Math.Power(2, A);653end;654
655function Exp2(const A: TVector2): TVector2;656begin
657Result.Init(Exp2(A.X), Exp2(A.Y));658end;659
660function Exp2(const A: TVector3): TVector3;661begin
662Result.Init(Exp2(A.X), Exp2(A.Y), Exp2(A.Z));663end;664
665function Exp2(const A: TVector4): TVector4;666begin
667Result.Init(Exp2(A.X), Exp2(A.Y), Exp2(A.Z), Exp2(A.W));668end;669
670function Log2(const A: Single): Single;671begin
672Result := System.Math.Log2(A);673end;674
675function Log2(const A: TVector2): TVector2;676begin
677Result.Init(System.Math.Log2(A.X), System.Math.Log2(A.Y));678end;679
680function Log2(const A: TVector3): TVector3;681begin
682Result.Init(System.Math.Log2(A.X), System.Math.Log2(A.Y), System.Math.Log2(A.Z));683end;684
685function Log2(const A: TVector4): TVector4;686begin
687Result.Init(System.Math.Log2(A.X), System.Math.Log2(A.Y), System.Math.Log2(A.Z), System.Math.Log2(A.W));688end;689
690{ Fast approximate Functions }
691
692function FastPower(const ABase, AExponent: Single): Single;693begin
694Result := FastExp2(AExponent * FastLog2(ABase));695end;696
697function FastPower(const ABase, AExponent: TVector2): TVector2;698begin
699Result := FastExp2(AExponent * FastLog2(ABase));700end;701
702function FastPower(const ABase, AExponent: TVector3): TVector3;703begin
704Result := FastExp2(AExponent * FastLog2(ABase));705end;706
707function FastPower(const ABase, AExponent: TVector4): TVector4;708begin
709Result := FastExp2(AExponent * FastLog2(ABase));710end;711
712function FastTan(const ARadians: Single): Single;713var
714S, C: Single;715begin
716FastSinCos(ARadians, S, C);717Result := S / C;718end;719
720function FastTan(const ARadians: TVector2): TVector2;721var
722S, C: TVector2;723begin
724FastSinCos(ARadians, S, C);725Result := S / C;726end;727
728function FastTan(const ARadians: TVector3): TVector3;729var
730S, C: TVector3;731begin
732FastSinCos(ARadians, S, C);733Result := S / C;734end;735
736function FastTan(const ARadians: TVector4): TVector4;737var
738S, C: TVector4;739begin
740FastSinCos(ARadians, S, C);741Result := S / C;742end;743
744function FastArcTan2(const Y, X: Single): Single;745var
746Z: Single;747begin
748if (X = 0) then749begin750if (Y > 0) then751Exit(0.5 * Pi);752if (Y = 0) then753Exit(0);754Exit(-0.5 * Pi);755end;756
757Z := Y / X;758if (Abs(Z) < 1) then759begin760Result := Z / (1.0 + 0.28 * Z * Z);761if (X < 0) then762begin763if (Y < 0) then764Result := Result - Pi765else766Result := Result + Pi;767end;768end769else770begin771Result := (0.5 * Pi) - Z / (Z * Z + 0.28);772if (Y < 0) then773Result := Result - Pi;774end;775end;776
777function FastArcTan2(const Y, X: TVector2): TVector2;778begin
779Result.Init(FastArcTan2(Y.X, X.X), FastArcTan2(Y.Y, X.Y));780end;781
782function FastArcTan2(const Y, X: TVector3): TVector3;783begin
784Result.Init(FastArcTan2(Y.X, X.X), FastArcTan2(Y.Y, X.Y), FastArcTan2(Y.Z, X.Z));785end;786
787function FastArcTan2(const Y, X: TVector4): TVector4;788begin
789Result.Init(FastArcTan2(Y.X, X.X), FastArcTan2(Y.Y, X.Y), FastArcTan2(Y.Z, X.Z), FastArcTan2(Y.W, X.W));790end;791
792{ Common functions }
793
794function Min(const A, B: Single): Single;795begin
796Result := System.Math.Min(A, B);797end;798
799function Max(const A, B: Single): Single;800begin
801Result := System.Math.Max(A, B);802end;803
804function Mix(const A, B, T: Single): Single;805begin
806// Result := (A * (1 - T)) + (B * T);
807Result := A + (T * (B - A)); // Faster808end;809
810function Step(const AEdge, A: Single): Single;811begin
812if (A < AEdge) then813Result := 0814else815Result := 1;816end;817
818function SmoothStep(const AEdge0, AEdge1, A: Single): Single;819var
820Temp: Single;821begin
822Assert(AEdge1 > AEdge0);823if (A < AEdge0) then824Result := 0825else if (A > AEdge1) then826Result := 1827else828begin829Temp := (A - AEdge0) / (AEdge1 - AEdge0);830Result := Temp * Temp * (3 - (2 * Temp));831end;832end;833
834function FMA(const A, B, C: Single): Single;835begin
836Result := (A * B) + C;837end;838
839{ TVector2 }
840
841function TVector2.AngleTo(const ATarget: TVector2): Single;842begin
843Result := Neslib.FastMath.ArcTan2(Cross(ATarget), Dot(ATarget));844end;845
846function TVector2.Clamp(const AMinLength, AMaxLength: Single): TVector2;847var
848LenSq, EdgeSq: Single;849begin
850LenSq := GetLengthSquared;851if (LenSq = 0) then852Exit(Self);853
854EdgeSq := AMaxLength * AMaxLength;855if (LenSq > EdgeSq) then856Exit(Self * Sqrt(EdgeSq / LenSq));857
858EdgeSq := AMinLength * AMinLength;859if (LenSq < EdgeSq) then860Exit(Self * Sqrt(EdgeSq / LenSq));861
862Result := Self;863end;864
865function TVector2.Cross(const AOther: TVector2): Single;866begin
867Result := (X * AOther.Y) - (Y * AOther.X);868end;869
870class operator TVector2.Equal(const A, B: TVector2): Boolean;871begin
872Result := (A.X = B.X) and (A.Y = B.Y);873end;874
875function TVector2.Equals(const AOther: TVector2; const ATolerance: Single): Boolean;876begin
877Result := (Abs(X - AOther.X) <= ATolerance)878and (Abs(Y - AOther.Y) <= ATolerance);879end;880
881function TVector2.GetAngle: Single;882begin
883Result := Neslib.FastMath.ArcTan2(Y, X)884end;885
886function TVector2.GetComponent(const AIndex: Integer): Single;887begin
888Assert((AIndex >= 0) and (AIndex < 2));889Result := C[AIndex];890end;891
892function TVector2.HasSameDirection(const AOther: TVector2): Boolean;893begin
894Result := (Dot(AOther) > 0);895end;896
897function TVector2.HasOppositeDirection(const AOther: TVector2): Boolean;898begin
899Result := (Dot(AOther) < 0);900end;901
902class operator TVector2.Implicit(const A: TPointF): TVector2;903begin
904Result.X := A.X;905Result.Y := A.Y;906end;907
908class operator TVector2.Implicit(const A: TVector2): TPointF;909begin
910Result.X := A.X;911Result.Y := A.Y;912end;913
914procedure TVector2.Init;915begin
916X := 0;917Y := 0;918end;919
920procedure TVector2.Init(const A: Single);921begin
922X := A;923Y := A;924end;925
926procedure TVector2.Init(const A1, A2: Single);927begin
928X := A1;929Y := A2;930end;931
932procedure TVector2.Init(const APoint: TPoint);933begin
934X := APoint.X;935Y := APoint.Y;936end;937
938function TVector2.IsCollinear(const AOther: TVector2; const ATolerance: Single): Boolean;939begin
940Result := IsParallel(AOther, ATolerance) and (Dot(AOther) > 0);941end;942
943function TVector2.IsCollinearOpposite(const AOther: TVector2; const ATolerance: Single): Boolean;944begin
945Result := IsParallel(AOther, ATolerance) and (Dot(AOther) < 0);946end;947
948function TVector2.IsNormalized: Boolean;949begin
950Result := IsNormalized(0.000000001);951end;952
953function TVector2.IsNormalized(const AErrorMargin: Single): Boolean;954begin
955Result := (Abs(LengthSquared - 1.0) < AErrorMargin);956end;957
958function TVector2.IsParallel(const AOther: TVector2; const ATolerance: Single): Boolean;959begin
960Result := (Abs(X * AOther.Y - Y * AOther.X) <= ATolerance);961end;962
963function TVector2.IsPerpendicular(const AOther: TVector2; const ATolerance: Single): Boolean;964begin
965Result := (Abs(Dot(AOther)) <= ATolerance);966end;967
968function TVector2.IsZero: Boolean;969begin
970Result := (X = 0) and (Y = 0);971end;972
973function TVector2.IsZero(const AErrorMargin: Single): Boolean;974begin
975Result := (LengthSquared < AErrorMargin);976end;977
978function TVector2.Lerp(const ATarget: TVector2; const AAlpha: Single): TVector2;979begin
980Result := Mix(Self, ATarget, AAlpha);981end;982
983function TVector2.Limit(const AMaxLength: Single): TVector2;984begin
985Result := LimitSquared(AMaxLength * AMaxLength);986end;987
988function TVector2.LimitSquared(const AMaxLengthSquared: Single): TVector2;989var
990LenSq: Single;991begin
992LenSq := GetLengthSquared;993if (LenSq > AMaxLengthSquared) then994Result := Self * Sqrt(AMaxLengthSquared / LenSq)995else996Result := Self;997end;998
999class operator TVector2.Negative(const A: TVector2): TVector2;1000begin
1001Result.X := -A.X;1002Result.Y := -A.Y;1003end;1004
1005function TVector2.Normalize: TVector2;1006begin
1007Result := Self / Length;1008end;1009
1010class operator TVector2.NotEqual(const A, B: TVector2): Boolean;1011begin
1012Result := (A.X <> B.X) or (A.Y <> B.Y);1013end;1014
1015procedure TVector2.Offset(const ADeltaX, ADeltaY: Single);1016begin
1017X := X + ADeltaX;1018Y := Y + ADeltaY;1019end;1020
1021procedure TVector2.Offset(const ADelta: TVector2);1022begin
1023Self := Self + ADelta;1024end;1025
1026function TVector2.Rotate(const ARadians: Single): TVector2;1027var
1028S, C: Single;1029begin
1030FastSinCos(ARadians, S, C);1031Result.X := (X * C) - (Y * S);1032Result.Y := (X * S) + (Y * C);1033end;1034
1035function TVector2.Rotate90CCW: TVector2;1036begin
1037Result.X := -Y;1038Result.Y := X;1039end;1040
1041function TVector2.Rotate90CW: TVector2;1042begin
1043Result.X := Y;1044Result.Y := -X;1045end;1046
1047procedure TVector2.SetLerp(const ATarget: TVector2; const AAlpha: Single);1048begin
1049Self := Mix(Self, ATarget, AAlpha);1050end;1051
1052procedure TVector2.SetNormalized;1053begin
1054Self := Self / Length;1055end;1056
1057procedure TVector2.SetRotated90CCW;1058begin
1059Self := Rotate90CCW;1060end;1061
1062procedure TVector2.SetRotated90CW;1063begin
1064Self := Rotate90CW;1065end;1066
1067procedure TVector2.SetAngle(const AValue: Single);1068begin
1069X := Length;1070Y := 0;1071SetRotated(AValue);1072end;1073
1074procedure TVector2.SetClamped(const AMinLength, AMaxLength: Single);1075begin
1076Self := Clamp(AMinLength, AMaxLength);1077end;1078
1079procedure TVector2.SetComponent(const AIndex: Integer; const Value: Single);1080begin
1081Assert((AIndex >= 0) and (AIndex < 2));1082C[AIndex] := Value;1083end;1084
1085procedure TVector2.SetLength(const AValue: Single);1086begin
1087SetLengthSquared(AValue * AValue);1088end;1089
1090procedure TVector2.SetLengthSquared(const AValue: Single);1091var
1092LenSq: Single;1093begin
1094LenSq := GetLengthSquared;1095if (LenSq <> 0) and (LenSq <> AValue) then1096Self := Self * Sqrt(AValue / LenSq);1097end;1098
1099procedure TVector2.SetLimit(const AMaxLength: Single);1100begin
1101Self := LimitSquared(AMaxLength * AMaxLength);1102end;1103
1104procedure TVector2.SetLimitSquared(const AMaxLengthSquared: Single);1105begin
1106Self := LimitSquared(AMaxLengthSquared);1107end;1108
1109procedure TVector2.SetRotated(const ARadians: Single);1110begin
1111Self := Rotate(ARadians);1112end;1113
1114{ _TVector2Helper }
1115
1116function _TVector2Helper.Floor: TIVector2;1117begin
1118Result := Neslib.FastMath.Floor(Self);1119end;1120
1121function _TVector2Helper.Ceiling: TIVector2;1122begin
1123Result := Neslib.FastMath.Ceil(Self);1124end;1125
1126function _TVector2Helper.Truncate: TIVector2;1127begin
1128Result := Neslib.FastMath.Trunc(Self);1129end;1130
1131function _TVector2Helper.Round: TIVector2;1132begin
1133Result := Neslib.FastMath.Round(Self);1134end;1135
1136{ TVector3 }
1137
1138function TVector3.Clamp(const AMinLength, AMaxLength: Single): TVector3;1139var
1140LenSq, EdgeSq: Single;1141begin
1142LenSq := GetLengthSquared;1143if (LenSq = 0) then1144Exit(Self);1145
1146EdgeSq := AMaxLength * AMaxLength;1147if (LenSq > EdgeSq) then1148Exit(Self * Sqrt(EdgeSq / LenSq));1149
1150EdgeSq := AMinLength * AMinLength;1151if (LenSq < EdgeSq) then1152Exit(Self * Sqrt(EdgeSq / LenSq));1153
1154Result := Self;1155end;1156
1157class operator TVector3.Equal(const A, B: TVector3): Boolean;1158begin
1159Result := (A.X = B.X) and (A.Y = B.Y) and (A.Z = B.Z);1160end;1161
1162function TVector3.Equals(const AOther: TVector3; const ATolerance: Single): Boolean;1163begin
1164Result := (Abs(X - AOther.X) <= ATolerance)1165and (Abs(Y - AOther.Y) <= ATolerance)1166and (Abs(Z - AOther.Z) <= ATolerance);1167end;1168
1169function TVector3.GetComponent(const AIndex: Integer): Single;1170begin
1171Assert((AIndex >= 0) and (AIndex < 3));1172Result := C[AIndex];1173end;1174
1175function TVector3.HasSameDirection(const AOther: TVector3): Boolean;1176begin
1177Result := (Dot(AOther) > 0);1178end;1179
1180function TVector3.HasOppositeDirection(const AOther: TVector3): Boolean;1181begin
1182Result := (Dot(AOther) < 0);1183end;1184
1185class operator TVector3.Implicit(const A: TPoint3D): TVector3;1186begin
1187Result.X := A.X;1188Result.Y := A.Y;1189Result.Z := A.Z;1190end;1191
1192class operator TVector3.Implicit(const A: TVector3): TPoint3D;1193begin
1194Result.X := A.X;1195Result.Y := A.Y;1196Result.Z := A.Z;1197end;1198
1199procedure TVector3.Init(const A: Single);1200begin
1201X := A;1202Y := A;1203Z := A;1204end;1205
1206procedure TVector3.Init;1207begin
1208X := 0;1209Y := 0;1210Z := 0;1211end;1212
1213procedure TVector3.Init(const A1, A2, A3: Single);1214begin
1215X := A1;1216Y := A2;1217Z := A3;1218end;1219
1220procedure TVector3.Init(const A1: Single; const A2: TVector2);1221begin
1222X := A1;1223Y := A2.X;1224Z := A2.Y;1225end;1226
1227procedure TVector3.Init(const A1: TVector2; const A2: Single);1228begin
1229X := A1.X;1230Y := A1.Y;1231Z := A2;1232end;1233
1234function TVector3.IsCollinear(const AOther: TVector3; const ATolerance: Single): Boolean;1235begin
1236Result := IsParallel(AOther, ATolerance) and (Dot(AOther) > 0);1237end;1238
1239function TVector3.IsCollinearOpposite(const AOther: TVector3; const ATolerance: Single): Boolean;1240begin
1241Result := IsParallel(AOther, ATolerance) and (Dot(AOther) < 0);1242end;1243
1244function TVector3.IsNormalized: Boolean;1245begin
1246Result := IsNormalized(0.000000001);1247end;1248
1249function TVector3.IsNormalized(const AErrorMargin: Single): Boolean;1250begin
1251Result := (Abs(LengthSquared - 1.0) < AErrorMargin);1252end;1253
1254function TVector3.IsParallel(const AOther: TVector3; const ATolerance: Single): Boolean;1255begin
1256Result := ((Vector3(Y * AOther.Z - Z * AOther.Y,1257Z * AOther.X - X * AOther.Z,1258X * AOther.Y - Y * AOther.X).LengthSquared) <= ATolerance);1259end;1260
1261function TVector3.IsPerpendicular(const AOther: TVector3; const ATolerance: Single): Boolean;1262begin
1263Result := (Abs(Dot(AOther)) <= ATolerance);1264end;1265
1266function TVector3.IsZero: Boolean;1267begin
1268Result := (X = 0) and (Y = 0) and (Z = 0);1269end;1270
1271function TVector3.IsZero(const AErrorMargin: Single): Boolean;1272begin
1273Result := (LengthSquared < AErrorMargin);1274end;1275
1276function TVector3.Lerp(const ATarget: TVector3; const AAlpha: Single): TVector3;1277begin
1278Result := Mix(Self, ATarget, AAlpha);1279end;1280
1281function TVector3.Limit(const AMaxLength: Single): TVector3;1282begin
1283Result := LimitSquared(AMaxLength * AMaxLength);1284end;1285
1286function TVector3.LimitSquared(const AMaxLengthSquared: Single): TVector3;1287var
1288LenSq: Single;1289begin
1290LenSq := GetLengthSquared;1291if (LenSq > AMaxLengthSquared) then1292Result := Self * Sqrt(AMaxLengthSquared / LenSq)1293else1294Result := Self;1295end;1296
1297function TVector3.Normalize: TVector3;1298begin
1299Result := Self / Length;1300end;1301
1302class operator TVector3.NotEqual(const A, B: TVector3): Boolean;1303begin
1304Result := (A.X <> B.X) or (A.Y <> B.Y) or (A.Z <> B.Z);1305end;1306
1307procedure TVector3.Offset(const ADeltaX, ADeltaY, ADeltaZ: Single);1308begin
1309X := X + ADeltaX;1310Y := Y + ADeltaY;1311Z := Z + ADeltaZ;1312end;1313
1314procedure TVector3.Offset(const ADelta: TVector3);1315begin
1316Self := Self + ADelta;1317end;1318
1319procedure TVector3.SetClamped(const AMinLength, AMaxLength: Single);1320begin
1321Self := Clamp(AMinLength, AMaxLength);1322end;1323
1324procedure TVector3.SetComponent(const AIndex: Integer; const Value: Single);1325begin
1326Assert((AIndex >= 0) and (AIndex < 3));1327C[AIndex] := Value;1328end;1329
1330procedure TVector3.SetLength(const AValue: Single);1331begin
1332SetLengthSquared(AValue * AValue);1333end;1334
1335procedure TVector3.SetLengthSquared(const AValue: Single);1336var
1337LenSq: Single;1338begin
1339LenSq := GetLengthSquared;1340if (LenSq <> 0) and (LenSq <> AValue) then1341Self := Self * Sqrt(AValue / LenSq);1342end;1343
1344procedure TVector3.SetLerp(const ATarget: TVector3; const AAlpha: Single);1345begin
1346Self := Mix(Self, ATarget, AAlpha);1347end;1348
1349procedure TVector3.SetLimit(const AMaxLength: Single);1350begin
1351Self := LimitSquared(AMaxLength * AMaxLength);1352end;1353
1354procedure TVector3.SetLimitSquared(const AMaxLengthSquared: Single);1355begin
1356Self := LimitSquared(AMaxLengthSquared);1357end;1358
1359procedure TVector3.SetNormalized;1360begin
1361Self := Self / Length;1362end;1363
1364{ _TVector3Helper }
1365
1366function _TVector3Helper.Floor: TIVector3;1367begin
1368Result := Neslib.FastMath.Floor(Self);1369end;1370
1371function _TVector3Helper.Ceiling: TIVector3;1372begin
1373Result := Neslib.FastMath.Ceil(Self);1374end;1375
1376function _TVector3Helper.Truncate: TIVector3;1377begin
1378Result := Neslib.FastMath.Trunc(Self);1379end;1380
1381function _TVector3Helper.Round: TIVector3;1382begin
1383Result := Neslib.FastMath.Round(Self);1384end;1385
1386{ TVector4 }
1387
1388function TVector4.Clamp(const AMinLength, AMaxLength: Single): TVector4;1389var
1390LenSq, EdgeSq: Single;1391begin
1392LenSq := GetLengthSquared;1393if (LenSq = 0) then1394Exit(Self);1395
1396EdgeSq := AMaxLength * AMaxLength;1397if (LenSq > EdgeSq) then1398Exit(Self * Sqrt(EdgeSq / LenSq));1399
1400EdgeSq := AMinLength * AMinLength;1401if (LenSq < EdgeSq) then1402Exit(Self * Sqrt(EdgeSq / LenSq));1403
1404Result := Self;1405end;1406
1407class operator TVector4.Equal(const A, B: TVector4): Boolean;1408begin
1409Result := (A.X = B.X) and (A.Y = B.Y) and (A.Z = B.Z) and (A.W = B.W);1410end;1411
1412function TVector4.Equals(const AOther: TVector4; const ATolerance: Single): Boolean;1413begin
1414Result := (Abs(X - AOther.X) <= ATolerance)1415and (Abs(Y - AOther.Y) <= ATolerance)1416and (Abs(Z - AOther.Z) <= ATolerance)1417and (Abs(W - AOther.W) <= ATolerance);1418end;1419
1420function TVector4.GetComponent(const AIndex: Integer): Single;1421begin
1422Assert((AIndex >= 0) and (AIndex < 4));1423Result := C[AIndex];1424end;1425
1426function TVector4.HasSameDirection(const AOther: TVector4): Boolean;1427begin
1428Result := (((X * AOther.X) + (Y * AOther.Y) + (Z * AOther.Z)) > 0);1429end;1430
1431function TVector4.HasOppositeDirection(const AOther: TVector4): Boolean;1432begin
1433Result := (((X * AOther.X) + (Y * AOther.Y) + (Z * AOther.Z)) < 0);1434end;1435
1436class operator TVector4.Implicit(const A: TVector3D): TVector4;1437begin
1438Result.X := A.X;1439Result.Y := A.Y;1440Result.Z := A.Z;1441Result.W := A.W;1442end;1443
1444class operator TVector4.Implicit(const A: TVector4): TVector3D;1445begin
1446Result.X := A.X;1447Result.Y := A.Y;1448Result.Z := A.Z;1449Result.W := A.W;1450end;1451
1452procedure TVector4.Init(const A1, A2, A3, A4: Single);1453begin
1454X := A1;1455Y := A2;1456Z := A3;1457W := A4;1458end;1459
1460procedure TVector4.Init(const A: Single);1461begin
1462X := A;1463Y := A;1464Z := A;1465W := A;1466end;1467
1468procedure TVector4.Init;1469begin
1470X := 0;1471Y := 0;1472Z := 0;1473W := 0;1474end;1475
1476procedure TVector4.Init(const A1: TVector2; const A2, A3: Single);1477begin
1478X := A1.X;1479Y := A1.Y;1480Z := A2;1481W := A3;1482end;1483
1484procedure TVector4.Init(const A1, A2: TVector2);1485begin
1486X := A1.X;1487Y := A1.Y;1488Z := A2.X;1489W := A2.Y;1490end;1491
1492procedure TVector4.Init(const A1, A2: Single; const A3: TVector2);1493begin
1494X := A1;1495Y := A2;1496Z := A3.X;1497W := A3.Y;1498end;1499
1500procedure TVector4.Init(const A1: Single; const A2: TVector2; const A3: Single);1501begin
1502X := A1;1503Y := A2.X;1504Z := A2.Y;1505W := A3;1506end;1507
1508procedure TVector4.Init(const A1: TVector3; const A2: Single);1509begin
1510X := A1.X;1511Y := A1.Y;1512Z := A1.Z;1513W := A2;1514end;1515
1516procedure TVector4.Init(const A1: Single; const A2: TVector3);1517begin
1518X := A1;1519Y := A2.X;1520Z := A2.Y;1521W := A2.Z;1522end;1523
1524function TVector4.IsCollinear(const AOther: TVector4; const ATolerance: Single): Boolean;1525begin
1526Result := IsParallel(AOther, ATolerance) and (HasSameDirection(AOther));1527end;1528
1529function TVector4.IsCollinearOpposite(const AOther: TVector4; const ATolerance: Single): Boolean;1530begin
1531Result := IsParallel(AOther, ATolerance) and (HasOppositeDirection(AOther));1532end;1533
1534function TVector4.IsNormalized: Boolean;1535begin
1536Result := IsNormalized(0.000000001);1537end;1538
1539function TVector4.IsNormalized(const AErrorMargin: Single): Boolean;1540begin
1541Result := (Abs(LengthSquared - 1.0) < AErrorMargin);1542end;1543
1544function TVector4.IsParallel(const AOther: TVector4; const ATolerance: Single): Boolean;1545begin
1546Result := ((Vector3(Y * AOther.Z - Z * AOther.Y,1547Z * AOther.X - X * AOther.Z,1548X * AOther.Y - Y * AOther.X).LengthSquared) <= ATolerance);1549end;1550
1551function TVector4.IsPerpendicular(const AOther: TVector4; const ATolerance: Single): Boolean;1552begin
1553Result := (Abs((X * AOther.X) + (Y * AOther.Y) + (Z * AOther.Z)) <= ATolerance);1554end;1555
1556function TVector4.IsZero: Boolean;1557begin
1558Result := (X = 0) and (Y = 0) and (Z = 0) and (W = 0);1559end;1560
1561function TVector4.IsZero(const AErrorMargin: Single): Boolean;1562begin
1563Result := (LengthSquared < AErrorMargin);1564end;1565
1566function TVector4.Lerp(const ATarget: TVector4; const AAlpha: Single): TVector4;1567begin
1568Result := Mix(Self, ATarget, AAlpha);1569end;1570
1571function TVector4.Limit(const AMaxLength: Single): TVector4;1572begin
1573Result := LimitSquared(AMaxLength * AMaxLength);1574end;1575
1576function TVector4.LimitSquared(const AMaxLengthSquared: Single): TVector4;1577var
1578LenSq: Single;1579begin
1580LenSq := GetLengthSquared;1581if (LenSq > AMaxLengthSquared) then1582Result := Self * Sqrt(AMaxLengthSquared / LenSq)1583else1584Result := Self;1585end;1586
1587function TVector4.Normalize: TVector4;1588begin
1589Result := Self / Length;1590end;1591
1592class operator TVector4.NotEqual(const A, B: TVector4): Boolean;1593begin
1594Result := (A.X <> B.X) or (A.Y <> B.Y) or (A.Z <> B.Z) or (A.W <> B.W);1595end;1596
1597procedure TVector4.Offset(const ADeltaX, ADeltaY, ADeltaZ, ADeltaW: Single);1598begin
1599X := X + ADeltaX;1600Y := Y + ADeltaY;1601Z := Z + ADeltaZ;1602W := W + ADeltaW;1603end;1604
1605procedure TVector4.Offset(const ADelta: TVector4);1606begin
1607Self := Self + ADelta;1608end;1609
1610procedure TVector4.SetClamped(const AMinLength, AMaxLength: Single);1611begin
1612Self := Clamp(AMinLength, AMaxLength);1613end;1614
1615procedure TVector4.SetComponent(const AIndex: Integer; const Value: Single);1616begin
1617Assert((AIndex >= 0) and (AIndex < 4));1618C[AIndex] := Value;1619end;1620
1621procedure TVector4.SetLength(const AValue: Single);1622begin
1623SetLengthSquared(AValue * AValue);1624end;1625
1626procedure TVector4.SetLengthSquared(const AValue: Single);1627var
1628LenSq: Single;1629begin
1630LenSq := GetLengthSquared;1631if (LenSq <> 0) and (LenSq <> AValue) then1632Self := Self * Sqrt(AValue / LenSq);1633end;1634
1635procedure TVector4.SetLerp(const ATarget: TVector4; const AAlpha: Single);1636begin
1637Self := Mix(Self, ATarget, AAlpha);1638end;1639
1640procedure TVector4.SetLimit(const AMaxLength: Single);1641begin
1642Self := LimitSquared(AMaxLength * AMaxLength);1643end;1644
1645procedure TVector4.SetLimitSquared(const AMaxLengthSquared: Single);1646begin
1647Self := LimitSquared(AMaxLengthSquared);1648end;1649
1650procedure TVector4.SetNormalized;1651begin
1652Self := Self / Length;1653end;1654
1655{ _TVector4Helper }
1656
1657function _TVector4Helper.Floor: TIVector4;1658begin
1659Result := Neslib.FastMath.Floor(Self);1660end;1661
1662function _TVector4Helper.Ceiling: TIVector4;1663begin
1664Result := Neslib.FastMath.Ceil(Self);1665end;1666
1667function _TVector4Helper.Truncate: TIVector4;1668begin
1669Result := Neslib.FastMath.Trunc(Self);1670end;1671
1672function _TVector4Helper.Round: TIVector4;1673begin
1674Result := Neslib.FastMath.Round(Self);1675end;1676
1677{ TQuaternion }
1678
1679function TQuaternion.Conjugate: TQuaternion;1680begin
1681Result.X := -X;1682Result.Y := -Y;1683Result.Z := -Z;1684Result.W := W;1685end;1686
1687class operator TQuaternion.Implicit(const A: TQuaternion3D): TQuaternion;1688begin
1689Result.X := A.V[0];1690Result.Y := A.V[1];1691Result.Z := A.V[2];1692Result.W := A.V[3];1693end;1694
1695class operator TQuaternion.Implicit(const A: TQuaternion): TQuaternion3D;1696begin
1697Result.V[0] := A.X;1698Result.V[1] := A.Y;1699Result.V[2] := A.Z;1700Result.V[3] := A.W;1701end;1702
1703procedure TQuaternion.Init;1704begin
1705X := 0;1706Y := 0;1707Z := 0;1708W := 1;1709end;1710
1711procedure TQuaternion.Init(const AX, AY, AZ, AW: Single);1712begin
1713X := AX;1714Y := AY;1715Z := AZ;1716W := AW;1717end;1718
1719procedure TQuaternion.Init(const AAxis: TVector3; const AAngleRadians: Single);1720var
1721D, S, C: Single;1722begin
1723D := AAxis.Length;1724if (D = 0) then1725begin1726Init;1727Exit;1728end;1729
1730D := 1 / D;1731FastSinCos(AAngleRadians * 0.5, S, C);1732X := D * AAxis.X * S;1733Y := D * AAxis.Y * S;1734Z := D * AAxis.Z * S;1735W := C;1736SetNormalized;1737end;1738
1739procedure TQuaternion.Init(const AYaw, APitch, ARoll: Single);1740var
1741A, S, C: TVector4;1742CYSP, SYCP, CYCP, SYSP: Single;1743begin
1744A.Init(APitch * 0.5, AYaw * 0.5, ARoll * 0.5, 0);1745FastSinCos(A, S, C);1746
1747CYSP := C.Y * S.X;1748SYCP := S.Y * C.X;1749CYCP := C.Y * C.X;1750SYSP := S.Y * S.X;1751
1752X := (CYSP * C.Z) + (SYCP * S.Z);1753Y := (SYCP * C.Z) - (CYSP * S.Z);1754Z := (CYCP * S.Z) - (SYSP * C.Z);1755W := (CYCP * C.Z) + (SYSP * S.Z);1756end;1757
1758procedure TQuaternion.Init(const AMatrix: TMatrix4);1759var
1760Trace, S: double;1761begin
1762Trace := AMatrix.m11 + AMatrix.m22 + AMatrix.m33;1763if (Trace > EPSILON) then1764begin1765S := 0.5 / Sqrt(Trace + 1.0);1766X := (AMatrix.m23 - AMatrix.m32) * S;1767Y := (AMatrix.m31 - AMatrix.m13) * S;1768Z := (AMatrix.m12 - AMatrix.m21) * S;1769W := 0.25 / S;1770end1771else if (AMatrix.m11 > AMatrix.m22) and (AMatrix.m11 > AMatrix.m33) then1772begin1773S := Sqrt(Neslib.FastMath.Max(EPSILON, 1 + AMatrix.m11 - AMatrix.m22 - AMatrix.m33)) * 2.0;1774X := 0.25 * S;1775Y := (AMatrix.m12 + AMatrix.m21) / S;1776Z := (AMatrix.m31 + AMatrix.m13) / S;1777W := (AMatrix.m23 - AMatrix.m32) / S;1778end1779else if (AMatrix.m22 > AMatrix.m33) then1780begin1781S := Sqrt(Neslib.FastMath.Max(EPSILON, 1 + AMatrix.m22 - AMatrix.m11 - AMatrix.m33)) * 2.0;1782X := (AMatrix.m12 + AMatrix.m21) / S;1783Y := 0.25 * S;1784Z := (AMatrix.m23 + AMatrix.m32) / S;1785W := (AMatrix.m31 - AMatrix.m13) / S;1786end else1787begin1788S := Sqrt(Neslib.FastMath.Max(EPSILON, 1 + AMatrix.m33 - AMatrix.m11 - AMatrix.m22)) * 2.0;1789X := (AMatrix.m31 + AMatrix.m13) / S;1790Y := (AMatrix.m23 + AMatrix.m32) / S;1791Z := 0.25 * S;1792W := (AMatrix.m12 - AMatrix.m21) / S;1793end;1794SetNormalized;1795end;1796
1797function TQuaternion.IsIdentity: Boolean;1798begin
1799Result := (X = 0) and (Y = 0) and (Z = 0) and (W = 1);1800end;1801
1802function TQuaternion.IsIdentity(const AErrorMargin: Single): Boolean;1803begin
1804Result := (Abs(X) <= AErrorMargin) and (Abs(Y) <= AErrorMargin)1805and (Abs(Z) <= AErrorMargin) and ((Abs(W) - 1) <= AErrorMargin)1806end;1807
1808function TQuaternion.Normalize: TQuaternion;1809begin
1810Result := Self * (1 / Length);1811end;1812
1813procedure TQuaternion.SetConjugate;1814begin
1815X := -X;1816Y := -Y;1817Z := -Z;1818end;1819
1820procedure TQuaternion.SetNormalized;1821begin
1822Self := Self * (1 / Length);1823end;1824
1825function TQuaternion.ToMatrix: TMatrix4;1826var
1827Q: TQuaternion;1828XX, XY, XZ, XW, YY, YZ, YW, ZZ, ZW: Single;1829begin
1830Q := Normalize;1831XX := Q.X * Q.X;1832XY := Q.X * Q.Y;1833XZ := Q.X * Q.Z;1834XW := Q.X * Q.W;1835YY := Q.Y * Q.Y;1836YZ := Q.Y * Q.Z;1837YW := Q.Y * Q.W;1838ZZ := Q.Z * Q.Z;1839ZW := Q.Z * Q.W;1840
1841Result.Init(18421 - 2 * (YY + ZZ), 2 * (XY + ZW), 2 * (XZ - YW), 0,18432 * (XY - ZW), 1 - 2 * (XX + ZZ), 2 * (YZ + XW), 0,18442 * (XZ + YW), 2 * (YZ - XW), 1 - 2 * (XX + YY), 0,18450, 0, 0, 1);1846end;1847
1848{ TMatrix2 }
1849
1850class operator TMatrix2.Divide(const A, B: TMatrix2): TMatrix2;1851begin
1852Result := A * B.Inverse;1853end;1854
1855class operator TMatrix2.Divide(const A: TVector2; const B: TMatrix2): TVector2;1856begin
1857Result := A * B.Inverse;1858end;1859
1860class operator TMatrix2.Divide(const A: TMatrix2; const B: TVector2): TVector2;1861begin
1862Result := A.Inverse * B;1863end;1864
1865function TMatrix2.GetDeterminant: Single;1866begin
1867Result :=1868+ (M[0,0] * M[1,1])1869- (M[1,0] * M[0,1]);1870end;1871
1872function TMatrix2.Inverse: TMatrix2;1873var
1874OneOverDeterminant: Single;1875begin
1876OneOverDeterminant := 1 / Determinant;1877Result.M[0,0] := +M[1,1] * OneOverDeterminant;1878Result.M[0,1] := -M[0,1] * OneOverDeterminant;1879Result.M[1,0] := -M[1,0] * OneOverDeterminant;1880Result.M[1,1] := +M[0,0] * OneOverDeterminant;1881end;1882
1883procedure TMatrix2.SetInversed;1884begin
1885Self := Inverse;1886end;1887
1888class operator TMatrix2.Equal(const A, B: TMatrix2): Boolean;1889begin
1890Result := (A.V[0] = B.V[0]) and (A.V[1] = B.V[1]);1891end;1892
1893procedure TMatrix2.Init(const ADiagonal: Single);1894begin
1895V[0].Init(ADiagonal, 0);1896V[1].Init(0, ADiagonal);1897end;1898
1899procedure TMatrix2.Init;1900begin
1901V[0].Init(1, 0);1902V[1].Init(0, 1);1903end;1904
1905procedure TMatrix2.Init(const A11, A12, A21, A22: Single);1906begin
1907V[0].Init(A11, A12);1908V[1].Init(A21, A22);1909end;1910
1911class operator TMatrix2.NotEqual(const A, B: TMatrix2): Boolean;1912begin
1913Result := (A.V[0] <> B.V[0]) or (A.V[1] <> B.V[1]);1914end;1915
1916{$IFDEF FM_COLUMN_MAJOR}
1917function TMatrix2.GetColumn(const AIndex: Integer): TVector2;1918begin
1919Assert((AIndex >= 0) and (AIndex < 2));1920Result := C[AIndex];1921end;1922
1923function TMatrix2.GetComponent(const AColumn, ARow: Integer): Single;1924begin
1925Assert((AColumn >= 0) and (AColumn < 2));1926Assert((ARow >= 0) and (ARow < 2));1927Result := M[AColumn, ARow];1928end;1929
1930procedure TMatrix2.Init(const AColumn0, AColumn1: TVector2);1931begin
1932C[0] := AColumn0;1933C[1] := AColumn1;1934end;1935
1936class operator TMatrix3.Implicit(const A: TMatrix): TMatrix3;1937var
1938M: TMatrix3 absolute A;1939begin
1940Result := M.Transpose;1941end;1942
1943class operator TMatrix3.Implicit(const A: TMatrix3): TMatrix;1944var
1945M: TMatrix3 absolute Result;1946begin
1947M := A.Transpose;1948end;1949
1950procedure TMatrix2.SetColumn(const AIndex: Integer; const Value: TVector2);1951begin
1952Assert((AIndex >= 0) and (AIndex < 2));1953C[AIndex] := Value;1954end;1955
1956procedure TMatrix2.SetComponent(const AColumn, ARow: Integer; const Value: Single);1957begin
1958Assert((AColumn >= 0) and (AColumn < 2));1959Assert((ARow >= 0) and (ARow < 2));1960M[AColumn, ARow] := Value;1961end;1962{$ELSE}
1963function TMatrix2.GetComponent(const ARow, AColumn: Integer): Single;1964begin
1965Assert((ARow >= 0) and (ARow < 2));1966Assert((AColumn >= 0) and (AColumn < 2));1967Result := M[ARow, AColumn];1968end;1969
1970function TMatrix2.GetRow(const AIndex: Integer): TVector2;1971begin
1972Assert((AIndex >= 0) and (AIndex < 2));1973Result := R[AIndex];1974end;1975
1976class operator TMatrix3.Implicit(const A: TMatrix): TMatrix3;1977begin
1978Move(A, Result, SizeOf(A));1979end;1980
1981class operator TMatrix3.Implicit(const A: TMatrix3): TMatrix;1982begin
1983Move(A, Result, SizeOf(A));1984end;1985
1986procedure TMatrix2.Init(const ARow0, ARow1: TVector2);1987begin
1988R[0] := ARow0;1989R[1] := ARow1;1990end;1991
1992procedure TMatrix2.SetComponent(const ARow, AColumn: Integer; const Value: Single);1993begin
1994Assert((ARow >= 0) and (ARow < 2));1995Assert((AColumn >= 0) and (AColumn < 2));1996M[ARow, AColumn] := Value;1997end;1998
1999procedure TMatrix2.SetRow(const AIndex: Integer; const Value: TVector2);2000begin
2001Assert((AIndex >= 0) and (AIndex < 2));2002R[AIndex] := Value;2003end;2004{$ENDIF}
2005
2006{ TMatrix3 }
2007
2008class operator TMatrix3.Divide(const A, B: TMatrix3): TMatrix3;2009begin
2010Result := A * B.Inverse;2011end;2012
2013class operator TMatrix3.Divide(const A: TVector3; const B: TMatrix3): TVector3;2014begin
2015Result := A * B.Inverse;2016end;2017
2018class operator TMatrix3.Divide(const A: TMatrix3; const B: TVector3): TVector3;2019begin
2020Result := A.Inverse * B;2021end;2022
2023function TMatrix3.GetDeterminant: Single;2024begin
2025Result :=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])));2029end;2030
2031function TMatrix3.Inverse: TMatrix3;2032var
2033OneOverDeterminant: Single;2034begin
2035OneOverDeterminant := 1 / Determinant;2036Result.M[0,0] := + ((M[1,1] * M[2,2]) - (M[2,1] * M[1,2])) * OneOverDeterminant;2037Result.M[1,0] := - ((M[1,0] * M[2,2]) - (M[2,0] * M[1,2])) * OneOverDeterminant;2038Result.M[2,0] := + ((M[1,0] * M[2,1]) - (M[2,0] * M[1,1])) * OneOverDeterminant;2039Result.M[0,1] := - ((M[0,1] * M[2,2]) - (M[2,1] * M[0,2])) * OneOverDeterminant;2040Result.M[1,1] := + ((M[0,0] * M[2,2]) - (M[2,0] * M[0,2])) * OneOverDeterminant;2041Result.M[2,1] := - ((M[0,0] * M[2,1]) - (M[2,0] * M[0,1])) * OneOverDeterminant;2042Result.M[0,2] := + ((M[0,1] * M[1,2]) - (M[1,1] * M[0,2])) * OneOverDeterminant;2043Result.M[1,2] := - ((M[0,0] * M[1,2]) - (M[1,0] * M[0,2])) * OneOverDeterminant;2044Result.M[2,2] := + ((M[0,0] * M[1,1]) - (M[1,0] * M[0,1])) * OneOverDeterminant;2045end;2046
2047procedure TMatrix3.SetInversed;2048begin
2049Self := Inverse;2050end;2051
2052class operator TMatrix3.Equal(const A, B: TMatrix3): Boolean;2053begin
2054Result := (A.V[0] = B.V[0]) and (A.V[1] = B.V[1]) and (A.V[2] = B.V[2]);2055end;2056
2057procedure TMatrix3.Init(const ADiagonal: Single);2058begin
2059V[0].Init(ADiagonal, 0, 0);2060V[1].Init(0, ADiagonal, 0);2061V[2].Init(0, 0, ADiagonal);2062end;2063
2064procedure TMatrix3.Init;2065begin
2066V[0].Init(1, 0, 0);2067V[1].Init(0, 1, 0);2068V[2].Init(0, 0, 1);2069end;2070
2071procedure TMatrix3.Init(const AMatrix: TMatrix2);2072begin
2073V[0].Init(AMatrix.V[0], 0);2074V[1].Init(AMatrix.V[1], 0);2075V[2].Init(0, 0, 1);2076end;2077
2078procedure TMatrix3.Init(const A11, A12, A13, A21, A22, A23, A31, A32,2079A33: Single);2080begin
2081V[0].Init(A11, A12, A13);2082V[1].Init(A21, A22, A23);2083V[2].Init(A31, A32, A33);2084end;2085
2086procedure TMatrix3.InitScaling(const AScale: Single);2087begin
2088V[0].Init(AScale, 0, 0);2089V[1].Init(0, AScale, 0);2090V[2].Init(0, 0, 1);2091end;2092
2093procedure TMatrix3.InitScaling(const AScaleX, AScaleY: Single);2094begin
2095V[0].Init(AScaleX, 0, 0);2096V[1].Init(0, AScaleY, 0);2097V[2].Init(0, 0, 1);2098end;2099
2100procedure TMatrix3.InitScaling(const AScale: TVector2);2101begin
2102V[0].Init(AScale.X, 0, 0);2103V[1].Init(0, AScale.Y, 0);2104V[2].Init(0, 0, 1);2105end;2106
2107procedure TMatrix3.InitTranslation(const ADeltaX, ADeltaY: Single);2108begin
2109V[0].Init(1, 0, 0);2110V[1].Init(0, 1, 0);2111V[2].Init(ADeltaX, ADeltaY, 1);2112end;2113
2114procedure TMatrix3.InitTranslation(const ADelta: TVector2);2115begin
2116V[0].Init(1, 0, 0);2117V[1].Init(0, 1, 0);2118V[2].Init(ADelta.X, ADelta.Y, 1);2119end;2120
2121class operator TMatrix3.NotEqual(const A, B: TMatrix3): Boolean;2122begin
2123Result := (A.V[0] <> B.V[0]) or (A.V[1] <> B.V[1]) or (A.V[2] <> B.V[2]);2124end;2125
2126{$IFDEF FM_COLUMN_MAJOR}
2127function TMatrix3.GetColumn(const AIndex: Integer): TVector3;2128begin
2129Assert((AIndex >= 0) and (AIndex < 3));2130Result := C[AIndex];2131end;2132
2133function TMatrix3.GetComponent(const AColumn, ARow: Integer): Single;2134begin
2135Assert((AColumn >= 0) and (AColumn < 3));2136Assert((ARow >= 0) and (ARow < 3));2137Result := M[AColumn, ARow];2138end;2139
2140procedure TMatrix3.Init(const AColumn0, AColumn1, AColumn2: TVector3);2141begin
2142C[0] := AColumn0;2143C[1] := AColumn1;2144C[2] := AColumn2;2145end;2146
2147procedure TMatrix3.InitRotation(const AAngle: Single);2148var
2149S, C: Single;2150begin
2151FastSinCos(AAngle, S, C);2152Self.C[0].Init(C, S, 0);2153Self.C[1].Init(-S, C, 0);2154Self.C[2].Init(0, 0, 1);2155end;2156
2157procedure TMatrix3.SetColumn(const AIndex: Integer; const Value: TVector3);2158begin
2159Assert((AIndex >= 0) and (AIndex < 3));2160C[AIndex] := Value;2161end;2162
2163procedure TMatrix3.SetComponent(const AColumn, ARow: Integer; const Value: Single);2164begin
2165Assert((AColumn >= 0) and (AColumn < 3));2166Assert((ARow >= 0) and (ARow < 3));2167M[AColumn, ARow] := Value;2168end;2169{$ELSE}
2170function TMatrix3.GetComponent(const ARow, AColumn: Integer): Single;2171begin
2172Assert((ARow >= 0) and (ARow < 3));2173Assert((AColumn >= 0) and (AColumn < 3));2174Result := M[ARow, AColumn];2175end;2176
2177function TMatrix3.GetRow(const AIndex: Integer): TVector3;2178begin
2179Assert((AIndex >= 0) and (AIndex < 3));2180Result := R[AIndex];2181end;2182
2183procedure TMatrix3.Init(const ARow0, ARow1, ARow2: TVector3);2184begin
2185R[0] := ARow0;2186R[1] := ARow1;2187R[2] := ARow2;2188end;2189
2190procedure TMatrix3.InitRotation(const AAngle: Single);2191var
2192S, C: Single;2193begin
2194FastSinCos(AAngle, S, C);2195R[0].Init(C, S, 0);2196R[1].Init(-S, C, 0);2197R[2].Init(0, 0, 1);2198end;2199
2200procedure TMatrix3.SetComponent(const ARow, AColumn: Integer; const Value: Single);2201begin
2202Assert((ARow >= 0) and (ARow < 3));2203Assert((AColumn >= 0) and (AColumn < 3));2204M[ARow, AColumn] := Value;2205end;2206
2207procedure TMatrix3.SetRow(const AIndex: Integer; const Value: TVector3);2208begin
2209Assert((AIndex >= 0) and (AIndex < 3));2210R[AIndex] := Value;2211end;2212{$ENDIF}
2213
2214{ TMatrix4 }
2215
2216class operator TMatrix4.Divide(const A, B: TMatrix4): TMatrix4;2217begin
2218Result := A * B.Inverse;2219end;2220
2221class operator TMatrix4.Divide(const A: TVector4; const B: TMatrix4): TVector4;2222begin
2223Result := A * B.Inverse;2224end;2225
2226class operator TMatrix4.Divide(const A: TMatrix4; const B: TVector4): TVector4;2227begin
2228Result := A.Inverse * B;2229end;2230
2231function TMatrix4.GetDeterminant: Single;2232var
2233F00, F01, F02, F03, F04, F05: Single;2234C: TVector4;2235begin
2236F00 := (M[2,2] * M[3,3]) - (M[3,2] * M[2,3]);2237F01 := (M[2,1] * M[3,3]) - (M[3,1] * M[2,3]);2238F02 := (M[2,1] * M[3,2]) - (M[3,1] * M[2,2]);2239F03 := (M[2,0] * M[3,3]) - (M[3,0] * M[2,3]);2240F04 := (M[2,0] * M[3,2]) - (M[3,0] * M[2,2]);2241F05 := (M[2,0] * M[3,1]) - (M[3,0] * M[2,1]);2242
2243C.X := + ((M[1,1] * F00) - (M[1,2] * F01) + (M[1,3] * F02));2244C.Y := - ((M[1,0] * F00) - (M[1,2] * F03) + (M[1,3] * F04));2245C.Z := + ((M[1,0] * F01) - (M[1,1] * F03) + (M[1,3] * F05));2246C.W := - ((M[1,0] * F02) - (M[1,1] * F04) + (M[1,2] * F05));2247
2248Result := (M[0,0] * C.X) + (M[0,1] * C.Y) + (M[0,2] * C.Z) + (M[0,3] * C.W);2249end;2250
2251class operator TMatrix4.Equal(const A, B: TMatrix4): Boolean;2252begin
2253Result := (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]);2254end;2255
2256procedure TMatrix4.Init(const ADiagonal: Single);2257begin
2258V[0].Init(ADiagonal, 0, 0, 0);2259V[1].Init(0, ADiagonal, 0, 0);2260V[2].Init(0, 0, ADiagonal, 0);2261V[3].Init(0, 0, 0, ADiagonal);2262end;2263
2264procedure TMatrix4.Init;2265begin
2266V[0].Init(1, 0, 0, 0);2267V[1].Init(0, 1, 0, 0);2268V[2].Init(0, 0, 1, 0);2269V[3].Init(0, 0, 0, 1);2270end;2271
2272procedure TMatrix4.Init(const A11, A12, A13, A14, A21, A22, A23, A24, A31, A32,2273A33, A34, A41, A42, A43, A44: Single);2274begin
2275V[0].Init(A11, A12, A13, A14);2276V[1].Init(A21, A22, A23, A24);2277V[2].Init(A31, A32, A33, A34);2278V[3].Init(A41, A42, A43, A44);2279end;2280
2281procedure TMatrix4.Init(const AMatrix: TMatrix2);2282begin
2283V[0].Init(AMatrix.V[0], 0, 0);2284V[1].Init(AMatrix.V[1], 0, 0);2285V[2].Init(0, 0, 1, 0);2286V[3].Init(0, 0, 0, 1);2287end;2288
2289procedure TMatrix4.Init(const AMatrix: TMatrix3);2290begin
2291V[0].Init(AMatrix.V[0], 0);2292V[1].Init(AMatrix.V[1], 0);2293V[2].Init(AMatrix.V[2], 0);2294V[3].Init(0, 0, 0, 1);2295end;2296
2297procedure TMatrix4.InitLookAtLH(const ACameraPosition, ACameraTarget,2298ACameraUp: TVector3);2299var
2300XAxis, YAxis, ZAxis: TVector3;2301begin
2302ZAxis := (ACameraTarget - ACameraPosition).Normalize;2303XAxis := ACameraUp.Cross(ZAxis).Normalize;2304YAxis := ZAxis.Cross(XAxis);2305
2306V[0].Init(XAxis.X, YAxis.X, ZAxis.X, 0);2307V[1].Init(XAxis.Y, YAxis.Y, ZAxis.Y, 0);2308V[2].Init(XAxis.Z, YAxis.Z, ZAxis.Z, 0);2309V[3].Init(-XAxis.Dot(ACameraPosition),2310-YAxis.Dot(ACameraPosition),2311-ZAxis.Dot(ACameraPosition), 1);2312end;2313
2314procedure TMatrix4.InitLookAtRH(const ACameraPosition, ACameraTarget,2315ACameraUp: TVector3);2316var
2317XAxis, YAxis, ZAxis: TVector3;2318begin
2319ZAxis := (ACameraPosition - ACameraTarget).Normalize;2320XAxis := ACameraUp.Cross(ZAxis).Normalize;2321YAxis := ZAxis.Cross(XAxis);2322
2323V[0].Init(XAxis.X, YAxis.X, ZAxis.X, 0);2324V[1].Init(XAxis.Y, YAxis.Y, ZAxis.Y, 0);2325V[2].Init(XAxis.Z, YAxis.Z, ZAxis.Z, 0);2326V[3].Init(-XAxis.Dot(ACameraPosition),2327-YAxis.Dot(ACameraPosition),2328-ZAxis.Dot(ACameraPosition), 1);2329end;2330
2331procedure TMatrix4.InitLookAtDirLH(const ACameraPosition, ACameraDirection,2332ACameraUp: TVector3);2333var
2334XAxis, YAxis, ZAxis: TVector3;2335begin
2336ZAxis := -ACameraDirection.Normalize;2337XAxis := ACameraUp.Cross(ZAxis).Normalize;2338YAxis := ZAxis.Cross(XAxis);2339
2340V[0].Init(XAxis.X, YAxis.X, ZAxis.X, 0);2341V[1].Init(XAxis.Y, YAxis.Y, ZAxis.Y, 0);2342V[2].Init(XAxis.Z, YAxis.Z, ZAxis.Z, 0);2343V[3].Init(-XAxis.Dot(ACameraPosition),2344-YAxis.Dot(ACameraPosition),2345-ZAxis.Dot(ACameraPosition), 1);2346end;2347
2348procedure TMatrix4.InitLookAtDirRH(const ACameraPosition, ACameraDirection,2349ACameraUp: TVector3);2350var
2351XAxis, YAxis, ZAxis: TVector3;2352begin
2353ZAxis := ACameraDirection.Normalize;2354XAxis := ACameraUp.Cross(ZAxis).Normalize;2355YAxis := ZAxis.Cross(XAxis);2356
2357V[0].Init(XAxis.X, YAxis.X, ZAxis.X, 0);2358V[1].Init(XAxis.Y, YAxis.Y, ZAxis.Y, 0);2359V[2].Init(XAxis.Z, YAxis.Z, ZAxis.Z, 0);2360V[3].Init(-XAxis.Dot(ACameraPosition),2361-YAxis.Dot(ACameraPosition),2362-ZAxis.Dot(ACameraPosition), 1);2363end;2364
2365procedure TMatrix4.InitScaling(const AScale: Single);2366begin
2367V[0].Init(AScale, 0, 0, 0);2368V[1].Init(0, AScale, 0, 0);2369V[2].Init(0, 0, AScale, 0);2370V[3].Init(0, 0, 0, 1);2371end;2372
2373procedure TMatrix4.InitScaling(const AScaleX, AScaleY, AScaleZ: Single);2374begin
2375V[0].Init(AScaleX, 0, 0, 0);2376V[1].Init(0, AScaleY, 0, 0);2377V[2].Init(0, 0, AScaleZ, 0);2378V[3].Init(0, 0, 0, 1);2379end;2380
2381procedure TMatrix4.InitScaling(const AScale: TVector3);2382begin
2383V[0].Init(AScale.X, 0, 0, 0);2384V[1].Init(0, AScale.Y, 0, 0);2385V[2].Init(0, 0, AScale.Z, 0);2386V[3].Init(0, 0, 0, 1);2387end;2388
2389procedure TMatrix4.InitTranslation(const ADeltaX, ADeltaY, ADeltaZ: Single);2390begin
2391V[0].Init(1, 0, 0, 0);2392V[1].Init(0, 1, 0, 0);2393V[2].Init(0, 0, 1, 0);2394V[3].Init(ADeltaX, ADeltaY, ADeltaZ, 1);2395end;2396
2397procedure TMatrix4.InitTranslation(const ADelta: TVector3);2398begin
2399V[0].Init(1, 0, 0, 0);2400V[1].Init(0, 1, 0, 0);2401V[2].Init(0, 0, 1, 0);2402V[3].Init(ADelta.X, ADelta.Y, ADelta.Z, 1);2403end;2404
2405class operator TMatrix4.NotEqual(const A, B: TMatrix4): Boolean;2406begin
2407Result := (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]);2408end;2409
2410procedure TMatrix4.InitRotationX(const AAngle: Single);2411var
2412S, C: Single;2413begin
2414FastSinCos(AAngle, S, C);2415V[0].Init(1, 0, 0, 0);2416V[1].Init(0, C, S, 0);2417V[2].Init(0, -S, C, 0);2418V[3].Init(0, 0, 0, 1);2419end;2420
2421procedure TMatrix4.InitRotationY(const AAngle: Single);2422var
2423S, C: Single;2424begin
2425FastSinCos(AAngle, S, C);2426V[0].Init(C, 0, -S, 0);2427V[1].Init(0, 1, 0, 0);2428V[2].Init(S, 0, C, 0);2429V[3].Init(0, 0, 0, 1);2430end;2431
2432procedure TMatrix4.InitRotationZ(const AAngle: Single);2433var
2434S, C: Single;2435begin
2436FastSinCos(AAngle, S, C);2437V[0].Init(C, S, 0, 0);2438V[1].Init(-S, C, 0, 0);2439V[2].Init(0, 0, 1, 0);2440V[3].Init(0, 0, 0, 1);2441end;2442
2443procedure TMatrix4.InitRotation(const AAxis: TVector3; const AAngle: Single);2444var
2445S, C, C1: Single;2446N: TVector3;2447begin
2448FastSinCos(AAngle, S, C);2449C1 := 1 - C;2450N := AAxis.Normalize;2451
2452V[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
2457V[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
2461V[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
2465V[3].Init(0, 0, 0, 1);2466end;2467
2468procedure TMatrix4.InitRotationYawPitchRoll(const AYaw, APitch, ARoll: Single);2469var
2470A, S, C: TVector4;2471begin
2472A.Init(APitch, AYaw, ARoll, 0);2473FastSinCos(A, S, C);2474
2475V[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
2479V[1].Init(C.X * S.Y,2480C.X * C.Y,2481S.X, 0);2482
2483V[2].Init((C.Y * S.Z) - (C.Z * S.X * S.Y),2484(-C.Z * C.Y * S.X) - (S.Z * S.Y),2485C.X * C.Z, 0);2486
2487V[3].Init(0, 0, 0, 1);2488end;2489
2490procedure TMatrix4.InitRotationHeadingPitchBank(const AHeading, APitch, ABank: Single);2491var
2492A, S, C: TVector4;2493begin
2494A.Init(AHeading, APitch, ABank, 0);2495FastSinCos(A, S, C);2496
2497V[0].Init((C.X * C.Z) + (S.X * S.Y * S.Z),2498(-C.X * S.Z) + (S.X * S.Y * C.Z),2499S.X * C.Y, 0);2500
2501V[1].Init(S.Z * C.Y,2502C.Y * C.Z,2503-S.Y, 0);2504
2505V[2].Init((-S.X * C.Z) + (C.X * S.Y * S.Z),2506(S.Z * S.X) + (C.X * S.Y * C.Z),2507C.X * C.Y, 0);2508
2509V[3].Init(0, 0, 0, 1);2510end;2511
2512{$IFDEF FM_COLUMN_MAJOR}
2513function TMatrix4.GetColumn(const AIndex: Integer): TVector4;2514begin
2515Assert((AIndex >= 0) and (AIndex < 4));2516Result := C[AIndex];2517end;2518
2519function TMatrix4.GetComponent(const AColumn, ARow: Integer): Single;2520begin
2521Assert((AColumn >= 0) and (AColumn < 4));2522Assert((ARow >= 0) and (ARow < 4));2523Result := M[AColumn, ARow];2524end;2525
2526procedure TMatrix4.Init(const AColumn0, AColumn1, AColumn2, AColumn3: TVector4);2527begin
2528C[0] := AColumn0;2529C[1] := AColumn1;2530C[2] := AColumn2;2531C[3] := AColumn3;2532end;2533
2534procedure TMatrix4.InitOrthoLH(const AWidth, AHeight, AZNearPlane,2535AZFarPlane: Single);2536begin
2537C[0].Init(2 / AWidth, 0, 0, 0);2538C[1].Init(0, 2 / AHeight, 0, 0);2539C[2].Init(0, 0, 2 / (AZFarPlane - AZNearPlane), 0);2540C[3].Init(-1, -1, -(AZFarPlane + AZNearPlane) / (AZFarPlane - AZNearPlane), 1);2541end;2542
2543procedure TMatrix4.InitOrthoRH(const AWidth, AHeight, AZNearPlane,2544AZFarPlane: Single);2545begin
2546C[0].Init(2 / AWidth, 0, 0, 0);2547C[1].Init(0, 2 / AHeight, 0, 0);2548C[2].Init(0, 0, -2 / (AZFarPlane - AZNearPlane), 0);2549C[3].Init(-1, -1, -(AZFarPlane + AZNearPlane) / (AZFarPlane - AZNearPlane), 1);2550end;2551
2552procedure TMatrix4.InitOrthoOffCenterLH(const ALeft, ATop, ARight, ABottom,2553AZNearPlane, AZFarPlane: Single);2554begin
2555C[0].Init(2 / (ARight - ALeft), 0, 0, 0);2556C[1].Init(0, 2 / (ATop - ABottom), 0, 0);2557C[2].Init(0, 0, 2 / (AZFarPlane - AZNearPlane), 0);2558C[3].Init(-(ALeft + ARight) / (ARight - ALeft),2559-(ATop + ABottom) / (ATop - ABottom),2560-(AZFarPlane + AZNearPlane) / (AZFarPlane - AZNearPlane), 1);2561end;2562
2563procedure TMatrix4.InitOrthoOffCenterRH(const ALeft, ATop, ARight, ABottom,2564AZNearPlane, AZFarPlane: Single);2565begin
2566C[0].Init(2 / (ARight - ALeft), 0, 0, 0);2567C[1].Init(0, 2 / (ATop - ABottom), 0, 0);2568C[2].Init(0, 0, -2 / (AZFarPlane - AZNearPlane), 0);2569C[3].Init(-(ALeft + ARight) / (ARight - ALeft),2570-(ATop + ABottom) / (ATop - ABottom),2571-(AZFarPlane + AZNearPlane) / (AZFarPlane - AZNearPlane), 1);2572end;2573
2574procedure TMatrix4.InitPerspectiveFovLH(const AFieldOfView, AAspectRatio,2575ANearPlaneDistance, AFarPlaneDistance: Single; const AHorizontalFOV: Boolean);2576var
2577XScale, YScale: Single;2578begin
2579if (AHorizontalFOV) then2580begin2581XScale := 1 / FastTan(0.5 * AFieldOfView);2582YScale := XScale / AAspectRatio;2583end2584else2585begin2586YScale := 1 / FastTan(0.5 * AFieldOfView);2587XScale := YScale / AAspectRatio;2588end;2589
2590C[0].Init(XScale, 0, 0, 0);2591C[1].Init(0, YScale, 0, 0);2592C[2].Init(0, 0, (AFarPlaneDistance + ANearPlaneDistance) / (AFarPlaneDistance - ANearPlaneDistance), 1);2593C[3].Init(0, 0, (-2 * ANearPlaneDistance * AFarPlaneDistance) / (AFarPlaneDistance - ANearPlaneDistance), 0);2594end;2595
2596procedure TMatrix4.InitPerspectiveFovRH(const AFieldOfView, AAspectRatio,2597ANearPlaneDistance, AFarPlaneDistance: Single; const AHorizontalFOV: Boolean);2598var
2599XScale, YScale: Single;2600begin
2601if (AHorizontalFOV) then2602begin2603XScale := 1 / FastTan(0.5 * AFieldOfView);2604YScale := XScale / AAspectRatio;2605end2606else2607begin2608YScale := 1 / FastTan(0.5 * AFieldOfView);2609XScale := YScale / AAspectRatio;2610end;2611
2612C[0].Init(XScale, 0, 0, 0);2613C[1].Init(0, YScale, 0, 0);2614C[2].Init(0, 0, -(AFarPlaneDistance + ANearPlaneDistance) / (AFarPlaneDistance - ANearPlaneDistance), -1);2615C[3].Init(0, 0, (-2 * ANearPlaneDistance * AFarPlaneDistance) / (AFarPlaneDistance - ANearPlaneDistance), 0);2616end;2617
2618class operator TMatrix4.Implicit(const A: TMatrix3D): TMatrix4;2619var
2620M: TMatrix4 absolute A;2621begin
2622Result := M.Transpose;2623end;2624
2625class operator TMatrix4.Implicit(const A: TMatrix4): TMatrix3D;2626var
2627M: TMatrix4 absolute Result;2628begin
2629M := A.Transpose;2630end;2631
2632procedure TMatrix4.SetComponent(const AColumn, ARow: Integer; const Value: Single);2633begin
2634Assert((AColumn >= 0) and (AColumn < 4));2635Assert((ARow >= 0) and (ARow < 4));2636M[AColumn, ARow] := Value;2637end;2638
2639procedure TMatrix4.SetColumn(const AIndex: Integer; const Value: TVector4);2640begin
2641Assert((AIndex >= 0) and (AIndex < 4));2642C[AIndex] := Value;2643end;2644{$ELSE}
2645function TMatrix4.GetComponent(const ARow, AColumn: Integer): Single;2646begin
2647Assert((ARow >= 0) and (ARow < 4));2648Assert((AColumn >= 0) and (AColumn < 4));2649Result := M[ARow, AColumn];2650end;2651
2652function TMatrix4.GetRow(const AIndex: Integer): TVector4;2653begin
2654Assert((AIndex >= 0) and (AIndex < 4));2655Result := R[AIndex];2656end;2657
2658procedure TMatrix4.Init(const ARow0, ARow1, ARow2, ARow3: TVector4);2659begin
2660R[0] := ARow0;2661R[1] := ARow1;2662R[2] := ARow2;2663R[3] := ARow3;2664end;2665
2666procedure TMatrix4.InitOrthoLH(const AWidth, AHeight, AZNearPlane,2667AZFarPlane: Single);2668begin
2669R[0].Init(2 / AWidth, 0, 0, 0);2670R[1].Init(0, 2 / AHeight, 0, 0);2671R[2].Init(0, 0, 1 / (AZFarPlane - AZNearPlane), 0);2672R[3].Init(0, AZNearPlane / (AZNearPlane - AZFarPlane), 0, 1);2673end;2674
2675procedure TMatrix4.InitOrthoRH(const AWidth, AHeight, AZNearPlane,2676AZFarPlane: Single);2677begin
2678R[0].Init(2 / AWidth, 0, 0, 0);2679R[1].Init(0, 2 / AHeight, 0, 0);2680R[2].Init(0, 0, 1 / (AZNearPlane - AZFarPlane), 0);2681R[3].Init(0, AZNearPlane / (AZNearPlane - AZFarPlane), 0, 1);2682end;2683
2684procedure TMatrix4.InitOrthoOffCenterLH(const ALeft, ATop, ARight, ABottom,2685AZNearPlane, AZFarPlane: Single);2686begin
2687R[0].Init(2 / (ARight - ALeft), 0, 0, 0);2688R[1].Init(0, 2 / (ATop - ABottom), 0, 0);2689R[2].Init(0, 0, 1 / (AZFarPlane - AZNearPlane), 0);2690R[3].Init((ALeft + ARight) / (ALeft - ARight),2691(ATop + ABottom) / (ABottom - ATop),2692AZNearPlane / (AZNearPlane - AZFarPlane), 1);2693end;2694
2695procedure TMatrix4.InitOrthoOffCenterRH(const ALeft, ATop, ARight, ABottom,2696AZNearPlane, AZFarPlane: Single);2697begin
2698R[0].Init(2 / (ARight - ALeft), 0, 0, 0);2699R[1].Init(0, 2 / (ATop - ABottom), 0, 0);2700R[2].Init(0, 0, 1 / (AZNearPlane - AZFarPlane), 0);2701R[3].Init((ALeft + ARight) / (ALeft - ARight),2702(ATop + ABottom) / (ABottom - ATop),2703AZNearPlane / (AZNearPlane - AZFarPlane), 1);2704end;2705
2706procedure TMatrix4.InitPerspectiveFovLH(const AFieldOfView, AAspectRatio,2707ANearPlaneDistance, AFarPlaneDistance: Single; const AHorizontalFOV: Boolean);2708var
2709XScale, YScale: Single;2710begin
2711if (AHorizontalFOV) then2712begin2713XScale := 1 / FastTan(0.5 * AFieldOfView);2714YScale := XScale / AAspectRatio;2715end2716else2717begin2718YScale := 1 / FastTan(0.5 * AFieldOfView);2719XScale := YScale / AAspectRatio;2720end;2721
2722R[0].Init(XScale, 0, 0, 0);2723R[1].Init(0, YScale, 0, 0);2724R[2].Init(0, 0, AFarPlaneDistance / (AFarPlaneDistance - ANearPlaneDistance), 1);2725R[3].Init(0, 0, (-ANearPlaneDistance * AFarPlaneDistance) / (AFarPlaneDistance - ANearPlaneDistance), 0);2726end;2727
2728procedure TMatrix4.InitPerspectiveFovRH(const AFieldOfView, AAspectRatio,2729ANearPlaneDistance, AFarPlaneDistance: Single; const AHorizontalFOV: Boolean);2730var
2731XScale, YScale: Single;2732begin
2733if (AHorizontalFOV) then2734begin2735XScale := 1 / FastTan(0.5 * AFieldOfView);2736YScale := XScale / AAspectRatio;2737end2738else2739begin2740YScale := 1 / FastTan(0.5 * AFieldOfView);2741XScale := YScale / AAspectRatio;2742end;2743
2744R[0].Init(XScale, 0, 0, 0);2745R[1].Init(0, YScale, 0, 0);2746R[2].Init(0, 0, AFarPlaneDistance / (ANearPlaneDistance - AFarPlaneDistance), -1);2747R[3].Init(0, 0, (ANearPlaneDistance * AFarPlaneDistance) / (ANearPlaneDistance - AFarPlaneDistance), 0);2748end;2749
2750procedure TMatrix4.SetComponent(const ARow, AColumn: Integer; const Value: Single);2751begin
2752Assert((ARow >= 0) and (ARow < 4));2753Assert((AColumn >= 0) and (AColumn < 4));2754M[ARow, AColumn] := Value;2755end;2756
2757class operator TMatrix4.Implicit(const A: TMatrix3D): TMatrix4;2758begin
2759Move(A, Result, SizeOf(TMatrix4));2760end;2761
2762class operator TMatrix4.Implicit(const A: TMatrix4): TMatrix3D;2763begin
2764Move(A, Result, SizeOf(TMatrix4));2765end;2766
2767procedure TMatrix4.SetRow(const AIndex: Integer; const Value: TVector4);2768begin
2769Assert((AIndex >= 0) and (AIndex < 4));2770R[AIndex] := Value;2771end;2772{$ENDIF}
2773
2774{ _TMatrix2Helper }
2775
2776procedure _TMatrix2Helper.Init(const AMatrix: TMatrix3);2777begin
2778V[0].Init(AMatrix.V[0].X, AMatrix.V[0].Y);2779V[1].Init(AMatrix.V[1].X, AMatrix.V[1].Y);2780end;2781
2782procedure _TMatrix2Helper.Init(const AMatrix: TMatrix4);2783begin
2784V[0].Init(AMatrix.V[0].X, AMatrix.V[0].Y);2785V[1].Init(AMatrix.V[1].X, AMatrix.V[1].Y);2786end;2787
2788{ _TMatrix3Helper }
2789
2790procedure _TMatrix3Helper.Init(const AMatrix: TMatrix4);2791begin
2792V[0].Init(AMatrix.V[0].X, AMatrix.V[0].Y, AMatrix.V[0].Z);2793V[1].Init(AMatrix.V[1].X, AMatrix.V[1].Y, AMatrix.V[1].Z);2794V[2].Init(AMatrix.V[2].X, AMatrix.V[2].Y, AMatrix.V[2].Z);2795end;2796
2797{ TIVector2 }
2798
2799class operator TIVector2.Add(const A: TIVector2; const B: Integer): TIVector2;2800begin
2801Result.X := A.X + B;2802Result.Y := A.Y + B;2803end;2804
2805class operator TIVector2.Add(const A: Integer; const B: TIVector2): TIVector2;2806begin
2807Result.X := A + B.X;2808Result.Y := A + B.Y;2809end;2810
2811class operator TIVector2.Add(const A, B: TIVector2): TIVector2;2812begin
2813Result.X := A.X + B.X;2814Result.Y := A.Y + B.Y;2815end;2816
2817class operator TIVector2.Equal(const A, B: TIVector2): Boolean;2818begin
2819Result := (A.X = B.X) and (A.Y = B.Y);2820end;2821
2822function TIVector2.GetComponent(const AIndex: Integer): Integer;2823begin
2824Assert((AIndex >= 0) and (AIndex < 2));2825Result := C[AIndex];2826end;2827
2828class operator TIVector2.Implicit(const A: TPoint): TIVector2;2829begin
2830Result.X := A.X;2831Result.Y := A.Y;2832end;2833
2834class operator TIVector2.Implicit(const A: TIVector2): TPoint;2835begin
2836Result.X := A.X;2837Result.Y := A.Y;2838end;2839
2840procedure TIVector2.Init;2841begin
2842X := 0;2843Y := 0;2844end;2845
2846procedure TIVector2.Init(const A: Integer);2847begin
2848X := A;2849Y := A;2850end;2851
2852procedure TIVector2.Init(const A1, A2: Integer);2853begin
2854X := A1;2855Y := A2;2856end;2857
2858class operator TIVector2.IntDivide(const A: TIVector2; const B: Integer): TIVector2;2859begin
2860Result.X := A.X div B;2861Result.Y := A.Y div B;2862end;2863
2864class operator TIVector2.IntDivide(const A: Integer; const B: TIVector2): TIVector2;2865begin
2866Result.X := A div B.X;2867Result.Y := A div B.Y;2868end;2869
2870class operator TIVector2.IntDivide(const A, B: TIVector2): TIVector2;2871begin
2872Result.X := A.X div B.X;2873Result.Y := A.Y div B.Y;2874end;2875
2876function TIVector2.IsZero: Boolean;2877begin
2878Result := (X = 0) and (Y = 0);2879end;2880
2881class operator TIVector2.Multiply(const A: TIVector2; const B: Integer): TIVector2;2882begin
2883Result.X := A.X * B;2884Result.Y := A.Y * B;2885end;2886
2887class operator TIVector2.Multiply(const A: Integer; const B: TIVector2): TIVector2;2888begin
2889Result.X := A * B.X;2890Result.Y := A * B.Y;2891end;2892
2893class operator TIVector2.Multiply(const A, B: TIVector2): TIVector2;2894begin
2895Result.X := A.X * B.X;2896Result.Y := A.Y * B.Y;2897end;2898
2899class operator TIVector2.Negative(const A: TIVector2): TIVector2;2900begin
2901Result.X := -A.X;2902Result.Y := -A.Y;2903end;2904
2905class operator TIVector2.NotEqual(const A, B: TIVector2): Boolean;2906begin
2907Result := (A.X <> B.X) or (A.Y <> B.Y);2908end;2909
2910procedure TIVector2.SetComponent(const AIndex: Integer; const Value: Integer);2911begin
2912Assert((AIndex >= 0) and (AIndex < 2));2913C[AIndex] := Value;2914end;2915
2916class operator TIVector2.Subtract(const A: TIVector2; const B: Integer): TIVector2;2917begin
2918Result.X := A.X - B;2919Result.Y := A.Y - B;2920end;2921
2922class operator TIVector2.Subtract(const A: Integer; const B: TIVector2): TIVector2;2923begin
2924Result.X := A - B.X;2925Result.Y := A - B.Y;2926end;2927
2928class operator TIVector2.Subtract(const A, B: TIVector2): TIVector2;2929begin
2930Result.X := A.X - B.X;2931Result.Y := A.Y - B.Y;2932end;2933
2934{ TIVector3 }
2935
2936class operator TIVector3.Add(const A: TIVector3; const B: Integer): TIVector3;2937begin
2938Result.X := A.X + B;2939Result.Y := A.Y + B;2940Result.Z := A.Z + B;2941end;2942
2943class operator TIVector3.Add(const A: Integer; const B: TIVector3): TIVector3;2944begin
2945Result.X := A + B.X;2946Result.Y := A + B.Y;2947Result.Z := A + B.Z;2948end;2949
2950class operator TIVector3.Add(const A, B: TIVector3): TIVector3;2951begin
2952Result.X := A.X + B.X;2953Result.Y := A.Y + B.Y;2954Result.Z := A.Z + B.Z;2955end;2956
2957class operator TIVector3.Equal(const A, B: TIVector3): Boolean;2958begin
2959Result := (A.X = B.X) and (A.Y = B.Y) and (A.Z = B.Z);2960end;2961
2962function TIVector3.GetComponent(const AIndex: Integer): Integer;2963begin
2964Assert((AIndex >= 0) and (AIndex < 3));2965Result := C[AIndex];2966end;2967
2968procedure TIVector3.Init(const A: Integer);2969begin
2970X := A;2971Y := A;2972Z := A;2973end;2974
2975procedure TIVector3.Init;2976begin
2977X := 0;2978Y := 0;2979Z := 0;2980end;2981
2982procedure TIVector3.Init(const A1, A2, A3: Integer);2983begin
2984X := A1;2985Y := A2;2986Z := A3;2987end;2988
2989class operator TIVector3.IntDivide(const A: TIVector3; const B: Integer): TIVector3;2990begin
2991Result.X := A.X div B;2992Result.Y := A.Y div B;2993Result.Z := A.Z div B;2994end;2995
2996class operator TIVector3.IntDivide(const A: Integer; const B: TIVector3): TIVector3;2997begin
2998Result.X := A div B.X;2999Result.Y := A div B.Y;3000Result.Z := A div B.Z;3001end;3002
3003class operator TIVector3.IntDivide(const A, B: TIVector3): TIVector3;3004begin
3005Result.X := A.X div B.X;3006Result.Y := A.Y div B.Y;3007Result.Z := A.Z div B.Z;3008end;3009
3010function TIVector3.IsZero: Boolean;3011begin
3012Result := (X = 0) and (Y = 0) and (Z = 0);3013end;3014
3015class operator TIVector3.Multiply(const A: TIVector3; const B: Integer): TIVector3;3016begin
3017Result.X := A.X * B;3018Result.Y := A.Y * B;3019Result.Z := A.Z * B;3020end;3021
3022class operator TIVector3.Multiply(const A: Integer; const B: TIVector3): TIVector3;3023begin
3024Result.X := A * B.X;3025Result.Y := A * B.Y;3026Result.Z := A * B.Z;3027end;3028
3029class operator TIVector3.Multiply(const A, B: TIVector3): TIVector3;3030begin
3031Result.X := A.X * B.X;3032Result.Y := A.Y * B.Y;3033Result.Z := A.Z * B.Z;3034end;3035
3036class operator TIVector3.Negative(const A: TIVector3): TIVector3;3037begin
3038Result.X := -A.X;3039Result.Y := -A.Y;3040Result.Z := -A.Z;3041end;3042
3043class operator TIVector3.NotEqual(const A, B: TIVector3): Boolean;3044begin
3045Result := (A.X <> B.X) or (A.Y <> B.Y) or (A.Z <> B.Z);3046end;3047
3048procedure TIVector3.SetComponent(const AIndex: Integer; const Value: Integer);3049begin
3050Assert((AIndex >= 0) and (AIndex < 3));3051C[AIndex] := Value;3052end;3053
3054class operator TIVector3.Subtract(const A: TIVector3; const B: Integer): TIVector3;3055begin
3056Result.X := A.X - B;3057Result.Y := A.Y - B;3058Result.Z := A.Z - B;3059end;3060
3061class operator TIVector3.Subtract(const A: Integer; const B: TIVector3): TIVector3;3062begin
3063Result.X := A - B.X;3064Result.Y := A - B.Y;3065Result.Z := A - B.Z;3066end;3067
3068class operator TIVector3.Subtract(const A, B: TIVector3): TIVector3;3069begin
3070Result.X := A.X - B.X;3071Result.Y := A.Y - B.Y;3072Result.Z := A.Z - B.Z;3073end;3074
3075{ TIVector4 }
3076
3077class operator TIVector4.Add(const A: TIVector4; const B: Integer): TIVector4;3078begin
3079Result.X := A.X + B;3080Result.Y := A.Y + B;3081Result.Z := A.Z + B;3082Result.W := A.W + B;3083end;3084
3085class operator TIVector4.Add(const A: Integer; const B: TIVector4): TIVector4;3086begin
3087Result.X := A + B.X;3088Result.Y := A + B.Y;3089Result.Z := A + B.Z;3090Result.W := A + B.W;3091end;3092
3093class operator TIVector4.Add(const A, B: TIVector4): TIVector4;3094begin
3095Result.X := A.X + B.X;3096Result.Y := A.Y + B.Y;3097Result.Z := A.Z + B.Z;3098Result.W := A.W + B.W;3099end;3100
3101class operator TIVector4.Equal(const A, B: TIVector4): Boolean;3102begin
3103Result := (A.X = B.X) and (A.Y = B.Y) and (A.Z = B.Z) and (A.W = B.W);3104end;3105
3106function TIVector4.GetComponent(const AIndex: Integer): Integer;3107begin
3108Assert((AIndex >= 0) and (AIndex < 4));3109Result := C[AIndex];3110end;3111
3112procedure TIVector4.Init(const A1, A2, A3, A4: Integer);3113begin
3114X := A1;3115Y := A2;3116Z := A3;3117W := A4;3118end;3119
3120procedure TIVector4.Init(const A: Integer);3121begin
3122X := A;3123Y := A;3124Z := A;3125W := A;3126end;3127
3128procedure TIVector4.Init;3129begin
3130X := 0;3131Y := 0;3132Z := 0;3133W := 0;3134end;3135
3136class operator TIVector4.IntDivide(const A: TIVector4; const B: Integer): TIVector4;3137begin
3138Result.X := A.X div B;3139Result.Y := A.Y div B;3140Result.Z := A.Z div B;3141Result.W := A.W div B;3142end;3143
3144class operator TIVector4.IntDivide(const A: Integer; const B: TIVector4): TIVector4;3145begin
3146Result.X := A div B.X;3147Result.Y := A div B.Y;3148Result.Z := A div B.Z;3149Result.W := A div B.W;3150end;3151
3152class operator TIVector4.IntDivide(const A, B: TIVector4): TIVector4;3153begin
3154Result.X := A.X div B.X;3155Result.Y := A.Y div B.Y;3156Result.Z := A.Z div B.Z;3157Result.W := A.W div B.W;3158end;3159
3160function TIVector4.IsZero: Boolean;3161begin
3162Result := (X = 0) and (Y = 0) and (Z = 0) and (W = 0);3163end;3164
3165class operator TIVector4.Multiply(const A: TIVector4; const B: Integer): TIVector4;3166begin
3167Result.X := A.X * B;3168Result.Y := A.Y * B;3169Result.Z := A.Z * B;3170Result.W := A.W * B;3171end;3172
3173class operator TIVector4.Multiply(const A: Integer; const B: TIVector4): TIVector4;3174begin
3175Result.X := A * B.X;3176Result.Y := A * B.Y;3177Result.Z := A * B.Z;3178Result.W := A * B.W;3179end;3180
3181class operator TIVector4.Multiply(const A, B: TIVector4): TIVector4;3182begin
3183Result.X := A.X * B.X;3184Result.Y := A.Y * B.Y;3185Result.Z := A.Z * B.Z;3186Result.W := A.W * B.W;3187end;3188
3189class operator TIVector4.Negative(const A: TIVector4): TIVector4;3190begin
3191Result.X := -A.X;3192Result.Y := -A.Y;3193Result.Z := -A.Z;3194Result.W := -A.W;3195end;3196
3197class operator TIVector4.NotEqual(const A, B: TIVector4): Boolean;3198begin
3199Result := (A.X <> B.X) or (A.Y <> B.Y) or (A.Z <> B.Z) or (A.W <> B.W);3200end;3201
3202procedure TIVector4.SetComponent(const AIndex: Integer; const Value: Integer);3203begin
3204Assert((AIndex >= 0) and (AIndex < 4));3205C[AIndex] := Value;3206end;3207
3208class operator TIVector4.Subtract(const A: TIVector4; const B: Integer): TIVector4;3209begin
3210Result.X := A.X - B;3211Result.Y := A.Y - B;3212Result.Z := A.Z - B;3213Result.W := A.W - B;3214end;3215
3216class operator TIVector4.Subtract(const A: Integer; const B: TIVector4): TIVector4;3217begin
3218Result.X := A - B.X;3219Result.Y := A - B.Y;3220Result.Z := A - B.Z;3221Result.W := A - B.W;3222end;3223
3224class operator TIVector4.Subtract(const A, B: TIVector4): TIVector4;3225begin
3226Result.X := A.X - B.X;3227Result.Y := A.Y - B.Y;3228Result.Z := A.Z - B.Z;3229Result.W := A.W - B.W;3230end;3231
3232