OpenWalnut  1.5.0dev
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 <memory>
27 #include <string>
28 #include <utility>
29 
30 #include <osg/Geometry>
31 #include <osg/LightModel>
32 #include <osg/LineWidth>
33 
34 #include "../common/WLogger.h"
35 #include "WGEGeodeUtils.h"
36 #include "WGEUtils.h"
37 #include "WGraphicsEngine.h"
38 #include "WROIBox.h"
39 #include "shaders/WGEShader.h"
40 
41 size_t WROIBox::maxBoxId = 0;
42 
44  WROI(),
45  boxId( maxBoxId++ ),
46  m_pickNormal( WVector3d() ),
47  m_oldPixelPosition( WVector2d::zero() ),
48  m_oldScrollWheel( 0 ),
49  m_color( osg::Vec4( 0.391f, 0.594f, 0.828f, 0.5f ) ),
50  m_notColor( osg::Vec4( 0.828f, 0.391f, 0.391f, 0.5f ) )
51 {
52  m_propGrp = m_properties->addPropertyGroup( "ROI Box", "Properties of this ROI Box" );
53  m_minPos = m_propGrp->addProperty( "Min Position", "When a box is described by its diagonal, this is the lower, left, front corner of it.",
54  minPos, boost::bind( &WROIBox::boxPropertiesChanged, this, boost::placeholders::_1 ) );
55  m_maxPos = m_propGrp->addProperty( "Max Position", "When a box is described by its diagonal, this is the upper, right, back corner of it.",
56  maxPos, boost::bind( &WROIBox::boxPropertiesChanged, this, boost::placeholders::_1 ) );
57 
58  std::shared_ptr< WGraphicsEngine > ge = WGraphicsEngine::getGraphicsEngine();
59  assert( ge );
60  std::shared_ptr< WGEViewer > viewer = ge->getViewerByName( "Main View" );
61  assert( viewer );
62  m_viewer = viewer;
63  m_pickHandler = m_viewer->getPickHandler();
64  m_pickHandler->getPickSignal()->connect( boost::bind( &WROIBox::registerRedrawRequest, this, boost::placeholders::_1 ) );
65 
66  std::stringstream ss;
67  ss << "ROIBox" << boxId;
68  setName( ss.str() );
69 
70  osg::StateSet* state = getOrCreateStateSet();
71  state->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
72 
73  osg::LineWidth* linewidth = new osg::LineWidth();
74  linewidth->setWidth( 2.0f );
75  state->setAttributeAndModes( linewidth, osg::StateAttribute::ON );
76 
77  osg::ref_ptr< osg::LightModel > lightModel = new osg::LightModel();
78  lightModel->setTwoSided( true );
79  //state->setAttributeAndModes( lightModel.get(), osg::StateAttribute::ON );
80  state->setMode( GL_BLEND, osg::StateAttribute::ON );
81 
82  // add a simple default lighting shader
83  m_lightShader = new WGEShader( "WGELighting" );
84 
85  m_not->set( false );
86 
88  WGraphicsEngine::getGraphicsEngine()->getScene()->addChild( this );
89 
90  setUserData( this );
91  setUpdateCallback( osg::ref_ptr<ROIBoxNodeCallback>( new ROIBoxNodeCallback ) );
92 
93  m_lightShader->apply( this );
94 
95  m_needVertexUpdate = true;
96  setDirty();
97 }
98 
99 WROIBox::~WROIBox()
100 {
101 }
102 
104 {
105  return m_minPos->get();
106 }
107 
109 {
110  return m_maxPos->get();
111 }
112 
114 {
115  return m_minPos;
116 }
117 
119 {
120  return m_maxPos;
121 }
122 
124 {
125  std::unique_lock< std::shared_mutex > lock;
126  lock = std::unique_lock< std::shared_mutex >( m_updateLock );
127 
128  m_pickInfo = pickInfo;
129 
130  lock.unlock();
131 }
132 
133 void WROIBox::boxPropertiesChanged( std::shared_ptr< WPropertyBase > /* property */ )
134 {
135  m_needVertexUpdate = true;
136 }
137 
139 {
140  std::unique_lock< std::shared_mutex > lock;
141  lock = std::unique_lock< std::shared_mutex >( m_updateLock );
142 
143  std::stringstream ss;
144  ss << "ROIBox" << boxId << "";
145  if( m_pickInfo.getName() == ss.str() )
146  {
147  WVector2d newPixelPos( m_pickInfo.getPickPixel() );
148  if( m_isPicked )
149  {
150  osg::Vec3 in( newPixelPos.x(), newPixelPos.y(), 0.0 );
151  osg::Vec3 world = wge::unprojectFromScreen( in, m_viewer->getCamera() );
152 
153  // we want the vector pointing into the screen in world coordinates
154  // NOTE: set w = 0 to use it as vector and ignore translation
155  osg::Vec4 toDepth = wge::unprojectFromScreen( osg::Vec4( 0.0, 0.0, 1.0, 0.0 ), m_viewer->getCamera() );
156  toDepth.normalize();
157  WPosition toDepthWorld( toDepth[0], toDepth[1], toDepth[2] );
158 
159  float depthMove = m_pickInfo.getScrollWheel() - m_oldScrollWheel;
160 
161  WPosition newPixelWorldPos( world[0], world[1], world[2] );
162  WPosition oldPixelWorldPos;
163  if( m_oldPixelPosition.x() == 0 && m_oldPixelPosition.y() == 0 )
164  {
165  oldPixelWorldPos = newPixelWorldPos;
166  }
167  else
168  {
169  osg::Vec3 in( m_oldPixelPosition.x(), m_oldPixelPosition.y(), 0.0 );
170  osg::Vec3 world = wge::unprojectFromScreen( in, m_viewer->getCamera() );
171  oldPixelWorldPos = WPosition( world[0], world[1], world[2] );
172  }
173 
174  WVector3d moveVec = newPixelWorldPos - oldPixelWorldPos;
175 
176  // resize Box
177  if( m_pickInfo.getModifierKey() == WPickInfo::SHIFT )
178  {
179  if( m_pickNormal[0] <= 0 && m_pickNormal[1] <= 0 && m_pickNormal[2] <= 0 )
180  {
181  m_minPos->set( m_minPos->get() + ( m_pickNormal * dot( moveVec, m_pickNormal ) ) );
182  }
183  if( m_pickNormal[0] >= 0 && m_pickNormal[1] >= 0 && m_pickNormal[2] >= 0 )
184  {
185  m_maxPos->set( m_maxPos->get() + ( m_pickNormal * dot( moveVec, m_pickNormal ) ) );
186  }
187  // NOTE: this sets m_needVertexUpdate
188  }
189 
190  // move Box
191  if( m_pickInfo.getModifierKey() == WPickInfo::NONE )
192  {
193  m_minPos->set( m_minPos->get() + moveVec + ( 2.0 * toDepthWorld * depthMove ) );
194  m_maxPos->set( m_maxPos->get() + moveVec + ( 2.0 * toDepthWorld * depthMove ) );
195  // NOTE: this sets m_needVertexUpdate
196  }
197  }
198  else
199  {
201  // color for moving box
202  if( m_pickInfo.getModifierKey() == WPickInfo::NONE )
203  {
204  if( m_not->get() )
205  {
207  }
208  else
209  {
210  updateColor( m_color );
211  }
212  }
213  if( m_pickInfo.getModifierKey() == WPickInfo::SHIFT )
214  {
215  updateColor( osg::Vec4( 0.0f, 1.0f, 0.0f, 0.4f ) );
216  }
217 
219  }
220  m_oldPixelPosition = newPixelPos;
221  setDirty();
222  m_isPicked = true;
224  }
226  {
227  // Perform all actions necessary for finishing a pick
228  if( m_not->get() )
229  {
231  }
232  else
233  {
234  updateColor( m_color );
235  }
236 
238  m_isPicked = false;
239  }
240 
241  if( m_needVertexUpdate )
242  {
243  removeDrawable( m_surfaceGeometry );
244 
245  WPosition pos = getMinPos();
246  WPosition size = getMaxPos() - getMinPos();
247 
248  // create a new geometry
249  m_surfaceGeometry = wge::createCube( pos, size, WColor( 1.0, 1.0, 1.0, 1.0 ) );
250 
251  // create nice outline
252  m_surfaceGeometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINE_LOOP, 0, 4 ) );
253  m_surfaceGeometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINE_LOOP, 4, 4 ) );
254  m_surfaceGeometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINE_LOOP, 8, 4 ) );
255  m_surfaceGeometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINE_LOOP, 12, 4 ) );
256  m_surfaceGeometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINE_LOOP, 16, 4 ) );
257  m_surfaceGeometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINE_LOOP, 20, 4 ) );
258 
259  // name it and add to geode
260  m_surfaceGeometry->setDataVariance( osg::Object::DYNAMIC );
261  m_surfaceGeometry->setName( ss.str() );
262 
263  addDrawable( m_surfaceGeometry );
264 
265  // NOTE: as we set the roi dirty, we ensure the color gets set properly in the next if-statement.
266  setDirty();
267  m_needVertexUpdate = false;
268  }
269 
270  if( m_dirty->get() )
271  {
272  if( m_not->get() )
273  {
275  }
276  else
277  {
278  updateColor( m_color );
279  }
280  }
281 
282  lock.unlock();
283 }
284 
285 void WROIBox::setColor( osg::Vec4 color )
286 {
287  m_color = color;
288 }
289 
290 void WROIBox::setNotColor( osg::Vec4 color )
291 {
292  m_notColor = color;
293 }
294 
295 void WROIBox::updateColor( osg::Vec4 color )
296 {
297  osg::ref_ptr<osg::Vec4Array> colors = osg::ref_ptr<osg::Vec4Array>( new osg::Vec4Array );
298  colors->push_back( color );
299 
300  WColor outline( 0.0, 0.0, 0.0, 1.0 );
301  // NOTE: also add a black color for the solid outlines
302  colors->push_back( outline );
303  colors->push_back( outline );
304  colors->push_back( outline );
305  colors->push_back( outline );
306  colors->push_back( outline );
307  colors->push_back( outline );
308  m_surfaceGeometry->setColorArray( colors );
309  m_surfaceGeometry->setColorBinding( osg::Geometry::BIND_PER_PRIMITIVE_SET );
310 }
Class encapsulating the OSG Program class for a more convenient way of adding and modifying shader.
Definition: WGEShader.h:48
static std::shared_ptr< WGraphicsEngine > getGraphicsEngine()
Returns instance of the graphics engine.
ValueT & y()
Access y element of vector.
ValueT & x()
Access x element of vector.
static const std::string unpickString
The string indicating picking has stopped.
Definition: WPickHandler.h:104
Encapsulates info for pick action.
Definition: WPickInfo.h:42
WVector2d getPickPixel() const
Returns the picked pixel coordinates in screen-space.
Definition: WPickInfo.h:275
WVector3d getPickNormal() const
Get normal at position where object was hit.
Definition: WPickInfo.h:258
int32_t getScrollWheel() const
Returns an integer denoting the wheel movement.
Definition: WPickInfo.h:283
std::string getName() const
Get name of picked object.
Definition: WPickInfo.h:243
modifierKey getModifierKey() const
Get the modifier key associated with the pick.
Definition: WPickInfo.h:223
This only is a 3d double vector.
Node callback to handle updates properly.
Definition: WROIBox.h:152
static size_t maxBoxId
Current maximum boxId over all boxes.
Definition: WROIBox.h:102
void setNotColor(osg::Vec4 color)
Setter for color in negated state.
Definition: WROIBox.cpp:290
WROIBox(WPosition minPos, WPosition maxPos)
Yields box with desired extremal points minPos and maxPos.
Definition: WROIBox.cpp:43
osg::Vec4 m_notColor
the color of the box when negated
Definition: WROIBox.h:135
WPropPosition getMinPosProperty()
Get the corner of the box that has minimal x, y and z values.
Definition: WROIBox.cpp:113
std::shared_ptr< WGEViewer > m_viewer
makes viewer available all over this class.
Definition: WROIBox.h:131
WVector3d m_pickNormal
Store the normal that occured when the pick action was started.
Definition: WROIBox.h:123
void updateColor(osg::Vec4 color)
Set new color of the box in the geometry.
Definition: WROIBox.cpp:295
WPosition getMinPos() const
Get the corner of the box that has minimal x, y and z values.
Definition: WROIBox.cpp:103
WPickInfo m_pickInfo
Stores the pick information for potential redraw.
Definition: WROIBox.h:129
WVector2d m_oldPixelPosition
Caches the old picked position to a allow for cmoparison.
Definition: WROIBox.h:124
WPropPosition m_minPos
The minimum position of the box.
Definition: WROIBox.h:109
osg::Vec4 m_color
the color of the box
Definition: WROIBox.h:133
int16_t m_oldScrollWheel
caches scroll wheel value
Definition: WROIBox.h:125
void registerRedrawRequest(WPickInfo pickInfo)
note that there was a pick
Definition: WROIBox.cpp:123
osg::ref_ptr< osg::Geometry > m_surfaceGeometry
store this pointer for use in updates
Definition: WROIBox.h:127
WPropPosition getMaxPosProperty()
Get the corner of the box that has maximal x, y and z values.
Definition: WROIBox.cpp:118
WPosition getMaxPos() const
Get the corner of the box that has maximal x, y and z values.
Definition: WROIBox.cpp:108
bool m_isPicked
Indicates whether the box is currently picked or not.
Definition: WROIBox.h:121
virtual void updateGFX()
updates the graphics
Definition: WROIBox.cpp:138
size_t boxId
Id of the current box.
Definition: WROIBox.h:103
WPropGroup m_propGrp
Group for box specific props.
Definition: WROIBox.h:108
WPropPosition m_maxPos
The maximum position of the box.
Definition: WROIBox.h:110
WGEShader::RefPtr m_lightShader
Shader for proper lighting.
Definition: WROIBox.h:115
bool m_needVertexUpdate
If true, the box' vertex data is updated.
Definition: WROIBox.h:120
void setColor(osg::Vec4 color)
Setter for standard color.
Definition: WROIBox.cpp:285
void boxPropertiesChanged(std::shared_ptr< WPropertyBase > property)
Called when the specified property has changed.
Definition: WROIBox.cpp:133
std::shared_mutex m_updateLock
Lock to prevent concurrent threads trying to update the osg node.
Definition: WROIBox.h:126
Superclass for different ROI (region of interest) types.
Definition: WROI.h:45
osg::ref_ptr< WPickHandler > m_pickHandler
A pointer to the pick handler used to get gui events for moving the box.
Definition: WROI.h:172
std::shared_ptr< WProperties > m_properties
the property object for the module
Definition: WROI.h:177
WPropBool m_not
indicates if the roi is negated
Definition: WROI.h:198
void setDirty()
sets the dirty flag
Definition: WROI.cpp:119
WPropBool m_dirty
dirty flag, indicating the graphics needs updating, it is no longer used for bitfield updating since ...
Definition: WROI.h:183
osg::Vec3 unprojectFromScreen(const osg::Vec3 screen, osg::ref_ptr< WGECamera > camera)
Converts screen coordinates into Camera coordinates.
Definition: WGEUtils.cpp:52
void createCube(osg::ref_ptr< osg::Geometry > geometry, const WPosition &position, const WPosition &size, const WColor &color)
Create an arbitrary cube and insert it into the given geometry.