Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentation/src/orxonox/objects/worldentities/WorldEntity.h @ 2540

Last change on this file since 2540 was 2540, checked in by rgrieder, 15 years ago

Added comments to the WorldEntity except for the non physics section of the header file (going to do that some time later).

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