Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/collisionshapes/CompoundCollisionShape.cc @ 8786

Last change on this file since 8786 was 8706, checked in by dafrick, 13 years ago

Merging presentation branch back into trunk.
There are many new features and also a lot of other changes and bugfixes, if you want to know, digg through the svn log.
Not everything is yet working as it should, but it should be fairly stable. If you habe any bug reports, just send me an email.

  • Property svn:eol-style set to native
File size: 10.7 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/**
30    @file CompoundCollisionShape.cc
31    @brief Implementation of the CompoundCollisionShape class.
32*/
33
34#include "CompoundCollisionShape.h"
35
36#include <BulletCollision/CollisionShapes/btCompoundShape.h>
37
38#include "core/CoreIncludes.h"
39#include "core/XMLPort.h"
40#include "tools/BulletConversions.h"
41
42namespace orxonox
43{
44    CreateFactory(CompoundCollisionShape);
45
46    /**
47    @brief
48        Constructor. Registers and initializes the object.
49    */
50    CompoundCollisionShape::CompoundCollisionShape(BaseObject* creator) : CollisionShape(creator)
51    {
52        RegisterObject(CompoundCollisionShape);
53
54        this->compoundShape_  = new btCompoundShape();
55    }
56
57    /**
58    @brief
59        Destructor.
60        Deletes all its children.
61    */
62    CompoundCollisionShape::~CompoundCollisionShape()
63    {
64        if (this->isInitialized())
65        {
66            // Delete all children
67            for (std::map<CollisionShape*, btCollisionShape*>::iterator it = this->attachedShapes_.begin();
68                it != this->attachedShapes_.end(); ++it)
69            {
70                // make sure that the child doesn't want to detach itself --> speedup because of the missing update
71                it->first->notifyDetached();
72                it->first->destroy();
73            }
74
75            delete this->compoundShape_;
76        }
77    }
78
79    void CompoundCollisionShape::XMLPort(Element& xmlelement, XMLPort::Mode mode)
80    {
81        SUPER(CompoundCollisionShape, XMLPort, xmlelement, mode);
82        // Attached collision shapes
83        XMLPortObject(CompoundCollisionShape, CollisionShape, "", attach, detach, xmlelement, mode);
84    }
85
86    /**
87    @brief
88        Attach the input CollisionShape to the CompoundCollisionShape.
89    @param shape
90        A pointer to the CollisionShape that is to be attached.
91    */
92    void CompoundCollisionShape::attach(CollisionShape* shape)
93    {
94        // If either the input shape is NULL or we try to attach the CollisionShape to itself.
95        if (!shape || static_cast<CollisionShape*>(this) == shape)
96            return;
97
98        if (this->attachedShapes_.find(shape) != this->attachedShapes_.end())
99        {
100            CCOUT(2) << "Warning: Attaching a CollisionShape twice is not yet supported." << std::endl;
101            return;
102        }
103
104        // Notify the CollisionShape that it is being attached to the CompoundCollisionShape.
105        if (!shape->notifyBeingAttached(this))
106            return;
107
108        // Attach it.
109        this->attachedShapes_[shape] = shape->getCollisionShape();
110
111        // Only actually attach if we didn't pick a CompoundCollisionShape with no content.
112        if (shape->getCollisionShape())
113        {
114            btTransform transf(multi_cast<btQuaternion>(shape->getOrientation()), multi_cast<btVector3>(shape->getPosition()));
115            // Add the btCollisionShape of the CollisionShape as a child shape to the btCompoundShape of the CompoundCollisionShape.
116            this->compoundShape_->addChildShape(transf, shape->getCollisionShape());
117
118            this->updatePublicShape();
119        }
120    }
121
122    /**
123    @brief
124        Detach the input CollisionShape form the CompoundCollisionShape.
125    @param shape
126        A pointer to the CollisionShape to be detached.
127    */
128    void CompoundCollisionShape::detach(CollisionShape* shape)
129    {
130        // If the input CollisionShape is actually attached.
131        if (this->attachedShapes_.find(shape) != this->attachedShapes_.end())
132        {
133            this->attachedShapes_.erase(shape);
134            if (shape->getCollisionShape())
135                this->compoundShape_->removeChildShape(shape->getCollisionShape()); // TODO: Apparently this is broken?
136            shape->notifyDetached();
137
138            this->updatePublicShape();
139        }
140        else
141            CCOUT(2) << "Warning: Cannot detach non child collision shape" << std::endl;
142    }
143
144    /**
145    @brief
146        Detach all attached CollisionShapes.
147    */
148    void CompoundCollisionShape::detachAll()
149    {
150        while (this->attachedShapes_.size() > 0)
151            this->detach(this->attachedShapes_.begin()->first);
152    }
153
154    /**
155    @brief
156        Update the input CollisionShape that is attached to the CompoundCollisionShape.
157        This is called when the input shape's internal collision shape (a btCollisionShape) has changed.
158    @param shape
159        A pointer to the CollisionShape to be updated.
160    */
161    void CompoundCollisionShape::updateAttachedShape(CollisionShape* shape)
162    {
163        if (!shape)
164            return;
165
166        std::map<CollisionShape*, btCollisionShape*>::iterator it = this->attachedShapes_.find(shape);
167        // Check whether the input shape belongs to this CompoundCollisionShape.
168        if (it == this->attachedShapes_.end())
169        {
170            CCOUT(2) << "Warning: Cannot update child shape: Instance not a child." << std::endl;
171            return;
172        }
173
174        // Remove old btCollisionShape, stored in the children map
175        if (it->second)
176            this->compoundShape_->removeChildShape(it->second); // TODO: Apparently this is broken?
177
178        // Only actually attach if we didn't pick a CompoundCollisionShape with no content
179        if (shape->getCollisionShape())
180        {
181            btTransform transf(multi_cast<btQuaternion>(shape->getOrientation()), multi_cast<btVector3>(shape->getPosition()));
182            this->compoundShape_->addChildShape(transf, shape->getCollisionShape());
183            it->second = shape->getCollisionShape();
184        }
185
186        this->updatePublicShape();
187    }
188
189    /**
190    @brief
191        Updates the public shape, the collision shape this CompoundCollisionShape has to the outside.
192    */
193    void CompoundCollisionShape::updatePublicShape()
194    {
195        btCollisionShape* primitive = 0; // The primitive shape, if there is one.
196        bool bPrimitive = true; // Whether the CompoundCollisionShape has just one non-empty CollisionShape. And that shape also has no transformation.
197        bool bEmpty = true; // Whether the CompoundCollisionShape is empty.
198        // Iterate over all CollisionShapes that belong to this CompoundCollisionShape.
199        for (std::map<CollisionShape*, btCollisionShape*>::const_iterator it = this->attachedShapes_.begin(); it != this->attachedShapes_.end(); ++it)
200        {
201            // TODO: Make sure this is correct.
202            if (it->second)
203            {
204                bEmpty = false;
205                if (!it->first->hasTransform() && bPrimitive)
206                    primitive = it->second;
207                else
208                {
209                    bPrimitive = false;
210                    break;
211                }
212            }
213        }
214
215        // If there is no non-empty CollisionShape.
216        if (bEmpty)
217        {
218            // If there was none all along, nothing needs to be changed.
219            if (this->collisionShape_ == 0)
220                return;
221            this->collisionShape_ = 0;
222        }
223        // If the CompoundCollisionShape is just a primitive.
224        // Only one shape to be added, no transform; return it directly.
225        else if (bPrimitive)
226            this->collisionShape_ = primitive;
227        // Make sure we use the compound shape when returning a btCollisionShape.
228        else
229            this->collisionShape_ = this->compoundShape_;
230
231        this->updateParent();
232    }
233
234    /**
235    @brief
236        Get the attached CollisionShape at the given index.
237    @param index
238        The index of the desired CollisionShape.
239    @return
240        Returns a pointer to the attached CollisionShape at the given index.
241    */
242    CollisionShape* CompoundCollisionShape::getAttachedShape(unsigned int index) const
243    {
244        unsigned int i = 0;
245        for (std::map<CollisionShape*, btCollisionShape*>::const_iterator it = this->attachedShapes_.begin(); it != this->attachedShapes_.end(); ++it)
246        {
247            if (i == index)
248                return it->first;
249            ++i;
250        }
251        return 0;
252    }
253
254    /**
255    @brief
256        Is called when the scale of the CompoundCollisionShape has changed.
257        Iterates over all attached CollisionShapes and scales them, then recomputes their compound shape.
258    */
259    void CompoundCollisionShape::changedScale()
260    {
261        CollisionShape::changedScale();
262
263        std::vector<CollisionShape*> shapes;
264        // Iterate through all attached CollisionShapes and add them to the list of shapes.
265        for(std::map<CollisionShape*, btCollisionShape*>::iterator it = this->attachedShapes_.begin(); it != this->attachedShapes_.end(); it++)
266            shapes.push_back(it->first);
267
268        // Delete the compound shape and create a new one.
269        delete this->compoundShape_;
270        this->compoundShape_ = new btCompoundShape();
271
272        // Re-attach all CollisionShapes.
273        for(std::vector<CollisionShape*>::iterator it = shapes.begin(); it != shapes.end(); it++)
274        {
275            CollisionShape* shape = *it;
276            shape->setScale3D(this->getScale3D());
277            // Only actually attach if we didn't pick a CompoundCollisionShape with no content.
278            if (shape->getCollisionShape())
279            {
280                btTransform transf(multi_cast<btQuaternion>(shape->getOrientation()), multi_cast<btVector3>(shape->getPosition()));
281                // Add the btCollisionShape of the CollisionShape as a child shape to the btCompoundShape of the CompoundCollisionShape.
282                this->compoundShape_->addChildShape(transf, shape->getCollisionShape());
283            }
284        }
285
286        this->updatePublicShape();
287
288        /*
289        // Iterate through all attached CollisionShapes
290        for(std::map<CollisionShape*, btCollisionShape*>::const_iterator it = this->attachedShapes_.begin(); it != this->attachedShapes_.end(); it++)
291        {
292            // Rescale the CollisionShape.
293            it->first->setScale3D(this->getScale3D());
294            this->updateAttachedShape(it->first);
295        }
296
297        this->updatePublicShape();*/
298    }
299}
Note: See TracBrowser for help on using the repository browser.