Good Place. Good Things. Good Time.

Physics engine and rigidbody sleep optimization

I am trying to add sleep optimization to my little physics engine(just for learning). I use SAT for collision detection that returns penetration normal and depth without contact points. Objects are put to sleep after 180 frames if their velocity is less then eps. When objects are stacked and in sleeping state when i add velocity to the bottom object, objects on top remain in sleep mode and just float in the air. Can sleeping be implemented without contact points at all?
This is done in 3d.

This is collision loop:

void Physics::updateReal(float dt){
    auto& rbs = EntitySystem::instance()->_rigidbodies;

    for (auto rb : rbs) {
        if(rb->isAwake())
            rb->integrate(dt);
    }

    for (int i = 0; i < 1; ++i) { //can be called multiple times per frame to improve stability
        blackList.clear();
        //std::cout << "########" << std::endl;
        for (auto rb : rbs) {
            if (!rb->isAwake() || rb->_inverseMass == 0.0f) continue;       //skip static and sleeping rbs

            //colliders c1 of current rigidbody
            std::vector RBColliders; rb->thisEntity()->getColliders(RBColliders);

            for (auto c1 : RBColliders) {
                glm::vec3 o, d; c1->getAABB(o, d); std::vector colliders2;
                SpatialPartitioning::instance()->queryAABB(colliders2, o, d, BVH_COLLIDERS);

                for (BVHTreeContainee* c2bvh : colliders2) {
                    auto c2 = (Collider*)c2bvh;
                    if (!c2->isRigidbody()) continue;
                    if (c1 == c2) continue;
                    if (c1->getEntity() == c2->getEntity()) continue;

                    //std::cout << c1->getEntity()->gameObject()->name << " AND " << c2->getEntity()->gameObject()->name << std::endl;
                    collide(c1, c2);
                }
                //blackList.push_back(c1);  //c1 is all tested
            }
        }
    }
}

This is integration of rigidbody:

void Rigidbody::integrate(float dt){
    if (_inverseMass == 0.0f) return;
    auto trans = thisEntity()->transform();

    //sleep
    if (glm::length(_velocity) < 3.5f)  ++_sleepStage;
    else                                _sleepStage = 0;

    if (_sleepStage > 180) { _awake = false; return; }

    std::cout << "# " << glm::length(_velocity) << " " << _sleepStage << std::endl;

    //euler integration of position
    _velocity.y -= _gravity * dt;           //rhs = ubrzanje * dt, lhs = brzina
    trans->addPosition(_velocity * dt);     //rhs = brzina * dt, lhs = pozicija
}

This function is called to resolve collision:

inline void Physics::collisionResolution(Collider* c1, Collider* c2, glm::vec3 mtvAxis, float mtvDist, bool flip){
    auto A = c1->getRigidbody();
    auto B = c2->getRigidbody();

    //COLLISION RESOLUTION
    if (flip) mtvAxis *= -1.f;
    mtvDist /= 2.f;

    if(A->_inverseMass > 0.0f && A->isAwake())
        c1->getEntity()->transform()->addPosition(mtvAxis * mtvDist);
    if(B->_inverseMass > 0.0f && B->isAwake())
        c2->getEntity()->transform()->addPosition(-mtvAxis * mtvDist);

    //LINEAR IMPULSE
    glm::vec3 rv = A->_velocity - B->_velocity;
    float velAlongNormal = glm::dot(rv, mtvAxis);
    if (velAlongNormal > 0.0f) return;

    float e = 0.2f;
    float j = -(1.0f + e) * velAlongNormal;
    j /= A->_inverseMass + B->_inverseMass;

    glm::vec3 impulse = mtvAxis * j;

    glm::vec3 impulseA = impulse * A->_inverseMass;
    glm::vec3 impulseB = impulse * B->_inverseMass;

    A->setAwake();  //sets _awake to true
    A->_velocity += impulseA;

    B->setAwake();
    B->_velocity -= impulseB;

    //FRICTION
    glm::vec3 t = rv - (mtvAxis * velAlongNormal);

    if (glm::length(t) == 0.0f) return;
    t = glm::normalize(t);

    float jt = -glm::dot(rv, t);
    jt /= A->_inverseMass + B->_inverseMass;
    if (jt == 0.0f) return;

    float friction = glm::sqrt(0.03f);
    if (jt > j * friction)
        jt = j * friction;
    else if (jt < -j * friction)
        jt = -j * friction;

    glm::vec3 tangentImpuse = t * jt;
    A->_velocity += tangentImpuse * A->_inverseMass;
    B->_velocity -= tangentImpuse * B->_inverseMass;

    //ANGULAR IMPULSE
    //THE DARKEST BLACK MAGIC
}

Search more articles here: Physics engine and rigidbody sleep optimization

Read original article here: Physics engine and rigidbody sleep optimization



Disclaimers and Denial of responsibility..!

Denial of responsibility! TheTopMag.com is an automatic aggregator of all media around the world. In each content, the hyperlink to the primary source is specified. All trademarks belong to their rightful owners, all materials to their authors. If you are the owner of the content and do not want us to publish your materials, please contact us by email – jamesonline999@gmail.com . The content will be deleted within 72 hours.
You might also like
Leave A Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.