Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/environment2/src/orxonox/worldentities/WorldEntity.h @ 8804

Last change on this file since 8804 was 8557, checked in by marwegma, 13 years ago

Godrays: Safety commit. 90017 N8

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