Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/hud/Navigation.cc @ 1580

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

started another attempt to fix the occasionally focus-cycling crash

  • Property svn:eol-style set to native
File size: 12.0 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 *      Felix Schulthess
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include "OrxonoxStableHeaders.h"
30#include "Navigation.h"
31
32#include <OgreOverlayManager.h>
33#include <OgreStringConverter.h>
34
35#include "GraphicsEngine.h"
36// TODO: remove the SpaceShip and CameraHandler dependencies
37#include "objects/SpaceShip.h"
38#include "objects/Projectile.h"
39#include "objects/CameraHandler.h"
40#include "RadarObject.h"
41#include "RadarOverlayElement.h"
42#include "HUD.h"
43#include "core/Debug.h"
44#include "util/Math.h"
45
46namespace orxonox
47{
48    using namespace Ogre;
49
50    Navigation::Navigation(OverlayContainer* container)
51    {
52        container_ = container;
53        focus_ = NULL;
54        init();
55    }
56
57    Navigation::~Navigation()
58    {
59        OverlayManager::getSingleton().destroyOverlayElement(this->navText_);
60        OverlayManager::getSingleton().destroyOverlayElement(this->navMarker_);
61        OverlayManager::getSingleton().destroyOverlayElement(this->aimMarker_);
62    }
63
64    void Navigation::init()
65    {
66        // create nav text
67        navText_ = static_cast<TextAreaOverlayElement*>(OverlayManager::getSingleton().createOverlayElement("TextArea", "navText"));
68        navText_->show();
69        navText_->setMetricsMode(Ogre::GMM_PIXELS);
70        navText_->setDimensions(0.001, 0.001);
71        navText_->setPosition(0.02, 0.02);
72        navText_->setFontName("Console");
73        navText_->setCharHeight(20);
74        navText_->setCaption("");
75        navText_->hide();
76        container_->addChild(navText_);
77
78
79        // create nav marker ...
80        navMarker_ = static_cast<PanelOverlayElement*>(OverlayManager::getSingleton().createOverlayElement("Panel", "NavMarker"));
81        aimMarker_ = static_cast<PanelOverlayElement*>(OverlayManager::getSingleton().createOverlayElement("Panel", "aimMarker"));
82        navMarker_->setMetricsMode(GMM_PIXELS);
83        aimMarker_->setMetricsMode(GMM_PIXELS);
84        navMarker_->hide();
85        aimMarker_->hide();
86        aimMarker_->setMaterialName("Orxonox/NavCrosshair");
87        aimMarker_->setDimensions(20, 20);
88        aimMarker_->setUV(0.0, 0.0, 1.0, 1.0);
89        container_->addChild(navMarker_);
90        container_->addChild(aimMarker_);
91    }
92
93    void Navigation::update()
94    {
95        if (!focus_)
96            return;
97
98        updateMarker();
99    }
100
101    void Navigation::updateMarker()
102    {
103        int windowW = GraphicsEngine::getSingleton().getWindowWidth();
104        int windowH = GraphicsEngine::getSingleton().getWindowHeight();
105
106        // set text
107        int dist = (int) getDist2Focus()/100;
108        navText_->setCaption(Ogre::StringConverter::toString(dist));
109
110        Ogre::Camera* navCam = SpaceShip::getLocalShip()->getCamera()->cam_;
111        // transform to screen coordinates
112        Vector3 pos = navCam->getProjectionMatrix() * navCam->getViewMatrix() * focus_->getPosition();
113        Vector3 aimpos = navCam->getProjectionMatrix() * navCam->getViewMatrix() * getPredictedPosition(SpaceShip::getLocalShip()->getPosition(), Projectile::getSpeed(), focus_->getPosition(), focus_->getOrientedVelocity());
114
115        float xPosRel = 0.5*pos.x+0.5;
116        float yPosRel = 1-(0.5*pos.y+0.5);
117        float xAimPosRel = 0.5*aimpos.x+0.5;
118        float yAimPosRel = 1-(0.5*aimpos.y+0.5);
119        int xPos = (int) (xPosRel*windowW);
120        int yPos = (int) (yPosRel*windowH);
121        int xAimPos = (int) (xAimPosRel*windowW);
122        int yAimPos = (int) (yAimPosRel*windowH);
123        int xFromCenter = xPos-windowW/2;
124        int yFromCenter = yPos-windowH/2;
125
126        // is object in view?
127        Vector3 navCamPos = SpaceShip::getLocalShip()->getPosition();
128        Vector3 currentDir = SpaceShip::getLocalShip()->getDir();
129        Vector3 currentOrth = SpaceShip::getLocalShip()->getOrth();
130        float radius = getAngle(navCamPos, currentDir, focus_->getPosition());
131        bool isRight = (currentDir.crossProduct(currentOrth)).dotProduct(focus_->getPosition() - navCamPos)>0;
132        bool isAbove = currentOrth.dotProduct(focus_->getPosition() - navCamPos)>0;
133        bool outOfView = (xPosRel<0 || xPosRel>1 || yPosRel<0 || yPosRel>1);
134
135        // if object is behind us, it is out of view anyway:
136        if (!outOfView && radius > Ogre::Math::PI / 2)
137            outOfView = true;
138
139        if (outOfView)
140        {
141            // object is not in view
142            navMarker_->setMaterialName("Orxonox/NavArrows");
143            navMarker_->setDimensions(16,16);
144            aimMarker_->hide();
145            float phiUpperCorner = atan((float)(windowW)/(float)(windowH));
146            // from the angle we find out on which edge to draw the marker
147            // and which of the four arrows to take
148            float phiNav = atan((float) xFromCenter / (float) yFromCenter);
149
150            if (isAbove && isRight)
151            {
152                // top right quadrant
153                if (-phiNav < phiUpperCorner)
154                {
155                    //COUT(3) << "arrow up\n";
156                    navMarker_->setPosition(-tan(phiNav)*windowH/2+windowW/2, 0);
157                    navMarker_->setUV(0.5, 0.0, 1.0, 0.5);
158                    navText_->setLeft(navMarker_->getLeft()+navMarker_->getWidth());
159                    navText_->setTop(navMarker_->getHeight());
160                }
161                else
162                {
163                    //COUT(3) << "arrow right\n";
164                    navMarker_->setPosition(windowW-16, tan((3.14-2*phiNav)/2)*windowW/2+windowH/2);
165                    navMarker_->setUV(0.5, 0.5, 1.0, 1.0);
166                    navText_->setLeft(navMarker_->getLeft()-navMarker_->getWidth());
167                    navText_->setTop(navMarker_->getTop()+navMarker_->getHeight());
168                }
169            }
170            if (!isAbove && isRight)
171            {
172                // bottom right quadrant
173                if (phiNav < phiUpperCorner)
174                {
175                    //COUT(3) << "arrow down\n";
176                    navMarker_->setPosition(tan(phiNav)*windowH/2+windowW/2, windowH-16);
177                    navMarker_->setUV(0.0, 0.5, 0.5, 1.0);
178                    navText_->setLeft(navMarker_->getLeft()+navMarker_->getWidth());
179                    navText_->setTop(navMarker_->getTop()-navMarker_->getHeight());
180                }
181                else
182                {
183                    //COUT(3) << "arrow right\n";
184                    navMarker_->setPosition(windowW-16, tan((3.14-2*phiNav)/2)*windowW/2+windowH/2);
185                    navMarker_->setUV(0.5, 0.5, 1.0, 1.0);
186                    navText_->setLeft(navMarker_->getLeft()-navMarker_->getWidth());
187                    navText_->setTop(navMarker_->getTop()+navMarker_->getHeight());
188                }
189            }
190            if (isAbove && !isRight)
191            {
192                // top left quadrant
193                if (phiNav<phiUpperCorner)
194                {
195                    //COUT(3) << "arrow up\n";
196                    navMarker_->setPosition(-tan(phiNav)*windowH/2+windowW/2, 0);
197                    navMarker_->setUV(0.5, 0.0, 1.0, 0.5);
198                    navText_->setLeft(navMarker_->getLeft()+navMarker_->getWidth());
199                    navText_->setTop(navMarker_->getHeight());
200                }
201                else
202                {
203                    //COUT(3) << "arrow left\n";
204                    navMarker_->setPosition(0, -tan((3.14-2*phiNav)/2)*windowW/2+windowH/2);
205                    navMarker_->setUV(0.0, 0.0, 0.5, 0.5);
206                    navText_->setLeft(navMarker_->getWidth());
207                    navText_->setTop(navMarker_->getTop()+navMarker_->getHeight());
208                }
209            }
210            if (!isAbove && !isRight)
211            {
212                // bottom left quadrant
213                if (phiNav>-phiUpperCorner)
214                {
215                    //COUT(3) << "arrow down\n";
216                    navMarker_->setPosition(tan(phiNav)*windowH/2+windowW/2, windowH-16);
217                    navMarker_->setUV(0.0, 0.5, 0.5, 1.0);
218                    navText_->setLeft(navMarker_->getLeft()+navMarker_->getWidth());
219                    navText_->setTop(navMarker_->getTop()-navMarker_->getHeight());
220                }
221                else
222                {
223                    //COUT(3) << "arrow left\n";
224                    navMarker_->setPosition(0, -tan((3.14-2*phiNav)/2)*windowW/2+windowH/2);
225                    navMarker_->setUV(0.0, 0.0, 0.5, 0.5);
226                    navText_->setLeft(navMarker_->getWidth());
227                    navText_->setTop(navMarker_->getTop()+navMarker_->getHeight());
228                }
229            }
230        }
231        else
232        {
233            // object is in view
234            navMarker_->setMaterialName("Orxonox/NavTDC");
235            navMarker_->setDimensions(35, 35);
236            navMarker_->setUV(0.0, 0.0, 1.0, 1.0);
237            navMarker_->setPosition(xPos-navMarker_->getWidth()/2, yPos-navMarker_->getHeight()/2);
238
239            aimMarker_->show();
240            aimMarker_->setPosition(xAimPos-aimMarker_->getWidth()/2, yAimPos-aimMarker_->getHeight()/2);
241
242            navText_->setPosition(xPos+navMarker_->getWidth()/2, yPos+navMarker_->getHeight()/2);
243        }
244    }
245
246    void Navigation::cycleFocus()
247    {
248        if (!focus_)
249        {
250            // Get closest object
251            float distance = (unsigned int) -1;
252            Vector3 shipPos = SpaceShip::getLocalShip()->getPosition();
253            it_ = HUD::getSingleton().getRadarObjects().begin();
254
255            for (std::list<RadarObject*>::iterator it = HUD::getSingleton().getRadarObjects().begin(); it != HUD::getSingleton().getRadarObjects().end(); ++it)
256            {
257                float newdist = (*it)->getPosition().squaredDistance(shipPos);
258                if (newdist < distance)
259                {
260                    distance = newdist;
261                    it_ = it;
262                }
263            }
264
265            if (it_ != HUD::getSingleton().getRadarObjects().end())
266            {
267                focus_ = *it_;
268
269                // move the focused object to the begin of the list, so we will iterate through all other objects when cycling
270                HUD::getSingleton().getRadarObjects().erase(it_);
271                HUD::getSingleton().getRadarObjects().insert(HUD::getSingleton().getRadarObjects().begin(), focus_);
272                it_ = HUD::getSingleton().getRadarObjects().begin();
273            }
274        }
275        else if (it_ != HUD::getSingleton().getRadarObjects().end())
276        {
277            focus_->resetMaterial();
278            ++it_;
279            if (it_ != HUD::getSingleton().getRadarObjects().end())
280                focus_ = *it_;
281            else
282                focus_ = 0;
283        }
284        else
285        {
286            focus_ = 0;
287        }
288        updateFocus();
289    }
290
291    void Navigation::updateFocus()
292    {
293        if (focus_)
294        {
295            navMarker_->show();
296            navText_->show();
297            focus_->setColour(ColourValue::White);
298        }
299        else
300        {
301            navMarker_->hide();
302            aimMarker_->hide();
303            navText_->hide();
304        }
305    }
306
307    void Navigation::releaseFocus()
308    {
309        this->focus_ = 0;
310        this->updateFocus();
311    }
312
313    float Navigation::getDist2Focus() const
314    {
315        if (focus_)
316            return (focus_->getPosition() - SpaceShip::getLocalShip()->getPosition()).length();
317        else
318            return 0;
319    }
320}
Note: See TracBrowser for help on using the repository browser.