fw4spl
RendererService.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2018.
3  * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
4  * published by the Free Software Foundation.
5  * ****** END LICENSE BLOCK ****** */
6 
7 #include "vtkCompositeMesh/RendererService.hpp"
8 
9 #include <fwCom/Signal.hxx>
10 #include <fwCom/Slots.hxx>
11 
12 #include <fwData/Composite.hpp>
13 #include <fwData/Material.hpp>
14 #include <fwData/Mesh.hpp>
15 #include <fwData/TransformationMatrix3D.hpp>
16 
17 #include <fwServices/macros.hpp>
18 #include <fwServices/registry/ActiveWorkers.hpp>
19 
20 #include <fwVtkIO/helper/Mesh.hpp>
21 #include <fwVtkIO/vtk.hpp>
22 
23 #include <vtkCamera.h>
24 #include <vtkCommand.h>
25 #include <vtkInteractorStyleTrackballCamera.h>
26 #include <vtkMatrix4x4.h>
27 #include <vtkPolyData.h>
28 #include <vtkPolyDataMapper.h>
29 #include <vtkPolyDataNormals.h>
30 #include <vtkProperty.h>
31 #include <vtkRenderer.h>
32 #include <vtkRenderWindow.h>
33 #include <vtkTransform.h>
34 
36 
37 namespace vtkCompositeMesh
38 {
39 
40 const ::fwCom::Slots::SlotKeyType RendererService::s_UPDATE_CAM_POSITION_SLOT = "updateCamPosition";
41 const ::fwCom::Slots::SlotKeyType RendererService::s_UPDATE_PIPELINE_SLOT = "updatePipeline";
42 const ::fwCom::Signals::SignalKeyType RendererService::s_CAM_UPDATED_SIG = "camUpdated";
43 
44 class vtkLocalCommand : public vtkCommand
45 {
46 public:
47 
49  {
50  m_service = _service;
51  this->m_isMousePressed = false;
52  }
53  //------------------------------------------------------------------------------
54 
55  void Execute(vtkObject* _caller, unsigned long _event, void* _obj)
56  {
57  if (_event == vtkCommand::StartInteractionEvent )
58  {
59  this->m_isMousePressed = true;
60  }
61  else if (_event == vtkCommand::EndInteractionEvent )
62  {
63  this->m_isMousePressed = false;
64  }
65  else if ( (_event == vtkCommand::ModifiedEvent && this->m_isMousePressed)
66  || _event == vtkCommand::MouseWheelBackwardEvent || _event == vtkCommand::MouseWheelForwardEvent)
67  {
68  m_service->notifyCamPositionUpdated();
69  ::fwThread::Worker::sptr worker = m_service->getWorker();
70  worker->processTasks();
71  }
72  }
73 private:
75  bool m_isMousePressed;
76 };
77 
79  m_render( 0 ),
80  m_bPipelineIsInit(false)
81 {
82  m_slotUpdateCamPosition = newSlot( s_UPDATE_CAM_POSITION_SLOT, &RendererService::updateCamPosition, this );
83  newSlot(s_UPDATE_PIPELINE_SLOT, &RendererService::updatePipeline, this);
84 
85  m_sigCamUpdated = CamUpdatedSignalType::New();
86 
87  // Register
88  ::fwCom::HasSignals::m_signals( s_CAM_UPDATED_SIG, m_sigCamUpdated);
89 
90 }
91 
92 //-----------------------------------------------------------------------------
93 
95 {
96 }
97 
98 //-----------------------------------------------------------------------------
99 
101 {
102  FW_DEPRECATED_MSG("This service is no longer supported.", "18.0");
103 
104  this->IGuiContainerSrv::create();
105 
106  m_bPipelineIsInit = false;
107 
108  m_interactorManager = ::fwRenderVTK::IVtkRenderWindowInteractorManager::createManager();
109  m_interactorManager->installInteractor( this->getContainer() );
110 
111  // Renderer
112  m_render = vtkRenderer::New();
113  m_interactorManager->getInteractor()->GetRenderWindow()->AddRenderer(m_render);
114 }
115 
116 //-----------------------------------------------------------------------------
117 
119 {
120  this->IGuiContainerSrv::initialize();
121 }
122 
123 //-----------------------------------------------------------------------------
124 
126 {
127  if( m_render == 0 )
128  {
129  return;
130  }
131 
132  assert( m_interactorManager->getInteractor() );
133  m_interactorManager->getInteractor()->RemoveObserver(m_loc);
134 
135  m_interactorManager->uninstallInteractor();
136  m_interactorManager.reset();
137 
138  SLM_ASSERT("m_render not instanced", m_render);
139  m_render->Delete();
140  m_render = 0;
141 
142  this->IGuiContainerSrv::destroy();
143 }
144 
145 //-----------------------------------------------------------------------------
146 
148 {
149  m_interactorManager->getInteractor()->Render();
150 }
151 
152 //-----------------------------------------------------------------------------
153 
154 void RendererService::updateCamPosition(SharedArray positionValue,
155  SharedArray focalValue,
156  SharedArray viewUpValue)
157 {
158  vtkCamera* camera = m_render->GetActiveCamera();
159 
160  camera->SetPosition(positionValue.get());
161  camera->SetFocalPoint(focalValue.get());
162  camera->SetViewUp(viewUpValue.get());
163  camera->SetClippingRange(0.1, 1000000);
164 
165  m_interactorManager->getInteractor()->Render();
166 }
167 
168 //-----------------------------------------------------------------------------
169 
170 void RendererService::initVTKPipeline()
171 {
172  //Create the view:
173  createAndAddActorToRender();
174 }
175 
176 //-----------------------------------------------------------------------------
177 void RendererService::createAndAddActorToRender()
178 {
179  //Check there is indeed a Composite object in this:
180  assert(this->getObject< ::fwData::Composite >());
181 
182  //Create a pointer on this object:
183  ::fwData::Composite::sptr myComposite = this->getObject< ::fwData::Composite >();
184 
185  OSLM_INFO( "VTK Pipeline ready TO UPDATE" << '\n' << "Object received:" << myComposite->getLeafClassname());
186 
187  // elementnumber increases for each mesh found:
188  unsigned int elementNumber = 0;
189 
190  //Loop through the composite objects, if it's a mesh, then render it:
191  for(::fwData::Composite::ContainerType::const_iterator it = myComposite->begin(); it != myComposite->end(); ++it)
192  {
193  OSLM_INFO("ObjectName: " << it->first);
194  OSLM_INFO("ObjectPointer: " << it->second);
195  OSLM_INFO("ObjectType: " << it->second->getClassname() << '\n');
196 
197  ::fwData::Mesh::sptr myMesh = ::fwData::Mesh::dynamicCast(it->second);
198 
199  // If it's a mesh, then put it in the pipeline:
200  if( myMesh )
201  {
202  vtkSmartPointer<vtkPolyData> vtk_polyData = vtkSmartPointer<vtkPolyData>::New();
203  ::fwVtkIO::helper::Mesh::toVTKMesh( myMesh, vtk_polyData);
204  OSLM_INFO("Loaded: " << it->first);
205  vtkPolyDataMapper* mapper = vtkPolyDataMapper::New();
206 
207  m_normals = vtkPolyDataNormals::New();
208  m_normals->SetInputData(vtk_polyData);
209  mapper->SetInputConnection(m_normals->GetOutputPort());
210 
211  vtkActor* actor = vtkActor::New();
212  actor->SetMapper( mapper);
213 
214  // Add the actors
215  m_render->AddActor( actor);
216 
217  OSLM_INFO("Mesh found: " << it->first);
218  if (!myMesh->getField( "MaterialMesh" ))
219  {
220  // No Material data then default
221  if(elementNumber == 0)
222  {
223  actor->GetProperty()->EdgeVisibilityOn();
224  actor->GetProperty()->SetInterpolationToFlat();
225  actor->GetProperty()->SetColor(1.0, 0.0, 0.0);
226  actor->GetProperty()->SetEdgeColor(1.0, 0.0, 0.0);
227  }
228  else
229  {
230  actor->GetProperty()->SetRepresentationToWireframe();
231  actor->GetProperty()->SetColor(1.0, 1.0, 1.0);
232  }
233  }
234  else
235  {
236  // Material exists
237  ::fwData::Material::sptr matObjPtr = myMesh->getField< ::fwData::Material >( "MaterialMesh" );
238  actor->GetProperty()->SetColor(matObjPtr->diffuse()->red(),
239  matObjPtr->diffuse()->green(), matObjPtr->diffuse()->blue());
240  }
241  mapper->Delete();
242  elementNumber++;
243  OSLM_INFO("displayed: " << it->first);
244  }
245  }
246  m_interactorManager->getInteractor()->SetInteractorStyle(vtkInteractorStyleTrackballCamera::New());
247  m_loc = new vtkLocalCommand(this);
248  m_interactorManager->getInteractor()->AddObserver(vtkCommand::AnyEvent, m_loc);
249 
250  // Repaint and resize window
251  m_render->ResetCamera();
252 }
253 
254 //-----------------------------------------------------------------------------
255 
256 void RendererService::updateVTKPipeline()
257 {
258  //Clear the view:
259  m_render->RemoveAllViewProps();
260  //Recreate the view:
261  createAndAddActorToRender();
262 }
263 
264 //-----------------------------------------------------------------------------
265 
266 void RendererService::updatePipeline()
267 {
268  if(!m_bPipelineIsInit)
269  {
270  this->initVTKPipeline();
271  m_bPipelineIsInit = true;
272  }
273  else
274  {
275  this->updateVTKPipeline();
276  }
277  m_interactorManager->getInteractor()->Render();
278 }
279 
280 //-----------------------------------------------------------------------------
281 
283 {
284  vtkCamera* camera = m_render->GetActiveCamera();
285 
286  SharedArray position = SharedArray(new double[3]);
287  SharedArray focal = SharedArray(new double[3]);
288  SharedArray viewUp = SharedArray(new double[3]);
289 
290  std::copy(camera->GetPosition(), camera->GetPosition()+3, position.get());
291  std::copy(camera->GetFocalPoint(), camera->GetFocalPoint()+3, focal.get());
292  std::copy(camera->GetViewUp(), camera->GetViewUp()+3, viewUp.get());
293 
294  {
295  ::fwCom::Connection::Blocker block(m_sigCamUpdated->getConnection(m_slotUpdateCamPosition));
296  m_sigCamUpdated->asyncEmit(position, focal, viewUp);
297  }
298 }
299 
300 //-----------------------------------------------------------------------------
301 
303 {
304  KeyConnectionsType connections;
305  connections.push_back( std::make_pair( ::fwData::Object::s_MODIFIED_SIG, s_UPDATE_PIPELINE_SLOT ) );
306  return connections;
307 }
308 
309 }
virtual VTKCOMPOSITEMESH_API void starting() override
Starting method.
Class allowing to block a Connection.
Definition: Connection.hpp:20
This class defines a material. A material is represented by an ambient color and a diffuse color...
static FWVTKIO_API void toVTKMesh(const ::fwData::Mesh::csptr &_mesh, vtkSmartPointer< vtkPolyData > _polyData)
Convert a ::fwData::Mesh::csptr to a vtkPolyData.
Service rendering fwData::Mesh contained in a fwData::Composite using VTK.
#define OSLM_INFO(message)
Definition: spyLog.hpp:252
virtual VTKCOMPOSITEMESH_API void configuring() override
Configuring method.
#define FW_DEPRECATED_MSG(message, version)
Use this macro when deprecating a function to warn the developer.
Definition: spyLog.hpp:360
Defines the service interface managing the rendering service for object.
Definition: IRender.hpp:36
void notifyCamPositionUpdated()
This method is used to notify that the VTK camera position is updated.
virtual VTKCOMPOSITEMESH_API KeyConnectionsType getObjSrvConnections() const override
Returns proposals to connect service slots to associated object signals, this method is used for obj/...
virtual VTKCOMPOSITEMESH_API void stopping() override
Stopping method.
The namespace vtkCompositeMesh contains a service which renders several meshes and store it on Compos...
VTKCOMPOSITEMESH_API RendererService() noexcept
Constructor.
#define SLM_ASSERT(message, cond)
work like &#39;assert&#39; from &#39;cassert&#39;, with in addition a message logged by spylog (with FATAL loglevel) ...
Definition: spyLog.hpp:308
virtual VTKCOMPOSITEMESH_API void updating() override
Updating method.
static VTKCOMPOSITEMESH_APIconst::fwCom::Slots::SlotKeyType s_UPDATE_PIPELINE_SLOT
Slot to update pipeline.
::fwCom::helper::SigSlotConnection::KeyConnectionsType KeyConnectionsType
Returns proposals to connect service slots to associated object signals, this method is used for obj/...
Definition: IService.hpp:449
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_MODIFIED_SIG
Key in m_signals map of signal m_sigModified.
This class defines a composite object.
virtual VTKCOMPOSITEMESH_API ~RendererService() noexcept
Destructor.
FWSERVICES_API std::shared_ptr< ::fwThread::Worker > getWorker() const
Returns associate worker.
Definition: IService.cpp:419