PhysicsInterface::BodyObject Bullet::createCapsuleBody(float height, float radius, float mass, bool fixed, const Entity* entity, const SimpleTransform& initialTransform) { auto collisionShape = new btCapsuleShape(radius, height); // Calculate inertia auto localInertia = btVector3(0.0f, 0.0f, 0.0f); if (!fixed) collisionShape->calculateLocalInertia(mass, localInertia); // Motion state for this body auto motionState = new btDefaultMotionState(toBullet(initialTransform)); // Create Bullet rigid body auto bulletBody = new btRigidBody( btRigidBody::btRigidBodyConstructionInfo(fixed ? 0.0f : mass, motionState, collisionShape, localInertia)); bulletBody->setDamping(DefaultLinearDamping, DefaultAngularDamping); bulletBody->setSleepingThresholds(DefaultLinearSleepingThreshold, DefaultAngularSleepingThreshold); bulletBody->setRestitution(0.0f); // Add body to the simulation dynamicsWorld_->addRigidBody(bulletBody); // Create local body auto body = new Body(bulletBody, entity, fixed); bodies_.append(body); body->ownedCollisionShape = collisionShape; bulletBody->setUserPointer(body); return body; }
PhysicsRigidBody* PhysicsMgr::createRigidBodyFromCompund(float mass, Matrix44* transform, PhysicsCompoundShape * tzwShape) { auto rig = new PhysicsRigidBody(); bool isDynamic = (mass != 0.f); btVector3 localInertia(0, 0, 0); auto shape = tzwShape->getShape(); if (isDynamic) shape->calculateLocalInertia(mass, localInertia); btTransform startTransform; startTransform.setFromOpenGLMatrix(transform->data()); auto btRig = shared()->createRigidBodyInternal(mass, startTransform, shape, btVector4(1, 0, 0, 1)); rig->setRigidBody(btRig); rig->genUserIndex(); btRig->setUserIndex(rig->userIndex()); btRig->setUserPointer(rig); return rig; }
PhysicsInterface::BodyObject Bullet::createBoundingBoxBody(const AABB& aabb, float mass, bool fixed, const Entity* entity, const SimpleTransform& initialTransform) { auto collisionShape = new btBoxShape(toBullet((aabb.getMaximum() - aabb.getMinimum()) * 0.5f)); // Calculate inertia auto localInertia = btVector3(0.0f, 0.0f, 0.0f); if (!fixed) collisionShape->calculateLocalInertia(mass, localInertia); // Motion state for this body auto motionState = new btDefaultMotionState(toBullet(initialTransform), btTransform(btQuaternion::getIdentity(), toBullet(aabb.getCenter()))); // Create Bullet rigid body auto bulletBody = new btRigidBody( btRigidBody::btRigidBodyConstructionInfo(fixed ? 0.0f : mass, motionState, collisionShape, localInertia)); bulletBody->setDamping(DefaultLinearDamping, DefaultAngularDamping); bulletBody->setSleepingThresholds(DefaultLinearSleepingThreshold, DefaultAngularSleepingThreshold); bulletBody->setRestitution(0.0f); // Add body to the simulation dynamicsWorld_->addRigidBody(bulletBody); // Create local body auto body = new Body(bulletBody, entity, fixed); bodies_.append(body); body->ownedCollisionShape = collisionShape; bulletBody->setUserPointer(body); return body; }
bool Physics3DRigidBody::init(Physics3DRigidBodyDes* info) { if (info->shape == nullptr) return false; btScalar mass = info->mass; auto shape = info->shape->getbtShape(); auto localInertia = convertVec3TobtVector3(info->localInertia); if (mass != 0.f) { shape->calculateLocalInertia(mass,localInertia); } auto transform = convertMat4TobtTransform(info->originalTransform); btDefaultMotionState* myMotionState = new btDefaultMotionState(transform); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,shape,localInertia); _btRigidBody = new btRigidBody(rbInfo); _type = Physics3DObject::PhysicsObjType::RIGID_BODY; _physics3DShape = info->shape; _physics3DShape->retain(); if (info->disableSleep) _btRigidBody->setActivationState(DISABLE_DEACTIVATION); return true; }
bool CLiftableObject::lift() { assert(m_eState == LOS_AT_DEFAULT_LOCATION); m_eState = LOS_LIFTED; sendCreateInnerObjectEvent(IOCE_LIFT); btRigidBody *pRB = btRigidBody::upcast(m_pCollisionObject); btRigidBody *pNewRB(NULL); assert(pRB); if (m_bRecreateOnLift) { Ogre::String meshFile; // create dynamic close of pRB -> pNewRB, and delete the other one in the next frame auto pSN = m_ObjectManager.getMap().getRootSceneNode()->createChildSceneNode(); CPhysicsCollisionObject *pCO = m_ObjectManager.getMap().getPhysicsManager()->findCollisionShape(m_pCollisionObject->getCollisionShape()); auto shape = pCO->getShape(); meshFile = m_ObjectManager.getMap().getPhysicsManager()->getCollisionShapeKey(*pCO); float mass = 100.0f; btVector3 inertia; shape->calculateLocalInertia(mass, inertia); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, new BtOgre::RigidBodyState(pSN, m_pCollisionObject->getWorldTransform(), btTransform(btQuaternion::getIdentity(), BtOgre::Convert::toBullet(-pCO->getOffset()))), shape,inertia); pNewRB = new btRigidBody(rbInfo); // object now belongs to player, so dont interact with each other // create the entity Ogre::Entity *pEnt = m_ObjectManager.getMap().getSceneManager()->createEntity(meshFile); pSN->attachObject(pEnt); //m_ObjectManager.getMap().destroyObjectsEntity(this, NULL, BtOgre::Convert::toOgre(pNewRB->getWorldTransform().getOrigin())); //m_ObjectManager.getMap().getPhysicsManager()->createLater(const_cast<btRigidBody*>(pNewRB)); //m_ObjectManager.getMap().getPhysicsManager()->deleteLater(const_cast<btRigidBody*>(pRB)); delete pRB->getMotionState(); delete pRB; m_pCollisionObject = pNewRB; setAsUserPointer(pNewRB); } else { pNewRB = pRB; } assert(pNewRB); m_ObjectManager.getMap().getPhysicsManager()->getWorld()->removeCollisionObject(const_cast<btRigidBody*>(pRB)); m_ObjectManager.getMap().getPhysicsManager()->getWorld()->addRigidBody(pNewRB, COL_DAMAGE_P, COL_STATIC | COL_WALL | COL_CHARACTER_N); // is there an linked object to delete on lift? Ogre::String sRemoveObjectOnLift(m_UserData.getStringUserData("removeObjectOnLift")); if (sRemoveObjectOnLift.length() > 0) { m_ObjectManager.getObjectBySafeStateId(sRemoveObjectOnLift)->suicide(); } return true; }
void RigidBodyNode::sync_shapes(bool do_not_lock) { has_static_shapes_ = false; if (!shapes_.size()) { if (body_->getCollisionShape() != bullet_empty_shape_) { CONDITION_LOCK(ph_ && !do_not_lock, ph_->lock()); body_->setCollisionShape(bullet_empty_shape_); } } else { if (body_->isStaticObject()) { //Static rigid body shape construction if (shapes_.size() == 1 && shapes_[0].shape->is_static_shape()) { //Rigid body has only one collision shape // //TODO: Implement offset transform for static rigid bodies. // Now the transform of the collision shape is ignored. // Do not forget to fix set_mass and set_kinematic funcs. auto sh = shapes_[0].shape->construct_static(); assert(sh); CONDITION_LOCK(ph_ && !do_not_lock, ph_->lock()); body_->setCollisionShape(sh); if (!shapes_[0].shape->has_identical_shape_constructor()) has_static_shapes_ = true; } else { //Rigid body has more than one collision shape or //it cannot be static auto cs = new btCompoundShape(); for (auto sh : shapes_) { if (sh.shape->is_static_shape()) { cs->addChildShape( math::mat4_to_btTransform(sh.transform), sh.shape->construct_static()); if (!sh.shape->has_identical_shape_constructor()) has_static_shapes_ = true; } else if (sh.shape->is_dynamic_shape()) sh.shape->construct_dynamic( cs, math::mat4_to_btTransform(sh.transform)); } //If all the shapes support dynamic bodies, recalculate inertia //(in case if the body becomes dynamic) if (!has_static_shapes_) { cs->calculateLocalInertia(mass_, inertia_); body_->setMassProps(mass_, inertia_); } CONDITION_LOCK(ph_ && !do_not_lock, ph_->lock()); body_->setCollisionShape(cs); if (bullet_compound_shape_) delete bullet_compound_shape_; bullet_compound_shape_ = cs; } } else { //Dynamic rigid body shape construction auto cs = new btCompoundShape(); for (auto sh : shapes_) { if (sh.shape->is_dynamic_shape()) sh.shape->construct_dynamic( cs, math::mat4_to_btTransform(sh.transform)); } cs->calculateLocalInertia(mass_, inertia_); body_->setMassProps(mass_, inertia_); CONDITION_LOCK(ph_ && !do_not_lock, ph_->lock()); body_->setCollisionShape(cs); if (bullet_compound_shape_) delete bullet_compound_shape_; bullet_compound_shape_ = cs; } } }