Фізика кулі - відкидання променя прямо від жорсткого тіла (камера від першої особи)


10

Я реалізував камеру від першої особи за допомогою Bullet - це жорстке тіло з формою капсули. Я використовую Bullet лише кілька днів, і фізичні двигуни для мене нові. Я використовую його btRigidBody::setLinearVelocity()для переміщення, і він ідеально стикається зі світом. Єдина проблема - вільне переміщення значення Y, яке я тимчасово вирішив, встановивши значення Y для вектора перекладу на нуль до переміщення тіла. Це працює в усіх випадках, крім падіння з висоти.

Коли тіло скидає високий предмет, ви все ще можете ковзати, оскільки Y-значення перекладеного вектора встановлено в нуль, поки ви не перестанете рухатися і не впадете на землю (швидкість встановлюється лише при русі). Тому для вирішення цього питання я хотів би спробувати відкинути промінь від тіла, щоб визначити значення Y світу, і перевірити різницю між цим значенням і значенням Y в корпусі камери, а також відключити або уповільнити рух, якщо різниця досить велика

Я трохи застряг у тому, щоб просто кинути промінь і визначити Y-значення світу, де він потрапив. Я реалізував цей зворотний дзвінок:

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;
    }
};

А у функції руху у мене є такий код:

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);

Отже, у мене є callback.m_hitPointWorldвектор, який, здається, просто показує положення камери в кожному кадрі. Я шукав у Google приклади лиття променів, а також документацію про кулю, і важко було просто знайти приклад. Приклад - це справді все, що мені потрібно.

А може, існує якийсь метод у кулі, щоб утримати жорстке тіло на землі?

Я використовую Ogre3D в якості двигуна візуалізації, і відкидання променя вниз є досить простим з цим, однак я хочу тримати весь промінь променя в кулі для простоти.

Чи міг би хтось вказати на мене в правильному напрямку? Дякую.

Відповіді:


10

Виявляється, рішення набагато простіше, ніж оригінальна спроба, і немає необхідності в підкласифікації, якщо ви просто тестуєте одне зіткнення променів.

Ось усе, що потрібно зробити, щоб отримати вектор зіткнення:

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());
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.