Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/controllers/FlyingController.cc @ 12037

Last change on this file since 12037 was 11071, checked in by landauf, 9 years ago

merged branch cpp11_v3 back to trunk

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