OpenWalnut  1.4.0
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/tokenizer.hpp>
00029 
00030 #include <osg/Camera>
00031 
00032 #include "../common/WLogger.h"
00033 #include "../common/WStringUtils.h"
00034 #include "../kernel/WProjectFile.h"
00035 
00036 #include "WGraphicsEngine.h"
00037 #include "WGEViewer.h"
00038 #include "WGECamera.h"
00039 
00040 #include "WGEProjectFileIO.h"
00041 
00042 WGEProjectFileIO::WGEProjectFileIO():
00043     WProjectFileIO()
00044 {
00045     // initialize members
00046 }
00047 
00048 WGEProjectFileIO::~WGEProjectFileIO()
00049 {
00050     // cleanup
00051 }
00052 
00053 WProjectFileIO::SPtr WGEProjectFileIO::clone( WProjectFile* project ) const
00054 {
00055     // nothing special. Simply create new instance.
00056     WProjectFileIO::SPtr p( new WGEProjectFileIO() );
00057     p->setProject( project );
00058     return p;
00059 }
00060 
00061 /**
00062  * Interpret a string as a ";"- separated sequence of doubles.
00063  *
00064  * \param seq   the sequence
00065  * \param size  the number of doubles needed
00066  *
00067  * \return the values
00068  */
00069 double* parseDoubleSequence( std::string seq, unsigned int size )
00070 {
00071     // parse the string
00072     // -> tokenize it and fill pointer appropriately
00073     typedef boost::tokenizer<boost::char_separator< char > > tokenizer;
00074     boost::char_separator< char > sep( ";" );   // separate by ;
00075     tokenizer tok( seq, sep );
00076 
00077     // each value must be stored at the proper position
00078     double* values = new double[ size ];
00079     unsigned int i = 0;
00080     for( tokenizer::iterator it = tok.begin(); ( it != tok.end() ) && ( i < size ); ++it )
00081     {
00082         values[ i ] = string_utils::fromString< double >( ( *it ) );
00083         ++i;
00084     }
00085 
00086     // finally, set the values
00087     return values;
00088 }
00089 
00090 /**
00091  * Parse a string and interpret it as matrix. It creates a array of 16 values representing a 4x4 matrix in OSG notation.
00092  *
00093  * \param matrix the matrix as string.
00094  *
00095  * \return the parsed values.
00096  */
00097 double* parseMatrix( std::string matrix )
00098 {
00099     return parseDoubleSequence( matrix, 16 );
00100 }
00101 
00102 /**
00103  * Parse a string and interpret it as vector. It creates an array of 3 values representing the vector in OSG notation-
00104  *
00105  * \param vec the string to parse
00106  *
00107  * \return the values.
00108  */
00109 double* parseVector( std::string vec )
00110 {
00111     return parseDoubleSequence( vec, 3 );
00112 }
00113 
00114 bool WGEProjectFileIO::parse( std::string line, unsigned int lineNumber )
00115 {
00116     // regular expressions to parse the line
00117     static const boost::regex camRe( "^ *CAMERA:([0-9]*):(.*)$" );
00118     static const boost::regex matrixRe(     "^ *MANIPULATOR:\\(([0-9]*),Matrix\\)=(.*)$" );
00119     static const boost::regex homeEyeRe(    "^ *MANIPULATOR:\\(([0-9]*),HomeEye\\)=(.*)$" );
00120     static const boost::regex homeCenterRe( "^ *MANIPULATOR:\\(([0-9]*),HomeCenter\\)=(.*)$" );
00121     static const boost::regex homeUpRe(     "^ *MANIPULATOR:\\(([0-9]*),HomeUp\\)=(.*)$" );
00122 
00123     // use regex to parse it
00124     boost::smatch matches;  // the list of matches
00125     if( boost::regex_match( line, matches, camRe ) )
00126     {
00127         // it is a camera line
00128         // matches[1] is the ID
00129         // matches[2] is the name of the view/camera
00130         wlog::debug( "Project Loader [Parser]" ) << "Line " << lineNumber << ": Camera \"" << matches[2] << "\" with ID " << matches[1];
00131 
00132         // store it
00133         m_cameras[ string_utils::fromString< unsigned int >( matches[1] ) ] = matches[2];
00134 
00135         return true;
00136     }
00137     else if( boost::regex_match( line, matches, matrixRe ) )
00138     {
00139         // it is a camera modelview matrix line
00140         // matches[1] is the ID of the camera
00141         // matches[2] is the matrix line
00142         wlog::debug( "Project Loader [Parser]" ) << "Line " << lineNumber << ": Camera Manipulator Matrix with ID " << matches[1];
00143 
00144         // is there already a matrix for this camera? -> we do not care :-). Overwrite it.
00145         m_manipulatorMatrices[ string_utils::fromString< unsigned int >( matches[1] ) ] =
00146             osg::Matrixd( parseMatrix( string_utils::toString( matches[2] ) ) );
00147 
00148         return true;
00149     }
00150     else if( boost::regex_match( line, matches, homeEyeRe ) )
00151     {
00152         // it is a eye point of the manipulator
00153 
00154         // matches[1] is the ID of the camera
00155         // matches[2] is the eye vector
00156         wlog::debug( "Project Loader [Parser]" ) << "Line " << lineNumber << ": Camera Manipulator Home Eye Point with ID " << matches[1];
00157 
00158         // is there already a vector set? -> ignore.
00159         double* vals = parseVector( string_utils::toString( matches[2] ) );
00160         m_homeEyeVectors[ string_utils::fromString< unsigned int >( matches[1] ) ] = osg::Vec3d( vals[0], vals[1], vals[2] );
00161 
00162         return true;
00163     }
00164     else if( boost::regex_match( line, matches, homeCenterRe ) )
00165     {
00166         // it is a center point of the manipulator
00167 
00168         // matches[1] is the ID of the camera
00169         // matches[2] is the eye vector
00170         wlog::debug( "Project Loader [Parser]" ) << "Line " << lineNumber << ": Camera Manipulator Home Center Point with ID " << matches[1];
00171 
00172         // is there already a vector set? -> ignore.
00173         double* vals = parseVector( string_utils::toString( matches[2] ) );
00174         m_homeCenterVectors[ string_utils::fromString< unsigned int >( matches[1] ) ] = osg::Vec3d( vals[0], vals[1], vals[2] );
00175 
00176         return true;
00177     }
00178     else if( boost::regex_match( line, matches, homeUpRe ) )
00179     {
00180         // it is a up vector of the manipulator
00181 
00182         // matches[1] is the ID of the camera
00183         // matches[2] is the eye vector
00184         wlog::debug( "Project Loader [Parser]" ) << "Line " << lineNumber << ": Camera Manipulator Home Up Point with ID " << matches[1];
00185 
00186         // is there already a vector set? -> ignore.
00187         double* vals = parseVector( string_utils::toString( matches[2] ) );
00188         m_homeUpVectors[string_utils::fromString< unsigned int >( matches[1] ) ] = osg::Vec3d( vals[0], vals[1], vals[2] );
00189 
00190         return true;
00191     }
00192 
00193     return false;
00194 }
00195 
00196 void WGEProjectFileIO::done()
00197 {
00198     // apply camera here
00199     for( CameraList::const_iterator iter = m_cameras.begin(); iter != m_cameras.end(); ++iter )
00200     {
00201         // does the corresponding view exists?
00202         boost::shared_ptr< WGEViewer > view = WGraphicsEngine::getGraphicsEngine()->getViewerByName( ( *iter ).second );
00203         if( !view )
00204         {
00205             wlog::warn( "Project Loader" ) << "Project file contained a camera \"" << ( *iter ).second << "\" but the corresponding view does " <<
00206                                               "not exist. Ignoring.";
00207         }
00208 
00209         // did we have a matrix?
00210         if( !m_manipulatorMatrices.count( ( *iter ).first ) )
00211         {
00212             wlog::warn( "Project Loader" ) << "Project file contained a camera \"" << ( *iter ).second << "\" but no proper manipulator matrix. " <<
00213                                               "Leaving current matrix untouched.";
00214         }
00215         else
00216         {
00217             view->getCameraManipulator()->setByMatrix( m_manipulatorMatrices[ ( *iter ).first ] );
00218         }
00219 
00220         // home position found?
00221         if( ( !m_homeEyeVectors.count( ( *iter ).first ) ) ||
00222              ( !m_homeCenterVectors.count( ( *iter ).first ) ) ||
00223              ( !m_homeUpVectors.count( ( *iter ).first ) )
00224            )
00225         {
00226             wlog::warn( "Project Loader" ) << "Project file contained a camera \"" << ( *iter ).second << "\" but no proper manipulator home " <<
00227                                               "position. Leaving current home untouched.";
00228         }
00229         else
00230         {
00231             view->getCameraManipulator()->setHomePosition( m_homeEyeVectors[ ( *iter ).first ],
00232                                                            m_homeCenterVectors[ ( *iter ).first ],
00233                                                            m_homeUpVectors[ ( *iter ).first ]
00234             );
00235         }
00236     }
00237 }
00238 
00239 void WGEProjectFileIO::save( std::ostream& output ) // NOLINT
00240 {
00241     output << "//////////////////////////////////////////////////////////////////////////////////////////////////////////////////" << std::endl <<
00242               "// Camera definitions" << std::endl <<
00243               "//////////////////////////////////////////////////////////////////////////////////////////////////////////////////" << std::endl <<
00244               std::endl;
00245 
00246     // grab the main camera
00247     osg::ref_ptr< WGECamera > cam = WGraphicsEngine::getGraphicsEngine()->getViewer()->getCamera();
00248     osg::ref_ptr< osgGA::MatrixManipulator > mani = WGraphicsEngine::getGraphicsEngine()->getViewer()->getCameraManipulator();
00249     std::string name = WGraphicsEngine::getGraphicsEngine()->getViewer()->getName();
00250     output << "CAMERA:0:" <<  name << std::endl;
00251 
00252     // NOTE: OSG uses manipulators to modify the camera's view and projection matrix every frame. -> it is useless to store view and projection
00253     // matrix as these get overwritten every frame -> we need to store the manipulator settings here.
00254 
00255     // get the matrices
00256     osg::Matrixd view = mani->getMatrix();
00257 
00258     output << "//Camera Matrices: \"" << name << "\"" << std::endl;
00259     output << "    MANIPULATOR:(0,Matrix)=";
00260     for( unsigned int i = 0; i < 16; ++i )
00261     {
00262         output << view.ptr()[i];
00263         if( i < 15 )
00264         {
00265             output << ";";
00266         }
00267     }
00268     output << std::endl;
00269 
00270     // get home position
00271     osg::Vec3d eye;
00272     osg::Vec3d center;
00273     osg::Vec3d up;
00274     mani->getHomePosition( eye, center, up );
00275 
00276     // write them
00277     // NOTE: vec3d already provides a << operator but it writes the vector in a space separated style -> this is not conform to our common style
00278     // -> we manually print them
00279     output << "    MANIPULATOR:(0,HomeEye)=";
00280     output << eye.x() << ";" << eye.y() << ";" << eye.z() << std::endl;
00281     output << "    MANIPULATOR:(0,HomeCenter)=";
00282     output << center.x() << ";" << center.y() << ";" << center.z() << std::endl;
00283     output << "    MANIPULATOR:(0,HomeUp)=";
00284     output << up.x() << ";" << up.y() << ";" << up.z() << std::endl;
00285 
00286     output << "//Camera Matrices END: \"" << name << "\"" << std::endl;
00287 }
00288