Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/collisionshapes/CollisionShape.cc @ 10426

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

merged branch presentationFS14 back to trunk

  • Property svn:eol-style set to native
File size: 9.8 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 CollisionShape.cc
31    @brief Implementation of the CollisionShape class.
32*/
33
34#include "CollisionShape.h"
35
36#include <BulletCollision/CollisionShapes/btCollisionShape.h>
37
38#include "core/CoreIncludes.h"
39#include "core/XMLPort.h"
40#include "worldentities/WorldEntity.h"
41#include "CompoundCollisionShape.h"
42#include "WorldEntityCollisionShape.h"
43
44namespace orxonox
45{
46    RegisterAbstractClass(CollisionShape).inheritsFrom(Class(BaseObject)).inheritsFrom(Class(Synchronisable));
47
48    /**
49    @brief
50        Constructor. Registers and initializes the object.
51    */
52    CollisionShape::CollisionShape(Context* context)
53        : BaseObject(context)
54        , Synchronisable(context)
55    {
56        RegisterObject(CollisionShape);
57
58        this->parent_ = 0;
59        this->parentID_ = OBJECTID_UNKNOWN;
60        this->collisionShape_ = 0;
61        this->position_ = Vector3::ZERO;
62        this->orientation_ = Quaternion::IDENTITY;
63        this->scale_ = Vector3::UNIT_SCALE;
64        this->uniformScale_ = true;
65
66        this->registerVariables();
67    }
68
69    /**
70    @brief
71        Destructor. Detaches the CollisionShape from its parent.
72    */
73    CollisionShape::~CollisionShape()
74    {
75        // Detach from parent CompoundCollisionShape.
76        if (this->isInitialized() && this->parent_)
77            this->parent_->detach(this);
78    }
79
80    void CollisionShape::XMLPort(Element& xmlelement, XMLPort::Mode mode)
81    {
82        SUPER(CollisionShape, XMLPort, xmlelement, mode);
83
84        XMLPortParamTemplate(CollisionShape, "position", setPosition, getPosition, xmlelement, mode, const Vector3&);
85        XMLPortParamTemplate(CollisionShape, "orientation", setOrientation, getOrientation, xmlelement, mode, const Quaternion&);
86        XMLPortParamTemplate(CollisionShape, "scale3D", setScale3D, getScale3D, xmlelement, mode, const Vector3&);
87        XMLPortParamLoadOnly(CollisionShape, "scale", setScale, xmlelement, mode);
88        XMLPortParamLoadOnly(CollisionShape, "yaw",   yaw,   xmlelement, mode);
89        XMLPortParamLoadOnly(CollisionShape, "pitch", pitch, xmlelement, mode);
90        XMLPortParamLoadOnly(CollisionShape, "roll",  roll,  xmlelement, mode);
91    }
92
93    /**
94    @brief
95        Register variables that need synchronizing over the network.
96    */
97    void CollisionShape::registerVariables()
98    {
99        // Keep the shape's parent (can be either a CompoundCollisionShape or a WorldEntity) consistent over the network.
100        registerVariable(this->parentID_, VariableDirection::ToClient, new NetworkCallback<CollisionShape>(this, &CollisionShape::parentChanged));
101    }
102
103    /**
104    @brief
105        Notifies the CollisionShape of being attached to a CompoundCollisionShape.
106    @param newParent
107        A pointer to the CompoundCollisionShape the CollisionShape was attached to.
108    @return
109        Returns
110    */
111    bool CollisionShape::notifyBeingAttached(CompoundCollisionShape* newParent)
112    {
113        // If the CollisionShape is attached to a CompoundCollisionShapes, detach it.
114        if (this->parent_)
115            this->parent_->detach(this);
116
117        this->parent_ = newParent;
118
119        // If the new parent is a WorldEntityCollisionShape, the parentID is set to the objectID of the WorldEntity that is its owner.
120        // TODO: Why?
121        WorldEntityCollisionShape* parentWECCS = orxonox_cast<WorldEntityCollisionShape*>(newParent);
122        if (parentWECCS)
123        {
124            this->parentID_ = parentWECCS->getWorldEntityOwner()->getObjectID();
125
126            // If this shape is not a CompoundCollisionShape (thus an actual physical shape) & the parent is a WorldEntity's CollisionShape,
127            // set it's userPointer to the WorldEntity this CompoundCollisionShape belongs to.
128            if (!orxonox_cast<CompoundCollisionShape*>(this))
129                this->getCollisionShape()->setUserPointer(parentWECCS->getWorldEntityOwner());
130        }
131        else
132        {
133            // Else it is set to the objectID of the CompoundCollisionShape.
134            this->parentID_ = newParent->getObjectID();
135        }
136
137        return true;
138    }
139
140    /**
141    @brief
142        Notifies the CollisionShape of being detached from a CompoundCollisionShape.
143    */
144    void CollisionShape::notifyDetached()
145    {
146        this->parent_ = 0;
147        this->parentID_ = OBJECTID_UNKNOWN;
148    }
149
150    /**
151    @brief
152        Updates the CompoundCollisionShape the CollisionShape belongs to (if it belongs to one), after the CollisionShape has changed.
153    */
154    void CollisionShape::updateParent()
155    {
156        if (this->parent_)
157            this->parent_->updateAttachedShape(this);
158    }
159
160    /**
161    @brief
162        Is called when the parentID of the CollisionShape has changed.
163        Attaches it to the object with the changed parentID, which can either be a CompoundCollisionShape or a WorldEntity.
164    */
165    void CollisionShape::parentChanged()
166    {
167        // Get the parent object from the network.
168        Synchronisable* parent = Synchronisable::getSynchronisable(this->parentID_);
169
170        // Parent can either be a WorldEntity or a CompoundCollisionShape. The reason is that the
171        // internal collision shape (which is compound) of a WE doesn't get synchronised.
172        CompoundCollisionShape* parentCCS = orxonox_cast<CompoundCollisionShape*>(parent);
173
174        // If the parent is a CompoundCollisionShape, attach the CollisionShape to it.
175        if (parentCCS)
176            parentCCS->attach(this);
177        else
178        {
179            // If the parent is a WorldEntity, attach the CollisionShape to its collision shapes.
180            WorldEntity* parentWE = orxonox_cast<WorldEntity*>(parent);
181            if (parentWE)
182                parentWE->attachCollisionShape(this);
183        }
184    }
185
186    /**
187    @brief
188        Check whether the CollisionShape has been either moved or rotated or both. (i.e. it doesn't have position zero and identity orientation any more)
189    @return
190        Returns true if it has been moved.
191    */
192    bool CollisionShape::hasTransform() const
193    {
194        return (!this->position_.positionEquals(Vector3(0, 0, 0), 0.001f) ||
195                !this->orientation_.equals(Quaternion(1,0,0,0), Degree(0.1f)));
196    }
197
198    /**
199    @brief
200        Set the scale of the CollisionShape.
201        Since the scale is a vector the CollisionShape can be scaled independently in each direction, allowing for linear distortions.
202        If the scale changes, this causes the parent CompoundCollisionShape (if there is one) to be updated.
203        Beware, non-uniform scaling (i.e. distortions) might not be supported by all CollisionShapes.
204    @param scale
205        The new scale to be set. Vector3::UNIT_SCALE is the initial scale.
206    */
207    void CollisionShape::setScale3D(const Vector3& scale)
208    {
209        if(this->scale_ == scale)
210            return;
211
212        // If the vectors are not in the same direction, then this is no longer a uniform scaling.
213        if(scale_.crossProduct(scale).squaredLength() != 0.0f)
214        {
215            orxout(internal_warning) << "Non-uniform scaling is not yet supported." << endl;
216            return;
217        }
218
219        this->scale_ = scale;
220
221        this->changedScale();
222        this->updateParent();
223    }
224
225    /**
226    @brief
227        Set the (uniform) scale of the CollisionShape.
228        If the scale changes, this causes the parent CompoundCollisionShape (if there is one) to be updated.
229    @param scale
230        The scale to scale the CollisionShape with. 1.0f is the initial scale.
231    */
232    void CollisionShape::setScale(float scale)
233    {
234        if(this->scale_.length() == scale)
235            return;
236
237        this->scale_ = Vector3::UNIT_SCALE*scale;
238
239        this->changedScale();
240        this->updateParent();
241    }
242
243    /**
244    @brief
245        Is called when the scale of the CollisionShape has changed.
246    */
247    void CollisionShape::changedScale()
248    {
249        // Adjust the position of the CollisionShape.
250        this->position_ *= this->getScale3D();
251    }
252
253    /**
254    @brief
255        Updates the shape.
256        Is called when the internal parameters of the shape have changed such that a new shape needs to be created.
257    */
258    void CollisionShape::updateShape()
259    {
260        btCollisionShape* oldShape = this->collisionShape_;
261        this->collisionShape_ = this->createNewShape();
262        // If the CollisionShape has been rescaled, scale the shape to fit the current scale.
263        if(this->scale_ != Vector3::UNIT_SCALE)
264            this->changedScale();
265        // When we recreate the shape, we have to inform the parent about this to update the shape
266        this->updateParent();
267        if (oldShape)
268            delete oldShape;
269    }
270
271    /**
272    @brief
273        Calculates the local inertia of the collision shape.
274    @todo
275        Document.
276    */
277    void CollisionShape::calculateLocalInertia(float mass, btVector3& inertia) const
278    {
279        if (this->collisionShape_)
280            this->collisionShape_->calculateLocalInertia(mass, inertia);
281        else
282            inertia.setValue(0, 0, 0);
283    }
284}
Note: See TracBrowser for help on using the repository browser.