Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 12303 was 11071, checked in by landauf, 9 years ago

merged branch cpp11_v3 back to trunk

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