Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Dec 1, 2008, 11:09:43 PM (16 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>

Location:
code/branches/physics/src/orxonox/objects/worldentities
Files:
7 added
5 edited

Legend:

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

    r2300 r2303  
    3030#include "MovableEntity.h"
    3131
     32#include "BulletDynamics/Dynamics/btRigidBody.h"
     33
    3234#include "util/Exception.h"
    3335#include "core/CoreIncludes.h"
     
    6163    {
    6264    }
    63 
    64     //void MovableEntity::setPosition(const Vector3& position)
    65     //{
    66     //    //if (isDynamic() && bAddedToPhysicalWorld_)
    67     //    //{
    68     //    //    this->getScene()->getPhysicalWorld()->removeRigidBody(this->physicalBody_);
    69     //    //    this->getScene()->getPhysicalWorld()->addRigidBody(this->physicalBody_);
    70     //    //}
    71     //    this->node_->setPosition(position);
    72     //    positionChanged();
    73     //}
    74 
    75     //void MovableEntity::translate(const Vector3& distance, Ogre::Node::TransformSpace relativeTo)
    76     //{
    77     //    //if (isDynamic() && bAddedToPhysicalWorld_)
    78     //    //{
    79     //    //    this->getScene()->getPhysicalWorld()->removeRigidBody(this->physicalBody_);
    80     //    //    this->getScene()->getPhysicalWorld()->addRigidBody(this->physicalBody_);
    81     //    //}
    82     //    this->node_->translate(distance, relativeTo);
    83     //    positionChanged();
    84     //}
    85 
    86     //void MovableEntity::setOrientation(const Quaternion& orientation)
    87     //{
    88     //    //if (isDynamic() && bAddedToPhysicalWorld_)
    89     //    //{
    90     //    //    this->getScene()->getPhysicalWorld()->removeRigidBody(this->physicalBody_);
    91     //    //    this->getScene()->getPhysicalWorld()->addRigidBody(this->physicalBody_);
    92     //    //}
    93     //    this->node_->setOrientation(orientation);
    94     //    orientationChanged();
    95     //}
    96 
    97     //void MovableEntity::rotate(const Quaternion& rotation, Ogre::Node::TransformSpace relativeTo)
    98     //{
    99     //    //if (isDynamic() && bAddedToPhysicalWorld_)
    100     //    //{
    101     //    //    this->getScene()->getPhysicalWorld()->removeRigidBody(this->physicalBody_);
    102     //    //    this->getScene()->getPhysicalWorld()->addRigidBody(this->physicalBody_);
    103     //    //}
    104     //    this->node_->rotate(rotation, relativeTo);
    105     //    orientationChanged();
    106     //}
    107 
    108     //void MovableEntity::yaw(const Degree& angle, Ogre::Node::TransformSpace relativeTo)
    109     //{
    110     //    //if (isDynamic() && bAddedToPhysicalWorld_)
    111     //    //{
    112     //    //    this->getScene()->getPhysicalWorld()->removeRigidBody(this->physicalBody_);
    113     //    //    this->getScene()->getPhysicalWorld()->addRigidBody(this->physicalBody_);
    114     //    //}
    115     //    this->node_->yaw(angle, relativeTo);
    116     //    orientationChanged();
    117     //}
    118 
    119     //void MovableEntity::pitch(const Degree& angle, Ogre::Node::TransformSpace relativeTo)
    120     //{
    121     //    //if (isDynamic() && bAddedToPhysicalWorld_)
    122     //    //{
    123     //    //    this->getScene()->getPhysicalWorld()->removeRigidBody(this->physicalBody_);
    124     //    //    this->getScene()->getPhysicalWorld()->addRigidBody(this->physicalBody_);
    125     //    //}
    126     //    this->node_->pitch(angle, relativeTo);
    127     //    orientationChanged();
    128     //}
    129 
    130     //void MovableEntity::roll(const Degree& angle, Ogre::Node::TransformSpace relativeTo)
    131     //{
    132     //    //if (isDynamic() && bAddedToPhysicalWorld_)
    133     //    //{
    134     //    //    this->getScene()->getPhysicalWorld()->removeRigidBody(this->physicalBody_);
    135     //    //    this->getScene()->getPhysicalWorld()->addRigidBody(this->physicalBody_);
    136     //    //}
    137     //    this->node_->roll(angle, relativeTo);
    138     //    orientationChanged();
    139     //}
    140 
    141     //void MovableEntity::lookAt(const Vector3& target, Ogre::Node::TransformSpace relativeTo, const Vector3& localDirectionVector)
    142     //{
    143     //    //if (isDynamic() && bAddedToPhysicalWorld_)
    144     //    //{
    145     //    //    this->getScene()->getPhysicalWorld()->removeRigidBody(this->physicalBody_);
    146     //    //    this->getScene()->getPhysicalWorld()->addRigidBody(this->physicalBody_);
    147     //    //}
    148     //    this->node_->lookAt(target, relativeTo, localDirectionVector);
    149     //    orientationChanged();
    150     //}
    151 
    152     //void MovableEntity::setDirection(const Vector3& direction, Ogre::Node::TransformSpace relativeTo, const Vector3& localDirectionVector)
    153     //{
    154     //    //if (isDynamic() && bAddedToPhysicalWorld_)
    155     //    //{
    156     //    //    this->getScene()->getPhysicalWorld()->removeRigidBody(this->physicalBody_);
    157     //    //    this->getScene()->getPhysicalWorld()->addRigidBody(this->physicalBody_);
    158     //    //}
    159     //    this->node_->setDirection(direction, relativeTo, localDirectionVector);
    160     //    orientationChanged();
    161     //}
    16265
    16366    void MovableEntity::setPosition(const Vector3& position)
  • code/branches/physics/src/orxonox/objects/worldentities/StaticEntity.cc

    r2300 r2303  
    6262    bool StaticEntity::isCollisionTypeLegal(WorldEntity::CollisionType type) const
    6363    {
    64         if (type == WorldEntity::Static)
     64        if (type == WorldEntity::Kinematic || type == WorldEntity::Dynamic)
    6565        {
    66             ThrowException(PhysicsViolation, "Cannot tell a MovableEntity to have static collision type");
     66            ThrowException(PhysicsViolation, "Cannot tell a StaticEntity to have kinematic or dynamic collision type");
    6767            return false;
    6868        }
  • 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
  • code/branches/physics/src/orxonox/objects/worldentities/WorldEntity.h

    r2300 r2303  
    3636
    3737#include "LinearMath/btMotionState.h"
    38 #include "BulletDynamics/Dynamics/btRigidBody.h"
    3938
    4039#include "network/Synchronisable.h"
     
    108107                { this->setDirection(Vector3(x, y, z), relativeTo, localDirectionVector); }
    109108
    110             inline void setScale3D(const Vector3& scale)
    111                 { this->node_->setScale(scale); }
     109            void setScale3D(const Vector3& scale);
    112110            inline void setScale3D(float x, float y, float z)
    113                 { this->node_->setScale(x, y, z); }
     111                { this->setScale3D(Vector3(x, y, z)); }
    114112            inline const Vector3& getScale3D(void) const
    115113                { return this->node_->getScale(); }
    116114
    117             inline void setScale(float scale)
    118                 { this->node_->setScale(scale, scale, scale); }
     115            void setScale(float scale)
     116                { this->setScale3D(scale, scale, scale); }
    119117            inline float getScale() const
    120118                { Vector3 scale = this->getScale3D(); return (scale.x == scale.y && scale.x == scale.z) ? scale.x : 1; }
    121119
    122             inline void scale3D(const Vector3& scale)
    123                 { this->node_->scale(scale); }
     120            void scale3D(const Vector3& scale);
    124121            inline void scale3D(float x, float y, float z)
    125                 { this->node_->scale(x, y, z); }
     122                { this->scale3D(Vector3(x, y, z)); }
    126123            inline void scale(float scale)
    127                 { this->node_->scale(scale, scale, scale); }
     124                { this->scale3D(scale, scale, scale); }
    128125
    129126            void attach(WorldEntity* object);
     127//            void attachAsdf(BlinkingBillboard* object);
    130128            void detach(WorldEntity* object);
    131129            WorldEntity* getAttachedObject(unsigned int index) const;
     130//            BlinkingBillboard* getAttachedAsdfObject(unsigned int index) const;
    132131            inline const std::set<WorldEntity*>& getAttachedObjects() const
    133132                { return this->children_; }
     
    195194
    196195            void setMass(float mass);
    197             float getMass() const;
    198 
    199             void setCollisionRadius(float radius);
    200             float getCollisionRadius() const;
     196            inline float getMass() const
     197                { return this->mass_; }
     198
     199            void attachCollisionShape(CollisionShape* shape);
     200            CollisionShape* getAttachedCollisionShape(unsigned int index) const;
     201
     202            CollisionShape* getCollisionShape() { return this->collisionShape_; }
     203            btRigidBody* getPhysicalBody() { return this->physicalBody_; }
    201204
    202205        protected:
     
    211214
    212215        private:
    213             CollisionType collisionType_;
    214 
     216            void mergeCollisionShape(CollisionShape* shape);
     217
     218            CollisionType                collisionType_;
     219            std::vector<CollisionShape*> attachedShapes_;
     220            CollisionShape*              collisionShape_;
     221            btScalar                     mass_;
    215222    };
    216223}
  • code/branches/physics/src/orxonox/objects/worldentities/pawns/SpaceShip.cc

    r2298 r2303  
    2929#include "OrxonoxStableHeaders.h"
    3030#include "SpaceShip.h"
     31
     32#include "BulletDynamics/Dynamics/btRigidBody.h"
    3133
    3234#include "util/Math.h"
Note: See TracChangeset for help on using the changeset viewer.