Changeset 2423 for code/branches/physics/src/orxonox/objects/collisionshapes/CompoundCollisionShape.cc
- Timestamp:
- Dec 13, 2008, 4:14:36 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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 }
Note: See TracChangeset
for help on using the changeset viewer.