Index: code/trunk/src/orxonox/objects/worldentities/WorldEntity.h
===================================================================
--- code/trunk/src/orxonox/objects/worldentities/WorldEntity.h	(revision 2171)
+++ code/trunk/src/orxonox/objects/worldentities/WorldEntity.h	(revision 2662)
@@ -22,4 +22,5 @@
  *   Author:
  *      Fabian 'x3n' Landau
+ *      Reto Grieder (physics)
  *   Co-authors:
  *      ...
@@ -32,16 +33,45 @@
 #include "OrxonoxPrereqs.h"
 
-#define OGRE_FORCE_ANGLE_TYPES
-
+#ifdef _NDEBUG
 #include <OgreSceneNode.h>
-
-#include "network/Synchronisable.h"
+#else
+#include <OgrePrerequisites.h>
+#endif
+#include "LinearMath/btMotionState.h"
+
+#include "util/Math.h"
 #include "core/BaseObject.h"
-#include "util/Math.h"
+#include "network/synchronisable/Synchronisable.h"
 
 namespace orxonox
 {
-    class _OrxonoxExport WorldEntity : public BaseObject, public Synchronisable
+    /**
+    @brief
+        The WorldEntity represents everything that can be put in a Scene at a certain location.
+
+        It is supposed to be the base class of everything you would call an 'object' in a Scene.
+        The class itself is abstract which means you cannot use it directly. You may use StaticEntity
+        as the simplest derivative or (derived from MobileEntity) MovableEntity and ControllableEntity
+        as more advanced ones.
+
+        The basic task of the WorldEntity is provide a location, a direction and a scaling and the possibility
+        to create an entire hierarchy of derivated objects.
+        It is also the basis for the physics interface to the Bullet physics engine.
+        Every WorldEntity can have a specific collision type: @see CollisionType
+        This would then imply that every scene object could have any collision type. To limit this, you can always
+        override this->isCollisionTypeLegal(CollisionType). Return false if the collision type is not supported
+        for a specific object.
+        There is also support for attaching WorldEntities with physics to each other. Currently, the collision shape
+        of both objects simply get merged into one larger shape (for static collision type).
+        The phyiscal body that is internally stored and administrated has the following supported properties:
+        - Restitution, angular factor, linear damping, angular damping, fricition, mass and collision shape.
+        You can get more information at the corresponding set function.
+
+        Collision shapes: These are controlled by the internal WorldEntityCollisionShape. @see WorldEntityCollisionShape.
+    */
+    class _OrxonoxExport WorldEntity : public BaseObject, public Synchronisable, public btMotionState
     {
+        friend class Scene;
+
         public:
             WorldEntity(BaseObject* creator);
@@ -51,5 +81,5 @@
             void registerVariables();
 
-            inline Ogre::SceneNode* getNode() const
+            inline const Ogre::SceneNode* getNode() const
                 { return this->node_; }
 
@@ -64,12 +94,13 @@
             inline void setPosition(float x, float y, float z)
                 { this->setPosition(Vector3(x, y, z)); }
-            inline const Vector3& getPosition() const
-                { return this->node_->getPosition(); }
-            inline const Vector3& getWorldPosition() const
-                { return this->node_->getWorldPosition(); }
-
-            virtual void translate(const Vector3& distance, Ogre::Node::TransformSpace relativeTo = Ogre::Node::TS_LOCAL) = 0;
-            inline void translate(float x, float y, float z, Ogre::Node::TransformSpace relativeTo = Ogre::Node::TS_LOCAL)
+            const Vector3& getPosition() const;
+            const Vector3& getWorldPosition() const;
+
+            void translate(const Vector3& distance, TransformSpace::Enum relativeTo = TransformSpace::Parent);
+            inline void translate(float x, float y, float z, TransformSpace::Enum relativeTo = TransformSpace::Parent)
                 { this->translate(Vector3(x, y, z), relativeTo); }
+
+            virtual inline const Vector3& getVelocity() const
+                { return Vector3::ZERO; }
 
             virtual void setOrientation(const Quaternion& orientation) = 0;
@@ -80,54 +111,53 @@
             inline void setOrientation(const Vector3& axis, const Degree& angle)
                 { this->setOrientation(Quaternion(angle, axis)); }
-            inline const Quaternion& getOrientation() const
-                { return this->node_->getOrientation(); }
-            inline const Quaternion& getWorldOrientation() const
-                { return this->node_->getWorldOrientation(); }
-
-            virtual void rotate(const Quaternion& rotation, Ogre::Node::TransformSpace relativeTo = Ogre::Node::TS_LOCAL) = 0;
-            inline void rotate(const Vector3& axis, const Degree& angle, Ogre::Node::TransformSpace relativeTo = Ogre::Node::TS_LOCAL)
+            const Quaternion& getOrientation() const;
+            const Quaternion& getWorldOrientation() const;
+
+            void rotate(const Quaternion& rotation, TransformSpace::Enum relativeTo = TransformSpace::Local);
+            inline void rotate(const Vector3& axis, const Degree& angle, TransformSpace::Enum relativeTo = TransformSpace::Local)
                 { this->rotate(Quaternion(angle, axis), relativeTo); }
-            inline void rotate(const Vector3& axis, const Radian& angle, Ogre::Node::TransformSpace relativeTo = Ogre::Node::TS_LOCAL)
-                { this->rotate(Quaternion(angle, axis), relativeTo); }
-
-            virtual void yaw(const Degree& angle, Ogre::Node::TransformSpace relativeTo = Ogre::Node::TS_LOCAL) = 0;
-            inline void yaw(const Radian& angle, Ogre::Node::TransformSpace relativeTo = Ogre::Node::TS_LOCAL)
-                { this->yaw(Degree(angle), relativeTo); }
-            virtual void pitch(const Degree& angle, Ogre::Node::TransformSpace relativeTo = Ogre::Node::TS_LOCAL) = 0;
-            inline void pitch(const Radian& angle, Ogre::Node::TransformSpace relativeTo = Ogre::Node::TS_LOCAL)
-                { this->pitch(Degree(angle), relativeTo); }
-            virtual void roll(const Degree& angle, Ogre::Node::TransformSpace relativeTo = Ogre::Node::TS_LOCAL) = 0;
-            inline void roll(const Radian& angle, Ogre::Node::TransformSpace relativeTo = Ogre::Node::TS_LOCAL)
-                { this->roll(Degree(angle), relativeTo); }
-
-            virtual void lookAt(const Vector3& target, Ogre::Node::TransformSpace relativeTo = Ogre::Node::TS_LOCAL, const Vector3& localDirectionVector = Vector3::NEGATIVE_UNIT_Z) = 0;
-            virtual void setDirection(const Vector3& direction, Ogre::Node::TransformSpace relativeTo = Ogre::Node::TS_LOCAL, const Vector3& localDirectionVector = Vector3::NEGATIVE_UNIT_Z) = 0;
-            inline void setDirection(float x, float y, float z, Ogre::Node::TransformSpace relativeTo = Ogre::Node::TS_LOCAL, const Vector3& localDirectionVector = Vector3::NEGATIVE_UNIT_Z)
+
+            inline void yaw(const Degree& angle, TransformSpace::Enum relativeTo = TransformSpace::Local)
+                { this->rotate(Quaternion(angle, Vector3::UNIT_Y), relativeTo); }
+            inline void pitch(const Degree& angle, TransformSpace::Enum relativeTo = TransformSpace::Local)
+                { this->rotate(Quaternion(angle, Vector3::UNIT_X), relativeTo); }
+            inline void roll(const Degree& angle, TransformSpace::Enum relativeTo = TransformSpace::Local)
+                { this->rotate(Quaternion(angle, Vector3::UNIT_Z), relativeTo); }
+
+            void lookAt(const Vector3& target, TransformSpace::Enum relativeTo = TransformSpace::Parent, const Vector3& localDirectionVector = Vector3::NEGATIVE_UNIT_Z);
+            void setDirection(const Vector3& direction, TransformSpace::Enum relativeTo = TransformSpace::Local, const Vector3& localDirectionVector = Vector3::NEGATIVE_UNIT_Z);
+            inline void setDirection(float x, float y, float z, TransformSpace::Enum relativeTo = TransformSpace::Local, const Vector3& localDirectionVector = Vector3::NEGATIVE_UNIT_Z)
                 { this->setDirection(Vector3(x, y, z), relativeTo, localDirectionVector); }
 
-            inline void setScale3D(const Vector3& scale)
-                { this->node_->setScale(scale); }
+            virtual void setScale3D(const Vector3& scale);
             inline void setScale3D(float x, float y, float z)
-                { this->node_->setScale(x, y, z); }
-            inline const Vector3& getScale3D(void) const
-                { return this->node_->getScale(); }
+                { this->setScale3D(Vector3(x, y, z)); }
+            const Vector3& getScale3D(void) const;
+            const Vector3& getWorldScale3D() const;
 
             inline void setScale(float scale)
-                { this->node_->setScale(scale, scale, scale); }
+                { this->setScale3D(scale, scale, scale); }
             inline float getScale() const
                 { Vector3 scale = this->getScale3D(); return (scale.x == scale.y && scale.x == scale.z) ? scale.x : 1; }
+            float getWorldScale() const;
 
             inline void scale3D(const Vector3& scale)
-                { this->node_->scale(scale); }
+                { this->setScale3D(this->getScale3D() * scale); }
             inline void scale3D(float x, float y, float z)
-                { this->node_->scale(x, y, z); }
+                { this->scale3D(Vector3(x, y, z)); }
             inline void scale(float scale)
-                { this->node_->scale(scale, scale, scale); }
+                { this->scale3D(scale, scale, scale); }
+
+            virtual void changedScale() {}
 
             void attach(WorldEntity* object);
             void detach(WorldEntity* object);
-            WorldEntity* getAttachedObject(unsigned int index) const;
+            WorldEntity* getAttachedObject(unsigned int index);
             inline const std::set<WorldEntity*>& getAttachedObjects() const
                 { return this->children_; }
+
+            void attachOgreObject(Ogre::MovableObject* object);
+            void detachOgreObject(Ogre::MovableObject* object);
+            Ogre::MovableObject* detachOgreObject(const Ogre::String& name);
 
             inline void attachToParent(WorldEntity* parent)
@@ -138,10 +168,15 @@
                 { return this->parent_; }
 
+            void attachNode(Ogre::SceneNode* node);
+            void detachNode(Ogre::SceneNode* node);
+            void attachToNode(Ogre::SceneNode* node);
+            void detachFromNode(Ogre::SceneNode* node);
+
+            void notifyChildPropsChanged();
+
         protected:
             Ogre::SceneNode* node_;
 
         private:
-            void updateParent();
-
             inline void lookAt_xmlport(const Vector3& target)
                 { this->lookAt(target); }
@@ -155,8 +190,243 @@
                 { this->roll(angle); }
 
+            // network callbacks
+            void parentChanged();
+            inline void scaleChanged()
+                { this->setScale3D(this->getScale3D()); }
+
             WorldEntity* parent_;
             unsigned int parentID_;
             std::set<WorldEntity*> children_;
+
+
+        /////////////
+        // Physics //
+        /////////////
+
+        public:
+            /**
+            @brief
+                Denotes the possible types of physical objects in a Scene.
+
+                Dynamic:   The object is influenced by its physical environment, like for instance little ball.
+                Kinematic: The object can only influence other dynamic objects. It's movement is coordinated by your own saying.
+                Static:    Like kinematic but the object is not allowed to move during the simulation.
+                None:      The object has no physics at all.
+            */
+            enum CollisionType
+            {
+                Dynamic,
+                Kinematic,
+                Static,
+                None
+            };
+
+            //! Tells whether the object has any connection to the Bullet physics engine. If hasPhysics() is false, the object may still have a velocity.
+            bool hasPhysics()       const { return getCollisionType() != None     ; }
+            //! @see CollisionType
+            bool isStatic()         const { return getCollisionType() == Static   ; }
+            //! @see CollisionType
+            bool isKinematic()      const { return getCollisionType() == Kinematic; }
+            //! @see CollisionType
+            bool isDynamic()        const { return getCollisionType() == Dynamic  ; }
+            //! Tells whether physics has been activated (you can temporarily deactivate it)
+            bool isPhysicsActive()  const { return this->bPhysicsActive_; }
+            bool addedToPhysicalWorld() const;
+
+            void activatePhysics();
+            void deactivatePhysics();
+
+            //! Returns the CollisionType. @see CollisionType.
+            inline CollisionType getCollisionType() const
+                { return this->collisionType_; }
+            void setCollisionType(CollisionType type);
+
+            void setCollisionTypeStr(const std::string& type);
+            std::string getCollisionTypeStr() const;
+
+            //! Sets the mass of this object. Note that the total mass may be influenced by attached objects!
+            inline void setMass(float mass)
+                { this->mass_ = mass; recalculateMassProps(); }
+            //! Returns the mass of this object without its children.
+            inline float getMass() const
+                { return this->mass_; }
+
+            //! Returns the total mass of this object with all its attached children.
+            inline float getTotalMass() const
+                { return this->mass_ + this->childrenMass_; }
+
+            /**
+            @brief
+                Returns the diagonal elements of the inertia tensor when calculated in local coordinates.
+            @Note
+                The local inertia tensor cannot be set, but is calculated by Bullet according to the collisionShape.
+                With compound collision shapes, an approximation is used.
+            */
+            inline const btVector3& getLocalInertia() const
+                { return this->localInertia_; }
+
+            /**
+            @brief
+                Sets how much reaction is applied in a collision.
+                
+                Consider two equal spheres colliding with equal velocities:
+                Restitution 1 means that both spheres simply reverse their velocity (no loss of energy)
+                Restitution 0 means that both spheres will immediately stop moving
+                (maximum loss of energy without violating of the preservation of momentum)
+            */
+            inline void setRestitution(float restitution)
+                { this->restitution_ = restitution; internalSetPhysicsProps(); }
+            //! Returns the restitution parameter. @see setRestitution.
+            inline float getRestitution() const
+                { return this->restitution_; }
+
+            /**
+            @brief
+                Sets an artificial parameter that tells how much torque is applied when you apply a non-central force.
+
+                Normally the angular factor is 1, which means it's physically 'correct'. Howerver if you have a player
+                character that should not rotate when hit sideways, you can set the angular factor to 0.
+            */
+            inline void setAngularFactor(float angularFactor)
+                { this->angularFactor_ = angularFactor; internalSetPhysicsProps(); }
+            //! Returns the angular factor. @see setAngularFactor.
+            inline float getAngularFactor() const
+                { return this->angularFactor_; }
+
+            //! Applies a mass independent damping. Velocities will simply diminish exponentially.
+            inline void setLinearDamping(float linearDamping)
+                { this->linearDamping_ = linearDamping; internalSetPhysicsProps(); }
+            //! Returns the linear damping. @see setLinearDamping.
+            inline float getLinearDamping() const
+                { return this->linearDamping_; }
+
+            //! Applies a tensor independent rotation damping. Angular velocities will simply diminish exponentially.
+            inline void setAngularDamping(float angularDamping)
+                { this->angularDamping_ = angularDamping; internalSetPhysicsProps(); }
+            //! Returns the angular damping. @see setAngularDamping.
+            inline float getAngularDamping() const
+                { return this->angularDamping_; }
+
+            //! Applies friction to the object. Friction occurs when two objects collide.
+            inline void setFriction(float friction)
+                { this->friction_ = friction; internalSetPhysicsProps(); }
+            //! Returns the amount of friction applied to the object.
+            inline float getFriction() const
+                { return this->friction_; }
+
+            void attachCollisionShape(CollisionShape* shape);
+            void detachCollisionShape(CollisionShape* shape);
+            CollisionShape* getAttachedCollisionShape(unsigned int index);
+
+            void notifyCollisionShapeChanged();
+            void notifyChildMassChanged();
+
+            /**
+            @brief
+                Virtual function that gets called when this object collides with another.
+            @param otherObject
+                The object this one has collided into.
+            @pram contactPoint
+                Contact point provided by Bullet. Holds more information and can me modified. See return value.
+            @Return
+                Returning false means that no modification to the contactPoint has been made. Return true otherwise!
+            @Note
+                Condition is that enableCollisionCallback() was called.
+            */
+            virtual inline bool collidesAgainst(WorldEntity* otherObject, btManifoldPoint& contactPoint)
+                { return false; } /* With false, Bullet assumes no modification to the collision objects. */
+
+            //! Enables the collidesAgainst(.) function. The object doesn't respond to collision otherwise!
+            inline void enableCollisionCallback()
+                { this->bCollisionCallbackActive_ = true; this->collisionCallbackActivityChanged(); }
+            //! Disables the collidesAgainst(.) function. @see enableCollisionCallback()
+            inline void disableCollisionCallback()
+                { this->bCollisionCallbackActive_ = false; this->collisionCallbackActivityChanged(); }
+            //! Tells whether there could be a collision callback via collidesAgainst(.)
+            inline bool isCollisionCallbackActive() const
+                { return this->bCollisionCallbackActive_; }
+
+            //! Enables or disables collision response (default is of course on)
+            inline void setCollisionResponse(bool value)
+                { this->bCollisionResponseActive_ = value; this->collisionResponseActivityChanged(); }
+            //! Tells whether there could be a collision response
+            inline bool hasCollisionResponse()
+                { return this->bCollisionResponseActive_; }
+
+        protected:
+            /**
+            @brief
+                Function checks whether the requested collision type is legal to this object.
+
+                You can override this function in a derived class to constrain the collision to e.g. None or Dynamic.
+                A projectile may not prove very useful if there is no physical body. Simply set the CollisionType
+                in its constructor and override this method. But be careful that a derived classe's virtual functions
+                don't yet exist in the constructor if a base class.
+            */
+            virtual bool isCollisionTypeLegal(CollisionType type) const = 0;
+
+            btRigidBody*  physicalBody_; //!< Bullet rigid body. Everything physical is applied to this instance.
+
+        private:
+            void recalculateMassProps();
+            void internalSetPhysicsProps();
+
+            bool notifyBeingAttached(WorldEntity* newParent);
+            void notifyDetached();
+
+            // network callbacks
+            void collisionTypeChanged();
+            void physicsActivityChanged();
+            void collisionCallbackActivityChanged();
+            void collisionResponseActivityChanged();
+            //! Network callback workaround to call a function when the value changes.
+            inline void massChanged()
+                { this->setMass(this->mass_); }
+            //! Network callback workaround to call a function when the value changes.
+            inline void restitutionChanged()
+                { this->setRestitution(this->restitution_); }
+            //! Network callback workaround to call a function when the value changes.
+            inline void angularFactorChanged()
+                { this->setAngularFactor(this->angularFactor_); }
+            //! Network callback workaround to call a function when the value changes.
+            inline void linearDampingChanged()
+                { this->setLinearDamping(this->linearDamping_); }
+            //! Network callback workaround to call a function when the value changes.
+            inline void angularDampingChanged()
+                { this->setAngularDamping(this->angularDamping_); }
+            //! Network callback workaround to call a function when the value changes.
+            inline void frictionChanged()
+                { this->setFriction(this->friction_); }
+
+            CollisionType                collisionType_;                 //!< @see setCollisionType
+            CollisionType                collisionTypeSynchronised_;     //!< Network synchronised variable for collisionType_
+            bool                         bPhysicsActive_;                //!< @see isPhysicsActive
+            bool                         bPhysicsActiveSynchronised_;    //!< Network synchronised variable for bPhysicsActive_
+            //! When attaching objects hierarchically this variable tells this object (as child) whether physics was activated before attaching (because the deactivate physics while being attached).
+            bool                         bPhysicsActiveBeforeAttaching_;
+            WorldEntityCollisionShape*   collisionShape_;                //!< Attached collision shapes go here
+            btScalar                     mass_;                          //!< @see setMass
+            btVector3                    localInertia_;                  //!< @see getLocalInertia
+            btScalar                     restitution_;                   //!< @see setRestitution
+            btScalar                     angularFactor_;                 //!< @see setAngularFactor
+            btScalar                     linearDamping_;                 //!< @see setLinearDamping
+            btScalar                     angularDamping_;                //!< @see setAngularDamping
+            btScalar                     friction_;                      //!< @see setFriction
+            btScalar                     childrenMass_;                  //!< Sum of all the children's masses
+            bool                         bCollisionCallbackActive_;      //!< @see enableCollisionCallback
+            bool                         bCollisionResponseActive_;      //!< Tells whether the object should respond to collisions
     };
+
+    // Inline heavily used functions for release builds. In debug, we better avoid including OgreSceneNode here.
+#ifdef _NDEBUG
+    inline const Vector3& WorldEntity::getPosition() const
+        { return this->node_->getPosition(); }
+    inline const Quaternion& WorldEntity::getOrientation() const
+        { return this->node_->getrOrientation(); }
+    inline const Vector3& WorldEntity::getScale3D(void) const
+        { return this->node_->getScale(); }
+#endif
+
+    SUPER_FUNCTION(5, WorldEntity, changedScale, false);
 }
 
