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

Delphi/CppBuilder

开发平台:

Delphi

  1.         b := def.body2;
  2.      s := b.m_shapeList;
  3.      while Assigned(s) do
  4.      begin
  5.         s.RefilterProxy(m_broadPhase, b.m_xf);
  6.         s := s.m_next;
  7.      end;
  8.    end;
  9.    if AutoFreeJointDef then
  10.       def.Free;
  11.    Result := j;
  12. end;
  13. procedure Tb2World.DestroyJoint(j: Tb2Joint);
  14. var
  15.    collideConnected: Boolean;
  16.    body1, body2, b: Tb2Body;
  17.    s: Tb2Shape;
  18. begin
  19.    //b2Assert(m_lock == False);
  20.    collideConnected := j.m_collideConnected;
  21.    // Remove from the doubly linked list.
  22.    if Assigned(j.m_prev) then
  23.       j.m_prev.m_next := j.m_next;
  24.    if Assigned(j.m_next) then
  25.       j.m_next.m_prev := j.m_prev;
  26.    if j = m_jointList then
  27.       m_jointList := j.m_next;
  28.    // Disconnect from island graph.
  29.    body1 := j.m_body1;
  30.    body2 := j.m_body2;
  31.    // Wake up connected bodies.
  32.    body1.WakeUp;
  33.    body2.WakeUp;
  34.    // Remove from body 1.
  35.    if Assigned(j.m_node1.prev) then
  36.       j.m_node1.prev^.next := j.m_node1.next;
  37.    if Assigned(j.m_node1.next) then
  38.       j.m_node1.next^.prev := j.m_node1.prev;
  39.    if (@j.m_node1) = body1.m_jointList then
  40.       body1.m_jointList := j.m_node1.next;
  41.    j.m_node1.prev := nil;
  42.    j.m_node1.next := nil;
  43.    // Remove from body 2
  44.    if Assigned(j.m_node2.prev) then
  45.       j.m_node2.prev^.next := j.m_node2.next;
  46.    if Assigned(j.m_node2.next) then
  47.       j.m_node2.next^.prev := j.m_node2.prev;
  48.    if (@j.m_node2) = body2.m_jointList then
  49.       body2.m_jointList := j.m_node2.next;
  50.    j.m_node2.prev := nil;
  51.    j.m_node2.next := nil;
  52.    j.Free;
  53.    //b2Assert(m_jointCount > 0);
  54.    Dec(m_jointCount);
  55.    // If the joint prevents collisions, then reset collision filtering.
  56.    if not collideConnected then
  57.    begin
  58.       // Reset the proxies on the body with the minimum number of shapes.
  59.       if body1.m_shapeCount < body2.m_shapeCount then
  60.          b := body1
  61.       else
  62.          b := body2;
  63.       s := b.m_shapeList;
  64.       while Assigned(s) do
  65.       begin
  66.          s.RefilterProxy(m_broadPhase, b.m_xf);
  67.          s := s.m_next;
  68.       end;
  69.    end;
  70. end;
  71. procedure Tb2World.Step(timeStep: Float; iterations: Int32; drawThisStep: Boolean = True);
  72. var
  73.    step: Tb2TimeStep;
  74. begin
  75.    m_lock := True;
  76.    step.dt := timeStep;
  77.    step.maxIterations := iterations;
  78.    if timeStep > 0.0 then
  79.       step.inv_dt := 1.0 / timeStep
  80.    else
  81.       step.inv_dt := 0.0;
  82.    step.dtRatio := m_inv_dt0 * timeStep;
  83.    step.positionCorrection := m_positionCorrection;
  84.    step.warmStarting := m_warmStarting;
  85.    // Update contacts.
  86.    m_contactManager.Collide;
  87.    if step.dt > 0.0 then
  88.    begin
  89.       Solve(step); // Integrate velocities, solve velocity constraints, and integrate positions.
  90.       if m_continuousPhysics then
  91.          SolveTOI(step); // Handle TOI events.
  92.    end;
  93.    if drawThisStep then
  94.       DrawDebugData;
  95.    m_inv_dt0 := step.inv_dt;
  96.    m_lock := False;
  97. end;
  98. function Tb2World.Query(const aabb: Tb2AABB; shapes: TList; maxCount: Int32): Int32;
  99. begin
  100.    Result := m_broadPhase.Query(aabb, shapes, maxCount);
  101. end;
  102. procedure Tb2World.Refilter(shape: Tb2Shape);
  103. begin
  104.    shape.RefilterProxy(m_broadPhase, shape.GetBody.m_xf);
  105. end;
  106. procedure Tb2World.Validate;
  107. begin
  108.    m_broadPhase.Validate;
  109. end;
  110. function Tb2World.GetProxyCount: Int32;
  111. begin
  112.    Result := m_broadPhase.m_proxyCount;
  113. end;
  114. function Tb2World.GetPairCount: Int32;
  115. begin
  116.    Result := m_broadPhase.m_pairManager.m_pairCount;
  117. end;
  118. procedure Tb2World.SetGravity(const gravity: TVector2);
  119. begin
  120.    m_gravity := gravity;
  121. end;
  122. procedure Tb2World.WakeAllSleepingBodies;
  123. var
  124.    b: Tb2Body;
  125. begin
  126.    b := m_bodyList;
  127.    while Assigned(b) do
  128.    begin
  129.       if b.IsDynamic and b.IsSleeping then
  130.          b.WakeUp;
  131.       b := b.GetNext;
  132.    end;
  133. end;
  134. ////////////////////////////////////////////////////
  135. // Contact
  136. { Tb2ContactFilter }
  137. function Tb2ContactFilter.ShouldCollide(shape1, shape2: Tb2Shape): Boolean;
  138. begin
  139.    with shape1.m_filter do
  140.       if (groupIndex = shape2.m_filter.groupIndex) and (groupIndex <> 0) then
  141.          Result := groupIndex > 0
  142.       else
  143.          Result := ((maskBits and shape2.m_filter.categoryBits) <> 0) and
  144.             ((categoryBits and shape2.m_filter.maskBits) <> 0);
  145. end;
  146. { Tb2ContactListener }
  147. procedure Tb2ContactListener.Add(var point: Tb2ContactPoint);
  148. begin
  149. end;
  150. procedure Tb2ContactListener.Persist(var point: Tb2ContactPoint);
  151. begin
  152. end;
  153. procedure Tb2ContactListener.Remove(var point: Tb2ContactPoint);
  154. begin
  155. end;
  156. procedure Tb2ContactListener.Result(var point: Tb2ContactResult);
  157. begin
  158. end;
  159. { Tb2Contact }
  160. constructor Tb2Contact.Create;
  161. begin
  162.    m_flags := 0;
  163.    m_shape1 := nil;
  164.    m_shape2 := nil;
  165. end;
  166. constructor Tb2Contact.Create(shape1, shape2: Tb2Shape);
  167. begin
  168.    Create;
  169.    if shape1.IsSensor or shape2.IsSensor then
  170.       m_flags := m_flags or e_nonSolidFlag;
  171.    m_shape1 := shape1;
  172.    m_shape2 := shape2;
  173.    m_manifoldCount := 0;
  174.    m_friction := b2MixFriction(m_shape1.GetFriction, m_shape2.GetFriction);
  175.    m_restitution := b2MixRestitution(m_shape1.GetRestitution, m_shape2.GetRestitution);
  176.    m_prev := nil;
  177.    m_next := nil;
  178.    m_node1.contact := nil;
  179.    m_node1.prev := nil;
  180.    m_node1.next := nil;
  181.    m_node1.other := nil;
  182.    m_node2.contact := nil;
  183.    m_node2.prev := nil;
  184.    m_node2.next := nil;
  185.    m_node2.other := nil;
  186. end;
  187. class function Tb2Contact.CreateContact(Shape1, Shape2: Tb2Shape): Tb2Contact;
  188. var
  189.    i: Integer;
  190.    p: Pb2Manifold;
  191. begin
  192.    with ContactCreateRecords[Shape1.GetType][Shape2.GetType] do
  193.    begin
  194.       if Primary then
  195.          Result := ClassType.Create(Shape1, Shape2)
  196.       else
  197.       begin
  198.          Result := ClassType.Create(Shape2, Shape1);
  199.          p := Result.GetManifolds;
  200.          for i := 0 to Result.GetManifoldCount - 1 do
  201.             {$IFDEF D2009UP}
  202.             {$IFDEF OP_OVERLOAD}
  203.             (p + i)^.normal.SetNegative;
  204.             {$ELSE}
  205.             SetNegative((p + i)^.normal);
  206.             {$ENDIF}
  207.             {$ELSE}
  208.             {$IFDEF OP_OVERLOAD}
  209.             Pb2Manifold(Integer(p) + i * SizeOf(Tb2Manifold))^.normal.SetNegative;
  210.             {$ELSE}
  211.             SetNegative(Pb2Manifold(Integer(p) + i * SizeOf(Tb2Manifold))^.normal);
  212.             {$ENDIF}
  213.             {$ENDIF}
  214.       end;
  215.    end;
  216. end;
  217. function Tb2Contact.IsSolid: Boolean;
  218. begin
  219.    Result := (m_flags and e_nonSolidFlag) = 0;
  220. end;
  221. procedure Tb2Contact.Update(listener: Tb2ContactListener);
  222. var
  223.    oldCount, newCount: Int32;
  224.    body1, body2: Tb2Body;
  225. begin
  226.    oldCount := m_manifoldCount;
  227.    Evaluate(listener);
  228.    newCount := m_manifoldCount;
  229.    body1 := m_shape1.GetBody;
  230.    body2 := m_shape2.GetBody;
  231.    if (newCount = 0) and (oldCount > 0) then
  232.    begin
  233.       body1.WakeUp;
  234.       body2.WakeUp;
  235.    end;
  236.    // Slow contacts don't generate TOI events.
  237.    if body1.IsStatic or body1.IsBullet or body2.IsStatic or body2.IsBullet then
  238.       m_flags := m_flags and (not e_slowFlag)
  239.    else
  240.       m_flags := m_flags or e_slowFlag;
  241. end;
  242. { Tb2ContactSolver }
  243. constructor Tb2ContactSolver.Create(const step: Tb2TimeStep;
  244.    contacts: TList; contactCount: Int32);
  245. var
  246.    i, j, k: Integer;
  247.    contact: Tb2Contact;
  248.    b1, b2: Tb2Body;
  249.    manifolds, manifold: Pb2Manifold;
  250.    count: Int32;
  251.    friction, restitution: Float;
  252.    w1, w2: Float;
  253.    v1, v2: TVector2;
  254.    normal, tangent: TVector2;
  255.    c: Pb2ContactConstraint;
  256.    cp: Pb2ManifoldPoint;
  257.    ccp: Pb2ContactConstraintPoint;
  258.    r1Sqr, r2Sqr, rn1, rn2: Float;
  259.    kNormal, kEqualized: Float;
  260.    rt1, rt2, kTangent: Float;
  261.    vRel: Float;
  262.    {$IFNDEF OP_OVERLOAD}tmpV: TVector2;{$ENDIF} 
  263. begin
  264.    //m_step := step;
  265.    m_constraintCount := 0;
  266.    for i := 0 to contactCount - 1 do
  267.    begin
  268.       //b2Assert(contacts[i]->IsSolid());
  269.       m_constraintCount := m_constraintCount + Tb2Contact(contacts[i]).GetManifoldCount;
  270.    end;
  271.    m_constraints := Pb2ContactConstraint(GetMemory(m_constraintCount * SizeOf(Tb2ContactConstraint)));
  272.    count := 0;
  273.    for i := 0 to contactCount - 1 do
  274.    begin
  275.       contact := Tb2Contact(contacts[i]);
  276.       b1 := contact.m_shape1.GetBody;
  277.       b2 := contact.m_shape2.GetBody;
  278.       manifolds := contact.GetManifolds;
  279.       friction := contact.m_friction;
  280.       restitution := contact.m_restitution;
  281.       v1 := b1.m_linearVelocity;
  282.       v2 := b2.m_linearVelocity;
  283.       w1 := b1.m_angularVelocity;
  284.       w2 := b2.m_angularVelocity;
  285.       for j := 0 to contact.GetManifoldCount - 1 do
  286.       begin
  287.          {$IFDEF D2009UP}
  288.          manifold := manifolds + j;
  289.          {$ELSE}
  290.          manifold := Pb2Manifold(Integer(manifolds) + j * SizeOf(Tb2Manifold));
  291.          {$ENDIF}
  292.          //b2Assert(manifold->pointCount > 0);
  293.          normal := manifold^.normal;
  294.          //b2Assert(count < m_constraintCount);
  295.          {$IFDEF D2009UP}
  296.          c := m_constraints + count;
  297.          {$ELSE}
  298.          c := Pb2ContactConstraint(Integer(m_constraints) + count * SizeOf(Tb2ContactConstraint));
  299.          {$ENDIF}
  300.          c.body1 := b1;
  301.          c.body2 := b2;
  302.          c.manifold := manifold;
  303.          c.normal := normal;
  304.          c.pointCount := manifold^.pointCount;
  305.          c.friction := friction;
  306.          c.restitution := restitution;
  307.          for k := 0 to c.pointCount - 1 do
  308.          begin
  309.             cp := @manifold^.points[k];
  310.             ccp := @c^.points[k];
  311.             with ccp^ do
  312.             begin
  313.                normalImpulse := cp^.normalImpulse;
  314.                tangentImpulse := cp^.tangentImpulse;
  315.                separation := cp^.separation;
  316.                positionImpulse := 0.0;
  317.                localAnchor1 := cp^.localPoint1;
  318.                localAnchor2 := cp^.localPoint2;
  319.                {$IFDEF OP_OVERLOAD}               
  320.                r1 := b2Mul(b1.m_xf.R, cp^.localPoint1 - b1.GetLocalCenter);
  321.                r2 := b2Mul(b2.m_xf.R, cp^.localPoint2 - b2.GetLocalCenter);
  322.                {$ELSE}               
  323.                r1 := b2Mul(b1.m_xf.R, Subtract(cp^.localPoint1, b1.GetLocalCenter));
  324.                r2 := b2Mul(b2.m_xf.R, Subtract(cp^.localPoint2, b2.GetLocalCenter));
  325.                {$ENDIF}                              
  326.                r1Sqr := b2Dot(r1, r1);
  327.                r2Sqr := b2Dot(r2, r2);
  328.                rn1 := b2Dot(r1, normal);
  329.                rn2 := b2Dot(r2, normal);
  330.                kNormal := b1.m_invMass + b2.m_invMass + b1.m_invI * (r1Sqr -
  331.                   rn1 * rn1) + b2.m_invI * (r2Sqr - rn2 * rn2);
  332.                //b2Assert(kNormal > B2_FLT_EPSILON);
  333.                normalMass := 1.0 / kNormal;
  334.                kEqualized := b1.m_mass * b1.m_invMass + b2.m_mass * b2.m_invMass +
  335.                   b1.m_mass * b1.m_invI * (r1Sqr - rn1 * rn1) + b2.m_mass *
  336.                   b2.m_invI * (r2Sqr - rn2 * rn2);
  337.                //b2Assert(kEqualized > B2_FLT_EPSILON);
  338.                equalizedMass := 1.0 / kEqualized;
  339.                tangent := b2Cross(normal, 1.0);
  340.                rt1 := b2Dot(r1, tangent);
  341.                rt2 := b2Dot(r2, tangent);
  342.                kTangent := b1.m_invMass + b2.m_invMass + b1.m_invI * (r1Sqr -
  343.                   rt1 * rt1) + b2.m_invI * (r2Sqr - rt2 * rt2);
  344.                //b2Assert(kTangent > B2_FLT_EPSILON);
  345.                tangentMass := 1.0 / kTangent;
  346.                // Setup a velocity bias for restitution.
  347.                velocityBias := 0.0;
  348.                if separation > 0.0 then
  349.                   velocityBias := -60.0 * separation; // TODO_ERIN b2TimeStep
  350.                {$IFDEF OP_OVERLOAD}
  351.                vRel := b2Dot(c.normal, v2 + b2Cross(w2, r2) - v1 - b2Cross(w1, ccp.r1));
  352.                {$ELSE}
  353.                tmpV := Subtract(v2, v1);
  354.                AddBy(tmpV, b2Cross(w2, r2));
  355.                SubtractBy(tmpV, b2Cross(w1, ccp.r1));
  356.                vRel := b2Dot(c.normal, tmpV);
  357.                {$ENDIF}
  358.                if vRel < -b2_velocityThreshold then
  359.                   velocityBias := velocityBias - c.restitution * vRel;
  360.             end;
  361.          end;
  362.          Inc(count);
  363.       end;
  364.    end;
  365.    //b2Assert(count == m_constraintCount);
  366. end;
  367. destructor Tb2ContactSolver.Destroy;
  368. begin
  369.    FreeMemory(m_constraints);
  370. end;
  371. procedure Tb2ContactSolver.InitVelocityConstraints(const step: Tb2TimeStep);
  372. var
  373.    i, j: Integer;
  374.    b1, b2: Tb2Body;
  375.    c: Pb2ContactConstraint;
  376.    invMass1, invI1, invMass2, invI2: Float;
  377.    normal, tangent: TVector2;
  378.    P: TVector2;
  379. begin
  380.    // Warm start.
  381.    for i := 0 to m_constraintCount - 1 do
  382.    begin
  383.       {$IFDEF D2009UP}
  384.       c := m_constraints + i;
  385.       {$ELSE}
  386.       c := Pb2ContactConstraint(Integer(m_constraints) + i * SizeOf(Tb2ContactConstraint));
  387.       {$ENDIF}
  388.       b1 := c.body1;
  389.       b2 := c.body2;
  390.       invMass1 := b1.m_invMass;
  391.       invI1 := b1.m_invI;
  392.       invMass2 := b2.m_invMass;
  393.       invI2 := b2.m_invI;
  394.       normal := c.normal;
  395.       tangent := b2Cross(normal, 1.0);
  396.       if step.warmStarting then
  397.       begin
  398.          for j := 0 to c.pointCount - 1 do
  399.             with c^.points[j] do
  400.             begin
  401.                normalImpulse := normalImpulse * step.dtRatio;
  402.                tangentImpulse := tangentImpulse * step.dtRatio;
  403.                {$IFDEF OP_OVERLOAD}               
  404.                P := normalImpulse * normal + tangentImpulse * tangent;                 
  405.                b1.m_linearVelocity.SubtractBy(invMass1 * P);
  406.                b2.m_linearVelocity.AddBy(invMass2 * P);
  407.                {$ELSE}               
  408.                P := Multiply(normal, normalImpulse);
  409.                AddBy(P, Multiply(tangent, tangentImpulse));
  410.                SubtractBy(b1.m_linearVelocity, Multiply(P, invMass1));
  411.                AddBy(b2.m_linearVelocity, Multiply(P, invMass2));
  412.                {$ENDIF}                              
  413.                
  414.                b1.m_angularVelocity := b1.m_angularVelocity - invI1 * b2Cross(r1, P);
  415.                b2.m_angularVelocity := b2.m_angularVelocity + invI2 * b2Cross(r2, P);                  
  416.             end;
  417.       end
  418.       else
  419.          for j := 0 to c.pointCount - 1 do
  420.             with c^.points[j] do
  421.             begin
  422.                normalImpulse := 0.0;
  423.                tangentImpulse := 0.0;
  424.             end;
  425.    end;
  426. end;
  427. procedure Tb2ContactSolver.SolveVelocityConstraints;
  428. var
  429.    i, j: Integer;
  430.    b1, b2: Tb2Body;
  431.    w1, w2: Float;
  432.    v1, v2: TVector2;
  433.    invMass1, invI1, invMass2, invI2: Float;
  434.    normal, tangent: TVector2;
  435.    friction: Float;
  436.    c: Pb2ContactConstraint;
  437.    dv, P: TVector2;
  438.    vn, vt, lambda, newImpulse, maxFriction: Float;
  439. begin
  440.    for i := 0 to m_constraintCount - 1 do
  441.    begin
  442.       {$IFDEF D2009UP}
  443.       c := m_constraints + i;
  444.       {$ELSE}
  445.       c := Pb2ContactConstraint(Integer(m_constraints) + i * SizeOf(Tb2ContactConstraint));
  446.       {$ENDIF}
  447.       b1 := c^.body1;
  448.       b2 := c^.body2;
  449.       w1 := b1.m_angularVelocity;
  450.       w2 := b2.m_angularVelocity;
  451.       v1 := b1.m_linearVelocity;
  452.       v2 := b2.m_linearVelocity;
  453.       invMass1 := b1.m_invMass;
  454.       invI1 := b1.m_invI;
  455.       invMass2 := b2.m_invMass;
  456.       invI2 := b2.m_invI;
  457.       normal := c^.normal;
  458.       tangent := b2Cross(normal, 1.0);
  459.       friction := c^.friction;
  460.       // Solve normal constraints
  461.       for j := 0 to c^.pointCount - 1 do
  462.          with c^.points[j] do
  463.          begin
  464.             // Relative velocity at contact
  465.             {$IFDEF OP_OVERLOAD}            
  466.             dv := v2 + b2Cross(w2, r2) - v1 - b2Cross(w1, r1);
  467.             {$ELSE}            
  468.             dv := Subtract(v2, v1);
  469.             AddBy(dv, b2Cross(w2, r2));
  470.             SubtractBy(dv, b2Cross(w1, r1));
  471.             {$ENDIF}                        
  472.             // Compute normal impulse
  473.             vn := b2Dot(dv, normal);
  474.             lambda := normalMass * (velocityBias - vn);
  475.             // b2Clamp the accumulated impulse
  476.             newImpulse := b2Max(normalImpulse + lambda, 0.0);
  477.             lambda := newImpulse - normalImpulse;
  478.             // Apply contact impulse
  479.             {$IFDEF OP_OVERLOAD}
  480.             P := lambda * normal;
  481.             v1 := v1 - invMass1 * P;
  482.             v2 := v2 + invMass2 * P;
  483.             {$ELSE}
  484.             P := Multiply(normal, lambda);
  485.             SubtractBy(v1, Multiply(P, invMass1));
  486.             AddBy(v2, Multiply(P, invMass2));
  487.             {$ENDIF}
  488.             w1 := w1 - invI1 * b2Cross(r1, P);
  489.             w2 := w2 + invI2 * b2Cross(r2, P);
  490.             normalImpulse := newImpulse;
  491.          end;
  492.       // Solve tangent constraints
  493.       for j := 0 to c^.pointCount - 1 do
  494.          with c^.points[j] do
  495.          begin
  496.             // Relative velocity at contact
  497.             {$IFDEF OP_OVERLOAD}            
  498.             dv := v2 + b2Cross(w2, r2) - v1 - b2Cross(w1, r1);
  499.             {$ELSE}            
  500.             dv := Subtract(v2, v1);
  501.             AddBy(dv, b2Cross(w2, r2));
  502.             SubtractBy(dv, b2Cross(w1, r1));
  503.             {$ENDIF}                        
  504.             // Compute tangent force
  505.             vt := b2Dot(dv, tangent);
  506.             lambda := tangentMass * (-vt);
  507.             // b2Clamp the accumulated force
  508.             maxFriction := friction * normalImpulse;
  509.             newImpulse := b2Clamp(tangentImpulse + lambda, -maxFriction, maxFriction);
  510.             lambda := newImpulse - tangentImpulse;
  511.             // Apply contact impulse
  512.             {$IFDEF OP_OVERLOAD}
  513.             P := lambda * tangent;
  514.             v1 := v1 - invMass1 * P;
  515.             v2 := v2 + invMass2 * P;
  516.             {$ELSE}            
  517.             P := Multiply(tangent, lambda);
  518.             SubtractBy(v1, Multiply(P, invMass1));
  519.             AddBy(v2, Multiply(P, invMass2));
  520.             {$ENDIF}
  521.             w1 := w1 - invI1 * b2Cross(r1, P);
  522.             w2 := w2 + invI2 * b2Cross(r2, P);
  523.             tangentImpulse := newImpulse;
  524.          end;
  525.       b1.m_linearVelocity := v1;
  526.       b1.m_angularVelocity := w1;
  527.       b2.m_linearVelocity := v2;
  528.       b2.m_angularVelocity := w2;
  529.    end;
  530. end;
  531. procedure Tb2ContactSolver.FinalizeVelocityConstraints;
  532. var
  533.    i, j: Integer;
  534.    m: Pb2Manifold;
  535.    c: Pb2ContactConstraint;
  536. begin
  537.    for i := 0 to m_constraintCount - 1 do
  538.    begin
  539.       {$IFDEF D2009UP}
  540.       c := m_constraints + i;
  541.       {$ELSE}
  542.       c := Pb2ContactConstraint(Integer(m_constraints) + i * SizeOf(Tb2ContactConstraint));
  543.       {$ENDIF}
  544.       m := c^.manifold;
  545.       for j := 0 to c^.pointCount - 1 do
  546.       begin
  547.          m^.points[j].normalImpulse := c^.points[j].normalImpulse;
  548.          m^.points[j].tangentImpulse := c^.points[j].tangentImpulse;
  549.       end;
  550.    end;
  551. end;
  552. function Tb2ContactSolver.SolvePositionConstraints(baumgarte: Float): Boolean;
  553. var
  554.    i, j: Integer;
  555.    b1, b2: Tb2Body;
  556.    c: Pb2ContactConstraint;
  557.    minSeparation: Float;
  558.    invMass1, invI1, invMass2, invI2: Float;
  559.    normal: TVector2;
  560.    _r1, _r2: TVector2;
  561.    p1, p2, dp: TVector2;
  562.    _separation: Float;
  563.    dImpulse, impulse0: Float;
  564.    impulse: TVector2;
  565. begin
  566.    minSeparation := 0.0;
  567.    for i := 0 to m_constraintCount - 1 do
  568.    begin
  569.       {$IFDEF D2009UP}
  570.       c := m_constraints + i;
  571.       {$ELSE}
  572.       c := Pb2ContactConstraint(Integer(m_constraints) + i * SizeOf(Tb2ContactConstraint));
  573.       {$ENDIF}
  574.       b1 := c.body1;
  575.       b2 := c.body2;
  576.       invMass1 := b1.m_mass * b1.m_invMass;
  577.       invI1 := b1.m_mass * b1.m_invI;
  578.       invMass2 := b2.m_mass * b2.m_invMass;
  579.       invI2 := b2.m_mass * b2.m_invI;
  580.       normal := c^.normal;
  581.       // Solver normal constraints
  582.       for j := 0 to c^.pointCount - 1 do
  583.          with c^.points[j] do
  584.          begin
  585.             {$IFDEF OP_OVERLOAD}         
  586.             _r1 := b2Mul(b1.m_xf.R, localAnchor1 - b1.GetLocalCenter);
  587.             _r2 := b2Mul(b2.m_xf.R, localAnchor2 - b2.GetLocalCenter);  
  588.             p1 := b1.m_sweep.c + _r1;
  589.             p2 := b2.m_sweep.c + _r2;
  590.             dp := p2 - p1;
  591.             {$ELSE}            
  592.             _r1 := b2Mul(b1.m_xf.R, Subtract(localAnchor1, b1.GetLocalCenter));
  593.             _r2 := b2Mul(b2.m_xf.R, Subtract(localAnchor2, b2.GetLocalCenter));  
  594.             p1 := Add(b1.m_sweep.c, _r1);
  595.             p2 := Add(b2.m_sweep.c, _r2);
  596.             dp := Subtract(p2, p1);
  597.             {$ENDIF}                        
  598.             // Approximate the current separation.
  599.             _separation := b2Dot(dp, normal) + separation;
  600.             // Track max constraint error.
  601.             minSeparation := b2Min(minSeparation, _separation);
  602.             // Compute normal impulse
  603.             dImpulse := -equalizedMass * baumgarte * b2Clamp(_separation +
  604.                b2_linearSlop, -b2_maxLinearCorrection, 0.0);
  605.             // b2Clamp the accumulated impulse
  606.             impulse0 := positionImpulse;
  607.             positionImpulse := b2Max(impulse0 + dImpulse, 0.0);
  608.             dImpulse := positionImpulse - impulse0;
  609.             {$IFDEF OP_OVERLOAD}            
  610.             impulse := dImpulse * normal;           
  611.             b1.m_sweep.c.SubtractBy(invMass1 * impulse);
  612.             {$ELSE}            
  613.             impulse := Multiply(normal, dImpulse);           
  614.             SubtractBy(b1.m_sweep.c, Multiply(impulse, invMass1));
  615.             {$ENDIF}                        
  616.             b1.m_sweep.a := b1.m_sweep.a - invI1 * b2Cross(_r1, impulse);
  617.             b1.SynchronizeTransform;
  618.             {$IFDEF OP_OVERLOAD}            
  619.             b2.m_sweep.c.AddBy(invMass2 * impulse);
  620.             {$ELSE}            
  621.             AddBy(b2.m_sweep.c, Multiply(impulse, invMass2));
  622.             {$ENDIF}                        
  623.             b2.m_sweep.a := b2.m_sweep.a + invI2 * b2Cross(_r2, impulse);
  624.             b2.SynchronizeTransform;
  625.          end;
  626.    end;
  627.    // We can't expect minSpeparation >= -b2_linearSlop because we don't
  628.    // push the separation above -b2_linearSlop.
  629.    Result := minSeparation >= -1.5 * b2_linearSlop;
  630. end;
  631. { Tb2NullContact }
  632. procedure Tb2NullContact.Evaluate(listener: Tb2ContactListener);
  633. begin
  634. end;
  635. function Tb2NullContact.GetManifolds: Pb2Manifold;
  636. begin
  637.    Result := nil;
  638. end;
  639. { Tb2ContactManager }
  640. constructor Tb2ContactManager.Create(world: Tb2World);
  641. begin         
  642.    m_world := world;
  643.    m_destroyImmediate := False;
  644. end;
  645. function Tb2ContactManager.PairAdded(proxyUserData1,
  646.    proxyUserData2: Pointer): Pointer;
  647. var
  648.    shape1, shape2: Tb2Shape;
  649.    body1, body2: Tb2Body;
  650.    c: Tb2Contact;
  651. begin
  652.    shape1 := Tb2Shape(proxyUserData1);
  653.    shape2 := Tb2Shape(proxyUserData2);
  654.    body1 := shape1.GetBody;
  655.    body2 := shape2.GetBody;
  656.    if body1.IsStatic() and body2.IsStatic() then
  657.    begin
  658.       Result := @m_nullContact;
  659.       Exit;
  660.    end;
  661.    if shape1.GetBody = shape2.GetBody then
  662.    begin
  663.       Result := @m_nullContact;
  664.       Exit;
  665.    end;
  666.    if body2.IsConnected(body1) then
  667.    begin
  668.       Result := @m_nullContact;
  669.       Exit;
  670.    end;
  671.    if Assigned(m_world.m_contactFilter) and
  672.       (not m_world.m_contactFilter.ShouldCollide(shape1, shape2)) then
  673.    begin
  674.       Result := @m_nullContact;
  675.       Exit;
  676.    end;
  677.    // Call the factory.
  678.    c := Tb2Contact.CreateContact(shape1, shape2);
  679.    // Contact creation may swap shapes.
  680.    shape1 := c.GetShape1;
  681.    shape2 := c.GetShape2;
  682.    body1 := shape1.GetBody;
  683.    body2 := shape2.GetBody;
  684.    // Insert into the world.
  685.    c.m_prev := nil;
  686.    c.m_next := m_world.m_contactList;
  687.    if Assigned(m_world.m_contactList) then
  688.       m_world.m_contactList.m_prev := c;
  689.    m_world.m_contactList := c;
  690.    // Connect to island graph.
  691.    // Connect to body 1
  692.    c.m_node1.contact := c;
  693.    c.m_node1.other := body2;
  694.    c.m_node1.prev := nil;
  695.    c.m_node1.next := body1.m_contactList;
  696.    if Assigned(body1.m_contactList) then
  697.       body1.m_contactList.prev := @c.m_node1;
  698.    body1.m_contactList := @c.m_node1;
  699.    // Connect to body 2
  700.    c.m_node2.contact := c;
  701.    c.m_node2.other := body1;
  702.    c.m_node2.prev := nil;
  703.    c.m_node2.next := body2.m_contactList;
  704.    if Assigned(body2.m_contactList) then
  705.       body2.m_contactList.prev := @c.m_node2;
  706.    body2.m_contactList := @c.m_node2;
  707.    Inc(m_world.m_contactCount);
  708.    Result := c;
  709. end;
  710. procedure Tb2ContactManager.PairRemoved(proxyUserData1, proxyUserData2,
  711.    pairUserData: Pointer);
  712. var
  713.    c: Tb2Contact;
  714. begin
  715.  //B2_NOT_USED(proxyUserData1);
  716.  //B2_NOT_USED(proxyUserData2);
  717.    if not Assigned(pairUserData) then
  718.       Exit;
  719.    c := Tb2Contact(pairUserData);
  720.    if c = @m_nullContact then
  721.       Exit;
  722.    // An attached body is being destroyed, we must destroy this contact
  723.    // immediately to avoid orphaned shape pointers.
  724.    Destroy(c);
  725. end;
  726. procedure Tb2ContactManager.Destroy(c: Tb2Contact);
  727. var
  728.    manifoldCount: Int32;
  729.    manifolds, manifold: Pb2Manifold;
  730.    cp: Tb2ContactPoint;
  731.    b1, b2: Tb2Body;
  732.    i, j: Integer;
  733.    v1, v2: TVector2;
  734. begin
  735.    b1 := c.GetShape1.GetBody;
  736.    b2 := c.GetShape2.GetBody;
  737.    // Inform the user that this contact is ending.
  738.    manifoldCount := c.GetManifoldCount;
  739.    if (manifoldCount > 0) and Assigned(m_world.m_contactListener) then
  740.    begin
  741.       manifolds := c.GetManifolds;
  742.       cp.shape1 := c.GetShape1;
  743.       cp.shape2 := c.GetShape2;
  744.       cp.friction := c.m_friction;
  745.       cp.restitution := c.m_restitution;
  746.       for i := 0 to manifoldCount - 1 do
  747.       begin
  748.          {$IFDEF D2009UP}
  749.          manifold := @manifolds[i];
  750.          {$ELSE}
  751.          manifold := Pb2Manifold(Integer(manifolds) + i * SizeOf(Tb2Manifold));
  752.          {$ENDIF}
  753.          cp.normal := manifold^.normal;
  754.          for j := 0 to manifold^.pointCount - 1 do
  755.             with manifold^.points[j] do
  756.             begin
  757.                cp.position := b1.GetWorldPoint(localPoint1);
  758.                v1 := b1.GetLinearVelocityFromLocalPoint(localPoint1);
  759.                v2 := b2.GetLinearVelocityFromLocalPoint(localPoint2);
  760.                {$IFDEF OP_OVERLOAD}               
  761.                cp.velocity := v2 - v1;
  762.                {$ELSE}               
  763.                cp.velocity := Subtract(v2, v1);
  764.                {$ENDIF}                              
  765.                cp.separation := separation;
  766.                cp.id := id;
  767.                m_world.m_contactListener.Remove(cp);
  768.             end;
  769.       end;
  770.    end;
  771.    // Remove from the world.
  772.    if Assigned(c.m_prev) then
  773.       c.m_prev.m_next := c.m_next;
  774.    if Assigned(c.m_next) then
  775.       c.m_next.m_prev := c.m_prev;
  776.    if (c = m_world.m_contactList) then
  777.       m_world.m_contactList := c.m_next;
  778.    // Remove from body 1
  779.    if Assigned(c.m_node1.prev) then
  780.       c.m_node1.prev.next := c.m_node1.next;
  781.    if Assigned(c.m_node1.next) then
  782.       c.m_node1.next.prev := c.m_node1.prev;
  783.    if @c.m_node1 = b1.m_contactList then
  784.       b1.m_contactList := c.m_node1.next;
  785.    // Remove from body 2
  786.    if Assigned(c.m_node2.prev) then
  787.       c.m_node2.prev.next := c.m_node2.next;
  788.    if Assigned(c.m_node2.next) then
  789.       c.m_node2.next.prev := c.m_node2.prev;
  790.    if @c.m_node2 = b2.m_contactList then
  791.       b2.m_contactList := c.m_node2.next;
  792.    c.Free;
  793.    Dec(m_world.m_contactCount);
  794. end;
  795. procedure Tb2ContactManager.Collide;
  796. var
  797.    c: Tb2Contact;
  798. begin
  799.    // Update awake contacts.
  800.    c := m_world.m_contactList;
  801.    while Assigned(c) do
  802.    begin
  803.       if c.GetShape1.GetBody.IsSleeping and
  804.          c.GetShape2.GetBody.IsSleeping then
  805.       begin
  806.          c := c.GetNext;
  807.          Continue;
  808.       end;
  809.       c.Update(m_world.m_contactListener);
  810.       c := c.GetNext;
  811.    end;
  812. end;
  813. ////////////////////////////////////////////////////
  814. // Island
  815. { Tb2Island }
  816. (*
  817. Position Correction Notes
  818. =========================
  819. I tried the several algorithms for position correction of the 2D revolute joint.
  820. I looked at these systems:
  821. - simple pendulum (1m diameter sphere on massless 5m stick) with initial angular velocity of 100 rad/s.
  822. - suspension bridge with 30 1m long planks of length 1m.
  823. - multi-link chain with 30 1m long links.
  824. Here are the algorithms:
  825. Baumgarte - A fraction of the position error is added to the velocity error. There is no
  826. separate position solver.
  827. Pseudo Velocities - After the velocity solver and position integration,
  828. the position error, Jacobian, and effective mass are recomputed. Then
  829. the velocity constraints are solved with pseudo velocities and a fraction
  830. of the position error is added to the pseudo velocity error. The pseudo
  831. velocities are initialized to zero and there is no warm-starting. After
  832. the position solver, the pseudo velocities are added to the positions.
  833. This is also called the First Order World method or the Position LCP method.
  834. Modified Nonlinear Gauss-Seidel (NGS) - Like Pseudo Velocities except the
  835. position error is re-computed for each constraint and the positions are updated
  836. after the constraint is solved. The radius vectors (aka Jacobians) are
  837. re-computed too (otherwise the algorithm has horrible instability). The pseudo
  838. velocity states are not needed because they are effectively zero at the beginning
  839. of each iteration. Since we have the current position error, we allow the
  840. iterations to terminate early if the error becomes smaller than b2_linearSlop.
  841. Full NGS or just NGS - Like Modified NGS except the effective mass are re-computed
  842. each time a constraint is solved.
  843. Here are the results:
  844. Baumgarte - this is the cheapest algorithm but it has some stability problems,
  845. especially with the bridge. The chain links separate easily close to the root
  846. and they jitter as they struggle to pull together. This is one of the most common
  847. methods in the field. The big drawback is that the position correction artificially
  848. affects the momentum, thus leading to instabilities and False bounce. I used a
  849. bias factor of 0.2. A larger bias factor makes the bridge less stable, a smaller
  850. factor makes joints and contacts more spongy.
  851. Pseudo Velocities - the is more stable than the Baumgarte method. The bridge is
  852. stable. However, joints still separate with large angular velocities. Drag the
  853. simple pendulum in a circle quickly and the joint will separate. The chain separates
  854. easily and does not recover. I used a bias factor of 0.2. A larger value lead to
  855. the bridge collapsing when a heavy cube drops on it.
  856. Modified NGS - this algorithm is better in some ways than Baumgarte and Pseudo
  857. Velocities, but in other ways it is worse. The bridge and chain are much more
  858. stable, but the simple pendulum goes unstable at high angular velocities.
  859. Full NGS - stable in all tests. The joints display good stiffness. The bridge
  860. still sags, but this is better than infinite forces.
  861. Recommendations
  862. Pseudo Velocities are not really worthwhile because the bridge and chain cannot
  863. recover from joint separation. In other cases the benefit over Baumgarte is small.
  864. Modified NGS is not a robust method for the revolute joint due to the violent
  865. instability seen in the simple pendulum. Perhaps it is viable with other constraint
  866. types, especially scalar constraints where the effectivprocedure Tb2Island.Solve(const step: Tb2TimeStep; const gravity: TVector2;
  867.   correctPositions, allowSleep: Boolean);
  868. begin
  869. end;
  870. procedure Tb2Island.SolveTOI(const subStep: Tb2TimeStep);
  871. begin
  872. end;
  873. e mass is a scalar.
  874. This leaves Baumgarte and Full NGS. Baumgarte has small, but manageable instabilities
  875. and is very fast. I don't think we can escape Baumgarte, especially in highly
  876. demanding cases where high constraint fidelity is not needed.
  877. Full NGS is robust and easy on the eyes. I recommend this as an option for
  878. higher fidelity simulation and certainly for suspension bridges and long chains.
  879. Full NGS might be a good choice for ragdolls, especially motorized ragdolls where
  880. joint separation can be problematic. The number of NGS iterations can be reduced
  881. for better performance without harming robustness much.
  882. Each joint in a can be handled differently in the position solver. So I recommend
  883. a system where the user can select the algorithm on a per joint basis. I would
  884. probably default to the slower Full NGS and let the user select the faster
  885. Baumgarte method in performance critical scenarios.
  886. *)
  887. constructor Tb2Island.Create(bodyCapacity, contactCapacity, jointCapacity: Int32;
  888.    listener: Tb2ContactListener);
  889. begin
  890.    m_bodyCapacity := bodyCapacity;
  891.    m_contactCapacity := contactCapacity;
  892.    m_jointCapacity  := jointCapacity;
  893.    m_bodyCount := 0;
  894.    m_contactCount := 0;
  895.    m_jointCount := 0;
  896.    m_listener := listener;
  897.    m_bodies := TList.Create;
  898.    m_bodies.Count := bodyCapacity;
  899.    m_contacts := TList.Create;
  900.    m_contacts.Count := contactCapacity;
  901.    m_joints := TList.Create;
  902.    m_joints.Count := jointCapacity;
  903.    m_positionIterationCount := 0;
  904. end;
  905. destructor Tb2Island.Destroy;
  906. begin
  907.    // Warning: the order should reverse the constructor order.
  908.    m_joints.Free;
  909.    m_contacts.Free;
  910.    m_bodies.Free;
  911.    inherited;
  912. end;
  913. procedure Tb2Island.Clear;
  914. begin
  915.    m_bodyCount := 0;
  916.    m_contactCount := 0;
  917.    m_jointCount := 0;
  918. end;
  919. procedure Tb2Island.Solve(const step: Tb2TimeStep; const gravity: TVector2;
  920.    correctPositions, allowSleep: Boolean);
  921. const
  922.    linTolSqr = b2_linearSleepTolerance * b2_linearSleepTolerance;
  923.    angTolSqr = b2_angularSleepTolerance * b2_angularSleepTolerance;
  924. var
  925.    i, j: Integer;
  926.    b: Tb2Body;
  927.    contactSolver: Tb2ContactSolver;
  928.    contactsOkay, jointsOkay: Boolean;
  929.    minSleepTime: Float;
  930. begin
  931.    // Integrate velocities and apply damping.
  932.    for i := 0 to m_bodyCount - 1 do
  933.    begin
  934.       b := Tb2Body(m_bodies[i]);
  935.       with b do
  936.       begin
  937.          if IsStatic() then
  938.             Continue;
  939.          // Integrate velocities.
  940.          {$IFDEF OP_OVERLOAD}         
  941.          m_linearVelocity.AddBy(step.dt * (gravity + m_invMass * m_force));
  942.          {$ELSE}
  943.          AddBy(m_linearVelocity, Multiply(UPhysics2DTypes.Add(gravity, 
  944.             Multiply(m_force, m_invMass)), step.dt));
  945.          {$ENDIF}                  
  946.          m_angularVelocity := m_angularVelocity + step.dt * m_invI * m_torque;
  947.          // Reset forces.
  948.          SetZero(m_force);
  949.          m_torque := 0.0;
  950.          // Apply damping.
  951.          // ODE: dv/dt + c * v = 0
  952.          // Solution: v(t) = v0 * exp(-c * t)
  953.          // Time step: v(t + dt) = v0 * exp(-c * (t + dt)) = v0 * exp(-c * t) * exp(-c * dt) = v * exp(-c * dt)
  954.          // v2 = exp(-c * dt) * v1
  955.          // Taylor expansion:
  956.          // v2 = (1.0f - c * dt) * v1
  957.          {$IFDEF OP_OVERLOAD}         
  958.          m_linearVelocity.MultiplyBy(b2Clamp(1.0 - step.dt * m_linearDamping, 0.0, 1.0));
  959.          {$ELSE}         
  960.          MultiplyBy(m_linearVelocity, b2Clamp(1.0 - step.dt * m_linearDamping, 0.0, 1.0));
  961.          {$ENDIF}                  
  962.          m_angularVelocity := m_angularVelocity * b2Clamp(1.0 - step.dt *
  963.             b.m_angularDamping, 0.0, 1.0);
  964.          // Check for large velocities.
  965.          if (b2Dot(m_linearVelocity, m_linearVelocity) > b2_maxLinearVelocitySquared) then
  966.          begin
  967.             {$IFDEF OP_OVERLOAD}         
  968.             m_linearVelocity.Normalize;
  969.             m_linearVelocity.MultiplyBy(b2_maxLinearVelocity);
  970.             {$ELSE}            
  971.             Normalize(m_linearVelocity);
  972.             MultiplyBy(m_linearVelocity, b2_maxLinearVelocity);
  973.             {$ENDIF}                        
  974.          end;
  975.          if m_angularVelocity * m_angularVelocity > b2_maxAngularVelocitySquared then
  976.             if m_angularVelocity < 0.0 then
  977.                m_angularVelocity := -b2_maxAngularVelocity
  978.             else
  979.                m_angularVelocity := b2_maxAngularVelocity;
  980.       end;
  981.    end;
  982.    contactSolver := Tb2ContactSolver.Create(step, m_contacts, m_contactCount);
  983.    try
  984.       // Initialize velocity constraints.
  985.       contactSolver.InitVelocityConstraints(step);
  986.       for i := 0 to m_jointCount - 1 do
  987.          Tb2Joint(m_joints[i]).InitVelocityConstraints(step);
  988.       // Solve velocity constraints.
  989.       if (contactSolver.m_constraintCount > 0) or (m_jointCount > 0) then
  990.          for i := 0 to step.maxIterations - 1 do
  991.          begin
  992.             contactSolver.SolveVelocityConstraints;
  993.             for j := 0 to m_jointCount - 1 do
  994.                Tb2Joint(m_joints[j]).SolveVelocityConstraints(step);
  995.          end;
  996.       // Post-solve (store impulses for warm starting).
  997.       contactSolver.FinalizeVelocityConstraints;
  998.       // Integrate positions.
  999.       for i := 0 to m_bodyCount - 1 do
  1000.       begin
  1001.          b := Tb2Body(m_bodies[i]);
  1002.          with b do
  1003.          begin
  1004.             if IsStatic() then
  1005.                Continue;
  1006.             // Store positions for continuous collision.
  1007.             m_sweep.c0 := m_sweep.c;
  1008.             m_sweep.a0 := m_sweep.a;
  1009.             // Integrate
  1010.             {$IFDEF OP_OVERLOAD}            
  1011.             m_sweep.c.AddBy(step.dt * m_linearVelocity);
  1012.             {$ELSE}            
  1013.             AddBy(m_sweep.c, Multiply(m_linearVelocity, step.dt));
  1014.             {$ENDIF}                        
  1015.             m_sweep.a := m_sweep.a + step.dt * m_angularVelocity;
  1016.             // Compute new transform
  1017.             SynchronizeTransform;
  1018.             // Note: shapes are synchronized later.
  1019.          end;
  1020.       end;
  1021.       if correctPositions then
  1022.       begin
  1023.          // Initialize position constraints.
  1024.          // Contacts don't need initialization.
  1025.          for i := 0 to m_jointCount - 1 do
  1026.             Tb2Joint(m_joints[i]).InitPositionConstraints;
  1027.          // Iterate over constraints.
  1028.          m_positionIterationCount := 0;
  1029.          while (m_positionIterationCount < step.maxIterations) do
  1030.          begin
  1031.             contactsOkay := contactSolver.SolvePositionConstraints(b2_contactBaumgarte);
  1032.             jointsOkay := True;
  1033.             for i := 0 to m_jointCount - 1 do
  1034.                jointsOkay := Tb2Joint(m_joints[i]).SolvePositionConstraints and jointsOkay;
  1035.             if contactsOkay and jointsOkay then
  1036.                Break;
  1037.             Inc(m_positionIterationCount);
  1038.          end;
  1039.       end;
  1040.       Report(contactSolver.m_constraints);
  1041.       if allowSleep then
  1042.       begin
  1043.          minSleepTime := FLT_MAX;
  1044.          for i := 0 to m_bodyCount - 1 do
  1045.          begin
  1046.             b := Tb2Body(m_bodies[i]);
  1047.             with b do
  1048.             begin
  1049.                if m_invMass = 0.0 then
  1050.                   Continue;
  1051.                if (m_flags and e_allowSleepFlag) = 0 then
  1052.                begin
  1053.                   m_sleepTime := 0.0;
  1054.                   minSleepTime := 0.0;
  1055.                end;
  1056.                if ((m_flags and e_allowSleepFlag) = 0) or
  1057.                   (m_angularVelocity * m_angularVelocity > angTolSqr) or
  1058.                   (b2Dot(m_linearVelocity, m_linearVelocity) > linTolSqr) then
  1059.                begin
  1060.                   m_sleepTime := 0.0;
  1061.                   minSleepTime := 0.0;
  1062.                end
  1063.                else
  1064.                begin
  1065.                   m_sleepTime := m_sleepTime + step.dt;
  1066.                   minSleepTime := b2Min(minSleepTime, m_sleepTime);
  1067.                end;
  1068.             end;
  1069.          end;
  1070.          if minSleepTime >= b2_timeToSleep then
  1071.             for i := 0 to m_bodyCount - 1 do
  1072.             begin
  1073.                b := Tb2Body(m_bodies[i]);
  1074.                with b do
  1075.                begin
  1076.                   m_flags := m_flags or e_sleepFlag;
  1077.                   m_linearVelocity := b2Vec2_zero;
  1078.                   m_angularVelocity := 0.0;
  1079.                end;
  1080.             end;
  1081.       end;
  1082.    finally
  1083.       contactSolver.Free;
  1084.    end;
  1085. end;
  1086. procedure Tb2Island.SolveTOI(const subStep: Tb2TimeStep);
  1087. var
  1088.    b: Tb2Body;
  1089.    i: Integer;
  1090.    contactSolver: Tb2ContactSolver;
  1091. begin
  1092.    contactSolver := Tb2ContactSolver.Create(subStep, m_contacts, m_contactCount);
  1093.    try
  1094.       // No warm starting needed for TOI events.
  1095.       // Solve velocity constraints.
  1096.       for i := 0 to subStep.maxIterations - 1 do
  1097.          contactSolver.SolveVelocityConstraints;
  1098.       // Don't store the TOI contact forces for warm starting
  1099.       // because they can be quite large.
  1100.       // Integrate positions.
  1101.       for i := 0 to m_bodyCount - 1 do
  1102.       begin
  1103.          b := Tb2Body(m_bodies[i]);
  1104.          with b do
  1105.          begin
  1106.             if IsStatic() then
  1107.               Continue;
  1108.             // Store positions for continuous collision.
  1109.             m_sweep.c0 := m_sweep.c;
  1110.             m_sweep.a0 := m_sweep.a;
  1111.             // Integrate
  1112.             {$IFDEF OP_OVERLOAD}
  1113.             m_sweep.c.AddBy(subStep.dt * m_linearVelocity);
  1114.             {$ELSE}            
  1115.             AddBy(m_sweep.c, Multiply(m_linearVelocity, subStep.dt));
  1116.             {$ENDIF}                        
  1117.             m_sweep.a := m_sweep.a + subStep.dt * m_angularVelocity;
  1118.             // Compute new transform
  1119.             SynchronizeTransform;
  1120.             // Note: shapes are synchronized later.
  1121.          end;
  1122.       end;
  1123.       // Solve position constraints.
  1124.       for i := 0 to subStep.maxIterations - 1 do
  1125.          if contactSolver.SolvePositionConstraints(0.75) then
  1126.             Break;
  1127.       Report(contactSolver.m_constraints);
  1128.    finally
  1129.       contactSolver.Free;
  1130.    end;
  1131. end;
  1132. procedure Tb2Island.Add(body: Tb2Body);
  1133. begin
  1134.  //b2Assert(m_bodyCount < m_bodyCapacity);
  1135.    m_bodies[m_bodyCount] := body;
  1136.    Inc(m_bodyCount);
  1137. end;
  1138. procedure Tb2Island.Add(contact: Tb2Contact);
  1139. begin
  1140.  //b2Assert(m_contactCount < m_contactCapacity);
  1141.    m_contacts[m_contactCount] := contact;
  1142.    Inc(m_contactCount);
  1143. end;
  1144. procedure Tb2Island.Add(joint: Tb2Joint);
  1145. begin
  1146.  //b2Assert(m_jointCount < m_jointCapacity);
  1147.    m_joints[m_jointCount] := joint;
  1148.    Inc(m_jointCount);
  1149. end;
  1150. procedure Tb2Island.Report(constraints: Pb2ContactConstraint);
  1151. var
  1152.    i, j, k: Integer;
  1153.    c: Tb2Contact;
  1154.    cc: Pb2ContactConstraint;
  1155.    cr: Tb2ContactResult;
  1156.    b1: Tb2Body;
  1157.    manifoldCount: Int32;
  1158.    manifolds, manifold: Pb2Manifold;
  1159.    point: Pb2ManifoldPoint;
  1160. begin
  1161.    if not Assigned(m_listener) then
  1162.       Exit;
  1163.    for i := 0 to m_contactCount - 1 do
  1164.    begin
  1165.       c := Tb2Contact(m_contacts[i]);
  1166.       {$IFDEF D2009UP}
  1167.       cc := constraints + i;
  1168.       {$ELSE}
  1169.       cc := Pb2ContactConstraint(Integer(constraints) + i * SizeOf(Tb2ContactConstraint));
  1170.       {$ENDIF}
  1171.       cr.shape1 := c.GetShape1;
  1172.       cr.shape2 := c.GetShape2;
  1173.       b1 := cr.shape1.GetBody;
  1174.       manifoldCount := c.GetManifoldCount;
  1175.       manifolds := c.GetManifolds;
  1176.       for j := 0 to manifoldCount - 1 do
  1177.       begin
  1178.          {$IFDEF D2009UP}
  1179.          manifold := manifolds + j;
  1180.          {$ELSE}
  1181.          manifold := Pb2Manifold(Integer(manifolds) + j * SizeOf(Tb2Manifold));
  1182.          {$ENDIF}
  1183.          cr.normal := manifold.normal;
  1184.          for k := 0 to manifold^.pointCount - 1 do
  1185.          begin
  1186.             point := @manifold.points[k];
  1187.             with cc.points[k] do
  1188.             begin
  1189.                cr.position := b1.GetWorldPoint(point^.localPoint1);
  1190.                // TOI constraint results are not stored, so get
  1191.                // the result from the constraint.
  1192.                cr.normalImpulse := normalImpulse;
  1193.                cr.tangentImpulse := tangentImpulse;
  1194.                cr.id := point^.id;
  1195.                m_listener.Result(cr);
  1196.             end;
  1197.          end;
  1198.       end;
  1199.    end;
  1200. end;
  1201. ////////////////////////////////////////////////////
  1202. //
  1203. {$IFDEF OP_OVERLOAD}
  1204. function Tb2Bound.IsLower: Boolean;
  1205. begin
  1206.    Result := (value and 1) = 0;
  1207. end;
  1208. function Tb2Bound.IsUpper: Boolean;
  1209. begin
  1210.    Result := (value and 1) = 1;
  1211. end;
  1212. {$ENDIF}
  1213. {$IFDEF OP_OVERLOAD}
  1214. function Tb2Proxy.GetNext: UInt16;
  1215. begin
  1216.    Result := lowerBounds[0];
  1217. end;
  1218. procedure Tb2Proxy.SetNext(Next: UInt16);
  1219. begin
  1220.    lowerBounds[0] := Next;
  1221. end;
  1222. function Tb2Proxy.IsValid: Boolean;
  1223. begin
  1224.    Result := overlapCount <> b2_invalid;
  1225. end;
  1226. {$ENDIF}
  1227. { Tb2BroadPhase }
  1228. constructor Tb2BroadPhase.Create(const worldAABB: Tb2AABB; callback: Tb2PairCallback);
  1229. var
  1230.    d: TVector2;
  1231.    i: Integer;
  1232. begin
  1233.    m_pairManager := Tb2PairManager.Create;
  1234.    m_pairManager.Initialize(Self, callback);
  1235.    //b2Assert(worldAABB.IsValid());
  1236.    m_worldAABB := worldAABB;
  1237.    m_proxyCount := 0;
  1238.    {$IFDEF OP_OVERLOAD}   
  1239.    d := worldAABB.upperBound - worldAABB.lowerBound;
  1240.    {$ELSE}   
  1241.    d := Subtract(worldAABB.upperBound, worldAABB.lowerBound);
  1242.    {$ENDIF}      
  1243.    m_quantizationFactor.x := B2BROADPHASE_MAX / d.x;
  1244.    m_quantizationFactor.y := B2BROADPHASE_MAX / d.y;
  1245.    for i := 0 to b2_maxProxies - 2 do
  1246.       with m_proxyPool[i] do
  1247.       begin
  1248.          {$IFDEF OP_OVERLOAD}      
  1249.          SetNext(i + 1);
  1250.          {$ELSE}         
  1251.          //SetNext(m_proxyPool[i], i + 1);
  1252.          lowerBounds[0] := i + 1;
  1253.          {$ENDIF}                  
  1254.          timeStamp := 0;
  1255.          overlapCount := b2_invalid;
  1256.          userData := nil;
  1257.       end;
  1258.    with m_proxyPool[b2_maxProxies - 1] do
  1259.    begin
  1260.       {$IFDEF OP_OVERLOAD}   
  1261.       SetNext(b2_nullProxy);
  1262.       {$ELSE}      
  1263.       //SetNext(m_proxyPool[b2_maxProxies - 1], b2_nullProxy);
  1264.       lowerBounds[0] := b2_nullProxy;
  1265.       {$ENDIF}            
  1266.       timeStamp := 0;
  1267.       overlapCount := b2_invalid;
  1268.       userData := nil;
  1269.    end;
  1270.    m_freeProxy := 0;
  1271.    m_timeStamp := 1;
  1272.    m_queryResultCount := 0;
  1273. end;
  1274. destructor Tb2BroadPhase.Destroy;
  1275. begin
  1276.    m_pairManager.Free;
  1277.    inherited;
  1278. end;
  1279. procedure Tb2BroadPhase.ComputeBounds(var lowerValues, upperValues: Tb2BoundValuesArray;
  1280.    const aabb: Tb2AABB);
  1281. var
  1282.    minVertex, maxVertex: TVector2;
  1283. begin
  1284.    //b2Assert(aabb.upperBound.x > aabb.lowerBound.x);
  1285.    //b2Assert(aabb.upperBound.y > aabb.lowerBound.y);
  1286.    minVertex := b2Clamp(aabb.lowerBound, m_worldAABB.lowerBound, m_worldAABB.upperBound);
  1287.    maxVertex := b2Clamp(aabb.upperBound, m_worldAABB.lowerBound, m_worldAABB.upperBound);
  1288.    // Bump lower bounds downs and upper bounds up. This ensures correct sorting of
  1289.    // lower/upper bounds that would have equal values.
  1290.    // TODO_ERIN implement fast float to uint16 conversion.
  1291.    lowerValues[0] := UInt16(Trunc((m_quantizationFactor.x * (minVertex.x -
  1292.       m_worldAABB.lowerBound.x)))) and (B2BROADPHASE_MAX - 1);
  1293.    upperValues[0] := UInt16(Trunc((m_quantizationFactor.x * (maxVertex.x -
  1294.       m_worldAABB.lowerBound.x)))) or 1;
  1295.    lowerValues[1] := UInt16(Trunc((m_quantizationFactor.y * (minVertex.y -
  1296.       m_worldAABB.lowerBound.y)))) and (B2BROADPHASE_MAX - 1);
  1297.    upperValues[1] := UInt16(Trunc((m_quantizationFactor.y * (maxVertex.y -
  1298.       m_worldAABB.lowerBound.y)))) or 1;
  1299. end;
  1300. function Tb2BroadPhase.TestOverlap(var p1, p2: Tb2Proxy): Boolean;
  1301. var
  1302.    axis: Integer;
  1303.    bounds: Pb2AxialBoundsArray;
  1304. begin
  1305.    for axis := 0 to 1 do
  1306.    begin
  1307.       bounds := @m_bounds[axis];
  1308.       //b2Assert(p1->lowerBounds[axis] < 2 * m_proxyCount);
  1309.       //b2Assert(p1->upperBounds[axis] < 2 * m_proxyCount);
  1310.       //b2Assert(p2->lowerBounds[axis] < 2 * m_proxyCount);
  1311.       //b2Assert(p2->upperBounds[axis] < 2 * m_proxyCount);
  1312.       if bounds^[p1.lowerBounds[axis]].value > bounds^[p2.upperBounds[axis]].value then
  1313.       begin
  1314.          Result := False;
  1315.          Exit;
  1316.       end;
  1317.       if bounds^[p1.upperBounds[axis]].value < bounds^[p2.lowerBounds[axis]].value then
  1318.       begin
  1319.          Result := False;
  1320.          Exit;
  1321.       end;
  1322.    end;
  1323.    Result := True;
  1324. end;
  1325. function Tb2BroadPhase.TestOverlap(const b: Tb2BoundValues; var p: Tb2Proxy): Boolean;
  1326. var
  1327.    axis: Integer;
  1328.    bounds: Pb2AxialBoundsArray;
  1329. begin
  1330.    for axis := 0 to 1 do
  1331.    begin
  1332.       bounds := @m_bounds[axis];
  1333.       //b2Assert(p->lowerBounds[axis] < 2 * m_proxyCount);
  1334.       //b2Assert(p->upperBounds[axis] < 2 * m_proxyCount);
  1335.       if b.lowerValues[axis] > bounds^[p.upperBounds[axis]].value then
  1336.       begin
  1337.          Result := False;
  1338.          Exit;
  1339.       end;
  1340.       if b.upperValues[axis] < bounds^[p.lowerBounds[axis]].value then
  1341.       begin
  1342.          Result := False;
  1343.          Exit;
  1344.       end;
  1345.    end;
  1346.    Result := True;
  1347. end;
  1348. procedure Tb2BroadPhase.Query(var lowerIndex, upperIndex: Int32; lowerValue,
  1349.    upperValue: UInt16; var bounds: Tb2AxialBoundsArray; boundCount, axis: Int32);
  1350. var
  1351.    i, s: Integer;
  1352.    lowerQuery, upperQuery: Int32;
  1353. begin
  1354.    lowerQuery := BroadPhase_BinarySearch(bounds, boundCount, lowerValue);
  1355.    upperQuery := BroadPhase_BinarySearch(bounds, boundCount, upperValue);
  1356.    // Easy case: lowerQuery <= lowerIndex(i) < upperQuery
  1357.    // Solution: search query range for min bounds.
  1358.    for i := lowerQuery to upperQuery - 1 do
  1359.    begin
  1360.       {$IFDEF OP_OVERLOAD}
  1361.       if bounds[i].IsLower() then
  1362.       {$ELSE}      
  1363.       if IsLower(bounds[i]) then
  1364.       {$ENDIF}            
  1365.         IncrementOverlapCount(bounds[i].proxyId);
  1366.    end;
  1367.    // Hard case: lowerIndex(i) < lowerQuery < upperIndex(i)
  1368.    // Solution: use the stabbing count to search down the bound array.
  1369.    if lowerQuery > 0 then
  1370.    begin
  1371.       i := lowerQuery - 1;
  1372.       s := bounds[i].stabbingCount;
  1373.       // Find the s overlaps.
  1374.       while (s > 0) do  //b2Assert(i >= 0);
  1375.          with bounds[i] do
  1376.          begin
  1377.             {$IFDEF OP_OVERLOAD}
  1378.             if IsLower() then
  1379.             {$ELSE}            
  1380.             if IsLower(bounds[i]) then
  1381.             {$ENDIF}                        
  1382.                if lowerQuery <= m_proxyPool[proxyId].upperBounds[axis] then
  1383.                begin
  1384.                   IncrementOverlapCount(proxyId);
  1385.                   Dec(s);
  1386.                end;
  1387.             Dec(i);
  1388.          end;
  1389.    end;
  1390.    lowerIndex := lowerQuery;
  1391.    upperIndex := upperQuery;
  1392. end;
  1393. procedure Tb2BroadPhase.IncrementOverlapCount(proxyId: Int32);
  1394. begin
  1395.    with m_proxyPool[proxyId] do
  1396.       if timeStamp < m_timeStamp then
  1397.       begin
  1398.          timeStamp := m_timeStamp;
  1399.          overlapCount := 1;
  1400.       end
  1401.       else
  1402.       begin
  1403.          overlapCount := 2;
  1404.          //b2Assert(m_queryResultCount < b2_maxProxies);
  1405.          m_queryResults[m_queryResultCount] := proxyId;
  1406.          Inc(m_queryResultCount);
  1407.       end;
  1408. end;
  1409. procedure Tb2BroadPhase.IncrementTimeStamp;
  1410. var
  1411.    i: Integer;
  1412. begin
  1413.    if m_timeStamp = B2BROADPHASE_MAX then
  1414.    begin
  1415.       for i := 0 to b2_maxProxies - 1 do
  1416.          m_proxyPool[i].timeStamp := 0;
  1417.       m_timeStamp := 1;
  1418.    end
  1419.    else
  1420.       Inc(m_timeStamp);
  1421. end;
  1422. function Tb2BroadPhase.InRange(const aabb: Tb2AABB): Boolean;
  1423. var
  1424.    d: TVector2;
  1425. begin
  1426.    {$IFDEF OP_OVERLOAD}
  1427.    d := b2Max(aabb.lowerBound - m_worldAABB.upperBound,
  1428.       m_worldAABB.lowerBound - aabb.upperBound);
  1429.    {$ELSE}      
  1430.    d := b2Max(Subtract(aabb.lowerBound, m_worldAABB.upperBound),
  1431.       Subtract(m_worldAABB.lowerBound, aabb.upperBound));
  1432.    {$ENDIF}      
  1433.    Result := b2Max(d.x, d.y) < 0.0;
  1434. end;
  1435. function Tb2BroadPhase.CreateProxy(const aabb: Tb2AABB; userData: Pointer): UInt16;
  1436. var
  1437.    AproxyId: UInt16;
  1438.    proxy: Pb2Proxy;
  1439.    index, boundCount, axis, lowerIndex, upperIndex: Int32;
  1440.    lowerValues, upperValues: Tb2BoundValuesArray;
  1441.    bounds: Pb2AxialBoundsArray;
  1442. begin
  1443.    //b2Assert(m_proxyCount < b2_maxProxies);
  1444.    //b2Assert(m_freeProxy != b2_nullProxy);
  1445.    AproxyId := m_freeProxy;
  1446.    proxy := @(m_proxyPool[AproxyId]);
  1447.    {$IFDEF OP_OVERLOAD}   
  1448.    m_freeProxy := proxy^.GetNext;
  1449.    {$ELSE}   
  1450.    m_freeProxy := GetNext(proxy^);
  1451.    {$ENDIF}      
  1452.    proxy^.overlapCount := 0;
  1453.    proxy^.userData := userData;
  1454.    boundCount := 2 * m_proxyCount;
  1455.    ComputeBounds(lowerValues, upperValues, aabb);
  1456.    for axis := 0 to 1 do
  1457.    begin
  1458.       bounds := @m_bounds[axis];
  1459.       Query(lowerIndex, upperIndex, lowerValues[axis], upperValues[axis],
  1460.          bounds^, boundCount, axis);
  1461.       Move(bounds^[upperIndex], bounds^[upperIndex + 2],
  1462.          (boundCount - upperIndex) * SizeOf(Tb2Bound));
  1463.       Move(bounds^[lowerIndex], bounds^[lowerIndex + 1],
  1464.          (upperIndex - lowerIndex) * SizeOf(Tb2Bound));
  1465.       // The upper index has increased because of the lower bound insertion.
  1466.       Inc(upperIndex);
  1467.       // Copy in the new bounds.
  1468.       with bounds^[lowerIndex] do
  1469.       begin
  1470.          value := lowerValues[axis];
  1471.          proxyId := AproxyId;
  1472.          if lowerIndex = 0 then
  1473.             stabbingCount := 0
  1474.          else
  1475.             stabbingCount := bounds^[lowerIndex - 1].stabbingCount;
  1476.       end;
  1477.       with bounds^[upperIndex] do
  1478.       begin
  1479.          value := upperValues[axis];
  1480.          proxyId := AproxyId;
  1481.          stabbingCount := bounds^[upperIndex - 1].stabbingCount;
  1482.       end;
  1483.       // Adjust the stabbing count between the new bounds.
  1484.       for index := lowerIndex to upperIndex - 1 do
  1485.          Inc(bounds^[index].stabbingCount);
  1486.       // Adjust the all the affected bound indices.
  1487.       for index := lowerIndex to boundCount + 1 do
  1488.       begin
  1489.          proxy := @m_proxyPool[bounds^[index].proxyId];
  1490.          {$IFDEF OP_OVERLOAD}
  1491.          if bounds^[index].IsLower() then
  1492.          {$ELSE}         
  1493.          if IsLower(bounds^[index]) then
  1494.          {$ENDIF}                  
  1495.             proxy^.lowerBounds[axis] := index
  1496.          else
  1497.             proxy^.upperBounds[axis] := index;
  1498.       end;
  1499.    end;
  1500.    Inc(m_proxyCount);
  1501.    //b2Assert(m_queryResultCount < b2_maxProxies);
  1502.    // Create pairs if the AABB is in range.
  1503.    for index := 0 to m_queryResultCount - 1 do
  1504.    begin
  1505.       //b2Assert(m_queryResults[i] < b2_maxProxies);
  1506.       //b2Assert(m_proxyPool[m_queryResults[i]].IsValid());
  1507.       m_pairManager.AddBufferedPair(AproxyId, m_queryResults[index]);
  1508.    end;
  1509.    m_pairManager.Commit;
  1510.    {$IFDEF CLASSVAR_AVAIL}
  1511.    if s_validate then
  1512.    {$ELSE}
  1513.    if b2BroadPhase_s_validate then
  1514.    {$ENDIF}
  1515.       Validate;
  1516.    // Prepare for next query.
  1517.    m_queryResultCount := 0;
  1518.    IncrementTimeStamp;
  1519.    Result := AproxyId;
  1520. end;
  1521. procedure Tb2BroadPhase.DestroyProxy(proxyId: Int32);
  1522. var
  1523.    proxy, proxy2: Pb2Proxy;
  1524.    i, boundCount: Int32;
  1525.    axis: Integer;
  1526.    bounds: Pb2AxialBoundsArray;
  1527.    lowerIndex, upperIndex: Int32;
  1528.    lowerValue, upperValue: UInt16;
  1529. begin
  1530.    //b2Assert(0 < m_proxyCount && m_proxyCount <= b2_maxProxies);
  1531.    proxy := @m_proxyPool[proxyId];
  1532.    //b2Assert(proxy->IsValid());
  1533.    boundCount := 2 * m_proxyCount;
  1534.    for axis := 0 to 1 do
  1535.    begin
  1536.       bounds := @m_bounds[axis];
  1537.       lowerIndex := proxy^.lowerBounds[axis];
  1538.       upperIndex := proxy^.upperBounds[axis];
  1539.       lowerValue := bounds^[lowerIndex].value;
  1540.       upperValue := bounds^[upperIndex].value;
  1541.       Move(bounds^[lowerIndex + 1], bounds^[lowerIndex],
  1542.          (upperIndex - lowerIndex - 1) * SizeOf(Tb2Bound));
  1543.       Move(bounds^[upperIndex + 1], bounds^[upperIndex - 1],
  1544.          (boundCount - upperIndex - 1) * SizeOf(Tb2Bound));
  1545.       // Fix bound indices.
  1546.       for i := lowerIndex to boundCount - 3 do
  1547.       begin
  1548.          proxy2 := @m_proxyPool[bounds^[i].proxyId];
  1549.          {$IFDEF OP_OVERLOAD}
  1550.          if bounds^[i].IsLower() then
  1551.          {$ELSE}         
  1552.          if IsLower(bounds^[i]) then
  1553.          {$ENDIF}                  
  1554.             proxy2^.lowerBounds[axis] := i
  1555.          else
  1556.             proxy2^.upperBounds[axis] := i;
  1557.       end;
  1558.       // Fix stabbing count.
  1559.       for i := lowerIndex to upperIndex - 2 do
  1560.          Dec(bounds^[i].stabbingCount);
  1561.       // Query for pairs to be removed. lowerIndex and upperIndex are not needed.
  1562.       Query(lowerIndex, upperIndex, lowerValue, upperValue,
  1563.          bounds^, boundCount - 2, axis);
  1564.    end;
  1565.    //b2Assert(m_queryResultCount < b2_maxProxies);
  1566.    for i := 0 to m_queryResultCount - 1 do
  1567.    begin
  1568.       //b2Assert(m_proxyPool[m_queryResults[i]].IsValid());
  1569.       m_pairManager.RemoveBufferedPair(proxyId, m_queryResults[i]);
  1570.    end;
  1571.    m_pairManager.Commit;
  1572.    // Prepare for next query.
  1573.    m_queryResultCount := 0;
  1574.    IncrementTimeStamp;
  1575.    // Return the proxy to the pool.
  1576.    with proxy^ do
  1577.    begin
  1578.       userData := nil;
  1579.       overlapCount := b2_invalid;
  1580.       lowerBounds[0] := b2_invalid;
  1581.       lowerBounds[1] := b2_invalid;
  1582.       upperBounds[0] := b2_invalid;
  1583.       upperBounds[1] := b2_invalid;
  1584.    end;
  1585.    {$IFDEF OP_OVERLOAD}   
  1586.    proxy^.SetNext(m_freeProxy);
  1587.    {$ELSE}   
  1588.    SetNext(proxy^, m_freeProxy);
  1589.    {$ENDIF}      
  1590.    m_freeProxy := proxyId;
  1591.    Dec(m_proxyCount);
  1592.    {$IFDEF CLASSVAR_AVAIL}
  1593.    if s_validate then
  1594.    {$ELSE}
  1595.    if b2BroadPhase_s_validate then
  1596.    {$ENDIF}
  1597.       Validate;
  1598. end;
  1599. procedure Tb2BroadPhase.MoveProxy(proxyId: Int32; const aabb: Tb2AABB);
  1600. var
  1601.    axis: Integer;
  1602.    index, boundCount, prevProxyId, nextProxyId: Int32;
  1603.    lowerIndex, upperIndex, deltaLower, deltaUpper: Int32;
  1604.    lowerValue, upperValue: UInt16;   
  1605.    proxy, prevProxy, nextProxy: Pb2Proxy;
  1606.    newValues, oldValues: Tb2BoundValues;
  1607.    bounds: Pb2AxialBoundsArray;
  1608.    bound, prevBound, nextBound: Pb2Bound;
  1609. begin
  1610.    if (proxyId = b2_nullProxy) or (b2_maxProxies <= proxyId) then
  1611.    begin
  1612.       //b2Assert(False);
  1613.       Exit;
  1614.    end;
  1615.    {$IFDEF OP_OVERLOAD}   
  1616.    if not aabb.IsValid() then
  1617.    {$ELSE}   
  1618.    if not IsValid(aabb) then
  1619.    {$ENDIF}      
  1620.    begin
  1621.       //b2Assert(False);
  1622.       Exit;;
  1623.    end;
  1624.    boundCount := 2 * m_proxyCount;
  1625.    proxy := @m_proxyPool[proxyId];
  1626.    // Get new bound values
  1627.    ComputeBounds(newValues.lowerValues, newValues.upperValues, aabb);
  1628.    // Get old bound values
  1629.    for axis := 0 to 1 do
  1630.    begin
  1631.       oldValues.lowerValues[axis] := m_bounds[axis][proxy^.lowerBounds[axis]].value;
  1632.       oldValues.upperValues[axis] := m_bounds[axis][proxy^.upperBounds[axis]].value;
  1633.    end;
  1634.    for axis := 0 to 1 do
  1635.    begin
  1636.       bounds := @m_bounds[axis];
  1637.       lowerIndex := proxy^.lowerBounds[axis];
  1638.       upperIndex := proxy^.upperBounds[axis];
  1639.       lowerValue := newValues.lowerValues[axis];
  1640.       upperValue := newValues.upperValues[axis];
  1641.       deltaLower := lowerValue - bounds^[lowerIndex].value;
  1642.       deltaUpper := upperValue - bounds^[upperIndex].value;
  1643.       bounds^[lowerIndex].value := lowerValue;
  1644.       bounds^[upperIndex].value := upperValue;
  1645.       // Expanding adds overlaps
  1646.       // Should we move the lower bound down?
  1647.       if deltaLower < 0 then
  1648.       begin
  1649.          index := lowerIndex;
  1650.          while ((index > 0) and (lowerValue < bounds^[index - 1].value)) do
  1651.          begin
  1652.             bound := @bounds^[index];
  1653.             prevBound := @bounds^[index - 1];
  1654.             prevProxyId := prevBound^.proxyId;
  1655.             prevProxy := @m_proxyPool[prevProxyId];
  1656.             Inc(prevBound^.stabbingCount);
  1657.             {$IFDEF OP_OVERLOAD}            
  1658.             if prevBound^.IsUpper() then
  1659.             {$ELSE}            
  1660.             if IsUpper(prevBound^) then
  1661.             {$ENDIF}                        
  1662.             begin
  1663.               if TestOverlap(newValues, prevProxy^) then
  1664.                  m_pairManager.AddBufferedPair(proxyId, prevProxyId);
  1665.                Inc(prevProxy^.upperBounds[axis]);
  1666.                Inc(bound^.stabbingCount);
  1667.             end
  1668.             else
  1669.             begin
  1670.                Inc(prevProxy^.lowerBounds[axis]);
  1671.                Dec(bound^.stabbingCount);
  1672.             end;
  1673.             Dec(proxy^.lowerBounds[axis]);
  1674.             b2Swap(bound^, prevBound^);
  1675.             Dec(index);
  1676.          end;
  1677.       end;
  1678.       // Should we move the upper bound up?
  1679.       if deltaUpper > 0 then
  1680.       begin
  1681.          index := upperIndex;
  1682.          while ((index < boundCount - 1) and (bounds^[index + 1].value <= upperValue)) do
  1683.          begin
  1684.             bound := @bounds^[index];
  1685.             nextBound := @bounds^[index + 1];
  1686.             nextProxyId := nextBound^.proxyId;
  1687.             nextProxy := @m_proxyPool[nextProxyId];
  1688.             Inc(nextBound^.stabbingCount);
  1689.             {$IFDEF OP_OVERLOAD}
  1690.             if nextBound^.IsLower() then
  1691.             {$ELSE}            
  1692.             if IsLower(nextBound^) then
  1693.             {$ENDIF}                        
  1694.             begin
  1695.                if TestOverlap(newValues, nextProxy^) then
  1696.                   m_pairManager.AddBufferedPair(proxyId, nextProxyId);
  1697.                Dec(nextProxy^.lowerBounds[axis]);
  1698.                Inc(bound^.stabbingCount);
  1699.             end
  1700.             else
  1701.             begin
  1702.                Dec(nextProxy^.upperBounds[axis]);
  1703.                Dec(bound^.stabbingCount);
  1704.             end;
  1705.             Inc(proxy^.upperBounds[axis]);
  1706.             b2Swap(bound^, nextBound^);
  1707.             Inc(index);
  1708.          end;
  1709.       end;
  1710.       // Shrinking removes overlaps
  1711.       // Should we move the lower bound up?
  1712.       if deltaLower > 0 then
  1713.       begin
  1714.          index := lowerIndex;
  1715.          while (index < boundCount - 1) and (bounds^[index + 1].value <= lowerValue) do
  1716.          begin
  1717.             bound := @bounds^[index];
  1718.             nextBound := @bounds^[index + 1];
  1719.             nextProxyId := nextBound^.proxyId;
  1720.             nextProxy := @m_proxyPool[nextProxyId];
  1721.             Dec(nextBound^.stabbingCount);
  1722.             {$IFDEF OP_OVERLOAD}            
  1723.             if nextBound^.IsUpper() then
  1724.             {$ELSE}            
  1725.             if IsUpper(nextBound^) then
  1726.             {$ENDIF}                        
  1727.             begin
  1728.                if TestOverlap(oldValues, nextProxy^) then
  1729.                   m_pairManager.RemoveBufferedPair(proxyId, nextProxyId);
  1730.                Dec(nextProxy^.upperBounds[axis]);
  1731.                Dec(bound^.stabbingCount);
  1732.             end
  1733.             else
  1734.             begin
  1735.                Dec(nextProxy^.lowerBounds[axis]);
  1736.                Inc(bound^.stabbingCount);
  1737.             end;
  1738.             Inc(proxy^.lowerBounds[axis]);
  1739.             b2Swap(bound^, nextBound^);
  1740.             Inc(index);
  1741.          end;
  1742.       end;
  1743.       // Should we move the upper bound down?
  1744.       if deltaUpper < 0 then
  1745.       begin
  1746.          index := upperIndex;
  1747.          while (index > 0) and (upperValue < bounds^[index - 1].value) do
  1748.          begin
  1749.             bound := @bounds^[index];
  1750.             prevBound := @bounds^[index - 1];
  1751.             prevProxyId := prevBound^.proxyId;
  1752.             prevProxy := @m_proxyPool[prevProxyId];
  1753.             Dec(prevBound^.stabbingCount);
  1754.             {$IFDEF OP_OVERLOAD}
  1755.             if prevBound^.IsLower() then
  1756.             {$ELSE}            
  1757.             if IsLower(prevBound^) then
  1758.             {$ENDIF}                        
  1759.             begin
  1760.                if TestOverlap(oldValues, prevProxy^) then
  1761.                   m_pairManager.RemoveBufferedPair(proxyId, prevProxyId);
  1762.                Inc(prevProxy^.lowerBounds[axis]);
  1763.                Dec(bound^.stabbingCount);
  1764.             end
  1765.             else
  1766.             begin
  1767.                Inc(prevProxy^.upperBounds[axis]);
  1768.                Inc(bound^.stabbingCount);
  1769.             end;
  1770.             Dec(proxy^.upperBounds[axis]);
  1771.             b2Swap(bound^, prevBound^);
  1772.             Dec(index);
  1773.          end;
  1774.       end;
  1775.    end;
  1776.    {$IFDEF CLASSVAR_AVAIL}
  1777.    if s_validate then
  1778.    {$ELSE}
  1779.    if b2BroadPhase_s_validate then
  1780.    {$ENDIF}
  1781.      Validate;
  1782. end;
  1783. procedure Tb2BroadPhase.Commit;
  1784. begin
  1785.    m_pairManager.Commit;
  1786. end;
  1787. function Tb2BroadPhase.GetProxy(proxyId: Int32): Pb2Proxy;
  1788. begin
  1789.    {$IFDEF OP_OVERLOAD}
  1790.    if (proxyId = b2_nullProxy) or (not m_proxyPool[proxyId].IsValid) then
  1791.    {$ELSE}   
  1792.    if (proxyId = b2_nullProxy) or (not IsValid(m_proxyPool[proxyId])) then
  1793.    {$ENDIF}      
  1794.       Result := nil
  1795.    else
  1796.       Result := @(m_proxyPool[proxyId]);
  1797. end;
  1798. function Tb2BroadPhase.Query(const aabb: Tb2AABB; userData: TList;
  1799.    maxCount: Int32): Int32;
  1800. var
  1801.    lowerValues, upperValues: Tb2BoundValuesArray;
  1802.    lowerIndex, upperIndex: Int32;
  1803.    count: Int32;
  1804.    i: Integer;
  1805.    proxy: Pb2Proxy;
  1806. begin
  1807.    ComputeBounds(lowerValues, upperValues, aabb);
  1808.    Query(lowerIndex, upperIndex, lowerValues[0], upperValues[0],
  1809.       m_bounds[0], 2 * m_proxyCount, 0);
  1810.    Query(lowerIndex, upperIndex, lowerValues[1], upperValues[1],
  1811.       m_bounds[1], 2 * m_proxyCount, 1);
  1812.    //b2Assert(m_queryResultCount < b2_maxProxies);
  1813.    count := 0;
  1814.    i := 0;
  1815.    while (i < m_queryResultCount) and (count < maxCount) do
  1816.    begin
  1817.       {//b2Assert(m_queryResults[i] < b2_maxProxies);
  1818.       proxy := @m_proxyPool[m_queryResults[i]];
  1819.       //b2Assert(proxy->IsValid());
  1820.       userData[i] := proxy^.userData;    }
  1821.       userData.Add(m_proxyPool[m_queryResults[i]].userData);
  1822.       Inc(i);
  1823.       Inc(count);
  1824.    end;
  1825.    // Prepare for next query.
  1826.    m_queryResultCount := 0;
  1827.    IncrementTimeStamp;
  1828.    Result := count;
  1829. end;
  1830. procedure Tb2BroadPhase.Validate;
  1831. var
  1832.    axis: Integer;
  1833.    bounds: Pb2AxialBoundsArray;
  1834.    bound: Pb2Bound;
  1835.    boundCount: Int32;
  1836.    stabbingCount: UInt16;
  1837.    i: Integer;
  1838. begin
  1839.    for axis := 0 to 1 do
  1840.    begin
  1841.       bounds := @m_bounds[axis];
  1842.       boundCount := 2 * m_proxyCount;
  1843.       stabbingCount := 0;
  1844.       for i := 0 to boundCount - 1 do
  1845.       begin
  1846.          bound := @bounds^[i];
  1847.          //b2Assert(i == 0 || bounds[i-1].value <= bound->value);
  1848.          //b2Assert(bound->proxyId != b2_nullProxy);
  1849.          //b2Assert(m_proxyPool[bound->proxyId].IsValid());
  1850.          {$IFDEF OP_OVERLOAD}
  1851.          if bound^.IsLower() then
  1852.          {$ELSE}         
  1853.          if IsLower(bound^) then
  1854.          {$ENDIF}                  
  1855.          begin
  1856.             //b2Assert(m_proxyPool[bound^.proxyId].lowerBounds[axis] == i);
  1857.             Inc(stabbingCount);
  1858.          end
  1859.          else
  1860.          begin
  1861.             //b2Assert(m_proxyPool[bound^.proxyId].upperBounds[axis] == i);
  1862.             Dec(stabbingCount);
  1863.          end;
  1864.          //b2Assert(bound->stabbingCount == stabbingCount);
  1865.       end;
  1866.    end;
  1867. end;
  1868. procedure Tb2BroadPhase.ValidatePairs;
  1869. begin
  1870. end;
  1871. ////////////////////////////////////////////////////
  1872. // Pair
  1873. {$IFDEF OP_OVERLOAD}
  1874. procedure Tb2Pair.SetBuffered;
  1875. begin
  1876.    status := status or e_pairBuffered;
  1877. end;
  1878. procedure Tb2Pair.ClearBuffered;
  1879. begin
  1880.    status := status and (not e_pairBuffered);
  1881. end;
  1882. function Tb2Pair.IsBuffered: Boolean;
  1883. begin
  1884.    Result := (status and e_pairBuffered) = e_pairBuffered;
  1885. end;
  1886. procedure Tb2Pair.SetRemoved;
  1887. begin
  1888.    status := status or e_pairRemoved;
  1889. end;
  1890. procedure Tb2Pair.ClearRemoved;
  1891. begin
  1892.    status := status and (not e_pairRemoved);
  1893. end;
  1894. function Tb2Pair.IsRemoved: Boolean;
  1895. begin
  1896.    Result := (status and e_pairRemoved) = e_pairRemoved;
  1897. end;
  1898. procedure Tb2Pair.SetFinal;
  1899. begin
  1900.    status := status or e_pairFinal;
  1901. end;
  1902. function Tb2Pair.IsFinal: Boolean;
  1903. begin
  1904.    Result := (status and e_pairFinal) = e_pairFinal;
  1905. end;
  1906. {$ENDIF}
  1907. { Tb2PairManager }
  1908. constructor Tb2PairManager.Create;
  1909. var
  1910.    i: Integer;
  1911. begin
  1912.    for i := 0 to b2_tableCapacity - 1 do
  1913.       m_hashTable[i] := b2_nullPair;
  1914.    m_freePair := 0;
  1915.    for i := 0 to b2_maxPairs - 1 do
  1916.    begin
  1917.       m_pairs[i].proxyId1 := b2_nullProxy;
  1918.       m_pairs[i].proxyId2 := b2_nullProxy;
  1919.       m_pairs[i].userData := nil;
  1920.       m_pairs[i].status := 0;
  1921.       m_pairs[i].next := i + 1;
  1922.    end;
  1923.    m_pairs[b2_maxPairs - 1].next := b2_nullPair;
  1924.    m_pairCount := 0;
  1925.    m_pairBufferCount := 0;
  1926. end;
  1927. function Tb2PairManager.Find(proxyId1, proxyId2: Int32): Pb2Pair;
  1928. var
  1929.    hash: Int32;
  1930. begin
  1931.    if proxyId1 > proxyId2 then
  1932.       b2Swap(proxyId1, proxyId2);
  1933.    hash := PairManager_Hash(proxyId1, proxyId2) and b2_tableMask;
  1934.    Result := Find(proxyId1, proxyId2, hash);
  1935. end;
  1936. function Tb2PairManager.Find(proxyId1, proxyId2: Int32; hashValue: UInt32): Pb2Pair;
  1937. var
  1938.    index: Int32;
  1939. begin
  1940.  index := m_hashTable[hashValue];
  1941.    while (index <> b2_nullPair) and (not PairManager_Equals(m_pairs[index], proxyId1, proxyId2)) do
  1942.   index := m_pairs[index].next;
  1943.  if index = b2_nullPair then
  1944.       Result := nil
  1945.    else
  1946.    begin
  1947.       //b2Assert(index < b2_maxPairs);
  1948.       Result := Pb2Pair(@m_pairs[index]);
  1949.    end;
  1950. end;
  1951. function Tb2PairManager.AddPair(proxyId1, proxyId2: Int32): Pb2Pair;
  1952. var
  1953.    hash: Int32;
  1954.    pairIndex: Int16;
  1955. begin
  1956.    if proxyId1 > proxyId2 then
  1957.       b2Swap(proxyId1, proxyId2);
  1958.    hash := PairManager_Hash(proxyId1, proxyId2) and b2_tableMask;
  1959.    Result := Find(proxyId1, proxyId2, hash);
  1960.    if Assigned(Result) then
  1961.       Exit;
  1962.    //b2Assert(m_pairCount < b2_maxPairs && m_freePair != b2_nullPair);
  1963.    pairIndex := m_freePair;
  1964.    Result := @m_pairs[pairIndex];
  1965.    m_freePair := Result^.next;
  1966.    Result^.proxyId1 := proxyId1;
  1967.    Result^.proxyId2 := proxyId2;
  1968.    Result^.status := 0;
  1969.    Result^.userData := nil;
  1970.    Result^.next := m_hashTable[hash];
  1971.    m_hashTable[hash] := pairIndex;
  1972.    Inc(m_pairCount);
  1973. end;
  1974. function Tb2PairManager.RemovePair(proxyId1, proxyId2: Int32): Pointer;
  1975. var
  1976.    hash: Int32;
  1977.    index: UInt16;
  1978.    pair: Pb2Pair;
  1979.    node: ^UInt16;
  1980.    userData: Pointer;
  1981. begin
  1982.    //b2Assert(m_pairCount > 0);
  1983.    if proxyId1 > proxyId2 then
  1984.       b2Swap(proxyId1, proxyId2);
  1985.    hash := PairManager_Hash(proxyId1, proxyId2) and b2_tableMask;
  1986.    node := @m_hashTable[hash];
  1987.    while (node^ <> b2_nullPair) do
  1988.    begin
  1989.       if PairManager_Equals(m_pairs[node^], proxyId1, proxyId2) then
  1990.       begin
  1991.          index := node^;
  1992.          node^ := m_pairs[node^].next;
  1993.          pair := @(m_pairs[index]);
  1994.          userData := pair^.userData;
  1995.          // Scrub
  1996.          pair^.next := m_freePair;
  1997.          pair^.proxyId1 := b2_nullProxy;
  1998.          pair^.proxyId2 := b2_nullProxy;
  1999.          pair^.userData := nil;
  2000.          pair^.status := 0;
  2001.          m_freePair := index;
  2002.          Dec(m_pairCount);
  2003.          Result := userData;
  2004.          Exit;
  2005.       end
  2006.       else
  2007.          node := @m_pairs[node^].next;
  2008.    end;
  2009.  //b2Assert(False);
  2010.    Result := nil;
  2011. end;
  2012. procedure Tb2PairManager.ValidateBuffer;
  2013. begin
  2014. (*
  2015. #ifdef _DEBUG
  2016. b2Assert(m_pairBufferCount <= m_pairCount);
  2017. std::sort(m_pairBuffer, m_pairBuffer + m_pairBufferCount);
  2018. for (int32 i = 0; i < m_pairBufferCount; ++i)
  2019. {
  2020. if (i > 0)
  2021. {
  2022. b2Assert(Equals(m_pairBuffer[i], m_pairBuffer[i-1]) == False);
  2023. }
  2024. b2Pair* pair = Find(m_pairBuffer[i].proxyId1, m_pairBuffer[i].proxyId2);
  2025. b2Assert(pair^.IsBuffered());
  2026. b2Assert(pair^.proxyId1 != pair^.proxyId2);
  2027. b2Assert(pair^.proxyId1 < b2_maxProxies);
  2028. b2Assert(pair^.proxyId2 < b2_maxProxies);
  2029. b2Proxy* proxy1 = m_broadPhase^.m_proxyPool + pair^.proxyId1;
  2030. b2Proxy* proxy2 = m_broadPhase^.m_proxyPool + pair^.proxyId2;
  2031. b2Assert(proxy1^.IsValid() == True);
  2032. b2Assert(proxy2^.IsValid() == True);
  2033. }
  2034. #endif
  2035. *)
  2036. end;
  2037. procedure Tb2PairManager.ValidateTable;
  2038. begin
  2039. (*
  2040. #ifdef _DEBUG
  2041. for (int32 i = 0; i < b2_tableCapacity; ++i)
  2042. {
  2043. uint16 index = m_hashTable[i];
  2044. while (index != b2_nullPair)
  2045. {
  2046. b2Pair* pair = m_pairs + index;
  2047. b2Assert(pair^.IsBuffered() == False);
  2048. b2Assert(pair^.IsFinal() == True);
  2049. b2Assert(pair^.IsRemoved() == False);
  2050. b2Assert(pair^.proxyId1 != pair^.proxyId2);
  2051. b2Assert(pair^.proxyId1 < b2_maxProxies);
  2052. b2Assert(pair^.proxyId2 < b2_maxProxies);
  2053. b2Proxy* proxy1 = m_broadPhase^.m_proxyPool + pair^.proxyId1;
  2054. b2Proxy* proxy2 = m_broadPhase^.m_proxyPool + pair^.proxyId2;
  2055. b2Assert(proxy1^.IsValid() == True);
  2056. b2Assert(proxy2^.IsValid() == True);
  2057. b2Assert(m_broadPhase^.TestOverlap(proxy1, proxy2) == True);
  2058. index = pair^.next;
  2059. }
  2060. }
  2061. #endif
  2062. *)
  2063. end;
  2064. procedure Tb2PairManager.Initialize(broadPhase: Tb2BroadPhase;
  2065.    callback: Tb2PairCallback);
  2066. begin
  2067.  m_broadPhase := broadPhase;
  2068.  m_callback := callback;
  2069. end;
  2070. {
  2071. As proxies are created and moved, many pairs are created and destroyed. Even worse, the same
  2072. pair may be added and removed multiple times in a single time step of the physics engine. To reduce
  2073. traffic in the pair manager, we try to avoid destroying pairs in the pair manager until the
  2074. end of the physics step. This is done by buffering all the RemovePair requests. AddPair
  2075. requests are processed immediately because we need the hash table entry for quick lookup.
  2076. All user user callbacks are delayed until the buffered pairs are confirmed in Commit.
  2077. This is very important because the user callbacks may be very expensive and client logic
  2078. may be harmed if pairs are added and removed within the same time step.
  2079. Buffer a pair for addition.
  2080. We may add a pair that is not in the pair manager or pair buffer.
  2081. We may add a pair that is already in the pair manager and pair buffer.
  2082. If the added pair is not a new pair, then it must be in the pair buffer (because RemovePair was called).
  2083. }
  2084. procedure Tb2PairManager.AddBufferedPair(proxyId1, proxyId2: Int32);
  2085. var
  2086.    pair: Pb2Pair;
  2087. begin
  2088.    //b2Assert(id1 != b2_nullProxy && id2 != b2_nullProxy);
  2089.    //b2Assert(m_pairBufferCount < b2_maxPairs);
  2090.    pair := AddPair(proxyId1, proxyId2);
  2091.    // If this pair is not in the pair buffer ...
  2092.    {$IFDEF OP_OVERLOAD}
  2093.    if not pair^.IsBuffered() then
  2094.    {$ELSE}
  2095.    if not IsBuffered(pair^) then
  2096.    {$ENDIF}
  2097.    begin
  2098.       // This must be a newly added pair.
  2099.       //b2Assert(pair^.IsFinal() == False);
  2100.       // Add it to the pair buffer.
  2101.       {$IFDEF OP_OVERLOAD}
  2102.       pair^.SetBuffered;
  2103.       {$ELSE}
  2104.       SetBuffered(pair^);
  2105.       {$ENDIF}
  2106.       m_pairBuffer[m_pairBufferCount].proxyId1 := pair^.proxyId1;
  2107.       m_pairBuffer[m_pairBufferCount].proxyId2 := pair^.proxyId2;
  2108.       Inc(m_pairBufferCount);
  2109.       //b2Assert(m_pairBufferCount <= m_pairCount);
  2110.    end;
  2111.    // Confirm this pair for the subsequent call to Commit.
  2112.    {$IFDEF OP_OVERLOAD}
  2113.    pair^.ClearRemoved;
  2114.    {$ELSE}
  2115.    ClearRemoved(pair^);
  2116.    {$ENDIF}
  2117.    {$IFDEF CLASSVAR_AVAIL}
  2118.    if Tb2BroadPhase.s_validate then
  2119.    {$ELSE}
  2120.    if b2BroadPhase_s_validate then
  2121.    {$ENDIF}
  2122.       ValidateBuffer;
  2123. end;
  2124. procedure Tb2PairManager.RemoveBufferedPair(proxyId1, proxyId2: Int32);
  2125. var
  2126.    pair: Pb2Pair;
  2127. begin
  2128.    //b2Assert(id1 != b2_nullProxy && id2 != b2_nullProxy);
  2129.    //b2Assert(m_pairBufferCount < b2_maxPairs);
  2130.    pair := Find(proxyId1, proxyId2);
  2131.    if not Assigned(pair) then
  2132.       // The pair never existed. This is legal (due to collision filtering).
  2133.       Exit;
  2134.    // If this pair is not in the pair buffer ...
  2135.    {$IFDEF OP_OVERLOAD}
  2136.    if (not pair^.IsBuffered()) then
  2137.    {$ELSE}
  2138.    if (not IsBuffered(pair^)) then
  2139.    {$ENDIF}
  2140.    begin
  2141.      // This must be an old pair.
  2142.      //b2Assert(pair^.IsFinal() == True);
  2143.      {$IFDEF OP_OVERLOAD}
  2144.      pair^.SetBuffered;
  2145.      {$ELSE}
  2146.      SetBuffered(pair^);
  2147.      {$ENDIF}
  2148.      m_pairBuffer[m_pairBufferCount].proxyId1 := pair^.proxyId1;
  2149.      m_pairBuffer[m_pairBufferCount].proxyId2 := pair^.proxyId2;
  2150.      Inc(m_pairBufferCount)
  2151.      //Assert(m_pairBufferCount <= m_pairCount);
  2152.    end;
  2153.    {$IFDEF OP_OVERLOAD}
  2154.    pair^.SetRemoved;
  2155.    {$ELSE}
  2156.    SetRemoved(pair^);
  2157.    {$ENDIF}
  2158.    {$IFDEF CLASSVAR_AVAIL}
  2159.    if Tb2BroadPhase.s_validate then
  2160.    {$ELSE}
  2161.    if b2BroadPhase_s_validate then
  2162.    {$ENDIF}
  2163.       ValidateBuffer;
  2164. end;
  2165. procedure Tb2PairManager.Commit;
  2166. var
  2167.    i: Integer;
  2168.    removeCount: Int32;
  2169.    proxy1, proxy2: Pb2Proxy;
  2170.    pair: Pb2Pair;
  2171. begin
  2172.    removeCount := 0;
  2173.    for i := 0 to m_pairBufferCount - 1 do
  2174.    begin
  2175.       pair := Find(m_pairBuffer[i].proxyId1, m_pairBuffer[i].proxyId2);
  2176.       //b2Assert(pair^.IsBuffered());
  2177.       {$IFDEF OP_OVERLOAD}
  2178.       pair^.ClearBuffered;
  2179.       {$ELSE}
  2180.       ClearBuffered(pair^);
  2181.       {$ENDIF}
  2182.       //b2Assert(pair^.proxyId1 < b2_maxProxies && pair^.proxyId2 < b2_maxProxies);
  2183.       proxy1 := @m_broadPhase.m_proxyPool[pair^.proxyId1];
  2184.       proxy2 := @m_broadPhase.m_proxyPool[pair^.proxyId2];
  2185.       //b2Assert(proxy1^.IsValid());
  2186.       //b2Assert(proxy2^.IsValid());
  2187.       {$IFDEF OP_OVERLOAD}
  2188.       if pair^.IsRemoved() then
  2189.       {$ELSE}
  2190.       if IsRemoved(pair^) then
  2191.       {$ENDIF}
  2192.       begin
  2193.          // It is possible a pair was added then removed before a commit. Therefore,
  2194.          // we should be careful not to tell the user the pair was removed when the
  2195.          // the user didn't receive a matching add.
  2196.          {$IFDEF OP_OVERLOAD}
  2197.          if pair^.IsFinal() then
  2198.          {$ELSE}
  2199.          if IsFinal(pair^) then
  2200.          {$ENDIF}
  2201.             m_callback.PairRemoved(proxy1^.userData, proxy2^.userData, pair^.userData);
  2202.          // Store the ids so we can actually remove the pair below.
  2203.          m_pairBuffer[removeCount].proxyId1 := pair^.proxyId1;
  2204.          m_pairBuffer[removeCount].proxyId2 := pair^.proxyId2;
  2205.          Inc(removeCount);
  2206.       end
  2207.       else
  2208.       begin
  2209.          //b2Assert(m_broadPhase^.TestOverlap(proxy1, proxy2) == True);
  2210.          {$IFDEF OP_OVERLOAD}
  2211.          if (not pair^.IsFinal()) then
  2212.          {$ELSE}
  2213.          if (not IsFinal(pair^)) then
  2214.          {$ENDIF}
  2215.          begin
  2216.             pair^.userData := m_callback.PairAdded(proxy1^.userData, proxy2^.userData);
  2217.             {$IFDEF OP_OVERLOAD}
  2218.             pair^.SetFinal;
  2219.             {$ELSE}
  2220.             SetFinal(pair^);
  2221.             {$ENDIF}
  2222.          end;
  2223.       end;
  2224.    end;
  2225.    for i := 0 to removeCount - 1 do
  2226.       RemovePair(m_pairBuffer[i].proxyId1, m_pairBuffer[i].proxyId2);
  2227.    m_pairBufferCount := 0;
  2228.    {$IFDEF CLASSVAR_AVAIL}
  2229.    if Tb2BroadPhase.s_validate then
  2230.    {$ELSE}
  2231.    if b2BroadPhase_s_validate then
  2232.    {$ENDIF}
  2233.       ValidateBuffer;
  2234. end;
  2235. { Tb2ShapeDef }
  2236. constructor Tb2ShapeDef.Create;
  2237. begin
  2238.    ShapeType := e_unknownShape;
  2239.    userData := nil;
  2240.    friction := 0.2;
  2241.    restitution := 0.0;
  2242.    density := 0.0;
  2243.    filter.categoryBits := $0001;
  2244.    filter.maskBits := $FFFF;
  2245.    filter.groupIndex := 0;
  2246.    isSensor := False;
  2247. end;
  2248. { Tb2Shape }
  2249. constructor Tb2Shape.Create(def: Tb2ShapeDef);
  2250. begin
  2251.    m_userData := def.userData;
  2252.    m_friction := def.friction;
  2253.    m_restitution := def.restitution;
  2254.    m_density := def.density;
  2255.    m_body := nil;
  2256.    m_sweepRadius := 0.0;
  2257.    m_next := nil;
  2258.    m_proxyId := b2_nullProxy;
  2259.    m_filter := def.filter;
  2260.    m_isSensor := def.isSensor;
  2261. end;
  2262. destructor Tb2Shape.Destroy;
  2263. begin
  2264.    if Assigned(m_body) then
  2265.       m_body.DestroyShape(Self, False);
  2266. end;
  2267. destructor Tb2Shape.Destroy2;
  2268. begin      
  2269. end;
  2270. procedure Tb2Shape.CreateProxy(broadPhase: Tb2BroadPhase; const xf: Tb2XForm);
  2271. var
  2272.    aabb: Tb2AABB;
  2273.    inRange: Boolean;
  2274. begin
  2275.    //b2Assert(m_proxyId == b2_nullProxy);
  2276.    ComputeAABB(aabb, xf);
  2277.    inRange := broadPhase.InRange(aabb);
  2278.    // You are creating a shape outside the world box.
  2279.    //b2Assert(inRange);
  2280.    if inRange then
  2281.       m_proxyId := broadPhase.CreateProxy(aabb, Self)
  2282.    else
  2283.       m_proxyId := b2_nullProxy;
  2284. end;
  2285. procedure Tb2Shape.DestroyProxy(broadPhase: Tb2BroadPhase);
  2286. begin
  2287.    if m_proxyId <> b2_nullProxy then
  2288.    begin
  2289.       broadPhase.DestroyProxy(m_proxyId);
  2290.       m_proxyId := b2_nullProxy;
  2291.    end;
  2292. end;
  2293. function Tb2Shape.Synchronize(broadPhase: Tb2BroadPhase; const xf1, xf2: Tb2XForm): Boolean;
  2294. var
  2295.    aabb: Tb2AABB;
  2296. begin
  2297.    if m_proxyId = b2_nullProxy then
  2298.    begin
  2299.       Result := False;
  2300.       Exit;
  2301.    end;
  2302.    // Compute an AABB that covers the swept shape (may miss some rotation effect).
  2303.    ComputeSweptAABB(aabb, xf1, xf2);
  2304.    if broadPhase.InRange(aabb) then
  2305.    begin
  2306.       broadPhase.MoveProxy(m_proxyId, aabb);
  2307.       Result := True;
  2308.    end
  2309.    else
  2310.       Result := False;
  2311. end;
  2312. procedure Tb2Shape.RefilterProxy(broadPhase: Tb2BroadPhase; const xf: Tb2XForm);
  2313. var
  2314.    aabb: Tb2AABB;
  2315. begin
  2316.    if m_proxyId = b2_nullProxy then
  2317.       Exit;
  2318.    broadPhase.DestroyProxy(m_proxyId);
  2319.    ComputeAABB(aabb, xf);
  2320.    if broadPhase.InRange(aabb) then
  2321.       m_proxyId := broadPhase.CreateProxy(aabb, Self)
  2322.    else
  2323.       m_proxyId := b2_nullProxy;
  2324. end;
  2325. //////////////////////////////////////////////////////////////
  2326. // Joints    
  2327. { Tb2Jacobian }
  2328. {$IFDEF OP_OVERLOAD}
  2329. procedure Tb2Jacobian.SetZero;
  2330. begin
  2331.    linear1.SetZero;
  2332.    linear2.SetZero;
  2333.    angular1 := 0.0;     
  2334.    angular2 := 0.0;
  2335. end;
  2336.       
  2337. procedure Tb2Jacobian.SetValue(const x1, x2: TVector2; a1, a2: Float);
  2338. begin
  2339.  linear1 := x1; 
  2340.    linear2 := x2;  
  2341.    angular1 := a1;    
  2342.    angular2 := a2;
  2343. end;
  2344.       
  2345. function Tb2Jacobian.Compute(const x1, x2: TVector2; a1, a2: Float): Float;
  2346. begin
  2347.    Result := b2Dot(linear1, x1) + angular1 * a1 + b2Dot(linear2, x2) + angular2 * a2;
  2348. end;  
  2349. {$ELSE}
  2350. // unfinished
  2351. {$ENDIF}        
  2352. { Tb2JointDef }
  2353. constructor Tb2JointDef.Create;
  2354. begin
  2355. JointType := e_unknownJoint;
  2356. userData := nil;
  2357. body1 := nil;
  2358. body2 := nil;
  2359. collideConnected := False;
  2360. end;
  2361. { Tb2Joint }
  2362. constructor Tb2Joint.Create(def: Tb2JointDef);
  2363. begin
  2364.    m_type := def.JointType;
  2365.    m_prev := nil;
  2366.    m_next := nil;
  2367.    m_body1 := def.body1;
  2368.    m_body2 := def.body2;
  2369.    m_collideConnected := def.collideConnected;
  2370.    m_islandFlag := False;
  2371.    m_userData := def.userData;
  2372. end;
  2373. procedure Tb2Joint.InitPositionConstraints;
  2374. begin
  2375. end;
  2376. //////////////////////////////////////////////////////////////
  2377. // Body
  2378. { Tb2BodyDef }
  2379. constructor Tb2BodyDef.Create;
  2380. begin
  2381.    SetZero(massData.center);
  2382.    massData.mass := 0.0;
  2383.    massData.I := 0.0;
  2384.    userData := nil;
  2385.    SetZero(position);
  2386.    angle := 0.0;
  2387.    linearDamping := 0.0;
  2388.    angularDamping := 0.0;
  2389.    allowSleep := True;
  2390.    isSleeping := False;
  2391.    fixedRotation := False;
  2392.    isBullet := False;
  2393. end;
  2394. { Tb2Body }
  2395. constructor Tb2Body.Create(bd: Tb2BodyDef; world: Tb2World);
  2396. begin
  2397.    //b2Assert(world->m_lock == False);
  2398.    m_flags := 0;
  2399.    if bd.isBullet then
  2400.       m_flags := m_flags or e_bulletFlag;
  2401.    if bd.fixedRotation then
  2402.       m_flags := m_flags or e_fixedRotationFlag;
  2403.    if bd.allowSleep then
  2404.       m_flags := m_flags or e_allowSleepFlag;
  2405.    if bd.isSleeping then
  2406.       m_flags := m_flags or e_sleepFlag;
  2407.    m_world := world;
  2408.    m_xf.position := bd.position;
  2409.    {$IFDEF OP_OVERLOAD}
  2410.    m_xf.R.SetValue(bd.angle);
  2411.    {$ELSE}
  2412.    SetValue(m_xf.R, bd.angle);
  2413.    {$ENDIF}
  2414.    m_sweep.localCenter := bd.massData.center;
  2415.    m_sweep.t0 := 1.0;
  2416.    m_sweep.a := bd.angle;
  2417.    m_sweep.a0 := bd.angle;
  2418.    m_sweep.c0 := b2Mul(m_xf, m_sweep.localCenter);
  2419.    m_sweep.c := m_sweep.c0;
  2420.    m_jointList := nil;
  2421.    m_contactList := nil;
  2422.    m_prev := nil;
  2423.    m_next := nil;
  2424.    m_linearDamping := bd.linearDamping;
  2425.    m_angularDamping := bd.angularDamping;
  2426.    SetZero(m_force);
  2427.    m_torque := 0.0;
  2428.    SetZero(m_linearVelocity);
  2429.    m_angularVelocity := 0.0;
  2430.    m_sleepTime := 0.0;
  2431.    m_invMass := 0.0;
  2432.    m_I := 0.0;
  2433.    m_invI := 0.0;
  2434.    m_mass := bd.massData.mass;
  2435.    if m_mass > 0.0 then
  2436.       m_invMass := 1.0 / m_mass;
  2437.    if (m_flags and e_fixedRotationFlag) = 0 then
  2438.       m_I := bd.massData.I;
  2439.    if m_I > 0.0 then
  2440.       m_invI := 1.0 / m_I;
  2441.    if (m_invMass = 0.0) and (m_invI = 0.0) then
  2442.       m_type := e_staticType
  2443.    else
  2444.       m_type := e_dynamicType;
  2445.    m_userData := bd.userData;
  2446.    m_shapeList := nil;
  2447.    m_shapeCount := 0;
  2448. end;
  2449. destructor Tb2Body.Destroy;
  2450. begin
  2451.    if Assigned(m_world) then 
  2452.       m_world.DestroyBody(Self, False);
  2453. end;
  2454. destructor Tb2Body.Destroy2;
  2455. begin 
  2456. end;
  2457. function Tb2Body.SynchronizeShapes: Boolean;
  2458. var
  2459.    s: Tb2Shape;
  2460.    xf1: Tb2XForm;
  2461.    inRange: Boolean;
  2462. begin
  2463.    {$IFDEF OP_OVERLOAD}
  2464.    xf1.R.SetValue(m_sweep.a0);
  2465.    xf1.position := m_sweep.c0 - b2Mul(xf1.R, m_sweep.localCenter);
  2466.    {$ELSE}
  2467.    SetValue(xf1.R, m_sweep.a0);
  2468.    xf1.position := Subtract(m_sweep.c0, b2Mul(xf1.R, m_sweep.localCenter));
  2469.    {$ENDIF}
  2470.    inRange := True;
  2471.    s := m_shapeList;
  2472.    while Assigned(s) do
  2473.    begin
  2474.       inRange := s.Synchronize(m_world.m_broadPhase, xf1, m_xf);
  2475.       if not inRange then
  2476.          Break;
  2477.       s := s.m_next;
  2478.    end;
  2479.    if not inRange then
  2480.    begin
  2481.       m_flags := m_flags or e_frozenFlag;
  2482.       SetZero(m_linearVelocity);
  2483.       m_angularVelocity := 0.0;
  2484.       s := m_shapeList;
  2485.       while Assigned(s) do
  2486.       begin
  2487.          s.DestroyProxy(m_world.m_broadPhase);
  2488.          s := s.m_next;
  2489.       end;
  2490.       // Failure
  2491.       Result := False;
  2492.       Exit;
  2493.    end;
  2494.    // Success
  2495.    Result := True;
  2496. end;
  2497. procedure Tb2Body.SynchronizeTransform;
  2498. begin
  2499.    {$IFDEF OP_OVERLOAD}
  2500.    m_xf.R.SetValue(m_sweep.a);
  2501.    m_xf.position := m_sweep.c - b2Mul(m_xf.R, m_sweep.localCenter);
  2502.    {$ELSE}
  2503.    SetValue(m_xf.R, m_sweep.a);
  2504.    m_xf.position := Subtract(m_sweep.c, b2Mul(m_xf.R, m_sweep.localCenter));
  2505.    {$ENDIF}
  2506. end;
  2507. function Tb2Body.IsConnected(other: Tb2Body): Boolean;
  2508. var
  2509.    jn: Pb2JointEdge;
  2510. begin
  2511.    jn := m_jointList;
  2512.    while Assigned(jn) do
  2513.    begin
  2514.       if jn^.other = other then
  2515.       begin
  2516.          Result := jn^.joint.m_collideConnected = False;
  2517.          Exit;
  2518.       end;
  2519.       jn := jn^.next;
  2520.    end;
  2521.    Result := False;
  2522. end;
  2523. procedure Tb2Body.Advance(t: Float);
  2524. begin
  2525.    // Advance to the new safe time.
  2526.    {$IFDEF OP_OVERLOAD}
  2527.    m_sweep.Advance(t);
  2528.    {$ELSE}
  2529.    UPhysics2DTypes.Advance(m_sweep, t);
  2530.    {$ENDIF}
  2531.    m_sweep.c := m_sweep.c0;
  2532.    m_sweep.a := m_sweep.a0;
  2533.    SynchronizeTransform;
  2534. end;
  2535. function Tb2Body.CreateShape(shapeDef: Tb2ShapeDef; AutoFreeShapeDef: Boolean = True): Tb2Shape;
  2536. begin
  2537.    //b2Assert(m_world->m_lock == False);
  2538.    if m_world.m_lock then
  2539.    begin
  2540.       Result := nil;
  2541.       Exit;
  2542.    end;
  2543.    case shapeDef.ShapeType of
  2544.       e_circleShape: Result := Tb2CircleShape.Create(shapeDef);
  2545.       e_polygonShape: Result := Tb2PolygonShape.Create(shapeDef);
  2546.    end;
  2547.    Result.m_next := m_shapeList;
  2548.    m_shapeList := Result;
  2549.    Inc(m_shapeCount);
  2550.    Result.m_body := Self;
  2551.    // Add the shape to the world's broad-phase.
  2552.    Result.CreateProxy(m_world.m_broadPhase, m_xf);
  2553.    // Compute the sweep radius for CCD.
  2554.    Result.UpdateSweepRadius(m_sweep.localCenter);
  2555.    if AutoFreeShapeDef then
  2556.       shapeDef.Free;
  2557. end;
  2558. procedure Tb2Body.DestroyShape(s: Tb2Shape; DoFree: Boolean = True);
  2559. var
  2560.    node: Pb2Shape;
  2561.    found: Boolean;
  2562. begin
  2563.    //b2Assert(m_world->m_lock == False);
  2564.    if m_world.m_lock then
  2565.       Exit;
  2566.    //b2Assert(s->GetBody() == this);
  2567.    s.DestroyProxy(m_world.m_broadPhase);
  2568.    //b2Assert(m_shapeCount > 0);
  2569.    node := @m_shapeList;
  2570.    found := False;
  2571.    while (node^ <> nil) do
  2572.    begin
  2573.       if node^ = s then
  2574.       begin
  2575.          node^ := s.m_next;
  2576.          found := True;
  2577.          Break;
  2578.       end;
  2579.       node := @node^.m_next;
  2580.    end;
  2581.    // You tried to remove a shape that is not attached to this body.
  2582.    //b2Assert(found);
  2583.    Dec(m_shapeCount);
  2584.    if DoFree then      
  2585.       s.Destroy2; // Call a destructor without side effects.
  2586. end;
  2587. procedure Tb2Body.SetMass(const massData: Tb2MassData);
  2588. var
  2589.    s: Tb2Shape;
  2590.    oldType: Tb2BodyType;
  2591. begin
  2592.    //b2Assert(m_world->m_lock == False);
  2593.    if m_world.m_lock then
  2594.       Exit;
  2595.    m_invMass := 0.0;
  2596.    m_I := 0.0;
  2597.    m_invI := 0.0;
  2598.    m_mass := massData.mass;
  2599.    if m_mass > 0.0 then
  2600.       m_invMass := 1.0 / m_mass;
  2601.    if (m_flags and e_fixedRotationFlag) = 0 then
  2602.       m_I := massData.I;
  2603.    if m_I > 0.0 then
  2604.       m_invI := 1.0 / m_I;
  2605.    // Move center of mass.
  2606.    m_sweep.localCenter := massData.center;
  2607.    m_sweep.c0 := b2Mul(m_xf, m_sweep.localCenter);
  2608.    m_sweep.c := m_sweep.c0;
  2609.    // Update the sweep radii of all child shapes.
  2610.    s := m_shapeList;
  2611.    while Assigned(s) do
  2612.    begin
  2613.       s.UpdateSweepRadius(m_sweep.localCenter);
  2614.       s := s.m_next;
  2615.    end;
  2616.    oldType := m_type;
  2617.    if (m_invMass = 0.0) and (m_invI = 0.0) then
  2618.       m_type := e_staticType
  2619.    else
  2620.       m_type := e_dynamicType;
  2621.    // If the body type changed, we need to refilter the broad-phase proxies.
  2622.    if oldType <> m_type then
  2623.    begin
  2624.       s := m_shapeList;
  2625.       while Assigned(s) do
  2626.       begin
  2627.          s.RefilterProxy(m_world.m_broadPhase, m_xf);
  2628.          s := s.m_next;
  2629.       end;
  2630.    end;
  2631. end;
  2632. procedure Tb2Body.SetMassFromShapes;
  2633. var
  2634.    s: Tb2Shape;
  2635.    center: TVector2;
  2636.    massData: Tb2MassData;
  2637.    oldType: Tb2BodyType;
  2638. begin
  2639.    //b2Assert(m_world->m_lock == False);
  2640.    if m_world.m_lock then
  2641.       Exit;
  2642.    // Compute mass data from shapes. Each shape has its own density.
  2643.    m_mass := 0.0;
  2644.    m_invMass := 0.0;
  2645.    m_I := 0.0;
  2646.    m_invI := 0.0;
  2647.    center := b2Vec2_zero;
  2648.    s := m_shapeList;
  2649.    while Assigned(s) do
  2650.    begin
  2651.       s.ComputeMass(massData);
  2652.       m_mass := m_mass + massData.mass;
  2653.       {$IFDEF OP_OVERLOAD}
  2654.       center.AddBy(massData.mass * massData.center);
  2655.       {$ELSE}
  2656.       AddBy(center, Multiply(massData.center, massData.mass));
  2657.       {$ENDIF}
  2658.       m_I := m_I + massData.I;
  2659.       s := s.m_next;
  2660.    end;
  2661.    // Compute center of mass, and shift the origin to the COM.
  2662.    if m_mass > 0.0 then
  2663.    begin
  2664.       m_invMass := 1.0 / m_mass;
  2665.       {$IFDEF OP_OVERLOAD}
  2666.       center.MultiplyBy(m_invMass);
  2667.       {$ELSE}
  2668.       MultiplyBy(center, m_invMass);
  2669.       {$ENDIF}
  2670.    end;
  2671.    if (m_I > 0.0) and ((m_flags and e_fixedRotationFlag) = 0) then
  2672.    begin
  2673.       // Center the inertia about the center of mass.
  2674.       m_I := m_I - m_mass * b2Dot(center, center);
  2675.       //b2Assert(m_I > 0.0f);
  2676.       m_invI := 1.0 / m_I;
  2677.    end
  2678.    else
  2679.    begin
  2680.       m_I := 0.0;
  2681.       m_invI := 0.0;
  2682.    end;
  2683.    // Move center of mass.
  2684.    m_sweep.localCenter := center;
  2685.    m_sweep.c := b2Mul(m_xf, m_sweep.localCenter);
  2686.    m_sweep.c0 := m_sweep.c;
  2687.    // Update the sweep radii of all child shapes.
  2688.    s := m_shapeList;
  2689.    while Assigned(s) do
  2690.    begin
  2691.       s.UpdateSweepRadius(m_sweep.localCenter);
  2692.       s := s.m_next;
  2693.    end;
  2694.    oldType := m_type;
  2695.    if (m_invMass = 0.0) and (m_invI = 0.0) then
  2696.       m_type := e_staticType
  2697.    else
  2698.       m_type := e_dynamicType;
  2699.    // If the body type changed, we need to refilter the broad-phase proxies.
  2700.    if oldType <> m_type then
  2701.    begin
  2702.       s := m_shapeList;
  2703.       while Assigned(s) do
  2704.       begin
  2705.          s.RefilterProxy(m_world.m_broadPhase, m_xf);
  2706.          s := s.m_next;
  2707.       end;
  2708.    end;
  2709. end;
  2710. function Tb2Body.SetXForm(const position: TVector2; angle: Float): Boolean;
  2711. var
  2712.    s: Tb2Shape;
  2713.    freeze: Boolean;
  2714. begin
  2715.    //b2Assert(m_world->m_lock == False);
  2716.    if m_world.m_lock then
  2717.    begin
  2718.       Result := True;
  2719.       Exit;
  2720.    end;
  2721.    if IsFrozen() then
  2722.    begin
  2723.       Result := False;
  2724.       Exit;
  2725.    end;
  2726.    {$IFDEF OP_OVERLOAD}
  2727.    m_xf.R.SetValue(angle);
  2728.    {$ELSE}
  2729.    SetValue(m_xf.R, angle);
  2730.    {$ENDIF}
  2731.    m_xf.position := position;
  2732.    m_sweep.c0 := b2Mul(m_xf, m_sweep.localCenter);
  2733.    m_sweep.c := m_sweep.c0;
  2734.    m_sweep.a0 := angle;
  2735.    m_sweep.a := angle;
  2736.    freeze := False;
  2737.    s := m_shapeList;
  2738.    while Assigned(s) do
  2739.    begin
  2740.       if not s.Synchronize(m_world.m_broadPhase, m_xf, m_xf) then
  2741.       begin
  2742.          freeze := True;
  2743.          Break;
  2744.       end;
  2745.       s := s.m_next;
  2746.    end;
  2747.    if freeze then
  2748.    begin
  2749.       m_flags := m_flags or e_frozenFlag;
  2750.       SetZero(m_linearVelocity);
  2751.       m_angularVelocity := 0.0;
  2752.       s := m_shapeList;
  2753.       while Assigned(s) do
  2754.       begin
  2755.          s.DestroyProxy(m_world.m_broadPhase);
  2756.          s := s.m_next;
  2757.       end;
  2758.       // Failure
  2759.       Result := False;
  2760.       Exit;
  2761.    end;
  2762.    // Success
  2763.    m_world.m_broadPhase.Commit;
  2764.    Result := True;
  2765. end;
  2766. procedure Tb2Body.SetLinearVelocity(const v: TVector2);
  2767. begin
  2768.    m_linearVelocity := v;
  2769. end;
  2770. procedure Tb2Body.SetAngularVelocity(omega: Float);
  2771. begin
  2772.    m_angularVelocity := omega;
  2773. end;
  2774. procedure Tb2Body.ApplyForce(const force, point: TVector2);
  2775. begin
  2776.    if IsSleeping() then
  2777.       WakeUp;
  2778.    {$IFDEF OP_OVERLOAD}
  2779.  m_force.AddBy(force);
  2780.    m_torque := m_torque + b2Cross(point - m_sweep.c, force);
  2781.    {$ELSE}
  2782.    AddBy(m_force, force);
  2783.    m_torque := m_torque + b2Cross(Subtract(point, m_sweep.c), force);
  2784.    {$ENDIF}
  2785. end;
  2786. procedure Tb2Body.ApplyTorque(torque: Float);
  2787. begin
  2788.    if IsSleeping() then
  2789.       WakeUp;
  2790.  m_torque := m_torque + torque;
  2791. end;
  2792. procedure Tb2Body.ApplyImpulse(const impulse, point: TVector2);
  2793. begin
  2794.    if IsSleeping() then
  2795.       WakeUp;
  2796.    {$IFDEF OP_OVERLOAD}
  2797.    m_linearVelocity.AddBy(m_invMass * impulse);
  2798.    m_angularVelocity := m_angularVelocity + m_invI * b2Cross(point -
  2799.       m_sweep.c, impulse);
  2800.    {$ELSE}
  2801.    AddBy(m_linearVelocity, Multiply(impulse, m_invMass));
  2802.    m_angularVelocity := m_angularVelocity + m_invI * b2Cross(Subtract(point,
  2803.       m_sweep.c), impulse);
  2804.    {$ENDIF}
  2805. end;
  2806. function Tb2Body.GetWorldPoint(const localPoint: TVector2): TVector2;
  2807. begin
  2808.    Result := b2Mul(m_xf, localPoint);
  2809. end;
  2810. function Tb2Body.GetWorldVector(const localVector: TVector2): TVector2;
  2811. begin
  2812.    Result := b2Mul(m_xf.R, localVector);
  2813. end;
  2814. function Tb2Body.GetLocalPoint(const worldPoint: TVector2): TVector2;
  2815. begin
  2816.    Result := b2MulT(m_xf, worldPoint);
  2817. end;
  2818. function Tb2Body.GetLocalVector(const worldVector: TVector2): TVector2;
  2819. begin
  2820.    Result := b2MulT(m_xf.R, worldVector);
  2821. end;
  2822. function Tb2Body.GetLinearVelocityFromWorldPoint(
  2823.    const worldPoint: TVector2): TVector2;
  2824. begin
  2825.    {$IFDEF OP_OVERLOAD}
  2826.    Result := m_linearVelocity + b2Cross(m_angularVelocity, worldPoint - m_sweep.c);
  2827.    {$ELSE}
  2828.    Result := Add(m_linearVelocity, b2Cross(m_angularVelocity,
  2829.       Subtract(worldPoint, m_sweep.c)));
  2830.    {$ENDIF}
  2831. end;
  2832. function Tb2Body.GetLinearVelocityFromLocalPoint(
  2833.    const localPoint: TVector2): TVector2;
  2834. begin
  2835.    Result := GetLinearVelocityFromWorldPoint(GetWorldPoint(localPoint));
  2836. end;
  2837. function Tb2Body.IsBullet: Boolean;
  2838. begin
  2839.    Result := (m_flags and e_bulletFlag) = e_bulletFlag;
  2840. end;
  2841. procedure Tb2Body.SetBullet(flag: Boolean);
  2842. begin
  2843.    if flag then
  2844.       m_flags := m_flags or e_bulletFlag
  2845.    else
  2846.       m_flags := m_flags and (not e_bulletFlag);
  2847. end;
  2848. function Tb2Body.IsStatic: Boolean;
  2849. begin
  2850.    Result := m_type = e_staticType;
  2851. end;
  2852. function Tb2Body.IsDynamic: Boolean;
  2853. begin
  2854.    Result := m_type = e_dynamicType;
  2855. end;
  2856. function Tb2Body.IsFrozen: Boolean;
  2857. begin
  2858.    Result := (m_flags and e_frozenFlag) = e_frozenFlag;
  2859. end;
  2860. function Tb2Body.IsSleeping: Boolean;
  2861. begin
  2862.    Result := (m_flags and e_sleepFlag) = e_sleepFlag;
  2863. end;
  2864. procedure Tb2Body.AllowSleeping(flag: Boolean);
  2865. begin
  2866.    if flag then
  2867.       m_flags := m_flags or e_allowSleepFlag
  2868.    else
  2869.    begin
  2870.       m_flags := m_flags and (not e_allowSleepFlag);
  2871.       WakeUp;
  2872.    end;
  2873. end;
  2874. procedure Tb2Body.WakeUp;
  2875. begin
  2876.  m_flags := m_flags and (not e_sleepFlag);
  2877.  m_sleepTime := 0.0;
  2878. end;
  2879. procedure Tb2Body.PutToSleep;
  2880. begin
  2881.    m_flags := m_flags or e_sleepFlag;
  2882.    m_sleepTime := 0.0;
  2883.    SetZero(m_linearVelocity);
  2884.    m_angularVelocity := 0.0;
  2885.    SetZero(m_force);
  2886.    m_torque := 0.0;
  2887. end;
  2888. ///////////////////////////////////////////////
  2889. // Specific implementations
  2890. procedure b2CollideCircles(var manifold: Tb2Manifold;
  2891.    circle1, circle2: Tb2CircleShape; const xf1, xf2: Tb2XForm);
  2892. var
  2893.    p1, p2, d: TVector2;
  2894.    distSqr, r1, r2, radiusSum, separation, dist, a: Float;
  2895. begin
  2896.    manifold.pointCount := 0;
  2897.    p1 := b2Mul(xf1, circle1.m_localPosition);
  2898.    p2 := b2Mul(xf2, circle2.m_localPosition);
  2899.    {$IFDEF OP_OVERLOAD}
  2900.    d := p2 - p1;
  2901.    {$ELSE}
  2902.    d := Subtract(p2, p1);
  2903.    {$ENDIF}
  2904.    distSqr := b2Dot(d, d);
  2905.    r1 := circle1.GetRadius;
  2906.    r2 := circle2.GetRadius;
  2907.    radiusSum := r1 + r2;
  2908.    if distSqr > radiusSum * radiusSum then
  2909.       Exit;
  2910.    if (distSqr < FLT_EPSILON) then
  2911.    begin
  2912.       separation := -radiusSum;
  2913.       {$IFDEF OP_OVERLOAD}
  2914.       manifold.normal.SetValue(0.0, 1.0);
  2915.       {$ELSE}
  2916.       SetValue(manifold.normal, 0.0, 1.0);
  2917.       {$ENDIF}
  2918.    end
  2919.    else
  2920.    begin
  2921.       dist := Sqrt(distSqr);
  2922.       separation := dist - radiusSum;
  2923.       a := 1.0 / dist;
  2924.       manifold.normal.x := a * d.x;
  2925.       manifold.normal.y := a * d.y;
  2926.    end;
  2927.    manifold.pointCount := 1;
  2928.    manifold.points[0].id.key := 0;
  2929.    manifold.points[0].separation := separation;
  2930.    {$IFDEF OP_OVERLOAD}
  2931.    p1.AddBy(r1 * manifold.normal);
  2932.    p2.SubtractBy(r2 * manifold.normal);
  2933.    d := 0.5 * (p1 + p2);
  2934.    {$ELSE}
  2935.    AddBy(p1, Multiply(manifold.normal, r1));
  2936.    SubtractBy(p2, Multiply(manifold.normal, r2));
  2937.    d := Add(p1, p2);
  2938.    MultiplyBy(d, 0.5);
  2939.    {$ENDIF}
  2940.    manifold.points[0].localPoint1 := b2MulT(xf1, d);
  2941.    manifold.points[0].localPoint2 := b2MulT(xf2, d);
  2942. end;
  2943. procedure b2CollidePolygonAndCircle(var manifold: Tb2Manifold;
  2944.    polygon: Tb2PolygonShape; circle: Tb2CircleShape; const xf1, xf2: Tb2XForm);
  2945. var
  2946.    i: Integer;
  2947.    c, cLocal, position, e, p, d: TVector2;
  2948.    normalIndex: Int32;
  2949.    _separation, radius, length, dist: Float;
  2950.    s, u: Float;
  2951.    vertIndex1, vertIndex2: Int32;
  2952. begin
  2953.    manifold.pointCount := 0;
  2954.    // Compute circle position in the frame of the polygon.
  2955.    c := b2Mul(xf2, circle.m_localPosition);
  2956.    cLocal := b2MulT(xf1, c);
  2957.    // Find the min separating edge.
  2958.    normalIndex := 0;
  2959.    _separation := -FLT_MAX;
  2960.    radius := circle.GetRadius;
  2961.    for i := 0 to polygon.GetVertexCount - 1 do
  2962.    begin
  2963.       {$IFDEF OP_OVERLOAD}
  2964.       s := b2Dot(polygon.m_normals[i], cLocal - polygon.m_vertices[i]);
  2965.       {$ELSE}
  2966.       s := b2Dot(polygon.m_normals[i], Subtract(cLocal, polygon.m_vertices[i]));
  2967.       {$ENDIF}
  2968.       if s > radius then
  2969.          Exit;
  2970.       if s > _separation then
  2971.       begin
  2972.          _separation := s;
  2973.          normalIndex := i;
  2974.       end;
  2975.    end;
  2976.    // If the center is inside the polygon ...
  2977.    if _separation < FLT_EPSILON then
  2978.       with manifold do
  2979.       begin
  2980.          pointCount := 1;
  2981.          normal := b2Mul(xf1.R, polygon.m_normals[normalIndex]);
  2982.          with points[0], id do
  2983.          begin
  2984.             incidentEdge := normalIndex;
  2985.             incidentVertex := b2_nullFeature;
  2986.             referenceEdge := 0;
  2987.             flip := 0;
  2988.             {$IFDEF OP_OVERLOAD}
  2989.             position := c - radius * manifold.normal;
  2990.             {$ELSE}
  2991.             position := Subtract(c, Multiply(manifold.normal, radius));
  2992.             {$ENDIF}
  2993.             localPoint1 := b2MulT(xf1, position);
  2994.             localPoint2 := b2MulT(xf2, position);
  2995.             separation := _separation - radius;
  2996.          end;
  2997.          Exit;
  2998.       end;
  2999.    // Project the circle center onto the edge segment.
  3000.    vertIndex1 := normalIndex;
  3001.    if vertIndex1 + 1 < polygon.GetVertexCount then
  3002.       vertIndex2 := vertIndex1 + 1
  3003.    else
  3004.       vertIndex2 := 0;
  3005.    {$IFDEF OP_OVERLOAD}
  3006.    e := polygon.m_vertices[vertIndex2] - polygon.m_vertices[vertIndex1];
  3007.    length := e.Normalize;
  3008.    //b2Assert(length > B2_FLT_EPSILON);
  3009.    // Project the center onto the edge.
  3010.    u := b2Dot(cLocal - polygon.m_vertices[vertIndex1], e);
  3011.    {$ELSE}
  3012.    e := Subtract(polygon.m_vertices[vertIndex2], polygon.m_vertices[vertIndex1]);
  3013.    length := Normalize(e);
  3014.    //b2Assert(length > B2_FLT_EPSILON);
  3015.    // Project the center onto the edge.
  3016.    u := b2Dot(Subtract(cLocal, polygon.m_vertices[vertIndex1]), e);
  3017.    {$ENDIF}
  3018.    if u <= 0.0 then
  3019.    begin
  3020.       p := polygon.m_vertices[vertIndex1];
  3021.       manifold.points[0].id.incidentEdge := b2_nullFeature;
  3022.       manifold.points[0].id.incidentVertex := vertIndex1;
  3023.    end
  3024.    else if u >= length then
  3025.    begin
  3026.       p := polygon.m_vertices[vertIndex2];
  3027.       manifold.points[0].id.incidentEdge := b2_nullFeature;
  3028.       manifold.points[0].id.incidentVertex := vertIndex2;
  3029.    end
  3030.    else
  3031.    begin
  3032.       {$IFDEF OP_OVERLOAD}
  3033.       p := polygon.m_vertices[vertIndex1] + u * e;
  3034.       {$ELSE}
  3035.       p := Add(polygon.m_vertices[vertIndex1], Multiply(e, u));
  3036.       {$ENDIF}
  3037.       manifold.points[0].id.incidentEdge := normalIndex;
  3038.       manifold.points[0].id.incidentVertex := 0;
  3039.    end;
  3040.    {$IFDEF OP_OVERLOAD}
  3041.    d := cLocal - p;
  3042.    dist := d.Normalize;
  3043.    {$ELSE}
  3044.    d := Subtract(cLocal, p);
  3045.    dist := Normalize(d);
  3046.    {$ENDIF}
  3047.    if dist > radius then
  3048.       Exit;
  3049.    manifold.pointCount := 1;
  3050.    manifold.normal := b2Mul(xf1.R, d);
  3051.    {$IFDEF OP_OVERLOAD}
  3052.    position := c - radius * manifold.normal;
  3053.    {$ELSE}
  3054.    position := Subtract(c, Multiply(manifold.normal, radius));
  3055.    {$ENDIF}
  3056.    with manifold.points[0] do
  3057.    begin
  3058.       localPoint1 := b2MulT(xf1, position);
  3059.       localPoint2 := b2MulT(xf2, position);
  3060.       separation := dist - radius;
  3061.       id.referenceEdge := 0;
  3062.       id.flip := 0;
  3063.    end;
  3064. end;
  3065. type
  3066.    PClipVertex = ^TClipVertex;
  3067.    TClipVertex = record
  3068.       v: TVector2;
  3069.       id: Tb2ContactID;
  3070.    end;
  3071.    PClipVertices = ^TClipVertices;
  3072.    TClipVertices = array[0..1] of TClipVertex;
  3073. function ClipSegmentToLine(vOut, vIn: PClipVertices; const normal: TVector2;
  3074.    offset: Float): Int32;
  3075. var
  3076.    distance0, distance1, interp: Float;
  3077. begin
  3078.    Result := 0; // Start with no output points
  3079.    // Calculate the distance of end points to the line
  3080.    distance0 := b2Dot(normal, vIn^[0].v) - offset;
  3081.    distance1 := b2Dot(normal, vIn^[1].v) - offset;
  3082.    // If the points are behind the plane
  3083.    if distance0 <= 0.0 then
  3084.    begin
  3085.       vOut^[Result] := vIn^[0];
  3086.       Inc(Result);
  3087.    end;
  3088.    if distance1 <= 0.0 then
  3089.    begin
  3090.       vOut^[Result] := vIn^[1];
  3091.       Inc(Result);
  3092.    end;
  3093.    // If the points are on different sides of the plane
  3094.    if distance0 * distance1 < 0.0 then
  3095.    begin
  3096.       // Find intersection point of edge and plane
  3097.       interp := distance0 / (distance0 - distance1);
  3098.       {$IFDEF OP_OVERLOAD}
  3099.       vOut^[Result].v := vIn^[0].v + interp * (vIn^[1].v - vIn^[0].v);
  3100.       {$ELSE}
  3101.       vOut^[Result].v := Add(vIn^[0].v, Multiply(Subtract(vIn^[1].v, vIn^[0].v), interp));
  3102.       {$ENDIF}
  3103.       if distance0 > 0.0 then
  3104.          vOut^[Result].id := vIn^[0].id
  3105.       else
  3106.          vOut^[Result].id := vIn^[1].id;
  3107.       Inc(Result);
  3108.    end;
  3109. end;
  3110. // Find the separation between poly1 and poly2 for a give edge normal on poly1.
  3111. function EdgeSeparation(poly1, poly2: Tb2PolygonShape; const xf1,
  3112.    xf2: Tb2XForm; edge1: Int32): Float;
  3113. var
  3114.    i: Integer;
  3115.    index: Int32;
  3116.    minDot, dot: Float;
  3117.    normal1World, normal1: TVector2;
  3118.    v1, v2: TVector2;
  3119. begin
  3120.    //b2Assert(0 <= edge1 && edge1 < count1);
  3121.    // Convert normal from poly1's frame into poly2's frame.
  3122.    normal1World := b2Mul(xf1.R, poly1.m_normals[edge1]);
  3123.    normal1 := b2MulT(xf2.R, normal1World);