⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 verlet.cpp.svn-base

📁 坦克大战游戏完整全套源代码
💻 SVN-BASE
字号:
#include "verlet/verlet.h"


namespace verlet
{
    size_t iBody::Collide(iBody& body, float dt, Contact *pxContacts, size_t numMaxContacts)
    {
        if (!shape || !body.shape || this->isStaticBody() && body.isStaticBody())
            return 0;
        assert(shape && body.shape);
        return shape->collide(*body.shape, dt, pxContacts, numMaxContacts);
    }
    void Body::Reset(const Point2f& xPosition, float fOrientation, float fMass)
    {
        this->pos           = xPosition;
        this->orientation   = fOrientation;
        this->mass          = fMass;
        this->invMass       = (fMass == 0.0f) ? 0.0f : 1.0f / fMass;
        this->inertia       = (fMass == 0.0f || !shape) ? 0.0f : mass * shape->GetInertiaMoment();
        this->invInertia    = (mass == 0.0f) ? 0.0f : 1.0f / inertia;
        this->velocity      = Point2f(0.0f, 0.0f);
        this->angVelocity   = 0.0f;
        this->netForce      = Point2f(0.0f, 0.0f);
        this->netTorque     = 0.0f;
        if (this->shape)
            this->shape->update();
    }
    void Body::Update(float dt)
    {
        //-------------------------------------------------------
        // Integrate position (verlet integration)
        //-------------------------------------------------------
        Point2f xAccel  = netForce * invMass;
        pos += velocity * dt;// + 0.5f * xAccel * dt*dt;
        orientation += angVelocity * dt;

        assert(xAccel.Length() < 1e3);
        //-------------------------------------------------------
        // Integrate velocity (implicit linear velocity)
        //-------------------------------------------------------
        velocity += xAccel * dt;
        angVelocity += netTorque * (invInertia * dt);

        //-------------------------------------------------------
        // clear forces
        //-------------------------------------------------------
        netForce = Point2f(0.0f, 0.0f);
        netTorque = 0.0f;

        if (shape)
            shape->update();
    }
    void StaticBody::Reset(const Point2f& xPosition, float fOrientation)
    {
        iBody::Reset(xPosition, fOrientation, 0.f);

        if (shape)
            shape->update();
    }
    bool ProjectPointOnSegment(const Point2f& P, const Point2f& E0, const Point2f& E1, Point2f& Q)
    {
        Point2f E = E1 - E0;
        Point2f D = P  - E0;
        float e2 = E * E;
        float de = D * E;

        if (de < 0.0f || de > e2)
            return false;

        Q = E0 + E * (de / e2);

        return true;
    }

    bool ConvertSupportPointsToContacts(const BoxShape& box1, const BoxShape& box2, 
        const Point2f& xAxis,
        Point2f* pxPoints0, size_t numP0, 
        Point2f* pxPoints1, size_t numP1,
        Contact* xContacts, size_t& iNumContacts)
    {
        iNumContacts = 0;

        Point2f xPerp(-xAxis.y, xAxis.x);

        float min0 = pxPoints0[0] * xPerp;
        float max0 = min0;
        float min1 =  pxPoints1[0] * xPerp;
        float max1 = min1;

        if (numP0 == 2)
        {
            max0 = pxPoints0[1] * xPerp;

            if (max0 < min0) 
            { 
                float c = min0;
                min0 = max0;
                max0 = c;

                Point2f T = pxPoints0[0];
                pxPoints0[0] = pxPoints0[1];
                pxPoints0[1] = T;
            }
        }

        if (numP1 == 2)
        {
            max1 = pxPoints1[1] * xPerp;

            if (max1 < min1) 
            { 
                float c = min1;
                min1 = max1;
                max1 = c;

                Point2f T = pxPoints1[0];
                pxPoints1[0] = pxPoints1[1];
                pxPoints1[1] = T;
            }
        }

        if (min0 > max1 || min1 > max0)
            return false;

        if (min0 > min1)
        {
            Point2f Pseg;
            if (ProjectPointOnSegment(pxPoints0[0], pxPoints1[0], pxPoints1[1], Pseg))
            {
                xContacts[iNumContacts++] = Contact(pxPoints0[0], Pseg, &box1.body, &box2.body);
            }
        }
        else
        {
            Point2f Pseg;
            if (ProjectPointOnSegment(pxPoints1[0], pxPoints0[0], pxPoints0[1], Pseg))
            {
                xContacts[iNumContacts++] = Contact(Pseg, pxPoints1[0], &box1.body, &box2.body);
            }
        }

        if (max0 != min0 && max1 != min1)
        {
            if (max0 < max1)
            {
                Point2f Pseg;
                if (ProjectPointOnSegment(pxPoints0[1], pxPoints1[0], pxPoints1[1], Pseg))
                {
                    xContacts[iNumContacts++] = Contact(pxPoints0[1], Pseg, &box1.body, &box2.body);
                }
            }
            else
            {
                Point2f Pseg;
                if (ProjectPointOnSegment(pxPoints1[1], pxPoints0[0], pxPoints0[1], Pseg))
                {
                    xContacts[iNumContacts++] = Contact(Pseg, pxPoints1[1], &box1.body, &box2.body);
                }
            }
        }
        return true;
    }

    bool FindCollisionPlane(const Point2f* xAxes, float* d, Point2f& Ncoll, float& dcoll)
    {
        float dmin = 1000000.0f;
        int imin = -1;

        for(int i = 0; i < 4; i ++)
        {
            float a = xAxes[i].Length();

            if (a < 0.000001f)
                continue;

            float depth = d[i] / a;

            if (depth < dmin)
            {
                dmin = depth;
                imin = i;
                Ncoll = xAxes[i] / a;
                dcoll = depth;
            }
        }

        return (imin != -1);
    }
    bool IntervalIntersect(const Point2f& xAxis, const BoxShape& box1, const BoxShape& box2, float& depth)
    {
        float min0, max0;
        float min1, max1;

        box1.GetInterval(xAxis, min0, max0);
        box2.GetInterval(xAxis, min1, max1);

        if (min0 > max1 || min1 > max0) return false;

        float d0 = max1 - min0;
        float d1 = max0 - min1;

        if (d0 < d1)
            depth = d0;
        else
            depth = d1;

        return true;
    }

    size_t collide(BoxShape &box1, BoxShape &box2, float dt, Contact *pxContacts, size_t numMaxContacts)
    {
        dt;

        Point2f xAxis [4];
        float  fDepth[4];

        xAxis[0] = box1.GetDir(0);
        if (!IntervalIntersect(xAxis[0], box1, box2, fDepth[0])) return 0;

        xAxis[1] = box1.GetDir(1);
        if (!IntervalIntersect(xAxis[1], box1, box2, fDepth[1])) return 0;

        xAxis[2] = box2.GetDir(0);
        if (!IntervalIntersect(xAxis[2], box1, box2, fDepth[2])) return 0;

        xAxis[3] = box2.GetDir(1);
        if (!IntervalIntersect(xAxis[3], box1, box2, fDepth[3])) return 0;

        float dcoll;
        Point2f Ncoll;
        if (!FindCollisionPlane(xAxis, fDepth, Ncoll, dcoll)) return 0;

        Point2f D = box1.body.getPosition() - box2.body.getPosition();

        if (D * Ncoll < 0.0f)
            Ncoll *= -1.0f;

        Point2f xPoints0[4];
        Point2f xPoints1[4];
        size_t numPoints0;
        size_t numPoints1;

        numPoints0 = box1.FindSupportPoints( Ncoll, xPoints0);
        numPoints1 = box2.FindSupportPoints(-Ncoll, xPoints1);

        if (!ConvertSupportPointsToContacts(box1, box2, Ncoll, xPoints0, numPoints0, xPoints1, numPoints1, pxContacts, numMaxContacts))
            return 0;
        return numMaxContacts;
    }
    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;
    }
    size_t collide(CircleShape &circle1, CircleShape &circle2, float dt, Contact *pxContacts, size_t numMaxContacts)
    {
        dt, numMaxContacts;

        float rR = circle1.GetRadius() + circle2.GetRadius();
        const Point2f &p1 = circle1.body.getPosition();
        const Point2f &p2 = circle2.body.getPosition();
        Point2f d = p2 - p1;
        float len = d.Length();
        if (len > rR)
        {
            return 0;
        }
        d.Normalize();
        
        pxContacts[0] = Contact(p1 + d * circle1.GetRadius(), p1 + d * (len - circle1.GetRadius()), &circle1.body, &circle2.body);
        return 1;
    }

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -