OpenWalnut 1.2.5
|
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