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