You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

596 regels
22 KiB

  1. unit ugluVectorExHelper;
  2. {$mode objfpc}{$H+}
  3. {$modeswitch typehelpers}
  4. interface
  5. uses
  6. Classes, SysUtils;
  7. type
  8. generic TgluVectorHelper<T> = class
  9. public type
  10. TBaseType = T;
  11. PBaseType = ^TBaseType;
  12. TVector2 = array[0..1] of T;
  13. TVector3 = array[0..2] of T;
  14. TVector4 = array[0..3] of T;
  15. PVector2 = ^TVector2;
  16. PVector3 = ^TVector3;
  17. PVector4 = ^TVector4;
  18. public
  19. class function Vector2(const x, y: T): TVector2; overload; inline;
  20. class function Vector3(const x, y, z: T): TVector3; overload; inline;
  21. class function Vector4(const x, y, z, w: T): TVector4; overload; inline;
  22. class function Equals(const v1: TVector2; const v2: TVector2): Boolean; overload; inline;
  23. class function Equals(const v1: TVector3; const v2: TVector3): Boolean; overload; inline;
  24. class function Equals(const v1: TVector4; const v2: TVector4): Boolean; overload; inline;
  25. class function ToString(const v: TVector2; const aRound: Integer = -3): String; overload;
  26. class function ToString(const v: TVector3; const aRound: Integer = -3): String; overload;
  27. class function ToString(const v: TVector4; const aRound: Integer = -3): String; overload;
  28. class function TryFromString(const s: String; out v: TVector2): Boolean; overload; inline;
  29. class function TryFromString(const s: String; out v: TVector3): Boolean; overload; inline;
  30. class function TryFromString(const s: String; out v: TVector4): Boolean; overload; inline;
  31. class function TryFromString(const s: String; p: PBaseType; aCount: Integer): Boolean;
  32. end;
  33. generic TgluVectorHelperI<T> = class(specialize TgluVectorHelper<T>)
  34. public
  35. class function Length(const v: TVector2): Double; overload; inline;
  36. class function Length(const v: TVector3): Double; overload; inline;
  37. class function Length(const v: TVector4): Double; overload; inline;
  38. class function SqrLength(const v: TVector2): Double; overload; inline;
  39. class function SqrLength(const v: TVector3): Double; overload; inline;
  40. class function SqrLength(const v: TVector4): Double; overload; inline;
  41. class function Multiply(const v: TVector2; const a: T): TVector2; overload; inline;
  42. class function Multiply(const v: TVector3; const a: T): TVector3; overload; inline;
  43. class function Multiply(const v: TVector4; const a: T): TVector4; overload; inline;
  44. class function Add(const v1, v2: TVector2): TVector2; overload; inline;
  45. class function Add(const v1, v2: TVector3): TVector3; overload; inline;
  46. class function Sub(const v1, v2: TVector2): TVector2; overload; inline;
  47. class function Sub(const v1, v2: TVector3): TVector3; overload; inline;
  48. class function ClampVal(const v, aMin, aMax: T): T; overload; inline;
  49. class function Clamp(const v, aMin, aMax: TVector2): TVector2; overload; inline;
  50. class function Clamp(const v, aMin, aMax: TVector3): TVector3; overload; inline;
  51. class function Clamp(const v, aMin, aMax: TVector4): TVector4; overload; inline;
  52. class function Clamp(const v: TVector2; const aMin, aMax: T): TVector2; overload; inline;
  53. class function Clamp(const v: TVector3; const aMin, aMax: T): TVector3; overload; inline;
  54. class function Clamp(const v: TVector4; const aMin, aMax: T): TVector4; overload; inline;
  55. end;
  56. generic TgluVectorHelperF<T> = class(specialize TgluVectorHelperI<T>)
  57. public
  58. class function Normalize(const v: TVector2): TVector2; overload; inline;
  59. class function Normalize(const v: TVector3): TVector3; overload; inline;
  60. class function Normalize(const v: TVector4): TVector4; overload; inline;
  61. class function Divide(const v: TVector2; const a: T): TVector2; overload; inline;
  62. class function Divide(const v: TVector3; const a: T): TVector3; overload; inline;
  63. class function Divide(const v: TVector4; const a: T): TVector4; overload; inline;
  64. class function Dot(const v1: TVector2; const v2: TVector2): T; overload; inline;
  65. class function Dot(const v1: TVector3; const v2: TVector3): T; overload; inline;
  66. class function Dot(const v1: TVector4; const v2: TVector4): T; overload; inline;
  67. class function Cross(const v1: TVector3; const v2: TVector3): TVector3; overload; inline;
  68. class function Angle(const v1: TVector2; const v2: TVector2): Double; overload; inline;
  69. class function Angle(const v1: TVector3; const v2: TVector3): Double; overload; inline;
  70. class function Angle2(const v1: TVector2; const v2: TVector2): Double; overload; inline;
  71. end;
  72. TgluVectorP = specialize TgluVectorHelper<Pointer>;
  73. TgluVectorE = specialize TgluVectorHelper<Cardinal>;
  74. TgluVectorI = specialize TgluVectorHelperI<Integer>;
  75. TgluVectorUS = specialize TgluVectorHelperI<Word>;
  76. TgluVectorUB = specialize TgluVectorHelperI<Byte>;
  77. TgluVectorF = specialize TgluVectorHelperF<Single>;
  78. TgluVectorD = specialize TgluVectorHelperF<Double>;
  79. TPointerTypeHelper = type helper for Pointer
  80. function ToString(const aRound: Integer = -3): String;
  81. class function TryFromString(s: String; out v: Pointer): Boolean; static;
  82. end;
  83. TCardinalTypeHelper = type helper for Cardinal
  84. function ToString(const aRound: Integer = -3): String;
  85. class function TryFromString(s: String; out v: Cardinal): Boolean; static;
  86. end;
  87. TIntegerTypeHelper = type helper for Integer
  88. function ToString(const aRound: Integer = -3): String;
  89. class function TryFromString(s: String; out v: Integer): Boolean; static;
  90. end;
  91. TWordTypeHelper = type helper for Word
  92. function ToString(const aRound: Integer = -3): String;
  93. class function TryFromString(s: String; out v: Word): Boolean; static;
  94. end;
  95. TByteTypeHelper = type helper for Byte
  96. function ToString(const aRound: Integer = -3): String;
  97. class function TryFromString(s: String; out v: Byte): Boolean; static;
  98. end;
  99. TSingleTypeHelper = type helper for Single
  100. function ToString(const aRound: Integer = -3): String;
  101. class function TryFromString(s: String; out v: Single): Boolean; static;
  102. end;
  103. TDoubleTypeHelper = type helper for Double
  104. function ToString(const aRound: Integer = -3): String;
  105. class function TryFromString(s: String; out v: Double): Boolean; static;
  106. end;
  107. implementation
  108. uses
  109. Math;
  110. function IntToStrRounded(i: Int64; const aRound: Integer): String;
  111. var p: Cardinal;
  112. begin
  113. if (aRound > 0) then begin
  114. p := Round(power(10, aRound));
  115. i := i div p;
  116. i := i * p;
  117. end;
  118. result := IntToStr(i);
  119. end;
  120. function FloatToStrRounded(f: Extended; const aRound: Integer): String;
  121. var p: Cardinal; fmt: TFormatSettings;
  122. begin
  123. if (aRound > 0) then begin
  124. p := Round(power(10, aRound));
  125. f := Round(f / p) * p;
  126. end;
  127. fmt.DecimalSeparator := '.';
  128. result := Format('%.*f', [Max(0, -aRound), f], fmt);
  129. end;
  130. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  131. //TPointerTypeHelper////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  132. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  133. function TPointerTypeHelper.ToString(const aRound: Integer): String;
  134. begin
  135. result := '0x' + IntToHex({%H-}PtrUInt(self), 2 * SizeOf(Pointer));
  136. end;
  137. class function TPointerTypeHelper.TryFromString(s: String; out v: Pointer): Boolean;
  138. var
  139. i: Int64;
  140. begin
  141. s := StringReplace(s, '0x', '$', [rfReplaceAll, rfIgnoreCase]);
  142. result := TryStrToInt64(s, i);
  143. if result
  144. then v := {%H-}Pointer(PtrUInt(i))
  145. else v := nil;
  146. end;
  147. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  148. //TCardinalTypeHelper///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  149. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  150. function TCardinalTypeHelper.ToString(const aRound: Integer): String;
  151. begin
  152. result := IntToStrRounded(self, aRound);
  153. end;
  154. class function TCardinalTypeHelper.TryFromString(s: String; out v: Cardinal): Boolean;
  155. var i: LongInt;
  156. begin
  157. result := TryStrToInt(s, i);
  158. if result
  159. then v := i
  160. else v := 0;
  161. end;
  162. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  163. //TIntegerTypeHelper////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  164. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  165. function TIntegerTypeHelper.ToString(const aRound: Integer): String;
  166. begin
  167. result := IntToStrRounded(self, aRound);
  168. end;
  169. class function TIntegerTypeHelper.TryFromString(s: String; out v: Integer): Boolean;
  170. begin
  171. result := TryStrToInt(s, v);
  172. end;
  173. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  174. //TWordTypeHelper///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  175. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  176. function TWordTypeHelper.ToString(const aRound: Integer): String;
  177. begin
  178. result := IntToStrRounded(self, aRound);
  179. end;
  180. class function TWordTypeHelper.TryFromString(s: String; out v: Word): Boolean;
  181. var i: LongInt;
  182. begin
  183. result := TryStrToInt(s, i);
  184. if result
  185. then v := i
  186. else v := 0;
  187. end;
  188. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  189. //TByteTypeHelper///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  190. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  191. function TByteTypeHelper.ToString(const aRound: Integer): String;
  192. begin
  193. result := IntToStrRounded(self, aRound);
  194. end;
  195. class function TByteTypeHelper.TryFromString(s: String; out v: Byte): Boolean;
  196. var i: LongInt;
  197. begin
  198. result := TryStrToInt(s, i);
  199. if result
  200. then v := i
  201. else v := 0;
  202. end;
  203. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  204. //TSingleTypeHelper/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  205. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  206. function TSingleTypeHelper.ToString(const aRound: Integer): String;
  207. begin
  208. result := FloatToStrRounded(self, aRound);
  209. end;
  210. class function TSingleTypeHelper.TryFromString(s: String; out v: Single): Boolean;
  211. var f: TFormatSettings;
  212. begin
  213. f.DecimalSeparator := '.';
  214. result := TryStrToFloat(s, v, f);
  215. end;
  216. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  217. //TDoubleTypeHelper/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  218. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  219. function TDoubleTypeHelper.ToString(const aRound: Integer): String;
  220. begin
  221. result := FloatToStrRounded(self, aRound);
  222. end;
  223. class function TDoubleTypeHelper.TryFromString(s: String; out v: Double): Boolean;
  224. var f: TFormatSettings;
  225. begin
  226. f.DecimalSeparator := '.';
  227. result := TryStrToFloat(s, v, f);
  228. end;
  229. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  230. //TgluVectorHelper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  231. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  232. class function TgluVectorHelper.Vector2(const x, y: T): TVector2;
  233. begin
  234. result[0] := x;
  235. result[1] := y;
  236. end;
  237. class function TgluVectorHelper.Vector3(const x, y, z: T): TVector3;
  238. begin
  239. result[0] := x;
  240. result[1] := y;
  241. result[2] := z;
  242. end;
  243. class function TgluVectorHelper.Vector4(const x, y, z, w: T): TVector4;
  244. begin
  245. result[0] := x;
  246. result[1] := y;
  247. result[2] := z;
  248. result[3] := w;
  249. end;
  250. class function TgluVectorHelper.Equals(const v1: TVector2; const v2: TVector2): Boolean;
  251. begin
  252. result := (v1[0] = v2[0]) and (v1[1] = v2[1]);
  253. end;
  254. class function TgluVectorHelper.Equals(const v1: TVector3; const v2: TVector3): Boolean;
  255. begin
  256. result := Equals(PVector2(@v1[0])^, PVector2(@v2[0])^) and (v1[2] = v2[2]);
  257. end;
  258. class function TgluVectorHelper.Equals(const v1: TVector4; const v2: TVector4): Boolean;
  259. begin
  260. result := Equals(PVector3(@v1[0])^, PVector3(@v2[0])^) and (v1[3] = v2[3]);
  261. end;
  262. class function TgluVectorHelper.ToString(const v: TVector2; const aRound: Integer): String;
  263. begin
  264. result := v[0].ToString(aRound) + '; ' + v[1].ToString(aRound);
  265. end;
  266. class function TgluVectorHelper.ToString(const v: TVector3; const aRound: Integer): String;
  267. begin
  268. result := v[0].ToString(aRound) + '; ' + v[1].ToString(aRound) + '; ' + v[2].ToString(aRound);
  269. end;
  270. class function TgluVectorHelper.ToString(const v: TVector4; const aRound: Integer): String;
  271. begin
  272. result := v[0].ToString(aRound) + '; ' + v[1].ToString(aRound) + '; ' + v[2].ToString(aRound) + '; ' + v[3].ToString(aRound);
  273. end;
  274. class function TgluVectorHelper.TryFromString(const s: String; out v: TVector2): Boolean;
  275. begin
  276. result := TryFromString(s, @v[0], 2);
  277. end;
  278. class function TgluVectorHelper.TryFromString(const s: String; out v: TVector3): Boolean;
  279. begin
  280. result := TryFromString(s, @v[0], 3);
  281. end;
  282. class function TgluVectorHelper.TryFromString(const s: String; out v: TVector4): Boolean;
  283. begin
  284. result := TryFromString(s, @v[0], 4);
  285. end;
  286. class function TgluVectorHelper.TryFromString(const s: String; p: PBaseType; aCount: Integer): Boolean;
  287. var
  288. i, j, l: Integer;
  289. begin
  290. result := true;
  291. i := 1;
  292. j := 1;
  293. l := Length(s);
  294. while ({%H-}i <= {%H-}l) and (aCount > 0) and result {%H-}do begin
  295. if (s[i] = ';') or (i = l) then begin
  296. if (i = l) then inc(i);
  297. result := TBaseType.TryFromString(Trim(copy(s, j, i-{%H-}j)), p^);
  298. j := i+1;
  299. inc(p);
  300. dec(aCount);
  301. end;
  302. inc(i);
  303. end;
  304. result := (aCount = 0);
  305. while (aCount > 0) do begin
  306. p^ := TBaseType(0);
  307. inc(p);
  308. dec(aCount);
  309. end;
  310. end;
  311. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  312. //TgluVectorHelperI/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  313. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  314. class function TgluVectorHelperI.Length(const v: TVector2): Double;
  315. begin
  316. result := SQRT(v[0]*v[0] + v[1]*v[1]);
  317. end;
  318. class function TgluVectorHelperI.Length(const v: TVector3): Double;
  319. begin
  320. result := SQRT(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
  321. end;
  322. class function TgluVectorHelperI.Length(const v: TVector4): Double;
  323. begin
  324. result := SQRT(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]) * v[3];
  325. end;
  326. class function TgluVectorHelperI.SqrLength(const v: TVector2): Double;
  327. begin
  328. result := v[0]*v[0] + v[1]*v[1];
  329. end;
  330. class function TgluVectorHelperI.SqrLength(const v: TVector3): Double;
  331. begin
  332. result := v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
  333. end;
  334. class function TgluVectorHelperI.SqrLength(const v: TVector4): Double;
  335. begin
  336. result := (v[0]*v[0] + v[1]*v[1] + v[2]*v[2]) * v[3];
  337. end;
  338. class function TgluVectorHelperI.Multiply(const v: TVector2; const a: T): TVector2;
  339. begin
  340. result[0] := v[0] * a;
  341. result[1] := v[1] * a;
  342. end;
  343. class function TgluVectorHelperI.Multiply(const v: TVector3; const a: T): TVector3;
  344. begin
  345. result[0] := v[0] * a;
  346. result[1] := v[1] * a;
  347. result[2] := v[2] * a;
  348. end;
  349. class function TgluVectorHelperI.Multiply(const v: TVector4; const a: T): TVector4;
  350. begin
  351. result[0] := v[0] * a;
  352. result[1] := v[1] * a;
  353. result[2] := v[2] * a;
  354. result[3] := v[3] * a;
  355. end;
  356. class function TgluVectorHelperI.Add(const v1, v2: TVector2): TVector2;
  357. begin
  358. result[0] := v1[0] + v2[0];
  359. result[1] := v1[1] + v2[1];
  360. end;
  361. class function TgluVectorHelperI.Add(const v1, v2: TVector3): TVector3;
  362. begin
  363. result[0] := v1[0] + v2[0];
  364. result[1] := v1[1] + v2[1];
  365. result[2] := v1[2] + v2[2];
  366. end;
  367. class function TgluVectorHelperI.Sub(const v1, v2: TVector2): TVector2;
  368. begin
  369. result[0] := v1[0] - v2[0];
  370. result[1] := v1[1] - v2[1];
  371. end;
  372. class function TgluVectorHelperI.Sub(const v1, v2: TVector3): TVector3;
  373. begin
  374. result[0] := v1[0] - v2[0];
  375. result[1] := v1[1] - v2[1];
  376. result[2] := v1[2] - v2[2];
  377. end;
  378. class function TgluVectorHelperI.ClampVal(const v, aMin, aMax: T): T;
  379. begin
  380. if (v < aMin) then
  381. result := aMin
  382. else if (v > aMax) then
  383. result := aMax
  384. else
  385. result := v;
  386. end;
  387. class function TgluVectorHelperI.Clamp(const v, aMin, aMax: TVector2): TVector2;
  388. begin
  389. result[0] := ClampVal(v[0], aMin[0], aMax[0]);
  390. result[1] := ClampVal(v[1], aMin[1], aMax[1]);
  391. end;
  392. class function TgluVectorHelperI.Clamp(const v, aMin, aMax: TVector3): TVector3;
  393. begin
  394. result[0] := ClampVal(v[0], aMin[0], aMax[0]);
  395. result[1] := ClampVal(v[1], aMin[1], aMax[1]);
  396. result[2] := ClampVal(v[2], aMin[2], aMax[2]);
  397. end;
  398. class function TgluVectorHelperI.Clamp(const v, aMin, aMax: TVector4): TVector4;
  399. begin
  400. result[0] := ClampVal(v[0], aMin[0], aMax[0]);
  401. result[1] := ClampVal(v[1], aMin[1], aMax[1]);
  402. result[2] := ClampVal(v[2], aMin[2], aMax[2]);
  403. result[3] := ClampVal(v[3], aMin[3], aMax[3]);
  404. end;
  405. class function TgluVectorHelperI.Clamp(const v: TVector2; const aMin, aMax: T): TVector2;
  406. begin
  407. result[0] := ClampVal(v[0], aMin, aMax);
  408. result[1] := ClampVal(v[1], aMin, aMax);
  409. end;
  410. class function TgluVectorHelperI.Clamp(const v: TVector3; const aMin, aMax: T): TVector3;
  411. begin
  412. result[0] := ClampVal(v[0], aMin, aMax);
  413. result[1] := ClampVal(v[1], aMin, aMax);
  414. result[2] := ClampVal(v[2], aMin, aMax);
  415. end;
  416. class function TgluVectorHelperI.Clamp(const v: TVector4; const aMin, aMax: T): TVector4;
  417. begin
  418. result[0] := ClampVal(v[0], aMin, aMax);
  419. result[1] := ClampVal(v[1], aMin, aMax);
  420. result[2] := ClampVal(v[2], aMin, aMax);
  421. end;
  422. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  423. //TgluVectorHelperF/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  424. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  425. class function TgluVectorHelperF.Normalize(const v: TVector2): TVector2;
  426. var l: Double;
  427. begin
  428. l := Length(v);
  429. result[0] := v[0] / l;
  430. result[1] := v[1] / l;
  431. end;
  432. class function TgluVectorHelperF.Normalize(const v: TVector3): TVector3;
  433. var l: Double;
  434. begin
  435. l := Length(v);
  436. result[0] := v[0] / l;
  437. result[1] := v[1] / l;
  438. result[2] := v[2] / l;
  439. end;
  440. class function TgluVectorHelperF.Normalize(const v: TVector4): TVector4;
  441. begin
  442. result := v;
  443. if (result[3] <> 0) then
  444. result := Divide(v, v[3]);
  445. PVector3(@result[0])^ := Normalize(PVector3(@result[0])^);
  446. end;
  447. class function TgluVectorHelperF.Divide(const v: TVector2; const a: T): TVector2;
  448. begin
  449. result[0] := v[0] / a;
  450. result[1] := v[1] / a;
  451. end;
  452. class function TgluVectorHelperF.Divide(const v: TVector3; const a: T): TVector3;
  453. begin
  454. result[0] := v[0] / a;
  455. result[1] := v[1] / a;
  456. result[2] := v[2] / a;
  457. end;
  458. class function TgluVectorHelperF.Divide(const v: TVector4; const a: T): TVector4;
  459. begin
  460. result[0] := v[0] / a;
  461. result[1] := v[1] / a;
  462. result[2] := v[2] / a;
  463. result[3] := v[3] / a;
  464. end;
  465. class function TgluVectorHelperF.Dot(const v1: TVector2; const v2: TVector2): T;
  466. begin
  467. result := v1[0] * v2[0] + v1[1] * v2[1];
  468. end;
  469. class function TgluVectorHelperF.Dot(const v1: TVector3; const v2: TVector3): T;
  470. begin
  471. result := v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
  472. end;
  473. class function TgluVectorHelperF.Dot(const v1: TVector4; const v2: TVector4): T;
  474. begin
  475. result := v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2] + v1[3] * v2[3];
  476. end;
  477. class function TgluVectorHelperF.Cross(const v1: TVector3; const v2: TVector3): TVector3;
  478. begin
  479. result[0] := v1[1] * v2[2] - v1[2] * v2[1];
  480. result[1] := v1[2] * v2[0] - v1[0] * v2[2];
  481. result[2] := v1[0] * v2[1] - v1[1] * v2[0];
  482. end;
  483. class function TgluVectorHelperF.Angle(const v1: TVector2; const v2: TVector2): Double;
  484. begin
  485. result := ArcCos(Dot(v1, v2) / (Length(v1) * Length(v2)));
  486. end;
  487. class function TgluVectorHelperF.Angle(const v1: TVector3; const v2: TVector3): Double;
  488. begin
  489. result := ArcCos(Dot(v1, v2) / (Length(v1) * Length(v2)));
  490. end;
  491. class function TgluVectorHelperF.Angle2(const v1: TVector2; const v2: TVector2): Double;
  492. begin
  493. result := arctan2(
  494. v2[0] * v1[1] - v2[1] * v1[0],
  495. v2[0] * v1[0] + v2[1] * v1[1]);
  496. end;
  497. end.