Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Dec 1, 2008, 11:09:43 PM (15 years ago)
Author:
rgrieder
Message:
  • Added support for attaching physical WorldEntities to each other. Currently you can only add static objects to kinematic/dynamic/static other objects. Future plans involve attaching kinematic objects to static/kinematic ones. All other combinations don't make sense at all.
  • Added CollisionShape, SphereCollisionShape and CompoundCollisionShape

Usage for collision shapes (example):

<LinearEntity collisionType="kinematic">

<attached>

<Model position="0,0,0" scale=10 mesh="ast1.mesh" />
<StaticEntity position="0,10,0" collisionType="static"> # Everything else than "static" fails!

<collisionShapes>

<SphereCollisionShape radius=40 position="10,10,-10"/>
<CompoundCollisionShape position="4,4,4"> # You can also make compound shapes directly

<SphereCollisionShape radius=10/>

</CompoundCollisionShape>

</collisionShapes>

</StaticEntity>

</attached>

</LinearEntity>

File:
1 edited

Legend:

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

    r2300 r2303  
    3333#include <OgreSceneManager.h>
    3434
    35 #include "BulletCollision/CollisionShapes/btSphereShape.h"
     35#include "BulletCollision/CollisionShapes/btCollisionShape.h"
     36#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
     37#include "BulletDynamics/Dynamics/btRigidBody.h"
    3638
    3739#include "util/Exception.h"
     
    4143
    4244#include "objects/Scene.h"
     45#include "objects/worldentities/collisionshapes/CollisionShape.h"
     46#include "objects/worldentities/collisionshapes/CompoundCollisionShape.h"
    4347
    4448namespace orxonox
     
    6872        // Default behaviour does not include physics
    6973        this->physicalBody_ = 0;
     74        this->collisionShape_ = 0;
     75        this->mass_ = 0;
    7076        updateCollisionType();
    7177
     
    100106
    101107        XMLPortParam(WorldEntity, "collisionType", setCollisionTypeStr, getCollisionTypeStr, xmlelement, mode);
    102         XMLPortParam(WorldEntity, "collisionRadius", setCollisionRadius, getCollisionRadius, xmlelement, mode);
     108        //XMLPortParam(WorldEntity, "collisionRadius", setCollisionRadius, getCollisionRadius, xmlelement, mode);
    103109        XMLPortParam(WorldEntity, "mass", setMass, getMass, xmlelement, mode);
    104110
    105111        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);
    110113    }
    111114
     
    131134    void WorldEntity::attach(WorldEntity* object)
    132135    {
     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
    133159        if (object->getParent())
    134160            object->detachFromParent();
     
    144170        object->parent_ = this;
    145171        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    }
    171173
    172174    void WorldEntity::detach(WorldEntity* object)
     
    192194    }
    193195
    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);
    203266    }
    204267
    205268    void WorldEntity::setMass(float mass)
    206269    {
    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;
    209273        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));
    218283        }
    219284    }
     
    221286    void WorldEntity::setCollisionType(CollisionType type)
    222287    {
    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.
    224299        if (type != None && this->collisionType_ == None)
    225300        {
    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 
    231301            // 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));
    233306            this->physicalBody_ = new btRigidBody(bodyConstructionInfo);
    234307            this->physicalBody_->setUserPointer(this);
    235 
    236             // Adjust parameters according to the node
    237             //btTransform nodeTransform;
    238             //this->
    239308        }
    240309        else if (type == None && this->collisionType_ != None)
     
    243312            if (this->physicalBody_->isInWorld())
    244313                this->getScene()->getPhysicalWorld()->removeRigidBody(this->physicalBody_);
    245             if (this->physicalBody_->getCollisionShape())
    246                 delete this->physicalBody_->getCollisionShape();
    247314            delete this->physicalBody_;
    248315            this->physicalBody_ = 0;
     
    250317            return;
    251318        }
    252 
    253         // Check for type legality. Could be StaticEntity or MovableEntity
    254         if (!this->isCollisionTypeLegal(type))
    255             return; // exception gets issued anyway
    256319
    257320        // Change type
     
    271334        }
    272335
     336        // update our variable for faster checks
     337        updateCollisionType();
     338
    273339        // 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)
    275341            this->setMass(0.0f);
    276342        // 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)
    278344            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));
    282347    }
    283348
     
    329394    }
    330395
    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    //}
    354431
    355432    bool WorldEntity::checkPhysics() const
Note: See TracChangeset for help on using the changeset viewer.