I am using bullet in an OpenGL application creating a 3D space shooter. At some point I want to ray cast from the middle of the screen to a rigid body on the screen. This works fine for rigid bodies with group 1 and mask 1. But I have some objects that don't collide with others set a group of 1 and mask of 0. On those objects the the ray misses. Here is the ray that I am casting :
Code: Select all
bool BphysicsManager::rayHasHit(glm::vec3& rayFromWorld, glm::vec3& rayToWorld, btVector3* hitPointWorld, btRigidBody** body)
{
mMutex->lock();
bool ret;
rayFrom.setX(rayFromWorld.x);
rayFrom.setY(rayFromWorld.y);
rayFrom.setZ(rayFromWorld.z);
rayTo.setX(rayToWorld.x);
rayTo.setY(rayToWorld.y);
rayTo.setZ(rayToWorld.z);
btCollisionWorld::ClosestRayResultCallback rayCallback(rayFrom, rayTo);
mpDynamicsWorld->rayTest(rayFrom, rayTo, rayCallback);
if (rayCallback.m_collisionObject)
{
*body = (btRigidBody*)btRigidBody::upcast(rayCallback.m_collisionObject);
*hitPointWorld = rayCallback.m_hitPointWorld;
auto colShape = (*body)->getCollisionShape();
if (dynamic_cast<btConcaveShape*>(colShape) != nullptr)
{
*body = nullptr;
}
}
ret = rayCallback.hasHit();
mMutex->unlock();
return ret;
}
Code: Select all
btRigidBody* BphysicsManager::loadBody(btVector3& pLocation, float pSizeX, float pSizeY, float pSizeZ, btVector3& scale , float pDensity, void* userPtr, shape_type_t type, int group, int mask)
{
mMutex->lock();
btCollisionShape* shape;
switch (type) {
case SHAPE_BOX:
shape = new btBoxShape(btVector3(pSizeX, pSizeY, pSizeZ));
break;
case SHAPE_SPHERE:
shape = new btSphereShape(pSizeX / 2);
break;
case SHAPE_CAPSULE:
shape = new btCapsuleShape(pSizeY, pSizeY / 4);
break;
case SHAPE_CYLINDER:
shape = new btCylinderShape(btVector3(pSizeX / 2, pSizeY / 2, pSizeZ / 2));
break;
default:
shape = new btSphereShape(pSizeX / 2);
break;
}
shape->setMargin(0.001f);
shape->setLocalScaling(scale);
btTransform startTransform = btTransform();
startTransform.setIdentity();
startTransform.setOrigin(pLocation); //put it to x,y,z coordinates
btAssert((!shape || shape->getShapeType() != INVALID_SHAPE_PROXYTYPE));
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (pDensity != 0.f);
btVector3 localInertia(0, 0, 0);
if (isDynamic)
shape->calculateLocalInertia(pDensity, localInertia);
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
#define USE_MOTIONSTATE 1
#ifdef USE_MOTIONSTATE
btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
vMotionStates.push_back(myMotionState);
btRigidBody::btRigidBodyConstructionInfo cInfo(pDensity, myMotionState, shape, localInertia);
btRigidBody* body = new btRigidBody(cInfo);
body->setWorldTransform(startTransform);
#else
btRigidBody* body = new btRigidBody(mass, 0, shape, localInertia);
body->setWorldTransform(startTransform);
#endif//
if (userPtr) body->setUserPointer(userPtr);
vCollisionShapes.push_back(shape);
vRigidBodies.push_back(body);
body->setAngularFactor(1.f);
body->setLinearVelocity(btVector3(0, 0, 0));
body->setAngularVelocity(btVector3(0, 0, 0));
body->setFriction(1.0);
body->activate(true);
body->setSleepingThresholds(0.f, 0.f);
if (userPtr) body->setUserPointer(userPtr);
mpDynamicsWorld->addRigidBody(body, group, mask);
mMutex->unlock();
return body;
}