Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core6/src/orxonox/collisionshapes/CollisionShape.cc @ 9654

Last change on this file since 9654 was 9629, checked in by landauf, 11 years ago

BaseObject now requires a Context instead of a creator (BaseObject*) in its constructor.
Namespace, Level, and Scene inherit from Context

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