Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentation/src/orxonox/objects/worldentities/WorldEntity.cc @ 2481

Last change on this file since 2481 was 2481, checked in by rgrieder, 15 years ago

Amateurs…

  • Property svn:eol-style set to native
File size: 25.4 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *      Reto Grieder (physics)
25 *   Co-authors:
26 *      ...
27 *
28 */
29
30#include "OrxonoxStableHeaders.h"
31#include "WorldEntity.h"
32
33#include <cassert>
34#include <OgreSceneNode.h>
35#include <OgreSceneManager.h>
36#include "BulletDynamics/Dynamics/btRigidBody.h"
37
38#include "util/Exception.h"
39#include "util/Convert.h"
40#include "core/CoreIncludes.h"
41#include "core/XMLPort.h"
42
43#include "objects/Scene.h"
44#include "objects/collisionshapes/CompoundCollisionShape.h"
45
46namespace orxonox
47{
48    const Vector3 WorldEntity::FRONT = Vector3::NEGATIVE_UNIT_Z;
49    const Vector3 WorldEntity::BACK  = Vector3::UNIT_Z;
50    const Vector3 WorldEntity::LEFT  = Vector3::NEGATIVE_UNIT_X;
51    const Vector3 WorldEntity::RIGHT = Vector3::UNIT_X;
52    const Vector3 WorldEntity::DOWN  = Vector3::NEGATIVE_UNIT_Y;
53    const Vector3 WorldEntity::UP    = Vector3::UNIT_Y;
54
55    WorldEntity::WorldEntity(BaseObject* creator) : BaseObject(creator), Synchronisable(creator)
56    {
57        RegisterObject(WorldEntity);
58
59        if (!this->getScene() || !this->getScene()->getRootSceneNode())
60            ThrowException(AbortLoading, "Can't create WorldEntity, no scene or no root-scenenode given.");
61
62        this->node_ = this->getScene()->getRootSceneNode()->createChildSceneNode();
63
64        this->parent_ = 0;
65        this->parentID_ = OBJECTID_UNKNOWN;
66
67        this->node_->setPosition(Vector3::ZERO);
68        this->node_->setOrientation(Quaternion::IDENTITY);
69
70        // Default behaviour does not include physics
71        this->physicalBody_ = 0;
72        this->bPhysicsActive_ = false;
73        this->collisionShape_ = new CompoundCollisionShape(this);
74        // Note: CompoundCollisionShape is a Synchronisable, but must not be synchronised.
75        //       All objects will get attached on the client anyway, so we don't need synchronisation.
76        this->collisionShape_->setWorldEntityParent(this);
77        this->collisionType_ = None;
78        this->collisionTypeSynchronised_ = None;
79        this->mass_           = 0;
80        this->childrenMass_   = 0;
81        // Use bullet default values
82        this->restitution_    = 0;
83        this->angularFactor_  = 1;
84        this->linearDamping_  = 0;
85        this->angularDamping_ = 0;
86        this->friction_       = 0.5;
87        this->bCollisionCallbackActive_ = false;
88
89        this->registerVariables();
90    }
91
92    WorldEntity::~WorldEntity()
93    {
94        if (this->isInitialized())
95        {
96            this->node_->detachAllObjects();
97            if (this->getScene()->getSceneManager())
98                this->getScene()->getSceneManager()->destroySceneNode(this->node_->getName());
99
100            // TODO: Detach from parent and detach all children.
101
102            if (this->physicalBody_)
103            {
104                this->deactivatePhysics();
105                delete this->physicalBody_;
106            }
107            delete this->collisionShape_;
108        }
109    }
110
111    void WorldEntity::XMLPort(Element& xmlelement, XMLPort::Mode mode)
112    {
113        SUPER(WorldEntity, XMLPort, xmlelement, mode);
114
115        XMLPortParamTemplate(WorldEntity, "position",    setPosition,    getPosition,    xmlelement, mode, const Vector3&);
116        XMLPortParamTemplate(WorldEntity, "orientation", setOrientation, getOrientation, xmlelement, mode, const Quaternion&);
117        XMLPortParamTemplate(WorldEntity, "scale3D",     setScale3D,     getScale3D,     xmlelement, mode, const Vector3&);
118        XMLPortParam        (WorldEntity, "scale",       setScale,       getScale,       xmlelement, mode);
119        XMLPortParamLoadOnly(WorldEntity, "lookat",      lookAt_xmlport,       xmlelement, mode);
120        XMLPortParamLoadOnly(WorldEntity, "direction",   setDirection_xmlport, xmlelement, mode);
121        XMLPortParamLoadOnly(WorldEntity, "yaw",         yaw_xmlport,          xmlelement, mode);
122        XMLPortParamLoadOnly(WorldEntity, "pitch",       pitch_xmlport,        xmlelement, mode);
123        XMLPortParamLoadOnly(WorldEntity, "roll",        roll_xmlport,         xmlelement, mode);
124
125        // Physics
126        XMLPortParam(WorldEntity, "collisionType",  setCollisionTypeStr, getCollisionTypeStr, xmlelement, mode);
127        XMLPortParam(WorldEntity, "mass",           setMass,             getMass,             xmlelement, mode);
128        XMLPortParam(WorldEntity, "restitution",    setRestitution,      getRestitution,      xmlelement, mode);
129        XMLPortParam(WorldEntity, "angularFactor",  setAngularFactor,    getAngularFactor,    xmlelement, mode);
130        XMLPortParam(WorldEntity, "linearDamping",  setLinearDamping,    getLinearDamping,    xmlelement, mode);
131        XMLPortParam(WorldEntity, "angularDamping", setAngularDamping,   getAngularDamping,   xmlelement, mode);
132        XMLPortParam(WorldEntity, "friction",       setFriction,         getFriction,         xmlelement, mode);
133
134        // Other attached WorldEntities
135        XMLPortObject(WorldEntity, WorldEntity, "attached", attach, getAttachedObject, xmlelement, mode);
136        // Attached collision shapes
137        XMLPortObject(WorldEntity, CollisionShape, "collisionShapes", attachCollisionShape, getAttachedCollisionShape, xmlelement, mode);
138    }
139
140    void WorldEntity::registerVariables()
141    {
142        registerVariable(this->bActive_,        variableDirection::toclient, new NetworkCallback<WorldEntity>(this, &WorldEntity::changedActivity));
143        registerVariable(this->bVisible_,       variableDirection::toclient, new NetworkCallback<WorldEntity>(this, &WorldEntity::changedVisibility));
144
145        registerVariable(this->getScale3D(),    variableDirection::toclient, new NetworkCallback<WorldEntity>(this, &WorldEntity::scaleChanged));
146
147        // Physics stuff
148        registerVariable(this->mass_,           variableDirection::toclient, new NetworkCallback<WorldEntity>(this, &WorldEntity::massChanged));
149        registerVariable(this->restitution_,    variableDirection::toclient, new NetworkCallback<WorldEntity>(this, &WorldEntity::restitutionChanged));
150        registerVariable(this->angularFactor_,  variableDirection::toclient, new NetworkCallback<WorldEntity>(this, &WorldEntity::angularFactorChanged));
151        registerVariable(this->linearDamping_,  variableDirection::toclient, new NetworkCallback<WorldEntity>(this, &WorldEntity::linearDampingChanged));
152        registerVariable(this->angularDamping_, variableDirection::toclient, new NetworkCallback<WorldEntity>(this, &WorldEntity::angularDampingChanged));
153        registerVariable(this->friction_,       variableDirection::toclient, new NetworkCallback<WorldEntity>(this, &WorldEntity::frictionChanged));
154        registerVariable(this->bCollisionCallbackActive_,
155                                                variableDirection::toclient, new NetworkCallback<WorldEntity>(this, &WorldEntity::collisionCallbackActivityChanged));
156        registerVariable((int&)this->collisionTypeSynchronised_,
157                                                variableDirection::toclient, new NetworkCallback<WorldEntity>(this, &WorldEntity::collisionTypeChanged));
158        registerVariable(this->bPhysicsActiveSynchronised_,
159                                                variableDirection::toclient, new NetworkCallback<WorldEntity>(this, &WorldEntity::physicsActivityChanged));
160
161        // Attach to parent if necessary
162        registerVariable(this->parentID_,       variableDirection::toclient, new NetworkCallback<WorldEntity>(this, &WorldEntity::parentChanged));
163    }
164
165    void WorldEntity::parentChanged()
166    {
167        if (this->parentID_ != OBJECTID_UNKNOWN)
168        {
169            WorldEntity* parent = dynamic_cast<WorldEntity*>(Synchronisable::getSynchronisable(this->parentID_));
170            if (parent)
171                this->attachToParent(parent);
172        }
173    }
174
175    void WorldEntity::collisionTypeChanged()
176    {
177        if (this->collisionTypeSynchronised_ != Dynamic &&
178            this->collisionTypeSynchronised_ != Kinematic &&
179            this->collisionTypeSynchronised_ != Static &&
180            this->collisionTypeSynchronised_ != None)
181        {
182            CCOUT(1) << "Error when collsion Type was received over network. Unknown enum value:" << this->collisionTypeSynchronised_ << std::endl;
183        }
184        else if (this->collisionTypeSynchronised_ != collisionType_)
185        {
186            if (this->parent_)
187                CCOUT(2) << "Warning: Network connection tried to set the collision type of an attached WE. Ignoring." << std::endl;
188            else
189                this->setCollisionType(this->collisionTypeSynchronised_);
190        }
191    }
192
193    void WorldEntity::physicsActivityChanged()
194    {
195        if (this->bPhysicsActiveSynchronised_)
196            this->activatePhysics();
197        else
198            this->deactivatePhysics();
199    }
200
201    void WorldEntity::collisionCallbackActivityChanged()
202    {
203        if (this->hasPhysics())
204        {
205            if (bCollisionCallbackActive_)
206                this->physicalBody_->setCollisionFlags(this->physicalBody_->getCollisionFlags() |
207                    btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
208            else
209                this->physicalBody_->setCollisionFlags(this->physicalBody_->getCollisionFlags() &
210                    ~btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
211        }
212    }
213
214    void WorldEntity::attach(WorldEntity* object)
215    {
216        // check first whether attaching is even allowed
217        if (object->hasPhysics())
218        {
219            if (!this->hasPhysics())
220            {
221                COUT(2) << "Warning: Cannot attach a physical object to a non physical one." << std::endl;
222                return;
223            }
224            else if (object->isDynamic())
225            {
226                COUT(2) << "Warning: Cannot attach a dynamic object to a WorldEntity." << std::endl;
227                return;
228            }
229            else if (object->isKinematic() && this->isDynamic())
230            {
231                COUT(2) << "Warning: Cannot attach a kinematic object to a dynamic one." << std::endl;
232                return;
233            }
234            else if (object->isKinematic())
235            {
236                COUT(2) << "Warning: Cannot attach a kinematic object to a static or kinematic one: Not yet implemented." << std::endl;
237                return;
238            }
239            else
240            {
241                object->deactivatePhysics();
242            }
243        }
244
245        if (object->getParent())
246            object->detachFromParent();
247        else
248        {
249            Ogre::Node* parent = object->node_->getParent();
250            if (parent)
251                parent->removeChild(object->node_);
252        }
253
254        this->node_->addChild(object->node_);
255        this->children_.insert(object);
256        object->parent_ = this;
257        object->parentID_ = this->getObjectID();
258
259        // collision shapes
260        this->attachCollisionShape(object->getCollisionShape());
261        // mass
262        this->childrenMass_ += object->getMass();
263        recalculateMassProps();
264    }
265
266    void WorldEntity::detach(WorldEntity* object)
267    {
268        // collision shapes
269        this->detachCollisionShape(object->getCollisionShape());
270        // mass
271        if (object->getMass() > 0.0f)
272        {
273            this->childrenMass_ -= object->getMass();
274            recalculateMassProps();
275        }
276
277        this->node_->removeChild(object->node_);
278        this->children_.erase(object);
279        object->parent_ = 0;
280        object->parentID_ = OBJECTID_UNKNOWN;
281//        this->getScene()->getRootSceneNode()->addChild(object->node_);
282
283        // Note: It is possible that the object has physics but was disabled when attaching
284        object->activatePhysics();
285    }
286
287    WorldEntity* WorldEntity::getAttachedObject(unsigned int index) const
288    {
289        unsigned int i = 0;
290        for (std::set<WorldEntity*>::const_iterator it = this->children_.begin(); it != this->children_.end(); ++it)
291        {
292            if (i == index)
293                return (*it);
294            ++i;
295        }
296        return 0;
297    }
298
299    void WorldEntity::attachOgreObject(Ogre::MovableObject* object)
300    {
301        this->node_->attachObject(object);
302    }
303
304    void WorldEntity::detachOgreObject(Ogre::MovableObject* object)
305    {
306        this->node_->detachObject(object);
307    }
308
309    Ogre::MovableObject* WorldEntity::detachOgreObject(const Ogre::String& name)
310    {
311        return this->node_->detachObject(name);
312    }
313
314    void WorldEntity::attachCollisionShape(CollisionShape* shape)
315    {
316        this->collisionShape_->addChildShape(shape);
317        // Note: this->collisionShape_ already notifies us of any changes.
318    }
319
320    void WorldEntity::detachCollisionShape(CollisionShape* shape)
321    {
322        this->collisionShape_->removeChildShape(shape);
323        // Note: this->collisionShape_ already notifies us of any changes.
324    }
325
326    CollisionShape* WorldEntity::getAttachedCollisionShape(unsigned int index) const
327    {
328        return this->collisionShape_->getChildShape(index);
329    }
330
331    void WorldEntity::activatePhysics()
332    {
333        if (this->isActive() && this->hasPhysics() && !this->isPhysicsActive() && !this->parent_)
334        {
335            this->getScene()->addPhysicalObject(this);
336            this->bPhysicsActive_ = true;
337        }
338    }
339
340    void WorldEntity::deactivatePhysics()
341    {
342        if (this->isPhysicsActive())
343        {
344            this->getScene()->removePhysicalObject(this);
345            this->bPhysicsActive_ = false;
346        }
347    }
348
349    bool WorldEntity::addedToPhysicalWorld() const
350    {
351        return this->physicalBody_ && this->physicalBody_->isInWorld();
352    }
353
354#ifndef _NDEBUG
355    const Vector3& WorldEntity::getPosition() const
356    {
357        return this->node_->getPosition();
358    }
359
360    const Quaternion& WorldEntity::getOrientation() const
361    {
362        return this->node_->getOrientation();
363    }
364
365    const Vector3& WorldEntity::getScale3D() const
366    {
367        return this->node_->getScale();
368    }
369#endif
370
371    const Vector3& WorldEntity::getWorldPosition() const
372    {
373        return this->node_->_getDerivedPosition();
374    }
375
376    const Quaternion& WorldEntity::getWorldOrientation() const
377    {
378        return this->node_->_getDerivedOrientation();
379    }
380
381    void WorldEntity::translate(const Vector3& distance, TransformSpace::Space relativeTo)
382    {
383        switch (relativeTo)
384        {
385        case TransformSpace::Local:
386            // position is relative to parent so transform downwards
387            this->setPosition(this->getPosition() + this->getOrientation() * distance);
388            break;
389        case TransformSpace::Parent:
390            this->setPosition(this->getPosition() + distance);
391            break;
392        case TransformSpace::World:
393            // position is relative to parent so transform upwards
394            if (this->node_->getParent())
395                setPosition(getPosition() + (node_->getParent()->_getDerivedOrientation().Inverse() * distance)
396                    / node_->getParent()->_getDerivedScale());
397            else
398                this->setPosition(this->getPosition() + distance);
399            break;
400        }
401    }
402
403    void WorldEntity::rotate(const Quaternion& rotation, TransformSpace::Space relativeTo)
404    {
405        switch(relativeTo)
406        {
407        case TransformSpace::Local:
408            this->setOrientation(this->getOrientation() * rotation);
409            break;
410        case TransformSpace::Parent:
411            // Rotations are normally relative to local axes, transform up
412            this->setOrientation(rotation * this->getOrientation());
413            break;
414        case TransformSpace::World:
415            // Rotations are normally relative to local axes, transform up
416            this->setOrientation(this->getOrientation() * this->getWorldOrientation().Inverse()
417                * rotation * this->getWorldOrientation());
418            break;
419        }
420    }
421
422    void WorldEntity::lookAt(const Vector3& target, TransformSpace::Space relativeTo, const Vector3& localDirectionVector)
423    {
424        Vector3 origin;
425        switch (relativeTo)
426        {
427        case TransformSpace::Local:
428            origin = Vector3::ZERO;
429            break;
430        case TransformSpace::Parent:
431            origin = this->getPosition();
432            break;
433        case TransformSpace::World:
434            origin = this->getWorldPosition();
435            break;
436        }
437        this->setDirection(target - origin, relativeTo, localDirectionVector);
438    }
439
440    void WorldEntity::setDirection(const Vector3& direction, TransformSpace::Space relativeTo, const Vector3& localDirectionVector)
441    {
442        Quaternion savedOrientation(this->getOrientation());
443        Ogre::Node::TransformSpace ogreRelativeTo;
444        switch (relativeTo)
445        {
446        case TransformSpace::Local:
447            ogreRelativeTo = Ogre::Node::TS_LOCAL; break;
448        case TransformSpace::Parent:
449            ogreRelativeTo = Ogre::Node::TS_PARENT; break;
450        case TransformSpace::World:
451            ogreRelativeTo = Ogre::Node::TS_WORLD; break;
452        }
453        this->node_->setDirection(direction, ogreRelativeTo, localDirectionVector);
454        Quaternion newOrientation(this->node_->getOrientation());
455        this->node_->setOrientation(savedOrientation);
456        this->setOrientation(newOrientation);
457    }
458
459    void WorldEntity::setScale3D(const Vector3& scale)
460    {
461        if (this->hasPhysics() && scale != Vector3::UNIT_SCALE)
462        {
463            CCOUT(2) << "Warning: Cannot set the scale of a physical object: Not yet implemented." << std::endl;
464            return;
465        }
466
467        this->node_->setScale(scale);
468    }
469
470    void WorldEntity::setCollisionType(CollisionType type)
471    {
472        // If we are already attached to a parent, this would be a bad idea..
473        if (this->parent_)
474        {
475            CCOUT(2) << "Warning: Cannot set the collision type of a WorldEntity with a parent." << std::endl;
476            return;
477        }
478        else if (this->addedToPhysicalWorld())
479        {
480            CCOUT(2) << "Warning: Cannot set the collision type at run time." << std::endl;
481            return;
482        }
483
484        // Check for type legality. Could be StaticEntity or MobileEntity
485        if (!this->isCollisionTypeLegal(type))
486            return;
487        if (type != None && !this->getScene()->hasPhysics())
488        {
489            CCOUT(2) << "Warning: Cannot have physical bodies in a non physical scene." << std::endl;
490            return;
491        }
492
493        // Check whether we have to create or destroy.
494        if (type != None && this->collisionType_ == None)
495        {
496            // Check whether there was some scaling applied.
497            if (!this->node_->getScale().positionEquals(Vector3(1, 1, 1), 0.001))
498            {
499                CCOUT(2) << "Warning: Cannot create a physical body if there is scaling applied to the node: Not yet implemented." << std::endl;
500                return;
501            }
502
503            // Create new rigid body
504            btRigidBody::btRigidBodyConstructionInfo bodyConstructionInfo(0, this, this->collisionShape_->getCollisionShape());
505            this->physicalBody_ = new btRigidBody(bodyConstructionInfo);
506            this->physicalBody_->setUserPointer(this);
507            this->physicalBody_->setActivationState(DISABLE_DEACTIVATION);
508        }
509        else if (type == None && this->collisionType_ != None)
510        {
511            // Destroy rigid body
512            assert(this->physicalBody_);
513            deactivatePhysics();
514            delete this->physicalBody_;
515            this->physicalBody_ = 0;
516            this->collisionType_ = None;
517            this->collisionTypeSynchronised_ = None;
518            return;
519        }
520
521        // Change type
522        switch (type)
523        {
524        case Dynamic:
525            this->physicalBody_->setCollisionFlags(this->physicalBody_->getCollisionFlags() & !(btCollisionObject::CF_STATIC_OBJECT | btCollisionObject::CF_KINEMATIC_OBJECT));
526            break;
527        case Kinematic:
528            this->physicalBody_->setCollisionFlags(this->physicalBody_->getCollisionFlags() & !btCollisionObject::CF_STATIC_OBJECT | btCollisionObject::CF_KINEMATIC_OBJECT);
529            break;
530        case Static:
531            this->physicalBody_->setCollisionFlags(this->physicalBody_->getCollisionFlags() & !btCollisionObject::CF_KINEMATIC_OBJECT | btCollisionObject::CF_STATIC_OBJECT);
532            break;
533        case None:
534            return; // this->collisionType_ was None too
535        }
536
537        // Only sets this->collisionShape_
538        // However the assertion is to ensure that the internal bullet setting is right
539        updateCollisionType();
540        assert(this->collisionType_ == type);
541
542        // update mass and inertia tensor
543        recalculateMassProps();
544        resetPhysicsProps();
545        collisionCallbackActivityChanged();
546        activatePhysics();
547    }
548
549    void WorldEntity::setCollisionTypeStr(const std::string& typeStr)
550    {
551        std::string typeStrLower = getLowercase(typeStr);
552        CollisionType type;
553        if (typeStrLower == "dynamic")
554            type = Dynamic;
555        else if (typeStrLower == "static")
556            type = Static;
557        else if (typeStrLower == "kinematic")
558            type = Kinematic;
559        else if (typeStrLower == "none")
560            type = None;
561        else
562            ThrowException(ParseError, std::string("Attempting to set an unknown collision type: '") + typeStr + "'.");
563        this->setCollisionType(type);
564    }
565
566    std::string WorldEntity::getCollisionTypeStr() const
567    {
568        switch (this->getCollisionType())
569        {
570            case Dynamic:
571                return "dynamic";
572            case Kinematic:
573                return "kinematic";
574            case Static:
575                return "static";
576            case None:
577                return "none";
578            default:
579                assert(false);
580                return "";
581        }
582    }
583
584    void WorldEntity::updateCollisionType()
585    {
586        if (!this->physicalBody_)
587            this->collisionType_ = None;
588        else if (this->physicalBody_->isKinematicObject())
589            this->collisionType_ = Kinematic;
590        else if (this->physicalBody_->isStaticObject())
591            this->collisionType_ = Static;
592        else
593            this->collisionType_ = Dynamic;
594        this->collisionTypeSynchronised_ = this->collisionType_;
595    }
596
597    void WorldEntity::notifyChildMassChanged() // Called by a child WE
598    {
599        // Note: CollisionShape changes of a child get handled over the internal CompoundCollisionShape already
600        // Recalculate mass
601        this->childrenMass_ = 0.0f;
602        for (std::set<WorldEntity*>::const_iterator it = this->children_.begin(); it != this->children_.end(); ++it)
603            this->childrenMass_ += (*it)->getMass();
604        recalculateMassProps();
605        // Notify parent WE
606        if (this->parent_)
607            parent_->notifyChildMassChanged();
608    }
609
610    void WorldEntity::notifyCollisionShapeChanged() // called by this->collisionShape_
611    {
612        if (hasPhysics())
613        {
614            // Bullet doesn't like sudden changes of the collision shape, so we remove and add it again
615            if (this->addedToPhysicalWorld())
616            {
617                this->deactivatePhysics();
618                this->physicalBody_->setCollisionShape(this->collisionShape_->getCollisionShape());
619                this->activatePhysics();
620            }
621            else
622                this->physicalBody_->setCollisionShape(this->collisionShape_->getCollisionShape());
623        }
624        recalculateMassProps();
625    }
626
627    void WorldEntity::recalculateMassProps()
628    {
629        // Store local inertia for faster access. Evaluates to (0,0,0) if there is no collision shape.
630        float totalMass = this->mass_ + this->childrenMass_;
631        this->collisionShape_->calculateLocalInertia(totalMass, this->localInertia_);
632        if (this->hasPhysics())
633        {
634            if (this->isStatic())
635            {
636                // Just set everything to zero
637                this->physicalBody_->setMassProps(0.0f, btVector3(0, 0, 0));
638            }
639            else if ((this->mass_ + this->childrenMass_) == 0.0f)
640            {
641                // Use default values to avoid very large or very small values
642                CCOUT(4) << "Warning: Setting the internal physical mass to 1.0 because mass_ is 0.0." << std::endl;
643                btVector3 inertia(0, 0, 0);
644                this->collisionShape_->calculateLocalInertia(1.0f, inertia);
645                this->physicalBody_->setMassProps(1.0f, inertia);
646            }
647            else
648            {
649                this->physicalBody_->setMassProps(totalMass, this->localInertia_);
650            }
651        }
652    }
653
654    void WorldEntity::resetPhysicsProps()
655    {
656        if (this->hasPhysics())
657        {
658            this->physicalBody_->setRestitution(this->restitution_);
659            this->physicalBody_->setAngularFactor(this->angularFactor_);
660            this->physicalBody_->setDamping(this->linearDamping_, this->angularDamping_);
661            this->physicalBody_->setFriction(this->friction_);
662        }
663    }
664}
Note: See TracBrowser for help on using the repository browser.