diff --git a/ugluMatrixEx.inc b/ugluMatrixEx.inc new file mode 100644 index 0000000..b8724b0 --- /dev/null +++ b/ugluMatrixEx.inc @@ -0,0 +1,281 @@ +{$IF DEFINED(__MATRIX_HELPER_INTERFACE)} + type __HELPER = type helper for __MAT + public const + {$IF __SIZE = 2} + Identity: __MAT = ((1, 0), (0, 1)); + {$ELSEIF __SIZE = 3} + Identity: __MAT = ((1, 0, 0), (0, 1, 0), (0, 0, 1)); + {$ELSEIF __SIZE = 4} + Identity: __MAT = ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)); + {$ELSE} + {$ERROR only vectors of size 2, 3 or 4 are supported} + {$ENDIF} + public + function ToString(const aRound: Integer = -3): String; inline; + function Transpose: __MAT; inline; + function Determinant: Double; inline; + function Invert: __MAT; inline; + + class function TryFromString(const s: String; out m: __MAT): Boolean; inline; static; + class function FromString(const s: String): __MAT; inline; static; + + {$IF __SIZE = 3} + function Sub(const aCol, aRow: Integer): __IMPL.TMat2; inline; + function Adjoint: __MAT; inline; + function Translate(const v: __IMPL.TVectorHelper.TVector2): __MAT; inline; + function Translate(const x, y: __IMPL.TBaseType): __MAT; inline; + function Scale(const v: __IMPL.TVectorHelper.TVector2): __MAT; inline; + function Scale(const v: __IMPL.TBaseType): __MAT; inline; + function Shear(const v: __IMPL.TVectorHelper.TVector2): __MAT; inline; + function Shear(const x, y: __IMPL.TBaseType): __MAT; inline; + function Rotate(const a: Double): __MAT; inline; + + class function CreateTranslate(const v: __IMPL.TVectorHelper.TVector2): __MAT; inline; static; + class function CreateTranslate(const x, y: __IMPL.TBaseType): __MAT; inline; static; + class function CreateScale(const v: __IMPL.TVectorHelper.TVector2): __MAT; inline; static; + class function CreateScale(const v: __IMPL.TBaseType): __MAT; inline; static; + class function CreateShear(const v: __IMPL.TVectorHelper.TVector2): __MAT; inline; static; + class function CreateShear(const x, y: __IMPL.TBaseType): __MAT; inline; static; + class function CreateRotate(const a: Double): __MAT; inline; static; + {$ELSEIF __SIZE = 4} + function Sub(const aCol, aRow: Integer): __IMPL.TMat3; inline; + function Adjoint: __MAT; inline; + function Translate(const v: __IMPL.TVectorHelper.TVector3): __MAT; inline; + function Translate(const x, y, z: __IMPL.TBaseType): __MAT; inline; + function Scale(const v: __IMPL.TVectorHelper.TVector3): __MAT; inline; + function Scale(const v: __IMPL.TBaseType): __MAT; inline; + function Rotate(const axis: __IMPL.TVectorHelper.TVector3; const a: Double): __MAT; inline; + + class function CreateTranslate(const v: __IMPL.TVectorHelper.TVector3): __MAT; inline; static; + class function CreateTranslate(const x, y, z: __IMPL.TBaseType): __MAT; inline; static; + class function CreateScale(const v: __IMPL.TVectorHelper.TVector3): __MAT; inline; static; + class function CreateScale(const v: __IMPL.TBaseType): __MAT; inline; static; + class function CreateShear(const x, y, z: __IMPL.TVectorHelper.TVector2): __MAT; inline; static; + class function CreateShear(const xy, xz, yx, yz, zx, zy: __IMPL.TBaseType): __MAT; inline; static; + class function CreateRotate(const axis: __IMPL.TVectorHelper.TVector3; const a: Double): __MAT; inline; static; + {$ENDIF} + end; + + operator = (const m1, m2: __MAT): Boolean; inline; + operator * (const m1, m2: __MAT): __MAT; inline; + operator * (const m: __MAT; const v: __VEC): __VEC; inline; + operator * (const s: __IMPL.TBaseType; const m: __MAT): __MAT; inline; + operator * (const m: __MAT; const s: __IMPL.TBaseType): __MAT; inline; +{$ELSEIF DEFINED (__MATRIX_HELPER_IMPL)} + operator = (const m1, m2: __MAT): Boolean; + begin + result := __IMPL.Equals(m1, m2); + end; + + operator * (const m1, m2: __MAT): __MAT; + begin + result := __IMPL.Multiply(m1, m2); + end; + + operator * (const m: __MAT; const v: __VEC): __VEC; + begin + result := __IMPL.Multiply(m, v); + end; + + operator * (const s: __IMPL.TBaseType; const m: __MAT): __MAT; + begin + result := __IMPL.Multiply(m, s); + end; + + operator * (const m: __MAT; const s: __IMPL.TBaseType): __MAT; + begin + result := __IMPL.Multiply(m, s); + end; + + function __HELPER.ToString(const aRound: Integer = -3): String; + begin + result := __IMPL.ToString(self, aRound); + end; + + function __HELPER.Transpose: __MAT; + begin + result := __IMPL.Transpose(self); + end; + + function __HELPER.Determinant: Double; + begin + result := __IMPL.Determinant(self); + end; + + function __HELPER.Invert: __MAT; + begin + result := __IMPL.Invert(self); + end; + + class function __HELPER.TryFromString(const s: String; out m: __MAT): Boolean; + begin + result := __IMPL.TryFromString(s, m); + end; + + class function __HELPER.FromString(const s: String): __MAT; + begin + if not __IMPL.TryFromString(s, result) then + result := Identity; + end; + + {$IF __SIZE = 3} + function __HELPER.Sub(const aCol, aRow: Integer): __IMPL.TMat2; + begin + result := __IMPL.Sub(self, aCol, aRow); + end; + + function __HELPER.Adjoint: __MAT; + begin + result := __IMPL.Adjoint(self); + end; + + function __HELPER.Translate(const v: __IMPL.TVectorHelper.TVector2): __MAT; + begin + result := __IMPL.Multiply(self, __IMPL.CreateTranslate(v)); + end; + + function __HELPER.Translate(const x, y: __IMPL.TBaseType): __MAT; + begin + result := __IMPL.Multiply(self, __IMPL.CreateTranslate(__IMPL.TVectorHelper.Vector2(x, y))); + end; + + function __HELPER.Scale(const v: __IMPL.TVectorHelper.TVector2): __MAT; + begin + result := __IMPL.Multiply(self, __IMPL.CreateScale(v)); + end; + + function __HELPER.Scale(const v: __IMPL.TBaseType): __MAT; + begin + result := __IMPL.Multiply(self, __IMPL.CreateScale(__IMPL.TVectorHelper.Vector2(v, v))); + end; + + function __HELPER.Shear(const v: __IMPL.TVectorHelper.TVector2): __MAT; + begin + result := __IMPL.Multiply(self, __IMPL.CreateShear(v)); + end; + + function __HELPER.Shear(const x, y: __IMPL.TBaseType): __MAT; + begin + result := __IMPL.Multiply(self, __IMPL.CreateShear(__IMPL.TVectorHelper.Vector2(x, y))); + end; + + function __HELPER.Rotate(const a: Double): __MAT; + begin + result := __IMPL.Multiply(self, __IMPL.CreateRotate(a)); + end; + + class function __HELPER.CreateTranslate(const v: __IMPL.TVectorHelper.TVector2): __MAT; + begin + result := __IMPL.CreateTranslate(v); + end; + + class function __HELPER.CreateTranslate(const x, y: __IMPL.TBaseType): __MAT; + begin + result := __IMPL.CreateTranslate(__IMPL.TVectorHelper.Vector2(x, y)); + end; + + class function __HELPER.CreateScale(const v: __IMPL.TVectorHelper.TVector2): __MAT; + begin + result := __IMPL.CreateScale(v); + end; + + class function __HELPER.CreateScale(const v: __IMPL.TBaseType): __MAT; + begin + result := __IMPL.CreateScale(__IMPL.TVectorHelper.Vector2(v, v)); + end; + + class function __HELPER.CreateShear(const v: __IMPL.TVectorHelper.TVector2): __MAT; + begin + result := __IMPL.CreateShear(v); + end; + + class function __HELPER.CreateShear(const x, y: __IMPL.TBaseType): __MAT; + begin + result := __IMPL.CreateShear(__IMPL.TVectorHelper.Vector2(x, y)); + end; + + class function __HELPER.CreateRotate(const a: Double): __MAT; + begin + result := __IMPL.CreateRotate(a); + end; + {$ELSEIF __SIZE = 4} + function __HELPER.Sub(const aCol, aRow: Integer): __IMPL.TMat3; + begin + result := __IMPL.Sub(self, aRow, aCol); + end; + + function __HELPER.Adjoint: __MAT; + begin + result := __IMPL.Adjoint(self); + end; + + function __HELPER.Translate(const v: __IMPL.TVectorHelper.TVector3): __MAT; + begin + result := __IMPL.Multiply(self, __IMPL.CreateTranslate(v)); + end; + + function __HELPER.Translate(const x, y, z: __IMPL.TBaseType): __MAT; + begin + result := __IMPL.Multiply(self, __IMPL.CreateTranslate(__IMPL.TVectorHelper.Vector3(x, y, z))); + end; + + function __HELPER.Scale(const v: __IMPL.TVectorHelper.TVector3): __MAT; + begin + result := __IMPL.Multiply(self, __IMPL.CreateScale(v)); + end; + + function __HELPER.Scale(const v: __IMPL.TBaseType): __MAT; + begin + result := __IMPL.Multiply(self, __IMPL.CreateScale(__IMPL.TVectorHelper.Vector3(v, v, v))); + end; + + function __HELPER.Rotate(const axis: __IMPL.TVectorHelper.TVector3; const a: Double): __MAT; + begin + result := __IMPL.Multiply(self, __IMPL.CreateRotate(axis, a)); + end; + + class function __HELPER.CreateTranslate(const v: __IMPL.TVectorHelper.TVector3): __MAT; + begin + result := __IMPL.CreateTranslate(v); + end; + + class function __HELPER.CreateTranslate(const x, y, z: __IMPL.TBaseType): __MAT; + begin + result := __IMPL.CreateTranslate(__IMPL.TVectorHelper.Vector3(x, y, z)); + end; + + class function __HELPER.CreateScale(const v: __IMPL.TVectorHelper.TVector3): __MAT; + begin + result := __IMPL.CreateScale(v); + end; + + class function __HELPER.CreateScale(const v: __IMPL.TBaseType): __MAT; + begin + result := __IMPL.CreateScale(__IMPL.TVectorHelper.Vector3(v, v, v)); + end; + + class function __HELPER.CreateShear(const x, y, z: __IMPL.TVectorHelper.TVector2): __MAT; + begin + result := __IMPL.CreateShear(x, y, z); + end; + + class function __HELPER.CreateShear(const xy, xz, yx, yz, zx, zy: __IMPL.TBaseType): __MAT; + begin + result := __IMPL.CreateShear( + __IMPL.TVectorHelper.Vector2(xy, xz), + __IMPL.TVectorHelper.Vector2(yx, yz), + __IMPL.TVectorHelper.Vector2(zx, zy)); + end; + + class function __HELPER.CreateRotate(const axis: __IMPL.TVectorHelper.TVector3; const a: Double): __MAT; + begin + result := __IMPL.CreateRotate(axis, a); + end; + {$ENDIF} +{$ENDIF} + +{$UNDEF __IMPL} +{$UNDEF __SIZE} +{$UNDEF __VEC} +{$UNDEF __MAT} +{$UNDEF __HELPER} diff --git a/ugluMatrixEx.pas b/ugluMatrixEx.pas new file mode 100644 index 0000000..6ecbe47 --- /dev/null +++ b/ugluMatrixEx.pas @@ -0,0 +1,129 @@ +unit ugluMatrixEx; + +{$mode objfpc}{$H+} +{$macro on} +{$modeswitch typehelpers} + +interface + +uses + Classes, SysUtils, + ugluVectorEx, ugluMatrixExHelper; + +type + TgluMatrix2f = TgluMatrixF.TMat2; + TgluMatrix3f = TgluMatrixF.TMat3; + TgluMatrix4f = TgluMatrixF.TMat4; + + TgluMatrix2d = TgluMatrixD.TMat2; + TgluMatrix3d = TgluMatrixD.TMat3; + TgluMatrix4d = TgluMatrixD.TMat4; + + + + PgluMatrix2f = ^TgluMatrix2f; + PgluMatrix3f = ^TgluMatrix3f; + PgluMatrix4f = ^TgluMatrix4f; + + PgluMatrix2d = ^TgluMatrix2d; + PgluMatrix3d = ^TgluMatrix3d; + PgluMatrix4d = ^TgluMatrix4d; + + + +{$DEFINE __MATRIX_HELPER_INTERFACE} + {$DEFINE __IMPL := TgluMatrixF} + {$DEFINE __SIZE := 2} + {$DEFINE __VEC := TgluVector2f} + {$DEFINE __MAT := TgluMatrix2f} + {$DEFINE __HELPER := TgluTypeHelperMatrix2f} + {$I ugluMatrixEx.inc} + + {$DEFINE __IMPL := TgluMatrixF} + {$DEFINE __SIZE := 3} + {$DEFINE __VEC := TgluVector3f} + {$DEFINE __MAT := TgluMatrix3f} + {$DEFINE __HELPER := TgluTypeHelperMatrix3f} + {$I ugluMatrixEx.inc} + + {$DEFINE __IMPL := TgluMatrixF} + {$DEFINE __SIZE := 4} + {$DEFINE __VEC := TgluVector4f} + {$DEFINE __MAT := TgluMatrix4f} + {$DEFINE __HELPER := TgluTypeHelperMatrix4f} + {$I ugluMatrixEx.inc} + + + + {$DEFINE __IMPL := TgluMatrixD} + {$DEFINE __SIZE := 2} + {$DEFINE __VEC := TgluVector2d} + {$DEFINE __MAT := TgluMatrix2d} + {$DEFINE __HELPER := TgluTypeHelperMatrix2d} + {$I ugluMatrixEx.inc} + + {$DEFINE __IMPL := TgluMatrixD} + {$DEFINE __SIZE := 3} + {$DEFINE __VEC := TgluVector3d} + {$DEFINE __MAT := TgluMatrix3d} + {$DEFINE __HELPER := TgluTypeHelperMatrix3d} + {$I ugluMatrixEx.inc} + + {$DEFINE __IMPL := TgluMatrixD} + {$DEFINE __SIZE := 4} + {$DEFINE __VEC := TgluVector4d} + {$DEFINE __MAT := TgluMatrix4d} + {$DEFINE __HELPER := TgluTypeHelperMatrix4d} + {$I ugluMatrixEx.inc} +{$UNDEF __MATRIX_HELPER_INTERFACE} + +implementation + +{$DEFINE __MATRIX_HELPER_IMPL} + {$DEFINE __IMPL := TgluMatrixF} + {$DEFINE __SIZE := 2} + {$DEFINE __VEC := TgluVector2f} + {$DEFINE __MAT := TgluMatrix2f} + {$DEFINE __HELPER := TgluTypeHelperMatrix2f} + {$I ugluMatrixEx.inc} + + {$DEFINE __IMPL := TgluMatrixF} + {$DEFINE __SIZE := 3} + {$DEFINE __VEC := TgluVector3f} + {$DEFINE __MAT := TgluMatrix3f} + {$DEFINE __HELPER := TgluTypeHelperMatrix3f} + {$I ugluMatrixEx.inc} + + {$DEFINE __IMPL := TgluMatrixF} + {$DEFINE __SIZE := 4} + {$DEFINE __VEC := TgluVector4f} + {$DEFINE __MAT := TgluMatrix4f} + {$DEFINE __HELPER := TgluTypeHelperMatrix4f} + {$I ugluMatrixEx.inc} + + + + {$DEFINE __IMPL := TgluMatrixD} + {$DEFINE __SIZE := 2} + {$DEFINE __VEC := TgluVector2d} + {$DEFINE __MAT := TgluMatrix2d} + {$DEFINE __HELPER := TgluTypeHelperMatrix2d} + {$I ugluMatrixEx.inc} + + {$DEFINE __IMPL := TgluMatrixD} + {$DEFINE __SIZE := 3} + {$DEFINE __VEC := TgluVector3d} + {$DEFINE __MAT := TgluMatrix3d} + {$DEFINE __HELPER := TgluTypeHelperMatrix3d} + {$I ugluMatrixEx.inc} + + {$DEFINE __IMPL := TgluMatrixD} + {$DEFINE __SIZE := 4} + {$DEFINE __VEC := TgluVector4d} + {$DEFINE __MAT := TgluMatrix4d} + {$DEFINE __HELPER := TgluTypeHelperMatrix4d} + {$I ugluMatrixEx.inc} +{$UNDEF __MATRIX_HELPER_IMPL} + +end. + diff --git a/ugluMatrixExHelper.pas b/ugluMatrixExHelper.pas new file mode 100644 index 0000000..6b13abf --- /dev/null +++ b/ugluMatrixExHelper.pas @@ -0,0 +1,540 @@ +unit ugluMatrixExHelper; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, + ugluVectorExHelper; + +type + generic TgluMatrixHelper = class + public type + TVectorHelper = specialize TgluVectorHelper; + TVectorHelperF = specialize TgluVectorHelperF; + TBaseType = T; + PBaseType = ^T; + + TMat2 = array[0..1] of TVectorHelper.TVector2; + TMat3 = array[0..2] of TVectorHelper.TVector3; + TMat4 = array[0..3] of TVectorHelper.TVector4; + + PMat2 = ^TMat2; + PMat3 = ^TMat3; + PMat4 = ^TMat4; + + public + class function Equals(const m1, m2: TMat2): Boolean; overload; inline; + class function Equals(const m1, m2: TMat3): Boolean; overload; inline; + class function Equals(const m1, m2: TMat4): Boolean; overload; inline; + + class function ToString(const m: TMat2; const aRound: Integer = -3): String; overload; inline; + class function ToString(const m: TMat3; const aRound: Integer = -3): String; overload; inline; + class function ToString(const m: TMat4; const aRound: Integer = -3): String; overload; inline; + + class function TryFromString(const s: String; out m: TMat2): Boolean; overload; inline; + class function TryFromString(const s: String; out m: TMat3): Boolean; overload; inline; + class function TryFromString(const s: String; out m: TMat4): Boolean; overload; inline; + + class function Transpose(const m: TMat2): TMat2; overload; inline; + class function Transpose(const m: TMat3): TMat3; overload; inline; + class function Transpose(const m: TMat4): TMat4; overload; inline; + + class function Sub(const m: TMat2; const c, r: Integer): TBaseType; overload; inline; + class function Sub(const m: TMat3; const c, r: Integer): TMat2; overload; inline; + class function Sub(const m: TMat4; const c, r: Integer): TMat3; overload; inline; + + class function Determinant(const m: TMat2): Double; overload; inline; + class function Determinant(const m: TMat3): Double; overload; inline; + class function Determinant(const m: TMat4): Double; overload; + + class function Adjoint(const m: TMat3): TMat3; overload; + class function Adjoint(const m: TMat4): TMat4; overload; + + class function Multiply(const m1, m2: TMat2): TMat2; overload; inline; + class function Multiply(const m1, m2: TMat3): TMat3; overload; inline; + class function Multiply(const m1, m2: TMat4): TMat4; overload; inline; + + class function Multiply(const m: TMat2; const v: TVectorHelper.TVector2): TVectorHelper.TVector2; overload; inline; + class function Multiply(const m: TMat3; const v: TVectorHelper.TVector3): TVectorHelper.TVector3; overload; inline; + class function Multiply(const m: TMat4; const v: TVectorHelper.TVector4): TVectorHelper.TVector4; overload; inline; + + class function Multiply(const m: TMat2; const v: TBaseType): TMat2; overload; inline; + class function Multiply(const m: TMat3; const v: TBaseType): TMat3; overload; inline; + class function Multiply(const m: TMat4; const v: TBaseType): TMat4; overload; inline; + + class function Invert(const m: TMat2): TMat2; overload; inline; + class function Invert(const m: TMat3): TMat3; overload; inline; + class function Invert(const m: TMat4): TMat4; overload; inline; + + class function CreateTranslate(const v: TVectorHelper.TVector2): TMat3; + class function CreateTranslate(const v: TVectorHelper.TVector3): TMat4; + + class function CreateScale(const v: TVectorHelper.TVector2): TMat3; + class function CreateScale(const v: TVectorHelper.TVector3): TMat4; + + class function CreateRotate(a: Double): TMat3; + class function CreateRotate(axis: TVectorHelper.TVector3; a: Double): TMat4; + + class function CreateShear(const v: TVectorHelper.TVector2): TMat3; + class function CreateShear(const x, y, z: TVectorHelper.TVector2): TMat4; + private + class function GetElement(p: PBaseType; x, y, sz: Integer): TBaseType; // TODO inline; + class procedure SetElement(p: PBaseType; x, y, sz: Integer; v: TBaseType); // TODO inline; + + class procedure Transpose(src, dst: PBaseType; sz: Integer); + class procedure Sub(src, dst: PBaseType; sz, c, r: Integer); + class procedure Mult(p1, p2, r: PBaseType; c1r2, r1, c2: Integer); + class procedure Mult(src, dst: PBaseType; c, r: Integer; v: TBaseType); + + class function TryFromString(const s: String; p: PBaseType; r, c: Integer): Boolean; + end; + + TgluMatrixF = specialize TgluMatrixHelper; + TgluMatrixD = specialize TgluMatrixHelper; + +implementation + +uses + Math; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TgluMatrixHelper////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class function TgluMatrixHelper.Equals(const m1, m2: TMat2): Boolean; +begin + result := + TVectorHelper.Equals(m1[0], m2[0]) and + TVectorHelper.Equals(m1[1], m2[1]); +end; + +class function TgluMatrixHelper.Equals(const m1, m2: TMat3): Boolean; +begin + result := + TVectorHelper.Equals(m1[0], m2[0]) and + TVectorHelper.Equals(m1[1], m2[1]) and + TVectorHelper.Equals(m1[2], m2[2]); +end; + +class function TgluMatrixHelper.Equals(const m1, m2: TMat4): Boolean; +begin + result := + TVectorHelper.Equals(m1[0], m2[0]) and + TVectorHelper.Equals(m1[1], m2[1]) and + TVectorHelper.Equals(m1[2], m2[2]) and + TVectorHelper.Equals(m1[3], m2[3]); +end; + +class function TgluMatrixHelper.ToString(const m: TMat2; const aRound: Integer): String; +begin + result := format('(%s); (%s)', [ + TVectorHelper.ToString(m[0], aRound), + TVectorHelper.ToString(m[1], aRound)]); +end; + +class function TgluMatrixHelper.ToString(const m: TMat3; const aRound: Integer): String; +begin + result := format('(%s); (%s); (%s)', [ + TVectorHelper.ToString(m[0], aRound), + TVectorHelper.ToString(m[1], aRound), + TVectorHelper.ToString(m[2], aRound)]); +end; + +class function TgluMatrixHelper.ToString(const m: TMat4; const aRound: Integer): String; +begin + result := format('(%s); (%s); (%s); (%s)', [ + TVectorHelper.ToString(m[0], aRound), + TVectorHelper.ToString(m[1], aRound), + TVectorHelper.ToString(m[2], aRound), + TVectorHelper.ToString(m[3], aRound)]); +end; + +class function TgluMatrixHelper.TryFromString(const s: String; out m: TMat2): Boolean; +begin + result := TryFromString(s, @m[0,0], 2, 2); +end; + +class function TgluMatrixHelper.TryFromString(const s: String; out m: TMat3): Boolean; +begin + result := TryFromString(s, @m[0,0], 3, 3); +end; + +class function TgluMatrixHelper.TryFromString(const s: String; out m: TMat4): Boolean; +begin + result := TryFromString(s, @m[0,0], 4, 4); +end; + +class function TgluMatrixHelper.Transpose(const m: TMat2): TMat2; +begin + Transpose(@m[0,0], @result[0,0], Length(m)); +end; + +class function TgluMatrixHelper.Transpose(const m: TMat3): TMat3; +begin + Transpose(@m[0,0], @result[0,0], Length(m)); +end; + +class function TgluMatrixHelper.Transpose(const m: TMat4): TMat4; +begin + Transpose(@m[0,0], @result[0,0], Length(m)); +end; + +class function TgluMatrixHelper.Sub(const m: TMat2; const c, r: Integer): TBaseType; +begin + Sub(@m[0,0], @result, 2, c, r); +end; + +class function TgluMatrixHelper.Sub(const m: TMat3; const c, r: Integer): TMat2; +begin + Sub(@m[0,0], @result[0,0], 3, c, r); +end; + +class function TgluMatrixHelper.Sub(const m: TMat4; const c, r: Integer): TMat3; +begin + Sub(@m[0,0], @result[0,0], 4, c, r); +end; + +class function TgluMatrixHelper.Determinant(const m: TMat2): Double; +begin + result := m[0,0] * m[1,1] - m[1,0] * m[0,1]; +end; + +class function TgluMatrixHelper.Determinant(const m: TMat3): Double; +begin + result := + m[0,0] * m[1,1] * m[2,2] + + m[1,0] * m[2,1] * m[0,2] + + m[2,0] * m[0,1] * m[1,2] - + m[2,0] * m[1,1] * m[0,2] - + m[1,0] * m[0,1] * m[2,2] - + m[0,0] * m[2,1] * m[1,2]; +end; + +class function TgluMatrixHelper.Determinant(const m: TMat4): Double; +var + i: Integer; +begin + result := 0.0; + for i := 0 to 3 do + result := result + power(-1, i) * m[i,0] * Determinant(Sub(m, i, 0)); +end; + +class function TgluMatrixHelper.Adjoint(const m: TMat3): TMat3; +var + i, j: Integer; +begin + for i := 0 to 2 do + for j := 0 to 2 do + result[i,j] := power(-1, i+j) * Determinant(Sub(m, i, j)); + result := Transpose(result{%H-}); +end; + +class function TgluMatrixHelper.Adjoint(const m: TMat4): TMat4; +var + i, j: Integer; +begin + for i := 0 to 3 do + for j := 0 to 3 do + result[i,j] := power(-1, i+j) * Determinant(Sub(m, i, j)); + result := Transpose(result{%H-}); +end; + +class function TgluMatrixHelper.Multiply(const m1, m2: TMat2): TMat2; +begin + Mult(@m1[0,0], @m2[0,0], @result[0,0], 2, 2, 2); +end; + +class function TgluMatrixHelper.Multiply(const m1, m2: TMat3): TMat3; +begin + Mult(@m1[0,0], @m2[0,0], @result[0,0], 3, 3, 3); +end; + +class function TgluMatrixHelper.Multiply(const m1, m2: TMat4): TMat4; +begin + Mult(@m1[0,0], @m2[0,0], @result[0,0], 4, 4, 4); +end; + +class function TgluMatrixHelper.Multiply(const m: TMat2; const v: TVectorHelper.TVector2): TVectorHelper.TVector2; +begin + Mult(@m[0,0], @v[0], @result[0], 2, 2, 1); +end; + +class function TgluMatrixHelper.Multiply(const m: TMat3; const v: TVectorHelper.TVector3): TVectorHelper.TVector3; +begin + Mult(@m[0,0], @v[0], @result[0], 3, 3, 1); +end; + +class function TgluMatrixHelper.Multiply(const m: TMat4; const v: TVectorHelper.TVector4): TVectorHelper.TVector4; +begin + Mult(@m[0,0], @v[0], @result[0], 4, 4, 1); +end; + +class function TgluMatrixHelper.Multiply(const m: TMat2; const v: TBaseType): TMat2; +begin + Mult(@m[0,0], @result[0,0], 2, 2, v); +end; + +class function TgluMatrixHelper.Multiply(const m: TMat3; const v: TBaseType): TMat3; +begin + Mult(@m[0,0], @result[0,0], 3, 3, v); +end; + +class function TgluMatrixHelper.Multiply(const m: TMat4; const v: TBaseType): TMat4; +begin + Mult(@m[0,0], @result[0,0], 4, 4, v); +end; + +class function TgluMatrixHelper.Invert(const m: TMat2): TMat2; +begin + result[0,0] := m[1,1]; + result[0,1] := -m[0,1]; + result[1,0] := -m[1,0]; + result[1,1] := m[0,0]; + Mult(@result[0,0], @result[0,0], 2, 2, 1 / Determinant(m)); +end; + +class function TgluMatrixHelper.Invert(const m: TMat3): TMat3; +begin + result := Adjoint(m); + Mult(@result[0,0], @result[0,0], 2, 2, 1 / Determinant(m)); +end; + +class function TgluMatrixHelper.Invert(const m: TMat4): TMat4; +begin + result := Adjoint(m); + Mult(@result[0,0], @result[0,0], 3, 3, 1 / Determinant(m)); +end; + +class function TgluMatrixHelper.CreateTranslate(const v: TVectorHelper.TVector2): TMat3; +begin + result[0, 0] := 1.0; + result[0, 1] := 0.0; + result[0, 2] := 0.0; + result[1, 0] := 0.0; + result[1, 1] := 1.0; + result[1, 2] := 0.0; + result[2, 0] := v[0]; + result[2, 1] := v[1]; + result[2, 2] := 1.0; +end; + +class function TgluMatrixHelper.CreateTranslate(const v: TVectorHelper.TVector3): TMat4; +begin + result[0, 0] := 1.0; + result[0, 1] := 0.0; + result[0, 2] := 0.0; + result[0, 3] := 0.0; + result[1, 0] := 0.0; + result[1, 1] := 1.0; + result[1, 2] := 0.0; + result[1, 3] := 0.0; + result[2, 0] := 0.0; + result[2, 1] := 0.0; + result[2, 2] := 1.0; + result[2, 3] := 0.0; + result[3, 0] := v[0]; + result[3, 1] := v[1]; + result[3, 2] := v[2]; + result[3, 3] := 1.0; +end; + +class function TgluMatrixHelper.CreateScale(const v: TVectorHelper.TVector2): TMat3; +begin + result[0, 0] := v[0]; + result[0, 1] := 0.0; + result[0, 2] := 0.0; + result[1, 0] := 0.0; + result[1, 1] := v[1]; + result[1, 2] := 0.0; + result[2, 0] := 0.0; + result[2, 1] := 0.0; + result[2, 2] := 1.0; +end; + +class function TgluMatrixHelper.CreateScale(const v: TVectorHelper.TVector3): TMat4; +begin + result[0, 0] := v[0]; + result[0, 1] := 0.0; + result[0, 2] := 0.0; + result[0, 3] := 0.0; + result[1, 0] := 0.0; + result[1, 1] := v[1]; + result[1, 2] := 0.0; + result[1, 3] := 0.0; + result[2, 0] := 0.0; + result[2, 1] := 0.0; + result[2, 2] := v[2]; + result[2, 3] := 0.0; + result[3, 0] := 0.0; + result[3, 1] := 0.0; + result[3, 2] := 0.0; + result[3, 3] := 1.0; +end; + +class function TgluMatrixHelper.CreateRotate(a: Double): TMat3; +begin + a := DegToRad(a); + result[0, 0] := cos(a); + result[0, 1] := -sin(a); + result[0, 2] := 0.0; + result[1, 0] := sin(a); + result[1, 1] := cos(a); + result[1, 2] := 0.0; + result[2, 0] := 0.0; + result[2, 1] := 0.0; + result[2, 2] := 1.0; +end; + +class function TgluMatrixHelper.CreateRotate(axis: TVectorHelper.TVector3; a: Double): TMat4; +var + X, Y, Z, s, c: Single; +begin + a := DegToRad(a); + axis := TVectorHelperF.Normalize(axis); + X := axis[0]; + Y := axis[1]; + Z := axis[2]; + s := sin(a); + c := cos(a); + result[0,0] := SQR(X) + (1-SQR(X))*c; + result[0,1] := X*Y*(1-c) + Z*s; + result[0,2] := X*Z*(1-c) - Y*s; + result[0,3] := 0.0; + result[1,0] := X*Y*(1-c) - Z*s; + result[1,1] := SQR(Y) + (1-SQR(Y))*c; + result[1,2] := Y*Z*(1-c) + X*s; + result[1,3] := 0.0; + result[2,0] := X*Z*(1-c) + Y*s; + result[2,1] := Y*Z*(1-c) - X*s; + result[2,2] := SQR(Z) + (1-SQR(Z))*c; + result[2,3] := 0.0; + result[3,0] := 0.0; + result[3,1] := 0.0; + result[3,2] := 0.0; + result[3,3] := 1.0; +end; + +class function TgluMatrixHelper.CreateShear(const v: TVectorHelper.TVector2): TMat3; +begin + result[0, 0] := 1.0; + result[0, 1] := v[1]; + result[0, 2] := 0.0; + result[1, 0] := v[0]; + result[1, 1] := 1.0; + result[1, 2] := 0.0; + result[2, 0] := 0.0; + result[2, 1] := 0.0; + result[2, 2] := 1.0; +end; + +class function TgluMatrixHelper.CreateShear(const x, y, z: TVectorHelper.TVector2): TMat4; +begin + result[0,0] := 1.0; + result[0,1] := y[0]; + result[0,2] := z[0]; + result[0,3] := 0.0; + result[1,0] := x[0]; + result[1,1] := 1.0; + result[1,2] := z[1]; + result[1,3] := 0.0; + result[2,0] := x[1]; + result[2,1] := y[1]; + result[2,2] := 1.0; + result[2,3] := 0.0; + result[3,0] := 0.0; + result[3,1] := 0.0; + result[3,2] := 0.0; + result[3,3] := 1.0; +end; + +class function TgluMatrixHelper.GetElement(p: PBaseType; x, y, sz: Integer): TBaseType; +begin + result := (p + (x * sz) + y)^; +end; + +class procedure TgluMatrixHelper.SetElement(p: PBaseType; x, y, sz: Integer; v: TBaseType); +begin + (p + (x * sz) + y)^ := v; +end; + +class procedure TgluMatrixHelper.Transpose(src, dst: PBaseType; sz: Integer); +var + i, j: Integer; +begin + for i := 0 to sz-1 do + for j := 0 to sz-1 do + SetElement(dst, i, j, sz, GetElement(src, j, i, sz)); +end; + +class procedure TgluMatrixHelper.Sub(src, dst: PBaseType; sz, c, r: Integer); +var + x, y, i, j: Integer; +begin + for i := 0 to sz-1 do begin + for j := 0 to sz-1 do begin + x := i; + y := j; + if (i >= c) then inc(x); + if (j >= r) then inc(y); + SetElement(dst, i, j, sz-1, GetElement(src, x, y, sz)); + end; + end; +end; + +class procedure TgluMatrixHelper.Mult(p1, p2, r: PBaseType; c1r2, r1, c2: Integer); +var + x, y, i: Integer; + sum: TBaseType; +begin + for x := 0 to c2-1 do begin + for y := 0 to r1-1 do begin + sum := 0; + for i := 0 to c1r2-1 do + sum := sum + GetElement(p1, i, y, c1r2) * GetElement(p2, x, i, c2); + SetElement(r, x, y, c2, sum); + end; + end; +end; + +class procedure TgluMatrixHelper.Mult(src, dst: PBaseType; c, r: Integer; v: TBaseType); +var + i, j: Integer; +begin + for i := 0 to c-1 do + for j := 0 to r-1 do + SetElement(dst, i, j, c, v * GetElement(src, i, j, c)); +end; + +class function TgluMatrixHelper.TryFromString(const s: String; p: PBaseType; r, c: Integer): Boolean; +var + i, j, l: Integer; +begin + result := true; + l := Length(s); + i := 1; + j := l; + while (i <= l) and (c > 0) and result do begin + if (s[i] = '(') then begin + j := i+1; + end else if (s[i] = ')') then begin + result := TVectorHelper.TryFromString(trim(copy(s, j, i-j)), p, r); + j := l; + inc(p, r); + dec(c); + end; + inc(i); + end; + + result := (c = 0); + while (c > 0) do begin + for i := 0 to r-1 do begin + p^ := 0; + inc(p); + end; + dec(c); + end; +end; + +end. + diff --git a/ugluVectorEx.pas b/ugluVectorEx.pas index fb6d582..86ded69 100644 --- a/ugluVectorEx.pas +++ b/ugluVectorEx.pas @@ -39,6 +39,38 @@ type TgluVector3d = TgluVectorD.TVector3; TgluVector4d = TgluVectorD.TVector4; + + + PgluVector2p = ^TgluVector2p; + PgluVector3p = ^TgluVector3p; + PgluVector4p = ^TgluVector4p; + + PgluVector2e = ^TgluVector2e; + PgluVector3e = ^TgluVector3e; + PgluVector4e = ^TgluVector4e; + + PgluVector2i = ^TgluVector2i; + PgluVector3i = ^TgluVector3i; + PgluVector4i = ^TgluVector4i; + + PgluVector2us = ^TgluVector2us; + PgluVector3us = ^TgluVector3us; + PgluVector4us = ^TgluVector4us; + + PgluVector2ub = ^TgluVector2ub; + PgluVector3ub = ^TgluVector3ub; + PgluVector4ub = ^TgluVector4ub; + + PgluVector2f = ^TgluVector2f; + PgluVector3f = ^TgluVector3f; + PgluVector4f = ^TgluVector4f; + + PgluVector2d = ^TgluVector2d; + PgluVector3d = ^TgluVector3d; + PgluVector4d = ^TgluVector4d; + + + {$DEFINE __VECTOR_HELPER_INTERFACE} { TgluVector2p } {$DEFINE __IMPL := TgluVectorP} diff --git a/ugluVectorExHelper.pas b/ugluVectorExHelper.pas index d20b92e..fb1b544 100644 --- a/ugluVectorExHelper.pas +++ b/ugluVectorExHelper.pas @@ -38,8 +38,6 @@ type class function TryFromString(const s: String; out v: TVector2): Boolean; overload; inline; class function TryFromString(const s: String; out v: TVector3): Boolean; overload; inline; class function TryFromString(const s: String; out v: TVector4): Boolean; overload; inline; - - private class function TryFromString(const s: String; p: PBaseType; aCount: Integer): Boolean; end; @@ -99,12 +97,6 @@ type TgluVectorF = specialize TgluVectorHelperF; TgluVectorD = specialize TgluVectorHelperF; -implementation - -uses - Math; - -type TPointerTypeHelper = type helper for Pointer function ToString(const aRound: Integer = -3): String; class function TryFromString(s: String; out v: Pointer): Boolean; static; @@ -140,6 +132,11 @@ type class function TryFromString(s: String; out v: Double): Boolean; static; end; +implementation + +uses + Math; + function IntToStrRounded(i: Int64; const aRound: Integer): String; var p: Cardinal; begin @@ -353,7 +350,8 @@ begin j := 1; l := Length(s); while ({%H-}i <= {%H-}l) and (aCount > 0) and result {%H-}do begin - if (s[i] = ';') then begin + if (s[i] = ';') or (i = l) then begin + if (i = l) then inc(i); result := TBaseType.TryFromString(Trim(copy(s, j, i-{%H-}j)), p^); j := i+1; inc(p); @@ -362,6 +360,7 @@ begin inc(i); end; + result := (aCount = 0); while (aCount > 0) do begin p^ := TBaseType(0); inc(p);