Bullet Vật lý - Đúc một tia thẳng xuống từ một cơ thể cứng nhắc (máy ảnh người thứ nhất)


10

Tôi đã triển khai máy ảnh người đầu tiên sử dụng Bullet - đó là một cơ thể cứng nhắc với hình dạng viên nang. Tôi mới chỉ sử dụng Bullet được vài ngày và động cơ vật lý còn mới đối với tôi. Tôi sử dụng btRigidBody::setLinearVelocity()để di chuyển nó và nó va chạm hoàn hảo với thế giới. Vấn đề duy nhất là giá trị Y di chuyển tự do, mà tôi tạm thời giải quyết bằng cách đặt giá trị Y của vectơ dịch về 0 trước khi cơ thể được di chuyển. Điều này hoạt động cho tất cả các trường hợp ngoại trừ khi rơi từ độ cao.

Khi cơ thể rơi ra khỏi một vật thể cao, bạn vẫn có thể lướt đi xung quanh vì giá trị Y của vectơ dịch được đặt thành 0, cho đến khi bạn ngừng di chuyển và rơi xuống đất (vận tốc chỉ được đặt khi di chuyển). Vì vậy, để giải quyết vấn đề này, tôi muốn thử truyền tia từ thân máy để xác định giá trị Y của thế giới và kiểm tra sự khác biệt giữa giá trị đó và giá trị Y của thân máy và vô hiệu hóa hoặc làm chậm chuyển động nếu sự khác biệt là đủ lớn.

Tôi hơi bị mắc kẹt khi chỉ đơn giản là chiếu một tia và xác định giá trị Y của thế giới nơi nó chiếu tới. Tôi đã thực hiện cuộc gọi lại nà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;
    }
};

Và trong hàm chuyển động, tôi có mã này:

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

Vì vậy, tôi có callback.m_hitPointWorldvector, dường như chỉ hiển thị vị trí của máy ảnh mỗi khung hình. Tôi đã tìm kiếm trên Google các ví dụ về các tia đúc, cũng như tài liệu Bullet và thật khó để tìm thấy một ví dụ. Một ví dụ thực sự là tất cả những gì tôi cần.

Hoặc có lẽ có một số phương pháp trong Bullet để giữ cơ thể cứng nhắc trên mặt đất?

Tôi đang sử dụng Ogre3D làm công cụ kết xuất và việc truyền tia xuống khá đơn giản với điều đó, tuy nhiên tôi muốn giữ tất cả việc truyền tia trong Bullet cho đơn giản.

Ai có thể chỉ cho tôi đi đúng hướng? Cảm ơn.

Câu trả lời:


10

Hóa ra giải pháp đơn giản hơn nhiều so với nỗ lực ban đầu và không cần phân lớp nếu bạn chỉ thử nghiệm va chạm một tia.

Đây là tất cả những gì bạn phải làm để lấy vectơ va chạm:

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());
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.