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