Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/modularships/src/orxonox/worldentities/WorldEntity.h @ 10066

Last change on this file since 10066 was 10033, checked in by noep, 11 years ago

Tried to find&solve the segfault. The detach-process itself is not the problem, but the collision on a deleted shape being handled. Maybe try using a smart pointer in the handling process, so that the shape only gets deleted when the process completed?

  • Property svn:eol-style set to native
File size: 23.4 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 *      Fabian 'x3n' Landau
24 *      Reto Grieder (physics)
25 *   Co-authors:
26 *      ...
27 *
28 */
29
30#ifndef _WorldEntity_H__
31#define _WorldEntity_H__
32
33#include "OrxonoxPrereqs.h"
34
35#ifdef ORXONOX_RELEASE
36#  include <OgreSceneNode.h>
37#endif
38#include <LinearMath/btMotionState.h>
39
40#include "util/Math.h"
41#include "util/OgreForwardRefs.h"
42#include "core/BaseObject.h"
43#include "network/synchronisable/Synchronisable.h"
44
45namespace orxonox
46{
47    /**
48    @brief
49        The WorldEntity represents everything that can be put in a Scene at a certain location.
50
51        It is supposed to be the base class of everything you would call an 'object' in a Scene.
52        The class itself is abstract which means you cannot use it directly. You may use StaticEntity
53        as the simplest derivative or (derived from MobileEntity) MovableEntity and ControllableEntity
54        as more advanced ones.
55
56        The basic task of the WorldEntity is provide a location, a direction and a scaling and the possibility
57        to create an entire hierarchy of derived objects.
58        It is also the basis for the physics interface to the Bullet physics engine.
59        Every WorldEntity can have a specific collision type: @see CollisionType
60        This would then imply that every scene object could have any collision type. To limit this, you can always
61        override this->isCollisionTypeLegal(CollisionType). Return false if the collision type is not supported
62        for a specific object.
63        There is also support for attaching WorldEntities with physics to each other. Currently, the collision shape
64        of both objects simply get merged into one larger shape (for static collision type).
65        The physical body that is internally stored and administrated has the following supported properties:
66        - Restitution, angular factor, linear damping, angular damping, friction, mass and collision shape.
67        You can get more information at the corresponding set function.
68
69        Collision shapes: These are controlled by the internal WorldEntityCollisionShape. @see WorldEntityCollisionShape.
70    */
71    class _OrxonoxExport WorldEntity : public BaseObject, public Synchronisable, public btMotionState
72    {
73        friend class Scene;
74        friend class ModularSpaceShip;
75
76        public:
77            // Define our own transform space enum to avoid Ogre includes here
78            /**
79            @brief
80                Enumeration denoting the spaces which a transform can be relative to.
81            */
82            enum TransformSpace
83            {
84                //! Transform is relative to the local space
85                Local,
86                //! Transform is relative to the space of the parent node
87                Parent,
88                //! Transform is relative to world space
89                World
90            };
91
92        public:
93            WorldEntity(Context* context);
94            virtual ~WorldEntity();
95
96            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
97
98            inline const Ogre::SceneNode* getNode() const
99                { return this->node_; }
100
101            static const Vector3 FRONT;
102            static const Vector3 BACK;
103            static const Vector3 LEFT;
104            static const Vector3 RIGHT;
105            static const Vector3 DOWN;
106            static const Vector3 UP;
107
108            virtual void changedActivity(void);
109            virtual void changedVisibility(void);
110
111            virtual void setPosition(const Vector3& position) = 0;
112            inline void setPosition(float x, float y, float z)
113                { this->setPosition(Vector3(x, y, z)); }
114            const Vector3& getPosition() const;
115            const Vector3& getWorldPosition() const;
116
117            void translate(const Vector3& distance, TransformSpace relativeTo = WorldEntity::Parent);
118            inline void translate(float x, float y, float z, TransformSpace relativeTo = WorldEntity::Parent)
119                { this->translate(Vector3(x, y, z), relativeTo); }
120
121            virtual inline const Vector3& getVelocity() const
122                { return Vector3::ZERO; }
123
124            virtual void setOrientation(const Quaternion& orientation) = 0;
125            inline void setOrientation(float w, float x, float y, float z)
126                { this->setOrientation(Quaternion(w, x, y, z)); }
127            inline void setOrientation(const Vector3& axis, const Radian& angle)
128                { this->setOrientation(Quaternion(angle, axis)); }
129            inline void setOrientation(const Vector3& axis, const Degree& angle)
130                { this->setOrientation(Quaternion(angle, axis)); }
131            const Quaternion& getOrientation() const;
132            const Quaternion& getWorldOrientation() const;
133
134            void rotate(const Quaternion& rotation, TransformSpace relativeTo = WorldEntity::Local);
135            inline void rotate(const Vector3& axis, const Degree& angle, TransformSpace relativeTo = WorldEntity::Local)
136                { this->rotate(Quaternion(angle, axis), relativeTo); }
137
138            inline void yaw(const Degree& angle, TransformSpace relativeTo = WorldEntity::Local)
139                { this->rotate(Quaternion(angle, Vector3::UNIT_Y), relativeTo); }
140            inline void pitch(const Degree& angle, TransformSpace relativeTo = WorldEntity::Local)
141                { this->rotate(Quaternion(angle, Vector3::UNIT_X), relativeTo); }
142            inline void roll(const Degree& angle, TransformSpace relativeTo = WorldEntity::Local)
143                { this->rotate(Quaternion(angle, Vector3::UNIT_Z), relativeTo); }
144
145            void lookAt(const Vector3& target, TransformSpace relativeTo = WorldEntity::Parent, const Vector3& localDirectionVector = Vector3::NEGATIVE_UNIT_Z);
146            void setDirection(const Vector3& direction, TransformSpace relativeTo = WorldEntity::Local, const Vector3& localDirectionVector = Vector3::NEGATIVE_UNIT_Z);
147            inline void setDirection(float x, float y, float z, TransformSpace relativeTo = WorldEntity::Local, const Vector3& localDirectionVector = Vector3::NEGATIVE_UNIT_Z)
148                { this->setDirection(Vector3(x, y, z), relativeTo, localDirectionVector); }
149
150            virtual void setScale3D(const Vector3& scale);
151            inline void setScale3D(float x, float y, float z)
152                { this->setScale3D(Vector3(x, y, z)); }
153            const Vector3& getScale3D() const;
154            const Vector3& getWorldScale3D() const;
155
156            inline void setScale(float scale)
157                { this->setScale3D(scale, scale, scale); }
158            inline float getScale() const
159                { Vector3 scale = this->getScale3D(); return (scale.x == scale.y && scale.x == scale.z) ? scale.x : 1; }
160            float getWorldScale() const;
161
162            inline void scale3D(const Vector3& scale)
163                { this->setScale3D(this->getScale3D() * scale); }
164            inline void scale3D(float x, float y, float z)
165                { this->scale3D(Vector3(x, y, z)); }
166            inline void scale(float scale)
167                { this->scale3D(scale, scale, scale); }
168
169            virtual void changedScale() {}
170
171            void attach(WorldEntity* object);
172            void detach(WorldEntity* object);
173            WorldEntity* getAttachedObject(unsigned int index);
174            inline const std::set<WorldEntity*>& getAttachedObjects() const
175                { return this->children_; }
176
177            void attachOgreObject(Ogre::MovableObject*  object);
178            void attachOgreObject(Ogre::BillboardSet*   object);
179            void attachOgreObject(Ogre::Camera*         object);
180            void attachOgreObject(Ogre::Entity*         object);
181            void attachOgreObject(Ogre::ParticleSystem* object);
182
183            void detachOgreObject(Ogre::MovableObject*  object);
184            void detachOgreObject(Ogre::BillboardSet*   object);
185            void detachOgreObject(Ogre::Camera*         object);
186            void detachOgreObject(Ogre::Entity*         object);
187            void detachOgreObject(Ogre::ParticleSystem* object);
188
189            Ogre::MovableObject* detachOgreObject(const Ogre::String& name);
190
191            inline void attachToParent(WorldEntity* parent)
192                { parent->attach(this); }
193            inline void detachFromParent()
194                { if (this->parent_) { this->parent_->detach(this); } }
195            inline WorldEntity* getParent() const
196                { return this->parent_; }
197
198            void attachNode(Ogre::SceneNode* node);
199            void detachNode(Ogre::SceneNode* node);
200            void attachToNode(Ogre::SceneNode* node);
201            void detachFromNode(Ogre::SceneNode* node);
202
203            inline void setDeleteWithParent(bool value)
204                { this->bDeleteWithParent_ = value; }
205            inline bool getDeleteWithParent() const
206                { return this->bDeleteWithParent_; }
207
208            void notifyChildPropsChanged();
209
210            inline int getNumAttachedObj()
211                { return this->children_.size(); }
212
213        protected:
214            virtual void parentChanged() {}
215
216            Ogre::SceneNode* node_;
217
218        private:
219            void registerVariables();
220
221            inline void lookAt_xmlport(const Vector3& target)
222                { this->lookAt(target); }
223            inline void setDirection_xmlport(const Vector3& direction)
224                { this->setDirection(direction); }
225            inline void yaw_xmlport(const Degree& angle)
226                { this->yaw(angle); }
227            inline void pitch_xmlport(const Degree& angle)
228                { this->pitch(angle); }
229            inline void roll_xmlport(const Degree& angle)
230                { this->roll(angle); }
231
232            // network callbacks
233            void networkcallback_parentChanged();
234            inline void scaleChanged()
235                { this->setScale3D(this->getScale3D()); }
236
237            WorldEntity* parent_;
238            unsigned int parentID_;
239            std::set<WorldEntity*> children_;
240            bool bDeleteWithParent_;
241
242            bool bActiveMem_;
243            bool bVisibleMem_;
244
245
246        /////////////
247        // Physics //
248        /////////////
249
250        public:
251            /**
252            @brief
253                Denotes the possible types of physical objects in a Scene.
254
255                Dynamic:   The object is influenced by its physical environment, like for instance little ball.
256                Kinematic: The object can only influence other dynamic objects. It's movement is coordinated by your own saying.
257                Static:    Like kinematic but the object is not allowed to move during the simulation.
258                None:      The object has no physics at all.
259            */
260            enum CollisionType
261            {
262                Dynamic,
263                Kinematic,
264                Static,
265                None
266            };
267
268            //! Tells whether the object has any connection to the Bullet physics engine. If hasPhysics() is false, the object may still have a velocity.
269            bool hasPhysics()       const { return getCollisionType() != None     ; }
270            //! @see CollisionType
271            bool isStatic()         const { return getCollisionType() == Static   ; }
272            //! @see CollisionType
273            bool isKinematic()      const { return getCollisionType() == Kinematic; }
274            //! @see CollisionType
275            bool isDynamic()        const { return getCollisionType() == Dynamic  ; }
276            //! Tells whether physics has been activated (you can temporarily deactivate it)
277            bool isPhysicsActive()  const { return this->bPhysicsActive_; }
278            bool addedToPhysicalWorld() const;
279
280            void activatePhysics();
281            void deactivatePhysics();
282
283            //! Returns the CollisionType. @see CollisionType.
284            inline CollisionType getCollisionType() const
285                { return this->collisionType_; }
286            void setCollisionType(CollisionType type);
287
288            void setCollisionTypeStr(const std::string& type);
289            std::string getCollisionTypeStr() const;
290
291            //! Sets the mass of this object. Note that the total mass may be influenced by attached objects!
292            inline void setMass(float mass)
293                { this->mass_ = mass; recalculateMassProps(); }
294            //! Returns the mass of this object without its children.
295            inline float getMass() const
296                { return this->mass_; }
297
298            //! Returns the total mass of this object with all its attached children.
299            inline float getTotalMass() const
300                { return this->mass_ + this->childrenMass_; }
301
302            /**
303            @brief
304                Returns the diagonal elements of the inertia tensor when calculated in local coordinates.
305            @note
306                The local inertia tensor cannot be set, but is calculated by Bullet according to the collisionShape.
307                With compound collision shapes, an approximation is used.
308            */
309            inline const btVector3& getLocalInertia() const
310                { return this->localInertia_; }
311
312            /**
313            @brief
314                Sets how much reaction is applied in a collision.
315
316                Consider two equal spheres colliding with equal velocities:
317                Restitution 1 means that both spheres simply reverse their velocity (no loss of energy)
318                Restitution 0 means that both spheres will immediately stop moving
319                (maximum loss of energy without violating of the preservation of momentum)
320            */
321            inline void setRestitution(float restitution)
322                { this->restitution_ = restitution; internalSetPhysicsProps(); }
323            //! Returns the restitution parameter. @see setRestitution.
324            inline float getRestitution() const
325                { return this->restitution_; }
326
327            /**
328            @brief
329                Sets an artificial parameter that tells how much torque is applied when you apply a non-central force.
330
331                Normally the angular factor is 1, which means it's physically 'correct'. However if you have a player
332                character that should not rotate when hit sideways, you can set the angular factor to 0.
333            */
334            inline void setAngularFactor(float angularFactor)
335                { this->angularFactor_ = angularFactor; internalSetPhysicsProps(); }
336            //! Returns the angular factor. @see setAngularFactor.
337            inline float getAngularFactor() const
338                { return this->angularFactor_; }
339
340            //! Applies a mass independent damping. Velocities will simply diminish exponentially.
341            inline void setLinearDamping(float linearDamping)
342                { this->linearDamping_ = linearDamping; internalSetPhysicsProps(); }
343            //! Returns the linear damping. @see setLinearDamping.
344            inline float getLinearDamping() const
345                { return this->linearDamping_; }
346
347            //! Applies a tensor independent rotation damping. Angular velocities will simply diminish exponentially.
348            inline void setAngularDamping(float angularDamping)
349                { this->angularDamping_ = angularDamping; internalSetPhysicsProps(); }
350            //! Returns the angular damping. @see setAngularDamping.
351            inline float getAngularDamping() const
352                { return this->angularDamping_; }
353
354            //! Applies friction to the object. Friction occurs when two objects collide.
355            inline void setFriction(float friction)
356                { this->friction_ = friction; internalSetPhysicsProps(); }
357            //! Returns the amount of friction applied to the object.
358            inline float getFriction() const
359                { return this->friction_; }
360
361            void attachCollisionShape(CollisionShape* shape);
362            void detachCollisionShape(CollisionShape* shape);
363            CollisionShape* getAttachedCollisionShape(unsigned int index);
364
365            void notifyCollisionShapeChanged();
366            void notifyChildMassChanged();
367
368            /**
369            @brief
370                Virtual function that gets called when this object collides with another.
371            @param otherObject
372                The object this one has collided into.
373            @param contactPoint
374                Contact point provided by Bullet. Holds more information and can me modified. See return value.
375            @return
376                Returning false means that no modification to the contactPoint has been made. Return true otherwise!
377            @note
378                Condition is that enableCollisionCallback() was called.
379            */
380            virtual inline bool collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint)
381                { return false; } /* With false, Bullet assumes no modification to the collision objects. */
382
383            //! Enables the collidesAgainst(.) function. The object doesn't respond to collision otherwise!
384            inline void enableCollisionCallback()
385                { this->bCollisionCallbackActive_ = true; this->collisionCallbackActivityChanged(); }
386            //! Disables the collidesAgainst(.) function. @see enableCollisionCallback()
387            inline void disableCollisionCallback()
388                { this->bCollisionCallbackActive_ = false; this->collisionCallbackActivityChanged(); }
389            //! Tells whether there could be a collision callback via collidesAgainst(.)
390            inline bool isCollisionCallbackActive() const
391                { return this->bCollisionCallbackActive_; }
392
393            //! Enables or disables collision response (default is of course on)
394            inline void setCollisionResponse(bool value)
395                { this->bCollisionResponseActive_ = value; this->collisionResponseActivityChanged(); }
396            //! Tells whether there could be a collision response
397            inline bool hasCollisionResponse()
398                { return this->bCollisionResponseActive_; }
399
400        protected:
401            /**
402            @brief
403                Function checks whether the requested collision type is legal to this object.
404
405                You can override this function in a derived class to constrain the collision to e.g. None or Dynamic.
406                A projectile may not prove very useful if there is no physical body. Simply set the CollisionType
407                in its constructor and override this method. But be careful that a derived class's virtual functions
408                don't yet exist in the constructor if a base class.
409            */
410            virtual bool isCollisionTypeLegal(CollisionType type) const = 0;
411
412            inline virtual WorldEntityCollisionShape* getWorldEntityCollisionShape()
413                { return this->collisionShape_; }
414
415            btRigidBody*  physicalBody_; //!< Bullet rigid body. Everything physical is applied to this instance.
416
417        private:
418            void recalculateMassProps();
419            void internalSetPhysicsProps();
420
421            bool notifyBeingAttached(WorldEntity* newParent);
422            void notifyDetached();
423
424            // network callbacks
425            void collisionTypeChanged();
426            void physicsActivityChanged();
427            void collisionCallbackActivityChanged();
428            void collisionResponseActivityChanged();
429            //! Network callback workaround to call a function when the value changes.
430            inline void massChanged()
431                { this->setMass(this->mass_); }
432            //! Network callback workaround to call a function when the value changes.
433            inline void restitutionChanged()
434                { this->setRestitution(this->restitution_); }
435            //! Network callback workaround to call a function when the value changes.
436            inline void angularFactorChanged()
437                { this->setAngularFactor(this->angularFactor_); }
438            //! Network callback workaround to call a function when the value changes.
439            inline void linearDampingChanged()
440                { this->setLinearDamping(this->linearDamping_); }
441            //! Network callback workaround to call a function when the value changes.
442            inline void angularDampingChanged()
443                { this->setAngularDamping(this->angularDamping_); }
444            //! Network callback workaround to call a function when the value changes.
445            inline void frictionChanged()
446                { this->setFriction(this->friction_); }
447
448            CollisionType                collisionType_;                 //!< @see setCollisionType
449            CollisionType                collisionTypeSynchronised_;     //!< Network synchronised variable for collisionType_
450            bool                         bPhysicsActive_;                //!< @see isPhysicsActive
451            bool                         bPhysicsActiveSynchronised_;    //!< Network synchronised variable for bPhysicsActive_
452            //! When attaching objects hierarchically this variable tells this object (as child) whether physics was activated before attaching (because the deactivate physics while being attached).
453            bool                         bPhysicsActiveBeforeAttaching_;
454            WorldEntityCollisionShape*   collisionShape_;                //!< Attached collision shapes go here
455            btScalar                     mass_;                          //!< @see setMass
456            btVector3                    localInertia_;                  //!< @see getLocalInertia
457            btScalar                     restitution_;                   //!< @see setRestitution
458            btScalar                     angularFactor_;                 //!< @see setAngularFactor
459            btScalar                     linearDamping_;                 //!< @see setLinearDamping
460            btScalar                     angularDamping_;                //!< @see setAngularDamping
461            btScalar                     friction_;                      //!< @see setFriction
462            btScalar                     childrenMass_;                  //!< Sum of all the children's masses
463            bool                         bCollisionCallbackActive_;      //!< @see enableCollisionCallback
464            bool                         bCollisionResponseActive_;      //!< Tells whether the object should respond to collisions
465    };
466
467    // Inline heavily used functions for release builds. In debug, we better avoid including OgreSceneNode here.
468#ifdef ORXONOX_RELEASE
469    inline const Vector3& WorldEntity::getPosition() const
470        { return this->node_->getPosition(); }
471    inline const Quaternion& WorldEntity::getOrientation() const
472        { return this->node_->getOrientation(); }
473    inline const Vector3& WorldEntity::getScale3D() const
474        { return this->node_->getScale(); }
475#endif
476
477    SUPER_FUNCTION(5, WorldEntity, changedScale, false);
478}
479
480#endif /* _WorldEntity_H__ */
Note: See TracBrowser for help on using the repository browser.