Vectors4.pas
上传用户:ctlcnc
上传日期:2021-12-10
资源大小:4933k
文件大小:15k
源码类别:

2D图形编程

开发平台:

Delphi

  1. unit Vectors4;
  2. //---------------------------------------------------------------------------
  3. // Vectors4.pas                                         Modified: 09-Mar-2007
  4. // Definitions and functions working with 4D vectors              Version 1.0
  5. //---------------------------------------------------------------------------
  6. // Important Notice:
  7. //
  8. // If you modify/use this code or one of its parts either in original or
  9. // modified form, you must comply with Mozilla Public License v1.1,
  10. // specifically section 3, "Distribution Obligations". Failure to do so will
  11. // result in the license breach, which will be resolved in the court.
  12. // Remember that violating author's rights is considered a serious crime in
  13. // many countries. Thank you!
  14. //
  15. // !! Please *read* Mozilla Public License 1.1 document located at:
  16. //  http://www.mozilla.org/MPL/
  17. //
  18. // If you require any clarifications about the license, feel free to contact
  19. // us or post your question on our forums at: http://www.afterwarp.net
  20. //---------------------------------------------------------------------------
  21. // The contents of this file are subject to the Mozilla Public License
  22. // Version 1.1 (the "License"); you may not use this file except in
  23. // compliance with the License. You may obtain a copy of the License at
  24. // http://www.mozilla.org/MPL/
  25. //
  26. // Software distributed under the License is distributed on an "AS IS"
  27. // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
  28. // License for the specific language governing rights and limitations
  29. // under the License.
  30. //
  31. // The Original Code is Vectors4.pas.
  32. //
  33. // The Initial Developer of the Original Code is M. Sc. Yuriy Kotsarenko.
  34. // Portions created by M. Sc. Yuriy Kotsarenko are Copyright (C) 2007,
  35. // Afterwarp Interactive. All Rights Reserved.
  36. //---------------------------------------------------------------------------
  37. interface
  38. //---------------------------------------------------------------------------
  39. uses
  40.  Math, D3DX9, Vectors3, Matrices4;
  41. //---------------------------------------------------------------------------
  42. type
  43.  PVector4 = ^TVector4;
  44.  TVector4 = record
  45.   x, y, z, w: Single;
  46.   class operator Implicit(const v: TVector4): TVector3;
  47.   class operator Implicit(const v: TVector3): TVector4;
  48.   class operator Explicit(const v: TVector4): TVector3;
  49.   class operator Explicit(const v: TVector3): TVector4;
  50.   class operator Add(const a, b: TVector4): TVector4;
  51.   class operator Subtract(const a, b: TVector4): TVector4;
  52.   class operator Multiply(const a, b: TVector4): TVector4;
  53.   class operator Divide(const a, b: TVector4): TVector4;
  54.   class operator Negative(const v: TVector4): TVector4;
  55.   class operator Multiply(const v: TVector4; const k: Single): TVector4;
  56.   class operator Divide(const v: TVector4; const k: Single): TVector4;
  57.   class operator Multiply(const v: TVector4; const m: TMatrix4): TVector4;
  58.  end;
  59. //---------------------------------------------------------------------------
  60.  TVectors4 = class
  61.  private
  62.   NativeAddr : Pointer;
  63.   AlignedAddr: Pointer;
  64.   Capacity   : Integer;
  65.   DataCount  : Integer;
  66.   procedure Request(Amount: Integer);
  67.   procedure Reallocate(Amount: Integer);
  68.   function GetVector(Num: Integer): PVector4;
  69.   function GetItem(Num: Integer): TVector4;
  70.   procedure SetItem(Num: Integer; const Value: TVector4);
  71.  public
  72.   property MemAddr: Pointer read AlignedAddr;
  73.   property Count: Integer read DataCount;
  74.   property Items[Num: Integer]: TVector4 read GetItem write SetItem; default;
  75.   property Vector[Num: Integer]: PVector4 read GetVector;
  76.   function Add(const Vector: TVector4): Integer; overload;
  77.   function Add(x, y, z: Single): Integer; overload;
  78.   procedure Remove(Index: Integer);
  79.   procedure RemoveAll();
  80.   procedure CopyFrom(Source: TVectors4);
  81.   procedure AddFrom(Source: TVectors4);
  82.   procedure Transform(Source: TVectors4; Matrix: PMatrix4);
  83.   constructor Create();
  84.   destructor Destroy(); override;
  85.  end;
  86. //---------------------------------------------------------------------------
  87. const
  88.  ZeroVec4 : TVector4 = (x: 0.0; y: 0.0; z: 0.0; w: 1.0);
  89.  UnityVec4: TVector4 = (x: 1.0; y: 1.0; z: 1.0; w: 1.0);
  90.  AxisXVec4: TVector4 = (x: 1.0; y: 0.0; z: 0.0; w: 1.0);
  91.  AxisYVec4: TVector4 = (x: 0.0; y: 1.0; z: 0.0; w: 1.0);
  92.  AxisZVec4: TVector4 = (x: 0.0; y: 0.0; z: 1.0; w: 1.0);
  93. //---------------------------------------------------------------------------
  94. function Vector4(x, y, z: Single): TVector4;
  95. function Length4(const v: TVector4): Single;
  96. function Norm4(const v: TVector4): TVector4;
  97. function Lerp4(const v0, v1: TVector4; Alpha: Single): TVector4;
  98. function Dot4(const a, b: TVector4): Single;
  99. function Cross4(const a, b: TVector4): TVector4;
  100. function Angle4(const a, b: TVector4): Single;
  101. function Parallel4(const v, n: TVector4): TVector4;
  102. function Perp4(const v, n: TVector4): TVector4;
  103. //---------------------------------------------------------------------------
  104. implementation
  105. //---------------------------------------------------------------------------
  106. const
  107.  VectorCache = 256;
  108. //---------------------------------------------------------------------------
  109. class operator TVector4.Explicit(const v: TVector4): TVector3;
  110. begin
  111.  Result.x:= v.x / v.w;
  112.  Result.y:= v.y / v.w;
  113.  Result.z:= v.z / v.w;
  114. end;
  115. //---------------------------------------------------------------------------
  116. class operator TVector4.Explicit(const v: TVector3): TVector4;
  117. begin
  118.  Result.x:= v.x;
  119.  Result.y:= v.y;
  120.  Result.z:= v.z;
  121.  Result.w:= 1.0;
  122. end;
  123. //---------------------------------------------------------------------------
  124. class operator TVector4.Implicit(const v: TVector4): TVector3;
  125. begin
  126.  Result.x:= v.x / v.w;
  127.  Result.y:= v.y / v.w;
  128.  Result.z:= v.z / v.w;
  129. end;
  130. //---------------------------------------------------------------------------
  131. class operator TVector4.Implicit(const v: TVector3): TVector4;
  132. begin
  133.  Result.x:= v.x;
  134.  Result.y:= v.y;
  135.  Result.z:= v.z;
  136.  Result.w:= 1.0;
  137. end;
  138. //---------------------------------------------------------------------------
  139. class operator TVector4.Add(const a, b: TVector4): TVector4;
  140. begin
  141.  Result.x:= a.x + b.x;
  142.  Result.y:= a.y + b.y;
  143.  Result.z:= a.z + b.z;
  144.  Result.w:= 1.0;
  145. end;
  146. //---------------------------------------------------------------------------
  147. class operator TVector4.Subtract(const a, b: TVector4): TVector4;
  148. begin
  149.  Result.x:= a.x - b.x;
  150.  Result.y:= a.y - b.y;
  151.  Result.z:= a.z - b.z;
  152.  Result.w:= 1.0;
  153. end;
  154. //---------------------------------------------------------------------------
  155. class operator TVector4.Multiply(const a, b: TVector4): TVector4;
  156. begin
  157.  Result.x:= a.x * b.x;
  158.  Result.y:= a.y * b.y;
  159.  Result.z:= a.z * b.z;
  160.  Result.w:= 1.0;
  161. end;
  162. //---------------------------------------------------------------------------
  163. class operator TVector4.Divide(const a, b: TVector4): TVector4;
  164. begin
  165.  Result.x:= a.x / b.x;
  166.  Result.y:= a.y / b.y;
  167.  Result.z:= a.z / b.z;
  168.  Result.w:= 1.0;
  169. end;
  170. //---------------------------------------------------------------------------
  171. class operator TVector4.Negative(const v: TVector4): TVector4;
  172. begin
  173.  Result.x:= -v.x;
  174.  Result.y:= -v.y;
  175.  Result.z:= -v.z;
  176.  Result.w:= 1.0;
  177. end;
  178. //---------------------------------------------------------------------------
  179. class operator TVector4.Multiply(const v: TVector4;
  180.  const k: Single): TVector4;
  181. begin
  182.  Result.x:= v.x * k;
  183.  Result.y:= v.y * k;
  184.  Result.z:= v.z * k;
  185.  Result.w:= 1.0;
  186. end;
  187. //---------------------------------------------------------------------------
  188. class operator TVector4.Divide(const v: TVector4;
  189.  const k: Single): TVector4;
  190. begin
  191.  Result.x:= v.x / k;
  192.  Result.y:= v.y / k;
  193.  Result.z:= v.z / k;
  194.  Result.w:= 1.0;
  195. end;
  196. //---------------------------------------------------------------------------
  197. class operator TVector4.Multiply(const v: TVector4;
  198.  const m: TMatrix4): TVector4;
  199. begin
  200.  Result.x:= (v.x * m.Data[0, 0]) + (v.y * m.Data[1, 0]) +
  201.   (v.z * m.Data[2, 0]) + (v.w * m.Data[3, 0]);
  202.  Result.y:= (v.x * m.Data[0, 1]) + (v.y * m.Data[1, 1]) +
  203.   (v.z * m.Data[2, 1]) + (v.w * m.Data[3, 1]);
  204.  Result.z:= (v.x * m.Data[0, 2]) + (v.y * m.Data[1, 2]) +
  205.   (v.z * m.Data[2, 2]) + (v.w * m.Data[3, 2]);
  206.  Result.w:= (v.x * m.Data[0, 3]) + (v.y * m.Data[1, 3]) +
  207.   (v.z * m.Data[2, 3]) + (v.w * m.Data[3, 3]);
  208. end;
  209. //---------------------------------------------------------------------------
  210. function Vector4(x, y, z: Single): TVector4;
  211. begin
  212.  Result.x:= x;
  213.  Result.y:= y;
  214.  Result.z:= z;
  215.  Result.w:= 1.0;
  216. end;
  217. //---------------------------------------------------------------------------
  218. function Length4(const v: TVector4): Single;
  219. begin
  220.  Result:= Sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
  221. end;
  222. //---------------------------------------------------------------------------
  223. function Norm4(const v: TVector4): TVector4;
  224. var
  225.  Amp: Single;
  226. begin
  227.  Amp:= Length3(v);
  228.  if (Amp <> 0.0) then
  229.   begin
  230.    Result.x:= v.x / Amp;
  231.    Result.y:= v.y / Amp;
  232.    Result.z:= v.z / Amp;
  233.    Result.w:= 1.0;
  234.   end else Result:= ZeroVec4;
  235. end;
  236. //---------------------------------------------------------------------------
  237. function Lerp4(const v0, v1: TVector4; Alpha: Single): TVector4;
  238. begin
  239.  Result.x:= v0.x + (v1.x - v0.x) * Alpha;
  240.  Result.y:= v0.y + (v1.y - v0.y) * Alpha;
  241.  Result.z:= v0.z + (v1.z - v0.z) * Alpha;
  242.  Result.w:= 1.0;
  243. end;
  244. //---------------------------------------------------------------------------
  245. function Dot4(const a, b: TVector4): Single;
  246. begin
  247.  Result:= (a.x * b.x) + (a.y * b.y) + (a.z * b.z);
  248. end;
  249. //---------------------------------------------------------------------------
  250. function Cross4(const a, b: TVector4): TVector4;
  251. begin
  252.  Result.x:= (a.y * b.z) - (a.z * b.y);
  253.  Result.y:= (a.z * b.x) - (a.x * b.z);
  254.  Result.z:= (a.x * b.y) - (a.y * b.x);
  255.  Result.w:= 1.0;
  256. end;
  257. //---------------------------------------------------------------------------
  258. function Angle4(const a, b: TVector4): Single;
  259. var
  260.  v: Single;
  261. begin
  262.  v:= Dot3(a, b) / (Length4(a) * Length4(b));
  263.  if (v < -1.0) then v:= -1.0
  264.   else if (v > 1.0) then v:= 1.0;
  265.  Result:= ArcCos(v);
  266. end;
  267. //---------------------------------------------------------------------------
  268. function Parallel4(const v, n: TVector4): TVector4;
  269. begin
  270.  Result:= n * (Dot4(v, n) / Sqr(Length4(n)));
  271. end;
  272. //--------------------------------------------------------------------------
  273. function Perp4(const v, n: TVector4): TVector4;
  274. begin
  275.  Result:= v - Parallel4(v, n);
  276. end;
  277. //---------------------------------------------------------------------------
  278. constructor TVectors4.Create();
  279. begin
  280.  inherited;
  281.  NativeAddr := nil;
  282.  AlignedAddr:= nil;
  283.  Capacity   := 0;
  284.  DataCount  := 0;
  285.  end;
  286. //---------------------------------------------------------------------------
  287. destructor TVectors4.Destroy();
  288. begin
  289.  if (NativeAddr <> nil) then
  290.   begin
  291.    FreeMem(NativeAddr);
  292.    NativeAddr := nil;
  293.    AlignedAddr:= nil;
  294.    Capacity   := 0;
  295.    DataCount  := 0;
  296.   end;
  297.  inherited;
  298. end;
  299. //---------------------------------------------------------------------------
  300. procedure TVectors4.Request(Amount: Integer);
  301. var
  302.  Required: Integer;
  303. begin
  304.  Required:= ((Amount + VectorCache - 1) div VectorCache) * VectorCache;
  305.  if (Capacity < Required) then Reallocate(Required);
  306. end;
  307. //---------------------------------------------------------------------------
  308. procedure TVectors4.Reallocate(Amount: Integer);
  309. var
  310.  NewAddr   : Pointer;
  311.  NewAligned: Pointer;
  312. begin
  313.  // allocate the requested amount of memory
  314.  GetMem(NewAddr, (Amount * SizeOf(TVector4)) + 16);
  315.  // align the memory address to 16-byte
  316.  NewAligned:= Pointer(Integer(NewAddr) + ($10 - (Integer(NewAddr) and $0F)));
  317.  // copy the contents of old buffer to the new one
  318.  if (DataCount > 0) then
  319.   Move(AlignedAddr^, NewAligned^, DataCount * SizeOf(TVector4));
  320.  // release the previously allocated memory
  321.  if (NativeAddr <> nil) then FreeMem(NativeAddr);
  322.  // update memory pointers
  323.  NativeAddr := NewAddr;
  324.  AlignedAddr:= NewAligned;
  325.  // update the capacity
  326.  Capacity:= Amount;
  327. end;
  328. //---------------------------------------------------------------------------
  329. function TVectors4.GetVector(Num: Integer): PVector4;
  330. begin
  331.  Result:= Pointer(Integer(AlignedAddr) + (Num * SizeOf(TVector4)));
  332. end;
  333. //---------------------------------------------------------------------------
  334. function TVectors4.GetItem(Num: Integer): TVector4;
  335. var
  336.  pVec: PVector4;
  337. begin
  338.  pVec:= GetVector(Num);
  339.  if (pVec <> nil) then Result:= pVec^
  340.   else Result:= ZeroVec4;
  341. end;
  342. //---------------------------------------------------------------------------
  343. procedure TVectors4.SetItem(Num: Integer; const Value: TVector4);
  344. var
  345.  pVec: PVector4;
  346. begin
  347.  pVec:= GetVector(Num);
  348.  if (pVec <> nil) then pVec^:= Value;
  349. end;
  350. //---------------------------------------------------------------------------
  351. function TVectors4.Add(const Vector: TVector4): Integer;
  352. var
  353.  Index: Integer;
  354.  pVec : PVector4;
  355. begin
  356.  Index:= DataCount;
  357.  Request(DataCount + 1);
  358.  Inc(DataCount);
  359.  pVec:= GetVector(Index);
  360.  pVec^:= Vector;
  361.  Result:= Index;
  362. end;
  363. //---------------------------------------------------------------------------
  364. function TVectors4.Add(x, y, z: Single): Integer;
  365. begin
  366.  Result:= Add(Vector4(x, y, z));
  367. end;
  368. //---------------------------------------------------------------------------
  369. procedure TVectors4.Remove(Index: Integer);
  370. var
  371.  Source: Pointer;
  372.  Dest  : Pointer;
  373.  Amount: Integer;
  374. begin
  375.  if (Index < 0)or(Index >= DataCount) then Exit;
  376.  Amount:= (DataCount - Index) - 1;
  377.  if (Amount > 0) then
  378.   begin
  379.    Source:= GetVector(Index + 1);
  380.    Dest  := GetVector(Index);
  381.    Move(Source^, Dest^, Amount * SizeOf(TVector4));
  382.   end;
  383.  Dec(DataCount);
  384. end;
  385. //---------------------------------------------------------------------------
  386. procedure TVectors4.RemoveAll();
  387. begin
  388.  DataCount:= 0;
  389. end;
  390. //---------------------------------------------------------------------------
  391. procedure TVectors4.CopyFrom(Source: TVectors4);
  392. begin
  393.  Request(Source.Count);
  394.  if (Source.Count > 0) then
  395.   Move(Source.MemAddr^, AlignedAddr^, Source.Count * SizeOf(TVector4));
  396.  DataCount:= Source.Count;
  397. end;
  398. //---------------------------------------------------------------------------
  399. procedure TVectors4.AddFrom(Source: TVectors4);
  400. var
  401.  DestAddr: Pointer;
  402. begin
  403.  Request(DataCount + Source.Count);
  404.  DestAddr:= GetVector(DataCount);
  405.  Move(Source.MemAddr^, DestAddr^, Source.Count * SizeOf(TVector4));
  406.  Inc(DataCount, Source.Count);
  407. end;
  408. //---------------------------------------------------------------------------
  409. procedure TVectors4.Transform(Source: TVectors4; Matrix: PMatrix4);
  410. begin
  411.  Request(Source.Count);
  412.  D3DXVec4TransformArray(AlignedAddr, SizeOf(TVector4),  Source.MemAddr,
  413.   SizeOf(TVector4), PD3DXMatrix(Matrix)^, Source.Count);
  414.  DataCount:= Source.Count;
  415. end;
  416. //---------------------------------------------------------------------------
  417. end.