OpenWalnut  1.2.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
WGEProjectFileIO.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <string>
26 
27 #include <boost/regex.hpp>
28 #include <boost/lexical_cast.hpp>
29 #include <boost/tokenizer.hpp>
30 
31 #include <osg/Camera>
32 
33 #include "../common/WLogger.h"
34 #include "WGraphicsEngine.h"
35 #include "WGEViewer.h"
36 
37 #include "WGEProjectFileIO.h"
38 
41 {
42  // initialize members
43 }
44 
46 {
47  // cleanup
48 }
49 
50 /**
51  * Interpret a string as a ";"- separated sequence of doubles.
52  *
53  * \param seq the sequence
54  * \param size the number of doubles needed
55  *
56  * \return the values
57  */
58 double* parseDoubleSequence( std::string seq, unsigned int size )
59 {
60  // parse the string
61  // -> tokenize it and fill pointer appropriately
62  typedef boost::tokenizer<boost::char_separator< char > > tokenizer;
63  boost::char_separator< char > sep( ";" ); // separate by ;
64  tokenizer tok( seq, sep );
65 
66  // each value must be stored at the proper position
67  double* values = new double[ size ];
68  unsigned int i = 0;
69  for( tokenizer::iterator it = tok.begin(); ( it != tok.end() ) && ( i < size ); ++it )
70  {
71  values[ i ] = boost::lexical_cast< double >( ( *it ) );
72  ++i;
73  }
74 
75  // finally, set the values
76  return values;
77 }
78 
79 /**
80  * Parse a string and interpret it as matrix. It creates a array of 16 values representing a 4x4 matrix in OSG notation.
81  *
82  * \param matrix the matrix as string.
83  *
84  * \return the parsed values.
85  */
86 double* parseMatrix( std::string matrix )
87 {
88  return parseDoubleSequence( matrix, 16 );
89 }
90 
91 /**
92  * Parse a string and interpret it as vector. It creates an array of 3 values representing the vector in OSG notation-
93  *
94  * \param vec the string to parse
95  *
96  * \return the values.
97  */
98 double* parseVector( std::string vec )
99 {
100  return parseDoubleSequence( vec, 3 );
101 }
102 
103 bool WGEProjectFileIO::parse( std::string line, unsigned int lineNumber )
104 {
105  // regular expressions to parse the line
106  static const boost::regex camRe( "^ *CAMERA:([0-9]*):(.*)$" );
107  static const boost::regex matrixRe( "^ *MANIPULATOR:\\(([0-9]*),Matrix\\)=(.*)$" );
108  static const boost::regex homeEyeRe( "^ *MANIPULATOR:\\(([0-9]*),HomeEye\\)=(.*)$" );
109  static const boost::regex homeCenterRe( "^ *MANIPULATOR:\\(([0-9]*),HomeCenter\\)=(.*)$" );
110  static const boost::regex homeUpRe( "^ *MANIPULATOR:\\(([0-9]*),HomeUp\\)=(.*)$" );
111 
112  // use regex to parse it
113  boost::smatch matches; // the list of matches
114  if( boost::regex_match( line, matches, camRe ) )
115  {
116  // it is a camera line
117  // matches[1] is the ID
118  // matches[2] is the name of the view/camera
119  wlog::debug( "Project Loader [Parser]" ) << "Line " << lineNumber << ": Camera \"" << matches[2] << "\" with ID " << matches[1];
120 
121  // store it
122  m_cameras[ boost::lexical_cast< unsigned int >( matches[1] ) ] = matches[2];
123 
124  return true;
125  }
126  else if( boost::regex_match( line, matches, matrixRe ) )
127  {
128  // it is a camera modelview matrix line
129  // matches[1] is the ID of the camera
130  // matches[2] is the matrix line
131  wlog::debug( "Project Loader [Parser]" ) << "Line " << lineNumber << ": Camera Manipulator Matrix with ID " << matches[1];
132 
133  // is there already a matrix for this camera? -> we do not care :-). Overwrite it.
134  m_manipulatorMatrices[ boost::lexical_cast< unsigned int >( matches[1] ) ] =
135  osg::Matrixd( parseMatrix( boost::lexical_cast< std::string >( matches[2] ) ) );
136 
137  return true;
138  }
139  else if( boost::regex_match( line, matches, homeEyeRe ) )
140  {
141  // it is a eye point of the manipulator
142 
143  // matches[1] is the ID of the camera
144  // matches[2] is the eye vector
145  wlog::debug( "Project Loader [Parser]" ) << "Line " << lineNumber << ": Camera Manipulator Home Eye Point with ID " << matches[1];
146 
147  // is there already a vector set? -> ignore.
148  double* vals = parseVector( boost::lexical_cast< std::string >( matches[2] ) );
149  m_homeEyeVectors[ boost::lexical_cast< unsigned int >( matches[1] ) ] = osg::Vec3d( vals[0], vals[1], vals[2] );
150 
151  return true;
152  }
153  else if( boost::regex_match( line, matches, homeCenterRe ) )
154  {
155  // it is a center point of the manipulator
156 
157  // matches[1] is the ID of the camera
158  // matches[2] is the eye vector
159  wlog::debug( "Project Loader [Parser]" ) << "Line " << lineNumber << ": Camera Manipulator Home Center Point with ID " << matches[1];
160 
161  // is there already a vector set? -> ignore.
162  double* vals = parseVector( boost::lexical_cast< std::string >( matches[2] ) );
163  m_homeCenterVectors[ boost::lexical_cast< unsigned int >( matches[1] ) ] = osg::Vec3d( vals[0], vals[1], vals[2] );
164 
165  return true;
166  }
167  else if( boost::regex_match( line, matches, homeUpRe ) )
168  {
169  // it is a up vector of the manipulator
170 
171  // matches[1] is the ID of the camera
172  // matches[2] is the eye vector
173  wlog::debug( "Project Loader [Parser]" ) << "Line " << lineNumber << ": Camera Manipulator Home Up Point with ID " << matches[1];
174 
175  // is there already a vector set? -> ignore.
176  double* vals = parseVector( boost::lexical_cast< std::string >( matches[2] ) );
177  m_homeUpVectors[ boost::lexical_cast< unsigned int >( matches[1] ) ] = osg::Vec3d( vals[0], vals[1], vals[2] );
178 
179  return true;
180  }
181 
182  return false;
183 }
184 
186 {
187  // apply camera here
188  for( CameraList::const_iterator iter = m_cameras.begin(); iter != m_cameras.end(); ++iter )
189  {
190  // does the corresponding view exists?
191  boost::shared_ptr< WGEViewer > view = WGraphicsEngine::getGraphicsEngine()->getViewerByName( ( *iter ).second );
192  if( !view )
193  {
194  wlog::warn( "Project Loader" ) << "Project file contained a camera \"" << ( *iter ).second << "\" but the corresponding view does " <<
195  "not exist. Ignoring.";
196  }
197 
198  // did we have a matrix?
199  if( !m_manipulatorMatrices.count( ( *iter ).first ) )
200  {
201  wlog::warn( "Project Loader" ) << "Project file contained a camera \"" << ( *iter ).second << "\" but no proper manipulator matrix. " <<
202  "Leaving current matrix untouched.";
203  }
204  else
205  {
206  view->getCameraManipulator()->setByMatrix( m_manipulatorMatrices[ ( *iter ).first ] );
207  }
208 
209  // home position found?
210  if( ( !m_homeEyeVectors.count( ( *iter ).first ) ) ||
211  ( !m_homeCenterVectors.count( ( *iter ).first ) ) ||
212  ( !m_homeUpVectors.count( ( *iter ).first ) )
213  )
214  {
215  wlog::warn( "Project Loader" ) << "Project file contained a camera \"" << ( *iter ).second << "\" but no proper manipulator home " <<
216  "position. Leaving current home untouched.";
217  }
218  else
219  {
220  view->getCameraManipulator()->setHomePosition( m_homeEyeVectors[ ( *iter ).first ],
221  m_homeCenterVectors[ ( *iter ).first ],
222  m_homeUpVectors[ ( *iter ).first ]
223  );
224  }
225  }
226 }
227 
228 void WGEProjectFileIO::save( std::ostream& output ) // NOLINT
229 {
230  output << "//////////////////////////////////////////////////////////////////////////////////////////////////////////////////" << std::endl <<
231  "// Camera definitions" << std::endl <<
232  "//////////////////////////////////////////////////////////////////////////////////////////////////////////////////" << std::endl <<
233  std::endl;
234 
235  // grab the main camera
236  osg::ref_ptr< osg::Camera > cam = WGraphicsEngine::getGraphicsEngine()->getViewer()->getCamera();
237  osg::ref_ptr< osgGA::MatrixManipulator > mani = WGraphicsEngine::getGraphicsEngine()->getViewer()->getCameraManipulator();
238  std::string name = WGraphicsEngine::getGraphicsEngine()->getViewer()->getName();
239  output << "CAMERA:0:" << name << std::endl;
240 
241  // NOTE: OSG uses manipulators to modify the camera's view and projection matrix every frame. -> it is useless to store view and projection
242  // matrix as these get overwritten every frame -> we need to store the manipulator settings here.
243 
244  // get the matrices
245  osg::Matrixd view = mani->getMatrix();
246 
247  output << "//Camera Matrices: \"" << name << "\"" << std::endl;
248  output << " MANIPULATOR:(0,Matrix)=";
249  for( unsigned int i = 0; i < 16; ++i )
250  {
251  output << view.ptr()[i];
252  if( i < 15 )
253  {
254  output << ";";
255  }
256  }
257  output << std::endl;
258 
259  // get home position
260  osg::Vec3d eye;
261  osg::Vec3d center;
262  osg::Vec3d up;
263  mani->getHomePosition( eye, center, up );
264 
265  // write them
266  // NOTE: vec3d already provides a << operator but it writes the vector in a space separated style -> this is not conform to our common style
267  // -> we manually print them
268  output << " MANIPULATOR:(0,HomeEye)=";
269  output << eye.x() << ";" << eye.y() << ";" << eye.z() << std::endl;
270  output << " MANIPULATOR:(0,HomeCenter)=";
271  output << center.x() << ";" << center.y() << ";" << center.z() << std::endl;
272  output << " MANIPULATOR:(0,HomeUp)=";
273  output << up.x() << ";" << up.y() << ";" << up.z() << std::endl;
274 
275  output << "//Camera Matrices END: \"" << name << "\"" << std::endl;
276 }
277