Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Nov 29, 2008, 12:45:19 AM (16 years ago)
Author:
rgrieder
Message:

Clarified use of different physical bodies. The "collisionType" XML attribute of WE specifies the following:
"none": There is not physical body at all. Physics disabled.
"static": It is a StaticEntity with physics. Any other derived class of WE issues an exception by choosing this collision type.
"kinematic" or "dynamic": MovableEntity with physics. StaticEntity issues an exception when choosing one of these two.

Added two new Exceptions: ParseError and PhysicsViolation.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • code/branches/physics/src/orxonox/objects/worldentities/WorldEntity.cc

    r2292 r2298  
    4141
    4242#include "objects/Scene.h"
    43 
    44 #include "StaticEntity.h"
    4543
    4644namespace orxonox
     
    7068        // Default behaviour does not include physics
    7169        this->physicalBody_ = 0;
     70        updateCollisionType();
    7271
    7372        this->registerVariables();
     
    8180            if (this->getScene()->getSceneManager())
    8281                this->getScene()->getSceneManager()->destroySceneNode(this->node_->getName());
    83            
    84             // Physics is not guaranteed, so check first
    85             if (this->physicalBody_)
    86             {
    87                 if (this->physicalBody_->isInWorld())
    88                     this->getScene()->getPhysicalWorld()->removeRigidBody(this->physicalBody_);
    89                 if (this->physicalBody_->getCollisionShape())
    90                     delete this->physicalBody_->getCollisionShape();
    91                 delete this->physicalBody_;
    92             }
     82
     83            this->setCollisionType(None);
    9384        }
    9485    }
     
    10899        XMLPortParam(WorldEntity, "scale", setScale, getScale, xmlelement, mode);
    109100
     101        XMLPortParam(WorldEntity, "collisionType", setCollisionTypeStr, getCollisionTypeStr, xmlelement, mode);
    110102        XMLPortParam(WorldEntity, "collisionRadius", setCollisionRadius, getCollisionRadius, xmlelement, mode);
    111         XMLPortParam(WorldEntity, "collisionType", setCollisionTypeStr, getCollisionTypeStr, xmlelement, mode);
    112103        XMLPortParam(WorldEntity, "mass", setMass, getMass, xmlelement, mode);
    113104
    114         if (this->physicalBody_)
     105        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)
    115109            this->getScene()->getPhysicalWorld()->addRigidBody(this->physicalBody_);
    116 
    117         XMLPortObject(WorldEntity, WorldEntity, "attached", attach, getAttachedObject, xmlelement, mode);
    118110    }
    119111
     
    200192    }
    201193
    202     void WorldEntity::createPhysicalBody()
    203     {
    204         // Note: The motion state will be configured in a derived class.
    205         btRigidBody::btRigidBodyConstructionInfo bodyConstructionInfo(0, this, 0, btVector3(0,0,0));
    206         this->physicalBody_ = new btRigidBody(bodyConstructionInfo);
    207     }
    208 
    209194    float WorldEntity::getMass()
    210195    {
    211         if (!this->physicalBody_)
     196        if (!checkPhysics())
    212197            return 0.0f;
    213198
     
    217202    void WorldEntity::setMass(float mass)
    218203    {
    219         if (!this->physicalBody_)
    220             this->createPhysicalBody();
    221 
    222         this->physicalBody_->setMassProps(mass, btVector3(0,0,0));
    223     }
    224 
    225     void WorldEntity::setCollisionType(WorldEntity::CollisionType type)
    226     {
    227         if (!this->physicalBody_)
    228             this->createPhysicalBody();
    229 
     204        if (!checkPhysics())
     205            return;
     206        else if (this->physicalBody_->isInWorld())
     207        {
     208            CCOUT(2) << "Cannot set the physical mass at run time." << std::endl;
     209            assert(false);
     210        }
     211        else
     212        {
     213            this->physicalBody_->setMassProps(mass, btVector3(0,0,0));
     214            updateCollisionType();
     215        }
     216    }
     217
     218    void WorldEntity::setCollisionType(CollisionType type)
     219    {
     220        // Check first whether we have to create or destroy.
     221        if (type != None && this->collisionType_ == None)
     222        {
     223            // Create new rigid body
     224            btRigidBody::btRigidBodyConstructionInfo bodyConstructionInfo(0, this, 0, btVector3(0,0,0));
     225            this->physicalBody_ = new btRigidBody(bodyConstructionInfo);
     226            this->physicalBody_->setUserPointer(this);
     227
     228            // Adjust parameters according to the node
     229            btTransform nodeTransform;
     230            //this->
     231        }
     232        else if (type == None && this->collisionType_ != None)
     233        {
     234            // Destroy rigid body
     235            if (this->physicalBody_->isInWorld())
     236                this->getScene()->getPhysicalWorld()->removeRigidBody(this->physicalBody_);
     237            if (this->physicalBody_->getCollisionShape())
     238                delete this->physicalBody_->getCollisionShape();
     239            delete this->physicalBody_;
     240            this->physicalBody_ = 0;
     241            this->collisionType_ = None;
     242            return;
     243        }
     244
     245        // Check for type legality. Could be StaticEntity or MovableEntity
     246        if (!this->isCollisionTypeLegal(type))
     247            return; // exception gets issued anyway
     248
     249        // Change type
    230250        switch (type)
    231251        {
     
    239259            this->physicalBody_->setCollisionFlags(this->physicalBody_->getCollisionFlags() & !btCollisionObject::CF_KINEMATIC_OBJECT | btCollisionObject::CF_STATIC_OBJECT);
    240260            break;
    241         }
    242     }
    243 
    244     WorldEntity::CollisionType WorldEntity::getCollisionType()
     261        case None:
     262            return; // this->collisionType_ was None too
     263        }
     264
     265        // Mass non zero is a bad idea for kinematic and static objects
     266        if ((type == Kinematic || type == Static) && getMass() != 0.0f)
     267            this->setMass(0.0f);
     268        // Mass zero is not such a good idea for dynamic objects
     269        else if (type == Dynamic && getMass() == 0.0f)
     270            this->setMass(1.0f);
     271
     272        // finally update our variable for faster checks
     273        updateCollisionType();
     274    }
     275
     276    void WorldEntity::updateCollisionType()
    245277    {
    246278        if (!this->physicalBody_)
    247             ThrowException(Argument, "Cannot retrieve collision type of a non physical object.");
    248 
    249         int flags = this->physicalBody_->getCollisionFlags();
    250         if (flags & btCollisionObject::CF_STATIC_OBJECT)
    251             return Static;
    252         else if (flags & btCollisionObject::CF_KINEMATIC_OBJECT)
    253             return Kinematic;
    254         else
    255             return Dynamic;
    256     }
    257 
    258     void WorldEntity::setCollisionTypeStr(const std::string& type)
    259     {
    260         std::string lower = getLowercase(type);
    261         if (lower == "dynamic")
    262             setCollisionType(Dynamic);
    263         else if (lower == "static")
    264             setCollisionType(Static);
    265         else if (lower == "kinematic")
    266             setCollisionType(Kinematic);
    267         else
    268             ThrowException(Argument, std::string("Trying to set an unknown collision type: '") + type + "'.");
     279            this->collisionType_ = None;
     280        else if (this->physicalBody_->isKinematicObject())
     281            this->collisionType_ = Kinematic;
     282        else if (this->physicalBody_->isStaticObject())
     283            this->collisionType_ = Static;
     284        else
     285            this->collisionType_ = Dynamic;
     286    }
     287
     288    void WorldEntity::setCollisionTypeStr(const std::string& typeStr)
     289    {
     290        std::string typeStrLower = getLowercase(typeStr);
     291        CollisionType type;
     292        if (typeStrLower == "dynamic")
     293            type = Dynamic;
     294        else if (typeStrLower == "static")
     295            type = Static;
     296        else if (typeStrLower == "kinematic")
     297            type = Kinematic;
     298        else if (typeStrLower == "none")
     299            type = None;
     300        else
     301            ThrowException(ParseError, std::string("Attempting to set an unknown collision type: '") + typeStr + "'.");
     302        this->setCollisionType(type);
    269303    }
    270304
     
    273307        switch (this->getCollisionType())
    274308        {
    275         case Dynamic:
    276             return "dynamic";
    277         case Kinematic:
    278             return "kinematic";
    279         case Static:
    280             return "static";
    281         default:
    282             ThrowException(Argument, "Encountered unknown collision Type.");
     309            case Dynamic:
     310                return "dynamic";
     311            case Kinematic:
     312                return "kinematic";
     313            case Static:
     314                return "static";
     315            case None:
     316                return "none";
     317            default:
     318                assert(false);
     319                return "";
    283320        }
    284321    }
     
    286323    void WorldEntity::setCollisionRadius(float radius)
    287324    {
    288         if (!this->physicalBody_)
    289             createPhysicalBody();
     325        if (!checkPhysics())
     326            return;
    290327
    291328        // destroy old one first
     
    299336    float WorldEntity::getCollisionRadius()
    300337    {
    301         if (this->physicalBody_)
     338        if (checkPhysics())
    302339        {
    303340            btSphereShape* sphere = dynamic_cast<btSphereShape*>(this->physicalBody_->getCollisionShape());
     
    307344        return 0.0f;
    308345    }
     346
     347    bool WorldEntity::checkPhysics()
     348    {
     349        if (!this->physicalBody_)
     350        {
     351            assert(this->getCollisionType() == None);
     352            COUT(2) << "WorldEntity was not fitted with physics, cannot set phyiscal property." << std::endl;
     353            return false;
     354        }
     355        else
     356            return true;
     357    }
    309358}
Note: See TracChangeset for help on using the changeset viewer.