Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/pickup3/src/orxonox/worldentities/WorldEntity.h @ 6486

Last change on this file since 6486 was 6485, checked in by dafrick, 15 years ago

Added changedActivity and changedVisibility method to WorldEntity, such that, when either is changed it is changed for all attached objects as well.
If this is already implemented somehow and somehwere, my mistake, but I looked and found nothing.

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