Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/waypoints/src/modules/overlays/hud/HUDNavigation.cc @ 9177

Last change on this file since 9177 was 9177, checked in by scmoritz, 12 years ago

3D arrow trial

  • Property svn:eol-style set to native
File size: 17.4 KB
RevLine 
[1505]1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
[1454]4 *
[1505]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 *
[1454]22 *   Author:
23 *      Felix Schulthess
24 *   Co-authors:
[1590]25 *      Reto Grieder
[7801]26 *      Oliver Scheuss
[9016]27 *      Matthias Spalinger
[1454]28 *
29 */
[1393]30
[1601]31#include "HUDNavigation.h"
[1410]32
[6417]33#include <OgreCamera.h>
[7163]34#include <OgreFontManager.h>
[1393]35#include <OgreOverlayManager.h>
[1614]36#include <OgreTextAreaOverlayElement.h>
37#include <OgrePanelOverlayElement.h>
[9159]38#include <OgreEntity.h>
[1410]39
[1614]40#include "util/Math.h"
[1616]41#include "util/Convert.h"
42#include "core/CoreIncludes.h"
43#include "core/XMLPort.h"
[6417]44#include "CameraManager.h"
[5929]45#include "Scene.h"
[5735]46#include "Radar.h"
[6417]47#include "graphics/Camera.h"
[9177]48#include "graphics/Model.h"
49#include "worldentities/MovableEntity.h"
[6417]50#include "controllers/HumanController.h"
51#include "worldentities/pawns/Pawn.h"
[7163]52#include "worldentities/WorldEntity.h"
53#include "core/ConfigValueIncludes.h"
54#include "tools/TextureGenerator.h"
55// #include <boost/bind/bind_template.hpp>
[1393]56
[7163]57
[1393]58namespace orxonox
59{
[7163]60bool compareDistance ( std::pair<RadarViewable*, unsigned int > a, std::pair<RadarViewable*, unsigned int > b )
61{
62    return a.second<b.second;
[1590]63
[7163]64}
[2087]65
[7163]66void HUDNavigation::setConfigValues()
67{
68  SetConfigValue(markerLimit_, 3);
[9016]69  SetConfigValue(showDistance, false);
[7163]70}
[2087]71
[7163]72CreateFactory ( HUDNavigation );
[2087]73
[7163]74HUDNavigation::HUDNavigation ( BaseObject* creator )
75        : OrxonoxOverlay ( creator )
76{
77    RegisterObject ( HUDNavigation );
78    this->setConfigValues();
[2087]79
[7163]80    // Set default values
[9016]81    this->setFont ( "Monofur" );
82    this->setTextSize ( 0.05f );
83    this->setNavMarkerSize ( 0.05f );
84    this->setDetectionLimit( 10000.0f ); 
[9159]85
[9177]86    //Ogre::Entity* ent = this->getScene()->getSceneManager()->createEntity("Arrow3D", "Arrow3D.mesh");
87
88    Model* arrow = new Model(this);
89    MovableEntity* arrowEntity = new MovableEntity(this);
90    arrow->setMeshSource("Arrow3D.mesh");
91    arrowEntity->attach(arrow);
92    arrowEntity->setVisible(true);
93    arrowEntity->scale(1);
94    arrowEntity->setPosition(0, 0, -200);
95    arrowEntity->attachToNode(this->overlay3d_);
96    //this->add3DMesh(arrowEntity);
97
98    this->overlay3d_->setPosition(0, 0, -200);
99    this->overlay3d_->setVisible(false, true);
[7163]100}
[2087]101
[7163]102HUDNavigation::~HUDNavigation()
103{
104    if ( this->isInitialized() )
105    {
106        for ( ObjectMap::iterator it = activeObjectList_.begin(); it != activeObjectList_.end(); )
107            removeObject ( ( it++ )->first );
[2087]108
[1393]109    }
110
[7163]111    sortedObjectList_.clear();
112}
[1564]113
[7401]114void HUDNavigation::XMLPort ( Element& xmlelement, XMLPort::Mode mode )
[7163]115{
[7401]116    SUPER ( HUDNavigation, XMLPort, xmlelement, mode );
[1394]117
[9016]118    XMLPortParam ( HUDNavigation, "font",          setFont,          getFont,          xmlelement, mode );
119    XMLPortParam ( HUDNavigation, "textSize",      setTextSize,      getTextSize,      xmlelement, mode );
120    XMLPortParam ( HUDNavigation, "navMarkerSize", setNavMarkerSize, getNavMarkerSize, xmlelement, mode );
121    XMLPortParam ( HUDNavigation, "detectionLimit", setDetectionLimit, getDetectionLimit, xmlelement, mode ); 
[7163]122}
[1393]123
[7163]124void HUDNavigation::setFont ( const std::string& font )
125{
126    const Ogre::ResourcePtr& fontPtr = Ogre::FontManager::getSingleton().getByName ( font );
127    if ( fontPtr.isNull() )
[1590]128    {
[8858]129        orxout(internal_warning) << "HUDNavigation: Font '" << font << "' not found" << endl;
[7163]130        return;
[1590]131    }
[7163]132    fontName_ = font;
133    for ( ObjectMap::iterator it = activeObjectList_.begin(); it != activeObjectList_.end(); ++it )
[1590]134    {
[7163]135        if ( it->second.text_ != NULL )
136            it->second.text_->setFontName ( fontName_ );
[1590]137    }
[7163]138}
[1590]139
[7163]140const std::string& HUDNavigation::getFont() const
141{
142    return fontName_;
143}
144
145void HUDNavigation::setTextSize ( float size )
146{
147    if ( size <= 0.0f )
[1590]148    {
[8858]149        orxout(internal_warning) << "HUDNavigation: Negative font size not allowed" << endl;
[7163]150        return;
[1590]151    }
[7163]152    textSize_ = size;
153    for ( ObjectMap::iterator it = activeObjectList_.begin(); it!=activeObjectList_.end(); ++it )
154    {
155        if ( it->second.text_ )
156            it->second.text_->setCharHeight ( size );
157    }
158}
[1590]159
[7163]160float HUDNavigation::getTextSize() const
161{
162    return textSize_;
163}
164
[9016]165float HUDNavigation::getArrowSizeX(int dist)
166{   
167    if (dist < 600) 
168        dist = 600;
169    return this->getActualSize().x * 900 * navMarkerSize_ / dist;
170}
[7163]171
[9016]172float HUDNavigation::getArrowSizeY(int dist)
173{   
174    if (dist < 600)
175        dist = 600;   
176    return this->getActualSize().y * 900 * navMarkerSize_ / dist;
177}
[7163]178
179void HUDNavigation::tick ( float dt )
180{
181    SUPER ( HUDNavigation, tick, dt );
182
183    Camera* cam = CameraManager::getInstance().getActiveCamera();
184    if ( cam == NULL )
185        return;
186    const Matrix4& camTransform = cam->getOgreCamera()->getProjectionMatrix() * cam->getOgreCamera()->getViewMatrix();
187
188
189    for ( sortedList::iterator listIt = sortedObjectList_.begin(); listIt != sortedObjectList_.end(); ++listIt )
[1590]190    {
[7163]191        listIt->second = ( int ) ( ( listIt->first->getRVWorldPosition() - HumanController::getLocalControllerSingleton()->getControllableEntity()->getWorldPosition() ).length() + 0.5f );
[1590]192    }
193
[7163]194    sortedObjectList_.sort ( compareDistance );
195
196    unsigned int markerCount_ = 0;
[8891]197    bool closeEnough_ = false; //only display objects that are close enough to be relevant for the player
[9016]198
[9177]199    //for the first element of sortedObjectList_ / the closest waypoint show the Arrow3D
200    if(!sortedObjectList_.empty())
201    {
202        showArrow3D();
203                sortedList::iterator firstIt = sortedObjectList_.begin();
204                Ogre::Vector3 pos1 = firstIt->first->getRVWorldPosition();
205                Ogre::Vector3 pos2 = cam->getPosition();
206                Ogre::Quaternion quat = pos2.getRotationTo(pos1);
207                this->overlay3d_->rotate(quat);
208                //this->overlay3d_->setDirection(pos1-pos2);
209    }
210
211
[7163]212//         for (ObjectMap::iterator it = activeObjectList_.begin(); it != activeObjectList_.end(); ++it)
213    for ( sortedList::iterator listIt = sortedObjectList_.begin(); listIt != sortedObjectList_.end(); ++markerCount_, ++listIt )
[1590]214    {
[7163]215        ObjectMap::iterator it = activeObjectList_.find ( listIt->first );
[8891]216        closeEnough_ = listIt->second < detectionLimit_ ;
[9016]217        // display radarviewables on HUD if the marker limit and max-distance is not exceeded
218        if ( markerCount_ < markerLimit_ && (closeEnough_ ||  detectionLimit_ < 0) ) 
[1613]219        {
[1400]220
[1399]221
[7163]222            // Get Distance to HumanController and save it in the TextAreaOverlayElement.
223            int dist = listIt->second;
[9016]224            float textLength = 0.0f;
225
226            //display distance next to cursor
227            if (showDistance){
[7163]228            it->second.text_->setCaption ( multi_cast<std::string> ( dist ) );
[9016]229            textLength = multi_cast<std::string> ( dist ).size() * it->second.text_->getCharHeight() * 0.3f;
230            }
[1564]231
[9016]232            //display name next to cursor
233            else{
234            it->second.text_->setCaption(it->first->getRVName()); 
235            textLength = it->first->getRVName().size() * it->second.text_->getCharHeight() * 0.3f;
236            }
237
[7163]238            // Transform to screen coordinates
239            Vector3 pos = camTransform * it->first->getRVWorldPosition();
[1399]240
[7163]241            bool outOfView = true;
242            if ( pos.z > 1.0 )
[1580]243            {
[7163]244                // z > 1.0 means that the object is behind the camera
245                outOfView = true;
246                // we have to switch all coordinates (if you don't know why,
247                // try linear algebra lectures, because I can't explain..)
248                pos.x = -pos.x;
249                pos.y = -pos.y;
[1411]250            }
[7163]251            else
252                outOfView = pos.x < -1.0 || pos.x > 1.0 || pos.y < -1.0 || pos.y > 1.0;
[1590]253
[7163]254            if ( outOfView )
[1580]255            {
[7163]256                // Object is not in view
257
258                // Change material only if outOfView changed
259                if ( !it->second.wasOutOfView_ )
[1580]260                {
[7368]261                    it->second.panel_->setMaterialName( TextureGenerator::getMaterialName( "arrows.png", it->first->getRadarObjectColour()) );
[7163]262                    it->second.wasOutOfView_ = true;
[1399]263                }
[7163]264
[9016]265                //float xDistScale = this->getActualSize().x * 1000.0f * navMarkerSize_ / dist;
266                //float yDistScale = this->getActualSize().y * 1000.0f * navMarkerSize_ / dist;
267
268                // Adjust Arrowsize according to distance
269                it->second.panel_->setDimensions(getArrowSizeX(dist),getArrowSizeY(dist));
270
[7163]271                // Switch between top, bottom, left and right position of the arrow at the screen border
272                if ( pos.x < pos.y )
273                {
274                    if ( pos.y > -pos.x )
275                    {
276                        // Top
277                        float position = pos.x / pos.y + 1.0f;
278                        it->second.panel_->setPosition ( ( position - it->second.panel_->getWidth() ) * 0.5f, 0.0f );
279                        it->second.panel_->setUV ( 0.5f, 0.0f, 1.0f, 0.5f );
280                        it->second.text_->setLeft ( ( position - textLength ) * 0.5f );
281                        it->second.text_->setTop ( it->second.panel_->getHeight() );
282                    }
283                    else
284                    {
285                        // Left
286                        float position = pos.y / pos.x + 1.0f;
287                        it->second.panel_->setPosition ( 0.0f, ( position - it->second.panel_->getWidth() ) * 0.5f );
288                        it->second.panel_->setUV ( 0.0f, 0.0f, 0.5f, 0.5f );
289                        it->second.text_->setLeft ( it->second.panel_->getWidth() + 0.01f );
290                        it->second.text_->setTop ( ( position - it->second.text_->getCharHeight() ) * 0.5f );
291                    }
292                }
293
[1580]294                else
295                {
[7163]296
297                    if ( pos.y < -pos.x )
298                    {
299                        // Bottom
300                        float position = -pos.x / pos.y + 1.0f;
301                        it->second.panel_->setPosition ( ( position - it->second.panel_->getWidth() ) * 0.5f, 1.0f - it->second.panel_->getHeight() );
302                        it->second.panel_->setUV ( 0.0f, 0.5f, 0.5f, 1.0f );
303                        it->second.text_->setLeft ( ( position - textLength ) * 0.5f );
304                        it->second.text_->setTop ( 1.0f - it->second.panel_->getHeight() - it->second.text_->getCharHeight() );
305                    }
306                    else
307                    {
308                        // Right
309                        float position = -pos.y / pos.x + 1.0f;
310                        it->second.panel_->setPosition ( 1.0f - it->second.panel_->getWidth(), ( position - it->second.panel_->getHeight() ) * 0.5f );
311                        it->second.panel_->setUV ( 0.5f, 0.5f, 1.0f, 1.0f );
312                        it->second.text_->setLeft ( 1.0f - it->second.panel_->getWidth() - textLength - 0.01f );
313                        it->second.text_->setTop ( ( position - it->second.text_->getCharHeight() ) * 0.5f );
314                    }
[1411]315                }
316            }
[1590]317            else
[1580]318            {
[7163]319                // Object is in view
320
321                // Change material only if outOfView changed
322                if ( it->second.wasOutOfView_ )
[1580]323                {
[7163]324                  //it->second.panel_->setMaterialName ( "Orxonox/NavTDC" );
[7368]325                    it->second.panel_->setMaterialName( TextureGenerator::getMaterialName( "tdc.png", it->first->getRadarObjectColour()) );
[9016]326                    it->second.panel_->setDimensions ( navMarkerSize_ * this->getActualSize().x, navMarkerSize_ * this->getActualSize().y );
[7163]327                    it->second.wasOutOfView_ = false;
[1399]328                }
[7163]329
330                // Position marker
331                it->second.panel_->setUV ( 0.0f, 0.0f, 1.0f, 1.0f );
332                it->second.panel_->setLeft ( ( pos.x + 1.0f - it->second.panel_->getWidth() ) * 0.5f );
333                it->second.panel_->setTop ( ( -pos.y + 1.0f - it->second.panel_->getHeight() ) * 0.5f );
334
335                // Position text
336                it->second.text_->setLeft ( ( pos.x + 1.0f + it->second.panel_->getWidth() ) * 0.5f );
337                it->second.text_->setTop ( ( -pos.y + 1.0f + it->second.panel_->getHeight() ) * 0.5f );
[1393]338            }
[7163]339
340            // Make sure the overlays are shown
341            it->second.panel_->show();
342            it->second.text_->show();
[1393]343        }
[9016]344        else // do not display on HUD
[1580]345        {
[7163]346            it->second.panel_->hide();
347            it->second.text_->hide();
348        }
[1590]349
[7163]350    }
351}
[1566]352
[7163]353
354/** Overridden method of OrxonoxOverlay.
355@details
356    Usually the entire overlay scales with scale().
357    Here we obviously have to adjust this.
[2087]358*/
[7163]359void HUDNavigation::sizeChanged()
360{
361    // Use size to compensate for aspect ratio if enabled.
362    float xScale = this->getActualSize().x;
363    float yScale = this->getActualSize().y;
364
365    for ( ObjectMap::iterator it = activeObjectList_.begin(); it!=activeObjectList_.end(); ++it )
366    {
367        if ( it->second.panel_ != NULL )
368            it->second.panel_->setDimensions ( navMarkerSize_ * xScale, navMarkerSize_ * yScale );
369        if ( it->second.text_ != NULL )
370            it->second.text_->setCharHeight ( it->second.text_->getCharHeight() * yScale );
[1410]371    }
[7163]372}
[1394]373
[7163]374void HUDNavigation::addObject ( RadarViewable* object )
375{
[9016]376    if( showObject(object)==false )
[7163]377        return;
378
379    if ( activeObjectList_.size() >= markerLimit_ )
380        if ( object == NULL )
381            return;
382
383    // Object hasn't been added yet (we know that)
384    assert ( this->activeObjectList_.find ( object ) == this->activeObjectList_.end() );
385
386    // Scales used for dimensions and text size
387    float xScale = this->getActualSize().x;
388    float yScale = this->getActualSize().y;
389
390    // Create everything needed to display the object on the radar and add it to the map
391
392    // Create arrow/marker
393    Ogre::PanelOverlayElement* panel = static_cast<Ogre::PanelOverlayElement*> ( Ogre::OverlayManager::getSingleton()
394                                       .createOverlayElement ( "Panel", "HUDNavigation_navMarker_" + getUniqueNumberString() ) );
395//     panel->setMaterialName ( "Orxonox/NavTDC" );
[7368]396    panel->setMaterialName( TextureGenerator::getMaterialName( "tdc.png", object->getRadarObjectColour()) );
[7163]397    panel->setDimensions ( navMarkerSize_ * xScale, navMarkerSize_ * yScale );
398//     panel->setColour( object->getRadarObjectColour() );
399
400    Ogre::TextAreaOverlayElement* text = static_cast<Ogre::TextAreaOverlayElement*> ( Ogre::OverlayManager::getSingleton()
401                                         .createOverlayElement ( "TextArea", "HUDNavigation_navText_" + getUniqueNumberString() ) );
402    text->setFontName ( this->fontName_ );
403    text->setCharHeight ( text->getCharHeight() * yScale );
404    text->setColour( object->getRadarObjectColour() );
405
406    panel->hide();
407    text->hide();
408
[8706]409    ObjectInfo tempStruct = {panel, text, false /*, TODO: initialize wasOutOfView_ */};
[7163]410    activeObjectList_[object] = tempStruct;
411
412    this->background_->addChild ( panel );
413    this->background_->addChild ( text );
414
415    sortedObjectList_.push_front ( std::make_pair ( object, ( unsigned int ) 0 ) );
416
417
418}
419
420void HUDNavigation::removeObject ( RadarViewable* viewable )
421{
422    ObjectMap::iterator it = activeObjectList_.find ( viewable );
423
424    if ( activeObjectList_.find ( viewable ) != activeObjectList_.end() )
[1580]425    {
[7163]426        // Detach overlays
427        this->background_->removeChild ( it->second.panel_->getName() );
428        this->background_->removeChild ( it->second.text_->getName() );
429        // Properly destroy the overlay elements (do not use delete!)
430        Ogre::OverlayManager::getSingleton().destroyOverlayElement ( it->second.panel_ );
431        Ogre::OverlayManager::getSingleton().destroyOverlayElement ( it->second.text_ );
432        // Remove from the list
433        activeObjectList_.erase ( viewable );
434
435
[1410]436    }
[1590]437
[7163]438    for ( sortedList::iterator listIt = sortedObjectList_.begin(); listIt != sortedObjectList_.end(); ++listIt )
[1590]439    {
[7163]440        if ( (listIt->first) == viewable )
441        {
442            sortedObjectList_.erase ( listIt );
443            break;
444        }
445
[1590]446    }
[7163]447
[1393]448}
[7163]449
450void HUDNavigation::objectChanged(RadarViewable* viewable)
451{
452    // TODO: niceification neccessary ;)
453    removeObject(viewable);
454    addObject(viewable);
455}
456
457
458bool HUDNavigation::showObject(RadarViewable* rv)
459{
460    if ( rv == dynamic_cast<RadarViewable*> ( this->getOwner() ) )
461        return false;
462    assert( rv->getWorldEntity() );
[9016]463    if ( rv->getWorldEntity()->isVisible()==false || rv->getRadarVisibility()==false )
[7163]464        return false;
465    return true;
466}
467
468void HUDNavigation::changedOwner()
469{
470
471    const std::set<RadarViewable*>& respawnObjects = this->getOwner()->getScene()->getRadar()->getRadarObjects();
472    for ( std::set<RadarViewable*>::const_iterator it = respawnObjects.begin(); it != respawnObjects.end(); ++it )
473    {
474        if ( ! ( *it )->isHumanShip_ )
475            this->addObject ( *it );
476    }
477}
[9177]478void HUDNavigation::showArrow3D()
479                { this->overlay3d_->setVisible(true, true);}
480void HUDNavigation::hideArrow3D()
481                { this->overlay3d_->setVisible(false, true);}
[7801]482
[9177]483
[7163]484}
Note: See TracBrowser for help on using the repository browser.