Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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