Bullet Physics-从刚体直接投射光线(第一人称相机)


10

我已经使用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上搜索了投射射线的示例以及Bullet文档,很难仅找到一个示例。我确实需要一个例子。

还是Bullet中有某种方法可以将刚体保持在地面上?

我使用Ogre3D作为渲染引擎,并且向下投射光线非常简单,但是为了简单起见,我希望将所有光线投射保留在Bullet中。

有人能指出我正确的方向吗?谢谢。

Answers:


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());
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.