MathgeomGLS
4846 строк · 178.6 Кб
1unit Neslib.FastMath;2{< Fast Math Library for Delphi.
3
4You can set these conditional defines to modify the behavior of this library:
5* FM_COLUMN_MAJOR: Store matrices in column-major order. Be default, matrices
6are store in row-major order for compatibility with the Delphi RTL. However,
7for OpenGL applications, it makes more sense to store matrices in column-
8major order. Another side effect of this define is that the depth of camera
9matrices are clipped to -1..1 (common with OpenGL) instead of 0..1 (uses
10by the Delphi RTL).
11* FM_NOSIMD: Disable SIMD (SSE2, NEON, ARM64) optimizations and run all
12calculations using Pascal code only. You will generally only enable this
13define for (performance) testing, or when running on an old PC that does
14not have support for SSE2. }
15
16{ Copyright (c) 2016 by Erik van Bilsen
17All rights reserved.
18
19Redistribution and use in source and binary forms, with or without
20modification, are permitted provided that the following conditions are met:
21
221. Redistributions of source code must retain the above copyright notice, this
23list of conditions and the following disclaimer.
242. Redistributions in binary form must reproduce the above copyright notice,
25this list of conditions and the following disclaimer in the documentation
26and/or other materials provided with the distribution.
27
28THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
29ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
30WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
32ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
34LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
35ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. }
38
39{$INCLUDE 'Neslib.FastMath.inc'}
40
41interface
42
43uses
44System.Math,45System.Math.Vectors,46System.Types;47
48const
49{ Default tolerance for comparing small floating-point values. }50SINGLE_TOLERANCE = 0.000001;51
52type
53{ A 2-dimensional vector. Can be used to represent points or vectors in542D space, using the X and Y fields. You can also use it to represent
55texture coordinates, by using S and T (these are just aliases for X and Y).
56It can also be used to group 2 arbitrary values together in an array (using
57C[0] and C[1], which are also just aliases for X and Y).
58
59TVector2 is compatible with TPointF in the Delphi RTL. You can typecast
60between these two types or implicitly convert from one to the other through
61assignment (eg. MyVector2 := MyPointF). }
62TVector2 = record63{$REGION 'Internal Declarations'}64private65function GetComponent(const AIndex: Integer): Single; inline;66procedure SetComponent(const AIndex: Integer; const Value: Single); inline;67function GetLength: Single; inline;68procedure SetLength(const AValue: Single); inline;69function GetLengthSquared: Single; inline;70procedure SetLengthSquared(const AValue: Single); inline;71function GetAngle: Single; inline;72procedure SetAngle(const AValue: Single); inline;73{$ENDREGION 'Internal Declarations'}74public75{ Sets the two elements (X and Y) to 0. }76procedure Init; overload; inline;77
78{ Sets the two elements (X and Y) to A.79
80Parameters:
81A: the value to set the two elements to. }
82procedure Init(const A: Single); overload; inline;83
84{ Sets the two elements (X and Y) to A1 and A2 respectively.85
86Parameters:
87A1: the value to set the first element to.
88A2: the value to set the second element to. }
89procedure Init(const A1, A2: Single); overload; inline;90
91{ Converts a TPoint to a TVector2.92
93Parameters:
94APoint: the TPoint to convert. }
95procedure Init(const APoint: TPoint); overload; inline;96
97{ Implicitly converts a TPointF to a TVector2. }98class operator Implicit(const A: TPointF): TVector2; inline;99
100{ Implicitly converts a TVector2 to a TPointF. }101class operator Implicit(const A: TVector2): TPointF; inline;102
103{ Checks two vectors for equality.104
105Returns:
106True if the two vectors match each other exactly. }
107class operator Equal(const A, B: TVector2): Boolean; inline;108
109{ Checks two vectors for inequality.110
111Returns:
112True if the two vectors are not equal. }
113class operator NotEqual(const A, B: TVector2): Boolean; inline;114
115{ Negates a vector.116
117Returns:
118The negative value of a vector (eg. (-A.X, -A.Y)) }
119class operator Negative(const A: TVector2): TVector2; {$IF Defined(FM_INLINE) or Defined(CPUX64)}inline;{$ENDIF}120
121{ Adds a scalar value to a vector.122
123Returns:
124(A.X + B, A.Y + B) }
125class operator Add(const A: TVector2; const B: Single): TVector2; inline;126
127{ Adds a vector to a scalar value.128
129Returns:
130(A + B.X, A + B.Y) }
131class operator Add(const A: Single; const B: TVector2): TVector2; inline;132
133{ Adds two vectors.134
135Returns:
136(A.X + B.X, A.Y + B.Y) }
137class operator Add(const A, B: TVector2): TVector2; {$IF Defined(FM_INLINE) or Defined(CPUX64)}inline;{$ENDIF}138
139{ Subtracts a scalar value from a vector.140
141Returns:
142(A.X - B, A.Y - B) }
143class operator Subtract(const A: TVector2; const B: Single): TVector2; inline;144
145{ Subtracts a vector from a scalar value.146
147Returns:
148(A - B.X, A - B.Y) }
149class operator Subtract(const A: Single; const B: TVector2): TVector2; inline;150
151{ Subtracts two vectors.152
153Returns:
154(A.X - B.X, A.Y - B.Y) }
155class operator Subtract(const A, B: TVector2): TVector2; {$IF Defined(FM_INLINE) or Defined(CPUX64)}inline;{$ENDIF}156
157{ Multiplies a vector with a scalar value.158
159Returns:
160(A.X * B, A.Y * B) }
161class operator Multiply(const A: TVector2; const B: Single): TVector2; inline;162
163{ Multiplies a scalar value with a vector.164
165Returns:
166(A * B.X, A * B.Y) }
167class operator Multiply(const A: Single; const B: TVector2): TVector2; inline;168
169{ Multiplies two vectors component-wise.170To calculate a dot or cross product instead, use the Dot or Cross function.
171
172Returns:
173(A.X * B.X, A.Y * B.Y) }
174class operator Multiply(const A, B: TVector2): TVector2; {$IF Defined(FM_INLINE) or Defined(CPUX64)}inline;{$ENDIF}175
176{ Divides a vector by a scalar value.177
178Returns:
179(A.X / B, A.Y / B) }
180class operator Divide(const A: TVector2; const B: Single): TVector2; {$IF Defined(FM_INLINE) or Defined(CPUX86)}inline;{$ENDIF}181
182{ Divides a scalar value by a vector.183
184Returns:
185(A / B.X, A / B.Y) }
186class operator Divide(const A: Single; const B: TVector2): TVector2; {$IFDEF FM_INLINE}inline;{$ENDIF}187
188{ Divides two vectors component-wise.189
190Returns:
191(A.X / B.X, A.Y / B.Y) }
192class operator Divide(const A, B: TVector2): TVector2; {$IFDEF FM_INLINE}inline;{$ENDIF}193
194{ Whether this vector equals another vector, within a certain tolerance.195
196Parameters:
197AOther: the other vector.
198ATolerance: (optional) tolerance. If not specified, a small tolerance
199is used.
200
201Returns:
202True if both vectors are equal (within the given tolerance). }
203function Equals(const AOther: TVector2; const ATolerance: Single = SINGLE_TOLERANCE): Boolean; inline;204
205{ Calculates the distance between this vector and another vector.206
207Parameters:
208AOther: the other vector.
209
210Returns:
211The distance between this vector and AOther.
212
213@bold(Note): If you only want to compare distances, you should use
214DistanceSquared instead, which is faster. }
215function Distance(const AOther: TVector2): Single; inline;216
217{ Calculates the squared distance between this vector and another vector.218
219Parameters:
220AOther: the other vector.
221
222Returns:
223The squared distance between this vector and AOther. }
224function DistanceSquared(const AOther: TVector2): Single; inline;225
226{ Calculates the dot product between this vector and another vector.227
228Parameters:
229AOther: the other vector.
230
231Returns:
232The dot product between this vector and AOther. }
233function Dot(const AOther: TVector2): Single; {$IFDEF FM_INLINE}inline;{$ENDIF}234
235{ Calculates the cross product between this vector and another vector.236
237Parameters:
238AOther: the other vector.
239
240Returns:
241The cross product between this vector and AOther. }
242function Cross(const AOther: TVector2): Single; {$IFDEF FM_INLINE}inline;{$ENDIF}243
244{ Offsets this vector in a certain direction.245
246Parameters:
247ADeltaX: the delta X direction.
248ADeltaY: the delta Y direction. }
249procedure Offset(const ADeltaX, ADeltaY: Single); overload; inline;250
251{ Offsets this vector in a certain direction.252
253Parameters:
254ADelta: the delta.
255
256@bold(Note): this is equivalent to adding two vectors together. }
257procedure Offset(const ADelta: TVector2); overload; inline;258
259{ Calculates a normalized version of this vector.260
261Returns:
262The normalized version of of this vector. That is, a vector in the same
263direction as A, but with a length of 1.
264
265@bold(Note): for a faster, less accurate version, use NormalizeFast.
266
267@bold(Note): Does not change this vector. To update this vector itself,
268use SetNormalized. }
269function Normalize: TVector2; inline;270
271{ Normalizes this vector. This is, keep the current direction, but set the272length to 1.
273
274@bold(Note): The SIMD optimized versions of this method use an
275approximation, resulting in a very small error.
276
277@bold(Note): If you do not want to change this vector, but get a
278normalized version instead, then use Normalize. }
279procedure SetNormalized; inline;280
281{ Calculates a normalized version of this vector.282
283Returns:
284The normalized version of of this vector. That is, a vector in the same
285direction as A, but with a length of 1.
286
287@bold(Note): this is an SIMD optimized version that uses an approximation,
288resulting in a small error. For an accurate version, use Normalize.
289
290@bold(Note): Does not change this vector. To update this vector itself,
291use SetNormalizedFast. }
292function NormalizeFast: TVector2; {$IFDEF FM_INLINE}inline;{$ENDIF}293
294{ Normalizes this vector. This is, keep the current direction, but set the295length to 1.
296
297@bold(Note): this is an SIMD optimized version that uses an approximation,
298resulting in a small error. For an accurate version, use SetNormalized.
299
300@bold(Note): If you do not want to change this vector, but get a
301normalized version instead, then use NormalizeFast. }
302procedure SetNormalizedFast; {$IFDEF FM_INLINE}inline;{$ENDIF}303
304{ Calculates a vector pointing in the same direction as this vector.305
306Parameters:
307I: the incident vector.
308NRef: the reference vector.
309
310Returns:
311A vector that points away from the surface as defined by its normal. If
312NRef.Dot(I) < 0 then it returns this vector, otherwise it returns the
313negative of this vector. }
314function FaceForward(const I, NRef: TVector2): TVector2; inline;315
316{ Calculates the reflection direction for this (incident) vector.317
318Parameters:
319N: the normal vector. Should be normalized in order to achieve the desired
320result.
321
322Returns:
323The reflection direction calculated as Self - 2 * N.Dot(Self) * N. }
324function Reflect(const N: TVector2): TVector2; inline;325
326{ Calculates the refraction direction for this (incident) vector.327
328Parameters:
329N: the normal vector. Should be normalized in order to achieve the
330desired result.
331Eta: the ratio of indices of refraction.
332
333Returns:
334The refraction vector.
335
336@bold(Note): This vector should be normalized in order to achieve the
337desired result.}
338function Refract(const N: TVector2; const Eta: Single): TVector2; inline;339
340{ Creates a vector with the same direction as this vector, but with the341length limited, based on the desired maximum length.
342
343Parameters:
344AMaxLength: The desired maximum length of the vector.
345
346Returns:
347A length-limited version of this vector.
348
349@bold(Note): Does not change this vector. To update this vector itself,
350use SetLimit. }
351function Limit(const AMaxLength: Single): TVector2; inline;352
353{ Limits the length of this vector, based on the desired maximum length.354
355Parameters:
356AMaxLength: The desired maximum length of this vector.
357
358@bold(Note): If you do not want to change this vector, but get a
359length-limited version instead, then use Limit. }
360procedure SetLimit(const AMaxLength: Single); inline;361
362{ Creates a vector with the same direction as this vector, but with the363length limited, based on the desired squared maximum length.
364
365Parameters:
366AMaxLengthSquared: The desired squared maximum length of the vector.
367
368Returns:
369A length-limited version of this vector.
370
371@bold(Note): Does not change this vector. To update this vector itself,
372use SetLimitSquared. }
373function LimitSquared(const AMaxLengthSquared: Single): TVector2;374
375{ Limits the length of this vector, based on the desired squared maximum376length.
377
378Parameters:
379AMaxLengthSquared: The desired squared maximum length of this vector.
380
381@bold(Note): If you do not want to change this vector, but get a
382length-limited version instead, then use LimitSquared. }
383procedure SetLimitSquared(const AMaxLengthSquared: Single); inline;384
385{ Creates a vector with the same direction as this vector, but with the386length clamped between a minimim and maximum length.
387
388Parameters:
389AMinLength: The minimum length of the vector.
390AMaxLength: The maximum length of the vector.
391
392Returns:
393A length-clamped version of this vector.
394
395@bold(Note): Does not change this vector. To update this vector itself,
396use SetClamped. }
397function Clamp(const AMinLength, AMaxLength: Single): TVector2;398
399{ Clamps the length of this vector between a minimim and maximum length.400
401Parameters:
402AMinLength: The minimum length of this vector.
403AMaxLength: The maximum length of this vector.
404
405@bold(Note): If you do not want to change this vector, but get a
406length-clamped version instead, then use Clamp. }
407procedure SetClamped(const AMinLength, AMaxLength: Single); inline;408
409{ Creates a vector by rotating this vector counter-clockwise.410
411AParameters:
412ARadians: the rotation angle in radians, counter-clockwise assuming the
413Y-axis points up.
414
415Returns:
416A rotated version version of this vector.
417
418@bold(Note): Does not change this vector. To update this vector itself,
419use SetRotated. }
420function Rotate(const ARadians: Single): TVector2;421
422{ Rotates this vector counter-clockwise.423
424AParameters:
425ARadians: the rotation angle in radians, counter-clockwise assuming the
426Y-axis points up.
427
428@bold(Note): If you do not want to change this vector, but get a
429rotated version instead, then use Rotate. }
430procedure SetRotated(const ARadians: Single); inline;431
432{ Creates a vector by rotating this vector 90 degrees counter-clockwise.433
434Returns:
435A rotated version version of this vector.
436
437@bold(Note): Does not change this vector. To update this vector itself,
438use SetRotated90CCW. }
439function Rotate90CCW: TVector2;440
441{ Rotates this vector 90 degrees counter-clockwise.442
443@bold(Note): If you do not want to change this vector, but get a
444rotated version instead, then use Rotate90CCW. }
445procedure SetRotated90CCW; inline;446
447{ Creates a vector by rotating this vector 90 degrees clockwise.448
449Returns:
450A rotated version version of this vector.
451
452@bold(Note): Does not change this vector. To update this vector itself,
453use SetRotated90CW. }
454function Rotate90CW: TVector2;455
456{ Rotates this vector 90 degrees clockwise.457
458@bold(Note): If you do not want to change this vector, but get a
459rotated version instead, then use Rotate90CW. }
460procedure SetRotated90CW; inline;461
462{ Calculates the angle in radians to rotate this vector/point to a target463vector. Angles are towards the positive Y-axis (counter-clockwise).
464
465Parameters:
466ATarget: the target vector.
467
468Returns:
469The angle in radians to the target vector, in the range -Pi to Pi. }
470function AngleTo(const ATarget: TVector2): Single;471
472{ Linearly interpolates between this vector and a target vector.473
474Parameters:
475ATarget: the target vector.
476AAlpha: the interpolation coefficient (between 0.0 and 1.0).
477
478Returns:
479The interpolation result vector.
480
481@bold(Note): Does not change this vector. To update this vector itself,
482use SetLerp. }
483function Lerp(const ATarget: TVector2; const AAlpha: Single): TVector2; inline;484
485{ Linearly interpolates between this vector and a target vector and stores486the result in this vector.
487
488Parameters:
489ATarget: the target vector.
490AAlpha: the interpolation coefficient (between 0.0 and 1.0).
491
492@bold(Note): If you do not want to change this vector, but get an
493interpolated version instead, then use Lerp. }
494procedure SetLerp(const ATarget: TVector2; const AAlpha: Single); inline;495
496{ Whether the vector is normalized (within a small margin of error).497
498Returns:
499True if the length of the vector is (very close to) 1.0 }
500function IsNormalized: Boolean; overload; inline;501
502{ Whether the vector is normalized within a given margin of error.503
504Parameters:
505AErrorMargin: the allowed margin of error.
506
507Returns:
508True if the squared length of the vector is 1.0 within the margin of
509error. }
510function IsNormalized(const AErrorMargin: Single): Boolean; overload;511
512{ Whether this is a zero vector.513
514Returns:
515True if X and Y are exactly 0.0 }
516function IsZero: Boolean; overload; inline;517
518{ Whether this is a zero vector within a given margin of error.519
520Parameters:
521AErrorMargin: the allowed margin of error.
522
523Returns:
524True if the squared length is smaller then the margin of error. }
525function IsZero(const AErrorMargin: Single): Boolean; overload;526
527{ Whether this vector has a similar direction compared to another vector.528
529Parameters:
530AOther: the other vector.
531
532Returns:
533True if the normalized dot product is greater than 0. }
534function HasSameDirection(const AOther: TVector2): Boolean; inline;535
536{ Whether this vector has an opposite direction compared to another vector.537
538Parameters:
539AOther: the other vector.
540
541Returns:
542True if the normalized dot product is less than 0. }
543function HasOppositeDirection(const AOther: TVector2): Boolean; inline;544
545{ Whether this vector runs parallel to another vector (either in the same546or the opposite direction).
547
548Parameters:
549AOther: the other vector.
550ATolerance: (optional) tolerance. If not specified, a small tolerance
551is used.
552
553Returns:
554True if this vector runs parallel to AOther (within the given tolerance)
555
556@bold(Note): every vector is considered to run parallel to a zero vector. }
557function IsParallel(const AOther: TVector2; const ATolerance: Single = SINGLE_TOLERANCE): Boolean;558
559{ Whether this vector is collinear with another vector. Two vectors are560collinear if they run parallel to each other and point in the same
561direction.
562
563Parameters:
564AOther: the other vector.
565ATolerance: (optional) tolerance. If not specified, a small tolerance
566is used.
567
568Returns:
569True if this vector is collinear to AOther (within the given tolerance) }
570function IsCollinear(const AOther: TVector2; const ATolerance: Single = SINGLE_TOLERANCE): Boolean;571
572{ Whether this vector is opposite collinear with another vector. Two vectors573are opposite collinear if they run parallel to each other and point in
574opposite directions.
575
576Parameters:
577AOther: the other vector.
578ATolerance: (optional) tolerance. If not specified, a small tolerance
579is used.
580
581Returns:
582True if this vector is opposite collinear to AOther (within the given
583tolerance) }
584function IsCollinearOpposite(const AOther: TVector2; const ATolerance: Single = SINGLE_TOLERANCE): Boolean;585
586{ Whether this vector is perpendicular to another vector.587
588Parameters:
589AOther: the other vector.
590ATolerance: (optional) tolerance. If not specified, a small tolerance
591is used.
592
593Returns:
594True if this vector is perpendicular to AOther. That is, if the dot
595product is 0 (within the given tolerance) }
596function IsPerpendicular(const AOther: TVector2; const ATolerance: Single = SINGLE_TOLERANCE): Boolean;597
598{ Returns the components of the vector.599This is identical to accessing the C-field, but this property can be used
600as a default array property.
601
602Parameters:
603AIndex: index of the component to return (0 or 1). Range is checked
604with an assertion. }
605property Components[const AIndex: Integer]: Single read GetComponent write SetComponent; default;606
607{ The euclidean length of this vector.608
609@bold(Note): If you only want to compare lengths of vectors, you should
610use LengthSquared instead, which is faster.
611
612@bold(Note): You can also set the length of the vector. In that case, it
613will keep the current direction. }
614property Length: Single read GetLength write SetLength;615
616{ The squared length of the vector.617
618@bold(Note): This property is faster than Length because it avoids
619calculating a square root. It is useful for comparing lengths instead of
620calculating actual lengths.
621
622@bold(Note): You can also set the squared length of the vector. In that
623case, it will keep the current direction. }
624property LengthSquared: Single read GetLengthSquared write SetLengthSquared;625
626{ The angle in radians of this vector/point relative to the X-axis. Angles627are towards the positive Y-axis (counter-clockwise).
628
629When getting the angle, the result will be between -Pi and Pi. }
630property Angle: Single read GetAngle write SetAngle;631public632case Byte of633{ X and Y components of the vector. Aliases for C[0] and C[1]. }6340: (X, Y: Single);635
636{ Red and Green components of the vector. Aliases for C[0] and C[1]. }6371: (R, G: Single);638
639{ S and T components of the vector. Aliases for C[0] and C[1]. }6402: (S, T: Single);641
642{ The two components of the vector. }6433: (C: array [0..1] of Single);644end;645PVector2 = ^TVector2;646
647type
648{ A 3-dimensional vector. Can be used for a variety of purposes:649* To represent points or vectors in 3D space, using the X, Y and Z fields.
650* To represent colors (using the R, G and B fields, which are just aliases
651for X, Y and Z)
652* To represent texture coordinates (S, T and P, again just aliases for X, Y
653and Z).
654* To group 3 arbitrary values together in an array (C[0]..C[2], also just
655aliases for X, Y and Z)
656
657@bold(Note): when possible, use TVector4 instead of TVector3, since TVector4
658has better hardware support. Operations on TVector4 types are usually faster
659than operations on TVector3 types.
660
661TVector3 is compatible with TPoint3D in the Delphi RTL. You can typecast
662between these two types or implicitly convert from one to the other through
663assignment (eg. MyVector3 := MyPoint3D). }
664TVector3 = record665{$REGION 'Internal Declarations'}666private667function GetComponent(const AIndex: Integer): Single; inline;668procedure SetComponent(const AIndex: Integer; const Value: Single); inline;669function GetLength: Single; {$IFDEF FM_INLINE}inline;{$ENDIF}670procedure SetLength(const AValue: Single); inline;671function GetLengthSquared: Single; inline;672procedure SetLengthSquared(const AValue: Single); inline;673{$ENDREGION 'Internal Declarations'}674public675{ Sets the three elements (X, Y and Z) to 0. }676procedure Init; overload; inline;677
678{ Sets the three elements (X, Y and Z) to A.679
680Parameters:
681A: the value to set the three elements to. }
682procedure Init(const A: Single); overload; inline;683
684{ Sets the three elements (X, Y and Z) to A1, A2 and A3 respectively.685
686Parameters:
687A1: the value to set the first element to.
688A2: the value to set the second element to.
689A3: the value to set the third element to. }
690procedure Init(const A1, A2, A3: Single); overload; inline;691
692{ Sets the first two elements from a 2D vector, and the third element from693a scalar.
694
695Parameters:
696A1: the vector to use for the first two elements.
697A2: the value to set the third element to. }
698procedure Init(const A1: TVector2; const A2: Single); overload; inline;699
700{ Sets the first element from a scaler, and the last two elements from a7012D vector.
702
703Parameters:
704A1: the value to set the first element to.
705A2: the vector to use for the last two elements. }
706procedure Init(const A1: Single; const A2: TVector2); overload; inline;707
708{ Implicitly converts a TPoint3D to a TVector3. }709class operator Implicit(const A: TPoint3D): TVector3; inline;710
711{ Implicitly converts a TVector3 to a TPoint3D. }712class operator Implicit(const A: TVector3): TPoint3D; inline;713
714{ Checks two vectors for equality.715
716Returns:
717True if the two vectors match each other exactly. }
718class operator Equal(const A, B: TVector3): Boolean; inline;719
720{ Checks two vectors for inequality.721
722Returns:
723True if the two vectors are not equal. }
724class operator NotEqual(const A, B: TVector3): Boolean; inline;725
726{ Negates a vector.727
728Returns:
729The negative value of a vector (eg. (-A.X, -A.Y, -A.Z)) }
730class operator Negative(const A: TVector3): TVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}731
732{ Adds a scalar value to a vector.733
734Returns:
735(A.X + B, A.Y + B, A.Z + B) }
736class operator Add(const A: TVector3; const B: Single): TVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}737
738{ Adds a vector to a scalar value.739
740Returns:
741(A + B.X, A + B.Y, A + B.Z) }
742class operator Add(const A: Single; const B: TVector3): TVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}743
744{ Adds two vectors.745
746Returns:
747(A.X + B.X, A.Y + B.Y, A.Z + B.Z) }
748class operator Add(const A, B: TVector3): TVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}749
750{ Subtracts a scalar value from a vector.751
752Returns:
753(A.X - B, A.Y - B, A.Z - B) }
754class operator Subtract(const A: TVector3; const B: Single): TVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}755
756{ Subtracts a vector from a scalar value.757
758Returns:
759(A - B.X, A - B.Y, A - B.Z) }
760class operator Subtract(const A: Single; const B: TVector3): TVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}761
762{ Subtracts two vectors.763
764Returns:
765(A.X - B.X, A.Y - B.Y, A.Z - B.Z) }
766class operator Subtract(const A, B: TVector3): TVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}767
768{ Multiplies a vector with a scalar value.769
770Returns:
771(A.X * B, A.Y * B, A.Z * B) }
772class operator Multiply(const A: TVector3; const B: Single): TVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}773
774{ Multiplies a scalar value with a vector.775
776Returns:
777(A * B.X, A * B.Y, A * B.Z) }
778class operator Multiply(const A: Single; const B: TVector3): TVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}779
780{ Multiplies two vectors component-wise.781To calculate a dot or cross product instead, use the Dot or Cross function.
782
783Returns:
784(A.X * B.X, A.Y * B.Y, A.Z * B.Z) }
785class operator Multiply(const A, B: TVector3): TVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}786
787{ Divides a vector by a scalar value.788
789Returns:
790(A.X / B, A.Y / B, A.Z / B) }
791class operator Divide(const A: TVector3; const B: Single): TVector3; inline;792
793{ Divides a scalar value by a vector.794
795Returns:
796(A / B.X, A / B.Y, A / B.Z) }
797class operator Divide(const A: Single; const B: TVector3): TVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}798
799{ Divides two vectors component-wise.800
801Returns:
802(A.X / B.X, A.Y / B.Y, A.Z / B.Z) }
803class operator Divide(const A, B: TVector3): TVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}804
805{ Whether this vector equals another vector, within a certain tolerance.806
807Parameters:
808AOther: the other vector.
809ATolerance: (optional) tolerance. If not specified, a small tolerance
810is used.
811
812Returns:
813True if both vectors are equal (within the given tolerance). }
814function Equals(const AOther: TVector3; const ATolerance: Single = SINGLE_TOLERANCE): Boolean; inline;815
816{ Calculates the distance between this vector and another vector.817
818Parameters:
819AOther: the other vector.
820
821Returns:
822The distance between this vector and AOther.
823
824@bold(Note): If you only want to compare distances, you should use
825DistanceSquared instead, which is faster. }
826function Distance(const AOther: TVector3): Single; {$IFDEF FM_INLINE}inline;{$ENDIF}827
828{ Calculates the squared distance between this vector and another vector.829
830Parameters:
831AOther: the other vector.
832
833Returns:
834The squared distance between this vector and AOther. }
835function DistanceSquared(const AOther: TVector3): Single; {$IFDEF FM_INLINE}inline;{$ENDIF}836
837{ Calculates the dot product between this vector and another vector.838
839Parameters:
840AOther: the other vector.
841
842Returns:
843The dot product between this vector and AOther. }
844function Dot(const AOther: TVector3): Single; inline;845
846{ Calculates the cross product between this vector and another vector.847
848Parameters:
849AOther: the other vector.
850
851Returns:
852The cross product between this vector and AOther. }
853function Cross(const AOther: TVector3): TVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}854
855{ Offsets this vector in a certain direction.856
857Parameters:
858ADeltaX: the delta X direction.
859ADeltaY: the delta Y direction.
860ADeltaZ: the delta Z direction. }
861procedure Offset(const ADeltaX, ADeltaY, ADeltaZ: Single); overload; inline;862
863{ Offsets this vector in a certain direction.864
865Parameters:
866ADelta: the delta.
867
868@bold(Note): this is equivalent to adding two vectors together. }
869procedure Offset(const ADelta: TVector3); overload; inline;870
871
872{ Calculates a normalized version of this vector.873
874Returns:
875The normalized version of of this vector. That is, a vector in the same
876direction as A, but with a length of 1.
877
878@bold(Note): for a faster, less accurate version, use NormalizeFast.
879
880@bold(Note): Does not change this vector. To update this vector itself,
881use SetNormalized. }
882function Normalize: TVector3; inline;883
884{ Normalizes this vector. This is, keep the current direction, but set the885length to 1.
886
887@bold(Note): The SIMD optimized versions of this method use an
888approximation, resulting in a very small error.
889
890@bold(Note): If you do not want to change this vector, but get a
891normalized version instead, then use Normalize. }
892procedure SetNormalized; inline;893
894{ Calculates a normalized version of this vector.895
896Returns:
897The normalized version of of this vector. That is, a vector in the same
898direction as A, but with a length of 1.
899
900@bold(Note): this is an SIMD optimized version that uses an approximation,
901resulting in a small error. For an accurate version, use Normalize.
902
903@bold(Note): Does not change this vector. To update this vector itself,
904use SetNormalizedFast. }
905function NormalizeFast: TVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}906
907{ Normalizes this vector. This is, keep the current direction, but set the908length to 1.
909
910@bold(Note): this is an SIMD optimized version that uses an approximation,
911resulting in a small error. For an accurate version, use SetNormalized.
912
913@bold(Note): If you do not want to change this vector, but get a
914normalized version instead, then use NormalizeFast. }
915procedure SetNormalizedFast; {$IFDEF FM_INLINE}inline;{$ENDIF}916
917{ Calculates a vector pointing in the same direction as this vector.918
919Parameters:
920I: the incident vector.
921NRef: the reference vector.
922
923Returns:
924A vector that points away from the surface as defined by its normal. If
925NRef.Dot(I) < 0 then it returns this vector, otherwise it returns the
926negative of this vector. }
927function FaceForward(const I, NRef: TVector3): TVector3; inline;928
929{ Calculates the reflection direction for this (incident) vector.930
931Parameters:
932N: the normal vector. Should be normalized in order to achieve the desired
933result.
934
935Returns:
936The reflection direction calculated as Self - 2 * N.Dot(Self) * N. }
937function Reflect(const N: TVector3): TVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}938
939{ Calculates the refraction direction for this (incident) vector.940
941Parameters:
942N: the normal vector. Should be normalized in order to achieve the
943desired result.
944Eta: the ratio of indices of refraction.
945
946Returns:
947The refraction vector.
948
949@bold(Note): This vector should be normalized in order to achieve the
950desired result.}
951function Refract(const N: TVector3; const Eta: Single): TVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}952
953{ Creates a vector with the same direction as this vector, but with the954length limited, based on the desired maximum length.
955
956Parameters:
957AMaxLength: The desired maximum length of the vector.
958
959Returns:
960A length-limited version of this vector.
961
962@bold(Note): Does not change this vector. To update this vector itself,
963use SetLimit. }
964function Limit(const AMaxLength: Single): TVector3; inline;965
966{ Limits the length of this vector, based on the desired maximum length.967
968Parameters:
969AMaxLength: The desired maximum length of this vector.
970
971@bold(Note): If you do not want to change this vector, but get a
972length-limited version instead, then use Limit. }
973procedure SetLimit(const AMaxLength: Single); inline;974
975{ Creates a vector with the same direction as this vector, but with the976length limited, based on the desired squared maximum length.
977
978Parameters:
979AMaxLengthSquared: The desired squared maximum length of the vector.
980
981Returns:
982A length-limited version of this vector.
983
984@bold(Note): Does not change this vector. To update this vector itself,
985use SetLimitSquared. }
986function LimitSquared(const AMaxLengthSquared: Single): TVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}987
988{ Limits the length of this vector, based on the desired squared maximum989length.
990
991Parameters:
992AMaxLengthSquared: The desired squared maximum length of this vector.
993
994@bold(Note): If you do not want to change this vector, but get a
995length-limited version instead, then use LimitSquared. }
996procedure SetLimitSquared(const AMaxLengthSquared: Single);997
998{ Creates a vector with the same direction as this vector, but with the999length clamped between a minimim and maximum length.
1000
1001Parameters:
1002AMinLength: The minimum length of the vector.
1003AMaxLength: The maximum length of the vector.
1004
1005Returns:
1006A length-clamped version of this vector.
1007
1008@bold(Note): Does not change this vector. To update this vector itself,
1009use SetClamped. }
1010function Clamp(const AMinLength, AMaxLength: Single): TVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}1011
1012{ Clamps the length of this vector between a minimim and maximum length.1013
1014Parameters:
1015AMinLength: The minimum length of this vector.
1016AMaxLength: The maximum length of this vector.
1017
1018@bold(Note): If you do not want to change this vector, but get a
1019length-clamped version instead, then use Clamp. }
1020procedure SetClamped(const AMinLength, AMaxLength: Single);1021
1022{ Linearly interpolates between this vector and a target vector.1023
1024Parameters:
1025ATarget: the target vector.
1026AAlpha: the interpolation coefficient (between 0.0 and 1.0).
1027
1028Returns:
1029The interpolation result vector.
1030
1031@bold(Note): Does not change this vector. To update this vector itself,
1032use SetLerp. }
1033function Lerp(const ATarget: TVector3; const AAlpha: Single): TVector3; inline;1034
1035{ Linearly interpolates between this vector and a target vector and stores1036the result in this vector.
1037
1038Parameters:
1039ATarget: the target vector.
1040AAlpha: the interpolation coefficient (between 0.0 and 1.0).
1041
1042@bold(Note): If you do not want to change this vector, but get an
1043interpolated version instead, then use Lerp. }
1044procedure SetLerp(const ATarget: TVector3; const AAlpha: Single); inline;1045
1046{ Whether the vector is normalized (within a small margin of error).1047
1048Returns:
1049True if the length of the vector is (very close to) 1.0 }
1050function IsNormalized: Boolean; overload; inline;1051
1052{ Whether the vector is normalized within a given margin of error.1053
1054Parameters:
1055AErrorMargin: the allowed margin of error.
1056
1057Returns:
1058True if the squared length of the vector is 1.0 within the margin of
1059error. }
1060function IsNormalized(const AErrorMargin: Single): Boolean; overload;1061
1062{ Whether this is a zero vector.1063
1064Returns:
1065True if X, Y and Z are exactly 0.0 }
1066function IsZero: Boolean; overload; inline;1067
1068{ Whether this is a zero vector within a given margin of error.1069
1070Parameters:
1071AErrorMargin: the allowed margin of error.
1072
1073Returns:
1074True if the squared length is smaller then the margin of error. }
1075function IsZero(const AErrorMargin: Single): Boolean; overload;1076
1077{ Whether this vector has a similar direction compared to another vector.1078
1079Parameters:
1080AOther: the other vector.
1081
1082Returns:
1083True if the normalized dot product is greater than 0. }
1084function HasSameDirection(const AOther: TVector3): Boolean; inline;1085
1086{ Whether this vector has an opposite direction compared to another vector.1087
1088Parameters:
1089AOther: the other vector.
1090
1091Returns:
1092True if the normalized dot product is less than 0. }
1093function HasOppositeDirection(const AOther: TVector3): Boolean; inline;1094
1095{ Whether this vector runs parallel to another vector (either in the same1096or the opposite direction).
1097
1098Parameters:
1099AOther: the other vector.
1100ATolerance: (optional) tolerance. If not specified, a small tolerance
1101is used.
1102
1103Returns:
1104True if this vector runs parallel to AOther (within the given tolerance) }
1105function IsParallel(const AOther: TVector3; const ATolerance: Single = SINGLE_TOLERANCE): Boolean;1106
1107{ Whether this vector is collinear with another vector. Two vectors are1108collinear if they run parallel to each other and point in the same
1109direction.
1110
1111Parameters:
1112AOther: the other vector.
1113ATolerance: (optional) tolerance. If not specified, a small tolerance
1114is used.
1115
1116Returns:
1117True if this vector is collinear to AOther (within the given tolerance) }
1118function IsCollinear(const AOther: TVector3; const ATolerance: Single = SINGLE_TOLERANCE): Boolean;1119
1120{ Whether this vector is opposite collinear with another vector. Two vectors1121are opposite collinear if they run parallel to each other and point in
1122opposite directions.
1123
1124Parameters:
1125AOther: the other vector.
1126ATolerance: (optional) tolerance. If not specified, a small tolerance
1127is used.
1128
1129Returns:
1130True if this vector is opposite collinear to AOther (within the given
1131tolerance) }
1132function IsCollinearOpposite(const AOther: TVector3; const ATolerance: Single = SINGLE_TOLERANCE): Boolean;1133
1134{ Whether this vector is perpendicular to another vector.1135
1136Parameters:
1137AOther: the other vector.
1138ATolerance: (optional) tolerance. If not specified, a small tolerance
1139is used.
1140
1141Returns:
1142True if this vector is perpendicular to AOther. That is, if the dot
1143product is 0 (within the given tolerance) }
1144function IsPerpendicular(const AOther: TVector3; const ATolerance: Single = SINGLE_TOLERANCE): Boolean;1145
1146{ Returns the components of the vector.1147This is identical to accessing the C-field, but this property can be used
1148as a default array property.
1149
1150Parameters:
1151AIndex: index of the component to return (0-2). Range is checked
1152with an assertion. }
1153property Components[const AIndex: Integer]: Single read GetComponent write SetComponent; default;1154
1155{ The euclidean length of this vector.1156
1157@bold(Note): If you only want to compare lengths of vectors, you should
1158use LengthSquared instead, which is faster.
1159
1160@bold(Note): You can also set the length of the vector. In that case, it
1161will keep the current direction. }
1162property Length: Single read GetLength write SetLength;1163
1164{ The squared length of the vector.1165
1166@bold(Note): This property is faster than Length because it avoids
1167calculating a square root. It is useful for comparing lengths instead of
1168calculating actual lengths.
1169
1170@bold(Note): You can also set the squared length of the vector. In that
1171case, it will keep the current direction. }
1172property LengthSquared: Single read GetLengthSquared write SetLengthSquared;1173public1174case Byte of1175{ X, Y and Z components of the vector. Aliases for C[0], C[1] and C[2]. }11760: (X, Y, Z: Single);1177
1178{ Red, Green and Blue components of the vector. Aliases for C[0], C[1]1179and C[2]. }
11801: (R, G, B: Single);1181
1182{ S, T and P components of the vector. Aliases for C[0], C[1] and C[2]. }11832: (S, T, P: Single);1184
1185{ The three components of the vector. }11863: (C: array [0..2] of Single);1187end;1188PVector3 = ^TVector3;1189
1190type
1191{ A 4-dimensional vector. Can be used for a variety of purposes:1192* To represent points or vectors in 4D space, using the X, Y, Z and W
1193fields.
1194* To represent colors with alpha channel information (using the R, G, B and
1195A fields, which are just aliases for X, Y, Z and W)
1196* To represent texture coordinates (S, T, P and Q, again just aliases for X,
1197Y, Z and W).
1198* To group 4 arbitrary values together in an array (C[0]..C[3], also just
1199aliases for X, Y, Z and W)
1200
1201TVector4 is compatible with TVector3D in the Delphi RTL. You can typecast
1202between these two types or implicitly convert from one to the other through
1203assignment (eg. MyVector4 := MyPoint3D). }
1204TVector4 = record1205{$REGION 'Internal Declarations'}1206private1207function GetComponent(const AIndex: Integer): Single; inline;1208procedure SetComponent(const AIndex: Integer; const Value: Single); inline;1209function GetLength: Single; {$IFDEF FM_INLINE}inline;{$ENDIF}1210procedure SetLength(const AValue: Single); inline;1211function GetLengthSquared: Single; inline;1212procedure SetLengthSquared(const AValue: Single); inline;1213{$ENDREGION 'Internal Declarations'}1214public1215{ Sets the four elements (X, Y, Z and W) to 0. }1216procedure Init; overload; inline;1217
1218{ Sets the four elements (X, Y, Z and W) to A.1219
1220Parameters:
1221A: the value to set the three elements to. }
1222procedure Init(const A: Single); overload; inline;1223
1224{ Sets the four elements (X, Y, Z and W) to A1, A2, A3 and A4 respectively.1225
1226Parameters:
1227A1: the value to set the first element to.
1228A2: the value to set the second element to.
1229A3: the value to set the third element to.
1230A4: the value to set the fourth element to. }
1231procedure Init(const A1, A2, A3, A4: Single); overload; inline;1232
1233{ Sets the first two elements from a 2D vector, and the last two elements1234from two scalars.
1235
1236Parameters:
1237A1: the vector to use for the first two elements.
1238A2: the value to set the third element to.
1239A3: the value to set the fourth element to. }
1240procedure Init(const A1: TVector2; const A2, A3: Single); overload; inline;1241
1242{ Sets the first and last elements from two scalars, and the middle two1243elements from a 2D vector.
1244
1245Parameters:
1246A1: the value to set the first element to.
1247A2: the vector to use for the second and third elements.
1248A3: the value to set the fourth element to. }
1249procedure Init(const A1: Single; const A2: TVector2; const A3: Single); overload; inline;1250
1251{ Sets the first two elements from two scalars and the last two elements1252from a 2D vector.
1253
1254Parameters:
1255A1: the value to set the first element to.
1256A2: the value to set the second element to.
1257A3: the vector to use for the last two elements. }
1258procedure Init(const A1, A2: Single; const A3: TVector2); overload; inline;1259
1260{ Sets the first two elements and last two elements from two 2D vectors.1261
1262Parameters:
1263A1: the vector to use for the first two elements.
1264A2: the vector to use for the last two elements. }
1265procedure Init(const A1, A2: TVector2); overload; inline;1266
1267{ Sets the first three elements from a 3D vector, and the fourth element1268from a scalar.
1269
1270Parameters:
1271A1: the vector to use for the first three elements.
1272A2: the value to set the fourth element to. }
1273procedure Init(const A1: TVector3; const A2: Single); overload; inline;1274
1275{ Sets the first element from a scaler, and the last three elements from a12763D vector.
1277
1278Parameters:
1279A1: the value to set the first element to.
1280A2: the vector to use for the last three elements. }
1281procedure Init(const A1: Single; const A2: TVector3); overload; inline;1282
1283{ Implicitly converts a TVector3D to a TVector4. }1284class operator Implicit(const A: TVector3D): TVector4; inline;1285
1286{ Implicitly converts a TVector4 to a TVector3D. }1287class operator Implicit(const A: TVector4): TVector3D; inline;1288
1289{ Checks two vectors for equality.1290
1291Returns:
1292True if the two vectors match each other exactly. }
1293class operator Equal(const A, B: TVector4): Boolean; inline;1294
1295{ Checks two vectors for inequality.1296
1297Returns:
1298True if the two vectors are not equal. }
1299class operator NotEqual(const A, B: TVector4): Boolean; inline;1300
1301{ Negates a vector.1302
1303Returns:
1304The negative value of a vector (eg. (-A.X, -A.Y, -A.Z, -A.W)) }
1305class operator Negative(const A: TVector4): TVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}1306
1307{ Adds a scalar value to a vector.1308
1309Returns:
1310(A.X + B, A.Y + B, A.Z + B, A.W + B) }
1311class operator Add(const A: TVector4; const B: Single): TVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}1312
1313{ Adds a vector to a scalar value.1314
1315Returns:
1316(A + B.X, A + B.Y, A + B.Z, A + B.W) }
1317class operator Add(const A: Single; const B: TVector4): TVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}1318
1319{ Adds two vectors.1320
1321Returns:
1322(A.X + B.X, A.Y + B.Y, A.Z + B.Z, A.W + B.W) }
1323class operator Add(const A, B: TVector4): TVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}1324
1325{ Subtracts a scalar value from a vector.1326
1327Returns:
1328(A.X - B, A.Y - B, A.Z - B, A.W - B) }
1329class operator Subtract(const A: TVector4; const B: Single): TVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}1330
1331{ Subtracts a vector from a scalar value.1332
1333Returns:
1334(A - B.X, A - B.Y, A - B.Z, A - B.W) }
1335class operator Subtract(const A: Single; const B: TVector4): TVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}1336
1337{ Subtracts two vectors.1338
1339Returns:
1340(A.X - B.X, A.Y - B.Y, A.Z - B.Z, A.W - B.W) }
1341class operator Subtract(const A, B: TVector4): TVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}1342
1343{ Multiplies a vector with a scalar value.1344
1345Returns:
1346(A.X * B, A.Y * B, A.Z * B, A.W * B) }
1347class operator Multiply(const A: TVector4; const B: Single): TVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}1348
1349{ Multiplies a scalar value with a vector.1350
1351Returns:
1352(A * B.X, A * B.Y, A * B.Z, A * B.W) }
1353class operator Multiply(const A: Single; const B: TVector4): TVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}1354
1355{ Multiplies two vectors component-wise.1356To calculate a dot product instead, use the Dot function.
1357
1358Returns:
1359(A.X * B.X, A.Y * B.Y, A.Z * B.Z, A.W * B.W) }
1360class operator Multiply(const A, B: TVector4): TVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}1361
1362{ Divides a vector by a scalar value.1363
1364Returns:
1365(A.X / B, A.Y / B, A.Z / B, A.W / B) }
1366class operator Divide(const A: TVector4; const B: Single): TVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}1367
1368{ Divides a scalar value by a vector.1369
1370Returns:
1371(A / B.X, A / B.Y, A / B.Z, A / B.W) }
1372class operator Divide(const A: Single; const B: TVector4): TVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}1373
1374{ Divides two vectors component-wise.1375
1376Returns:
1377(A.X / B.X, A.Y / B.Y, A.Z / B.Z, A.W / B.W) }
1378class operator Divide(const A, B: TVector4): TVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}1379
1380{ Whether this vector equals another vector, within a certain tolerance.1381
1382Parameters:
1383AOther: the other vector.
1384ATolerance: (optional) tolerance. If not specified, a small tolerance
1385is used.
1386
1387Returns:
1388True if both vectors are equal (within the given tolerance). }
1389function Equals(const AOther: TVector4; const ATolerance: Single = SINGLE_TOLERANCE): Boolean; inline;1390
1391{ Calculates the distance between this vector and another vector.1392
1393Parameters:
1394AOther: the other vector.
1395
1396Returns:
1397The distance between this vector and AOther.
1398
1399@bold(Note): If you only want to compare distances, you should use
1400DistanceSquared instead, which is faster. }
1401function Distance(const AOther: TVector4): Single; {$IFDEF FM_INLINE}inline;{$ENDIF}1402
1403{ Calculates the squared distance between this vector and another vector.1404
1405Parameters:
1406AOther: the other vector.
1407
1408Returns:
1409The squared distance between this vector and AOther. }
1410function DistanceSquared(const AOther: TVector4): Single; {$IFDEF FM_INLINE}inline;{$ENDIF}1411
1412{ Calculates the dot product between this vector and another vector.1413
1414Parameters:
1415AOther: the other vector.
1416
1417Returns:
1418The dot product between this vector and AOther. }
1419function Dot(const AOther: TVector4): Single; inline;1420
1421{ Offsets this vector in a certain direction.1422
1423Parameters:
1424ADeltaX: the delta X direction.
1425ADeltaY: the delta Y direction.
1426ADeltaZ: the delta Z direction.
1427ADeltaW: the delta W direction. }
1428procedure Offset(const ADeltaX, ADeltaY, ADeltaZ, ADeltaW: Single); overload; inline;1429
1430{ Offsets this vector in a certain direction.1431
1432Parameters:
1433ADelta: the delta.
1434
1435@bold(Note): this is equivalent to adding two vectors together. }
1436procedure Offset(const ADelta: TVector4); overload; inline;1437
1438
1439{ Calculates a normalized version of this vector.1440
1441Returns:
1442The normalized version of of this vector. That is, a vector in the same
1443direction as A, but with a length of 1.
1444
1445@bold(Note): for a faster, less accurate version, use NormalizeFast.
1446
1447@bold(Note): Does not change this vector. To update this vector itself,
1448use SetNormalized. }
1449function Normalize: TVector4; inline;1450
1451{ Normalizes this vector. This is, keep the current direction, but set the1452length to 1.
1453
1454@bold(Note): The SIMD optimized versions of this method use an
1455approximation, resulting in a very small error.
1456
1457@bold(Note): If you do not want to change this vector, but get a
1458normalized version instead, then use Normalize. }
1459procedure SetNormalized; inline;1460
1461{ Calculates a normalized version of this vector.1462
1463Returns:
1464The normalized version of of this vector. That is, a vector in the same
1465direction as A, but with a length of 1.
1466
1467@bold(Note): this is an SIMD optimized version that uses an approximation,
1468resulting in a small error. For an accurate version, use Normalize.
1469
1470@bold(Note): Does not change this vector. To update this vector itself,
1471use SetNormalizedFast. }
1472function NormalizeFast: TVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}1473
1474{ Normalizes this vector. This is, keep the current direction, but set the1475length to 1.
1476
1477@bold(Note): this is an SIMD optimized version that uses an approximation,
1478resulting in a small error. For an accurate version, use SetNormalized.
1479
1480@bold(Note): If you do not want to change this vector, but get a
1481normalized version instead, then use NormalizeFast. }
1482procedure SetNormalizedFast; {$IFDEF FM_INLINE}inline;{$ENDIF}1483
1484{ Calculates a vector pointing in the same direction as this vector.1485
1486Parameters:
1487I: the incident vector.
1488NRef: the reference vector.
1489
1490Returns:
1491A vector that points away from the surface as defined by its normal. If
1492NRef.Dot(I) < 0 then it returns this vector, otherwise it returns the
1493negative of this vector. }
1494function FaceForward(const I, NRef: TVector4): TVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}1495
1496{ Calculates the reflection direction for this (incident) vector.1497
1498Parameters:
1499N: the normal vector. Should be normalized in order to achieve the desired
1500result.
1501
1502Returns:
1503The reflection direction calculated as Self - 2 * N.Dot(Self) * N. }
1504function Reflect(const N: TVector4): TVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}1505
1506{ Calculates the refraction direction for this (incident) vector.1507
1508Parameters:
1509N: the normal vector. Should be normalized in order to achieve the
1510desired result.
1511Eta: the ratio of indices of refraction.
1512
1513Returns:
1514The refraction vector.
1515
1516@bold(Note): This vector should be normalized in order to achieve the
1517desired result.}
1518function Refract(const N: TVector4; const Eta: Single): TVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}1519
1520{ Creates a vector with the same direction as this vector, but with the1521length limited, based on the desired maximum length.
1522
1523Parameters:
1524AMaxLength: The desired maximum length of the vector.
1525
1526Returns:
1527A length-limited version of this vector.
1528
1529@bold(Note): Does not change this vector. To update this vector itself,
1530use SetLimit. }
1531function Limit(const AMaxLength: Single): TVector4; inline;1532
1533{ Limits the length of this vector, based on the desired maximum length.1534
1535Parameters:
1536AMaxLength: The desired maximum length of this vector.
1537
1538@bold(Note): If you do not want to change this vector, but get a
1539length-limited version instead, then use Limit. }
1540procedure SetLimit(const AMaxLength: Single); inline;1541
1542{ Creates a vector with the same direction as this vector, but with the1543length limited, based on the desired squared maximum length.
1544
1545Parameters:
1546AMaxLengthSquared: The desired squared maximum length of the vector.
1547
1548Returns:
1549A length-limited version of this vector.
1550
1551@bold(Note): Does not change this vector. To update this vector itself,
1552use SetLimitSquared. }
1553function LimitSquared(const AMaxLengthSquared: Single): TVector4;1554
1555{ Limits the length of this vector, based on the desired squared maximum1556length.
1557
1558Parameters:
1559AMaxLengthSquared: The desired squared maximum length of this vector.
1560
1561@bold(Note): If you do not want to change this vector, but get a
1562length-limited version instead, then use LimitSquared. }
1563procedure SetLimitSquared(const AMaxLengthSquared: Single);1564
1565{ Creates a vector with the same direction as this vector, but with the1566length clamped between a minimim and maximum length.
1567
1568Parameters:
1569AMinLength: The minimum length of the vector.
1570AMaxLength: The maximum length of the vector.
1571
1572Returns:
1573A length-clamped version of this vector.
1574
1575@bold(Note): Does not change this vector. To update this vector itself,
1576use SetClamped. }
1577function Clamp(const AMinLength, AMaxLength: Single): TVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}1578
1579{ Clamps the length of this vector between a minimim and maximum length.1580
1581Parameters:
1582AMinLength: The minimum length of this vector.
1583AMaxLength: The maximum length of this vector.
1584
1585@bold(Note): If you do not want to change this vector, but get a
1586length-clamped version instead, then use Clamp. }
1587procedure SetClamped(const AMinLength, AMaxLength: Single);1588
1589{ Linearly interpolates between this vector and a target vector.1590
1591Parameters:
1592ATarget: the target vector.
1593AAlpha: the interpolation coefficient (between 0.0 and 1.0).
1594
1595Returns:
1596The interpolation result vector.
1597
1598@bold(Note): Does not change this vector. To update this vector itself,
1599use SetLerp. }
1600function Lerp(const ATarget: TVector4; const AAlpha: Single): TVector4; inline;1601
1602{ Linearly interpolates between this vector and a target vector and stores1603the result in this vector.
1604
1605Parameters:
1606ATarget: the target vector.
1607AAlpha: the interpolation coefficient (between 0.0 and 1.0).
1608
1609@bold(Note): If you do not want to change this vector, but get an
1610interpolated version instead, then use Lerp. }
1611procedure SetLerp(const ATarget: TVector4; const AAlpha: Single); inline;1612
1613{ Whether the vector is normalized (within a small margin of error).1614
1615Returns:
1616True if the length of the vector is (very close to) 1.0 }
1617function IsNormalized: Boolean; overload; inline;1618
1619{ Whether the vector is normalized within a given margin of error.1620
1621Parameters:
1622AErrorMargin: the allowed margin of error.
1623
1624Returns:
1625True if the squared length of the vector is 1.0 within the margin of
1626error. }
1627function IsNormalized(const AErrorMargin: Single): Boolean; overload;1628
1629{ Whether this is a zero vector.1630
1631Returns:
1632True if X, Y, Z and W are exactly 0.0 }
1633function IsZero: Boolean; overload; inline;1634
1635{ Whether this is a zero vector within a given margin of error.1636
1637Parameters:
1638AErrorMargin: the allowed margin of error.
1639
1640Returns:
1641True if the squared length is smaller then the margin of error. }
1642function IsZero(const AErrorMargin: Single): Boolean; overload;1643
1644{ Whether this vector has a similar direction compared to another vector.1645The test is performed in 3 dimensions (that is, the W-component is ignored).
1646Parameters:
1647AOther: the other vector.
1648
1649Returns:
1650True if the normalized dot product (ignoring the W-component) is greater
1651than 0. }
1652function HasSameDirection(const AOther: TVector4): Boolean; inline;1653
1654{ Whether this vector has an opposite direction compared to another vector.1655The test is performed in 3 dimensions (that is, the W-component is ignored).
1656
1657Parameters:
1658AOther: the other vector.
1659
1660Returns:
1661True if the normalized dot product (ignoring the W-component) is less
1662than 0. }
1663function HasOppositeDirection(const AOther: TVector4): Boolean; inline;1664
1665{ Whether this vector runs parallel to another vector (either in the same1666or the opposite direction). The test is performed in 3 dimensions (that
1667is, the W-component is ignored).
1668
1669Parameters:
1670AOther: the other vector.
1671ATolerance: (optional) tolerance. If not specified, a small tolerance
1672is used.
1673
1674Returns:
1675True if this vector runs parallel to AOther (within the given tolerance
1676and ignoring the W-component) }
1677function IsParallel(const AOther: TVector4; const ATolerance: Single = SINGLE_TOLERANCE): Boolean;1678
1679{ Whether this vector is collinear with another vector. Two vectors are1680collinear if they run parallel to each other and point in the same
1681direction. The test is performed in 3 dimensions (that is, the W-component
1682is ignored).
1683
1684Parameters:
1685AOther: the other vector.
1686ATolerance: (optional) tolerance. If not specified, a small tolerance
1687is used.
1688
1689Returns:
1690True if this vector is collinear to AOther (within the given tolerance
1691and ignoring the W-component) }
1692function IsCollinear(const AOther: TVector4; const ATolerance: Single = SINGLE_TOLERANCE): Boolean;1693
1694{ Whether this vector is opposite collinear with another vector. Two vectors1695are opposite collinear if they run parallel to each other and point in
1696opposite directions. The test is performed in 3 dimensions (that is, the
1697W-component is ignored).
1698
1699Parameters:
1700AOther: the other vector.
1701ATolerance: (optional) tolerance. If not specified, a small tolerance
1702is used.
1703
1704Returns:
1705True if this vector is opposite collinear to AOther (within the given
1706tolerance and ignoring the W-component) }
1707function IsCollinearOpposite(const AOther: TVector4; const ATolerance: Single = SINGLE_TOLERANCE): Boolean;1708
1709{ Whether this vector is perpendicular to another vector. The test is1710performed in 3 dimensions (that is, the W-component is ignored).
1711
1712Parameters:
1713AOther: the other vector.
1714ATolerance: (optional) tolerance. If not specified, a small tolerance
1715is used.
1716
1717Returns:
1718True if this vector is perpendicular to AOther. That is, if the dot
1719product is 0 (within the given tolerance and ignoring the W-component) }
1720function IsPerpendicular(const AOther: TVector4; const ATolerance: Single = SINGLE_TOLERANCE): Boolean;1721
1722{ Returns the components of the vector.1723This is identical to accessing the C-field, but this property can be used
1724as a default array property.
1725
1726Parameters:
1727AIndex: index of the component to return (0-3). Range is checked
1728with an assertion. }
1729property Components[const AIndex: Integer]: Single read GetComponent write SetComponent; default;1730
1731{ The euclidean length of this vector.1732
1733@bold(Note): If you only want to compare lengths of vectors, you should
1734use LengthSquared instead, which is faster.
1735
1736@bold(Note): You can also set the length of the vector. In that case, it
1737will keep the current direction. }
1738property Length: Single read GetLength write SetLength;1739
1740{ The squared length of the vector.1741
1742@bold(Note): This property is faster than Length because it avoids
1743calculating a square root. It is useful for comparing lengths instead of
1744calculating actual lengths.
1745
1746@bold(Note): You can also set the squared length of the vector. In that
1747case, it will keep the current direction. }
1748property LengthSquared: Single read GetLengthSquared write SetLengthSquared;1749public1750case Byte of1751{ X, Y, Z and W components of the vector. Aliases for C[0], C[1], C[2]1752and C[3]. }
17530: (X, Y, Z, W: Single);1754
1755{ Red, Green, Blue and Alpha components of the vector. Aliases for C[0],1756C[1], C[2] and C[3]. }
17571: (R, G, B, A: Single);1758
1759{ S, T, P and Q components of the vector. Aliases for C[0], C[1], C[2] and1760C[3]. }
17612: (S, T, P, Q: Single);1762
1763{ The four components of the vector. }17643: (C: array [0..3] of Single);1765end;1766PVector4 = ^TVector4;1767
1768type
1769{ A 2x2 matrix in row-major order (M[Row, Column]).1770You can access the elements directly using M[0,0]..M[1,1] or m11..m22.
1771You can also access the matrix using its two rows R[0]..R[1] (which map
1772directly to the elements M[]).
1773
1774When the conditional define FM_COLUMN_MAJOR is set, the matrix is stored
1775in column-major order instead (M[Column, Row]), and the Rows property
1776and R fields are replaced by Columns and C respectively. }
1777TMatrix2 = record1778{$REGION 'Internal Declarations'}1779private1780{$IFDEF FM_COLUMN_MAJOR}1781function GetComponent(const AColumn, ARow: Integer): Single; inline;1782procedure SetComponent(const AColumn, ARow: Integer; const Value: Single); inline;1783function GetColumn(const AIndex: Integer): TVector2; inline;1784procedure SetColumn(const AIndex: Integer; const Value: TVector2); inline;1785{$ELSE}1786function GetComponent(const ARow, AColumn: Integer): Single; inline;1787procedure SetComponent(const ARow, AColumn: Integer; const Value: Single); inline;1788function GetRow(const AIndex: Integer): TVector2; inline;1789procedure SetRow(const AIndex: Integer; const Value: TVector2); inline;1790{$ENDIF}1791function GetDeterminant: Single; inline;1792{$ENDREGION 'Internal Declarations'}1793public1794{ Initializes the matrix to an identity matrix (filled with 0 and value 11795for the diagonal) }
1796procedure Init; overload; inline;1797
1798{ Fills the matrix with zeros and sets the diagonal.1799
1800Parameters:
1801ADiagonal: the value to use for the diagonal. Use 1 to set the matrix
1802to an identity matrix. }
1803procedure Init(const ADiagonal: Single); overload; inline;1804
1805{$IFDEF FM_COLUMN_MAJOR}1806{ Initializes the matrix using two column vectors.1807
1808Parameters:
1809AColumn0: the first column of the matrix.
1810AColumn1: the second column of the matrix. }
1811procedure Init(const AColumn0, AColumn1: TVector2); overload; inline;1812{$ELSE}1813{ Initializes the matrix using two row vectors.1814
1815Parameters:
1816ARow0: the first row of the matrix.
1817ARow1: the second row of the matrix. }
1818procedure Init(const ARow0, ARow1: TVector2); overload; inline;1819{$ENDIF}1820
1821{ Initializes the matrix with explicit values.1822
1823Parameters:
1824A11-A12: the values of the matrix elements, in row-major order. }
1825procedure Init(const A11, A12, A21, A22: Single); overload; inline;1826
1827{ Checks two matrices for equality.1828
1829Returns:
1830True if the two matrices match each other exactly. }
1831class operator Equal(const A, B: TMatrix2): Boolean; inline;1832
1833{ Checks two matrices for inequality.1834
1835Returns:
1836True if the two matrices are not equal. }
1837class operator NotEqual(const A, B: TMatrix2): Boolean; inline;1838
1839{ Negates a matrix.1840
1841Returns:
1842The negative value of the matrix (with all elements negated). }
1843class operator Negative(const A: TMatrix2): TMatrix2; {$IFDEF FM_INLINE}inline;{$ENDIF}1844
1845{ Adds a scalar value to each element of a matrix. }1846class operator Add(const A: TMatrix2; const B: Single): TMatrix2; {$IFDEF FM_INLINE}inline;{$ENDIF}1847
1848{ Adds a scalar value to each element of a matrix. }1849class operator Add(const A: Single; const B: TMatrix2): TMatrix2; {$IFDEF FM_INLINE}inline;{$ENDIF}1850
1851{ Adds two matrices component-wise. }1852class operator Add(const A, B: TMatrix2): TMatrix2; {$IFDEF FM_INLINE}inline;{$ENDIF}1853
1854{ Subtracts a scalar value from each element of a matrix. }1855class operator Subtract(const A: TMatrix2; const B: Single): TMatrix2; {$IFDEF FM_INLINE}inline;{$ENDIF}1856
1857{ Subtracts a matrix from a scalar value. }1858class operator Subtract(const A: Single; const B: TMatrix2): TMatrix2; {$IFDEF FM_INLINE}inline;{$ENDIF}1859
1860{ Subtracts two matrices component-wise. }1861class operator Subtract(const A, B: TMatrix2): TMatrix2; {$IFDEF FM_INLINE}inline;{$ENDIF}1862
1863{ Multiplies a matrix with a scalar value. }1864class operator Multiply(const A: TMatrix2; const B: Single): TMatrix2; {$IFDEF FM_INLINE}inline;{$ENDIF}1865
1866{ Multiplies a matrix with a scalar value. }1867class operator Multiply(const A: Single; const B: TMatrix2): TMatrix2; {$IFDEF FM_INLINE}inline;{$ENDIF}1868
1869{ Performs a matrix * row vector linear algebraic multiplication. }1870class operator Multiply(const A: TMatrix2; const B: TVector2): TVector2; inline;1871
1872{ Performs a column vector * matrix linear algebraic multiplication. }1873class operator Multiply(const A: TVector2; const B: TMatrix2): TVector2; inline;1874
1875{ Multiplies two matrices using linear algebraic multiplication. }1876class operator Multiply(const A, B: TMatrix2): TMatrix2; {$IFDEF FM_INLINE}inline;{$ENDIF}1877
1878{ Divides a matrix by a scalar value. }1879class operator Divide(const A: TMatrix2; const B: Single): TMatrix2; {$IFDEF FM_INLINE}inline;{$ENDIF}1880
1881{ Divides a scalar value by a matrix. }1882class operator Divide(const A: Single; const B: TMatrix2): TMatrix2; {$IFDEF FM_INLINE}inline;{$ENDIF}1883
1884{ Divides a matrix by a vector. This is equivalent to multiplying the1885inverse of the matrix with a row vector using linear algebraic
1886multiplication. }
1887class operator Divide(const A: TMatrix2; const B: TVector2): TVector2; inline;1888
1889{ Divides a vector by a matrix. This is equivalent to multiplying a column1890vector with the inverse of the matrix using linear algebraic
1891multiplication. }
1892class operator Divide(const A: TVector2; const B: TMatrix2): TVector2; inline;1893
1894{ Divides two matrices. This is equivalent to multiplying the first matrix1895with the inverse of the second matrix using linear algebraic
1896multiplication. }
1897class operator Divide(const A, B: TMatrix2): TMatrix2; inline;1898
1899{ Multiplies this matrix with another matrix component-wise.1900
1901Parameters:
1902AOther: the other matrix.
1903
1904Returns:
1905This matrix multiplied by AOther component-wise.
1906That is, Result.M[I,J] := M[I,J] * AOther.M[I,J].
1907
1908@bold(Note): For linear algebraic matrix multiplication, use the multiply
1909(*) operator instead. }
1910function CompMult(const AOther: TMatrix2): TMatrix2; {$IFDEF FM_INLINE}inline;{$ENDIF}1911
1912{ Creates a transposed version of this matrix.1913
1914Returns:
1915The transposed version of this matrix.
1916
1917@bold(Note): Does not change this matrix. To update this itself, use
1918SetTransposed. }
1919function Transpose: TMatrix2; inline;1920
1921{ Transposes this matrix.1922
1923@bold(Note): If you do not want to change this matrix, but get a
1924transposed version instead, then use Transpose. }
1925procedure SetTransposed; inline;1926
1927{ Calculates the inverse of this matrix.1928
1929Returns:
1930The inverse of this matrix.
1931
1932@bold(Note): Does not change this matrix. To update this itself, use
1933SetInversed.
1934
1935@bold(Note): The values in the returned matrix are undefined if this
1936matrix is singular or poorly conditioned (nearly singular). }
1937function Inverse: TMatrix2; {$IFDEF FM_INLINE}inline;{$ENDIF}1938
1939{ Inverts this matrix.1940
1941@bold(Note): If you do not want to change this matrix, but get an
1942inversed version instead, then use Inverse.
1943
1944@bold(Note): The values in the inversed matrix are undefined if this
1945matrix is singular or poorly conditioned (nearly singular). }
1946procedure SetInversed;1947
1948{$IFDEF FM_COLUMN_MAJOR}1949{ Returns the columns of the matrix. This is identical to accessing the1950C-field.
1951
1952Parameters:
1953AIndex: index of the row to return (0 or 1). Range is checked with
1954an assertion. }
1955property Columns[const AIndex: Integer]: TVector2 read GetColumn write SetColumn;1956
1957{ Returns the elements of the matrix (in column-major order).1958This is identical to accessing the M-field, but this property can be used
1959as a default array property.
1960
1961Parameters:
1962AColumn: the column index (0 or 1). Range is checked with an assertion.
1963ARow: the row index (0 or 1). Range is checked with an assertion. }
1964property Components[const AColumn, ARow: Integer]: Single read GetComponent write SetComponent; default;1965{$ELSE}1966{ Returns the rows of the matrix. This is identical to accessing the1967R-field.
1968
1969Parameters:
1970AIndex: index of the column to return (0 or 1). Range is checked with
1971an assertion. }
1972property Rows[const AIndex: Integer]: TVector2 read GetRow write SetRow;1973
1974{ Returns the elements of the matrix (in row-major order).1975This is identical to accessing the M-field, but this property can be used
1976as a default array property.
1977
1978Parameters:
1979ARow: the row index (0 or 1). Range is checked with an assertion.
1980AColumn: the column index (0 or 1). Range is checked with an assertion. }
1981property Components[const ARow, AColumn: Integer]: Single read GetComponent write SetComponent; default;1982{$ENDIF}1983
1984{ The determinant of this matrix. }1985property Determinant: Single read GetDeterminant;1986public1987case Byte of1988{ Row or column vectors, depending on FM_COLUMN_MAJOR define }19890: (V: array [0..1] of TVector2);1990
1991{$IFDEF FM_COLUMN_MAJOR}1992{ The two column vectors making up the matrix }19931: (C: array [0..1] of TVector2);1994{$ELSE}1995{ The two row vectors making up the matrix }19962: (R: array [0..1] of TVector2);1997{$ENDIF}1998
1999{ The elements of the matrix in row-major order }20003: (M: array [0..1, 0..1] of Single);20014: (m11, m12: Single;2002m21, m22: Single);2003end;2004PMatrix2 = ^TMatrix2;2005
2006type
2007{ A 3x3 matrix in row-major order (M[Row, Column]).2008You can access the elements directly using M[0,0]..M[2,2] or m11..m33.
2009You can also access the matrix using its three rows R[0]..R[2] (which map
2010directly to the elements M[]).
2011
2012TMatrix3 is compatible with TMatrix in the Delphi RTL. You can typecast
2013between these two types or implicitly convert from one to the other through
2014assignment (eg. MyMatrix3 := MyMatrix).
2015
2016When the conditional define FM_COLUMN_MAJOR is set, the matrix is stored
2017in column-major order instead (M[Column, Row]), and the Rows property
2018and R fields are replaced by Columns and C respectively. Also, in that case
2019assigning an RTL TMatrix to a TMatrix3 will transpose the matrix to keep
2020behavior the same. }
2021TMatrix3 = record2022{$REGION 'Internal Declarations'}2023private2024{$IFDEF FM_COLUMN_MAJOR}2025function GetComponent(const AColumn, ARow: Integer): Single; inline;2026procedure SetComponent(const AColumn, ARow: Integer; const Value: Single); inline;2027function GetColumn(const AIndex: Integer): TVector3; inline;2028procedure SetColumn(const AIndex: Integer; const Value: TVector3); inline;2029{$ELSE}2030function GetComponent(const ARow, AColumn: Integer): Single; inline;2031procedure SetComponent(const ARow, AColumn: Integer; const Value: Single); inline;2032function GetRow(const AIndex: Integer): TVector3; inline;2033procedure SetRow(const AIndex: Integer; const Value: TVector3); inline;2034{$ENDIF}2035function GetDeterminant: Single;2036{$ENDREGION 'Internal Declarations'}2037public2038{ Initializes the matrix to an identity matrix (filled with 0 and value 12039for the diagonal) }
2040procedure Init; overload; inline;2041
2042{ Fills the matrix with zeros and sets the diagonal.2043
2044Parameters:
2045ADiagonal: the value to use for the diagonal. Use 1 to set the matrix
2046to an identity matrix. }
2047procedure Init(const ADiagonal: Single); overload; inline;2048
2049{$IFDEF FM_COLUMN_MAJOR}2050{ Initializes the matrix using three column vectors.2051
2052Parameters:
2053AColumn0: the first column of the matrix.
2054AColumn1: the second column of the matrix.
2055AColumn2: the third column of the matrix. }
2056procedure Init(const AColumn0, AColumn1, AColumn2: TVector3); overload; inline;2057{$ELSE}2058{ Initializes the matrix using three row vectors.2059
2060Parameters:
2061ARow0: the first row of the matrix.
2062ARow1: the second row of the matrix.
2063ARow2: the third row of the matrix. }
2064procedure Init(const ARow0, ARow1, ARow2: TVector3); overload; inline;2065{$ENDIF}2066
2067{ Initializes the matrix with explicit values.2068
2069Parameters:
2070A11-A33: the values of the matrix elements, in row-major order. }
2071procedure Init(const A11, A12, A13, A21, A22, A23, A31, A32, A33: Single); overload; inline;2072
2073{ Initializes the matrix with a 2x2 matrix. The 2x2 matrix is copied to the2074top-left corner of the 3x3 matrix, and the remaining elements are set
2075according to an identity matrix.
2076
2077Parameters:
2078AMatrix: the source 2x2 matrix. }
2079procedure Init(const AMatrix: TMatrix2); overload; inline;2080
2081{ Creates a scaling matrix that scales uniformly.2082
2083Parameters:
2084AScale: the uniform scale factor }
2085procedure InitScaling(const AScale: Single); overload;2086
2087{ Creates a scaling matrix.2088
2089Parameters:
2090AScaleX: the value to scale by on the X axis
2091AScaleY: the value to scale by on the Y axis }
2092procedure InitScaling(const AScaleX, AScaleY: Single); overload; inline;2093
2094{ Creates a scaling matrix.2095
2096Parameters:
2097AScale: the scale factors }
2098procedure InitScaling(const AScale: TVector2); overload; inline;2099
2100{ Creates a translation matrix.2101
2102Parameters:
2103ADeltaX: translation in the X direction
2104ADeltaY: translation in the Y direction }
2105procedure InitTranslation(const ADeltaX, ADeltaY: Single); overload; inline;2106
2107{ Creates a translation matrix.2108
2109Parameters:
2110ADelta: translation vector }
2111procedure InitTranslation(const ADelta: TVector2); overload; inline;2112
2113{ Creates a rotation the matrix using a rotation angle in radians.2114
2115Parameters:
2116AAngle: the rotation angle in radians }
2117procedure InitRotation(const AAngle: Single);2118
2119{ Implicitly converts a TMatrix to a TMatrix3. }2120class operator Implicit(const A: TMatrix): TMatrix3; inline;2121
2122{ Implicitly converts a TMatrix3 to a TMatrix. }2123class operator Implicit(const A: TMatrix3): TMatrix; inline;2124
2125{ Checks two matrices for equality.2126
2127Returns:
2128True if the two matrices match each other exactly. }
2129class operator Equal(const A, B: TMatrix3): Boolean; inline;2130
2131{ Checks two matrices for inequality.2132
2133Returns:
2134True if the two matrices are not equal. }
2135class operator NotEqual(const A, B: TMatrix3): Boolean; inline;2136
2137{ Negates a matrix.2138
2139Returns:
2140The negative value of the matrix (with all elements negated). }
2141class operator Negative(const A: TMatrix3): TMatrix3; {$IFDEF FM_INLINE}inline;{$ENDIF}2142
2143{ Adds a scalar value to each element of a matrix. }2144class operator Add(const A: TMatrix3; const B: Single): TMatrix3; {$IFDEF FM_INLINE}inline;{$ENDIF}2145
2146{ Adds a scalar value to each element of a matrix. }2147class operator Add(const A: Single; const B: TMatrix3): TMatrix3; {$IFDEF FM_INLINE}inline;{$ENDIF}2148
2149{ Adds two matrices component-wise. }2150class operator Add(const A, B: TMatrix3): TMatrix3; {$IFDEF FM_INLINE}inline;{$ENDIF}2151
2152{ Subtracts a scalar value from each element of a matrix. }2153class operator Subtract(const A: TMatrix3; const B: Single): TMatrix3; {$IFDEF FM_INLINE}inline;{$ENDIF}2154
2155{ Subtracts a matrix from a scalar value. }2156class operator Subtract(const A: Single; const B: TMatrix3): TMatrix3; {$IFDEF FM_INLINE}inline;{$ENDIF}2157
2158{ Subtracts two matrices component-wise. }2159class operator Subtract(const A, B: TMatrix3): TMatrix3; {$IFDEF FM_INLINE}inline;{$ENDIF}2160
2161{ Multiplies a matrix with a scalar value. }2162class operator Multiply(const A: TMatrix3; const B: Single): TMatrix3; {$IFDEF FM_INLINE}inline;{$ENDIF}2163
2164{ Multiplies a matrix with a scalar value. }2165class operator Multiply(const A: Single; const B: TMatrix3): TMatrix3; {$IFDEF FM_INLINE}inline;{$ENDIF}2166
2167{ Performs a matrix * row vector linear algebraic multiplication. }2168class operator Multiply(const A: TMatrix3; const B: TVector3): TVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}2169
2170{ Performs a column vector * matrix linear algebraic multiplication. }2171class operator Multiply(const A: TVector3; const B: TMatrix3): TVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}2172
2173{ Multiplies two matrices using linear algebraic multiplication. }2174class operator Multiply(const A, B: TMatrix3): TMatrix3; {$IFDEF FM_INLINE}inline;{$ENDIF}2175
2176{ Divides a matrix by a scalar value. }2177class operator Divide(const A: TMatrix3; const B: Single): TMatrix3; {$IFDEF FM_INLINE}inline;{$ENDIF}2178
2179{ Divides a scalar value by a matrix. }2180class operator Divide(const A: Single; const B: TMatrix3): TMatrix3; {$IFDEF FM_INLINE}inline;{$ENDIF}2181
2182{ Divides a matrix by a vector. This is equivalent to multiplying the2183inverse of the matrix with a row vector using linear algebraic
2184multiplication. }
2185class operator Divide(const A: TMatrix3; const B: TVector3): TVector3; inline;2186
2187{ Divides a vector by a matrix. This is equivalent to multiplying a column2188vector with the inverse of the matrix using linear algebraic
2189multiplication. }
2190class operator Divide(const A: TVector3; const B: TMatrix3): TVector3; inline;2191
2192{ Divides two matrices. This is equivalent to multiplying the first matrix2193with the inverse of the second matrix using linear algebraic
2194multiplication. }
2195class operator Divide(const A, B: TMatrix3): TMatrix3; inline;2196
2197{ Multiplies this matrix with another matrix component-wise.2198
2199Parameters:
2200AOther: the other matrix.
2201
2202Returns:
2203This matrix multiplied by AOther component-wise.
2204That is, Result.M[I,J] := M[I,J] * AOther.M[I,J].
2205
2206@bold(Note): For linear algebraic matrix multiplication, use the multiply
2207(*) operator instead. }
2208function CompMult(const AOther: TMatrix3): TMatrix3; {$IFDEF FM_INLINE}inline;{$ENDIF}2209
2210{ Creates a transposed version of this matrix.2211
2212Returns:
2213The transposed version of this matrix.
2214
2215@bold(Note): Does not change this matrix. To update this itself, use
2216SetTransposed. }
2217function Transpose: TMatrix3; {$IFDEF FM_INLINE}inline;{$ENDIF}2218
2219{ Transposes this matrix.2220
2221@bold(Note): If you do not want to change this matrix, but get a
2222transposed version instead, then use Transpose. }
2223procedure SetTransposed;2224
2225{ Calculates the inverse of this matrix.2226
2227Returns:
2228The inverse of this matrix.
2229
2230@bold(Note): Does not change this matrix. To update this itself, use
2231SetInversed.
2232
2233@bold(Note): The values in the returned matrix are undefined if this
2234matrix is singular or poorly conditioned (nearly singular). }
2235function Inverse: TMatrix3; {$IFDEF FM_INLINE}inline;{$ENDIF}2236
2237{ Inverts this matrix.2238
2239@bold(Note): If you do not want to change this matrix, but get an
2240inversed version instead, then use Inverse.
2241
2242@bold(Note): The values in the inversed matrix are undefined if this
2243matrix is singular or poorly conditioned (nearly singular). }
2244procedure SetInversed;2245
2246{$IFDEF FM_COLUMN_MAJOR}2247{ Returns the columns of the matrix. This is identical to accessing the2248C-field.
2249
2250Parameters:
2251AIndex: index of the column to return (0-2). Range is checked with
2252an assertion. }
2253property Columns[const AIndex: Integer]: TVector3 read GetColumn write SetColumn;2254
2255{ Returns the elements of the matrix (in column-major order).2256This is identical to accessing the M-field, but this property can be used
2257as a default array property.
2258
2259Parameters:
2260AColumn: the column index (0-2). Range is checked with an assertion.
2261ARow: the row index (0-2). Range is checked with an assertion. }
2262property Components[const AColumn, ARow: Integer]: Single read GetComponent write SetComponent; default;2263{$ELSE}2264{ Returns the rows of the matrix. This is identical to accessing the2265R-field.
2266
2267Parameters:
2268AIndex: index of the row to return (0-2). Range is checked with
2269an assertion. }
2270property Rows[const AIndex: Integer]: TVector3 read GetRow write SetRow;2271
2272{ Returns the elements of the matrix (in row-major order).2273This is identical to accessing the M-field, but this property can be used
2274as a default array property.
2275
2276Parameters:
2277ARow: the row index (0-2). Range is checked with an assertion.
2278AColumn: the column index (0-2). Range is checked with an assertion. }
2279property Components[const ARow, AColumn: Integer]: Single read GetComponent write SetComponent; default;2280{$ENDIF}2281
2282{ The determinant of this matrix. }2283property Determinant: Single read GetDeterminant;2284public2285case Byte of2286{ Row or column vectors, depending on FM_COLUMN_MAJOR define }22870: (V: array [0..2] of TVector3);2288
2289{$IFDEF FM_COLUMN_MAJOR}2290{ The three column vectors making up the matrix }22911: (C: array [0..2] of TVector3);2292{$ELSE}2293{ The three row vectors making up the matrix }22942: (R: array [0..2] of TVector3);2295{$ENDIF}2296
2297{ The elements of the matrix in row-major order }22983: (M: array [0..2, 0..2] of Single);22994: (m11, m12, m13: Single;2300m21, m22, m23: Single;2301m31, m32, m33: Single);2302end;2303PMatrix3 = ^TMatrix3;2304
2305type
2306{ A 4x4 matrix in row-major order (M[Row, Column]).2307You can access the elements directly using M[0,0]..M[3,3] or m11..m44.
2308You can also access the matrix using its four rows R[0]..R[3] (which map
2309directly to the elements M[]).
2310
2311TMatrix4 is compatible with TMatrix3D in the Delphi RTL. You can typecast
2312between these two types or implicitly convert from one to the other through
2313assignment (eg. MyMatrix4 := MyMatrix3D).
2314
2315When the conditional define FM_COLUMN_MAJOR is set, the matrix is stored
2316in column-major order instead (M[Column, Row]), and the Rows property
2317and R fields are replaced by Columns and C respectively. Also, in that case
2318assigning an RTL TMatrix3D to a TMatrix4 will transpose the matrix to keep
2319behavior the same. }
2320TMatrix4 = record2321{$REGION 'Internal Declarations'}2322private2323{$IFDEF FM_COLUMN_MAJOR}2324function GetComponent(const AColumn, ARow: Integer): Single; inline;2325procedure SetComponent(const AColumn, ARow: Integer; const Value: Single); inline;2326function GetColumn(const AIndex: Integer): TVector4; inline;2327procedure SetColumn(const AIndex: Integer; const Value: TVector4); inline;2328{$ELSE}2329function GetComponent(const ARow, AColumn: Integer): Single; inline;2330procedure SetComponent(const ARow, AColumn: Integer; const Value: Single); inline;2331function GetRow(const AIndex: Integer): TVector4; inline;2332procedure SetRow(const AIndex: Integer; const Value: TVector4); inline;2333{$ENDIF}2334function GetDeterminant: Single;2335{$ENDREGION 'Internal Declarations'}2336public2337{ Initializes the matrix to an identity matrix (filled with 0 and value 12338for the diagonal) }
2339procedure Init; overload; inline;2340
2341{ Fills the matrix with zeros and sets the diagonal.2342
2343Parameters:
2344ADiagonal: the value to use for the diagonal. Use 1 to set the matrix
2345to an identity matrix. }
2346procedure Init(const ADiagonal: Single); overload; inline;2347
2348{$IFDEF FM_COLUMN_MAJOR}2349{ Initializes the matrix using four column vectors.2350
2351Parameters:
2352AColumn0: the first column of the matrix.
2353AColumn1: the second column of the matrix.
2354AColumn2: the third column of the matrix.
2355AColumn3: the fourth column of the matrix. }
2356procedure Init(const AColumn0, AColumn1, AColumn2, AColumn3: TVector4); overload; inline;2357{$ELSE}2358{ Initializes the matrix using four row vectors.2359
2360Parameters:
2361ARow0: the first row of the matrix.
2362ARow1: the second row of the matrix.
2363ARow2: the third row of the matrix.
2364ARow3: the fourth row of the matrix. }
2365procedure Init(const ARow0, ARow1, ARow2, ARow3: TVector4); overload; inline;2366{$ENDIF}2367
2368{ Initializes the matrix with explicit values.2369
2370Parameters:
2371A11-A44: the values of the matrix elements, in row-major order. }
2372procedure Init(const A11, A12, A13, A14, A21, A22, A23, A24, A31, A32, A33,2373A34, A41, A42, A43, A44: Single); overload; inline;2374
2375{ Initializes the matrix with a 2x2 matrix. The 2x2 matrix is copied to the2376top-left corner of the 4x4 matrix, and the remaining elements are set
2377according to an identity matrix.
2378
2379Parameters:
2380AMatrix: the source 2x2 matrix. }
2381procedure Init(const AMatrix: TMatrix2); overload; inline;2382
2383{ Initializes the matrix with a 3x3 matrix. The 3x3 matrix is copied to the2384top-left corner of the 4x4 matrix, and the remaining elements are set
2385according to an identity matrix.
2386
2387Parameters:
2388AMatrix: the source 3x3 matrix. }
2389procedure Init(const AMatrix: TMatrix3); overload; inline;2390
2391{ Creates a scaling matrix that scales uniformly.2392
2393Parameters:
2394AScale: the uniform scale factor }
2395procedure InitScaling(const AScale: Single); overload;2396
2397{ Creates a scaling matrix.2398
2399Parameters:
2400AScaleX: the value to scale by on the X axis
2401AScaleY: the value to scale by on the Y axis
2402AScaleZ: the value to scale by on the Z axis }
2403procedure InitScaling(const AScaleX, AScaleY, AScaleZ: Single); overload; inline;2404
2405{ Creates a scaling matrix.2406
2407Parameters:
2408AScale: the scale factors }
2409procedure InitScaling(const AScale: TVector3); overload; inline;2410
2411{ Creates a translation matrix.2412
2413Parameters:
2414ADeltaX: translation in the X direction
2415ADeltaY: translation in the Y direction
2416ADeltaZ: translation in the Z direction }
2417procedure InitTranslation(const ADeltaX, ADeltaY, ADeltaZ: Single); overload; inline;2418
2419{ Creates a translation matrix.2420
2421Parameters:
2422ADelta: translation vector }
2423procedure InitTranslation(const ADelta: TVector3); overload; inline;2424
2425{ Creates a matrix for rotating points around the X axis.2426
2427Parameters:
2428AAngle: the rotation angle around the X axis, in radians }
2429procedure InitRotationX(const AAngle: Single);2430
2431{ Creates a matrix for rotating points around the Y axis.2432
2433Parameters:
2434AAngle: the rotation angle around the Y axis, in radians }
2435procedure InitRotationY(const AAngle: Single);2436
2437{ Creates a matrix for rotating points around the Z axis.2438
2439Parameters:
2440AAngle: the rotation angle around the Z axis, in radians }
2441procedure InitRotationZ(const AAngle: Single);2442
2443{ Creates a matrix for rotating points around a certain axis.2444
2445Parameters:
2446AAxis: the direction of the axis to rotate around.
2447AAngle: the rotation angle around AAxis, in radians }
2448procedure InitRotation(const AAxis: TVector3; const AAngle: Single);2449
2450{ Creates a rotation matrix from a yaw, pitch and roll angle.2451
2452Parameters:
2453AYaw: the rotation angle around the Y axis, in radians
2454APitch: the rotation angle around the X axis, in radians
2455ARoll: the rotation angle around the Z axis, in radians }
2456procedure InitRotationYawPitchRoll(const AYaw, APitch, ARoll: Single);2457
2458{ Creates a rotation matrix from a heading, pitch and bank angle.2459
2460Parameters:
2461AHeading: the heading angle, in radians
2462APitch: the pitch angle, in radians
2463ABank: the bank angle, in radians }
2464procedure InitRotationHeadingPitchBank(const AHeading, APitch, ABank: Single);2465
2466{ Creates a left-handed view matrix looking at a certain target.2467
2468Parameters:
2469ACameraPosition: position of the camera (or eye).
2470ACameraTarget: the target towards which the camera is pointing.
2471ACameraUp: the direction that is "up" from the camera's point of view }
2472procedure InitLookAtLH(const ACameraPosition, ACameraTarget, ACameraUp: TVector3);2473
2474{ Creates a right-handed view matrix looking at a certain target.2475
2476Parameters:
2477ACameraPosition: position of the camera (or eye).
2478ACameraTarget: the target towards which the camera is pointing.
2479ACameraUp: the direction that is "up" from the camera's point of view }
2480procedure InitLookAtRH(const ACameraPosition, ACameraTarget, ACameraUp: TVector3);2481
2482{ Creates a left-handed view matrix looking into a certain direction.2483
2484Parameters:
2485ACameraPosition: position of the camera (or eye).
2486ACameraDirection: the direction the camera is pointing in.
2487ACameraUp: the direction that is "up" from the camera's point of view }
2488procedure InitLookAtDirLH(const ACameraPosition, ACameraDirection, ACameraUp: TVector3);2489
2490{ Creates a right-handed view matrix looking into a certain direction.2491
2492Parameters:
2493ACameraPosition: position of the camera (or eye).
2494ACameraDirection: the direction the camera is pointing in.
2495ACameraUp: the direction that is "up" from the camera's point of view }
2496procedure InitLookAtDirRH(const ACameraPosition, ACameraDirection, ACameraUp: TVector3);2497
2498{ Creates a left-handed orthographic projection matrix from the given view2499volume dimensions.
2500
2501Parameters:
2502AWidth: the width of the view volume.
2503AHeight: the height of the view volume.
2504AZNearPlane: the minimum Z-value of the view volume.
2505AZFarPlane: the maximum Z-value of the view volume. }
2506procedure InitOrthoLH(const AWidth, AHeight, AZNearPlane, AZFarPlane: Single);2507
2508{ Creates a right-handed orthographic projection matrix from the given view2509volume dimensions.
2510
2511Parameters:
2512AWidth: the width of the view volume.
2513AHeight: the height of the view volume.
2514AZNearPlane: the minimum Z-value of the view volume.
2515AZFarPlane: the maximum Z-value of the view volume. }
2516procedure InitOrthoRH(const AWidth, AHeight, AZNearPlane, AZFarPlane: Single);2517
2518{ Creates a customized left-handed orthographic projection matrix.2519
2520Parameters:
2521ALeft: the minimum X-value of the view volume.
2522ATop: the maximum Y-value of the view volume.
2523ARight: the maximum X-value of the view volume.
2524ABottom: the minimum Y-value of the view volume.
2525AZNearPlane: the minimum Z-value of the view volume.
2526AZFarPlane: the maximum Z-value of the view volume. }
2527procedure InitOrthoOffCenterLH(const ALeft, ATop, ARight, ABottom,2528AZNearPlane, AZFarPlane: Single);2529
2530{ Creates a customized right-handed orthographic projection matrix.2531
2532Parameters:
2533ALeft: the minimum X-value of the view volume.
2534ATop: the maximum Y-value of the view volume.
2535ARight: the maximum X-value of the view volume.
2536ABottom: the minimum Y-value of the view volume.
2537AZNearPlane: the minimum Z-value of the view volume.
2538AZFarPlane: the maximum Z-value of the view volume. }
2539procedure InitOrthoOffCenterRH(const ALeft, ATop, ARight, ABottom,2540AZNearPlane, AZFarPlane: Single);2541
2542{ Creates a left-handed perspective projection matrix based on a field of2543view, aspect ratio, and near and far view plane distances.
2544
2545Parameters:
2546AFieldOfView: the field of view in radians.
2547AAspectRatio: the aspect ratio, defined as view space width divided by
2548height.
2549ANearPlaneDistance:the distance to the near view plane.
2550AFarPlaneDistance:the distance to the far view plane.
2551AHorizontalFOV: (optional) boolean indicating the direction of the
2552field of view. If False (default), AFieldOfView is in the Y direction,
2553otherwise in the X direction }
2554procedure InitPerspectiveFovLH(const AFieldOfView, AAspectRatio,2555ANearPlaneDistance, AFarPlaneDistance: Single;2556const AHorizontalFOV: Boolean = False);2557
2558{ Creates a right-handed perspective projection matrix based on a field of2559view, aspect ratio, and near and far view plane distances.
2560
2561Parameters:
2562AFieldOfView: the field of view in radians.
2563AAspectRatio: the aspect ratio, defined as view space width divided by
2564height.
2565ANearPlaneDistance:the distance to the near view plane.
2566AFarPlaneDistance:the distance to the far view plane.
2567AHorizontalFOV: (optional) boolean indicating the direction of the
2568field of view. If False (default), AFieldOfView is in the Y direction,
2569otherwise in the X direction }
2570procedure InitPerspectiveFovRH(const AFieldOfView, AAspectRatio,2571ANearPlaneDistance, AFarPlaneDistance: Single;2572const AHorizontalFOV: Boolean = False);2573
2574{ Implicitly converts a TMatrix3D to a TMatrix4. }2575class operator Implicit(const A: TMatrix3D): TMatrix4; inline;2576
2577{ Implicitly converts a TMatrix4 to a TMatrix3D. }2578class operator Implicit(const A: TMatrix4): TMatrix3D; inline;2579
2580{ Checks two matrices for equality.2581
2582Returns:
2583True if the two matrices match each other exactly. }
2584class operator Equal(const A, B: TMatrix4): Boolean; inline;2585
2586{ Checks two matrices for inequality.2587
2588Returns:
2589True if the two matrices are not equal. }
2590class operator NotEqual(const A, B: TMatrix4): Boolean; inline;2591
2592{ Negates a matrix.2593
2594Returns:
2595The negative value of the matrix (with all elements negated). }
2596class operator Negative(const A: TMatrix4): TMatrix4; {$IFDEF FM_INLINE}inline;{$ENDIF}2597
2598{ Adds a scalar value to each element of a matrix. }2599class operator Add(const A: TMatrix4; const B: Single): TMatrix4; {$IFDEF FM_INLINE}inline;{$ENDIF}2600
2601{ Adds a scalar value to each element of a matrix. }2602class operator Add(const A: Single; const B: TMatrix4): TMatrix4; {$IFDEF FM_INLINE}inline;{$ENDIF}2603
2604{ Adds two matrices component-wise. }2605class operator Add(const A, B: TMatrix4): TMatrix4; {$IFDEF FM_INLINE}inline;{$ENDIF}2606
2607{ Subtracts a scalar value from each element of a matrix. }2608class operator Subtract(const A: TMatrix4; const B: Single): TMatrix4; {$IFDEF FM_INLINE}inline;{$ENDIF}2609
2610{ Subtracts a matrix from a scalar value. }2611class operator Subtract(const A: Single; const B: TMatrix4): TMatrix4; {$IFDEF FM_INLINE}inline;{$ENDIF}2612
2613{ Subtracts two matrices component-wise. }2614class operator Subtract(const A, B: TMatrix4): TMatrix4; {$IFDEF FM_INLINE}inline;{$ENDIF}2615
2616{ Multiplies a matrix with a scalar value. }2617class operator Multiply(const A: TMatrix4; const B: Single): TMatrix4; {$IFDEF FM_INLINE}inline;{$ENDIF}2618
2619{ Multiplies a matrix with a scalar value. }2620class operator Multiply(const A: Single; const B: TMatrix4): TMatrix4; {$IFDEF FM_INLINE}inline;{$ENDIF}2621
2622{ Performs a matrix * row vector linear algebraic multiplication. }2623class operator Multiply(const A: TMatrix4; const B: TVector4): TVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}2624
2625{ Performs a column vector * matrix linear algebraic multiplication. }2626class operator Multiply(const A: TVector4; const B: TMatrix4): TVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}2627
2628{ Multiplies two matrices using linear algebraic multiplication. }2629class operator Multiply(const A, B: TMatrix4): TMatrix4; {$IFDEF FM_INLINE}inline;{$ENDIF}2630
2631{ Divides a matrix by a scalar value. }2632class operator Divide(const A: TMatrix4; const B: Single): TMatrix4; {$IFDEF FM_INLINE}inline;{$ENDIF}2633
2634{ Divides a scalar value by a matrix. }2635class operator Divide(const A: Single; const B: TMatrix4): TMatrix4; {$IFDEF FM_INLINE}inline;{$ENDIF}2636
2637{ Divides a matrix by a vector. This is equivalent to multiplying the2638inverse of the matrix with a row vector using linear algebraic
2639multiplication. }
2640class operator Divide(const A: TMatrix4; const B: TVector4): TVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}2641
2642{ Divides a vector by a matrix. This is equivalent to multiplying a column2643vector with the inverse of the matrix using linear algebraic
2644multiplication. }
2645class operator Divide(const A: TVector4; const B: TMatrix4): TVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}2646
2647{ Divides two matrices. This is equivalent to multiplying the first matrix2648with the inverse of the second matrix using linear algebraic
2649multiplication. }
2650class operator Divide(const A, B: TMatrix4): TMatrix4; inline;2651
2652{ Multiplies this matrix with another matrix component-wise.2653
2654Parameters:
2655AOther: the other matrix.
2656
2657Returns:
2658This matrix multiplied by AOther component-wise.
2659That is, Result.M[I,J] := M[I,J] * AOther.M[I,J].
2660
2661@bold(Note): For linear algebraic matrix multiplication, use the multiply
2662(*) operator instead. }
2663function CompMult(const AOther: TMatrix4): TMatrix4; {$IFDEF FM_INLINE}inline;{$ENDIF}2664
2665{ Creates a transposed version of this matrix.2666
2667Returns:
2668The transposed version of this matrix.
2669
2670@bold(Note): Does not change this matrix. To update this itself, use
2671SetTransposed. }
2672function Transpose: TMatrix4; {$IFDEF FM_INLINE}inline;{$ENDIF}2673
2674{ Transposes this matrix.2675
2676@bold(Note): If you do not want to change this matrix, but get a
2677transposed version instead, then use Transpose. }
2678procedure SetTransposed;2679
2680{ Calculates the inverse of this matrix.2681
2682Returns:
2683The inverse of this matrix.
2684
2685@bold(Note): Does not change this matrix. To update this itself, use
2686SetInversed.
2687
2688@bold(Note): The values in the returned matrix are undefined if this
2689matrix is singular or poorly conditioned (nearly singular). }
2690function Inverse: TMatrix4; {$IFDEF FM_INLINE}inline;{$ENDIF}2691
2692{ Inverts this matrix.2693
2694@bold(Note): If you do not want to change this matrix, but get an
2695inversed version instead, then use Inverse.
2696
2697@bold(Note): The values in the inversed matrix are undefined if this
2698matrix is singular or poorly conditioned (nearly singular). }
2699procedure SetInversed;2700
2701{$IFDEF FM_COLUMN_MAJOR}2702{ Returns the columns of the matrix. This is identical to accessing the2703C-field.
2704
2705Parameters:
2706AIndex: index of the column to return (0-3). Range is checked with
2707an assertion. }
2708property Columns[const AIndex: Integer]: TVector4 read GetColumn write SetColumn;2709
2710{ Returns the elements of the matrix (in column-major order).2711This is identical to accessing the M-field, but this property can be used
2712as a default array property.
2713
2714Parameters:
2715AColumn: the column index (0-3). Range is checked with an assertion.
2716ARow: the row index (0-3). Range is checked with an assertion. }
2717property Components[const AColumn, ARow: Integer]: Single read GetComponent write SetComponent; default;2718{$ELSE}2719{ Returns the rows of the matrix. This is identical to accessing the2720R-field.
2721
2722Parameters:
2723AIndex: index of the row to return (0-3). Range is checked with
2724an assertion. }
2725property Rows[const AIndex: Integer]: TVector4 read GetRow write SetRow;2726
2727{ Returns the elements of the matrix (in row-major order).2728This is identical to accessing the M-field, but this property can be used
2729as a default array property.
2730
2731Parameters:
2732ARow: the row index (0-3). Range is checked with an assertion.
2733AColumn: the column index (0-3). Range is checked with an assertion. }
2734property Components[const ARow, AColumn: Integer]: Single read GetComponent write SetComponent; default;2735{$ENDIF}2736
2737{ The determinant of this matrix. }2738property Determinant: Single read GetDeterminant;2739public2740case Byte of2741{ Row or column vectors, depending on FM_COLUMN_MAJOR define }27420: (V: array [0..3] of TVector4);2743
2744{$IFDEF FM_COLUMN_MAJOR}2745{ The four column vectors making up the matrix }27461: (C: array [0..3] of TVector4);2747{$ELSE}2748{ The four row vectors making up the matrix }27492: (R: array [0..3] of TVector4);2750{$ENDIF}2751
2752{ The elements of the matrix in row-major order }27533: (M: array [0..3, 0..3] of Single);27544: (m11, m12, m13, m14: Single;2755m21, m22, m23, m24: Single;2756m31, m32, m33, m34: Single;2757m41, m42, m43, m44: Single);2758end;2759PMatrix4 = ^TMatrix4;2760
2761type
2762{ Adds common constants of type TMatrix2 }2763_TMatrix2Helper = record helper for TMatrix22764public const2765Zero : TMatrix2 = (M: ((0, 0), (0, 0)));2766Identity: TMatrix2 = (M: ((1, 0), (0, 1)));2767public2768{ Initializes the matrix with a 3x3 matrix. The upper-left corner of the27693x3 matrix is copied to the 2x2 matrix.
2770
2771Parameters:
2772AMatrix: the source 3x3 matrix. }
2773
2774procedure Init(const AMatrix: TMatrix3); overload;2775
2776{ Initializes the matrix with a 4x4 matrix. The upper-left corner of the27774x4 matrix is copied to the 3x3 matrix.
2778
2779Parameters:
2780AMatrix: the source 4x4 matrix. }
2781procedure Init(const AMatrix: TMatrix4); overload;2782end;2783
2784type
2785{ Adds common constants of type TMatrix3 }2786_TMatrix3Helper = record helper for TMatrix32787public const2788Zero : TMatrix3 = (M: ((0, 0, 0), (0, 0, 0), (0, 0, 0)));2789Identity: TMatrix3 = (M: ((1, 0, 0), (0, 1, 0), (0, 0, 1)));2790public2791{ Initializes the matrix with a 4x4 matrix. The upper-left corner of the27924x4 matrix is copied to the 3x3 matrix.
2793
2794Parameters:
2795AMatrix: the source 4x4 matrix. }
2796procedure Init(const AMatrix: TMatrix4); overload;2797end;2798
2799type
2800{ Adds common constants of type TMatrix4 }2801_TMatrix4Helper = record helper for TMatrix42802public const2803Zero : TMatrix4 = (M: ((0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0)));2804Identity: TMatrix4 = (M: ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)));2805end;2806
2807type
2808{ A quaternion.2809
2810TQuaternion is compatible with TQuaternion3D in the Delphi RTL. You can
2811typecast between these two types or implicitly convert from one to the other
2812through assignment (eg. MyQuaternion := MyQuaternion3D). }
2813TQuaternion = record2814{$REGION 'Internal Declarations'}2815private2816function GetLength: Single; {$IFDEF FM_INLINE}inline;{$ENDIF}2817function GetLengthSquared: Single; {$IFDEF FM_INLINE}inline;{$ENDIF}2818{$ENDREGION 'Internal Declarations'}2819public2820{ Initializes the quaternion to an identity quaternion. Sets the X, Y and2821Z components to 0 and the W component to 1. }
2822procedure Init; overload; inline;2823
2824{ Sets the four components of the quaternion.2825
2826Parameters:
2827AX: the X-component.
2828AY: the Y-component.
2829AZ: the Z-component.
2830AW: the W-component. }
2831procedure Init(const AX, AY, AZ, AW: Single); overload; inline;2832
2833{ Sets the quaternion from the given axis vector and the angle around that2834axis in radians.
2835
2836Parameters:
2837AAxis: The axis.
2838AAngleRadians: The angle in radians. }
2839procedure Init(const AAxis: TVector3; const AAngleRadians: Single); overload;2840
2841{ Sets the quaternion to the given euler angles in radians.2842
2843Parameters:
2844AYaw: the rotation around the Y axis in radians.
2845APitch: the rotation around the X axis in radians.
2846ARoll: the rotation around the Z axis in radians. }
2847procedure Init(const AYaw, APitch, ARoll: Single); overload;2848
2849{ Sets the quaternion from a matrix.2850
2851Parameters:
2852AMatrix: the matrix. }
2853procedure Init(const AMatrix: TMatrix4); overload;2854
2855{ Creates a rotation matrix that represents this quaternion.2856
2857Returns:
2858A rotation matrix that represents this quaternion. }
2859function ToMatrix: TMatrix4;2860
2861{ Implicitly converts a TQuaternion3D to a TQuaternion. }2862class operator Implicit(const A: TQuaternion3D): TQuaternion; inline;2863
2864{ Implicitly converts a TQuaternion to a TQuaternion3D. }2865class operator Implicit(const A: TQuaternion): TQuaternion3D; inline;2866
2867{ Adds to quaternions together.2868
2869Returns:
2870A + B }
2871class operator Add(const A, B: TQuaternion): TQuaternion; {$IFDEF FM_INLINE}inline;{$ENDIF}2872
2873{ Multiplies a vector with a scalar value.2874
2875Returns:
2876(A.X * B, A.Y * B, A.Z * B, A.W * B) }
2877class operator Multiply(const A: TQuaternion; const B: Single): TQuaternion; {$IFDEF FM_INLINE}inline;{$ENDIF}2878
2879{ Multiplies a vector with a scalar value.2880
2881Returns:
2882(A * B.X, A * B.Y, A * B.Z, A * B.W) }
2883class operator Multiply(const A: Single; const B: TQuaternion): TQuaternion; {$IFDEF FM_INLINE}inline;{$ENDIF}2884
2885{ Multiplies two quaternions.2886
2887Returns:
2888A * B }
2889class operator Multiply(const A, B: TQuaternion): TQuaternion; {$IFDEF FM_INLINE}inline;{$ENDIF}2890
2891{ Whether this is an identity quaternion.2892
2893Returns:
2894True if X, Y and Z are exactly 0.0 and W is exactly 1.0 }
2895function IsIdentity: Boolean; overload; inline;2896
2897{ Whether this is an identity quaternion within a given margin of error.2898
2899Parameters:
2900AErrorMargin: the allowed margin of error.
2901
2902Returns:
2903True if this is an identity quaternion within the error margin. }
2904function IsIdentity(const AErrorMargin: Single): Boolean; overload;2905
2906{ Calculates a normalized version of this quaternion.2907
2908Returns:
2909The normalized quaternion of of this vector (with a length of 1).
2910
2911@bold(Note): for a faster, less accurate version, use NormalizeFast.
2912
2913@bold(Note): Does not change this quaternion. To update this quaternion
2914itself, use SetNormalized. }
2915function Normalize: TQuaternion; inline;2916
2917{ Normalizes this quaternion to a length of 1.2918
2919@bold(Note): The SIMD optimized versions of this method use an
2920approximation, resulting in a very small error.
2921
2922@bold(Note): If you do not want to change this quaternion, but get a
2923normalized version instead, then use Normalize. }
2924procedure SetNormalized; inline;2925
2926{ Calculates a normalized version of this quaternion.2927
2928Returns:
2929The normalized version of of this quaternion (with a length of 1).
2930
2931@bold(Note): this is an SIMD optimized version that uses an approximation,
2932resulting in a small error. For an accurate version, use Normalize.
2933
2934@bold(Note): Does not change this quaternion. To update this quaternion
2935itself, use SetNormalizedFast. }
2936function NormalizeFast: TQuaternion; {$IFDEF FM_INLINE}inline;{$ENDIF}2937
2938{ Normalizes this quaternion to a length of 1.2939
2940@bold(Note): this is an SIMD optimized version that uses an approximation,
2941resulting in a small error. For an accurate version, use SetNormalized.
2942
2943@bold(Note): If you do not want to change this quaternion, but get a
2944normalized version instead, then use NormalizeFast. }
2945procedure SetNormalizedFast; {$IFDEF FM_INLINE}inline;{$ENDIF}2946
2947{ Creates a conjugate of the quaternion.2948
2949Returns:
2950The conjugate (eg. (-X, -Y, -Z, W))
2951
2952@bold(Note): Does not change this quaterion. To update this quaterion
2953itself, use SetConjugate. }
2954function Conjugate: TQuaternion;2955
2956{ Conjugate this quaternion.2957
2958@bold(Note): If you do not want to change this quaternion, but get a
2959conjugate version instead, then use Conjugate. }
2960procedure SetConjugate; inline;2961
2962{ The euclidean length of this quaternion.2963
2964@bold(Note): If you only want to compare lengths of quaternion, you should
2965use LengthSquared instead, which is faster. }
2966property Length: Single read GetLength;2967
2968{ The squared length of the quaternion.2969
2970@bold(Note): This property is faster than Length because it avoids
2971calculating a square root. It is useful for comparing lengths instead of
2972calculating actual lengths. }
2973property LengthSquared: Single read GetLengthSquared;2974public2975case Byte of2976{ X, Y, Z and W components of the quaternion }29770: (X, Y, Z, W: Single);2978
2979{ The four components of the quaternion. }29801: (C: array [0..3] of Single);2981end;2982
2983type
2984{ Adds common constants and functionality to TQuaternion }2985_TQuaternionHelper = record helper for TQuaternion2986public const2987Identity: TQuaternion = (X: 0; Y: 0; Z: 0; W: 1);2988end;2989
2990type
2991{ A 2-dimensional vector that uses integer components instead of2992floating-point components.
2993
2994TIVector2 is compatible with TPoint in the Delphi RTL. You can typecast
2995between these two types or implicitly convert from one to the other through
2996assignment (eg. MyIVector := MyPoint). }
2997TIVector2 = record2998{$REGION 'Internal Declarations'}2999private3000function GetComponent(const AIndex: Integer): Integer; inline;3001procedure SetComponent(const AIndex: Integer; const Value: Integer); inline;3002{$ENDREGION 'Internal Declarations'}3003public3004{ Sets the two elements (X and Y) to 0. }3005procedure Init; overload; inline;3006
3007{ Sets the two elements (X and Y) to A.3008
3009Parameters:
3010A: the value to set the two elements to. }
3011procedure Init(const A: Integer); overload; inline;3012
3013{ Sets the two elements (X and Y) to A1 and A2 respectively.3014
3015Parameters:
3016A1: the value to set the first element to.
3017A2: the value to set the second element to. }
3018procedure Init(const A1, A2: Integer); overload; inline;3019
3020{ Implicitly converts a TPoint to a TIVector2. }3021class operator Implicit(const A: TPoint): TIVector2; inline;3022
3023{ Implicitly converts a TQuaternion to a TPoint. }3024class operator Implicit(const A: TIVector2): TPoint; inline;3025
3026{ Checks two vectors for equality.3027
3028Returns:
3029True if the two vectors match each other. }
3030class operator Equal(const A, B: TIVector2): Boolean; inline;3031
3032{ Checks two vectors for inequality.3033
3034Returns:
3035True if the two vectors are not equal. }
3036class operator NotEqual(const A, B: TIVector2): Boolean; inline;3037
3038{ Negates a vector.3039
3040Returns:
3041The negative value of a vector (eg. (-A.X, -A.Y)) }
3042class operator Negative(const A: TIVector2): TIVector2; inline;3043
3044{ Adds a scalar value to a vector.3045
3046Returns:
3047(A.X + B, A.Y + B) }
3048class operator Add(const A: TIVector2; const B: Integer): TIVector2; {$IFDEF FM_INLINE}inline;{$ENDIF}3049
3050{ Adds a vector to a scalar value.3051
3052Returns:
3053(A + B.X, A + B.Y) }
3054class operator Add(const A: Integer; const B: TIVector2): TIVector2; {$IFDEF FM_INLINE}inline;{$ENDIF}3055
3056{ Adds two vectors.3057
3058Returns:
3059(A.X + B.X, A.Y + B.Y) }
3060class operator Add(const A, B: TIVector2): TIVector2; {$IFDEF FM_INLINE}inline;{$ENDIF}3061
3062{ Subtracts a scalar value from a vector.3063
3064Returns:
3065(A.X - B, A.Y - B) }
3066class operator Subtract(const A: TIVector2; const B: Integer): TIVector2; {$IFDEF FM_INLINE}inline;{$ENDIF}3067
3068{ Subtracts a vector from a scalar value.3069
3070Returns:
3071(A - B.X, A - B.Y) }
3072class operator Subtract(const A: Integer; const B: TIVector2): TIVector2; {$IFDEF FM_INLINE}inline;{$ENDIF}3073
3074{ Subtracts two vectors.3075
3076Returns:
3077(A.X - B.X, A.Y - B.Y) }
3078class operator Subtract(const A, B: TIVector2): TIVector2; {$IFDEF FM_INLINE}inline;{$ENDIF}3079
3080{ Multiplies a vector with a scalar value.3081
3082Returns:
3083(A.X * B, A.Y * B) }
3084class operator Multiply(const A: TIVector2; const B: Integer): TIVector2; {$IFDEF FM_INLINE}inline;{$ENDIF}3085
3086{ Multiplies a scalar value with a vector.3087
3088Returns:
3089(A * B.X, A * B.Y) }
3090class operator Multiply(const A: Integer; const B: TIVector2): TIVector2; {$IFDEF FM_INLINE}inline;{$ENDIF}3091
3092{ Multiplies two vectors component-wise.3093
3094Returns:
3095(A.X * B.X, A.Y * B.Y) }
3096class operator Multiply(const A, B: TIVector2): TIVector2; {$IFDEF FM_INLINE}inline;{$ENDIF}3097
3098{ Divides a vector by a scalar value.3099
3100Returns:
3101(A.X div B, A.Y div B) }
3102class operator IntDivide(const A: TIVector2; const B: Integer): TIVector2; {$IFDEF FM_INLINE}inline;{$ENDIF}3103
3104{ Divides a scalar value by a vector.3105
3106Returns:
3107(A div B.X, A div B.Y) }
3108class operator IntDivide(const A: Integer; const B: TIVector2): TIVector2; {$IFDEF FM_INLINE}inline;{$ENDIF}3109
3110{ Divides two vectors component-wise.3111
3112Returns:
3113(A.X div B.X, A.Y div B.Y) }
3114class operator IntDivide(const A, B: TIVector2): TIVector2; {$IFDEF FM_INLINE}inline;{$ENDIF}3115
3116{ Whether this is a zero vector.3117
3118Returns:
3119True if X and Y are 0 }
3120function IsZero: Boolean; inline;3121
3122{ Returns the components of the vector.3123This is identical to accessing the C-field, but this property can be used
3124as a default array property.
3125
3126Parameters:
3127AIndex: index of the component to return (0 or 1). Range is checked
3128with an assertion. }
3129property Components[const AIndex: Integer]: Integer read GetComponent write SetComponent; default;3130public3131case Byte of3132{ X and Y components of the vector. Aliases for C[0] and C[1]. }31330: (X, Y: Integer);3134
3135{ Red and Green components of the vector. Aliases for C[0] and C[1]. }31361: (R, G: Integer);3137
3138{ S and T components of the vector. Aliases for C[0] and C[1]. }31392: (S, T: Integer);3140
3141{ The two components of the vector. }31423: (C: array [0..1] of Integer);3143end;3144PIVector2 = ^TIVector2;3145
3146type
3147{ Adds common constants of type TVector2 }3148_TVector2Helper = record helper for TVector23149public const3150Zero : TVector2 = (X: 0; Y: 0);3151One : TVector2 = (X: 1; Y: 1);3152UnitX: TVector2 = (X: 1; Y: 0);3153UnitY: TVector2 = (X: 0; Y: 1);3154public3155{ Rounds the components of the vector towards negative infinity.3156
3157Returns:
3158The rounded vector. }
3159function Floor: TIVector2; inline;3160
3161{ Rounds the components of the vector towards positive infinity.3162
3163Returns:
3164The rounded vector. }
3165function Ceiling: TIVector2; inline;3166
3167{ Rounds the components of the vector towards 0.3168
3169Returns:
3170The rounded vector. }
3171function Truncate: TIVector2; inline;3172
3173{ Rounds the components of the vector towards the nearest integer.3174
3175Returns:
3176The rounded vector.
3177
3178If a component is exactly between two integer values (if the fraction is
31790.5), then it is set to the even number }
3180function Round: TIVector2; inline;3181end;3182
3183type
3184{ A 3-dimensional vector that uses integer components instead of3185floating-point components. }
3186TIVector3 = record3187{$REGION 'Internal Declarations'}3188private3189function GetComponent(const AIndex: Integer): Integer; inline;3190procedure SetComponent(const AIndex: Integer; const Value: Integer); inline;3191{$ENDREGION 'Internal Declarations'}3192public3193{ Sets the three elements (X, Y and Z) to 0. }3194procedure Init; overload; inline;3195
3196{ Sets the three elements (X, Y and Z) to A.3197
3198Parameters:
3199A: the value to set the three elements to. }
3200procedure Init(const A: Integer); overload; inline;3201
3202{ Sets the three elements (X, Y and Z) to A1, A2 and A3 respectively.3203
3204Parameters:
3205A1: the value to set the first element to.
3206A2: the value to set the second element to.
3207A3: the value to set the third element to. }
3208procedure Init(const A1, A2, A3: Integer); overload; inline;3209
3210{ Checks two vectors for equality.3211
3212Returns:
3213True if the two vectors match each other exactly. }
3214class operator Equal(const A, B: TIVector3): Boolean; inline;3215
3216{ Checks two vectors for inequality.3217
3218Returns:
3219True if the two vectors are not equal. }
3220class operator NotEqual(const A, B: TIVector3): Boolean; inline;3221
3222{ Negates a vector.3223
3224Returns:
3225The negative value of a vector (eg. (-A.X, -A.Y, -A.Z)) }
3226class operator Negative(const A: TIVector3): TIVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}3227
3228{ Adds a scalar value to a vector.3229
3230Returns:
3231(A.X + B, A.Y + B, A.Z + B) }
3232class operator Add(const A: TIVector3; const B: Integer): TIVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}3233
3234{ Adds a vector to a scalar value.3235
3236Returns:
3237(A + B.X, A + B.Y, A + B.Z) }
3238class operator Add(const A: Integer; const B: TIVector3): TIVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}3239
3240{ Adds two vectors.3241
3242Returns:
3243(A.X + B.X, A.Y + B.Y, A.Z + B.Z) }
3244class operator Add(const A, B: TIVector3): TIVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}3245
3246{ Subtracts a scalar value from a vector.3247
3248Returns:
3249(A.X - B, A.Y - B, A.Z - B) }
3250class operator Subtract(const A: TIVector3; const B: Integer): TIVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}3251
3252{ Subtracts a vector from a scalar value.3253
3254Returns:
3255(A - B.X, A - B.Y, A - B.Z) }
3256class operator Subtract(const A: Integer; const B: TIVector3): TIVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}3257
3258{ Subtracts two vectors.3259
3260Returns:
3261(A.X - B.X, A.Y - B.Y, A.Z - B.Z) }
3262class operator Subtract(const A, B: TIVector3): TIVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}3263
3264{ Multiplies a vector with a scalar value.3265
3266Returns:
3267(A.X * B, A.Y * B, A.Z * B) }
3268class operator Multiply(const A: TIVector3; const B: Integer): TIVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}3269
3270{ Multiplies a scalar value with a vector.3271
3272Returns:
3273(A * B.X, A * B.Y, A * B.Z) }
3274class operator Multiply(const A: Integer; const B: TIVector3): TIVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}3275
3276{ Multiplies two vectors component-wise.3277
3278Returns:
3279(A.X * B.X, A.Y * B.Y, A.Z * B.Z) }
3280class operator Multiply(const A, B: TIVector3): TIVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}3281
3282{ Divides a vector by a scalar value.3283
3284Returns:
3285(A.X div B, A.Y div B, A.Z div B) }
3286class operator IntDivide(const A: TIVector3; const B: Integer): TIVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}3287
3288{ Divides a scalar value by a vector.3289
3290Returns:
3291(A div B.X, A div B.Y, A div B.Z) }
3292class operator IntDivide(const A: Integer; const B: TIVector3): TIVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}3293
3294{ Divides two vectors component-wise.3295
3296Returns:
3297(A.X div B.X, A.Y div B.Y, A.Z div B.Z) }
3298class operator IntDivide(const A, B: TIVector3): TIVector3; {$IFDEF FM_INLINE}inline;{$ENDIF}3299
3300{ Whether this is a zero vector.3301
3302Returns:
3303True if X, Y and Z are 0 }
3304function IsZero: Boolean; inline;3305
3306{ Returns the components of the vector.3307This is identical to accessing the C-field, but this property can be used
3308as a default array property.
3309
3310Parameters:
3311AIndex: index of the component to return (0-2). Range is checked
3312with an assertion. }
3313property Components[const AIndex: Integer]: Integer read GetComponent write SetComponent; default;3314public3315case Byte of3316{ X, Y and Z components of the vector. Aliases for C[0], C[1] and C[2]. }33170: (X, Y, Z: Integer);3318
3319{ Red, Green and Blue components of the vector. Aliases for C[0], C[1]3320and C[2]. }
33211: (R, G, B: Integer);3322
3323{ S, T and P components of the vector. Aliases for C[0], C[1] and C[2]. }33242: (S, T, P: Integer);3325
3326{ The three components of the vector. }33273: (C: array [0..2] of Integer);3328end;3329PIVector3 = ^TIVector3;3330
3331type
3332{ Adds common constants of type TVector3 }3333_TVector3Helper = record helper for TVector33334public const3335Zero : TVector3 = (X: 0; Y: 0; Z: 0);3336One : TVector3 = (X: 1; Y: 1; Z: 1);3337UnitX: TVector3 = (X: 1; Y: 0; Z: 0);3338UnitY: TVector3 = (X: 0; Y: 1; Z: 0);3339UnitZ: TVector3 = (X: 0; Y: 0; Z: 1);3340public3341{ Rounds the components of the vector towards negative infinity.3342
3343Returns:
3344The rounded vector. }
3345function Floor: TIVector3; inline;3346
3347{ Rounds the components of the vector towards positive infinity.3348
3349Returns:
3350The rounded vector. }
3351function Ceiling: TIVector3; inline;3352
3353{ Rounds the components of the vector towards 0.3354
3355Returns:
3356The rounded vector. }
3357function Truncate: TIVector3; inline;3358
3359{ Rounds the components of the vector towards the nearest integer.3360
3361Returns:
3362The rounded vector.
3363
3364If a component is exactly between two integer values (if the fraction is
33650.5), then it is set to the even number }
3366function Round: TIVector3; inline;3367end;3368
3369type
3370{ A 4-dimensional vector that uses integer components instead of3371floating-point components. }
3372TIVector4 = record3373{$REGION 'Internal Declarations'}3374private3375function GetComponent(const AIndex: Integer): Integer; inline;3376procedure SetComponent(const AIndex: Integer; const Value: Integer); inline;3377{$ENDREGION 'Internal Declarations'}3378public3379{ Sets the four elements (X, Y, Z and W) to 0. }3380procedure Init; overload; inline;3381
3382{ Sets the four elements (X, Y, Z and W) to A.3383
3384Parameters:
3385A: the value to set the three elements to. }
3386procedure Init(const A: Integer); overload; inline;3387
3388{ Sets the four elements (X, Y, Z and W) to A1, A2, A3 and A4 respectively.3389
3390Parameters:
3391A1: the value to set the first element to.
3392A2: the value to set the second element to.
3393A3: the value to set the third element to.
3394A4: the value to set the fourth element to. }
3395procedure Init(const A1, A2, A3, A4: Integer); overload; inline;3396
3397{ Checks two vectors for equality.3398
3399Returns:
3400True if the two vectors match each other. }
3401class operator Equal(const A, B: TIVector4): Boolean; inline;3402
3403{ Checks two vectors for inequality.3404
3405Returns:
3406True if the two vectors are not equal. }
3407class operator NotEqual(const A, B: TIVector4): Boolean; inline;3408
3409{ Negates a vector.3410
3411Returns:
3412The negative value of a vector (eg. (-A.X, -A.Y, -A.Z, -A.W)) }
3413class operator Negative(const A: TIVector4): TIVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}3414
3415{ Adds a scalar value to a vector.3416
3417Returns:
3418(A.X + B, A.Y + B, A.Z + B, A.W + B) }
3419class operator Add(const A: TIVector4; const B: Integer): TIVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}3420
3421{ Adds a vector to a scalar value.3422
3423Returns:
3424(A + B.X, A + B.Y, A + B.Z, A + B.W) }
3425class operator Add(const A: Integer; const B: TIVector4): TIVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}3426
3427{ Adds two vectors.3428
3429Returns:
3430(A.X + B.X, A.Y + B.Y, A.Z + B.Z, A.W + B.W) }
3431class operator Add(const A, B: TIVector4): TIVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}3432
3433{ Subtracts a scalar value from a vector.3434
3435Returns:
3436(A.X - B, A.Y - B, A.Z - B, A.W - B) }
3437class operator Subtract(const A: TIVector4; const B: Integer): TIVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}3438
3439{ Subtracts a vector from a scalar value.3440
3441Returns:
3442(A - B.X, A - B.Y, A - B.Z, A - B.W) }
3443class operator Subtract(const A: Integer; const B: TIVector4): TIVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}3444
3445{ Subtracts two vectors.3446
3447Returns:
3448(A.X - B.X, A.Y - B.Y, A.Z - B.Z, A.W - B.W) }
3449class operator Subtract(const A, B: TIVector4): TIVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}3450
3451{ Multiplies a vector with a scalar value.3452
3453Returns:
3454(A.X * B, A.Y * B, A.Z * B, A.W * B) }
3455class operator Multiply(const A: TIVector4; const B: Integer): TIVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}3456
3457{ Multiplies a scalar value with a vector.3458
3459Returns:
3460(A * B.X, A * B.Y, A * B.Z, A * B.W) }
3461class operator Multiply(const A: Integer; const B: TIVector4): TIVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}3462
3463{ Multiplies two vectors component-wise.3464
3465Returns:
3466(A.X * B.X, A.Y * B.Y, A.Z * B.Z, A.W * B.W) }
3467class operator Multiply(const A, B: TIVector4): TIVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}3468
3469{ Divides a vector by a scalar value.3470
3471Returns:
3472(A.X div B, A.Y div B, A.Z div B, A.W div B) }
3473class operator IntDivide(const A: TIVector4; const B: Integer): TIVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}3474
3475{ Divides a scalar value by a vector.3476
3477Returns:
3478(A div B.X, A div B.Y, A div B.Z, A div B.W) }
3479class operator IntDivide(const A: Integer; const B: TIVector4): TIVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}3480
3481{ Divides two vectors component-wise.3482
3483Returns:
3484(A.X div B.X, A.Y div B.Y, A.Z div B.Z, A.W div B.W) }
3485class operator IntDivide(const A, B: TIVector4): TIVector4; {$IFDEF FM_INLINE}inline;{$ENDIF}3486
3487{ Whether this is a zero vector.3488
3489Returns:
3490True if X, Y, Z and W are 0 }
3491function IsZero: Boolean; inline;3492
3493{ Returns the components of the vector.3494This is identical to accessing the C-field, but this property can be used
3495as a default array property.
3496
3497Parameters:
3498AIndex: index of the component to return (0-3). Range is checked
3499with an assertion. }
3500property Components[const AIndex: Integer]: Integer read GetComponent write SetComponent; default;3501public3502case Byte of3503{ X, Y, Z and W components of the vector. Aliases for C[0], C[1], C[2]3504and C[3]. }
35050: (X, Y, Z, W: Integer);3506
3507{ Red, Green, Blue and Alpha components of the vector. Aliases for C[0],3508C[1], C[2] and C[3]. }
35091: (R, G, B, A: Integer);3510
3511{ S, T, P and Q components of the vector. Aliases for C[0], C[1], C[2] and3512C[3]. }
35132: (S, T, P, Q: Integer);3514
3515{ The four components of the vector. }35163: (C: array [0..3] of Integer);3517end;3518PIVector4 = ^TIVector4;3519
3520type
3521{ Adds common constants of type TVector4 }3522_TVector4Helper = record helper for TVector43523public const3524Zero : TVector4 = (X: 0; Y: 0; Z: 0; W: 0);3525One : TVector4 = (X: 1; Y: 1; Z: 1; W: 1);3526UnitX: TVector4 = (X: 1; Y: 0; Z: 0; W: 0);3527UnitY: TVector4 = (X: 0; Y: 1; Z: 0; W: 0);3528UnitZ: TVector4 = (X: 0; Y: 0; Z: 1; W: 0);3529UnitW: TVector4 = (X: 0; Y: 0; Z: 0; W: 1);3530public3531{ Rounds the components of the vector towards negative infinity.3532
3533Returns:
3534The rounded vector. }
3535function Floor: TIVector4; inline;3536
3537{ Rounds the components of the vector towards positive infinity.3538
3539Returns:
3540The rounded vector. }
3541function Ceiling: TIVector4; inline;3542
3543{ Rounds the components of the vector towards 0.3544
3545Returns:
3546The rounded vector. }
3547function Truncate: TIVector4; inline;3548
3549{ Rounds the components of the vector towards the nearest integer.3550
3551Returns:
3552The rounded vector.
3553
3554If a component is exactly between two integer values (if the fraction is
35550.5), then it is set to the even number }
3556function Round: TIVector4; inline;3557end;3558
3559{******************************************************}
3560{* Helper functions for creating vectors and matrices *}
3561{* Note that these are (much) less efficient than the *}
3562{* respective Init methods *}
3563{******************************************************}
3564
3565{***** TVector2 *****}
3566
3567{ Creates a 2D zero-vector.
3568
3569@bold(Note): it is more efficient to use TVector2.Init instead. }
3570function Vector2: TVector2; overload; inline;3571
3572{ Creates a 2D vector with the two elements (X and Y) set to A.
3573
3574Parameters:
3575A: the value to set the two elements to.
3576
3577@bold(Note): it is more efficient to use TVector2.Init instead. }
3578function Vector2(const A: Single): TVector2; overload; inline;3579
3580{ Creates a 2D vector with the two elements (X and Y) set to A1 and A2
3581respectively.
3582
3583Parameters:
3584A1: the value to set the first element to.
3585A2: the value to set the second element to.
3586
3587@bold(Note): it is more efficient to use TVector2.Init instead. }
3588function Vector2(const A1, A2: Single): TVector2; overload; inline;3589
3590{ Creates a 2D vector using the first to elements (X and Y) of a 3D vector.
3591
3592Parameters:
3593AVector: the source vector
3594
3595@bold(Note): it is more efficient to use TVector2.Init instead. }
3596function Vector2(const AVector: TVector3): TVector2; overload; inline;3597
3598{ Creates a 2D vector using the first two elements (X and Y) of a 4D vector.
3599
3600Parameters:
3601AVector: the source vector
3602
3603@bold(Note): it is more efficient to use TVector2.Init instead. }
3604function Vector2(const AVector: TVector4): TVector2; overload; inline;3605
3606{***** TVector3 *****}
3607
3608{ Creates a 3D zero-vector.
3609
3610@bold(Note): it is more efficient to use TVector3.Init instead. }
3611function Vector3: TVector3; overload;3612
3613{ Creates a 3D vector with the three elements (X, Y and Z) set to A.
3614
3615Parameters:
3616A: the value to set the three elements to.
3617
3618@bold(Note): it is more efficient to use TVector3.Init instead. }
3619function Vector3(const A: Single): TVector3; overload;3620
3621{ Creates a 3D vector with the three elements (X, Y and Z) set to A1, A2 and A3
3622respectively.
3623
3624Parameters:
3625A1: the value to set the first element to.
3626A2: the value to set the second element to.
3627A3: the value to set the third element to.
3628
3629@bold(Note): it is more efficient to use TVector3.Init instead. }
3630function Vector3(const A1, A2, A3: Single): TVector3; overload;3631
3632{ Creates a 3D vector with the first two elements from a 2D vector, and the
3633third element from a scalar.
3634
3635Parameters:
3636A1: the vector to use for the first two elements.
3637A2: the value to set the third element to.
3638
3639@bold(Note): it is more efficient to use TVector3.Init instead. }
3640function Vector3(const A1: TVector2; const A2: Single): TVector3; overload;3641
3642{ Creates a 3D vector with the first element from a scaler, and the last two
3643elements from a 2D vector.
3644
3645Parameters:
3646A1: the value to set the first element to.
3647A2: the vector to use for the last two elements.
3648
3649@bold(Note): it is more efficient to use TVector3.Init instead. }
3650function Vector3(const A1: Single; const A2: TVector2): TVector3; overload;3651
3652{ Creates a 3D vector using the first three elements (X, Y and Z) of a 4D vector.
3653
3654Parameters:
3655AVector: the source vector
3656
3657@bold(Note): it is more efficient to use TVector3.Init instead. }
3658function Vector3(const AVector: TVector4): TVector3; overload;3659
3660{***** TVector4 *****}
3661
3662{ Creates a 4D zero-vector.
3663
3664@bold(Note): it is more efficient to use TVector4.Init instead. }
3665function Vector4: TVector4; overload;3666
3667{ Creates a 4D vector with the four elements (X, Y, Z and W) set to A.
3668
3669Parameters:
3670A: the value to set the four elements to.
3671
3672@bold(Note): it is more efficient to use TVector4.Init instead. }
3673function Vector4(const A: Single): TVector4; overload;3674
3675{ Creates a 4D vector with the four elements (X, Y, Z and W) set to A1, A2, A3
3676and A4 respectively.
3677
3678Parameters:
3679A1: the value to set the first element to.
3680A2: the value to set the second element to.
3681A3: the value to set the third element to.
3682A4: the value to set the fourth element to.
3683
3684@bold(Note): it is more efficient to use TVector4.Init instead. }
3685function Vector4(const A1, A2, A3, A4: Single): TVector4; overload;3686
3687{ Creates a 4D vector with the first two elements from a 2D vector, and the last
3688two elements from two scalars.
3689
3690Parameters:
3691A1: the vector to use for the first two elements.
3692A2: the value to set the third element to.
3693A3: the value to set the fourth element to.
3694
3695@bold(Note): it is more efficient to use TVector4.Init instead. }
3696function Vector4(const A1: TVector2; const A2, A3: Single): TVector4; overload;3697
3698{ Creates a 4D vector with the first and last elements from two scalars, and the
3699middle two elements from a 2D vector.
3700
3701Parameters:
3702A1: the value to set the first element to.
3703A2: the vector to use for the second and third elements.
3704A3: the value to set the fourth element to.
3705
3706@bold(Note): it is more efficient to use TVector4.Init instead. }
3707function Vector4(const A1: Single; const A2: TVector2; const A3: Single): TVector4; overload;3708
3709{ Creates a 4D vector with the first two elements from two scalars and the last
3710two elements from a 2D vector.
3711
3712Parameters:
3713A1: the value to set the first element to.
3714A2: the value to set the second element to.
3715A3: the vector to use for the last two elements.
3716
3717@bold(Note): it is more efficient to use TVector4.Init instead. }
3718function Vector4(const A1, A2: Single; const A3: TVector2): TVector4; overload;3719
3720{ Creates a 4D vector with the first two elements and last two elements from two
37212D vectors.
3722
3723Parameters:
3724A1: the vector to use for the first two elements.
3725A2: the vector to use for the last two elements.
3726
3727@bold(Note): it is more efficient to use TVector4.Init instead. }
3728function Vector4(const A1, A2: TVector2): TVector4; overload;3729
3730{ Creates a 4D vector with the first three elements from a 3D vector, and the
3731fourth element from a scalar.
3732
3733Parameters:
3734A1: the vector to use for the first three elements.
3735A2: the value to set the fourth element to.
3736
3737@bold(Note): it is more efficient to use TVector4.Init instead. }
3738function Vector4(const A1: TVector3; const A2: Single): TVector4; overload;3739
3740{ Creates a 4D vector with the first element from a scaler, and the last three
3741elements from a 3D vector.
3742
3743Parameters:
3744A1: the value to set the first element to.
3745A2: the vector to use for the last three elements.
3746
3747@bold(Note): it is more efficient to use TVector4.Init instead. }
3748function Vector4(const A1: Single; const A2: TVector3): TVector4; overload;3749
3750{***** TQuaternion *****}
3751
3752{ Creates an identity quaternion (with X, Y and Z set to 0 and W set to 1).
3753
3754@bold(Note): it is more efficient to use TQuaternion.Init instead. }
3755function Quaternion: TQuaternion; overload;3756
3757{ Creates a quaternion with the given components.
3758
3759Parameters:
3760AX: the X-component.
3761AY: the Y-component.
3762AZ: the Z-component.
3763AW: the W-component.
3764
3765@bold(Note): it is more efficient to use TQuaternion.Init instead. }
3766function Quaternion(const AX, AY, AZ, AW: Single): TQuaternion; overload;3767
3768{ Creates a quaternion from the given axis vector and the angle around that
3769axis in radians.
3770
3771Parameters:
3772AAxis: The axis.
3773AAngleRadians: The angle in radians.
3774
3775@bold(Note): it is more efficient to use TQuaternion.Init instead. }
3776function Quaternion(const AAxis: TVector3; const AAngleRadians: Single): TQuaternion; overload;3777
3778{***** TMatrix2 *****}
3779
3780{ Creates a 2x2 identity matrix
3781
3782@bold(Note): it is more efficient to use TMatrix2.Init instead. }
3783function Matrix2: TMatrix2; overload;3784
3785{ Creates a 2x2 matrix fill with zeros and sets the diagonal.
3786
3787Parameters:
3788ADiagonal: the value to use for the diagonal. Use 1 for an identity matrix.
3789
3790@bold(Note): it is more efficient to use TMatrix2.Init instead. }
3791function Matrix2(const ADiagonal: Single): TMatrix2; overload;3792
3793{ Creates a 2x2 matrix using two row vectors.
3794
3795Parameters:
3796ARow0: the first row of the matrix.
3797ARow1: the second row of the matrix.
3798
3799@bold(Note): it is more efficient to use TMatrix2.Init instead. }
3800function Matrix2(const ARow0, ARow1: TVector2): TMatrix2; overload;3801
3802{ Creates a 2x2 matrix with explicit values.
3803
3804Parameters:
3805A11-A12: the values of the matrix elements, in row-major order.
3806
3807@bold(Note): it is more efficient to use TMatrix2.Init instead. }
3808function Matrix2(const A11, A12, A21, A22: Single): TMatrix2; overload;3809
3810{ Creates a 2x2 using the top-left corner of a 3x3 matrix.
3811The remaining values of the source matrix are not used.
3812
3813Parameters:
3814AMatrix: the source 3x3 matrix.
3815
3816@bold(Note): it is more efficient to use TMatrix2.Init instead. }
3817function Matrix2(const AMatrix: TMatrix3): TMatrix2; overload;3818
3819{ Creates a 2x2 using the top-left corner of a 4x4 matrix.
3820The remaining values of the source matrix are not used.
3821
3822Parameters:
3823AMatrix: the source 4x4 matrix.
3824
3825@bold(Note): it is more efficient to use TMatrix2.Init instead. }
3826function Matrix2(const AMatrix: TMatrix4): TMatrix2; overload;3827
3828{***** TMatrix3 *****}
3829
3830{ Creates a 3x3 identity matrix
3831
3832@bold(Note): it is more efficient to use TMatrix3.Init instead. }
3833function Matrix3: TMatrix3; overload;3834
3835{ Creates a 3x3 matrix fill with zeros and sets the diagonal.
3836
3837Parameters:
3838ADiagonal: the value to use for the diagonal. Use 1 for an identity matrix.
3839
3840@bold(Note): it is more efficient to use TMatrix3.Init instead. }
3841function Matrix3(const ADiagonal: Single): TMatrix3; overload;3842
3843{ Creates a 3x3 matrix using three row vectors.
3844
3845Parameters:
3846ARow0: the first row of the matrix.
3847ARow1: the second row of the matrix.
3848ARow2: the third row of the matrix.
3849
3850@bold(Note): it is more efficient to use TMatrix3.Init instead. }
3851function Matrix3(const ARow0, ARow1, ARow2: TVector3): TMatrix3; overload;3852
3853{ Creates a 3x3 matrix with explicit values.
3854
3855Parameters:
3856A11-A33: the values of the matrix elements, in row-major order.
3857
3858@bold(Note): it is more efficient to use TMatrix3.Init instead. }
3859function Matrix3(const A11, A12, A13, A21, A22, A23, A31, A32, A33: Single): TMatrix3; overload;3860
3861{ Creates a 3x3 matrix by copying a 2x2 matrix to the top-left corner of the 3x3
3862matrix, and setting the remaining elements according to an identity matrix.
3863
3864Parameters:
3865AMatrix: the source 2x2 matrix.
3866
3867@bold(Note): it is more efficient to use TMatrix3.Init instead. }
3868function Matrix3(const AMatrix: TMatrix2): TMatrix3; overload;3869
3870{ Creates a 3x3 using the top-left corner of a 4x4 matrix.
3871The remaining values of the source matrix are not used.
3872
3873Parameters:
3874AMatrix: the 4x4 source matrix.
3875
3876@bold(Note): it is more efficient to use TMatrix3.Init instead. }
3877function Matrix3(const AMatrix: TMatrix4): TMatrix3; overload;3878
3879{***** TMatrix4 *****}
3880
3881{ Creates a 4x4 identity matrix
3882
3883@bold(Note): it is more efficient to use TMatrix4.Init instead. }
3884function Matrix4: TMatrix4; overload;3885
3886{ Creates a 4x4 matrix fill with zeros and sets the diagonal.
3887
3888Parameters:
3889ADiagonal: the value to use for the diagonal. Use 1 for an identity matrix.
3890
3891@bold(Note): it is more efficient to use TMatrix4.Init instead. }
3892function Matrix4(const ADiagonal: Single): TMatrix4; overload;3893
3894{ Creates a 4x4 matrix using four row vectors.
3895
3896Parameters:
3897ARow0: the first row of the matrix.
3898ARow1: the second row of the matrix.
3899ARow2: the third row of the matrix.
3900ARow3: the fourth row of the matrix.
3901
3902@bold(Note): it is more efficient to use TMatrix4.Init instead. }
3903function Matrix4(const ARow0, ARow1, ARow2, ARow3: TVector4): TMatrix4; overload;3904
3905{ Creates a 4x4 matrix with explicit values.
3906
3907Parameters:
3908A11-A44: the values of the matrix elements, in row-major order.
3909
3910@bold(Note): it is more efficient to use TMatrix4.Init instead. }
3911function Matrix4(const A11, A12, A13, A14, A21, A22, A23, A24, A31, A32, A33,3912A34, A41, A42, A43, A44: Single): TMatrix4; overload;3913
3914{ Creates a 4x4 matrix by copying a 2x2 matrix to the top-left corner of the 4x4
3915matrix, and setting the remaining elements according to an identity matrix.
3916
3917Parameters:
3918AMatrix: the source 2x2 matrix.
3919
3920@bold(Note): it is more efficient to use TMatrix4.Init instead. }
3921function Matrix4(const AMatrix: TMatrix2): TMatrix4; overload;3922
3923{ Creates a 4x4 matrix by copying a 3x3 matrix to the top-left corner of the 4x4
3924matrix, and setting the remaining elements according to an identity matrix.
3925
3926Parameters:
3927AMatrix: the source 3x3 matrix.
3928
3929@bold(Note): it is more efficient to use TMatrix4.Init instead. }
3930function Matrix4(const AMatrix: TMatrix3): TMatrix4; overload;3931
3932{***** TIVector2 *****}
3933
3934{ Creates a 2D zero-vector.
3935
3936@bold(Note): it is more efficient to use TIVector2.Init instead. }
3937function IVector2: TIVector2; overload; inline;3938
3939{ Creates a 2D vector with the two elements (X and Y) set to A.
3940
3941Parameters:
3942A: the value to set the two elements to.
3943
3944@bold(Note): it is more efficient to use TIVector2.Init instead. }
3945function IVector2(const A: Integer): TIVector2; overload; inline;3946
3947{ Creates a 2D vector with the two elements (X and Y) set to A1 and A2
3948respectively.
3949
3950Parameters:
3951A1: the value to set the first element to.
3952A2: the value to set the second element to.
3953
3954@bold(Note): it is more efficient to use TIVector2.Init instead. }
3955function IVector2(const A1, A2: Integer): TIVector2; overload; inline;3956
3957{***** TIVector3 *****}
3958
3959{ Creates a 3D zero-vector.
3960
3961@bold(Note): it is more efficient to use TIVector3.Init instead. }
3962function IVector3: TIVector3; overload;3963
3964{ Creates a 3D vector with the three elements (X, Y and Z) set to A.
3965
3966Parameters:
3967A: the value to set the three elements to.
3968
3969@bold(Note): it is more efficient to use TIVector3.Init instead. }
3970function IVector3(const A: Integer): TIVector3; overload;3971
3972{ Creates a 3D vector with the three elements (X, Y and Z) set to A1, A2 and A3
3973respectively.
3974
3975Parameters:
3976A1: the value to set the first element to.
3977A2: the value to set the second element to.
3978A3: the value to set the third element to.
3979
3980@bold(Note): it is more efficient to use TIVector3.Init instead. }
3981function IVector3(const A1, A2, A3: Integer): TIVector3; overload;3982
3983{***** TIVector4 *****}
3984
3985{ Creates a 4D zero-vector.
3986
3987@bold(Note): it is more efficient to use TIVector4.Init instead. }
3988function IVector4: TIVector4; overload;3989
3990{ Creates a 4D vector with the four elements (X, Y, Z and W) set to A.
3991
3992Parameters:
3993A: the value to set the four elements to.
3994
3995@bold(Note): it is more efficient to use TIVector4.Init instead. }
3996function IVector4(const A: Integer): TIVector4; overload;3997
3998{ Creates a 4D vector with the four elements (X, Y, Z and W) set to A1, A2, A3
3999and A4 respectively.
4000
4001Parameters:
4002A1: the value to set the first element to.
4003A2: the value to set the second element to.
4004A3: the value to set the third element to.
4005A4: the value to set the fourth element to.
4006
4007@bold(Note): it is more efficient to use TIVector4.Init instead. }
4008function IVector4(const A1, A2, A3, A4: Integer): TIVector4; overload;4009
4010{******************************************************}
4011{* Angle and Trigonometry Functions *}
4012{******************************************************}
4013
4014{ Converts degrees to radians.
4015
4016Parameters:
4017ADegrees: number of degrees.
4018
4019Returns:
4020ADegrees converted to radians. }
4021function Radians(const ADegrees: Single): Single; overload; inline;4022function Radians(const ADegrees: TVector2): TVector2; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4023function Radians(const ADegrees: TVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4024function Radians(const ADegrees: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4025
4026{ Converts radians to degrees.
4027
4028Parameters:
4029ARadians: number of radians.
4030
4031Returns:
4032ARadians converted to degrees. }
4033function Degrees(const ARadians: Single): Single; overload; inline;4034function Degrees(const ARadians: TVector2): TVector2; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4035function Degrees(const ARadians: TVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4036function Degrees(const ARadians: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4037
4038{ Calculates the sine of an angle.
4039
4040Parameters:
4041ARadians: the angle in radians.
4042
4043Returns:
4044The sine of the given angle.
4045
4046@bold(Note): You probably want to use FastSin instead, which is much faster
4047but still very accurate to about +/-4000 radians (or +/-230,000 degrees). }
4048function Sin(const ARadians: Single): Single; overload; inline;4049function Sin(const ARadians: TVector2): TVector2; overload; inline;4050function Sin(const ARadians: TVector3): TVector3; overload; inline;4051function Sin(const ARadians: TVector4): TVector4; overload; inline;4052
4053{ Calculates the cosine of an angle.
4054
4055Parameters:
4056ARadians: the angle in radians.
4057
4058Returns:
4059The cosine of the given angle.
4060
4061@bold(Note): You probably want to use FastCos instead, which is much faster
4062but still very accurate to about +/-4000 radians (or +/-230,000 degrees). }
4063function Cos(const ARadians: Single): Single; overload; inline;4064function Cos(const ARadians: TVector2): TVector2; overload; inline;4065function Cos(const ARadians: TVector3): TVector3; overload; inline;4066function Cos(const ARadians: TVector4): TVector4; overload; inline;4067
4068{ Calculates the sine and cosine of an angle. This is faster than calling Sin
4069and Cos separately.
4070
4071Parameters:
4072ARadians: the angle in radians.
4073ASin: is set to the sine of the angle.
4074ACos: is set to the cosine of the angle.
4075
4076@bold(Note): You probably want to use FastSinCos instead, which is much faster
4077but still very accurate to about +/-4000 radians (or +/-230,000 degrees). }
4078procedure SinCos(const ARadians: Single; out ASin, ACos: Single); overload;4079procedure SinCos(const ARadians: TVector2; out ASin, ACos: TVector2); overload;4080procedure SinCos(const ARadians: TVector3; out ASin, ACos: TVector3); overload;4081procedure SinCos(const ARadians: TVector4; out ASin, ACos: TVector4); overload;4082
4083{ Calculates the tangent of an angle.
4084
4085Parameters:
4086ARadians: the angle in radians.
4087
4088Returns:
4089The tangent of the given angle.
4090
4091@bold(Note): You probably want to use FastTan instead, which is much faster
4092but still very accurate to about +/-4000 radians (or +/-230,000 degrees). }
4093function Tan(const ARadians: Single): Single; overload; inline;4094function Tan(const ARadians: TVector2): TVector2; overload; inline;4095function Tan(const ARadians: TVector3): TVector3; overload; inline;4096function Tan(const ARadians: TVector4): TVector4; overload; inline;4097
4098{ Calculates the angle whose sine is A.
4099
4100Parameters:
4101A: the sine whose angle to calculate. Results are undefined if (A < -1) or
4102(A > 1).
4103
4104Returns:
4105The angle in radians, in the range [-Pi/2..Pi/2] }
4106function ArcSin(const A: Single): Single; overload; inline;4107function ArcSin(const A: TVector2): TVector2; overload; inline;4108function ArcSin(const A: TVector3): TVector3; overload; inline;4109function ArcSin(const A: TVector4): TVector4; overload; inline;4110
4111{ Calculates the angle whose cosine is A.
4112
4113Parameters:
4114A: the cosine whose angle to calculate. Results are undefined if (A < -1) or
4115(A > 1).
4116
4117Returns:
4118The angle in radians, in the range [0..Pi] }
4119function ArcCos(const A: Single): Single; overload; inline;4120function ArcCos(const A: TVector2): TVector2; overload; inline;4121function ArcCos(const A: TVector3): TVector3; overload; inline;4122function ArcCos(const A: TVector4): TVector4; overload; inline;4123
4124{ Calculates the angle whose tangent is A.
4125
4126Parameters:
4127A: the tangent whose angle to calculate.
4128
4129Returns:
4130The angle in radians, in the range [-Pi/2..Pi/2] }
4131function ArcTan(const A: Single): Single; overload; inline;4132function ArcTan(const A: TVector2): TVector2; overload; inline;4133function ArcTan(const A: TVector3): TVector3; overload; inline;4134function ArcTan(const A: TVector4): TVector4; overload; inline;4135
4136{ Calculates the principal value of the arctangent of Y/X, expressed in radians.
4137
4138Parameters:
4139Y: proportion of the Y-coordinate.
4140X: proportion of the X-coordinate.
4141
4142Returns:
4143The angle in radians, in the range [-Pi..Pi] }
4144function ArcTan2(const Y, X: Single): Single; overload; inline;4145function ArcTan2(const Y, X: TVector2): TVector2; overload; inline;4146function ArcTan2(const Y, X: TVector3): TVector3; overload; inline;4147function ArcTan2(const Y, X: TVector4): TVector4; overload; inline;4148
4149{ Calculates a hyperbolic sine.
4150
4151Parameters:
4152A: the value.
4153
4154Returns:
4155The hyperbolic sine of A. }
4156function Sinh(const A: Single): Single; overload; inline;4157function Sinh(const A: TVector2): TVector2; overload; inline;4158function Sinh(const A: TVector3): TVector3; overload; inline;4159function Sinh(const A: TVector4): TVector4; overload; inline;4160
4161{ Calculates a hyperbolic cosine.
4162
4163Parameters:
4164A: the value.
4165
4166Returns:
4167The hyperbolic cosine of A. }
4168function Cosh(const A: Single): Single; overload; inline;4169function Cosh(const A: TVector2): TVector2; overload; inline;4170function Cosh(const A: TVector3): TVector3; overload; inline;4171function Cosh(const A: TVector4): TVector4; overload; inline;4172
4173{ Calculates a hyperbolic tangent.
4174
4175Parameters:
4176A: the value.
4177
4178Returns:
4179The hyperbolic tangent of A. }
4180function Tanh(const A: Single): Single; overload; inline;4181function Tanh(const A: TVector2): TVector2; overload; inline;4182function Tanh(const A: TVector3): TVector3; overload; inline;4183function Tanh(const A: TVector4): TVector4; overload; inline;4184
4185{ Calculates an inverse hyperbolic sine.
4186
4187Parameters:
4188A: the value.
4189
4190Returns:
4191The inverse hyperbolic sine of A. }
4192function ArcSinh(const A: Single): Single; overload; inline;4193function ArcSinh(const A: TVector2): TVector2; overload; inline;4194function ArcSinh(const A: TVector3): TVector3; overload; inline;4195function ArcSinh(const A: TVector4): TVector4; overload; inline;4196
4197{ Calculates an inverse hyperbolic cosine.
4198
4199Parameters:
4200A: the value.
4201
4202Returns:
4203The inverse hyperbolic cosine of A. }
4204function ArcCosh(const A: Single): Single; overload; inline;4205function ArcCosh(const A: TVector2): TVector2; overload; inline;4206function ArcCosh(const A: TVector3): TVector3; overload; inline;4207function ArcCosh(const A: TVector4): TVector4; overload; inline;4208
4209{ Calculates an inverse hyperbolic tangent.
4210
4211Parameters:
4212A: the value.
4213
4214Returns:
4215The inverse hyperbolic tangent of A. }
4216function ArcTanh(const A: Single): Single; overload; inline;4217function ArcTanh(const A: TVector2): TVector2; overload; inline;4218function ArcTanh(const A: TVector3): TVector3; overload; inline;4219function ArcTanh(const A: TVector4): TVector4; overload; inline;4220
4221{******************************************************}
4222{* Exponential Functions *}
4223{******************************************************}
4224
4225{ Calculates ABase raised to the AExponent power.
4226
4227Parameters:
4228ABase: the base value. Must be >= 0.
4229AExponent: the exponent value.
4230
4231Returns:
4232ABase raised to the AExponent power. Results are undefined if both ABase=0
4233and AExponent<=0.
4234
4235@bold(Note): Consider using FastPower instead, which is much faster, but at a
4236maximum relative error of about 0.2%. }
4237function Power(const ABase, AExponent: Single): Single; overload; inline;4238function Power(const ABase, AExponent: TVector2): TVector2; overload; inline;4239function Power(const ABase, AExponent: TVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4240function Power(const ABase, AExponent: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4241
4242{ Calculates a natural exponentiation (that is, e raised to a given power).
4243
4244Parameters:
4245A: the value
4246
4247Returns:
4248The natural exponentation of A (e raised to the power of A).
4249
4250@bold(Note): Consider using FastExp instead, which is much faster, but at a
4251maximum absolute error of about 0.00001. }
4252function Exp(const A: Single): Single; overload; inline;4253function Exp(const A: TVector2): TVector2; overload; inline;4254function Exp(const A: TVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4255function Exp(const A: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4256
4257{ Calculates a natural logarithm.
4258
4259Parameters:
4260A: the value. Results are undefined if A <= 0.
4261
4262Returns:
4263The natural logarithm of A (that is, the value B so that A equals e raised
4264to the power of B)
4265
4266@bold(Note): Consider using FastLn instead, which is much faster, but at a
4267maximum absolute error of about 0.00003. }
4268function Ln(const A: Single): Single; overload; inline;4269function Ln(const A: TVector2): TVector2; overload; inline;4270function Ln(const A: TVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4271function Ln(const A: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4272
4273{ Calculates 2 raised to a power.
4274
4275Parameters:
4276A: the value
4277
4278Returns:
42792 raised to the power of A.
4280
4281@bold(Note): Consider using FastExp2 instead, which is much faster, but less
4282accurate. }
4283function Exp2(const A: Single): Single; overload; inline;4284function Exp2(const A: TVector2): TVector2; overload; inline;4285function Exp2(const A: TVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4286function Exp2(const A: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4287
4288{ Calculates a base 2 logarithm.
4289
4290Parameters:
4291A: the value. Results are undefined if A <= 0.
4292
4293Returns:
4294The base 2 logarithm of A (that is, the value B so that A equals 2 raised
4295to the power of B)
4296
4297@bold(Note): Consider using FastLog2 instead, which is much faster, but at a
4298maximum absolute error of about 0.0002. }
4299function Log2(const A: Single): Single; overload; inline;4300function Log2(const A: TVector2): TVector2; overload; inline;4301function Log2(const A: TVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4302function Log2(const A: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4303
4304{ Calculates a square root.
4305
4306Parameters:
4307A: the value. Results are undefined if A < 0.
4308
4309Returns:
4310The square root of A.
4311
4312@bold(Note): If you plan to divide a certain value by the returned square
4313root, then consider using InverseSqrt instead. That version is usually faster
4314to calculate and you can replace an expensive division with a faster
4315multiplication. }
4316function Sqrt(const A: Single): Single; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4317function Sqrt(const A: TVector2): TVector2; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4318function Sqrt(const A: TVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4319function Sqrt(const A: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4320
4321{ Calculates an inverse square root.
4322
4323Parameters:
4324A: the value. Results are undefined if A <= 0.
4325
4326Returns:
43271/Sqrt(A)
4328
4329@bold(Note): You can use this function if you need to divide a given value by
4330a square root. The inverse square root is usually faster to calculate, and you
4331can replace an expensive division with a faster multiplication.
4332
4333@bold(Note): The SIMD optimized versions of these functions use an
4334approximation, resulting in a very small error. }
4335function InverseSqrt(const A: Single): Single; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4336function InverseSqrt(const A: TVector2): TVector2; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4337function InverseSqrt(const A: TVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4338function InverseSqrt(const A: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4339
4340{******************************************************}
4341{* Fast Approximate Functions *}
4342{******************************************************}
4343
4344{ These functions are usually (much) faster than their counterparts, but are
4345less accurate. For gaming and animation, this loss in accuracy is perfectly
4346acceptible and outweighed by the increase in speed.
4347
4348These functions use approximations as described in:
4349http://gallium.inria.fr/blog/fast-vectorizable-math-approx/
4350http://www.machinedlearnings.com/2011/06/fast-approximate-logarithm-exponential.html
4351http://gruntthepeon.free.fr/ssemath/ }
4352
4353{ Calculates the sine of an angle.
4354
4355Parameters:
4356ARadians: the angle in radians.
4357
4358Returns:
4359The (approximate) sine of the given angle.
4360
4361@bold(Note): This function provides excellent precisions when ARadians is
4362about the range [-4000..4000] (about +/-230,000 degrees) }
4363function FastSin(const ARadians: Single): Single; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4364function FastSin(const ARadians: TVector2): TVector2; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4365function FastSin(const ARadians: TVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4366function FastSin(const ARadians: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4367
4368{ Calculates the cosine of an angle.
4369
4370Parameters:
4371ARadians: the angle in radians.
4372
4373Returns:
4374The (approximate) cosine of the given angle.
4375
4376@bold(Note): This function provides excellent precisions when ARadians is
4377about the range [-4000..4000] (about +/-230,000 degrees) }
4378function FastCos(const ARadians: Single): Single; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4379function FastCos(const ARadians: TVector2): TVector2; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4380function FastCos(const ARadians: TVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4381function FastCos(const ARadians: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4382
4383{ Calculates the sine and cosine of an angle. This is faster than calling
4384FastSin and FastCos separately.
4385
4386Parameters:
4387ARadians: the angle in radians.
4388ASin: is set to the (approximate) sine of the angle.
4389ACos: is set to the (approximate) cosine of the angle.
4390
4391@bold(Note): This function provides excellent precisions when ARadians is
4392about the range [-4000..4000] (about +/-230,000 degrees) }
4393procedure FastSinCos(const ARadians: Single; out ASin, ACos: Single); overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4394procedure FastSinCos(const ARadians: TVector2; out ASin, ACos: TVector2); overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4395procedure FastSinCos(const ARadians: TVector3; out ASin, ACos: TVector3); overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4396procedure FastSinCos(const ARadians: TVector4; out ASin, ACos: TVector4); overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4397
4398{ Calculates the tangent of an angle.
4399
4400Parameters:
4401ARadians: the angle in radians.
4402
4403Returns:
4404The (approximate) tangent of the given angle.
4405
4406@bold(Note): This function provides excellent precisions when ARadians is
4407about the range [-4000..4000] (about +/-230,000 degrees) }
4408function FastTan(const ARadians: Single): Single; overload;4409function FastTan(const ARadians: TVector2): TVector2; overload;4410function FastTan(const ARadians: TVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4411function FastTan(const ARadians: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4412
4413{ Calculates the principal value of the arctangent of Y/X, expressed in radians.
4414
4415Parameters:
4416Y: proportion of the Y-coordinate.
4417X: proportion of the X-coordinate.
4418
4419Returns:
4420The (approximate) angle in radians, in the range [-Pi..Pi] }
4421function FastArcTan2(const Y, X: Single): Single; overload;4422function FastArcTan2(const Y, X: TVector2): TVector2; overload;4423function FastArcTan2(const Y, X: TVector3): TVector3; overload;4424function FastArcTan2(const Y, X: TVector4): TVector4; overload;4425
4426{ Calculates ABase raised to the AExponent power.
4427
4428Parameters:
4429ABase: the base value. Must be >= 0.
4430AExponent: the exponent value.
4431
4432Returns:
4433(Approximate) ABase raised to the AExponent power. Results are undefined if
4434both ABase=0 and AExponent<=0.
4435
4436@bold(Note): The error depends on the magnitude of the result. The relative
4437error is at most about 0.2% }
4438function FastPower(const ABase, AExponent: Single): Single; overload; inline;4439function FastPower(const ABase, AExponent: TVector2): TVector2; overload; inline;4440function FastPower(const ABase, AExponent: TVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4441function FastPower(const ABase, AExponent: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4442
4443{ Calculates a natural exponentiation (that is, e raised to a given power).
4444
4445Parameters:
4446A: the value
4447
4448Returns:
4449The (approximate) natural exponentation of A (e raised to the power of A)
4450
4451@bold(Note): Maximum absolute error is about 0.00001 }
4452function FastExp(const A: Single): Single; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4453function FastExp(const A: TVector2): TVector2; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4454function FastExp(const A: TVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4455function FastExp(const A: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4456
4457{ Calculates a natural logarithm.
4458
4459Parameters:
4460A: the value. Results are undefined if A <= 0.
4461
4462Returns:
4463The (approximate) natural logarithm of A (that is, the value B so that A
4464equals e raised to the power of B)
4465
4466@bold(Note): Maximum absolute error is about 0.00003. }
4467function FastLn(const A: Single): Single; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4468function FastLn(const A: TVector2): TVector2; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4469function FastLn(const A: TVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4470function FastLn(const A: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4471
4472{ Calculates a base 2 logarithm.
4473
4474Parameters:
4475A: the value. Results are undefined if A <= 0.
4476
4477Returns:
4478The (approximate) base 2 logarithm of A (that is, the value B so that A
4479equals 2 raised to the power of B)
4480
4481@bold(Note): Maximum absolute error is about 0.0002 }
4482function FastLog2(const A: Single): Single; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4483function FastLog2(const A: TVector2): TVector2; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4484function FastLog2(const A: TVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4485function FastLog2(const A: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4486
4487{ Calculates 2 raised to a power.
4488
4489Parameters:
4490A: the value. Must be in the range [-127..127] for valid results.
4491
4492Returns:
4493(Approximate) 2 raised to the power of A.
4494
4495@bold(Note): If A needs to be outside of the range [-127..127], then use Exp2
4496instead. }
4497function FastExp2(const A: Single): Single; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4498function FastExp2(const A: TVector2): TVector2; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4499function FastExp2(const A: TVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4500function FastExp2(const A: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4501
4502{******************************************************}
4503{* Common Functions *}
4504{******************************************************}
4505
4506{ Calculates an absolute value.
4507
4508Parameters:
4509A: the value.
4510
4511Returns:
4512A if A >= 0, otherwise -A. }
4513function Abs(const A: Single): Single; overload; inline;4514function Abs(const A: TVector2): TVector2; overload; inline;4515function Abs(const A: TVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4516function Abs(const A: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4517
4518{ Calculates the sign of a value.
4519
4520Parameters:
4521A: the value.
4522
4523Returns:
4524-1.0 if A < 0, 0.0 if A = 0, or 1.0 if A > 0. }
4525function Sign(const A: Single): Single; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4526function Sign(const A: TVector2): TVector2; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4527function Sign(const A: TVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4528function Sign(const A: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4529
4530{ Rounds a value towards negative infinity.
4531
4532Parameters:
4533A: the value.
4534
4535Returns:
4536A value equal to the nearest integer that is less than or equal to A. }
4537function Floor(const A: Single): Integer; overload; {$IF Defined(FM_INLINE) or Defined(CPUX64)}inline;{$ENDIF}4538function Floor(const A: TVector2): TIVector2; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4539function Floor(const A: TVector3): TIVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4540function Floor(const A: TVector4): TIVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4541
4542{ Rounds a value towards 0.
4543
4544Parameters:
4545A: the value.
4546
4547Returns:
4548The value A rounded towards 0. That is, with its fractional part removed. }
4549function Trunc(const A: Single): Integer; overload; inline;4550function Trunc(const A: TVector2): TIVector2; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4551function Trunc(const A: TVector3): TIVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4552function Trunc(const A: TVector4): TIVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4553
4554{ Rounds a value towards its nearest integer.
4555
4556Parameters:
4557A: the value.
4558
4559Returns:
4560The integer value closest to A. If A is exactly between two integer values
4561(if the fraction is 0.5), then the result is the even number. }
4562function Round(const A: Single): Integer; overload; inline;4563function Round(const A: TVector2): TIVector2; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4564function Round(const A: TVector3): TIVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4565function Round(const A: TVector4): TIVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4566
4567{ Rounds a value towards positive infinity.
4568
4569Parameters:
4570A: the value.
4571
4572Returns:
4573A value equal to the nearest integer that is greater than or equal to A. }
4574function Ceil(const A: Single): Integer; overload; {$IF Defined(FM_INLINE) or Defined(CPUX64)}inline;{$ENDIF}4575function Ceil(const A: TVector2): TIVector2; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4576function Ceil(const A: TVector3): TIVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4577function Ceil(const A: TVector4): TIVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4578
4579{ Returns the fractional part of a number.
4580
4581Parameters:
4582A: the value.
4583
4584Returns:
4585The fractional part of A, calculated as to A - Trunc(A) }
4586function Frac(const A: Single): Single; overload; {$IF Defined(FM_INLINE) or Defined(CPUX64)}inline;{$ENDIF}4587function Frac(const A: TVector2): TVector2; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4588function Frac(const A: TVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4589function Frac(const A: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4590
4591{ Modulus. Calculates the remainder of a floating-point division.
4592
4593Parameters:
4594A: the dividend.
4595B: the divisor.
4596
4597Returns:
4598The remainder of A / B, calculated as A - B * Trunc(A / B)
4599
4600@bold(Note): When used with vectors, B can be a scalar or a vector. }
4601function FMod(const A, B: Single): Single; overload; inline;4602function FMod(const A: TVector2; const B: Single): TVector2; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4603function FMod(const A, B: TVector2): TVector2; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4604function FMod(const A: TVector3; const B: Single): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4605function FMod(const A, B: TVector3): TVector3; overload; {$IF Defined(FM_INLINE) or Defined(CPUX64)}inline;{$ENDIF}4606function FMod(const A: TVector4; const B: Single): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4607function FMod(const A, B: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4608
4609{ Splits a floating-point value into its integer and fractional parts.
4610
4611Parameters:
4612A: the value to split.
4613B: is set to the integer part of A
4614
4615Returns:
4616The fractional part of A.
4617
4618@bold(Note): Both the return value and output parameter B will have the same
4619sign as A. }
4620function ModF(const A: Single; out B: Integer): Single; overload; {$IF Defined(FM_INLINE) or Defined(CPUX64)}inline;{$ENDIF}4621function ModF(const A: TVector2; out B: TIVector2): TVector2; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4622function ModF(const A: TVector3; out B: TIVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4623function ModF(const A: TVector4; out B: TIVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4624
4625{ Calculates the minimum of two values.
4626
4627Parameters:
4628A: the first value.
4629B: the second value.
4630
4631Returns:
4632The minimum of A and B.
4633
4634@bold(Note): When used with vectors, B can be a scalar or a vector. }
4635function Min(const A, B: Single): Single; overload; inline;4636function Min(const A: TVector2; const B: Single): TVector2; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4637function Min(const A, B: TVector2): TVector2; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4638function Min(const A: TVector3; const B: Single): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4639function Min(const A, B: TVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4640function Min(const A: TVector4; const B: Single): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4641function Min(const A, B: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4642
4643{ Calculates the maximum of two values.
4644
4645Parameters:
4646A: the first value.
4647B: the second value.
4648
4649Returns:
4650The maximum of A and B.
4651
4652@bold(Note): When used with vectors, B can be a scalar or a vector. }
4653function Max(const A, B: Single): Single; overload; inline;4654function Max(const A: TVector2; const B: Single): TVector2; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4655function Max(const A, B: TVector2): TVector2; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4656function Max(const A: TVector3; const B: Single): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4657function Max(const A, B: TVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4658function Max(const A: TVector4; const B: Single): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4659function Max(const A, B: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4660
4661{ Clamps a given value into a range.
4662
4663Parameters:
4664A: the value to clamp.
4665AMin: the minimum value of the range.
4666AMax: the maximum value of the range. Must be >= AMin.
4667
4668Returns:
4669A clamped to the range [AMin..AMax]. Results are undefined if AMin > AMax.
4670No error checking is performed for this situation.
4671
4672@bold(Note): When used with vectors, AMin and AMax can be scalars or vectors. }
4673function EnsureRange(const A, AMin, AMax: Single): Single; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4674function EnsureRange(const A: TVector2; const AMin, AMax: Single): TVector2; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4675function EnsureRange(const A, AMin, AMax: TVector2): TVector2; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4676function EnsureRange(const A: TVector3; const AMin, AMax: Single): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4677function EnsureRange(const A, AMin, AMax: TVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4678function EnsureRange(const A: TVector4; const AMin, AMax: Single): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4679function EnsureRange(const A, AMin, AMax: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4680
4681{ Calculates a linear blend between two values, using on a progress value.
4682
4683Parameters:
4684A: the first value.
4685B: the second value.
4686T: the progress value, usually between 0.0 and 1.0.
4687
4688Returns:
4689A value interpolated between A and B, as controlled by T. If T=0, then A
4690is returned. If T=1 then B is returned. For values in between 0 and 1, the
4691result is linearly interpolated with the formula "A * (1 - T) + (B * T)".
4692
4693@bold(Note): When used with vectors, T can be a scalar or a vector. }
4694function Mix(const A, B, T: Single): Single; overload; inline;4695function Mix(const A, B: TVector2; const T: Single): TVector2; overload; inline;4696function Mix(const A, B, T: TVector2): TVector2; overload; inline;4697function Mix(const A, B: TVector3; const T: Single): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4698function Mix(const A, B, T: TVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4699function Mix(const A, B: TVector4; const T: Single): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4700function Mix(const A, B, T: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4701
4702{ Step function.
4703
4704Parameters:
4705AEdge: the edge value.
4706A: the value to check.
4707
4708Returns:
47090.0 if A < AEdge. Otherwise it returns 1.0.
4710
4711@bold(Note): When used with vectors, AEdge can be a scalar or a vector. }
4712function Step(const AEdge, A: Single): Single; overload; inline;4713function Step(const AEdge: Single; const A: TVector2): TVector2; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4714function Step(const AEdge, A: TVector2): TVector2; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4715function Step(const AEdge: Single; const A: TVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4716function Step(const AEdge, A: TVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4717function Step(const AEdge: Single; const A: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4718function Step(const AEdge, A: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4719
4720{ Performs smooth Hermite interpolation between 0 and 1.
4721
4722Parameters:
4723AEdge0: the left value of the edge.
4724AEdge1: the right value of the edge.
4725A: the value used to control the interpolation.
4726
4727Returns:
47280.0 if A <= AEdge0 and 1.0 if A >= AEdge1. Otherwise it performs a smooth
4729Hermite interpolation between 0 and 1, based on the position of A between
4730AEdge0 and AEdge1. This is useful in cases where you would want a threshold
4731function with a smooth transition (as compared to the Step function). The
4732graph would show a curve increasing slowly from 0.0, the speeding up towards
47330.5 and finally slowing down towards 1.0.
4734
4735@bold(Note): The interpolation is calculated using the algorithm:
4736
4737<source>
4738T := EnsureRange((A - AEdge0) / (AEdge1 - AEdge0), 0, 1);
4739Result := T * T * (3 - 2 * T);
4740</source>
4741
4742Results are undefined if AEdge0 >= AEdge1. When used with vectors, AEdge0
4743and AEdge1 can be scalars or vectors. }
4744function SmoothStep(const AEdge0, AEdge1, A: Single): Single; overload; inline;4745function SmoothStep(const AEdge0, AEdge1: Single; const A: TVector2): TVector2; overload; inline;4746function SmoothStep(const AEdge0, AEdge1, A: TVector2): TVector2; overload; inline;4747function SmoothStep(const AEdge0, AEdge1: Single; const A: TVector3): TVector3; overload; inline;4748function SmoothStep(const AEdge0, AEdge1, A: TVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4749function SmoothStep(const AEdge0, AEdge1: Single; const A: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4750function SmoothStep(const AEdge0, AEdge1, A: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4751
4752{ Fused Multiply and Add (if available).
4753
4754Parameters:
4755A: the first value.
4756B: the second value.
4757C: the third value.
4758
4759Returns:
4760(A * B) + C
4761
4762@bold(Note): On ARM platforms (iOS and Android), the calculation is performed
4763with as a single (fused) operation. This provides better precision (because it
4764skips the intermediate rounding).
4765
4766On other platforms, this is not really a fused operation, but just a separate
4767muliplication and addition. }
4768function FMA(const A, B, C: Single): Single; overload; inline;4769function FMA(const A, B, C: TVector2): TVector2; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4770function FMA(const A, B, C: TVector3): TVector3; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4771function FMA(const A, B, C: TVector4): TVector4; overload; {$IFDEF FM_INLINE}inline;{$ENDIF}4772
4773{******************************************************}
4774{* Matrix Functions *}
4775{******************************************************}
4776
4777{ Treats the first parameter C as a column vector (matrix with one column) and
4778the second parameter R as a row vector (matrix with one row) and does a linear
4779algebraic matrix multiply C * R, yielding a matrix whose number of rows and
4780columns matches that of the two vectors.
4781
4782Parameters:
4783C: the column vector.
4784R: the row vector.
4785
4786Returns:
4787The outer product of C and R. }
4788function OuterProduct(const C, R: TVector2): TMatrix2; overload;4789function OuterProduct(const C, R: TVector3): TMatrix3; overload;4790function OuterProduct(const C, R: TVector4): TMatrix4; overload;4791
4792{******************************************************}
4793{* Configuration Functions *}
4794{******************************************************}
4795
4796{ Disables floating-point exceptions. Instead invalid floating-point operations
4797will return one of the following values:
4798* 0: if underflow occurs (if the value is smaller than can be represented
4799using floating-point). For example by evaluating "0.5 * MinSingle".
4800* MaxSingle/MaxDouble: if there is not enough precision available.
4801For example by evaluating "MaxSingle + 1".
4802* +/-INF: when a division by zero or overflow occurs. For example by
4803evaluating "Value / 0" or "MaxSingle * 2".
4804* +/-NAN: when an invalid operation occurs. For example by evaluating
4805"Sqrt(-1)"
4806
4807@bold(Note): On some platforms, this only disables exceptions on the thread
4808that calls this routine. So in multi-threaded scenarios, it is best to call
4809this routine in the Execute block of every thread where you want to ignore
4810floating point exceptions.
4811
4812@bold(Note): For more fine-grained control over which exception types to
4813disable, use the SetExceptionMask and/or SetSSEExceptionMask functions in the
4814System.Math unit.}
4815procedure DisableFloatingPointExceptions;4816
4817{ Restore the floating-point exception flags to the state before you called
4818DisableFloatingPointExceptions }
4819procedure RestoreFloatingPointExceptions;4820
4821{$INCLUDE 'Neslib.FastMath.Internal.inc'}
4822
4823implementation
4824
4825// Platform-independent implementations
4826{$INCLUDE 'Neslib.FastMath.Common.inc'}
4827
4828{$IF Defined(FM_PASCAL)}
4829// Pascal implementations4830{$INCLUDE 'Neslib.FastMath.Pascal.inc'}4831{$ELSEIF Defined(FM_X86)}
4832// 32-bit SSE2 implementations4833{$INCLUDE 'Neslib.FastMath.Sse2_32.inc'}4834{$ELSEIF Defined(FM_X64)}
4835// 64-bit SSE2 implementations4836{$IF Defined(MACOS64)}4837{$INCLUDE 'Neslib.FastMath.Sse2_64.MacOS.inc'}4838{$ELSE}4839{$INCLUDE 'Neslib.FastMath.Sse2_64.inc'}4840{$ENDIF}4841{$ELSEIF Defined(FM_ARM)}
4842// Arm NEON/Arm64 implementations4843{$INCLUDE 'Neslib.FastMath.Arm.inc'}4844{$ENDIF}
4845
4846end.4847