- Timestamp:
- Dec 1, 2008, 11:09:43 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
code/branches/physics/src/orxonox/objects/worldentities/WorldEntity.cc
r2300 r2303 33 33 #include <OgreSceneManager.h> 34 34 35 #include "BulletCollision/CollisionShapes/btSphereShape.h" 35 #include "BulletCollision/CollisionShapes/btCollisionShape.h" 36 #include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" 37 #include "BulletDynamics/Dynamics/btRigidBody.h" 36 38 37 39 #include "util/Exception.h" … … 41 43 42 44 #include "objects/Scene.h" 45 #include "objects/worldentities/collisionshapes/CollisionShape.h" 46 #include "objects/worldentities/collisionshapes/CompoundCollisionShape.h" 43 47 44 48 namespace orxonox … … 68 72 // Default behaviour does not include physics 69 73 this->physicalBody_ = 0; 74 this->collisionShape_ = 0; 75 this->mass_ = 0; 70 76 updateCollisionType(); 71 77 … … 100 106 101 107 XMLPortParam(WorldEntity, "collisionType", setCollisionTypeStr, getCollisionTypeStr, xmlelement, mode); 102 XMLPortParam(WorldEntity, "collisionRadius", setCollisionRadius, getCollisionRadius, xmlelement, mode);108 //XMLPortParam(WorldEntity, "collisionRadius", setCollisionRadius, getCollisionRadius, xmlelement, mode); 103 109 XMLPortParam(WorldEntity, "mass", setMass, getMass, xmlelement, mode); 104 110 105 111 XMLPortObject(WorldEntity, WorldEntity, "attached", attach, getAttachedObject, xmlelement, mode); 106 107 // Add the physical after loading because we cannot change its attributes without removing. 108 if (getCollisionType() != None) 109 this->getScene()->getPhysicalWorld()->addRigidBody(this->physicalBody_); 112 XMLPortObject(WorldEntity, CollisionShape, "collisionShapes", attachCollisionShape, getAttachedCollisionShape, xmlelement, mode); 110 113 } 111 114 … … 131 134 void WorldEntity::attach(WorldEntity* object) 132 135 { 136 // check first whether attaching is even allowed 137 if (object->hasPhysics()) 138 { 139 if (!this->hasPhysics()) 140 ThrowException(PhysicsViolation, "Cannot attach a physical object to a non physical one."); 141 else if (object->isDynamic()) 142 ThrowException(PhysicsViolation, "Cannot attach a dynamic object to a WorldEntity."); 143 else if (object->isKinematic() && this->isDynamic()) 144 ThrowException(PhysicsViolation, "Cannot attach a kinematic object to a dynamic one."); 145 else if (object->isKinematic()) 146 ThrowException(NotImplemented, "Cannot attach a kinematic object to a static or kinematic one: Not yet implemented."); 147 else if (object->physicalBody_->isInWorld() || this->physicalBody_->isInWorld()) 148 ThrowException(PhysicsViolation, "Cannot attach a physical object at runtime."); 149 else 150 { 151 // static to static/kinematic/dynamic --> merge shapes 152 this->attachCollisionShape(object->getCollisionShape()); 153 // Remove the btRigidBody from the child object. 154 // That also implies that cannot add a physics WE to the child afterwards. 155 object->setCollisionType(None); 156 } 157 } 158 133 159 if (object->getParent()) 134 160 object->detachFromParent(); … … 144 170 object->parent_ = this; 145 171 object->parentID_ = this->getObjectID(); 146 147 // Do the physical connection if required 148 //this->attachPhysicalObject(object); 149 } 150 151 //void WorldEntity::attachPhysicalObject(WorldEntity* object) 152 //{ 153 // StaticEntity* staticObject = dynamic_cast<StaticEntity*>(object); 154 // if (staticObject != 0 && this->hasPhysics()) 155 // { 156 // btCompoundShape* compoundShape = dynamic_cast<btCompoundShape*>(this->physicalBody_->getCollisionShape()); 157 // if (compoundShape == 0) 158 // { 159 // // create a compound shape and add both 160 // compoundShape = new btCompoundShape(); 161 // compoundShape->addChildShape(this->physicalBody_->getCollisionShape()); 162 // compoundShape->addChildShape(staticObject->getCollisionShape()); 163 // this->physicalBody_->setCollisionShape(); 164 // } 165 // else 166 // { 167 // compoundShape -> addChildShape(staticObject->getCollisionShape()); 168 // } 169 // } 170 //} 172 } 171 173 172 174 void WorldEntity::detach(WorldEntity* object) … … 192 194 } 193 195 194 float WorldEntity::getMass() const 195 { 196 if (!checkPhysics()) 197 return 0.0f; 198 199 if (this->physicalBody_->getInvMass() == 0.0f) 200 return 0.0f; 201 else 202 return 1.0f/this->physicalBody_->getInvMass(); 196 void WorldEntity::mergeCollisionShape(CollisionShape* shape) 197 { 198 if (!this->collisionShape_) 199 this->collisionShape_ = new CompoundCollisionShape(this); 200 assert(this->collisionShape_->isCompoundShape()); 201 202 // merge with transform 203 CompoundCollisionShape* compoundShape = static_cast<CompoundCollisionShape*>(this->collisionShape_); 204 assert(compoundShape); 205 compoundShape->addChildShape(shape); 206 } 207 208 void WorldEntity::attachCollisionShape(CollisionShape* shape) 209 { 210 this->attachedShapes_.push_back(shape); 211 212 if (!this->collisionShape_ && shape->hasNoTransform()) 213 { 214 // Simply add the shape as is. 215 shape->getCollisionShape()->setLocalScaling(shape->getTotalScaling()); 216 this->collisionShape_ = shape; 217 } 218 else 219 { 220 if (this->collisionShape_ && !this->collisionShape_->isCompoundShape()) 221 { 222 // We have to create a new compound shape and add the old one first. 223 CollisionShape* thisShape = this->collisionShape_; 224 this->collisionShape_ = 0; 225 this->mergeCollisionShape(thisShape); 226 } 227 this->mergeCollisionShape(shape); 228 } 229 230 if (this->physicalBody_) 231 { 232 if (this->physicalBody_->isInWorld()) 233 COUT(2) << "Warning: Cannot attach a physical object at runtime."; 234 else 235 this->physicalBody_->setCollisionShape(this->collisionShape_->getCollisionShape()); 236 } 237 } 238 239 CollisionShape* WorldEntity::getAttachedCollisionShape(unsigned int index) const 240 { 241 if (index < this->attachedShapes_.size()) 242 return attachedShapes_[index]; 243 else 244 return 0; 245 } 246 247 //BlinkingBillboard* WorldEntity::getAttachedAsdfObject(unsigned int index) const 248 //{ 249 // return 0; 250 //} 251 252 void WorldEntity::setScale3D(const Vector3& scale) 253 { 254 if (this->hasPhysics()) 255 ThrowException(NotImplemented, "Cannot set the scale of a physical object: Not yet implemented."); 256 257 this->node_->setScale(scale); 258 } 259 260 void WorldEntity::scale3D(const Vector3& scale) 261 { 262 if (this->hasPhysics()) 263 ThrowException(NotImplemented, "Cannot set the scale of a physical object: Not yet implemented."); 264 265 this->node_->scale(scale); 203 266 } 204 267 205 268 void WorldEntity::setMass(float mass) 206 269 { 207 if (!checkPhysics()) 208 return; 270 this->mass_ = mass; 271 if (!hasPhysics()) 272 COUT(2) << "Warning: Setting the mass of a WorldEntity with no physics has no effect." << std::endl; 209 273 else if (this->physicalBody_->isInWorld()) 210 { 211 CCOUT(2) << "Cannot set the physical mass at run time." << std::endl; 212 assert(false); 213 } 214 else 215 { 216 this->physicalBody_->setMassProps(mass, btVector3(0,0,0)); 217 updateCollisionType(); 274 COUT(2) << "Warning: Cannot set the physical mass at run time. Storing temporarily." << std::endl; 275 else 276 { 277 if (this->collisionType_ != Dynamic) 278 COUT(2) << "Warning: Cannot set the physical mass of a static or kinematic object. Storing temporarily." << std::endl; 279 else if (mass == 0.0f) 280 COUT(2) << "Warning: Cannot set physical mass of a dynamic object to zero. Storing temporarily." << std::endl; 281 else 282 this->physicalBody_->setMassProps(mass, btVector3(0,0,0)); 218 283 } 219 284 } … … 221 286 void WorldEntity::setCollisionType(CollisionType type) 222 287 { 223 // Check first whether we have to create or destroy. 288 // If we are already attached to a parent, this would be a bad idea.. 289 if (this->parent_) 290 ThrowException(PhysicsViolation, "Cannot set the collision type of a WorldEntity with a parent"); 291 else if (this->physicalBody_ && this->physicalBody_->isInWorld()) 292 ThrowException(PhysicsViolation, "Warning: Cannot set the collision type at run time."); 293 294 // Check for type legality. Could be StaticEntity or MovableEntity 295 if (!this->isCollisionTypeLegal(type)) 296 return; // exception gets issued anyway 297 298 // Check whether we have to create or destroy. 224 299 if (type != None && this->collisionType_ == None) 225 300 { 226 // First, check whether our SceneNode is relative to the root space of the scene.227 // TODO: Static and Kinematic objects don't always have to obey this rule.228 if (this->node_->getParent() != this->getScene()->getRootSceneNode())229 ThrowException(PhysicsViolation, "Cannot make WorldEntity physical that is not in the root space of the Scene.");230 231 301 // Create new rigid body 232 btRigidBody::btRigidBodyConstructionInfo bodyConstructionInfo(0, this, 0, btVector3(0,0,0)); 302 btCollisionShape* temp = 0; 303 if (this->collisionShape_) 304 temp = this->collisionShape_->getCollisionShape(); 305 btRigidBody::btRigidBodyConstructionInfo bodyConstructionInfo(0, this, temp, btVector3(0,0,0)); 233 306 this->physicalBody_ = new btRigidBody(bodyConstructionInfo); 234 307 this->physicalBody_->setUserPointer(this); 235 236 // Adjust parameters according to the node237 //btTransform nodeTransform;238 //this->239 308 } 240 309 else if (type == None && this->collisionType_ != None) … … 243 312 if (this->physicalBody_->isInWorld()) 244 313 this->getScene()->getPhysicalWorld()->removeRigidBody(this->physicalBody_); 245 if (this->physicalBody_->getCollisionShape())246 delete this->physicalBody_->getCollisionShape();247 314 delete this->physicalBody_; 248 315 this->physicalBody_ = 0; … … 250 317 return; 251 318 } 252 253 // Check for type legality. Could be StaticEntity or MovableEntity254 if (!this->isCollisionTypeLegal(type))255 return; // exception gets issued anyway256 319 257 320 // Change type … … 271 334 } 272 335 336 // update our variable for faster checks 337 updateCollisionType(); 338 273 339 // Mass non zero is a bad idea for kinematic and static objects 274 if ((type == Kinematic || type == Static) && getMass()!= 0.0f)340 if ((type == Kinematic || type == Static) && this->mass_ != 0.0f) 275 341 this->setMass(0.0f); 276 342 // Mass zero is not such a good idea for dynamic objects 277 else if (type == Dynamic && getMass()== 0.0f)343 else if (type == Dynamic && this->mass_ == 0.0f) 278 344 this->setMass(1.0f); 279 280 // finally update our variable for faster checks 281 updateCollisionType(); 345 else if (hasPhysics()) 346 this->physicalBody_->setMassProps(this->mass_, btVector3(0,0,0)); 282 347 } 283 348 … … 329 394 } 330 395 331 void WorldEntity::setCollisionRadius(float radius) 332 { 333 if (!checkPhysics()) 334 return; 335 336 // destroy old one first 337 btCollisionShape* oldShape = this->physicalBody_->getCollisionShape(); 338 if (oldShape) 339 delete oldShape; 340 341 this->physicalBody_->setCollisionShape(new btSphereShape(btScalar(radius))); 342 } 343 344 float WorldEntity::getCollisionRadius() const 345 { 346 if (checkPhysics()) 347 { 348 btSphereShape* sphere = dynamic_cast<btSphereShape*>(this->physicalBody_->getCollisionShape()); 349 if (sphere) 350 return (float)sphere->getRadius(); 351 } 352 return 0.0f; 353 } 396 //void WorldEntity::setCollisionRadius(float radius) 397 //{ 398 // if (!checkPhysics()) 399 // return; 400 401 // // destroy old one first 402 // btCollisionShape* oldShape = this->physicalBody_->getCollisionShape(); 403 // if (oldShape) 404 // delete oldShape; 405 406 // //if (this->getName() == "blubb") 407 // //{ 408 // // btCompoundShape* cShape = new btCompoundShape(); 409 // // cShape->setLocalScaling(btVector3(1,1,1)); 410 // // btTransform offset(btQuaternion(0, 0, 0), btVector3(0, 0, 0)); 411 // // offset.setBasis(btMatrix3x3(3, 0, 0, 0, 3, 0, 0, 0, 3)); 412 // // btSphereShape* sphere = new btSphereShape(radius); 413 // // sphere->setLocalScaling(btVector3(1,1,3)); 414 // // cShape->addChildShape(offset, sphere); 415 // // this->physicalBody_->setCollisionShape(cShape); 416 // //} 417 // //else 418 // this->physicalBody_->setCollisionShape(new btSphereShape(btScalar(radius))); 419 //} 420 421 //float WorldEntity::getCollisionRadius() const 422 //{ 423 // if (checkPhysics()) 424 // { 425 // btSphereShape* sphere = dynamic_cast<btSphereShape*>(this->physicalBody_->getCollisionShape()); 426 // if (sphere) 427 // return (float)sphere->getRadius(); 428 // } 429 // return 0.0f; 430 //} 354 431 355 432 bool WorldEntity::checkPhysics() const
Note: See TracChangeset
for help on using the changeset viewer.