Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/physics/src/orxonox/objects/worldentities/MobileEntity.cc @ 2518

Last change on this file since 2518 was 2427, checked in by rgrieder, 16 years ago

Changed the way setPosition, setVelocity, setOrientation and setAngularVelocity is handled in MobileEntity and upwards.
This allows to introduce a lost feature: Position of an enemy ship on the client can't be set anymore at all (local changes were allowed before).

  • Property svn:eol-style set to native
File size: 7.8 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 *      Reto Grieder
24 *   Co-authors:
25 *      Martin Stypinski
26 *
27 */
28
29#include "OrxonoxStableHeaders.h"
30#include "MobileEntity.h"
31
32#include <OgreSceneNode.h>
33#include "BulletDynamics/Dynamics/btRigidBody.h"
34
35#include "util/Debug.h"
36#include "util/MathConvert.h"
37#include "util/Exception.h"
38#include "core/CoreIncludes.h"
39#include "core/XMLPort.h"
40
41#include "objects/Scene.h"
42
43namespace orxonox
44{
45    MobileEntity::MobileEntity(BaseObject* creator) : WorldEntity(creator)
46    {
47        RegisterObject(MobileEntity);
48
49        this->linearAcceleration_  = Vector3::ZERO;
50        this->linearVelocity_      = Vector3::ZERO;
51        this->angularAcceleration_ = Vector3::ZERO;
52        this->angularVelocity_     = Vector3::ZERO;
53
54        this->registerVariables();
55    }
56
57    MobileEntity::~MobileEntity()
58    {
59    }
60
61    void MobileEntity::XMLPort(Element& xmlelement, XMLPort::Mode mode)
62    {
63        SUPER(MobileEntity, XMLPort, xmlelement, mode);
64
65        XMLPortParamTemplate(MobileEntity, "velocity",     setVelocity,     getVelocity,     xmlelement, mode, const Vector3&);
66        XMLPortParamTemplate(MobileEntity, "rotationaxis", setRotationAxis, getRotationAxis, xmlelement, mode, const Vector3&);
67        XMLPortParam(MobileEntity, "rotationrate", setRotationRate, getRotationRate, xmlelement, mode);
68    }
69
70    void MobileEntity::registerVariables()
71    {
72    }
73
74    void MobileEntity::tick(float dt)
75    {
76        if (this->isActive())
77        {
78            // Check whether Bullet doesn't do the physics for us
79            if (!this->isDynamic())
80            {
81                // Linear part
82                this->linearVelocity_.x += this->linearAcceleration_.x * dt;
83                this->linearVelocity_.y += this->linearAcceleration_.y * dt;
84                this->linearVelocity_.z += this->linearAcceleration_.z * dt;
85                this->node_->translate(this->linearVelocity_ * dt);
86
87                // Angular part
88                // Note: angularVelocity_ is a Quaternion with w = 0 while angularAcceleration_ is a Vector3
89                this->angularVelocity_.x += angularAcceleration_.x * dt;
90                this->angularVelocity_.y += angularAcceleration_.y * dt;
91                this->angularVelocity_.z += angularAcceleration_.z * dt;
92                // Calculate new orientation with quaternion derivative. This is about 30% faster than with angle/axis method.
93                float mult = dt * 0.5;
94                // TODO: this could be optimized by writing it out. The calls currently create 4 new Quaternions!
95                Quaternion newOrientation(0.0f, this->angularVelocity_.x * mult, this->angularVelocity_.y * mult, this->angularVelocity_.z * mult);
96                newOrientation = this->node_->getOrientation() + newOrientation * this->node_->getOrientation();
97                newOrientation.normalise();
98                this->node_->setOrientation(newOrientation);
99            }
100        }
101    }
102
103    void MobileEntity::setPosition(const Vector3& position)
104    {
105        if (this->isDynamic())
106        {
107            btTransform transf = this->physicalBody_->getWorldTransform();
108            transf.setOrigin(btVector3(position.x, position.y, position.z));
109            this->physicalBody_->setWorldTransform(transf);
110        }
111
112        this->node_->setPosition(position);
113    }
114
115    void MobileEntity::setOrientation(const Quaternion& orientation)
116    {
117        if (this->isDynamic())
118        {
119            btTransform transf = this->physicalBody_->getWorldTransform();
120            transf.setRotation(btQuaternion(orientation.x, orientation.y, orientation.z, orientation.w));
121            this->physicalBody_->setWorldTransform(transf);
122        }
123
124        this->node_->setOrientation(orientation);
125    }
126
127    void MobileEntity::setVelocity(const Vector3& velocity)
128    {
129        if (this->isDynamic())
130            this->physicalBody_->setLinearVelocity(btVector3(velocity.x, velocity.y, velocity.z));
131
132        this->linearVelocity_ = velocity;
133    }
134
135    void MobileEntity::setAngularVelocity(const Vector3& velocity)
136    {
137        if (this->isDynamic())
138            this->physicalBody_->setAngularVelocity(btVector3(velocity.x, velocity.y, velocity.z));
139
140        this->angularVelocity_ = velocity;
141    }
142
143    void MobileEntity::setAcceleration(const Vector3& acceleration)
144    {
145        if (this->isDynamic())
146            this->physicalBody_->applyCentralForce(btVector3(acceleration.x * this->getMass(), acceleration.y * this->getMass(), acceleration.z * this->getMass()));
147
148        this->linearAcceleration_ = acceleration;
149    }
150
151    void MobileEntity::setAngularAcceleration(const Vector3& acceleration)
152    {
153        if (this->isDynamic())
154        {
155            btVector3 inertia(btVector3(1, 1, 1) / this->physicalBody_->getInvInertiaDiagLocal());
156            this->physicalBody_->applyTorque(btVector3(acceleration.x, acceleration.y, acceleration.z) * inertia);
157        }
158
159        this->angularAcceleration_ = acceleration;
160    }
161
162    bool MobileEntity::isCollisionTypeLegal(WorldEntity::CollisionType type) const
163    {
164        if (type == WorldEntity::Static)
165        {
166            ThrowException(PhysicsViolation, "Cannot tell a MobileEntity to have static collision type");
167            return false;
168        }
169        else
170            return true;
171    }
172
173    void MobileEntity::setWorldTransform(const btTransform& worldTrans)
174    {
175        // We use a dynamic body. So we translate our node accordingly.
176        this->node_->setPosition(Vector3(worldTrans.getOrigin().x(), worldTrans.getOrigin().y(), worldTrans.getOrigin().z()));
177        this->node_->setOrientation(Quaternion(worldTrans.getRotation().w(), worldTrans.getRotation().x(), worldTrans.getRotation().y(), worldTrans.getRotation().z()));
178        this->linearVelocity_.x = this->physicalBody_->getLinearVelocity().x();
179        this->linearVelocity_.y = this->physicalBody_->getLinearVelocity().y();
180        this->linearVelocity_.z = this->physicalBody_->getLinearVelocity().z();
181        this->angularVelocity_.x = this->physicalBody_->getAngularVelocity().x();
182        this->angularVelocity_.y = this->physicalBody_->getAngularVelocity().y();
183        this->angularVelocity_.z = this->physicalBody_->getAngularVelocity().z();
184    }
185
186    void MobileEntity::getWorldTransform(btTransform& worldTrans) const
187    {
188        // We use a kinematic body
189        worldTrans.setOrigin(btVector3(node_->getPosition().x, node_->getPosition().y, node_->getPosition().z));
190        worldTrans.setRotation(btQuaternion(node_->getOrientation().x, node_->getOrientation().y, node_->getOrientation().z, node_->getOrientation().w));
191        if (this->isDynamic())
192        {
193            // This function gets called only once for dynamic objects to set the initial conditions
194            // We have to set the velocities too.
195            this->physicalBody_->setLinearVelocity(btVector3(linearVelocity_.x, linearVelocity_.y, linearVelocity_.z));
196            this->physicalBody_->setAngularVelocity(btVector3(angularVelocity_.x, angularVelocity_.y, angularVelocity_.z));
197        }
198    }
199}
Note: See TracBrowser for help on using the repository browser.