Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/network2/src/orxonox/worldentities/MobileEntity.cc @ 6703

Last change on this file since 6703 was 6448, checked in by scheusso, 15 years ago

made registerVariables always private. otherwise bad things may happen with variables registered twice or even 3 times (as has happened in ControllableEntity until now)

  • Property svn:eol-style set to native
File size: 8.2 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            this->physicalBody_->applyCentralForce(btVector3(acceleration.x * this->getMass(), acceleration.y * this->getMass(), acceleration.z * this->getMass()));
146
147        this->linearAcceleration_ = acceleration;
148    }
149
150    void MobileEntity::setAngularAcceleration(const Vector3& acceleration)
151    {
152        if (this->isDynamic())
153        {
154            btVector3 inertia(btVector3(1, 1, 1) / this->physicalBody_->getInvInertiaDiagLocal());
155            this->physicalBody_->applyTorque(btVector3(acceleration.x, acceleration.y, acceleration.z) * inertia);
156        }
157
158        this->angularAcceleration_ = acceleration;
159    }
160
161    void MobileEntity::applyCentralForce(const Vector3& force)
162    {
163        if (this->isDynamic())
164            this->physicalBody_->applyCentralForce(btVector3(force.x * this->getMass(), force.y * this->getMass(), force.z * this->getMass()));
165    }
166
167    bool MobileEntity::isCollisionTypeLegal(WorldEntity::CollisionType type) const
168    {
169        if (type == WorldEntity::Static)
170        {
171            CCOUT(1) << "Error: Cannot tell a MobileEntity to have static collision type! Ignoring." << std::endl;
172            assert(false); // Only in debug mode
173            return false;
174        }
175        else
176            return true;
177    }
178
179    void MobileEntity::setWorldTransform(const btTransform& worldTrans)
180    {
181        // We use a dynamic body. So we translate our node accordingly.
182        this->node_->setPosition(Vector3(worldTrans.getOrigin().x(), worldTrans.getOrigin().y(), worldTrans.getOrigin().z()));
183        btQuaternion temp(worldTrans.getRotation());
184        this->node_->setOrientation(Quaternion(temp.w(), temp.x(), temp.y(), temp.z()));
185        this->linearVelocity_.x = this->physicalBody_->getLinearVelocity().x();
186        this->linearVelocity_.y = this->physicalBody_->getLinearVelocity().y();
187        this->linearVelocity_.z = this->physicalBody_->getLinearVelocity().z();
188        this->angularVelocity_.x = this->physicalBody_->getAngularVelocity().x();
189        this->angularVelocity_.y = this->physicalBody_->getAngularVelocity().y();
190        this->angularVelocity_.z = this->physicalBody_->getAngularVelocity().z();
191    }
192
193    void MobileEntity::getWorldTransform(btTransform& worldTrans) const
194    {
195        // We use a kinematic body
196        worldTrans.setOrigin(btVector3(node_->getPosition().x, node_->getPosition().y, node_->getPosition().z));
197        worldTrans.setRotation(btQuaternion(node_->getOrientation().x, node_->getOrientation().y, node_->getOrientation().z, node_->getOrientation().w));
198        if (this->isDynamic())
199        {
200            // This function gets called only once for dynamic objects to set the initial conditions
201            // We have to set the velocities too.
202            this->physicalBody_->setLinearVelocity(btVector3(linearVelocity_.x, linearVelocity_.y, linearVelocity_.z));
203            this->physicalBody_->setAngularVelocity(btVector3(angularVelocity_.x, angularVelocity_.y, angularVelocity_.z));
204        }
205    }
206}
Note: See TracBrowser for help on using the repository browser.