BoundingBox CollisionShape::GetWorldBoundingBox() const { if (shape_ && node_) { // Use the rigid body's world transform if possible, as it may be different from the rendering transform RigidBody* body = GetComponent<RigidBody>(); Matrix3x4 worldTransform = body ? Matrix3x4(body->GetPosition(), body->GetRotation(), node_->GetWorldScale()) : node_->GetWorldTransform(); Vector3 worldPosition(worldTransform * position_); Quaternion worldRotation(worldTransform.Rotation() * rotation_); btTransform shapeWorldTransform(ToBtQuaternion(worldRotation), ToBtVector3(worldPosition)); btVector3 aabbMin, aabbMax; shape_->getAabb(shapeWorldTransform, aabbMin, aabbMax); return BoundingBox(ToVector3(aabbMin), ToVector3(aabbMax)); } else return BoundingBox(); }
void RigidBody::SetRotation(Quaternion rotation) { if (body_) { Vector3 oldPosition = GetPosition(); btTransform& worldTrans = body_->getWorldTransform(); worldTrans.setRotation(ToBtQuaternion(rotation)); if (!centerOfMass_.Equals(Vector3::ZERO)) worldTrans.setOrigin(ToBtVector3(oldPosition + rotation * centerOfMass_)); btTransform interpTrans = body_->getInterpolationWorldTransform(); interpTrans.setRotation(worldTrans.getRotation()); if (!centerOfMass_.Equals(Vector3::ZERO)) interpTrans.setOrigin(worldTrans.getOrigin()); body_->setInterpolationWorldTransform(interpTrans); body_->updateInertiaTensor(); Activate(); MarkNetworkUpdate(); } }
void RigidBody::SetTransform(const Vector3& position, const Quaternion& rotation) { if (body_) { btTransform& worldTrans = body_->getWorldTransform(); worldTrans.setRotation(ToBtQuaternion(rotation)); worldTrans.setOrigin(ToBtVector3(position + rotation * centerOfMass_)); if (physicsWorld_->IsSimulating()) { btTransform interpTrans = body_->getInterpolationWorldTransform(); interpTrans.setOrigin(worldTrans.getOrigin()); interpTrans.setRotation(worldTrans.getRotation()); body_->setInterpolationWorldTransform(interpTrans); } body_->updateInertiaTensor(); Activate(); MarkNetworkUpdate(); } }
void CollisionShape::DrawDebugGeometry(DebugRenderer* debug, bool depthTest) { if (debug && physicsWorld_ && shape_ && node_ && IsEnabledEffective()) { physicsWorld_->SetDebugRenderer(debug); physicsWorld_->SetDebugDepthTest(depthTest); // Use the rigid body's world transform if possible, as it may be different from the rendering transform Matrix3x4 worldTransform; RigidBody* body = GetComponent<RigidBody>(); bool bodyActive = false; if (body) { worldTransform = Matrix3x4(body->GetPosition(), body->GetRotation(), node_->GetWorldScale()); bodyActive = body->IsActive(); } else worldTransform = node_->GetWorldTransform(); Vector3 position = position_; // For terrains, undo the height centering performed automatically by Bullet if (shapeType_ == SHAPE_TERRAIN && geometry_) { HeightfieldData* heightfield = static_cast<HeightfieldData*>(geometry_.Get()); position.y_ += (heightfield->minHeight_ + heightfield->maxHeight_) * 0.5f; } Vector3 worldPosition(worldTransform * position); Quaternion worldRotation(worldTransform.Rotation() * rotation_); btDiscreteDynamicsWorld* world = physicsWorld_->GetWorld(); world->debugDrawObject(btTransform(ToBtQuaternion(worldRotation), ToBtVector3(worldPosition)), shape_, bodyActive ? WHITE : GREEN); physicsWorld_->SetDebugRenderer(0); } }
void Constraint::CreateConstraint() { PROFILE(CreateConstraint); cachedWorldScale_ = node_->GetWorldScale(); ReleaseConstraint(); ownBody_ = GetComponent<RigidBody>(); btRigidBody* ownBody = ownBody_ ? ownBody_->GetBody() : 0; btRigidBody* otherBody = otherBody_ ? otherBody_->GetBody() : 0; // If no physics world available now mark for retry later if (!physicsWorld_ || !ownBody) { retryCreation_ = true; return; } if (!otherBody) otherBody = &btTypedConstraint::getFixedBody(); Vector3 ownBodyScaledPosition = position_ * cachedWorldScale_ - ownBody_->GetCenterOfMass(); Vector3 otherBodyScaledPosition = otherBody_ ? otherPosition_ * otherBody_->GetNode()->GetWorldScale() - otherBody_->GetCenterOfMass() : otherPosition_; switch (constraintType_) { case CONSTRAINT_POINT: { constraint_ = new btPoint2PointConstraint(*ownBody, *otherBody, ToBtVector3(ownBodyScaledPosition), ToBtVector3(otherBodyScaledPosition)); } break; case CONSTRAINT_HINGE: { btTransform ownFrame(ToBtQuaternion(rotation_), ToBtVector3(ownBodyScaledPosition)); btTransform otherFrame(ToBtQuaternion(otherRotation_), ToBtVector3(otherBodyScaledPosition)); constraint_ = new btHingeConstraint(*ownBody, *otherBody, ownFrame, otherFrame); } break; case CONSTRAINT_SLIDER: { btTransform ownFrame(ToBtQuaternion(rotation_), ToBtVector3(ownBodyScaledPosition)); btTransform otherFrame(ToBtQuaternion(otherRotation_), ToBtVector3(otherBodyScaledPosition)); constraint_ = new btSliderConstraint(*ownBody, *otherBody, ownFrame, otherFrame, false); } break; case CONSTRAINT_CONETWIST: { btTransform ownFrame(ToBtQuaternion(rotation_), ToBtVector3(ownBodyScaledPosition)); btTransform otherFrame(ToBtQuaternion(otherRotation_), ToBtVector3(otherBodyScaledPosition)); constraint_ = new btConeTwistConstraint(*ownBody, *otherBody, ownFrame, otherFrame); } break; default: break; } if (constraint_) { constraint_->setUserConstraintPtr(this); constraint_->setEnabled(IsEnabledEffective()); ownBody_->AddConstraint(this); if (otherBody_) otherBody_->AddConstraint(this); ApplyLimits(); physicsWorld_->GetWorld()->addConstraint(constraint_, disableCollision_); } recreateConstraint_ = false; framesDirty_ = false; retryCreation_ = false; }
PintObjectHandle Bullet::CreateObject(const PINT_OBJECT_CREATE& desc) { udword NbShapes = desc.GetNbShapes(); if(!NbShapes) return null; ASSERT(mDynamicsWorld); const PINT_SHAPE_CREATE* CurrentShape = desc.mShapes; float FrictionCoeff = 0.5f; float RestitutionCoeff = 0.0f; btCollisionShape* colShape = null; if(NbShapes>1) { btCompoundShape* CompoundShape = new btCompoundShape(); colShape = CompoundShape; mCollisionShapes.push_back(colShape); while(CurrentShape) { if(CurrentShape->mMaterial) { FrictionCoeff = CurrentShape->mMaterial->mDynamicFriction; RestitutionCoeff = CurrentShape->mMaterial->mRestitution; } const btTransform LocalPose(ToBtQuaternion(CurrentShape->mLocalRot), ToBtVector3(CurrentShape->mLocalPos)); // ### TODO: where is this deleted? btCollisionShape* subShape = CreateBulletShape(*CurrentShape); if(subShape) { CompoundShape->addChildShape(LocalPose, subShape); } CurrentShape = CurrentShape->mNext; } } else { colShape = CreateBulletShape(*CurrentShape); if(CurrentShape->mMaterial) { FrictionCoeff = CurrentShape->mMaterial->mDynamicFriction; RestitutionCoeff = CurrentShape->mMaterial->mRestitution; } } const bool isDynamic = (desc.mMass != 0.0f); btVector3 localInertia(0,0,0); if(isDynamic) colShape->calculateLocalInertia(desc.mMass, localInertia); const btTransform startTransform(ToBtQuaternion(desc.mRotation), ToBtVector3(desc.mPosition)); //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); btRigidBody::btRigidBodyConstructionInfo rbInfo(desc.mMass, myMotionState, colShape, localInertia); { rbInfo.m_friction = FrictionCoeff; rbInfo.m_restitution = RestitutionCoeff; // rbInfo.m_startWorldTransform; rbInfo.m_linearDamping = gLinearDamping; rbInfo.m_angularDamping = gAngularDamping; if(!gEnableSleeping) { // rbInfo.m_linearSleepingThreshold = 99999999.0f; // rbInfo.m_angularSleepingThreshold = 99999999.0f; // rbInfo.m_linearSleepingThreshold = 0.0f; // rbInfo.m_angularSleepingThreshold = 0.0f; } // rbInfo.m_additionalDamping; // rbInfo.m_additionalDampingFactor; // rbInfo.m_additionalLinearDampingThresholdSqr; // rbInfo.m_additionalAngularDampingThresholdSqr; // rbInfo.m_additionalAngularDampingFactor; } btRigidBody* body = new btRigidBody(rbInfo); ASSERT(body); if(!gEnableSleeping) body->setActivationState(DISABLE_DEACTIVATION); sword collisionFilterGroup, collisionFilterMask; if(isDynamic) { body->setLinearVelocity(ToBtVector3(desc.mLinearVelocity)); body->setAngularVelocity(ToBtVector3(desc.mAngularVelocity)); collisionFilterGroup = short(btBroadphaseProxy::DefaultFilter); collisionFilterMask = short(btBroadphaseProxy::AllFilter); if(desc.mCollisionGroup) { const udword btGroup = RemapCollisionGroup(desc.mCollisionGroup); ASSERT(btGroup<32); collisionFilterGroup = short(1<<btGroup); collisionFilterMask = short(mGroupMasks[btGroup]); } } else { // body->setCollisionFlags(btCollisionObject::CF_STATIC_OBJECT); body->setCollisionFlags(btCollisionObject::CF_STATIC_OBJECT|btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); collisionFilterGroup = short(btBroadphaseProxy::StaticFilter); collisionFilterMask = short(btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter); } if(desc.mAddToWorld) // mDynamicsWorld->addRigidBody(body); mDynamicsWorld->addRigidBody(body, collisionFilterGroup, collisionFilterMask); if(gUseCCD) { // body->setCcdMotionThreshold(1e-7); // body->setCcdSweptSphereRadius(0.9*CUBE_HALF_EXTENTS); body->setCcdMotionThreshold(0.0001f); body->setCcdSweptSphereRadius(0.4f); } return body; }