Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Changeset 2423


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.

Location:
code/branches/physics/src/orxonox
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • code/branches/physics/src/orxonox/OrxonoxPrereqs.h

    r2408 r2423  
    212212// Bullet Physics Engine
    213213
     214class btTransform;
     215class btVector3;
     216
    214217class btRigidBody;
    215218class btCollisionObject;
  • code/branches/physics/src/orxonox/OrxonoxStableHeaders.h

    r2192 r2423  
    103103//#endif /* ifdef NDEBUG */
    104104
    105 #endif /* ORXONOX_COMPILER == ORXONOX_COMPILER_MSVC && !defined(ORXONOX_DISABLE_PCH) */
     105#endif /* defined(ORXONOX_ENABLE_PCH) */
    106106
    107107#endif /* _OrxonoxStableHeaders_H__ */
  • code/branches/physics/src/orxonox/objects/collisionshapes/CollisionShape.cc

    r2403 r2423  
    7676    void CollisionShape::registerVariables()
    7777    {
    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);
    7986    }
    8087
    8188    void CollisionShape::updateParent()
    8289    {
    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);
    8692    }
    8793
     
    95101    {
    96102        ThrowException(NotImplemented, "Cannot set the scale of a collision shape: Not yet implemented.");
     103        this->updateParent();
    97104    }
    98105
     
    100107    {
    101108        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;
    102118    }
    103119}
  • code/branches/physics/src/orxonox/objects/collisionshapes/CollisionShape.h

    r2377 r2423  
    3232#include "OrxonoxPrereqs.h"
    3333
     34#include "LinearMath/btVector3.h"
    3435#include "util/Math.h"
    3536#include "core/BaseObject.h"
     
    4849
    4950            inline void setPosition(const Vector3& position)
    50                 { this->position_ = position; }
     51                { this->position_ = position; this->updateParent(); }
    5152            inline const Vector3& getPosition() const
    5253                { return this->position_; }
    5354
    5455            inline void setOrientation(const Quaternion& orientation)
    55                 { this->orientation_ = orientation; }
     56                { this->orientation_ = orientation; this->updateParent(); }
    5657            inline const Quaternion& getOrientation() const
    5758                { return this->orientation_; }
    5859
    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)); }
    6263
    6364            virtual void setScale3D(const Vector3& scale);
     
    6667                { return this->scale_; }
    6768
    68             virtual inline btCollisionShape* getCollisionShape() const
     69            btVector3 getLocalInertia(float mass) const;
     70
     71            inline btCollisionShape* getCollisionShape() const
    6972                { return this->collisionShape_; }
    7073
     
    7578
    7679        protected:
    77             btCollisionShape* collisionShape_;
     80            virtual void updateParent();
     81
     82            btCollisionShape*       collisionShape_;
     83            CompoundCollisionShape* parent_;
    7884
    7985        private:
    80             void updateParent();
     86            void parentChanged();
    8187
    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_;
    8792    };
    8893}
  • 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}
  • code/branches/physics/src/orxonox/objects/collisionshapes/CompoundCollisionShape.h

    r2407 r2423  
    4545            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
    4646
    47             void addChildShape(CollisionShape* shape, bool bWorldEntityRoot = false);
     47            void addChildShape(CollisionShape* shape);
     48            void removeChildShape(CollisionShape* shape);
     49            void removeAllChildShapes();
    4850            CollisionShape* getChildShape(unsigned int index) const;
    4951
    50             virtual btCollisionShape* getCollisionShape() const;
     52            void updateChildShape(CollisionShape* shape);
    5153
    52             inline bool empty() const
    53                 { return this->childShapes_.size() == 0; }
     54        protected:
     55            virtual void updateParent();
    5456
    5557        private:
    56             btCompoundShape*             compoundShape_;
    57             std::vector<CollisionShape*> childShapes_;
     58            void updatePublicShape();
     59
     60            btCompoundShape* compoundShape_;
     61            std::map<CollisionShape*, btCollisionShape*> childShapes_;
    5862    };
    5963}
  • code/branches/physics/src/orxonox/objects/collisionshapes/PlaneCollisionShape.cc

    r2403 r2423  
    7474            delete this->collisionShape_;
    7575        this->collisionShape_ = new btStaticPlaneShape(omni_cast<btVector3>(this->normal_), this->offset_);
     76        this->updateParent();
    7677    }
    7778}
  • code/branches/physics/src/orxonox/objects/collisionshapes/SphereCollisionShape.cc

    r2403 r2423  
    7272        if (this->collisionShape_)
    7373            delete this->collisionShape_;
     74        // When we recreate the shape, we have to inform the parent about this to update the shape
    7475        this->collisionShape_ = new btSphereShape(this->radius_);
     76        this->updateParent();
    7577    }
    7678}
  • code/branches/physics/src/orxonox/objects/worldentities/StaticEntity.cc

    r2374 r2423  
    6060    void StaticEntity::setPosition(const Vector3& position)
    6161    {
    62         if (this->isPhysicsRunning())
     62        if (this->addedToPhysicalWorld())
    6363            ThrowException(PhysicsViolation, "Cannot change position or orientation of a StaticEntity with physics at run time.");
    6464        if (this->isStatic())
     
    7474    void StaticEntity::translate(const Vector3& distance, Ogre::Node::TransformSpace relativeTo)
    7575    {
    76         if (this->isPhysicsRunning())
     76        if (this->addedToPhysicalWorld())
    7777            ThrowException(PhysicsViolation, "Cannot change position or orientation of a StaticEntity with physics at run time.");
    7878        if (this->isStatic())
     
    8888    void StaticEntity::setOrientation(const Quaternion& orientation)
    8989    {
    90         if (this->isPhysicsRunning())
     90        if (this->addedToPhysicalWorld())
    9191            ThrowException(PhysicsViolation, "Cannot change position or orientation of a StaticEntity with physics at run time.");
    9292        if (this->isStatic())
     
    102102    void StaticEntity::rotate(const Quaternion& rotation, Ogre::Node::TransformSpace relativeTo)
    103103    {
    104         if (this->isPhysicsRunning())
     104        if (this->addedToPhysicalWorld())
    105105            ThrowException(PhysicsViolation, "Cannot change position or orientation of a StaticEntity with physics at run time.");
    106106        if (this->isStatic())
     
    117117    void StaticEntity::yaw(const Degree& angle, Ogre::Node::TransformSpace relativeTo)
    118118    {
    119         if (this->isPhysicsRunning())
     119        if (this->addedToPhysicalWorld())
    120120            ThrowException(PhysicsViolation, "Cannot change position or orientation of a StaticEntity with physics at run time.");
    121121        if (this->isStatic())
     
    133133    void StaticEntity::pitch(const Degree& angle, Ogre::Node::TransformSpace relativeTo)
    134134    {
    135         if (this->isPhysicsRunning())
     135        if (this->addedToPhysicalWorld())
    136136            ThrowException(PhysicsViolation, "Cannot change position or orientation of a StaticEntity with physics at run time.");
    137137        if (this->isStatic())
     
    149149    void StaticEntity::roll(const Degree& angle, Ogre::Node::TransformSpace relativeTo)
    150150    {
    151         if (this->isPhysicsRunning())
     151        if (this->addedToPhysicalWorld())
    152152            ThrowException(PhysicsViolation, "Cannot change position or orientation of a StaticEntity with physics at run time.");
    153153        if (this->isStatic())
     
    165165    void StaticEntity::lookAt(const Vector3& target, Ogre::Node::TransformSpace relativeTo, const Vector3& localDirectionVector)
    166166    {
    167         if (this->isPhysicsRunning())
     167        if (this->addedToPhysicalWorld())
    168168            ThrowException(PhysicsViolation, "Cannot change position or orientation of a StaticEntity with physics at run time.");
    169169        if (this->isStatic())
     
    179179    void StaticEntity::setDirection(const Vector3& direction, Ogre::Node::TransformSpace relativeTo, const Vector3& localDirectionVector)
    180180    {
    181         if (this->isPhysicsRunning())
     181        if (this->addedToPhysicalWorld())
    182182            ThrowException(PhysicsViolation, "Cannot change position or orientation of a StaticEntity with physics at run time.");
    183183        if (this->isStatic())
  • code/branches/physics/src/orxonox/objects/worldentities/WorldEntity.cc

    r2408 r2423  
    3333#include <cassert>
    3434#include <OgreSceneManager.h>
    35 
    36 #include "BulletCollision/CollisionShapes/btCollisionShape.h"
    37 #include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
    3835#include "BulletDynamics/Dynamics/btRigidBody.h"
    3936
     
    4441
    4542#include "objects/Scene.h"
    46 #include "objects/collisionshapes/CollisionShape.h"
    4743#include "objects/collisionshapes/CompoundCollisionShape.h"
    4844
     
    7369        // Default behaviour does not include physics
    7470        this->physicalBody_ = 0;
     71        this->bPhysicsActive_ = false;
    7572        this->collisionShape_ = new CompoundCollisionShape(this);
    7673        this->mass_ = 0;
    77         this->childMass_ = 0;
     74        this->childrenMass_ = 0;
    7875        this->collisionType_ = None;
    7976        this->collisionTypeSynchronised_ = None;
     
    9087                this->getScene()->getSceneManager()->destroySceneNode(this->node_->getName());
    9188
     89            // TODO: Detach from parent and detach all children.
     90
    9291            if (this->physicalBody_)
    9392            {
    94                 if (this->physicalBody_->isInWorld())
    95                     this->getScene()->getPhysicalWorld()->removeRigidBody(this->physicalBody_);
     93                this->deactivatePhysics();
    9694                delete this->physicalBody_;
    9795            }
    98             // TODO: Delete collisionShapes
     96            delete this->collisionShape_;
    9997        }
    10098    }
     
    129127        REGISTERDATA(this->bVisible_,    network::direction::toclient, new network::NetworkCallback<WorldEntity>(this, &WorldEntity::changedVisibility));
    130128
    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));
    139138    }
    140139
     
    167166    {
    168167        this->setMass(this->mass_);
     168    }
     169
     170    void WorldEntity::physicsActivityChanged()
     171    {
     172        if (this->bPhysicsActiveSynchronised_)
     173            this->activatePhysics();
     174        else
     175            this->deactivatePhysics();
    169176    }
    170177
     
    184191            else
    185192            {
    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();
    199194            }
    200195        }
     
    213208        object->parent_ = this;
    214209        object->parentID_ = this->getObjectID();
     210
     211        // collision shapes
     212        this->attachCollisionShape(object->getCollisionShape());
     213        // mass
     214        this->childrenMass_ += object->getMass();
     215        recalculatePhysicsProps();
    215216    }
    216217
    217218    void WorldEntity::detach(WorldEntity* object)
    218219    {
     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
    219229        this->node_->removeChild(object->node_);
    220230        this->children_.erase(object);
    221231        object->parent_ = 0;
    222232        object->parentID_ = (unsigned int)-1;
    223 
    224233//        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();
    225237    }
    226238
     
    237249    }
    238250
    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.
    256261    }
    257262
     
    261266    }
    262267
    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        {
    266272            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        {
    272281            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();
    273289    }
    274290
     
    292308    {
    293309        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();
    336311    }
    337312
     
    341316        if (this->parent_)
    342317            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())
    344319            ThrowException(PhysicsViolation, "Warning: Cannot set the collision type at run time.");
    345320
     
    357332            // Create new rigid body
    358333            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;
    362336            this->physicalBody_ = new btRigidBody(bodyConstructionInfo);
    363337            this->physicalBody_->setUserPointer(this);
     
    368342            // Destroy rigid body
    369343            assert(this->physicalBody_);
    370             removeFromPhysicalWorld();
     344            deactivatePhysics();
    371345            delete this->physicalBody_;
    372346            this->physicalBody_ = 0;
     
    392366        }
    393367
    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
    395370        updateCollisionType();
    396371        assert(this->collisionType_ == type);
    397372
    398373        // update mass and inertia tensor
    399         internalSetMassProps(); // type is not None! See case None in switch
    400 
    401         addToPhysicalWorld();
     374        recalculatePhysicsProps();
     375        activatePhysics();
    402376    }
    403377
     
    450424    }
    451425
    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        }
    467477    }
    468478}
  • code/branches/physics/src/orxonox/objects/worldentities/WorldEntity.h

    r2407 r2423  
    3535#define OGRE_FORCE_ANGLE_TYPES
    3636#include <OgreSceneNode.h>
    37 
    3837#include "LinearMath/btMotionState.h"
    3938
     
    126125
    127126            void attach(WorldEntity* object);
    128 //            void attachAsdf(BlinkingBillboard* object);
    129127            void detach(WorldEntity* object);
    130128            WorldEntity* getAttachedObject(unsigned int index) const;
    131 //            BlinkingBillboard* getAttachedAsdfObject(unsigned int index) const;
    132129            inline const std::set<WorldEntity*>& getAttachedObjects() const
    133130                { return this->children_; }
     
    146143            inline WorldEntity* getParent() const
    147144                { return this->parent_; }
     145
     146            void notifyChildPropsChanged();
    148147
    149148        protected:
     
    185184            };
    186185
    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();
    192195
    193196            inline CollisionType getCollisionType() const
     
    201204            inline float getMass() const
    202205                { 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);
    205211            CollisionShape* getAttachedCollisionShape(unsigned int index) const;
    206212
     
    210216                { return this->physicalBody_; }
    211217
     218            void notifyCollisionShapeChanged();
     219            void notifyChildMassChanged();
     220
    212221        protected:
    213222            virtual bool isCollisionTypeLegal(CollisionType type) const = 0;
     
    217226        private:
    218227            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();
    225229
    226230            // network callbacks
    227231            void collisionTypeChanged();
    228232            void massChanged();
     233            void physicsActivityChanged();
    229234
    230235            CollisionType                collisionType_;
    231236            CollisionType                collisionTypeSynchronised_;
     237            bool                         bPhysicsActive_;
     238            bool                         bPhysicsActiveSynchronised_;
    232239            CompoundCollisionShape*      collisionShape_;
    233240            btScalar                     mass_;
    234             btScalar                     childMass_;
     241            btScalar                     childrenMass_;
    235242    };
    236243}
Note: See TracChangeset for help on using the changeset viewer.