Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/physics/src/orxonox/objects/worldentities/WorldEntity.cc @ 2426

Last change on this file since 2426 was 2426, checked in by rgrieder, 15 years ago
  • Handled translate, rotate, yaw, pitch, roll, lookAt and setDirection internally in WE. That only leaves setPosition and setOrientation to be pure virtual.
  • Removed loads of redundant and now obsolete code in MobileEntity and StaticEntity
  • Removed OgreSceneNode.h from WorldEntity in debug builds. getPosition, getOrientation and getScale3D are only inline in release mode. That should speed up dev builds a lot (the include is about 8300 line without Vector3, Quaternion, etc.)

Important:

  • Fixed a bug or introduced one: the lookAt(…) function in WE had default TransformSpace "TS_LOCAL", but that makes no sense the way I see it. Consider a SpaceShip and you would like it to face an asteroid. Then TS_LOCAL would yield weird results. The XMLPort attribute "lookAt" used the default value. That's where the bug might have been fixed or (I don't believe so) introduced.
  • Property svn:eol-style set to native
File size: 21.6 KB
RevLine 
[2072]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
[2374]16 *   GNU General Public License for more details.
[2072]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
[2304]24 *      Reto Grieder (physics)
[2072]25 *   Co-authors:
26 *      ...
27 *
28 */
29
30#include "OrxonoxStableHeaders.h"
31#include "WorldEntity.h"
32
33#include <cassert>
[2426]34#include <OgreSceneNode.h>
[2072]35#include <OgreSceneManager.h>
[2303]36#include "BulletDynamics/Dynamics/btRigidBody.h"
[2072]37
[2292]38#include "util/Exception.h"
39#include "util/Convert.h"
[2072]40#include "core/CoreIncludes.h"
41#include "core/XMLPort.h"
42
43#include "objects/Scene.h"
[2407]44#include "objects/collisionshapes/CompoundCollisionShape.h"
[2072]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), network::Synchronisable(creator)
56    {
57        RegisterObject(WorldEntity);
58
59        assert(this->getScene());
60        assert(this->getScene()->getRootSceneNode());
61
62        this->node_ = this->getScene()->getRootSceneNode()->createChildSceneNode();
63
64        this->parent_ = 0;
65        this->parentID_ = (unsigned int)-1;
66
67        this->node_->setPosition(Vector3::ZERO);
68        this->node_->setOrientation(Quaternion::IDENTITY);
69
[2192]70        // Default behaviour does not include physics
71        this->physicalBody_ = 0;
[2423]72        this->bPhysicsActive_ = false;
[2374]73        this->collisionShape_ = new CompoundCollisionShape(this);
[2303]74        this->mass_ = 0;
[2423]75        this->childrenMass_ = 0;
[2306]76        this->collisionType_ = None;
[2374]77        this->collisionTypeSynchronised_ = None;
[2192]78
[2072]79        this->registerVariables();
80    }
81
82    WorldEntity::~WorldEntity()
83    {
84        if (this->isInitialized())
85        {
86            this->node_->detachAllObjects();
87            if (this->getScene()->getSceneManager())
88                this->getScene()->getSceneManager()->destroySceneNode(this->node_->getName());
[2298]89
[2423]90            // TODO: Detach from parent and detach all children.
91
[2313]92            if (this->physicalBody_)
93            {
[2423]94                this->deactivatePhysics();
[2313]95                delete this->physicalBody_;
96            }
[2423]97            delete this->collisionShape_;
[2072]98        }
99    }
100
101    void WorldEntity::XMLPort(Element& xmlelement, XMLPort::Mode mode)
102    {
103        SUPER(WorldEntity, XMLPort, xmlelement, mode);
104
105        XMLPortParamTemplate(WorldEntity, "position", setPosition, getPosition, xmlelement, mode, const Vector3&);
106        XMLPortParamTemplate(WorldEntity, "orientation", setOrientation, getOrientation, xmlelement, mode, const Quaternion&);
107        XMLPortParamLoadOnly(WorldEntity, "lookat", lookAt_xmlport, xmlelement, mode);
108        XMLPortParamLoadOnly(WorldEntity, "direction", setDirection_xmlport, xmlelement, mode);
109        XMLPortParamLoadOnly(WorldEntity, "yaw", yaw_xmlport, xmlelement, mode);
110        XMLPortParamLoadOnly(WorldEntity, "pitch", pitch_xmlport, xmlelement, mode);
111        XMLPortParamLoadOnly(WorldEntity, "roll", roll_xmlport, xmlelement, mode);
112        XMLPortParamTemplate(WorldEntity, "scale3D", setScale3D, getScale3D, xmlelement, mode, const Vector3&);
113        XMLPortParam(WorldEntity, "scale", setScale, getScale, xmlelement, mode);
114
[2374]115        // Physics
[2298]116        XMLPortParam(WorldEntity, "collisionType", setCollisionTypeStr, getCollisionTypeStr, xmlelement, mode);
[2292]117        XMLPortParam(WorldEntity, "mass", setMass, getMass, xmlelement, mode);
118
[2374]119        // Other attached WorldEntities
[2298]120        XMLPortObject(WorldEntity, WorldEntity, "attached", attach, getAttachedObject, xmlelement, mode);
[2374]121        // Attached collision shapes
[2303]122        XMLPortObject(WorldEntity, CollisionShape, "collisionShapes", attachCollisionShape, getAttachedCollisionShape, xmlelement, mode);
[2072]123    }
124
125    void WorldEntity::registerVariables()
126    {
[2374]127        REGISTERDATA(this->bActive_,     network::direction::toclient, new network::NetworkCallback<WorldEntity>(this, &WorldEntity::changedActivity));
128        REGISTERDATA(this->bVisible_,    network::direction::toclient, new network::NetworkCallback<WorldEntity>(this, &WorldEntity::changedVisibility));
[2072]129
[2423]130        REGISTERDATA(this->getScale3D(), network::direction::toclient, new network::NetworkCallback<WorldEntity>(this, &WorldEntity::scaleChanged));
[2072]131
[2423]132        REGISTERDATA((int&)this->collisionTypeSynchronised_,
133                                         network::direction::toclient, new network::NetworkCallback<WorldEntity>(this, &WorldEntity::collisionTypeChanged));
134        REGISTERDATA(this->mass_,        network::direction::toclient, new network::NetworkCallback<WorldEntity>(this, &WorldEntity::massChanged));
135        REGISTERDATA(this->bPhysicsActiveSynchronised_,
136                                         network::direction::toclient, new network::NetworkCallback<WorldEntity>(this, &WorldEntity::physicsActivityChanged));
[2374]137
[2423]138        REGISTERDATA(this->parentID_,    network::direction::toclient, new network::NetworkCallback<WorldEntity>(this, &WorldEntity::updateParent));
[2072]139    }
140
141    void WorldEntity::updateParent()
142    {
143        WorldEntity* parent = dynamic_cast<WorldEntity*>(Synchronisable::getSynchronisable(this->parentID_));
144        if (parent)
145            this->attachToParent(parent);
146    }
147
[2374]148    void WorldEntity::collisionTypeChanged()
149    {
150        if (this->collisionTypeSynchronised_ != Dynamic &&
151            this->collisionTypeSynchronised_ != Kinematic &&
152            this->collisionTypeSynchronised_ != Static &&
153            this->collisionTypeSynchronised_ != None)
154        {
155            CCOUT(1) << "Error when collsion Type was received over network. Unknown enum value:" << this->collisionTypeSynchronised_ << std::endl;
156        }
157        else if (this->collisionTypeSynchronised_ != collisionType_)
158        {
159            if (this->parent_)
160                CCOUT(2) << "Warning: Network connection tried to set the collision type of an attached WE. Ignoring." << std::endl;
161            else
162                this->setCollisionType(this->collisionTypeSynchronised_);
163        }
164    }
165
166    void WorldEntity::massChanged()
167    {
168        this->setMass(this->mass_);
169    }
170
[2423]171    void WorldEntity::physicsActivityChanged()
172    {
173        if (this->bPhysicsActiveSynchronised_)
174            this->activatePhysics();
175        else
176            this->deactivatePhysics();
177    }
178
[2072]179    void WorldEntity::attach(WorldEntity* object)
180    {
[2303]181        // check first whether attaching is even allowed
182        if (object->hasPhysics())
183        {
184            if (!this->hasPhysics())
185                ThrowException(PhysicsViolation, "Cannot attach a physical object to a non physical one.");
186            else if (object->isDynamic())
187                ThrowException(PhysicsViolation, "Cannot attach a dynamic object to a WorldEntity.");
188            else if (object->isKinematic() && this->isDynamic())
189                ThrowException(PhysicsViolation, "Cannot attach a kinematic object to a dynamic one.");
190            else if (object->isKinematic())
191                ThrowException(NotImplemented, "Cannot attach a kinematic object to a static or kinematic one: Not yet implemented.");
192            else
193            {
[2423]194                object->deactivatePhysics();
[2303]195            }
196        }
197
[2072]198        if (object->getParent())
199            object->detachFromParent();
200        else
201        {
202            Ogre::Node* parent = object->node_->getParent();
203            if (parent)
204                parent->removeChild(object->node_);
205        }
206
207        this->node_->addChild(object->node_);
208        this->children_.insert(object);
209        object->parent_ = this;
210        object->parentID_ = this->getObjectID();
[2423]211
212        // collision shapes
213        this->attachCollisionShape(object->getCollisionShape());
214        // mass
215        this->childrenMass_ += object->getMass();
216        recalculatePhysicsProps();
[2072]217    }
218
219    void WorldEntity::detach(WorldEntity* object)
220    {
[2423]221        // collision shapes
222        this->detachCollisionShape(object->getCollisionShape());
223        // mass
224        if (object->getMass() > 0.0f)
225        {
226            this->childrenMass_ -= object->getMass();
227            recalculatePhysicsProps();
228        }
229
[2072]230        this->node_->removeChild(object->node_);
231        this->children_.erase(object);
232        object->parent_ = 0;
233        object->parentID_ = (unsigned int)-1;
[2423]234//        this->getScene()->getRootSceneNode()->addChild(object->node_);
[2072]235
[2423]236        // Note: It is possible that the object has physics but was disabled when attaching
237        object->activatePhysics();
[2072]238    }
239
240    WorldEntity* WorldEntity::getAttachedObject(unsigned int index) const
241    {
242        unsigned int i = 0;
243        for (std::set<WorldEntity*>::const_iterator it = this->children_.begin(); it != this->children_.end(); ++it)
244        {
245            if (i == index)
246                return (*it);
247            ++i;
248        }
249        return 0;
250    }
[2192]251
[2426]252    void WorldEntity::attachOgreObject(Ogre::MovableObject* object)
253    {
254        this->node_->attachObject(object);
255    }
256
257    void WorldEntity::detachOgreObject(Ogre::MovableObject* object)
258    {
259        this->node_->detachObject(object);
260    }
261
262    Ogre::MovableObject* WorldEntity::detachOgreObject(const Ogre::String& name)
263    {
264        return this->node_->detachObject(name);
265    }
266
[2423]267    void WorldEntity::attachCollisionShape(CollisionShape* shape)
[2303]268    {
[2423]269        this->collisionShape_->addChildShape(shape);
270        // Note: this->collisionShape_ already notifies us of any changes.
271    }
[2303]272
[2423]273    void WorldEntity::detachCollisionShape(CollisionShape* shape)
274    {
275        this->collisionShape_->removeChildShape(shape);
276        // Note: this->collisionShape_ already notifies us of any changes.
[2292]277    }
278
[2303]279    CollisionShape* WorldEntity::getAttachedCollisionShape(unsigned int index) const
280    {
[2374]281        return this->collisionShape_->getChildShape(index);
[2303]282    }
283
[2423]284    void WorldEntity::activatePhysics()
[2313]285    {
[2423]286        if (this->isActive() && this->hasPhysics() && !this->isPhysicsActive() && !this->parent_)
287        {
[2313]288            this->getScene()->addRigidBody(this->physicalBody_);
[2423]289            this->bPhysicsActive_ = true;
290        }
[2313]291    }
292
[2423]293    void WorldEntity::deactivatePhysics()
[2313]294    {
[2423]295        if (this->isPhysicsActive())
296        {
[2313]297            this->getScene()->removeRigidBody(this->physicalBody_);
[2423]298            this->bPhysicsActive_ = false;
299        }
[2313]300    }
301
[2423]302    bool WorldEntity::addedToPhysicalWorld() const
303    {
304        return this->physicalBody_ && this->physicalBody_->isInWorld();
305    }
306
[2426]307#ifndef _NDEBUG
308    const Vector3& WorldEntity::getPosition() const
[2303]309    {
[2426]310        return this->node_->getPosition();
311    }
[2303]312
[2426]313    const Quaternion& WorldEntity::getOrientation() const
314    {
315        return this->node_->getOrientation();
[2303]316    }
317
[2426]318    const Vector3& WorldEntity::getScale3D() const
[2303]319    {
[2426]320        return this->node_->getScale();
321    }
322#endif
323
324    const Vector3& WorldEntity::getWorldPosition() const
325    {
326        return this->node_->_getDerivedPosition();
327    }
328
329    const Quaternion& WorldEntity::getWorldOrientation() const
330    {
331        return this->node_->_getDerivedOrientation();
332    }
333
334    void WorldEntity::translate(const Vector3& distance, TransformSpace::Space relativeTo)
335    {
336        switch (relativeTo)
337        {
338        case TransformSpace::Local:
339            // position is relative to parent so transform downwards
340            this->setPosition(this->getPosition() + this->getOrientation() * distance);
341            break;
342        case TransformSpace::Parent:
343            this->setPosition(this->getPosition() + distance);
344            break;
345        case TransformSpace::World:
346            // position is relative to parent so transform upwards
347            if (this->node_->getParent())
348                setPosition(getPosition() + (node_->getParent()->_getDerivedOrientation().Inverse() * distance)
349                    / node_->getParent()->_getDerivedScale());
350            else
351                this->setPosition(this->getPosition() + distance);
352            break;
353        }
354    }
355
356    void WorldEntity::rotate(const Quaternion& rotation, TransformSpace::Space relativeTo)
357    {
358        switch(relativeTo)
359        {
360        case TransformSpace::Local:
361            this->setOrientation(this->getOrientation() * rotation);
362            break;
363        case TransformSpace::Parent:
364            // Rotations are normally relative to local axes, transform up
365            this->setOrientation(rotation * this->getOrientation());
366            break;
367        case TransformSpace::World:
368            // Rotations are normally relative to local axes, transform up
369            this->setOrientation(this->getOrientation() * this->getWorldOrientation().Inverse()
370                * rotation * this->getWorldOrientation());
371            break;
372        }
373    }
374
375    void WorldEntity::lookAt(const Vector3& target, TransformSpace::Space relativeTo, const Vector3& localDirectionVector)
376    {
377        Vector3 origin;
378        switch (relativeTo)
379        {
380        case TransformSpace::Local:
381            origin = Vector3::ZERO;
382            break;
383        case TransformSpace::Parent:
384            origin = this->getPosition();
385            break;
386        case TransformSpace::World:
387            origin = this->getWorldPosition();
388            break;
389        }
390        this->setDirection(target - origin, relativeTo, localDirectionVector);
391    }
392
393    void WorldEntity::setDirection(const Vector3& direction, TransformSpace::Space relativeTo, const Vector3& localDirectionVector)
394    {
395        Quaternion savedOrientation(this->getOrientation());
396        Ogre::Node::TransformSpace ogreRelativeTo;
397        switch (relativeTo)
398        {
399        case TransformSpace::Local:
400            ogreRelativeTo = Ogre::Node::TS_LOCAL; break;
401        case TransformSpace::Parent:
402            ogreRelativeTo = Ogre::Node::TS_PARENT; break;
403        case TransformSpace::World:
404            ogreRelativeTo = Ogre::Node::TS_WORLD; break;
405        }
406        this->node_->setDirection(direction, ogreRelativeTo, localDirectionVector);
407        Quaternion newOrientation(this->node_->getOrientation());
408        this->node_->setOrientation(savedOrientation);
409        this->setOrientation(newOrientation);
410    }
411
412    void WorldEntity::setScale3D(const Vector3& scale)
413    {
[2303]414        if (this->hasPhysics())
415            ThrowException(NotImplemented, "Cannot set the scale of a physical object: Not yet implemented.");
416
[2426]417        this->node_->setScale(scale);
[2303]418    }
419
[2292]420    void WorldEntity::setMass(float mass)
421    {
[2303]422        this->mass_ = mass;
[2423]423        recalculatePhysicsProps();
[2306]424    }
425
[2298]426    void WorldEntity::setCollisionType(CollisionType type)
[2292]427    {
[2303]428        // If we are already attached to a parent, this would be a bad idea..
429        if (this->parent_)
430            ThrowException(PhysicsViolation, "Cannot set the collision type of a WorldEntity with a parent");
[2423]431        else if (this->addedToPhysicalWorld())
[2303]432            ThrowException(PhysicsViolation, "Warning: Cannot set the collision type at run time.");
433
[2408]434        // Check for type legality. Could be StaticEntity or MobileEntity
[2303]435        if (!this->isCollisionTypeLegal(type))
436            return; // exception gets issued anyway
437
438        // Check whether we have to create or destroy.
[2298]439        if (type != None && this->collisionType_ == None)
440        {
[2306]441            // Check whether there was some scaling applied.
442            if (!this->node_->getScale().positionEquals(Vector3(1, 1, 1), 0.001))
443                ThrowException(NotImplemented, "Cannot create a physical body if there is scaling applied to the node: Not yet implemented.");
444
[2298]445            // Create new rigid body
[2303]446            btCollisionShape* temp = 0;
[2423]447            btRigidBody::btRigidBodyConstructionInfo bodyConstructionInfo(0, this, this->collisionShape_->getCollisionShape());
448            bodyConstructionInfo.m_restitution = 1;
[2298]449            this->physicalBody_ = new btRigidBody(bodyConstructionInfo);
450            this->physicalBody_->setUserPointer(this);
[2374]451            this->physicalBody_->setActivationState(DISABLE_DEACTIVATION);
[2298]452        }
453        else if (type == None && this->collisionType_ != None)
454        {
455            // Destroy rigid body
[2313]456            assert(this->physicalBody_);
[2423]457            deactivatePhysics();
[2298]458            delete this->physicalBody_;
459            this->physicalBody_ = 0;
460            this->collisionType_ = None;
[2374]461            this->collisionTypeSynchronised_ = None;
[2298]462            return;
463        }
464
465        // Change type
[2292]466        switch (type)
467        {
468        case Dynamic:
469            this->physicalBody_->setCollisionFlags(this->physicalBody_->getCollisionFlags() & !(btCollisionObject::CF_STATIC_OBJECT | btCollisionObject::CF_KINEMATIC_OBJECT));
470            break;
471        case Kinematic:
472            this->physicalBody_->setCollisionFlags(this->physicalBody_->getCollisionFlags() & !btCollisionObject::CF_STATIC_OBJECT | btCollisionObject::CF_KINEMATIC_OBJECT);
473            break;
474        case Static:
475            this->physicalBody_->setCollisionFlags(this->physicalBody_->getCollisionFlags() & !btCollisionObject::CF_KINEMATIC_OBJECT | btCollisionObject::CF_STATIC_OBJECT);
476            break;
[2298]477        case None:
478            return; // this->collisionType_ was None too
[2292]479        }
[2298]480
[2423]481        // Only sets this->collisionShape_
482        // However the assertion is to ensure that the internal bullet setting is right
[2303]483        updateCollisionType();
[2306]484        assert(this->collisionType_ == type);
[2303]485
[2306]486        // update mass and inertia tensor
[2423]487        recalculatePhysicsProps();
488        activatePhysics();
[2292]489    }
490
[2298]491    void WorldEntity::setCollisionTypeStr(const std::string& typeStr)
[2292]492    {
[2298]493        std::string typeStrLower = getLowercase(typeStr);
494        CollisionType type;
495        if (typeStrLower == "dynamic")
496            type = Dynamic;
497        else if (typeStrLower == "static")
498            type = Static;
499        else if (typeStrLower == "kinematic")
500            type = Kinematic;
501        else if (typeStrLower == "none")
502            type = None;
[2292]503        else
[2298]504            ThrowException(ParseError, std::string("Attempting to set an unknown collision type: '") + typeStr + "'.");
505        this->setCollisionType(type);
[2292]506    }
507
[2300]508    std::string WorldEntity::getCollisionTypeStr() const
[2292]509    {
510        switch (this->getCollisionType())
511        {
[2298]512            case Dynamic:
513                return "dynamic";
514            case Kinematic:
515                return "kinematic";
516            case Static:
517                return "static";
518            case None:
519                return "none";
520            default:
521                assert(false);
522                return "";
[2292]523        }
524    }
525
[2306]526    void WorldEntity::updateCollisionType()
527    {
528        if (!this->physicalBody_)
529            this->collisionType_ = None;
530        else if (this->physicalBody_->isKinematicObject())
531            this->collisionType_ = Kinematic;
532        else if (this->physicalBody_->isStaticObject())
533            this->collisionType_ = Static;
534        else
535            this->collisionType_ = Dynamic;
[2374]536        this->collisionTypeSynchronised_ = this->collisionType_;
[2306]537    }
538
[2423]539    void WorldEntity::notifyChildMassChanged() // Called by a child WE
[2374]540    {
[2423]541        // Note: CollisionShape changes of a child get handled over the internal CompoundCollisionShape already
542        // Recalculate mass
543        this->childrenMass_ = 0.0f;
544        for (std::set<WorldEntity*>::const_iterator it = this->children_.begin(); it != this->children_.end(); ++it)
545            this->childrenMass_ += (*it)->getMass();
546        recalculatePhysicsProps();
547        // Notify parent WE
548        if (this->parent_)
549            parent_->notifyChildMassChanged();
[2374]550    }
551
[2423]552    void WorldEntity::notifyCollisionShapeChanged() // called by this->collisionShape_
[2298]553    {
[2423]554        if (hasPhysics())
[2298]555        {
[2423]556            // Bullet doesn't like sudden changes of the collision shape, so we remove and add it again
557            if (this->addedToPhysicalWorld())
558            {
559                this->deactivatePhysics();
560                this->physicalBody_->setCollisionShape(this->collisionShape_->getCollisionShape());
561                this->activatePhysics();
562            }
563            else
564                this->physicalBody_->setCollisionShape(this->collisionShape_->getCollisionShape());
[2298]565        }
[2423]566        recalculatePhysicsProps();
[2298]567    }
[2423]568
569    void WorldEntity::recalculatePhysicsProps()
570    {
571        if (this->hasPhysics())
572        {
573            if (this->isStatic())
574            {
575                // Just set everything to zero
576                this->physicalBody_->setMassProps(0.0f, btVector3(0, 0, 0));
577            }
578            else if ((this->mass_ + this->childrenMass_) == 0.0f)
579            {
580                // Use default values to avoid very large or very small values
581                CCOUT(4) << "Warning: Setting the internal physical mass to 1.0 because mass_ is 0.0." << std::endl;
582                this->physicalBody_->setMassProps(1.0f, this->collisionShape_->getLocalInertia(1.0f));
583            }
584            else
585            {
586                float mass = this->mass_ + this->childrenMass_;
587                this->physicalBody_->setMassProps(mass, this->collisionShape_->getLocalInertia(mass));
588            }
589        }
590    }
[2072]591}
Note: See TracBrowser for help on using the repository browser.