Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 7150 was 6524, checked in by dafrick, 15 years ago

Merged pickup branch into trunk. Yay. Persisting bugs will be fixed, very soon.

  • Property svn:eol-style set to native
File size: 23.1 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 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        protected:
211            virtual void parentChanged() {}
212
213            Ogre::SceneNode* node_;
214
215        private:
216            inline void lookAt_xmlport(const Vector3& target)
217                { this->lookAt(target); }
218            inline void setDirection_xmlport(const Vector3& direction)
219                { this->setDirection(direction); }
220            inline void yaw_xmlport(const Degree& angle)
221                { this->yaw(angle); }
222            inline void pitch_xmlport(const Degree& angle)
223                { this->pitch(angle); }
224            inline void roll_xmlport(const Degree& angle)
225                { this->roll(angle); }
226
227            // network callbacks
228            void networkcallback_parentChanged();
229            inline void scaleChanged()
230                { this->setScale3D(this->getScale3D()); }
231
232            WorldEntity* parent_;
233            unsigned int parentID_;
234            std::set<WorldEntity*> children_;
235            bool bDeleteWithParent_;
236           
237            bool bActiveMem_;
238            bool bVisibleMem_;
239
240
241        /////////////
242        // Physics //
243        /////////////
244
245        public:
246            /**
247            @brief
248                Denotes the possible types of physical objects in a Scene.
249
250                Dynamic:   The object is influenced by its physical environment, like for instance little ball.
251                Kinematic: The object can only influence other dynamic objects. It's movement is coordinated by your own saying.
252                Static:    Like kinematic but the object is not allowed to move during the simulation.
253                None:      The object has no physics at all.
254            */
255            enum CollisionType
256            {
257                Dynamic,
258                Kinematic,
259                Static,
260                None
261            };
262
263            //! Tells whether the object has any connection to the Bullet physics engine. If hasPhysics() is false, the object may still have a velocity.
264            bool hasPhysics()       const { return getCollisionType() != None     ; }
265            //! @see CollisionType
266            bool isStatic()         const { return getCollisionType() == Static   ; }
267            //! @see CollisionType
268            bool isKinematic()      const { return getCollisionType() == Kinematic; }
269            //! @see CollisionType
270            bool isDynamic()        const { return getCollisionType() == Dynamic  ; }
271            //! Tells whether physics has been activated (you can temporarily deactivate it)
272            bool isPhysicsActive()  const { return this->bPhysicsActive_; }
273            bool addedToPhysicalWorld() const;
274
275            void activatePhysics();
276            void deactivatePhysics();
277
278            //! Returns the CollisionType. @see CollisionType.
279            inline CollisionType getCollisionType() const
280                { return this->collisionType_; }
281            void setCollisionType(CollisionType type);
282
283            void setCollisionTypeStr(const std::string& type);
284            std::string getCollisionTypeStr() const;
285
286            //! Sets the mass of this object. Note that the total mass may be influenced by attached objects!
287            inline void setMass(float mass)
288                { this->mass_ = mass; recalculateMassProps(); }
289            //! Returns the mass of this object without its children.
290            inline float getMass() const
291                { return this->mass_; }
292
293            //! Returns the total mass of this object with all its attached children.
294            inline float getTotalMass() const
295                { return this->mass_ + this->childrenMass_; }
296
297            /**
298            @brief
299                Returns the diagonal elements of the inertia tensor when calculated in local coordinates.
300            @Note
301                The local inertia tensor cannot be set, but is calculated by Bullet according to the collisionShape.
302                With compound collision shapes, an approximation is used.
303            */
304            inline const btVector3& getLocalInertia() const
305                { return this->localInertia_; }
306
307            /**
308            @brief
309                Sets how much reaction is applied in a collision.
310
311                Consider two equal spheres colliding with equal velocities:
312                Restitution 1 means that both spheres simply reverse their velocity (no loss of energy)
313                Restitution 0 means that both spheres will immediately stop moving
314                (maximum loss of energy without violating of the preservation of momentum)
315            */
316            inline void setRestitution(float restitution)
317                { this->restitution_ = restitution; internalSetPhysicsProps(); }
318            //! Returns the restitution parameter. @see setRestitution.
319            inline float getRestitution() const
320                { return this->restitution_; }
321
322            /**
323            @brief
324                Sets an artificial parameter that tells how much torque is applied when you apply a non-central force.
325
326                Normally the angular factor is 1, which means it's physically 'correct'. However if you have a player
327                character that should not rotate when hit sideways, you can set the angular factor to 0.
328            */
329            inline void setAngularFactor(float angularFactor)
330                { this->angularFactor_ = angularFactor; internalSetPhysicsProps(); }
331            //! Returns the angular factor. @see setAngularFactor.
332            inline float getAngularFactor() const
333                { return this->angularFactor_; }
334
335            //! Applies a mass independent damping. Velocities will simply diminish exponentially.
336            inline void setLinearDamping(float linearDamping)
337                { this->linearDamping_ = linearDamping; internalSetPhysicsProps(); }
338            //! Returns the linear damping. @see setLinearDamping.
339            inline float getLinearDamping() const
340                { return this->linearDamping_; }
341
342            //! Applies a tensor independent rotation damping. Angular velocities will simply diminish exponentially.
343            inline void setAngularDamping(float angularDamping)
344                { this->angularDamping_ = angularDamping; internalSetPhysicsProps(); }
345            //! Returns the angular damping. @see setAngularDamping.
346            inline float getAngularDamping() const
347                { return this->angularDamping_; }
348
349            //! Applies friction to the object. Friction occurs when two objects collide.
350            inline void setFriction(float friction)
351                { this->friction_ = friction; internalSetPhysicsProps(); }
352            //! Returns the amount of friction applied to the object.
353            inline float getFriction() const
354                { return this->friction_; }
355
356            void attachCollisionShape(CollisionShape* shape);
357            void detachCollisionShape(CollisionShape* shape);
358            CollisionShape* getAttachedCollisionShape(unsigned int index);
359
360            void notifyCollisionShapeChanged();
361            void notifyChildMassChanged();
362
363            /**
364            @brief
365                Virtual function that gets called when this object collides with another.
366            @param otherObject
367                The object this one has collided into.
368            @pram contactPoint
369                Contact point provided by Bullet. Holds more information and can me modified. See return value.
370            @Return
371                Returning false means that no modification to the contactPoint has been made. Return true otherwise!
372            @Note
373                Condition is that enableCollisionCallback() was called.
374            */
375            virtual inline bool collidesAgainst(WorldEntity* otherObject, btManifoldPoint& contactPoint)
376                { return false; } /* With false, Bullet assumes no modification to the collision objects. */
377
378            //! Enables the collidesAgainst(.) function. The object doesn't respond to collision otherwise!
379            inline void enableCollisionCallback()
380                { this->bCollisionCallbackActive_ = true; this->collisionCallbackActivityChanged(); }
381            //! Disables the collidesAgainst(.) function. @see enableCollisionCallback()
382            inline void disableCollisionCallback()
383                { this->bCollisionCallbackActive_ = false; this->collisionCallbackActivityChanged(); }
384            //! Tells whether there could be a collision callback via collidesAgainst(.)
385            inline bool isCollisionCallbackActive() const
386                { return this->bCollisionCallbackActive_; }
387
388            //! Enables or disables collision response (default is of course on)
389            inline void setCollisionResponse(bool value)
390                { this->bCollisionResponseActive_ = value; this->collisionResponseActivityChanged(); }
391            //! Tells whether there could be a collision response
392            inline bool hasCollisionResponse()
393                { return this->bCollisionResponseActive_; }
394
395        protected:
396            /**
397            @brief
398                Function checks whether the requested collision type is legal to this object.
399
400                You can override this function in a derived class to constrain the collision to e.g. None or Dynamic.
401                A projectile may not prove very useful if there is no physical body. Simply set the CollisionType
402                in its constructor and override this method. But be careful that a derived class's virtual functions
403                don't yet exist in the constructor if a base class.
404            */
405            virtual bool isCollisionTypeLegal(CollisionType type) const = 0;
406
407            btRigidBody*  physicalBody_; //!< Bullet rigid body. Everything physical is applied to this instance.
408
409        private:
410            void recalculateMassProps();
411            void internalSetPhysicsProps();
412
413            bool notifyBeingAttached(WorldEntity* newParent);
414            void notifyDetached();
415
416            // network callbacks
417            void collisionTypeChanged();
418            void physicsActivityChanged();
419            void collisionCallbackActivityChanged();
420            void collisionResponseActivityChanged();
421            //! Network callback workaround to call a function when the value changes.
422            inline void massChanged()
423                { this->setMass(this->mass_); }
424            //! Network callback workaround to call a function when the value changes.
425            inline void restitutionChanged()
426                { this->setRestitution(this->restitution_); }
427            //! Network callback workaround to call a function when the value changes.
428            inline void angularFactorChanged()
429                { this->setAngularFactor(this->angularFactor_); }
430            //! Network callback workaround to call a function when the value changes.
431            inline void linearDampingChanged()
432                { this->setLinearDamping(this->linearDamping_); }
433            //! Network callback workaround to call a function when the value changes.
434            inline void angularDampingChanged()
435                { this->setAngularDamping(this->angularDamping_); }
436            //! Network callback workaround to call a function when the value changes.
437            inline void frictionChanged()
438                { this->setFriction(this->friction_); }
439
440            CollisionType                collisionType_;                 //!< @see setCollisionType
441            CollisionType                collisionTypeSynchronised_;     //!< Network synchronised variable for collisionType_
442            bool                         bPhysicsActive_;                //!< @see isPhysicsActive
443            bool                         bPhysicsActiveSynchronised_;    //!< Network synchronised variable for bPhysicsActive_
444            //! When attaching objects hierarchically this variable tells this object (as child) whether physics was activated before attaching (because the deactivate physics while being attached).
445            bool                         bPhysicsActiveBeforeAttaching_;
446            WorldEntityCollisionShape*   collisionShape_;                //!< Attached collision shapes go here
447            btScalar                     mass_;                          //!< @see setMass
448            btVector3                    localInertia_;                  //!< @see getLocalInertia
449            btScalar                     restitution_;                   //!< @see setRestitution
450            btScalar                     angularFactor_;                 //!< @see setAngularFactor
451            btScalar                     linearDamping_;                 //!< @see setLinearDamping
452            btScalar                     angularDamping_;                //!< @see setAngularDamping
453            btScalar                     friction_;                      //!< @see setFriction
454            btScalar                     childrenMass_;                  //!< Sum of all the children's masses
455            bool                         bCollisionCallbackActive_;      //!< @see enableCollisionCallback
456            bool                         bCollisionResponseActive_;      //!< Tells whether the object should respond to collisions
457    };
458
459    // Inline heavily used functions for release builds. In debug, we better avoid including OgreSceneNode here.
460#ifdef ORXONOX_RELEASE
461    inline const Vector3& WorldEntity::getPosition() const
462        { return this->node_->getPosition(); }
463    inline const Quaternion& WorldEntity::getOrientation() const
464        { return this->node_->getOrientation(); }
465    inline const Vector3& WorldEntity::getScale3D() const
466        { return this->node_->getScale(); }
467#endif
468
469    SUPER_FUNCTION(5, WorldEntity, changedScale, false);
470}
471
472#endif /* _WorldEntity_H__ */
Note: See TracBrowser for help on using the repository browser.