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

2D图形编程

开发平台:

Delphi

  1. unit Vectors3;
  2. //---------------------------------------------------------------------------
  3. // Vectors3.pas                                         Modified: 28-Jan-2007
  4. // Definitions and functions working with 3D 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 Vectors3.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.  Types, Classes, SysUtils, Math, Vectors2, Vectors2px;
  41. //---------------------------------------------------------------------------
  42. type
  43.  PVector3 = ^TVector3;
  44.  TVector3 = record
  45.   x, y, z: Single;
  46.   class operator Add(const a, b: TVector3): TVector3;
  47.   class operator Subtract(const a, b: TVector3): TVector3;
  48.   class operator Multiply(const a, b: TVector3): TVector3;
  49.   class operator Divide(const a, b: TVector3): TVector3;
  50.   class operator Negative(const v: TVector3): TVector3;
  51.   class operator Multiply(const v: TVector3; const k: Single): TVector3;
  52.   class operator Divide(const v: TVector3; const k: Single): TVector3;
  53.   class operator Implicit(v: Single): TVector3;
  54.   function GetXY(): TPoint2;
  55.   function GetXYpx(): TPoint2px;
  56.   function ToString(): string;
  57.  end;
  58. //---------------------------------------------------------------------------
  59.  TVectors3 = class
  60.  private
  61.   Data: array of TVector3;
  62.   DataCount: Integer;
  63.  
  64.   function GetItem(Num: Integer): TVector3;
  65.   procedure SetItem(Num: Integer; const Value: TVector3);
  66.   function GetVector(Num: Integer): PVector3;
  67.   procedure Request(Amount: Integer);
  68.   public
  69.   property Count: Integer read DataCount;
  70.   property Items[Num: Integer]: TVector3 read GetItem write SetItem; default;
  71.   property Vector[Num: Integer]: PVector3 read GetVector;
  72.   function Add(const v: TVector3): Integer; overload;
  73.   function Add(x, y, z: Single): Integer; overload;
  74.   procedure Remove(Index: Integer);
  75.   procedure RemoveAll();
  76.   procedure CopyFrom(Source: TVectors3);
  77.   procedure AddFrom(Source: TVectors3);
  78.   procedure Normalize();
  79.   procedure Rescale(Scale: Real);
  80.   procedure Invert();
  81.   procedure Centralize();
  82.   procedure SaveToStream(Stream: TStream);
  83.   procedure LoadFromStream(Stream: TStream);
  84.   constructor Create();
  85.   destructor Destroy(); override;
  86.  end;
  87. //---------------------------------------------------------------------------
  88. const
  89.  ZeroVec3 : TVector3 = (x: 0.0; y: 0.0; z: 0.0);
  90.  UnityVec3: TVector3 = (x: 1.0; y: 1.0; z: 1.0);
  91.  AxisXVec3: TVector3 = (x: 1.0; y: 0.0; z: 0.0);
  92.  AxisYVec3: TVector3 = (x: 0.0; y: 1.0; z: 0.0);
  93.  AxisZVec3: TVector3 = (x: 0.0; y: 0.0; z: 1.0);
  94. //---------------------------------------------------------------------------
  95. function Vector3(x, y, z: Single): TVector3;
  96. function Length3(const v: TVector3): Single;
  97. function Norm3(const v: TVector3): TVector3;
  98. function Lerp3(const v0, v1: TVector3; Alpha: Single): TVector3;
  99. function Dot3(const a, b: TVector3): Single;
  100. function Cross3(const a, b: TVector3): TVector3;
  101. function Angle3(const a, b: TVector3): Single;
  102. function Parallel3(const v, n: TVector3): TVector3;
  103. function Perp3(const v, n: TVector3): TVector3;
  104. //---------------------------------------------------------------------------
  105. implementation
  106. //---------------------------------------------------------------------------
  107. const
  108.  CacheSize = 512;
  109. //---------------------------------------------------------------------------
  110. class operator TVector3.Add(const a, b: TVector3): TVector3;
  111. begin
  112.  Result.x:= a.x + b.x;
  113.  Result.y:= a.y + b.y;
  114.  Result.z:= a.z + b.z;
  115. end;
  116. //---------------------------------------------------------------------------
  117. class operator TVector3.Subtract(const a, b: TVector3): TVector3;
  118. begin
  119.  Result.x:= a.x - b.x;
  120.  Result.y:= a.y - b.y;
  121.  Result.z:= a.z - b.z;
  122. end;
  123. //---------------------------------------------------------------------------
  124. class operator TVector3.Multiply(const a, b: TVector3): TVector3;
  125. begin
  126.  Result.x:= a.x * b.x;
  127.  Result.y:= a.y * b.y;
  128.  Result.z:= a.z * b.z;
  129. end;
  130. //---------------------------------------------------------------------------
  131. class operator TVector3.Divide(const a, b: TVector3): TVector3;
  132. begin
  133.  Result.x:= a.x / b.x;
  134.  Result.y:= a.y / b.y;
  135.  Result.z:= a.z / b.z;
  136. end;
  137. //---------------------------------------------------------------------------
  138. class operator TVector3.Negative(const v: TVector3): TVector3;
  139. begin
  140.  Result.x:= -v.x;
  141.  Result.y:= -v.y;
  142.  Result.z:= -v.z;
  143. end;
  144. //---------------------------------------------------------------------------
  145. class operator TVector3.Multiply(const v: TVector3;
  146.  const k: Single): TVector3;
  147. begin
  148.  Result.x:= v.x * k;
  149.  Result.y:= v.y * k;
  150.  Result.z:= v.z * k;
  151. end;
  152. //---------------------------------------------------------------------------
  153. class operator TVector3.Divide(const v: TVector3;
  154.  const k: Single): TVector3;
  155. begin
  156.  Result.x:= v.x / k;
  157.  Result.y:= v.y / k;
  158.  Result.z:= v.z / k;
  159. end;
  160. //---------------------------------------------------------------------------
  161. class operator TVector3.Implicit(v: Single): TVector3;
  162. begin
  163.  Result.x:= v;
  164.  Result.y:= v;
  165.  Result.z:= v;
  166. end;
  167. //---------------------------------------------------------------------------
  168. function TVector3.ToString(): string;
  169. begin
  170.  Result:= Format('(%1.2f, %1.2f, %1.2f)', [x, y, z]);
  171. end;
  172. //---------------------------------------------------------------------------
  173. function TVector3.GetXY(): TPoint2;
  174. begin
  175.  Result.x:= x;
  176.  Result.y:= y;
  177. end;
  178. //---------------------------------------------------------------------------
  179. function TVector3.GetXYpx(): TPoint2px;
  180. begin
  181.  Result.x:= Round(x);
  182.  Result.y:= Round(y);
  183. end;
  184. //---------------------------------------------------------------------------
  185. function Vector3(x, y, z: Single): TVector3;
  186. begin
  187.  Result.x:= x;
  188.  Result.y:= y;
  189.  Result.z:= z;
  190. end;
  191. //---------------------------------------------------------------------------
  192. function Length3(const v: TVector3): Single;
  193. begin
  194.  Result:= Sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
  195. end;
  196. //---------------------------------------------------------------------------
  197. function Norm3(const v: TVector3): TVector3;
  198. var
  199.  Amp: Single;
  200. begin
  201.  Amp:= Length3(v);
  202.  if (Amp <> 0.0) then
  203.   begin
  204.    Result.x:= v.x / Amp;
  205.    Result.y:= v.y / Amp;
  206.    Result.z:= v.z / Amp;
  207.   end else Result:= ZeroVec3;
  208. end;
  209. //---------------------------------------------------------------------------
  210. function Lerp3(const v0, v1: TVector3; Alpha: Single): TVector3;
  211. begin
  212.  Result.x:= v0.x + (v1.x - v0.x) * Alpha;
  213.  Result.y:= v0.y + (v1.y - v0.y) * Alpha;
  214.  Result.z:= v0.z + (v1.z - v0.z) * Alpha;
  215. end;
  216. //---------------------------------------------------------------------------
  217. function Dot3(const a, b: TVector3): Single;
  218. begin
  219.  Result:= (a.x * b.x) + (a.y * b.y) + (a.z * b.z);
  220. end;
  221. //---------------------------------------------------------------------------
  222. function Cross3(const a, b: TVector3): TVector3;
  223. begin
  224.  Result.x:= (a.y * b.z) - (a.z * b.y);
  225.  Result.y:= (a.z * b.x) - (a.x * b.z);
  226.  Result.z:= (a.x * b.y) - (a.y * b.x);
  227. end;
  228. //---------------------------------------------------------------------------
  229. function Angle3(const a, b: TVector3): Single;
  230. var
  231.  v: Single;
  232. begin
  233.  v:= Dot3(a, b) / (Length3(a) * Length3(b));
  234.  if (v < -1.0) then v:= -1.0
  235.   else if (v > 1.0) then v:= 1.0;
  236.  Result:= ArcCos(v);
  237. end;
  238. //---------------------------------------------------------------------------
  239. function Parallel3(const v, n: TVector3): TVector3;
  240. begin
  241.  Result:= n * (Dot3(v, n) / Sqr(Length3(n)));
  242. end;
  243. //--------------------------------------------------------------------------
  244. function Perp3(const v, n: TVector3): TVector3;
  245. begin
  246.  Result:= v - Parallel3(v, n);
  247. end;
  248. //---------------------------------------------------------------------------
  249. constructor TVectors3.Create();
  250. begin
  251.  inherited;
  252.  DataCount:= 0;
  253. end;
  254. //---------------------------------------------------------------------------
  255. destructor TVectors3.Destroy();
  256. begin
  257.  DataCount:= 0;
  258.  SetLength(Data, 0);
  259.  inherited;
  260. end;
  261. //---------------------------------------------------------------------------
  262. function TVectors3.GetItem(Num: Integer): TVector3;
  263. begin
  264.  Result:= Data[Num];
  265. end;
  266. //---------------------------------------------------------------------------
  267. procedure TVectors3.SetItem(Num: Integer; const Value: TVector3);
  268. begin
  269.  Data[Num]:= Value;
  270. end;
  271. //---------------------------------------------------------------------------
  272. function TVectors3.GetVector(Num: Integer): PVector3;
  273. begin
  274.  Result:= @Data[Num];
  275. end;
  276. //---------------------------------------------------------------------------
  277. procedure TVectors3.Request(Amount: Integer);
  278. var
  279.  Required: Integer;
  280. begin
  281.  Required:= ((Amount + CacheSize - 1) div CacheSize) * CacheSize;
  282.  if (Length(Data) < Required) then SetLength(Data, Required);
  283. end;
  284. //---------------------------------------------------------------------------
  285. function TVectors3.Add(const v: TVector3): Integer;
  286. var
  287.  Index: Integer;
  288. begin
  289.  Index:= DataCount;
  290.  Request(DataCount + 1);
  291.  Data[Index]:= v;
  292.  Inc(DataCount);
  293.  Result:= Index;
  294. end;
  295. //---------------------------------------------------------------------------
  296. function TVectors3.Add(x, y, z: Single): Integer;
  297. begin
  298.  Result:= Add(Vector3(x, y, z));
  299. end;
  300. //---------------------------------------------------------------------------
  301. procedure TVectors3.Remove(Index: Integer);
  302. var
  303.  i: Integer;
  304. begin
  305.  if (Index < 0)or(Index >= DataCount) then Exit;
  306.  for i:= Index to DataCount - 2 do
  307.   Data[i]:= Data[i + 1];
  308.  Dec(DataCount);
  309. end;
  310. //---------------------------------------------------------------------------
  311. procedure TVectors3.RemoveAll();
  312. begin
  313.  DataCount:= 0;
  314. end;
  315. //---------------------------------------------------------------------------
  316. procedure TVectors3.CopyFrom(Source: TVectors3);
  317. var
  318.  i: Integer;
  319. begin
  320.  Request(Source.DataCount);
  321.  for i:= 0 to Source.DataCount - 1 do
  322.   Data[i]:= Source.Data[i];
  323.  DataCount:= Source.DataCount;
  324. end;
  325. //---------------------------------------------------------------------------
  326. procedure TVectors3.AddFrom(Source: TVectors3);
  327. var
  328.  i: Integer;
  329. begin
  330.  Request(DataCount + Source.DataCount);
  331.  for i:= 0 to Source.DataCount - 1 do
  332.   Data[i + DataCount]:= Source.Data[i];
  333.  Inc(DataCount, Source.DataCount);
  334. end;
  335. //--------------------------------------------------------------------------
  336. procedure TVectors3.Normalize();
  337. var
  338.  i: Integer;
  339. begin
  340.  for i:= 0 to DataCount - 1 do
  341.   Data[i]:= Norm3(Data[i]);
  342. end;
  343. //--------------------------------------------------------------------------
  344. procedure TVectors3.Rescale(Scale: Real);
  345. var
  346.  i: Integer;
  347. begin
  348.  for i:= 0 to DataCount - 1 do
  349.   Data[i]:= Data[i] * Scale;
  350. end;
  351. //---------------------------------------------------------------------------
  352. procedure TVectors3.Invert();
  353. var
  354.  i: Integer;
  355. begin
  356.  for i:= 0 to DataCount - 1 do
  357.   Data[i]:= -Data[i];
  358. end;
  359. //--------------------------------------------------------------------------
  360. procedure TVectors3.Centralize();
  361. var
  362.  i: Integer;
  363.  MinPoint: TVector3;
  364.  MaxPoint: TVector3;
  365.  Middle  : TVector3;
  366. begin
  367.  if (DataCount < 1) then Exit;
  368.  MinPoint:= Vector3(High(Integer), High(Integer), High(Integer));
  369.  MaxPoint:= Vector3(Low(Integer), Low(Integer), Low(Integer));
  370.  for i:= 0 to DataCount - 1 do
  371.   begin
  372.    MinPoint.x:= Min(MinPoint.x, Data[i].x);
  373.    MinPoint.y:= Min(MinPoint.y, Data[i].y);
  374.    MinPoint.z:= Min(MinPoint.z, Data[i].z);
  375.    MaxPoint.x:= Max(MaxPoint.x, Data[i].x);
  376.    MaxPoint.y:= Max(MaxPoint.y, Data[i].y);
  377.    MaxPoint.z:= Max(MaxPoint.z, Data[i].z);
  378.   end;
  379.  Middle.x:= (MinPoint.x + MaxPoint.x) / 2.0;
  380.  Middle.y:= (MinPoint.y + MaxPoint.y) / 2.0;
  381.  Middle.z:= (MinPoint.z + MaxPoint.z) / 2.0;
  382.  for i:= 0 to DataCount - 1 do
  383.   Data[i]:= Data[i] - Middle;
  384. end;
  385. //---------------------------------------------------------------------------
  386. procedure TVectors3.SaveToStream(Stream: TStream);
  387. var
  388.  i: Integer;
  389. begin
  390.  Stream.WriteBuffer(DataCount, SizeOf(Integer));
  391.  for i:= 0 to DataCount - 1 do
  392.   Stream.WriteBuffer(Data[i], SizeOf(TVector3));
  393. end;
  394. //---------------------------------------------------------------------------
  395. procedure TVectors3.LoadFromStream(Stream: TStream);
  396. var
  397.  NewAmount, i: Integer;
  398. begin
  399.  Stream.ReadBuffer(NewAmount, SizeOf(Integer));
  400.  Request(NewAmount);
  401.  for i:= 0 to NewAmount - 1 do
  402.   Stream.ReadBuffer(Data[i], SizeOf(TVector3));
  403.  DataCount:= NewAmount;
  404. end;
  405. //---------------------------------------------------------------------------
  406. end.