Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/worldentities/MobileEntity.cc @ 8721

Last change on this file since 8721 was 8706, checked in by dafrick, 14 years ago

Merging presentation branch back into trunk.
There are many new features and also a lot of other changes and bugfixes, if you want to know, digg through the svn log.
Not everything is yet working as it should, but it should be fairly stable. If you habe any bug reports, just send me an email.

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