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, 13 years ago

3D arrow trial

  • Property svn:eol-style set to native
File size: 17.4 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 *      Reto Grieder
26 *      Oliver Scheuss
27 *      Matthias Spalinger
28 *
29 */
30
31#include "HUDNavigation.h"
32
33#include <OgreCamera.h>
34#include <OgreFontManager.h>
35#include <OgreOverlayManager.h>
36#include <OgreTextAreaOverlayElement.h>
37#include <OgrePanelOverlayElement.h>
38#include <OgreEntity.h>
39
40#include "util/Math.h"
41#include "util/Convert.h"
42#include "core/CoreIncludes.h"
43#include "core/XMLPort.h"
44#include "CameraManager.h"
45#include "Scene.h"
46#include "Radar.h"
47#include "graphics/Camera.h"
48#include "graphics/Model.h"
49#include "worldentities/MovableEntity.h"
50#include "controllers/HumanController.h"
51#include "worldentities/pawns/Pawn.h"
52#include "worldentities/WorldEntity.h"
53#include "core/ConfigValueIncludes.h"
54#include "tools/TextureGenerator.h"
55// #include <boost/bind/bind_template.hpp>
56
57
58namespace orxonox
59{
60bool compareDistance ( std::pair<RadarViewable*, unsigned int > a, std::pair<RadarViewable*, unsigned int > b )
61{
62    return a.second<b.second;
63
64}
65
66void HUDNavigation::setConfigValues()
67{
68  SetConfigValue(markerLimit_, 3);
69  SetConfigValue(showDistance, false);
70}
71
72CreateFactory ( HUDNavigation );
73
74HUDNavigation::HUDNavigation ( BaseObject* creator )
75        : OrxonoxOverlay ( creator )
76{
77    RegisterObject ( HUDNavigation );
78    this->setConfigValues();
79
80    // Set default values
81    this->setFont ( "Monofur" );
82    this->setTextSize ( 0.05f );
83    this->setNavMarkerSize ( 0.05f );
84    this->setDetectionLimit( 10000.0f ); 
85
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);
100}
101
102HUDNavigation::~HUDNavigation()
103{
104    if ( this->isInitialized() )
105    {
106        for ( ObjectMap::iterator it = activeObjectList_.begin(); it != activeObjectList_.end(); )
107            removeObject ( ( it++ )->first );
108
109    }
110
111    sortedObjectList_.clear();
112}
113
114void HUDNavigation::XMLPort ( Element& xmlelement, XMLPort::Mode mode )
115{
116    SUPER ( HUDNavigation, XMLPort, xmlelement, mode );
117
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 ); 
122}
123
124void HUDNavigation::setFont ( const std::string& font )
125{
126    const Ogre::ResourcePtr& fontPtr = Ogre::FontManager::getSingleton().getByName ( font );
127    if ( fontPtr.isNull() )
128    {
129        orxout(internal_warning) << "HUDNavigation: Font '" << font << "' not found" << endl;
130        return;
131    }
132    fontName_ = font;
133    for ( ObjectMap::iterator it = activeObjectList_.begin(); it != activeObjectList_.end(); ++it )
134    {
135        if ( it->second.text_ != NULL )
136            it->second.text_->setFontName ( fontName_ );
137    }
138}
139
140const std::string& HUDNavigation::getFont() const
141{
142    return fontName_;
143}
144
145void HUDNavigation::setTextSize ( float size )
146{
147    if ( size <= 0.0f )
148    {
149        orxout(internal_warning) << "HUDNavigation: Negative font size not allowed" << endl;
150        return;
151    }
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}
159
160float HUDNavigation::getTextSize() const
161{
162    return textSize_;
163}
164
165float HUDNavigation::getArrowSizeX(int dist)
166{   
167    if (dist < 600) 
168        dist = 600;
169    return this->getActualSize().x * 900 * navMarkerSize_ / dist;
170}
171
172float HUDNavigation::getArrowSizeY(int dist)
173{   
174    if (dist < 600)
175        dist = 600;   
176    return this->getActualSize().y * 900 * navMarkerSize_ / dist;
177}
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 )
190    {
191        listIt->second = ( int ) ( ( listIt->first->getRVWorldPosition() - HumanController::getLocalControllerSingleton()->getControllableEntity()->getWorldPosition() ).length() + 0.5f );
192    }
193
194    sortedObjectList_.sort ( compareDistance );
195
196    unsigned int markerCount_ = 0;
197    bool closeEnough_ = false; //only display objects that are close enough to be relevant for the player
198
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
212//         for (ObjectMap::iterator it = activeObjectList_.begin(); it != activeObjectList_.end(); ++it)
213    for ( sortedList::iterator listIt = sortedObjectList_.begin(); listIt != sortedObjectList_.end(); ++markerCount_, ++listIt )
214    {
215        ObjectMap::iterator it = activeObjectList_.find ( listIt->first );
216        closeEnough_ = listIt->second < detectionLimit_ ;
217        // display radarviewables on HUD if the marker limit and max-distance is not exceeded
218        if ( markerCount_ < markerLimit_ && (closeEnough_ ||  detectionLimit_ < 0) ) 
219        {
220
221
222            // Get Distance to HumanController and save it in the TextAreaOverlayElement.
223            int dist = listIt->second;
224            float textLength = 0.0f;
225
226            //display distance next to cursor
227            if (showDistance){
228            it->second.text_->setCaption ( multi_cast<std::string> ( dist ) );
229            textLength = multi_cast<std::string> ( dist ).size() * it->second.text_->getCharHeight() * 0.3f;
230            }
231
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
238            // Transform to screen coordinates
239            Vector3 pos = camTransform * it->first->getRVWorldPosition();
240
241            bool outOfView = true;
242            if ( pos.z > 1.0 )
243            {
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;
250            }
251            else
252                outOfView = pos.x < -1.0 || pos.x > 1.0 || pos.y < -1.0 || pos.y > 1.0;
253
254            if ( outOfView )
255            {
256                // Object is not in view
257
258                // Change material only if outOfView changed
259                if ( !it->second.wasOutOfView_ )
260                {
261                    it->second.panel_->setMaterialName( TextureGenerator::getMaterialName( "arrows.png", it->first->getRadarObjectColour()) );
262                    it->second.wasOutOfView_ = true;
263                }
264
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
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
294                else
295                {
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                    }
315                }
316            }
317            else
318            {
319                // Object is in view
320
321                // Change material only if outOfView changed
322                if ( it->second.wasOutOfView_ )
323                {
324                  //it->second.panel_->setMaterialName ( "Orxonox/NavTDC" );
325                    it->second.panel_->setMaterialName( TextureGenerator::getMaterialName( "tdc.png", it->first->getRadarObjectColour()) );
326                    it->second.panel_->setDimensions ( navMarkerSize_ * this->getActualSize().x, navMarkerSize_ * this->getActualSize().y );
327                    it->second.wasOutOfView_ = false;
328                }
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 );
338            }
339
340            // Make sure the overlays are shown
341            it->second.panel_->show();
342            it->second.text_->show();
343        }
344        else // do not display on HUD
345        {
346            it->second.panel_->hide();
347            it->second.text_->hide();
348        }
349
350    }
351}
352
353
354/** Overridden method of OrxonoxOverlay.
355@details
356    Usually the entire overlay scales with scale().
357    Here we obviously have to adjust this.
358*/
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 );
371    }
372}
373
374void HUDNavigation::addObject ( RadarViewable* object )
375{
376    if( showObject(object)==false )
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" );
396    panel->setMaterialName( TextureGenerator::getMaterialName( "tdc.png", object->getRadarObjectColour()) );
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
409    ObjectInfo tempStruct = {panel, text, false /*, TODO: initialize wasOutOfView_ */};
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() )
425    {
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
436    }
437
438    for ( sortedList::iterator listIt = sortedObjectList_.begin(); listIt != sortedObjectList_.end(); ++listIt )
439    {
440        if ( (listIt->first) == viewable )
441        {
442            sortedObjectList_.erase ( listIt );
443            break;
444        }
445
446    }
447
448}
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() );
463    if ( rv->getWorldEntity()->isVisible()==false || rv->getRadarVisibility()==false )
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}
478void HUDNavigation::showArrow3D()
479                { this->overlay3d_->setVisible(true, true);}
480void HUDNavigation::hideArrow3D()
481                { this->overlay3d_->setVisible(false, true);}
482
483
484}
Note: See TracBrowser for help on using the repository browser.