示例#1
0
    size_t collide(CircleShape &circle, BoxShape &box, float dt, Contact *pxContacts, size_t numMaxContacts)
    {
        dt, pxContacts, numMaxContacts;
        const Point2f &p1 = circle.body.getPosition();
        const Point2f &p2 = box.body.getPosition();

        // work in the box's coordinate system
        const Point2f kDiff = p1 - p2;

        // compute squared distance and closest point on box
        float fSqrDistance = 0.0f, fDelta;
        Point2f kClosest(kDiff * box.GetDir(0), kDiff * box.GetDir(1));
        const Point2f &extents = box.GetExtents();
        if (kClosest.x < -extents.x)
        {
            fDelta = kClosest.x + extents.x;
            fSqrDistance += fDelta*fDelta;
            kClosest.x = -extents.x;
        }
        else if (kClosest.x > extents.x)
        {
            fDelta = kClosest.x - extents.x;
            fSqrDistance += fDelta*fDelta;
            kClosest.x = extents.x;
        }
        if (kClosest.y < -extents.y)
        {
            fDelta = kClosest.y + extents.y;
            fSqrDistance += fDelta*fDelta;
            kClosest.y = -extents.y;
        }
        else if (kClosest.y > extents.y)
        {
            fDelta = kClosest.y - extents.y;
            fSqrDistance += fDelta*fDelta;
            kClosest.y = extents.y;
        }
        if (fSqrDistance > circle.GetRadius() * circle.GetRadius())
        {
            return 0;
        }
        Point2f d = p2 + kClosest - p1;
        d.Normalize();

        pxContacts[0] = Contact(p1 + d * circle.GetRadius(), p2 + kClosest, &circle.body, &box.body);
        return 1;
    }
Real DistVector3Ellipsoid3<Real>::GetSquared ()
{
    // compute coordinates of point in ellipsoid coordinate system
    Vector3<Real> kDiff = m_rkVector - m_rkEllipsoid.Center;
    Vector3<Real> kEPoint(kDiff.Dot(m_rkEllipsoid.Axis[0]),
        kDiff.Dot(m_rkEllipsoid.Axis[1]),kDiff.Dot(m_rkEllipsoid.Axis[2]));

    const Real* afExtent = m_rkEllipsoid.Extent;
    Real fA2 = afExtent[0]*afExtent[0];
    Real fB2 = afExtent[1]*afExtent[1];
    Real fC2 = afExtent[2]*afExtent[2];
    Real fU2 = kEPoint.X()*kEPoint.X();
    Real fV2 = kEPoint.Y()*kEPoint.Y();
    Real fW2 = kEPoint.Z()*kEPoint.Z();
    Real fA2U2 = fA2*fU2, fB2V2 = fB2*fV2, fC2W2 = fC2*fW2;

    // initial guess
    Real fURatio = kEPoint.X()/afExtent[0];
    Real fVRatio = kEPoint.Y()/afExtent[1];
    Real fWRatio = kEPoint.Z()/afExtent[2];
    Real fT;
    if (fURatio*fURatio+fVRatio*fVRatio+fWRatio*fWRatio < (Real)1.0)
    {
        fT = (Real)0.0;
    }
    else
    {
        Real fMax = afExtent[0];
        if (afExtent[1] > fMax)
        {
            fMax = afExtent[1];
        }
        if (afExtent[2] > fMax)
        {
            fMax = afExtent[2];
        }

        fT = fMax*kEPoint.Length();
    }

    // Newton's method
    const int iMaxIteration = 64;
    Real fP, fQ, fR;
    for (int i = 0; i < iMaxIteration; i++)
    {
        fP = fT+fA2;
        fQ = fT+fB2;
        fR = fT+fC2;
        Real fP2 = fP*fP;
        Real fQ2 = fQ*fQ;
        Real fR2 = fR*fR;
        Real fS = fP2*fQ2*fR2-fA2U2*fQ2*fR2-fB2V2*fP2*fR2-fC2W2*fP2*fQ2;
        if (Math<Real>::FAbs(fS) < Math<Real>::ZERO_TOLERANCE)
        {
            break;
        }

        Real fPQ = fP*fQ, fPR = fP*fR, fQR = fQ*fR, fPQR = fP*fQ*fR;
        Real fDS = ((Real)2.0)*(fPQR*(fQR+fPR+fPQ)-fA2U2*fQR*(fQ+fR)-
            fB2V2*fPR*(fP+fR)-fC2W2*fPQ*(fP+fQ));
        fT -= fS/fDS;
    }

    Vector3<Real> kClosest(fA2*kEPoint.X()/fP,fB2*kEPoint.Y()/fQ,
        fC2*kEPoint.Z()/fR);
    kDiff = kClosest - kEPoint;
    Real fSqrDistance = kDiff.SquaredLength();

    m_kClosestPoint0 = m_rkVector;
    m_kClosestPoint1 = m_rkEllipsoid.Center +
        kClosest.X()*m_rkEllipsoid.Axis[0] +
        kClosest.Y()*m_rkEllipsoid.Axis[1] +
        kClosest.Z()*m_rkEllipsoid.Axis[2];

    return fSqrDistance;
}