source: osgVisual/trunk/src/util/visual_util.cpp @ 262

Last change on this file since 262 was 226, checked in by Torben Dannhauer, 14 years ago

TRacking nodes by XML config should work now

File size: 17.8 KB
Line 
1/* -*-c++-*- osgVisual - Copyright (C) 2009-2011 Torben Dannhauer
2 *
3 * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
9 * You have to aquire licenses for all used proprietary modules.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * OpenSceneGraph Public License for more details.
15*/
16
17#include <visual_util.h>
18
19using namespace osgVisual;
20
21util::util(void)
22{
23}
24
25util::~util(void)
26{
27}
28
29xmlNode* util::getSceneryXMLConfig(std::string configFilename, xmlDoc*& doc)
30{
31        doc = NULL;
32        xmlNode *root_element = NULL;
33
34        // Check for valid parameters
35        if(configFilename == "")
36        {
37                OSG_ALWAYS << "ERROR - util::getModuleXMLConfig() : Invalid Configuration Filename!" << std::endl;
38                return NULL;
39        }
40
41        // It is a valid XML document?
42        doc = xmlReadFile(configFilename.c_str(), NULL, 0);     
43        if (doc == NULL)
44        {
45                OSG_ALWAYS << "ERROR - util::getModuleXMLConfig() : " << configFilename << " is not a valid XML file!" << std::endl;
46                return NULL;
47        }
48
49        //  Get the root element node
50        root_element = xmlDocGetRootElement(doc);
51
52        // If file is a valid osgVisual config file, check all the root xml node and all of it's children of osgvisualconfiguration for the specified module
53        xmlNode* tmpNode = checkXMLNodeChildrenForScenery(root_element);
54
55        if( !tmpNode ) // if no valid node was found: clena up. Otherwise: the caller has to clean up.
56        {
57                xmlFreeDoc(doc);        // free the document
58                xmlCleanupParser();     // Free the global variables that may have been allocated by the parser.
59                return NULL;
60        }
61        else
62                return tmpNode;
63}
64
65xmlNode* util::checkXMLNodeChildrenForScenery(xmlNode* node)
66{
67        for (xmlNode *cur_node = node; cur_node; cur_node = cur_node->next)     // iterate through all elements
68        {
69                // Is the node the one we are searching for?
70                if (cur_node->type == XML_ELEMENT_NODE)
71                {
72                        std::string node_name=reinterpret_cast<const char*>(cur_node->name);
73                        if (node_name == "scenery")
74                        {
75                                OSG_DEBUG << "XML node scenery found" << std::endl;
76                                return cur_node;
77                        }
78                        else    // Otherwise: check its children..
79                        {
80                                xmlNode* tmp_XmlNode = checkXMLNodeChildrenForScenery(cur_node->children);
81                                if(tmp_XmlNode)
82                                        return tmp_XmlNode;
83                        }
84                }       // IF NODE TYPE = ELEMENT END
85
86                // Proceed with next node in this loop.
87        }
88        return NULL;
89}
90
91xmlNode* util::getModuleXMLConfig(std::string configFilename, std::string moduleName, xmlDoc*& doc, bool& disabled)
92{
93        doc = NULL;
94        disabled = false;
95        xmlNode *root_element = NULL;
96
97        // Check for valid parameters
98        if(configFilename == "")
99        {
100                OSG_ALWAYS << "ERROR - util::getModuleXMLConfig() : Invalid Configuration Filename!" << std::endl;
101                return NULL;
102        }
103        if(moduleName == "")
104        {
105                OSG_ALWAYS << "ERROR - util::getModuleXMLConfig() : Invalid Module Filename!" << std::endl;
106                return NULL;
107        }
108
109        // It is a valid XML document?
110        doc = xmlReadFile(configFilename.c_str(), NULL, 0);     
111        if (doc == NULL)
112        {
113                OSG_ALWAYS << "ERROR - util::getModuleXMLConfig() : " << configFilename << " is not a valid XML file!" << std::endl;
114                return NULL;
115        }
116
117        //  Get the root element node
118        root_element = xmlDocGetRootElement(doc);
119
120        // Check if it is an osgVisual configuration file
121        std::string node_name=reinterpret_cast<const char*>(root_element->name);
122        if(!(root_element->type == XML_ELEMENT_NODE && node_name == "osgvisualconfiguration"))
123        {
124                OSG_ALWAYS << "ERROR - util::getModuleXMLConfig() : " << configFilename << " is not an osgVisual configuration file!" << std::endl;
125                return NULL;
126        }
127
128        // If file is a valid osgVisual config file, check all the root xml node and all of it's children of osgvisualconfiguration for the specified module
129        xmlNode* tmpNode = checkXMLNodeChildrenForModule(root_element, moduleName, disabled);
130
131        if( !tmpNode ) // if no valid node was found or the module is disabled: clean up. Otherwise: the caller has to clean up.
132        {
133                xmlFreeDoc(doc);        // free the document
134                xmlCleanupParser();     // Free the global variables that may have been allocated by the parser.
135                return NULL;
136        }
137        else
138                return tmpNode;
139
140}
141
142xmlNode* util::checkXMLNodeChildrenForModule(xmlNode* node, std::string moduleName, bool& disabled)
143{
144        for (xmlNode *cur_node = node; cur_node; cur_node = cur_node->next)     // iterate through all XML elements
145        {
146                // Is the node the one we are searching for?
147                if (cur_node->type == XML_ELEMENT_NODE)
148                {
149                        // Extract Node Name and the first attribute: "module name"
150                        std::string node_name = reinterpret_cast<const char*>(cur_node->name);
151                        std::string modName = "";
152                        xmlAttr  *attr = cur_node->properties;
153                        while ( attr ) 
154                        { 
155                                std::string attr_name=reinterpret_cast<const char*>(attr->name);
156                                std::string attr_value=reinterpret_cast<const char*>(attr->children->content);
157                                if( attr_name == "name" )
158                                        modName = attr_value;
159                                attr = attr->next;
160                        }
161                       
162                        // Check each node for the searched module
163                        if (node_name == "module" && modName == moduleName)
164                        {
165                                // Check if the module is active
166                                xmlAttr  *attr = cur_node->properties;
167                                while ( attr ) 
168                                { 
169                                        std::string attr_name=reinterpret_cast<const char*>(attr->name);
170                                        std::string attr_value=reinterpret_cast<const char*>(attr->children->content);
171                                        if( attr_name == "enabled" && attr_value == "yes" )
172                                        {
173                                                OSG_DEBUG << "Found XML module configuration for " << moduleName << std::endl;
174                                                return cur_node;
175                                        }
176                                        if( attr_name == "enabled" && attr_value == "no" )
177                                        {
178                                                disabled = true;
179                                                OSG_DEBUG << "Found XML module configuration for " << moduleName << ", but it is DISABLED." << std::endl;
180                                                return NULL;
181                                        }
182                                        attr = attr->next;
183                                }
184                        }
185                        else    // Otherwise: check its children..
186                        {
187                                xmlNode* tmp_XmlNode = checkXMLNodeChildrenForModule(cur_node->children, moduleName, disabled);
188                                if(tmp_XmlNode)
189                                        return tmp_XmlNode;
190                        }
191                }       // IF NODE TYPE = ELEMENT END
192
193                // Proceed with next node in this loop.
194        }
195        return NULL;
196}
197
198osg::Node* util::findNamedNode(const std::string& searchName_, osg::Node* currNode_)
199{
200   osg::Group* currGroup;
201   osg::Node* foundNode;
202
203   // check to see if we have a valid (non-NULL) node.
204   // if we do have a null node, return NULL.
205   if ( !currNode_)
206   {
207      return NULL;
208   }
209
210   // We have a valid node, check to see if this is the node we
211   // are looking for. If so, return the current node.
212   if (currNode_->getName() == searchName_)
213   {
214      return currNode_;
215   }
216
217   // We have a valid node, but not the one we are looking for.
218   // Check to see if it has children (non-leaf node). If the node
219   // has children, check each of the child nodes by recursive call.
220   // If one of the recursive calls returns a non-null value we have
221   // found the correct node, so return this node.
222   // If we check all of the children and have not found the node,
223   // return NULL
224   currGroup = currNode_->asGroup(); // returns NULL if not a group.
225   if ( currGroup ) 
226   {
227      for (unsigned int i = 0 ; i < currGroup->getNumChildren(); i ++)
228      { 
229         foundNode = findNamedNode(searchName_, currGroup->getChild(i));
230         if (foundNode)
231                 {
232                         std::cout << "Node gefunden in Ebene: " << i << std::endl;
233            return foundNode; // found a match!
234                }
235      }
236      return NULL; // We have checked each child node - no match found.
237   }
238   else 
239           return NULL; // leaf node, no match
240}
241
242osg::ref_ptr<osg::Geode> util::getDemoCylinder(double length_, double width_, osg::Vec3 offset_ )
243{
244        osg::ref_ptr<osg::Geode> cyl = new osg::Geode();
245        osg::ref_ptr<osg::ShapeDrawable> shape = new osg::ShapeDrawable(new osg::Cylinder( offset_, width_, length_ ));
246        osg::Vec4 color = osg::Vec4(255.0, 0.0, 0.0, 1.0);
247        shape->setColor( color );
248        cyl->addDrawable( shape );
249
250        return cyl;
251}
252
253osg::ref_ptr<osg::Geode> util::getDemoSphere(double radius_, osg::Vec3 offset_ )
254{
255        osg::ref_ptr<osg::Geode> sphere = new osg::Geode();
256        osg::ref_ptr<osg::ShapeDrawable> shape = new osg::ShapeDrawable(new osg::Sphere( offset_, radius_ ) );
257        osg::Vec4 color = osg::Vec4(255.0, 0.0, 0.0, 1.0);
258        shape->setColor( color );
259        sphere->addDrawable( shape );
260
261        return sphere;
262}
263
264bool util::intersect(const osg::Vec3d& start_, const osg::Vec3d& end_, osg::Vec3d& intersection_, osg::Node* node_, osg::Node::NodeMask intersectTraversalMask_ )
265{
266        osg::ref_ptr<osgUtil::LineSegmentIntersector> lsi = new osgUtil::LineSegmentIntersector(start_,end_);
267
268        osgUtil::IntersectionVisitor iv(lsi.get());
269        iv.setTraversalMask(intersectTraversalMask_);
270   
271        node_->accept(iv);
272   
273        if (lsi->containsIntersections())
274        {
275                intersection_ = lsi->getIntersections().begin()->getWorldIntersectPoint();
276                return true;    // Intersect found
277        }
278        return false;   // No intersect found
279}
280
281bool util::queryHeightOfTerrain(double& hot_, osg::Node* rootNode_, double lat_, double lon_, osg::Node::NodeMask traversalMask_)
282{
283        // Get ellipsoid model
284        osg::CoordinateSystemNode* csn = dynamic_cast<osg::CoordinateSystemNode*>(rootNode_);
285        if ( !csn )
286        {
287                OSG_NOTIFY( osg::FATAL ) << "util::queryHeightOfTerrain() :: Invalid CSN!" << std::endl;
288                return false;
289        }
290        osg::EllipsoidModel* ellipsoid = csn->getEllipsoidModel();
291        if ( !ellipsoid )
292        {
293                OSG_NOTIFY( osg::FATAL ) << "util::queryHeightOfTerrain() :: Invalid ellipsoid!" << std::endl;
294                return false;
295        }
296
297        // Setup both endpoints of intersect line
298        double X,Y,Z;
299        ellipsoid->convertLatLongHeightToXYZ(lat_, lon_, 30000, X, Y, Z);
300        osg::Vec3d s = osg::Vec3d(X, Y, Z);
301        ellipsoid->convertLatLongHeightToXYZ(lat_, lon_, -30000, X, Y, Z);
302        osg::Vec3d e = osg::Vec3d(X, Y, Z);
303
304        // Query intersection point
305        osg::Vec3d ip;
306        if ( util::intersect(s, e, ip, rootNode_, traversalMask_) )
307        {
308                double lat2_, lon2_;
309                ellipsoid->convertXYZToLatLongHeight( ip.x(), ip.y(), ip.z(), lat2_, lon2_, hot_ );     // Convert Intersection Point back to Lat Lon, HOT.
310                //OSG_NOTIFY(osg::ALWAYS) << "lat: "<< osg::RadiansToDegrees(lat2_) <<", Lon: " << osg::RadiansToDegrees(lon2_) << ", Hot: " << hot_ << std::endl;
311                return true;
312        }
313
314        // If no intersection point found: set HOT to zero and return false.
315        hot_ = 0;
316        return false;
317}
318
319bool util::queryHeightAboveTerrainInWGS84(double& hat_, osg::Node* rootNode_, double lat_, double lon_, double height_, osg::Node::NodeMask traversalMask_)
320{
321        // Get HOT by asking util::queryHeightOfTerrain() :)
322        double HOT;
323        if ( !util::queryHeightOfTerrain(HOT, rootNode_, lat_, lon_, traversalMask_) )
324        {
325                OSG_NOTIFY( osg::INFO ) << "util::queryHeightAboveTerrainInWGS84() :: Unable to get HOT, will use 0 for HOT!" << std::endl;
326        }
327
328        // Calculate HAT
329        hat_ = height_ - HOT;
330        return true;
331}
332
333bool util::queryHeightAboveTerrainInWorld(double& hat_, osg::Node* rootNode_, double x_, double y_, double z_, osg::Node::NodeMask traversalMask_)
334{
335        // Get ellipsoid model
336        osg::CoordinateSystemNode* csn = dynamic_cast<osg::CoordinateSystemNode*>(rootNode_);
337        if ( !csn )
338        {
339                OSG_NOTIFY( osg::FATAL ) << "util::queryHeightAboveTerrainInWorld() :: Invalid CSN!" << std::endl;
340                return false;
341        }
342        osg::EllipsoidModel* ellipsoid = csn->getEllipsoidModel();
343        if ( !ellipsoid )
344        {
345                OSG_NOTIFY( osg::FATAL ) << "util::queryHeightAboveTerrainInWorld() :: Invalid ellipsoid!" << std::endl;
346                return false;
347        }
348
349        // Transform XYZ into LatLonHeight
350        double lat_, lon_, height_;
351        ellipsoid->convertXYZToLatLongHeight(x_, y_, z_, lat_, lon_, height_);
352
353        // ask util::queryHeightAboveTerrainInWGS84() to calc HAT :)
354        if( !util::queryHeightAboveTerrainInWGS84(hat_, rootNode_, lat_, lon_, height_, traversalMask_ ) )
355        {
356                OSG_NOTIFY( osg::FATAL ) << "util::queryHeightAboveTerrainInWorld() :: Unable to get HAT!" << std::endl;
357                return false;
358        }
359
360        return true;
361}
362
363bool util::calculateEarthRadiusAtWGS84Coordinate(double lat_, double lon_, osg::Node* rootNode_, double& radius_)
364{
365        // Calculate radius:
366        double x, y, z;
367       
368        if ( util::calculateXYZAtWGS84Coordinate(lat_, lon_, 0.0, rootNode_, x, y, z) )
369        {
370                radius_ = sqrt( pow(x, 2) + pow(y, 2) + pow(z, 2) );
371                return true;
372        }
373        else
374        {
375                OSG_NOTIFY( osg::FATAL ) << "util::calculateEarthRadiusAtWGS84Coordinate() :: Unable to calculate Earth Radius!" << std::endl;
376                return false;
377        }
378}
379
380bool util::calculateXYZAtWGS84Coordinate(double lat_, double lon_, double height_, osg::Node* rootNode_, double& x_, double& y_, double& z_)
381{
382        // Get ellipsoid model
383        osg::CoordinateSystemNode* csn = dynamic_cast<osg::CoordinateSystemNode*>(rootNode_);
384        if ( !csn )
385                return false;
386        osg::EllipsoidModel* ellipsoid = csn->getEllipsoidModel();
387        if ( !ellipsoid )
388                return false;
389
390        // Calculate xyz:
391        ellipsoid->convertLatLongHeightToXYZ( lat_, lon_, height_, x_, y_, z_);
392        return true;
393}
394
395bool util::getWGS84ofCamera( osg::Camera* camera_, osg::Node* rootNode_, double& lat_, double& lon_, double& height_ )
396{
397        // Get ellipsoid model
398        osg::CoordinateSystemNode* csn = dynamic_cast<osg::CoordinateSystemNode*>(rootNode_);
399        if ( !csn )
400                return false;
401        osg::EllipsoidModel* ellipsoid = csn->getEllipsoidModel();
402        if ( !ellipsoid )
403                return false;
404
405        osg::Vec3d eye, dir, up;
406        camera_->getViewMatrixAsLookAt(eye,dir,up); // Get XYZ from camera
407        ellipsoid->convertXYZToLatLongHeight(eye.x(), eye.y(), eye.z(), lat_, lon_, height_);
408        return true;
409}
410
411void util::getXYZofCamera( osg::Camera* camera_, double& x_, double& y_, double& z_ )
412{
413        osg::Vec3d eye, dir, up;
414        camera_->getViewMatrixAsLookAt(eye,dir,up); // Get XYZ from camera
415        x_ = eye.x();
416        y_ = eye.y();
417        z_ = eye.z();
418}
419
420bool util::removeClosebuttonOnGLWindow(osgViewer::Viewer* viewer_)
421{
422#ifdef FUNFUNCTIONS_ENABLED
423#ifdef WIN32
424        osgViewer::ViewerBase::Windows wins;
425        viewer_->getWindows(wins);
426        osgViewer::GraphicsHandleWin32* hwnd = dynamic_cast<osgViewer::GraphicsHandleWin32*>(wins[0]);
427       
428        HMENU hMenu = GetSystemMenu(hwnd->getHWND(), FALSE);
429        ::EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | (MF_DISABLED | MF_GRAYED)); 
430#endif
431#endif
432        return true;
433}
434
435bool util::setTransparentWindowBackground(osgViewer::Viewer* viewer_)
436{
437#ifdef FUNFUNCTIONS_ENABLED
438#ifdef WIN32
439        osgViewer::ViewerBase::Windows wins;
440        viewer_->getWindows(wins);
441        osgViewer::GraphicsHandleWin32* hwnd = dynamic_cast<osgViewer::GraphicsHandleWin32*>(wins[0]);
442        HWND _hwnd = hwnd->getHWND();
443        viewer_->getDisplaySettings()->setMinimumNumAlphaBits(8);
444
445   // Create and populate the Blur Behind structure
446   DWM_BLURBEHIND bb = {0};
447   // Disable Blur Behind and Blur Region;
448   bb.dwFlags = DWM_BB_ENABLE;
449   bb.fEnable = true;
450   bb.hRgnBlur = NULL;
451
452   // Ensable Blur Behind
453   HRESULT hr = DwmEnableBlurBehindWindow(_hwnd, &bb);
454   if (SUCCEEDED(hr))
455      return true;
456   else
457           return false;
458
459#endif
460#endif
461        return true;
462}
463
464std::vector<std::string> util::getTerrainFromXMLConfig(std::string configFilename)
465{
466        xmlDoc* tmpDoc;
467        xmlNode* sceneryNode = util::getSceneryXMLConfig(configFilename, tmpDoc);
468        std::vector<std::string> filenames;
469
470        // Iterate through nodes and search for terrian entry
471        for (xmlNode *cur_node = sceneryNode->children; cur_node; cur_node = cur_node->next)
472        {
473                std::string node_name=reinterpret_cast<const char*>(cur_node->name);
474
475                if(cur_node->type == XML_ELEMENT_NODE && node_name == "terrain")
476                {
477                        xmlAttr  *attr = cur_node->properties;
478                        while ( attr ) 
479                        { 
480                                std::string attr_name=reinterpret_cast<const char*>(attr->name);
481                                std::string attr_value=reinterpret_cast<const char*>(attr->children->content);
482                                if( attr_name.find("filename") != std::string::npos )
483                                {
484                                        filenames.push_back(attr_value);
485                                }
486                                attr = attr->next; 
487                        }
488                }
489        }// FOR all nodes END
490
491        // Cleanup
492        if(sceneryNode)
493        {
494                xmlFreeDoc(tmpDoc); xmlCleanupParser();
495        }
496
497        return filenames;
498}
499
500std::string util::getAnimationPathFromXMLConfig(std::string configFilename)
501{
502        xmlDoc* tmpDoc;
503        xmlNode* sceneryNode = util::getSceneryXMLConfig(configFilename, tmpDoc);
504        std::string animationpath = "";
505
506        // Iterate through nodes and search for terrian entry
507        for (xmlNode *cur_node = sceneryNode->children; cur_node; cur_node = cur_node->next)
508        {
509                std::string node_name=reinterpret_cast<const char*>(cur_node->name);
510
511                if(cur_node->type == XML_ELEMENT_NODE && node_name == "animationpath")
512                {
513                        xmlAttr  *attr = cur_node->properties;
514                        while ( attr ) 
515                        { 
516                                std::string attr_name=reinterpret_cast<const char*>(attr->name);
517                                std::string attr_value=reinterpret_cast<const char*>(attr->children->content);
518                                if( attr_name == "filename" )
519                                {
520                                        animationpath = attr_value;
521                                }
522                                attr = attr->next; 
523                        }
524                }
525        }// FOR all nodes END
526
527        // Cleanup
528        if(sceneryNode)
529        {
530                xmlFreeDoc(tmpDoc); xmlCleanupParser();
531        }
532
533        return animationpath;
534}
535
536double util::strToDouble(std::string s)
537{
538        double tmp;
539        std::stringstream sstr(s);
540    if (!(sstr >> tmp))
541        {
542                OSG_ALWAYS << __FUNCTION__ << "Warning:Unable to convert "<< s <<" to double, using 0.0 as default!" << std::endl;
543                return 0.0;
544        }
545        else
546                return tmp;
547}
548
549int util::strToInt(std::string s)
550{
551        int tmp;
552        std::stringstream sstr(s);
553        if (!(sstr >> tmp))
554        {
555                OSG_ALWAYS << __FUNCTION__ << "Warning:Unable to convert "<< s <<" to int, using 0 as default!" << std::endl;
556                return 0;
557        }
558        else
559                return tmp;
560}
561
562bool util::strToBool(std::string s)
563{
564        if(s=="yes")
565                return(true);
566        if(s=="no")
567                return(false);
568        OSG_ALWAYS << __FUNCTION__ << "Warning:Unable to convert "<< s <<" to bool, using false as default!" << std::endl;
569        return(false);
570}
Note: See TracBrowser for help on using the repository browser.