Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentationHS15/src/orxonox/controllers/FlyingController.cc @ 11026

Last change on this file since 11026 was 11026, checked in by landauf, 8 years ago

eol-style:native

  • Property svn:eol-style set to native
File size: 9.6 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 *      Gani Aliguzhinov
24
25 *   Co-authors:
26 *   ...
27 *
28 */
29#include <OgreMatrix3.h>                        //for Quaternion manipulations
30
31#include "util/Math.h"                         
32#include "core/XMLPort.h"
33#include "controllers/FlyingController.h"
34
35#include "worldentities/pawns/SpaceShip.h"      //for boosting
36
37namespace orxonox
38{   
39    RegisterClass (FlyingController);
40   
41    FlyingController::FlyingController(Context* context): CommonController(context)
42    {
43        RegisterObject(FlyingController);       
44        this->rotationProgress_ = 0;
45        this->spread_ = 200;
46        this->tolerance_ = 80;
47        this->bCopyOrientation_ = true;
48    }
49    FlyingController::~FlyingController() 
50    {
51    }
52
53    void FlyingController::XMLPort(Element& xmlelement, XMLPort::Mode mode)
54    {
55        XMLPortParam(FlyingController, "spread", setSpread, getSpread,  xmlelement, mode);
56        XMLPortParam(FlyingController, "formationMode", setFormationModeXML, getFormationModeXML,  xmlelement, mode);
57        SUPER(FlyingController, XMLPort, xmlelement, mode);
58    }
59   
60    void FlyingController::setFormationModeXML(std::string val)
61    {
62        const std::string valUpper = getUppercase(val);
63        FormationMode::Value value;
64       
65        if (valUpper == "WALL")
66            value = FormationMode::WALL;
67        else if (valUpper == "FINGER4")
68            value = FormationMode::FINGER4;
69        else if (valUpper == "DIAMOND")
70            value = FormationMode::DIAMOND;
71        else
72            ThrowException(ParseError, std::string("Attempting to set an unknown FormationMode: '")+ val + "'.");
73        this->setFormationMode(value);
74    }
75    std::string FlyingController::getFormationModeXML() const
76    {
77        switch (this->formationMode_)
78        {
79            case FormationMode::WALL:
80            { return "WALL"; }
81            case FormationMode::FINGER4:
82            { return "FINGER4"; }
83            case FormationMode::DIAMOND:
84            { return "DIAMOND"; }
85            default:
86                return "DIAMOND";
87        }
88    }
89    void FlyingController::stopMoving()
90    {
91        this->bHasTargetPosition_ = false;
92    }
93    /**
94    @brief
95      if distance to targetPosition is smaller than this->tolerance_, no moving should be made, otherwise
96      find amount of yaw and pitch that have to be applied, so that ship looks at targetPosition, then
97      ship is moved forward towards targetPosition. Also target orientation is being applied.
98    */
99    void FlyingController::moveToPosition(const Vector3& targetPosition, float dt)
100    {
101        if (!this->getControllableEntity())
102            return;
103        ControllableEntity* entity = this->getControllableEntity();
104
105        float distance = (targetPosition - entity->getPosition()).length();
106
107        if (distance >= this->tolerance_)
108        {
109            //function that calculates how much yaw and pitch are to be applied
110            Vector2 coord = get2DViewCoordinates
111                (entity->getPosition() , 
112                entity->getOrientation()  * WorldEntity::FRONT, 
113                entity->getOrientation()  * WorldEntity::UP, 
114                targetPosition);
115            //limit yaw and pitch by [-1,1]
116            float rotateX = -clamp(coord.x * 10, -1.0f, 1.0f);
117            float rotateY = clamp(coord.y * 10, -1.0f, 1.0f);
118
119            if (!entity)
120                return;
121
122            //apply yaw and pitch
123            entity->rotateYaw(ROTATEFACTOR * rotateX * dt);
124            entity->rotatePitch(ROTATEFACTOR * rotateY * dt);
125           
126            if (!entity)
127                return;
128           
129            //only move either if ship looks at target with a certain tolerance, or if ship is far enough for it to be ok to move in a curve.
130            if (distance > this->tolerance_*1.5f || (rotateX > -0.03 && rotateX < 0.03 && rotateY > -0.03 && rotateY < 0.03))
131                entity->moveFrontBack(SPEED * dt);
132            //roll
133            copyTargetOrientation(dt);
134        }
135        else
136        {     
137            bHasTargetPosition_ = false;
138        }
139    }
140    /**
141    @brief
142      fly towards a preset targetPosition_
143    */
144    void FlyingController::moveToTargetPosition(float dt)
145    {
146        this->moveToPosition (this->targetPosition_, dt);
147    }
148    /**
149    @brief
150      roll ship so that it has same roll as orient
151    */
152    void FlyingController::copyOrientation(const Quaternion& orient, float dt)
153    {
154        //copied from
155        //http://www.ogre3d.org/tikiwiki/tiki-index.php?page=Quaternion+and+Rotation+Primer&structure=Tutorials#Q._How_can_I_make_my_objects_rotate_smoothly_You_mentioned_slerp_etc_
156        //how can I make my objects rotate smoothly?
157        if (!this->getControllableEntity())
158            return;
159        Quaternion myOrient = this->getControllableEntity()->getOrientation();
160        this->rotationProgress_ += dt;
161
162        if (this->rotationProgress_ > 1)
163        {
164            this->rotationProgress_ = 0;
165            this->bHasTargetOrientation_ = false;
166        }
167        else
168        {
169            Quaternion deltaOrientation = Quaternion::Slerp(rotationProgress_, myOrient, orient, true);
170           
171            Matrix3 deltaMatrix, myMatrix;
172
173            deltaOrientation.ToRotationMatrix(deltaMatrix);
174            myOrient.ToRotationMatrix (myMatrix);
175
176            Radian yawDelta, pitchDelta, rollDelta, yawMy, pitchMy, rollMy;
177            deltaMatrix.ToEulerAnglesYXZ(yawDelta, pitchDelta, rollDelta);
178            myMatrix.ToEulerAnglesYXZ (yawMy, pitchMy, rollMy);
179
180            if (!this->getControllableEntity())
181                return;
182            this->getControllableEntity()->rotateRoll ((rollDelta.valueRadians() - rollMy.valueRadians())*ROTATEFACTOR*dt);
183        }
184    }
185    /**
186    @brief
187      roll ship so that it has same roll as a preset targetOrientation_
188    */
189    void FlyingController::copyTargetOrientation(float dt)
190    {
191        if (bHasTargetOrientation_)
192        {   
193            this->copyOrientation(targetOrientation_, dt);
194        }
195    }
196    /**
197    @brief
198      set Vector to fly to
199    */
200    void FlyingController::setTargetPosition(const Vector3& target)
201    {
202        this->targetPosition_ = target;
203        this->bHasTargetPosition_ = true;
204    }
205    /**
206    @brief
207      set orientation to apply
208    */
209    void FlyingController::setTargetOrientation(const Quaternion& orient)
210    {
211        this->targetOrientation_=orient;
212        this->bHasTargetOrientation_=true;
213    }
214    /**
215    @brief
216      set orientation to apply
217    */
218    void FlyingController::setTargetOrientation(ControllableEntity* target)
219    {
220        if (target)
221            this->setTargetOrientation(target->getOrientation());
222    }
223    /**
224    @brief
225      boost if you can
226    */
227    void FlyingController::boostControl()
228    {
229        if (!this->getControllableEntity())
230            return;
231        SpaceShip* ship = orxonox_cast<SpaceShip*>(this->getControllableEntity());
232        if(ship == NULL) return;
233        if(ship->getBoostPower()*1.5f > ship->getInitialBoostPower()) //upper limit ->boost
234        {
235            this->getControllableEntity()->boost(true);
236        }
237        else if(ship->getBoostPower()*4.0f < ship->getInitialBoostPower()) //lower limit ->do not boost
238        {
239           this->getControllableEntity()->boost(false);
240        }
241    }
242    /**
243    @brief
244      keep this ship in a formation with its division
245    */
246    void FlyingController::keepFormation(const ControllableEntity* leaderEntity, Vector3& targetRelativePosition)
247    {
248        if (!this->getControllableEntity())
249            return;
250        ControllableEntity* myEntity = this->getControllableEntity();
251        Vector3 myPosition = myEntity->getWorldPosition();
252
253        if (!leaderEntity)
254        {
255            return;
256        }
257        Quaternion orient = leaderEntity->getWorldOrientation();
258        Vector3 leaderPosition = leaderEntity->getWorldPosition();
259
260        if (!leaderEntity)
261        {
262            return;
263        }
264        //calculate where in world coordinates this ship should fly
265        Vector3 targetAbsolutePosition = 
266            (leaderPosition + (orient*WorldEntity::FRONT) * (leaderEntity->getVelocity().length()/5)
267             + (orient* (targetRelativePosition)));
268        //let ship finish rotating. also don't call copyOrientation too often as it is a slow function. Don't know how to do it different
269        if (this->bCopyOrientation_)
270            this->setTargetOrientation (orient);
271        //set a position to fly to
272        this->setTargetPosition (targetAbsolutePosition);
273
274        //boost if too far
275        if ((targetAbsolutePosition - myPosition).length() > this->tolerance_ * 1.5f)
276        {
277            this->boostControl();
278        }
279        else
280        {
281            if (!this->getControllableEntity())
282                return;
283            this->getControllableEntity()->boost(false);
284        }
285    }
286}
Note: See TracBrowser for help on using the repository browser.