Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3088 was 3077, checked in by landauf, 15 years ago

Added Attacher - a class which attaches itself to an object with a given name

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