GLTypes.pas 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371
  1. //
  2. // This unit is part of the GLScene Engine, http://glscene.org
  3. //
  4. {
  5. Defines common vector types as advanced records.
  6. }
  7. unit GLTypes;
  8. interface
  9. {$I GLScene.inc}
  10. uses
  11. System.Types,
  12. System.SysUtils,
  13. System.Rtti,
  14. System.Math,
  15. System.Math.Vectors,
  16. GLVectorTypes;
  17. type
  18. TAbstractVector = array of Extended;
  19. TAbstractMatrix = array of array of Extended;
  20. TxQuaternion = record
  21. private
  22. FData: array[0..3] of Extended;
  23. procedure SetElement(Index: Byte; Value: Extended);
  24. function GetElement(Index: Byte): Extended;
  25. public
  26. constructor Create(Q: TAbstractVector);
  27. class operator Multiply(Q1, Q2: TxQuaternion): TxQuaternion;
  28. class operator Multiply(Q: TxQuaternion; Sc: Extended): TxQuaternion;
  29. class operator Multiply(Scalar: Extended; Q: TxQuaternion): TxQuaternion;
  30. class operator Implicit(V: TAbstractVector): TxQuaternion;
  31. function Inv: TxQuaternion;
  32. function TruncateSTI: TxQuaternion;
  33. property Element[index: Byte]: Extended read GetElement
  34. write SetElement; default;
  35. end;
  36. PxVector = ^TxVector;
  37. TxVector = record
  38. private
  39. FData: TAbstractVector;
  40. FCount: Word;
  41. procedure SetElement(Index: Word; Value: Extended);
  42. function GetElement(Index: Word): Extended;
  43. procedure CheckUnique;
  44. public
  45. constructor Create(ElementsCount: Word); overload;
  46. constructor Create(V: TAbstractVector); overload;
  47. class operator Add(V1, V2: TxVector): TxVector;
  48. class operator Add(V: TxVector; Scalar: Extended): TxVector;
  49. class operator Add(Scalar: Extended; V: TxVector): TxVector;
  50. class operator Subtract(V1, V2: TxVector): TxVector;
  51. class operator Subtract(Scalar: Extended; V: TxVector): TxVector;
  52. class operator Subtract(V: TxVector; Scalar: Extended): TxVector;
  53. class operator Multiply(V1, V2: TxVector): TxVector;
  54. class operator Multiply(V: TxVector; Scalar: Extended): TxVector;
  55. class operator Multiply(Scalar: Extended; V: TxVector): TxVector;
  56. class operator Divide(V: TxVector; Scalar: Extended): TxVector;
  57. class operator Divide(V1, V2: TxVector): TxVector;
  58. class operator Implicit(V: TAbstractVector): TxVector;
  59. function Norm: Extended;
  60. function SumOfSquares: Extended;
  61. function SumOfElments: Extended;
  62. function TruncateSTI: TxVector;
  63. function ToQuat: TxQuaternion;
  64. procedure Fill(Value: Extended);
  65. function ScalarMult(V: TxVector): Extended;
  66. property Count: Word read FCount;
  67. property Elements[index: Word]: Extended read GetElement
  68. write SetElement; default;
  69. end;
  70. PxMatrix = ^TxMatrix;
  71. TxMatrix = record
  72. private
  73. FData: TAbstractMatrix;
  74. FRowsCount: Word;
  75. FColsCount: Word;
  76. procedure SetElement(Row, Col: Word; Value: Extended);
  77. function GetElement(Row, Col: Word): Extended;
  78. function GetRow(Row: Word): TxVector;
  79. procedure SetRow(Row: Word; Value: TxVector);
  80. function GetCol(Col: Word): TxVector;
  81. procedure SetCol(Col: Word; Value: TxVector);
  82. function Del(A: TxMatrix; I, J: Integer; M: Integer): TxMatrix;
  83. function Det(A: TxMatrix; M: Integer): Extended;
  84. procedure CheckUnique;
  85. public
  86. constructor Create(RowsCount, ColsCount: Word); overload;
  87. constructor CreateDiag(Dim: Word; Value: Extended = 1.0);
  88. constructor Create(M: TAbstractMatrix); overload;
  89. class operator Add(M1, M2: TxMatrix): TxMatrix;
  90. class operator Subtract(M1, M2: TxMatrix): TxMatrix;
  91. class operator Multiply(M1, M2: TxMatrix): TxMatrix;
  92. class operator Multiply(M: TxMatrix; V: TxVector): TxVector;
  93. class operator Multiply(V: TxVector; M: TxMatrix): TxVector;
  94. class operator Multiply(M: TxMatrix; Scalar: Extended): TxMatrix;
  95. class operator Multiply(Scalar: Extended; M: TxMatrix): TxMatrix;
  96. class operator Multiply(M: TxMatrix; Q: TxQuaternion): TxQuaternion;
  97. class operator Implicit(M: TAbstractMatrix): TxMatrix;
  98. function Transp: TxMatrix;
  99. function Inv: TxMatrix;
  100. function ToQuat: TxQuaternion;
  101. function Determinant: Extended;
  102. function TruncateSTI: TxMatrix;
  103. function Trace: Extended; // sum on diagonal elements
  104. procedure Fill(Scalar: Extended);
  105. property RowCount: Word read FRowsCount;
  106. property ColCount: Word read FColsCount;
  107. property Row[Row: Word]: TxVector read GetRow write SetRow;
  108. property Col[Col: Word]: TxVector read GetCol write SetCol;
  109. property Elements[Row, Col: Word]: Extended read GetElement
  110. write SetElement; default;
  111. end;
  112. TxQuatHelper = record helper for TxQuaternion
  113. function ToMatrix: TxMatrix;
  114. end;
  115. TxVecHelper = record helper for TxVector
  116. function ToDiagMatrix: TxMatrix;
  117. end;
  118. TxDim = class(TCustomAttribute)
  119. private
  120. FRowCount: Integer;
  121. FColCount: Integer;
  122. public
  123. constructor Create(ARowCount: Integer; AColCount: Integer = 0); overload;
  124. property RowCount: Integer read FRowCount;
  125. property ColCount: Integer read FColCount;
  126. end;
  127. function TxVec(V: TAbstractVector): TxVector;
  128. function TxMat(M: TAbstractMatrix): TxMatrix;
  129. function TxQuat(Q: TAbstractVector): TxQuaternion;
  130. procedure Init(Obj, TypeInfoOfObj: Pointer; Offset: Integer = 0);
  131. //-----------------------
  132. // Point types
  133. //-----------------------
  134. type
  135. TxScalarValue = Single;
  136. TxScalarField = function(X, Y, Z: Single): TxScalarValue;
  137. // If data are made on integer XYZ index
  138. TxScalarFieldInt = function(iX, iY, iZ: Integer): TxScalarValue of object;
  139. TxVertex = record
  140. P, N: TVector3f; //Point and Normal
  141. Density: Single;
  142. end;
  143. TxFace = record
  144. Normal: TVector3f;
  145. V1: TVector3f; // vertex 1
  146. V2: TVector3f; // vertex 2
  147. V3: TVector3f; // vertex 3
  148. Padding: array [0 .. 1] of Byte;
  149. end;
  150. PxPoint2D = ^TxPoint2D;
  151. TxPoint2D = record
  152. X: Single;
  153. Y: Single;
  154. public
  155. function Create(X, Y : Single): TxPoint2D;
  156. procedure SetPosition(const X, Y : Single);
  157. function Add(const APoint2D: TxPoint2D): TxPoint2D;
  158. function Length: Single; //distance to origin
  159. function Distance(const APoint2D : TxPoint2D) : Single;
  160. class function PointInCircle(const Point, Center: TxPoint2D;
  161. const Radius: Integer):Boolean; static; inline;
  162. procedure Offset(const ADeltaX, ADeltaY : Single);
  163. end;
  164. PxPoint3D = ^TxPoint3D;
  165. TxPoint3D = record
  166. X: Single;
  167. Y: Single;
  168. Z: Single;
  169. public
  170. function Create(X, Y, Z: Single): TxPoint3D;
  171. procedure SetPosition(const X, Y, Z : Single);
  172. function Add(const AGLPoint3D: TxPoint3D): TxPoint3D;
  173. function Length: Single; //distance to origin
  174. function Distance(const APoint3D : TxPoint3D) : Single;
  175. procedure Offset(const ADeltaX, ADeltaY, ADeltaZ : Single);
  176. end;
  177. TxPoint2DArray = array of TxPoint2D;
  178. TxPoint3DArray = array of TxPoint3D;
  179. // Voxel types
  180. TxVoxelStatus = (bpExternal, bpInternal);
  181. TxVoxel = record
  182. P: TVector3f;
  183. Density: TxScalarValue;
  184. Status: TxVoxelStatus;
  185. end;
  186. PxVoxel = ^TxVoxel;
  187. TxVoxelData = array [0 .. (MaxInt shr 8)] of TxVoxel;
  188. PxVoxelData = ^TxVoxelData;
  189. //-----------------------
  190. // Vector types
  191. //-----------------------
  192. TxVector2DType = array [0..1] of Single;
  193. TxVector3DType = array [0..2] of Single;
  194. TxVector2D = record
  195. function Create(const AX, AY, AW : Single): TxVector2D;
  196. function Add(const AVector2D: TxVector2D): TxVector2D;
  197. function Length: Single;
  198. function Norm: Single;
  199. function Normalize: TxVector2D;
  200. function CrossProduct(const AVector: TxVector2D): TxVector2D;
  201. function DotProduct(const AVector: TxVector2D): Single;
  202. case Integer of
  203. 0: (V: TxVector2DType;);
  204. 1: (X: Single;
  205. Y: Single;
  206. W: Single;)
  207. end;
  208. TxVector3D = record
  209. function Create(const AX, AY, AZ, AW : Single): TxVector3D;
  210. function Add(const AVector3D: TxVector3D): TxVector3D;
  211. function Length: Single;
  212. function Norm: Single;
  213. function Normalize: TxVector3D;
  214. function CrossProduct(const AVector3D: TVector3D): TVector3D;
  215. function DotProduct(const AVector3D: TVector3D): Single; inline;
  216. case Integer of
  217. 0: (V: TxVector3DType;);
  218. 1: (X: Single;
  219. Y: Single;
  220. Z: Single;
  221. W: Single;)
  222. end;
  223. // Vector Arrays
  224. TxVector2DArray = array of TxVector2D;
  225. TxVector3DArray = array of TxVector3D;
  226. //-----------------------
  227. // Matrix types
  228. //-----------------------
  229. TxMatrix2DType = array[0..3] of TxVector2D;
  230. TxMatrix3DType = array[0..3] of TxVector3D;
  231. TxMatrix2D = record
  232. private
  233. public
  234. case Integer of
  235. 0: (M: TxMatrix2DType;);
  236. 1: (e11, e12, e13: Single;
  237. e21, e22, e23: Single;
  238. e31, e32, e33: Single);
  239. end;
  240. TxMatrix3D = record
  241. private
  242. public
  243. case Integer of
  244. 0: (M: TxMatrix3DType;);
  245. 1: (e11, e12, e13, e14: Single;
  246. e21, e22, e23, e24: Single;
  247. e31, e32, e33, e34: Single;
  248. e41, e42, e43, e44: Single);
  249. end;
  250. // Matrix Arrays
  251. TxMatrix2DArray = array of TxMatrix2D;
  252. TxMatrix3DArray = array of TxMatrix3D;
  253. //-----------------------
  254. // Polygon types
  255. //-----------------------
  256. TxPolygon2D = TxPoint2DArray;
  257. TxPolygon3D = TxPoint3DArray;
  258. {
  259. TxPolygon3D = record
  260. Vertices: array of TxPoint3D;
  261. function Area;
  262. end;
  263. }
  264. const
  265. ClosedPolygon2D: TxPoint2D = (X: $FFFF; Y: $FFFF);
  266. ClosedPolygon3D: TxPoint3D = (X: $FFFF; Y: $FFFF; Z: $FFFF);
  267. type
  268. PxVertexArray = ^TxVertexArray;
  269. TxVertexArray = array [0 .. (MaxInt shr 8)] of TxVertex;
  270. type
  271. TxTriangle = record
  272. v1, v2, v3: Integer;
  273. ///Vertices: array[0..2] of TxPoint3D;
  274. ///function Area;
  275. end;
  276. PxTriangleArray = ^TxTriangleArray;
  277. TxTriangleArray = array [0 .. (MaxInt shr 8)] of TxTriangle;
  278. //-----------------------
  279. // Polyhedron types
  280. //-----------------------
  281. type
  282. TxPolyhedron = array of TxPolygon3D;
  283. {
  284. TxPolyhedron = record
  285. Facets: array of TxPolygon3D;
  286. function NetLength;
  287. function Area;
  288. function Volume;
  289. end;
  290. }
  291. //--------------------------
  292. // Mesh simple record types
  293. //--------------------------
  294. type
  295. TxMesh2DVertex = record
  296. X, Y: Single;
  297. NX, NY: Single;
  298. tU, tV: Single;
  299. end;
  300. TxMesh3DVertex = packed record
  301. X, Y, Z: Single;
  302. NX, NY, NZ: Single;
  303. tU, tV: Single;
  304. end;
  305. TxMesh2D = array of TxMesh2DVertex;
  306. TxMesh3D = array of TxMesh3DVertex;
  307. //--------------------------
  308. // Quaternion record types
  309. //--------------------------
  310. type
  311. TxQuaternion3D = record
  312. ImPart: TxVector3D;
  313. RePart: Single;
  314. end;
  315. TxQuaternionArray = array of TxQuaternion3D;
  316. type
  317. TxBox = record
  318. ALeft, ATop, ANear, ARight, ABottom, AFar: Single;
  319. end;
  320. const
  321. sWRONG_ELEMENT = 'Wrong element';
  322. sWRONG_SIZE = 'Wrong size';
  323. sNOT_QUAD = 'Matrix not quadratic';
  324. sSINGULAR = 'Singular matrix founded';
  325. //---------------------------------------------------------------
  326. implementation
  327. //---------------------------------------------------------------
  328. function TxVec(V: TAbstractVector): TxVector;
  329. begin
  330. Result.Create(V);
  331. end;
  332. function TxMat(M: TAbstractMatrix): TxMatrix;
  333. begin
  334. Result.Create(M);
  335. end;
  336. function TxQuat(Q: TAbstractVector): TxQuaternion;
  337. begin
  338. Result.Create(Q);
  339. end;
  340. {$POINTERMATH ON}
  341. function NotUnique(PArr: PCardinal): Boolean;
  342. begin
  343. Result := (PArr - 2)^ > 1;
  344. end;
  345. { TxMatrix }
  346. // Removing i-th row and j-th col
  347. function TxMatrix.Del(A: TxMatrix; I, J: Integer; M: Integer): TxMatrix;
  348. var
  349. K, G: Integer;
  350. begin
  351. for G := I to M - 1 do
  352. for K := 1 to M do
  353. A[G, K] := A[G + 1, K];
  354. for G := J to M - 1 do
  355. for K := 1 to M - 1 do
  356. A[K, G] := A[K, G + 1];
  357. Result := A;
  358. end;
  359. // Recursive calculation of det for matrix
  360. function TxMatrix.Det(A: TxMatrix; M: Integer): Extended;
  361. var
  362. I: Integer;
  363. Buf: Extended;
  364. begin
  365. Buf := 0;
  366. if M = 1 then
  367. Buf := A[1, 1]
  368. else
  369. for I := 1 to M do
  370. Buf := Buf + Power10(-1, I + 1) * A[I, 1] *
  371. Det(Del(A, I, 1, M), M - 1);
  372. Result := Buf;
  373. end;
  374. class operator TxMatrix.Add(M1, M2: TxMatrix): TxMatrix;
  375. var
  376. I, J: Integer;
  377. begin
  378. if (M1.FRowsCount <> M2.FRowsCount) or (M1.FColsCount <> M2.FColsCount) then
  379. raise EMathError.Create(sWRONG_SIZE);
  380. Result.Create(M1.FRowsCount, M1.FColsCount);
  381. for I := 0 to M1.FRowsCount - 1 do
  382. for J := 0 to M1.FColsCount - 1 do
  383. Result.FData[I, J] := M1.FData[I, J] + M2.FData[I, J];
  384. end;
  385. procedure TxMatrix.CheckUnique;
  386. var
  387. I: Integer;
  388. begin
  389. if NotUnique(@FData) then
  390. begin
  391. FData := Copy(FData);
  392. for I := 0 to Pred(FRowsCount) do
  393. FData[i] := Copy(FData[i]);
  394. end;
  395. end;
  396. constructor TxMatrix.Create(RowsCount, ColsCount: Word);
  397. begin
  398. FRowsCount := RowsCount;
  399. FColsCount := ColsCount;
  400. FData := nil;
  401. SetLength(FData, FRowsCount, FColsCount);
  402. end;
  403. constructor TxMatrix.Create(M: TAbstractMatrix);
  404. var
  405. I: Integer;
  406. begin
  407. FRowsCount := Length(M);
  408. FColsCount := Length(M[0]);
  409. FData := nil;
  410. SetLength(FData, FRowsCount, FColsCount);
  411. for I := 0 to Pred(FRowsCount) do
  412. begin
  413. if Length(M[I]) <> FColsCount then
  414. raise EMathError.Create('Wrong matrix proportions');
  415. FData[I] := Copy(M[I]);
  416. end;
  417. end;
  418. constructor TxMatrix.CreateDiag(Dim: Word; Value: Extended = 1.0);
  419. var
  420. I: Integer;
  421. begin
  422. Create(Dim, Dim);
  423. for I := 0 to Dim - 1 do
  424. FData[I, I] := Value;
  425. end;
  426. function TxMatrix.Determinant: Extended;
  427. begin
  428. if (FRowsCount <> FColsCount) then
  429. raise EMathError.Create(sNOT_QUAD);
  430. Result := Det(Self, FRowsCount);
  431. end;
  432. procedure TxMatrix.Fill(Scalar: Extended);
  433. var
  434. I, J: Integer;
  435. begin
  436. if Scalar = 0 then
  437. begin
  438. FData := nil;
  439. SetLength(FData, FRowsCount, FColsCount);
  440. end
  441. else
  442. for I := 0 to FRowsCount - 1 do
  443. for J := 0 to FColsCount - 1 do
  444. FData[I, J] := Scalar;
  445. end;
  446. function TxMatrix.GetCol(Col: Word): TxVector;
  447. var
  448. I: Integer;
  449. begin
  450. if (Col = 0) or (Col > FColsCount) then
  451. raise EMathError.Create(sWRONG_ELEMENT);
  452. Result.Create(FRowsCount);
  453. for I := 0 to FRowsCount - 1 do
  454. Result.FData[I] := FData[I, Col - 1];
  455. end;
  456. function TxMatrix.GetElement(Row, Col: Word): Extended;
  457. begin
  458. {$R+}
  459. Result := FData[Pred(Row), Pred(Col)];
  460. end;
  461. function TxMatrix.GetRow(Row: Word): TxVector;
  462. var
  463. I: Integer;
  464. begin
  465. if (Row = 0) or (Row > FRowsCount) then
  466. raise EMathError.Create(sWRONG_ELEMENT);
  467. Result.Create(FColsCount);
  468. for I := 0 to FColsCount - 1 do
  469. Result.FData[I] := FData[Row - 1, I];
  470. end;
  471. class operator TxMatrix.Implicit(M: TAbstractMatrix): TxMatrix;
  472. begin
  473. Result.Create(M);
  474. end;
  475. function TxMatrix.Inv: TxMatrix;
  476. var
  477. Ipiv, Indxr, Indxc: array of Integer;
  478. DimMat, I, J, K, L, N, ICol, IRow: Integer;
  479. Big, Dum, Pivinv: Extended;
  480. begin
  481. // Jordan algorithm
  482. if (FRowsCount <> FColsCount) then
  483. raise EMathError.Create(sNOT_QUAD);
  484. Result := Self;
  485. DimMat := FRowsCount;
  486. SetLength(Ipiv, DimMat);
  487. SetLength(Indxr, DimMat);
  488. SetLength(Indxc, DimMat);
  489. IRow := 1;
  490. ICol := 1;
  491. for I := 1 to DimMat do
  492. begin
  493. Big := 0;
  494. for J := 1 to DimMat do
  495. if (Ipiv[J - 1] <> 1) then
  496. for K := 1 to DimMat do
  497. if (Ipiv[K - 1] = 0) then
  498. if (Abs(Result[J, K]) >= Big) then
  499. begin
  500. Big := Abs(Result[J, K]);
  501. IRow := J;
  502. ICol := K;
  503. end;
  504. Ipiv[ICol - 1] := Ipiv[ICol - 1] + 1;
  505. if (IRow <> ICol) then
  506. for L := 1 to DimMat do
  507. begin
  508. Dum := Result[IRow, L];
  509. Result[IRow, L] := Result[ICol, L];
  510. Result[ICol, L] := Dum;
  511. end;
  512. Indxr[I - 1] := IRow;
  513. Indxc[I - 1] := ICol;
  514. if Result[ICol, ICol] = 0 then
  515. raise EMathError.Create(sSINGULAR);
  516. Pivinv := 1.0 / Result[ICol, ICol];
  517. Result[ICol, ICol] := 1.0;
  518. for L := 1 to DimMat do
  519. Result[ICol, L] := Result[ICol, L] * Pivinv;
  520. for N := 1 to DimMat do
  521. if (N <> ICol) then
  522. begin
  523. Dum := Result[N, ICol];
  524. Result[N, ICol] := 0.0;
  525. for L := 1 to DimMat do
  526. Result[N, L] := Result[N, L] - Result[ICol, L] * Dum;
  527. end;
  528. end;
  529. for L := DimMat downto 1 do
  530. if (Indxr[L - 1] <> Indxc[L - 1]) then
  531. for K := 1 to DimMat do
  532. begin
  533. Dum := Result[K, Indxr[L - 1]];
  534. Result[K, Indxr[L - 1]] := Result[K, Indxc[L - 1]];
  535. Result[K, Indxc[L - 1]] := Dum;
  536. end;
  537. end;
  538. function TxMatrix.ToQuat: TxQuaternion;
  539. begin
  540. Result[0] := 0.5 * Sqrt(Abs(1 + Self[1,1] + Self[2,2] + Self[3,3]));
  541. Result[1] := 0.5 * Sqrt(Abs(1 + Self[1,1] - Self[2,2] - Self[3,3]));
  542. if Self[3,2] < Self[2,3] then
  543. Result[1] := -Result[1];
  544. Result[2] := 0.5 * Sqrt(Abs(1 - Self[1,1] + Self[2,2] - Self[3,3]));
  545. if Self[1,3] < Self[3,1] then
  546. Result[2] := -Result[2];
  547. Result[3] := 0.5 * Sqrt(Abs(1 - Self[1,1] - Self[2,2] + Self[3,3]));
  548. if Self[2,1] < Self[1,2] then
  549. Result[3] := -Result[3];
  550. end;
  551. class operator TxMatrix.Multiply(M: TxMatrix; Q: TxQuaternion): TxQuaternion;
  552. var
  553. I, J: Integer;
  554. begin
  555. if (M.FRowsCount <> 4) or (M.FRowsCount <> M.FColsCount) then
  556. raise EMathError.Create(sWRONG_SIZE);
  557. FillChar(Result.FData, SizeOf(Result.FData), 0);
  558. for I := 0 to 3 do
  559. for J := 0 to 3 do
  560. Result.FData[I] := Result.FData[I] + M.FData[I, J] * Q.FData[J];
  561. end;
  562. class operator TxMatrix.Multiply(Scalar: Extended; M: TxMatrix): TxMatrix;
  563. begin
  564. Result := M * Scalar;
  565. end;
  566. class operator TxMatrix.Multiply(V: TxVector; M: TxMatrix): TxVector;
  567. var
  568. I, J: Integer;
  569. begin
  570. if (V.FCount <> M.FRowsCount) then
  571. raise EMathError.Create(sWRONG_SIZE);
  572. Result.Create(V.FCount);
  573. for I := 0 to V.FCount - 1 do
  574. for J := 0 to V.FCount - 1 do
  575. Result.FData[I] := Result.FData[I] + V.FData[J] * M.FData[J, I];
  576. end;
  577. class operator TxMatrix.Multiply(M: TxMatrix; V: TxVector): TxVector;
  578. var
  579. I, J: Integer;
  580. begin
  581. if (M.FColsCount <> V.FCount) then
  582. raise EMathError.Create(sWRONG_SIZE);
  583. Result.Create(M.FRowsCount);
  584. for I := 0 to M.FRowsCount - 1 do
  585. for J := 0 to M.FColsCount - 1 do
  586. Result.FData[I] := Result.FData[I] + M.FData[I, J] * V.FData[J];
  587. end;
  588. class operator TxMatrix.Multiply(M: TxMatrix; Scalar: Extended): TxMatrix;
  589. var
  590. I, J: Integer;
  591. begin
  592. Result.Create(M.FRowsCount, M.FColsCount);
  593. for I := 0 to M.FRowsCount - 1 do
  594. for J := 0 to M.FColsCount - 1 do
  595. Result.FData[I, J] := M.FData[I, J] * Scalar;
  596. end;
  597. class operator TxMatrix.Multiply(M1, M2: TxMatrix): TxMatrix;
  598. var
  599. I, J, K: Integer;
  600. begin
  601. if (M1.FColsCount <> M2.FRowsCount) then
  602. raise EMathError.Create(sWRONG_SIZE);
  603. Result.Create(M1.FRowsCount, M2.FColsCount);
  604. for I := 0 to M1.FRowsCount - 1 do
  605. for J := 0 to M2.FColsCount - 1 do
  606. for K := 0 to M1.FColsCount - 1 do
  607. Result.FData[I, J] := Result.FData[I, J] + M1.FData[I, K] * M2.FData[K, J];
  608. end;
  609. procedure TxMatrix.SetCol(Col: Word; Value: TxVector);
  610. var
  611. I: Integer;
  612. begin
  613. if (Col = 0) or (Col > FColsCount) then
  614. raise EMathError.Create(sWRONG_ELEMENT);
  615. if (Value.Count <> FRowsCount) then
  616. raise EMathError.Create(sWRONG_SIZE);
  617. for I := 0 to FRowsCount - 1 do
  618. FData[I, Col - 1] := Value.FData[I];
  619. end;
  620. procedure TxMatrix.SetElement(Row, Col: Word; Value: Extended);
  621. begin
  622. {$R+}
  623. CheckUnique;
  624. FData[Pred(Row), Pred(Col)] := Value;
  625. end;
  626. procedure TxMatrix.SetRow(Row: Word; Value: TxVector);
  627. var
  628. I: Integer;
  629. begin
  630. if (Row = 0) or (Row > FRowsCount) then
  631. raise EMathError.Create(sWRONG_ELEMENT);
  632. if (Value.Count <> FColsCount) then
  633. raise EMathError.Create(sWRONG_SIZE);
  634. for I := 0 to FColsCount - 1 do
  635. FData[Row - 1, I] := Value.FData[I];
  636. end;
  637. class operator TxMatrix.Subtract(M1, M2: TxMatrix): TxMatrix;
  638. var
  639. I, J: Integer;
  640. begin
  641. if (M1.FColsCount <> M2.FColsCount) or (M1.FRowsCount <> M2.FRowsCount) then
  642. raise EMathError.Create(sWRONG_SIZE);
  643. Result.Create(M1.FRowsCount, M1.FColsCount);
  644. for I := 0 to M1.FRowsCount - 1 do
  645. for J := 0 to M1.FColsCount - 1 do
  646. Result.FData[I, J] := M1.FData[I, J] - M2.FData[I, J];
  647. end;
  648. function TxMatrix.Trace: Extended;
  649. var
  650. I: Integer;
  651. begin
  652. Result := 0;
  653. if FColsCount <> FRowsCount then
  654. raise EMathError.Create(sNOT_QUAD);
  655. for I := 0 to FColsCount - 1 do
  656. Result := Result + FData[I, I];
  657. end;
  658. function TxMatrix.Transp: TxMatrix;
  659. var
  660. I, J: Integer;
  661. begin
  662. Result.Create(FColsCount, FRowsCount);
  663. for I := 0 to FColsCount - 1 do
  664. for J := 0 to FRowsCount - 1 do
  665. Result.FData[I, J] := FData[J, I];
  666. end;
  667. function TxMatrix.TruncateSTI: TxMatrix;
  668. const
  669. Int32Max: Double = Integer.MaxValue;
  670. Int32Min: Double = Integer.MinValue;
  671. var
  672. I, J: Integer;
  673. begin
  674. Result.Create(FRowsCount, FColsCount);
  675. for I := 0 to FRowsCount - 1 do
  676. for J := 0 to FColsCount - 1 do
  677. begin
  678. if (FData[I, J] >= Int32Min) and (FData[I, J] <= Int32Max) then
  679. Result.FData[I, J] := Trunc(FData[I, J])
  680. else
  681. if (FData[I, J] < Int32Min) then
  682. Result.FData[I, J] := Int32Min
  683. else
  684. Result.FData[I, J] := Int32Max;
  685. end;
  686. end;
  687. { TxVector }
  688. constructor TxVector.Create(V: TAbstractVector);
  689. begin
  690. FCount := Length(V);
  691. FData := Copy(V);
  692. end;
  693. constructor TxVector.Create(ElementsCount: Word);
  694. begin
  695. FCount := ElementsCount;
  696. FData := nil;
  697. SetLength(FData, FCount);
  698. end;
  699. class operator TxVector.Add(V1, V2: TxVector): TxVector;
  700. var
  701. i: Integer;
  702. begin
  703. if (V1.FCount <> V2.FCount) then
  704. raise EMathError.Create(sWRONG_SIZE);
  705. Result := TxVector.Create(V1.FCount);
  706. for i := 0 to V1.FCount - 1 do
  707. Result.FData[i] := V1.FData[i] + V2.FData[i];
  708. end;
  709. class operator TxVector.Add(V: TxVector; Scalar: Extended): TxVector;
  710. var
  711. I: Integer;
  712. begin
  713. Result.Create(V.FCount);
  714. for I := 0 to V.FCount - 1 do
  715. Result.FData[I] := V.FData[I] + Scalar;
  716. end;
  717. class operator TxVector.Add(Scalar: Extended; V: TxVector): TxVector;
  718. begin
  719. Result := V + Scalar;
  720. end;
  721. procedure TxVector.CheckUnique;
  722. begin
  723. if NotUnique(@FData) then
  724. FData := Copy(FData);
  725. end;
  726. class operator TxVector.Divide(V1, V2: TxVector): TxVector;
  727. var
  728. I: Integer;
  729. begin
  730. if (V1.FCount <> V2.FCount) then
  731. raise EMathError.Create(sWRONG_SIZE);
  732. Result.Create(V1.FCount);
  733. for I := 0 to V1.FCount - 1 do
  734. Result.FData[I] := V1.FData[I] / V2.FData[I];
  735. end;
  736. class operator TxVector.Divide(V: TxVector; Scalar: Extended): TxVector;
  737. begin
  738. Result := V * (1 / Scalar);
  739. end;
  740. class operator TxVector.Implicit(V: TAbstractVector): TxVector;
  741. begin
  742. Result.Create(V);
  743. end;
  744. procedure TxVector.Fill(Value: Extended);
  745. var
  746. I: Integer;
  747. begin
  748. if Value = 0 then
  749. begin
  750. FData := nil;
  751. SetLength(FData, FCount);
  752. end
  753. else
  754. for I := 0 to FCount - 1 do
  755. FData[I] := Value;
  756. end;
  757. function TxVector.GetElement(Index: Word): Extended;
  758. begin
  759. if (Index = 0) or (Index > FCount) then
  760. raise EMathError.Create(sWRONG_ELEMENT);
  761. Result := FData[Pred(Index)];
  762. end;
  763. class operator TxVector.Multiply(V: TxVector; Scalar: Extended): TxVector;
  764. var
  765. I: Integer;
  766. begin
  767. Result.Create(V.FCount);
  768. for I := 0 to V.FCount - 1 do
  769. Result.FData[I] := V.FData[I] * Scalar;
  770. end;
  771. class operator TxVector.Multiply(Scalar: Extended; V: TxVector): TxVector;
  772. begin
  773. Result := V * Scalar;
  774. end;
  775. function TxVector.Norm: Extended;
  776. begin
  777. Result := System.Math.Norm(FData);
  778. end;
  779. class operator TxVector.Multiply(V1, V2: TxVector): TxVector;
  780. begin
  781. if (V1.FCount <> 3) or (V2.FCount <> 3) then
  782. raise EMathError.Create(sWRONG_SIZE);
  783. Result.Create(V1.FCount);
  784. Result.FData[0] := V1.FData[1] * V2.FData[2] - V1.FData[2] * V2.FData[1];
  785. Result.FData[1] := V1.FData[2] * V2.FData[0] - V1.FData[0] * V2.FData[2];
  786. Result.FData[2] := V1.FData[0] * V2.FData[1] - V1.FData[1] * V2.FData[0];
  787. end;
  788. function TxVector.ScalarMult(V: TxVector): Extended;
  789. var
  790. I: Integer;
  791. begin
  792. if V.FCount <> FCount then
  793. raise EMathError.Create(sWRONG_SIZE);
  794. Result := 0.0;
  795. for I := 0 to FCount - 1 do
  796. Result := Result + FData[I] * V.FData[I];
  797. end;
  798. procedure TxVector.SetElement(Index: Word; Value: Extended);
  799. begin
  800. if (Index = 0) or (Index > FCount) then
  801. raise EMathError.Create(sWRONG_ELEMENT);
  802. CheckUnique;
  803. FData[Pred(Index)] := Value;
  804. end;
  805. class operator TxVector.Subtract(V1, V2: TxVector): TxVector;
  806. var
  807. I: Integer;
  808. begin
  809. if (V1.FCount <> V2.FCount) then
  810. raise EMathError.Create(sWRONG_SIZE);
  811. Result.Create(V1.FCount);
  812. for I := 0 to V1.FCount - 1 do
  813. Result.FData[I] := V1.FData[I] - V2.FData[I];
  814. end;
  815. class operator TxVector.Subtract(Scalar: Extended; V: TxVector): TxVector;
  816. var
  817. I: Integer;
  818. begin
  819. Result.Create(V.FCount);
  820. for I := 0 to V.FCount - 1 do
  821. Result.FData[I] := Scalar - V.FData[I];
  822. end;
  823. class operator TxVector.Subtract(V: TxVector; Scalar: Extended): TxVector;
  824. var
  825. I: Integer;
  826. begin
  827. Result.Create(V.FCount);
  828. for I := 0 to V.Count - 1 do
  829. Result.FData[I] := V.FData[I] - Scalar;
  830. end;
  831. function TxVector.SumOfElments: Extended;
  832. begin
  833. Result := Sum(FData);
  834. end;
  835. function TxVector.SumOfSquares: Extended;
  836. begin
  837. Result := System.Math.SumOfSquares(FData);
  838. end;
  839. function TxVector.ToQuat: TxQuaternion;
  840. var
  841. ModVec: Extended;
  842. C1, C2: Extended;
  843. begin
  844. if (FCount <> 3) then
  845. raise EMathError.Create(sWRONG_SIZE);
  846. ModVec := Norm;
  847. C1 := Cos(ModVec / 2);
  848. if ModVec > 1e-15 then
  849. C2 := Sin(ModVec / 2) / ModVec
  850. else
  851. C2 := 1;
  852. Result := [C1, FData[0] * C2, FData[1] * C2, FData[2] * C2];
  853. end;
  854. function TxVector.TruncateSTI: TxVector;
  855. const
  856. Int32Max: Double = Integer.MaxValue;
  857. Int32Min: Double = Integer.MinValue;
  858. var
  859. I: Integer;
  860. begin
  861. Result.Create(FCount);
  862. for I := 0 to FCount - 1 do
  863. begin
  864. if (FData[I] >= Int32Min) and (FData[I] <= Int32Max) then
  865. Result.FData[I] := Trunc(FData[I])
  866. else
  867. if (FData[I] < Int32Min) then
  868. Result.FData[I] := Int32Min
  869. else
  870. Result.FData[I] := Int32Max;
  871. end;
  872. end;
  873. { TxQuatHelper }
  874. function TxQuatHelper.ToMatrix: TxMatrix;
  875. begin
  876. Result.Create(3, 3);
  877. Result[1, 1] := Sqr(FData[0]) + Sqr(FData[1]) - Sqr(FData[2]) - Sqr(FData[3]);
  878. Result[1, 2] := 2 * (FData[1] * FData[2] - FData[0] * FData[3]);
  879. Result[1, 3] := 2 * (FData[1] * FData[3] + FData[0] * FData[2]);
  880. Result[2, 1] := 2 * (FData[1] * FData[2] + FData[0] * FData[3]);
  881. Result[2, 2] := Sqr(FData[0]) - Sqr(FData[1]) + Sqr(FData[2]) - Sqr(FData[3]);
  882. Result[2, 3] := 2 * (FData[2] * FData[3] - FData[0] * FData[1]);
  883. Result[3, 1] := 2 * (FData[1] * FData[3] - FData[0] * FData[2]);
  884. Result[3, 2] := 2 * (FData[2] * FData[3] + FData[0] * FData[1]);
  885. Result[3, 3] := Sqr(FData[0]) - Sqr(FData[1]) - Sqr(FData[2]) + Sqr(FData[3]);
  886. end;
  887. { TxVecHelper }
  888. function TxVecHelper.ToDiagMatrix: TxMatrix;
  889. var
  890. I: Integer;
  891. begin
  892. Result.Create(FCount, FCount);
  893. for I := 0 to FCount - 1 do
  894. Result.FData[I, I] := FData[I];
  895. end;
  896. procedure Init(Obj, TypeInfoOfObj: Pointer; Offset: Integer = 0);
  897. const
  898. DefaultRowCount = 3;
  899. DefaultColCount = 3;
  900. VectorTypeName = 'TVector';
  901. MatrixTypeName = 'TMatrix';
  902. var
  903. RTTIContext: TRttiContext;
  904. Field : TRttiField;
  905. ArrFld: TRttiArrayType;
  906. I: Integer;
  907. Dim: TCustomAttribute;
  908. RowCount, ColCount: Integer;
  909. OffsetFromArray: Integer;
  910. begin
  911. for Field in RTTIContext.GetType(TypeInfoOfObj).GetFields do
  912. begin
  913. if Field.FieldType <> nil then
  914. begin
  915. RowCount := DefaultRowCount;
  916. ColCount := DefaultColCount;
  917. for Dim in Field.GetAttributes do
  918. begin
  919. RowCount := (Dim as TxDim).RowCount;
  920. ColCount := (Dim as TxDim).ColCount;
  921. end;
  922. if Field.FieldType.TypeKind = tkArray then
  923. begin
  924. ArrFld := TRttiArrayType(Field.FieldType);
  925. if ArrFld.ElementType.TypeKind = tkRecord then
  926. begin
  927. for I := 0 to ArrFld.TotalElementCount - 1 do
  928. begin
  929. OffsetFromArray := I * ArrFld.ElementType.TypeSize;
  930. if ArrFld.ElementType.Name = VectorTypeName then
  931. PxVector(Integer(Obj) +
  932. Field.Offset +
  933. OffsetFromArray +
  934. Offset)^ := TxVector.Create(RowCount)
  935. else if ArrFld.ElementType.Name = MatrixTypeName then
  936. PxMatrix(Integer(Obj) +
  937. Field.Offset +
  938. OffsetFromArray +
  939. Offset)^ := TxMatrix.Create(RowCount, ColCount)
  940. else
  941. Init(Obj, ArrFld.ElementType.Handle, Field.Offset + OffsetFromArray);
  942. end;
  943. end;
  944. end
  945. else if Field.FieldType.TypeKind = tkRecord then
  946. begin
  947. if Field.FieldType.Name = VectorTypeName then
  948. PxVector(Integer(Obj) +
  949. Field.Offset +
  950. Offset)^ := TxVector.Create(RowCount)
  951. else if Field.FieldType.Name = MatrixTypeName then
  952. PxMatrix(Integer(Obj) +
  953. Field.Offset +
  954. Offset)^ := TxMatrix.Create(RowCount, ColCount)
  955. else
  956. Init(Obj, Field.FieldType.Handle, Field.Offset)
  957. end;
  958. end;
  959. end;
  960. end;
  961. { TxDim }
  962. constructor TxDim.Create(ARowCount: Integer; AColCount: Integer = 0);
  963. begin
  964. FRowCount := ARowCount;
  965. FColCount := AColCount;
  966. end;
  967. { TxPoint2D }
  968. function TxPoint2D.Create(X, Y : Single): TxPoint2D;
  969. begin
  970. Result.X := X;
  971. Result.Y := Y;
  972. end;
  973. procedure TxPoint2D.SetPosition(const X, Y: Single);
  974. begin
  975. Self.X := X;
  976. Self.Y := Y;
  977. end;
  978. function TxPoint2D.Length: Single;
  979. begin
  980. Result := Sqrt(Self.X * Self.X + Self.Y * Self.Y);
  981. end;
  982. function TxPoint2D.Add(const APoint2D: TxPoint2D): TxPoint2D;
  983. begin
  984. Result.SetPosition(Self.X + APoint2D.X, Self.Y + APoint2D.Y);
  985. end;
  986. function TxPoint2D.Distance(const APoint2D: TxPoint2D): Single;
  987. begin
  988. Result := Sqrt(Sqr(Self.X - APoint2D.X) + Sqr(Self.Y - APoint2D.Y));
  989. end;
  990. procedure TxPoint2D.Offset(const ADeltaX, ADeltaY: Single);
  991. begin
  992. Self.X := Self.X + ADeltaX;
  993. Self.Y := Self.Y + ADeltaY;
  994. end;
  995. class function TxPoint2D.PointInCircle(const Point, Center: TxPoint2D;
  996. const Radius: Integer): Boolean;
  997. begin
  998. Result := Point.Distance(Center) <= Radius;
  999. end;
  1000. { TxPoint3D }
  1001. function TxPoint3D.Create(X, Y, Z: Single): TxPoint3D;
  1002. begin
  1003. Result.X := X;
  1004. Result.Y := Y;
  1005. Result.Z := Z;
  1006. end;
  1007. function TxPoint3D.Add(const AGLPoint3D: TxPoint3D): TxPoint3D;
  1008. begin
  1009. Result.X := Self.X + AGLPoint3D.X;
  1010. Result.Y := Self.Y + AGLPoint3D.Y;
  1011. Result.Z := Self.Z + AGLPoint3D.Z;
  1012. end;
  1013. function TxPoint3D.Distance(const APoint3D: TxPoint3D): Single;
  1014. begin
  1015. Result := Self.Length - APoint3D.Length;
  1016. end;
  1017. function TxPoint3D.Length: Single;
  1018. begin
  1019. Result := Sqrt(Self.X * Self.X + Self.Y * Self.Y + Self.Z * Self.Z);
  1020. end;
  1021. procedure TxPoint3D.Offset(const ADeltaX, ADeltaY, ADeltaZ: Single);
  1022. begin
  1023. Self.X := Self.X + ADeltaX;
  1024. Self.Y := Self.Y + ADeltaY;
  1025. Self.Z := Self.Z + ADeltaZ;
  1026. end;
  1027. procedure TxPoint3D.SetPosition(const X, Y, Z: Single);
  1028. begin
  1029. Self.X := X;
  1030. Self.Y := Y;
  1031. Self.Z := Z;
  1032. end;
  1033. { TxVector2D }
  1034. function TxVector2D.Create(const AX, AY, AW: Single): TxVector2D;
  1035. begin
  1036. Result.X := AX;
  1037. Result.Y := AY;
  1038. Result.W := AW;
  1039. end;
  1040. function TxVector2D.CrossProduct(const AVector: TxVector2D): TxVector2D;
  1041. begin
  1042. Result.X := (Self.Y * AVector.W) - (Self.W * AVector.Y);
  1043. Result.Y := (Self.W * AVector.X) - (Self.X * AVector.W);
  1044. Result.W := (Self.X * AVector.Y) - (Self.Y * AVector.X);
  1045. end;
  1046. function TxVector2D.DotProduct(const AVector: TxVector2D): Single;
  1047. begin
  1048. Result := (Self.X * AVector.X) + (Self.Y * AVector.Y) + (Self.W * AVector.W);
  1049. end;
  1050. function TxVector2D.Add(const AVector2D: TxVector2D): TxVector2D;
  1051. begin
  1052. Result.X := Self.X + AVector2D.X;
  1053. Result.Y := Self.Y + AVector2D.Y;
  1054. Result.W := 1.0;
  1055. end;
  1056. function TxVector2D.Length: Single;
  1057. begin
  1058. Result := Sqrt((Self.X * Self.X) + (Self.Y * Self.Y));
  1059. end;
  1060. function TxVector2D.Norm: Single;
  1061. begin
  1062. Result := Sqr(Self.X) + Sqr(Self.Y);
  1063. end;
  1064. function TxVector2D.Normalize: TxVector2D;
  1065. var
  1066. invLen: Single;
  1067. vn: Single;
  1068. const
  1069. Tolerance: Single = 1E-12;
  1070. begin
  1071. vn := Self.Norm;
  1072. if vn > Tolerance then
  1073. begin
  1074. invLen := 1/Sqrt(vn);
  1075. Result.X := Self.X * invLen;
  1076. Result.Y := Self.Y * invLen;
  1077. end
  1078. else
  1079. Result := Self;
  1080. end;
  1081. //---------------------------------
  1082. { TxVector3D }
  1083. //---------------------------------
  1084. function TxVector3D.Create(const AX, AY, AZ, AW: Single): TxVector3D;
  1085. begin
  1086. Result.X := AX;
  1087. Result.Y := AY;
  1088. Result.Z := AZ;
  1089. Result.W := AW;
  1090. end;
  1091. function TxVector3D.Add(const AVector3D: TxVector3D): TxVector3D;
  1092. begin
  1093. Result.X := Self.X + AVector3D.X;
  1094. Result.Y := Self.Y + AVector3D.Y;
  1095. Result.Z := Self.Z + AVector3D.Z;
  1096. Result.W := 1.0;
  1097. end;
  1098. function TxVector3D.Norm: Single;
  1099. begin
  1100. result := Self.X * Self.X + Self.Y * Self.Y + Self.Z * Self.Z;
  1101. end;
  1102. function TxVector3D.Normalize: TxVector3D;
  1103. var
  1104. invLen: Single;
  1105. vn: Single;
  1106. const
  1107. Tolerance: Single = 1E-12;
  1108. begin
  1109. vn := Self.Norm;
  1110. if vn > 0 then
  1111. begin
  1112. invLen := 1/Sqrt(vn);
  1113. Result.X := Self.X * invLen;
  1114. Result.Y := Self.Y * invLen;
  1115. Result.Z := Self.Z * invLen;
  1116. Result.W := 0;
  1117. end
  1118. else
  1119. Result := Self;
  1120. end;
  1121. function TxVector3D.DotProduct(const AVector3D: TVector3D): Single;
  1122. begin
  1123. Result := (Self.X * AVector3D.X) + (Self.Y * AVector3D.Y) + (Self.Z * AVector3D.Z);
  1124. end;
  1125. function TxVector3D.CrossProduct(const AVector3D: TVector3D): TVector3D;
  1126. begin
  1127. Result.X := (Self.Y * AVector3D.Z) - (Self.Z * AVector3D.Y);
  1128. Result.Y := (Self.Z * AVector3D.X) - (Self.X * AVector3D.Z);
  1129. Result.Z := (Self.X * AVector3D.Y) - (Self.Y * AVector3D.X);
  1130. end;
  1131. function TxVector3D.Length: Single;
  1132. begin
  1133. Result := Sqrt((Self.X * Self.X) + (Self.Y * Self.Y) + (Self.Z * Self.Z));
  1134. end;
  1135. //---------------------------------
  1136. { TxQuaternion }
  1137. //---------------------------------
  1138. function TxQuaternion.GetElement(Index: Byte): Extended;
  1139. begin
  1140. if (Index > 3) then
  1141. raise EMathError.Create(sWRONG_ELEMENT);
  1142. Result := FData[Index];
  1143. end;
  1144. class operator TxQuaternion.Implicit(V: TAbstractVector): TxQuaternion;
  1145. begin
  1146. if (Length(V) <> 4) then
  1147. raise EMathError.Create(sWRONG_SIZE);
  1148. Move(V[0], Result.FData, SizeOf(Result.FData));
  1149. end;
  1150. function TxQuaternion.Inv: TxQuaternion;
  1151. begin
  1152. Result := [FData[0], -FData[1], -FData[2], -FData[3]];
  1153. end;
  1154. class operator TxQuaternion.Multiply(Scalar: Extended; Q: TxQuaternion): TxQuaternion;
  1155. begin
  1156. Result := Q * Scalar;
  1157. end;
  1158. class operator TxQuaternion.Multiply(Q: TxQuaternion; Sc: Extended): TxQuaternion;
  1159. begin
  1160. Result := [Q.FData[0] * Sc, Q.FData[1] * Sc, Q.FData[2] * Sc, Q.FData[3] * Sc];
  1161. end;
  1162. class operator TxQuaternion.Multiply(Q1, Q2: TxQuaternion): TxQuaternion;
  1163. var
  1164. Mat: TxMatrix;
  1165. begin
  1166. Mat := [[Q1.FData[0], -Q1.FData[1], -Q1.FData[2], -Q1.FData[3]],
  1167. [Q1.FData[1], Q1.FData[0], -Q1.FData[3], Q1.FData[2]],
  1168. [Q1.FData[2], Q1.FData[3], Q1.FData[0], -Q1.FData[1]],
  1169. [Q1.FData[3], -Q1.FData[2], Q1.FData[1], Q1.FData[0]]];
  1170. Result := Mat * Q2;
  1171. end;
  1172. constructor TxQuaternion.Create(Q: TAbstractVector);
  1173. begin
  1174. if Length(Q) <> 4 then
  1175. raise EMathError.Create(sWRONG_SIZE);
  1176. Move(Q[0], FData[0], SizeOf(FData));
  1177. end;
  1178. procedure TxQuaternion.SetElement(Index: Byte; Value: Extended);
  1179. begin
  1180. if (Index > 3) then
  1181. raise EMathError.Create(sWRONG_ELEMENT);
  1182. FData[Index] := Value;
  1183. end;
  1184. function TxQuaternion.TruncateSTI: TxQuaternion;
  1185. const
  1186. Int32Max: Double = Integer.MaxValue;
  1187. Int32Min: Double = Integer.MinValue;
  1188. function xTrunc(Value: Extended): Double;
  1189. begin
  1190. if (Value >= Int32Min) and (Value <= Int32Max) then
  1191. Result := Trunc(Value)
  1192. else
  1193. if (Value < Int32Min) then
  1194. Result := Int32Min
  1195. else
  1196. Result := Int32Max;
  1197. end;
  1198. begin
  1199. Result[0] := xTrunc(FData[0]);
  1200. Result[1] := xTrunc(FData[1]);
  1201. Result[2] := xTrunc(FData[2]);
  1202. Result[3] := xTrunc(FData[3]);
  1203. end;
  1204. end.