Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 11518 was 11518, checked in by kohlia, 7 years ago

Nothing to see yet, really.

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