Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Ensured OGRE v1.7 "Cthugha" code compatibility. Does not yet seem to run run though.

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