Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/physics/src/orxonox/objects/collisionshapes/CompoundCollisionShape.cc @ 2518

Last change on this file since 2518 was 2433, checked in by rgrieder, 16 years ago

Replaced most Exception throwing considering physics with warnings. Actions are simply ignored then.

  • Property svn:eol-style set to native
File size: 6.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 *      Reto Grieder
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include "OrxonoxStableHeaders.h"
30#include "CompoundCollisionShape.h"
31
32#include "BulletCollision/CollisionShapes/btCompoundShape.h"
33
34#include "util/Exception.h"
35#include "core/CoreIncludes.h"
36#include "core/XMLPort.h"
37#include "tools/BulletConversions.h"
38#include "objects/worldentities/WorldEntity.h"
39
40namespace orxonox
41{
42    CreateFactory(CompoundCollisionShape);
43
44    CompoundCollisionShape::CompoundCollisionShape(BaseObject* creator) : CollisionShape(creator)
45    {
46        RegisterObject(CompoundCollisionShape);
47
48        this->compoundShape_  = new btCompoundShape();
49    }
50
51    CompoundCollisionShape::~CompoundCollisionShape()
52    {
53        if (this->isInitialized())
54        {
55            // Detatch all children first
56            this->removeAllChildShapes();
57            delete this->compoundShape_;
58        }
59    }
60
61    void CompoundCollisionShape::XMLPort(Element& xmlelement, XMLPort::Mode mode)
62    {
63        SUPER(CompoundCollisionShape, XMLPort, xmlelement, mode);
64        // Attached collision shapes
65        XMLPortObject(CompoundCollisionShape, CollisionShape, "", addChildShape, getChildShape, xmlelement, mode);
66    }
67
68    void CompoundCollisionShape::addChildShape(CollisionShape* shape)
69    {
70        if (!shape || static_cast<CollisionShape*>(this) == shape)
71            return;
72        if (this->childShapes_.find(shape) != this->childShapes_.end())
73        {
74            CCOUT(2) << "Warning: Attaching a CollisionShape twice is not yet supported." << std::endl;
75            return;
76        }
77        this->childShapes_[shape] = shape->getCollisionShape();
78
79        if (shape->getCollisionShape())
80        {
81            // Only actually attach if we didn't pick a CompoundCollisionShape with no content
82            btTransform transf(omni_cast<btQuaternion>(shape->getOrientation()), omni_cast<btVector3>(shape->getPosition()));
83            this->compoundShape_->addChildShape(transf, shape->getCollisionShape());
84
85            this->updatePublicShape();
86        }
87
88        // network synchro
89        shape->setParent(this, this->getObjectID());
90    }
91
92    void CompoundCollisionShape::removeChildShape(CollisionShape* shape)
93    {
94        if (this->childShapes_.find(shape) != this->childShapes_.end())
95        {
96            shape->setParent(0, (unsigned int)-1);
97            this->childShapes_.erase(shape);
98            if (shape->getCollisionShape())
99                this->compoundShape_->removeChildShape(shape->getCollisionShape());
100
101            this->updatePublicShape();
102        }
103    }
104
105    void CompoundCollisionShape::removeAllChildShapes()
106    {
107        while (this->childShapes_.size() > 0)
108            this->removeChildShape(this->childShapes_.begin()->first);
109    }
110
111    void CompoundCollisionShape::updateChildShape(CollisionShape* shape)
112    {
113        if (!shape)
114            return;
115        std::map<CollisionShape*, btCollisionShape*>::iterator it = this->childShapes_.find(shape);
116        if (it == this->childShapes_.end())
117        {
118            CCOUT(2) << "Warning: Cannot update child shape: Instance not a child." << std::endl;
119            return;
120        }
121
122        // Remove old btCollisionShape, stored in the children map
123        if (it->second)
124            this->compoundShape_->removeChildShape(it->second);
125        if (shape->getCollisionShape())
126        {
127            // Only actually attach if we didn't pick a CompoundCollisionShape with no content
128            btTransform transf(omni_cast<btQuaternion>(shape->getOrientation()), omni_cast<btVector3>(shape->getPosition()));
129            this->compoundShape_->addChildShape(transf, shape->getCollisionShape());
130            it->second = shape->getCollisionShape();
131        }
132
133        this->updatePublicShape();
134    }
135
136    void CompoundCollisionShape::updatePublicShape()
137    {
138        btCollisionShape* primitive = 0;
139        bool bPrimitive = true;
140        bool bEmpty = true;
141        for (std::map<CollisionShape*, btCollisionShape*>::const_iterator it = this->childShapes_.begin(); it != this->childShapes_.end(); ++it)
142        {
143            if (it->second)
144            {
145                bEmpty = false;
146                if (!it->first->hasTransform())
147                    primitive = it->second;
148                else
149                    bPrimitive = false;
150            }
151        }
152        if (bEmpty)
153            this->collisionShape_ = 0;
154        else if (bPrimitive)
155        {
156            // --> Only one shape to be added, no transform; return it directly
157            this->collisionShape_ = primitive;
158        }
159        else
160        {
161            // Make sure we use the compound shape when returning a btCollisionShape
162            this->collisionShape_ = this->compoundShape_;
163        }
164        this->updateParent();
165    }
166
167    void CompoundCollisionShape::updateParent()
168    {
169        if (this->parent_)
170            this->parent_->updateChildShape(this);
171        else
172        {
173            // We can do this, because the CompoundCollisionShape of a WorldEntity always belongs to it,
174            // as long as its lifetime.
175            WorldEntity* parent = dynamic_cast<WorldEntity*>(this->getCreator());
176            if (parent)
177                parent->notifyCollisionShapeChanged();
178        }
179    }
180
181    CollisionShape* CompoundCollisionShape::getChildShape(unsigned int index) const
182    {
183        unsigned int i = 0;
184        for (std::map<CollisionShape*, btCollisionShape*>::const_iterator it = this->childShapes_.begin(); it != this->childShapes_.end(); ++it)
185        {
186            if (i == index)
187                return it->first;
188            ++i;
189        }
190        return 0;
191    }
192}
Note: See TracBrowser for help on using the repository browser.