Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/campaignHS15/src/orxonox/controllers/FlyingController.cc @ 10946

Last change on this file since 10946 was 10946, checked in by gania, 8 years ago

fix for sigsegv?

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