Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 10253 was 9655, checked in by landauf, 11 years ago

register abstract classes

  • Property svn:eol-style set to native
File size: 9.3 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            this->parentID_ = parentWECCS->getWorldEntityOwner()->getObjectID();
124        // Else it is set to the objectID of the CompoundCollisionShape.
125        else
126            this->parentID_ = newParent->getObjectID();
127
128        return true;
129    }
130
131    /**
132    @brief
133        Notifies the CollisionShape of being detached from a CompoundCollisionShape.
134    */
135    void CollisionShape::notifyDetached()
136    {
137        this->parent_ = 0;
138        this->parentID_ = OBJECTID_UNKNOWN;
139    }
140
141    /**
142    @brief
143        Updates the CompoundCollisionShape the CollisionShape belongs to (if it belongs to one), after the CollisionShape has changed.
144    */
145    void CollisionShape::updateParent()
146    {
147        if (this->parent_)
148            this->parent_->updateAttachedShape(this);
149    }
150
151    /**
152    @brief
153        Is called when the parentID of the CollisionShape has changed.
154        Attaches it to the object with the changed parentID, which can either be a CompoundCollisionShape or a WorldEntity.
155    */
156    void CollisionShape::parentChanged()
157    {
158        // Get the parent object from the network.
159        Synchronisable* parent = Synchronisable::getSynchronisable(this->parentID_);
160
161        // Parent can either be a WorldEntity or a CompoundCollisionShape. The reason is that the
162        // internal collision shape (which is compound) of a WE doesn't get synchronised.
163        CompoundCollisionShape* parentCCS = orxonox_cast<CompoundCollisionShape*>(parent);
164
165        // If the parent is a CompoundCollisionShape, attach the CollisionShape to it.
166        if (parentCCS)
167            parentCCS->attach(this);
168        else
169        {
170            // If the parent is a WorldEntity, attach the CollisionShape to its collision shapes.
171            WorldEntity* parentWE = orxonox_cast<WorldEntity*>(parent);
172            if (parentWE)
173                parentWE->attachCollisionShape(this);
174        }
175    }
176
177    /**
178    @brief
179        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)
180    @return
181        Returns true if it has been moved.
182    */
183    bool CollisionShape::hasTransform() const
184    {
185        return (!this->position_.positionEquals(Vector3(0, 0, 0), 0.001f) ||
186                !this->orientation_.equals(Quaternion(1,0,0,0), Degree(0.1f)));
187    }
188
189    /**
190    @brief
191        Set the scale of the CollisionShape.
192        Since the scale is a vector the CollisionShape can be scaled independently in each direction, allowing for linear distortions.
193        If the scale changes, this causes the parent CompoundCollisionShape (if there is one) to be updated.
194        Beware, non-uniform scaling (i.e. distortions) might not be supported by all CollisionShapes.
195    @param scale
196        The new scale to be set. Vector3::UNIT_SCALE is the initial scale.
197    */
198    void CollisionShape::setScale3D(const Vector3& scale)
199    {
200        if(this->scale_ == scale)
201            return;
202
203        // If the vectors are not in the same direction, then this is no longer a uniform scaling.
204        if(scale_.crossProduct(scale).squaredLength() != 0.0f)
205        {
206            orxout(internal_warning) << "Non-uniform scaling is not yet supported." << endl;
207            return;
208        }
209
210        this->scale_ = scale;
211
212        this->changedScale();
213        this->updateParent();
214    }
215
216    /**
217    @brief
218        Set the (uniform) scale of the CollisionShape.
219        If the scale changes, this causes the parent CompoundCollisionShape (if there is one) to be updated.
220    @param scale
221        The scale to scale the CollisionShape with. 1.0f is the initial scale.
222    */
223    void CollisionShape::setScale(float scale)
224    {
225        if(this->scale_.length() == scale)
226            return;
227
228        this->scale_ = Vector3::UNIT_SCALE*scale;
229
230        this->changedScale();
231        this->updateParent();
232    }
233
234    /**
235    @brief
236        Is called when the scale of the CollisionShape has changed.
237    */
238    void CollisionShape::changedScale()
239    {
240        // Adjust the position of the CollisionShape.
241        this->position_ *= this->getScale3D();
242    }
243
244    /**
245    @brief
246        Updates the shape.
247        Is called when the internal parameters of the shape have changed such that a new shape needs to be created.
248    */
249    void CollisionShape::updateShape()
250    {
251        btCollisionShape* oldShape = this->collisionShape_;
252        this->collisionShape_ = this->createNewShape();
253        // If the CollisionShape has been rescaled, scale the shape to fit the current scale.
254        if(this->scale_ != Vector3::UNIT_SCALE)
255            this->changedScale();
256        // When we recreate the shape, we have to inform the parent about this to update the shape
257        this->updateParent();
258        if (oldShape)
259            delete oldShape;
260    }
261
262    /**
263    @brief
264        Calculates the local inertia of the collision shape.
265    @todo
266        Document.
267    */
268    void CollisionShape::calculateLocalInertia(float mass, btVector3& inertia) const
269    {
270        if (this->collisionShape_)
271            this->collisionShape_->calculateLocalInertia(mass, inertia);
272        else
273            inertia.setValue(0, 0, 0);
274    }
275}
Note: See TracBrowser for help on using the repository browser.