Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ScriptableController_HS17/src/orxonox/worldentities/WorldEntity.h @ 11562

Last change on this file since 11562 was 11562, checked in by kohlia, 6 years ago

Figuring out when the different things are ready in orxonox

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