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