/**
 * We attempt to have the player pick up a gun by raycasting to whatever the player is
 * looking at, and then if we hit something in the raycast, we check the distance,
 * and then we have to determine whether or not it's a gun.
 */
void attempt_to_pick_up_weapon()
{
    if (player_held_item != nullptr)
        return;

    GLfloat yaw = camera._yaw;
    GLfloat pitch = camera._pitch;
    glm::vec3 pos = camera._position;

    btScalar xz_len = cos(glm::radians(pitch));
    btVector3 bt_to(xz_len * cos(glm::radians(yaw)),
                    sin(glm::radians(pitch)),
                    xz_len * sin(glm::radians(yaw)));
    btVector3 bt_from(pos.x, pos.y, pos.z);
    bt_from += bt_to;
    bt_to *= 20;
    btCollisionWorld::ClosestRayResultCallback result(bt_from, bt_to);
    world->get_dynamics_world()->rayTest(bt_from, bt_to, result);

    if (result.hasHit() && (bt_from - result.m_hitPointWorld).length() < 0.7)
    {
        btRigidBody* collided = const_cast<btRigidBody*>(static_cast<const btRigidBody*>(result.m_collisionObject));
        Larp::Node* user_pointer = static_cast<Larp::Node*>(collided->getUserPointer());
        Weapon* weaponptr = nullptr;
        if(user_pointer != nullptr)
        {
           for (auto& it:pickupable_items) {
                if(it->_node == user_pointer)
                {
                    weaponptr = it;
                }
            }
        }
        if (weaponptr != nullptr)
        {
            world->get_dynamics_world()->removeRigidBody(const_cast<btRigidBody*>(collided));
            user_pointer->detach_this_from_parent();
            Larp::Node* gun_parent = camera_node->create_child();
            gun_parent->attach_child(user_pointer);
            user_pointer->set_position(0.0, 0.0, 0.0);
            gun_parent->set_position(-0.2, -0.25, weaponptr->_offset_z);
            glm::vec3 player_scale = static_cast<Larp::Node*>(player->get_user_pointer())->get_scale();
            glm::vec3 user_pointer_scale = user_pointer->get_scale();
            user_pointer->set_scale(user_pointer_scale.x / player_scale.x,
                                    user_pointer_scale.y / player_scale.y,
                                    user_pointer_scale.z / player_scale.z);
            user_pointer->set_orientation(glm::quat(1, 0, 0, 0));
            user_pointer->pitch(weaponptr->_offset_pitch);
            user_pointer->yaw(weaponptr->_offset_yaw);

            // Finally, update our player_held_item to denote that we are actually holding something
            player_held_item = weaponptr;
        }
    }
}
Esempio n. 2
0
float du_check_ray_hit(du_body_id du_body_a, float *from, float *to, bool local,
        du_body_id du_body_b_arr[], int du_body_b_num, du_body_id *du_body_b_hit_ptr)
{
    duWorld *world = get_active_world();

    btCollisionObject *bt_body_a = reinterpret_cast <btCollisionObject*>(du_body_a);
    btCollisionObject **bt_body_b_arr = reinterpret_cast <btCollisionObject**>(du_body_b_arr);

    btVector3 bt_from(from[0], from[1], from[2]);
    btVector3 bt_to(to[0], to[1], to[2]);

    btVector3 bt_from_w, bt_to_w;

    if (local) {
        // offsets in local space of A
        bt_from_w = bt_body_a->getWorldTransform() * bt_from;
        bt_to_w = bt_body_a->getWorldTransform() * bt_to;
    } else {
        // offsets in world space
        btTransform transform = bt_body_a->getWorldTransform();
        btVector3 origin = transform.getOrigin();

        bt_from_w = origin + bt_from;
        bt_to_w = origin + bt_to;
    }

    ClosestArrayRayResultCallback ray_cb(bt_body_b_arr, du_body_b_num);
    world->rayTest(bt_from_w, bt_to_w, ray_cb);

    if (ray_cb.hasHit()) {
        *du_body_b_hit_ptr = (du_body_id)ray_cb.m_collisionObject;
        return ray_cb.m_closestHitFraction;
    } else {
        *du_body_b_hit_ptr = NULL;
        return 1.0;
    }
}