Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 2926 was 2851, checked in by landauf, 16 years ago

Fixed attachment of "absolute" CameraPosition-Nodes in the Network (this refers to the top-down camera in Pong)

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