Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 2939 was 2911, checked in by landauf, 16 years ago

Merged r1-2096 of questsystem5 back to trunk

I hope there weren't more "hidden merge changes" in r2909 than the one in OverlayGroup (removeElement) (and related to this the adjustments in NotificationQueue).

The corresponding media commit seems not yet to be done, but it doesn't break the build.

File size: 8.1 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
67        Vector3 rotationAxis(this->getRotationAxis());
68        Degree rotationRate = this->getRotationRate();
69        XMLPortParamVariable(MobileEntity, "rotationaxis", rotationAxis, xmlelement, mode);
70        XMLPortParamVariable(MobileEntity, "rotationrate", rotationRate, xmlelement, mode);
71        if (mode == XMLPort::LoadObject)
72        {
73            if (rotationAxis == Vector3::ZERO)
74                this->setAngularVelocity(Vector3::ZERO);
75            else
76                this->setAngularVelocity(rotationAxis.normalisedCopy() * rotationRate.valueRadians());
77        }
78    }
79
80    void MobileEntity::tick(float dt)
81    {
82        if (this->isActive())
83        {
84            // Check whether Bullet doesn't do the physics for us
85            if (!this->isDynamic())
86            {
87                // Linear part
88                this->linearVelocity_.x += this->linearAcceleration_.x * dt;
89                this->linearVelocity_.y += this->linearAcceleration_.y * dt;
90                this->linearVelocity_.z += this->linearAcceleration_.z * dt;
91                this->node_->translate(this->linearVelocity_ * dt);
92
93                // Angular part
94                // Note: angularVelocity_ is a Quaternion with w = 0 while angularAcceleration_ is a Vector3
95                this->angularVelocity_.x += angularAcceleration_.x * dt;
96                this->angularVelocity_.y += angularAcceleration_.y * dt;
97                this->angularVelocity_.z += angularAcceleration_.z * dt;
98                // Calculate new orientation with quaternion derivative. This is about 30% faster than with angle/axis method.
99                float mult = dt * 0.5;
100                // TODO: this could be optimized by writing it out. The calls currently create 4 new Quaternions!
101                Quaternion newOrientation(0.0f, this->angularVelocity_.x * mult, this->angularVelocity_.y * mult, this->angularVelocity_.z * mult);
102                newOrientation = this->node_->getOrientation() + newOrientation * this->node_->getOrientation();
103                newOrientation.normalise();
104                this->node_->setOrientation(newOrientation);
105            }
106        }
107    }
108
109    void MobileEntity::setPosition(const Vector3& position)
110    {
111        if (this->isDynamic())
112        {
113            btTransform transf = this->physicalBody_->getWorldTransform();
114            transf.setOrigin(btVector3(position.x, position.y, position.z));
115            this->physicalBody_->setWorldTransform(transf);
116        }
117
118        this->node_->setPosition(position);
119    }
120
121    void MobileEntity::setOrientation(const Quaternion& orientation)
122    {
123        if (this->isDynamic())
124        {
125            btTransform transf = this->physicalBody_->getWorldTransform();
126            transf.setRotation(btQuaternion(orientation.x, orientation.y, orientation.z, orientation.w));
127            this->physicalBody_->setWorldTransform(transf);
128        }
129
130        this->node_->setOrientation(orientation);
131    }
132
133    void MobileEntity::setVelocity(const Vector3& velocity)
134    {
135        if (this->isDynamic())
136            this->physicalBody_->setLinearVelocity(btVector3(velocity.x, velocity.y, velocity.z));
137
138        this->linearVelocity_ = velocity;
139    }
140
141    void MobileEntity::setAngularVelocity(const Vector3& velocity)
142    {
143        if (this->isDynamic())
144            this->physicalBody_->setAngularVelocity(btVector3(velocity.x, velocity.y, velocity.z));
145
146        this->angularVelocity_ = velocity;
147    }
148
149    void MobileEntity::setAcceleration(const Vector3& acceleration)
150    {
151        if (this->isDynamic())
152            this->physicalBody_->applyCentralForce(btVector3(acceleration.x * this->getMass(), acceleration.y * this->getMass(), acceleration.z * this->getMass()));
153
154        this->linearAcceleration_ = acceleration;
155    }
156
157    void MobileEntity::setAngularAcceleration(const Vector3& acceleration)
158    {
159        if (this->isDynamic())
160        {
161            btVector3 inertia(btVector3(1, 1, 1) / this->physicalBody_->getInvInertiaDiagLocal());
162            this->physicalBody_->applyTorque(btVector3(acceleration.x, acceleration.y, acceleration.z) * inertia);
163        }
164
165        this->angularAcceleration_ = acceleration;
166    }
167
168    bool MobileEntity::isCollisionTypeLegal(WorldEntity::CollisionType type) const
169    {
170        if (type == WorldEntity::Static)
171        {
172            CCOUT(1) << "Error: Cannot tell a MobileEntity to have static collision type! Ignoring." << std::endl;
173            assert(false); // Only in debug mode
174            return false;
175        }
176        else
177            return true;
178    }
179
180    void MobileEntity::setWorldTransform(const btTransform& worldTrans)
181    {
182        // We use a dynamic body. So we translate our node accordingly.
183        this->node_->setPosition(Vector3(worldTrans.getOrigin().x(), worldTrans.getOrigin().y(), worldTrans.getOrigin().z()));
184        btQuaternion temp(worldTrans.getRotation());
185        this->node_->setOrientation(Quaternion(temp.w(), temp.x(), temp.y(), temp.z()));
186        this->linearVelocity_.x = this->physicalBody_->getLinearVelocity().x();
187        this->linearVelocity_.y = this->physicalBody_->getLinearVelocity().y();
188        this->linearVelocity_.z = this->physicalBody_->getLinearVelocity().z();
189        this->angularVelocity_.x = this->physicalBody_->getAngularVelocity().x();
190        this->angularVelocity_.y = this->physicalBody_->getAngularVelocity().y();
191        this->angularVelocity_.z = this->physicalBody_->getAngularVelocity().z();
192    }
193
194    void MobileEntity::getWorldTransform(btTransform& worldTrans) const
195    {
196        // We use a kinematic body
197        worldTrans.setOrigin(btVector3(node_->getPosition().x, node_->getPosition().y, node_->getPosition().z));
198        worldTrans.setRotation(btQuaternion(node_->getOrientation().x, node_->getOrientation().y, node_->getOrientation().z, node_->getOrientation().w));
199        if (this->isDynamic())
200        {
201            // This function gets called only once for dynamic objects to set the initial conditions
202            // We have to set the velocities too.
203            this->physicalBody_->setLinearVelocity(btVector3(linearVelocity_.x, linearVelocity_.y, linearVelocity_.z));
204            this->physicalBody_->setAngularVelocity(btVector3(angularVelocity_.x, angularVelocity_.y, angularVelocity_.z));
205        }
206    }
207}
Note: See TracBrowser for help on using the repository browser.