Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/network2/src/orxonox/worldentities/WorldEntity.h @ 7193

Last change on this file since 7193 was 6448, checked in by scheusso, 15 years ago

made registerVariables always private. otherwise bad things may happen with variables registered twice or even 3 times (as has happened in ControllableEntity until now)

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