UPhysics2DTypes.pas
上传用户:zkjn0718
上传日期:2021-01-01
资源大小:776k
文件大小:39k
源码类别:

Delphi/CppBuilder

开发平台:

Delphi

  1. unit UPhysics2DTypes;
  2. { This unit is written based on Box2D whose author is Erin Catto (http://www.gphysics.com)
  3.   All type names follow the Delphi custom Txxx and xxx means the corresponding
  4.   type in cpp source.
  5.   Because versions before Delphi 2007 don't support operator overloading, so
  6.   I write two versions of all math operations for vector and matrix, etc. But
  7.   later I found that the version without operator overloading runs faster.
  8.   So if you want a better performance, DEFINE BETTER_PERFORMANCE in Physics2D.inc
  9.   which will UNDEFINE OP_OVERLOAD even if you are using Delphi 2010.
  10.   This library supports three kinds of floats, Single(32bit), Double(64bit) and
  11.   Extended(80bit).
  12.        flags        EXTENDED_PRECISION        DOUBLE_PRECISION
  13.      Extended               ON                     whatever
  14.       Double(default)       OFF                       ON
  15.       Single                OFF                       OFF
  16.   There is also a flag SINGLE_PRECISION in the include file but it doesn't affect
  17.   Float type definition.
  18.   All assertions are ignored.
  19.   Translator:  Qianyuan Wang(王乾元)
  20.   Contact me: http://hi.baidu.com/wqyfavor
  21.                       wqyfavor@163.com
  22.                       QQ: 466798985   }
  23. interface
  24. {$I Physics2D.inc}
  25. uses
  26.    Math, Classes, SysUtils,
  27.    {$IFDEF HANDLE_EXCEPTION}
  28.    UPhysics2DMessages,
  29.    {$ENDIF}
  30.    Dialogs;
  31. type
  32.    Int8   = ShortInt;
  33.    Int16  = SmallInt;
  34.    Int32  = Integer;
  35.    UInt8  = Byte;
  36.    UInt16 = Word;
  37.    UInt32 = Cardinal;
  38.    PUInt16 = ^UInt16;
  39.    // If handle exception and give localizable messages. Messages are stored in UPhysics2DMessages.pas
  40.    {$IFDEF HANDLE_EXCEPTION}
  41.    TPhysics2DExceptionCode = (ecDivByZero);
  42.    TPhysics2DException = class(Exception)
  43.       constructor Create(ErrorCode: TPhysics2DExceptionCode);
  44.    end;
  45.    {$ENDIF}
  46.    // Float type
  47.    PFloat = ^Float;
  48.    {$IFDEF EXTENDED_PRECISION}
  49.    Float = Extended;
  50.    {$ELSE}
  51.       {$IFDEF DOUBLE_PRECISION}
  52.       Float = Double;
  53.       {$ELSE}
  54.       Float = Single;
  55.       {$ENDIF}
  56.    {$ENDIF}
  57.    Float32 = Single;
  58.    Float64 = Double;
  59.    Float80 = Extended;
  60. const
  61.    {$IFDEF EXTENDED_PRECISION}
  62.    FLT_EPSILON = 1.084202172485504E-19;
  63.    FLT_MAX = MaxExtended;
  64.    {$ELSE}
  65.       {$IFDEF DOUBLE_PRECISION}
  66.       FLT_EPSILON = 2.2204460492503131e-16;
  67.       FLT_MAX = MaxDouble;
  68.       {$ELSE}
  69.       FLT_EPSILON = 1.192092896e-7;
  70.       FLT_MAX = MaxSingle;
  71.       {$ENDIF}
  72.    {$ENDIF}
  73.    function IsValid(f: Float): Boolean; {$IFNDEF OP_OVERLOAD}overload;{$ENDIF}
  74. type
  75.    PVector2 = ^TVector2;
  76.    TVector2 = record
  77.       x, y: Float;
  78.       {$IFDEF OP_OVERLOAD}
  79.       function IsValid: Boolean; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  80.       function Length: Float; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  81.       function SqrLength: Float; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  82.       function Normalize: Float; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  83.       procedure SetZero; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  84.       procedure SetNegative; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  85.       procedure SetValue(x, y: Float); {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  86.       class function From(const x, y: Float): TVector2; static; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  87.       // Operators
  88.       class operator Negative(const AValue: TVector2): TVector2; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  89.       class operator Add(const Left, Right: TVector2): TVector2; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  90.       class operator Subtract(const Left, Right: TVector2): TVector2; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  91.       class operator Multiply(const Left: TVector2; const Right: Single): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  92.       class operator Multiply(const Left: TVector2; const Right: Double): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  93.       class operator Multiply(const Left: TVector2; const Right: Extended): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  94.       class operator Multiply(const Left: Single; const Right: TVector2): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  95.       class operator Multiply(const Left: Double; const Right: TVector2): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  96.       class operator Multiply(const Left: Extended; const Right: TVector2): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  97.       class operator Divide(const Left: TVector2; const Right: Single): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  98.       class operator Divide(const Left: TVector2; const Right: Double): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  99.       class operator Divide(const Left: TVector2; const Right: Extended): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  100.       procedure AddBy(const Operand: TVector2); {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  101.       procedure SubtractBy(const Operand: TVector2); {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  102.       procedure MultiplyBy(const Operand: Single); overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  103.       procedure MultiplyBy(const Operand: Double); overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  104.       procedure MultiplyBy(const Operand: Extended); overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  105.       procedure DivideBy(const Operand: Single); overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  106.       procedure DivideBy(const Operand: Double); overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  107.       procedure DivideBy(const Operand: Extended); overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  108.       {$ENDIF}
  109.    end;
  110.    TVectorArray4 = array[0..3] of TVector2;
  111.    TMatrix22 = record
  112.       col1, col2: TVector2;
  113.       {$IFDEF OP_OVERLOAD}
  114.       procedure SetIdentity;
  115.       procedure SetZero;
  116.       procedure SetValue(const _col1, _col2: TVector2); overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  117.       /// Initialize this matrix using an angle. This matrix becomes
  118.     /// an orthonormal rotation matrix.
  119.       procedure SetValue(angle: Float); overload;
  120.       function Invert: TMatrix22;
  121.       function Solve(const b: TVector2): TVector2; // Solve A * x = b, where b is a column vector.
  122.       // Operators
  123.       class operator Negative(const AValue: TMatrix22): TMatrix22;
  124.       class operator Add(const Left, Right: TMatrix22): TMatrix22;
  125.       class operator Subtract(const Left, Right: TMatrix22): TMatrix22;
  126.       {$ENDIF}
  127.    end;
  128.    /// A transform contains translation and rotation. It is used to represent
  129.    /// the position and orientation of rigid bodies.
  130.    Tb2XForm = record
  131.       position: TVector2;
  132.       R: TMatrix22;
  133.       {$IFDEF OP_OVERLOAD}
  134.       procedure SetIdentity;
  135.       class function From(const position: TVector2; const R: TMatrix22): Tb2XForm; static;
  136.       {$ENDIF}
  137.    end;
  138.    /// This describes the motion of a body/shape for TOI computation.
  139.    /// Shapes are defined with respect to the body origin, which may
  140.    /// no coincide with the center of mass. However, to support dynamics
  141.    /// we must interpolate the center of mass position.
  142.    Tb2Sweep = record
  143.       localCenter: TVector2; // local center of mass position
  144.       c0, c: TVector2; // center world positions
  145.       a0, a: Float; // world angles
  146.       t0: Float; // time interval = [t0,1], where t0 is in [0,1]
  147.       {$IFDEF OP_OVERLOAD}
  148.       /// Get the interpolated transform at a specific time.
  149.      /// @param t the normalized time in [0,1].
  150.      procedure GetXForm(var xf: Tb2XForm; t: Float);
  151.     /// Advance the sweep forward, yielding a new initial state.
  152.      /// @param t the new initial time.
  153.       procedure Advance(t: Float);
  154.       {$ENDIF}
  155.    end;
  156. const
  157.    b2Vec2_Zero: TVector2 = (X: 0.0; Y: 0.0);
  158.    b2Mat22_identity: TMatrix22 = (col1: (X: 1.0; Y: 0.0); col2: (X: 0.0; Y: 1.0));
  159.    b2XForm_identity: Tb2XForm = (position: (X: 0.0; Y: 0.0); R: (col1: (X: 1.0; Y: 0.0); col2: (X: 0.0; Y: 1.0)));
  160. const
  161.    UInt8_MAX = $FF;
  162.    UINT16_MAX = $FFFF;
  163.    b2_maxManifoldPoints = 2;
  164.    b2_maxPolygonVertices = 8;
  165.    b2_maxProxies = 512; // this must be a power of two
  166.    b2_maxPairs = 8 * b2_maxProxies; // this must be a power of two
  167.    b2_nullFeature: UInt8 = UInt8_MAX;
  168.    b2_nullPair: UInt16 = UINT16_MAX;
  169.    b2_nullProxy: UInt16 = UINT16_MAX;
  170.    b2_tableCapacity = b2_maxPairs; // must be a power of two
  171.    b2_tableMask = b2_tableCapacity - 1; // should be (b2_tableCapacity - 1) but won't compile.
  172.    B2BROADPHASE_MAX = UINT16_MAX;
  173.    b2_invalid: UInt16 = B2BROADPHASE_MAX;
  174.    b2_nullEdge: UInt16 = B2BROADPHASE_MAX;
  175.    // Dynamics
  176.    /// A small length used as a collision and constraint tolerance. Usually it is
  177.    /// chosen to be numerically significant, but visually insignificant.
  178.    b2_linearSlop = 0.005; // 0.5 cm
  179.    /// A small angle used as a collision and constraint tolerance. Usually it is
  180.    /// chosen to be numerically significant, but visually insignificant.
  181.    b2_angularSlop = 2.0 / 180.0 * Pi; // 2 degrees
  182.    /// Continuous collision detection (CCD) works with core, shrunken shapes. This is the
  183.    /// amount by which shapes are automatically shrunk to work with CCD. This must be
  184.    /// larger than b2_linearSlop.
  185.    b2_toiSlop = 8.0 * b2_linearSlop;
  186.    /// Maximum number of contacts to be handled to solve a TOI island.
  187.    b2_maxTOIContactsPerIsland: Int32 = 32;
  188.    /// A velocity threshold for elastic collisions. Any collision with a relative linear
  189.    /// velocity below this threshold will be treated as inelastic.
  190.    b2_velocityThreshold = 1.0; // 1 m/s
  191.    /// The maximum linear position correction used when solving constraints. This helps to
  192.    /// prevent overshoot.
  193.    b2_maxLinearCorrection = 0.2; // 20 cm
  194.    /// The maximum angular position correction used when solving constraints. This helps to
  195.    /// prevent overshoot.
  196.    b2_maxAngularCorrection = 8.0 / 180.0 * Pi; // 8 degrees
  197.    /// The maximum linear velocity of a body. This limit is very large and is used
  198.    /// to prevent numerical problems. You shouldn't need to adjust this.
  199.    b2_maxLinearVelocity = 200.0;
  200.    b2_maxLinearVelocitySquared = b2_maxLinearVelocity * b2_maxLinearVelocity;
  201.    /// The maximum angular velocity of a body. This limit is very large and is used
  202.    /// to prevent numerical problems. You shouldn't need to adjust this.
  203.    b2_maxAngularVelocity = 250.0;
  204.    b2_maxAngularVelocitySquared = b2_maxAngularVelocity * b2_maxAngularVelocity;
  205.    /// This scale factor controls how fast overlap is resolved. Ideally this would be 1 so
  206.    /// that overlap is removed in one time step. However using values close to 1 often lead
  207.    /// to overshoot.
  208.    b2_contactBaumgarte = 0.2;
  209.    // Sleep
  210.    /// The time that a body must be still before it will go to sleep.
  211.    b2_timeToSleep  = 0.5; // half a second
  212.    /// A body cannot sleep if its linear velocity is above this tolerance.
  213.    b2_linearSleepTolerance = 0.01; // 1 cm/s
  214.    /// A body cannot sleep if its angular velocity is above this tolerance.
  215.    b2_angularSleepTolerance = 2.0 / 180.0; // 2 degrees/s
  216. function MakeVector(x, y: Float): TVector2; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  217. procedure SetZero(var v: TVector2); {$IFNDEF OP_OVERLOAD}overload;{$ENDIF} {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  218. procedure SetValue(var v: TVector2; ax, ay: Float); {$IFNDEF OP_OVERLOAD}overload;{$ENDIF} {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  219. {$IFNDEF OP_OVERLOAD}
  220. // For TVector2
  221. function IsValid(const v: TVector2): Boolean; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  222. function Length(const v: TVector2): Float; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  223. function SqrLength(const v: TVector2): Float; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  224. function Normalize(var v: TVector2): Float; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  225. procedure SetNegative(var v: TVector2); {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  226. function Negative(const AValue: TVector2): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  227. function Add(const Left, Right: TVector2): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  228. function Add(const p1, p2, p3: TVector2): TVector2; overload;
  229. function Subtract(const Left, Right: TVector2): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  230. function Multiply(const Left: TVector2; const Right: Single): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  231. function Multiply(const Left: TVector2; const Right: Double): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  232. function Multiply(const Left: TVector2; const Right: Extended): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  233. function Divide(const Left: TVector2; const Right: Single): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  234. function Divide(const Left: TVector2; const Right: Double): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  235. function Divide(const Left: TVector2; const Right: Extended): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  236. procedure AddBy(var v: TVector2; const Operand: TVector2); {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  237. procedure SubtractBy(var v: TVector2; const Operand: TVector2); {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  238. procedure MultiplyBy(var v: TVector2; const Operand: Single); overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  239. procedure MultiplyBy(var v: TVector2; const Operand: Double); overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  240. procedure MultiplyBy(var v: TVector2; const Operand: Extended); overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  241. procedure DivideBy(var v: TVector2; const Operand: Single); overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  242. procedure DivideBy(var v: TVector2; const Operand: Double); overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  243. procedure DivideBy(var v: TVector2; const Operand: Extended); overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  244. // For TMatrix22
  245. procedure SetIdentity(var m: TMatrix22); overload;
  246. procedure SetZero(var m: TMatrix22); overload;
  247. procedure SetValue(var m: TMatrix22; const _col1, _col2: TVector2); overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  248. procedure SetValue(var m: TMatrix22; angle: Float); overload;
  249. function Invert(const m: TMatrix22): TMatrix22;
  250. function Solve(const m: TMatrix22; const b: TVector2): TVector2; // Solve A * x = b, where b is a column vector.
  251. function Negative(const AValue: TMatrix22): TMatrix22; overload;
  252. function Add(const Left, Right: TMatrix22): TMatrix22; overload;
  253. function Add(const m1, m2, m3: TMatrix22): TMatrix22; overload;
  254. function Subtract(const Left, Right: TMatrix22): TMatrix22; overload;
  255. // For T2bXForm
  256. procedure SetIdentity(var xf: Tb2XForm); overload;
  257. // For Tb2Sweep
  258. procedure GetXForm(const Sweep: Tb2Sweep; var xf: Tb2XForm; t: Float);
  259. procedure Advance(var Sweep: Tb2Sweep; t: Float);
  260. {$ENDIF}
  261. function b2MixFriction(friction1, friction2: Float): Float; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  262. function b2MixRestitution(restitution1, restitution2: Float): Float; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  263. function b2Max(const a, b: Float): Float; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  264. function b2Max(const a, b: TVector2): TVector2; overload;
  265. function b2Min(const a, b: Float): Float; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  266. function b2Min(const a, b: TVector2): TVector2; overload;
  267. function b2Max(const a, b: Int32): Int32; overload;
  268. function b2Min(const a, b: Int32): Int32; overload;
  269. procedure b2Swap(var a, b: Float); overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  270. procedure b2Swap(var a, b: Int32); overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  271. procedure b2Swap(var a, b: TVector2); overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  272. function b2Clamp(const a, low, high: TVector2): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  273. function b2Clamp(const a, low, high: Float): Float; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  274. function b2Dot(const a, b: TVector2): Float; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  275. function b2Cross(const a, b: TVector2): Float; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  276. function b2Cross(const a: TVector2; s: Float): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  277. function b2Cross(s: Float; const a: TVector2): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  278. function b2Mul(const A: TMatrix22; const v: TVector2): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  279. function b2MulT(const A: TMatrix22; const v: TVector2): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  280. function b2Distance(const a, b: TVector2): Float; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  281. function b2DistanceSquared(const a, b: TVector2): Float; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  282. function b2Mul(const A, B: TMatrix22): TMatrix22; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  283. function b2MulT(const A, B: TMatrix22): TMatrix22; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  284. function b2Mul(const T: Tb2XForm; const v: TVector2): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  285. function b2MulT(const T: Tb2XForm; const v: TVector2): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  286. function b2Abs(const a: TVector2): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  287. function b2Abs(const a: TMatrix22): TMatrix22; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  288. {$IFDEF EXTENDED_PRECISION}
  289. procedure SinCos(const Theta: Extended; var Sin, Cos: Extended);
  290. {$ELSE}
  291. {$IFDEF DOUBLE_PRECISION}
  292. procedure SinCos(const Theta: Double; var Sin, Cos: Double);
  293. {$ELSE}
  294. procedure SinCos(const Theta: Single; var Sin, Cos: Single);
  295. {$ENDIF}
  296. {$ENDIF}
  297. implementation
  298. {$IFDEF EXTENDED_PRECISION}
  299. procedure SinCos(const Theta: Extended; var Sin, Cos: Extended);
  300. asm
  301.    FLD  Theta
  302.    FSINCOS
  303.    FSTP TBYTE PTR [EDX]    // cosine
  304.    FSTP TBYTE PTR [EAX]    // sine
  305. end;
  306. {$ELSE}
  307. {$IFDEF DOUBLE_PRECISION}
  308. procedure SinCos(const Theta: Double; var Sin, Cos: Double);
  309. asm
  310.    FLD  Theta
  311.    FSINCOS
  312.    FSTP QWORD PTR [EDX]    // cosine
  313.    FSTP QWORD PTR [EAX]    // sine
  314. end;
  315. {$ELSE}
  316. procedure SinCos(const Theta: Single; var Sin, Cos: Single);
  317. asm
  318.    FLD  Theta
  319.    FSINCOS
  320.    FSTP DWORD PTR [EDX]    // cosine
  321.    FSTP DWORD PTR [EAX]    // sine
  322. end;
  323. {$ENDIF}
  324. {$ENDIF}
  325. function MakeVector(x, y: Float): TVector2;
  326. begin
  327.    Result.x := x;
  328.    Result.y := y;
  329. end;
  330. procedure SetZero(var v: TVector2);
  331. begin
  332.    with v do
  333.    begin
  334.       x := 0.0;
  335.       y := 0.0;
  336.    end;
  337. end;
  338. procedure SetValue(var v: TVector2; ax, ay: Float);
  339. begin
  340.    with v do
  341.    begin
  342.       x := ax;
  343.       y := ay;
  344.    end;
  345. end;
  346. {$IFNDEF OP_OVERLOAD}
  347. function IsValid(const v: TVector2): Boolean;
  348. begin
  349.    Result := UPhysics2DTypes.IsValid(v.x) and UPhysics2DTypes.IsValid(v.y);
  350. end;
  351. function Length(const v: TVector2): Float;
  352. begin
  353.    with v do
  354.       Result := Sqrt(x * x + y * y);
  355. end;
  356. function SqrLength(const v: TVector2): Float;
  357. begin
  358.    with v do
  359.       Result := x * x + y * y;
  360. end;
  361. function Normalize(var v: TVector2): Float;
  362. begin
  363.    Result := Length(v);
  364.  if Result < FLT_EPSILON then
  365.    begin
  366.       Result := 0.0;
  367.       Exit;
  368.    end;
  369.    with v do
  370.    begin
  371.       x := x / Result;
  372.       y := y / Result;
  373.    end;
  374. end;
  375. procedure SetNegative(var v: TVector2);
  376. begin
  377.    with v do
  378.    begin
  379.       x := -x;
  380.       y := -y;
  381.    end;
  382. end;
  383. function Negative(const AValue: TVector2): TVector2;
  384. begin
  385.    Result.x := -AValue.x;
  386.    Result.y := -AValue.y;
  387. end;
  388. function Add(const Left, Right: TVector2): TVector2;
  389. begin
  390.    Result.x := Left.x + Right.x;
  391.    Result.y := Left.y + Right.y;
  392. end;
  393. function Add(const p1, p2, p3: TVector2): TVector2;
  394. begin
  395.    Result.x := p1.x + p2.x + p3.x;
  396.    Result.y := p1.y + p2.y + p3.y;
  397. end;
  398. function Subtract(const Left, Right: TVector2): TVector2;
  399. begin
  400.    Result.x := Left.x - Right.x;
  401.    Result.y := Left.y - Right.y;
  402. end;
  403. function Multiply(const Left: TVector2; const Right: Single): TVector2;
  404. begin
  405.    Result.x := Left.x * Right;
  406.    Result.y := Left.y * Right;
  407. end;
  408. function Multiply(const Left: TVector2; const Right: Double): TVector2;
  409. begin
  410.    Result.x := Left.x * Right;
  411.    Result.y := Left.y * Right;
  412. end;
  413. function Multiply(const Left: TVector2; const Right: Extended): TVector2;
  414. begin
  415.    Result.x := Left.x * Right;
  416.    Result.y := Left.y * Right;
  417. end;
  418. function Divide(const Left: TVector2; const Right: Single): TVector2;
  419. begin
  420.    Result.x := Left.x / Right;
  421.    Result.y := Left.y / Right;
  422. end;
  423. function Divide(const Left: TVector2; const Right: Double): TVector2;
  424. begin
  425.    Result.x := Left.x / Right;
  426.    Result.y := Left.y / Right;
  427. end;
  428. function Divide(const Left: TVector2; const Right: Extended): TVector2;
  429. begin
  430.    Result.x := Left.x / Right;
  431.    Result.y := Left.y / Right;
  432. end;
  433. procedure AddBy(var v: TVector2; const Operand: TVector2);
  434. begin
  435.    with v do
  436.    begin
  437.       x := x + Operand.x;
  438.       y := y + Operand.y;
  439.    end;
  440. end;
  441. procedure SubtractBy(var v: TVector2; const Operand: TVector2);
  442. begin
  443.    with v do
  444.    begin
  445.       x := x - Operand.x;
  446.       y := y - Operand.y;
  447.    end;
  448. end;
  449. procedure MultiplyBy(var v: TVector2; const Operand: Single);
  450. begin
  451.    with v do
  452.    begin
  453.       x := x * Operand;
  454.       y := y * Operand;
  455.    end;
  456. end;
  457. procedure MultiplyBy(var v: TVector2; const Operand: Double);
  458. begin
  459.    with v do
  460.    begin
  461.       x := x * Operand;
  462.       y := y * Operand;
  463.    end;
  464. end;
  465. procedure MultiplyBy(var v: TVector2; const Operand: Extended);
  466. begin
  467.    with v do
  468.    begin
  469.       x := x * Operand;
  470.       y := y * Operand;
  471.    end;
  472. end;
  473. procedure DivideBy(var v: TVector2; const Operand: Single);
  474. begin
  475.    with v do
  476.    begin
  477.       x := x / Operand;
  478.       y := y / Operand;
  479.    end;
  480. end;
  481. procedure DivideBy(var v: TVector2; const Operand: Double);
  482. begin
  483.    with v do
  484.    begin
  485.       x := x / Operand;
  486.       y := y / Operand;
  487.    end;
  488. end;
  489. procedure DivideBy(var v: TVector2; const Operand: Extended);
  490. begin
  491.    with v do
  492.    begin
  493.       x := x / Operand;
  494.       y := y / Operand;
  495.    end;
  496. end;
  497. procedure SetIdentity(var m: TMatrix22);
  498. begin
  499.    with m do
  500.    begin
  501.       col1.x := 1.0;
  502.       col2.x := 0.0;
  503.       col1.y := 0.0;
  504.       col2.y := 1.0;
  505.    end;
  506. end;
  507. procedure SetZero(var m: TMatrix22);
  508. begin
  509.    with m do
  510.    begin
  511.       col1.x := 0.0;
  512.       col2.x := 0.0;
  513.       col1.y := 0.0;
  514.       col2.y := 0.0;
  515.    end;
  516. end;
  517. procedure SetValue(var m: TMatrix22; const _col1, _col2: TVector2);
  518. begin
  519.    with m do
  520.    begin
  521.       col1 := _col1;
  522.       col2 := _col2;
  523.    end;
  524. end;
  525. procedure SetValue(var m: TMatrix22; angle: Float);
  526. var
  527.    c, s: Float;
  528. begin
  529.     SinCos(angle, s, c);
  530.     with m do
  531.     begin
  532.        col1.x := c;
  533.        col2.x := -s;
  534.        col1.y := s;
  535.        col2.y := c;
  536.     end;
  537. end;
  538. function Invert(const m: TMatrix22): TMatrix22;
  539. var
  540.    a, b, c, d, det: Float;
  541. begin
  542.    with m do
  543.    begin
  544.       a := col1.x;
  545.       b := col2.x;
  546.       c := col1.y;
  547.       d := col2.y;
  548.    end;
  549.    det := a * d - b * c;
  550.    {$IFDEF HANDLE_EXCEPTION}
  551.    if IsZero(det) then
  552.       raise TPhysics2DException.Create(ecDivByZero);
  553.    {$ENDIF}
  554.    det := 1.0 / det;
  555.    with Result do
  556.    begin
  557.       col1.x :=  det * d;
  558.       col2.x := -det * b;
  559.       col1.y := -det * c;
  560.       col2.y :=  det * a;
  561.    end;
  562. end;
  563. function Solve(const m: TMatrix22; const b: TVector2): TVector2;
  564. var
  565.    a11, a12, a21, a22, det: Float;
  566. begin
  567.    with m do
  568.    begin
  569.       a11 := col1.x;
  570.       a12 := col2.x;
  571.       a21 := col1.y;
  572.       a22 := col2.y;
  573.    end;
  574.    det := a11 * a22 - a12 * a21;
  575.    {$IFDEF HANDLE_EXCEPTION}
  576.    if IsZero(det) then
  577.       raise TPhysics2DException.Create(ecDivByZero);
  578.    {$ENDIF}
  579.    det := 1.0 / det;
  580.    Result.x := det * (a22 * b.x - a12 * b.y);
  581.    Result.y := det * (a11 * b.y - a21 * b.x);
  582. end;
  583. function Negative(const AValue: TMatrix22): TMatrix22;
  584. begin
  585.    with Result do
  586.    begin
  587.       col1.x := -AValue.col1.x;
  588.       col1.y := -AValue.col1.y;
  589.       col2.x := -AValue.col2.x;
  590.       col2.y := -AValue.col2.y;
  591.    end;
  592. end;
  593. function Add(const Left, Right: TMatrix22): TMatrix22;
  594. begin
  595.    with Result do
  596.    begin
  597.       col1.x := Left.col1.x + Right.col1.x;
  598.       col1.y := Left.col1.y + Right.col1.y;
  599.       col2.x := Left.col2.x + Right.col2.x;
  600.       col2.y := Left.col2.y + Right.col2.y;
  601.    end;
  602. end;
  603. function Add(const m1, m2, m3: TMatrix22): TMatrix22;
  604. begin
  605.    with Result do
  606.    begin
  607.       col1.x := m1.col1.x + m2.col1.x + m3.col1.x;
  608.       col1.y := m1.col1.y + m2.col1.y + m3.col1.y;
  609.       col2.x := m1.col2.x + m2.col2.x + m3.col2.x;
  610.       col2.y := m1.col2.y + m2.col2.y + m3.col2.y;
  611.    end;
  612. end;
  613. function Subtract(const Left, Right: TMatrix22): TMatrix22;
  614. begin
  615.    with Result do
  616.    begin
  617.       col1.x := Left.col1.x - Right.col1.x;
  618.       col1.y := Left.col1.y - Right.col1.y;
  619.       col2.x := Left.col2.x - Right.col2.x;
  620.       col2.y := Left.col2.y - Right.col2.y;
  621.    end;
  622. end;
  623. procedure SetIdentity(var xf: Tb2XForm);
  624. begin
  625.    with xf do
  626.    begin
  627.       SetZero(position);
  628.       SetIdentity(R);
  629.    end;
  630. end;
  631. procedure GetXForm(const Sweep: Tb2Sweep; var xf: Tb2XForm; t: Float);
  632. var
  633.    alpha: Float;
  634. begin
  635.    with Sweep do
  636.    begin
  637.       // center = p + R * localCenter
  638.       if (1.0 - t0 > FLT_EPSILON) then
  639.       begin
  640.          alpha := (t - t0) / (1.0 - t0);
  641.          xf.position := Add(Multiply(c0, 1.0 - alpha), Multiply(c, alpha));
  642.          SetValue(xf.R, (1.0 - alpha) * a0 + alpha * a);
  643.       end
  644.       else
  645.       begin
  646.          // center = p + R * localCenter
  647.          xf.position := c;
  648.          SetValue(xf.R, a);
  649.       end;
  650.       // Shift to origin
  651.       SubtractBy(xf.position, b2Mul(xf.R, localCenter));
  652.    end;
  653. end;
  654. procedure Advance(var Sweep: Tb2Sweep; t: Float);
  655. var
  656.    alpha: Float;
  657. begin
  658.    with Sweep do
  659.    begin
  660.       if (t0 < t) and (t0 < 1.0 - FLT_EPSILON) then
  661.       begin
  662.          alpha := (t - t0) / (1.0 - t0);
  663.          c0 := Add(Multiply(c0, 1.0 - alpha), Multiply(c, alpha));
  664.          a0 := (1.0 - alpha) * a0 + alpha * a;
  665.          t0 := t;
  666.       end;
  667.    end;
  668. end;
  669. {$ENDIF}
  670. /// Friction mixing law. Feel free to customize this.
  671. function b2MixFriction(friction1, friction2: Float): Float; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  672. begin
  673.  Result := Sqrt(friction1 * friction2);
  674. end;
  675. /// Restitution mixing law. Feel free to customize this.
  676. function b2MixRestitution(restitution1, restitution2: Float): Float; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  677. begin
  678.    if restitution1 > restitution2 then
  679.       Result := restitution1
  680.    else
  681.       Result := restitution2;
  682. end;
  683. function b2Max(const a, b: Float): Float;
  684. begin
  685.    if a >= b then
  686.       Result := a
  687.    else
  688.       Result := b;
  689. end;
  690. function b2Max(const a, b: TVector2): TVector2;
  691. begin
  692.    Result.x := b2Max(a.x, b.x);
  693.    Result.y := b2Max(a.y, b.y);
  694. end;
  695. function b2Min(const a, b: Float): Float;
  696. begin
  697.    if a >= b then
  698.       Result := b
  699.    else
  700.       Result := a;
  701. end;
  702. function b2Min(const a, b: TVector2): TVector2;
  703. begin
  704.    Result.x := b2Min(a.x, b.x);
  705.    Result.y := b2Min(a.y, b.y);
  706. end;
  707. function b2Max(const a, b: Int32): Int32;
  708. begin
  709.    if a >= b then
  710.       Result := a
  711.    else
  712.       Result := b;
  713. end;
  714. function b2Min(const a, b: Int32): Int32;
  715. begin
  716.    if a >= b then
  717.       Result := b
  718.    else
  719.       Result := a;
  720. end;
  721. procedure b2Swap(var a, b: Float);
  722. var
  723.    tmp: Float;
  724. begin
  725.    tmp := a;
  726.    a := b;
  727.    b := tmp;
  728. end;
  729. procedure b2Swap(var a, b: Int32);
  730. var
  731.    tmp: Int32;
  732. begin
  733.    tmp := a;
  734.    a := b;
  735.    b := tmp;
  736. end;
  737. procedure b2Swap(var a, b: TVector2);
  738. var
  739.    tmp: TVector2;
  740. begin
  741.    tmp := a;
  742.    a := b;
  743.    b := tmp;
  744. end;
  745. function b2Clamp(const a, low, high: TVector2): TVector2;
  746. begin
  747.    Result := b2Max(low, b2Min(a, high));
  748. end;
  749. function b2Clamp(const a, low, high: Float): Float;
  750. begin
  751.    Result := b2Max(low, b2Min(a, high));
  752. end;
  753. function IsValid(f: Float): Boolean; {$IFNDEF OP_OVERLOAD}overload;{$ENDIF}
  754. begin
  755.    Result := not (IsNan(f) or IsInfinite(f));
  756. end;
  757. /// Peform the dot product on two vectors.
  758. function b2Dot(const a, b: TVector2): Float; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  759. begin
  760.    Result := a.x * b.x + a.y * b.y;
  761. end;
  762. /// Perform the cross product on two vectors. In 2D this produces a scalar.
  763. function b2Cross(const a, b: TVector2): Float; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  764. begin
  765.  Result := a.x * b.y - a.y * b.x;
  766. end;
  767. /// Perform the cross product on a vector and a scalar. In 2D this produces a vector.
  768. function b2Cross(const a: TVector2; s: Float): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  769. begin
  770.    Result.x := s * a.y;
  771.    Result.y := -s * a.x;
  772. end;
  773. /// Perform the cross product on a scalar and a vector. In 2D this produces a vector.
  774. function b2Cross(s: Float; const a: TVector2): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  775. begin
  776.    Result.x := -s * a.y;
  777.    Result.y := s * a.x;
  778. end;
  779. /// Multiply a matrix times a vector. If a rotation matrix is provided,
  780. /// then this transforms the vector from one frame to another.
  781. function b2Mul(const A: TMatrix22; const v: TVector2): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  782. begin
  783.    Result.x := A.col1.x * v.x + A.col2.x * v.y;
  784.    Result.y := A.col1.y * v.x + A.col2.y * v.y;
  785. end;
  786. /// Multiply a matrix transpose times a vector. If a rotation matrix is provided,
  787. /// then this transforms the vector from one frame to another (inverse transform).
  788. function b2MulT(const A: TMatrix22; const v: TVector2): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  789. begin
  790.    Result.x := b2Dot(v, A.col1);
  791.    Result.y := b2Dot(v, A.col2);
  792. end;
  793. {$IFDEF OP_OVERLOAD}
  794. function b2Distance(const a, b: TVector2): Float; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  795. begin
  796.    Result := (a - b).Length;
  797. end;
  798. function b2DistanceSquared(const a, b: TVector2): Float; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  799. begin
  800.    Result := (a - b).SqrLength;
  801. end;
  802. {$ELSE}
  803. function b2Distance(const a, b: TVector2): Float; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  804. begin
  805.    Result := Length(Subtract(a, b));
  806. end;
  807. function b2DistanceSquared(const a, b: TVector2): Float; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  808. begin
  809.    Result := SqrLength(Subtract(a, b));
  810. end;
  811. {$ENDIF}
  812. // A * B
  813. function b2Mul(const A, B: TMatrix22): TMatrix22; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  814. begin
  815.    Result.col1 := b2Mul(A, B.col1);
  816.    Result.col2 := b2Mul(A, B.col2);
  817. end;
  818. // A^T * B
  819. function b2MulT(const A, B: TMatrix22): TMatrix22; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  820. var
  821.    c1, c2: TVector2;
  822. begin
  823.    with Result do
  824.    begin
  825.       col1.x := b2Dot(A.col1, B.col1);
  826.       col1.y := b2Dot(A.col2, B.col1);
  827.       col2.x := b2Dot(A.col1, B.col2);
  828.       col2.y := b2Dot(A.col2, B.col2);
  829.    end;
  830. end;
  831. {$IFDEF OP_OVERLOAD}
  832. function b2Mul(const T: Tb2XForm; const v: TVector2): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  833. begin
  834.    Result := T.position + b2Mul(T.R, v);
  835. end;
  836. {$ELSE}
  837. function b2Mul(const T: Tb2XForm; const v: TVector2): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  838. var
  839.    tmp: TVector2;
  840. begin
  841.    tmp := b2Mul(T.R, v);
  842.    Result.x := T.position.x + tmp.x;
  843.    Result.y := T.position.y + tmp.y;
  844. end;
  845. {$ENDIF}
  846. {$IFDEF OP_OVERLOAD}
  847. function b2MulT(const T: Tb2XForm; const v: TVector2): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  848. begin
  849.    Result := b2MulT(T.R, v - T.position);
  850. end;
  851. {$ELSE}
  852. // unfinished
  853. function b2MulT(const T: Tb2XForm; const v: TVector2): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  854. var
  855.    tmp: TVector2;
  856. begin
  857.    tmp := Subtract(v, T.position);
  858.    Result := b2MulT(T.R, tmp);
  859. end;
  860. {$ENDIF}
  861. function b2Abs(const a: TVector2): TVector2; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  862. begin
  863.    Result.x := Abs(a.x);
  864.    Result.y := Abs(a.y);
  865. end;
  866. function b2Abs(const a: TMatrix22): TMatrix22; overload; {$IFDEF INLINE_AVAIL}inline;{$ENDIF}
  867. begin
  868.    Result.col1 := b2Abs(a.col1);
  869.    Result.col2 := b2Abs(a.col2);
  870. end;
  871. {$IFDEF HANDLE_EXCEPTION}
  872. constructor TPhysics2DException.Create(ErrorCode: TPhysics2DExceptionCode);
  873. begin
  874.    case ErrorCode of
  875.       ecDivByZero: ;
  876.    end;
  877. end;
  878. {$ENDIF}
  879. { TVector2 }
  880. {$IFDEF OP_OVERLOAD}
  881. function TVector2.IsValid: Boolean;
  882. begin
  883.    Result := UPhysics2DTypes.IsValid(x) and UPhysics2DTypes.IsValid(y);
  884. end;
  885. function TVector2.Length: Float;
  886. begin
  887.    Result := Sqrt(x * x + y * y);
  888. end;
  889. function TVector2.Normalize: Float;
  890. begin
  891.    Result := Length();
  892.  if Result < FLT_EPSILON then
  893.    begin
  894.       Result := 0.0;
  895.       Exit;
  896.    end;
  897.    x := x / Result;
  898.    y := y / Result;
  899. end;
  900. procedure TVector2.SetZero;
  901. begin
  902.    x := 0.0;
  903.    y := 0.0;
  904. end;
  905. procedure TVector2.SetNegative;
  906. begin
  907.    x := -x;
  908.    y := -y;
  909. end;
  910. procedure TVector2.SetValue(x, y: Float);
  911. begin
  912.    Self.x := x;
  913.    Self.y := y;
  914. end;
  915. function TVector2.SqrLength: Float;
  916. begin
  917.    Result := x * x + y * y;
  918. end;
  919. class function TVector2.From(const x, y: Float): TVector2;
  920. begin
  921.    Result.x := x;
  922.    Result.y := y;
  923. end;
  924. class operator TVector2.Negative(const AValue: TVector2): TVector2;
  925. begin
  926.    Result.x := -AValue.x;
  927.    Result.y := -AValue.y;
  928. end;
  929. class operator TVector2.Add(const Left, Right: TVector2): TVector2;
  930. begin
  931.    Result.x := Left.x + Right.x;
  932.    Result.y := Left.y + Right.y;
  933. end;
  934. class operator TVector2.Subtract(const Left, Right: TVector2): TVector2;
  935. begin
  936.    Result.x := Left.x - Right.x;
  937.    Result.y := Left.y - Right.y;
  938. end;
  939. class operator TVector2.Multiply(const Left: TVector2; const Right: Single): TVector2;
  940. begin
  941.    Result.x := Left.x * Right;
  942.    Result.y := Left.y * Right;
  943. end;
  944. class operator TVector2.Multiply(const Left: TVector2; const Right: Double): TVector2;
  945. begin
  946.    Result.x := Left.x * Right;
  947.    Result.y := Left.y * Right;
  948. end;
  949. class operator TVector2.Multiply(const Left: TVector2; const Right: Extended): TVector2;
  950. begin
  951.    Result.x := Left.x * Right;
  952.    Result.y := Left.y * Right;
  953. end;
  954. class operator TVector2.Multiply(const Left: Single; const Right: TVector2): TVector2;
  955. begin
  956.    Result.x := Left * Right.x;
  957.    Result.y := Left * Right.y;
  958. end;
  959. class operator TVector2.Multiply(const Left: Double; const Right: TVector2): TVector2;
  960. begin
  961.    Result.x := Left * Right.x;
  962.    Result.y := Left * Right.y;
  963. end;
  964. class operator TVector2.Multiply(const Left: Extended; const Right: TVector2): TVector2;
  965. begin
  966.    Result.x := Left * Right.x;
  967.    Result.y := Left * Right.y;
  968. end;
  969. class operator TVector2.Divide(const Left: TVector2; const Right: Single): TVector2;
  970. begin
  971.    Result.x := Left.x / Right;
  972.    Result.y := Left.y / Right;
  973. end;
  974. class operator TVector2.Divide(const Left: TVector2; const Right: Double): TVector2;
  975. begin
  976.    Result.x := Left.x / Right;
  977.    Result.y := Left.y / Right;
  978. end;
  979. class operator TVector2.Divide(const Left: TVector2; const Right: Extended): TVector2;
  980. begin
  981.    Result.x := Left.x / Right;
  982.    Result.y := Left.y / Right;
  983. end;
  984. procedure TVector2.AddBy(const Operand: TVector2);
  985. begin
  986.    x := x + Operand.x;
  987.    y := y + Operand.y;
  988. end;
  989. procedure TVector2.SubtractBy(const Operand: TVector2);
  990. begin
  991.    x := x - Operand.x;
  992.    y := y - Operand.y;
  993. end;
  994. procedure TVector2.MultiplyBy(const Operand: Single);
  995. begin
  996.    x := x * Operand;
  997.    y := y * Operand;
  998. end;
  999. procedure TVector2.MultiplyBy(const Operand: Double);
  1000. begin
  1001.    x := x * Operand;
  1002.    y := y * Operand;
  1003. end;
  1004. procedure TVector2.MultiplyBy(const Operand: Extended);
  1005. begin
  1006.    x := x * Operand;
  1007.    y := y * Operand;
  1008. end;
  1009. procedure TVector2.DivideBy(const Operand: Single);
  1010. begin
  1011.    x := x / Operand;
  1012.    y := y / Operand;
  1013. end;
  1014. procedure TVector2.DivideBy(const Operand: Double);
  1015. begin
  1016.    x := x / Operand;
  1017.    y := y / Operand;
  1018. end;
  1019. procedure TVector2.DivideBy(const Operand: Extended);
  1020. begin
  1021.    x := x / Operand;
  1022.    y := y / Operand;
  1023. end;
  1024. {$ENDIF}
  1025. { TMatrix22 }
  1026. {$IFDEF OP_OVERLOAD}
  1027. procedure TMatrix22.SetIdentity;
  1028. begin
  1029.  col1.x := 1.0;
  1030.    col2.x := 0.0;
  1031.  col1.y := 0.0;
  1032.    col2.y := 1.0;
  1033. end;
  1034. procedure TMatrix22.SetZero;
  1035. begin
  1036.  col1.x := 0.0;
  1037.    col2.x := 0.0;
  1038.  col1.y := 0.0;
  1039.    col2.y := 0.0;
  1040. end;
  1041. procedure TMatrix22.SetValue(const _col1, _col2: TVector2);
  1042. begin
  1043.    col1 := _col1;
  1044.    col2 := _col2;
  1045. end;
  1046. procedure TMatrix22.SetValue(angle: Float);
  1047. var
  1048.    c, s: Float;
  1049. begin
  1050.     SinCos(angle, s, c);
  1051. col1.x := c;
  1052.     col2.x := -s;
  1053. col1.y := s;
  1054.     col2.y := c;
  1055. end;
  1056. function TMatrix22.Invert: TMatrix22;
  1057. var
  1058.    a, b, c, d, det: Float;
  1059. begin
  1060.     a := col1.x;
  1061.     b := col2.x;
  1062.     c := col1.y;
  1063.     d := col2.y;
  1064. det := a * d - b * c;
  1065.     {$IFDEF HANDLE_EXCEPTION}
  1066.     if IsZero(det) then
  1067.        raise TPhysics2DException.Create(ecDivByZero);
  1068.     {$ENDIF}
  1069. det := 1.0 / det;
  1070.     with Result do
  1071.     begin
  1072.        col1.x :=  det * d;
  1073.        col2.x := -det * b;
  1074.        col1.y := -det * c;
  1075.        col2.y :=  det * a;
  1076.     end;
  1077. end;
  1078. function TMatrix22.Solve(const b: TVector2): TVector2;
  1079. var
  1080.    a11, a12, a21, a22, det: Float;
  1081. begin
  1082. a11 := col1.x;
  1083.     a12 := col2.x;
  1084.     a21 := col1.y;
  1085.     a22 := col2.y;
  1086. det := a11 * a22 - a12 * a21;
  1087.     {$IFDEF HANDLE_EXCEPTION}
  1088.     if IsZero(det) then
  1089.        raise TPhysics2DException.Create(ecDivByZero);
  1090.     {$ENDIF}
  1091. det := 1.0 / det;
  1092. Result.x := det * (a22 * b.x - a12 * b.y);
  1093. Result.y := det * (a11 * b.y - a21 * b.x);
  1094. end;
  1095. class operator TMatrix22.Negative(const AValue: TMatrix22): TMatrix22;
  1096. begin
  1097.    with Result do
  1098.    begin
  1099.       col1.x := -AValue.col1.x;
  1100.       col1.y := -AValue.col1.y;
  1101.       col2.x := -AValue.col2.x;
  1102.       col2.y := -AValue.col2.y;
  1103.    end;
  1104. end;
  1105. class operator TMatrix22.Add(const Left, Right: TMatrix22): TMatrix22;
  1106. begin
  1107.    with Result do
  1108.    begin
  1109.       col1.x := Left.col1.x + Right.col1.x;
  1110.       col1.y := Left.col1.y + Right.col1.y;
  1111.       col2.x := Left.col2.x + Right.col2.x;
  1112.       col2.y := Left.col2.y + Right.col2.y;
  1113.    end;
  1114. end;
  1115. class operator TMatrix22.Subtract(const Left, Right: TMatrix22): TMatrix22;
  1116. begin
  1117.    with Result do
  1118.    begin
  1119.       col1.x := Left.col1.x - Right.col1.x;
  1120.       col1.y := Left.col1.y - Right.col1.y;
  1121.       col2.x := Left.col2.x - Right.col2.x;
  1122.       col2.y := Left.col2.y - Right.col2.y;
  1123.    end;
  1124. end;
  1125. {$ENDIF}
  1126. { Tb2XForm }
  1127. {$IFDEF OP_OVERLOAD}
  1128. procedure Tb2XForm.SetIdentity;
  1129. begin
  1130.    position.SetZero;
  1131.    R.SetIdentity;
  1132. end;
  1133. class function Tb2XForm.From(const position: TVector2; const R: TMatrix22): Tb2XForm;
  1134. begin
  1135.    Result.position := position;
  1136.    Result.R := R;
  1137. end;
  1138. {$ENDIF}
  1139. { Tb2Sweep }
  1140. {$IFDEF OP_OVERLOAD}
  1141. procedure Tb2Sweep.GetXForm(var xf: Tb2XForm; t: Float);
  1142. var
  1143.    alpha: Float;
  1144. begin
  1145.  if (1.0 - t0 > FLT_EPSILON) then
  1146.  begin
  1147.       alpha := (t - t0) / (1.0 - t0);
  1148.       xf.position := (1.0 - alpha) * c0 + alpha * c;
  1149.       xf.R.SetValue((1.0 - alpha) * a0 + alpha * a);
  1150.    end
  1151.    else
  1152.    begin
  1153.       // center = p + R * localCenter
  1154.       xf.position := c;
  1155.       xf.R.SetValue(a);
  1156.    end;
  1157.    // Shift to origin
  1158.    xf.position.SubtractBy(b2Mul(xf.R, localCenter));
  1159. end;
  1160. procedure Tb2Sweep.Advance(t: Float);
  1161. var
  1162.    alpha: Float;
  1163. begin
  1164.    if (t0 < t) and (t0 < 1.0 - FLT_EPSILON) then
  1165.    begin
  1166.       alpha := (t - t0) / (1.0 - t0);
  1167.       c0 := (1.0 - alpha) * c0 + alpha * c;
  1168.       a0 := (1.0 - alpha) * a0 + alpha * a;
  1169.       t0 := t;
  1170.    end;
  1171. end;
  1172. {$ENDIF}
  1173. end.