- Timestamp:
- Dec 13, 2008, 4:14:36 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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 }
Note: See TracChangeset
for help on using the changeset viewer.