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