{ ****************************************************************************** } { * geometry 3D Advance library writen by QQ 600585@qq.com * } { * https://zpascal.net * } { * https://github.com/PassByYou888/zAI * } { * https://github.com/PassByYou888/ZServer4D * } { * https://github.com/PassByYou888/PascalString * } { * https://github.com/PassByYou888/zRasterization * } { * https://github.com/PassByYou888/CoreCipher * } { * https://github.com/PassByYou888/zSound * } { * https://github.com/PassByYou888/zChinese * } { * https://github.com/PassByYou888/zExpression * } { * https://github.com/PassByYou888/zGameWare * } { * https://github.com/PassByYou888/zAnalysis * } { * https://github.com/PassByYou888/FFMPEG-Header * } { * https://github.com/PassByYou888/zTranslate * } { * https://github.com/PassByYou888/InfiniteIoT * } { * https://github.com/PassByYou888/FastMD5 * } { ****************************************************************************** } unit Geometry3DUnit; {$DEFINE FPC_DELPHI_MODE} {$INCLUDE zDefine.inc} interface uses Types, CoreClasses, GeometryLib, Geometry2DUnit, PascalStrings, UnicodeMixedLib; type TMat4 = TMatrix; TVec4 = TVector; TVec3 = TAffineVector; TMatrix4 = record Buff: TMat4; public class operator Equal(const Lhs, Rhs: TMatrix4): Boolean; class operator NotEqual(const Lhs, Rhs: TMatrix4): Boolean; class operator Multiply(const Lhs, Rhs: TMatrix4): TMatrix4; class operator Implicit(Value: TGeoFloat): TMatrix4; class operator Implicit(Value: TMat4): TMatrix4; function Swap: TMatrix4; function Lerp(M: TMatrix4; Delta: TGeoFloat): TMatrix4; function AffineMatrix: TAffineMatrix; function Invert: TMatrix4; function Translate(v: TVec3): TMatrix4; function Normalize: TMatrix4; function Transpose: TMatrix4; function AnglePreservingInvert: TMatrix4; function Determinant: TGeoFloat; function Adjoint: TMatrix4; function Pitch(angle: TGeoFloat): TMatrix4; function Roll(angle: TGeoFloat): TMatrix4; function Turn(angle: TGeoFloat): TMatrix4; end; TVector4 = record Buff: TVec4; private function GetVec3: TVec3; procedure SetVec3(const Value: TVec3); function GetVec2: TVec2; procedure SetVec2(const Value: TVec2); function GetLinkValue(index: Integer): TGeoFloat; procedure SetLinkValue(index: Integer; const Value: TGeoFloat); public property vec2: TVec2 read GetVec2 write SetVec2; property Vec3: TVec3 read GetVec3 write SetVec3; property XYZ: TVec3 read GetVec3 write SetVec3; property RGB: TVec3 read GetVec3 write SetVec3; property Vec4: TVec4 read Buff write Buff; property RGBA: TVec4 read Buff write Buff; property COLOR: TVec4 read Buff write Buff; property LinkValue[index: Integer]: TGeoFloat read GetLinkValue write SetLinkValue; default; class operator Equal(const Lhs, Rhs: TVector4): Boolean; class operator NotEqual(const Lhs, Rhs: TVector4): Boolean; class operator GreaterThan(const Lhs, Rhs: TVector4): Boolean; class operator GreaterThanOrEqual(const Lhs, Rhs: TVector4): Boolean; class operator LessThan(const Lhs, Rhs: TVector4): Boolean; class operator LessThanOrEqual(const Lhs, Rhs: TVector4): Boolean; class operator Add(const Lhs, Rhs: TVector4): TVector4; class operator Add(const Lhs: TVector4; const Rhs: TGeoFloat): TVector4; class operator Add(const Lhs: TGeoFloat; const Rhs: TVector4): TVector4; class operator Subtract(const Lhs, Rhs: TVector4): TVector4; class operator Subtract(const Lhs: TVector4; const Rhs: TGeoFloat): TVector4; class operator Subtract(const Lhs: TGeoFloat; const Rhs: TVector4): TVector4; class operator Multiply(const Lhs, Rhs: TVector4): TVector4; class operator Multiply(const Lhs: TVector4; const Rhs: TGeoFloat): TVector4; class operator Multiply(const Lhs: TGeoFloat; const Rhs: TVector4): TVector4; class operator Multiply(const Lhs: TVector4; const Rhs: TMatrix4): TVector4; class operator Multiply(const Lhs: TMatrix4; const Rhs: TVector4): TVector4; class operator Multiply(const Lhs: TVector4; const Rhs: TMat4): TVector4; class operator Multiply(const Lhs: TMat4; const Rhs: TVector4): TVector4; class operator Multiply(const Lhs: TVector4; const Rhs: TAffineMatrix): TVector4; class operator Multiply(const Lhs: TAffineMatrix; const Rhs: TVector4): TVector4; class operator Divide(const Lhs, Rhs: TVector4): TVector4; class operator Divide(const Lhs: TVector4; const Rhs: TGeoFloat): TVector4; class operator Divide(const Lhs: TGeoFloat; const Rhs: TVector4): TVector4; class operator Implicit(Value: TGeoFloat): TVector4; class operator Implicit(Value: TVec4): TVector4; class operator Implicit(Value: TVec3): TVector4; class operator Implicit(Value: TVec2): TVector4; class operator Explicit(Value: TVector4): TVec4; class operator Explicit(Value: TVector4): TVec3; class operator Explicit(Value: TVector4): TVec2; procedure SetRGBA(const r, g, b, a: TGeoFloat); overload; procedure SetLocation(const fx, fy, fz, fw: TGeoFloat); overload; procedure SetLocation(const fx, fy, fz: TGeoFloat); overload; function Distance4D(const v2: TVector4): TGeoFloat; function Distance3D(const v2: TVector4): TGeoFloat; function Distance2D(const v2: TVector4): TGeoFloat; function Lerp(const v2: TVector4; const t: TGeoFloat): TVector4; function LerpDistance(const v2: TVector4; const d: TGeoFloat): TVector4; function Norm: TGeoFloat; function length: TGeoFloat; function Normalize: TVector4; function Cross(const v2: TVector4): TVector4; overload; function Cross(const v2: TVec3): TVector4; overload; function Cross(const v2: TVec4): TVector4; overload; end; TVector3 = record Buff: TVec3; private function GetVec2: TVec2; procedure SetVec2(const Value: TVec2); function GetLinkValue(index: Integer): TGeoFloat; procedure SetLinkValue(index: Integer; const Value: TGeoFloat); public property vec2: TVec2 read GetVec2 write SetVec2; property Vec3: TVec3 read Buff write Buff; property XYZ: TVec3 read Buff write Buff; property COLOR: TVec3 read Buff write Buff; property RGB: TVec3 read Buff write Buff; property LinkValue[index: Integer]: TGeoFloat read GetLinkValue write SetLinkValue; default; class operator Equal(const Lhs, Rhs: TVector3): Boolean; class operator NotEqual(const Lhs, Rhs: TVector3): Boolean; class operator GreaterThan(const Lhs, Rhs: TVector3): Boolean; class operator GreaterThanOrEqual(const Lhs, Rhs: TVector3): Boolean; class operator LessThan(const Lhs, Rhs: TVector3): Boolean; class operator LessThanOrEqual(const Lhs, Rhs: TVector3): Boolean; class operator Add(const Lhs, Rhs: TVector3): TVector3; class operator Add(const Lhs: TVector3; const Rhs: TGeoFloat): TVector3; class operator Add(const Lhs: TGeoFloat; const Rhs: TVector3): TVector3; class operator Subtract(const Lhs, Rhs: TVector3): TVector3; class operator Subtract(const Lhs: TVector3; const Rhs: TGeoFloat): TVector3; class operator Subtract(const Lhs: TGeoFloat; const Rhs: TVector3): TVector3; class operator Multiply(const Lhs, Rhs: TVector3): TVector3; class operator Multiply(const Lhs: TVector3; const Rhs: TGeoFloat): TVector3; class operator Multiply(const Lhs: TGeoFloat; const Rhs: TVector3): TVector3; class operator Multiply(const Lhs: TVector3; const Rhs: TMatrix4): TVector3; class operator Multiply(const Lhs: TMatrix4; const Rhs: TVector3): TVector3; class operator Multiply(const Lhs: TVector3; const Rhs: TMat4): TVector3; class operator Multiply(const Lhs: TMat4; const Rhs: TVector3): TVector3; class operator Multiply(const Lhs: TVector3; const Rhs: TAffineMatrix): TVector3; class operator Multiply(const Lhs: TAffineMatrix; const Rhs: TVector3): TVector3; class operator Divide(const Lhs, Rhs: TVector3): TVector3; class operator Divide(const Lhs: TVector3; const Rhs: TGeoFloat): TVector3; class operator Divide(const Lhs: TGeoFloat; const Rhs: TVector3): TVector3; class operator Implicit(Value: TGeoFloat): TVector3; class operator Implicit(Value: TVec4): TVector3; class operator Implicit(Value: TVec3): TVector3; class operator Implicit(Value: TVec2): TVector3; class operator Explicit(Value: TVector3): TVec4; class operator Explicit(Value: TVector3): TVec3; class operator Explicit(Value: TVector3): TVec2; procedure SetLocation(const fx, fy, fz: TGeoFloat); overload; function Distance3D(const v2: TVector3): TGeoFloat; function Distance2D(const v2: TVector3): TGeoFloat; function Lerp(const v2: TVector3; const t: TGeoFloat): TVector3; function LerpDistance(const v2: TVector3; const d: TGeoFloat): TVector3; function Norm: TGeoFloat; function length: TGeoFloat; function Normalize: TVector3; function Cross(const v2: TVector3): TVector3; function Vec4(fw: TGeoFloat): TVector4; overload; function Vec4: TVector4; overload; end; TAABB = record Min, Max: TAffineVector; public { : Resize the AABB if necessary to include p. } procedure Include(const p: TVector3); { : Make an AABB that is formed by sweeping a sphere (or AABB) from Start to Dest } procedure FromSweep(const Start, dest: TVector3; const radius: TGeoFloat); { : Returns the intersection AABB of two AABBs.

If the AABBs don't intersect, will return a degenerated AABB (plane, line or point). } function Intersection(const aabb2: TAABB): TAABB; { : Adds delta to min and max of the AABB. } procedure Offset(const Delta: TVector3); { : Checks if a point "p" is inside an AABB } function PointIn(const p: TVector3): Boolean; end; TVector2 = record Buff: TVec2; private function GetLinkValue(index: Integer): TGeoFloat; procedure SetLinkValue(index: Integer; const Value: TGeoFloat); public property LinkValue[index: Integer]: TGeoFloat read GetLinkValue write SetLinkValue; default; class operator Equal(const Lhs, Rhs: TVector2): Boolean; class operator NotEqual(const Lhs, Rhs: TVector2): Boolean; class operator GreaterThan(const Lhs, Rhs: TVector2): Boolean; class operator GreaterThanOrEqual(const Lhs, Rhs: TVector2): Boolean; class operator LessThan(const Lhs, Rhs: TVector2): Boolean; class operator LessThanOrEqual(const Lhs, Rhs: TVector2): Boolean; class operator Add(const Lhs, Rhs: TVector2): TVector2; class operator Add(const Lhs: TVector2; const Rhs: TGeoFloat): TVector2; class operator Add(const Lhs: TGeoFloat; const Rhs: TVector2): TVector2; class operator Subtract(const Lhs, Rhs: TVector2): TVector2; class operator Subtract(const Lhs: TVector2; const Rhs: TGeoFloat): TVector2; class operator Subtract(const Lhs: TGeoFloat; const Rhs: TVector2): TVector2; class operator Multiply(const Lhs, Rhs: TVector2): TVector2; class operator Multiply(const Lhs: TVector2; const Rhs: TGeoFloat): TVector2; class operator Multiply(const Lhs: TGeoFloat; const Rhs: TVector2): TVector2; class operator Divide(const Lhs, Rhs: TVector2): TVector2; class operator Divide(const Lhs: TVector2; const Rhs: TGeoFloat): TVector2; class operator Divide(const Lhs: TGeoFloat; const Rhs: TVector2): TVector2; class operator Implicit(Value: TGeoFloat): TVector2; class operator Implicit(Value: TPoint): TVector2; class operator Implicit(Value: TPointf): TVector2; class operator Implicit(Value: TVec2): TVector2; class operator Explicit(Value: TVector2): TPointf; class operator Explicit(Value: TVector2): TPoint; class operator Explicit(Value: TVector2): TVec2; procedure SetLocation(const fx, fy: TGeoFloat); overload; function Distance(const v2: TVector2): TGeoFloat; function Lerp(const v2: TVector2; const t: TGeoFloat): TVector2; function LerpDistance(const v2: TVector2; const d: TGeoFloat): TVector2; function Norm: TGeoFloat; function length: TGeoFloat; function Normalize: TVector2; end; function Vector4(x, y, z, w: TGeoFloat): TVector4; overload; function Vector4(x, y, z: TGeoFloat): TVector4; overload; function Vector4(v: TVec3): TVector4; overload; function Vector4(v: TVec4): TVector4; overload; function Vector3(x, y, z: TGeoFloat): TVector3; overload; function Vector3(v: TVec3): TVector3; overload; function Vector3(v: TVec4): TVector3; overload; function Vec3(const x, y, z: TGeoFloat): TVec3; overload; function Vec3(const v: TVec4): TVec3; overload; function Vec3(const v: TVector3): TVec3; overload; function Vec3(const v: TVector2): TVec3; overload; function Vec3(const v: TVector2; z: TGeoFloat): TVec3; overload; function Vec4(const x, y, z: TGeoFloat): TVec4; overload; function Vec4(const x, y, z, w: TGeoFloat): TVec4; overload; function Vec4(const v: TVec3): TVec4; overload; function Vec4(const v: TVec3; const z: TGeoFloat): TVec4; overload; function Vec4(const v: TVector3): TVec4; overload; function vec2(const v: TVec3): TVector2; overload; function vec2(const v: TVec4): TVector2; overload; function vec2(const v: TVector3): TVector2; overload; function vec2(const v: TVector4): TVector2; overload; function VecToStr(const v: TVec2): SystemString; overload; function VecToStr(const v: TVector2): SystemString; overload; function VecToStr(const v: TArrayVec2): TPascalString; overload; function VecToStr(const v: TVec3): SystemString; overload; function VecToStr(const v: TVec4): SystemString; overload; function VecToStr(const v: TVector3): SystemString; overload; function VecToStr(const v: TVector4): SystemString; overload; function RectToStr(const v: TRectV2): SystemString; overload; function RectToStr(const v: TRect): SystemString; overload; function StrToVec2(const s: SystemString): TVec2; function StrToVector2(const s: SystemString): TVector2; function StrToArrayVec2(const s: SystemString): TArrayVec2; function StrToVec3(const s: SystemString): TVec3; function StrToVec4(const s: SystemString): TVec4; function StrToVector3(const s: SystemString): TVector3; function StrToVector4(const s: SystemString): TVector4; function StrToRect(const s: SystemString): TRect; function StrToRectV2(const s: SystemString): TRectV2; function GetMin(const arry: array of TGeoFloat): TGeoFloat; overload; function GetMin(const arry: array of Integer): Integer; overload; function GetMax(const arry: array of TGeoFloat): TGeoFloat; overload; function GetMax(const arry: array of Integer): Integer; overload; function FinalAngle4FMX(const a: TGeoFloat): TGeoFloat; function CalcAngle(const v1, v2: TVec2): TGeoFloat; function AngleDistance(const sour, dest: TGeoFloat): TGeoFloat; function SmoothAngle(const sour, dest, Delta: TGeoFloat): TGeoFloat; function AngleEqual(const a1, a2: TGeoFloat): Boolean; function Distance(const v1, v2: TVec2): TGeoFloat; overload; function Distance(const v1, v2: TRectV2): TGeoFloat; overload; function MovementLerp(const s, d, Lerp: TGeoFloat): TGeoFloat; overload; function MovementLerp(const s, d: TVec2; Lerp: TGeoFloat): TVec2; overload; function MovementLerp(const s, d: TRectV2; Lerp: TGeoFloat): TRectV2; overload; function MovementDistance(const s, d: TVec2; dt: TGeoFloat): TVec2; overload; function MovementDistance(const s, d: TRectV2; dt: TGeoFloat): TRectV2; overload; function MovementDistance(const sour, dest: TVector4; Distance: TGeoFloat): TVector4; overload; function MovementDistance(const sour, dest: TVector3; Distance: TGeoFloat): TVector3; overload; function MovementDistanceDeltaTime(const s, d: TVec2; ASpeed: TGeoFloat): Double; overload; function MovementDistanceDeltaTime(const s, d: TRectV2; ASpeed: TGeoFloat): Double; overload; function AngleRollDistanceDeltaTime(const s, d: TGeoFloat; ARollSpeed: TGeoFloat): Double; overload; function BounceVector(const Current: TVector4; DeltaDistance: TGeoFloat; const BeginVector, EndVector: TVector4; var EndFlag: Boolean): TVector4; overload; function BounceVector(const Current: TVector3; DeltaDistance: TGeoFloat; const BeginVector, EndVector: TVector3; var EndFlag: Boolean): TVector3; overload; function BounceVector(const Current: TVector2; DeltaDistance: TGeoFloat; const BeginVector, EndVector: TVector2; var EndFlag: Boolean): TVector2; overload; function BounceFloat(const CurrentVal, DeltaVal, StartVal, OverVal: TGeoFloat; var EndFlag: Boolean): TGeoFloat; overload; implementation function Vector4(x, y, z, w: TGeoFloat): TVector4; begin Result.Buff[0] := x; Result.Buff[1] := y; Result.Buff[2] := z; Result.Buff[3] := w; end; function Vector4(x, y, z: TGeoFloat): TVector4; begin Result.Buff[0] := x; Result.Buff[1] := y; Result.Buff[2] := z; Result.Buff[3] := 0; end; function Vector4(v: TVec3): TVector4; begin Result.Buff[0] := v[0]; Result.Buff[1] := v[1]; Result.Buff[2] := v[2]; Result.Buff[3] := 0; end; function Vector4(v: TVec4): TVector4; begin Result.Buff := v; end; function Vector3(x, y, z: TGeoFloat): TVector3; begin Result.Buff[0] := x; Result.Buff[1] := y; Result.Buff[2] := z; end; function Vector3(v: TVec3): TVector3; begin Result.Buff := v; end; function Vector3(v: TVec4): TVector3; begin Result.Buff[0] := v[0]; Result.Buff[1] := v[1]; Result.Buff[2] := v[2]; end; function Vec3(const x, y, z: TGeoFloat): TVec3; begin Result := AffineVectorMake(x, y, z); end; function Vec3(const v: TVec4): TVec3; begin Result[0] := v[0]; Result[1] := v[1]; Result[2] := v[2]; end; function Vec3(const v: TVector3): TVec3; begin Result := v.Buff; end; function Vec3(const v: TVector2): TVec3; begin Result[0] := v[0]; Result[1] := v[1]; Result[2] := 0; end; function Vec3(const v: TVector2; z: TGeoFloat): TVec3; begin Result[0] := v[0]; Result[1] := v[1]; Result[2] := z; end; function Vec4(const x, y, z: TGeoFloat): TVec4; begin Result := VectorMake(x, y, z, 0); end; function Vec4(const x, y, z, w: TGeoFloat): TVec4; begin Result := VectorMake(x, y, z, w); end; function Vec4(const v: TVec3): TVec4; begin Result := VectorMake(v); end; function Vec4(const v: TVec3; const z: TGeoFloat): TVec4; begin Result := VectorMake(v, z); end; function Vec4(const v: TVector3): TVec4; begin Result := VectorMake(v.Buff); end; function vec2(const v: TVec3): TVector2; begin Result := vec2(v[0], v[1]); end; function vec2(const v: TVec4): TVector2; begin Result := vec2(v[0], v[1]); end; function vec2(const v: TVector3): TVector2; begin Result[0] := v.Buff[0]; Result[1] := v.Buff[1]; end; function vec2(const v: TVector4): TVector2; begin Result[0] := v.Buff[0]; Result[1] := v.Buff[1]; end; function VecToStr(const v: TVec2): SystemString; begin Result := PFormat('%g,%g', [v[0], v[1]]); end; function VecToStr(const v: TVector2): SystemString; begin Result := PFormat('%g,%g', [v[0], v[1]]); end; function VecToStr(const v: TArrayVec2): TPascalString; var i: Integer; begin Result := ''; for i := low(v) to high(v) do begin if i <> Low(v) then Result.Append(','); Result.Append('%g,%g', [v[i, 0], v[i, 1]]); end; end; function VecToStr(const v: TVec3): SystemString; begin Result := PFormat('%g,%g,%g', [v[0], v[1], v[2]]); end; function VecToStr(const v: TVec4): SystemString; begin Result := PFormat('%g,%g,%g,%g', [v[0], v[1], v[2], v[3]]); end; function VecToStr(const v: TVector3): SystemString; begin Result := VecToStr(v.Buff); end; function VecToStr(const v: TVector4): SystemString; begin Result := VecToStr(v.Buff); end; function RectToStr(const v: TRectV2): SystemString; begin Result := PFormat('%g,%g,%g,%g', [v[0][0], v[0][1], v[1][0], v[1][1]]); end; function RectToStr(const v: TRect): SystemString; begin Result := PFormat('%d,%d,%d,%d', [v.Left, v.Top, v.Right, v.Bottom]); end; function StrToVec2(const s: SystemString): TVec2; var v, v1, v2: U_String; begin v := umlTrimSpace(s); v1 := umlGetFirstStr(v, ',: '); v := umlDeleteFirstStr(v, ',: '); v2 := umlGetFirstStr(v, ',: '); Result[0] := umlStrToFloat(v1, 0); Result[1] := umlStrToFloat(v2, 0); end; function StrToVector2(const s: SystemString): TVector2; var v, v1, v2: U_String; begin v := umlTrimSpace(s); v1 := umlGetFirstStr(v, ',: '); v := umlDeleteFirstStr(v, ',: '); v2 := umlGetFirstStr(v, ',: '); Result[0] := umlStrToFloat(v1, 0); Result[1] := umlStrToFloat(v2, 0); end; function StrToArrayVec2(const s: SystemString): TArrayVec2; var n, v1, v2: U_String; L: TVec2List; begin L := TVec2List.Create; n := umlTrimSpace(s); while n.L > 0 do begin v1 := umlGetFirstStr(n, ',: '); n := umlDeleteFirstStr(n, ',: '); v2 := umlGetFirstStr(n, ',: '); n := umlDeleteFirstStr(n, ',: '); L.Add(umlStrToFloat(v1, 0), umlStrToFloat(v2, 0)); end; Result := L.BuildArray(); DisposeObject(L); end; function StrToVec3(const s: SystemString): TVec3; var v, v1, v2, v3: U_String; begin v := umlTrimSpace(s); v1 := umlGetFirstStr(v, ',: '); v := umlDeleteFirstStr(v, ',: '); v2 := umlGetFirstStr(v, ',: '); v := umlDeleteFirstStr(v, ',: '); v3 := umlGetFirstStr(v, ',: '); Result[0] := umlStrToFloat(v1, 0); Result[1] := umlStrToFloat(v2, 0); Result[2] := umlStrToFloat(v3, 0); end; function StrToVec4(const s: SystemString): TVec4; var v, v1, v2, v3, v4: U_String; begin v := umlTrimSpace(s); v1 := umlGetFirstStr(v, ',: '); v := umlDeleteFirstStr(v, ',: '); v2 := umlGetFirstStr(v, ',: '); v := umlDeleteFirstStr(v, ',: '); v3 := umlGetFirstStr(v, ',: '); v := umlDeleteFirstStr(v, ',: '); v4 := umlGetFirstStr(v, ',: '); Result[0] := umlStrToFloat(v1, 0); Result[1] := umlStrToFloat(v2, 0); Result[2] := umlStrToFloat(v3, 0); Result[3] := umlStrToFloat(v4, 0); end; function StrToVector3(const s: SystemString): TVector3; var v, v1, v2, v3: U_String; begin v := umlTrimSpace(s); v1 := umlGetFirstStr(v, ',: '); v := umlDeleteFirstStr(v, ',: '); v2 := umlGetFirstStr(v, ',: '); v := umlDeleteFirstStr(v, ',: '); v3 := umlGetFirstStr(v, ',: '); Result.Buff[0] := umlStrToFloat(v1, 0); Result.Buff[1] := umlStrToFloat(v2, 0); Result.Buff[2] := umlStrToFloat(v3, 0); end; function StrToVector4(const s: SystemString): TVector4; var v, v1, v2, v3, v4: U_String; begin v := umlTrimSpace(s); v1 := umlGetFirstStr(v, ',: '); v := umlDeleteFirstStr(v, ',: '); v2 := umlGetFirstStr(v, ',: '); v := umlDeleteFirstStr(v, ',: '); v3 := umlGetFirstStr(v, ',: '); v := umlDeleteFirstStr(v, ',: '); v4 := umlGetFirstStr(v, ',: '); Result.Buff[0] := umlStrToFloat(v1, 0); Result.Buff[1] := umlStrToFloat(v2, 0); Result.Buff[2] := umlStrToFloat(v3, 0); Result.Buff[3] := umlStrToFloat(v4, 0); end; function StrToRect(const s: SystemString): TRect; begin Result := Rect2Rect(StrToRectV2(s)); end; function StrToRectV2(const s: SystemString): TRectV2; var v, v1, v2, v3, v4: U_String; begin v := umlTrimSpace(s); v1 := umlGetFirstStr(v, ',: '); v := umlDeleteFirstStr(v, ',: '); v2 := umlGetFirstStr(v, ',: '); v := umlDeleteFirstStr(v, ',: '); v3 := umlGetFirstStr(v, ',: '); v := umlDeleteFirstStr(v, ',: '); v4 := umlGetFirstStr(v, ',: '); Result[0][0] := umlStrToFloat(v1, 0); Result[0][1] := umlStrToFloat(v2, 0); Result[1][0] := umlStrToFloat(v3, 0); Result[1][1] := umlStrToFloat(v4, 0); end; function GetMin(const arry: array of TGeoFloat): TGeoFloat; var i: Integer; begin Result := arry[low(arry)]; for i := low(arry) + 1 to high(arry) do if Result > arry[i] then Result := arry[i]; end; function GetMin(const arry: array of Integer): Integer; var i: Integer; begin Result := arry[low(arry)]; for i := low(arry) + 1 to high(arry) do if Result > arry[i] then Result := arry[i]; end; function GetMax(const arry: array of TGeoFloat): TGeoFloat; var i: Integer; begin Result := arry[low(arry)]; for i := low(arry) + 1 to high(arry) do if Result < arry[i] then Result := arry[i]; end; function GetMax(const arry: array of Integer): Integer; var i: Integer; begin Result := arry[low(arry)]; for i := low(arry) + 1 to high(arry) do if Result < arry[i] then Result := arry[i]; end; function FinalAngle4FMX(const a: TGeoFloat): TGeoFloat; begin Result := NormalizeDegAngle((-a - 90) + 180); end; function CalcAngle(const v1, v2: TVec2): TGeoFloat; begin if IsEqual(v1, v2) then Result := 0 else Result := RadToDeg(ArcTan2(v1[0] - v2[0], v1[1] - v2[1])); end; function AngleDistance(const sour, dest: TGeoFloat): TGeoFloat; begin Result := Abs(sour - dest); if Result > 180.0 then Result := 360.0 - Result; end; function SmoothAngle(const sour, dest, Delta: TGeoFloat): TGeoFloat; var a1, a2: TGeoFloat; begin if sour <> dest then begin if sour >= 0 then begin a1 := sour + Delta; a2 := sour - Delta; end else begin a1 := sour + -Delta; a2 := sour + Delta; end; if AngleDistance(dest, a1) >= AngleDistance(dest, a2) then begin if AngleDistance(dest, a2) > Delta then Result := a2 else Result := dest; end else if AngleDistance(dest, a1) > Delta then Result := a1 else Result := dest; end else Result := dest; end; function AngleEqual(const a1, a2: TGeoFloat): Boolean; begin Result := AngleDistance(a1, a2) < 0.01; end; function Distance(const v1, v2: TVec2): TGeoFloat; begin Result := PointDistance(v1, v2); end; function Distance(const v1, v2: TRectV2): TGeoFloat; var d1, d2: TGeoFloat; begin d1 := PointDistance(v1[0], v2[0]); d2 := PointDistance(v1[1], v2[1]); if d1 >= d2 then Result := d1 else Result := d2; end; function MovementLerp(const s, d, Lerp: TGeoFloat): TGeoFloat; begin if Lerp < 1.0 then Result := s + Lerp * (d - s) else Result := d; end; function MovementLerp(const s, d: TVec2; Lerp: TGeoFloat): TVec2; begin if Lerp < 1.0 then begin Result[0] := s[0] + Lerp * (d[0] - s[0]); Result[1] := s[1] + Lerp * (d[1] - s[1]); end else Result := d; end; function MovementLerp(const s, d: TRectV2; Lerp: TGeoFloat): TRectV2; begin if Lerp < 1.0 then begin Result[0] := MovementLerp(s[0], d[0], Lerp); Result[1] := MovementLerp(s[1], d[1], Lerp); end else Result := d; end; function MovementDistance(const s, d: TVec2; dt: TGeoFloat): TVec2; var k: Double; begin k := dt / Sqrt((d[0] - s[0]) * (d[0] - s[0]) + (d[1] - s[1]) * (d[1] - s[1])); Result[0] := s[0] + k * (d[0] - s[0]); Result[1] := s[1] + k * (d[1] - s[1]); end; function MovementDistance(const s, d: TRectV2; dt: TGeoFloat): TRectV2; begin if Distance(s[0], d[0]) > dt then Result[0] := MovementDistance(s[0], d[0], dt) else Result[0] := d[0]; if Distance(s[1], d[1]) > dt then Result[1] := MovementDistance(s[1], d[1], dt) else Result[1] := d[1]; end; function MovementDistance(const sour, dest: TVector4; Distance: TGeoFloat): TVector4; var k: TGeoFloat; begin // calc distance k := Distance / Sqrt((dest[0] - sour[0]) * (dest[0] - sour[0]) + (dest[1] - sour[1]) * (dest[1] - sour[1]) + (dest[2] - sour[2]) * (dest[2] - sour[2]) + (dest[3] - sour[3]) * (dest[3] - sour[3])); // done Result[0] := sour[0] + k * (dest[0] - sour[0]); Result[1] := sour[1] + k * (dest[1] - sour[1]); Result[2] := sour[2] + k * (dest[2] - sour[2]); Result[3] := sour[3] + k * (dest[3] - sour[3]); end; function MovementDistance(const sour, dest: TVector3; Distance: TGeoFloat): TVector3; var k: TGeoFloat; begin // calc distance k := Distance / Sqrt((dest[0] - sour[0]) * (dest[0] - sour[0]) + (dest[1] - sour[1]) * (dest[1] - sour[1]) + (dest[2] - sour[2]) * (dest[2] - sour[2])); // done Result[0] := sour[0] + k * (dest[0] - sour[0]); Result[1] := sour[1] + k * (dest[1] - sour[1]); Result[2] := sour[2] + k * (dest[2] - sour[2]); end; function MovementDistanceDeltaTime(const s, d: TVec2; ASpeed: TGeoFloat): Double; begin Result := Distance(s, d) / ASpeed; end; function MovementDistanceDeltaTime(const s, d: TRectV2; ASpeed: TGeoFloat): Double; var d1, d2: Double; begin d1 := MovementDistanceDeltaTime(s[0], d[0], ASpeed); d2 := MovementDistanceDeltaTime(s[1], d[1], ASpeed); if d1 > d2 then Result := d1 else Result := d2; end; function AngleRollDistanceDeltaTime(const s, d: TGeoFloat; ARollSpeed: TGeoFloat): Double; begin Result := AngleDistance(s, d) / ARollSpeed; end; function BounceVector(const Current: TVector4; DeltaDistance: TGeoFloat; const BeginVector, EndVector: TVector4; var EndFlag: Boolean): TVector4; function ToVector: TVector4; begin if EndFlag then Result := EndVector else Result := BeginVector; end; var k: TGeoFloat; begin k := Current.Distance4D(ToVector); if k >= DeltaDistance then Result := MovementDistance(Current, ToVector, DeltaDistance) else begin Result := ToVector; EndFlag := not EndFlag; Result := MovementDistance(Result, ToVector, DeltaDistance - k); end; end; function BounceVector(const Current: TVector3; DeltaDistance: TGeoFloat; const BeginVector, EndVector: TVector3; var EndFlag: Boolean): TVector3; function ToVector: TVector3; begin if EndFlag then Result := EndVector else Result := BeginVector; end; var k: TGeoFloat; begin k := Current.Distance3D(ToVector); if k >= DeltaDistance then Result := MovementDistance(Current, ToVector, DeltaDistance) else begin Result := ToVector; EndFlag := not EndFlag; Result := MovementDistance(Result, ToVector, DeltaDistance - k); end; end; function BounceVector(const Current: TVector2; DeltaDistance: TGeoFloat; const BeginVector, EndVector: TVector2; var EndFlag: Boolean): TVector2; function ToVector: TVector2; begin if EndFlag then Result := EndVector else Result := BeginVector; end; var k: TGeoFloat; begin k := Vec2Distance(Current.Buff, ToVector.Buff); if k >= DeltaDistance then Result := Vec2LerpTo(Current.Buff, ToVector.Buff, DeltaDistance) else begin Result := ToVector; EndFlag := not EndFlag; Result := Vec2LerpTo(Result.Buff, ToVector.Buff, DeltaDistance - k); end; end; function BounceFloat(const CurrentVal, DeltaVal, StartVal, OverVal: TGeoFloat; var EndFlag: Boolean): TGeoFloat; function IfOut(Cur, Delta, dest: TGeoFloat): Boolean; begin if Cur > dest then Result := Cur - Delta < dest else Result := Cur + Delta > dest; end; function GetOutValue(Cur, Delta, dest: TGeoFloat): TGeoFloat; begin if IfOut(Cur, Delta, dest) then begin if Cur > dest then Result := dest - (Cur - Delta) else Result := Cur + Delta - dest; end else Result := 0; end; function GetDeltaValue(Cur, Delta, dest: TGeoFloat): TGeoFloat; begin if Cur > dest then Result := Cur - Delta else Result := Cur + Delta; end; begin if (DeltaVal > 0) and (StartVal <> OverVal) then begin if EndFlag then begin if IfOut(CurrentVal, DeltaVal, OverVal) then begin EndFlag := False; Result := umlProcessCycleValue(OverVal, GetOutValue(CurrentVal, DeltaVal, OverVal), StartVal, OverVal, EndFlag); end else Result := GetDeltaValue(CurrentVal, DeltaVal, OverVal); end else begin if IfOut(CurrentVal, DeltaVal, StartVal) then begin EndFlag := True; Result := umlProcessCycleValue(StartVal, GetOutValue(CurrentVal, DeltaVal, StartVal), StartVal, OverVal, EndFlag); end else Result := GetDeltaValue(CurrentVal, DeltaVal, StartVal); end end else Result := CurrentVal; end; class operator TMatrix4.Equal(const Lhs, Rhs: TMatrix4): Boolean; begin Result := VectorEquals(Lhs.Buff[0], Rhs.Buff[0]) and VectorEquals(Lhs.Buff[1], Rhs.Buff[1]) and VectorEquals(Lhs.Buff[2], Rhs.Buff[2]) and VectorEquals(Lhs.Buff[3], Rhs.Buff[3]); end; class operator TMatrix4.NotEqual(const Lhs, Rhs: TMatrix4): Boolean; begin Result := not(Lhs = Rhs); end; class operator TMatrix4.Multiply(const Lhs, Rhs: TMatrix4): TMatrix4; begin Result.Buff := GeometryLib.MatrixMultiply(Lhs.Buff, Rhs.Buff); end; class operator TMatrix4.Implicit(Value: TGeoFloat): TMatrix4; var i, j: Integer; begin for i := 0 to 3 do for j := 0 to 3 do Result.Buff[i, j] := Value; end; class operator TMatrix4.Implicit(Value: TMat4): TMatrix4; begin Result.Buff := Value; end; function TMatrix4.Swap: TMatrix4; var i, j: Integer; begin for i := 0 to 3 do for j := 0 to 3 do Result.Buff[j, i] := Buff[i, j]; end; function TMatrix4.Lerp(M: TMatrix4; Delta: TGeoFloat): TMatrix4; var i, j: Integer; begin for j := 0 to 3 do for i := 0 to 3 do Result.Buff[i][j] := Buff[i][j] + (M.Buff[i][j] - Buff[i][j]) * Delta; end; function TMatrix4.AffineMatrix: TAffineMatrix; begin Result[0, 0] := Buff[0, 0]; Result[0, 1] := Buff[0, 1]; Result[0, 2] := Buff[0, 2]; Result[1, 0] := Buff[1, 0]; Result[1, 1] := Buff[1, 1]; Result[1, 2] := Buff[1, 2]; Result[2, 0] := Buff[2, 0]; Result[2, 1] := Buff[2, 1]; Result[2, 2] := Buff[2, 2]; end; function TMatrix4.Invert: TMatrix4; var det: TGeoFloat; begin Result.Buff := Buff; det := GeometryLib.MatrixDeterminant(Result.Buff); if Abs(det) < Epsilon then Result.Buff := GeometryLib.IdentityHmgMatrix else begin GeometryLib.AdjointMatrix(Result.Buff); GeometryLib.ScaleMatrix(Result.Buff, 1 / det); end; end; function TMatrix4.Translate(v: TVec3): TMatrix4; begin Result.Buff := Buff; GeometryLib.TranslateMatrix(Result.Buff, v); end; function TMatrix4.Normalize: TMatrix4; begin Result.Buff := Buff; GeometryLib.NormalizeMatrix(Result.Buff); end; function TMatrix4.Transpose: TMatrix4; begin Result.Buff := Buff; GeometryLib.TransposeMatrix(Result.Buff); end; function TMatrix4.AnglePreservingInvert: TMatrix4; begin Result.Buff := GeometryLib.AnglePreservingMatrixInvert(Buff); end; function TMatrix4.Determinant: TGeoFloat; begin Result := GeometryLib.MatrixDeterminant(Buff); end; function TMatrix4.Adjoint: TMatrix4; begin Result.Buff := Buff; GeometryLib.AdjointMatrix(Result.Buff); end; function TMatrix4.Pitch(angle: TGeoFloat): TMatrix4; begin Result.Buff := GeometryLib.Pitch(Buff, angle); end; function TMatrix4.Roll(angle: TGeoFloat): TMatrix4; begin Result.Buff := GeometryLib.Roll(Buff, angle); end; function TMatrix4.Turn(angle: TGeoFloat): TMatrix4; begin Result.Buff := GeometryLib.Turn(Buff, angle); end; function TVector4.GetVec3: TVec3; begin Result := AffineVectorMake(Buff); end; procedure TVector4.SetVec3(const Value: TVec3); begin Buff := VectorMake(Value); end; function TVector4.GetVec2: TVec2; begin Result[0] := Buff[0]; Result[1] := Buff[1]; end; procedure TVector4.SetVec2(const Value: TVec2); begin Buff[0] := Value[0]; Buff[1] := Value[1]; end; function TVector4.GetLinkValue(index: Integer): TGeoFloat; begin Result := Buff[index]; end; procedure TVector4.SetLinkValue(index: Integer; const Value: TGeoFloat); begin Buff[index] := Value; end; class operator TVector4.Equal(const Lhs, Rhs: TVector4): Boolean; begin Result := (Lhs.Buff[0] = Rhs.Buff[0]) and (Lhs.Buff[1] = Rhs.Buff[1]) and (Lhs.Buff[2] = Rhs.Buff[2]) and (Lhs.Buff[3] = Rhs.Buff[3]); end; class operator TVector4.NotEqual(const Lhs, Rhs: TVector4): Boolean; begin Result := (Lhs.Buff[0] <> Rhs.Buff[0]) or (Lhs.Buff[1] <> Rhs.Buff[1]) or (Lhs.Buff[2] <> Rhs.Buff[2]) or (Lhs.Buff[3] <> Rhs.Buff[3]); end; class operator TVector4.GreaterThan(const Lhs, Rhs: TVector4): Boolean; begin Result := (Lhs.Buff[0] > Rhs.Buff[0]) and (Lhs.Buff[1] > Rhs.Buff[1]) and (Lhs.Buff[2] > Rhs.Buff[2]) and (Lhs.Buff[3] > Rhs.Buff[3]); end; class operator TVector4.GreaterThanOrEqual(const Lhs, Rhs: TVector4): Boolean; begin Result := (Lhs.Buff[0] >= Rhs.Buff[0]) and (Lhs.Buff[1] >= Rhs.Buff[1]) and (Lhs.Buff[2] >= Rhs.Buff[2]) and (Lhs.Buff[3] >= Rhs.Buff[3]); end; class operator TVector4.LessThan(const Lhs, Rhs: TVector4): Boolean; begin Result := (Lhs.Buff[0] < Rhs.Buff[0]) and (Lhs.Buff[1] < Rhs.Buff[1]) and (Lhs.Buff[2] < Rhs.Buff[2]) and (Lhs.Buff[3] < Rhs.Buff[3]); end; class operator TVector4.LessThanOrEqual(const Lhs, Rhs: TVector4): Boolean; begin Result := (Lhs.Buff[0] <= Rhs.Buff[0]) and (Lhs.Buff[1] <= Rhs.Buff[1]) and (Lhs.Buff[2] <= Rhs.Buff[2]) and (Lhs.Buff[3] <= Rhs.Buff[3]); end; class operator TVector4.Add(const Lhs, Rhs: TVector4): TVector4; begin Result.Buff[0] := Lhs.Buff[0] + Rhs.Buff[0]; Result.Buff[1] := Lhs.Buff[1] + Rhs.Buff[1]; Result.Buff[2] := Lhs.Buff[2] + Rhs.Buff[2]; Result.Buff[3] := Lhs.Buff[3] + Rhs.Buff[3]; end; class operator TVector4.Add(const Lhs: TVector4; const Rhs: TGeoFloat): TVector4; begin Result.Buff[0] := Lhs.Buff[0] + Rhs; Result.Buff[1] := Lhs.Buff[1] + Rhs; Result.Buff[2] := Lhs.Buff[2] + Rhs; Result.Buff[3] := Lhs.Buff[3] + Rhs; end; class operator TVector4.Add(const Lhs: TGeoFloat; const Rhs: TVector4): TVector4; begin Result.Buff[0] := Lhs + Rhs.Buff[0]; Result.Buff[1] := Lhs + Rhs.Buff[1]; Result.Buff[2] := Lhs + Rhs.Buff[2]; Result.Buff[3] := Lhs + Rhs.Buff[3]; end; class operator TVector4.Subtract(const Lhs, Rhs: TVector4): TVector4; begin Result.Buff[0] := Lhs.Buff[0] - Rhs.Buff[0]; Result.Buff[1] := Lhs.Buff[1] - Rhs.Buff[1]; Result.Buff[2] := Lhs.Buff[2] - Rhs.Buff[2]; Result.Buff[3] := Lhs.Buff[3] - Rhs.Buff[3]; end; class operator TVector4.Subtract(const Lhs: TVector4; const Rhs: TGeoFloat): TVector4; begin Result.Buff[0] := Lhs.Buff[0] - Rhs; Result.Buff[1] := Lhs.Buff[1] - Rhs; Result.Buff[2] := Lhs.Buff[2] - Rhs; Result.Buff[3] := Lhs.Buff[3] - Rhs; end; class operator TVector4.Subtract(const Lhs: TGeoFloat; const Rhs: TVector4): TVector4; begin Result.Buff[0] := Lhs - Rhs.Buff[0]; Result.Buff[1] := Lhs - Rhs.Buff[1]; Result.Buff[2] := Lhs - Rhs.Buff[2]; Result.Buff[3] := Lhs - Rhs.Buff[3]; end; class operator TVector4.Multiply(const Lhs, Rhs: TVector4): TVector4; begin Result.Buff[0] := Lhs.Buff[0] * Rhs.Buff[0]; Result.Buff[1] := Lhs.Buff[1] * Rhs.Buff[1]; Result.Buff[2] := Lhs.Buff[2] * Rhs.Buff[2]; Result.Buff[3] := Lhs.Buff[2] * Rhs.Buff[3]; end; class operator TVector4.Multiply(const Lhs: TVector4; const Rhs: TGeoFloat): TVector4; begin Result.Buff[0] := Lhs.Buff[0] * Rhs; Result.Buff[1] := Lhs.Buff[1] * Rhs; Result.Buff[2] := Lhs.Buff[2] * Rhs; Result.Buff[3] := Lhs.Buff[3] * Rhs; end; class operator TVector4.Multiply(const Lhs: TGeoFloat; const Rhs: TVector4): TVector4; begin Result.Buff[0] := Lhs * Rhs.Buff[0]; Result.Buff[1] := Lhs * Rhs.Buff[1]; Result.Buff[2] := Lhs * Rhs.Buff[2]; Result.Buff[3] := Lhs * Rhs.Buff[3]; end; class operator TVector4.Multiply(const Lhs: TVector4; const Rhs: TMatrix4): TVector4; begin Result.Buff := GeometryLib.VectorTransform(Lhs.Buff, Rhs.Buff); end; class operator TVector4.Multiply(const Lhs: TMatrix4; const Rhs: TVector4): TVector4; begin Result.Buff := VectorTransform(Rhs.Buff, Lhs.Buff); end; class operator TVector4.Multiply(const Lhs: TVector4; const Rhs: TMat4): TVector4; begin Result.Buff := GeometryLib.VectorTransform(Lhs.Buff, Rhs); end; class operator TVector4.Multiply(const Lhs: TMat4; const Rhs: TVector4): TVector4; begin Result.Buff := GeometryLib.VectorTransform(Rhs.Buff, Lhs); end; class operator TVector4.Multiply(const Lhs: TVector4; const Rhs: TAffineMatrix): TVector4; begin Result.Buff := GeometryLib.VectorTransform(Lhs.Buff, Rhs); end; class operator TVector4.Multiply(const Lhs: TAffineMatrix; const Rhs: TVector4): TVector4; begin Result.Buff := GeometryLib.VectorTransform(Rhs.Buff, Lhs); end; class operator TVector4.Divide(const Lhs, Rhs: TVector4): TVector4; begin Result.Buff[0] := Lhs.Buff[0] / Rhs.Buff[0]; Result.Buff[1] := Lhs.Buff[1] / Rhs.Buff[1]; Result.Buff[2] := Lhs.Buff[2] / Rhs.Buff[2]; Result.Buff[3] := Lhs.Buff[3] / Rhs.Buff[3]; end; class operator TVector4.Divide(const Lhs: TVector4; const Rhs: TGeoFloat): TVector4; begin Result.Buff[0] := Lhs.Buff[0] / Rhs; Result.Buff[1] := Lhs.Buff[1] / Rhs; Result.Buff[2] := Lhs.Buff[2] / Rhs; Result.Buff[3] := Lhs.Buff[3] / Rhs; end; class operator TVector4.Divide(const Lhs: TGeoFloat; const Rhs: TVector4): TVector4; begin Result.Buff[0] := Lhs / Rhs.Buff[0]; Result.Buff[1] := Lhs / Rhs.Buff[1]; Result.Buff[2] := Lhs / Rhs.Buff[2]; Result.Buff[3] := Lhs / Rhs.Buff[3]; end; class operator TVector4.Implicit(Value: TGeoFloat): TVector4; begin Result.Buff[0] := Value; Result.Buff[1] := Value; Result.Buff[2] := Value; Result.Buff[3] := Value; end; class operator TVector4.Implicit(Value: TVec4): TVector4; begin Result.Buff := Value; end; class operator TVector4.Implicit(Value: TVec3): TVector4; begin Result.Buff := VectorMake(Value); end; class operator TVector4.Implicit(Value: TVec2): TVector4; begin Result.Buff := VectorMake(Value[0], Value[1], 0, 0); end; class operator TVector4.Explicit(Value: TVector4): TVec4; begin Result := Value.Buff; end; class operator TVector4.Explicit(Value: TVector4): TVec3; begin Result := AffineVectorMake(Value.Buff); end; class operator TVector4.Explicit(Value: TVector4): TVec2; begin Result[0] := Value.Buff[0]; Result[1] := Value.Buff[1]; end; procedure TVector4.SetRGBA(const r, g, b, a: TGeoFloat); begin Buff[0] := r; Buff[1] := g; Buff[2] := b; Buff[3] := a; end; procedure TVector4.SetLocation(const fx, fy, fz, fw: TGeoFloat); begin Buff[0] := fx; Buff[1] := fy; Buff[2] := fz; Buff[3] := fw; end; procedure TVector4.SetLocation(const fx, fy, fz: TGeoFloat); begin Buff[0] := fx; Buff[1] := fy; Buff[2] := fz; end; function TVector4.Distance4D(const v2: TVector4): TGeoFloat; begin Result := Sqrt(Sqr(v2.Buff[0] - Buff[0]) + Sqr(v2.Buff[1] - Buff[1]) + Sqr(v2.Buff[2] - Buff[2]) + Sqr(v2.Buff[3] - Buff[3])); end; function TVector4.Distance3D(const v2: TVector4): TGeoFloat; begin Result := Sqrt(Sqr(v2.Buff[0] - Buff[0]) + Sqr(v2.Buff[1] - Buff[1]) + Sqr(v2.Buff[2] - Buff[2])); end; function TVector4.Distance2D(const v2: TVector4): TGeoFloat; begin Result := Sqrt(Sqr(v2.Buff[0] - Buff[0]) + Sqr(v2.Buff[1] - Buff[1])); end; function TVector4.Lerp(const v2: TVector4; const t: TGeoFloat): TVector4; begin Result.Buff[0] := Buff[0] + (v2.Buff[0] - Buff[0]) * t; Result.Buff[1] := Buff[1] + (v2.Buff[1] - Buff[1]) * t; Result.Buff[2] := Buff[2] + (v2.Buff[2] - Buff[2]) * t; Result.Buff[3] := Buff[3] + (v2.Buff[3] - Buff[3]) * t; end; function TVector4.LerpDistance(const v2: TVector4; const d: TGeoFloat): TVector4; var k: Double; begin k := d / Sqrt((v2.Buff[0] - Buff[0]) * (v2.Buff[0] - Buff[0]) + (v2.Buff[1] - Buff[1]) * (v2.Buff[1] - Buff[1]) + (v2.Buff[2] - Buff[2]) * (v2.Buff[2] - Buff[2]) + (v2.Buff[3] - Buff[3]) * (v2.Buff[3] - Buff[3])); Result.Buff[0] := Buff[0] + k * (v2.Buff[0] - Buff[0]); Result.Buff[1] := Buff[1] + k * (v2.Buff[1] - Buff[1]); Result.Buff[2] := Buff[2] + k * (v2.Buff[2] - Buff[2]); Result.Buff[3] := Buff[3] + k * (v2.Buff[3] - Buff[3]); end; function TVector4.Norm: TGeoFloat; begin Result := Buff[0] * Buff[0] + Buff[1] * Buff[1] + Buff[2] * Buff[2] + Buff[3] * Buff[3]; end; function TVector4.length: TGeoFloat; begin Result := Sqrt(Norm); end; function TVector4.Normalize: TVector4; var InvLen: TGeoFloat; vn: TGeoFloat; begin vn := Norm; if vn = 0 then Result := Self else begin InvLen := RSqrt(vn); Result.Buff[0] := Buff[0] * InvLen; Result.Buff[1] := Buff[1] * InvLen; Result.Buff[2] := Buff[2] * InvLen; Result.Buff[3] := Buff[3] * InvLen; end; end; function TVector4.Cross(const v2: TVector4): TVector4; begin Result.Buff[0] := Buff[1] * v2.Buff[2] - Buff[2] * v2.Buff[1]; Result.Buff[1] := Buff[2] * v2.Buff[0] - Buff[0] * v2.Buff[2]; Result.Buff[2] := Buff[0] * v2.Buff[1] - Buff[1] * v2.Buff[0]; Result.Buff[3] := 0; end; function TVector4.Cross(const v2: TVec3): TVector4; begin Result.Buff[0] := Buff[1] * v2[2] - Buff[2] * v2[1]; Result.Buff[1] := Buff[2] * v2[0] - Buff[0] * v2[2]; Result.Buff[2] := Buff[0] * v2[1] - Buff[1] * v2[0]; Result.Buff[3] := 0; end; function TVector4.Cross(const v2: TVec4): TVector4; begin Result.Buff[0] := Buff[1] * v2[2] - Buff[2] * v2[1]; Result.Buff[1] := Buff[2] * v2[0] - Buff[0] * v2[2]; Result.Buff[2] := Buff[0] * v2[1] - Buff[1] * v2[0]; Result.Buff[3] := 0; end; function TVector3.GetVec2: TVec2; begin Result[0] := Buff[0]; Result[1] := Buff[1]; end; procedure TVector3.SetVec2(const Value: TVec2); begin Buff[0] := Value[0]; Buff[1] := Value[1]; end; function TVector3.GetLinkValue(index: Integer): TGeoFloat; begin Result := Buff[index]; end; procedure TVector3.SetLinkValue(index: Integer; const Value: TGeoFloat); begin Buff[index] := Value; end; class operator TVector3.Equal(const Lhs, Rhs: TVector3): Boolean; begin Result := (Lhs.Buff[0] = Rhs.Buff[0]) and (Lhs.Buff[1] = Rhs.Buff[1]) and (Lhs.Buff[2] = Rhs.Buff[2]); end; class operator TVector3.NotEqual(const Lhs, Rhs: TVector3): Boolean; begin Result := (Lhs.Buff[0] <> Rhs.Buff[0]) or (Lhs.Buff[1] <> Rhs.Buff[1]) or (Lhs.Buff[2] <> Rhs.Buff[2]); end; class operator TVector3.GreaterThan(const Lhs, Rhs: TVector3): Boolean; begin Result := (Lhs.Buff[0] > Rhs.Buff[0]) and (Lhs.Buff[1] > Rhs.Buff[1]) and (Lhs.Buff[2] > Rhs.Buff[2]); end; class operator TVector3.GreaterThanOrEqual(const Lhs, Rhs: TVector3): Boolean; begin Result := (Lhs.Buff[0] >= Rhs.Buff[0]) and (Lhs.Buff[1] >= Rhs.Buff[1]) and (Lhs.Buff[2] >= Rhs.Buff[2]); end; class operator TVector3.LessThan(const Lhs, Rhs: TVector3): Boolean; begin Result := (Lhs.Buff[0] < Rhs.Buff[0]) and (Lhs.Buff[1] < Rhs.Buff[1]) and (Lhs.Buff[2] < Rhs.Buff[2]); end; class operator TVector3.LessThanOrEqual(const Lhs, Rhs: TVector3): Boolean; begin Result := (Lhs.Buff[0] <= Rhs.Buff[0]) and (Lhs.Buff[1] <= Rhs.Buff[1]) and (Lhs.Buff[2] <= Rhs.Buff[2]); end; class operator TVector3.Add(const Lhs, Rhs: TVector3): TVector3; begin Result.Buff[0] := Lhs.Buff[0] + Rhs.Buff[0]; Result.Buff[1] := Lhs.Buff[1] + Rhs.Buff[1]; Result.Buff[2] := Lhs.Buff[2] + Rhs.Buff[2]; end; class operator TVector3.Add(const Lhs: TVector3; const Rhs: TGeoFloat): TVector3; begin Result.Buff[0] := Lhs.Buff[0] + Rhs; Result.Buff[1] := Lhs.Buff[1] + Rhs; Result.Buff[2] := Lhs.Buff[2] + Rhs; end; class operator TVector3.Add(const Lhs: TGeoFloat; const Rhs: TVector3): TVector3; begin Result.Buff[0] := Lhs + Rhs.Buff[0]; Result.Buff[1] := Lhs + Rhs.Buff[1]; Result.Buff[2] := Lhs + Rhs.Buff[2]; end; class operator TVector3.Subtract(const Lhs, Rhs: TVector3): TVector3; begin Result.Buff[0] := Lhs.Buff[0] - Rhs.Buff[0]; Result.Buff[1] := Lhs.Buff[1] - Rhs.Buff[1]; Result.Buff[2] := Lhs.Buff[2] - Rhs.Buff[2]; end; class operator TVector3.Subtract(const Lhs: TVector3; const Rhs: TGeoFloat): TVector3; begin Result.Buff[0] := Lhs.Buff[0] - Rhs; Result.Buff[1] := Lhs.Buff[1] - Rhs; Result.Buff[2] := Lhs.Buff[2] - Rhs; end; class operator TVector3.Subtract(const Lhs: TGeoFloat; const Rhs: TVector3): TVector3; begin Result.Buff[0] := Lhs - Rhs.Buff[0]; Result.Buff[1] := Lhs - Rhs.Buff[1]; Result.Buff[2] := Lhs - Rhs.Buff[2]; end; class operator TVector3.Multiply(const Lhs, Rhs: TVector3): TVector3; begin Result.Buff[0] := Lhs.Buff[0] * Rhs.Buff[0]; Result.Buff[1] := Lhs.Buff[1] * Rhs.Buff[1]; Result.Buff[2] := Lhs.Buff[2] * Rhs.Buff[2]; end; class operator TVector3.Multiply(const Lhs: TVector3; const Rhs: TGeoFloat): TVector3; begin Result.Buff[0] := Lhs.Buff[0] * Rhs; Result.Buff[1] := Lhs.Buff[1] * Rhs; Result.Buff[2] := Lhs.Buff[2] * Rhs; end; class operator TVector3.Multiply(const Lhs: TGeoFloat; const Rhs: TVector3): TVector3; begin Result.Buff[0] := Lhs * Rhs.Buff[0]; Result.Buff[1] := Lhs * Rhs.Buff[1]; Result.Buff[2] := Lhs * Rhs.Buff[2]; end; class operator TVector3.Multiply(const Lhs: TVector3; const Rhs: TMatrix4): TVector3; begin Result.Buff := GeometryLib.VectorTransform(Lhs.Buff, Rhs.Buff); end; class operator TVector3.Multiply(const Lhs: TMatrix4; const Rhs: TVector3): TVector3; begin Result.Buff := GeometryLib.VectorTransform(Rhs.Buff, Lhs.Buff); end; class operator TVector3.Multiply(const Lhs: TVector3; const Rhs: TMat4): TVector3; begin Result.Buff := GeometryLib.VectorTransform(Lhs.Buff, Rhs); end; class operator TVector3.Multiply(const Lhs: TMat4; const Rhs: TVector3): TVector3; begin Result.Buff := GeometryLib.VectorTransform(Rhs.Buff, Lhs); end; class operator TVector3.Multiply(const Lhs: TVector3; const Rhs: TAffineMatrix): TVector3; begin Result.Buff := GeometryLib.VectorTransform(Lhs.Buff, Rhs); end; class operator TVector3.Multiply(const Lhs: TAffineMatrix; const Rhs: TVector3): TVector3; begin Result.Buff := GeometryLib.VectorTransform(Rhs.Buff, Lhs); end; class operator TVector3.Divide(const Lhs, Rhs: TVector3): TVector3; begin Result.Buff[0] := Lhs.Buff[0] / Rhs.Buff[0]; Result.Buff[1] := Lhs.Buff[1] / Rhs.Buff[1]; Result.Buff[2] := Lhs.Buff[2] / Rhs.Buff[2]; end; class operator TVector3.Divide(const Lhs: TVector3; const Rhs: TGeoFloat): TVector3; begin Result.Buff[0] := Lhs.Buff[0] / Rhs; Result.Buff[1] := Lhs.Buff[1] / Rhs; Result.Buff[2] := Lhs.Buff[2] / Rhs; end; class operator TVector3.Divide(const Lhs: TGeoFloat; const Rhs: TVector3): TVector3; begin Result.Buff[0] := Lhs / Rhs.Buff[0]; Result.Buff[1] := Lhs / Rhs.Buff[1]; Result.Buff[2] := Lhs / Rhs.Buff[2]; end; class operator TVector3.Implicit(Value: TGeoFloat): TVector3; begin Result.Buff[0] := Value; Result.Buff[1] := Value; Result.Buff[2] := Value; end; class operator TVector3.Implicit(Value: TVec4): TVector3; begin Result.Buff := AffineVectorMake(Value); end; class operator TVector3.Implicit(Value: TVec3): TVector3; begin Result.Buff := Value; end; class operator TVector3.Implicit(Value: TVec2): TVector3; begin Result.Buff := AffineVectorMake(Value[0], Value[1], 0); end; class operator TVector3.Explicit(Value: TVector3): TVec4; begin Result := VectorMake(Value.Buff); end; class operator TVector3.Explicit(Value: TVector3): TVec3; begin Result := Value.Buff; end; class operator TVector3.Explicit(Value: TVector3): TVec2; begin Result[0] := Value.Buff[0]; Result[1] := Value.Buff[1]; end; procedure TVector3.SetLocation(const fx, fy, fz: TGeoFloat); begin Buff[0] := fx; Buff[1] := fy; Buff[2] := fz; end; function TVector3.Distance3D(const v2: TVector3): TGeoFloat; begin Result := Sqrt(Sqr(v2.Buff[0] - Buff[0]) + Sqr(v2.Buff[1] - Buff[1]) + Sqr(v2.Buff[2] - Buff[2])); end; function TVector3.Distance2D(const v2: TVector3): TGeoFloat; begin Result := Sqrt(Sqr(v2.Buff[0] - Buff[0]) + Sqr(v2.Buff[1] - Buff[1])); end; function TVector3.Lerp(const v2: TVector3; const t: TGeoFloat): TVector3; begin Result.Buff[0] := Buff[0] + (v2.Buff[0] - Buff[0]) * t; Result.Buff[1] := Buff[1] + (v2.Buff[1] - Buff[1]) * t; Result.Buff[2] := Buff[2] + (v2.Buff[2] - Buff[2]) * t; end; function TVector3.LerpDistance(const v2: TVector3; const d: TGeoFloat): TVector3; var k: Double; begin k := d / Sqrt((v2.Buff[0] - Buff[0]) * (v2.Buff[0] - Buff[0]) + (v2.Buff[1] - Buff[1]) * (v2.Buff[1] - Buff[1]) + (v2.Buff[2] - Buff[2]) * (v2.Buff[2] - Buff[2])); Result.Buff[0] := Buff[0] + k * (v2.Buff[0] - Buff[0]); Result.Buff[1] := Buff[1] + k * (v2.Buff[1] - Buff[1]); Result.Buff[2] := Buff[2] + k * (v2.Buff[2] - Buff[2]); end; function TVector3.Norm: TGeoFloat; begin Result := Buff[0] * Buff[0] + Buff[1] * Buff[1] + Buff[2] * Buff[2]; end; function TVector3.length: TGeoFloat; begin Result := Sqrt(Norm); end; function TVector3.Normalize: TVector3; var InvLen: TGeoFloat; vn: TGeoFloat; begin vn := Norm; if vn = 0 then Result := Self else begin InvLen := RSqrt(vn); Result.Buff[0] := Buff[0] * InvLen; Result.Buff[1] := Buff[1] * InvLen; Result.Buff[2] := Buff[2] * InvLen; end; end; function TVector3.Cross(const v2: TVector3): TVector3; begin Result.Buff[0] := Buff[1] * v2.Buff[2] - Buff[2] * v2.Buff[1]; Result.Buff[1] := Buff[2] * v2.Buff[0] - Buff[0] * v2.Buff[2]; Result.Buff[2] := Buff[0] * v2.Buff[1] - Buff[1] * v2.Buff[0]; end; function TVector3.Vec4(fw: TGeoFloat): TVector4; begin Result.SetLocation(Buff[0], Buff[1], Buff[2], fw); end; function TVector3.Vec4: TVector4; begin Result.SetLocation(Buff[0], Buff[1], Buff[2], 0); end; { TAABB } procedure TAABB.Include(const p: TVector3); begin if p.Buff[0] < Min[0] then Min[0] := p.Buff[0]; if p.Buff[0] > Max[0] then Max[0] := p.Buff[0]; if p.Buff[1] < Min[1] then Min[1] := p.Buff[1]; if p.Buff[1] > Max[1] then Max[1] := p.Buff[1]; if p.Buff[2] < Min[2] then Min[2] := p.Buff[2]; if p.Buff[2] > Max[2] then Max[2] := p.Buff[2]; end; procedure TAABB.FromSweep(const Start, dest: TVector3; const radius: TGeoFloat); begin if Start.Buff[0] < dest.Buff[0] then begin Min[0] := Start.Buff[0] - radius; Max[0] := dest.Buff[0] + radius; end else begin Min[0] := dest.Buff[0] - radius; Max[0] := Start.Buff[0] + radius; end; if Start.Buff[1] < dest.Buff[1] then begin Min[1] := Start.Buff[1] - radius; Max[1] := dest.Buff[1] + radius; end else begin Min[1] := dest.Buff[1] - radius; Max[1] := Start.Buff[1] + radius; end; if Start.Buff[2] < dest.Buff[2] then begin Min[2] := Start.Buff[2] - radius; Max[2] := dest.Buff[2] + radius; end else begin Min[2] := dest.Buff[2] - radius; Max[2] := Start.Buff[2] + radius; end; end; function TAABB.Intersection(const aabb2: TAABB): TAABB; var i: Integer; begin for i := 0 to 2 do begin Result.Min[i] := MaxFloat(Min[i], aabb2.Min[i]); Result.Max[i] := MinFloat(Max[i], aabb2.Max[i]); end; end; procedure TAABB.Offset(const Delta: TVector3); begin AddVector(Min, Delta.Buff); AddVector(Max, Delta.Buff); end; function TAABB.PointIn(const p: TVector3): Boolean; begin Result := (p.Buff[0] <= Max[0]) and (p.Buff[0] >= Min[0]) and (p.Buff[1] <= Max[1]) and (p.Buff[1] >= Min[1]) and (p.Buff[2] <= Max[2]) and (p.Buff[2] >= Min[2]); end; function TVector2.GetLinkValue(index: Integer): TGeoFloat; begin Result := Buff[index]; end; procedure TVector2.SetLinkValue(index: Integer; const Value: TGeoFloat); begin Buff[index] := Value; end; class operator TVector2.Equal(const Lhs, Rhs: TVector2): Boolean; begin Result := IsEqual(Lhs.Buff, Rhs.Buff); end; class operator TVector2.NotEqual(const Lhs, Rhs: TVector2): Boolean; begin Result := NotEqual(Lhs.Buff, Rhs.Buff); end; class operator TVector2.GreaterThan(const Lhs, Rhs: TVector2): Boolean; begin Result := (Lhs.Buff[0] > Rhs.Buff[0]) and (Lhs.Buff[1] > Rhs.Buff[1]); end; class operator TVector2.GreaterThanOrEqual(const Lhs, Rhs: TVector2): Boolean; begin Result := (Lhs.Buff[0] >= Rhs.Buff[0]) and (Lhs.Buff[1] >= Rhs.Buff[1]); end; class operator TVector2.LessThan(const Lhs, Rhs: TVector2): Boolean; begin Result := (Lhs.Buff[0] < Rhs.Buff[0]) and (Lhs.Buff[1] < Rhs.Buff[1]); end; class operator TVector2.LessThanOrEqual(const Lhs, Rhs: TVector2): Boolean; begin Result := (Lhs.Buff[0] <= Rhs.Buff[0]) and (Lhs.Buff[1] <= Rhs.Buff[1]); end; class operator TVector2.Add(const Lhs, Rhs: TVector2): TVector2; begin Result.Buff := Vec2Add(Lhs.Buff, Rhs.Buff); end; class operator TVector2.Add(const Lhs: TVector2; const Rhs: TGeoFloat): TVector2; begin Result.Buff := Vec2Add(Lhs.Buff, Rhs); end; class operator TVector2.Add(const Lhs: TGeoFloat; const Rhs: TVector2): TVector2; begin Result.Buff := Vec2Add(Lhs, Rhs.Buff); end; class operator TVector2.Subtract(const Lhs, Rhs: TVector2): TVector2; begin Result.Buff := Vec2Sub(Lhs.Buff, Rhs.Buff); end; class operator TVector2.Subtract(const Lhs: TVector2; const Rhs: TGeoFloat): TVector2; begin Result.Buff := Vec2Sub(Lhs.Buff, Rhs); end; class operator TVector2.Subtract(const Lhs: TGeoFloat; const Rhs: TVector2): TVector2; begin Result.Buff := Vec2Sub(Lhs, Rhs.Buff); end; class operator TVector2.Multiply(const Lhs, Rhs: TVector2): TVector2; begin Result.Buff := Vec2Mul(Lhs.Buff, Rhs.Buff); end; class operator TVector2.Multiply(const Lhs: TVector2; const Rhs: TGeoFloat): TVector2; begin Result.Buff := Vec2Mul(Lhs.Buff, Rhs); end; class operator TVector2.Multiply(const Lhs: TGeoFloat; const Rhs: TVector2): TVector2; begin Result.Buff := Vec2Mul(Lhs, Rhs.Buff); end; class operator TVector2.Divide(const Lhs, Rhs: TVector2): TVector2; begin Result.Buff := Vec2Div(Lhs.Buff, Rhs.Buff); end; class operator TVector2.Divide(const Lhs: TVector2; const Rhs: TGeoFloat): TVector2; begin Result.Buff := Vec2Div(Lhs.Buff, Rhs); end; class operator TVector2.Divide(const Lhs: TGeoFloat; const Rhs: TVector2): TVector2; begin Result.Buff := Vec2Div(Lhs, Rhs.Buff); end; class operator TVector2.Implicit(Value: TGeoFloat): TVector2; begin Result.Buff := vec2(Value); end; class operator TVector2.Implicit(Value: TPoint): TVector2; begin Result.Buff := vec2(Value); end; class operator TVector2.Implicit(Value: TPointf): TVector2; begin Result.Buff := vec2(Value); end; class operator TVector2.Implicit(Value: TVec2): TVector2; begin Result.Buff := Value; end; class operator TVector2.Explicit(Value: TVector2): TPointf; begin Result := MakePointf(Value.Buff); end; class operator TVector2.Explicit(Value: TVector2): TPoint; begin Result := MakePoint(Value.Buff); end; class operator TVector2.Explicit(Value: TVector2): TVec2; begin Result := Value.Buff; end; procedure TVector2.SetLocation(const fx, fy: TGeoFloat); begin Buff := vec2(fx, fy); end; function TVector2.Distance(const v2: TVector2): TGeoFloat; begin Result := Vec2Distance(Buff, v2.Buff); end; function TVector2.Lerp(const v2: TVector2; const t: TGeoFloat): TVector2; begin Result.Buff := Vec2Lerp(Buff, v2.Buff, t); end; function TVector2.LerpDistance(const v2: TVector2; const d: TGeoFloat): TVector2; begin Result.Buff := Vec2LerpTo(Buff, v2.Buff, d); end; function TVector2.Norm: TGeoFloat; begin Result := Vec2Norm(Buff); end; function TVector2.length: TGeoFloat; begin Result := Vec2Length(Buff); end; function TVector2.Normalize: TVector2; begin Result.Buff := Vec2Normalize(Buff); end; end.