Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Dec 13, 2008, 4:14:36 PM (15 years ago)
Author:
rgrieder
Message:
  • Added detach functions to CollisionShapes
  • Added update functions across the CollisionShape hierarchy so that when you change the radius of a sphere, everything up to the WE gets updated.
  • Setting the btCollisionShape at run time doesn't work after all, fixed that (you can still do it, just a question of internals)
  • Improved network synchronisation
  • new WE function: addedToPhysicalWorld() to check whether we can still perform operations that are disallowed at run time (esp. StaticEntity)

Conclusively, I can say that right now, all operations considering physics should be handled automatically, bugs not withstanding.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • code/branches/physics/src/orxonox/objects/collisionshapes/CompoundCollisionShape.cc

    r2407 r2423  
    3232#include "BulletCollision/CollisionShapes/btCompoundShape.h"
    3333
     34#include "util/Exception.h"
    3435#include "core/CoreIncludes.h"
    3536#include "core/XMLPort.h"
    3637#include "tools/BulletConversions.h"
     38#include "objects/worldentities/WorldEntity.h"
    3739
    3840namespace orxonox
     
    5052    {
    5153        if (this->isInitialized())
     54        {
     55            // Detatch all children first
     56            this->removeAllChildShapes();
    5257            delete this->compoundShape_;
     58        }
    5359    }
    5460
     
    6066    }
    6167
    62     btCollisionShape* CompoundCollisionShape::getCollisionShape() const
     68    void CompoundCollisionShape::addChildShape(CollisionShape* shape)
    6369    {
    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)
    7771            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();
    7978
    8079        if (shape->getCollisionShape())
     
    8483            this->compoundShape_->addChildShape(transf, shape->getCollisionShape());
    8584
    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();
    9686        }
    9787
    9888        // 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        }
    101179    }
    102180
    103181    CollisionShape* CompoundCollisionShape::getChildShape(unsigned int index) const
    104182    {
    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;
    109191    }
    110192}
Note: See TracChangeset for help on using the changeset viewer.