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

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

osgVisual now compiles and configure cloudlayer via XML.

todo at all:
cluster: channelname is currently not defined by XML. Should it be?
sky: precipitation has to be activated
XML: model configuration must be implemented
XML: only lowercase in attribute names
XML: cloudlayer should be crapped in a node called cloudlayers.

File size: 17.1 KB
Line 
1/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 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   {
240      return NULL; // leaf node, no match
241   }
242}
243
244osg::ref_ptr<osg::Geode> util::getDemoCylinder(double length_, double width_, osg::Vec3 offset_ )
245{
246        osg::ref_ptr<osg::Geode> cyl = new osg::Geode();
247        osg::ref_ptr<osg::ShapeDrawable> shape = new osg::ShapeDrawable(new osg::Cylinder( offset_, width_, length_ ));
248        osg::Vec4 color = osg::Vec4(255.0, 0.0, 0.0, 1.0);
249        shape->setColor( color );
250        cyl->addDrawable( shape );
251
252        return cyl;
253}
254
255osg::ref_ptr<osg::Geode> util::getDemoSphere(double radius_, osg::Vec3 offset_ )
256{
257        osg::ref_ptr<osg::Geode> sphere = new osg::Geode();
258        osg::ref_ptr<osg::ShapeDrawable> shape = new osg::ShapeDrawable(new osg::Sphere( offset_, radius_ ) );
259        osg::Vec4 color = osg::Vec4(255.0, 0.0, 0.0, 1.0);
260        shape->setColor( color );
261        sphere->addDrawable( shape );
262
263        return sphere;
264}
265
266bool util::intersect(const osg::Vec3d& start_, const osg::Vec3d& end_, osg::Vec3d& intersection_, osg::Node* node_, osg::Node::NodeMask intersectTraversalMask_ )
267{
268        osg::ref_ptr<osgUtil::LineSegmentIntersector> lsi = new osgUtil::LineSegmentIntersector(start_,end_);
269
270        osgUtil::IntersectionVisitor iv(lsi.get());
271        iv.setTraversalMask(intersectTraversalMask_);
272   
273        node_->accept(iv);
274   
275        if (lsi->containsIntersections())
276        {
277                intersection_ = lsi->getIntersections().begin()->getWorldIntersectPoint();
278                return true;    // Intersect found
279        }
280        return false;   // No intersect found
281}
282
283bool util::queryHeightOfTerrain(double& hot_, osg::Node* rootNode_, double lat_, double lon_, osg::Node::NodeMask traversalMask_)
284{
285        // Get ellipsoid model
286        osg::CoordinateSystemNode* csn = dynamic_cast<osg::CoordinateSystemNode*>(rootNode_);
287        if ( !csn )
288        {
289                OSG_NOTIFY( osg::FATAL ) << "util::queryHeightOfTerrain() :: Invalid CSN!" << std::endl;
290                return false;
291        }
292        osg::EllipsoidModel* ellipsoid = csn->getEllipsoidModel();
293        if ( !ellipsoid )
294        {
295                OSG_NOTIFY( osg::FATAL ) << "util::queryHeightOfTerrain() :: Invalid ellipsoid!" << std::endl;
296                return false;
297        }
298
299        // Setup both endpoints of intersect line
300        double X,Y,Z;
301        ellipsoid->convertLatLongHeightToXYZ(lat_, lon_, 30000, X, Y, Z);
302        osg::Vec3d s = osg::Vec3d(X, Y, Z);
303        ellipsoid->convertLatLongHeightToXYZ(lat_, lon_, -30000, X, Y, Z);
304        osg::Vec3d e = osg::Vec3d(X, Y, Z);
305
306        // Query intersection point
307        osg::Vec3d ip;
308        if ( util::intersect(s, e, ip, rootNode_, traversalMask_) )
309        {
310                double lat2_, lon2_;
311                ellipsoid->convertXYZToLatLongHeight( ip.x(), ip.y(), ip.z(), lat2_, lon2_, hot_ );     // Convert Intersection Point back to Lat Lon, HOT.
312                //OSG_NOTIFY(osg::ALWAYS) << "lat: "<< osg::RadiansToDegrees(lat2_) <<", Lon: " << osg::RadiansToDegrees(lon2_) << ", Hot: " << hot_ << std::endl;
313                return true;
314        }
315
316        // If no intersection point found: set HOT to zero and return false.
317        hot_ = 0;
318        return false;
319}
320
321bool util::queryHeightAboveTerrainInWGS84(double& hat_, osg::Node* rootNode_, double lat_, double lon_, double height_, osg::Node::NodeMask traversalMask_)
322{
323        // Get HOT by asking util::queryHeightOfTerrain() :)
324        double HOT;
325        if ( !util::queryHeightOfTerrain(HOT, rootNode_, lat_, lon_, traversalMask_) )
326        {
327                OSG_NOTIFY( osg::INFO ) << "util::queryHeightAboveTerrainInWGS84() :: Unable to get HOT, will use 0 for HOT!" << std::endl;
328        }
329
330        // Calculate HAT
331        hat_ = height_ - HOT;
332        return true;
333}
334
335bool util::queryHeightAboveTerrainInWorld(double& hat_, osg::Node* rootNode_, double x_, double y_, double z_, osg::Node::NodeMask traversalMask_)
336{
337        // Get ellipsoid model
338        osg::CoordinateSystemNode* csn = dynamic_cast<osg::CoordinateSystemNode*>(rootNode_);
339        if ( !csn )
340        {
341                OSG_NOTIFY( osg::FATAL ) << "util::queryHeightAboveTerrainInWorld() :: Invalid CSN!" << std::endl;
342                return false;
343        }
344        osg::EllipsoidModel* ellipsoid = csn->getEllipsoidModel();
345        if ( !ellipsoid )
346        {
347                OSG_NOTIFY( osg::FATAL ) << "util::queryHeightAboveTerrainInWorld() :: Invalid ellipsoid!" << std::endl;
348                return false;
349        }
350
351        // Transform XYZ into LatLonHeight
352        double lat_, lon_, height_;
353        ellipsoid->convertXYZToLatLongHeight(x_, y_, z_, lat_, lon_, height_);
354
355        // ask util::queryHeightAboveTerrainInWGS84() to calc HAT :)
356        if( !util::queryHeightAboveTerrainInWGS84(hat_, rootNode_, lat_, lon_, height_, traversalMask_ ) )
357        {
358                OSG_NOTIFY( osg::FATAL ) << "util::queryHeightAboveTerrainInWorld() :: Unable to get HAT!" << std::endl;
359                return false;
360        }
361
362        return true;
363}
364
365bool util::calculateEarthRadiusAtWGS84Coordinate(double lat_, double lon_, osg::Node* rootNode_, double& radius_)
366{
367        // Calculate radius:
368        double x, y, z;
369       
370        if ( util::calculateXYZAtWGS84Coordinate(lat_, lon_, 0.0, rootNode_, x, y, z) )
371        {
372                radius_ = sqrt( pow(x, 2) + pow(y, 2) + pow(z, 2) );
373                return true;
374        }
375        else
376        {
377                OSG_NOTIFY( osg::FATAL ) << "util::calculateEarthRadiusAtWGS84Coordinate() :: Unable to calculate Earth Radius!" << std::endl;
378                return false;
379        }
380}
381
382bool util::calculateXYZAtWGS84Coordinate(double lat_, double lon_, double height_, osg::Node* rootNode_, double& x_, double& y_, double& z_)
383{
384        // Get ellipsoid model
385        osg::CoordinateSystemNode* csn = dynamic_cast<osg::CoordinateSystemNode*>(rootNode_);
386        if ( !csn )
387                return false;
388        osg::EllipsoidModel* ellipsoid = csn->getEllipsoidModel();
389        if ( !ellipsoid )
390                return false;
391
392        // Calculate xyz:
393        ellipsoid->convertLatLongHeightToXYZ( lat_, lon_, height_, x_, y_, z_);
394        return true;
395}
396
397bool util::getWGS84ofCamera( osg::Camera* camera_, osg::Node* rootNode_, double& lat_, double& lon_, double& height_ )
398{
399        // Get ellipsoid model
400        osg::CoordinateSystemNode* csn = dynamic_cast<osg::CoordinateSystemNode*>(rootNode_);
401        if ( !csn )
402                return false;
403        osg::EllipsoidModel* ellipsoid = csn->getEllipsoidModel();
404        if ( !ellipsoid )
405                return false;
406
407        osg::Vec3d eye, dir, up;
408        camera_->getViewMatrixAsLookAt(eye,dir,up); // Get XYZ from camera
409        ellipsoid->convertXYZToLatLongHeight(eye.x(), eye.y(), eye.z(), lat_, lon_, height_);
410        return true;
411}
412
413void util::getXYZofCamera( osg::Camera* camera_, double& x_, double& y_, double& z_ )
414{
415        osg::Vec3d eye, dir, up;
416        camera_->getViewMatrixAsLookAt(eye,dir,up); // Get XYZ from camera
417        x_ = eye.x();
418        y_ = eye.y();
419        z_ = eye.z();
420}
421
422bool util::removeClosebuttonOnGLWindow(osgViewer::Viewer* viewer_)
423{
424#ifdef FUNFUNCTIONS_ENABLED
425#ifdef WIN32
426        osgViewer::ViewerBase::Windows wins;
427        viewer_->getWindows(wins);
428        osgViewer::GraphicsHandleWin32* hwnd = dynamic_cast<osgViewer::GraphicsHandleWin32*>(wins[0]);
429       
430        HMENU hMenu = GetSystemMenu(hwnd->getHWND(), FALSE);
431        ::EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | (MF_DISABLED | MF_GRAYED)); 
432#endif
433#endif
434        return true;
435}
436
437bool util::setTransparentWindowBackground(osgViewer::Viewer* viewer_)
438{
439#ifdef FUNFUNCTIONS_ENABLED
440#ifdef WIN32
441        osgViewer::ViewerBase::Windows wins;
442        viewer_->getWindows(wins);
443        osgViewer::GraphicsHandleWin32* hwnd = dynamic_cast<osgViewer::GraphicsHandleWin32*>(wins[0]);
444        HWND _hwnd = hwnd->getHWND();
445        viewer_->getDisplaySettings()->setMinimumNumAlphaBits(8);
446
447   // Create and populate the Blur Behind structure
448   DWM_BLURBEHIND bb = {0};
449   // Disable Blur Behind and Blur Region;
450   bb.dwFlags = DWM_BB_ENABLE;
451   bb.fEnable = true;
452   bb.hRgnBlur = NULL;
453
454   // Ensable Blur Behind
455   HRESULT hr = DwmEnableBlurBehindWindow(_hwnd, &bb);
456   if (SUCCEEDED(hr))
457      return true;
458   else
459           return false;
460
461#endif
462#endif
463        return true;
464}
465
466std::vector<std::string> util::getTerrainFromXMLConfig(std::string configFilename)
467{
468        xmlDoc* tmpDoc;
469        xmlNode* sceneryNode = util::getSceneryXMLConfig(configFilename, tmpDoc);
470        std::vector<std::string> filenames;
471
472        // Iterate through nodes and search for terrian entry
473        for (xmlNode *cur_node = sceneryNode->children; cur_node; cur_node = cur_node->next)
474        {
475                std::string node_name=reinterpret_cast<const char*>(cur_node->name);
476
477                if(cur_node->type == XML_ELEMENT_NODE && node_name == "terrain")
478                {
479                        xmlAttr  *attr = cur_node->properties;
480                        while ( attr ) 
481                        { 
482                                std::string attr_name=reinterpret_cast<const char*>(attr->name);
483                                std::string attr_value=reinterpret_cast<const char*>(attr->children->content);
484                                if( attr_name.find("filename") != std::string::npos )
485                                {
486                                        filenames.push_back(attr_value);
487                                }
488                                attr = attr->next; 
489                        }
490                }
491        }// FOR all nodes END
492
493        // Cleanup
494        if(sceneryNode)
495        {
496                xmlFreeDoc(tmpDoc); xmlCleanupParser();
497        }
498
499        return filenames;
500}
501
502std::string util::getAnimationPathFromXMLConfig(std::string configFilename)
503{
504        xmlDoc* tmpDoc;
505        xmlNode* sceneryNode = util::getSceneryXMLConfig(configFilename, tmpDoc);
506        std::string animationpath = "";
507
508        // Iterate through nodes and search for terrian entry
509        for (xmlNode *cur_node = sceneryNode->children; cur_node; cur_node = cur_node->next)
510        {
511                std::string node_name=reinterpret_cast<const char*>(cur_node->name);
512
513                if(cur_node->type == XML_ELEMENT_NODE && node_name == "animationpath")
514                {
515                        xmlAttr  *attr = cur_node->properties;
516                        while ( attr ) 
517                        { 
518                                std::string attr_name=reinterpret_cast<const char*>(attr->name);
519                                std::string attr_value=reinterpret_cast<const char*>(attr->children->content);
520                                if( attr_name == "filename" )
521                                {
522                                        animationpath = attr_value;
523                                }
524                                attr = attr->next; 
525                        }
526                }
527        }// FOR all nodes END
528
529        // Cleanup
530        if(sceneryNode)
531        {
532                xmlFreeDoc(tmpDoc); xmlCleanupParser();
533        }
534
535        return animationpath;
536}
Note: See TracBrowser for help on using the repository browser.