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

Delphi/CppBuilder

开发平台:

Delphi

  1.    // Find support vertex on poly2 for -normal.
  2.    index := 0;
  3.    minDot := FLT_MAX;
  4.    for i := 0 to poly2.GetVertexCount - 1 do
  5.    begin
  6.       dot := b2Dot(poly2.m_vertices[i], normal1);
  7.       if dot < minDot then
  8.       begin
  9.          minDot := dot;
  10.          index := i;
  11.       end;
  12.    end;
  13.    v1 := b2Mul(xf1, poly1.m_vertices[edge1]);
  14.    v2 := b2Mul(xf2, poly2.m_vertices[index]);
  15.    {$IFDEF OP_OVERLOAD}
  16.    Result := b2Dot(v2 - v1, normal1World);
  17.    {$ELSE}
  18.    Result := b2Dot(Subtract(v2, v1), normal1World);
  19.    {$ENDIF}
  20. end;
  21. // Find the max separation between poly1 and poly2 using edge normals from poly1.
  22. function FindMaxSeparation(var edgeIndex: Int32;
  23.    poly1, poly2: Tb2PolygonShape; const xf1, xf2: Tb2XForm): Float;
  24. var
  25.    i: Integer;
  26.    edge, prevEdge, nextEdge, bestEdge, increment: Int32;
  27.    d, dLocal1: TVector2;
  28.    maxDot, dot, s, sPrev, sNext, bestSeparation: Float;
  29. begin
  30.    // Vector pointing from the centroid of poly1 to the centroid of poly2.
  31.    {$IFDEF OP_OVERLOAD}
  32.    d := b2Mul(xf2, poly2.m_centroid) - b2Mul(xf1, poly1.m_centroid);
  33.    {$ELSE}
  34.    d := Subtract(b2Mul(xf2, poly2.m_centroid), b2Mul(xf1, poly1.m_centroid));
  35.    {$ENDIF}
  36.    dLocal1 := b2MulT(xf1.R, d);
  37.    // Find edge normal on poly1 that has the largest projection onto d.
  38.    edge := 0;
  39.    maxDot := -FLT_MAX;
  40.    for i := 0 to poly1.GetVertexCount - 1 do
  41.    begin
  42.       dot := b2Dot(poly1.m_normals[i], dLocal1);
  43.       if dot > maxDot then
  44.       begin
  45.          maxDot := dot;
  46.          edge := i;
  47.       end;
  48.    end;
  49.    // Get the separation for the edge normal.
  50.    s := EdgeSeparation(poly1, poly2, xf1, xf2, edge);
  51.    if s > 0.0 then
  52.    begin
  53.       Result := s;
  54.       Exit;
  55.    end;
  56.    // Check the separation for the previous edge normal.
  57.    if edge - 1 >= 0 then
  58.       prevEdge := edge - 1
  59.    else
  60.       prevEdge := poly1.GetVertexCount - 1;
  61.    sPrev := EdgeSeparation(poly1, poly2, xf1, xf2, prevEdge);
  62.    if sPrev > 0.0 then
  63.    begin
  64.       Result := sPrev;
  65.       Exit;
  66.    end;
  67.    // Check the separation for the next edge normal.
  68.    if edge + 1 < poly1.GetVertexCount then
  69.       nextEdge := edge + 1
  70.    else
  71.       nextEdge := 0;
  72.    sNext := EdgeSeparation(poly1, poly2, xf1, xf2, nextEdge);
  73.    if sNext > 0.0 then
  74.    begin
  75.       Result := sNext;
  76.       Exit;
  77.    end;
  78.    // Find the best edge and the search direction.
  79.    if (sPrev > s) and (sPrev > sNext) then
  80.    begin
  81.       increment := -1;
  82.       bestEdge := prevEdge;
  83.       bestSeparation := sPrev;
  84.    end
  85.    else if sNext > s then
  86.    begin
  87.       increment := 1;
  88.       bestEdge := nextEdge;
  89.       bestSeparation := sNext;
  90.    end
  91.    else
  92.    begin
  93.       edgeIndex := edge;
  94.       Result := s;
  95.       Exit;
  96.    end;
  97.    // Perform a local search for the best edge normal.
  98.    while True do
  99.    begin
  100.       if increment = -1 then
  101.       begin
  102.          if bestEdge - 1 >= 0 then
  103.             edge := bestEdge - 1
  104.          else
  105.             edge := poly1.GetVertexCount - 1;
  106.       end
  107.       else
  108.          if bestEdge + 1 < poly1.GetVertexCount then
  109.             edge := bestEdge + 1
  110.          else
  111.             edge := 0;
  112.       s := EdgeSeparation(poly1, poly2, xf1, xf2, edge);
  113.       if s > 0.0 then
  114.       begin
  115.          Result := s;
  116.          Exit;
  117.       end;
  118.       if s > bestSeparation then
  119.       begin
  120.          bestEdge := edge;
  121.          bestSeparation := s;
  122.       end
  123.       else
  124.          Break;
  125.    end;
  126.    edgeIndex := bestEdge;
  127.    Result := bestSeparation;
  128. end;
  129. procedure FindIncidentEdge(c: PClipVertices; poly1, poly2: Tb2PolygonShape;
  130.    const xf1, xf2: Tb2XForm; edge1: Int32);
  131. var
  132.    i: Integer;
  133.    index, i1, i2: Int32;
  134.    normal1: TVector2;
  135.    minDot, dot: Float;
  136. begin
  137.    //b2Assert(0 <= edge1 && edge1 < poly1.GetVertexCount);
  138.    // Get the normal of the reference edge in poly2's frame.
  139.    normal1 := b2MulT(xf2.R, b2Mul(xf1.R, poly1.m_normals[edge1]));
  140.    // Find the incident edge on poly2.
  141.    index := 0;
  142.    minDot := FLT_MAX;
  143.    for i := 0 to poly2.GetVertexCount - 1 do
  144.    begin
  145.       dot := b2Dot(normal1, poly2.m_normals[i]);
  146.       if dot < minDot then
  147.       begin
  148.          minDot := dot;
  149.          index := i;
  150.       end;
  151.    end;
  152.    // Build the clip vertices for the incident edge.
  153.    i1 := index;
  154.    if i1 + 1 < poly2.GetVertexCount then
  155.       i2 := i1 + 1
  156.    else
  157.       i2 := 0;
  158.    c^[0].v := b2Mul(xf2, poly2.m_vertices[i1]);
  159.    c^[0].id.referenceEdge := edge1;
  160.    c^[0].id.incidentEdge := i1;
  161.    c^[0].id.incidentVertex := 0;
  162.    c^[1].v := b2Mul(xf2, poly2.m_vertices[i2]);
  163.    c^[1].id.referenceEdge := edge1;
  164.    c^[1].id.incidentEdge := i2;
  165.    c^[1].id.incidentVertex := 1;
  166. end;
  167. // Find edge normal of max separation on A - return if separating axis is found
  168. // Find edge normal of max separation on B - return if separation axis is found
  169. // Choose reference edge as min(minA, minB)
  170. // Find incident edge
  171. // Clip
  172. // The normal points from 1 to 2
  173. procedure b2CollidePolygons(var manifold: Tb2Manifold;
  174.    polyA, polyB: Tb2PolygonShape; xfA, xfB: Tb2XForm);
  175. var
  176.    i: Integer;
  177.    edgeA, edgeB: Int32;
  178.    edge1: Int32; // reference edge
  179.    flip: UInt8;
  180.    separationA, separationB: Float;
  181.    poly1, poly2: Tb2PolygonShape; // reference poly and incident poly
  182.    xf1, xf2: Tb2XForm;
  183.    k_relativeTol, k_absoluteTol: Float;
  184.    incidentEdge, clipPoints1, clipPoints2: TClipVertices;
  185.    v11, v12, sideNormal, frontNormal: TVector2;
  186.    frontOffset, sideOffset1, sideOffset2: Float;
  187.    np: Int32; // Clip incident edge against extruded edge1 side edges.
  188.    pointCount: Int32;
  189.    _separation: Float;
  190. begin
  191.    manifold.pointCount := 0;
  192.    separationA := FindMaxSeparation(edgeA, polyA, polyB, xfA, xfB);
  193.    if separationA > 0.0 then
  194.       Exit;
  195.    edgeB := 0;
  196.    separationB := FindMaxSeparation(edgeB, polyB, polyA, xfB, xfA);
  197.    if separationB > 0.0 then
  198.       Exit;
  199.    k_relativeTol := 0.98;
  200.    k_absoluteTol := 0.001;
  201.    // TODO_ERIN use "radius" of poly for absolute tolerance.
  202.    if separationB > k_relativeTol * separationA + k_absoluteTol then
  203.    begin
  204.       poly1 := polyB;
  205.       poly2 := polyA;
  206.       xf1 := xfB;
  207.       xf2 := xfA;
  208.       edge1 := edgeB;
  209.       flip := 1;
  210.    end
  211.    else
  212.    begin
  213.       poly1 := polyA;
  214.       poly2 := polyB;
  215.       xf1 := xfA;
  216.       xf2 := xfB;
  217.       edge1 := edgeA;
  218.       flip := 0;
  219.    end;
  220.    FindIncidentEdge(@incidentEdge, poly1, poly2, xf1, xf2, edge1);
  221.    v11 := poly1.m_vertices[edge1];
  222.    if edge1 + 1 < poly1.GetVertexCount then
  223.       v12 := poly1.m_vertices[edge1+1]
  224.    else
  225.       v12 := poly1.m_vertices[0];
  226.    {$IFDEF OP_OVERLOAD}
  227.    sideNormal := b2Mul(xf1.R, v12 - v11);
  228.    sideNormal.Normalize;
  229.    {$ELSE}
  230.    sideNormal := b2Mul(xf1.R, Subtract(v12, v11));
  231.    Normalize(sideNormal);
  232.    {$ENDIF}
  233.    frontNormal := b2Cross(sideNormal, 1.0);
  234.    v11 := b2Mul(xf1, v11);
  235.    v12 := b2Mul(xf1, v12);
  236.    frontOffset := b2Dot(frontNormal, v11);
  237.    sideOffset1 := -b2Dot(sideNormal, v11);
  238.    sideOffset2 := b2Dot(sideNormal, v12);
  239.    // Clip to box side 1
  240.    {$IFDEF OP_OVERLOAD}
  241.    np := ClipSegmentToLine(@clipPoints1, @incidentEdge, -sideNormal, sideOffset1);
  242.    {$ELSE}
  243.    np := ClipSegmentToLine(@clipPoints1, @incidentEdge, Negative(sideNormal), sideOffset1);
  244.    {$ENDIF}
  245.    if np < 2 then
  246.       Exit;
  247.    // Clip to negative box side 1
  248.    np := ClipSegmentToLine(@clipPoints2, @clipPoints1, sideNormal, sideOffset2);
  249.    if np < 2 then
  250.       Exit;
  251.    // Now clipPoints2 contains the clipped points.
  252.    if flip <> 0 then
  253.       {$IFDEF OP_OVERLOAD}
  254.       manifold.normal := -frontNormal
  255.       {$ELSE}
  256.       manifold.normal := Negative(frontNormal)
  257.       {$ENDIF}
  258.    else
  259.       manifold.normal := frontNormal;
  260.    pointCount := 0;
  261.    for i := 0 to b2_maxManifoldPoints - 1 do
  262.    begin
  263.       _separation := b2Dot(frontNormal, clipPoints2[i].v) - frontOffset;
  264.       if _separation <= 0.0 then
  265.          with manifold.points[pointCount] do
  266.          begin
  267.             separation := _separation;
  268.             localPoint1 := b2MulT(xfA, clipPoints2[i].v);
  269.             localPoint2 := b2MulT(xfB, clipPoints2[i].v);
  270.             id := clipPoints2[i].id;
  271.             id.flip := flip;
  272.             Inc(pointCount);
  273.          end;
  274.    end;
  275.    manifold.pointCount := pointCount;
  276. end;
  277. { Tb2CircleDef }
  278. constructor Tb2CircleDef.Create;
  279. begin
  280.    inherited Create;
  281.    ShapeType := e_circleShape;
  282.    SetZero(localPosition);
  283.  radius := 1.0;
  284. end;
  285. { Tb2CircleShape }
  286. constructor Tb2CircleShape.Create(def: Tb2ShapeDef);
  287. var
  288.    circleDef: Tb2CircleDef;
  289. begin
  290.    inherited Create(def);
  291.    //b2Assert(def->type == e_circleShape);
  292.    circleDef := Tb2CircleDef(def);
  293.    m_type := e_circleShape;
  294.    m_localPosition := circleDef.localPosition;
  295.    m_radius := circleDef.radius;
  296. end;
  297. procedure Tb2CircleShape.UpdateSweepRadius(const center: TVector2);
  298. begin
  299.    // Update the sweep radius (maximum radius) as measured from a local center point.
  300.    {$IFDEF OP_OVERLOAD}
  301.  m_sweepRadius := (m_localPosition - center).Length() + m_radius - b2_toiSlop;
  302.    {$ELSE}
  303.    m_sweepRadius := Length(Subtract(m_localPosition, center)) + m_radius - b2_toiSlop;
  304.    {$ENDIF}
  305. end;
  306. function Tb2CircleShape.TestPoint(const transform: Tb2XForm; const p: TVector2): Boolean;
  307. var
  308.    center, d: TVector2;
  309. begin
  310.    {$IFDEF OP_OVERLOAD}
  311.    center := transform.position + b2Mul(transform.R, m_localPosition);
  312.    d := p - center;
  313.    {$ELSE}
  314.    center := Add(transform.position, b2Mul(transform.R, m_localPosition));
  315.    d := Subtract(p, center);
  316.    {$ENDIF}
  317.  Result := b2Dot(d, d) <= m_radius * m_radius;
  318. end;
  319. function Tb2CircleShape.TestSegment(const xf: Tb2XForm; var lambda: Float;
  320.    var normal: TVector2; const segment: Tb2Segment; maxLambda: Float): Boolean;
  321. var
  322.    position, s, r: TVector2;
  323.    b, c, rr, sigma, a: Float;
  324. begin
  325.    {$IFDEF OP_OVERLOAD}
  326.    position := xf.position + b2Mul(xf.R, m_localPosition);
  327.    s := segment.p1 - position;
  328.    {$ELSE}
  329.    position := Add(xf.position, b2Mul(xf.R, m_localPosition));
  330.    s := Subtract(segment.p1, position);
  331.    {$ENDIF}
  332.    b := b2Dot(s, s) - m_radius * m_radius;
  333.    // Does the segment start inside the circle?
  334.    if b < 0.0 then
  335.    begin
  336.       Result := False;
  337.       Exit;
  338.    end;
  339.    // Solve quadratic equation.
  340.    {$IFDEF OP_OVERLOAD}
  341.    r := segment.p2 - segment.p1;
  342.    {$ELSE}
  343.    r := Subtract(segment.p2, segment.p1);
  344.    {$ENDIF}
  345.    c :=  b2Dot(s, r);
  346.    rr := b2Dot(r, r);
  347.    sigma := c * c - rr * b;
  348.    // Check for negative discriminant and short segment.
  349.    if (sigma < 0.0) or (rr < FLT_EPSILON) then
  350.    begin
  351.       Result := False;
  352.       Exit;
  353.    end;
  354.    // Find the point of intersection of the line with the circle.
  355.    a := -(c + Sqrt(sigma));
  356.    // Is the intersection point on the segment?
  357.    if (0.0 <= a) and (a <= maxLambda * rr) then
  358.    begin
  359.       a := a / rr;
  360.       lambda := a;
  361.       {$IFDEF OP_OVERLOAD}
  362.       normal := s + a * r;
  363.       normal.Normalize;
  364.       {$ELSE}
  365.       normal := Add(s, Multiply(r, a));
  366.       Normalize(normal);
  367.       {$ENDIF}
  368.       Result := True;
  369.    end
  370.    else
  371.       Result := False;
  372. end;
  373. procedure Tb2CircleShape.ComputeAABB(var aabb: Tb2AABB; const xf: Tb2XForm);
  374. var
  375.    p: TVector2;
  376. begin
  377.    {$IFDEF OP_OVERLOAD}
  378.    p := xf.position + b2Mul(xf.R, m_localPosition);
  379.    aabb.lowerBound.SetValue(p.x - m_radius, p.y - m_radius);
  380.    aabb.upperBound.SetValue(p.x + m_radius, p.y + m_radius);
  381.    {$ELSE}
  382.    p := Add(xf.position, b2Mul(xf.R, m_localPosition));
  383.    SetValue(aabb.lowerBound, p.x - m_radius, p.y - m_radius);
  384.    SetValue(aabb.upperBound, p.x + m_radius, p.y + m_radius);
  385.    {$ENDIF}
  386. end;
  387. procedure Tb2CircleShape.ComputeSweptAABB(var aabb: Tb2AABB; const xf1, xf2: Tb2XForm);
  388. var
  389.    p1, p2, lower, upper: TVector2;
  390. begin
  391.    {$IFDEF OP_OVERLOAD}
  392.    p1 := xf1.position + b2Mul(xf1.R, m_localPosition);
  393.    p2 := xf2.position + b2Mul(xf2.R, m_localPosition);
  394.    {$ELSE}
  395.    p1 := Add(xf1.position, b2Mul(xf1.R, m_localPosition));
  396.    p2 := Add(xf2.position, b2Mul(xf2.R, m_localPosition));
  397.    {$ENDIF}
  398.    lower := b2Min(p1, p2);
  399.    upper := b2Max(p1, p2);
  400.    {$IFDEF OP_OVERLOAD}
  401.    aabb.lowerBound.SetValue(lower.x - m_radius, lower.y - m_radius);
  402.    aabb.upperBound.SetValue(upper.x + m_radius, upper.y + m_radius);
  403.    {$ELSE}
  404.    SetValue(aabb.lowerBound, lower.x - m_radius, lower.y - m_radius);
  405.    SetValue(aabb.upperBound, upper.x + m_radius, upper.y + m_radius);
  406.    {$ENDIF}
  407. end;
  408. procedure Tb2CircleShape.ComputeMass(var massData: Tb2MassData);
  409. begin
  410.    massData.mass := m_density * Pi * m_radius * m_radius;
  411.    massData.center := m_localPosition;
  412.    // inertia about the local origin
  413.    massData.I := massData.mass * (0.5 * m_radius * m_radius +
  414.       b2Dot(m_localPosition, m_localPosition));
  415. end;
  416. { Tb2PolygonDef }
  417. constructor Tb2PolygonDef.Create;
  418. begin
  419.    inherited Create;
  420.  ShapeType := e_polygonShape;
  421.  vertexCount := 0;
  422. end;
  423. procedure Tb2PolygonDef.SetAsBox(hx, hy: Float);
  424. begin
  425.    vertexCount := 4;
  426.    {$IFDEF OP_OVERLOAD}
  427.    vertices[0].SetValue(-hx, -hy);
  428.    vertices[1].SetValue(hx, -hy);
  429.    vertices[2].SetValue(hx, hy);
  430.    vertices[3].SetValue(-hx, hy);
  431.    {$ELSE}
  432.    SetValue(vertices[0], -hx, -hy);
  433.    SetValue(vertices[1], hx, -hy);
  434.    SetValue(vertices[2], hx, hy);
  435.    SetValue(vertices[3], -hx, hy);
  436.    {$ENDIF}
  437. end;
  438. procedure Tb2PolygonDef.SetAsBox(hx, hy: Float; const center: TVector2; angle: Float);
  439. var
  440.    i: Integer;
  441.    xf: Tb2XForm;
  442. begin
  443.    SetAsBox(hx, hy);
  444.    xf.position := center;
  445.    {$IFDEF OP_OVERLOAD}
  446.    xf.R.SetValue(angle);
  447.    {$ELSE}
  448.    SetValue(xf.R, angle);
  449.    {$ENDIF}
  450.    for i := 0 to vertexCount - 1 do
  451.       vertices[i] := b2Mul(xf, vertices[i]);
  452. end;
  453. { Tb2PolygonShape }
  454. constructor Tb2PolygonShape.Create(const def: Tb2ShapeDef);
  455. var
  456.    i: Integer;
  457.    i2: Int32;
  458.    poly: Tb2PolygonDef;
  459.    edge, n1, n2, v, d: TVector2;
  460.    A: TMatrix22;
  461. begin
  462.    inherited Create(def);
  463.    pm_vertices := @m_vertices[0];
  464.    pm_normals := @m_normals[0];
  465.    pm_coreVertices := @m_coreVertices[0];
  466.    //b2Assert(def.type == e_polygonShape);
  467.    m_type := e_polygonShape;
  468.    poly := Tb2PolygonDef(def);
  469.    // Get the vertices transformed into the body frame.
  470.    m_vertexCount := poly.vertexCount;
  471.    //b2Assert(3 <= m_vertexCount && m_vertexCount <= b2_maxPolygonVertices);
  472.    // Copy vertices.
  473.    m_vertices := poly.vertices;
  474.    // Compute normals. Ensure the edges have non-zero length.
  475.    for i := 0 to m_vertexCount - 1 do
  476.    begin
  477.       if i + 1 < m_vertexCount then
  478.          i2 := i + 1
  479.       else
  480.          i2 := 0;      
  481.       {$IFDEF OP_OVERLOAD}
  482.       edge := m_vertices[i2] - m_vertices[i];
  483.       //b2Assert(edge.LengthSquared() > B2_FLT_EPSILON * B2_FLT_EPSILON);
  484.       m_normals[i] := b2Cross(edge, 1.0);
  485.       m_normals[i].Normalize;
  486.       {$ELSE}
  487.       edge := Subtract(m_vertices[i2], m_vertices[i]);
  488.       //b2Assert(edge.LengthSquared() > B2_FLT_EPSILON * B2_FLT_EPSILON);
  489.       m_normals[i] := b2Cross(edge, 1.0);
  490.       Normalize(m_normals[i]);
  491.       {$ENDIF}
  492.    end;
  493.    // Compute the polygon centroid.
  494.    m_centroid := ComputeCentroid(poly.vertices, poly.vertexCount);
  495.    // Compute the oriented bounding box.
  496.    ComputeOBB(m_obb, m_vertices, m_vertexCount);
  497.    // Create core polygon shape by shifting edges inward.
  498.    // Also compute the min/max radius for CCD.
  499.    for i := 0 to m_vertexCount - 1 do
  500.    begin
  501.       if i - 1 >= 0 then
  502.          i2 := i - 1
  503.       else
  504.          i2 := m_vertexCount - 1; 
  505.       n1 := m_normals[i2];
  506.       n2 := m_normals[i];
  507.       {$IFDEF OP_OVERLOAD}
  508.       v := m_vertices[i] - m_centroid;
  509.       {$ELSE}
  510.       v := Subtract(m_vertices[i], m_centroid);
  511.       {$ENDIF}
  512.       d.x := b2Dot(n1, v) - b2_toiSlop;
  513.       d.y := b2Dot(n2, v) - b2_toiSlop;
  514.       // Shifting the edge inward by b2_toiSlop should
  515.       // not cause the plane to pass the centroid.
  516.       // Your shape has a radius/extent less than b2_toiSlop.
  517.       //b2Assert(d.x >= 0.0f);
  518.       //b2Assert(d.y >= 0.0f);
  519.       A.col1.x := n1.x;
  520.       A.col2.x := n1.y;
  521.       A.col1.y := n2.x; 
  522.       A.col2.y := n2.y;
  523.       {$IFDEF OP_OVERLOAD}
  524.       m_coreVertices[i] := A.Solve(d) + m_centroid;
  525.       {$ELSE}
  526.       m_coreVertices[i] := Add(Solve(A, d), m_centroid);
  527.       {$ENDIF}
  528.    end;
  529. end;
  530. procedure Tb2PolygonShape.UpdateSweepRadius(const center: TVector2);
  531. var
  532.    i: Integer;
  533.    d: TVector2;
  534. begin
  535.    // Update the sweep radius (maximum radius) as measured from a local center point.
  536.    m_sweepRadius := 0.0;
  537.    for i := 0 to m_vertexCount - 1 do
  538.    begin
  539.       {$IFDEF OP_OVERLOAD}
  540.       d := m_coreVertices[i] - center;
  541.       m_sweepRadius := b2Max(m_sweepRadius, d.Length());
  542.       {$ELSE}
  543.       d := Subtract(m_coreVertices[i], center);
  544.       m_sweepRadius := b2Max(m_sweepRadius, Length(d));
  545.       {$ENDIF}
  546.    end;
  547. end;
  548. function Tb2PolygonShape.TestPoint(const transform: Tb2XForm;
  549.    const p: TVector2): Boolean;
  550. var
  551.    i: Integer;
  552.    pLocal: TVector2;
  553. begin
  554.    {$IFDEF OP_OVERLOAD}
  555.    pLocal := b2MulT(transform.R, p - transform.position);
  556.    {$ELSE}
  557.    pLocal := b2MulT(transform.R, Subtract(p, transform.position));
  558.    {$ENDIF}
  559.    for i := 0 to m_vertexCount - 1 do
  560.       {$IFDEF OP_OVERLOAD}
  561.       if b2Dot(m_normals[i], pLocal - m_vertices[i]) > 0.0 then
  562.       {$ELSE}
  563.       if b2Dot(m_normals[i], Subtract(pLocal, m_vertices[i])) > 0.0 then
  564.       {$ENDIF}
  565.       begin
  566.          Result := False;
  567.          Exit;
  568.       end;
  569.    Result := True;
  570. end;
  571. function Tb2PolygonShape.TestSegment(const xf: Tb2XForm; var lambda: Float;
  572.    var normal: TVector2; const segment: Tb2Segment; maxLambda: Float): Boolean;
  573. var
  574.    lower, upper: Float;
  575.    p1, p2, d: TVector2;
  576.    index: Int32;
  577.    i: Integer;
  578.    numerator, denominator: Float;
  579. begin
  580.    lower := 0.0;
  581.    upper := maxLambda;
  582.    {$IFDEF OP_OVERLOAD}
  583.    p1 := b2MulT(xf.R, segment.p1 - xf.position);
  584.    p2 := b2MulT(xf.R, segment.p2 - xf.position);
  585.    d := p2 - p1;
  586.    {$ELSE}
  587.    p1 := b2MulT(xf.R, Subtract(segment.p1, xf.position));
  588.    p2 := b2MulT(xf.R, Subtract(segment.p2, xf.position));
  589.    d := Subtract(p2, p1);
  590.    {$ENDIF}
  591.    index := -1;
  592.    for i := 0 to m_vertexCount - 1 do
  593.    begin
  594.       // p := p1 + a * d
  595.       // dot(normal, p - v) := 0
  596.       // dot(normal, p1 - v) + a * dot(normal, d) := 0
  597.       {$IFDEF OP_OVERLOAD}
  598.       numerator := b2Dot(m_normals[i], m_vertices[i] - p1);
  599.       {$ELSE}
  600.       numerator := b2Dot(m_normals[i], Subtract(m_vertices[i], p1));
  601.       {$ENDIF}
  602.       denominator := b2Dot(m_normals[i], d);
  603.       // Note: we want this predicate without division:
  604.       // lower < numerator / denominator, where denominator < 0
  605.       // Since denominator < 0, we have to flip the inequality:
  606.       // lower < numerator / denominator <==> denominator * lower > numerator.
  607.       if (denominator < 0.0) and (numerator < lower * denominator) then
  608.       begin
  609.          // Increase lower.
  610.          // The segment enters this half-space.
  611.          lower := numerator / denominator;
  612.          index := i;
  613.       end
  614.       else if (denominator > 0.0) and (numerator < upper * denominator) then
  615.       begin
  616.          // Decrease upper.
  617.          // The segment exits this half-space.
  618.          upper := numerator / denominator;
  619.       end;
  620.       if upper < lower then
  621.       begin
  622.          Result := False;
  623.          Exit;
  624.       end;
  625.    end;
  626.    //b2Assert(0.0f <= lower && lower <= maxLambda);
  627.    if index >= 0 then
  628.    begin
  629.       lambda := lower;
  630.       normal := b2Mul(xf.R, m_normals[index]);
  631.       Result := True;
  632.    end
  633.    else
  634.       Result := False;
  635. end;
  636. procedure Tb2PolygonShape.ComputeAABB(var aabb: Tb2AABB; const xf: Tb2XForm);
  637. var
  638.    R, absR: TMatrix22;
  639.    h, position: TVector2;
  640. begin
  641.    R := b2Mul(xf.R, m_obb.R);
  642.    absR := b2Abs(R);
  643.    h := b2Mul(absR, m_obb.extents);
  644.    {$IFDEF OP_OVERLOAD}
  645.    position := xf.position + b2Mul(xf.R, m_obb.center);
  646.    aabb.lowerBound := position - h;
  647.    aabb.upperBound := position + h;
  648.    {$ELSE}
  649.    position := Add(xf.position, b2Mul(xf.R, m_obb.center));
  650.    aabb.lowerBound := Subtract(position, h);
  651.    aabb.upperBound := Add(position, h);
  652.    {$ENDIF}
  653. end;
  654. procedure Tb2PolygonShape.ComputeMass(var massData: Tb2MassData);
  655. const
  656.    k_inv3 = 1.0 / 3.0;
  657. var
  658.    i: Integer;
  659.    center, pRef, p1, p2, p3, e1, e2: TVector2;
  660.    area, inertia: Float;
  661.    D, triangleArea: Float;
  662.    px, py, ex1, ey1, ex2, ey2: Float;
  663.    intx2, inty2: Float;
  664. begin
  665.    // Polygon mass, centroid, and inertia.
  666.    // Let rho be the polygon density in mass per unit area.
  667.    // Then:
  668.    // mass = rho * int(dA)
  669.    // centroid.x = (1/mass) * rho * int(x * dA)
  670.    // centroid.y = (1/mass) * rho * int(y * dA)
  671.    // I = rho * int((x*x + y*y) * dA)
  672.    //
  673.    // We can compute these integrals by summing all the integrals
  674.    // for each triangle of the polygon. To evaluate the integral
  675.    // for a single triangle, we make a change of variables to
  676.    // the (u,v) coordinates of the triangle:
  677.    // x = x0 + e1x * u + e2x * v
  678.    // y = y0 + e1y * u + e2y * v
  679.    // where 0 <= u && 0 <= v && u + v <= 1.
  680.    //
  681.    // We integrate u from [0,1-v] and then v from [0,1].
  682.    // We also need to use the Jacobian of the transformation:
  683.    // D = cross(e1, e2)
  684.    //
  685.    // Simplification: triangle centroid = (1/3) * (p1 + p2 + p3)
  686.    //
  687.    // The rest of the derivation is handled by computer algebra.
  688.    //b2Assert(m_vertexCount >= 3);
  689.    SetZero(center);
  690.    area := 0.0;
  691.    inertia := 0.0;
  692.    // pRef is the reference point for forming triangles.
  693.    // It's location doesn't change the result (except for rounding error).
  694.    SetZero(pRef);
  695.    for i := 0 to m_vertexCount - 1 do
  696.    begin
  697.       // Triangle vertices.
  698.       p1 := pRef;
  699.       p2 := m_vertices[i];
  700.       if (i + 1 < m_vertexCount) then
  701.          p3 := m_vertices[i + 1]
  702.       else
  703.          p3 := m_vertices[0];
  704.       {$IFDEF OP_OVERLOAD}
  705.       e1 := p2 - p1;
  706.       e2 := p3 - p1;
  707.       {$ELSE}
  708.       e1 := Subtract(p2, p1);
  709.       e2 := Subtract(p3, p1);
  710.       {$ENDIF}
  711.       D := b2Cross(e1, e2);
  712.       triangleArea := 0.5 * D;
  713.       area := area + triangleArea;
  714.       // Area weighted centroid
  715.       {$IFDEF OP_OVERLOAD}
  716.       center.AddBy(triangleArea * k_inv3 * (p1 + p2 + p3));
  717.       {$ELSE}
  718.       AddBy(center, Multiply(Add(p1, p2, p3), triangleArea * k_inv3));
  719.       {$ENDIF}
  720.       px := p1.x;
  721.       py := p1.y;
  722.       ex1 := e1.x;
  723.       ey1 := e1.y;
  724.       ex2 := e2.x;
  725.       ey2 := e2.y;
  726.       intx2 := k_inv3 * (0.25 * (ex1 * ex1 + ex2 * ex1 + ex2 * ex2) +
  727.          (px * ex1 + px * ex2)) + 0.5 * px * px;
  728.       inty2 := k_inv3 * (0.25 * (ey1 * ey1 + ey2 * ey1 + ey2 * ey2) +
  729.          (py * ey1 + py * ey2)) + 0.5 * py * py;
  730.       inertia := inertia + D * (intx2 + inty2);
  731.    end;
  732.    // Total mass
  733.    massData.mass := m_density * area;
  734.    // Center of mass
  735.    //b2Assert(area > B2_FLT_EPSILON);
  736.    {$IFDEF OP_OVERLOAD}
  737.    center.DivideBy(area);
  738.    {$ELSE}
  739.    DivideBy(center, area);
  740.    {$ENDIF}
  741.    massData.center := center;
  742.    // Inertia tensor relative to the local origin.
  743.    massData.I := m_density * inertia;
  744. end;
  745. procedure Tb2PolygonShape.ComputeSweptAABB(var aabb: Tb2AABB; const xf1,
  746.    xf2: Tb2XForm);
  747. var
  748.    aabb1, aabb2: Tb2AABB;
  749. begin
  750.    ComputeAABB(aabb1, xf1);
  751.    ComputeAABB(aabb2, xf2);
  752.    aabb.lowerBound := b2Min(aabb1.lowerBound, aabb2.lowerBound);
  753.    aabb.upperBound := b2Max(aabb1.upperBound, aabb2.upperBound);
  754. end;
  755. function Tb2PolygonShape.GetFirstVertex(const xf: Tb2XForm): TVector2;
  756. begin
  757.    Result := b2Mul(xf, m_coreVertices[0]);
  758. end;
  759. function Tb2PolygonShape.Centroid(const xf: Tb2XForm): TVector2;
  760. begin
  761.    Result := b2Mul(xf, m_centroid);
  762. end;
  763. function Tb2PolygonShape.Support(const xf: Tb2XForm; const d: TVector2): TVector2;
  764. var
  765.    i: Integer;
  766.    dLocal: TVector2;
  767.    bestIndex: Int32;
  768.    bestValue, value: Float;
  769. begin
  770.    dLocal := b2MulT(xf.R, d);
  771.    bestIndex := 0;
  772.    bestValue := b2Dot(m_coreVertices[0], dLocal);
  773.    for i := 1 to m_vertexCount - 1 do
  774.    begin
  775.       value := b2Dot(m_coreVertices[i], dLocal);
  776.       if value > bestValue then
  777.       begin
  778.          bestIndex := i;
  779.          bestValue := value;
  780.       end;
  781.    end;
  782.    Result := b2Mul(xf, m_coreVertices[bestIndex]);
  783. end;
  784. { Tb2CircleContact }
  785. constructor Tb2CircleContact.Create(shape1, shape2: Tb2Shape);
  786. begin
  787.    inherited Create(shape1, shape2);
  788.    //b2Assert(m_shape1->GetType() == e_circleShape);
  789.    //b2Assert(m_shape2->GetType() == e_circleShape);
  790.    m_manifold.pointCount := 0;
  791.    m_manifold.points[0].normalImpulse := 0.0;
  792.    m_manifold.points[0].tangentImpulse := 0.0;
  793. end;
  794. procedure Tb2CircleContact.Evaluate(listener: Tb2ContactListener);
  795. var
  796.    b1, b2: Tb2Body;
  797.    m0: Tb2Manifold;
  798.    cp: Tb2ContactPoint;
  799.    v1, v2: TVector2;
  800. begin
  801.    b1 := m_shape1.GetBody;
  802.    b2 := m_shape2.GetBody;
  803.    m0 := m_manifold;
  804.    b2CollideCircles(m_manifold, Tb2CircleShape(m_shape1), Tb2CircleShape(m_shape2),
  805.       b1.m_xf, b2.m_xf);
  806.    cp.shape1 := m_shape1;
  807.    cp.shape2 := m_shape2;
  808.    cp.friction := m_friction;
  809.    cp.restitution := m_restitution;
  810.    if m_manifold.pointCount > 0 then
  811.    begin
  812.       m_manifoldCount := 1;
  813.       with m_manifold.points[0] do
  814.       begin
  815.          if m0.pointCount = 0 then
  816.          begin
  817.             normalImpulse := 0.0;
  818.             tangentImpulse := 0.0;
  819.             if Assigned(listener) then
  820.             begin
  821.                cp.position := b1.GetWorldPoint(localPoint1);
  822.                v1 := b1.GetLinearVelocityFromLocalPoint(localPoint1);
  823.                v2 := b2.GetLinearVelocityFromLocalPoint(localPoint2);
  824.                {$IFDEF OP_OVERLOAD}
  825.                cp.velocity := v2 - v1;
  826.                {$ELSE}
  827.                cp.velocity := Subtract(v2, v1);
  828.                {$ENDIF}
  829.                cp.normal := m_manifold.normal;
  830.                cp.separation := separation;
  831.                cp.id := id;
  832.                listener.Add(cp);
  833.             end;
  834.          end
  835.          else
  836.          begin
  837.             normalImpulse := m0.points[0].normalImpulse;
  838.             tangentImpulse := m0.points[0].tangentImpulse;
  839.             if Assigned(listener) then
  840.             begin
  841.                cp.position := b1.GetWorldPoint(localPoint1);
  842.                v1 := b1.GetLinearVelocityFromLocalPoint(localPoint1);
  843.                v2 := b2.GetLinearVelocityFromLocalPoint(localPoint2);
  844.                {$IFDEF OP_OVERLOAD}
  845.                cp.velocity := v2 - v1;
  846.                {$ELSE}
  847.                cp.velocity := Subtract(v2, v1);
  848.                {$ENDIF}
  849.                cp.normal := m_manifold.normal;
  850.                cp.separation := separation;
  851.                cp.id := id;
  852.                listener.Persist(cp);
  853.             end;
  854.          end;
  855.       end;
  856.    end
  857.    else
  858.    begin
  859.       m_manifoldCount := 0;
  860.       if (m0.pointCount > 0) and Assigned(listener) then
  861.       begin
  862.          with m0.points[0] do
  863.          begin
  864.             cp.position := b1.GetWorldPoint(localPoint1);
  865.             v1 := b1.GetLinearVelocityFromLocalPoint(localPoint1);
  866.             v2 := b2.GetLinearVelocityFromLocalPoint(localPoint2);
  867.             {$IFDEF OP_OVERLOAD}
  868.             cp.velocity := v2 - v1;
  869.             {$ELSE}
  870.             cp.velocity := Subtract(v2, v1);
  871.             {$ENDIF}
  872.             cp.normal := m0.normal;
  873.             cp.separation := separation;
  874.             cp.id := id;
  875.             listener.Remove(cp);
  876.          end;
  877.       end;
  878.    end;
  879. end;
  880. function Tb2CircleContact.GetManifolds: Pb2Manifold;
  881. begin
  882.    Result := @m_manifold;
  883. end;
  884. { Tb2PolyAndCircleContact }
  885. constructor Tb2PolyAndCircleContact.Create(shape1, shape2: Tb2Shape);
  886. begin
  887.    inherited Create(shape1, shape2);
  888.    //b2Assert(m_shape1->GetType() == e_polygonShape);
  889.  //b2Assert(m_shape2->GetType() == e_circleShape);
  890.  m_manifold.pointCount := 0;
  891.    m_manifold.points[0].normalImpulse := 0.0;
  892.  m_manifold.points[0].tangentImpulse := 0.0;
  893. end;
  894. procedure Tb2PolyAndCircleContact.Evaluate(listener: Tb2ContactListener);
  895. var
  896.    i, j: Integer;
  897.    b1, b2: Tb2Body;
  898.    m0: Tb2Manifold;
  899.    persisted: array[0..b2_maxManifoldPoints - 1] of Boolean;
  900.    cp: Tb2ContactPoint;
  901.    found: Boolean;
  902.    mp0: Pb2ManifoldPoint;
  903.    local_id: Tb2ContactID;
  904.    v1, v2: TVector2;
  905. begin
  906.    b1 := m_shape1.GetBody;
  907.    b2 := m_shape2.GetBody;
  908.    m0 := m_manifold;
  909.    b2CollidePolygonAndCircle(m_manifold, Tb2PolygonShape(m_shape1),
  910.       Tb2CircleShape(m_shape2), b1.m_xf, b2.m_xf);
  911.    persisted[0] := False;
  912.    persisted[1] := False;
  913.    cp.shape1 := m_shape1;
  914.    cp.shape2 := m_shape2;
  915.    cp.friction := m_friction;
  916.    cp.restitution := m_restitution;
  917.    // Match contact ids to facilitate warm starting.
  918.    if m_manifold.pointCount > 0 then
  919.    begin
  920.       // Match old contact ids to new contact ids and copy the
  921.       // stored impulses to warm start the solver.
  922.       for i := 0 to m_manifold.pointCount - 1 do
  923.          with m_manifold.points[i] do
  924.          begin
  925.             normalImpulse := 0.0;
  926.             tangentImpulse := 0.0;
  927.             found := False;
  928.             local_id := id;
  929.             for j := 0 to m0.pointCount - 1 do
  930.             begin
  931.                if persisted[j] then
  932.                   Continue;
  933.                mp0 := @m0.points[j];
  934.                if mp0.id.key = local_id.key then
  935.                begin
  936.                   persisted[j] := True;
  937.                   normalImpulse := mp0.normalImpulse;
  938.                   tangentImpulse := mp0.tangentImpulse;
  939.                   // A persistent point.
  940.                   found := True;
  941.                   // Report persistent point.
  942.                   if Assigned(listener) then
  943.                   begin
  944.                      cp.position := b1.GetWorldPoint(localPoint1);
  945.                      v1 := b1.GetLinearVelocityFromLocalPoint(localPoint1);
  946.                      v2 := b2.GetLinearVelocityFromLocalPoint(localPoint2);
  947.                      {$IFDEF OP_OVERLOAD}
  948.                      cp.velocity := v2 - v1;
  949.                      {$ELSE}
  950.                      cp.velocity := Subtract(v2, v1);
  951.                      {$ENDIF}
  952.                      cp.normal := m_manifold.normal;
  953.                      cp.separation := separation;
  954.                      cp.id := local_id;
  955.                      listener.Persist(cp);
  956.                   end;
  957.                   Break;
  958.                end;
  959.             end;
  960.             // Report added point.
  961.             if (not found) and Assigned(listener) then
  962.             begin
  963.                cp.position := b1.GetWorldPoint(localPoint1);
  964.                v1 := b1.GetLinearVelocityFromLocalPoint(localPoint1);
  965.                v2 := b2.GetLinearVelocityFromLocalPoint(localPoint2);
  966.                {$IFDEF OP_OVERLOAD}
  967.                cp.velocity := v2 - v1;
  968.                {$ELSE}
  969.                cp.velocity := Subtract(v2, v1);
  970.                {$ENDIF}
  971.                cp.normal := m_manifold.normal;
  972.                cp.separation := separation;
  973.                cp.id := local_id;
  974.                listener.Add(cp);
  975.             end;
  976.          end;
  977.       m_manifoldCount := 1;
  978.    end
  979.    else
  980.       m_manifoldCount := 0;
  981.    if not Assigned(listener) then
  982.       Exit;
  983.    // Report removed points.
  984.    for i := 0 to m0.pointCount - 1 do
  985.    begin
  986.       if persisted[i] then
  987.          Continue;
  988.       with m0.points[i] do
  989.       begin
  990.          cp.position := b1.GetWorldPoint(localPoint1);
  991.          v1 := b1.GetLinearVelocityFromLocalPoint(localPoint1);
  992.          v2 := b2.GetLinearVelocityFromLocalPoint(localPoint2);
  993.          {$IFDEF OP_OVERLOAD}
  994.          cp.velocity := v2 - v1;
  995.          {$ELSE}
  996.          cp.velocity := Subtract(v2, v1);
  997.          {$ENDIF}
  998.          cp.normal := m0.normal;
  999.          cp.separation := separation;
  1000.          cp.id := id;
  1001.          listener.Remove(cp);
  1002.       end;
  1003.    end;
  1004. end;
  1005. function Tb2PolyAndCircleContact.GetManifolds: Pb2Manifold;
  1006. begin
  1007.    Result := @m_manifold;
  1008. end;
  1009. { Tb2PolygonContact }
  1010. constructor Tb2PolygonContact.Create(shape1, shape2: Tb2Shape);
  1011. begin
  1012.    inherited Create(shape1, shape2);
  1013.  //b2Assert(m_shape1->GetType() == e_polygonShape);
  1014.  //b2Assert(m_shape2->GetType() == e_polygonShape);
  1015.  m_manifold.pointCount := 0;
  1016. end;
  1017. procedure Tb2PolygonContact.Evaluate(listener: Tb2ContactListener);
  1018. var
  1019.    i, j: Integer;
  1020.    b1, b2: Tb2Body;
  1021.    m0: Tb2Manifold;
  1022.    persisted: array[0..b2_maxManifoldPoints - 1] of Boolean;
  1023.    cp: Tb2ContactPoint;
  1024.    v1, v2: TVector2;
  1025.    found: Boolean;
  1026.    local_id: Tb2ContactID;
  1027.    mp0: Pb2ManifoldPoint;
  1028. begin
  1029.    b1 := m_shape1.GetBody;
  1030.    b2 := m_shape2.GetBody;
  1031.    m0 := m_manifold;
  1032.    b2CollidePolygons(m_manifold, Tb2PolygonShape(m_shape1), Tb2PolygonShape(m_shape2),
  1033.       b1.m_xf, b2.m_xf);
  1034.    persisted[0] := False;
  1035.    persisted[1] := False;
  1036.    cp.shape1 := m_shape1;
  1037.    cp.shape2 := m_shape2;
  1038.    cp.friction := m_friction;
  1039.    cp.restitution := m_restitution;
  1040.    // Match contact ids to facilitate warm starting.
  1041.    if m_manifold.pointCount > 0 then
  1042.    begin
  1043.       // Match old contact ids to new contact ids and copy the
  1044.       // stored impulses to warm start the solver.
  1045.       for i := 0 to m_manifold.pointCount - 1 do
  1046.          with m_manifold.points[i] do
  1047.          begin
  1048.             normalImpulse := 0.0;
  1049.             tangentImpulse := 0.0;
  1050.             found := False;
  1051.             local_id := id;
  1052.             for j := 0 to m0.pointCount - 1 do
  1053.             begin
  1054.                if persisted[j] then
  1055.                   Continue;
  1056.                mp0 := @m0.points[j];
  1057.                if mp0.id.key = id.key then
  1058.                begin
  1059.                   persisted[j] := True;
  1060.                   normalImpulse := mp0.normalImpulse;
  1061.                   tangentImpulse := mp0.tangentImpulse;
  1062.                   // A persistent point.
  1063.                   found := True;
  1064.                   // Report persistent point.
  1065.                   if Assigned(listener) then
  1066.                   begin
  1067.                      cp.position := b1.GetWorldPoint(localPoint1);
  1068.                      v1 := b1.GetLinearVelocityFromLocalPoint(localPoint1);
  1069.                      v2 := b2.GetLinearVelocityFromLocalPoint(localPoint2);
  1070.                      {$IFDEF OP_OVERLOAD}
  1071.                      cp.velocity := v2 - v1;
  1072.                      {$ELSE}
  1073.                      cp.velocity := Subtract(v2, v1);
  1074.                      {$ENDIF}
  1075.                      cp.normal := m_manifold.normal;
  1076.                      cp.separation := separation;
  1077.                      cp.id := local_id;
  1078.                      listener.Persist(cp);
  1079.                   end;
  1080.                   Break;
  1081.                end;
  1082.             end;
  1083.             // Report added point.
  1084.             if (not found) and Assigned(listener) then
  1085.             begin
  1086.                cp.position := b1.GetWorldPoint(localPoint1);
  1087.                v1 := b1.GetLinearVelocityFromLocalPoint(localPoint1);
  1088.                v2 := b2.GetLinearVelocityFromLocalPoint(localPoint2);
  1089.                {$IFDEF OP_OVERLOAD}
  1090.                cp.velocity := v2 - v1;
  1091.                {$ELSE}
  1092.                cp.velocity := Subtract(v2, v1);
  1093.                {$ENDIF}
  1094.                cp.normal := m_manifold.normal;
  1095.                cp.separation := separation;
  1096.                cp.id := local_id;
  1097.                listener.Add(cp);
  1098.             end;
  1099.          end;
  1100.       m_manifoldCount := 1;
  1101.    end
  1102.    else
  1103.       m_manifoldCount := 0;
  1104.    if not Assigned(listener) then
  1105.       Exit;
  1106.    // Report removed points.
  1107.    for i := 0 to m0.pointCount - 1 do
  1108.    begin
  1109.       if persisted[i] then
  1110.          Continue;
  1111.       with m0.points[i] do
  1112.       begin
  1113.          cp.position := b1.GetWorldPoint(localPoint1);
  1114.          v1 := b1.GetLinearVelocityFromLocalPoint(localPoint1);
  1115.          v2 := b2.GetLinearVelocityFromLocalPoint(localPoint2);
  1116.          {$IFDEF OP_OVERLOAD}
  1117.          cp.velocity := v2 - v1;
  1118.          {$ELSE}
  1119.          cp.velocity := Subtract(v2, v1);
  1120.          {$ENDIF}
  1121.          cp.normal := m0.normal;
  1122.          cp.separation := separation;
  1123.          cp.id := id;
  1124.          listener.Remove(cp);
  1125.       end;
  1126.    end;
  1127. end;
  1128. function Tb2PolygonContact.GetManifolds: Pb2Manifold;
  1129. begin
  1130.    Result := @m_manifold;
  1131. end;
  1132. { Tb2DistanceJointDef }
  1133. // 1-D constrained system
  1134. // m (v2 - v1) = lambda
  1135. // v2 + (beta/h) * x1 + gamma * lambda = 0, gamma has units of inverse mass.
  1136. // x2 = x1 + h * v2
  1137. // 1-D mass-damper-spring system
  1138. // m (v2 - v1) + h * d * v2 + h * k *
  1139. // C = norm(p2 - p1) - L
  1140. // u = (p2 - p1) / norm(p2 - p1)
  1141. // Cdot = dot(u, v2 + cross(w2, r2) - v1 - cross(w1, r1))
  1142. // J = [-u -cross(r1, u) u cross(r2, u)]
  1143. // K = J * invM * JT
  1144. //   = invMass1 + invI1 * cross(r1, u)^2 + invMass2 + invI2 * cross(r2, u)^2
  1145. constructor Tb2DistanceJointDef.Create;
  1146. begin
  1147.    JointType := e_distanceJoint;
  1148.    SetZero(localAnchor1);
  1149.    SetZero(localAnchor2);
  1150.    length := 1.0;
  1151.    frequencyHz := 0.0;
  1152.    dampingRatio := 0.0;
  1153. end;
  1154. procedure Tb2DistanceJointDef.Initialize(body1, body2: Tb2Body; const anchor1,
  1155.    anchor2: TVector2);
  1156. begin
  1157.    Self.body1 := body1;
  1158.    Self.body2 := body2;
  1159.    localAnchor1 := body1.GetLocalPoint(anchor1);
  1160.    localAnchor2 := body2.GetLocalPoint(anchor2);
  1161.    {$IFDEF OP_OVERLOAD}
  1162.    length := (anchor2 - anchor1).Length;
  1163.    {$ELSE}
  1164.    length := UPhysics2DTypes.Length(Subtract(anchor2, anchor1));
  1165.    {$ENDIF}
  1166. end;
  1167. { Tb2DistanceJoint }
  1168. constructor Tb2DistanceJoint.Create(def: Tb2DistanceJointDef);
  1169. begin
  1170.    inherited Create(def);
  1171.    m_localAnchor1 := def.localAnchor1;
  1172.    m_localAnchor2 := def.localAnchor2;
  1173.    m_length := def.length;
  1174.    m_frequencyHz := def.frequencyHz;
  1175.    m_dampingRatio := def.dampingRatio;
  1176.    m_impulse := 0.0;
  1177.    m_gamma := 0.0;
  1178.    m_bias := 0.0;
  1179.    m_inv_dt := 0.0;
  1180. end;
  1181. function Tb2DistanceJoint.GetAnchor1: TVector2;
  1182. begin
  1183.    Result := m_body1.GetWorldPoint(m_localAnchor1);
  1184. end;
  1185. function Tb2DistanceJoint.GetAnchor2: TVector2;
  1186. begin
  1187.    Result := m_body2.GetWorldPoint(m_localAnchor2);
  1188. end;
  1189. function Tb2DistanceJoint.GetReactionForce: TVector2;
  1190. begin
  1191.    {$IFDEF OP_OVERLOAD}
  1192.    Result := (m_inv_dt * m_impulse) * m_u;
  1193.    {$ELSE}
  1194.    Result := Multiply(m_u, m_inv_dt * m_impulse);
  1195.    {$ENDIF}
  1196. end;
  1197. function Tb2DistanceJoint.GetReactionTorque: Float;
  1198. begin
  1199.    Result := 0.0;
  1200. end;
  1201. procedure Tb2DistanceJoint.InitVelocityConstraints(const step: Tb2TimeStep);
  1202. var
  1203.    r1, r2, P: TVector2;
  1204.    length, cr1u, cr2u, invMass: Float;
  1205.    C, omega, d, k: Float;
  1206. begin
  1207.    m_inv_dt := step.inv_dt;
  1208.    // Compute the effective mass matrix.
  1209.    {$IFDEF OP_OVERLOAD}
  1210.    r1 := b2Mul(m_body1.m_xf.R, m_localAnchor1 - m_body1.GetLocalCenter);
  1211.    r2 := b2Mul(m_body2.m_xf.R, m_localAnchor2 - m_body2.GetLocalCenter);
  1212.    m_u := m_body2.m_sweep.c + r2 - m_body1.m_sweep.c - r1;
  1213.    {$ELSE}
  1214.    r1 := b2Mul(m_body1.m_xf.R, Subtract(m_localAnchor1, m_body1.GetLocalCenter));
  1215.    r2 := b2Mul(m_body2.m_xf.R, Subtract(m_localAnchor2, m_body2.GetLocalCenter));
  1216.    m_u := Subtract(r2, r1);
  1217.    AddBy(m_u, m_body2.m_sweep.c);
  1218.    SubtractBy(m_u, m_body1.m_sweep.c);
  1219.    {$ENDIF}
  1220.    // Handle singularity.
  1221.    {$IFDEF OP_OVERLOAD}
  1222.    length := m_u.Length;
  1223.    if length > b2_linearSlop then
  1224.       m_u := m_u / length
  1225.    else
  1226.       m_u.SetZero;
  1227.    {$ELSE}
  1228.    length := UPhysics2DTypes.Length(m_u);
  1229.    if length > b2_linearSlop then
  1230.       DivideBy(m_u, length)
  1231.    else
  1232.       SetZero(m_u);
  1233.    {$ENDIF}
  1234.    cr1u := b2Cross(r1, m_u);
  1235.    cr2u := b2Cross(r2, m_u);
  1236.    invMass := m_body1.m_invMass + m_body1.m_invI * cr1u * cr1u +
  1237.       m_body2.m_invMass + m_body2.m_invI * cr2u * cr2u;
  1238.    //b2Assert(invMass > B2_FLT_EPSILON);
  1239.    m_mass := 1.0 / invMass;
  1240.    if m_frequencyHz > 0.0 then
  1241.    begin
  1242.       C := length - m_length;
  1243.       omega := 2.0 * Pi * m_frequencyHz; // Frequency
  1244.       d := 2.0 * m_mass * m_dampingRatio * omega; // Damping coefficient
  1245.       k := m_mass * omega * omega; // Spring stiffness
  1246.       m_gamma := 1.0 / (step.dt * (d + step.dt * k)); // magic formulas
  1247.       m_bias := C * step.dt * k * m_gamma;
  1248.       m_mass := 1.0 / (invMass + m_gamma);
  1249.    end;
  1250.    if step.warmStarting then
  1251.    begin
  1252.       m_impulse := m_impulse * step.dtRatio;
  1253.       {$IFDEF OP_OVERLOAD}
  1254.       P := m_impulse * m_u;
  1255.       m_body1.m_linearVelocity.SubtractBy(m_body1.m_invMass * P);
  1256.       m_body2.m_linearVelocity.AddBy(m_body2.m_invMass * P);
  1257.       {$ELSE}
  1258.       P := Multiply(m_u, m_impulse);
  1259.       SubtractBy(m_body1.m_linearVelocity, Multiply(P, m_body1.m_invMass));
  1260.       AddBy(m_body2.m_linearVelocity, Multiply(P, m_body2.m_invMass));
  1261.       {$ENDIF}
  1262.       m_body1.m_angularVelocity := m_body1.m_angularVelocity - m_body1.m_invI * b2Cross(r1, P);
  1263.       m_body2.m_angularVelocity := m_body2.m_angularVelocity + m_body2.m_invI * b2Cross(r2, P);
  1264.    end
  1265.    else
  1266.       m_impulse := 0.0;
  1267. end;
  1268. procedure Tb2DistanceJoint.SolveVelocityConstraints(const step: Tb2TimeStep);
  1269. var
  1270.    r1, r2, v1, v2, P: TVector2;
  1271.    Cdot, impulse: Float;
  1272. begin
  1273.    {$IFDEF OP_OVERLOAD}
  1274.    r1 := b2Mul(m_body1.m_xf.R, m_localAnchor1 - m_body1.GetLocalCenter);
  1275.    r2 := b2Mul(m_body2.m_xf.R, m_localAnchor2 - m_body2.GetLocalCenter);
  1276.    // Cdot = dot(u, v + cross(w, r))
  1277.    v1 := m_body1.m_linearVelocity + b2Cross(m_body1.m_angularVelocity, r1);
  1278.    v2 := m_body2.m_linearVelocity + b2Cross(m_body2.m_angularVelocity, r2);
  1279.    Cdot := b2Dot(m_u, v2 - v1);
  1280.    {$ELSE}
  1281.    r1 := b2Mul(m_body1.m_xf.R, Subtract(m_localAnchor1, m_body1.GetLocalCenter));
  1282.    r2 := b2Mul(m_body2.m_xf.R, Subtract(m_localAnchor2, m_body2.GetLocalCenter));
  1283.    // Cdot = dot(u, v + cross(w, r))
  1284.    v1 := Add(m_body1.m_linearVelocity, b2Cross(m_body1.m_angularVelocity, r1));
  1285.    v2 := Add(m_body2.m_linearVelocity, b2Cross(m_body2.m_angularVelocity, r2));
  1286.    Cdot := b2Dot(m_u, Subtract(v2, v1));
  1287.    {$ENDIF}
  1288.    impulse := -m_mass * (Cdot + m_bias + m_gamma * m_impulse);
  1289.    m_impulse := m_impulse + impulse;
  1290.    {$IFDEF OP_OVERLOAD}
  1291.    P := impulse * m_u;
  1292.    m_body1.m_linearVelocity.SubtractBy(m_body1.m_invMass * P);
  1293.    m_body2.m_linearVelocity.AddBy(m_body2.m_invMass * P);
  1294.    {$ELSE}
  1295.    P := Multiply(m_u, impulse);
  1296.    SubtractBy(m_body1.m_linearVelocity, Multiply(P, m_body1.m_invMass));
  1297.    AddBy(m_body2.m_linearVelocity, Multiply(P, m_body2.m_invMass));
  1298.    {$ENDIF}
  1299.    m_body1.m_angularVelocity := m_body1.m_angularVelocity - m_body1.m_invI * b2Cross(r1, P);
  1300.    m_body2.m_angularVelocity := m_body2.m_angularVelocity + m_body2.m_invI * b2Cross(r2, P);
  1301. end;
  1302. function Tb2DistanceJoint.SolvePositionConstraints: Boolean;
  1303. var
  1304.    r1, r2, d, P: TVector2;
  1305.    C, impulse: Float;
  1306. begin
  1307.    if m_frequencyHz > 0.0 then
  1308.    begin
  1309.       Result := True;
  1310.       Exit;
  1311.    end;
  1312.    {$IFDEF OP_OVERLOAD}
  1313.    r1 := b2Mul(m_body1.m_xf.R, m_localAnchor1 - m_body1.GetLocalCenter);
  1314.    r2 := b2Mul(m_body2.m_xf.R, m_localAnchor2 - m_body2.GetLocalCenter);
  1315.    d := m_body2.m_sweep.c + r2 - m_body1.m_sweep.c - r1;
  1316.    C := d.Normalize() - m_length;
  1317.    {$ELSE}
  1318.    r1 := b2Mul(m_body1.m_xf.R, Subtract(m_localAnchor1, m_body1.GetLocalCenter));
  1319.    r2 := b2Mul(m_body2.m_xf.R, Subtract(m_localAnchor2, m_body2.GetLocalCenter));
  1320.    d := Subtract(r2, r1);
  1321.    AddBy(d, m_body2.m_sweep.c);
  1322.    SubtractBy(d, m_body1.m_sweep.c);
  1323.    C := Normalize(d) - m_length;
  1324.    {$ENDIF}
  1325.    C := b2Clamp(C, -b2_maxLinearCorrection, b2_maxLinearCorrection);
  1326.    impulse := -m_mass * C;
  1327.    m_u := d;
  1328.    {$IFDEF OP_OVERLOAD}
  1329.    P := impulse * m_u;
  1330.    m_body1.m_sweep.c.SubtractBy(m_body1.m_invMass * P);
  1331.    m_body2.m_sweep.c.AddBy(m_body2.m_invMass * P);
  1332.    {$ELSE}
  1333.    P := Multiply(m_u, impulse);
  1334.    SubtractBy(m_body1.m_sweep.c, Multiply(P, m_body1.m_invMass));
  1335.    AddBy(m_body2.m_sweep.c, Multiply(P, m_body2.m_invMass));
  1336.    {$ENDIF}
  1337.    m_body1.m_sweep.a := m_body1.m_sweep.a - m_body1.m_invI * b2Cross(r1, P);
  1338.    m_body2.m_sweep.a := m_body2.m_sweep.a + m_body2.m_invI * b2Cross(r2, P);
  1339.    m_body1.SynchronizeTransform;
  1340.    m_body2.SynchronizeTransform;
  1341.    Result := Abs(C) < b2_linearSlop;
  1342. end;
  1343. { Tb2PrismaticJointDef }
  1344. // Linear constraint (point-to-line)
  1345. // d = p2 - p1 = x2 + r2 - x1 - r1
  1346. // C = dot(ay1, d)
  1347. // Cdot = dot(d, cross(w1, ay1)) + dot(ay1, v2 + cross(w2, r2) - v1 - cross(w1, r1))
  1348. //      = -dot(ay1, v1) - dot(cross(d + r1, ay1), w1) + dot(ay1, v2) + dot(cross(r2, ay1), v2)
  1349. // J = [-ay1 -cross(d+r1,ay1) ay1 cross(r2,ay1)]
  1350. //
  1351. // Angular constraint
  1352. // C = a2 - a1 + a_initial
  1353. // Cdot = w2 - w1
  1354. // J = [0 0 -1 0 0 1]
  1355. // Motor/Limit linear constraint
  1356. // C = dot(ax1, d)
  1357. // Cdot = = -dot(ax1, v1) - dot(cross(d + r1, ax1), w1) + dot(ax1, v2) + dot(cross(r2, ax1), v2)
  1358. // J = [-ax1 -cross(d+r1,ax1) ax1 cross(r2,ax1)]
  1359. constructor Tb2PrismaticJointDef.Create;
  1360. begin
  1361.    JointType := e_prismaticJoint;
  1362.    SetZero(localAnchor1);
  1363.    SetZero(localAnchor2);
  1364.    {$IFDEF OP_OVERLOAD}
  1365.    localAxis1.SetValue(1.0, 0.0);
  1366.    {$ELSE}
  1367.    SetValue(localAxis1, 1.0, 0.0);
  1368.    {$ENDIF}
  1369.    referenceAngle := 0.0;
  1370.    enableLimit := False;
  1371.    lowerTranslation := 0.0;
  1372.    upperTranslation := 0.0;
  1373.    enableMotor := False;
  1374.    maxMotorForce := 0.0;
  1375.    motorSpeed := 0.0;
  1376. end;
  1377. procedure Tb2PrismaticJointDef.Initialize(body1, body2: Tb2Body; const anchor,
  1378.    axis: TVector2);
  1379. begin
  1380.    Self.body1 := body1;
  1381.    Self.body2 := body2;
  1382.    localAnchor1 := body1.GetLocalPoint(anchor);
  1383.    localAnchor2 := body2.GetLocalPoint(anchor);
  1384.    localAxis1 := body1.GetLocalVector(axis);
  1385.    referenceAngle := body2.GetAngle - body1.GetAngle;
  1386. end;
  1387. { Tb2PrismaticJoint }
  1388. constructor Tb2PrismaticJoint.Create(def: Tb2PrismaticJointDef);
  1389. begin
  1390.    inherited Create(def);
  1391.    m_localAnchor1 := def.localAnchor1;
  1392.    m_localAnchor2 := def.localAnchor2;
  1393.    m_localXAxis1 := def.localAxis1;
  1394.    m_localYAxis1 := b2Cross(1.0, m_localXAxis1);
  1395.    m_refAngle := def.referenceAngle;
  1396.    {$IFDEF OP_OVERLOAD}
  1397.    m_linearJacobian.SetZero;
  1398.    m_motorJacobian.SetZero;
  1399.    {$ELSE}
  1400.    SetZero(m_linearJacobian);
  1401.    SetZero(m_motorJacobian);
  1402.    {$ENDIF}
  1403.    m_linearMass := 0.0;
  1404.    m_force := 0.0;
  1405.    m_angularMass := 0.0;
  1406.    m_torque := 0.0;
  1407.    m_motorMass := 0.0;
  1408.    m_motorForce := 0.0;
  1409.    m_limitForce := 0.0;
  1410.    m_limitPositionImpulse := 0.0;
  1411.    m_lowerTranslation := def.lowerTranslation;
  1412.    m_upperTranslation := def.upperTranslation;
  1413.    m_maxMotorForce := def.maxMotorForce;
  1414.    m_motorSpeed := def.motorSpeed;
  1415.    m_enableLimit := def.enableLimit;
  1416.    m_enableMotor := def.enableMotor;
  1417. end;
  1418. function Tb2PrismaticJoint.GetAnchor1: TVector2;
  1419. begin
  1420.    Result := m_body1.GetWorldPoint(m_localAnchor1);
  1421. end;
  1422. function Tb2PrismaticJoint.GetAnchor2: TVector2;
  1423. begin
  1424.    Result := m_body2.GetWorldPoint(m_localAnchor2);
  1425. end;
  1426. function Tb2PrismaticJoint.GetReactionForce: TVector2;
  1427. var
  1428.    ax1, ay1: TVector2;
  1429. begin
  1430.    ax1 := b2Mul(m_body1.m_xf.R, m_localXAxis1);
  1431.  ay1 := b2Mul(m_body1.m_xf.R, m_localYAxis1);
  1432.    {$IFDEF OP_OVERLOAD}
  1433.    Result := m_limitForce * ax1 + m_force * ay1;
  1434.    {$ELSE}
  1435.    Result := Add(Multiply(ax1, m_limitForce), Multiply(ay1, m_force));
  1436.    {$ENDIF}
  1437. end;
  1438. function Tb2PrismaticJoint.GetReactionTorque: Float;
  1439. begin
  1440.    Result := m_torque;
  1441. end;
  1442. procedure Tb2PrismaticJoint.InitVelocityConstraints(const step: Tb2TimeStep);
  1443. var
  1444.    r1, r2, ay1, e, ax1, d: TVector2;
  1445.    invMass1, invMass2, invI1, invI2, jointTranslation, L1, L2: Float;
  1446. begin
  1447.    // Compute the effective masses.
  1448.    {$IFDEF OP_OVERLOAD}
  1449.    r1 := b2Mul(m_body1.m_xf.R, m_localAnchor1 - m_body1.GetLocalCenter);
  1450.    r2 := b2Mul(m_body2.m_xf.R, m_localAnchor2 - m_body2.GetLocalCenter);
  1451.    {$ELSE}
  1452.    r1 := b2Mul(m_body1.m_xf.R, Subtract(m_localAnchor1, m_body1.GetLocalCenter));
  1453.    r2 := b2Mul(m_body2.m_xf.R, Subtract(m_localAnchor2, m_body2.GetLocalCenter));
  1454.    {$ENDIF}
  1455.    invMass1 := m_body1.m_invMass;
  1456.    invMass2 := m_body2.m_invMass;
  1457.    invI1 := m_body1.m_invI;
  1458.    invI2 := m_body2.m_invI;
  1459.    // Compute point to line constraint effective mass.
  1460.    // J := [-ay1 -cross(d+r1,ay1) ay1 cross(r2,ay1)]
  1461.    ay1 := b2Mul(m_body1.m_xf.R, m_localYAxis1);
  1462.    {$IFDEF OP_OVERLOAD}
  1463.    e := m_body2.m_sweep.c + r2 - m_body1.m_sweep.c; // e := d + r1
  1464.    m_linearJacobian.SetValue(-ay1, ay1, -b2Cross(e, ay1), b2Cross(r2, ay1));
  1465.    {$ELSE}
  1466.    e := Subtract(m_body2.m_sweep.c, m_body1.m_sweep.c);
  1467.    AddBy(e, r2);
  1468.    SetValue(m_linearJacobian, Negative(ay1), ay1, -b2Cross(e, ay1), b2Cross(r2, ay1));
  1469.    {$ENDIF}
  1470.    m_linearMass := invMass1 + invI1 * m_linearJacobian.angular1 *
  1471.       m_linearJacobian.angular1 + invMass2 + invI2 *
  1472.       m_linearJacobian.angular2 * m_linearJacobian.angular2;
  1473.    //b2Assert(m_linearMass > B2_FLT_EPSILON);
  1474.    m_linearMass := 1.0 / m_linearMass;
  1475.    // Compute angular constraint effective mass.
  1476.    m_angularMass := invI1 + invI2;
  1477.    if m_angularMass > FLT_EPSILON then
  1478.       m_angularMass := 1.0 / m_angularMass;
  1479.    // Compute motor and limit terms.
  1480.    if m_enableLimit or m_enableMotor then
  1481.    begin
  1482.       // The motor and limit share a Jacobian and effective mass.
  1483.       ax1 := b2Mul(m_body1.m_xf.R, m_localXAxis1);
  1484.       {$IFDEF OP_OVERLOAD}
  1485.       m_motorJacobian.SetValue(-ax1, ax1, -b2Cross(e, ax1), b2Cross(r2, ax1));
  1486.       {$ELSE}
  1487.       SetValue(m_motorJacobian, Negative(ax1), ax1, -b2Cross(e, ax1), b2Cross(r2, ax1));
  1488.       {$ENDIF}
  1489.       m_motorMass := invMass1 + invI1 * m_motorJacobian.angular1 * m_motorJacobian.angular1 +
  1490.               invMass2 + invI2 * m_motorJacobian.angular2 * m_motorJacobian.angular2;
  1491.       //b2Assert(m_motorMass > B2_FLT_EPSILON);
  1492.       m_motorMass := 1.0 / m_motorMass;
  1493.       if m_enableLimit then
  1494.       begin
  1495.          {$IFDEF OP_OVERLOAD}
  1496.          d := e - r1; // p2 - p1
  1497.          {$ELSE}
  1498.          d := Subtract(e, r1); // p2 - p1
  1499.          {$ENDIF}
  1500.          jointTranslation := b2Dot(ax1, d);
  1501.          if Abs(m_upperTranslation - m_lowerTranslation) < 2.0 * b2_linearSlop then
  1502.             m_limitState := e_equalLimits
  1503.          else if jointTranslation <= m_lowerTranslation then
  1504.          begin
  1505.             if m_limitState <> e_atLowerLimit then
  1506.                m_limitForce := 0.0;
  1507.             m_limitState := e_atLowerLimit;
  1508.          end
  1509.          else if jointTranslation >= m_upperTranslation then
  1510.          begin
  1511.             if m_limitState <> e_atUpperLimit then
  1512.                m_limitForce := 0.0;
  1513.             m_limitState := e_atUpperLimit;
  1514.          end
  1515.          else
  1516.          begin
  1517.             m_limitState := e_inactiveLimit;
  1518.             m_limitForce := 0.0;
  1519.          end;
  1520.       end;
  1521.    end;
  1522.    if not m_enableMotor then
  1523.       m_motorForce := 0.0;
  1524.    if not m_enableLimit then
  1525.       m_limitForce := 0.0;
  1526.    if step.warmStarting then
  1527.    begin
  1528.       {$IFDEF OP_OVERLOAD}
  1529.       r1 := step.dt * (m_force * m_linearJacobian.linear1 + (m_motorForce +
  1530.          m_limitForce) * m_motorJacobian.linear1);
  1531.       r2 := step.dt * (m_force * m_linearJacobian.linear2 + (m_motorForce +
  1532.          m_limitForce) * m_motorJacobian.linear2);
  1533.       {$ELSE}
  1534.       r1 := Multiply(m_motorJacobian.linear1, m_motorForce + m_limitForce);
  1535.       AddBy(r1, Multiply(m_linearJacobian.linear1, m_force));
  1536.       MultiplyBy(r1, step.dt);
  1537.       r2 := Multiply(m_motorJacobian.linear2, m_motorForce + m_limitForce);
  1538.       AddBy(r2, Multiply(m_linearJacobian.linear2, m_force));
  1539.       MultiplyBy(r2, step.dt);
  1540.       {$ENDIF}
  1541.       L1 := step.dt * (m_force * m_linearJacobian.angular1 - m_torque +
  1542.          (m_motorForce + m_limitForce) * m_motorJacobian.angular1);
  1543.       L2 := step.dt * (m_force * m_linearJacobian.angular2 + m_torque +
  1544.          (m_motorForce + m_limitForce) * m_motorJacobian.angular2);
  1545.       {$IFDEF OP_OVERLOAD}
  1546.       m_body1.m_linearVelocity.AddBy(invMass1 * r1);
  1547.       m_body2.m_linearVelocity.AddBy(invMass2 * r2);
  1548.       {$ELSE}
  1549.       AddBy(m_body1.m_linearVelocity, Multiply(r1, invMass1));
  1550.       AddBy(m_body2.m_linearVelocity, Multiply(r2, invMass2));
  1551.       {$ENDIF}
  1552.       m_body1.m_angularVelocity := m_body1.m_angularVelocity + invI1 * L1;
  1553.       m_body2.m_angularVelocity := m_body2.m_angularVelocity + invI2 * L2;
  1554.    end
  1555.    else
  1556.    begin
  1557.       m_force := 0.0;
  1558.       m_torque := 0.0;
  1559.       m_limitForce := 0.0;
  1560.       m_motorForce := 0.0;
  1561.    end;
  1562.    m_limitPositionImpulse := 0.0;
  1563. end;
  1564. procedure Tb2PrismaticJoint.SolveVelocityConstraints(const step: Tb2TimeStep);
  1565. var
  1566.    invMass1, invMass2, invI1, invI2: Float;
  1567.    linearCdot, force, P, angularCdot, torque, L: Float;
  1568.    motorCdot, motorForce, oldMotorForce: Float;
  1569.    limitCdot, limitForce, oldLimitForce: Float;
  1570. begin
  1571.    invMass1 := m_body1.m_invMass;
  1572.    invMass2 := m_body2.m_invMass;
  1573.    invI1 := m_body1.m_invI;
  1574.    invI2 := m_body2.m_invI;
  1575.    // Solve linear constraint.
  1576.    {$IFDEF OP_OVERLOAD}
  1577.    linearCdot := m_linearJacobian.Compute(m_body1.m_linearVelocity,
  1578.       m_body2.m_linearVelocity, m_body1.m_angularVelocity, m_body2.m_angularVelocity);
  1579.    {$ELSE}
  1580.    linearCdot := Compute(m_linearJacobian, m_body1.m_linearVelocity,
  1581.       m_body2.m_linearVelocity, m_body1.m_angularVelocity, m_body2.m_angularVelocity);
  1582.    {$ENDIF}
  1583.    force := -step.inv_dt * m_linearMass * linearCdot;
  1584.    m_force := m_force + force;
  1585.    P := step.dt * force;
  1586.    {$IFDEF OP_OVERLOAD}
  1587.    m_body1.m_linearVelocity.AddBy((invMass1 * P) * m_linearJacobian.linear1);
  1588.    m_body2.m_linearVelocity.AddBy((invMass2 * P) * m_linearJacobian.linear2);
  1589.    {$ELSE}
  1590.    AddBy(m_body1.m_linearVelocity, Multiply(m_linearJacobian.linear1, invMass1 * P));
  1591.    AddBy(m_body2.m_linearVelocity, Multiply(m_linearJacobian.linear2, invMass2 * P));
  1592.    {$ENDIF}
  1593.    m_body1.m_angularVelocity := m_body1.m_angularVelocity + invI1 * P * m_linearJacobian.angular1;
  1594.    m_body2.m_angularVelocity := m_body2.m_angularVelocity + invI2 * P * m_linearJacobian.angular2;
  1595.    // Solve angular constraint.
  1596.    angularCdot := m_body2.m_angularVelocity - m_body1.m_angularVelocity;
  1597.    torque := -step.inv_dt * m_angularMass * angularCdot;
  1598.    m_torque := m_torque + torque;
  1599.    L := step.dt * torque;
  1600.    m_body1.m_angularVelocity := m_body1.m_angularVelocity - invI1 * L;
  1601.    m_body2.m_angularVelocity := m_body2.m_angularVelocity + invI2 * L;
  1602.    // Solve linear motor constraint.
  1603.    if m_enableMotor and (m_limitState <> e_equalLimits) then
  1604.    begin
  1605.       {$IFDEF OP_OVERLOAD}
  1606.       motorCdot := m_motorJacobian.Compute(m_body1.m_linearVelocity,
  1607.          m_body2.m_linearVelocity, m_body1.m_angularVelocity,
  1608.          m_body2.m_angularVelocity) - m_motorSpeed;
  1609.       {$ELSE}
  1610.       motorCdot := Compute(m_motorJacobian, m_body1.m_linearVelocity,
  1611.          m_body2.m_linearVelocity, m_body1.m_angularVelocity,
  1612.          m_body2.m_angularVelocity) - m_motorSpeed;
  1613.       {$ENDIF}
  1614.       motorForce := -step.inv_dt * m_motorMass * motorCdot;
  1615.       oldMotorForce := m_motorForce;
  1616.       m_motorForce := b2Clamp(m_motorForce + motorForce, -m_maxMotorForce, m_maxMotorForce);
  1617.       motorForce := m_motorForce - oldMotorForce;
  1618.       P := step.dt * motorForce;
  1619.       {$IFDEF OP_OVERLOAD}
  1620.       m_body1.m_linearVelocity.AddBy((invMass1 * P) * m_motorJacobian.linear1);
  1621.       m_body2.m_linearVelocity.AddBy((invMass2 * P) * m_motorJacobian.linear2);
  1622.       {$ELSE}
  1623.       AddBy(m_body1.m_linearVelocity, Multiply(m_motorJacobian.linear1, invMass1 * P));
  1624.       AddBy(m_body2.m_linearVelocity, Multiply(m_motorJacobian.linear2, invMass2 * P));
  1625.       {$ENDIF}
  1626.       m_body1.m_angularVelocity := m_body1.m_angularVelocity + invI1 * P * m_motorJacobian.angular1;
  1627.       m_body2.m_angularVelocity := m_body2.m_angularVelocity + invI2 * P * m_motorJacobian.angular2;
  1628.    end;
  1629.    // Solve linear limit constraint.
  1630.    if m_enableLimit and (m_limitState <> e_inactiveLimit) then
  1631.    begin
  1632.       {$IFDEF OP_OVERLOAD}
  1633.       limitCdot := m_motorJacobian.Compute(m_body1.m_linearVelocity,
  1634.          m_body2.m_linearVelocity, m_body1.m_angularVelocity, m_body2.m_angularVelocity);
  1635.       {$ELSE}
  1636.       limitCdot := Compute(m_motorJacobian, m_body1.m_linearVelocity,
  1637.          m_body2.m_linearVelocity, m_body1.m_angularVelocity, m_body2.m_angularVelocity);
  1638.       {$ENDIF}
  1639.       limitForce := -step.inv_dt * m_motorMass * limitCdot;
  1640.       case m_limitState of
  1641.          e_equalLimits: m_limitForce := m_limitForce + limitForce;
  1642.          e_atLowerLimit:
  1643.             begin
  1644.                oldLimitForce := m_limitForce;
  1645.                m_limitForce := b2Max(m_limitForce + limitForce, 0.0);
  1646.                limitForce := m_limitForce - oldLimitForce;
  1647.             end;
  1648.          e_atUpperLimit:
  1649.             begin
  1650.                oldLimitForce := m_limitForce;
  1651.                m_limitForce := b2Min(m_limitForce + limitForce, 0.0);
  1652.                limitForce := m_limitForce - oldLimitForce;
  1653.             end;
  1654.       end;
  1655.       P := step.dt * limitForce;
  1656.       {$IFDEF OP_OVERLOAD}
  1657.       m_body1.m_linearVelocity.AddBy((invMass1 * P) * m_motorJacobian.linear1);
  1658.       m_body2.m_linearVelocity.AddBy((invMass2 * P) * m_motorJacobian.linear2);
  1659.       {$ELSE}
  1660.       AddBy(m_body1.m_linearVelocity, Multiply(m_motorJacobian.linear1, invMass1 * P));
  1661.       AddBy(m_body2.m_linearVelocity, Multiply(m_motorJacobian.linear2, invMass2 * P));
  1662.       {$ENDIF}
  1663.       m_body1.m_angularVelocity := m_body1.m_angularVelocity + invI1 * P * m_motorJacobian.angular1;
  1664.       m_body2.m_angularVelocity := m_body2.m_angularVelocity + invI2 * P * m_motorJacobian.angular2;
  1665.    end;
  1666. end;
  1667. function Tb2PrismaticJoint.SolvePositionConstraints: Boolean;
  1668. var
  1669.    invMass1, invMass2, invI1, invI2: Float;
  1670.    r1, r2, p1, p2, d, ay1, ax1: TVector2;
  1671.    linearC, linearImpulse, positionError, angularC, angularImpulse, angularError: Float;
  1672.    translation, limitImpulse, limitC, oldLimitImpulse: Float;
  1673. begin
  1674.    invMass1 := m_body1.m_invMass;
  1675.    invMass2 := m_body2.m_invMass;
  1676.    invI1 := m_body1.m_invI;
  1677.    invI2 := m_body2.m_invI;
  1678.    {$IFDEF OP_OVERLOAD}
  1679.    r1 := b2Mul(m_body1.m_xf.R, m_localAnchor1 - m_body1.GetLocalCenter);
  1680.    r2 := b2Mul(m_body2.m_xf.R, m_localAnchor2 - m_body2.GetLocalCenter);
  1681.    p1 := m_body1.m_sweep.c + r1;
  1682.    p2 := m_body2.m_sweep.c + r2;
  1683.    d := p2 - p1;
  1684.    {$ELSE}
  1685.    r1 := b2Mul(m_body1.m_xf.R, Subtract(m_localAnchor1, m_body1.GetLocalCenter));
  1686.    r2 := b2Mul(m_body2.m_xf.R, Subtract(m_localAnchor2, m_body2.GetLocalCenter));
  1687.    p1 := Add(m_body1.m_sweep.c, r1);
  1688.    p2 := Add(m_body2.m_sweep.c, r2);
  1689.    d := Subtract(p2, p1);
  1690.    {$ENDIF}
  1691.    ay1 := b2Mul(m_body1.m_xf.R, m_localYAxis1);
  1692.    // Solve linear (point-to-line) constraint.
  1693.    linearC := b2Dot(ay1, d);
  1694.    // Prevent overly large corrections.
  1695.    linearC := b2Clamp(linearC, -b2_maxLinearCorrection, b2_maxLinearCorrection);
  1696.    linearImpulse := -m_linearMass * linearC;
  1697.    {$IFDEF OP_OVERLOAD}
  1698.    m_body1.m_sweep.c.AddBy((invMass1 * linearImpulse) * m_linearJacobian.linear1);
  1699.    m_body2.m_sweep.c.AddBy((invMass2 * linearImpulse) * m_linearJacobian.linear2);
  1700.    {$ELSE}
  1701.    AddBy(m_body1.m_sweep.c, Multiply(m_linearJacobian.linear1, invMass1 * linearImpulse));
  1702.    AddBy(m_body2.m_sweep.c, Multiply(m_linearJacobian.linear2, invMass2 * linearImpulse));
  1703.    {$ENDIF}
  1704.    m_body1.m_sweep.a := m_body1.m_sweep.a + invI1 * linearImpulse * m_linearJacobian.angular1;
  1705.    //m_body1.SynchronizeTransform; // updated by angular constraint
  1706.    m_body2.m_sweep.a := m_body2.m_sweep.a + invI2 * linearImpulse * m_linearJacobian.angular2;
  1707.    //m_body2.SynchronizeTransform; // updated by angular constraint
  1708.    positionError := Abs(linearC);
  1709.    // Solve angular constraint.
  1710.    angularC := m_body2.m_sweep.a - m_body1.m_sweep.a - m_refAngle;
  1711.    // Prevent overly large corrections.
  1712.    angularC := b2Clamp(angularC, -b2_maxAngularCorrection, b2_maxAngularCorrection);
  1713.    angularImpulse := -m_angularMass * angularC;
  1714.    m_body1.m_sweep.a := m_body1.m_sweep.a - m_body1.m_invI * angularImpulse;
  1715.    m_body2.m_sweep.a := m_body2.m_sweep.a + m_body2.m_invI * angularImpulse;
  1716.    m_body1.SynchronizeTransform;
  1717.    m_body2.SynchronizeTransform;
  1718.    angularError := Abs(angularC);
  1719.    // Solve linear limit constraint.
  1720.    if m_enableLimit and (m_limitState <> e_inactiveLimit) then
  1721.    begin
  1722.       {$IFDEF OP_OVERLOAD}
  1723.       r1 := b2Mul(m_body1.m_xf.R, m_localAnchor1 - m_body1.GetLocalCenter);
  1724.       r2 := b2Mul(m_body2.m_xf.R, m_localAnchor2 - m_body2.GetLocalCenter);
  1725.       p1 := m_body1.m_sweep.c + r1;
  1726.       p2 := m_body2.m_sweep.c + r2;
  1727.       d := p2 - p1;
  1728.       {$ELSE}
  1729.       r1 := b2Mul(m_body1.m_xf.R, Subtract(m_localAnchor1, m_body1.GetLocalCenter));
  1730.       r2 := b2Mul(m_body2.m_xf.R, Subtract(m_localAnchor2, m_body2.GetLocalCenter));
  1731.       p1 := Add(m_body1.m_sweep.c, r1);
  1732.       p2 := Add(m_body2.m_sweep.c, r2);
  1733.       d := Subtract(p2, p1);
  1734.       {$ENDIF}
  1735.       ax1 := b2Mul(m_body1.m_xf.R, m_localXAxis1);
  1736.       translation := b2Dot(ax1, d);
  1737.       limitImpulse := 0.0;
  1738.       if m_limitState = e_equalLimits then
  1739.       begin
  1740.          // Prevent large angular corrections
  1741.          limitC := b2Clamp(translation, -b2_maxLinearCorrection, b2_maxLinearCorrection);
  1742.          limitImpulse := -m_motorMass * limitC;
  1743.          positionError := b2Max(positionError, Abs(angularC));
  1744.       end
  1745.       else if m_limitState = e_atLowerLimit then
  1746.       begin
  1747.          limitC := translation - m_lowerTranslation;
  1748.          positionError := b2Max(positionError, -limitC);
  1749.          // Prevent large linear corrections and allow some slop.
  1750.          limitC := b2Clamp(limitC + b2_linearSlop, -b2_maxLinearCorrection, 0.0);
  1751.          limitImpulse := -m_motorMass * limitC;
  1752.          oldLimitImpulse := m_limitPositionImpulse;
  1753.          m_limitPositionImpulse := b2Max(m_limitPositionImpulse + limitImpulse, 0.0);
  1754.          limitImpulse := m_limitPositionImpulse - oldLimitImpulse;
  1755.       end
  1756.       else if m_limitState = e_atUpperLimit then
  1757.       begin
  1758.          limitC := translation - m_upperTranslation;
  1759.          positionError := b2Max(positionError, limitC);
  1760.          // Prevent large linear corrections and allow some slop.
  1761.          limitC := b2Clamp(limitC - b2_linearSlop, 0.0, b2_maxLinearCorrection);
  1762.          limitImpulse := -m_motorMass * limitC;
  1763.          oldLimitImpulse := m_limitPositionImpulse;
  1764.          m_limitPositionImpulse := b2Min(m_limitPositionImpulse + limitImpulse, 0.0);
  1765.          limitImpulse := m_limitPositionImpulse - oldLimitImpulse;
  1766.       end;
  1767.       {$IFDEF OP_OVERLOAD}
  1768.       m_body1.m_sweep.c.AddBy((invMass1 * limitImpulse) * m_motorJacobian.linear1);
  1769.       m_body2.m_sweep.c.AddBy((invMass2 * limitImpulse) * m_motorJacobian.linear2);
  1770.       {$ELSE}
  1771.       AddBy(m_body1.m_sweep.c, Multiply(m_motorJacobian.linear1, invMass1 * limitImpulse));
  1772.       AddBy(m_body2.m_sweep.c, Multiply(m_motorJacobian.linear2, invMass2 * limitImpulse));
  1773.       {$ENDIF}
  1774.       m_body1.m_sweep.a := m_body1.m_sweep.a + invI1 * limitImpulse * m_motorJacobian.angular1;
  1775.       m_body2.m_sweep.a := m_body2.m_sweep.a + invI2 * limitImpulse * m_motorJacobian.angular2;
  1776.       m_body1.SynchronizeTransform;
  1777.       m_body2.SynchronizeTransform;
  1778.    end;
  1779.    Result := (positionError <= b2_linearSlop) and (angularError <= b2_angularSlop);
  1780. end;
  1781. function Tb2PrismaticJoint.GetJointTranslation: Float;
  1782. var
  1783.    d, axis: TVector2;
  1784. begin
  1785.    {$IFDEF OP_OVERLOAD}
  1786.    d := m_body2.GetWorldPoint(m_localAnchor2) - m_body1.GetWorldPoint(m_localAnchor1);
  1787.    {$ELSE}
  1788.    d := Subtract(m_body2.GetWorldPoint(m_localAnchor2), m_body1.GetWorldPoint(m_localAnchor1));
  1789.    {$ENDIF}
  1790.    axis := m_body1.GetWorldVector(m_localXAxis1);
  1791.    Result := b2Dot(d, axis);
  1792. end;
  1793. function Tb2PrismaticJoint.GetJointSpeed: Float;
  1794. var
  1795.    r1, r2, d, axis: TVector2;
  1796.    w1: Float;
  1797. begin
  1798.    {$IFDEF OP_OVERLOAD}
  1799.    r1 := b2Mul(m_body1.m_xf.R, m_localAnchor1 - m_body1.GetLocalCenter);
  1800.    r2 := b2Mul(m_body2.m_xf.R, m_localAnchor2 - m_body2.GetLocalCenter);
  1801.    d := (m_body2.m_sweep.c + r2) - (m_body1.m_sweep.c + r1);
  1802.    {$ELSE}
  1803.    r1 := b2Mul(m_body1.m_xf.R, Subtract(m_localAnchor1, m_body1.GetLocalCenter));
  1804.    r2 := b2Mul(m_body2.m_xf.R, Subtract(m_localAnchor2, m_body2.GetLocalCenter));
  1805.    d := Subtract(Add(m_body2.m_sweep.c, r2), Add(m_body1.m_sweep.c, r1));
  1806.    {$ENDIF}
  1807.    axis := m_body1.GetWorldVector(m_localXAxis1);
  1808.    w1 := m_body1.m_angularVelocity;
  1809.    {$IFDEF OP_OVERLOAD}
  1810.    Result := b2Dot(d, b2Cross(w1, axis)) +
  1811.       b2Dot(axis, m_body2.m_linearVelocity + b2Cross(m_body2.m_angularVelocity, r2) -
  1812.       m_body1.m_linearVelocity - b2Cross(w1, r1));
  1813.    {$ELSE}
  1814.    Result := b2Dot(d, b2Cross(w1, axis)) +
  1815.       b2Dot(axis, Subtract(Add(m_body2.m_linearVelocity, b2Cross(m_body2.m_angularVelocity, r2)),
  1816.       Add(m_body1.m_linearVelocity, b2Cross(w1, r1))));
  1817.    {$ENDIF}
  1818. end;
  1819. procedure Tb2PrismaticJoint.SetLimits(lower, upper: Float);
  1820. begin
  1821.    //b2Assert(lower <= upper);
  1822.  m_lowerTranslation := lower;
  1823.  m_upperTranslation := upper;
  1824. end;
  1825. { Tb2MouseJointDef }
  1826. // p = attached point, m = mouse point
  1827. // C = p - m
  1828. // Cdot = v
  1829. //      = v + cross(w, r)
  1830. // J = [I r_skew]
  1831. // Identity used:
  1832. // w k % (rx i + ry j) = w * (-ry i + rx j)
  1833. constructor Tb2MouseJointDef.Create;
  1834. begin
  1835. JointType := e_mouseJoint;
  1836.     SetZero(target);
  1837. maxForce := 0.0;
  1838. frequencyHz := 5.0;
  1839. dampingRatio := 0.7;
  1840. timeStep := 1.0 / 60.0;
  1841. end;
  1842. { Tb2MouseJoint }
  1843. constructor Tb2MouseJoint.Create(def: Tb2MouseJointDef);
  1844. var
  1845.    omega, d, k: Float;
  1846. begin
  1847.    inherited Create(def);
  1848.    m_target := def.target;
  1849.    m_localAnchor := b2MulT(m_body2.m_xf, m_target);
  1850.    m_maxForce := def.maxForce;
  1851.    SetZero(m_impulse);
  1852.    omega := 2.0 * Pi * def.frequencyHz; // Frequency
  1853.    d := 2.0 * m_body2.m_mass * def.dampingRatio * omega; // Damping coefficient
  1854.    k := (def.timeStep * m_body2.m_mass) * (omega * omega); // Spring stiffness
  1855.    //b2Assert(d + k > B2_FLT_EPSILON);
  1856.    m_gamma := 1.0 / (d + k);
  1857.    m_beta := k / (d + k);
  1858. end;
  1859. function Tb2MouseJoint.GetAnchor1: TVector2;
  1860. begin
  1861.    Result := m_target;
  1862. end;
  1863. function Tb2MouseJoint.GetAnchor2: TVector2;
  1864. begin
  1865.    Result := m_body2.GetWorldPoint(m_localAnchor);
  1866. end;
  1867. function Tb2MouseJoint.GetReactionForce: TVector2;
  1868. begin
  1869.    Result := m_impulse;
  1870. end;
  1871. function Tb2MouseJoint.GetReactionTorque: Float;
  1872. begin
  1873.    Result := 0.0;
  1874. end;
  1875. procedure Tb2MouseJoint.InitVelocityConstraints(const step: Tb2TimeStep);
  1876. var
  1877.    r, P: TVector2;
  1878.    invMass, invI: Float;
  1879.    K1, K2, K: TMatrix22;
  1880. begin
  1881.    // Compute the effective mass matrix.
  1882.    {$IFDEF OP_OVERLOAD}
  1883.    r := b2Mul(m_body2.m_xf.R, m_localAnchor - m_body2.GetLocalCenter);
  1884.    {$ELSE}
  1885.    r := b2Mul(m_body2.m_xf.R, Subtract(m_localAnchor, m_body2.GetLocalCenter));
  1886.    {$ENDIF}
  1887.    // K    := [(1/m1 + 1/m2) * eye(2) - skew(r1) * invI1 * skew(r1) - skew(r2) * invI2 * skew(r2)]
  1888.    //      := [1/m1+1/m2     0    ] + invI1 * [r1.y*r1.y -r1.x*r1.y] + invI2 * [r1.y*r1.y -r1.x*r1.y]
  1889.    //        [    0     1/m1+1/m2]           [-r1.x*r1.y r1.x*r1.x]           [-r1.x*r1.y r1.x*r1.x]
  1890.    invMass := m_body2.m_invMass;
  1891.    invI := m_body2.m_invI;
  1892.    K1.col1.x := invMass;
  1893.    K1.col2.x := 0.0;
  1894.    K1.col1.y := 0.0;
  1895.    K1.col2.y := invMass;
  1896.    K2.col1.x :=  invI * r.y * r.y;
  1897.    K2.col2.x := -invI * r.x * r.y;
  1898.    K2.col1.y := K2.col2.x;
  1899.    K2.col2.y :=  invI * r.x * r.x;
  1900.    {$IFDEF OP_OVERLOAD}
  1901.    K := K1 + K2;
  1902.    {$ELSE}
  1903.    K := Add(K1, K2);
  1904.    {$ENDIF}
  1905.    K.col1.x := K.col1.x + m_gamma;
  1906.    K.col2.y := K.col2.y + m_gamma;
  1907.    {$IFDEF OP_OVERLOAD}
  1908.    m_mass := K.Invert;
  1909.    m_C := m_body2.m_sweep.c + r - m_target;
  1910.    {$ELSE}
  1911.    m_mass := Invert(K);
  1912.    m_C := Add(m_body2.m_sweep.c, r);
  1913.    SubtractBy(m_C, m_target);
  1914.    {$ENDIF}
  1915.    m_body2.m_angularVelocity := m_body2.m_angularVelocity * 0.98; // Cheat with some damping
  1916.    // Warm starting.
  1917.    {$IFDEF OP_OVERLOAD}
  1918.    P := step.dt * m_impulse;
  1919.    m_body2.m_linearVelocity.AddBy(invMass * P);
  1920.    {$ELSE}
  1921.    P := Multiply(m_impulse, step.dt);
  1922.    AddBy(m_body2.m_linearVelocity, Multiply(P, invMass));
  1923.    {$ENDIF}
  1924.    m_body2.m_angularVelocity := m_body2.m_angularVelocity + invI * b2Cross(r, P);
  1925. end;
  1926. procedure Tb2MouseJoint.SolveVelocityConstraints(const step: Tb2TimeStep);
  1927. var
  1928.    r, Cdot, force, oldForce, P: TVector2;
  1929.    forceMagnitude: Float;
  1930. begin
  1931.    oldForce := m_impulse;
  1932.    // Cdot := v + cross(w, r)
  1933.    {$IFDEF OP_OVERLOAD}
  1934.    r := b2Mul(m_body2.m_xf.R, m_localAnchor - m_body2.GetLocalCenter);
  1935.    Cdot := m_body2.m_linearVelocity + b2Cross(m_body2.m_angularVelocity, r);
  1936.    force := -step.inv_dt * b2Mul(m_mass, Cdot + (m_beta * step.inv_dt) * m_C +
  1937.       step.dt * (m_gamma * m_impulse));
  1938.    m_impulse.AddBy(force);
  1939.    forceMagnitude := m_impulse.Length;
  1940.    if forceMagnitude > m_maxForce then
  1941.       m_impulse.MultiplyBy(m_maxForce / forceMagnitude);
  1942.    force := m_impulse - oldForce;
  1943.    P := step.dt * force;
  1944.    m_body2.m_linearVelocity.AddBy(m_body2.m_invMass * P);
  1945.    {$ELSE}
  1946.    r := b2Mul(m_body2.m_xf.R, Subtract(m_localAnchor, m_body2.GetLocalCenter));
  1947.    Cdot := Add(m_body2.m_linearVelocity, b2Cross(m_body2.m_angularVelocity, r));
  1948.    force := Multiply(b2Mul(m_mass, Add(Cdot, Multiply(m_C, m_beta * step.inv_dt),
  1949.       Multiply(m_impulse, step.dt * m_gamma))), -step.inv_dt);
  1950.    AddBy(m_impulse, force);
  1951.    forceMagnitude := Length(m_impulse);
  1952.    if forceMagnitude > m_maxForce then
  1953.       MultiplyBy(m_impulse, m_maxForce / forceMagnitude);
  1954.    force := Subtract(m_impulse, oldForce);
  1955.    P := Multiply(force, step.dt);
  1956.    AddBy(m_body2.m_linearVelocity, Multiply(P, m_body2.m_invMass));
  1957.    {$ENDIF}
  1958.    m_body2.m_angularVelocity := m_body2.m_angularVelocity + m_body2.m_invI * b2Cross(r, P);
  1959. end;
  1960. function Tb2MouseJoint.SolvePositionConstraints: Boolean;
  1961. begin
  1962.    Result := True;
  1963. end;
  1964. procedure Tb2MouseJoint.SetTarget(const target: TVector2);
  1965. begin
  1966.    if m_body2.IsSleeping() then
  1967.       m_body2.WakeUp;
  1968.    m_target := target;
  1969. end;
  1970. { Tb2PulleyJointDef }
  1971. // Pulley:
  1972. // length1 = norm(p1 - s1)
  1973. // length2 = norm(p2 - s2)
  1974. // C0 = (length1 + ratio * length2)_initial
  1975. // C = C0 - (length1 + ratio * length2) >= 0
  1976. // u1 = (p1 - s1) / norm(p1 - s1)
  1977. // u2 = (p2 - s2) / norm(p2 - s2)
  1978. // Cdot = -dot(u1, v1 + cross(w1, r1)) - ratio * dot(u2, v2 + cross(w2, r2))
  1979. // J = -[u1 cross(r1, u1) ratio * u2  ratio * cross(r2, u2)]
  1980. // K = J * invM * JT
  1981. //   = invMass1 + invI1 * cross(r1, u1)^2 + ratio^2 * (invMass2 + invI2 * cross(r2, u2)^2)
  1982. //
  1983. // Limit:
  1984. // C = maxLength - length
  1985. // u = (p - s) / norm(p - s)
  1986. // Cdot = -dot(u, v + cross(w, r))
  1987. // K = invMass + invI * cross(r, u)^2
  1988. // 0 <= impulse
  1989. const
  1990.    b2_minPulleyLength = 2.0;
  1991. constructor Tb2PulleyJointDef.Create;
  1992. begin
  1993.    JointType := e_pulleyJoint;
  1994.    {$IFDEF OP_OVERLOAD}
  1995.    groundAnchor1.SetValue(-1.0, 1.0);
  1996.    groundAnchor2.SetValue(1.0, 1.0);
  1997.    localAnchor1.SetValue(-1.0, 0.0);
  1998.    localAnchor2.SetValue(1.0, 0.0);
  1999.    {$ELSE}
  2000.    SetValue(groundAnchor1, -1.0, 1.0);
  2001.    SetValue(groundAnchor2, 1.0, 1.0);
  2002.    SetValue(localAnchor1, -1.0, 0.0);
  2003.    SetValue(localAnchor2, 1.0, 0.0);
  2004.    {$ENDIF}
  2005.    length1 := 0.0;
  2006.    maxLength1 := 0.0;
  2007.    length2 := 0.0;
  2008.    maxLength2 := 0.0;
  2009.    ratio := 1.0;
  2010.    collideConnected := True;
  2011. end;
  2012. procedure Tb2PulleyJointDef.Initialize(body1, body2: Tb2Body; const groundAnchor1,
  2013.    groundAnchor2, anchor1, anchor2: TVector2; ratio: Float);
  2014. var
  2015.    C: Float;
  2016. begin
  2017.    Self.body1 := body1;
  2018.    Self.body2 := body2;
  2019.    Self.groundAnchor1 := groundAnchor1;
  2020.    Self.groundAnchor2 := groundAnchor2;
  2021.    Self.localAnchor1 := body1.GetLocalPoint(anchor1);
  2022.    Self.localAnchor2 := body2.GetLocalPoint(anchor2);
  2023.    {$IFDEF OP_OVERLOAD}
  2024.    length1 := (anchor1 - groundAnchor1).Length;
  2025.    length2 := (anchor2 - groundAnchor2).Length;
  2026.    {$ELSE}
  2027.    length1 := Length(Subtract(anchor1, groundAnchor1));
  2028.    length2 := Length(Subtract(anchor2, groundAnchor2));
  2029.    {$ENDIF}
  2030.    Self.ratio := ratio;
  2031.    //b2Assert(ratio > B2_FLT_EPSILON);
  2032.    C := length1 + ratio * length2;
  2033.    maxLength1 := C - ratio * b2_minPulleyLength;
  2034.    maxLength2 := (C - b2_minPulleyLength) / ratio;
  2035. end;
  2036. { Tb2PulleyJoint }
  2037. constructor Tb2PulleyJoint.Create(def: Tb2PulleyJointDef);
  2038. begin
  2039.    inherited Create(def);
  2040.    m_ground := m_body1.GetWorld.GetGroundBody;
  2041.    {$IFDEF OP_OVERLOAD}
  2042.    m_groundAnchor1 := def.groundAnchor1 - m_ground.m_xf.position;
  2043.    m_groundAnchor2 := def.groundAnchor2 - m_ground.m_xf.position;
  2044.    {$ELSE}
  2045.    m_groundAnchor1 := Subtract(def.groundAnchor1, m_ground.m_xf.position);
  2046.    m_groundAnchor2 := Subtract(def.groundAnchor2, m_ground.m_xf.position);
  2047.    {$ENDIF}
  2048.    m_localAnchor1 := def.localAnchor1;
  2049.    m_localAnchor2 := def.localAnchor2;
  2050.    //b2Assert(def.ratio != 0.0);
  2051.    m_ratio := def.ratio;
  2052.    m_constant := def.length1 + m_ratio * def.length2;
  2053.    m_maxLength1 := b2Min(def.maxLength1, m_constant - m_ratio * b2_minPulleyLength);
  2054.    m_maxLength2 := b2Min(def.maxLength2, (m_constant - b2_minPulleyLength) / m_ratio);
  2055.    m_force := 0.0;
  2056.    m_limitForce1 := 0.0;
  2057.    m_limitForce2 := 0.0;
  2058. end;
  2059. function Tb2PulleyJoint.GetAnchor1: TVector2;
  2060. begin
  2061.    Result := m_body1.GetWorldPoint(m_localAnchor1);
  2062. end;
  2063. function Tb2PulleyJoint.GetAnchor2: TVector2;
  2064. begin
  2065.    Result := m_body2.GetWorldPoint(m_localAnchor2);
  2066. end;
  2067. function Tb2PulleyJoint.GetReactionForce: TVector2;
  2068. begin
  2069.    {$IFDEF OP_OVERLOAD}
  2070.    Result := m_force * m_u2;
  2071.    {$ELSE}
  2072.    Result := Multiply(m_u2, m_force);
  2073.    {$ENDIF}
  2074. end;
  2075. function Tb2PulleyJoint.GetReactionTorque: Float;
  2076. begin
  2077.    Result := 0.0;
  2078. end;
  2079. procedure Tb2PulleyJoint.InitVelocityConstraints(const step: Tb2TimeStep);
  2080. var
  2081.    r1, r2, P1, P2: TVector2;
  2082.    length1, length2, C, cr1u1, cr2u2: Float;
  2083. begin
  2084.    {$IFDEF OP_OVERLOAD}
  2085.    r1 := b2Mul(m_body1.m_xf.R, m_localAnchor1 - m_body1.GetLocalCenter);
  2086.    r2 := b2Mul(m_body2.m_xf.R, m_localAnchor2 - m_body2.GetLocalCenter);
  2087.    // Get the pulley axes.
  2088.    m_u1 := m_body1.m_sweep.c + r1 - (m_ground.m_xf.position + m_groundAnchor1);
  2089.    m_u2 := m_body2.m_sweep.c + r2 - (m_ground.m_xf.position + m_groundAnchor2);
  2090.    length1 := m_u1.Length;
  2091.    length2 := m_u2.Length;
  2092.    if length1 > b2_linearSlop then
  2093.       m_u1.DivideBy(length1)
  2094.    else
  2095.       m_u1.SetZero;
  2096.    if length2 > b2_linearSlop then
  2097.       m_u2.DivideBy(length2)
  2098.    else
  2099.       m_u2.SetZero;
  2100.    {$ELSE}
  2101.    r1 := b2Mul(m_body1.m_xf.R, Subtract(m_localAnchor1, m_body1.GetLocalCenter));
  2102.    r2 := b2Mul(m_body2.m_xf.R, Subtract(m_localAnchor2, m_body2.GetLocalCenter));
  2103.    // Get the pulley axes.
  2104.    m_u1 := Subtract(Add(m_body1.m_sweep.c, r1), Add(m_ground.m_xf.position, m_groundAnchor1));
  2105.    m_u2 := Subtract(Add(m_body2.m_sweep.c, r2), Add(m_ground.m_xf.position, m_groundAnchor2));
  2106.    length1 := Length(m_u1);
  2107.    length2 := Length(m_u2);
  2108.    if length1 > b2_linearSlop then
  2109.       DivideBy(m_u1, length1)
  2110.    else
  2111.       SetZero(m_u1);
  2112.    if length2 > b2_linearSlop then
  2113.       DivideBy(m_u2, length2)
  2114.    else
  2115.       SetZero(m_u2);
  2116.    {$ENDIF}
  2117.    C := m_constant - length1 - m_ratio * length2;
  2118.    if C > 0.0 then
  2119.    begin
  2120.       m_state := e_inactiveLimit;
  2121.       m_force := 0.0;
  2122.    end
  2123.    else
  2124.    begin
  2125.       m_state := e_atUpperLimit;
  2126.       m_positionImpulse := 0.0;
  2127.    end;
  2128.    if length1 < m_maxLength1 then
  2129.    begin
  2130.       m_limitState1 := e_inactiveLimit;
  2131.       m_limitForce1 := 0.0;
  2132.    end
  2133.    else
  2134.    begin
  2135.       m_limitState1 := e_atUpperLimit;
  2136.       m_limitPositionImpulse1 := 0.0;
  2137.    end;
  2138.    if length2 < m_maxLength2 then
  2139.    begin
  2140.       m_limitState2 := e_inactiveLimit;
  2141.       m_limitForce2 := 0.0;
  2142.    end
  2143.    else
  2144.    begin
  2145.       m_limitState2 := e_atUpperLimit;
  2146.       m_limitPositionImpulse2 := 0.0;
  2147.    end;
  2148.    // Compute effective mass.
  2149.    cr1u1 := b2Cross(r1, m_u1);
  2150.    cr2u2 := b2Cross(r2, m_u2);
  2151.    m_limitMass1 := m_body1.m_invMass + m_body1.m_invI * cr1u1 * cr1u1;
  2152.    m_limitMass2 := m_body2.m_invMass + m_body2.m_invI * cr2u2 * cr2u2;
  2153.    m_pulleyMass := m_limitMass1 + m_ratio * m_ratio * m_limitMass2;
  2154.    //b2Assert(m_limitMass1 > B2_FLT_EPSILON);
  2155.    //b2Assert(m_limitMass2 > B2_FLT_EPSILON);
  2156.    //b2Assert(m_pulleyMass > B2_FLT_EPSILON);
  2157.    m_limitMass1 := 1.0 / m_limitMass1;
  2158.    m_limitMass2 := 1.0 / m_limitMass2;
  2159.    m_pulleyMass := 1.0 / m_pulleyMass;
  2160.    if step.warmStarting then
  2161.    begin
  2162.       // Warm starting.
  2163.       {$IFDEF OP_OVERLOAD}
  2164.       P1 := step.dt * (-m_force - m_limitForce1) * m_u1;
  2165.       P2 := step.dt * (-m_ratio * m_force - m_limitForce2) * m_u2;
  2166.       m_body1.m_linearVelocity.AddBy(m_body1.m_invMass * P1);
  2167.       m_body2.m_linearVelocity.AddBy(m_body2.m_invMass * P2);
  2168.       {$ELSE}
  2169.       P1 := Multiply(m_u1, -step.dt * (m_force + m_limitForce1));
  2170.       P2 := Multiply(m_u2, -step.dt * (m_ratio * m_force + m_limitForce2));
  2171.       AddBy(m_body1.m_linearVelocity, Multiply(P1, m_body1.m_invMass));
  2172.       AddBy(m_body2.m_linearVelocity, Multiply(P2, m_body2.m_invMass));
  2173.       {$ENDIF}
  2174.       m_body1.m_angularVelocity := m_body1.m_angularVelocity + m_body1.m_invI * b2Cross(r1, P1);
  2175.       m_body2.m_angularVelocity := m_body2.m_angularVelocity + m_body2.m_invI * b2Cross(r2, P2);
  2176.    end
  2177.    else
  2178.    begin
  2179.       m_force := 0.0;
  2180.       m_limitForce1 := 0.0;
  2181.       m_limitForce2 := 0.0;
  2182.    end;
  2183. end;
  2184. procedure Tb2PulleyJoint.SolveVelocityConstraints(const step: Tb2TimeStep);
  2185. var
  2186.    r1, r2, v1, v2, P1, P2: TVector2;
  2187.    Cdot, force, oldForce: Float;
  2188. begin
  2189.    {$IFDEF OP_OVERLOAD}
  2190.    r1 := b2Mul(m_body1.m_xf.R, m_localAnchor1 - m_body1.GetLocalCenter);
  2191.    r2 := b2Mul(m_body2.m_xf.R, m_localAnchor2 - m_body2.GetLocalCenter);
  2192.    {$ELSE}
  2193.    r1 := b2Mul(m_body1.m_xf.R, Subtract(m_localAnchor1, m_body1.GetLocalCenter));
  2194.    r2 := b2Mul(m_body2.m_xf.R, Subtract(m_localAnchor2, m_body2.GetLocalCenter));
  2195.    {$ENDIF}
  2196.    if m_state = e_atUpperLimit then
  2197.    begin
  2198.       {$IFDEF OP_OVERLOAD}
  2199.       v1 := m_body1.m_linearVelocity + b2Cross(m_body1.m_angularVelocity, r1);
  2200.       v2 := m_body2.m_linearVelocity + b2Cross(m_body2.m_angularVelocity, r2);
  2201.       {$ELSE}
  2202.       v1 := Add(m_body1.m_linearVelocity, b2Cross(m_body1.m_angularVelocity, r1));
  2203.       v2 := Add(m_body2.m_linearVelocity, b2Cross(m_body2.m_angularVelocity, r2));
  2204.       {$ENDIF}
  2205.       Cdot := -b2Dot(m_u1, v1) - m_ratio * b2Dot(m_u2, v2);
  2206.       force := -step.inv_dt * m_pulleyMass * Cdot;
  2207.       oldForce := m_force;
  2208.       m_force := b2Max(0.0, m_force + force);
  2209.       force := m_force - oldForce;
  2210.       {$IFDEF OP_OVERLOAD}
  2211.       P1 := -step.dt * force * m_u1;
  2212.       P2 := -step.dt * m_ratio * force * m_u2;
  2213.       m_body1.m_linearVelocity.AddBy(m_body1.m_invMass * P1);
  2214.       m_body2.m_linearVelocity.AddBy(m_body2.m_invMass * P2);
  2215.       {$ELSE}
  2216.       P1 := Multiply(m_u1, -step.dt * force);
  2217.       P2 := Multiply(m_u2, -step.dt * m_ratio * force);
  2218.       AddBy(m_body1.m_linearVelocity, Multiply(P1, m_body1.m_invMass));
  2219.       AddBy(m_body2.m_linearVelocity, Multiply(P2, m_body2.m_invMass));
  2220.       {$ENDIF}
  2221.       m_body1.m_angularVelocity := m_body1.m_angularVelocity + m_body1.m_invI * b2Cross(r1, P1);
  2222.       m_body2.m_angularVelocity := m_body2.m_angularVelocity + m_body2.m_invI * b2Cross(r2, P2);
  2223.    end;
  2224.    if m_limitState1 = e_atUpperLimit then
  2225.    begin
  2226.       {$IFDEF OP_OVERLOAD}
  2227.       v1 := m_body1.m_linearVelocity + b2Cross(m_body1.m_angularVelocity, r1);
  2228.       {$ELSE}
  2229.       v1 := Add(m_body1.m_linearVelocity, b2Cross(m_body1.m_angularVelocity, r1));
  2230.       {$ENDIF}
  2231.       Cdot := -b2Dot(m_u1, v1);
  2232.       force := -step.inv_dt * m_limitMass1 * Cdot;
  2233.       oldForce := m_limitForce1;
  2234.       m_limitForce1 := b2Max(0.0, m_limitForce1 + force);
  2235.       force := m_limitForce1 - oldForce;
  2236.       {$IFDEF OP_OVERLOAD}
  2237.       P1 := -step.dt * force * m_u1;
  2238.       m_body1.m_linearVelocity.AddBy(m_body1.m_invMass * P1);
  2239.       {$ELSE}
  2240.       P1 := Multiply(m_u1, -step.dt * force);
  2241.       AddBy(m_body1.m_linearVelocity, Multiply(P1, m_body1.m_invMass));
  2242.       {$ENDIF}
  2243.       m_body1.m_angularVelocity := m_body1.m_angularVelocity + m_body1.m_invI * b2Cross(r1, P1);
  2244.    end;
  2245.    if m_limitState2 = e_atUpperLimit then
  2246.    begin
  2247.       {$IFDEF OP_OVERLOAD}
  2248.       v2 := m_body2.m_linearVelocity + b2Cross(m_body2.m_angularVelocity, r2);
  2249.       {$ELSE}
  2250.       v2 := Add(m_body2.m_linearVelocity, b2Cross(m_body2.m_angularVelocity, r2));
  2251.       {$ENDIF}
  2252.       Cdot := -b2Dot(m_u2, v2);
  2253.       force := -step.inv_dt * m_limitMass2 * Cdot;
  2254.       oldForce := m_limitForce2;
  2255.       m_limitForce2 := b2Max(0.0, m_limitForce2 + force);
  2256.       force := m_limitForce2 - oldForce;
  2257.       {$IFDEF OP_OVERLOAD}
  2258.       P2 := -step.dt * force * m_u2;
  2259.       m_body2.m_linearVelocity.AddBy(m_body2.m_invMass * P2);
  2260.       {$ELSE}
  2261.       P2 := Multiply(m_u2, -step.dt * force);
  2262.       AddBy(m_body2.m_linearVelocity, Multiply(P2, m_body2.m_invMass));
  2263.       {$ENDIF}
  2264.       m_body2.m_angularVelocity := m_body2.m_angularVelocity + m_body2.m_invI * b2Cross(r2, P2);
  2265.    end;
  2266. end;
  2267. function Tb2PulleyJoint.SolvePositionConstraints: Boolean;
  2268. var
  2269.    s1, s2, r1, r2, P1, P2: TVector2;
  2270.    linearError, length1, length2, C, impulse, oldImpulse, oldLimitPositionImpulse: Float;
  2271. begin
  2272.    {$IFDEF OP_OVERLOAD}
  2273.    s1 := m_ground.m_xf.position + m_groundAnchor1;
  2274.    s2 := m_ground.m_xf.position + m_groundAnchor2;
  2275.    {$ELSE}
  2276.    s1 := Add(m_ground.m_xf.position, m_groundAnchor1);
  2277.    s2 := Add(m_ground.m_xf.position, m_groundAnchor2);
  2278.    {$ENDIF}
  2279.    linearError := 0.0;
  2280.    if m_state = e_atUpperLimit then
  2281.    begin
  2282.       {$IFDEF OP_OVERLOAD}
  2283.       r1 := b2Mul(m_body1.m_xf.R, m_localAnchor1 - m_body1.GetLocalCenter);
  2284.       r2 := b2Mul(m_body2.m_xf.R, m_localAnchor2 - m_body2.GetLocalCenter);
  2285.       // Get the pulley axes.
  2286.       m_u1 := m_body1.m_sweep.c + r1 - s1;
  2287.       m_u2 := m_body2.m_sweep.c + r2 - s2;
  2288.       length1 := m_u1.Length;
  2289.       length2 := m_u2.Length;
  2290.       if length1 > b2_linearSlop then
  2291.          m_u1.DivideBy(length1)
  2292.       else
  2293.          m_u1.SetZero;
  2294.       if length2 > b2_linearSlop then
  2295.          m_u2.DivideBy(length2)
  2296.       else
  2297.          m_u2.SetZero;
  2298.       {$ELSE}
  2299.       r1 := b2Mul(m_body1.m_xf.R, Subtract(m_localAnchor1, m_body1.GetLocalCenter));
  2300.       r2 := b2Mul(m_body2.m_xf.R, Subtract(m_localAnchor2, m_body2.GetLocalCenter));
  2301.       // Get the pulley axes.
  2302.       m_u1 := Subtract(Add(m_body1.m_sweep.c, r1), s1);
  2303.       m_u2 := Subtract(Add(m_body2.m_sweep.c, r2), s2);
  2304.       length1 := Length(m_u1);
  2305.       length2 := Length(m_u2);
  2306.       if length1 > b2_linearSlop then
  2307.          DivideBy(m_u1, length1)
  2308.       else
  2309.          SetZero(m_u1);
  2310.       if length2 > b2_linearSlop then
  2311.          DivideBy(m_u2, length2)
  2312.       else
  2313.          SetZero(m_u2);
  2314.       {$ENDIF}
  2315.       C := m_constant - length1 - m_ratio * length2;
  2316.       linearError := b2Max(linearError, -C);
  2317.       C := b2Clamp(C + b2_linearSlop, -b2_maxLinearCorrection, 0.0);
  2318.       impulse := -m_pulleyMass * C;
  2319.       oldImpulse := m_positionImpulse;
  2320.       m_positionImpulse := b2Max(0.0, m_positionImpulse + impulse);
  2321.       impulse := m_positionImpulse - oldImpulse;
  2322.       {$IFDEF OP_OVERLOAD}
  2323.       P1 := -impulse * m_u1;
  2324.       P2 := -m_ratio * impulse * m_u2;
  2325.       m_body1.m_sweep.c.AddBy(m_body1.m_invMass * P1);
  2326.       m_body2.m_sweep.c.AddBy(m_body2.m_invMass * P2);
  2327.       {$ELSE}
  2328.       P1 := Multiply(m_u1, -impulse);
  2329.       P2 := Multiply(m_u2, -m_ratio * impulse);
  2330.       AddBy(m_body1.m_sweep.c, Multiply(P1, m_body1.m_invMass));
  2331.       AddBy(m_body2.m_sweep.c, Multiply(P2, m_body2.m_invMass));
  2332.       {$ENDIF}
  2333.       m_body1.m_sweep.a := m_body1.m_sweep.a + m_body1.m_invI * b2Cross(r1, P1);
  2334.       m_body2.m_sweep.a := m_body2.m_sweep.a + m_body2.m_invI * b2Cross(r2, P2);
  2335.       m_body1.SynchronizeTransform;
  2336.       m_body2.SynchronizeTransform;
  2337.    end;
  2338.    if m_limitState1 = e_atUpperLimit then
  2339.    begin
  2340.       {$IFDEF OP_OVERLOAD}
  2341.       r1 := b2Mul(m_body1.m_xf.R, m_localAnchor1 - m_body1.GetLocalCenter);
  2342.       p1 := m_body1.m_sweep.c + r1;
  2343.       m_u1 := p1 - s1;
  2344.       length1 := m_u1.Length;
  2345.       if length1 > b2_linearSlop then
  2346.          m_u1.DivideBy(length1)
  2347.       else
  2348.          m_u1.SetZero;
  2349.       {$ELSE}
  2350.       r1 := b2Mul(m_body1.m_xf.R, Subtract(m_localAnchor1, m_body1.GetLocalCenter));
  2351.       p1 := Add(m_body1.m_sweep.c, r1);
  2352.       m_u1 := Subtract(p1, s1);
  2353.       length1 := Length(m_u1);
  2354.       if length1 > b2_linearSlop then
  2355.          DivideBy(m_u1, length1)
  2356.       else
  2357.          SetZero(m_u1);
  2358.       {$ENDIF}
  2359.       C := m_maxLength1 - length1;
  2360.       linearError := b2Max(linearError, -C);
  2361.       C := b2Clamp(C + b2_linearSlop, -b2_maxLinearCorrection, 0.0);
  2362.       impulse := -m_limitMass1 * C;
  2363.       oldLimitPositionImpulse := m_limitPositionImpulse1;
  2364.       m_limitPositionImpulse1 := b2Max(0.0, m_limitPositionImpulse1 + impulse);
  2365.       impulse := m_limitPositionImpulse1 - oldLimitPositionImpulse;
  2366.       {$IFDEF OP_OVERLOAD}
  2367.       P1 := -impulse * m_u1;
  2368.       m_body1.m_sweep.c.AddBy(m_body1.m_invMass * P1);
  2369.       {$ELSE}
  2370.       P1 := Multiply(m_u1, -impulse);
  2371.       AddBy(m_body1.m_sweep.c, Multiply(P1, m_body1.m_invMass));
  2372.       {$ENDIF}
  2373.       m_body1.m_sweep.a := m_body1.m_sweep.a + m_body1.m_invI * b2Cross(r1, P1);
  2374.       m_body1.SynchronizeTransform;
  2375.    end;
  2376.    if m_limitState2 = e_atUpperLimit then
  2377.    begin
  2378.       {$IFDEF OP_OVERLOAD}
  2379.       r2 := b2Mul(m_body2.m_xf.R, m_localAnchor2 - m_body2.GetLocalCenter);
  2380.       p2 := m_body2.m_sweep.c + r2;
  2381.       m_u2 := p2 - s2;
  2382.       length2 := m_u2.Length;
  2383.       if length2 > b2_linearSlop then
  2384.          m_u2.DivideBy(length2)
  2385.       else
  2386.          m_u2.SetZero;
  2387.       {$ELSE}
  2388.       r2 := b2Mul(m_body2.m_xf.R, Subtract(m_localAnchor2, m_body2.GetLocalCenter));
  2389.       p2 := Add(m_body2.m_sweep.c, r2);
  2390.       m_u2 := Subtract(p2, s2);
  2391.       length2 := Length(m_u2);
  2392.       if length2 > b2_linearSlop then
  2393.          DivideBy(m_u2, length2)
  2394.       else
  2395.          SetZero(m_u2);
  2396.       {$ENDIF}
  2397.       C := m_maxLength2 - length2;
  2398.       linearError := b2Max(linearError, -C);
  2399.       C := b2Clamp(C + b2_linearSlop, -b2_maxLinearCorrection, 0.0);
  2400.       impulse := -m_limitMass2 * C;
  2401.       oldLimitPositionImpulse := m_limitPositionImpulse2;
  2402.       m_limitPositionImpulse2 := b2Max(0.0, m_limitPositionImpulse2 + impulse);
  2403.       impulse := m_limitPositionImpulse2 - oldLimitPositionImpulse;
  2404.       {$IFDEF OP_OVERLOAD}
  2405.       P2 := -impulse * m_u2;
  2406.       m_body2.m_sweep.c.AddBy(m_body2.m_invMass * P2);
  2407.       {$ELSE}
  2408.       P2 := Multiply(m_u2, -impulse);
  2409.       AddBy(m_body2.m_sweep.c, Multiply(P2, m_body2.m_invMass));
  2410.       {$ENDIF}
  2411.       m_body2.m_sweep.a := m_body2.m_sweep.a + m_body2.m_invI * b2Cross(r2, P2);
  2412.       m_body2.SynchronizeTransform;
  2413.    end;
  2414.    Result := linearError < b2_linearSlop;
  2415. end;
  2416. function Tb2PulleyJoint.GetLength1: Float;
  2417. begin
  2418.    {$IFDEF OP_OVERLOAD}
  2419.    Result := (m_body1.GetWorldPoint(m_localAnchor1) - (m_ground.m_xf.position +
  2420.       m_groundAnchor1)).Length;
  2421.    {$ELSE}
  2422.    Result := Length(Subtract(m_body1.GetWorldPoint(m_localAnchor1),
  2423.       Add(m_ground.m_xf.position, m_groundAnchor1)));
  2424.    {$ENDIF}
  2425. end;
  2426. function Tb2PulleyJoint.GetLength2: Float;
  2427. begin
  2428.    {$IFDEF OP_OVERLOAD}
  2429.    Result := (m_body2.GetWorldPoint(m_localAnchor2) - (m_ground.m_xf.position +
  2430.       m_groundAnchor2)).Length;
  2431.    {$ELSE}
  2432.    Result := Length(Subtract(m_body2.GetWorldPoint(m_localAnchor2),
  2433.       Add(m_ground.m_xf.position, m_groundAnchor2)));
  2434.    {$ENDIF}
  2435. end;
  2436. function Tb2PulleyJoint.GetGroundAnchor1: TVector2;
  2437. begin
  2438.    {$IFDEF OP_OVERLOAD}
  2439.    Result := m_ground.m_xf.position + m_groundAnchor1;
  2440.    {$ELSE}
  2441.    Result := Add(m_ground.m_xf.position, m_groundAnchor1);
  2442.    {$ENDIF}
  2443. end;
  2444. function Tb2PulleyJoint.GetGroundAnchor2: TVector2;
  2445. begin
  2446.    {$IFDEF OP_OVERLOAD}
  2447.    Result := m_ground.m_xf.position + m_groundAnchor2;
  2448.    {$ELSE}
  2449.    Result := Add(m_ground.m_xf.position, m_groundAnchor2);
  2450.    {$ENDIF}
  2451. end;
  2452. { Tb2RevoluteJointDef }
  2453. // Point-to-point constraint
  2454. // C = p2 - p1
  2455. // Cdot = v2 - v1
  2456. //      = v2 + cross(w2, r2) - v1 - cross(w1, r1)
  2457. // J = [-I -r1_skew I r2_skew ]
  2458. // Identity used:
  2459. // w k % (rx i + ry j) = w * (-ry i + rx j)
  2460. // Motor constraint
  2461. // Cdot = w2 - w1
  2462. // J = [0 0 -1 0 0 1]
  2463. // K = invI1 + invI2
  2464. constructor Tb2RevoluteJointDef.Create;
  2465. begin
  2466.    JointType := e_revoluteJoint;
  2467.    SetZero(localAnchor1);
  2468.    SetZero(localAnchor2);
  2469.    referenceAngle := 0.0;
  2470.    lowerAngle := 0.0;
  2471.    upperAngle := 0.0;
  2472.    maxMotorTorque := 0.0;
  2473.    motorSpeed := 0.0;
  2474.    enableLimit := False;
  2475.    enableMotor := False;
  2476. end;
  2477. procedure Tb2RevoluteJointDef.Initialize(body1, body2: Tb2Body; const anchor: TVector2);
  2478. begin
  2479.    Self.body1 := body1;
  2480.  Self.body2 := body2;
  2481.  localAnchor1 := body1.GetLocalPoint(anchor);
  2482.  localAnchor2 := body2.GetLocalPoint(anchor);
  2483.  referenceAngle := body2.GetAngle - body1.GetAngle;
  2484. end;
  2485. { Tb2RevoluteJoint }
  2486. constructor Tb2RevoluteJoint.Create(def: Tb2RevoluteJointDef);
  2487. begin
  2488.    inherited Create(def);
  2489.    m_localAnchor1 := def.localAnchor1;
  2490.    m_localAnchor2 := def.localAnchor2;
  2491.    m_referenceAngle := def.referenceAngle;
  2492.    SetZero(m_pivotForce);
  2493.    m_motorForce := 0.0;
  2494.    m_limitForce := 0.0;
  2495.    m_limitPositionImpulse := 0.0;
  2496.    m_lowerAngle := def.lowerAngle;
  2497.    m_upperAngle := def.upperAngle;
  2498.    m_maxMotorTorque := def.maxMotorTorque;
  2499.    m_motorSpeed := def.motorSpeed;
  2500.    m_enableLimit := def.enableLimit;
  2501.    m_enableMotor := def.enableMotor;
  2502. end;
  2503. function Tb2RevoluteJoint.GetAnchor1: TVector2;
  2504. begin
  2505.    Result := m_body1.GetWorldPoint(m_localAnchor1);
  2506. end;
  2507. function Tb2RevoluteJoint.GetAnchor2: TVector2;
  2508. begin
  2509.    Result := m_body2.GetWorldPoint(m_localAnchor2);
  2510. end;
  2511. function Tb2RevoluteJoint.GetReactionForce: TVector2;
  2512. begin
  2513.    Result := m_pivotForce;
  2514. end;
  2515. function Tb2RevoluteJoint.GetReactionTorque: Float;
  2516. begin
  2517.    Result := m_limitForce;
  2518. end;
  2519. procedure Tb2RevoluteJoint.InitVelocityConstraints(const step: Tb2TimeStep);
  2520. var
  2521.    r1, r2: TVector2;
  2522.    K1, K2, K3, K: TMatrix22;
  2523.    jointAngle: Float;
  2524.    tmp: Float;
  2525. begin
  2526.    // Compute the effective mass matrix.
  2527.    {$IFDEF OP_OVERLOAD}
  2528.    r1 := b2Mul(m_body1.m_xf.R, m_localAnchor1 - m_body1.GetLocalCenter);
  2529.    r2 := b2Mul(m_body2.m_xf.R, m_localAnchor2 - m_body2.GetLocalCenter);
  2530.    {$ELSE}
  2531.    r1 := b2Mul(m_body1.m_xf.R, Subtract(m_localAnchor1, m_body1.GetLocalCenter));
  2532.    r2 := b2Mul(m_body2.m_xf.R, Subtract(m_localAnchor2, m_body2.GetLocalCenter));
  2533.    {$ENDIF}
  2534.    // K    := [(1/m1 + 1/m2) * eye(2) - skew(r1) * invI1 * skew(r1) - skew(r2) * invI2 * skew(r2)]
  2535.    //      := [1/m1+1/m2     0    ] + invI1 * [r1.y*r1.y -r1.x*r1.y] + invI2 * [r1.y*r1.y -r1.x*r1.y]
  2536.    //        [    0     1/m1+1/m2]           [-r1.x*r1.y r1.x*r1.x]           [-r1.x*r1.y r1.x*r1.x]
  2537.    K1.col1.x := m_body1.m_invMass + m_body2.m_invMass;
  2538.    K1.col2.x := 0.0;
  2539.    K1.col1.y := 0.0;
  2540.    K1.col2.y := K1.col1.x;
  2541.    tmp := m_body1.m_invI;
  2542.    K2.col1.x := tmp * r1.y * r1.y;
  2543.    tmp := tmp * r1.x;
  2544.    K2.col2.x := -tmp * r1.y;
  2545.    K2.col1.y := K2.col2.x;
  2546.    K2.col2.y := tmp * r1.x;
  2547.    tmp := m_body2.m_invI;
  2548.    K3.col1.x := tmp * r2.y * r2.y;
  2549.    tmp := tmp * r2.x;
  2550.    K3.col2.x := -tmp * r2.y;
  2551.    K3.col1.y := K3.col2.x;
  2552.    K3.col2.y := tmp * r2.x;
  2553.    {$IFDEF OP_OVERLOAD}
  2554.    K := K1 + K2 + K3;
  2555.    m_pivotMass := K.Invert;
  2556.    {$ELSE}
  2557.    K := Add(K1, K2, K3);
  2558.    m_pivotMass := Invert(K);
  2559.    {$ENDIF}
  2560.    m_motorMass := 1.0 / (m_body1.m_invI + m_body2.m_invI);
  2561.    if not m_enableMotor then
  2562.       m_motorForce := 0.0;
  2563.    if m_enableLimit then
  2564.    begin
  2565.       jointAngle := m_body2.m_sweep.a - m_body1.m_sweep.a - m_referenceAngle;
  2566.       if Abs(m_upperAngle - m_lowerAngle) < 2.0 * b2_angularSlop then
  2567.          m_limitState := e_equalLimits
  2568.       else if jointAngle <= m_lowerAngle then
  2569.       begin
  2570.          if m_limitState <> e_atLowerLimit then
  2571.             m_limitForce := 0.0;
  2572.          m_limitState := e_atLowerLimit;
  2573.       end
  2574.       else if jointAngle >= m_upperAngle then
  2575.       begin
  2576.          if m_limitState <> e_atUpperLimit then
  2577.             m_limitForce := 0.0;
  2578.          m_limitState := e_atUpperLimit;
  2579.       end
  2580.       else
  2581.       begin
  2582.          m_limitState := e_inactiveLimit;
  2583.          m_limitForce := 0.0;
  2584.       end;
  2585.    end
  2586.    else
  2587.       m_limitForce := 0.0;
  2588.    if step.warmStarting then
  2589.    begin
  2590.       {$IFDEF OP_OVERLOAD}
  2591.       m_body1.m_linearVelocity.SubtractBy(step.dt * m_body1.m_invMass * m_pivotForce);
  2592.       m_body2.m_linearVelocity.AddBy(step.dt * m_body2.m_invMass * m_pivotForce);
  2593.       {$ELSE}
  2594.       SubtractBy(m_body1.m_linearVelocity, Multiply(m_pivotForce, step.dt * m_body1.m_invMass));
  2595.       AddBy(m_body2.m_linearVelocity, Multiply(m_pivotForce, step.dt * m_body2.m_invMass));
  2596.       {$ENDIF}
  2597.       m_body1.m_angularVelocity := m_body1.m_angularVelocity - step.dt * m_body1.m_invI *
  2598.          (b2Cross(r1, m_pivotForce) + m_motorForce + m_limitForce);
  2599.       m_body2.m_angularVelocity := m_body2.m_angularVelocity + step.dt * m_body2.m_invI *
  2600.          (b2Cross(r2, m_pivotForce) + m_motorForce + m_limitForce);
  2601.    end
  2602.    else
  2603.    begin
  2604.       SetZero(m_pivotForce);
  2605.       m_motorForce := 0.0;
  2606.       m_limitForce := 0.0;
  2607.    end;
  2608.    m_limitPositionImpulse := 0.0;
  2609. end;
  2610. procedure Tb2RevoluteJoint.SolveVelocityConstraints(const step: Tb2TimeStep);
  2611. var
  2612.    r1, r2, pivotCdot, pivotForce, P: TVector2;
  2613.    motorCdot, motorForce, oldMotorForce, limitCdot, limitForce, oldLimitForce, tmp: Float;
  2614. begin
  2615.    {$IFDEF OP_OVERLOAD}
  2616.    r1 := b2Mul(m_body1.m_xf.R, m_localAnchor1 - m_body1.GetLocalCenter);
  2617.    r2 := b2Mul(m_body2.m_xf.R, m_localAnchor2 - m_body2.GetLocalCenter);
  2618.    // Solve point-to-point constraint
  2619.    pivotCdot := m_body2.m_linearVelocity + b2Cross(m_body2.m_angularVelocity, r2) -
  2620.       m_body1.m_linearVelocity - b2Cross(m_body1.m_angularVelocity, r1);
  2621.    pivotForce := -step.inv_dt * b2Mul(m_pivotMass, pivotCdot);
  2622.    m_pivotForce.AddBy(pivotForce);
  2623.    P := step.dt * pivotForce;
  2624.    m_body1.m_linearVelocity.SubtractBy(m_body1.m_invMass * P);
  2625.    m_body2.m_linearVelocity.AddBy(m_body2.m_invMass * P);
  2626.    {$ELSE}
  2627.    r1 := b2Mul(m_body1.m_xf.R, Subtract(m_localAnchor1, m_body1.GetLocalCenter));
  2628.    r2 := b2Mul(m_body2.m_xf.R, Subtract(m_localAnchor2, m_body2.GetLocalCenter));
  2629.    // Solve point-to-point constraint
  2630.    pivotCdot := Subtract(m_body2.m_linearVelocity, m_body1.m_linearVelocity);
  2631.    AddBy(pivotCdot, b2Cross(m_body2.m_angularVelocity, r2));
  2632.    SubtractBy(pivotCdot, b2Cross(m_body1.m_angularVelocity, r1));
  2633.    pivotForce := Multiply(b2Mul(m_pivotMass, pivotCdot), -step.inv_dt);
  2634.    AddBy(m_pivotForce, pivotForce);
  2635.    P := Multiply(pivotForce, step.dt);
  2636.    SubtractBy(m_body1.m_linearVelocity, Multiply(P, m_body1.m_invMass));
  2637.    AddBy(m_body2.m_linearVelocity, Multiply(P, m_body2.m_invMass));
  2638.    {$ENDIF}
  2639.    m_body1.m_angularVelocity := m_body1.m_angularVelocity - m_body1.m_invI * b2Cross(r1, P);
  2640.    m_body2.m_angularVelocity := m_body2.m_angularVelocity + m_body2.m_invI * b2Cross(r2, P);
  2641.    if m_enableMotor and (m_limitState <> e_equalLimits) then
  2642.    begin
  2643.       motorCdot := m_body2.m_angularVelocity - m_body1.m_angularVelocity - m_motorSpeed;
  2644.       motorForce := -step.inv_dt * m_motorMass * motorCdot;
  2645.       oldMotorForce := m_motorForce;
  2646.       m_motorForce := b2Clamp(m_motorForce + motorForce, -m_maxMotorTorque, m_maxMotorTorque);
  2647.       motorForce := m_motorForce - oldMotorForce;
  2648.       tmp := step.dt * motorForce;
  2649.       m_body1.m_angularVelocity := m_body1.m_angularVelocity - m_body1.m_invI * tmp;
  2650.       m_body2.m_angularVelocity := m_body2.m_angularVelocity + m_body2.m_invI * tmp;
  2651.    end;
  2652.    if m_enableLimit and (m_limitState <> e_inactiveLimit) then
  2653.    begin
  2654.       limitCdot := m_body2.m_angularVelocity - m_body1.m_angularVelocity;
  2655.       limitForce := -step.inv_dt * m_motorMass * limitCdot;
  2656.       if m_limitState = e_equalLimits then
  2657.          m_limitForce := m_limitForce + limitForce
  2658.       else if m_limitState = e_atLowerLimit then
  2659.       begin
  2660.          oldLimitForce := m_limitForce;
  2661.          m_limitForce := b2Max(m_limitForce + limitForce, 0.0);
  2662.          limitForce := m_limitForce - oldLimitForce;
  2663.       end
  2664.       else if m_limitState = e_atUpperLimit then
  2665.       begin
  2666.          oldLimitForce := m_limitForce;
  2667.          m_limitForce := b2Min(m_limitForce + limitForce, 0.0);
  2668.          limitForce := m_limitForce - oldLimitForce;
  2669.       end;
  2670.       tmp := step.dt * limitForce;
  2671.       m_body1.m_angularVelocity := m_body1.m_angularVelocity - m_body1.m_invI * tmp;
  2672.       m_body2.m_angularVelocity := m_body2.m_angularVelocity + m_body2.m_invI * tmp;
  2673.    end;
  2674. end;
  2675. function Tb2RevoluteJoint.SolvePositionConstraints: Boolean;
  2676. var
  2677.    positionError, angularError, angle, limitImpulse, limitC, oldLimitImpulse: Float;
  2678.    r1, r2, ptpC, impulse: TVector2;
  2679.    K1, K2, K3, K: TMatrix22;
  2680.    tmp: Float;
  2681. begin
  2682.    positionError := 0.0;
  2683.    // Solve point-to-point position error.
  2684.    {$IFDEF OP_OVERLOAD}
  2685.    r1 := b2Mul(m_body1.m_xf.R, m_localAnchor1 - m_body1.GetLocalCenter);
  2686.    r2 := b2Mul(m_body2.m_xf.R, m_localAnchor2 - m_body2.GetLocalCenter);
  2687.    ptpC := m_body2.m_sweep.c + r2 - (m_body1.m_sweep.c + r1);
  2688.    positionError := ptpC.Length;
  2689.    {$ELSE}
  2690.    r1 := b2Mul(m_body1.m_xf.R, Subtract(m_localAnchor1, m_body1.GetLocalCenter));
  2691.    r2 := b2Mul(m_body2.m_xf.R, Subtract(m_localAnchor2, m_body2.GetLocalCenter));
  2692.    ptpC := Subtract(Add(m_body2.m_sweep.c, r2), Add(m_body1.m_sweep.c, r1));
  2693.    positionError := Length(ptpC);
  2694.    {$ENDIF}
  2695.    // Prevent overly large corrections.
  2696.    //b2Vec2 dpMax(b2_maxLinearCorrection, b2_maxLinearCorrection);
  2697.    //ptpC := b2Clamp(ptpC, -dpMax, dpMax);
  2698.    K1.col1.x := m_body1.m_invMass + m_body2.m_invMass;
  2699.    K1.col2.x := 0.0;
  2700.    K1.col1.y := 0.0;
  2701.    K1.col2.y := K1.col1.x;
  2702.    tmp := m_body1.m_invI;
  2703.    K2.col1.x := tmp * r1.y * r1.y;
  2704.    tmp := tmp * r1.x;
  2705.    K2.col2.x := -tmp * r1.y;
  2706.    K2.col1.y := K2.col2.x;
  2707.    K2.col2.y := tmp * r1.x;
  2708.    tmp := m_body2.m_invI;
  2709.    K3.col1.x := tmp * r2.y * r2.y;
  2710.    tmp := tmp * r2.x;
  2711.    K3.col2.x := -tmp * r2.y;
  2712.    K3.col1.y := K3.col2.x;
  2713.    K3.col2.y := tmp * r2.x;
  2714.    {$IFDEF OP_OVERLOAD}
  2715.    K := K1 + K2 + K3;
  2716.    impulse := K.Solve(-ptpC);
  2717.    m_body1.m_sweep.c.SubtractBy(m_body1.m_invMass * impulse);
  2718.    m_body2.m_sweep.c.AddBy(m_body2.m_invMass * impulse);
  2719.    {$ELSE}
  2720.    K := Add(K1, K2, K3);
  2721.    impulse := Solve(K, Negative(ptpC));
  2722.    SubtractBy(m_body1.m_sweep.c, Multiply(impulse, m_body1.m_invMass));
  2723.    AddBy(m_body2.m_sweep.c, Multiply(impulse, m_body2.m_invMass));
  2724.    {$ENDIF}
  2725.    m_body1.m_sweep.a := m_body1.m_sweep.a - m_body1.m_invI * b2Cross(r1, impulse);
  2726.    m_body2.m_sweep.a := m_body2.m_sweep.a + m_body2.m_invI * b2Cross(r2, impulse);
  2727.    m_body1.SynchronizeTransform;
  2728.    m_body2.SynchronizeTransform;
  2729.    // Handle limits.
  2730.    angularError := 0.0;
  2731.    if m_enableLimit and (m_limitState <> e_inactiveLimit) then
  2732.    begin
  2733.       angle := m_body2.m_sweep.a - m_body1.m_sweep.a - m_referenceAngle;
  2734.       limitImpulse := 0.0;
  2735.       if m_limitState = e_equalLimits then
  2736.       begin
  2737.          // Prevent large angular corrections
  2738.          limitC := b2Clamp(angle, -b2_maxAngularCorrection, b2_maxAngularCorrection);
  2739.          limitImpulse := -m_motorMass * limitC;
  2740.          angularError := Abs(limitC);
  2741.       end
  2742.       else if m_limitState = e_atLowerLimit then
  2743.       begin
  2744.          limitC := angle - m_lowerAngle;
  2745.          angularError := b2Max(0.0, -limitC);
  2746.          // Prevent large angular corrections and allow some slop.
  2747.          limitC := b2Clamp(limitC + b2_angularSlop, -b2_maxAngularCorrection, 0.0);
  2748.          limitImpulse := -m_motorMass * limitC;
  2749.          oldLimitImpulse := m_limitPositionImpulse;
  2750.          m_limitPositionImpulse := b2Max(m_limitPositionImpulse + limitImpulse, 0.0);
  2751.          limitImpulse := m_limitPositionImpulse - oldLimitImpulse;
  2752.       end
  2753.       else if m_limitState = e_atUpperLimit then
  2754.       begin
  2755.          limitC := angle - m_upperAngle;
  2756.          angularError := b2Max(0.0, limitC);
  2757.          // Prevent large angular corrections and allow some slop.
  2758.          limitC := b2Clamp(limitC - b2_angularSlop, 0.0, b2_maxAngularCorrection);
  2759.          limitImpulse := -m_motorMass * limitC;
  2760.          oldLimitImpulse := m_limitPositionImpulse;
  2761.          m_limitPositionImpulse := b2Min(m_limitPositionImpulse + limitImpulse, 0.0);
  2762.          limitImpulse := m_limitPositionImpulse - oldLimitImpulse;
  2763.       end;
  2764.       m_body1.m_sweep.a := m_body1.m_sweep.a - m_body1.m_invI * limitImpulse;
  2765.       m_body2.m_sweep.a := m_body2.m_sweep.a + m_body2.m_invI * limitImpulse;
  2766.       m_body1.SynchronizeTransform;
  2767.       m_body2.SynchronizeTransform;
  2768.    end;
  2769.    Result := (positionError <= b2_linearSlop) and (angularError <= b2_angularSlop);
  2770. end;
  2771. function Tb2RevoluteJoint.GetJointAngle: Float;
  2772. begin
  2773.  Result := m_body2.m_sweep.a - m_body1.m_sweep.a - m_referenceAngle;
  2774. end;
  2775. function Tb2RevoluteJoint.GetJointSpeed: Float;
  2776. begin
  2777.  Result := m_body2.m_angularVelocity - m_body1.m_angularVelocity;
  2778. end;
  2779. { Tb2GearJointDef }
  2780. // Gear Joint:
  2781. // C0 = (coordinate1 + ratio * coordinate2)_initial
  2782. // C = C0 - (cordinate1 + ratio * coordinate2) = 0
  2783. // Cdot = -(Cdot1 + ratio * Cdot2)
  2784. // J = -[J1 ratio * J2]
  2785. // K = J * invM * JT
  2786. //   = J1 * invM1 * J1T + ratio * ratio * J2 * invM2 * J2T
  2787. //
  2788. // Revolute:
  2789. // coordinate = rotation
  2790. // Cdot = angularVelocity
  2791. // J = [0 0 1]
  2792. // K = J * invM * JT = invI
  2793. //
  2794. // Prismatic:
  2795. // coordinate = dot(p - pg, ug)
  2796. // Cdot = dot(v + cross(w, r), ug)
  2797. // J = [ug cross(r, ug)]
  2798. // K = J * invM * JT = invMass + invI * cross(r, ug)^2
  2799. constructor Tb2GearJointDef.Create;
  2800. begin
  2801.  JointType := e_gearJoint;
  2802.  joint1 := nil;
  2803.  joint2 := nil;
  2804.  ratio := 1.0;
  2805. end;
  2806. { Tb2GearJoint }
  2807. constructor Tb2GearJoint.Create(def: Tb2GearJointDef);
  2808. var
  2809.    type1, type2: Tb2JointType;
  2810.    coordinate1, coordinate2: Float;
  2811. begin
  2812.    inherited Create(def);
  2813.    type1 := def.joint1.GetType;
  2814.    type2 := def.joint2.GetType;
  2815.    //b2Assert(type1 == e_revoluteJoint || type1 == e_prismaticJoint);
  2816.    //b2Assert(type2 == e_revoluteJoint || type2 == e_prismaticJoint);
  2817.    //b2Assert(def.joint1.GetBody1().IsStatic());
  2818.    //b2Assert(def.joint2.GetBody1().IsStatic());
  2819.    m_revolute1 := nil;
  2820.    m_prismatic1 := nil;
  2821.    m_revolute2 := nil;
  2822.    m_prismatic2 := nil;
  2823.    m_ground1 := def.joint1.GetBody1;
  2824.    m_body1 := def.joint1.GetBody2;
  2825.    if type1 = e_revoluteJoint then
  2826.    begin
  2827.       m_revolute1 := Tb2RevoluteJoint(def.joint1);
  2828.       m_groundAnchor1 := m_revolute1.m_localAnchor1;
  2829.       m_localAnchor1 := m_revolute1.m_localAnchor2;
  2830.       coordinate1 := m_revolute1.GetJointAngle;
  2831.    end
  2832.    else
  2833.    begin
  2834.       m_prismatic1 := Tb2PrismaticJoint(def.joint1);
  2835.       m_groundAnchor1 := m_prismatic1.m_localAnchor1;
  2836.       m_localAnchor1 := m_prismatic1.m_localAnchor2;
  2837.       coordinate1 := m_prismatic1.GetJointTranslation;
  2838.    end;
  2839.    m_ground2 := def.joint2.GetBody1;
  2840.    m_body2 := def.joint2.GetBody2;
  2841.    if type2 = e_revoluteJoint then
  2842.    begin
  2843.       m_revolute2 := Tb2RevoluteJoint(def.joint2);
  2844.       m_groundAnchor2 := m_revolute2.m_localAnchor1;
  2845.       m_localAnchor2 := m_revolute2.m_localAnchor2;
  2846.       coordinate2 := m_revolute2.GetJointAngle;
  2847.    end
  2848.    else
  2849.    begin
  2850.       m_prismatic2 := Tb2PrismaticJoint(def.joint2);
  2851.       m_groundAnchor2 := m_prismatic2.m_localAnchor1;
  2852.       m_localAnchor2 := m_prismatic2.m_localAnchor2;
  2853.       coordinate2 := m_prismatic2.GetJointTranslation;
  2854.    end;
  2855.    m_ratio := def.ratio;
  2856.    m_constant := coordinate1 + m_ratio * coordinate2;
  2857.    m_force := 0.0;
  2858. end;
  2859. function Tb2GearJoint.GetAnchor1: TVector2;
  2860. begin
  2861.    Result := m_body1.GetWorldPoint(m_localAnchor1);
  2862. end;
  2863. function Tb2GearJoint.GetAnchor2: TVector2;
  2864. begin
  2865.    Result := m_body2.GetWorldPoint(m_localAnchor2);
  2866. end;
  2867. function Tb2GearJoint.GetReactionForce: TVector2;
  2868. begin
  2869.  // TODO_ERIN not tested
  2870.    {$IFDEF OP_OVERLOAD}
  2871.  Result := m_force * m_J.linear2;
  2872.    {$ELSE}
  2873.    Result := Multiply(m_J.linear2, m_force);
  2874.    {$ENDIF}
  2875. end;
  2876. function Tb2GearJoint.GetReactionTorque: Float;
  2877. var
  2878.    r, F: TVector2;
  2879. begin
  2880.    // TODO_ERIN not tested
  2881.    {$IFDEF OP_OVERLOAD}
  2882.    r := b2Mul(m_body2.m_xf.R, m_localAnchor2 - m_body2.GetLocalCenter);
  2883.    F := m_force * m_J.linear2;
  2884.    {$ELSE}
  2885.    r := b2Mul(m_body2.m_xf.R, Subtract(m_localAnchor2, m_body2.GetLocalCenter));
  2886.    F := Multiply(m_J.linear2, m_force);
  2887.    {$ENDIF}
  2888.    Result := m_force * m_J.angular2 - b2Cross(r, F);
  2889. end;
  2890. procedure Tb2GearJoint.InitVelocityConstraints(const step: Tb2TimeStep);
  2891. var
  2892.    K, crug, P: Float;
  2893.    ug, r: TVector2;
  2894. begin
  2895.    K := 0.0;
  2896.    {$IFDEF OP_OVERLOAD}
  2897.    m_J.SetZero;
  2898.    {$ELSE}
  2899.    SetZero(m_J);
  2900.    {$ENDIF}
  2901.    if Assigned(m_revolute1) then
  2902.    begin
  2903.       m_J.angular1 := -1.0;
  2904.       K := K + m_body1.m_invI;
  2905.    end
  2906.    else
  2907.    begin
  2908.       ug := b2Mul(m_ground1.m_xf.R, m_prismatic1.m_localXAxis1);
  2909.       {$IFDEF OP_OVERLOAD}
  2910.       r := b2Mul(m_body1.m_xf.R, m_localAnchor1 - m_body1.GetLocalCenter);
  2911.       m_J.linear1 := -ug;
  2912.       {$ELSE}
  2913.       r := b2Mul(m_body1.m_xf.R, Subtract(m_localAnchor1, m_body1.GetLocalCenter));
  2914.       m_J.linear1 := Negative(ug);
  2915.       {$ENDIF}
  2916.       crug := b2Cross(r, ug);
  2917.       m_J.angular1 := -crug;
  2918.       K := K + m_body1.m_invMass + m_body1.m_invI * crug * crug;
  2919.    end;
  2920.    if Assigned(m_revolute2) then
  2921.    begin
  2922.       m_J.angular2 := -m_ratio;
  2923.       K := K + m_ratio * m_ratio * m_body2.m_invI;
  2924.    end
  2925.    else
  2926.    begin
  2927.       ug := b2Mul(m_ground2.m_xf.R, m_prismatic2.m_localXAxis1);
  2928.       {$IFDEF OP_OVERLOAD}
  2929.       r := b2Mul(m_body2.m_xf.R, m_localAnchor2 - m_body2.GetLocalCenter);
  2930.       m_J.linear2 := -m_ratio * ug;
  2931.       {$ELSE}
  2932.       r := b2Mul(m_body2.m_xf.R, Subtract(m_localAnchor2, m_body2.GetLocalCenter));
  2933.       m_J.linear2 := Multiply(ug, -m_ratio);
  2934.       {$ENDIF}
  2935.       crug := b2Cross(r, ug);
  2936.       m_J.angular2 := -m_ratio * crug;
  2937.       K := K + m_ratio * m_ratio * (m_body2.m_invMass + m_body2.m_invI * crug * crug);
  2938.    end;
  2939.    // Compute effective mass.
  2940.    //b2Assert(K > 0.0);
  2941.    m_mass := 1.0 / K;
  2942.    if step.warmStarting then
  2943.    begin
  2944.       // Warm starting.
  2945.       P := step.dt * m_force;
  2946.       {$IFDEF OP_OVERLOAD}
  2947.       m_body1.m_linearVelocity.AddBy(m_body1.m_invMass * P * m_J.linear1);
  2948.       m_body2.m_linearVelocity.AddBy(m_body2.m_invMass * P * m_J.linear2);
  2949.       {$ELSE}
  2950.       AddBy(m_body1.m_linearVelocity, Multiply(m_J.linear1, m_body1.m_invMass * P));
  2951.       AddBy(m_body2.m_linearVelocity, Multiply(m_J.linear2, m_body2.m_invMass * P));
  2952.       {$ENDIF}
  2953.       m_body1.m_angularVelocity := m_body1.m_angularVelocity + m_body1.m_invI * P * m_J.angular1;
  2954.       m_body2.m_angularVelocity := m_body2.m_angularVelocity + m_body2.m_invI * P * m_J.angular2;
  2955.    end
  2956.    else
  2957.       m_force := 0.0;
  2958. end;
  2959. procedure Tb2GearJoint.SolveVelocityConstraints(const step: Tb2TimeStep);
  2960. var
  2961.    Cdot, force, P: Float;
  2962. begin
  2963.    {$IFDEF OP_OVERLOAD}
  2964.    Cdot := m_J.Compute(m_body1.m_linearVelocity, m_body2.m_linearVelocity,
  2965.    m_body1.m_angularVelocity, m_body2.m_angularVelocity);
  2966.    {$ELSE}
  2967.    Cdot := Compute(m_J, m_body1.m_linearVelocity, m_body2.m_linearVelocity,
  2968.    m_body1.m_angularVelocity, m_body2.m_angularVelocity);
  2969.    {$ENDIF}
  2970.    force := -step.inv_dt * m_mass * Cdot;
  2971.    m_force := m_force + force;
  2972.    P := step.dt * force;
  2973.    {$IFDEF OP_OVERLOAD}
  2974.    m_body1.m_linearVelocity.AddBy(m_body1.m_invMass * P * m_J.linear1);
  2975.    m_body2.m_linearVelocity.AddBy(m_body2.m_invMass * P * m_J.linear2);
  2976.    {$ELSE}
  2977.    AddBy(m_body1.m_linearVelocity, Multiply(m_J.linear1, m_body1.m_invMass * P));
  2978.    AddBy(m_body2.m_linearVelocity, Multiply(m_J.linear2, m_body2.m_invMass * P));
  2979.    {$ENDIF}
  2980.    m_body1.m_angularVelocity := m_body1.m_angularVelocity + m_body1.m_invI * P * m_J.angular1;
  2981.    m_body2.m_angularVelocity := m_body2.m_angularVelocity + m_body2.m_invI * P * m_J.angular2;
  2982. end;
  2983. function Tb2GearJoint.SolvePositionConstraints: Boolean;
  2984. var
  2985.    linearError, coordinate1, coordinate2, C, impulse: Float;
  2986. begin
  2987.    linearError := 0.0;
  2988.    if Assigned(m_revolute1) then
  2989.       coordinate1 := m_revolute1.GetJointAngle()
  2990.    else
  2991.       coordinate1 := m_prismatic1.GetJointTranslation;
  2992.    if Assigned(m_revolute2) then
  2993.       coordinate2 := m_revolute2.GetJointAngle()
  2994.    else
  2995.       coordinate2 := m_prismatic2.GetJointTranslation;
  2996.    C := m_constant - (coordinate1 + m_ratio * coordinate2);
  2997.    impulse := -m_mass * C;
  2998.    {$IFDEF OP_OVERLOAD}
  2999.    m_body1.m_sweep.c.AddBy(m_body1.m_invMass * impulse * m_J.linear1);
  3000.    m_body2.m_sweep.c.AddBy(m_body2.m_invMass * impulse * m_J.linear2);
  3001.    {$ELSE}
  3002.    AddBy(m_body1.m_sweep.c, Multiply(m_J.linear1, m_body1.m_invMass * impulse));
  3003.    AddBy(m_body2.m_sweep.c, Multiply(m_J.linear2, m_body2.m_invMass * impulse));
  3004.    {$ENDIF}
  3005.    m_body1.m_sweep.a := m_body1.m_sweep.a + m_body1.m_invI * impulse * m_J.angular1;
  3006.    m_body2.m_sweep.a := m_body2.m_sweep.a + m_body2.m_invI * impulse * m_J.angular2;
  3007.    m_body1.SynchronizeTransform;
  3008.    m_body2.SynchronizeTransform;
  3009.    Result := linearError < b2_linearSlop;
  3010. end;
  3011. { Tb2FixedJointDef }
  3012. constructor Tb2FixedJointDef.Create;
  3013. begin
  3014.  JointType := e_fixedJoint;
  3015. end;
  3016. procedure Tb2FixedJointDef.Initialize(body1, body2: Tb2Body);
  3017. begin
  3018.    Self.body1 := body1;
  3019.  Self.body2 := body2;
  3020. end;
  3021. { Tb2FixedJoint }
  3022. constructor Tb2FixedJoint.Create(def: Tb2FixedJointDef);
  3023. begin
  3024.    inherited Create(def);
  3025.    // Get initial delta position and angle
  3026.    {$IFDEF OP_OVERLOAD}
  3027.    m_dp := b2MulT(m_body1.m_xf.R, m_body2.m_xf.position - m_body1.m_xf.position);
  3028.    {$ELSE}
  3029.    m_dp := b2MulT(m_body1.m_xf.R, Subtract(m_body2.m_xf.position, m_body1.m_xf.position));
  3030.    {$ENDIF}
  3031.    m_a := m_body2.GetAngle - m_body1.GetAngle;
  3032.    m_R0 := b2MulT(m_body1.m_xf.R, m_body2.m_xf.R);
  3033.    // Reset accumulated lambda
  3034.    m_lambda[0] := 0.0;
  3035.    m_lambda[1] := 0.0;
  3036.    m_lambda[2] := 0.0;
  3037. end;
  3038. procedure Tb2FixedJoint.CalculateMC;
  3039. var
  3040.    invM12, invI1, a, b, c, d, e, f, c1, c2, c3, den: Float;
  3041. begin
  3042.    UPhysics2DTypes.SinCos(m_body1.m_sweep.a, m_s, m_c);
  3043.    // Calculate vector A w1 := d/dt (R(a1) d)
  3044.    m_Ax := -m_s * m_d.x - m_c * m_d.y;
  3045.    m_Ay := m_c * m_d.x - m_s * m_d.y;
  3046.    // Calculate effective constraint mass: mC := (J M^-1 J^T)^-1
  3047.    invM12 := m_body1.m_invMass + m_body2.m_invMass;
  3048.    invI1 := m_body1.m_invI;
  3049.    a := invM12 + m_Ax * m_Ax * invI1;
  3050.    b := m_Ax * m_Ay * invI1;
  3051.    c := m_Ax * invI1;
  3052.    d := invM12 + m_Ay * m_Ay * invI1;
  3053.    e := m_Ay * invI1;
  3054.    f := m_body1.m_invI + invI1;
  3055.    c1 := d * f - e * e;
  3056.    c2 := c * e - b * f;
  3057.    c3 := b * e - c * d;
  3058.    den := a * c1 + b * c2 + c * c3;
  3059.    m_mc[0][0] := c1 / den;
  3060.    m_mc[1][0] := c2 / den;
  3061.    m_mc[2][0] := c3 / den;
  3062.    m_mc[0][1] := m_mc[1][0];
  3063.    m_mc[1][1] := (a * f - c * c ) / den;
  3064.    m_mc[2][1] := (b * c - a * e ) / den;
  3065.    m_mc[0][2] := m_mc[2][0];
  3066.    m_mc[1][2] := m_mc[2][1];
  3067.    m_mc[2][2] := (a * d - b * b ) / den;
  3068. end;
  3069. function Tb2FixedJoint.GetAnchor1: TVector2;
  3070. begin
  3071.  // Return arbitrary position (we have to implement this abstract virtual function)
  3072.  Result := m_body1.GetWorldCenter;
  3073. end;
  3074. function Tb2FixedJoint.GetAnchor2: TVector2;
  3075. begin
  3076.  // Return arbitrary position (we have to implement this abstract virtual function)
  3077.  Result := m_body2.GetWorldCenter;
  3078. end;
  3079. function Tb2FixedJoint.GetReactionForce: TVector2;
  3080. begin
  3081.    {$IFDEF OP_OVERLOAD}
  3082.    Result := m_inv_dt * MakeVector(m_lambda[0], m_lambda[1]);
  3083.    {$ELSE}
  3084.    Result := Multiply(MakeVector(m_lambda[0], m_lambda[1]), m_inv_dt);
  3085.    {$ENDIF}
  3086. end;
  3087. function Tb2FixedJoint.GetReactionTorque: Float;
  3088. begin
  3089.    Result := m_inv_dt * m_lambda[2];
  3090. end;
  3091. procedure Tb2FixedJoint.InitVelocityConstraints(const step: Tb2TimeStep);
  3092. begin
  3093.    // Store step
  3094.    m_inv_dt := step.inv_dt;
  3095.    // Get d for this step (transform from delta between positions to delta between center of masses)
  3096.    {$IFDEF OP_OVERLOAD}
  3097.    m_d := m_dp - m_body1.m_sweep.localCenter + b2Mul(m_R0, m_body2.m_sweep.localCenter);
  3098.    {$ELSE}
  3099.    m_d := Add(Subtract(m_dp, m_body1.m_sweep.localCenter), b2Mul(m_R0, m_body2.m_sweep.localCenter));
  3100.    {$ENDIF}
  3101.    // Calculate effective joint mass (stays constant during velocity solving)
  3102.    CalculateMC;
  3103.    if step.warmStarting then
  3104.    begin
  3105.       // Apply initial impulse
  3106.       with m_body1 do
  3107.       begin
  3108.          m_linearVelocity.x := m_linearVelocity.x - m_invMass * m_lambda[0];
  3109.          m_linearVelocity.y := m_linearVelocity.y - m_invMass * m_lambda[1];
  3110.          m_angularVelocity := m_angularVelocity - m_invI * (m_lambda[0] * m_Ax + m_lambda[1] * m_Ay + m_lambda[2]);
  3111.       end;
  3112.       with m_body2 do
  3113.       begin
  3114.          m_linearVelocity.x := m_linearVelocity.x + m_invMass * m_lambda[0];
  3115.          m_linearVelocity.y := m_linearVelocity.y + m_invMass * m_lambda[1];
  3116.          m_angularVelocity := m_angularVelocity + m_invI * m_lambda[2];
  3117.       end;
  3118.    end
  3119.    else
  3120.    begin
  3121.       // Reset accumulated lambda
  3122.       m_lambda[0] := 0.0;
  3123.       m_lambda[1] := 0.0;
  3124.       m_lambda[2] := 0.0;
  3125.    end;
  3126. end;
  3127. procedure Tb2FixedJoint.SolveVelocityConstraints(const step: Tb2TimeStep);
  3128. var
  3129.    i: Integer;
  3130.    Cdot, lambda: array[0..2] of Float;
  3131. begin
  3132.    // Assert that angle is still the same so the effective joint mass is still valid
  3133.    //assert(m_body1.m_sweep.a == m_a1);
  3134.    // Calculate Cdot
  3135.    Cdot[0] := m_body2.m_linearVelocity.x - m_body1.m_linearVelocity.x - m_Ax * m_body1.m_angularVelocity;
  3136.    Cdot[1] := m_body2.m_linearVelocity.y - m_body1.m_linearVelocity.y - m_Ay * m_body1.m_angularVelocity;
  3137.    Cdot[2] := m_body2.m_angularVelocity - m_body1.m_angularVelocity;
  3138.    // Calculate lambda
  3139.    for i := 0 to 2 do
  3140.       lambda[i] := -(m_mc[i][0] * Cdot[0] + m_mc[i][1] * Cdot[1] + m_mc[i][2] * Cdot[2]);
  3141.    // Apply impulse
  3142.    with m_body1 do
  3143.    begin
  3144.       m_linearVelocity.x := m_linearVelocity.x - m_invMass * lambda[0];
  3145.       m_linearVelocity.y := m_linearVelocity.y - m_invMass * lambda[1];
  3146.       m_angularVelocity := m_angularVelocity - m_invI * (lambda[0] * m_Ax + lambda[1] * m_Ay + lambda[2]);
  3147.    end;
  3148.    with m_body2 do
  3149.    begin
  3150.       m_linearVelocity.x := m_linearVelocity.x + m_invMass * lambda[0];
  3151.       m_linearVelocity.y := m_linearVelocity.y + m_invMass * lambda[1];
  3152.       m_angularVelocity := m_angularVelocity + m_invI * lambda[2];
  3153.    end;
  3154.    // Accumulate total lambda
  3155.    for i := 0 to 2 do
  3156.      m_lambda[i] := m_lambda[i] + lambda[i];
  3157. end;
  3158. function Tb2FixedJoint.SolvePositionConstraints: Boolean;
  3159. var
  3160.    i: Integer;
  3161.    C, lambda: array[0..2] of Float;
  3162. begin
  3163.    // Recalculate effective constraint mass if angle changed enough
  3164.    if Abs(m_body1.m_sweep.a - m_a1) > 1e-3 then
  3165.      CalculateMC;
  3166.    // Calculate C
  3167.    C[0] := m_body2.m_sweep.c.x - m_body1.m_sweep.c.x - m_c * m_d.x + m_s * m_d.y;
  3168.    C[1] := m_body2.m_sweep.c.y - m_body1.m_sweep.c.y - m_s * m_d.x - m_c * m_d.y;
  3169.    C[2] := m_body2.m_sweep.a - m_a1 - m_a;
  3170.    // Calculate lambda
  3171.    for i := 0 to 2 do
  3172.      lambda[i] := -(m_mc[i][0] * C[0] + m_mc[i][1] * C[1] + m_mc[i][2] * C[2]);
  3173.    // Apply impulse
  3174.    with m_body1, m_sweep do
  3175.    begin
  3176.       c.x := c.x - m_invMass * lambda[0];
  3177.       c.y := c.y - m_invMass * lambda[1];
  3178.       a := a - m_invI * (lambda[0] * m_Ax + lambda[1] * m_Ay + lambda[2]);
  3179.    end;
  3180.    with m_body2, m_sweep do
  3181.    begin
  3182.       c.x := c.x + m_invMass * lambda[0];
  3183.       c.y := c.y + m_invMass * lambda[1];
  3184.       a := a + m_invI * lambda[2];
  3185.    end;
  3186.    // Push the changes to the transforms
  3187.    m_body1.SynchronizeTransform;
  3188.    m_body2.SynchronizeTransform;
  3189.    // Constraint is satisfied if all constraint equations are nearly zero
  3190.    Result := (Abs(C[0]) < b2_linearSlop) and (Abs(C[1]) < b2_linearSlop) and (Abs(C[2]) < b2_angularSlop);
  3191. end;
  3192. initialization
  3193.    b2_defaultFilter := Tb2ContactFilter.Create;
  3194.    g_GJK_Iterations := 0;
  3195. {$IFDEF CLASSVAR_AVAIL}
  3196.    Tb2BroadPhase.s_validate := False;
  3197. {$ELSE}
  3198.    b2BroadPhase_s_validate := False;
  3199. {$ENDIF}
  3200. finalization
  3201.    b2_defaultFilter.Free;
  3202. {$IFDEF DEBUG_LOG}
  3203.    DEBUG.Free;
  3204. {$ENDIF}
  3205. end.