Bullet Physics - Wirft einen Strahl direkt von einem starren Körper (Ego-Kamera)


10

Ich habe eine First-Person-Kamera mit Bullet implementiert - es ist ein starrer Körper mit einer Kapselform. Ich benutze Bullet erst seit ein paar Tagen und Physik-Engines sind für mich neu. Ich btRigidBody::setLinearVelocity()bewege es und es kollidiert perfekt mit der Welt. Das einzige Problem ist, dass sich der Y-Wert frei bewegt, was ich vorübergehend gelöst habe, indem ich den Y-Wert des Translationsvektors auf Null gesetzt habe, bevor der Körper bewegt wird. Dies funktioniert in allen Fällen, außer wenn Sie aus großer Höhe fallen.

Wenn der Körper von einem hohen Objekt abfällt, können Sie immer noch herumgleiten, da der Y-Wert des Übersetzungsvektors auf Null gesetzt wird, bis Sie aufhören, sich zu bewegen und auf den Boden fallen (die Geschwindigkeit wird nur beim Bewegen eingestellt). Um dies zu lösen, möchte ich versuchen, einen Strahl vom Körper herabzuwerfen, um den Y-Wert der Welt zu bestimmen, die Differenz zwischen diesem Wert und dem Y-Wert des Kameragehäuses zu überprüfen und die Bewegung zu deaktivieren oder zu verlangsamen, wenn Der Unterschied ist groß genug.

Ich bin ein bisschen festgefahren, einfach einen Strahl zu werfen und den Y-Wert der Welt zu bestimmen, in der er getroffen hat. Ich habe diesen Rückruf implementiert:

struct AllRayResultCallback : public btCollisionWorld::RayResultCallback{
    AllRayResultCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld)
        : m_rayFromWorld(rayFromWorld), m_rayToWorld(rayToWorld), m_closestHitFraction(1.0){}

    btVector3   m_rayFromWorld;
    btVector3   m_rayToWorld;
    btVector3   m_hitNormalWorld;
    btVector3   m_hitPointWorld;
    float       m_closestHitFraction;

    virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace)
    {
        if(rayResult.m_hitFraction < m_closestHitFraction)
            m_closestHitFraction = rayResult.m_hitFraction;

        m_collisionObject = rayResult.m_collisionObject;
        if(normalInWorldSpace){
            m_hitNormalWorld = rayResult.m_hitNormalLocal;
        }
        else{
            m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis() * rayResult.m_hitNormalLocal;
        }

        m_hitPointWorld.setInterpolate3(m_rayFromWorld, m_rayToWorld, m_closestHitFraction);
        return 1.0f;
    }
};

Und in der Bewegungsfunktion habe ich diesen Code:

btVector3 from(pos.x, pos.y + 1000, pos.z); // pos is the camera's rigid body position
btVector3 to(pos.x, 0, pos.z); // not sure if 0 is correct for Y

AllRayResultCallback callback(from, to);
Base::getSingletonPtr()->m_btWorld->rayTest(from, to, callback);

Ich habe also den callback.m_hitPointWorldVektor, der nur die Position der Kamera in jedem Bild zu zeigen scheint. Ich habe Google nach Beispielen für das Strahlen von Strahlen sowie nach der Bullet-Dokumentation durchsucht, und es war schwierig, nur ein Beispiel zu finden. Ein Beispiel ist wirklich alles was ich brauche.

Oder gibt es in Bullet eine Methode, um den starren Körper auf dem Boden zu halten?

Ich verwende Ogre3D als Rendering-Engine, und das Abwerfen eines Strahls ist damit recht einfach. Der Einfachheit halber möchte ich jedoch das gesamte Strahlen-Casting in Bullet beibehalten.

Könnte mich jemand in die richtige Richtung weisen? Vielen Dank.

Antworten:


10

Es stellt sich heraus, dass die Lösung viel einfacher ist als der ursprüngliche Versuch, und es ist keine Unterklasse erforderlich, wenn Sie nur eine Strahlenkollision testen.

Hier ist alles, was Sie tun müssen, um den Kollisionsvektor abzurufen:

btVector3 btFrom(camPos.x, camPos.y, camPos.z);
btVector3 btTo(camPos.x, -5000.0f, camPos.z);
btCollisionWorld::ClosestRayResultCallback res(btFrom, btTo);

Base::getSingletonPtr()->m_btWorld->rayTest(btFrom, btTo, res); // m_btWorld is btDiscreteDynamicsWorld

if(res.hasHit()){
    printf("Collision at: <%.2f, %.2f, %.2f>\n", res.m_hitPointWorld.getX(), res.m_hitPointWorld.getY(), res.m_hitPointWorld.getZ());
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.