Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/objects/worldentities/WorldEntity.h @ 2787

Last change on this file since 2787 was 2787, checked in by rgrieder, 15 years ago

Bugfix: _NDEBUG is never defined.

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