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.

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