OpenWalnut  1.3.1
WROIBox.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 <algorithm>
26 #include <string>
27 #include <utility>
28 
29 #include <osg/LineWidth>
30 #include <osg/LightModel>
31 #include <osg/Geometry>
32 
33 #include "../common/WLogger.h"
34 
35 #include "WROIBox.h"
36 #include "WGraphicsEngine.h"
37 #include "WGEUtils.h"
38 
39 size_t WROIBox::maxBoxId = 0;
40 
41 void buildFacesFromPoints( osg::DrawElementsUInt* surfaceElements )
42 {
43  surfaceElements->push_back( 0 );
44  surfaceElements->push_back( 2 );
45  surfaceElements->push_back( 3 );
46  surfaceElements->push_back( 1 );
47 
48  surfaceElements->push_back( 2 );
49  surfaceElements->push_back( 6 );
50  surfaceElements->push_back( 7 );
51  surfaceElements->push_back( 3 );
52 
53  surfaceElements->push_back( 6 );
54  surfaceElements->push_back( 4 );
55  surfaceElements->push_back( 5 );
56  surfaceElements->push_back( 7 );
57 
58  surfaceElements->push_back( 4 );
59  surfaceElements->push_back( 0 );
60  surfaceElements->push_back( 1 );
61  surfaceElements->push_back( 5 );
62 
63  surfaceElements->push_back( 1 );
64  surfaceElements->push_back( 3 );
65  surfaceElements->push_back( 7 );
66  surfaceElements->push_back( 5 );
67 
68  surfaceElements->push_back( 0 );
69  surfaceElements->push_back( 4 );
70  surfaceElements->push_back( 6 );
71  surfaceElements->push_back( 2 );
72 }
73 
74 void buildLinesFromPoints( osg::DrawElementsUInt* surfaceElements )
75 {
76  surfaceElements->push_back( 0 );
77  surfaceElements->push_back( 2 );
78  surfaceElements->push_back( 2 );
79  surfaceElements->push_back( 3 );
80  surfaceElements->push_back( 3 );
81  surfaceElements->push_back( 1 );
82  surfaceElements->push_back( 1 );
83  surfaceElements->push_back( 0 );
84 
85  surfaceElements->push_back( 6 );
86  surfaceElements->push_back( 4 );
87  surfaceElements->push_back( 4 );
88  surfaceElements->push_back( 5 );
89  surfaceElements->push_back( 5 );
90  surfaceElements->push_back( 7 );
91  surfaceElements->push_back( 7 );
92  surfaceElements->push_back( 6 );
93 
94  surfaceElements->push_back( 2 );
95  surfaceElements->push_back( 6 );
96  surfaceElements->push_back( 7 );
97  surfaceElements->push_back( 3 );
98 
99  surfaceElements->push_back( 4 );
100  surfaceElements->push_back( 0 );
101  surfaceElements->push_back( 1 );
102  surfaceElements->push_back( 5 );
103 }
104 
105 void setVertices( osg::Vec3Array* vertices, WPosition minPos, WPosition maxPos )
106 {
107  vertices->push_back( osg::Vec3( minPos[0], minPos[1], minPos[2] ) );
108  vertices->push_back( osg::Vec3( minPos[0], minPos[1], maxPos[2] ) );
109  vertices->push_back( osg::Vec3( minPos[0], maxPos[1], minPos[2] ) );
110  vertices->push_back( osg::Vec3( minPos[0], maxPos[1], maxPos[2] ) );
111  vertices->push_back( osg::Vec3( maxPos[0], minPos[1], minPos[2] ) );
112  vertices->push_back( osg::Vec3( maxPos[0], minPos[1], maxPos[2] ) );
113  vertices->push_back( osg::Vec3( maxPos[0], maxPos[1], minPos[2] ) );
114  vertices->push_back( osg::Vec3( maxPos[0], maxPos[1], maxPos[2] ) );
115 }
116 
118  WROI(),
119  boxId( maxBoxId++ ),
120  m_pickNormal( WVector3d() ),
121  m_oldPixelPosition( WVector2d::zero() ),
122  m_oldScrollWheel( 0 ),
123  m_color( osg::Vec4( 0.f, 1.f, 1.f, 0.4f ) ),
124  m_notColor( osg::Vec4( 1.0f, 0.0f, 0.0f, 0.4f ) )
125 {
126  m_minPos = minPos;
127  m_maxPos = maxPos;
128 
129  boost::shared_ptr< WGraphicsEngine > ge = WGraphicsEngine::getGraphicsEngine();
130  assert( ge );
131  boost::shared_ptr< WGEViewer > viewer = ge->getViewerByName( "Main View" );
132  assert( viewer );
133  m_viewer = viewer;
134  m_pickHandler = m_viewer->getPickHandler();
135  m_pickHandler->getPickSignal()->connect( boost::bind( &WROIBox::registerRedrawRequest, this, _1 ) );
136 
137  m_surfaceGeometry = osg::ref_ptr<osg::Geometry>( new osg::Geometry() );
138  m_surfaceGeometry->setDataVariance( osg::Object::DYNAMIC );
139 
140  std::stringstream ss;
141  ss << "ROIBox" << boxId;
142 
143  setName( ss.str() );
144  m_surfaceGeometry->setName( ss.str() );
145 
146  osg::ref_ptr<osg::Vec3Array> vertices = osg::ref_ptr<osg::Vec3Array>( new osg::Vec3Array );
147  setVertices( vertices, minPos, maxPos );
148  m_surfaceGeometry->setVertexArray( vertices );
149 
150  osg::DrawElementsUInt* surfaceElements;
151  surfaceElements = new osg::DrawElementsUInt( osg::PrimitiveSet::QUADS, 0 );
152  buildFacesFromPoints( surfaceElements );
153 
154  osg::DrawElementsUInt* lineElements;
155  lineElements = new osg::DrawElementsUInt( osg::PrimitiveSet::LINES, 0 );
156  buildLinesFromPoints( lineElements );
157 
158  m_surfaceGeometry->addPrimitiveSet( surfaceElements );
159  m_surfaceGeometry->addPrimitiveSet( lineElements );
160  addDrawable( m_surfaceGeometry );
161  osg::StateSet* state = getOrCreateStateSet();
162  state->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
163 
164  osg::LineWidth* linewidth = new osg::LineWidth();
165  linewidth->setWidth( 2.f );
166  state->setAttributeAndModes( linewidth, osg::StateAttribute::ON );
167 
168  // ------------------------------------------------
169  // colors
170  osg::ref_ptr<osg::Vec4Array> colors = osg::ref_ptr<osg::Vec4Array>( new osg::Vec4Array );
171 
172  colors->push_back( osg::Vec4( 0.0f, 0.0f, 1.0f, 0.5f ) );
173  m_surfaceGeometry->setColorArray( colors );
174  m_surfaceGeometry->setColorBinding( osg::Geometry::BIND_OVERALL );
175 
176  osg::ref_ptr< osg::LightModel > lightModel = new osg::LightModel();
177  lightModel->setTwoSided( true );
178  state->setAttributeAndModes( lightModel.get(), osg::StateAttribute::ON );
179  state->setMode( GL_BLEND, osg::StateAttribute::ON );
180 
181  m_not->set( false );
182 
184  WGraphicsEngine::getGraphicsEngine()->getScene()->addChild( this );
185 
186  setUserData( this );
187  setUpdateCallback( osg::ref_ptr<ROIBoxNodeCallback>( new ROIBoxNodeCallback ) );
188 
189  setDirty();
190 }
191 
192 WROIBox::~WROIBox()
193 {
194 }
195 
197 {
198  return m_minPos;
199 }
200 
202 {
203  return m_maxPos;
204 }
205 
207 {
208  boost::unique_lock< boost::shared_mutex > lock;
209  lock = boost::unique_lock< boost::shared_mutex >( m_updateLock );
210 
211  m_pickInfo = pickInfo;
212 
213  lock.unlock();
214 }
215 
217 {
218  boost::unique_lock< boost::shared_mutex > lock;
219  lock = boost::unique_lock< boost::shared_mutex >( m_updateLock );
220 
221  std::stringstream ss;
222  ss << "ROIBox" << boxId << "";
223  if( m_pickInfo.getName() == ss.str() )
224  {
225  WVector2d newPixelPos( m_pickInfo.getPickPixel() );
226  if( m_isPicked )
227  {
228  osg::Vec3 in( newPixelPos.x(), newPixelPos.y(), 0.0 );
229  osg::Vec3 world = wge::unprojectFromScreen( in, m_viewer->getCamera() );
230 
231  // we want the vector pointing into the screen in world coordinates
232  // NOTE: set w = 0 to use it as vector and ignore translation
233  osg::Vec4 toDepth = wge::unprojectFromScreen( osg::Vec4( 0.0, 0.0, 1.0, 0.0 ), m_viewer->getCamera() );
234  toDepth.normalize();
235  WPosition toDepthWorld( toDepth[0], toDepth[1], toDepth[2] );
236 
237  float depthMove = m_pickInfo.getScrollWheel() - m_oldScrollWheel;
238 
239  WPosition newPixelWorldPos( world[0], world[1], world[2] );
240  WPosition oldPixelWorldPos;
241  if( m_oldPixelPosition.x() == 0 && m_oldPixelPosition.y() == 0 )
242  {
243  oldPixelWorldPos = newPixelWorldPos;
244  }
245  else
246  {
247  osg::Vec3 in( m_oldPixelPosition.x(), m_oldPixelPosition.y(), 0.0 );
248  osg::Vec3 world = wge::unprojectFromScreen( in, m_viewer->getCamera() );
249  oldPixelWorldPos = WPosition( world[0], world[1], world[2] );
250  }
251 
252  WVector3d moveVec = newPixelWorldPos - oldPixelWorldPos;
253 
254  osg::ref_ptr<osg::Vec3Array> vertices = osg::ref_ptr<osg::Vec3Array>( new osg::Vec3Array );
255 
256  // resize Box
257  if( m_pickInfo.getModifierKey() == WPickInfo::SHIFT )
258  {
259  if( m_pickNormal[0] <= 0 && m_pickNormal[1] <= 0 && m_pickNormal[2] <= 0 )
260  {
261  m_maxPos += m_pickNormal * dot( moveVec, m_pickNormal );
262  }
263  if( m_pickNormal[0] >= 0 && m_pickNormal[1] >= 0 && m_pickNormal[2] >= 0 )
264  {
265  m_minPos += m_pickNormal * dot( moveVec, m_pickNormal );
266  }
267 
268  setVertices( vertices, m_minPos, m_maxPos );
269  m_surfaceGeometry->setVertexArray( vertices );
270  }
271 
272  // move Box
273  if( m_pickInfo.getModifierKey() == WPickInfo::NONE )
274  {
275  m_minPos += moveVec;
276  m_maxPos += moveVec;
277 
278  m_minPos += 2.0 * toDepthWorld * depthMove;
279  m_maxPos += 2.0 * toDepthWorld * depthMove;
280  setVertices( vertices, m_minPos, m_maxPos );
281  m_surfaceGeometry->setVertexArray( vertices );
282  }
283  }
284  else
285  {
287  // color for moving box
288  if( m_pickInfo.getModifierKey() == WPickInfo::NONE )
289  {
290  osg::ref_ptr<osg::Vec4Array> colors = osg::ref_ptr<osg::Vec4Array>( new osg::Vec4Array );
291  if( m_not->get() )
292  {
293  colors->push_back( m_notColor );
294  }
295  else
296  {
297  colors->push_back( m_color );
298  }
299  m_surfaceGeometry->setColorArray( colors );
300  }
301  if( m_pickInfo.getModifierKey() == WPickInfo::SHIFT )
302  {
303  osg::ref_ptr<osg::Vec4Array> colors = osg::ref_ptr<osg::Vec4Array>( new osg::Vec4Array );
304  colors->push_back( osg::Vec4( 0.0f, 1.0f, 0.0f, 0.4f ) );
305  m_surfaceGeometry->setColorArray( colors );
306  }
307 
309  }
310  m_oldPixelPosition = newPixelPos;
311  setDirty();
312  m_isPicked = true;
314 
315  signalRoiChange();
316  }
317  if( m_isPicked && m_pickInfo.getName() == "unpick" )
318  {
319  // Perform all actions necessary for finishing a pick
320 
321  osg::ref_ptr<osg::Vec4Array> colors = osg::ref_ptr<osg::Vec4Array>( new osg::Vec4Array );
322  if( m_not->get() )
323  {
324  colors->push_back( m_notColor );
325  }
326  else
327  {
328  colors->push_back( m_color );
329  }
330  m_surfaceGeometry->setColorArray( colors );
332  m_isPicked = false;
333  }
334 
335  if( m_dirty->get() )
336  {
337  osg::ref_ptr<osg::Vec4Array> colors = osg::ref_ptr<osg::Vec4Array>( new osg::Vec4Array );
338  if( m_not->get() )
339  {
340  colors->push_back( m_notColor );
341  }
342  else
343  {
344  colors->push_back( m_color );
345  }
346  m_surfaceGeometry->setColorArray( colors );
347  }
348 
349  lock.unlock();
350 }
351 
352 void WROIBox::setColor( osg::Vec4 color )
353 {
354  m_color = color;
355 }
356 
357 void WROIBox::setNotColor( osg::Vec4 color )
358 {
359  m_notColor = color;
360 }