GLS.VectorTypesExt.pas 36 KB

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