Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/pch/src/orxonox/objects/collisionshapes/CompoundCollisionShape.cc @ 3149

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

Extracted OrxAssert from Exception.h to OrxAssert.h since it doesn't really have anything to do with exceptions.

  • 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 "CompoundCollisionShape.h"
30
31#include "BulletCollision/CollisionShapes/btCompoundShape.h"
32
33#include "core/CoreIncludes.h"
34#include "core/XMLPort.h"
35#include "tools/BulletConversions.h"
36
37namespace orxonox
38{
39    CreateFactory(CompoundCollisionShape);
40
41    CompoundCollisionShape::CompoundCollisionShape(BaseObject* creator) : CollisionShape(creator)
42    {
43        RegisterObject(CompoundCollisionShape);
44
45        this->compoundShape_  = new btCompoundShape();
46    }
47
48    CompoundCollisionShape::~CompoundCollisionShape()
49    {
50        if (this->isInitialized())
51        {
52            // Delete all children
53            for (std::map<CollisionShape*, btCollisionShape*>::iterator it = this->attachedShapes_.begin();
54                it != this->attachedShapes_.end(); ++it)
55            {
56                // make sure that the child doesn't want to detach itself --> speedup because of the missing update
57                it->first->notifyDetached();
58                delete it->first;
59            }
60
61            delete this->compoundShape_;
62        }
63    }
64
65    void CompoundCollisionShape::XMLPort(Element& xmlelement, XMLPort::Mode mode)
66    {
67        SUPER(CompoundCollisionShape, XMLPort, xmlelement, mode);
68        // Attached collision shapes
69        XMLPortObject(CompoundCollisionShape, CollisionShape, "", attach, detach, xmlelement, mode);
70    }
71
72    void CompoundCollisionShape::attach(CollisionShape* shape)
73    {
74        if (!shape || static_cast<CollisionShape*>(this) == shape)
75            return;
76        if (this->attachedShapes_.find(shape) != this->attachedShapes_.end())
77        {
78            CCOUT(2) << "Warning: Attaching a CollisionShape twice is not yet supported." << std::endl;
79            return;
80        }
81
82        if (!shape->notifyBeingAttached(this))
83            return;
84
85        this->attachedShapes_[shape] = shape->getCollisionShape();
86
87        if (shape->getCollisionShape())
88        {
89            // Only actually attach if we didn't pick a CompoundCollisionShape with no content
90            btTransform transf(multi_cast<btQuaternion>(shape->getOrientation()), multi_cast<btVector3>(shape->getPosition()));
91            this->compoundShape_->addChildShape(transf, shape->getCollisionShape());
92
93            this->updatePublicShape();
94        }
95    }
96
97    void CompoundCollisionShape::detach(CollisionShape* shape)
98    {
99        if (this->attachedShapes_.find(shape) != this->attachedShapes_.end())
100        {
101            this->attachedShapes_.erase(shape);
102            if (shape->getCollisionShape())
103                this->compoundShape_->removeChildShape(shape->getCollisionShape());
104            shape->notifyDetached();
105
106            this->updatePublicShape();
107        }
108        else
109            CCOUT(2) << "Warning: Cannot detach non child collision shape" << std::endl;
110    }
111
112    void CompoundCollisionShape::detachAll()
113    {
114        while (this->attachedShapes_.size() > 0)
115            this->detach(this->attachedShapes_.begin()->first);
116    }
117
118    void CompoundCollisionShape::updateAttachedShape(CollisionShape* shape)
119    {
120        if (!shape)
121            return;
122        std::map<CollisionShape*, btCollisionShape*>::iterator it = this->attachedShapes_.find(shape);
123        if (it == this->attachedShapes_.end())
124        {
125            CCOUT(2) << "Warning: Cannot update child shape: Instance not a child." << std::endl;
126            return;
127        }
128
129        // Remove old btCollisionShape, stored in the children map
130        if (it->second)
131            this->compoundShape_->removeChildShape(it->second);
132        if (shape->getCollisionShape())
133        {
134            // Only actually attach if we didn't pick a CompoundCollisionShape with no content
135            btTransform transf(multi_cast<btQuaternion>(shape->getOrientation()), multi_cast<btVector3>(shape->getPosition()));
136            this->compoundShape_->addChildShape(transf, shape->getCollisionShape());
137            it->second = shape->getCollisionShape();
138        }
139
140        this->updatePublicShape();
141    }
142
143    void CompoundCollisionShape::updatePublicShape()
144    {
145        btCollisionShape* primitive = 0;
146        bool bPrimitive = true;
147        bool bEmpty = true;
148        for (std::map<CollisionShape*, btCollisionShape*>::const_iterator it = this->attachedShapes_.begin(); it != this->attachedShapes_.end(); ++it)
149        {
150            if (it->second)
151            {
152                bEmpty = false;
153                if (!it->first->hasTransform() && !bPrimitive)
154                    primitive = it->second;
155                else
156                    bPrimitive = false;
157            }
158        }
159        if (bEmpty)
160        {
161            if (this->collisionShape_ == 0)
162            {
163                this->collisionShape_ = 0;
164                return;
165            }
166            this->collisionShape_ = 0;
167        }
168        else if (bPrimitive)
169        {
170            // --> Only one shape to be added, no transform; return it directly
171            this->collisionShape_ = primitive;
172        }
173        else
174        {
175            // Make sure we use the compound shape when returning a btCollisionShape
176            this->collisionShape_ = this->compoundShape_;
177        }
178        this->updateParent();
179    }
180
181    CollisionShape* CompoundCollisionShape::getAttachedShape(unsigned int index) const
182    {
183        unsigned int i = 0;
184        for (std::map<CollisionShape*, btCollisionShape*>::const_iterator it = this->attachedShapes_.begin(); it != this->attachedShapes_.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.