Changeset 2423
- Timestamp:
- Dec 13, 2008, 4:14:36 PM (16 years ago)
- Location:
- code/branches/physics/src/orxonox
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
code/branches/physics/src/orxonox/OrxonoxPrereqs.h
r2408 r2423 212 212 // Bullet Physics Engine 213 213 214 class btTransform; 215 class btVector3; 216 214 217 class btRigidBody; 215 218 class btCollisionObject; -
code/branches/physics/src/orxonox/OrxonoxStableHeaders.h
r2192 r2423 103 103 //#endif /* ifdef NDEBUG */ 104 104 105 #endif /* ORXONOX_COMPILER == ORXONOX_COMPILER_MSVC && !defined(ORXONOX_DISABLE_PCH) */105 #endif /* defined(ORXONOX_ENABLE_PCH) */ 106 106 107 107 #endif /* _OrxonoxStableHeaders_H__ */ -
code/branches/physics/src/orxonox/objects/collisionshapes/CollisionShape.cc
r2403 r2423 76 76 void CollisionShape::registerVariables() 77 77 { 78 REGISTERDATA(this->parentID_, network::direction::toclient, new network::NetworkCallback<CollisionShape>(this, &CollisionShape::updateParent)); 78 REGISTERDATA(this->parentID_, network::direction::toclient, new network::NetworkCallback<CollisionShape>(this, &CollisionShape::parentChanged)); 79 } 80 81 void CollisionShape::parentChanged() 82 { 83 CompoundCollisionShape* parent = dynamic_cast<CompoundCollisionShape*>(Synchronisable::getSynchronisable(this->parentID_)); 84 if (parent) 85 parent->addChildShape(this); 79 86 } 80 87 81 88 void CollisionShape::updateParent() 82 89 { 83 CompoundCollisionShape* parent = dynamic_cast<CompoundCollisionShape*>(Synchronisable::getSynchronisable(this->parentID_)); 84 if (parent) 85 parent->addChildShape(this); 90 if (this->parent_) 91 this->parent_->updateChildShape(this); 86 92 } 87 93 … … 95 101 { 96 102 ThrowException(NotImplemented, "Cannot set the scale of a collision shape: Not yet implemented."); 103 this->updateParent(); 97 104 } 98 105 … … 100 107 { 101 108 ThrowException(NotImplemented, "Cannot set the scale of a collision shape: Not yet implemented."); 109 this->updateParent(); 110 } 111 112 btVector3 CollisionShape::getLocalInertia(btScalar mass) const 113 { 114 btVector3 inertia(0, 0, 0); 115 if (this->collisionShape_) 116 this->collisionShape_->calculateLocalInertia(mass, inertia); 117 return inertia; 102 118 } 103 119 } -
code/branches/physics/src/orxonox/objects/collisionshapes/CollisionShape.h
r2377 r2423 32 32 #include "OrxonoxPrereqs.h" 33 33 34 #include "LinearMath/btVector3.h" 34 35 #include "util/Math.h" 35 36 #include "core/BaseObject.h" … … 48 49 49 50 inline void setPosition(const Vector3& position) 50 { this->position_ = position; }51 { this->position_ = position; this->updateParent(); } 51 52 inline const Vector3& getPosition() const 52 53 { return this->position_; } 53 54 54 55 inline void setOrientation(const Quaternion& orientation) 55 { this->orientation_ = orientation; }56 { this->orientation_ = orientation; this->updateParent(); } 56 57 inline const Quaternion& getOrientation() const 57 58 { return this->orientation_; } 58 59 59 void yaw(const Degree& angle) { this-> orientation_ = this->orientation_ * Quaternion(angle, Vector3::UNIT_Y); }60 void pitch(const Degree& angle) { this-> orientation_ = this->orientation_ * Quaternion(angle, Vector3::UNIT_X); }61 void roll(const Degree& angle) { this-> orientation_ = this->orientation_ * Quaternion(angle, Vector3::UNIT_Z); }60 void yaw(const Degree& angle) { this->setOrientation(this->orientation_ * Quaternion(angle, Vector3::UNIT_Y)); } 61 void pitch(const Degree& angle) { this->setOrientation(this->orientation_ * Quaternion(angle, Vector3::UNIT_X)); } 62 void roll(const Degree& angle) { this->setOrientation(this->orientation_ * Quaternion(angle, Vector3::UNIT_Z)); } 62 63 63 64 virtual void setScale3D(const Vector3& scale); … … 66 67 { return this->scale_; } 67 68 68 virtual inline btCollisionShape* getCollisionShape() const 69 btVector3 getLocalInertia(float mass) const; 70 71 inline btCollisionShape* getCollisionShape() const 69 72 { return this->collisionShape_; } 70 73 … … 75 78 76 79 protected: 77 btCollisionShape* collisionShape_; 80 virtual void updateParent(); 81 82 btCollisionShape* collisionShape_; 83 CompoundCollisionShape* parent_; 78 84 79 85 private: 80 void updateParent();86 void parentChanged(); 81 87 82 Vector3 position_; 83 Quaternion orientation_; 84 Vector3 scale_; 85 CompoundCollisionShape* parent_; 86 unsigned int parentID_; 88 Vector3 position_; 89 Quaternion orientation_; 90 Vector3 scale_; 91 unsigned int parentID_; 87 92 }; 88 93 } -
code/branches/physics/src/orxonox/objects/collisionshapes/CompoundCollisionShape.cc
r2407 r2423 32 32 #include "BulletCollision/CollisionShapes/btCompoundShape.h" 33 33 34 #include "util/Exception.h" 34 35 #include "core/CoreIncludes.h" 35 36 #include "core/XMLPort.h" 36 37 #include "tools/BulletConversions.h" 38 #include "objects/worldentities/WorldEntity.h" 37 39 38 40 namespace orxonox … … 50 52 { 51 53 if (this->isInitialized()) 54 { 55 // Detatch all children first 56 this->removeAllChildShapes(); 52 57 delete this->compoundShape_; 58 } 53 59 } 54 60 … … 60 66 } 61 67 62 btCollisionShape* CompoundCollisionShape::getCollisionShape() const68 void CompoundCollisionShape::addChildShape(CollisionShape* shape) 63 69 { 64 // Note: Returning collisionShape_ means that it's the only one and has no transform. 65 // So we can get rid of the additional overhead with the compound shape. 66 if (this->collisionShape_) 67 return this->collisionShape_; 68 else if (!this->empty()) 69 return this->compoundShape_; 70 else 71 return 0; 72 } 73 74 void CompoundCollisionShape::addChildShape(CollisionShape* shape, bool bWorldEntityRoot) 75 { 76 if (!shape) 70 if (!shape || static_cast<CollisionShape*>(this) == shape) 77 71 return; 78 this->childShapes_.push_back(shape); 72 if (this->childShapes_.find(shape) != this->childShapes_.end()) 73 { 74 ThrowException(NotImplemented, "Warning: Attaching a CollisionShape twice is not yet supported."); 75 return; 76 } 77 this->childShapes_[shape] = shape->getCollisionShape(); 79 78 80 79 if (shape->getCollisionShape()) … … 84 83 this->compoundShape_->addChildShape(transf, shape->getCollisionShape()); 85 84 86 if (this->childShapes_.size() == 1 && !this->childShapes_[0]->hasTransform()) 87 { 88 // --> Only shape to be added, no transform; add it directly 89 this->collisionShape_ = shape->getCollisionShape(); 90 } 91 else 92 { 93 // Make sure we use the compound shape when returning the btCollisionShape 94 this->collisionShape_ = 0; 95 } 85 this->updatePublicShape(); 96 86 } 97 87 98 88 // network synchro 99 if (!bWorldEntityRoot) 100 shape->setParent(this, this->getObjectID()); 89 shape->setParent(this, this->getObjectID()); 90 } 91 92 void CompoundCollisionShape::removeChildShape(CollisionShape* shape) 93 { 94 if (this->childShapes_.find(shape) != this->childShapes_.end()) 95 { 96 shape->setParent(0, (unsigned int)-1); 97 this->childShapes_.erase(shape); 98 if (shape->getCollisionShape()) 99 this->compoundShape_->removeChildShape(shape->getCollisionShape()); 100 101 this->updatePublicShape(); 102 } 103 } 104 105 void CompoundCollisionShape::removeAllChildShapes() 106 { 107 while (this->childShapes_.size() > 0) 108 this->removeChildShape(this->childShapes_.begin()->first); 109 } 110 111 void CompoundCollisionShape::updateChildShape(CollisionShape* shape) 112 { 113 if (!shape) 114 return; 115 std::map<CollisionShape*, btCollisionShape*>::iterator it = this->childShapes_.find(shape); 116 if (it == this->childShapes_.end()) 117 { 118 CCOUT(2) << "Warning: Cannot update child shape: Instance not a child." << std::endl; 119 return; 120 } 121 122 // Remove old btCollisionShape, stored in the children map 123 if (it->second) 124 this->compoundShape_->removeChildShape(it->second); 125 if (shape->getCollisionShape()) 126 { 127 // Only actually attach if we didn't pick a CompoundCollisionShape with no content 128 btTransform transf(omni_cast<btQuaternion>(shape->getOrientation()), omni_cast<btVector3>(shape->getPosition())); 129 this->compoundShape_->addChildShape(transf, shape->getCollisionShape()); 130 it->second = shape->getCollisionShape(); 131 } 132 133 this->updatePublicShape(); 134 } 135 136 void CompoundCollisionShape::updatePublicShape() 137 { 138 btCollisionShape* primitive = 0; 139 bool bPrimitive = true; 140 bool bEmpty = true; 141 for (std::map<CollisionShape*, btCollisionShape*>::const_iterator it = this->childShapes_.begin(); it != this->childShapes_.end(); ++it) 142 { 143 if (it->second) 144 { 145 bEmpty = false; 146 if (!it->first->hasTransform()) 147 primitive = it->second; 148 else 149 bPrimitive = false; 150 } 151 } 152 if (bEmpty) 153 this->collisionShape_ = 0; 154 else if (bPrimitive) 155 { 156 // --> Only one shape to be added, no transform; return it directly 157 this->collisionShape_ = primitive; 158 } 159 else 160 { 161 // Make sure we use the compound shape when returning a btCollisionShape 162 this->collisionShape_ = this->compoundShape_; 163 } 164 this->updateParent(); 165 } 166 167 void CompoundCollisionShape::updateParent() 168 { 169 if (this->parent_) 170 this->parent_->updateChildShape(this); 171 else 172 { 173 // We can do this, because the CompoundCollisionShape of a WorldEntity always belongs to it, 174 // as long as its lifetime. 175 WorldEntity* parent = dynamic_cast<WorldEntity*>(this->getCreator()); 176 if (parent) 177 parent->notifyCollisionShapeChanged(); 178 } 101 179 } 102 180 103 181 CollisionShape* CompoundCollisionShape::getChildShape(unsigned int index) const 104 182 { 105 if (index < this->childShapes_.size()) 106 return this->childShapes_[index]; 107 else 108 return 0; 183 unsigned int i = 0; 184 for (std::map<CollisionShape*, btCollisionShape*>::const_iterator it = this->childShapes_.begin(); it != this->childShapes_.end(); ++it) 185 { 186 if (i == index) 187 return it->first; 188 ++i; 189 } 190 return 0; 109 191 } 110 192 } -
code/branches/physics/src/orxonox/objects/collisionshapes/CompoundCollisionShape.h
r2407 r2423 45 45 virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode); 46 46 47 void addChildShape(CollisionShape* shape, bool bWorldEntityRoot = false); 47 void addChildShape(CollisionShape* shape); 48 void removeChildShape(CollisionShape* shape); 49 void removeAllChildShapes(); 48 50 CollisionShape* getChildShape(unsigned int index) const; 49 51 50 v irtual btCollisionShape* getCollisionShape() const;52 void updateChildShape(CollisionShape* shape); 51 53 52 inline bool empty() const53 { return this->childShapes_.size() == 0; }54 protected: 55 virtual void updateParent(); 54 56 55 57 private: 56 btCompoundShape* compoundShape_; 57 std::vector<CollisionShape*> childShapes_; 58 void updatePublicShape(); 59 60 btCompoundShape* compoundShape_; 61 std::map<CollisionShape*, btCollisionShape*> childShapes_; 58 62 }; 59 63 } -
code/branches/physics/src/orxonox/objects/collisionshapes/PlaneCollisionShape.cc
r2403 r2423 74 74 delete this->collisionShape_; 75 75 this->collisionShape_ = new btStaticPlaneShape(omni_cast<btVector3>(this->normal_), this->offset_); 76 this->updateParent(); 76 77 } 77 78 } -
code/branches/physics/src/orxonox/objects/collisionshapes/SphereCollisionShape.cc
r2403 r2423 72 72 if (this->collisionShape_) 73 73 delete this->collisionShape_; 74 // When we recreate the shape, we have to inform the parent about this to update the shape 74 75 this->collisionShape_ = new btSphereShape(this->radius_); 76 this->updateParent(); 75 77 } 76 78 } -
code/branches/physics/src/orxonox/objects/worldentities/StaticEntity.cc
r2374 r2423 60 60 void StaticEntity::setPosition(const Vector3& position) 61 61 { 62 if (this-> isPhysicsRunning())62 if (this->addedToPhysicalWorld()) 63 63 ThrowException(PhysicsViolation, "Cannot change position or orientation of a StaticEntity with physics at run time."); 64 64 if (this->isStatic()) … … 74 74 void StaticEntity::translate(const Vector3& distance, Ogre::Node::TransformSpace relativeTo) 75 75 { 76 if (this-> isPhysicsRunning())76 if (this->addedToPhysicalWorld()) 77 77 ThrowException(PhysicsViolation, "Cannot change position or orientation of a StaticEntity with physics at run time."); 78 78 if (this->isStatic()) … … 88 88 void StaticEntity::setOrientation(const Quaternion& orientation) 89 89 { 90 if (this-> isPhysicsRunning())90 if (this->addedToPhysicalWorld()) 91 91 ThrowException(PhysicsViolation, "Cannot change position or orientation of a StaticEntity with physics at run time."); 92 92 if (this->isStatic()) … … 102 102 void StaticEntity::rotate(const Quaternion& rotation, Ogre::Node::TransformSpace relativeTo) 103 103 { 104 if (this-> isPhysicsRunning())104 if (this->addedToPhysicalWorld()) 105 105 ThrowException(PhysicsViolation, "Cannot change position or orientation of a StaticEntity with physics at run time."); 106 106 if (this->isStatic()) … … 117 117 void StaticEntity::yaw(const Degree& angle, Ogre::Node::TransformSpace relativeTo) 118 118 { 119 if (this-> isPhysicsRunning())119 if (this->addedToPhysicalWorld()) 120 120 ThrowException(PhysicsViolation, "Cannot change position or orientation of a StaticEntity with physics at run time."); 121 121 if (this->isStatic()) … … 133 133 void StaticEntity::pitch(const Degree& angle, Ogre::Node::TransformSpace relativeTo) 134 134 { 135 if (this-> isPhysicsRunning())135 if (this->addedToPhysicalWorld()) 136 136 ThrowException(PhysicsViolation, "Cannot change position or orientation of a StaticEntity with physics at run time."); 137 137 if (this->isStatic()) … … 149 149 void StaticEntity::roll(const Degree& angle, Ogre::Node::TransformSpace relativeTo) 150 150 { 151 if (this-> isPhysicsRunning())151 if (this->addedToPhysicalWorld()) 152 152 ThrowException(PhysicsViolation, "Cannot change position or orientation of a StaticEntity with physics at run time."); 153 153 if (this->isStatic()) … … 165 165 void StaticEntity::lookAt(const Vector3& target, Ogre::Node::TransformSpace relativeTo, const Vector3& localDirectionVector) 166 166 { 167 if (this-> isPhysicsRunning())167 if (this->addedToPhysicalWorld()) 168 168 ThrowException(PhysicsViolation, "Cannot change position or orientation of a StaticEntity with physics at run time."); 169 169 if (this->isStatic()) … … 179 179 void StaticEntity::setDirection(const Vector3& direction, Ogre::Node::TransformSpace relativeTo, const Vector3& localDirectionVector) 180 180 { 181 if (this-> isPhysicsRunning())181 if (this->addedToPhysicalWorld()) 182 182 ThrowException(PhysicsViolation, "Cannot change position or orientation of a StaticEntity with physics at run time."); 183 183 if (this->isStatic()) -
code/branches/physics/src/orxonox/objects/worldentities/WorldEntity.cc
r2408 r2423 33 33 #include <cassert> 34 34 #include <OgreSceneManager.h> 35 36 #include "BulletCollision/CollisionShapes/btCollisionShape.h"37 #include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"38 35 #include "BulletDynamics/Dynamics/btRigidBody.h" 39 36 … … 44 41 45 42 #include "objects/Scene.h" 46 #include "objects/collisionshapes/CollisionShape.h"47 43 #include "objects/collisionshapes/CompoundCollisionShape.h" 48 44 … … 73 69 // Default behaviour does not include physics 74 70 this->physicalBody_ = 0; 71 this->bPhysicsActive_ = false; 75 72 this->collisionShape_ = new CompoundCollisionShape(this); 76 73 this->mass_ = 0; 77 this->child Mass_ = 0;74 this->childrenMass_ = 0; 78 75 this->collisionType_ = None; 79 76 this->collisionTypeSynchronised_ = None; … … 90 87 this->getScene()->getSceneManager()->destroySceneNode(this->node_->getName()); 91 88 89 // TODO: Detach from parent and detach all children. 90 92 91 if (this->physicalBody_) 93 92 { 94 if (this->physicalBody_->isInWorld()) 95 this->getScene()->getPhysicalWorld()->removeRigidBody(this->physicalBody_); 93 this->deactivatePhysics(); 96 94 delete this->physicalBody_; 97 95 } 98 // TODO: Delete collisionShapes96 delete this->collisionShape_; 99 97 } 100 98 } … … 129 127 REGISTERDATA(this->bVisible_, network::direction::toclient, new network::NetworkCallback<WorldEntity>(this, &WorldEntity::changedVisibility)); 130 128 131 // HACK: Removed the call because it gets called the first time as well 132 REGISTERDATA(this->getScale3D(), network::direction::toclient);//, new network::NetworkCallback<WorldEntity>(this, &WorldEntity::scaleChanged)); 133 134 int* collisionType = (int*)&this->collisionTypeSynchronised_; 135 REGISTERDATA(*collisionType, network::direction::toclient, new network::NetworkCallback<WorldEntity>(this, &WorldEntity::collisionTypeChanged)); 136 REGISTERDATA(this->mass_, network::direction::toclient, new network::NetworkCallback<WorldEntity>(this, &WorldEntity::massChanged)); 137 138 REGISTERDATA(this->parentID_, network::direction::toclient, new network::NetworkCallback<WorldEntity>(this, &WorldEntity::updateParent)); 129 REGISTERDATA(this->getScale3D(), network::direction::toclient, new network::NetworkCallback<WorldEntity>(this, &WorldEntity::scaleChanged)); 130 131 REGISTERDATA((int&)this->collisionTypeSynchronised_, 132 network::direction::toclient, new network::NetworkCallback<WorldEntity>(this, &WorldEntity::collisionTypeChanged)); 133 REGISTERDATA(this->mass_, network::direction::toclient, new network::NetworkCallback<WorldEntity>(this, &WorldEntity::massChanged)); 134 REGISTERDATA(this->bPhysicsActiveSynchronised_, 135 network::direction::toclient, new network::NetworkCallback<WorldEntity>(this, &WorldEntity::physicsActivityChanged)); 136 137 REGISTERDATA(this->parentID_, network::direction::toclient, new network::NetworkCallback<WorldEntity>(this, &WorldEntity::updateParent)); 139 138 } 140 139 … … 167 166 { 168 167 this->setMass(this->mass_); 168 } 169 170 void WorldEntity::physicsActivityChanged() 171 { 172 if (this->bPhysicsActiveSynchronised_) 173 this->activatePhysics(); 174 else 175 this->deactivatePhysics(); 169 176 } 170 177 … … 184 191 else 185 192 { 186 if (this->physicalBody_->isInWorld()) 187 removeFromPhysicalWorld(); 188 if (object->physicalBody_->isInWorld()) 189 this->getScene()->removeRigidBody(object->physicalBody_); 190 191 // static to static/kinematic/dynamic --> merge shapes 192 this->childMass_ += object->getMass(); 193 this->attachCollisionShape(object->getCollisionShape(), true); 194 // Remove the btRigidBody from the child object. 195 // That also implies that cannot add a physics WE to the child afterwards. 196 object->setCollisionType(None); 197 198 addToPhysicalWorld(); 193 object->deactivatePhysics(); 199 194 } 200 195 } … … 213 208 object->parent_ = this; 214 209 object->parentID_ = this->getObjectID(); 210 211 // collision shapes 212 this->attachCollisionShape(object->getCollisionShape()); 213 // mass 214 this->childrenMass_ += object->getMass(); 215 recalculatePhysicsProps(); 215 216 } 216 217 217 218 void WorldEntity::detach(WorldEntity* object) 218 219 { 220 // collision shapes 221 this->detachCollisionShape(object->getCollisionShape()); 222 // mass 223 if (object->getMass() > 0.0f) 224 { 225 this->childrenMass_ -= object->getMass(); 226 recalculatePhysicsProps(); 227 } 228 219 229 this->node_->removeChild(object->node_); 220 230 this->children_.erase(object); 221 231 object->parent_ = 0; 222 232 object->parentID_ = (unsigned int)-1; 223 224 233 // this->getScene()->getRootSceneNode()->addChild(object->node_); 234 235 // Note: It is possible that the object has physics but was disabled when attaching 236 object->activatePhysics(); 225 237 } 226 238 … … 237 249 } 238 250 239 void WorldEntity::attachCollisionShape(CollisionShape* shape, bool bWorldEntityRoot) 240 { 241 this->collisionShape_->addChildShape(shape, bWorldEntityRoot); 242 243 if (this->physicalBody_) 244 { 245 if (this->physicalBody_->isInWorld()) 246 { 247 COUT(2) << "Warning: Attaching collision shapes at run time causes its physical body to be removed and added again."; 248 removeFromPhysicalWorld(); 249 } 250 if (this->collisionShape_->getCollisionShape()) 251 this->physicalBody_->setCollisionShape(this->collisionShape_->getCollisionShape()); 252 // recalculate inertia tensor 253 internalSetMassProps(); 254 addToPhysicalWorld(); 255 } 251 void WorldEntity::attachCollisionShape(CollisionShape* shape) 252 { 253 this->collisionShape_->addChildShape(shape); 254 // Note: this->collisionShape_ already notifies us of any changes. 255 } 256 257 void WorldEntity::detachCollisionShape(CollisionShape* shape) 258 { 259 this->collisionShape_->removeChildShape(shape); 260 // Note: this->collisionShape_ already notifies us of any changes. 256 261 } 257 262 … … 261 266 } 262 267 263 void WorldEntity::addToPhysicalWorld() const 264 { 265 if (this->isActive() && this->hasPhysics() && !this->physicalBody_->isInWorld()) 268 void WorldEntity::activatePhysics() 269 { 270 if (this->isActive() && this->hasPhysics() && !this->isPhysicsActive() && !this->parent_) 271 { 266 272 this->getScene()->addRigidBody(this->physicalBody_); 267 } 268 269 void WorldEntity::removeFromPhysicalWorld() const 270 { 271 if (this->hasPhysics()) 273 this->bPhysicsActive_ = true; 274 } 275 } 276 277 void WorldEntity::deactivatePhysics() 278 { 279 if (this->isPhysicsActive()) 280 { 272 281 this->getScene()->removeRigidBody(this->physicalBody_); 282 this->bPhysicsActive_ = false; 283 } 284 } 285 286 bool WorldEntity::addedToPhysicalWorld() const 287 { 288 return this->physicalBody_ && this->physicalBody_->isInWorld(); 273 289 } 274 290 … … 292 308 { 293 309 this->mass_ = mass; 294 if (!this->hasPhysics()) 295 return; 296 // TODO: Add this again when new network callbacks work properly 297 //COUT(3) << "Warning: Setting the mass of a WorldEntity with no physics has no effect." << std::endl; 298 else 299 { 300 if (this->physicalBody_->isInWorld()) 301 { 302 COUT(2) << "Warning: Setting the mass of a WorldEntity at run time causes its physical body to be removed and added again." << std::endl; 303 removeFromPhysicalWorld(); 304 } 305 internalSetMassProps(); 306 } 307 308 addToPhysicalWorld(); 309 } 310 311 void WorldEntity::internalSetMassProps() 312 { 313 assert(hasPhysics()); 314 315 if (this->isStatic()) 316 { 317 // Just set everything to zero 318 this->physicalBody_->setMassProps(0.0f, btVector3(0, 0, 0)); 319 } 320 else if ((this->mass_ + this->childMass_) == 0.0f) 321 { 322 // Use default values to avoid very large or very small values 323 CCOUT(2) << "Warning: Setting the internal physical mass to 1.0 because mass_ is 0.0." << std::endl; 324 this->physicalBody_->setMassProps(1.0f, this->getLocalInertia(1.0f)); 325 } 326 else 327 this->physicalBody_->setMassProps(this->mass_, this->getLocalInertia(this->mass_ + this->childMass_)); 328 } 329 330 btVector3 WorldEntity::getLocalInertia(btScalar mass) const 331 { 332 btVector3 inertia(0, 0, 0); 333 if (this->collisionShape_->getCollisionShape()) 334 this->collisionShape_->getCollisionShape()->calculateLocalInertia(mass, inertia); 335 return inertia; 310 recalculatePhysicsProps(); 336 311 } 337 312 … … 341 316 if (this->parent_) 342 317 ThrowException(PhysicsViolation, "Cannot set the collision type of a WorldEntity with a parent"); 343 else if (this-> physicalBody_ && this->physicalBody_->isInWorld())318 else if (this->addedToPhysicalWorld()) 344 319 ThrowException(PhysicsViolation, "Warning: Cannot set the collision type at run time."); 345 320 … … 357 332 // Create new rigid body 358 333 btCollisionShape* temp = 0; 359 if (this->collisionShape_) 360 temp = this->collisionShape_->getCollisionShape(); 361 btRigidBody::btRigidBodyConstructionInfo bodyConstructionInfo(0, this, temp, btVector3(0,0,0)); 334 btRigidBody::btRigidBodyConstructionInfo bodyConstructionInfo(0, this, this->collisionShape_->getCollisionShape()); 335 bodyConstructionInfo.m_restitution = 1; 362 336 this->physicalBody_ = new btRigidBody(bodyConstructionInfo); 363 337 this->physicalBody_->setUserPointer(this); … … 368 342 // Destroy rigid body 369 343 assert(this->physicalBody_); 370 removeFromPhysicalWorld();344 deactivatePhysics(); 371 345 delete this->physicalBody_; 372 346 this->physicalBody_ = 0; … … 392 366 } 393 367 394 // update our variable for faster checks 368 // Only sets this->collisionShape_ 369 // However the assertion is to ensure that the internal bullet setting is right 395 370 updateCollisionType(); 396 371 assert(this->collisionType_ == type); 397 372 398 373 // update mass and inertia tensor 399 internalSetMassProps(); // type is not None! See case None in switch 400 401 addToPhysicalWorld(); 374 recalculatePhysicsProps(); 375 activatePhysics(); 402 376 } 403 377 … … 450 424 } 451 425 452 bool WorldEntity::isPhysicsRunning() const 453 { 454 return this->physicalBody_ && this->physicalBody_->isInWorld(); 455 } 456 457 bool WorldEntity::checkPhysics() const 458 { 459 if (!this->physicalBody_) 460 { 461 assert(this->getCollisionType() == None); 462 COUT(2) << "WorldEntity was not fitted with physics, cannot set phyiscal property." << std::endl; 463 return false; 464 } 465 else 466 return true; 426 void WorldEntity::notifyChildMassChanged() // Called by a child WE 427 { 428 // Note: CollisionShape changes of a child get handled over the internal CompoundCollisionShape already 429 // Recalculate mass 430 this->childrenMass_ = 0.0f; 431 for (std::set<WorldEntity*>::const_iterator it = this->children_.begin(); it != this->children_.end(); ++it) 432 this->childrenMass_ += (*it)->getMass(); 433 recalculatePhysicsProps(); 434 // Notify parent WE 435 if (this->parent_) 436 parent_->notifyChildMassChanged(); 437 } 438 439 void WorldEntity::notifyCollisionShapeChanged() // called by this->collisionShape_ 440 { 441 if (hasPhysics()) 442 { 443 // Bullet doesn't like sudden changes of the collision shape, so we remove and add it again 444 if (this->addedToPhysicalWorld()) 445 { 446 this->deactivatePhysics(); 447 this->physicalBody_->setCollisionShape(this->collisionShape_->getCollisionShape()); 448 this->activatePhysics(); 449 } 450 else 451 this->physicalBody_->setCollisionShape(this->collisionShape_->getCollisionShape()); 452 } 453 recalculatePhysicsProps(); 454 } 455 456 void WorldEntity::recalculatePhysicsProps() 457 { 458 if (this->hasPhysics()) 459 { 460 if (this->isStatic()) 461 { 462 // Just set everything to zero 463 this->physicalBody_->setMassProps(0.0f, btVector3(0, 0, 0)); 464 } 465 else if ((this->mass_ + this->childrenMass_) == 0.0f) 466 { 467 // Use default values to avoid very large or very small values 468 CCOUT(4) << "Warning: Setting the internal physical mass to 1.0 because mass_ is 0.0." << std::endl; 469 this->physicalBody_->setMassProps(1.0f, this->collisionShape_->getLocalInertia(1.0f)); 470 } 471 else 472 { 473 float mass = this->mass_ + this->childrenMass_; 474 this->physicalBody_->setMassProps(mass, this->collisionShape_->getLocalInertia(mass)); 475 } 476 } 467 477 } 468 478 } -
code/branches/physics/src/orxonox/objects/worldentities/WorldEntity.h
r2407 r2423 35 35 #define OGRE_FORCE_ANGLE_TYPES 36 36 #include <OgreSceneNode.h> 37 38 37 #include "LinearMath/btMotionState.h" 39 38 … … 126 125 127 126 void attach(WorldEntity* object); 128 // void attachAsdf(BlinkingBillboard* object);129 127 void detach(WorldEntity* object); 130 128 WorldEntity* getAttachedObject(unsigned int index) const; 131 // BlinkingBillboard* getAttachedAsdfObject(unsigned int index) const;132 129 inline const std::set<WorldEntity*>& getAttachedObjects() const 133 130 { return this->children_; } … … 146 143 inline WorldEntity* getParent() const 147 144 { return this->parent_; } 145 146 void notifyChildPropsChanged(); 148 147 149 148 protected: … … 185 184 }; 186 185 187 bool hasPhysics() const { return getCollisionType() != None ; } 188 bool isStatic() const { return getCollisionType() == Static ; } 189 bool isKinematic() const { return getCollisionType() == Kinematic; } 190 bool isDynamic() const { return getCollisionType() == Dynamic ; } 191 bool isPhysicsRunning() const; 186 bool hasPhysics() const { return getCollisionType() != None ; } 187 bool isStatic() const { return getCollisionType() == Static ; } 188 bool isKinematic() const { return getCollisionType() == Kinematic; } 189 bool isDynamic() const { return getCollisionType() == Dynamic ; } 190 bool isPhysicsActive() const { return this->bPhysicsActive_; } 191 bool addedToPhysicalWorld() const; 192 193 void activatePhysics(); 194 void deactivatePhysics(); 192 195 193 196 inline CollisionType getCollisionType() const … … 201 204 inline float getMass() const 202 205 { return this->mass_; } 203 204 void attachCollisionShape(CollisionShape* shape, bool bWorldEntityRoot = false); 206 inline float getTotalMass() const 207 { return this->mass_ + this->childrenMass_; } 208 209 void attachCollisionShape(CollisionShape* shape); 210 void detachCollisionShape(CollisionShape* shape); 205 211 CollisionShape* getAttachedCollisionShape(unsigned int index) const; 206 212 … … 210 216 { return this->physicalBody_; } 211 217 218 void notifyCollisionShapeChanged(); 219 void notifyChildMassChanged(); 220 212 221 protected: 213 222 virtual bool isCollisionTypeLegal(CollisionType type) const = 0; … … 217 226 private: 218 227 void updateCollisionType(); 219 void mergeCollisionShape(CollisionShape* shape); 220 void internalSetMassProps(); 221 btVector3 getLocalInertia(btScalar mass) const; 222 bool checkPhysics() const; 223 void addToPhysicalWorld() const; 224 void removeFromPhysicalWorld() const; 228 void recalculatePhysicsProps(); 225 229 226 230 // network callbacks 227 231 void collisionTypeChanged(); 228 232 void massChanged(); 233 void physicsActivityChanged(); 229 234 230 235 CollisionType collisionType_; 231 236 CollisionType collisionTypeSynchronised_; 237 bool bPhysicsActive_; 238 bool bPhysicsActiveSynchronised_; 232 239 CompoundCollisionShape* collisionShape_; 233 240 btScalar mass_; 234 btScalar child Mass_;241 btScalar childrenMass_; 235 242 }; 236 243 }
Note: See TracChangeset
for help on using the changeset viewer.