Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentation2/src/orxonox/worldentities/WorldEntity.h @ 6407

Last change on this file since 6407 was 6108, checked in by scheusso, 15 years ago

merged steering branch to presentation2 branch

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