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