Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Dec 14, 2008, 4:16:52 PM (16 years ago)
Author:
rgrieder
Message:

Finally merged physics stuff. Target is physics_merge because I'll have to do some testing first.

Location:
code/branches/physics_merge
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • code/branches/physics_merge

  • code/branches/physics_merge/src/orxonox/objects/worldentities/WorldEntity.cc

    r2371 r2442  
    2222 *   Author:
    2323 *      Fabian 'x3n' Landau
     24 *      Reto Grieder (physics)
    2425 *   Co-authors:
    2526 *      ...
     
    3132
    3233#include <cassert>
     34#include <OgreSceneNode.h>
    3335#include <OgreSceneManager.h>
    34 
     36#include "BulletDynamics/Dynamics/btRigidBody.h"
     37
     38#include "util/Exception.h"
     39#include "util/Convert.h"
    3540#include "core/CoreIncludes.h"
    3641#include "core/XMLPort.h"
    37 #include "util/Convert.h"
    38 #include "util/Exception.h"
    3942
    4043#include "objects/Scene.h"
     44#include "objects/collisionshapes/CompoundCollisionShape.h"
    4145
    4246namespace orxonox
     
    6468        this->node_->setOrientation(Quaternion::IDENTITY);
    6569
     70        // Default behaviour does not include physics
     71        this->physicalBody_ = 0;
     72        this->bPhysicsActive_ = false;
     73        this->collisionShape_ = new CompoundCollisionShape(this);
     74        this->collisionType_ = None;
     75        this->collisionTypeSynchronised_ = None;
     76        this->mass_           = 0;
     77        this->childrenMass_   = 0;
     78        // Use bullet default values
     79        this->restitution_    = 0;
     80        this->angularFactor_  = 1;
     81        this->linearDamping_  = 0;
     82        this->angularDamping_ = 0;
     83        this->friction_       = 0.5;
     84
    6685        this->registerVariables();
    6786    }
     
    7493            if (this->getScene()->getSceneManager())
    7594                this->getScene()->getSceneManager()->destroySceneNode(this->node_->getName());
     95
     96            // TODO: Detach from parent and detach all children.
     97
     98            if (this->physicalBody_)
     99            {
     100                this->deactivatePhysics();
     101                delete this->physicalBody_;
     102            }
     103            delete this->collisionShape_;
    76104        }
    77105    }
     
    81109        SUPER(WorldEntity, XMLPort, xmlelement, mode);
    82110
    83         XMLPortParamTemplate(WorldEntity, "position", setPosition, getPosition, xmlelement, mode, const Vector3&);
     111        XMLPortParamTemplate(WorldEntity, "position",    setPosition,    getPosition,    xmlelement, mode, const Vector3&);
    84112        XMLPortParamTemplate(WorldEntity, "orientation", setOrientation, getOrientation, xmlelement, mode, const Quaternion&);
    85         XMLPortParamLoadOnly(WorldEntity, "lookat", lookAt_xmlport, xmlelement, mode);
    86         XMLPortParamLoadOnly(WorldEntity, "direction", setDirection_xmlport, xmlelement, mode);
    87         XMLPortParamLoadOnly(WorldEntity, "yaw", yaw_xmlport, xmlelement, mode);
    88         XMLPortParamLoadOnly(WorldEntity, "pitch", pitch_xmlport, xmlelement, mode);
    89         XMLPortParamLoadOnly(WorldEntity, "roll", roll_xmlport, xmlelement, mode);
    90         XMLPortParamTemplate(WorldEntity, "scale3D", setScale3D, getScale3D, xmlelement, mode, const Vector3&);
    91         XMLPortParam(WorldEntity, "scale", setScale, getScale, xmlelement, mode);
    92 
     113        XMLPortParamTemplate(WorldEntity, "scale3D",     setScale3D,     getScale3D,     xmlelement, mode, const Vector3&);
     114        XMLPortParam        (WorldEntity, "scale",       setScale,       getScale,       xmlelement, mode);
     115        XMLPortParamLoadOnly(WorldEntity, "lookat",      lookAt_xmlport,       xmlelement, mode);
     116        XMLPortParamLoadOnly(WorldEntity, "direction",   setDirection_xmlport, xmlelement, mode);
     117        XMLPortParamLoadOnly(WorldEntity, "yaw",         yaw_xmlport,          xmlelement, mode);
     118        XMLPortParamLoadOnly(WorldEntity, "pitch",       pitch_xmlport,        xmlelement, mode);
     119        XMLPortParamLoadOnly(WorldEntity, "roll",        roll_xmlport,         xmlelement, mode);
     120
     121        // Physics
     122        XMLPortParam(WorldEntity, "collisionType",  setCollisionTypeStr, getCollisionTypeStr, xmlelement, mode);
     123        XMLPortParam(WorldEntity, "mass",           setMass,             getMass,             xmlelement, mode);
     124        XMLPortParam(WorldEntity, "restitution",    setRestitution,      getRestitution,      xmlelement, mode);
     125        XMLPortParam(WorldEntity, "angularFactor",  setAngularFactor,    getAngularFactor,    xmlelement, mode);
     126        XMLPortParam(WorldEntity, "linearDamping",  setLinearDamping,    getLinearDamping,    xmlelement, mode);
     127        XMLPortParam(WorldEntity, "angularDamping", setAngularDamping,   getAngularDamping,   xmlelement, mode);
     128        XMLPortParam(WorldEntity, "friction",       setFriction,         getFriction,         xmlelement, mode);
     129
     130        // Other attached WorldEntities
    93131        XMLPortObject(WorldEntity, WorldEntity, "attached", attach, getAttachedObject, xmlelement, mode);
     132        // Attached collision shapes
     133        XMLPortObject(WorldEntity, CollisionShape, "collisionShapes", attachCollisionShape, getAttachedCollisionShape, xmlelement, mode);
    94134    }
    95135
    96136    void WorldEntity::registerVariables()
    97137    {
    98         registerVariable(this->bActive_,  variableDirection::toclient, new NetworkCallback<WorldEntity>(this, &WorldEntity::changedActivity));
    99         registerVariable(this->bVisible_, variableDirection::toclient, new NetworkCallback<WorldEntity>(this, &WorldEntity::changedVisibility));
    100  
    101         registerVariable(this->getScale3D().x, variableDirection::toclient);
    102         registerVariable(this->getScale3D().y, variableDirection::toclient);
    103         registerVariable(this->getScale3D().z, variableDirection::toclient);
    104  
    105         registerVariable(this->parentID_, variableDirection::toclient, new NetworkCallback<WorldEntity>(this, &WorldEntity::updateParent));
    106     }
    107 
    108     void WorldEntity::updateParent()
     138        registerVariable(this->bActive_,        variableDirection::toclient, new NetworkCallback<WorldEntity>(this, &WorldEntity::changedActivity));
     139        registerVariable(this->bVisible_,       variableDirection::toclient, new NetworkCallback<WorldEntity>(this, &WorldEntity::changedVisibility));
     140
     141        registerVariable(this->getScale3D(),    variableDirection::toclient, new NetworkCallback<WorldEntity>(this, &WorldEntity::scaleChanged));
     142
     143        registerVariable((int&)this->collisionTypeSynchronised_,
     144                                                variableDirection::toclient, new NetworkCallback<WorldEntity>(this, &WorldEntity::collisionTypeChanged));
     145        registerVariable(this->mass_,           variableDirection::toclient, new NetworkCallback<WorldEntity>(this, &WorldEntity::massChanged));
     146        registerVariable(this->restitution_,    variableDirection::toclient, new NetworkCallback<WorldEntity>(this, &WorldEntity::restitutionChanged));
     147        registerVariable(this->angularFactor_,  variableDirection::toclient, new NetworkCallback<WorldEntity>(this, &WorldEntity::angularFactorChanged));
     148        registerVariable(this->linearDamping_,  variableDirection::toclient, new NetworkCallback<WorldEntity>(this, &WorldEntity::linearDampingChanged));
     149        registerVariable(this->angularDamping_, variableDirection::toclient, new NetworkCallback<WorldEntity>(this, &WorldEntity::angularDampingChanged));
     150        registerVariable(this->friction_,       variableDirection::toclient, new NetworkCallback<WorldEntity>(this, &WorldEntity::frictionChanged));
     151        registerVariable(this->bPhysicsActiveSynchronised_,
     152                                                variableDirection::toclient, new NetworkCallback<WorldEntity>(this, &WorldEntity::physicsActivityChanged));
     153
     154        registerVariable(this->parentID_,       variableDirection::toclient, new NetworkCallback<WorldEntity>(this, &WorldEntity::parentChanged));
     155    }
     156
     157    void WorldEntity::parentChanged()
    109158    {
    110159        if (this->parentID_ != OBJECTID_UNKNOWN)
     
    116165    }
    117166
     167    void WorldEntity::collisionTypeChanged()
     168    {
     169        if (this->collisionTypeSynchronised_ != Dynamic &&
     170            this->collisionTypeSynchronised_ != Kinematic &&
     171            this->collisionTypeSynchronised_ != Static &&
     172            this->collisionTypeSynchronised_ != None)
     173        {
     174            CCOUT(1) << "Error when collsion Type was received over network. Unknown enum value:" << this->collisionTypeSynchronised_ << std::endl;
     175        }
     176        else if (this->collisionTypeSynchronised_ != collisionType_)
     177        {
     178            if (this->parent_)
     179                CCOUT(2) << "Warning: Network connection tried to set the collision type of an attached WE. Ignoring." << std::endl;
     180            else
     181                this->setCollisionType(this->collisionTypeSynchronised_);
     182        }
     183    }
     184
     185    void WorldEntity::physicsActivityChanged()
     186    {
     187        if (this->bPhysicsActiveSynchronised_)
     188            this->activatePhysics();
     189        else
     190            this->deactivatePhysics();
     191    }
     192
    118193    void WorldEntity::attach(WorldEntity* object)
    119194    {
     195        // check first whether attaching is even allowed
     196        if (object->hasPhysics())
     197        {
     198            if (!this->hasPhysics())
     199            {
     200                COUT(2) << "Warning: Cannot attach a physical object to a non physical one." << std::endl;
     201                return;
     202            }
     203            else if (object->isDynamic())
     204            {
     205                COUT(2) << "Warning: Cannot attach a dynamic object to a WorldEntity." << std::endl;
     206                return;
     207            }
     208            else if (object->isKinematic() && this->isDynamic())
     209            {
     210                COUT(2) << "Warning: Cannot attach a kinematic object to a dynamic one." << std::endl;
     211                return;
     212            }
     213            else if (object->isKinematic())
     214            {
     215                COUT(2) << "Warning: Cannot attach a kinematic object to a static or kinematic one: Not yet implemented." << std::endl;
     216                return;
     217            }
     218            else
     219            {
     220                object->deactivatePhysics();
     221            }
     222        }
     223
    120224        if (object->getParent())
    121225            object->detachFromParent();
     
    131235        object->parent_ = this;
    132236        object->parentID_ = this->getObjectID();
     237
     238        // collision shapes
     239        this->attachCollisionShape(object->getCollisionShape());
     240        // mass
     241        this->childrenMass_ += object->getMass();
     242        recalculateMassProps();
    133243    }
    134244
    135245    void WorldEntity::detach(WorldEntity* object)
    136246    {
     247        // collision shapes
     248        this->detachCollisionShape(object->getCollisionShape());
     249        // mass
     250        if (object->getMass() > 0.0f)
     251        {
     252            this->childrenMass_ -= object->getMass();
     253            recalculateMassProps();
     254        }
     255
    137256        this->node_->removeChild(object->node_);
    138257        this->children_.erase(object);
    139258        object->parent_ = 0;
    140259        object->parentID_ = OBJECTID_UNKNOWN;
    141 
    142260//        this->getScene()->getRootSceneNode()->addChild(object->node_);
     261
     262        // Note: It is possible that the object has physics but was disabled when attaching
     263        object->activatePhysics();
    143264    }
    144265
     
    154275        return 0;
    155276    }
     277
     278    void WorldEntity::attachOgreObject(Ogre::MovableObject* object)
     279    {
     280        this->node_->attachObject(object);
     281    }
     282
     283    void WorldEntity::detachOgreObject(Ogre::MovableObject* object)
     284    {
     285        this->node_->detachObject(object);
     286    }
     287
     288    Ogre::MovableObject* WorldEntity::detachOgreObject(const Ogre::String& name)
     289    {
     290        return this->node_->detachObject(name);
     291    }
     292
     293    void WorldEntity::attachCollisionShape(CollisionShape* shape)
     294    {
     295        this->collisionShape_->addChildShape(shape);
     296        // Note: this->collisionShape_ already notifies us of any changes.
     297    }
     298
     299    void WorldEntity::detachCollisionShape(CollisionShape* shape)
     300    {
     301        this->collisionShape_->removeChildShape(shape);
     302        // Note: this->collisionShape_ already notifies us of any changes.
     303    }
     304
     305    CollisionShape* WorldEntity::getAttachedCollisionShape(unsigned int index) const
     306    {
     307        return this->collisionShape_->getChildShape(index);
     308    }
     309
     310    void WorldEntity::activatePhysics()
     311    {
     312        if (this->isActive() && this->hasPhysics() && !this->isPhysicsActive() && !this->parent_)
     313        {
     314            this->getScene()->addRigidBody(this->physicalBody_);
     315            this->bPhysicsActive_ = true;
     316        }
     317    }
     318
     319    void WorldEntity::deactivatePhysics()
     320    {
     321        if (this->isPhysicsActive())
     322        {
     323            this->getScene()->removeRigidBody(this->physicalBody_);
     324            this->bPhysicsActive_ = false;
     325        }
     326    }
     327
     328    bool WorldEntity::addedToPhysicalWorld() const
     329    {
     330        return this->physicalBody_ && this->physicalBody_->isInWorld();
     331    }
     332
     333#ifndef _NDEBUG
     334    const Vector3& WorldEntity::getPosition() const
     335    {
     336        return this->node_->getPosition();
     337    }
     338
     339    const Quaternion& WorldEntity::getOrientation() const
     340    {
     341        return this->node_->getOrientation();
     342    }
     343
     344    const Vector3& WorldEntity::getScale3D() const
     345    {
     346        return this->node_->getScale();
     347    }
     348#endif
     349
     350    const Vector3& WorldEntity::getWorldPosition() const
     351    {
     352        return this->node_->_getDerivedPosition();
     353    }
     354
     355    const Quaternion& WorldEntity::getWorldOrientation() const
     356    {
     357        return this->node_->_getDerivedOrientation();
     358    }
     359
     360    void WorldEntity::translate(const Vector3& distance, TransformSpace::Space relativeTo)
     361    {
     362        switch (relativeTo)
     363        {
     364        case TransformSpace::Local:
     365            // position is relative to parent so transform downwards
     366            this->setPosition(this->getPosition() + this->getOrientation() * distance);
     367            break;
     368        case TransformSpace::Parent:
     369            this->setPosition(this->getPosition() + distance);
     370            break;
     371        case TransformSpace::World:
     372            // position is relative to parent so transform upwards
     373            if (this->node_->getParent())
     374                setPosition(getPosition() + (node_->getParent()->_getDerivedOrientation().Inverse() * distance)
     375                    / node_->getParent()->_getDerivedScale());
     376            else
     377                this->setPosition(this->getPosition() + distance);
     378            break;
     379        }
     380    }
     381
     382    void WorldEntity::rotate(const Quaternion& rotation, TransformSpace::Space relativeTo)
     383    {
     384        switch(relativeTo)
     385        {
     386        case TransformSpace::Local:
     387            this->setOrientation(this->getOrientation() * rotation);
     388            break;
     389        case TransformSpace::Parent:
     390            // Rotations are normally relative to local axes, transform up
     391            this->setOrientation(rotation * this->getOrientation());
     392            break;
     393        case TransformSpace::World:
     394            // Rotations are normally relative to local axes, transform up
     395            this->setOrientation(this->getOrientation() * this->getWorldOrientation().Inverse()
     396                * rotation * this->getWorldOrientation());
     397            break;
     398        }
     399    }
     400
     401    void WorldEntity::lookAt(const Vector3& target, TransformSpace::Space relativeTo, const Vector3& localDirectionVector)
     402    {
     403        Vector3 origin;
     404        switch (relativeTo)
     405        {
     406        case TransformSpace::Local:
     407            origin = Vector3::ZERO;
     408            break;
     409        case TransformSpace::Parent:
     410            origin = this->getPosition();
     411            break;
     412        case TransformSpace::World:
     413            origin = this->getWorldPosition();
     414            break;
     415        }
     416        this->setDirection(target - origin, relativeTo, localDirectionVector);
     417    }
     418
     419    void WorldEntity::setDirection(const Vector3& direction, TransformSpace::Space relativeTo, const Vector3& localDirectionVector)
     420    {
     421        Quaternion savedOrientation(this->getOrientation());
     422        Ogre::Node::TransformSpace ogreRelativeTo;
     423        switch (relativeTo)
     424        {
     425        case TransformSpace::Local:
     426            ogreRelativeTo = Ogre::Node::TS_LOCAL; break;
     427        case TransformSpace::Parent:
     428            ogreRelativeTo = Ogre::Node::TS_PARENT; break;
     429        case TransformSpace::World:
     430            ogreRelativeTo = Ogre::Node::TS_WORLD; break;
     431        }
     432        this->node_->setDirection(direction, ogreRelativeTo, localDirectionVector);
     433        Quaternion newOrientation(this->node_->getOrientation());
     434        this->node_->setOrientation(savedOrientation);
     435        this->setOrientation(newOrientation);
     436    }
     437
     438    void WorldEntity::setScale3D(const Vector3& scale)
     439    {
     440        if (this->hasPhysics())
     441        {
     442            CCOUT(2) << "Warning: Cannot set the scale of a physical object: Not yet implemented." << std::endl;
     443            return;
     444        }
     445
     446        this->node_->setScale(scale);
     447    }
     448
     449    void WorldEntity::setCollisionType(CollisionType type)
     450    {
     451        // If we are already attached to a parent, this would be a bad idea..
     452        if (this->parent_)
     453        {
     454            CCOUT(2) << "Warning: Cannot set the collision type of a WorldEntity with a parent." << std::endl;
     455            return;
     456        }
     457        else if (this->addedToPhysicalWorld())
     458        {
     459            CCOUT(2) << "Warning: Cannot set the collision type at run time." << std::endl;
     460            return;
     461        }
     462
     463        // Check for type legality. Could be StaticEntity or MobileEntity
     464        if (!this->isCollisionTypeLegal(type))
     465            return; // exception gets issued anyway
     466        if (type != None && !this->getScene()->hasPhysics())
     467        {
     468            CCOUT(2) << "Warning: Cannot have physical bodies in a non physical scene." << std::endl;
     469            return;
     470        }
     471
     472        // Check whether we have to create or destroy.
     473        if (type != None && this->collisionType_ == None)
     474        {
     475            // Check whether there was some scaling applied.
     476            if (!this->node_->getScale().positionEquals(Vector3(1, 1, 1), 0.001))
     477            {
     478                CCOUT(2) << "Warning: Cannot create a physical body if there is scaling applied to the node: Not yet implemented." << std::endl;
     479                return;
     480            }
     481
     482            // Create new rigid body
     483            btRigidBody::btRigidBodyConstructionInfo bodyConstructionInfo(0, this, this->collisionShape_->getCollisionShape());
     484            this->physicalBody_ = new btRigidBody(bodyConstructionInfo);
     485            this->physicalBody_->setUserPointer(this);
     486            this->physicalBody_->setActivationState(DISABLE_DEACTIVATION);
     487        }
     488        else if (type == None && this->collisionType_ != None)
     489        {
     490            // Destroy rigid body
     491            assert(this->physicalBody_);
     492            deactivatePhysics();
     493            delete this->physicalBody_;
     494            this->physicalBody_ = 0;
     495            this->collisionType_ = None;
     496            this->collisionTypeSynchronised_ = None;
     497            return;
     498        }
     499
     500        // Change type
     501        switch (type)
     502        {
     503        case Dynamic:
     504            this->physicalBody_->setCollisionFlags(this->physicalBody_->getCollisionFlags() & !(btCollisionObject::CF_STATIC_OBJECT | btCollisionObject::CF_KINEMATIC_OBJECT));
     505            break;
     506        case Kinematic:
     507            this->physicalBody_->setCollisionFlags(this->physicalBody_->getCollisionFlags() & !btCollisionObject::CF_STATIC_OBJECT | btCollisionObject::CF_KINEMATIC_OBJECT);
     508            break;
     509        case Static:
     510            this->physicalBody_->setCollisionFlags(this->physicalBody_->getCollisionFlags() & !btCollisionObject::CF_KINEMATIC_OBJECT | btCollisionObject::CF_STATIC_OBJECT);
     511            break;
     512        case None:
     513            return; // this->collisionType_ was None too
     514        }
     515
     516        // Only sets this->collisionShape_
     517        // However the assertion is to ensure that the internal bullet setting is right
     518        updateCollisionType();
     519        assert(this->collisionType_ == type);
     520
     521        // update mass and inertia tensor
     522        recalculateMassProps();
     523        resetPhysicsProps();
     524        activatePhysics();
     525    }
     526
     527    void WorldEntity::setCollisionTypeStr(const std::string& typeStr)
     528    {
     529        std::string typeStrLower = getLowercase(typeStr);
     530        CollisionType type;
     531        if (typeStrLower == "dynamic")
     532            type = Dynamic;
     533        else if (typeStrLower == "static")
     534            type = Static;
     535        else if (typeStrLower == "kinematic")
     536            type = Kinematic;
     537        else if (typeStrLower == "none")
     538            type = None;
     539        else
     540            ThrowException(ParseError, std::string("Attempting to set an unknown collision type: '") + typeStr + "'.");
     541        this->setCollisionType(type);
     542    }
     543
     544    std::string WorldEntity::getCollisionTypeStr() const
     545    {
     546        switch (this->getCollisionType())
     547        {
     548            case Dynamic:
     549                return "dynamic";
     550            case Kinematic:
     551                return "kinematic";
     552            case Static:
     553                return "static";
     554            case None:
     555                return "none";
     556            default:
     557                assert(false);
     558                return "";
     559        }
     560    }
     561
     562    void WorldEntity::updateCollisionType()
     563    {
     564        if (!this->physicalBody_)
     565            this->collisionType_ = None;
     566        else if (this->physicalBody_->isKinematicObject())
     567            this->collisionType_ = Kinematic;
     568        else if (this->physicalBody_->isStaticObject())
     569            this->collisionType_ = Static;
     570        else
     571            this->collisionType_ = Dynamic;
     572        this->collisionTypeSynchronised_ = this->collisionType_;
     573    }
     574
     575    void WorldEntity::notifyChildMassChanged() // Called by a child WE
     576    {
     577        // Note: CollisionShape changes of a child get handled over the internal CompoundCollisionShape already
     578        // Recalculate mass
     579        this->childrenMass_ = 0.0f;
     580        for (std::set<WorldEntity*>::const_iterator it = this->children_.begin(); it != this->children_.end(); ++it)
     581            this->childrenMass_ += (*it)->getMass();
     582        recalculateMassProps();
     583        // Notify parent WE
     584        if (this->parent_)
     585            parent_->notifyChildMassChanged();
     586    }
     587
     588    void WorldEntity::notifyCollisionShapeChanged() // called by this->collisionShape_
     589    {
     590        if (hasPhysics())
     591        {
     592            // Bullet doesn't like sudden changes of the collision shape, so we remove and add it again
     593            if (this->addedToPhysicalWorld())
     594            {
     595                this->deactivatePhysics();
     596                this->physicalBody_->setCollisionShape(this->collisionShape_->getCollisionShape());
     597                this->activatePhysics();
     598            }
     599            else
     600                this->physicalBody_->setCollisionShape(this->collisionShape_->getCollisionShape());
     601        }
     602        recalculateMassProps();
     603    }
     604
     605    void WorldEntity::recalculateMassProps()
     606    {
     607        if (this->hasPhysics())
     608        {
     609            if (this->isStatic())
     610            {
     611                // Just set everything to zero
     612                this->physicalBody_->setMassProps(0.0f, btVector3(0, 0, 0));
     613            }
     614            else if ((this->mass_ + this->childrenMass_) == 0.0f)
     615            {
     616                // Use default values to avoid very large or very small values
     617                CCOUT(4) << "Warning: Setting the internal physical mass to 1.0 because mass_ is 0.0." << std::endl;
     618                this->physicalBody_->setMassProps(1.0f, this->collisionShape_->getLocalInertia(1.0f));
     619            }
     620            else
     621            {
     622                float mass = this->mass_ + this->childrenMass_;
     623                this->physicalBody_->setMassProps(mass, this->collisionShape_->getLocalInertia(mass));
     624            }
     625        }
     626    }
     627
     628    void WorldEntity::resetPhysicsProps()
     629    {
     630        if (this->hasPhysics())
     631        {
     632            this->physicalBody_->setRestitution(this->restitution_);
     633            this->physicalBody_->setAngularFactor(this->angularFactor_);
     634            this->physicalBody_->setDamping(this->linearDamping_, this->angularDamping_);
     635            this->physicalBody_->setFriction(this->friction_);
     636        }
     637    }
    156638}
Note: See TracChangeset for help on using the changeset viewer.