Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

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