Index: /osgVisual/src/cluster/dataIO_clusterDummy.cpp
===================================================================
--- /osgVisual/src/cluster/dataIO_clusterDummy.cpp	(revision 31)
+++ /osgVisual/src/cluster/dataIO_clusterDummy.cpp	(revision 31)
@@ -0,0 +1,80 @@
+/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
+ *
+ * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under 
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
+ * You have to aquire licenses for all used proprietary modules.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#include "dataIO_clusterDummy.h"
+
+#include "memoryLeakDetection.h"
+
+dataIO_clusterDummy::dataIO_clusterDummy()
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "clusterDummy constructed" << std::endl;
+}
+
+dataIO_clusterDummy::~dataIO_clusterDummy(void)
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "clusterDummy destructed" << std::endl;
+}
+
+void dataIO_clusterDummy::init( osg::ArgumentParser& arguments_, osgVisual::dataIO_transportContainer* sendContainer_, bool compressionEnabled_, bool asAscii_ )
+{
+	sendContainer = sendContainer_;
+	OSG_NOTIFY( osg::ALWAYS ) << "clusterDummy init();" << std::endl;
+}
+
+void dataIO_clusterDummy::shutdown()
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "clusterDummy shutdown();" << std::endl;
+}
+
+bool dataIO_clusterDummy::sendTO_OBJvaluesToSlaves()
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "clusterDummy sendTO_OBJvaluesToSlaves()" << std::endl;
+
+	return true;
+}
+
+bool dataIO_clusterDummy::readTO_OBJvaluesFromMaster()
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "clusterDummy readTO_OBJvaluesFromMaster()" << std::endl;
+
+	return true;
+}
+
+void dataIO_clusterDummy::reportAsReadyToSwap()
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "clusterDummy reportAsReadyToSwap()" << std::endl;
+}
+
+bool dataIO_clusterDummy::waitForSwap()
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "clusterDummy waitForSwap()" << std::endl;
+
+	return true;
+}
+
+bool dataIO_clusterDummy::waitForAllReadyToSwap()
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "clusterDummy waitForAllReadyToSwap()" << std::endl;
+
+	return true;
+}
+
+bool dataIO_clusterDummy::sendSwapCommand()
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "clusterDummy sendSwapCommand()" << std::endl;
+
+	return true;
+}
Index: /osgVisual/src/cluster/dataIO_clusterUDP.cpp
===================================================================
--- /osgVisual/src/cluster/dataIO_clusterUDP.cpp	(revision 31)
+++ /osgVisual/src/cluster/dataIO_clusterUDP.cpp	(revision 31)
@@ -0,0 +1,160 @@
+/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
+ *
+ * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under 
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
+ * You have to aquire licenses for all used proprietary modules.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#include "dataIO_clusterUDP.h"
+
+using namespace osgVisual;
+
+
+dataIO_clusterUDP::dataIO_clusterUDP()
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "clusterUDP constructed" << std::endl;
+
+	compressionEnabled = true;
+	broadcaster = NULL;
+	receiver = NULL;
+}
+
+dataIO_clusterUDP::~dataIO_clusterUDP(void)
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "clusterUDP destructed" << std::endl;
+}
+
+void dataIO_clusterUDP::init( osg::ArgumentParser& arguments_, osgVisual::dataIO_transportContainer* sendContainer_, bool compressionEnabled_, bool asAscii_ )
+{
+	// set Variables
+	sendContainer = sendContainer_;
+
+	// Configure Compression and instantiate read/write-options
+	std::string readOptionString = "";
+	std::string writeOptionString = "";
+	if(asAscii_)
+	{
+		readOptionString = "Ascii";
+		writeOptionString = "Ascii";
+	}
+	if (compressionEnabled_)
+		writeOptionString+=" Compressor=zlib";
+	readOptions = new osgDB::Options( readOptionString.c_str() );
+	writeOptions = new osgDB::Options( writeOptionString.c_str() );
+
+	// Get ReaderWriter
+	rw = osgDB::Registry::instance()->getReaderWriterForExtension("osgb");	
+
+	// Instantiate broadcaster and reciever
+	broadcaster = new osgVisual::Broadcaster();
+	broadcaster->init(12345);
+	receiver = new osgVisual::Receiver();
+	receiver->init(12345);
+	
+	OSG_NOTIFY( osg::ALWAYS ) << "clusterUDP init()" << std::endl;
+}
+
+void dataIO_clusterUDP::shutdown()
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "clusterUDP shutdown()" << std::endl;
+}
+
+bool dataIO_clusterUDP::sendTO_OBJvaluesToSlaves()
+{
+	OSG_NOTIFY( osg::INFO ) << "clusterUDP sendTO_OBJvaluesToSlaves()" << std::endl;
+
+	if(sendContainer.valid())
+	{
+		// Writing node to stream
+		std::stringstream myOstream;
+		if ( rw )
+		{
+			osgDB::ReaderWriter::WriteResult wr = rw->writeObject( *sendContainer.get(), myOstream, writeOptions );
+			if (wr.success() )			
+			{
+				// Send Data via UDP:
+				//OSG_NOTIFY( osg::ALWAYS ) << "dataIO_clusterUDP::sendTO_OBJvaluesToSlaves() - Bytes to send: " << myOstream.str().length() << std::endl;
+				//OSG_NOTIFY( osg::ALWAYS ) << "Send: " << myOstream.str() << std::endl;
+				broadcaster->transmitBuffer( myOstream.str().c_str() , myOstream.str().length() );
+			}
+			else OSG_NOTIFY( osg::WARN ) << "ERROR: clusterUDP sendTO_OBJvaluesToSlaves() :: Save failed: " << wr.message() << std::endl;
+		}
+		else OSG_NOTIFY( osg::WARN ) << "ERROR: clusterUDP sendTO_OBJvaluesToSlaves() :: Unable to get readerWriter for osgb" << std::endl;
+	}
+	else OSG_NOTIFY( osg::WARN ) << "ERROR: clusterUDP sendTO_OBJvaluesToSlaves() :: Invalid transportContainer" << std::endl;
+
+	return true;
+}
+
+bool dataIO_clusterUDP::readTO_OBJvaluesFromMaster()
+{
+	OSG_NOTIFY( osg::INFO ) << "clusterUDP readTO_OBJvaluesFromMaster()" << std::endl;
+
+	std::stringstream received;
+	receiver->waitBlockingforSocketData( received );
+
+	int bytes_received = received.str().length();
+	if (bytes_received > 0 )
+	{
+		OSG_NOTIFY( osg::ALWAYS ) << "dataIO_clusterUDP::readTO_OBJvaluesFromMaster() - Bytes received: " << bytes_received << std::endl;
+		OSG_NOTIFY( osg::ALWAYS ) << "Received: " << received.str() << std::endl;
+
+		// Unserialize data
+		if ( rw )
+		{
+			osgDB::ReaderWriter::ReadResult rr = rw->readObject( received, readOptions );
+			if (rr.success())
+			{
+				sendContainer = dynamic_cast<osgVisual::dataIO_transportContainer*>(rr.takeObject());
+				if (sendContainer)
+				{
+					OSG_NOTIFY( osg::ALWAYS ) << "Received::FrameID is: " << sendContainer->getFrameID() << std::endl;
+				}
+				else
+					OSG_NOTIFY( osg::WARN ) << "ERROR: dataIO_clusterUDP::readTO_OBJvaluesFromMaster() - Unable to cast converted node to transportContainer" << std::endl;
+			}
+			else
+				OSG_NOTIFY( osg::WARN ) << "ERROR: dataIO_clusterUDP::readTO_OBJvaluesFromMaster() - Unable to convert stream to node" << std::endl;
+		}
+		else
+			OSG_NOTIFY( osg::WARN ) << "ERROR: dataIO_clusterUDP::readTO_OBJvaluesFromMaster() - Unable to get readerWriter for osgb" << std::endl;
+	}
+
+
+	return true;
+}
+
+void dataIO_clusterUDP::reportAsReadyToSwap()
+{
+	OSG_NOTIFY( osg::INFO ) << "clusterUDP reportAsReadyToSwap()" << std::endl;
+}
+
+bool dataIO_clusterUDP::waitForSwap()
+{
+	OSG_NOTIFY( osg::INFO ) << "clusterUDP waitForSwap()" << std::endl;
+
+	return true;
+}
+
+bool dataIO_clusterUDP::waitForAllReadyToSwap()
+{
+	OSG_NOTIFY( osg::INFO ) << "clusterUDP waitForAllReadyToSwap()" << std::endl;
+
+	return true;
+}
+
+bool dataIO_clusterUDP::sendSwapCommand()
+{
+	OSG_NOTIFY( osg::INFO ) << "clusterUDP sendSwapCommand()" << std::endl;
+
+	return true;
+}
Index: /osgVisual/src/cluster/dataIO_clusterUDP_Transmission.cpp
===================================================================
--- /osgVisual/src/cluster/dataIO_clusterUDP_Transmission.cpp	(revision 31)
+++ /osgVisual/src/cluster/dataIO_clusterUDP_Transmission.cpp	(revision 31)
@@ -0,0 +1,207 @@
+/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
+ *
+ * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under 
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
+ * You have to aquire licenses for all used proprietary modules.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#include "dataIO_clusterUDP_Transmission.h"
+
+using namespace osgVisual;
+
+
+Broadcaster::Broadcaster()
+{
+    _initialized = false;
+    _destinationAddress = 0;
+	requestedWSAVersion = MAKEWORD(2,0);
+}
+
+Broadcaster::~Broadcaster()
+{
+    closesocket( _so);
+}
+
+bool Broadcaster::init(const short port_)
+{
+    WSADATA wsaData;
+
+    // First, we start up Winsock
+    WSAStartup(requestedWSAVersion, &wsaData);
+
+    if( port_ == 0 )
+    {
+		OSG_NOTIFY( osg::FATAL ) << "ERROR: Broadcaster::init() - port not defined: " << std::endl;
+        return false;
+    }
+
+	// Create Socket
+    if( (_so = socket( AF_INET, SOCK_DGRAM, 0 )) < 0 )
+    {
+		OSG_NOTIFY( osg::FATAL ) << "ERROR: Broadcaster::init() - Unable to create socket!" << std::endl;
+        return false;
+    }
+    const BOOL on = TRUE;
+
+	// Set Socket options
+    setsockopt( _so, SOL_SOCKET, SO_REUSEADDR, (const char *) &on, sizeof(int));
+    saddr.sin_family = AF_INET;	// Internetwork UDP, TCP etc.
+    saddr.sin_port   = htons( port_ );	// Port festlegen
+    if( _destinationAddress == 0 )	// Wenn keine Zieladresse festgelegt: Broadcasten
+    {
+        setsockopt( _so, SOL_SOCKET, SO_BROADCAST, (const char *) &on, sizeof(int));
+        saddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
+    }
+
+	// Print out destination address
+    unsigned char *ptr = (unsigned char *)&saddr.sin_addr.s_addr;
+	OSG_NOTIFY( osg::ALWAYS ) << "INFO: Broadcaster::init() - Broadcast address = " << (unsigned int)ptr[0] << "." << (unsigned int)ptr[1] << "." << (unsigned int)ptr[2] << "." << (unsigned int)ptr[3] << std::endl;
+
+	// Note: Initialization finished.
+    _initialized = true;
+    return _initialized;
+}
+
+void Broadcaster::setDestinationHost( const char *hostname )
+{
+    struct hostent *h;
+    if( (h = gethostbyname( hostname )) == 0L )
+    {
+		OSG_NOTIFY( osg::FATAL ) << "ERROR: Broadcaster::setHost() - Cannot resolve an address for " << hostname;
+        _destinationAddress = 0;
+    }
+    else
+        _destinationAddress = *(( unsigned long  *)h->h_addr);
+}
+
+void Broadcaster::transmitBuffer( const char* buffer_, const unsigned int size_ )
+{
+    if(!_initialized) 
+	{
+		OSG_NOTIFY( osg::FATAL ) << "ERROR: Broadcaster not initialized!" << std::endl;
+		return;
+	}
+
+    if( buffer_ == NULL )
+    {
+		OSG_NOTIFY( osg::FATAL ) << "ERROR: Broadcaster::transmitBuffer() - No buffer" << std::endl;
+        return;
+    }
+
+    unsigned int addrSize = sizeof( SOCKADDR_IN );
+    sendto( _so, buffer_, size_, 0, (struct sockaddr *)&saddr, addrSize );
+    int err = WSAGetLastError ();
+    if (err!=0)
+		OSG_NOTIFY( osg::FATAL ) << "ERROR: Broadcaster::transmitBuffer() - Error #: " << err << std::endl;
+}
+
+//
+//--------------------------------------------------------
+//
+
+Receiver::Receiver( void )
+{
+    _initialized = false;
+	requestedWSAVersion = MAKEWORD(2,0);
+}
+
+Receiver::~Receiver( void )
+{
+    closesocket( _so);
+}
+
+bool Receiver::init( const short port_ )
+{
+    WSADATA wsaData;
+    // First, we start up Winsock
+    WSAStartup(requestedWSAVersion, &wsaData);
+
+	if( port_ == 0 )
+    {
+		OSG_NOTIFY( osg::FATAL ) << "ERROR: Receiver::init() - port not defined: " << std::endl;
+        return false;
+    }
+
+	// Create Socket
+    if( (_so = socket( AF_INET, SOCK_DGRAM, 0 )) < 0 )
+    {
+		OSG_NOTIFY( osg::FATAL ) << "ERROR: Receiver::init() -Could not create Socket" << std::endl;
+		return false;
+    }
+
+	// Set Socket Protocolfamily and Protocoldata (IP address, port, etc.)
+    //// Protokollfamilie
+	saddr.sin_family = AF_INET;
+    //// Port:
+	saddr.sin_port   = htons( port_ );	// The htons function converts a u_short from host to TCP/IP network byte order (which is big-endian)
+	//////Socketadresse. INADDR_ANY ist das Schlüsselwort für 0x00000000 und bindet den Socket auf alle lokalen IP-Adressen:
+	saddr.sin_addr.s_addr =  htonl(INADDR_ANY);		// The htonl function converts a u_long from host to TCP/IP network byte order (which is big endian).
+ 
+
+	// Bind socket to local address and port.
+    if( bind( _so, (struct sockaddr *)&saddr, sizeof( saddr )) < 0 )
+    {
+        OSG_NOTIFY( osg::FATAL ) << "ERROR: Receiver::init() - Could not bind Socket" << std::endl;
+        return false;
+    }
+
+	// Note: Initialization finished.
+    _initialized = true;
+    return _initialized;
+}
+
+void Receiver::waitBlockingforSocketData( std::stringstream& writeInto_ )
+{
+	if(!_initialized) 
+	{
+		OSG_NOTIFY( osg::FATAL ) << "ERROR: Receiver not initialized!" << std::endl;
+		return;
+	}
+
+	// ?? Size des Addresspaketes ermitteln
+    int size = sizeof( struct sockaddr_in );
+
+    fd_set fdset;	// Filedescriptor Set
+    FD_ZERO( &fdset );	// Initialisiert das FDS als Null
+    FD_SET( _so, &fdset );	// Fügt dem FDS ein FileDescriptor hinzu
+
+	// Set Timeintervall for select() timeout
+    struct timeval tv;
+    tv.tv_sec = 0;
+    tv.tv_usec = 0;
+
+	// In einer Schleife: Solange lesen bis keine Daten mehr in dem Socket warten.
+    while( select( _so, &fdset, 0L, 0L, &tv ) )	// <0: error, =0 timeout, >0: socket to read
+    {
+        if( FD_ISSET( _so, &fdset ) )
+        {
+            int ret = recvfrom( _so, buffer, 65000, 0, (sockaddr*)&saddr, &size );
+			// check for size
+			if (ret > 0)
+			{
+				writeInto_.str("");
+				OSG_NOTIFY( osg::INFO ) <<  "Receiver::waitBlockingforSocketData() - Empfangene Bytes:" << ret << std::endl;
+				for(int i=0;i<ret;i++)
+					writeInto_ << buffer[i];
+			}
+			else
+			{
+				int err = WSAGetLastError ();
+				if (err!=0) 
+					OSG_NOTIFY( osg::FATAL ) <<  "Receiver::waitBlockingforSocketData() - Error #" << err << std::endl;
+			}
+		}	// END IF_ISSET
+    }
+	OSG_NOTIFY( osg::INFO ) << "Socket leergelesen!" << std::endl;
+}
+
+
Index: /osgVisual/src/core/osgVisual.cpp
===================================================================
--- /osgVisual/src/core/osgVisual.cpp	(revision 31)
+++ /osgVisual/src/core/osgVisual.cpp	(revision 31)
@@ -0,0 +1,39 @@
+/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
+ *
+ * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under 
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
+ * You have to aquire licenses for all used proprietary modules.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#include <osg/ArgumentParser>
+#include <osg/Referenced>
+#include <osgDB/Registry>
+
+#include <visual_core.h>
+
+
+const unsigned int MAX_NUM_EVENTS = 10;
+const unsigned int SWAP_BYTES_COMPARE = 0x12345678;
+
+int main(int argc, char** argv)
+{
+    // Use an ArgumentParser object to manage the program arguments.
+	osg::ArgumentParser arguments(&argc,argv);
+
+    // Instantiate osgVisual main class
+	osg::ref_ptr<osgVisual::visual_core> core = new osgVisual::visual_core(arguments);
+
+    // Visual initialisieren
+    core->initialize();
+
+	return 0;
+}
Index: /osgVisual/src/core/visual_core.cpp
===================================================================
--- /osgVisual/src/core/visual_core.cpp	(revision 31)
+++ /osgVisual/src/core/visual_core.cpp	(revision 31)
@@ -0,0 +1,438 @@
+/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
+ *
+ * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under 
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
+ * You have to aquire licenses for all used proprietary modules.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#include <visual_core.h>
+
+using namespace osgVisual;
+
+visual_core::visual_core(osg::ArgumentParser& arguments_) : arguments(arguments_)
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "visual_core instantiated." << std::endl;
+
+	// Setup pathes
+	osgDB::Registry::instance()->getDataFilePathList().push_back( "D:\\DA\\osgVisual\\models" );
+	
+	// Setup viewer
+	viewer = new osgViewer::Viewer(arguments);
+
+	// Setup coordinate system node
+	rootNode = new osg::CoordinateSystemNode;
+	rootNode->setEllipsoidModel(new osg::EllipsoidModel());
+
+	// Test memory leak (todo)
+	//double* test = new double[1000];
+
+	mouse = NULL;
+}
+
+visual_core::~visual_core(void)
+{
+	// shut osgVisual down
+	shutdown();
+
+	OSG_NOTIFY( osg::ALWAYS ) << "visual_core destroyed." << std::endl;
+
+}
+
+void visual_core::initialize()
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "Initialize visual_core..." << std::endl;
+
+	// Process commandline arguments for configuration parameter
+	processCommandlineArguments();
+	
+	// Add manipulators for user interaction
+	addManipulators();
+
+	// Load terrain
+	loadTerrain(arguments);
+
+	// Show model
+	viewer->setSceneData( rootNode );
+
+#ifdef USE_DISTORTION
+	// Initialize distortion
+	distortion = new visual_distortion( viewer, arguments );
+	distortion->initialize( rootNode, viewer->getCamera()->getClearColor() );
+#endif
+
+#ifdef USE_SKY_SILVERLINING
+	// Initialize sky
+	sky = new visual_skySilverLining( viewer );
+	#ifdef USE_DISTORTION
+		if ( distortion.valid() )
+		{
+			OSG_NOTIFY( osg::ALWAYS ) << "Using sky with distortion." << std::endl;
+			sky->init( distortion->getDistortedSceneGraph(), rootNode);
+		}
+	#else
+		OSG_NOTIFY( osg::ALWAYS ) << "Using Sky without distortion." << std::endl;
+		sky->init(rootNode);
+	#endif
+#endif
+
+	// Initialize DataIO interface
+	visual_dataIO::getInstance()->init(viewer, arguments);
+
+	// All modules are initialized - now check arguments for any unused parameter.
+	checkCommandlineArgumentsForFinalErrors();
+
+	// create the windows and run the threads.
+	viewer->realize();
+
+	// setup scenery
+	setupScenery();
+
+	// Run visual main loop
+	mainLoop();
+}
+
+void visual_core::mainLoop()
+{
+	// run main loop
+	while( !viewer->done() )
+    {
+		// next frame please....
+        viewer->advance();
+
+		/*double hat, hot, lat, lon, height;
+		util::getWGS84ofCamera( viewer->getCamera(), rootNode, lat, lon, height);
+		if (util::queryHeightOfTerrain( hot, rootNode, lat, lon) && util::queryHeightAboveTerrainInWGS84( hat, rootNode, lat, lon, height ) )
+			OSG_NOTIFY( osg::ALWAYS ) << "HOT is: " << hot << ", HAT is: " << hat << std::endl;*/
+	
+		// update the scene by traversing it with the the update visitor which will
+        // call all node update callbacks and animations.
+        viewer->eventTraversal();
+        viewer->updateTraversal();
+		
+        // Render the Frame.
+        viewer->renderingTraversals();
+
+    }	// END WHILE
+}
+
+void visual_core::shutdown()
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "Shutdown visual_core..." << std::endl;
+
+	// Unset scene data
+	viewer->setSceneData( NULL );
+
+#ifdef USE_SKY_SILVERLINING
+	// Shutdown sky
+	if( sky.valid() )
+		sky->shutdown();
+#endif
+
+#ifdef USE_DISTORTION
+	// Shutdown distortion
+	if( distortion.valid() )
+		distortion->shutdown();
+#endif
+
+	// Shutdown dataIO
+	visual_dataIO::getInstance()->shutdown();
+
+	
+#ifdef USE_SPACENAVIGATOR
+	//Delete SpaceMouse driver
+	if(mouse)
+	{
+		mouse->shutdown();
+		delete mouse;
+	}
+#endif
+}
+
+bool visual_core::loadTerrain(osg::ArgumentParser& arguments_)
+{
+	osg::ref_ptr<osg::Node> model = osgDB::readNodeFiles(arguments_);
+	if( model.valid() )
+	{
+        rootNode->addChild( model.get() );
+		return true;
+	}
+	else
+	{
+        OSG_NOTIFY( osg::FATAL ) << arguments_.getApplicationName() <<"Load terrain: No data loaded" << std::endl;
+        return false;
+    }    
+
+	return false;
+}
+
+void visual_core::addManipulators()
+{
+	// set up the camera manipulators.
+    {
+        osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;
+
+        keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
+        keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
+        keyswitchManipulator->addMatrixManipulator( '3', "Terrain", new osgGA::TerrainManipulator() );
+		nt = new osgGA::NodeTrackerManipulator();
+		keyswitchManipulator->addMatrixManipulator( '4', "NodeTrackerManipulator", nt );
+		
+#ifdef USE_SPACENAVIGATOR
+		// SpaceNavigator manipulator
+		mouse = new SpaceMouse();
+		mouse->initialize();
+		mouseTrackerManip = new NodeTrackerSpaceMouse(mouse);
+		mouseTrackerManip->setTrackerMode(NodeTrackerSpaceMouse::NODE_CENTER);
+		mouseTrackerManip->setRotationMode(NodeTrackerSpaceMouse::ELEVATION_AZIM);
+		mouseTrackerManip->setAutoComputeHomePosition( true );
+		keyswitchManipulator->addMatrixManipulator( '5', "Spacemouse Node Tracker", mouseTrackerManip );
+		keyswitchManipulator->addMatrixManipulator( '6', "Spacemouse Free (Airplane)", new FreeManipulator(mouse) );
+#endif
+
+		// objectMounted Manipulator for Camera control by Nodes
+		objectMountedCameraManip = new objectMountedManipulator();
+		keyswitchManipulator->addMatrixManipulator( '7', "Object mounted Camera", objectMountedCameraManip );
+
+		// Animation path manipulator
+        std::string pathfile;
+        char keyForAnimationPath = '8';
+        while (arguments.read("-p",pathfile))
+        {
+            osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(pathfile);
+            if (apm || !apm->valid()) 
+            {
+                unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
+                keyswitchManipulator->addMatrixManipulator( keyForAnimationPath, "Path", apm );
+                keyswitchManipulator->selectMatrixManipulator(num);
+                ++keyForAnimationPath;
+            }
+        }
+
+        viewer->setCameraManipulator( keyswitchManipulator.get() );
+    }
+
+    // add the state manipulator
+    viewer->addEventHandler( new osgGA::StateSetManipulator(rootNode->getOrCreateStateSet()) );
+    
+    // add the thread model handler
+    viewer->addEventHandler(new osgViewer::ThreadingHandler);
+
+    // add the window size toggle handler
+    viewer->addEventHandler(new osgViewer::WindowSizeHandler);
+        
+    // add the stats handler
+    viewer->addEventHandler(new osgViewer::StatsHandler);
+
+    // add the help handler
+    viewer->addEventHandler(new osgViewer::HelpHandler(arguments.getApplicationUsage()));
+
+    // add the record camera path handler
+    viewer->addEventHandler(new osgViewer::RecordCameraPathHandler);
+
+    // add the LOD Scale handler
+    viewer->addEventHandler(new osgViewer::LODScaleHandler);
+
+    // add the screen capture handler
+    viewer->addEventHandler(new osgViewer::ScreenCaptureHandler);
+}
+
+void visual_core::processCommandlineArguments()
+{
+	std::cout << "Processing general commandline arguments..." << std::endl;
+
+	// Setup Application Usage
+	arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
+	arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the new FSD visualization tool, written by Torben Dannhauer");
+    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] Terrain_filename");
+	arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
+
+    // if user request help write it out to cout.
+    if (arguments.read("-h") || arguments.read("--help"))
+    {
+        arguments.getApplicationUsage()->write(std::cout);
+		//cause the viewer to exit and shut down clean.
+        viewer->setDone(true);
+    }
+
+    // report any errors if they have occurred when parsing the program arguments.
+    if (arguments.errors())
+    {
+        arguments.writeErrorMessages(std::cout);
+		//cause the viewer to exit and shut down clean.
+        viewer->setDone(true);
+    }
+}
+
+bool visual_core::checkCommandlineArgumentsForFinalErrors()
+{
+	 // any option left unread are converted into errors to write out later.
+    arguments.reportRemainingOptionsAsUnrecognized();
+
+    // report any errors if they have occurred when parsing the program arguments.
+    if (arguments.errors())
+    {
+        arguments.writeErrorMessages(std::cout);
+        return false;
+    }
+	return true;
+}
+
+void visual_core::setupScenery()
+{
+	//testObj = new visual_object( rootNode, "testStab", objectMountedCameraManip );
+	//testObj->setNewPosition( osg::DegreesToRadians(47.7123), osg::DegreesToRadians(12.84088), 600 );
+	///* using a huge cylinder to test position & orientation */
+	//testObj->setGeometry( util::getDemoCylinder(5000.0, 20.0 ) );
+	//testObj->addUpdater( new object_updater(testObj) );
+
+	osg::ref_ptr<visual_object> testObj2 = new visual_object( rootNode, "cessna" );
+	//testObj2->setNewPosition( osg::DegreesToRadians(47.8123), osg::DegreesToRadians(12.94088), 600 );
+	testObj2->setNewPosition( osg::DegreesToRadians(50.8123), osg::DegreesToRadians(8.94088), 600 );
+	testObj2->loadGeometry( "../models/cessna.osg" );
+	testObj2->addUpdater( new object_updater(testObj2) );
+
+	osg::ref_ptr<visual_object> testObj3 = new visual_object( rootNode, "SAENGER1" );
+	testObj3->setNewPosition( osg::DegreesToRadians(47.8123), osg::DegreesToRadians(12.94088), 600 );
+	testObj3->loadGeometry( "../models/saenger1.flt" );
+	testObj3->addUpdater( new object_updater(testObj3) );
+	
+
+	osg::ref_ptr<visual_object> testObj4 = new visual_object( rootNode, "SAENGER2" );
+	testObj4->setNewPosition( osg::DegreesToRadians(47.8123), osg::DegreesToRadians(12.94088), 650 );
+	testObj4->loadGeometry( "../models/saenger2.flt" );
+	testObj4->addUpdater( new object_updater(testObj4) );
+	testObj4->addLabel("testLabel", "LabelTest!!\nnächste Zeile :)",osg::Vec4(1.0f,0.25f,1.0f,1.0f));
+
+	osg::ref_ptr<visual_object> testObj5 = new visual_object( rootNode, "SAENGER" );
+	testObj5->setNewPosition( osg::DegreesToRadians(47.8123), osg::DegreesToRadians(12.94088), 550 );
+	testObj5->loadGeometry( "../models/saengerCombine.flt" );
+	//testObj5->setScale( 2 );
+	testObj5->addUpdater( new object_updater(testObj5) );
+
+#ifdef USE_SPACENAVIGATOR
+	// Manipulatoren auf dieses Objekt binden (Primärobjekt)
+	if (objectMountedCameraManip.valid())
+		objectMountedCameraManip->setAttachedObject( testObj4 );
+	if (mouseTrackerManip.valid())
+	{
+		mouseTrackerManip->setTrackNode( testObj4->getGeometry() );
+		mouseTrackerManip->setMinimumDistance( 100 );
+	}
+#endif
+
+	osgGA::NodeTrackerManipulator::TrackerMode trackerMode = osgGA::NodeTrackerManipulator::NODE_CENTER;
+	osgGA::NodeTrackerManipulator::RotationMode rotationMode = osgGA::NodeTrackerManipulator::ELEVATION_AZIM;
+	nt->setTrackerMode(trackerMode);
+    nt->setRotationMode(rotationMode);
+	//nt->setAutoComputeHomePosition( true );
+	nt->setMinimumDistance( 100 );
+	nt->setTrackNode(testObj4->getGeometry());
+	//nt->computeHomePosition();
+	nt->setAutoComputeHomePosition( true );
+	nt->setDistance( 250 );
+
+
+	// Load EDDF
+	//std::string filename = "D:\\DA\\EDDF_test\\eddf.ive";
+	//if( !osgDB::fileExists(filename) )
+	//{
+	//	OSG_NOTIFY(osg::ALWAYS) << "Warning: EDDF Model not loaded. File '" << filename << "' does not exist. Skipping.";
+	//}
+	//// read model
+	//osg::ref_ptr<osg::Node> tmpModel = osgDB::readNodeFile( filename );
+	//if (tmpModel.valid())
+	//	rootNode->addChild( tmpModel );
+	
+ 
+	visual_draw2D::getInstance()->init( rootNode, viewer );
+	//osg::ref_ptr<visual_hud> hud = new visual_hud();
+	osg::ref_ptr<visual_debug_hud> hud = new visual_debug_hud();
+	hud->init( viewer, rootNode );
+	
+
+	//osg::ref_ptr<visual_draw3D> test = new visual_draw3D();
+	//test->init( rootNode, viewer );
+
+	// Creating Testclasses
+	osg::ref_ptr<osgVisual::dataIO_transportContainer> test = new osgVisual::dataIO_transportContainer();
+	osg::ref_ptr<osgVisual::dataIO_executer> testEx = new osgVisual::dataIO_executer();
+	osg::ref_ptr<osgVisual::dataIO_slot> testSlot = new osgVisual::dataIO_slot();
+	test->setFrameID( 22 );
+	test->setName("ugamoep");
+	testEx->setexecuterID( osgVisual::dataIO_executer::IS_COLLISION );
+	testSlot->setVariableName(std::string("HalloName"));
+	testSlot->setdataDirection( osgVisual::dataIO_slot::TO_OBJ );
+	testSlot->setvarType( osgVisual::dataIO_slot::DOUBLE );
+	testSlot->setValue( 0.12345 );
+	test->addExecuter( testEx );
+	test->addSlot( testSlot );
+
+	// Writing object to stream
+	//std::ofstream myOstream("test.txt" );
+	std::stringstream myOstream;
+	std::string extension = "osgb";
+	bool compressed = false;
+	osgDB::ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension(extension.c_str());
+	if ( rw )
+	{
+		osgDB::ReaderWriter::WriteResult wr;
+
+		if (extension == "osgb")
+		{
+			if (compressed)
+				wr = rw->writeObject( *test, myOstream, new osgDB::Options("Compressor=zlib") );
+			else
+				wr = rw->writeObject( *test, myOstream );
+		}
+
+		if (extension == "osgt")
+		{
+			if (compressed)
+				wr = rw->writeObject( *test, myOstream, new osgDB::Options("Ascii Compressor=zlib") );
+			else
+				wr = rw->writeObject( *test, myOstream, new osgDB::Options("Ascii") );
+		}
+
+		if (extension == "osgx")
+		{
+			if (compressed)
+				wr = rw->writeObject( *test, myOstream, new osgDB::Options("XML Compressor=zlib") );
+			else
+				wr = rw->writeObject( *test, myOstream, new osgDB::Options("XML") );
+		}
+
+
+		if (!wr.success() )	OSG_NOTIFY( osg::WARN ) << "ERROR: Save failed: " << wr.message() << std::endl;
+	}
+	else
+		OSG_NOTIFY( osg::WARN ) << "error getting readerWriter for osgt" << std::endl;
+
+	// Size ermitteln.
+	stringbuf *pbuf;
+	pbuf = myOstream.rdbuf();
+	OSG_NOTIFY( osg::WARN ) << "PBUF Bytes available: " << pbuf->in_avail() << std::endl;
+	OSG_NOTIFY( osg::ALWAYS ) << "STRING Bytes available: " << myOstream.str().length() << std::endl;
+	OSG_NOTIFY( osg::ALWAYS ) << "STRING content: " << myOstream.str() << std::endl;
+
+	//Reading Stream to node
+	if ( rw )
+	{
+		osgDB::ReaderWriter::ReadResult rr = rw->readObject( myOstream );
+		osg::ref_ptr<osgVisual::dataIO_transportContainer> test2 = dynamic_cast<osgVisual::dataIO_transportContainer*>(rr.takeObject());
+		if (test2)
+		{
+			OSG_NOTIFY( osg::WARN ) << "TEST::FrameID is: " << test->getFrameID() << std::endl;
+		}
+		else
+			OSG_NOTIFY( osg::WARN ) << "Error converting stream to Node" << std::endl;
+	}
+}
Index: /osgVisual/src/dataIO/dataIO_executer.cpp
===================================================================
--- /osgVisual/src/dataIO/dataIO_executer.cpp	(revision 31)
+++ /osgVisual/src/dataIO/dataIO_executer.cpp	(revision 31)
@@ -0,0 +1,38 @@
+/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
+ *
+ * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under 
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
+ * You have to aquire licenses for all used proprietary modules.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#include "dataIO_executer.h"
+
+REGISTER_OBJECT_WRAPPER( dataIO_executer,                 // The unique wrapper name
+						new osgVisual::dataIO_executer,             // The proto
+                         osgVisual::dataIO_executer,                 // The class typename
+						 "osg::Node osgVisual::dataIO_executer" )  // The inheritance relations
+{
+    // Serializers for different members    
+	BEGIN_ENUM_SERIALIZER( executerID, DO_NOTHING );
+		ADD_ENUM_VALUE( GET_HAT );
+		ADD_ENUM_VALUE( GET_HOT );
+		ADD_ENUM_VALUE( GET_LAT );
+		ADD_ENUM_VALUE( GET_LON );
+		ADD_ENUM_VALUE( IS_COLLISION );
+		ADD_ENUM_VALUE( IS_INSIDE_CLOUD );
+		ADD_ENUM_VALUE( IS_WIND );
+		ADD_ENUM_VALUE( IS_PRECIPITATION );
+		ADD_ENUM_VALUE( DO_NOTHING );
+		END_ENUM_SERIALIZER();
+		ADD_LIST_SERIALIZER( DoubleParameter, osgVisual::dataIO_executer::parameterList );
+	ADD_STRING_SERIALIZER( StringParameter, "" );	
+}
Index: /osgVisual/src/dataIO/dataIO_slot.cpp
===================================================================
--- /osgVisual/src/dataIO/dataIO_slot.cpp	(revision 31)
+++ /osgVisual/src/dataIO/dataIO_slot.cpp	(revision 31)
@@ -0,0 +1,37 @@
+#pragma once
+/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
+ *
+ * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under 
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
+ * You have to aquire licenses for all used proprietary modules.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#include "dataIO_slot.h"
+
+REGISTER_OBJECT_WRAPPER( dataIO_slot,                 // The unique wrapper name
+                         new osgVisual::dataIO_slot,             // The proto
+                         osgVisual::dataIO_slot,                 // The class typename
+						 "osg::Object osgVisual::dataIO_slot" )  // The inheritance relations
+{
+    // Serializers for different members    
+	BEGIN_ENUM_SERIALIZER( dataDirection, TO_OBJ );
+		ADD_ENUM_VALUE( TO_OBJ );
+		ADD_ENUM_VALUE( FROM_OBJ );
+		END_ENUM_SERIALIZER();
+	BEGIN_ENUM_SERIALIZER( varType, DOUBLE );
+		ADD_ENUM_VALUE( DOUBLE );
+		ADD_ENUM_VALUE( STRING );
+		END_ENUM_SERIALIZER();
+	ADD_STRING_SERIALIZER( VariableName, "" );
+	ADD_DOUBLE_SERIALIZER( Value, 0.0 );
+	ADD_STRING_SERIALIZER( SValue, "" );	
+}
Index: /osgVisual/src/dataIO/dataIO_transportContainer.cpp
===================================================================
--- /osgVisual/src/dataIO/dataIO_transportContainer.cpp	(revision 31)
+++ /osgVisual/src/dataIO/dataIO_transportContainer.cpp	(revision 31)
@@ -0,0 +1,31 @@
+/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
+ *
+ * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under 
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
+ * You have to aquire licenses for all used proprietary modules.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#include "dataIO_transportContainer.h"
+#include <osgDB/ObjectWrapper>
+#include <osgDB/InputStream>
+#include <osgDB/OutputStream>
+
+REGISTER_OBJECT_WRAPPER( dataIO_transportContainer,                      // The unique wrapper name
+                         new osgVisual::dataIO_transportContainer,             // The proto
+                         osgVisual::dataIO_transportContainer,                 // The class typename
+						 "osg::Object osgVisual::dataIO_transportContainer" )  // The inheritance relations
+{
+	ADD_INT_SERIALIZER( FrameID, 0 );
+	ADD_MATRIXD_SERIALIZER( ViewMatrix, osg::Matrixd() );
+	ADD_LIST_SERIALIZER( Executer, osgVisual::dataIO_transportContainer::executerList );
+	ADD_LIST_SERIALIZER( IOSlots, osgVisual::dataIO_transportContainer::slotList );
+}
Index: /osgVisual/src/dataIO/visual_dataIO.cpp
===================================================================
--- /osgVisual/src/dataIO/visual_dataIO.cpp	(revision 31)
+++ /osgVisual/src/dataIO/visual_dataIO.cpp	(revision 31)
@@ -0,0 +1,297 @@
+/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
+ *
+ * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under 
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
+ * You have to aquire licenses for all used proprietary modules.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#include "visual_dataIO.h"
+
+using namespace osgVisual;
+
+visual_dataIO::visual_dataIO()
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "visual_dataIO constructed" << std::endl;
+
+	initialized = false;
+}
+
+visual_dataIO::~visual_dataIO()
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "visual_dataIO destructed" << std::endl;
+}
+
+visual_dataIO* visual_dataIO::getInstance()
+{
+	static visual_dataIO instance; 
+	return &instance; 
+};
+
+void visual_dataIO::init(osgViewer::Viewer* viewer_, osg::ArgumentParser& arguments_)
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "visual_dataIO init()" << std::endl;
+
+	// Init variables
+	viewer = viewer_;
+
+	// Parse operating Mode
+    if (arguments_.read("-m"))
+	{
+		OSG_NOTIFY( osg::ALWAYS ) << "Configure osgVisual as MASTER" << std::endl;
+		clusterMode = osgVisual::dataIO_cluster::MASTER;
+		// Create Container:
+		slotContainer = new osgVisual::dataIO_transportContainer();
+	}
+	else if (arguments_.read("-s"))
+	{
+		OSG_NOTIFY( osg::ALWAYS ) << "Configure osgVisual as SLAVE" << std::endl;
+		clusterMode = osgVisual::dataIO_cluster::SLAVE;
+		// Slave only recieves container, therefor set this Pointer null.
+		slotContainer = NULL;
+	}
+	else
+	{
+		OSG_NOTIFY( osg::ALWAYS ) << "Configure osgVisual as STANDALONE" << std::endl;
+		clusterMode = osgVisual::dataIO_cluster::STANDALONE;
+		// Create Container:
+		slotContainer = new osgVisual::dataIO_transportContainer();
+	}
+
+	// Create Cluster.
+	#ifdef USE_CLUSTER_DUMMY
+		cluster = new dataIO_clusterDummy();
+	#endif
+	#ifdef USE_CLUSTER_UDP
+		cluster = new dataIO_clusterUDP();
+	#endif
+	cluster->init(arguments_, slotContainer, true, false);
+
+	// Create extLink.
+	#ifdef USE_EXTLINK_DUMMY
+		extLink = new dataIO_extLinkDummy( dataSlots );
+	#endif
+	#ifdef USE_EXTLINK_VCL
+		extLink = new dataIO_extLinkVCL( dataSlots );
+	#endif
+	extLink->init();
+
+	
+
+	// Install callbacks to perform DataIO activities every frame:
+	//// EventCallback at the absolute beginning of the frame
+	eventCallback = new dataIO_eventCallback(this);
+	viewer->getCamera()->setEventCallback( eventCallback );
+	//// FinalDrawCallback at the end of event and update handling, but BEFORE rendering the frame
+	finalDrawCallback = new dataIO_finalDrawCallback(this);
+	viewer->getCamera()->setFinalDrawCallback( finalDrawCallback );
+
+
+	initialized = true;
+}
+
+void visual_dataIO::shutdown()
+{
+	if(initialized)
+	{
+		OSG_NOTIFY( osg::ALWAYS ) << "Shutdown visual_dataIO..." << std::endl;
+
+		viewer->getCamera()->removeEventCallback( NULL );
+		eventCallback = NULL;
+		viewer->getCamera()->setFinalDrawCallback( NULL );
+		finalDrawCallback = NULL;
+		viewer = NULL;
+
+		cluster->shutdown();
+		extLink->shutdown();
+	}
+}
+
+void visual_dataIO::dataIO_eventCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
+{
+	// perform all actions for the eventDrawCallback.
+	OSG_NOTIFY( osg::INFO ) << "---- Executing EventCallback.." <<  std::endl;
+
+	switch( dataIO->clusterMode )
+	{
+		case osgVisual::dataIO_cluster::MASTER : 
+			{
+				dataIO->extLink->readTO_OBJvalues();
+				dataIO->cluster->sendTO_OBJvaluesToSlaves();
+			}
+			break;
+		case osgVisual::dataIO_cluster::SLAVE : 
+			{
+				dataIO->cluster->readTO_OBJvaluesFromMaster();
+			}
+			break;
+		case osgVisual::dataIO_cluster::STANDALONE : 
+			{
+				dataIO->extLink->readTO_OBJvalues();
+			}
+			break;
+		default:
+			OSG_NOTIFY( osg::FATAL ) << "ERROR: Unkown clustermode!" <<  std::endl;
+			break;
+	};
+}
+
+void visual_dataIO::dataIO_finalDrawCallback::operator() (const osg::Camera& camera) const
+{
+	// perform all actions for the initialDrawCallback.
+	OSG_NOTIFY( osg::INFO ) << "---- Executing InitialDrawCallback.." << std::endl;
+
+	switch( dataIO->clusterMode )
+	{
+		case osgVisual::dataIO_cluster::MASTER : 
+			{
+				dataIO->extLink->writebackFROM_OBJvalues();
+				dataIO->cluster->waitForAllReadyToSwap();
+				dataIO->cluster->sendSwapCommand();
+			}
+			break;
+		case osgVisual::dataIO_cluster::SLAVE : 
+			{
+				dataIO->cluster->reportAsReadyToSwap();
+				dataIO->cluster->waitForSwap();
+			}
+			break;
+		case osgVisual::dataIO_cluster::STANDALONE : 
+			{
+				dataIO->extLink->writebackFROM_OBJvalues();
+			}
+			break;
+		default:
+			OSG_NOTIFY( osg::FATAL ) << "ERROR: visual_dataIO::dataIO_finalDrawCallback::operator() - Unkown clustermode!" <<  std::endl;
+			break;
+	};
+}
+
+void* visual_dataIO::getSlotPointer(std::string variableName_, osgVisual::dataIO_slot::dataDirection direction_, osgVisual::dataIO_slot::varType variableTyp_ )
+{
+	// iterate through slotlist. If found, return pointer, else add slot to list and return pointer
+	for (unsigned int i=0; i<dataSlots.size(); i++)
+	{
+		// Check if this variable name&-type already exists
+		if( dataSlots[i].variableName == variableName_ && dataSlots[i].direction == direction_  && dataSlots[i].variableType ==  variableTyp_)
+		{
+			//OSG_NOTIFY( osg::INFO ) << "visual_dataIO::getSlotPointer() - Slot found at position " << i << std::endl;
+			// Return pointer to the value
+			if (variableTyp_ == osgVisual::dataIO_slot::STRING )
+				return &(dataSlots[i].sValue);
+			else
+				return &(dataSlots[i].value);
+		}
+	}
+
+	// Slot does not exist -> add it to slot list
+	//OSG_NOTIFY( osg::INFO ) << "visual_dataIO::getSlotPointer() - Slot not found, will add as new slot " << std::endl;
+	dataIO_slot newSlot;
+	newSlot.variableName = variableName_;
+	newSlot.variableType = variableTyp_;
+	newSlot.value = 0;
+	newSlot.sValue = "";
+	dataSlots.push_back( newSlot );
+	if (variableTyp_ == osgVisual::dataIO_slot::STRING )
+		return &(dataSlots.back().sValue);
+	else
+	{
+		return &(dataSlots.back().value);
+	}
+}
+
+double visual_dataIO::getSlotDataAsDouble(std::string variableName_, osgVisual::dataIO_slot::dataDirection direction_ )
+{
+	// iterate through slotlist. If found, return value
+	for (unsigned int i=0; i<dataSlots.size(); i++)
+	{
+		// Check if this variable name&-type already exists
+		if( dataSlots[i].variableName == variableName_ && dataSlots[i].direction == direction_  && dataSlots[i].variableType == osgVisual::dataIO_slot::DOUBLE )
+		{
+			//OSG_NOTIFY( osg::INFO ) << "visual_dataIO::getSlotDataAsDouble() - Slot found at position " << i << std::endl;
+			return dataSlots[i].value;
+		}
+	}
+	return 0;
+}
+
+std::string visual_dataIO::getSlotDataAsString(std::string variableName_, osgVisual::dataIO_slot::dataDirection direction_ )
+{
+	// iterate through slotlist. If found, return value
+	for (unsigned int i=0; i<dataSlots.size(); i++)
+	{
+		// Check if this variable name&-type already exists
+		if( dataSlots[i].variableName == variableName_ && dataSlots[i].direction == direction_  && dataSlots[i].variableType == osgVisual::dataIO_slot::STRING )
+		{
+			//OSG_NOTIFY( osg::INFO ) << "visual_dataIO::getSlotDataAsDouble() - Slot found at position " << i << std::endl;
+			return dataSlots[i].sValue;
+		}
+	}
+	return "";
+}
+
+void visual_dataIO::setSlotData(std::string variableName_, osgVisual::dataIO_slot::dataDirection direction_, std::string sValue_ )
+{
+	bool slotFound = false;
+	// iterate through slotlist. If found, return pointer, else add slot to list
+	for (unsigned int i=0; i<dataSlots.size(); i++)
+	{
+		// Check if this variable name&-type already exists
+		if( dataSlots[i].variableName == variableName_ && dataSlots[i].direction == direction_ && dataSlots[i].variableType ==  osgVisual::dataIO_slot::STRING)
+		{
+			// Update value
+			dataSlots[i].sValue = sValue_;
+			slotFound = true;
+		}
+		
+	}
+
+	if (!slotFound)
+	{
+		// Slot does not exist -> add it to slot list
+		dataIO_slot newSlot;
+		newSlot.variableName = variableName_;
+		newSlot.direction = direction_;
+		newSlot.variableType = osgVisual::dataIO_slot::STRING;
+		newSlot.value = 0;
+		newSlot.sValue = sValue_;
+		dataSlots.push_back( newSlot );
+	}
+}
+
+void visual_dataIO::setSlotData(std::string variableName_, osgVisual::dataIO_slot::dataDirection direction_, double value_ )
+{
+	// iterate through slotlist. If found, return pointer, else add slot to list
+	bool slotFound = false;
+	for (unsigned int i=0; i<dataSlots.size(); i++)
+	{
+		// Check if this variableName & -type already exists
+		if( dataSlots[i].variableName == variableName_ && dataSlots[i].direction == direction_ && dataSlots[i].variableType ==  osgVisual::dataIO_slot::DOUBLE)
+		{
+			// Update value
+			//OSG_NOTIFY( osg::ALWAYS ) << "setSlotData: " << variableName_ << " - value: " << value_ << std::endl;
+			dataSlots[i].value = value_;
+			slotFound = true;
+		}	
+	}
+
+	if (!slotFound)
+	{
+		// Slot does not exist -> add it to slot list
+		dataIO_slot newSlot;
+		newSlot.variableName = variableName_;
+		newSlot.direction = direction_;
+		newSlot.variableType = osgVisual::dataIO_slot::DOUBLE;
+		newSlot.value = value_;
+		newSlot.sValue = "";
+		dataSlots.push_back( newSlot );
+	}
+}
Index: /osgVisual/src/distortion/visual_distortion.cpp
===================================================================
--- /osgVisual/src/distortion/visual_distortion.cpp	(revision 31)
+++ /osgVisual/src/distortion/visual_distortion.cpp	(revision 31)
@@ -0,0 +1,467 @@
+/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
+ *
+ * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under 
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
+ * You have to aquire licenses for all used proprietary modules.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#include <visual_distortion.h>
+
+using namespace osgVisual;
+
+visual_distortion::visual_distortion(osgViewer::Viewer* viewer_, osg::ArgumentParser& arguments_) : viewer(viewer_), arguments(arguments_)
+{
+	OSG_NOTIFY (osg::ALWAYS ) << "visual_distortion instantiated." << std::endl;
+
+	initialized = false;
+	distortionEnabled = false;
+	parser = new CameraConfigParser();
+
+	distortedGraph = NULL;
+	cleanGraph = NULL;
+
+	distortMapTexture = NULL;
+	blendMapTexture = NULL;
+}
+
+visual_distortion::~visual_distortion(void)
+{
+	OSG_NOTIFY (osg::ALWAYS ) << "visual_distortion destroyed." << std::endl;
+}
+
+bool visual_distortion::processCommandlineparameters()
+{
+	arguments.getApplicationUsage()->addCommandLineOption("-C <channelname>","Setup the channel name, this is the preset for blendmap, distortionmap and camera configuration file.");
+	arguments.getApplicationUsage()->addCommandLineOption("--fbo","Use Frame Buffer Object for render to texture, where supported.");
+    arguments.getApplicationUsage()->addCommandLineOption("--fb","Use FrameBuffer for render to texture.");
+    arguments.getApplicationUsage()->addCommandLineOption("--pbuffer","Use Pixel Buffer for render to texture, where supported.");
+    arguments.getApplicationUsage()->addCommandLineOption("--window","Use a seperate Window for render to texture.");
+    arguments.getApplicationUsage()->addCommandLineOption("--width","Set the width of the render to texture.");
+    arguments.getApplicationUsage()->addCommandLineOption("--height","Set the height of the render to texture.");
+    arguments.getApplicationUsage()->addCommandLineOption("--texture-rectangle","Use osg::TextureRectangle for doing the render to texure to.");
+    arguments.getApplicationUsage()->addCommandLineOption("--distortionmap","Set a distortion map file name.");
+    arguments.getApplicationUsage()->addCommandLineOption("--blendmap","Set a blend map file name.");
+    arguments.getApplicationUsage()->addCommandLineOption("--shaderDistortion","Use OpenGL shader for distortion and blending.");
+	arguments.getApplicationUsage()->addKeyboardMouseBinding("d", "Toggle Distortion.");
+
+	// Read out Distortion CMDLine arguments
+	tex_width = 2048;
+    tex_height = 2048;
+    while (arguments.read("--width", tex_width)) {}
+    while (arguments.read("--height", tex_height)) {}
+
+	renderImplementation = osg::Camera::FRAME_BUFFER_OBJECT;
+
+    while (arguments.read("--fbo")) { renderImplementation = osg::Camera::FRAME_BUFFER_OBJECT; }
+    while (arguments.read("--pbuffer")) { renderImplementation = osg::Camera::PIXEL_BUFFER; }
+    while (arguments.read("--pbuffer-rtt")) { renderImplementation = osg::Camera::PIXEL_BUFFER_RTT; }
+    while (arguments.read("--fb")) { renderImplementation = osg::Camera::FRAME_BUFFER; }
+    while (arguments.read("--window")) { renderImplementation = osg::Camera::SEPERATE_WINDOW; }
+
+    useTextureRectangle = false;
+    while (arguments.read("--texture-rectangle")) { useTextureRectangle = true; }
+	useShaderDistortion = false;
+    while (arguments.read("--shaderDistortion")) { useShaderDistortion = true; }
+    useHDR = false; 
+    while (arguments.read("--hdr")) { useHDR = true; }
+
+	distortMapFileName = "..\\resources\\distortion\\distort_distDisabled.bmp";
+    while (arguments.read("--distortionmap", distortMapFileName)) { }
+	blendMapFileName = "..\\resources\\distortion\\blend_distDisabled.bmp";
+    while (arguments.read("--blendmap", blendMapFileName)) { }
+
+	std::string pre_cfg("..\\resources\\distortion\\view_");
+	std::string pre_distortion("..\\resources\\distortion\\distort_");
+	std::string pre_blend("..\\resources\\distortion\\blend_");
+	std::string post_cfg(".cfg");
+	std::string post_distortion(".bmp");
+	std::string post_blend(".bmp");
+	std::string channelname;
+	while (arguments.read("-C",channelname))
+	{
+		OSG_NOTIFY(osg::INFO) << "channelname:" << channelname << std::endl;
+		// load channel config
+		parser->parseConfigFile((pre_cfg+channelname+post_cfg).data());
+		// load channel blendmap
+		blendMapFileName = (pre_blend+channelname+post_blend).data();
+		// load channel distortionmap
+		distortMapFileName = (pre_distortion+channelname+post_distortion).data(); 
+		// set channel frustum
+		if( parser->isConfigParsed())
+ 			viewer->getCamera()->setProjectionMatrixAsFrustum((parser->getFrustumDataset())[0], (parser->getFrustumDataset())[1], (parser->getFrustumDataset())[2], (parser->getFrustumDataset())[3], (parser->getFrustumDataset())[4], (parser->getFrustumDataset())[5]);
+		else
+			OSG_NOTIFY(osg::WARN) << "WARNING: Unable to parse Frustum values from '" << pre_cfg<<channelname<<post_cfg << "' -- continue without valid frustum values." << std::endl;
+	}
+
+	 // report any errors if they have occurred when parsing the program arguments.
+    if (arguments.errors())
+    {
+        arguments.writeErrorMessages(std::cout);
+		exit(1);
+    }
+	return true;
+}
+
+osg::Group* visual_distortion::initialize(osg::Group* subgraph, const osg::Vec4& clearColor )
+{
+	OSG_NOTIFY (osg::ALWAYS ) << "visual_distortion initialize..." << std::endl;
+
+	// Process Commandline arguments:
+	processCommandlineparameters();
+
+	// Add this node to the scenegraph to get updated during update traversal.
+	subgraph->addChild( this );
+
+	// add the keyboard handler for toggle distortion
+	kBEventHandler = new ToggleDistortionKBEventHandler( this );
+	viewer->addEventHandler( kBEventHandler );
+
+	cleanGraph = subgraph;
+	distortedGraph = createPreRenderSubGraph( subgraph, clearColor );
+
+	// Create and install updateCallback (to get called for copying the main cameras view matrixes to the PRE_RENDER camera)
+	// -- must be called _AFTER_ createPreRenderSubGraph() (necessary because sceneCamera is set by createPreRenderSubGraph())
+	updateCallback = new distortionUpdateCallback( viewer, sceneCamera );
+	this->setUpdateCallback( updateCallback );
+
+	// Note down state flags..
+	initialized = true;
+	distortionEnabled = true;
+
+	distortionEnabled = true;
+	viewer->setSceneData( distortedGraph );
+	
+	return distortedGraph;
+}
+
+void visual_distortion::shutdown()
+{
+	if(initialized)
+	{
+		// Remove this Node from scenegraph
+		cleanGraph->removeChild( this );
+
+		// Remove update callback
+		this->removeUpdateCallback( updateCallback );
+		updateCallback = NULL;
+
+		OSG_NOTIFY (osg::ALWAYS ) << "visual_distortion shutdown complete." << std::endl;
+	}
+}
+
+void visual_distortion::distortionUpdateCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
+{
+	// Copy Main Camera's matrixes to the PRE_RENDER Camera.
+	sceneCamera->setViewMatrix( viewer->getCamera()->getViewMatrix() );
+	sceneCamera->setProjectionMatrix( viewer->getCamera()->getProjectionMatrix() );
+}
+
+void visual_distortion::toggleDistortion()
+{
+	// Toggle
+	//// If not Distorted: enabled distortion
+	if( !distortionEnabled )
+	{
+		distortionEnabled = true;
+		viewer->setSceneData( distortedGraph );
+	}
+	else	// .. otherwise disable distortion
+	{
+		distortionEnabled = false;
+		viewer->setSceneData( cleanGraph );
+	}
+}
+
+
+osg::Group* visual_distortion::createPreRenderSubGraph(osg::Group* subgraph, const osg::Vec4& clearColor )
+{
+    if (!subgraph) return 0;
+
+    // create a group to contain the flag and the pre rendering camera.
+    osg::Group* parent = new osg::Group;
+
+    // texture to render to and to use for rendering of flag.
+    osg::Texture* texture = 0;
+    if (useTextureRectangle)
+    {
+        osg::TextureRectangle* textureRect = new osg::TextureRectangle;
+        textureRect->setTextureSize(tex_width, tex_height);
+        textureRect->setInternalFormat(GL_RGBA);
+        textureRect->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
+        textureRect->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
+        
+        texture = textureRect;
+    }
+    else
+    {
+        osg::Texture2D* texture2D = new osg::Texture2D;
+        texture2D->setTextureSize(tex_width, tex_height);
+        texture2D->setInternalFormat(GL_RGBA);
+        texture2D->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
+        texture2D->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
+        
+        texture = texture2D;
+    } 
+
+    if (useHDR)
+    {
+        texture->setInternalFormat(GL_RGBA16F_ARB);
+        texture->setSourceFormat(GL_RGBA);
+        texture->setSourceType(GL_FLOAT);
+    }
+
+    // load a distortion map texture file
+	if ( osgDB::fileExists( distortMapFileName ) )
+		distortMapTexture = loadTexture(distortMapFileName);
+	else
+	{
+		OSG_NOTIFY(osg::FATAL) << "ERROR: Distortionmap file'" << distortMapFileName << "' not found! Please change the channelname, filename or copy the desired file to the applications root folder!" << std::endl;
+		exit(-1);
+	}
+
+    // load a blend map texture file
+	if ( osgDB::fileExists( blendMapFileName ) )
+		blendMapTexture = loadTexture(blendMapFileName);
+	else
+	{
+		OSG_NOTIFY(osg::FATAL) << "ERROR: Blendmap file'" << blendMapFileName << "' not found! Please change the channelname, filename or copy the desired file to the applications root folder!" << std::endl;
+		exit(-1);
+	}
+
+    // set up the plane to render the rendered view.
+    {
+        // create the quad to visualize.
+        osg::Geometry* polyGeom = new osg::Geometry();
+
+        polyGeom->setSupportsDisplayList(false);
+
+        osg::Vec3 origin(0.0f,0.0f,0.0f);
+        osg::Vec3 xAxis(1.0f,0.0f,0.0f);
+        osg::Vec3 yAxis(0.0f,1.0f,0.0f);
+        osg::Vec3 zAxis(0.0f,0.0f,1.0f);
+        float height = 1024.0f;
+        float width = 1280.0f;
+        int noSteps = 128;
+        if (useShaderDistortion)
+            noSteps = 2;
+
+        osg::Vec3Array* vertices = new osg::Vec3Array;
+        osg::Vec2Array* texcoords = new osg::Vec2Array;
+        osg::Vec2Array* texcoords2 = useShaderDistortion?NULL:(new osg::Vec2Array);
+        osg::Vec4Array* colors = new osg::Vec4Array;
+
+        osg::Vec3 bottom = origin;
+        osg::Vec3 dx = xAxis*(width/((float)(noSteps-1)));
+        osg::Vec3 dy = yAxis*(height/((float)(noSteps-1)));
+
+        osg::Vec2 bottom_texcoord(0.0f,0.0f);
+        osg::Vec2 dx_texcoord(1.0f/(float)(noSteps-1),0.0f);
+        osg::Vec2 dy_texcoord(0.0f,1.0f/(float)(noSteps-1));
+
+        osg::Vec3 cursor = bottom;
+        osg::Vec2 texcoord = bottom_texcoord;
+        int i,j;
+        for(i=0;i<noSteps;++i)
+        {
+            osg::Vec3 cursor = bottom+dy*(float)i;
+            osg::Vec2 texcoord = bottom_texcoord+dy_texcoord*(float)i;
+            for(j=0;j<noSteps;++j)
+            {
+                vertices->push_back(cursor);
+                if (distortMapTexture && !useShaderDistortion)
+                {
+                    osg::Vec2 imgcoord = osg::Vec2((distortMapTexture->getImage(0)->s()-1) * texcoord.x(),
+                                                   (distortMapTexture->getImage(0)->t()-1) * texcoord.y());
+                    unsigned char* pPixel = &distortMapTexture->getImage(0)->data()[(int)imgcoord.y()*distortMapTexture->getImage(0)->getRowSizeInBytes()+
+                                                                                    (int)imgcoord.x()*distortMapTexture->getImage(0)->getPixelSizeInBits()/8];
+                    texcoords->push_back(osg::Vec2(((float)pPixel[2] / 255.0f + (pPixel[0] % 16)) / 16.0f,
+                                                   1.0f - ((float)pPixel[1] / 255.0f + (pPixel[0] / 16)) / 16.0f));
+                    texcoords2->push_back(osg::Vec2(texcoord.x(), texcoord.y()));
+                }
+                else
+                    texcoords->push_back(osg::Vec2(texcoord.x(), texcoord.y()));
+                colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
+
+                cursor += dx;
+                texcoord += dx_texcoord;
+            }
+        }
+
+        // pass the created vertex array to the points geometry object.
+        polyGeom->setVertexArray(vertices);
+
+        polyGeom->setColorArray(colors);
+        polyGeom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
+        polyGeom->setTexCoordArray(0,texcoords);
+        if (!useShaderDistortion)
+            polyGeom->setTexCoordArray(2,texcoords2);
+
+        for(i=0;i<noSteps-1;++i)
+        {
+            osg::DrawElementsUShort* elements = new osg::DrawElementsUShort(osg::PrimitiveSet::QUAD_STRIP);
+            for(j=0;j<noSteps;++j)
+            {
+                elements->push_back(j+(i+1)*noSteps);
+                elements->push_back(j+(i)*noSteps);
+            }
+            polyGeom->addPrimitiveSet(elements);
+        }
+
+        // new we need to add the texture to the Drawable, we do so by creating a 
+        // StateSet to contain the Texture StateAttribute.
+        osg::StateSet* stateset = polyGeom->getOrCreateStateSet();
+        stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
+        stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
+        stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
+
+        osg::Geode* geode = new osg::Geode();
+        geode->addDrawable(polyGeom);
+
+        if (useShaderDistortion)
+        {
+            // apply the distortion map texture
+            if (distortMapTexture)
+                geode->getOrCreateStateSet()->setTextureAttributeAndModes(1, distortMapTexture, osg::StateAttribute::ON);
+        }
+
+        // apply the blend map texture
+        if (blendMapTexture)
+            geode->getOrCreateStateSet()->setTextureAttributeAndModes(2, blendMapTexture, osg::StateAttribute::ON);
+
+        // set up the camera to render the textured quad
+        osg::Camera* camera = new osg::Camera;
+
+        // just inherit the main cameras view
+        camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
+        camera->setViewMatrix(osg::Matrix::identity());
+        //camera->setProjectionMatrixAsOrtho2D(0,viewer->getCamera()->getViewport()->width(),0,viewer->getCamera()->getViewport()->height());
+		camera->setProjectionMatrixAsOrtho2D(0,1280,0,1024);
+
+        // set the camera to render before the main camera.
+        camera->setRenderOrder(osg::Camera::POST_RENDER, 200);
+
+        // only clear the depth buffer
+        camera->setClearMask(0);
+
+        // add subgraph to render
+        camera->addChild(geode);
+
+        if (useShaderDistortion)
+        {
+            // create shaders for distortion
+            osg::StateSet* ss = geode->getOrCreateStateSet();
+
+            osg::Program* distortProgram = new osg::Program;
+            distortProgram->setName( "distortion" );
+            osg::Shader* distortVertObj = new osg::Shader( osg::Shader::VERTEX );
+            osg::Shader* distortFragObj = new osg::Shader( osg::Shader::FRAGMENT );
+
+            if (loadShaderSource( distortVertObj, "shader.vert" ) &&
+                loadShaderSource( distortFragObj, "shader.frag" ) &&
+                distortMapTexture)
+            {
+                distortProgram->addShader( distortFragObj );
+                distortProgram->addShader( distortVertObj );
+                ss->addUniform( new osg::Uniform("textureImage", 0) );
+                ss->addUniform( new osg::Uniform("textureDistort", 1) );
+                ss->addUniform( new osg::Uniform("textureBlend", 2) );
+                ss->setAttributeAndModes(distortProgram, osg::StateAttribute::ON);
+            }
+			else
+			{
+				OSG_NOTIFY(osg::FATAL) << "##################################" << std::endl << "## Unable to activate ShaderDistortion!" << std::endl << "## ABORT" << std::endl << "##################################" << std::endl;
+				exit(0);
+			}
+        }
+
+        parent->addChild(camera);
+    }
+
+    // then create the camera node to do the render to texture
+    {    
+        osg::Camera* camera = new osg::Camera;
+
+        // set up the background color and clear mask.
+        camera->setClearColor(clearColor);
+        camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+
+        // just inherit the main cameras view
+		/* ABSOLUTE_RF required to make intersections possible.
+		Disadvantage of ABOLUTE_RF : the maincameras view matrix and projection
+		matrix has to copied to the PRE_RENDER camera by our self.
+		Therefore an update callback is installed.
+		*/
+		camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);	
+        camera->setProjectionMatrix(osg::Matrixd::identity());
+        camera->setViewMatrix(osg::Matrixd::identity());
+
+        // set viewport
+        camera->setViewport(0,0,tex_width,tex_height);
+
+        // set the camera to render before the main camera.
+        camera->setRenderOrder(osg::Camera::PRE_RENDER, 0);
+
+		sceneCamera = camera;
+
+        // tell the camera to use OpenGL frame buffer object where supported.
+        camera->setRenderTargetImplementation(renderImplementation);
+
+        // attach the texture and use it as the color buffer.
+        camera->attach(osg::Camera::COLOR_BUFFER, texture);	// No Multisampling/Antialiasing
+		//camera->attach(osg::Camera::COLOR_BUFFER, texture, 0, 0, false, 4, 4); // 4x Multisampling/Antialiasing
+
+        // add subgraph to render
+        camera->addChild(subgraph);
+
+        parent->addChild(camera);
+    }    
+    return parent;
+}
+
+
+bool visual_distortion::loadShaderSource( osg::Shader* shader, const std::string& fileName )
+{
+    std::string foundFileName = osgDB::findDataFile(fileName);
+    if (foundFileName.length() != 0 )
+    {
+        return shader->loadShaderSourceFromFile( foundFileName.c_str() );
+    }
+
+    OSG_NOTIFY(osg::WARN) << "File \"" << fileName << "\" not found." << std::endl;
+
+    return false;
+}
+
+osg::Texture* visual_distortion::loadTexture( const std::string& fileName )
+{
+    std::string foundFileName = osgDB::findDataFile(fileName);
+    if (foundFileName.length() != 0 )
+    {
+        // load distortion map texture file
+        osg::Image* image = osgDB::readImageFile(foundFileName);
+        if (image)
+        {
+			osg::Texture2D* texture = new osg::Texture2D;
+            texture->setImage(image);
+            texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST);
+            texture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::NEAREST);
+            texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::CLAMP_TO_EDGE);
+            texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::CLAMP_TO_EDGE);
+            return texture;
+        }
+    }
+
+    OSG_NOTIFY(osg::WARN) << "File \"" << fileName << "\" not found." << std::endl;
+
+    return NULL;
+}
Index: /osgVisual/src/draw2D/visual_debug_hud.cpp
===================================================================
--- /osgVisual/src/draw2D/visual_debug_hud.cpp	(revision 31)
+++ /osgVisual/src/draw2D/visual_debug_hud.cpp	(revision 31)
@@ -0,0 +1,175 @@
+/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
+ *
+ * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under 
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
+ * You have to aquire licenses for all used proprietary modules.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#include <visual_debug_hud.h>
+
+using namespace osgVisual;
+
+visual_debug_hud::visual_debug_hud(void)
+{
+
+}
+
+visual_debug_hud::~visual_debug_hud(void)
+{
+}
+
+bool visual_debug_hud::init( osgViewer::Viewer *viewer_, osg::CoordinateSystemNode* rootNode_  )
+{	
+
+
+
+    screen_width = viewer_->getCamera()->getViewport()->width();
+    screen_height = viewer_->getCamera()->getViewport()->height();
+   	
+	visual_draw2D::getInstance()->addDrawContent( addContent(), "HUD" );
+
+	// Set callback.
+	updateCallback = new HudUpdateCallback( rootNode_, viewer_->getCamera() );
+	this->setEventCallback( updateCallback );
+
+	isInitialized = true;
+
+	return true;
+}
+
+void visual_debug_hud::shutdown()
+{
+	if (isInitialized)
+	{	
+		// Remove updatecallback
+		this->removeUpdateCallback( updateCallback );
+		updateCallback = NULL;
+	}
+}
+
+osg::ref_ptr<osg::Geode> visual_debug_hud::addContent()
+{
+	osg::ref_ptr<osg::Geode> hudGeode = this;
+
+	// turn lighting off
+	osg::ref_ptr<osg::StateSet> stateset = hudGeode->getOrCreateStateSet();
+    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
+
+
+    
+	// Add Text: 
+	osg::Vec3 position(screen_width-180.0f,120.0f,0.0f);
+	osg::Vec3 delta(0.0f,-25.0f,0.0f);
+	std::string timesFont("fonts/arial.ttf");
+	{
+		textLat = new osgText::Text;
+		hudGeode->addDrawable( textLat );
+		textLat->setFont(timesFont);
+		textLat->setPosition(position);
+		textLat->setCharacterSize(21);
+		textLat->setDataVariance(osg::Object::DYNAMIC); 
+
+		position += delta;
+
+		textLon = new osgText::Text;
+		hudGeode->addDrawable( textLon );
+		textLon->setFont(timesFont);
+		textLon->setPosition(position);
+		textLon->setCharacterSize(21);
+		textLon->setDataVariance(osg::Object::DYNAMIC); 
+
+		position += delta;
+
+		textAlt = new osgText::Text;
+		hudGeode->addDrawable( textAlt );
+		textAlt->setFont(timesFont);
+		textAlt->setPosition(position);
+		textAlt->setCharacterSize(21);
+		textAlt->setDataVariance(osg::Object::DYNAMIC); 
+
+		position += delta;
+
+		textHat = new osgText::Text;
+		hudGeode->addDrawable( textHat );
+		textHat->setFont(timesFont);
+		textHat->setPosition(position);
+		textHat->setCharacterSize(21);
+		textHat->setDataVariance(osg::Object::DYNAMIC); 
+
+		position += delta;
+
+		textHot = new osgText::Text;
+		hudGeode->addDrawable( textHot );
+		textHot->setFont(timesFont);
+		textHot->setPosition(position);
+		textHot->setCharacterSize(21);
+		textHot->setDataVariance(osg::Object::DYNAMIC); 
+
+		position += delta;
+	}
+
+	return hudGeode.get();
+}
+
+void visual_debug_hud::HudUpdateCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
+{
+	visual_debug_hud* hud = dynamic_cast<visual_debug_hud*>(node);
+	if ( !hud )
+	{
+		OSG_NOTIFY(osg::FATAL) << "ERROR : No object found. Unable to apply this callback!" << std::endl;
+		return;
+	}
+
+	// Retrieving new HUD values
+
+	double lat = 0;
+	double lon = 0;
+	double hat = 0;
+	double hot = 0;
+	double alt = 0;
+
+	util::getWGS84ofCamera( sceneCamera, csn, lat, lon, alt ); 
+	util::queryHeightAboveTerrainInWGS84(hat, csn, lat, lon, alt);
+	util::queryHeightOfTerrain(hot, csn, lat, lon);
+
+
+	// Updating Display Elements:
+	std::ostringstream valuestring;
+	
+	valuestring.str("");
+	valuestring << osg::RadiansToDegrees( lat );
+	hud->textLat->setText("LAT: "+valuestring.str());
+
+	valuestring.str("");
+	valuestring << osg::RadiansToDegrees( lon );
+	hud->textLon->setText("LON: "+valuestring.str());
+
+	valuestring << std::fixed;
+	valuestring.precision(2);
+	valuestring.fill('0');
+
+	valuestring.width(8);
+	valuestring.str("");
+	valuestring << alt;
+	hud->textAlt->setText("ALT: "+valuestring.str());
+
+
+	valuestring.width(8);
+	valuestring.str("");
+	valuestring << hat;
+	hud->textHat->setText("HAT: "+valuestring.str());
+
+	valuestring.width(8);
+	valuestring.str("");
+	valuestring << hot;
+	hud->textHot->setText("HOT: "+valuestring.str());
+}
Index: /osgVisual/src/draw2D/visual_draw2D.cpp
===================================================================
--- /osgVisual/src/draw2D/visual_draw2D.cpp	(revision 31)
+++ /osgVisual/src/draw2D/visual_draw2D.cpp	(revision 31)
@@ -0,0 +1,142 @@
+/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
+ *
+ * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under 
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
+ * You have to aquire licenses for all used proprietary modules.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#include <visual_draw2D.h>
+
+using namespace osgVisual;
+
+visual_draw2D::visual_draw2D(void)
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "visual_draw2D constructed" << std::endl;
+	initialized = false;
+}
+
+visual_draw2D::~visual_draw2D(void)
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "visual_draw2D destroyed: " << std::endl;
+}
+
+visual_draw2D* visual_draw2D::getInstance()
+{
+	static visual_draw2D instance; 
+	return &instance; 
+};
+
+bool visual_draw2D::init( osg::CoordinateSystemNode *sceneGraphRoot_, osgViewer::Viewer *viewer_ )
+{
+    screen_width = viewer_->getCamera()->getViewport()->width();
+    screen_height = viewer_->getCamera()->getViewport()->height();
+ 
+   // Projection node for defining view frustrum for the HUD:
+	draw2DProjectionMatrix = new osg::Projection;
+
+   // Initialize the projection matrix for viewing everything we
+   // will add as descendants of this node. Use screen coordinates
+   // to define the horizontal and vertical extent of the projection
+   // matrix. Positions described under this node will equate to
+   // pixel coordinates.
+   draw2DProjectionMatrix->setMatrix(osg::Matrix::ortho2D(0,screen_width,0,screen_height));
+
+   // For the HUD model view matrix use an identity matrix:
+   draw2DModelViewMatrix = new osg::MatrixTransform;
+   draw2DModelViewMatrix->setMatrix(osg::Matrix::identity());
+
+   // Make sure the model view matrix is not affected by any transforms
+   // above it in the scene graph:
+   draw2DModelViewMatrix->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
+   
+
+   // Add the HUD projection matrix as a child of the root node
+   // and the HUD model view matrix as a child of the projection matrix
+   // Anything under this node will be viewed using this projection matrix
+   // and positioned with this model view matrix.
+   draw2DProjectionMatrix->addChild(draw2DModelViewMatrix);
+   sceneGraphRoot_->addChild( draw2DProjectionMatrix );
+
+   initialized = true;
+   return true;
+}
+
+void visual_draw2D::shutdown()
+{
+	if (!initialized)
+		return;
+
+	// Remove all Drawcontens
+	removeAllDrawContents();
+
+	// Remove Projectionmatrix
+	draw2DProjectionMatrix->removeChild( draw2DModelViewMatrix );
+	draw2DProjectionMatrix = NULL;
+
+	initialized = false;
+}
+
+bool visual_draw2D::addDrawContent( osg::Geode* content_, std::string name_,int renderBinDetail_ )
+{
+	if (!initialized)
+		return false;
+
+	// Add the Geometry node to contain HUD geometry as a child of the
+    // HUD model view matrix.
+	draw2DModelViewMatrix->addChild( content_ );
+	content_->setName( name_ );
+	
+	osg::StateSet* stateSet = content_->getOrCreateStateSet();
+	stateSet->setRenderBinDetails( renderBinDetail_, "RenderBin");
+	// disable depth test to ensure that it is always drawn.
+	stateSet->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
+
+	return true;
+}
+
+osg::Geode* visual_draw2D::getDrawContent( std::string name_ )
+{
+	osg::Node* tmp = util::findNamedNode(name_, draw2DModelViewMatrix);
+	if(tmp)
+	{
+		osg::Geode* tmp2 = tmp->asGeode();
+		if (tmp2)
+			return tmp2;
+		else
+			return NULL;
+	}
+	else 
+		return NULL;
+}
+
+bool visual_draw2D::removeDrawContent( std::string name_ )
+{
+	osg::Node* tmp = util::findNamedNode(name_, draw2DModelViewMatrix);
+	if(tmp)
+	{
+		draw2DModelViewMatrix->removeChild( tmp );
+		return true;
+	}
+	else
+		return false;
+}
+	
+void visual_draw2D::removeAllDrawContents()
+{
+	if (getDrawContentNum() > 0)
+		draw2DModelViewMatrix->removeChildren(0, getDrawContentNum() );
+}
+
+int visual_draw2D::getDrawContentNum()
+{
+	return draw2DModelViewMatrix->getNumChildren();
+}
Index: /osgVisual/src/draw2D/visual_hud.cpp
===================================================================
--- /osgVisual/src/draw2D/visual_hud.cpp	(revision 31)
+++ /osgVisual/src/draw2D/visual_hud.cpp	(revision 31)
@@ -0,0 +1,106 @@
+/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
+ *
+ * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under 
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
+ * You have to aquire licenses for all used proprietary modules.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#include <visual_hud.h>
+
+using namespace osgVisual;
+
+visual_hud::visual_hud(void)
+{
+}
+
+visual_hud::~visual_hud(void)
+{
+}
+
+bool visual_hud::init( osgViewer::Viewer *viewer_ )
+{	
+    screen_width = viewer_->getCamera()->getViewport()->width();
+    screen_height = viewer_->getCamera()->getViewport()->height();
+   	
+	visual_draw2D::getInstance()->addDrawContent( addContent(), "HUD" );
+
+	return true;
+}
+
+osg::ref_ptr<osg::Geode> visual_hud::addContent()
+{
+	osg::ref_ptr<osg::Geode> hudGeode = this;
+
+	// turn lighting off
+    osg::StateSet* stateset = hudGeode->getOrCreateStateSet();
+    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
+
+    // create background
+	{
+		// configuring background shape
+		float depth = -0.1; // Paint background behind text. 
+		osg::Vec4f bgColor_rgba = osg::Vec4(1.0f,1.0,0.8f,0.2f);
+		osg::Vec3 hudCenter = osg::Vec3((float)(screen_width/2), (float)(screen_height/2), 0.0);
+		float baseSize = 200;
+		float addSize = 70;
+
+
+		osg::Geometry* hudBackground = new osg::Geometry;
+
+		osg::Vec3Array* vertices = new osg::Vec3Array;
+		vertices->push_back(hudCenter+osg::Vec3(baseSize+addSize, baseSize, depth));
+		vertices->push_back(hudCenter+osg::Vec3(baseSize, baseSize+addSize, depth));
+		vertices->push_back(hudCenter+osg::Vec3(-baseSize , baseSize+addSize, depth));
+		vertices->push_back(hudCenter+osg::Vec3(-baseSize-addSize, baseSize,depth));
+		vertices->push_back(hudCenter+osg::Vec3(-baseSize-addSize, -baseSize,depth));
+		vertices->push_back(hudCenter+osg::Vec3(-baseSize , -baseSize-addSize, depth));
+		vertices->push_back(hudCenter+osg::Vec3(baseSize, -baseSize-addSize, depth));
+		vertices->push_back(hudCenter+osg::Vec3(baseSize+addSize, -baseSize, depth));
+		hudBackground->setVertexArray(vertices);
+		
+		osg::Vec3Array* normals = new osg::Vec3Array;
+		normals->push_back(osg::Vec3(0.0f,0.0f,1.0f));
+		hudBackground->setNormalArray(normals);
+		hudBackground->setNormalBinding(osg::Geometry::BIND_OVERALL);
+		
+		osg::Vec4Array* colors = new osg::Vec4Array;
+		colors->push_back( bgColor_rgba );
+		hudBackground->setColorArray(colors);
+		hudBackground->setColorBinding(osg::Geometry::BIND_OVERALL);
+		
+		hudBackground->addPrimitiveSet(new osg::DrawArrays(GL_POLYGON,0,8));
+		
+		osg::StateSet* stateset = hudBackground->getOrCreateStateSet();
+		stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
+		stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
+
+		hudGeode->addDrawable(hudBackground);    
+	}
+    
+	// Add Text: 
+	//osg::Vec3 position(550.0f,450.0f,0.0f);
+	osg::Vec3 position(100.0f,100.0f,0.0f);
+	osg::Vec3 delta(0.0f,-120.0f,0.0f);
+	std::string timesFont("fonts/arial.ttf");
+	{
+		osgText::Text* text = new  osgText::Text;
+		hudGeode->addDrawable( text );
+
+		text->setFont(timesFont);
+		text->setPosition(position);
+		text->setText("Head Up Displays\nare simple ;-)");
+
+		position += delta;
+	}
+
+	return hudGeode.get();
+}
Index: /osgVisual/src/draw3D/visual_draw3D.cpp
===================================================================
--- /osgVisual/src/draw3D/visual_draw3D.cpp	(revision 31)
+++ /osgVisual/src/draw3D/visual_draw3D.cpp	(revision 31)
@@ -0,0 +1,78 @@
+/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
+ *
+ * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under 
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
+ * You have to aquire licenses for all used proprietary modules.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#include <visual_draw3D.h>
+
+using namespace osgVisual;
+
+visual_draw3D::visual_draw3D(void)
+{
+}
+
+visual_draw3D::~visual_draw3D(void)
+{
+}
+
+void visual_draw3D::init( osg::CoordinateSystemNode* rootNode_, osgViewer::Viewer *viewer_ )
+{
+	osg::Matrix testmatrix = viewer_->getCamera()->getViewMatrix();
+
+	testmatrix.makeTranslate( 2.0, 2.0, 2.0 );
+	//testmatrix.
+	osg::ref_ptr<osg::Geode> hudGeode = new osg::Geode();
+	rootNode_->addChild( hudGeode );
+
+
+    // create background
+	
+	// configuring background shape
+	float depth = -0.1; // Paint background behind text. 
+	osg::Vec4f bgColor_rgba = osg::Vec4(1.0f,1.0,0.8f,0.2f);
+	osg::Vec3 hudCenter = osg::Vec3(0.0, 0.0, 0.0);
+	float baseSize = 200;
+	float addSize = 70;
+
+
+	osg::Geometry* hudBackground = new osg::Geometry;
+
+	osg::Vec3Array* vertices = new osg::Vec3Array;
+	vertices->push_back(hudCenter+osg::Vec3(baseSize+addSize, baseSize, depth));
+	vertices->push_back(hudCenter+osg::Vec3(baseSize, baseSize+addSize, depth));
+	vertices->push_back(hudCenter+osg::Vec3(-baseSize , baseSize+addSize, depth));
+	vertices->push_back(hudCenter+osg::Vec3(-baseSize-addSize, baseSize,depth));
+	vertices->push_back(hudCenter+osg::Vec3(-baseSize-addSize, -baseSize,depth));
+	vertices->push_back(hudCenter+osg::Vec3(-baseSize , -baseSize-addSize, depth));
+	vertices->push_back(hudCenter+osg::Vec3(baseSize, -baseSize-addSize, depth));
+	vertices->push_back(hudCenter+osg::Vec3(baseSize+addSize, -baseSize, depth));
+	hudBackground->setVertexArray(vertices);
+	
+	osg::Vec3Array* normals = new osg::Vec3Array;
+	normals->push_back(osg::Vec3(0.0f,0.0f,1.0f));
+	hudBackground->setNormalArray(normals);
+	hudBackground->setNormalBinding(osg::Geometry::BIND_OVERALL);
+	
+	osg::Vec4Array* colors = new osg::Vec4Array;
+	colors->push_back( bgColor_rgba );
+	hudBackground->setColorArray(colors);
+	hudBackground->setColorBinding(osg::Geometry::BIND_OVERALL);
+	
+	hudBackground->addPrimitiveSet(new osg::DrawArrays(GL_POLYGON,0,8));
+	
+	osg::StateSet* stateset = hudBackground->getOrCreateStateSet();
+	stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
+	stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
+
+}
Index: /osgVisual/src/extLink/dataIO_extLinkDummy.cpp
===================================================================
--- /osgVisual/src/extLink/dataIO_extLinkDummy.cpp	(revision 31)
+++ /osgVisual/src/extLink/dataIO_extLinkDummy.cpp	(revision 31)
@@ -0,0 +1,58 @@
+/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
+ *
+ * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under 
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
+ * You have to aquire licenses for all used proprietary modules.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#include "dataIO_extLinkDummy.h"
+
+#include "memoryLeakDetection.h"
+
+dataIO_extLinkDummy::dataIO_extLinkDummy(std::vector<dataIOSlot>& dataSlots_) : dataIO_extLink(dataSlots_)
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "extLinkDummy constructed" << std::endl;
+}
+
+dataIO_extLinkDummy::~dataIO_extLinkDummy(void)
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "extLinkDummy destroyed" << std::endl;
+}
+
+void dataIO_extLinkDummy::init()
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "extLinkDummy init()" << std::endl;
+}
+
+void dataIO_extLinkDummy::shutdown()
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "extLinkDummy shutdown()" << std::endl;
+}
+
+bool dataIO_extLinkDummy::readTO_OBJvalues()
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "extLinkDummy readTO_OBJvalues()" << std::endl;
+
+	return true;
+}
+
+bool dataIO_extLinkDummy::writebackFROM_OBJvalues()
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "extLinkDummy writebackFROM_OBJvalues()" << std::endl;
+
+	return true;
+}
+
+void dataIO_extLinkDummy::provideSlots()
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "extLinkDummy provideSlots()" << std::endl;
+}
Index: /osgVisual/src/extLink/dataIO_extLinkVCL.cpp
===================================================================
--- /osgVisual/src/extLink/dataIO_extLinkVCL.cpp	(revision 31)
+++ /osgVisual/src/extLink/dataIO_extLinkVCL.cpp	(revision 31)
@@ -0,0 +1,146 @@
+/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
+ *
+ * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under 
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
+ * You have to aquire licenses for all used proprietary modules.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#include <dataIO_extLinkVCL.h>
+
+#include <visual_dataIO.h>
+
+using namespace osgVisual;
+
+dataIO_extLinkVCL::dataIO_extLinkVCL(std::vector<dataIO_slot>& dataSlots_) : dataIO_extLink(dataSlots_)
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "extLinkVCL constructed" << std::endl;
+}
+
+dataIO_extLinkVCL::~dataIO_extLinkVCL(void)
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "extLinkVCL destroyed" << std::endl;
+}
+
+void dataIO_extLinkVCL::init()
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "extLinkVCL init()" << std::endl;
+
+	std::string VCLConfigFilename = "osgVisual.xml";
+	if ( osgDB::fileExists( VCLConfigFilename ) )
+	{
+		CVCLIO::GetInstance().LoadProject(VCLConfigFilename.c_str());
+		bool error = false;
+
+		if( !SAENGER1_POS_LAT.Attach("VISENGINE_CAMERA_CHANNEL", "SAENGER1_POS_LAT") )
+			error = true;
+		if( !SAENGER1_POS_LON.Attach("VISENGINE_CAMERA_CHANNEL", "SAENGER1_POS_LON") )
+			error = true;
+		if( !SAENGER1_POS_ALT.Attach("VISENGINE_CAMERA_CHANNEL", "SAENGER1_POS_ALT") )
+			error = true;
+		if( !SAENGER1_ROT_X.Attach("VISENGINE_CAMERA_CHANNEL", "SAENGER1_ROT_X") )
+			error = true;
+		if( !SAENGER1_ROT_Y.Attach("VISENGINE_CAMERA_CHANNEL", "SAENGER1_ROT_Y") )
+			error = true;
+		if( !SAENGER1_ROT_Z.Attach("VISENGINE_CAMERA_CHANNEL", "SAENGER1_ROT_Z") )
+			error = true;
+
+		if( !SAENGER2_POS_LAT.Attach("VISENGINE_CAMERA_CHANNEL", "SAENGER2_POS_LAT") )
+			error = true;
+		if( !SAENGER2_POS_LON.Attach("VISENGINE_CAMERA_CHANNEL", "SAENGER2_POS_LON") )
+			error = true;
+		if( !SAENGER2_POS_ALT.Attach("VISENGINE_CAMERA_CHANNEL", "SAENGER2_POS_ALT") )
+			error = true;
+		if( !SAENGER2_ROT_X.Attach("VISENGINE_CAMERA_CHANNEL", "SAENGER2_ROT_X") )
+			error = true;
+		if( !SAENGER2_ROT_Y.Attach("VISENGINE_CAMERA_CHANNEL", "SAENGER2_ROT_Y") )
+			error = true;
+		if( !SAENGER2_ROT_Z.Attach("VISENGINE_CAMERA_CHANNEL", "SAENGER2_ROT_Z") )
+			error = true;
+	
+		if( !SAENGER_POS_LAT.Attach("VISENGINE_CAMERA_CHANNEL", "SAENGER_POS_LAT") )
+			error = true;
+		if( !SAENGER_POS_LON.Attach("VISENGINE_CAMERA_CHANNEL", "SAENGER_POS_LON") )
+			error = true;
+		if( !SAENGER_POS_ALT.Attach("VISENGINE_CAMERA_CHANNEL", "SAENGER_POS_ALT") )
+			error = true;
+		if( !SAENGER_ROT_X.Attach("VISENGINE_CAMERA_CHANNEL", "SAENGER_ROT_X") )
+			error = true;
+		if( !SAENGER_ROT_Y.Attach("VISENGINE_CAMERA_CHANNEL", "SAENGER_ROT_Y") )
+			error = true;
+		if( !SAENGER_ROT_Z.Attach("VISENGINE_CAMERA_CHANNEL", "SAENGER_ROT_Z") )
+			error = true;
+
+		if (error)
+			OSG_NOTIFY( osg::FATAL ) << "ERROR: An error occured while attaching VCL." << std::endl;
+		initialized = true;
+	}
+	else
+	{
+		OSG_NOTIFY( osg::FATAL ) << "ERROR: Could not find VCL Configuration file " << VCLConfigFilename << std::endl;
+		exit(-1);
+	}
+
+}
+
+void dataIO_extLinkVCL::shutdown()
+{
+	OSG_NOTIFY( osg::ALWAYS ) << "extLinkVCL shutdown()" << std::endl;
+}
+
+
+bool dataIO_extLinkVCL::readTO_OBJvalues()
+{
+	OSG_NOTIFY( osg::INFO ) << "extLinkVCL readTO_OBJvalues()" << std::endl;
+
+	// perform external data exchange
+	CVCLIO::GetInstance().DoDataExchange();
+
+	// Copy data from VCL variables to slot variables:
+	osgVisual::visual_dataIO::getInstance()->setSlotData( "SAENGER1_POS_LAT", osgVisual::dataIO_slot::TO_OBJ, SAENGER1_POS_LAT.GetValue() );
+	osgVisual::visual_dataIO::getInstance()->setSlotData( "SAENGER1_POS_LON", osgVisual::dataIO_slot::TO_OBJ, SAENGER1_POS_LON.GetValue() );
+	osgVisual::visual_dataIO::getInstance()->setSlotData( "SAENGER1_POS_ALT", osgVisual::dataIO_slot::TO_OBJ, -SAENGER1_POS_ALT.GetValue() );	// Negatives Vorzeichen da Z-Koordinaten anders herum.
+	osgVisual::visual_dataIO::getInstance()->setSlotData( "SAENGER1_ROT_X", osgVisual::dataIO_slot::TO_OBJ, SAENGER1_ROT_X.GetValue() );
+	osgVisual::visual_dataIO::getInstance()->setSlotData( "SAENGER1_ROT_Y", osgVisual::dataIO_slot::TO_OBJ, SAENGER1_ROT_Y.GetValue() );
+	osgVisual::visual_dataIO::getInstance()->setSlotData( "SAENGER1_ROT_Z", osgVisual::dataIO_slot::TO_OBJ, SAENGER1_ROT_Z.GetValue() );
+
+	osgVisual::visual_dataIO::getInstance()->setSlotData( "SAENGER2_POS_LAT", osgVisual::dataIO_slot::TO_OBJ, SAENGER2_POS_LAT.GetValue() );
+	osgVisual::visual_dataIO::getInstance()->setSlotData( "SAENGER2_POS_LON", osgVisual::dataIO_slot::TO_OBJ, SAENGER2_POS_LON.GetValue() );
+	osgVisual::visual_dataIO::getInstance()->setSlotData( "SAENGER2_POS_ALT", osgVisual::dataIO_slot::TO_OBJ, -SAENGER2_POS_ALT.GetValue() );	// Negatives Vorzeichen da Z-Koordinaten anders herum.
+	osgVisual::visual_dataIO::getInstance()->setSlotData( "SAENGER2_ROT_X", osgVisual::dataIO_slot::TO_OBJ, SAENGER2_ROT_X.GetValue() );
+	osgVisual::visual_dataIO::getInstance()->setSlotData( "SAENGER2_ROT_Y", osgVisual::dataIO_slot::TO_OBJ, SAENGER2_ROT_Y.GetValue() );
+	osgVisual::visual_dataIO::getInstance()->setSlotData( "SAENGER2_ROT_Z", osgVisual::dataIO_slot::TO_OBJ, SAENGER2_ROT_Z.GetValue() );
+
+	osgVisual::visual_dataIO::getInstance()->setSlotData( "SAENGER_POS_LAT", osgVisual::dataIO_slot::TO_OBJ, SAENGER_POS_LAT.GetValue() );
+	osgVisual::visual_dataIO::getInstance()->setSlotData( "SAENGER_POS_LON", osgVisual::dataIO_slot::TO_OBJ, SAENGER_POS_LON.GetValue() );
+	osgVisual::visual_dataIO::getInstance()->setSlotData( "SAENGER_POS_ALT", osgVisual::dataIO_slot::TO_OBJ, -SAENGER_POS_ALT.GetValue() );	// Negatives Vorzeichen da Z-Koordinaten anders herum.
+	osgVisual::visual_dataIO::getInstance()->setSlotData( "SAENGER_ROT_X", osgVisual::dataIO_slot::TO_OBJ, SAENGER_ROT_X.GetValue() );
+	osgVisual::visual_dataIO::getInstance()->setSlotData( "SAENGER_ROT_Y", osgVisual::dataIO_slot::TO_OBJ, SAENGER_ROT_Y.GetValue() );
+	osgVisual::visual_dataIO::getInstance()->setSlotData( "SAENGER_ROT_Z", osgVisual::dataIO_slot::TO_OBJ, SAENGER_ROT_Z.GetValue() );
+
+	//OSG_NOTIFY( osg::ALWAYS ) << "LAT: " << osgVisual::visual_dataIO::getInstance()->getSlotDataAsDouble("SAENGER1_POS_LAT", osgVisual::dataIO_slot::TO_OBJ ) << std::endl;
+	return true;
+}
+
+bool dataIO_extLinkVCL::writebackFROM_OBJvalues()
+{
+	OSG_NOTIFY( osg::INFO ) << "extLinkVCL writebackFROM_OBJvalues()" << std::endl;
+
+	// Copy slot data to variables
+		// Nothing to do
+		// Example: MY_CHANNEL.setValue( myValue );
+
+	/* In VCL no writeback transaction is done, 
+	it is postponed until the next frame beginning,
+	where TO_OBJ exchange calls CVCLIO::GetInstance().DoDataExchange();.
+	*/
+	return true;
+}
Index: /osgVisual/src/extLink/manip_extLink.cpp
===================================================================
--- /osgVisual/src/extLink/manip_extLink.cpp	(revision 31)
+++ /osgVisual/src/extLink/manip_extLink.cpp	(revision 31)
@@ -0,0 +1,70 @@
+/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
+ *
+ * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under 
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
+ * You have to aquire licenses for all used proprietary modules.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+*/
+#include <manip_extLink.h>
+
+
+
+using namespace osg;
+using namespace osgGA;
+using namespace osgVisual;
+
+extLinkManipulator::extLinkManipulator()
+{
+}
+
+extLinkManipulator::~extLinkManipulator()
+{
+}
+
+void extLinkManipulator::init(const GUIEventAdapter& ,GUIActionAdapter& )
+{
+}
+
+void extLinkManipulator::getUsage(osg::ApplicationUsage& usage) const
+{
+}
+
+bool extLinkManipulator::handle(const GUIEventAdapter& ea,GUIActionAdapter& us)
+{
+    switch(ea.getEventType())
+    {
+    case(GUIEventAdapter::FRAME):
+        if (attachedObject.valid())
+		{
+			setByMatrix( attachedObject->getCameraMatrix() );
+		}
+        return false;
+    default:
+        break;
+    }
+
+    return false;
+}
+
+void extLinkManipulator::setByMatrix(const osg::Matrixd& matrix)
+{
+    manipMatrix = matrix;
+}
+
+osg::Matrixd extLinkManipulator::getMatrix() const
+{
+    return manipMatrix;
+}
+
+osg::Matrixd extLinkManipulator::getInverseMatrix() const
+{
+	return osg::Matrixd::inverse(manipMatrix);
+}
Index: /osgVisual/src/manip_ObjectMounted/manip_objectMounted.cpp
===================================================================
--- /osgVisual/src/manip_ObjectMounted/manip_objectMounted.cpp	(revision 31)
+++ /osgVisual/src/manip_ObjectMounted/manip_objectMounted.cpp	(revision 31)
@@ -0,0 +1,71 @@
+/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
+ *
+ * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under 
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
+ * You have to aquire licenses for all used proprietary modules.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#include <manip_objectMounted.h>
+
+
+
+using namespace osg;
+using namespace osgGA;
+using namespace osgVisual;
+
+objectMountedManipulator::objectMountedManipulator()
+{
+}
+
+objectMountedManipulator::~objectMountedManipulator()
+{
+}
+
+void objectMountedManipulator::init(const GUIEventAdapter& ,GUIActionAdapter& )
+{
+}
+
+void objectMountedManipulator::getUsage(osg::ApplicationUsage& usage) const
+{
+}
+
+bool objectMountedManipulator::handle(const GUIEventAdapter& ea,GUIActionAdapter& us)
+{
+    switch(ea.getEventType())
+    {
+    case(GUIEventAdapter::FRAME):
+        if (attachedObject.valid())
+		{
+			setByMatrix( attachedObject->getCameraMatrix() );
+		}
+        return false;
+    default:
+        break;
+    }
+
+    return false;
+}
+
+void objectMountedManipulator::setByMatrix(const osg::Matrixd& matrix)
+{
+    manipMatrix = matrix;
+}
+
+osg::Matrixd objectMountedManipulator::getMatrix() const
+{
+    return manipMatrix;
+}
+
+osg::Matrixd objectMountedManipulator::getInverseMatrix() const
+{
+	return osg::Matrixd::inverse(manipMatrix);
+}
Index: /osgVisual/src/manip_Spacemouse/manip_freeSpaceMouse.cpp
===================================================================
--- /osgVisual/src/manip_Spacemouse/manip_freeSpaceMouse.cpp	(revision 31)
+++ /osgVisual/src/manip_Spacemouse/manip_freeSpaceMouse.cpp	(revision 31)
@@ -0,0 +1,208 @@
+/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
+ *
+ * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under 
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
+ * You have to aquire licenses for all used proprietary modules.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#include <manip_freeSpaceMouse.h>
+
+
+
+using namespace osg;
+using namespace osgGA;
+using namespace osgVisual;
+
+FreeManipulator::FreeManipulator(SpaceMouse* spacemouse) : _spaceMouse(spacemouse)
+{
+}
+
+FreeManipulator::~FreeManipulator()
+{
+}
+
+void FreeManipulator::init(const GUIEventAdapter& ,GUIActionAdapter& )
+{
+}
+
+void FreeManipulator::getUsage(osg::ApplicationUsage& usage) const
+{
+}
+
+bool FreeManipulator::handle(const GUIEventAdapter& ea,GUIActionAdapter& us)
+{
+    switch(ea.getEventType())
+    {
+    case(GUIEventAdapter::FRAME):
+        if (calcMovement())
+            us.requestRedraw();
+        return false;
+    default:
+        break;
+    }
+
+    return false;
+}
+
+void FreeManipulator::setByMatrix(const osg::Matrixd& matrix)
+{
+    _position = matrix.getTrans();
+    _attitude = matrix.getRotate();
+}
+
+osg::Matrixd FreeManipulator::getMatrix() const
+{
+    return osg::Matrixd::rotate(_attitude)*osg::Matrixd::translate(_position);
+}
+
+osg::Matrixd FreeManipulator::getInverseMatrix() const
+{
+    return osg::Matrixd::translate(-_position)*osg::Matrixd::rotate(_attitude.inverse());
+}
+
+bool FreeManipulator::calcMovement()
+{
+    double dTX, dTY, dTZ;
+    _spaceMouse->getTranslations(dTX, dTY, dTZ);
+
+    double dRX, dRY, dRZ;
+    _spaceMouse->getRotations(dRX, dRY, dRZ);
+
+    osg::Matrix rotation_matrix;
+    rotation_matrix.makeRotate(_attitude);
+
+    osg::Vec3d lookVector = -getUpVector(rotation_matrix);
+    osg::Vec3d sideVector = getSideVector(rotation_matrix);
+    osg::Vec3d upVector = getFrontVector(rotation_matrix);
+
+    lookVector.normalize();
+    sideVector.normalize();
+    upVector.normalize();
+
+    // POSITION
+    _position -= lookVector * dTZ;
+    _position += upVector   * dTY;
+    _position += sideVector * dTX;
+	//std::cout << "Translation: "<< dTX * 1000000.0<< ", " << dTY * 1000000.0<< ", " << dTZ * 1000000.0<< std::endl;
+
+    // ATTITUDE
+    _attitude *= osg::Quat( dRY, osg::Vec3(0.0, 0.0, 1.0));		//Yaw
+    _attitude *= osg::Quat( dRX, sideVector);					// Pitch
+	_attitude *= osg::Quat( -dRZ, lookVector);					// Bank
+
+
+    if (!_trackNodePath.empty())
+    {
+        osg::Vec3 trackNodeCenter = getTrackNodeCenter();
+
+        osg::Matrix matrixLookAt;
+        matrixLookAt.makeLookAt(_position, trackNodeCenter, osg::Vec3(0.0, 0.0, 1.0));
+
+        osg::Quat attitude = matrixLookAt.getRotate().inverse();
+        _attitude = attitude;
+    }
+
+    return true;
+}
+
+osg::Vec3 FreeManipulator::getTrackNodeCenter()
+{
+    osg::Matrixd localToWorld, worldToLocal;
+    computeNodeLocalToWorld(localToWorld);
+    computeNodeWorldToLocal(worldToLocal);
+
+    osg::Vec3 center(0.0, 0.0, 0.0);
+    if (validateNodePath())
+        center = osg::Vec3d(_trackNodePath.back()->getBound().center())*localToWorld;
+    else
+        center = osg::Vec3d(0.0f,0.0f,0.0f)*localToWorld;
+
+    return(center);
+}
+
+void FreeManipulator::computeNodeWorldToLocal(osg::Matrixd& worldToLocal) const
+{
+    if (validateNodePath())
+    {
+        worldToLocal = osg::computeWorldToLocal(getNodePath());
+    }
+}
+
+void FreeManipulator::computeNodeLocalToWorld(osg::Matrixd& localToWorld) const
+{
+    if (validateNodePath())
+    {
+        localToWorld = osg::computeLocalToWorld(getNodePath());
+    }
+
+}
+
+bool FreeManipulator::validateNodePath() const
+{
+    for(ObserverNodePath::const_iterator itr = _trackNodePath.begin();
+        itr != _trackNodePath.begin();
+        ++itr)
+    {
+        if (*itr==0) 
+        {
+            OSG_NOTIFY(osg::NOTICE)<<"Warning: tracked node path has been invalidated by changes in the scene graph."<<std::endl;
+            const_cast<ObserverNodePath&>(_trackNodePath).clear();
+            return false;
+        }
+    }
+    return true;
+}
+
+osg::NodePath FreeManipulator::getNodePath() const
+{
+    osg::NodePath nodePath;
+    for(ObserverNodePath::const_iterator itr = _trackNodePath.begin();
+        itr != _trackNodePath.end();
+        ++itr)
+    {
+        nodePath.push_back(const_cast<osg::Node*>(itr->get()));
+    }
+    return nodePath;
+}
+
+void FreeManipulator::setTrackNode(osg::Node* node)
+{
+    if (!node)
+    {
+        OSG_NOTIFY(osg::NOTICE)<<"NodeTrackerManipulator::setTrackNode(Node*):  Unable to set tracked node due to null Node*"<<std::endl;
+        return;
+    }
+
+    osg::NodePathList nodePaths = node->getParentalNodePaths();
+    if (!nodePaths.empty())
+    {
+        if (nodePaths.size()>1)
+        {
+            OSG_NOTIFY(osg::NOTICE)<<"osgGA::NodeTrackerManipualtor::setTrackNode(..) taking first parent path, ignoring others."<<std::endl;
+        }
+
+        OSG_NOTIFY(osg::INFO)<<"NodeTrackerManipulator::setTrackNode(Node*"<<node<<" "<<node->getName()<<"): Path set"<<std::endl;
+        _trackNodePath.clear();
+        setTrackNodePath( nodePaths.front() );
+    }
+    else
+    {
+        OSG_NOTIFY(osg::NOTICE)<<"NodeTrackerManipulator::setTrackNode(Node*): Unable to set tracked node due to empty parental path."<<std::endl;
+    }
+    
+    OSG_NOTIFY(osg::INFO)<<"setTrackNode("<<node->getName()<<")"<<std::endl;
+    for(unsigned int i=0; i<_trackNodePath.size(); ++i)
+    {
+        OSG_NOTIFY(osg::INFO)<<"  "<<_trackNodePath[i]->className()<<" '"<<_trackNodePath[i]->getName()<<"'"<<std::endl;
+    }
+
+}
Index: /osgVisual/src/manip_Spacemouse/manip_nodeTrackerSpaceMouse.cpp
===================================================================
--- /osgVisual/src/manip_Spacemouse/manip_nodeTrackerSpaceMouse.cpp	(revision 31)
+++ /osgVisual/src/manip_Spacemouse/manip_nodeTrackerSpaceMouse.cpp	(revision 31)
@@ -0,0 +1,723 @@
+/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
+ *
+ * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under 
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
+ * You have to aquire licenses for all used proprietary modules.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#include <manip_nodeTrackerSpaceMouse.h>
+
+
+
+using namespace osg;
+using namespace osgVisual;
+
+
+NodeTrackerSpaceMouse::NodeTrackerSpaceMouse(SpaceMouse* spacemouse) : _spaceMouse(spacemouse)
+{
+    _trackerMode = NODE_CENTER_AND_ROTATION; 
+    _rotationMode = TRACKBALL; 
+
+    _distance = 1.0;
+
+    _thrown = false;
+	_autohoming = false;
+	_ah_init = false;
+	_distanceDependendAV = false;
+
+	TZ=0;
+	RX=0;
+	RY=0;
+	RZ=0;
+
+}
+
+
+NodeTrackerSpaceMouse::~NodeTrackerSpaceMouse()
+{
+}
+
+void NodeTrackerSpaceMouse::setTrackNode(osg::Node* node)
+{
+    if (!node)
+    {
+        osg::notify(osg::NOTICE)<<"NodeTrackerSpaceMouse::setTrackNode(Node*):  Unable to set tracked node due to null Node*"<<std::endl;
+        return;
+    }
+
+    osg::NodePathList parentNodePaths = node->getParentalNodePaths();
+
+    if (!parentNodePaths.empty())
+    {
+        osg::notify(osg::INFO)<<"NodeTrackerSpaceMouse::setTrackNode(Node*): Path set"<<std::endl;
+        setTrackNodePath(parentNodePaths[0]);
+    }
+    else
+    {
+        osg::notify(osg::NOTICE)<<"NodeTrackerSpaceMouse::setTrackNode(Node*): Unable to set tracked node due to empty parental path."<<std::endl;
+    }
+}
+
+osg::Node* NodeTrackerSpaceMouse::getTrackNode()
+{
+    osg::NodePath nodePath;
+    if (_trackNodePath.getNodePath(nodePath)) return nodePath.back();
+    else return 0;
+}
+
+const osg::Node* NodeTrackerSpaceMouse::getTrackNode() const
+{
+    osg::NodePath nodePath;
+    if (_trackNodePath.getNodePath(nodePath)) return nodePath.back();
+    else return 0;
+}
+
+void NodeTrackerSpaceMouse::setTrackerMode(TrackerMode mode)
+{
+    _trackerMode = mode;
+}
+
+void NodeTrackerSpaceMouse::setRotationMode(RotationMode mode)
+{
+    _rotationMode = mode;
+    if (getAutoComputeHomePosition()) computeHomePosition();    
+}
+
+void NodeTrackerSpaceMouse::setNode(osg::Node* node)
+{
+    _node = node;
+    
+    if (_node.get())
+    {
+        const osg::BoundingSphere& boundingSphere=_node->getBound();
+        const float minimumDistanceScale = 0.001f;
+        _minimumDistance = osg::clampBetween(
+            float(boundingSphere._radius) * minimumDistanceScale,
+            0.00001f,1.0f);
+            
+        osg::notify(osg::INFO)<<"Setting Tracker manipulator _minimumDistance to "<<_minimumDistance<<std::endl;
+    }
+    if (getAutoComputeHomePosition()) computeHomePosition();    
+}
+
+const osg::Node* NodeTrackerSpaceMouse::getNode() const
+{
+    return _node.get();
+}
+
+
+osg::Node* NodeTrackerSpaceMouse::getNode()
+{
+    return _node.get();
+}
+
+
+void NodeTrackerSpaceMouse::home(const GUIEventAdapter& ,GUIActionAdapter& us)
+{
+    if (getAutoComputeHomePosition()) computeHomePosition();
+
+    computePosition(_homeEye, _homeCenter, _homeUp);
+    us.requestRedraw();
+}
+
+void NodeTrackerSpaceMouse::computeHomePosition()
+{
+    osg::NodePath nodePath;
+    _trackNodePath.getNodePath(nodePath);
+
+    osg::Node* node = nodePath.empty() ? getNode() : nodePath.back();
+    
+    if(node)
+    {
+        const osg::BoundingSphere& boundingSphere=node->getBound();
+
+        setHomePosition(boundingSphere._center+osg::Vec3( 0.0,-3.5f * boundingSphere._radius,0.0f),
+                        boundingSphere._center,
+                        osg::Vec3(0.0f,0.0f,1.0f),
+                        _autoComputeHomePosition);
+    }
+}
+
+
+
+void NodeTrackerSpaceMouse::init(const GUIEventAdapter& ,GUIActionAdapter& )
+{
+    flushMouseEventStack();
+}
+
+
+void NodeTrackerSpaceMouse::getUsage(osg::ApplicationUsage& usage) const
+{
+    usage.addKeyboardMouseBinding("SN Tracker: Space","Toggle camera auto homing");
+	usage.addKeyboardMouseBinding("SN Tracker: m","Toggle Nodetracker Mode");
+	usage.addKeyboardMouseBinding("SN Tracker: n","Toggle distance dependend angular velocity");
+    usage.addKeyboardMouseBinding("SN Tracker: +","When in stereo, increase the fusion distance");
+    usage.addKeyboardMouseBinding("SN Tracker: -","When in stereo, reduce the fusion distance");
+}
+
+bool NodeTrackerSpaceMouse::handle(const GUIEventAdapter& ea,GUIActionAdapter& us)
+{
+    switch(ea.getEventType())
+    {
+        case(GUIEventAdapter::PUSH):
+        {
+            flushMouseEventStack();
+            addMouseEvent(ea);
+            if (calcMovement()) us.requestRedraw();
+            us.requestContinuousUpdate(false);
+            _thrown = false;
+            return true;
+        }
+
+        case(GUIEventAdapter::RELEASE):
+        {
+            if (ea.getButtonMask()==0)
+            {
+
+                double timeSinceLastRecordEvent = _ga_t0.valid() ? (ea.getTime() - _ga_t0->getTime()) : DBL_MAX;
+                if (timeSinceLastRecordEvent>0.02) flushMouseEventStack();
+
+                if (isMouseMoving())
+                {
+                    if (calcMovement())
+                    {
+                        us.requestRedraw();
+                        us.requestContinuousUpdate(true);
+                        _thrown = true;
+                    }
+                }
+                else
+                {
+                    flushMouseEventStack();
+                    addMouseEvent(ea);
+                    if (calcMovement()) us.requestRedraw();
+                    us.requestContinuousUpdate(false);
+                    _thrown = false;
+                }
+
+            }
+            else
+            {
+                flushMouseEventStack();
+                addMouseEvent(ea);
+                if (calcMovement()) us.requestRedraw();
+                us.requestContinuousUpdate(false);
+                _thrown = false;
+            }
+            return true;
+        }
+
+        case(GUIEventAdapter::DRAG):
+        {
+            addMouseEvent(ea);
+            if (calcMovement()) us.requestRedraw();
+            us.requestContinuousUpdate(false);
+            _thrown = false;
+            return true;
+        }
+
+        case(GUIEventAdapter::MOVE):
+        {
+            return false;
+        }
+
+        case(GUIEventAdapter::KEYDOWN):
+            if (ea.getKey()==' ')
+            {
+				if (_autohoming)
+					_autohoming=false;
+				else
+					_autohoming=true;
+                return true;
+            }
+			if (ea.getKey()=='m')
+            {
+				switch(_trackerMode)
+				{
+					case NODE_CENTER: _trackerMode=NODE_CENTER_AND_AZIM;
+						break;
+					case NODE_CENTER_AND_AZIM: _trackerMode=NODE_CENTER_AND_ROTATION;
+						break;
+					case  NODE_CENTER_AND_ROTATION: _trackerMode=NODE_CENTER;
+						break;
+					default: _trackerMode = NODE_CENTER;
+						break;
+				};
+                return true;
+            }
+			if (ea.getKey()=='n')
+            {
+				if (_distanceDependendAV)
+					_distanceDependendAV=false;
+				else
+					_distanceDependendAV=true;
+                return true;
+            }
+            return false;
+        case(GUIEventAdapter::FRAME):
+            if (_thrown)
+            {
+                if (calcMovement()) us.requestRedraw();
+            }
+
+			computeHomePosition();
+			computePosition(_homeEye, _homeCenter, _homeUp);
+			if (calcMovementSpaceMouse())
+				us.requestRedraw();
+
+            return false;
+        default:
+            return false;
+    }
+}
+
+
+bool NodeTrackerSpaceMouse::isMouseMoving()
+{
+    if (_ga_t0.get()==NULL || _ga_t1.get()==NULL) return false;
+
+    static const float velocity = 0.1f;
+
+    float dx = _ga_t0->getXnormalized()-_ga_t1->getXnormalized();
+    float dy = _ga_t0->getYnormalized()-_ga_t1->getYnormalized();
+    float len = sqrtf(dx*dx+dy*dy);
+    float dt = _ga_t0->getTime()-_ga_t1->getTime();
+
+    return (len>dt*velocity);
+}
+
+
+void NodeTrackerSpaceMouse::flushMouseEventStack()
+{
+    _ga_t1 = NULL;
+    _ga_t0 = NULL;
+}
+
+
+void NodeTrackerSpaceMouse::addMouseEvent(const GUIEventAdapter& ea)
+{
+    _ga_t1 = _ga_t0;
+    _ga_t0 = &ea;
+}
+
+void NodeTrackerSpaceMouse::setByMatrix(const osg::Matrixd& matrix)
+{
+    osg::Vec3d eye,center,up;
+    matrix.getLookAt(eye,center,up,_distance);
+    computePosition(eye,center,up);
+}
+
+void NodeTrackerSpaceMouse::computeNodeCenterAndRotation(osg::Vec3d& nodeCenter, osg::Quat& nodeRotation) const
+{
+    osg::Matrixd localToWorld, worldToLocal;
+    osg::NodePath nodePath;
+    if (_trackNodePath.getNodePath(nodePath))
+    {
+        worldToLocal = osg::computeWorldToLocal(nodePath);
+        localToWorld = osg::computeLocalToWorld(nodePath);
+        nodeCenter = osg::Vec3d(nodePath.back()->getBound().center())*localToWorld;
+    }
+    else
+    {
+        nodeCenter = osg::Vec3d(0.0f,0.0f,0.0f)*localToWorld;
+    }
+
+
+    switch(_trackerMode)
+    {
+        case(NODE_CENTER_AND_AZIM):
+        {
+            CoordinateFrame coordinateFrame = getCoordinateFrame(nodeCenter);
+            osg::Matrixd localToFrame(localToWorld*osg::Matrixd::inverse(coordinateFrame));
+
+            double azim = atan2(-localToFrame(0,1),localToFrame(0,0));
+            osg::Quat nodeRotationRelToFrame, rotationOfFrame;
+            nodeRotationRelToFrame.makeRotate(-azim,0.0,0.0,1.0);
+            rotationOfFrame = coordinateFrame.getRotate();
+            nodeRotation = nodeRotationRelToFrame*rotationOfFrame;
+            break;
+        }
+        case(NODE_CENTER_AND_ROTATION):
+        {
+            // scale the matrix to get rid of any scales before we extract the rotation.
+            double sx = 1.0/sqrt(localToWorld(0,0)*localToWorld(0,0) + localToWorld(1,0)*localToWorld(1,0) + localToWorld(2,0)*localToWorld(2,0));
+            double sy = 1.0/sqrt(localToWorld(0,1)*localToWorld(0,1) + localToWorld(1,1)*localToWorld(1,1) + localToWorld(2,1)*localToWorld(2,1));
+            double sz = 1.0/sqrt(localToWorld(0,2)*localToWorld(0,2) + localToWorld(1,2)*localToWorld(1,2) + localToWorld(2,2)*localToWorld(2,2));
+            localToWorld = localToWorld*osg::Matrixd::scale(sx,sy,sz);
+
+            nodeRotation = localToWorld.getRotate();
+            break;
+        }
+        case(NODE_CENTER):
+        default:
+        {
+            CoordinateFrame coordinateFrame = getCoordinateFrame(nodeCenter);
+            nodeRotation = coordinateFrame.getRotate();
+            break;
+        }
+    }
+
+}
+
+
+osg::Matrixd NodeTrackerSpaceMouse::getMatrix() const
+{
+    osg::Vec3d nodeCenter;
+    osg::Quat nodeRotation;
+    computeNodeCenterAndRotation(nodeCenter,nodeRotation);
+    return osg::Matrixd::translate(0.0,0.0,_distance)*osg::Matrixd::rotate(_rotation)*osg::Matrixd::rotate(nodeRotation)*osg::Matrix::translate(nodeCenter);
+}
+
+osg::Matrixd NodeTrackerSpaceMouse::getInverseMatrix() const
+{
+    osg::Vec3d nodeCenter;
+    osg::Quat nodeRotation;
+    computeNodeCenterAndRotation(nodeCenter,nodeRotation);
+    return osg::Matrixd::translate(-nodeCenter)*osg::Matrixd::rotate(nodeRotation.inverse())*osg::Matrixd::rotate(_rotation.inverse())*osg::Matrixd::translate(0.0,0.0,-_distance);
+}
+
+void NodeTrackerSpaceMouse::computePosition(const osg::Vec3d& eye,const osg::Vec3d& center,const osg::Vec3d& up)
+{
+    if (!_node) return;
+
+    // compute rotation matrix
+    osg::Vec3 lv(center-eye);
+    _distance = lv.length();
+    
+    osg::Matrixd lookat;
+    lookat.makeLookAt(eye,center,up);
+    
+    _rotation = lookat.getRotate().inverse();
+}
+
+bool NodeTrackerSpaceMouse::calcMovement()
+{
+    // return if less then two events have been added.
+    if (_ga_t0.get()==NULL || _ga_t1.get()==NULL) return false;
+
+    double dx = _ga_t0->getXnormalized()-_ga_t1->getXnormalized();
+    double dy = _ga_t0->getYnormalized()-_ga_t1->getYnormalized();
+
+
+    float distance = sqrtf(dx*dx + dy*dy);
+    // return if movement is too fast, indicating an error in event values or change in screen.
+    if (distance>0.5)
+    {
+        return false;
+    }
+    
+    // return if there is no movement.
+    if (distance==0.0f)
+    {
+        return false;
+    }
+
+    osg::Vec3d nodeCenter;
+    osg::Quat nodeRotation;
+    computeNodeCenterAndRotation(nodeCenter, nodeRotation);
+
+    unsigned int buttonMask = _ga_t1->getButtonMask();
+
+    if (buttonMask==GUIEventAdapter::LEFT_MOUSE_BUTTON)
+    {
+
+        if (_rotationMode==TRACKBALL)
+        {
+
+            // rotate camera.
+            osg::Vec3 axis;
+            double angle;
+
+            double px0 = _ga_t0->getXnormalized();
+            double py0 = _ga_t0->getYnormalized();
+
+            double px1 = _ga_t1->getXnormalized();
+            double py1 = _ga_t1->getYnormalized();
+
+
+            trackball(axis,angle,px1,py1,px0,py0);
+
+            osg::Quat new_rotate;
+            new_rotate.makeRotate(angle,axis);
+
+            _rotation = _rotation*new_rotate;
+        }
+        else
+        {
+            osg::Matrix rotation_matrix;
+            rotation_matrix.makeRotate(_rotation);
+
+            osg::Vec3d lookVector = -getUpVector(rotation_matrix);
+            osg::Vec3d sideVector = getSideVector(rotation_matrix);
+            osg::Vec3d upVector = getFrontVector(rotation_matrix);
+            
+            osg::Vec3d localUp(0.0f,0.0f,1.0f);
+
+            osg::Vec3d forwardVector = localUp^sideVector;
+            sideVector = forwardVector^localUp;
+
+            forwardVector.normalize();
+            sideVector.normalize();
+            
+            osg::Quat rotate_elevation;
+            rotate_elevation.makeRotate(dy,sideVector);
+
+            osg::Quat rotate_azim;
+            rotate_azim.makeRotate(-dx,localUp);
+            
+            _rotation = _rotation * rotate_elevation * rotate_azim;
+            
+        }
+        
+        return true;
+
+    }
+    else if (buttonMask==GUIEventAdapter::MIDDLE_MOUSE_BUTTON ||
+        buttonMask==(GUIEventAdapter::LEFT_MOUSE_BUTTON|GUIEventAdapter::RIGHT_MOUSE_BUTTON))
+    {
+        return true;
+    }
+    else if (buttonMask==GUIEventAdapter::RIGHT_MOUSE_BUTTON)
+    {
+
+        // zoom model.
+
+        double fd = _distance;
+        double scale = 1.0f+dy;
+        if (fd*scale>_minimumDistance)
+        {
+
+            _distance *= scale;
+
+        } else
+        {
+            _distance = _minimumDistance;
+        }
+        
+        return true;
+
+    }
+
+    return false;
+}
+
+bool NodeTrackerSpaceMouse::calcMovementSpaceMouse()
+{
+	// TRACKBALL mode is not possible, because it uses the mouseevent, which does not happen with Spacemouse.
+
+   double dTX, dTY, dTZ;	// Only TZ is used later.
+    _spaceMouse->getTranslations(dTX, dTY, dTZ);
+
+    double dRX, dRY, dRZ;
+    _spaceMouse->getRotations(dRX, dRY, dRZ);
+
+	//OSG_NOTIFY( osg::INFO ) << "Recieved Spacemousevalues: dRX:" << dRX << ", dRY:" << dRY << ", dRZ:" << dRZ << ", dTX:" << dTX << std::endl;
+
+	if(!_ah_init)
+	{
+		TZ=dTZ;
+		RX=dRX;
+		RY=dRY;
+		RZ=dRZ;
+		_ah_init=true;
+	}
+
+	if (_autohoming)	// The factors are required to allow macroscopic movements.
+	{
+		TZ=dTZ*5;
+		if (!_distanceDependendAV)
+		{
+			RX=dRX*100;
+			RY=dRY*100;
+			RZ=dRZ*100;
+		}
+	}
+	else		// NOT Autohoming
+	{
+		TZ+=dTZ;
+		//OSG_NOTIFY( osg::INFO ) << "Stored Spacemousevalues: RX:" << RX << ", RY:" << RY << ", RZ:" << RZ << ", TX:" << TX << std::endl;
+		if (_distanceDependendAV)
+		{
+			RX+=(dRX*800/TZ);
+			RY+=(dRY*800/TZ);
+			RZ+=(dRZ*800/TZ);
+		}
+		else
+		{
+			RX+=dRX;
+			RY+=dRY;
+			RZ+=dRZ;
+		}
+	}
+
+    osg::Vec3d nodeCenter;
+    osg::Quat nodeRotation;
+    computeNodeCenterAndRotation(nodeCenter, nodeRotation);
+
+    // ROTATION PART
+    if (_rotationMode==TRACKBALL)
+    {
+		// return if less then two events have been added.
+		if (_ga_t0.get()==NULL || _ga_t1.get()==NULL) return false;
+
+        // rotate camera.
+        osg::Vec3 axis;
+        double angle;
+
+        double px0 = _ga_t0->getXnormalized();
+        double py0 = _ga_t0->getYnormalized();
+
+        double px1 = _ga_t1->getXnormalized();
+        double py1 = _ga_t1->getYnormalized();
+
+
+        trackball(axis,angle,px1,py1,px0,py0);
+
+        osg::Quat new_rotate;
+        new_rotate.makeRotate(angle,axis);
+
+        _rotation = _rotation*new_rotate;
+    }
+    else
+    {
+        osg::Matrix rotation_matrix;
+        rotation_matrix.makeRotate(_rotation);
+
+        osg::Vec3d lookVector = -getUpVector(rotation_matrix);
+        osg::Vec3d sideVector = getSideVector(rotation_matrix);
+        osg::Vec3d upVector = getFrontVector(rotation_matrix);
+        
+        osg::Vec3d localUp(0.0f,0.0f,1.0f);
+
+        osg::Vec3d forwardVector = localUp^sideVector;
+        sideVector = forwardVector^localUp;
+
+        forwardVector.normalize();
+        sideVector.normalize();
+        
+        osg::Quat rotate_elevation;
+		rotate_elevation.makeRotate(osg::DegreesToRadians(RX*90), sideVector);
+
+        osg::Quat rotate_azim;
+		rotate_azim.makeRotate(osg::DegreesToRadians(RY*90), localUp);
+        
+        _rotation = _rotation * rotate_elevation * rotate_azim;
+        
+    }
+
+    // TRANSLATION PART
+    double scale = 1.0f+TZ/100;
+	if (_distance*scale>_minimumDistance)
+    {
+
+        _distance *= scale;
+
+    } else
+    {
+		TZ = (_minimumDistance/_distance - 1)*100;	// Reset TZ to the value f(_minimalDistance, _distance, scale-function). 
+        _distance = _minimumDistance;
+    }
+    return true;
+}
+
+void NodeTrackerSpaceMouse::clampOrientation()
+{
+}
+
+
+/*
+ * This size should really be based on the distance from the center of
+ * rotation to the point on the object underneath the mouse.  That
+ * point would then track the mouse as closely as possible.  This is a
+ * simple example, though, so that is left as an Exercise for the
+ * Programmer.
+ */
+const float TRACKBALLSIZE = 0.8f;
+
+/*
+ * Ok, simulate a track-ball.  Project the points onto the virtual
+ * trackball, then figure out the axis of rotation, which is the cross
+ * product of P1 P2 and O P1 (O is the center of the ball, 0,0,0)
+ * Note:  This is a deformed trackball-- is a trackball in the center,
+ * but is deformed into a hyperbolic sheet of rotation away from the
+ * center.  This particular function was chosen after trying out
+ * several variations.
+ *
+ * It is assumed that the arguments to this routine are in the range
+ * (-1.0 ... 1.0)
+ */
+void NodeTrackerSpaceMouse::trackball(osg::Vec3& axis,double & angle, double  p1x, double  p1y, double  p2x, double  p2y)
+{
+    /*
+     * First, figure out z-coordinates for projection of P1 and P2 to
+     * deformed sphere
+     */
+
+    osg::Matrix rotation_matrix(_rotation);
+
+
+    osg::Vec3d uv = osg::Vec3d(0.0,1.0,0.0)*rotation_matrix;
+    osg::Vec3d sv = osg::Vec3d(1.0,0.0,0.0)*rotation_matrix;
+    osg::Vec3d lv = osg::Vec3d(0.0,0.0,-1.0)*rotation_matrix;
+
+    osg::Vec3d p1 = sv*p1x+uv*p1y-lv*tb_project_to_sphere(TRACKBALLSIZE,p1x,p1y);
+    osg::Vec3d p2 = sv*p2x+uv*p2y-lv*tb_project_to_sphere(TRACKBALLSIZE,p2x,p2y);
+
+    /*
+     *  Now, we want the cross product of P1 and P2
+     */
+
+// Robert,
+//
+// This was the quick 'n' dirty  fix to get the trackball doing the right 
+// thing after fixing the Quat rotations to be right-handed.  You may want
+// to do something more elegant.
+//   axis = p1^p2;
+axis = p2^p1;
+    axis.normalize();
+
+    /*
+     *  Figure out how much to rotate around that axis.
+     */
+    double t = (p2-p1).length() / (2.0*TRACKBALLSIZE);
+
+    /*
+     * Avoid problems with out-of-control values...
+     */
+    if (t > 1.0) t = 1.0;
+    if (t < -1.0) t = -1.0;
+    angle = inRadians(asin(t));
+
+}
+
+
+/*
+ * Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet
+ * if we are away from the center of the sphere.
+ */
+double NodeTrackerSpaceMouse::tb_project_to_sphere(double  r, double  x, double  y)
+{
+    float d, t, z;
+
+    d = sqrt(x*x + y*y);
+                                 /* Inside sphere */
+    if (d < r * 0.70710678118654752440)
+    {
+        z = sqrt(r*r - d*d);
+    }                            /* On hyperbola */
+    else
+    {
+        t = r / 1.41421356237309504880;
+        z = t*t / d;
+    }
+    return z;
+}
Index: /osgVisual/src/manip_Spacemouse/manip_spaceMouse.cpp
===================================================================
--- /osgVisual/src/manip_Spacemouse/manip_spaceMouse.cpp	(revision 31)
+++ /osgVisual/src/manip_Spacemouse/manip_spaceMouse.cpp	(revision 31)
@@ -0,0 +1,202 @@
+/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
+ *
+ * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under 
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
+ * You have to aquire licenses for all used proprietary modules.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#include <manip_spaceMouse.h>
+
+#define _ATL_APARTMENT_THREADED
+#define _ATL_NO_AUTOMATIC_NAMESPACE
+
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS	// some CString constructors will be explicit
+
+#define _WIN32_DCOM
+
+#include <objbase.h>
+#include <atlbase.h>
+#include <atlcom.h>
+#include <atlwin.h>
+#include <atltypes.h>
+#include <atlctl.h>
+#include <atlhost.h>
+
+
+
+using namespace ATL;
+using namespace osgVisual;
+
+
+#import "progid:TDxInput.Device" no_namespace
+
+class SpaceMouse::SpaceMouseImpl
+{
+public:
+    enum SupportedStatus
+    {
+        DETECTION_PENDING,
+        SUPPORTED,
+        NOT_SUPPORTED
+    };
+
+    SpaceMouseImpl() : _supported(DETECTION_PENDING)
+    {
+    }
+
+    SupportedStatus isSupported() const
+    {
+        return(_supported);
+    }
+
+    int initialize()
+    {
+        HRESULT hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
+
+        // Create the device object
+        hr = _3DxDevice.CoCreateInstance(__uuidof(Device));
+        if (SUCCEEDED(hr))
+        {
+            CComPtr<ISimpleDevice> _3DxSimpleDevice;
+
+            hr = _3DxDevice.QueryInterface(&_3DxSimpleDevice);
+            if (SUCCEEDED(hr))
+            {
+                // Get the interfaces to the sensor and the keyboard;
+                _3DSensor   = _3DxSimpleDevice->Sensor;
+                _3DKeyboard = _3DxSimpleDevice->Keyboard;
+
+                // Associate a configuration with this device
+                hr = _3DxSimpleDevice->LoadPreferences(_T("RBAnimation"));
+                // Connect to the driver
+                hr = _3DxSimpleDevice->Connect();
+
+                _supported = SUPPORTED;
+
+                return(1); //Base::SUCCESS
+            }
+        }
+
+        _supported = NOT_SUPPORTED;
+
+        return(0);	//Base::FAILURE
+    }
+
+    void shutdown()
+    {
+        if (_3DSensor)
+            _3DSensor.Release();
+
+        if (_3DKeyboard)
+            _3DKeyboard.Release();
+
+        if (_3DxDevice)
+        {
+            _3DxDevice->Disconnect();
+            _3DxDevice.Release();
+        }
+    }
+
+
+    int getTranslations(double& dTX, double& dTY, double& dTZ)
+    {
+        try {
+            CComPtr<IVector3D> pTranslation = _3DSensor->Translation;
+
+            double dTransFactor = pTranslation->Length;
+            dTransFactor /= 5.0;
+
+            dTX = pTranslation->X * dTransFactor;
+            dTY = pTranslation->Y * dTransFactor;
+            dTZ = pTranslation->Z * dTransFactor;
+
+            pTranslation.Release();
+        }
+        catch (...)
+        {
+            return 0;	//Base::FAILURE
+        }
+
+        return 1;	//Base::SUCCESS
+    }
+
+    int getRotations(double& dRX, double& dRY, double& dRZ)
+    {
+        try {
+            CComPtr<IAngleAxis> pRotation = _3DSensor->Rotation;
+
+            double dRotAngle = pRotation->Angle;
+            dRotAngle /= 4000.0;
+
+            dRX = pRotation->X * dRotAngle;
+            dRY = pRotation->Y * dRotAngle;
+            dRZ = pRotation->Z * dRotAngle;
+
+            pRotation.Release();
+        }
+        catch (...)
+        {
+            return 0;	//Base::FAILURE
+        }
+
+        return 1;	//Base::SUCCESS
+    }
+
+private:
+    SupportedStatus _supported;
+
+    CComPtr<ISimpleDevice> _3DxDevice;
+    CComPtr<ISensor>       _3DSensor;
+    CComPtr<IKeyboard>     _3DKeyboard;
+};
+
+
+
+
+
+
+
+
+SpaceMouse::SpaceMouse() : _spaceMouseImpl(new SpaceMouseImpl)
+{
+}
+
+SpaceMouse::~SpaceMouse()
+{
+    delete _spaceMouseImpl;
+}
+
+int SpaceMouse::initialize()
+{
+    return(_spaceMouseImpl->initialize());
+}
+
+void SpaceMouse::shutdown()
+{
+    _spaceMouseImpl->shutdown();
+}
+
+int SpaceMouse::getTranslations(double& dX, double& dY, double& dZ)
+{
+    dX = 0;
+    dY = 0;
+    dZ = 0;
+    return(_spaceMouseImpl->getTranslations(dX, dY, dZ));
+}
+
+int SpaceMouse::getRotations(double& dX, double& dY, double& dZ)
+{
+    dX = 0;
+    dY = 0;
+    dZ = 0;
+    return(_spaceMouseImpl->getRotations(dX, dY, dZ));
+}
Index: /osgVisual/src/object/object_updater.cpp
===================================================================
--- /osgVisual/src/object/object_updater.cpp	(revision 31)
+++ /osgVisual/src/object/object_updater.cpp	(revision 31)
@@ -0,0 +1,70 @@
+/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
+ *
+ * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under 
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
+ * You have to aquire licenses for all used proprietary modules.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#include <object_updater.h>
+
+using namespace osgVisual;
+
+object_updater::object_updater(osgVisual::visual_object* object_ )
+{
+}
+
+object_updater::~object_updater(void)
+{
+}
+
+void object_updater::preUpdate(osgVisual::visual_object* object_ )
+{
+	OSG_NOTIFY( osg::INFO ) << "preUpdate visual Object " << object_->getName() << std::endl;
+	// perform this preUpdater...
+	//For each visual_object.member,
+	//	try to search according variable in dataIO with direction TO_OBJ and copy value to visual_object.
+
+	
+	object_->lat = osg::DegreesToRadians(osgVisual::visual_dataIO::getInstance()->getSlotDataAsDouble(object_->getName()+"_POS_LAT", osgVisual::dataIO_slot::TO_OBJ ));
+	object_->lon = osg::DegreesToRadians(osgVisual::visual_dataIO::getInstance()->getSlotDataAsDouble(object_->getName()+"_POS_LON", osgVisual::dataIO_slot::TO_OBJ ));
+	object_->alt = osgVisual::visual_dataIO::getInstance()->getSlotDataAsDouble(object_->getName()+"_POS_ALT", osgVisual::dataIO_slot::TO_OBJ );
+	object_->azimuthAngle_psi = osg::DegreesToRadians(osgVisual::visual_dataIO::getInstance()->getSlotDataAsDouble(object_->getName()+"_ROT_Z", osgVisual::dataIO_slot::TO_OBJ ));
+	object_->pitchAngle_theta = osg::DegreesToRadians(osgVisual::visual_dataIO::getInstance()->getSlotDataAsDouble(object_->getName()+"_ROT_Y", osgVisual::dataIO_slot::TO_OBJ ));
+	object_->bankAngle_phi = osg::DegreesToRadians(osgVisual::visual_dataIO::getInstance()->getSlotDataAsDouble(object_->getName()+"_ROT_X", osgVisual::dataIO_slot::TO_OBJ ));
+
+	//object_->setCameraOffsetTranslation(0.0, -150.0, 50.0);	// Trans: (rechts davon, longitudinal, vertikal)
+	object_->setCameraOffsetTranslation( 150.0, 0.0, 30.0);
+	object_->setCameraOffsetRotation( osg::DegreesToRadians(0.0), osg::DegreesToRadians(-15.0), osg::DegreesToRadians(-90.0) );
+	
+
+
+	// Finally execute nested PreUpdater
+	if ( updater.valid() )
+		updater->preUpdate(object_);
+}
+
+void object_updater::postUpdate(osgVisual::visual_object* object_ )
+{
+	OSG_NOTIFY( osg::INFO ) << "postUpdate visual Object " << object_->getName() << std::endl;
+
+	// Finally execute nested PostUpdater
+	if ( updater.valid() )
+		updater->postUpdate(object_);
+}
+
+void object_updater::addUpdater( object_updater* updater_ )
+{
+	if (updater.valid())
+		updater->addUpdater( updater_ );
+	else
+		updater = updater_;
+}
Index: /osgVisual/src/object/visual_object.cpp
===================================================================
--- /osgVisual/src/object/visual_object.cpp	(revision 31)
+++ /osgVisual/src/object/visual_object.cpp	(revision 31)
@@ -0,0 +1,409 @@
+/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
+ *
+ * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under 
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
+ * You have to aquire licenses for all used proprietary modules.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#include <visual_object.h>
+
+using namespace osgVisual;
+
+visual_object::visual_object( osg::CoordinateSystemNode* sceneRoot_, std::string nodeName_)
+{
+	// Add this node to Scenegraph
+	sceneRoot_->addChild( this );
+
+	// Set Nodename for further identification
+	this->setName( nodeName_ );
+
+	// Set callback.
+	/** \todo: welcher update ist der richtige? voraussichtlich event.) */
+	//this->setUpdateCallback( new visual_objectPositionCallback() );
+	this->setEventCallback( new visual_objectPositionCallback() );
+
+	// Init Position and Attitude
+	lat = 0;
+	lon = 0;
+	alt = 0;
+
+	azimuthAngle_psi = 0;
+	pitchAngle_theta = 0;
+	bankAngle_phi = 0;
+
+	geometry_offset_rotation.makeRotate( 0.0, 1.0, 1.0, 1.0 );
+
+	// Init Scale
+	scaleX = 1.0;
+	scaleY = 1.0;
+	scaleZ = 1.0;
+
+	// Init cameraOffset 
+	cameraTranslationOffset.makeTranslate( osg::Vec3d(0.0, 0.0, 0.0) );	// Trans: (y, x, -z_down)
+	cameraRotationOffset.makeRotate( osg::DegreesToRadians( 90.0 ), osg::Vec3(1, 0, 0) );	// Rot: (-y, +x , -z)
+
+	// Geometrynode hinzufügen
+	geometry = new osg::Group();
+	this->addChild( geometry );
+
+	// Labelnode hinzufügen
+	labels = new osg::Geode();
+	this->addChild( labels ); 
+}
+
+visual_object::~visual_object()
+{
+
+}
+
+void visual_object::setNewPositionAttitude( double lat_, double lon_, double alt_, double azimuthAngle_psi_, double pitchAngle_theta_, double bankAngle_phi_ )
+{
+	lat = lat_;
+	lon = lon_;
+	alt = alt_;
+
+	azimuthAngle_psi = azimuthAngle_psi_;
+	pitchAngle_theta = pitchAngle_theta_;
+	bankAngle_phi = bankAngle_phi_;
+}
+
+void visual_object::setNewPosition( double lat_, double lon_, double alt_ )
+{
+	lat = lat_;
+	lon = lon_;
+	alt = alt_;
+}
+
+void visual_object::setNewAttitude( double azimuthAngle_psi_, double pitchAngle_theta_, double bankAngle_phi_ )
+{
+	azimuthAngle_psi = azimuthAngle_psi_;
+	pitchAngle_theta = pitchAngle_theta_;
+	bankAngle_phi = bankAngle_phi_;
+}
+
+void visual_object::setGeometryOffset( double rotX_, double rotY_, double rotZ_ )
+{
+	geometry_offset_rotation.makeRotate( rotX_, osg::Vec3f(1.0, 0.0, 0.0), 
+						rotY_, osg::Vec3f(0.0, 1.0, 0.0),
+						rotZ_, osg::Vec3f(0.0, 0.0, 1.0) );
+}
+
+void visual_object::setScale( double scale_ )
+{
+	scaleX = scale_;
+	scaleY = scale_;
+	scaleZ = scale_;
+}
+
+void visual_object::setScale( double scaleX_, double scaleY_, double scaleZ_ )
+{
+	scaleX = scaleX_;
+	scaleY = scaleY_;
+	scaleZ = scaleZ_;
+}
+
+bool visual_object::loadGeometry(std::string filename_)
+{
+	// Check if file exists
+	if( !osgDB::fileExists(filename_) )
+	{
+		OSG_NOTIFY(osg::FATAL) << "Error: Model not loaded. File '" << filename_ << "' does not exist." << std::endl;
+	}
+
+	osg::ref_ptr<osg::Node> tmpModel = osgDB::readNodeFile( filename_ );
+	
+	if( tmpModel.valid() )
+	{
+		// remove old geometry
+		geometry->removeChildren(0, geometry->getNumChildren());
+
+		// add new geometry
+		geometry->addChild( tmpModel.get() );
+		return true;
+	}
+	else
+	{
+		std::cout <<": No model loaded: " << filename_ << std::endl;
+        return false;
+    }
+}
+
+bool visual_object::setGeometry(osg::Node* geometry_)
+{
+	// remove old geometry
+	geometry->removeChildren(0, geometry->getNumChildren());
+
+	// add new geometry
+	geometry->addChild( geometry_ );
+
+	return true;
+}
+
+void visual_object::unsetGeometry()
+{
+	// remove old geometry
+	geometry->removeChildren(0, geometry->getNumChildren());
+}
+
+void visual_object::addUpdater( object_updater* updater_ )
+{
+	if ( updater.valid() )
+		updater->addUpdater( updater_ );
+	else
+		updater = updater_;
+}
+
+void visual_object::clearAllUpdater()
+{
+	// release only first updater. Because smartpointer: Will be deleted if not referenced.
+	if ( updater.valid() )
+		updater = NULL;
+}
+
+std::vector<object_updater*> visual_object::getUpdaterList()
+{
+	// iterate through updater and add all pointer.
+	std::vector<object_updater*> updaterList;
+	osg::ref_ptr<object_updater> tmpUpdater = updater;
+
+	while (tmpUpdater.valid())
+	{
+		updaterList.push_back( tmpUpdater );
+		tmpUpdater = tmpUpdater->getPointer();
+	}
+
+	// return list
+	return updaterList;
+}
+
+void visual_object::visual_objectPositionCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
+{
+	visual_object* object = dynamic_cast<visual_object*>(node);
+	if ( !object )
+	{
+		OSG_NOTIFY(osg::FATAL) << "ERROR : No object found. Unable to apply this callback!" << std::endl;
+		return;
+	}
+
+	// execute preUpdater to get new data of this object.
+	if ( object->updater.valid() )
+		object->updater->preUpdate(object);
+    
+	// Nodepath from this node to absolute parent (if no endnode specified)
+	osg::NodePath nodePath = nv->getNodePath();
+
+	// If Nodepath != empty, then mt = last element of node path
+	osg::MatrixTransform* mt = nodePath.empty() ? 0 : dynamic_cast<osg::MatrixTransform*>(nodePath.back());
+	if (mt)
+	{
+		osg::CoordinateSystemNode* csn = 0;
+
+		// find coordinate system node from our parental chain: traverse chain and try to convert every node to a csn.
+		unsigned int i;
+		for(i=0; i<nodePath.size() && csn==0; ++i)	// "&& csn" means: exit loop if csn found
+		{
+			csn = dynamic_cast<osg::CoordinateSystemNode*>(nodePath[i]);	// dynamic_cast returns 0 if dynamic_cast fails.
+		}
+        
+		// Wenn csn gefunden:
+		if (csn)
+		{
+			// Ellipsoidmodel erfragen
+			osg::EllipsoidModel* ellipsoid = csn->getEllipsoidModel();
+			if (ellipsoid)
+			{
+				osg::Matrix inheritedMatrix;
+
+				// durch den _restlichen_ Nodepath durchgehen und alle anfallenden Transformationen durchführen.
+				for(i+=1; i<nodePath.size()-1; ++i)
+				{
+					osg::Transform* transform = nodePath[i]->asTransform();	// Versuchen, den Node zu einer Transformation zu konvertieren
+                    
+					// wenn Node wirklich Trafo, dann die Tranformationsmatrix von Nodekoordinaten nach Global auf inheritedMatrix draufschlagen.
+					if (transform) transform->computeLocalToWorldMatrix(inheritedMatrix, nv);
+				}
+                
+				osg::Matrixd matrix(inheritedMatrix);
+
+				// Set position
+				ellipsoid->computeLocalToWorldTransformFromLatLongHeight(object->lat, object->lon, object->alt, matrix);
+
+				// Set Upvector for position
+				double X,Y,Z;
+				util::calculateXYZAtWGS84Coordinate(object->lat, object->lon, object->alt, csn, X, Y, Z );
+				object->upVector = ellipsoid->computeLocalUpVector(X,Y,Z);
+
+				// Set scale
+				osg::Matrixd scaleMatrix;
+				scaleMatrix.makeScale( object->scaleX, object->scaleY, object->scaleZ );
+				matrix.preMult( scaleMatrix );
+
+				// Set rotation
+				// rotation von links ranmultiplizieren, entspricht: matrix = rotation * matrix. Da rotation ein Quat ist, wäre die direkte Multiplikation nur über Umwege machbar.
+				// Rotate Object to Attitude.
+				osg::Matrixd rotationMatrix;
+				// Move Model by Azimuth
+				rotationMatrix.makeRotate( -object->azimuthAngle_psi, osg::Vec3d(0.0, 0.0, 1.0) );
+				matrix.preMult(rotationMatrix);	
+				// Move Model by Pitch
+				rotationMatrix.makeRotate( object->pitchAngle_theta, osg::Vec3d(1.0, 0.0, 0.0) );
+				matrix.preMult(rotationMatrix);
+				// Move Model by Bank
+				rotationMatrix.makeRotate( object->bankAngle_phi, osg::Vec3d(0.0, 1.0, 0.0) );
+				matrix.preMult(rotationMatrix);
+
+				// Also update camera matrix (without geometry offset, because camera is interested in the objects matrix, not in the model's matrix.)
+				object->cameraMatrix = matrix;
+				/** \todo : Clean up camera matrix management: try to solve it with a single matrix. (each frame two matrix mults less) */
+				// dont know, why this rotation is necessary - maybe manipulator and node MatrixTransform interpret a matrix in different way?
+				object->cameraMatrix.preMult( object->cameraTranslationOffset );
+				object->cameraMatrix.preMult( object->cameraRotationOffset );
+							
+
+				// Set geometry correction
+				matrix.preMultRotate( object->geometry_offset_rotation );
+
+				// Set matrix as cumulated object matrix
+				mt->setMatrix(matrix);
+			}
+		}        
+	}
+      
+	// Call any nested callbacks.
+	traverse(node,nv);
+
+	// If SLAVE: execute postUpdater to pass new data of this object to dataIO.
+	if( visual_dataIO::getInstance()->isSlave() )
+	{
+		if ( object->updater.valid() )
+			object->updater->postUpdate(object);
+	}
+
+}   // Callbackfunction [ Operater() ] END
+
+void visual_object::setCameraOffsetTranslation( double x_, double y_, double z_)
+{
+	cameraTranslationOffset.makeTranslate( osg::Vec3d(x_, y_, z_) );	// Trans: (rechts davon, longitudinal, vertikal)
+}
+
+void visual_object::setCameraOffset(double x_, double y_, double z_, double rotX_, double rotY_, double rotZ_)
+{
+	setCameraOffsetTranslation( x_, y_, z_);
+	setCameraOffsetRotation( rotX_, rotY_, rotZ_);
+}
+
+void visual_object::setCameraOffsetRotation(double rotX_, double rotY_, double rotZ_)
+{
+	osg::Matrix tmp;
+	cameraRotationOffset.makeRotate( osg::DegreesToRadians( 90.0 ), osg::Vec3(1, 0, 0) );
+	tmp.makeRotate( -rotZ_, osg::Vec3d(0.0, 1.0, 0.0) );
+	cameraRotationOffset.preMult(tmp);
+	tmp.makeRotate( rotY_, osg::Vec3d(1.0, 0.0, 0.0) );	
+	cameraRotationOffset.preMult(tmp);
+	tmp.makeRotate( -rotX_, osg::Vec3d(0.0, 0.0, 1.0) );	
+	cameraRotationOffset.preMult(tmp);
+}
+
+void visual_object::clearLabels()
+{
+	labels->removeDrawables(0, labels->getNumDrawables());
+}
+
+void visual_object::addLabel(std::string idString_, std::string label_, osg::Vec4 color_, osg::Vec3 offset_)
+{
+	osg::ref_ptr<osgText::Text> text = new osgText::Text();
+
+	text->setName(idString_);
+	text->setText(label_);
+	text->setColor(color_);
+	text->setFont("fonts/arial.ttf");
+	text->setCharacterSizeMode(osgText::Text::OBJECT_COORDS_WITH_MAXIMUM_SCREEN_SIZE_CAPPED_BY_FONT_HEIGHT);
+	text->setAutoRotateToScreen(true);
+	text->setPosition(offset_);
+
+	text->getOrCreateStateSet()->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
+	labels->addDrawable( text );
+}
+
+bool visual_object::removeLabel(std::string idString_)
+{
+	osg::Node* labelToRemove = util::findNamedNode(idString_, this);
+
+	if(labelToRemove)
+	{
+		removeChild( labelToRemove );
+		return true;
+	}
+	else
+		return false;
+}
+
+bool visual_object::updateLabelText(std::string idString_, std::string label_)
+{
+	osg::Node* labelToUpdate = util::findNamedNode(idString_, this);
+
+	if(labelToUpdate)
+	{
+		osgText::Text* text = dynamic_cast<osgText::Text*>(labelToUpdate);
+		if(text)
+		{
+			text->setText(label_);
+			return true;
+		}
+		return false;
+	}
+	return false;
+}
+
+osgText::Text* visual_object::getLabel(std::string idString_)
+{
+	osg::Node* labelToFind = util::findNamedNode(idString_, this);
+
+	if(labelToFind)
+	{
+		osgText::Text* text = dynamic_cast<osgText::Text*>(labelToFind);
+		if(text)
+			return text;
+	}
+	return NULL;
+
+}
+
+bool visual_object::setDrawLabelAsOverlay(std::string idString_, bool drawAsOverlay)
+{
+	osg::Node* labelToFind = util::findNamedNode(idString_, this);
+
+	if(labelToFind)
+	{
+		if (drawAsOverlay)
+			labelToFind->getOrCreateStateSet()->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
+		else
+			labelToFind->getOrCreateStateSet()->setMode(GL_DEPTH_TEST,osg::StateAttribute::ON);
+		return true;
+	}
+	else 
+		return false;
+}
+
+bool visual_object::getDrawLabelAsOverlay(std::string idString_)
+{
+	osg::Node* labelToFind = util::findNamedNode(idString_, this);
+
+	if(labelToFind)
+	{
+		if(labelToFind->getOrCreateStateSet()->getMode(GL_DEPTH_TEST) == osg::StateAttribute::OFF)
+			return false;
+		else 
+			return true;
+	}
+	return false;
+}
Index: /osgVisual/src/sky_Silverlining/skySilverLining_cloudsDrawable.cpp
===================================================================
--- /osgVisual/src/sky_Silverlining/skySilverLining_cloudsDrawable.cpp	(revision 31)
+++ /osgVisual/src/sky_Silverlining/skySilverLining_cloudsDrawable.cpp	(revision 31)
@@ -0,0 +1,63 @@
+/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
+ *
+ * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under 
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
+ * You have to aquire licenses for all used proprietary modules.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+ * 
+ * This file is based on the OSG example of the Silverlining SDK:
+ * Copyright (c) 2008 Sundog Software, LLC. All rights reserved worldwide.
+*/
+
+#include <skySilverLining_cloudsDrawable.h>
+#include <SilverLining.h>
+#include <skySilverLining_AtmosphereReference.h>
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <assert.h>
+
+
+using namespace osgVisual;
+using namespace SilverLining;
+
+skySilverLining_cloudsDrawable::skySilverLining_cloudsDrawable()
+        : osg::Drawable()
+{
+    setDataVariance(osg::Object::DYNAMIC);
+    setUseVertexBufferObjects(false);
+    setUseDisplayList(false);
+}
+
+skySilverLining_cloudsDrawable::skySilverLining_cloudsDrawable(osgViewer::Viewer* view)
+        : osg::Drawable()
+        , _view(view)
+{
+    setDataVariance(osg::Object::DYNAMIC);
+    setUseVertexBufferObjects(false);
+    setUseDisplayList(false);
+}
+
+void skySilverLining_cloudsDrawable::drawImplementation(osg::RenderInfo& renderInfo) const
+{
+	osgVisual::skySilverLining_atmosphereReference *ar = dynamic_cast<osgVisual::skySilverLining_atmosphereReference *>(renderInfo.getCurrentCamera()->getUserData());
+	SilverLining::Atmosphere *atmosphere = 0;
+	if (ar) atmosphere = ar->atmosphere;
+
+	renderInfo.getState()->disableAllVertexArrays();
+
+    if (atmosphere)
+    {
+        atmosphere->EndFrame(true);
+    }
+
+	renderInfo.getState()->dirtyAllVertexArrays();
+}
Index: /osgVisual/src/sky_Silverlining/skySilverLining_skyDrawable.cpp
===================================================================
--- /osgVisual/src/sky_Silverlining/skySilverLining_skyDrawable.cpp	(revision 31)
+++ /osgVisual/src/sky_Silverlining/skySilverLining_skyDrawable.cpp	(revision 31)
@@ -0,0 +1,279 @@
+/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
+ *
+ * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under 
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
+ * You have to aquire licenses for all used proprietary modules.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+ * 
+ * This file is based on the OSG example of the Silverlining SDK:
+ * Copyright (c) 2008 Sundog Software, LLC. All rights reserved worldwide.
+*/
+
+#include <skySilverLining_skyDrawable.h>
+#include <SilverLining.h>
+#include <skySilverLining_AtmosphereReference.h>
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <assert.h>
+
+
+
+using namespace SilverLining;
+using namespace osgVisual;
+
+skySilverLining_skyDrawable::skySilverLining_skyDrawable()
+        : osg::Drawable()
+		, _view(0)
+		, _skyboxSize(0)
+{
+    setDataVariance(osg::Object::DYNAMIC);
+    setUseVertexBufferObjects(false);
+    setUseDisplayList(false);
+	cloudLayerSlots.clear();
+	newCloudLayersToAdd = false;
+}
+
+skySilverLining_skyDrawable::skySilverLining_skyDrawable(osgViewer::Viewer* view)
+        : osg::Drawable()
+        , _view(view)
+		, _skyboxSize(0)
+{
+    setDataVariance(osg::Object::DYNAMIC);
+    setUseVertexBufferObjects(false);
+    setUseDisplayList(false);
+	cloudLayerSlots.clear();
+	newCloudLayersToAdd = false;
+}
+
+void skySilverLining_skyDrawable::setLighting(SilverLining::Atmosphere *atmosphere) const
+{
+    osg::Light *light = _view->getLight();
+    osg::Vec4 ambient, diffuse;
+    osg::Vec3 direction;
+
+    if (atmosphere && light)
+    {
+        float ra, ga, ba, rd, gd, bd, x, y, z;
+        atmosphere->GetAmbientColor(&ra, &ga, &ba);
+        atmosphere->GetSunOrMoonColor(&rd, &gd, &bd);
+        atmosphere->GetSunOrMoonPosition(&x, &y, &z);
+
+        direction = osg::Vec3(x, y, z);
+        ambient = osg::Vec4(ra, ga, ba, 1.0);
+        diffuse = osg::Vec4(rd, gd, bd, 1.0);
+
+        // xform the light direction into camera coordinates
+        osg::Quat view = _view->getCamera()->getViewMatrix().getRotate();
+        //direction = view * direction;
+        direction.normalize();
+
+        light->setAmbient(ambient);
+        light->setDiffuse(diffuse);
+        light->setSpecular(osg::Vec4(0,0,0,1));
+        light->setPosition(osg::Vec4(direction.x(), direction.y(), direction.z(), 0));
+    }
+}
+
+void skySilverLining_skyDrawable::setSceneFog(SilverLining::Atmosphere *atmosphere) const
+{    
+	glEnable(GL_FOG);
+    glFogi(GL_FOG_MODE, GL_EXP);
+
+	//float hazeR, hazeG, hazeB;
+	//double hazeDepth, hazeDensity;
+	//atmosphere->GetHaze(hazeR, hazeG, hazeB, hazeDepth, hazeDensity);
+
+    //hazeDensity = 1.0 / 40000;
+	//hazeDensity = 0;
+	float hazeDensity = 1.0 / atmosphere->GetConditions()->GetVisibility();
+
+    // Decrease fog density with altitude, to avoid fog effects through the vacuum of space.
+    static const double H = 8435.0; // Pressure scale height of Earth's atmosphere
+    double isothermalEffect = exp(-(atmosphere->GetConditions()->GetLocation().GetAltitude() / H));     
+    if (isothermalEffect <= 0) isothermalEffect = 1E-9;
+    if (isothermalEffect > 1.0) isothermalEffect = 1.0;
+    hazeDensity *= isothermalEffect;
+
+    bool silverLiningHandledTheFog = false;
+
+    if (atmosphere->GetFogEnabled())
+    {
+            float density, r, g, b;
+            // Note, the fog color returned is already lit
+            atmosphere->GetFogSettings(&density, &r, &g, &b);
+
+            if (density > hazeDensity)
+            {
+                    glFogf(GL_FOG_DENSITY, density);
+
+                    GLfloat fogColor[4] = {r, g, b, 1.0};
+                    glFogfv(GL_FOG_COLOR, fogColor);
+
+                    silverLiningHandledTheFog = true;
+            }
+    }
+    
+    if (!silverLiningHandledTheFog)
+    {
+            GLfloat fogColor[4];
+            //atmosphere->GetHorizonColor(yaw, &fogColor[0], &fogColor[1], &fogColor[2]);	// New version of this call: SL_1.94 /** \todo transmit the yaw value of the center channel to all slaves for consistent fog color. */
+			atmosphere->GetHorizonColor( 0, &fogColor[0], &fogColor[1], &fogColor[2]);
+            glFogfv(GL_FOG_COLOR, fogColor);
+
+            glFogf(GL_FOG_DENSITY, hazeDensity);
+    }
+
+
+ //   _fog = new osg::Fog;
+	//_objectsNode  = erde oder object, das mit nebel bedacht werden soll	
+	//_objectsNode->getOrCreateStateSet()->setAttributeAndModes(_fog.get());
+
+	//fog->setMode(osg::Fog::EXP);
+
+ //   float hazeDensity = 0;//1.0 / 10000.0; //0.000075f
+ //   bool silverLiningHandledTheFog = false;
+
+ //   if (atmosphere->GetFogEnabled())
+ //   {
+ //       float density, r, g, b;
+ //       atmosphere->GetFogSettings(&density, &r, &g, &b);
+
+ //       if (density > hazeDensity)
+ //       {
+ //           fog->setDensity(density);
+ //           fog->setColor(osg::Vec4(r, g, b, 1.0));
+
+ //           silverLiningHandledTheFog = true;
+ //       }
+ //   }
+
+ //   if (!silverLiningHandledTheFog)
+ //   {
+ //       float r, g, b;
+ //       atmosphere->GetHorizonColor(0, &r, &g, &b);
+
+ //       fog->setDensity(hazeDensity);
+ //       fog->setColor(osg::Vec4(r, g, b, 1.0));
+ //   }
+}
+
+void skySilverLining_skyDrawable::initializeSilverLining(skySilverLining_atmosphereReference *ar)
+{
+    if (ar && !ar->atmosphereInitialized)
+    {
+        ar->atmosphereInitialized = true; // only try once.
+		SilverLining::Atmosphere *atmosphere = ar->atmosphere;
+
+		if (atmosphere)
+        {
+			srand(1234); // constant random seed to ensure consistent clouds across windows
+
+            // Update the path below to where you installed SilverLining's resources folder.
+            //int ret = atmosphere->Initialize(SilverLining::Atmosphere::OPENGL, "C:\\Program Files\\SilverLining SDK\\resources\\", true, 0);
+			int ret = atmosphere->Initialize(SilverLining::Atmosphere::OPENGL, "../resources/sky_silverlining/", true, 0);
+            if (ret != SilverLining::Atmosphere::E_NOERROR)
+            {
+                printf("SilverLining failed to initialize; error code %d.\n", ret);
+                printf("Check that the path to the SilverLining installation directory is set properly ");
+                printf("in skySilverLining_skyDrawable.cpp (in SkyDrawable::initializeSilverLining)\n");
+                exit(0);
+            }
+
+            // Let SilverLining know which way is up. OSG usually has Z going up.
+            //atmosphere->SetUpVector(0, 0, 1);
+            //atmosphere->SetRightVector(1, 0, 0);
+			atmosphere->SetUpVector(0.662994, 0.136169, 0.736136);
+			atmosphere->SetRightVector(-0.201185, 0.979553, 0.0);
+
+            // Set our location (change this to your own latitude and longitude)
+            SilverLining::Location loc;
+            loc.SetAltitude(0);
+            loc.SetLatitude(47);
+            loc.SetLongitude(11);
+            atmosphere->GetConditions()->SetLocation(loc);
+
+            // Set the sstem time in PST
+            SilverLining::LocalTime t;
+            t.SetFromSystemTime();
+			t.SetTimeZone(CET);
+            atmosphere->GetConditions()->SetTime(t);
+
+			// Setting Up Visibility
+			atmosphere->GetConditions()->SetVisibility(40000);
+
+			// Setting Up Haze
+			atmosphere->GetConditions()->SetTurbidity(2.2);
+
+			atmosphere->GetConditions()->EnableTimePassage( true, 5000 );
+			
+		}	// if atmosphere ENDE
+
+    }	// If atmosphere not initialized ENDE
+}
+
+void skySilverLining_skyDrawable::drawImplementation(osg::RenderInfo& renderInfo) const
+{
+	skySilverLining_atmosphereReference *ar = dynamic_cast<skySilverLining_atmosphereReference *>(renderInfo.getCurrentCamera()->getUserData());
+	SilverLining::Atmosphere *atmosphere = 0;
+
+	if (ar) atmosphere = ar->atmosphere;
+
+	renderInfo.getState()->disableAllVertexArrays();
+
+    if (atmosphere)
+    {
+        initializeSilverLining(ar);
+		const_cast<skySilverLining_skyDrawable*>(this)->seedAndAddCloudLayers(atmosphere);
+
+
+        atmosphere->BeginFrame(true, true, _skyboxSize);
+        setLighting(atmosphere);
+		setSceneFog(atmosphere);
+    }
+
+	renderInfo.getState()->dirtyAllVertexArrays();
+}
+
+void skySilverLining_skyDrawable::addCloudLayer(cloudLayerSlot *cloudLayerSlot_)
+{
+	OpenThreads::ScopedLock<OpenThreads::Mutex> sLock(cloudLayersToAddMutex); 
+	cloudLayerSlots.push_back( cloudLayerSlot_ );
+	newCloudLayersToAdd = true;
+}
+
+
+
+void skySilverLining_skyDrawable::seedAndAddCloudLayers(SilverLining::Atmosphere *atmosphere)
+{
+	// Only try to add if anything to do..
+	if ( newCloudLayersToAdd )
+	{
+		OpenThreads::ScopedLock<OpenThreads::Mutex> sLock(cloudLayersToAddMutex); 
+		for ( unsigned int i=0; cloudLayerSlots.size() > 0; i++)
+		{
+			// Seed cloudLayer
+			cloudLayerSlots.back()->cloudLayerPointer->SeedClouds(*atmosphere);
+
+			//cloudLayerSlots.back()->cloudLayerPointer->SetEnabled( false );	// Todo: testing, please remove
+			//cloudLayerSlots.back()->cloudLayerPointer->SetEnabled( true, 30000);	// Todo: testing, please remove
+
+			// add cloudLayer to atmosphere
+			cloudLayerSlots.back()->cloudLayerHandle = atmosphere->GetConditions()->AddCloudLayer( cloudLayerSlots.back()->cloudLayerPointer );
+
+			// Delete this cloudLayer from the ToDo list.
+			cloudLayerSlots.pop_back();
+		}
+
+		// Note nothing to do.
+		newCloudLayersToAdd = false;
+	}
+}
Index: /osgVisual/src/sky_Silverlining/visual_skySilverLining.cpp
===================================================================
--- /osgVisual/src/sky_Silverlining/visual_skySilverLining.cpp	(revision 31)
+++ /osgVisual/src/sky_Silverlining/visual_skySilverLining.cpp	(revision 31)
@@ -0,0 +1,841 @@
+/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
+ *
+ * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under 
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
+ * You have to aquire licenses for all used proprietary modules.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#include <visual_skySilverLining.h>
+
+using namespace osgVisual;
+
+visual_skySilverLining::visual_skySilverLining(osgViewer::Viewer* viewer_)
+{
+	atmosphereInitialized = false;
+	postInitialized = false;
+	atmosphere = NULL;
+	viewer = viewer_;
+	for( int i=0; i<MAX_CLOUDLAYER_SLOTS; i++ )
+	{
+		cloudLayerSlots.push_back( cloudLayerSlot() );
+		cloudLayerSlots.back().slot_id = i;
+	}
+}
+
+visual_skySilverLining::~visual_skySilverLining(void)
+{
+	this->removeUpdateCallback( updateCallback );
+	if ( atmosphere != NULL )
+		delete atmosphere;
+}
+
+void visual_skySilverLining::skyUpdateCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
+{
+	// Check if atmosphere is initialized.
+	if (!sky->isInitialized())
+		return;
+
+	// on first time: perform Post-Init.
+	sky->postInit();
+
+	// Update sky
+	double lat, lon, height, x, y, z;
+	util::getXYZofCamera( sceneCamera, x, y, z);
+	util::getWGS84ofCamera( sceneCamera, csn, lat, lon, height );
+	//std::cout << "lat: " << osg::RadiansToDegrees(lat) << ", lon: " << osg::RadiansToDegrees(lon) << ", height: " << height << std::endl;
+	sky->setLocation( lat, lon, height );
+}
+
+void visual_skySilverLining::setDateTime( int year_, int month_, int day_, int hour_, int minute_, int second_, bool daylightSaving_, double timezoneOffset_ )
+{
+	// Check if atmosphere is initialized.
+	if (!isInitialized())
+		return;
+
+	SilverLining::LocalTime t = atmosphere->GetConditions()->GetTime();
+	t.SetYear( year_ );
+	t.SetMonth( month_ );
+	t.SetDay( day_ );
+	t.SetHour( hour_ );
+	t.SetMinutes( minute_ );
+	t.SetSeconds( second_ );
+	t.SetObservingDaylightSavingsTime( daylightSaving_ );
+	t.SetTimeZone( timezoneOffset_ );
+}
+
+void visual_skySilverLining::setTime( int hour_, int minute_, int second_ )
+{
+	// Check if atmosphere is initialized.
+	if (!isInitialized())
+		return;
+	
+	SilverLining::LocalTime t = atmosphere->GetConditions()->GetTime();
+	t.SetHour( hour_ );
+	t.SetMinutes( minute_ );
+	t.SetSeconds( second_ );
+	atmosphere->GetConditions()->SetTime( t );
+}
+
+void visual_skySilverLining::setDate( int year_, int month_, int day_ )
+{
+	// Check if atmosphere is initialized.
+	if (!isInitialized())
+		return;
+
+	SilverLining::LocalTime t = atmosphere->GetConditions()->GetTime();
+	t.SetYear( year_ );
+	t.SetMonth( month_ );
+	t.SetDay( day_ );
+}
+
+void visual_skySilverLining::setDateByEpoch( int secondsSince1970_ )
+{
+	// Check if atmosphere is initialized.
+	if (!isInitialized())
+		return;
+	
+	SilverLining::LocalTime t = atmosphere->GetConditions()->GetTime();
+	t.SetFromEpochSeconds( secondsSince1970_ );
+}
+
+void visual_skySilverLining::setLocation(double lat_, double lon_, double alt_)
+{
+	// Check if atmosphere is initialized.
+	if (!isInitialized())
+		return;
+
+	lat = lat_;
+	lon = lon_;
+	height = alt_;
+	
+	SilverLining::Location loc = atmosphere->GetConditions()->GetLocation();
+	loc.SetAltitude(alt_);
+	loc.SetLatitude(lat_);
+	loc.SetLongitude(lon_);		
+	atmosphere->GetConditions()->SetLocation( loc );
+
+	updateUpVector();
+}
+
+
+bool visual_skySilverLining::isInitialized()
+{
+	// Check if atmosphere is initialized. If not: make a deep lookup. If initialized, perform. Otherwise return
+	if (!atmosphereInitialized)
+	{
+		skySilverLining_atmosphereReference *ar = dynamic_cast<skySilverLining_atmosphereReference *>(viewer->getCamera()->getUserData());
+		if (ar != NULL )
+		{
+			if (ar->atmosphereInitialized)
+				atmosphereInitialized = true;
+		}
+	}
+	return(atmosphereInitialized);
+}
+
+void visual_skySilverLining::init(osg::Group *distortedRoot, osg::CoordinateSystemNode *sceneGraphRoot)
+{
+	sceneRoot = sceneGraphRoot;
+
+	// Use projection matrix callback oder fixed Cullsettings?
+	bool useProjMatrixCallback = true;
+
+	// add Sky to SceneGraphRoot
+	sceneGraphRoot->addChild( this );
+
+	// Deactivate culling for the sky node (required by the silverlining sky framework)
+	this->setCullingActive(false);
+
+	// Instantiate an Atmosphere and associate it with this camera. If you have multiple cameras
+	// in multiple contexts, be sure to instantiate seperate Atmosphere objects for each.
+    // ***IMPORTANT!**** Check that the path to the resources folder for SilverLining in SkyDrawable.cpp
+    // SkyDrawable::initializeSilverLining matches with where you installed SilverLining.
+	atmosphere = new SilverLining::Atmosphere(SILVERLINING_LICENSEE, SILVERLINING_LICENSE);
+
+    // Add the sky (calls Atmosphere::BeginFrame and handles initialization once you're in
+    // the rendering thread)
+	skyDrawable = new skySilverLining_skyDrawable(viewer);
+
+	osg::Camera *mainCamera = viewer->getCamera();
+	if (!useProjMatrixCallback)
+	{
+		mainCamera->setClearMask(0);
+		mainCamera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
+		double fovy, aspect, zNear, zFar;
+		mainCamera->getProjectionMatrixAsPerspective(fovy, aspect, zNear, zFar);
+		mainCamera->setProjectionMatrixAsPerspective(fovy, aspect, 2, 125000);
+	}
+
+    int rootKids = distortedRoot->getNumChildren();
+    for (int i = 0; i < rootKids; i++)
+    {
+        osg::Node *n = distortedRoot->getChild(i);
+        osg::Camera *cam = dynamic_cast<osg::Camera*>(n);
+        if (cam)
+        {
+            if (cam->getRenderOrder() == osg::Camera::PRE_RENDER)
+            {
+                cam->setClearMask(0);
+
+                osg::ref_ptr<skySilverLining_atmosphereReference> ar = new skySilverLining_atmosphereReference;
+				ar->atmosphere = atmosphere;
+                cam->setUserData(ar);
+				mainCamera->setUserData(ar);
+				sceneCamera = cam;
+
+				if (useProjMatrixCallback)
+				{
+					skySilverLining_projectionMatrixCallback *cb = new skySilverLining_projectionMatrixCallback( atmosphere, viewer->getCamera(), sceneRoot);
+					cam->setClampProjectionMatrixCallback(cb);
+					cb->setSkyDrawable(skyDrawable);
+				}
+            }
+        }
+    }
+
+	// Create and install updateCallback (for position etc.)
+	updateCallback = new skyUpdateCallback( sceneGraphRoot, sceneCamera, this );
+	this->setUpdateCallback( updateCallback );
+
+    // Use a RenderBin to enforce that the sky gets drawn first, then the scene, then the clouds
+	skyDrawable->getOrCreateStateSet()->setRenderBinDetails(-1, "RenderBin");
+
+    // Add the models
+    sceneGraphRoot->getOrCreateStateSet()->setRenderBinDetails(1, "RenderBin");
+
+    // Add the clouds (note, you need this even if you don't want clouds - it calls
+    // Atmosphere::EndFrame() )
+	cloudsDrawable = new skySilverLining_cloudsDrawable(viewer);
+	cloudsDrawable->getOrCreateStateSet()->setRenderBinDetails(99, "RenderBin");
+
+	// Add drawable to this geode to get rendered
+	this->addDrawable(skyDrawable);
+	this->addDrawable(cloudsDrawable);
+}
+
+void visual_skySilverLining::init(osg::CoordinateSystemNode *sceneGraphRoot)
+{
+	sceneRoot = sceneGraphRoot;
+
+	// Use projection matrix callback oder fixed Cullsettings?
+	bool useProjMatrixCallback = true;
+
+	// add Sky to SceneRoot
+	sceneGraphRoot->addChild( this );
+
+	// Deactivate culling for the sky node (required by the silverlining sky framework)
+	this->setCullingActive(false);
+
+	// Instantiate an Atmosphere and associate it with this camera. If you have multiple cameras
+	// in multiple contexts, be sure to instantiate seperate Atmosphere objects for each.
+    // ***IMPORTANT!**** Check that the path to the resources folder for SilverLining in SkyDrawable.cpp
+    // SkyDrawable::initializeSilverLining matches with where you installed SilverLining.
+	atmosphere = new SilverLining::Atmosphere(SILVERLINING_LICENSEE, SILVERLINING_LICENSE);
+	
+    // Add the sky (calls Atmosphere::BeginFrame and handles initialization once you're in
+    // the rendering thread)
+	skyDrawable = new skySilverLining_skyDrawable(viewer);
+ 
+	if (!useProjMatrixCallback)
+	{
+		viewer->getCamera()->setClearMask(0);
+		viewer->getCamera()->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
+		double fovy, aspect, zNear, zFar;
+		viewer->getCamera()->getProjectionMatrixAsPerspective(fovy, aspect, zNear, zFar);
+		viewer->getCamera()->setProjectionMatrixAsPerspective(fovy, aspect, 2, 125000);
+	}
+	else
+	{
+		cb = new skySilverLining_projectionMatrixCallback( atmosphere, viewer->getCamera(), sceneRoot);
+		viewer->getCamera()->setClampProjectionMatrixCallback(cb);
+		cb->setSkyDrawable(skyDrawable);
+	}
+
+
+    viewer->getCamera()->setClearMask(0);
+
+    osg::ref_ptr<skySilverLining_atmosphereReference> ar = new skySilverLining_atmosphereReference;
+	ar->atmosphere = atmosphere;
+    viewer->getCamera()->setUserData(ar);
+	sceneCamera = viewer->getCamera();
+
+	
+	// Create and install updateCallback (for position etc.)
+	updateCallback = new skyUpdateCallback( sceneGraphRoot, sceneCamera, this );
+	this->setUpdateCallback( updateCallback );
+
+    // Use a RenderBin to enforce that the sky gets drawn first, then the scene, then the clouds
+	skyDrawable->getOrCreateStateSet()->setRenderBinDetails(-1, "RenderBin");
+
+    // Add the models
+    sceneGraphRoot->getOrCreateStateSet()->setRenderBinDetails(1, "RenderBin");
+
+    // Add the clouds (note, you need this even if you don't want clouds - it calls
+    // Atmosphere::EndFrame() )
+	cloudsDrawable = new skySilverLining_cloudsDrawable(viewer);
+	cloudsDrawable->getOrCreateStateSet()->setRenderBinDetails(99, "RenderBin");
+
+	// Add drawable to this geode to get rendered
+	this->addDrawable(skyDrawable);
+	this->addDrawable(cloudsDrawable);
+}
+
+void visual_skySilverLining::postInit()
+{
+	// Only allow one execution
+	if(postInitialized)
+		return;
+	else postInitialized = true;
+
+	// Execute Updatecallback once before adding Clouds.
+	updateCallback->operator ()(this, NULL);
+
+	setTime(16,00,23);
+	setVisibility(50000);
+
+	//Todo: secure memory-manager of timer*. oder remove paragraph
+	//MyMillisecondTimer *timer = new MyMillisecondTimer();
+ //   atmosphere->GetConditions()->SetMillisecondTimer(timer);
+	//atmosphere->GetConditions()->EnableTimePassage(true, -1);
+
+	//addWindVolume( 0.0, 15000.0, 300.0, 90.0 );
+	
+	//addCloudLayer( 0, 300000, 300000, 600.0, 2351.0, 0.5, NIMBOSTRATUS );
+	//addCloudLayer( 0, 5000000, 5000000, 600.0, 7351.0, 0.2, CIRRUS_FIBRATUS );
+	addCloudLayer( 1, 8000, 10000, 3000, 2000.0, 0.01, CUMULONIMBUS_CAPPILATUS );
+	//addCloudLayer( 1, 25000, 25000, 3000, 2000.0, 0.05, CUMULUS_CONGESTUS );
+	//addCloudLayer( 1, 500000, 500000, 15000, 2000.0, 0.6, STRATUS );
+	//cloudLayerSlots[1].cloudLayerPointer->SetPrecipitation(SilverLining::CloudLayer::RAIN, 15.0 );
+
+}
+
+void visual_skySilverLining::updateUpVector()
+{
+	// Allowed deltaLat and deltaLon between Updating the upvector
+	double deltaLatToUpdate = osg::DegreesToRadians( 0.1 );	// 0.5 deg
+	double deltaLonToUpdate = osg::DegreesToRadians( 0.1 ); // 0.5 deg
+
+	if ( fabs(lat-upVectorLat) > deltaLatToUpdate || fabs(lon-upVectorLon) > deltaLonToUpdate )
+	{
+		// Get ellipsoid model
+		osg::EllipsoidModel* ellipsoid = sceneRoot->getEllipsoidModel();
+		if ( !ellipsoid )
+			return;
+
+		//OSG_NOTIFY( osg::ALWAYS ) << "update Upvector.." << std::endl;
+
+		// Calculate up vector
+		double x,y,z;
+		util::getXYZofCamera(sceneCamera, x, y, z);
+		osg::Vec3d upVector = ellipsoid->computeLocalUpVector( x, y, z );
+		upVector.normalize();
+		
+		// Calculate side vector
+		osg::Matrixd localToWorld;
+		ellipsoid->computeLocalToWorldTransformFromLatLongHeight(lat, lon, height, localToWorld);
+
+		osg::Vec3d sideVector(localToWorld(0, 0), localToWorld(0, 1), localToWorld(0, 2));
+		sideVector.normalize();
+
+		// Update silverlining vectors
+		//std::cout << "upVector: X: " << upVector.x() << ", Y: "<<  upVector.y() << ", Z: "<< upVector.z() << std::endl;
+		//std::cout << "sideVector: X: " << sideVector.x() << ", Y: "<<  sideVector.y() << ", Z: "<< sideVector.z() << std::endl;
+		atmosphere->SetUpVector( upVector.x(), upVector.y(), upVector.z() );
+		atmosphere->SetRightVector( sideVector.x(), sideVector.y(), sideVector.z() );
+
+		// Note new upvector lat/lon
+		upVectorLon = lon;
+		upVectorLat = lat;
+	}	// If update requiered END
+}
+
+void visual_skySilverLining::shutdown()
+{
+	if (isInitialized())
+	{
+		// Remove this Node from scenegraph
+		sceneRoot->removeChild( this );
+		
+		// Remove updatecallback
+		this->removeUpdateCallback( updateCallback );
+		updateCallback = NULL;
+
+		// delete drawables
+		this->removeDrawable(skyDrawable);
+		this->removeDrawable(cloudsDrawable);
+	}
+}
+
+void visual_skySilverLining::setVisibility(double visibility_)
+{
+	if (isInitialized())
+	{
+		atmosphere->GetConditions()->SetVisibility( visibility_ );
+	}
+}
+
+double visual_skySilverLining::getVisibility()
+{
+	if (isInitialized())
+	{
+		return atmosphere->GetConditions()->GetVisibility();
+	}
+	else
+		return -1;
+}
+
+void visual_skySilverLining::setTurbidity(double turbidity_)
+{
+	if (isInitialized())
+	{
+		atmosphere->GetConditions()->SetTurbidity( turbidity_ );
+	}
+}
+
+double visual_skySilverLining::getTurbidity()
+{
+	if (isInitialized())
+	{
+		return atmosphere->GetConditions()->GetTurbidity();
+	}
+	else
+		return -1;
+}
+
+void visual_skySilverLining::clearAllWindVolumes()
+{
+	if (isInitialized())
+	{
+		atmosphere->GetConditions()->ClearWindVolumes();
+	}
+}
+
+bool visual_skySilverLining::insideWind(double height_, double& bottom_, double& top_, double& speed_, double& direction_)
+{
+	if (isInitialized())
+	{
+		// Calculation earth radius on the wind positionl approximated through the now used position.
+		double radius;
+		if ( util::calculateEarthRadiusAtWGS84Coordinate(lat, lon, sceneRoot, radius) )
+		{
+			// go through all wind volumes an check them for inside()
+			std::vector<SilverLining::WindVolume> windvolumes = atmosphere->GetConditions()->GetWindVolumes();
+			for(unsigned int i=0; i<windvolumes.size(); i++)
+			{
+				if( windvolumes[i].Inside(radius + height_) )
+				{
+					// save wind data
+					bottom_ = windvolumes[i].GetMinAltitude();
+					top_ = windvolumes[i].GetMaxAltitude() - radius;
+					speed_ = windvolumes[i].GetWindSpeed() - radius;
+					direction_ = windvolumes[i].GetDirection();
+					// return that wind was found
+					return true;
+				}
+			}	// For END
+		}	// If valid radius END
+	}	// If initialized() END
+	bottom_ = -1;
+	top_ = -1;
+	speed_ = -1;
+	direction_ = -1;
+	return false;
+}
+
+void visual_skySilverLining::addWindVolume(double bottom_, double top_, double speed_, int direction_)
+{
+	if (isInitialized())		
+	{
+		// Calculation earth radius on current lat lon position
+		double radius;
+		if ( util::calculateEarthRadiusAtWGS84Coordinate(lat, lon, sceneRoot, radius) )
+		{
+			// correct wind value:
+			if ( direction_ < 180 )
+				direction_ += 180;
+			else direction_ -= 180;
+
+			// Setting up Wind
+			SilverLining::WindVolume wv;
+			wv.SetDirection( direction_ );
+			wv.SetMinAltitude( radius + bottom_ );
+			wv.SetMaxAltitude( radius + top_ );
+			wv.SetWindSpeed( speed_ );
+			atmosphere->GetConditions()->SetWind(wv);
+		}
+	}
+}
+
+void visual_skySilverLining::setLightPollution(double lightPollution_)
+{
+	if (isInitialized())
+	{
+		return atmosphere->GetConditions()->SetLightPollution( lightPollution_ );
+	}
+}
+
+double visual_skySilverLining::getLightPollution()
+{
+	if (isInitialized())
+	{
+		return atmosphere->GetConditions()->GetLightPollution();
+	}
+	else
+		return -1;
+
+}
+
+void visual_skySilverLining::addCloudLayer(int slot_, double baseLength_, double baseWidth_, double thickness_, double baseHeight_, double density_, CloudTypes cloudtype_ )
+{
+	if (isInitialized() && slot_ >= 0 && slot_ < MAX_CLOUDLAYER_SLOTS)
+	{
+		// Calculation earth radius on current lat lon position
+		double radius;
+		if ( util::calculateEarthRadiusAtWGS84Coordinate(lat, lon, sceneRoot, radius) )
+		{
+			// generate Cloud Layer
+			SilverLining::CloudLayer *cloudLayer_;
+			cloudLayer_ = SilverLining::CloudLayerFactory::Create(cloudtype_);
+			cloudLayer_->SetBaseAltitude( baseHeight_ + radius);
+			
+			cloudLayer_->SetThickness(thickness_);
+			cloudLayer_->SetBaseLength(baseLength_);
+			cloudLayer_->SetBaseWidth(baseWidth_);
+			cloudLayer_->SetDensity(density_);
+			cloudLayer_->SetLayerPosition( 0.0, 0.0 );
+			cloudLayer_->GenerateShadowMaps(false);
+
+			//Save cloudlayer information into SLOT
+			cloudLayerSlots[slot_].used = true;
+			cloudLayerSlots[slot_].enabled = true;
+			cloudLayerSlots[slot_].cloudLayerPointer = cloudLayer_;
+			switch(cloudtype_)
+			{
+			case 0: cloudLayerSlots[slot_].typeName = "CIRROCUMULUS";				// High planar cloud puffs		
+				break;
+			case 1: cloudLayerSlots[slot_].typeName = "CIRRUS_FIBRATUS";			// High, thicker and fibrous clouds that signal changing weather
+    			break;
+			case 2: cloudLayerSlots[slot_].typeName = "NIMBOSTRATUS";               // Low rain clouds that cover the sky
+    			break;
+			case 3: cloudLayerSlots[slot_].typeName = "CUMULUS_MEDIOCRIS";          // Low, puffy clouds on fair days
+    			break;
+			case 4: cloudLayerSlots[slot_].typeName = "CUMULUS_CONGESTUS";          // Large cumulus clouds that could turn into a thunderhead
+    			break;
+			case 5: cloudLayerSlots[slot_].typeName = "CUMULONIMBUS_CAPPILATUS";    // Big storm clouds.
+    			break;
+			case 6: cloudLayerSlots[slot_].typeName = "CUMULUS_CONGESTUS_INFINITE"; // Cumulus congestus layer that wraps to surround the camera at all times. 
+    			break;
+			case 7: cloudLayerSlots[slot_].typeName = "CUMULUS_MEDIOCRIS_INFINITE"; // Cumulus mediocris layer that wraps to surround the camera at all times. 
+				break;
+			default: OSG_NOTIFY( osg::FATAL ) << "visual_skySilverlining::addCloudLayer - Invalid cloud type." << std::cout;
+				 break;
+			};
+		
+			// Pass cloudlayer for seeding and adding to sky framework to the render thread
+			skyDrawable->addCloudLayer( &cloudLayerSlots[slot_] );
+		} // If valid radius END
+	}	 // If isInitialized() END
+}
+
+void visual_skySilverLining::removeCloudLayer( int slot_ )
+{
+	if (isInitialized() && slot_ >= 0 && slot_ < MAX_CLOUDLAYER_SLOTS)
+	{
+		atmosphere->GetConditions()->RemoveCloudLayer( cloudLayerSlots[slot_].cloudLayerHandle );
+		cloudLayerSlots[slot_].used = false;
+		cloudLayerSlots[slot_].cloudLayerHandle = -1;
+		cloudLayerSlots[slot_].cloudLayerPointer = NULL;
+		cloudLayerSlots[slot_].enabled = false;
+	}
+}
+
+void visual_skySilverLining::clearAllSlots()
+{
+	if (isInitialized())
+	{
+		atmosphere->GetConditions()->RemoveAllCloudLayers();
+		for( int i=0; i<MAX_CLOUDLAYER_SLOTS; i++ )
+		{
+			cloudLayerSlots[i].used = false;
+			cloudLayerSlots[i].cloudLayerHandle = -1;
+			cloudLayerSlots[i].cloudLayerPointer = NULL;
+			cloudLayerSlots[i].enabled = false;
+		}
+	}
+}
+
+SilverLining::CloudLayer* visual_skySilverLining::getCloudLayer( int slot_ )
+{
+	if (isInitialized() && slot_ >= 0 && slot_ < MAX_CLOUDLAYER_SLOTS)
+	{
+		if ( cloudLayerSlots[slot_].used )
+			return cloudLayerSlots[slot_].cloudLayerPointer; 
+	}
+
+	return NULL;
+}
+
+void visual_skySilverLining::setEnabled(int slot_, bool enabled_ )
+{
+	if (isInitialized() && slot_ >= 0 && slot_ < MAX_CLOUDLAYER_SLOTS)
+	{
+		cloudLayerSlots[slot_].enabled = enabled_;
+	}
+}
+
+bool visual_skySilverLining::isEnabled( int slot_ )
+{
+	if (isInitialized() && slot_ >= 0 && slot_ < MAX_CLOUDLAYER_SLOTS)
+	{
+		return cloudLayerSlots[slot_].enabled;
+	}
+	return false;
+}
+
+void visual_skySilverLining::fadeVisibility( int slot_, int fadetimeMS_ )
+{
+	if (isInitialized() && slot_ >= 0 && slot_ < MAX_CLOUDLAYER_SLOTS)
+	{
+		if (cloudLayerSlots[slot_].enabled)
+		{
+			cloudLayerSlots[slot_].enabled = false;
+			cloudLayerSlots[slot_].cloudLayerPointer->SetEnabled( false, fadetimeMS_ );
+		}
+		else
+		{
+			cloudLayerSlots[slot_].enabled = true;
+			cloudLayerSlots[slot_].cloudLayerPointer->SetEnabled( true, fadetimeMS_ );
+		}
+	}
+}
+
+std::string visual_skySilverLining::getCloudLayerTypeName( int slot_ )
+{
+	if (isInitialized() && slot_ >= 0 && slot_ < MAX_CLOUDLAYER_SLOTS)
+	{
+		return cloudLayerSlots[slot_].typeName;
+	}
+	return "";
+}
+
+void visual_skySilverLining::clearGlobalPrecipitation()
+{
+	if (isInitialized())
+	{
+		atmosphere->GetConditions()->SetPrecipitation( SilverLining::CloudLayer::NONE, 0.0 );
+	}
+}
+
+void visual_skySilverLining::setGlobalPrecipitation( double rate_mmPerHour_rain_, double rate_mmPerHour_drySnow_, double rate_mmPerHour_wetSnow_, double rate_mmPerHour_sleet_ )
+{
+	if ( isInitialized() )
+	{
+		// Delete old Precipitation
+		atmosphere->GetConditions()->SetPrecipitation( SilverLining::CloudLayer::NONE, 0.0 );
+		
+		// Set new Precipitation
+		atmosphere->GetConditions()->SetPrecipitation( SilverLining::CloudLayer::RAIN, rate_mmPerHour_rain_ );
+		atmosphere->GetConditions()->SetPrecipitation( SilverLining::CloudLayer::WET_SNOW, rate_mmPerHour_drySnow_ );
+		atmosphere->GetConditions()->SetPrecipitation( SilverLining::CloudLayer::DRY_SNOW, rate_mmPerHour_wetSnow_ );
+		atmosphere->GetConditions()->SetPrecipitation( SilverLining::CloudLayer::SLEET, rate_mmPerHour_sleet_ );
+	}
+}
+	
+bool visual_skySilverLining::getOverallPrecipitationAtLocation( double& rate_mmPerHour_rain, double& rate_mmPerHour_drySnow, double& rate_mmPerHour_wetSnow, double& rate_mmPerHour_sleet, double lat_, double lon_, double height_ )
+{
+	if (isInitialized())
+	{
+		// Init
+		bool hasPrecipitation = false;
+		double x = 0;
+		double y = 0;
+		double z = 0;
+		//// If -1 : Use sky internal values
+		if ( lat_ == -1 )
+			lat_ = lat;
+		if ( lon_ == -1 )
+			lon_ = lon;
+		if ( height_ == -1 )
+			height_ = height;
+
+		// Set precipitation to zero;
+		rate_mmPerHour_rain = 0;
+		rate_mmPerHour_drySnow = 0;
+		rate_mmPerHour_wetSnow = 0;
+		rate_mmPerHour_sleet = 0;
+
+		// Get global position
+		util::calculateXYZAtWGS84Coordinate(lat_, lon_, height_, sceneRoot, x, y, z);
+
+		// Look up every cloud layer for it's precipitation.
+		for( int i=0; i<MAX_CLOUDLAYER_SLOTS; i++ )
+		{
+			if ( cloudLayerSlots[i].used )	// IF used, Pointer should be valid
+			{
+				if( cloudLayerSlots[i].cloudLayerPointer->HasPrecipitationAtPosition(x, y, z) )
+				{
+					hasPrecipitation = true;
+					std::map<int, double> precipitationMap = cloudLayerSlots[i].cloudLayerPointer->GetPrecipitation();
+					for( std::map<int, double>::iterator it = precipitationMap.begin(); it != precipitationMap.end(); it++ )
+					{
+						switch(it->first)
+						{
+							case SilverLining::CloudLayer::RAIN : rate_mmPerHour_rain += it->second;
+								break;
+							case SilverLining::CloudLayer::DRY_SNOW : rate_mmPerHour_drySnow += it->second;
+								break;
+							case SilverLining::CloudLayer::WET_SNOW : rate_mmPerHour_wetSnow += it->second;
+								break;
+							case SilverLining::CloudLayer::SLEET : rate_mmPerHour_sleet += it->second;
+								break;
+							default: OSG_NOTIFY( osg::FATAL ) << "ERROR: visual_skySilverLining::getOverallPrecipitationAtLocation() : Wrong precipitation type in map!" << std::endl;
+								break;
+						};
+					}
+				}	// If slot has Precipitation END
+			}	// If used END
+		}	// For all slots END
+
+		OSG_NOTIFY( osg::ALWAYS ) << "Rain: " << rate_mmPerHour_rain << ", dry snow: " << rate_mmPerHour_drySnow << ", wet snow: " << rate_mmPerHour_wetSnow << ", sleet: " << rate_mmPerHour_sleet << std::endl;
+		return hasPrecipitation;
+
+	}	// If initialized END
+	return false;
+}
+
+
+bool visual_skySilverLining::getSlotPrecipitationAtLocation( int slot_, double& rate_mmPerHour_rain, double& rate_mmPerHour_drySnow, double& rate_mmPerHour_wetSnow, double& rate_mmPerHour_sleet, double lat_, double lon_, double height_ )
+{
+	if (isInitialized() && slot_ >= 0 && slot_ < MAX_CLOUDLAYER_SLOTS)
+	{
+		if( cloudLayerSlots[slot_].used )	// IF used, Pointer should be valid
+		{
+			double x = 0;
+			double y = 0;
+			double z = 0;
+			rate_mmPerHour_rain = 0;
+			rate_mmPerHour_drySnow = 0;
+			rate_mmPerHour_wetSnow = 0;
+			rate_mmPerHour_sleet = 0;
+			//// If -1 : Use sky internal values
+			if ( lat_ == -1 )
+				lat_ = lat;
+			if ( lon_ == -1 )
+				lon_ = lon;
+			if ( height_ == -1 )
+				height_ = height;
+
+			// Get global position
+			util::calculateXYZAtWGS84Coordinate(lat_, lon_, height_, sceneRoot, x, y, z);
+
+			// Check for precipitation
+			if( cloudLayerSlots[slot_].cloudLayerPointer->HasPrecipitationAtPosition(x, y, z) )
+			{
+				std::map<int, double> precipitationMap = cloudLayerSlots[slot_].cloudLayerPointer->GetPrecipitation();
+				for( std::map<int, double>::iterator it = precipitationMap.begin(); it != precipitationMap.end(); it++ )
+				{
+					switch(it->first)
+					{
+						case SilverLining::CloudLayer::RAIN : rate_mmPerHour_rain = it->second;
+							break;
+						case SilverLining::CloudLayer::DRY_SNOW : rate_mmPerHour_drySnow = it->second;
+							break;
+						case SilverLining::CloudLayer::WET_SNOW : rate_mmPerHour_wetSnow = it->second;
+							break;
+						case SilverLining::CloudLayer::SLEET : rate_mmPerHour_sleet = it->second;
+							break;
+						default: OSG_NOTIFY( osg::FATAL ) << "ERROR: visual_skySilverLining::getSlotPrecipitationAtLocation() : Wrong precipitation type in map!" << std::endl;
+							break;
+					};
+				}	// FOR END
+				OSG_NOTIFY( osg::ALWAYS ) << "Rain: " << rate_mmPerHour_rain << ", dry snow: " << rate_mmPerHour_drySnow << ", wet snow: " << rate_mmPerHour_wetSnow << ", sleet: " << rate_mmPerHour_sleet << std::endl;
+				return true;
+			}	// If slot has Precipitation END
+			else 
+				return false;
+		}	// If used END
+		else
+			return false;
+	}	// If initialized END
+	return false;
+}
+
+bool visual_skySilverLining::getSlotPrecipitation( int slot_, double& rate_mmPerHour_rain, double& rate_mmPerHour_drySnow, double& rate_mmPerHour_wetSnow, double& rate_mmPerHour_sleet )
+{
+	if (isInitialized() && slot_ >= 0 && slot_ < MAX_CLOUDLAYER_SLOTS)
+	{
+		if( cloudLayerSlots[slot_].used )	// IF used, Pointer should be valid
+		{
+			rate_mmPerHour_rain = 0;
+			rate_mmPerHour_drySnow = 0;
+			rate_mmPerHour_wetSnow = 0;
+			rate_mmPerHour_sleet = 0;
+
+			// Check for precipitation
+
+				std::map<int, double> precipitationMap = cloudLayerSlots[slot_].cloudLayerPointer->GetPrecipitation();
+				for( std::map<int, double>::iterator it = precipitationMap.begin(); it != precipitationMap.end(); it++ )
+				{
+					switch(it->first)
+					{
+						case SilverLining::CloudLayer::RAIN : rate_mmPerHour_rain = it->second;
+							break;
+						case SilverLining::CloudLayer::DRY_SNOW : rate_mmPerHour_drySnow = it->second;
+							break;
+						case SilverLining::CloudLayer::WET_SNOW : rate_mmPerHour_wetSnow = it->second;
+							break;
+						case SilverLining::CloudLayer::SLEET : rate_mmPerHour_sleet = it->second;
+							break;
+						default: OSG_NOTIFY( osg::FATAL ) << "ERROR: visual_skySilverLining::getSlotPrecipitation() : Wrong precipitation type in map!" << std::endl;
+							break;
+					};
+				}	// FOR END
+				
+				if ( rate_mmPerHour_rain>0 || rate_mmPerHour_drySnow>0 || rate_mmPerHour_wetSnow>0 || rate_mmPerHour_sleet>0)
+				{
+					OSG_NOTIFY( osg::ALWAYS ) << "Rain: " << rate_mmPerHour_rain << ", dry snow: " << rate_mmPerHour_drySnow << ", wet snow: " << rate_mmPerHour_wetSnow << ", sleet: " << rate_mmPerHour_sleet << std::endl;
+					return true;
+				}
+				else
+					return false;
+		}	// If used END
+		else
+			return false;
+	}	// If initialized END
+	return false;
+}
+
+void visual_skySilverLining::clearAllPrecipitation( int slot_ )
+{
+	if (isInitialized() && slot_ >= 0 && slot_ < MAX_CLOUDLAYER_SLOTS)
+	{
+		if( cloudLayerSlots[slot_].used )	// IF used, Pointer should be valid
+		{
+			cloudLayerSlots[slot_].cloudLayerPointer->SetPrecipitation( SilverLining::CloudLayer::NONE, 0.0 );
+			cloudLayerSlots[slot_].cloudLayerPointer->SetPrecipitation( SilverLining::CloudLayer::NONE, 0.0 ); // Second Call to clear precipitation rate.
+		}
+	}
+}
+
+void visual_skySilverLining::setSlotPrecipitation( int slot_, double rate_mmPerHour_rain_, double rate_mmPerHour_drySnow_, double rate_mmPerHour_wetSnow_, double rate_mmPerHour_sleet_ )
+{
+	if (isInitialized() && slot_ >= 0 && slot_ < MAX_CLOUDLAYER_SLOTS)
+	{
+		if( cloudLayerSlots[slot_].used )	// IF used, Pointer should be valid
+		{
+			cloudLayerSlots[slot_].cloudLayerPointer->SetPrecipitation( SilverLining::CloudLayer::RAIN, rate_mmPerHour_rain_ );
+			cloudLayerSlots[slot_].cloudLayerPointer->SetPrecipitation( SilverLining::CloudLayer::DRY_SNOW, rate_mmPerHour_drySnow_ );
+			cloudLayerSlots[slot_].cloudLayerPointer->SetPrecipitation( SilverLining::CloudLayer::WET_SNOW, rate_mmPerHour_wetSnow_ );
+			cloudLayerSlots[slot_].cloudLayerPointer->SetPrecipitation( SilverLining::CloudLayer::SLEET, rate_mmPerHour_sleet_ );
+		}
+	}
+}
Index: /osgVisual/src/util/visual_util.cpp
===================================================================
--- /osgVisual/src/util/visual_util.cpp	(revision 31)
+++ /osgVisual/src/util/visual_util.cpp	(revision 31)
@@ -0,0 +1,295 @@
+/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
+ *
+ * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under 
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
+ * You have to aquire licenses for all used proprietary modules.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#include <visual_util.h>
+
+using namespace osgVisual;
+
+util::util(void)
+{
+}
+
+util::~util(void)
+{
+}
+
+osg::Node* util::findNamedNode(const std::string& searchName_, osg::Node* currNode_)
+{
+   osg::Group* currGroup;
+   osg::Node* foundNode;
+
+   // check to see if we have a valid (non-NULL) node.
+   // if we do have a null node, return NULL.
+   if ( !currNode_)
+   {
+      return NULL;
+   }
+
+   // We have a valid node, check to see if this is the node we 
+   // are looking for. If so, return the current node.
+   if (currNode_->getName() == searchName_)
+   {
+      return currNode_;
+   }
+
+   // We have a valid node, but not the one we are looking for.
+   // Check to see if it has children (non-leaf node). If the node
+   // has children, check each of the child nodes by recursive call.
+   // If one of the recursive calls returns a non-null value we have
+   // found the correct node, so return this node.
+   // If we check all of the children and have not found the node,
+   // return NULL
+   currGroup = currNode_->asGroup(); // returns NULL if not a group.
+   if ( currGroup ) 
+   {
+      for (unsigned int i = 0 ; i < currGroup->getNumChildren(); i ++)
+      { 
+         foundNode = findNamedNode(searchName_, currGroup->getChild(i));
+         if (foundNode)
+		 {
+			 std::cout << "Node gefunden in Ebene: " << i << std::endl;
+            return foundNode; // found a match!
+		}
+      }
+      return NULL; // We have checked each child node - no match found.
+   }
+   else 
+   {
+      return NULL; // leaf node, no match 
+   }
+}
+
+osg::ref_ptr<osg::Geode> util::getDemoCylinder(double length_, double width_, osg::Vec3 offset_ )
+{
+	osg::ref_ptr<osg::Geode> cyl = new osg::Geode();
+	osg::ref_ptr<osg::ShapeDrawable> shape = new osg::ShapeDrawable(new osg::Cylinder( offset_, width_, length_ ));
+	osg::Vec4 color = osg::Vec4(255.0, 0.0, 0.0, 1.0);
+	shape->setColor( color );
+	cyl->addDrawable( shape );
+
+	return cyl;
+}
+
+osg::ref_ptr<osg::Geode> util::getDemoSphere(double radius_, osg::Vec3 offset_ )
+{
+	osg::ref_ptr<osg::Geode> sphere = new osg::Geode();
+	osg::ref_ptr<osg::ShapeDrawable> shape = new osg::ShapeDrawable(new osg::Sphere( offset_, radius_ ) );
+	osg::Vec4 color = osg::Vec4(255.0, 0.0, 0.0, 1.0);
+	shape->setColor( color );
+	sphere->addDrawable( shape );
+
+	return sphere;
+}
+
+bool util::intersect(const osg::Vec3d& start_, const osg::Vec3d& end_, osg::Vec3d& intersection_, osg::Node* node_, osg::Node::NodeMask intersectTraversalMask_ )
+{
+	osg::ref_ptr<osgUtil::LineSegmentIntersector> lsi = new osgUtil::LineSegmentIntersector(start_,end_);
+
+	osgUtil::IntersectionVisitor iv(lsi.get());
+	iv.setTraversalMask(intersectTraversalMask_);
+    
+	node_->accept(iv);
+    
+	if (lsi->containsIntersections())
+	{
+		intersection_ = lsi->getIntersections().begin()->getWorldIntersectPoint();
+		return true;	// Intersect found
+	}
+	return false;	// No intersect found
+}
+
+bool util::queryHeightOfTerrain(double& hot_, osg::Node* rootNode_, double lat_, double lon_, osg::Node::NodeMask traversalMask_)
+{
+	// Get ellipsoid model
+	osg::CoordinateSystemNode* csn = dynamic_cast<osg::CoordinateSystemNode*>(rootNode_);
+	if ( !csn )
+	{
+		OSG_NOTIFY( osg::FATAL ) << "util::queryHeightOfTerrain() :: Invalid CSN!" << std::endl;
+		return false;
+	}
+	osg::EllipsoidModel* ellipsoid = csn->getEllipsoidModel();
+	if ( !ellipsoid )
+	{
+		OSG_NOTIFY( osg::FATAL ) << "util::queryHeightOfTerrain() :: Invalid ellipsoid!" << std::endl;
+		return false;
+	}
+
+	// Setup both endpoints of intersect line
+	double X,Y,Z;
+	ellipsoid->convertLatLongHeightToXYZ(lat_, lon_, 30000, X, Y, Z);
+	osg::Vec3d s = osg::Vec3d(X, Y, Z);
+	ellipsoid->convertLatLongHeightToXYZ(lat_, lon_, -30000, X, Y, Z);
+	osg::Vec3d e = osg::Vec3d(X, Y, Z);
+
+	// Query intersection point
+	osg::Vec3d ip;
+	if ( util::intersect(s, e, ip, rootNode_, traversalMask_) )
+	{
+		double lat2_, lon2_;
+		ellipsoid->convertXYZToLatLongHeight( ip.x(), ip.y(), ip.z(), lat2_, lon2_, hot_ );	// Convert Intersection Point back to Lat Lon, HOT.
+		//OSG_NOTIFY(osg::ALWAYS) << "lat: "<< osg::RadiansToDegrees(lat2_) <<", Lon: " << osg::RadiansToDegrees(lon2_) << ", Hot: " << hot_ << std::endl;
+		return true;
+	}
+
+	// If no intersection point found: set HOT to zero and return false.
+	hot_ = 0;
+	return false;
+}
+
+bool util::queryHeightAboveTerrainInWGS84(double& hat_, osg::Node* rootNode_, double lat_, double lon_, double height_, osg::Node::NodeMask traversalMask_)
+{
+	// Get HOT by asking util::queryHeightOfTerrain() :)
+	double HOT;
+	if ( !util::queryHeightOfTerrain(HOT, rootNode_, lat_, lon_, traversalMask_) )
+	{
+		OSG_NOTIFY( osg::INFO ) << "util::queryHeightAboveTerrainInWGS84() :: Unable to get HOT, will use 0 for HOT!" << std::endl;
+	}
+
+	// Calculate HAT
+	hat_ = height_ - HOT;
+	return true;
+}
+
+bool util::queryHeightAboveTerrainInWorld(double& hat_, osg::Node* rootNode_, double x_, double y_, double z_, osg::Node::NodeMask traversalMask_)
+{
+	// Get ellipsoid model
+	osg::CoordinateSystemNode* csn = dynamic_cast<osg::CoordinateSystemNode*>(rootNode_);
+	if ( !csn )
+	{
+		OSG_NOTIFY( osg::FATAL ) << "util::queryHeightAboveTerrainInWorld() :: Invalid CSN!" << std::endl;
+		return false;
+	}
+	osg::EllipsoidModel* ellipsoid = csn->getEllipsoidModel();
+	if ( !ellipsoid )
+	{
+		OSG_NOTIFY( osg::FATAL ) << "util::queryHeightAboveTerrainInWorld() :: Invalid ellipsoid!" << std::endl;
+		return false;
+	}
+
+	// Transform XYZ into LatLonHeight
+	double lat_, lon_, height_;
+	ellipsoid->convertXYZToLatLongHeight(x_, y_, z_, lat_, lon_, height_);
+
+	// ask util::queryHeightAboveTerrainInWGS84() to calc HAT :)
+	if( !util::queryHeightAboveTerrainInWGS84(hat_, rootNode_, lat_, lon_, height_, traversalMask_ ) )
+	{
+		OSG_NOTIFY( osg::FATAL ) << "util::queryHeightAboveTerrainInWorld() :: Unable to get HAT!" << std::endl;
+		return false;
+	}
+
+	return true;
+}
+
+bool util::calculateEarthRadiusAtWGS84Coordinate(double lat_, double lon_, osg::Node* rootNode_, double& radius_)
+{
+	// Calculate radius:
+	double x, y, z;
+	
+	if ( util::calculateXYZAtWGS84Coordinate(lat_, lon_, 0.0, rootNode_, x, y, z) )
+	{
+		radius_ = sqrt( pow(x, 2) + pow(y, 2) + pow(z, 2) );
+		return true;
+	}
+	else
+	{
+		OSG_NOTIFY( osg::FATAL ) << "util::calculateEarthRadiusAtWGS84Coordinate() :: Unablöe to calculate Earth Radius!" << std::endl;
+		return false;
+	}
+}
+
+bool util::calculateXYZAtWGS84Coordinate(double lat_, double lon_, double height_, osg::Node* rootNode_, double& x_, double& y_, double& z_)
+{
+	// Get ellipsoid model
+	osg::CoordinateSystemNode* csn = dynamic_cast<osg::CoordinateSystemNode*>(rootNode_);
+	if ( !csn )
+		return false;
+	osg::EllipsoidModel* ellipsoid = csn->getEllipsoidModel();
+	if ( !ellipsoid )
+		return false;
+
+	// Calculate xyz:
+	ellipsoid->convertLatLongHeightToXYZ( lat_, lon_, height_, x_, y_, z_);
+	return true;
+}
+
+bool util::getWGS84ofCamera( osg::Camera* camera_, osg::Node* rootNode_, double& lat_, double& lon_, double& height_ )
+{
+	// Get ellipsoid model
+	osg::CoordinateSystemNode* csn = dynamic_cast<osg::CoordinateSystemNode*>(rootNode_);
+	if ( !csn )
+		return false;
+	osg::EllipsoidModel* ellipsoid = csn->getEllipsoidModel();
+	if ( !ellipsoid )
+		return false;
+
+	osg::Vec3d eye, dir, up;
+	camera_->getViewMatrixAsLookAt(eye,dir,up); // Get XYZ from camera
+	ellipsoid->convertXYZToLatLongHeight(eye.x(), eye.y(), eye.z(), lat_, lon_, height_);
+	return true;
+}
+
+void util::getXYZofCamera( osg::Camera* camera_, double& x_, double& y_, double& z_ )
+{
+	osg::Vec3d eye, dir, up;
+	camera_->getViewMatrixAsLookAt(eye,dir,up); // Get XYZ from camera
+	x_ = eye.x();
+	y_ = eye.y();
+	z_ = eye.z();
+}
+
+bool util::removeClosebuttonOnGLWindow(osgViewer::Viewer* viewer_)
+{
+#ifdef FUNFUNCTIONS_ENABLED
+#ifdef WIN32
+	osgViewer::ViewerBase::Windows wins;
+	viewer_->getWindows(wins);
+	osgViewer::GraphicsHandleWin32* hwnd = dynamic_cast<osgViewer::GraphicsHandleWin32*>(wins[0]);
+	
+	HMENU hMenu = GetSystemMenu(hwnd->getHWND(), FALSE);
+	::EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | (MF_DISABLED | MF_GRAYED)); 
+#endif
+#endif
+	return true;
+}
+
+bool util::setTransparentWindowBackground(osgViewer::Viewer* viewer_)
+{
+#ifdef FUNFUNCTIONS_ENABLED
+#ifdef WIN32
+	osgViewer::ViewerBase::Windows wins;
+	viewer_->getWindows(wins);
+	osgViewer::GraphicsHandleWin32* hwnd = dynamic_cast<osgViewer::GraphicsHandleWin32*>(wins[0]);
+	HWND _hwnd = hwnd->getHWND();
+	viewer_->getDisplaySettings()->setMinimumNumAlphaBits(8);
+
+   // Create and populate the Blur Behind structure
+   DWM_BLURBEHIND bb = {0};
+   // Disable Blur Behind and Blur Region;
+   bb.dwFlags = DWM_BB_ENABLE;
+   bb.fEnable = true;
+   bb.hRgnBlur = NULL;
+
+   // Ensable Blur Behind
+   HRESULT hr = DwmEnableBlurBehindWindow(_hwnd, &bb);
+   if (SUCCEEDED(hr))
+      return true;
+   else
+	   return false;
+
+#endif
+#endif
+	return true;
+}
Index: /osgVisual/src/vista2D/visual_vista2D.cpp
===================================================================
--- /osgVisual/src/vista2D/visual_vista2D.cpp	(revision 31)
+++ /osgVisual/src/vista2D/visual_vista2D.cpp	(revision 31)
@@ -0,0 +1,124 @@
+/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
+ *
+ * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under 
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
+ * You have to aquire licenses for all used proprietary modules.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#include "visual_vista2D.h"
+
+
+using namespace osgVisual;
+
+visual_vista2D::visual_vista2D(void)
+{
+   // Create a Vista2D View
+   view = new Vista2D::VistaView();
+}
+
+visual_vista2D::~visual_vista2D(void)
+{
+}
+
+void visual_vista2D::init(std::string vista2DFilename_)
+{	
+    /***************
+    load view
+    ***************/
+	view->load( vista2DFilename_ );
+    view->setBackgroundMode(false);	// don't paint background
+	view->setPosition(800,450);
+	view->setZoom( 0.5 );
+
+    /***************
+    start animation with
+    self running datasource
+    ***************/
+    view->startView (true);
+
+}
+
+bool visual_vista2D::createVistaOverlay( std::string vista2DFilename_, osg::CoordinateSystemNode *sceneGraphRoot_ )
+{
+	// Check if Vista2D file exist
+	if (! osgDB::fileExists( vista2DFilename_ ) )
+	{
+		osg::notify( osg::WARN ) << "WARNING: Could not find specified Vista2D projectfile. Skip adding Vista2D project." << std::endl;
+		return false;
+	}
+
+   osg::Geode* vista2Dgeode = new osg::Geode();
+   // Projection node for defining view frustrum for the vista2D-SceneOverlay:
+   osg::Projection* vista2DProjectionMatrix = new osg::Projection;
+
+    // Initialize the projection matrix for viewing everything we
+   // will add as descendants of this node. Use screen coordinates
+   // to define the horizontal and vertical extent of the projection
+   // matrix. Positions described under this node will equate to
+   // pixel coordinates.
+   vista2DProjectionMatrix->setMatrix(osg::Matrix::ortho2D(0,1600,0,900));
+  
+   // For the HUD model view matrix use an identity matrix:
+   osg::MatrixTransform* vista2DModelViewMatrix = new osg::MatrixTransform;
+   vista2DModelViewMatrix->setMatrix(osg::Matrix::identity());
+
+   // Make sure the model view matrix is not affected by any transforms
+   // above it in the scene graph:
+   vista2DModelViewMatrix->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
+
+   // Set Stateset of vista2DGeode Renderbin to render quite late..
+	osg::StateSet* vista2DoverlayStateSet = vista2Dgeode->getOrCreateStateSet();
+	vista2DoverlayStateSet->setRenderBinDetails( 99, "RenderBin");
+
+   // Add the HUD projection matrix as a child of the root node
+   // and the HUD model view matrix as a child of the projection matrix
+   // Anything under this node will be viewed using this projection matrix
+   // and positioned with this model view matrix.
+   vista2DProjectionMatrix->addChild(vista2DModelViewMatrix);
+
+   // Add the Geometry node to contain HUD geometry as a child of the
+   // HUD model view matrix.
+   vista2DModelViewMatrix->addChild( vista2Dgeode );
+
+	// Add Payload: Vista2D			
+	osg::ref_ptr<visual_vista2D> vista2D = new visual_vista2D();
+	vista2D->init( vista2DFilename_ );
+
+	vista2D.get()->setUseDisplayList( false );
+	vista2Dgeode->addDrawable( vista2D.get() );
+
+	sceneGraphRoot_->addChild( vista2DProjectionMatrix );
+	return true;
+}
+
+void visual_vista2D::drawImplementation(osg::RenderInfo& renderInfo) const
+{
+	// save OSG-State
+	osg::ref_ptr<osg::StateSet> clonedStateSet = reinterpret_cast<osg::StateSet*>( renderInfo.getCurrentCamera()->getOrCreateStateSet()->clone(osg::CopyOp::DEEP_COPY_ALL) );
+
+	// Draw View
+    view->draw();
+
+	// restore OSG-State
+	renderInfo.getCurrentCamera()->setStateSet( clonedStateSet );
+
+}
+
+osg::Object* visual_vista2D::cloneType() const
+{
+	return NULL;
+}
+
+osg::Object* visual_vista2D::clone(const osg::CopyOp& copyop) const
+{ 
+	return NULL;
+}
