Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/cpp11_v2/src/orxonox/collisionshapes/CompoundCollisionShape.cc @ 10916

Last change on this file since 10916 was 10916, checked in by landauf, 10 years ago

use actual types instead of 'auto'. only exception is for complicated template types, e.g. when iterating over a map

  • Property svn:eol-style set to native
File size: 10.7 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
[10916]67            for (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
[10916]70                mapEntry.first->notifyDetached();
71                mapEntry.first->destroy();
72                if (this->collisionShape_ == mapEntry.second)
[10765]73                    this->collisionShape_ = nullptr; // don't destroy it twice
[2477]74            }
75
[2303]76            delete this->compoundShape_;
[10624]77            if (this->collisionShape_ == this->compoundShape_)
[10765]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    {
[10765]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    {
[10768]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.
[2527]202        for (std::map<CollisionShape*, btCollisionShape*>::const_iterator it = this->attachedShapes_.begin(); it != this->attachedShapes_.end(); ++it)
[2423]203        {
[8706]204            // TODO: Make sure this is correct.
[2423]205            if (it->second)
[2403]206            {
[2423]207                bEmpty = false;
[8706]208                if (!it->first->hasTransform() && bPrimitive)
[2423]209                    primitive = it->second;
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.
[10768]222            if (this->collisionShape_ == nullptr)
[2463]223                return;
[10768]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;
[10916]248        for (const auto& mapEntry : this->attachedShapes_)
[2423]249        {
250            if (i == index)
[10916]251                return mapEntry.first;
[2423]252            ++i;
253        }
[10768]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.
[10916]268        for(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.
[10916]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.