OpenWalnut 1.2.5
WGEProjectFileIO.cpp
00001 //---------------------------------------------------------------------------
00002 //
00003 // Project: OpenWalnut ( http://www.openwalnut.org )
00004 //
00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
00006 // For more information see http://www.openwalnut.org/copying
00007 //
00008 // This file is part of OpenWalnut.
00009 //
00010 // OpenWalnut is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenWalnut is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public License
00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
00022 //
00023 //---------------------------------------------------------------------------
00024 
00025 #include <string>
00026 
00027 #include <boost/regex.hpp>
00028 #include <boost/lexical_cast.hpp>
00029 #include <boost/tokenizer.hpp>
00030 
00031 #include <osg/Camera>
00032 
00033 #include "../common/WLogger.h"
00034 #include "WGraphicsEngine.h"
00035 #include "WGEViewer.h"
00036 
00037 #include "WGEProjectFileIO.h"
00038 
00039 WGEProjectFileIO::WGEProjectFileIO():
00040     WProjectFileIO()
00041 {
00042     // initialize members
00043 }
00044 
00045 WGEProjectFileIO::~WGEProjectFileIO()
00046 {
00047     // cleanup
00048 }
00049 
00050 /**
00051  * Interpret a string as a ";"- separated sequence of doubles.
00052  *
00053  * \param seq   the sequence
00054  * \param size  the number of doubles needed
00055  *
00056  * \return the values
00057  */
00058 double* parseDoubleSequence( std::string seq, unsigned int size )
00059 {
00060     // parse the string
00061     // -> tokenize it and fill pointer appropriately
00062     typedef boost::tokenizer<boost::char_separator< char > > tokenizer;
00063     boost::char_separator< char > sep( ";" );   // separate by ;
00064     tokenizer tok( seq, sep );
00065 
00066     // each value must be stored at the proper position
00067     double* values = new double[ size ];
00068     unsigned int i = 0;
00069     for( tokenizer::iterator it = tok.begin(); ( it != tok.end() ) && ( i < size ); ++it )
00070     {
00071         values[ i ] = boost::lexical_cast< double >( ( *it ) );
00072         ++i;
00073     }
00074 
00075     // finally, set the values
00076     return values;
00077 }
00078 
00079 /**
00080  * Parse a string and interpret it as matrix. It creates a array of 16 values representing a 4x4 matrix in OSG notation.
00081  *
00082  * \param matrix the matrix as string.
00083  *
00084  * \return the parsed values.
00085  */
00086 double* parseMatrix( std::string matrix )
00087 {
00088     return parseDoubleSequence( matrix, 16 );
00089 }
00090 
00091 /**
00092  * Parse a string and interpret it as vector. It creates an array of 3 values representing the vector in OSG notation-
00093  *
00094  * \param vec the string to parse
00095  *
00096  * \return the values.
00097  */
00098 double* parseVector( std::string vec )
00099 {
00100     return parseDoubleSequence( vec, 3 );
00101 }
00102 
00103 bool WGEProjectFileIO::parse( std::string line, unsigned int lineNumber )
00104 {
00105     // regular expressions to parse the line
00106     static const boost::regex camRe( "^ *CAMERA:([0-9]*):(.*)$" );
00107     static const boost::regex matrixRe(     "^ *MANIPULATOR:\\(([0-9]*),Matrix\\)=(.*)$" );
00108     static const boost::regex homeEyeRe(    "^ *MANIPULATOR:\\(([0-9]*),HomeEye\\)=(.*)$" );
00109     static const boost::regex homeCenterRe( "^ *MANIPULATOR:\\(([0-9]*),HomeCenter\\)=(.*)$" );
00110     static const boost::regex homeUpRe(     "^ *MANIPULATOR:\\(([0-9]*),HomeUp\\)=(.*)$" );
00111 
00112     // use regex to parse it
00113     boost::smatch matches;  // the list of matches
00114     if( boost::regex_match( line, matches, camRe ) )
00115     {
00116         // it is a camera line
00117         // matches[1] is the ID
00118         // matches[2] is the name of the view/camera
00119         wlog::debug( "Project Loader [Parser]" ) << "Line " << lineNumber << ": Camera \"" << matches[2] << "\" with ID " << matches[1];
00120 
00121         // store it
00122         m_cameras[ boost::lexical_cast< unsigned int >( matches[1] ) ] = matches[2];
00123 
00124         return true;
00125     }
00126     else if( boost::regex_match( line, matches, matrixRe ) )
00127     {
00128         // it is a camera modelview matrix line
00129         // matches[1] is the ID of the camera
00130         // matches[2] is the matrix line
00131         wlog::debug( "Project Loader [Parser]" ) << "Line " << lineNumber << ": Camera Manipulator Matrix with ID " << matches[1];
00132 
00133         // is there already a matrix for this camera? -> we do not care :-). Overwrite it.
00134         m_manipulatorMatrices[ boost::lexical_cast< unsigned int >( matches[1] ) ] =
00135             osg::Matrixd( parseMatrix( boost::lexical_cast< std::string >( matches[2] ) ) );
00136 
00137         return true;
00138     }
00139     else if( boost::regex_match( line, matches, homeEyeRe ) )
00140     {
00141         // it is a eye point of the manipulator
00142 
00143         // matches[1] is the ID of the camera
00144         // matches[2] is the eye vector
00145         wlog::debug( "Project Loader [Parser]" ) << "Line " << lineNumber << ": Camera Manipulator Home Eye Point with ID " << matches[1];
00146 
00147         // is there already a vector set? -> ignore.
00148         double* vals = parseVector( boost::lexical_cast< std::string >( matches[2] ) );
00149         m_homeEyeVectors[ boost::lexical_cast< unsigned int >( matches[1] ) ] = osg::Vec3d( vals[0], vals[1], vals[2] );
00150 
00151         return true;
00152     }
00153     else if( boost::regex_match( line, matches, homeCenterRe ) )
00154     {
00155         // it is a center point of the manipulator
00156 
00157         // matches[1] is the ID of the camera
00158         // matches[2] is the eye vector
00159         wlog::debug( "Project Loader [Parser]" ) << "Line " << lineNumber << ": Camera Manipulator Home Center Point with ID " << matches[1];
00160 
00161         // is there already a vector set? -> ignore.
00162         double* vals = parseVector( boost::lexical_cast< std::string >( matches[2] ) );
00163         m_homeCenterVectors[ boost::lexical_cast< unsigned int >( matches[1] ) ] = osg::Vec3d( vals[0], vals[1], vals[2] );
00164 
00165         return true;
00166     }
00167     else if( boost::regex_match( line, matches, homeUpRe ) )
00168     {
00169         // it is a up vector of the manipulator
00170 
00171         // matches[1] is the ID of the camera
00172         // matches[2] is the eye vector
00173         wlog::debug( "Project Loader [Parser]" ) << "Line " << lineNumber << ": Camera Manipulator Home Up Point with ID " << matches[1];
00174 
00175         // is there already a vector set? -> ignore.
00176         double* vals = parseVector( boost::lexical_cast< std::string >( matches[2] ) );
00177         m_homeUpVectors[ boost::lexical_cast< unsigned int >( matches[1] ) ] = osg::Vec3d( vals[0], vals[1], vals[2] );
00178 
00179         return true;
00180     }
00181 
00182     return false;
00183 }
00184 
00185 void WGEProjectFileIO::done()
00186 {
00187     // apply camera here
00188     for( CameraList::const_iterator iter = m_cameras.begin(); iter != m_cameras.end(); ++iter )
00189     {
00190         // does the corresponding view exists?
00191         boost::shared_ptr< WGEViewer > view = WGraphicsEngine::getGraphicsEngine()->getViewerByName( ( *iter ).second );
00192         if( !view )
00193         {
00194             wlog::warn( "Project Loader" ) << "Project file contained a camera \"" << ( *iter ).second << "\" but the corresponding view does " <<
00195                                               "not exist. Ignoring.";
00196         }
00197 
00198         // did we have a matrix?
00199         if( !m_manipulatorMatrices.count( ( *iter ).first ) )
00200         {
00201             wlog::warn( "Project Loader" ) << "Project file contained a camera \"" << ( *iter ).second << "\" but no proper manipulator matrix. " <<
00202                                               "Leaving current matrix untouched.";
00203         }
00204         else
00205         {
00206             view->getCameraManipulator()->setByMatrix( m_manipulatorMatrices[ ( *iter ).first ] );
00207         }
00208 
00209         // home position found?
00210         if( ( !m_homeEyeVectors.count( ( *iter ).first ) ) ||
00211              ( !m_homeCenterVectors.count( ( *iter ).first ) ) ||
00212              ( !m_homeUpVectors.count( ( *iter ).first ) )
00213            )
00214         {
00215             wlog::warn( "Project Loader" ) << "Project file contained a camera \"" << ( *iter ).second << "\" but no proper manipulator home " <<
00216                                               "position. Leaving current home untouched.";
00217         }
00218         else
00219         {
00220             view->getCameraManipulator()->setHomePosition( m_homeEyeVectors[ ( *iter ).first ],
00221                                                            m_homeCenterVectors[ ( *iter ).first ],
00222                                                            m_homeUpVectors[ ( *iter ).first ]
00223             );
00224         }
00225     }
00226 }
00227 
00228 void WGEProjectFileIO::save( std::ostream& output ) // NOLINT
00229 {
00230     output << "//////////////////////////////////////////////////////////////////////////////////////////////////////////////////" << std::endl <<
00231               "// Camera definitions" << std::endl <<
00232               "//////////////////////////////////////////////////////////////////////////////////////////////////////////////////" << std::endl <<
00233               std::endl;
00234 
00235     // grab the main camera
00236     osg::ref_ptr< osg::Camera > cam = WGraphicsEngine::getGraphicsEngine()->getViewer()->getCamera();
00237     osg::ref_ptr< osgGA::MatrixManipulator > mani = WGraphicsEngine::getGraphicsEngine()->getViewer()->getCameraManipulator();
00238     std::string name = WGraphicsEngine::getGraphicsEngine()->getViewer()->getName();
00239     output << "CAMERA:0:" <<  name << std::endl;
00240 
00241     // NOTE: OSG uses manipulators to modify the camera's view and projection matrix every frame. -> it is useless to store view and projection
00242     // matrix as these get overwritten every frame -> we need to store the manipulator settings here.
00243 
00244     // get the matrices
00245     osg::Matrixd view = mani->getMatrix();
00246 
00247     output << "//Camera Matrices: \"" << name << "\"" << std::endl;
00248     output << "    MANIPULATOR:(0,Matrix)=";
00249     for( unsigned int i = 0; i < 16; ++i )
00250     {
00251         output << view.ptr()[i];
00252         if( i < 15 )
00253         {
00254             output << ";";
00255         }
00256     }
00257     output << std::endl;
00258 
00259     // get home position
00260     osg::Vec3d eye;
00261     osg::Vec3d center;
00262     osg::Vec3d up;
00263     mani->getHomePosition( eye, center, up );
00264 
00265     // write them
00266     // NOTE: vec3d already provides a << operator but it writes the vector in a space separated style -> this is not conform to our common style
00267     // -> we manually print them
00268     output << "    MANIPULATOR:(0,HomeEye)=";
00269     output << eye.x() << ";" << eye.y() << ";" << eye.z() << std::endl;
00270     output << "    MANIPULATOR:(0,HomeCenter)=";
00271     output << center.x() << ";" << center.y() << ";" << center.z() << std::endl;
00272     output << "    MANIPULATOR:(0,HomeUp)=";
00273     output << up.x() << ";" << up.y() << ";" << up.z() << std::endl;
00274 
00275     output << "//Camera Matrices END: \"" << name << "\"" << std::endl;
00276 }
00277 
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends