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