CustusX  2023.01.05-dev+develop.0da12
An IGT application
cxTexture3DSlicerProxy.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
11 
12 #include "cxTexture3DSlicerProxy.h"
13 
14 #include <vtkRenderer.h>
15 #include <vtkFloatArray.h>
16 #include <vtkPlaneSource.h>
17 #include <vtkPointData.h>
18 #include <vtkTriangleFilter.h>
19 #include <vtkStripper.h>
20 #include <vtkImageData.h>
21 #include <vtkLookupTable.h>
22 #include <vtkOpenGLRenderWindow.h>
23 
24 #include <vtkOpenGLPolyDataMapper.h>
25 
26 #include "cxImage.h"
27 #include "cxView.h"
28 #include "cxImageLUT2D.h"
29 #include "cxSliceProxy.h"
30 #include "cxTypeConversions.h"
31 #include "cxGPUImageBuffer.h"
32 #include "cxReporter.h"
33 #include "cxConfig.h"
34 
35 #include "cxDataLocations.h"
36 #include <qtextstream.h>
37 
38 #include "cxSharedOpenGLContext.h"
39 #include "cxOpenGLShaders.h"
40 
41 namespace cx
42 {
43 
44 //---------------------------------------------------------
45 
47 {
48  return Texture3DSlicerProxyImpl::New(context);
49 }
50 //---------------------------------------------------------
51 
52 
54 {
55  mTargetSpaceIsR = true;
56 }
57 
58 void Texture3DSlicerProxyImpl::generateAndSetShaders()
59 {
60  //===========
61  // Modify vertex shader declarations
62  //===========
63  std::string vtk_dec = "//VTK::PositionVC::Dec";
64  mOpenGLPolyDataMapper->AddShaderReplacement(
65  vtkShader::Vertex,
66  vtk_dec, // replace the normal block
67  true, // before the standard replacements
68  getVSReplacement_dec(vtk_dec, mShaderCallback->getNumberOfUploadedTextures()),
69  false // only do it once
70  );
71 
72  //===========
73  // Modify vertex shader implementations
74  //===========
75  std::string vtk_impl = "//VTK::PositionVC::Impl";
76  mOpenGLPolyDataMapper->AddShaderReplacement(
77  vtkShader::Vertex,
78  vtk_impl, // replace the normal block
79  true, // before the standard replacements
80  getVSReplacement_impl(vtk_impl, mShaderCallback->getNumberOfUploadedTextures()),
81  false // only do it once
82  );
83 
84  //===========
85  // Replace the fragment shader
86  //===========
87  mOpenGLPolyDataMapper->SetFragmentShaderCode(getFS(mShaderCallback->getNumberOfUploadedTextures()).c_str());
88 }
89 
91  mSharedOpenGLContext(context)
92 {
93  mShaderCallback = ShaderCallbackPtr::New();
94 
95  QString unique_string = qstring_cast(reinterpret_cast<long>(this));
96  mUid = QString("Texture3DSlicerProxyImpl_%1").arg(unique_string);
97  mTargetSpaceIsR = false;
98 
99  mActor = vtkActorPtr::New();
100 
101  mOpenGLPolyDataMapper = vtkOpenGLPolyDataMapperPtr::New();
102  mOpenGLPolyDataMapper->AddObserver(vtkCommand::UpdateShaderEvent, mShaderCallback);
103 
104  mPlaneSource = vtkPlaneSourcePtr::New();
105 
106  vtkTriangleFilterPtr triangleFilter = vtkTriangleFilterPtr::New(); //create triangle polygons from input polygons
107  triangleFilter->SetInputConnection(mPlaneSource->GetOutputPort()); //in this case a Planesource
108 
109  vtkStripperPtr stripper = vtkStripperPtr::New();
110  stripper->SetInputConnection(triangleFilter->GetOutputPort());
111 
112  mPolyDataAlgorithm = stripper;
113  mPolyDataAlgorithm->Update();
114  mPolyData = mPolyDataAlgorithm->GetOutput();
115 
116  mOpenGLPolyDataMapper->SetInputConnection(mPolyDataAlgorithm->GetOutputPort());
117  mOpenGLPolyDataMapper->SetInputData(mPolyData);
118 
119  this->generateAndSetShaders();
120 
121  mActor->SetMapper(mOpenGLPolyDataMapper);
122 }
123 
124 
126 {
127  mImages.clear();
128 }
129 
131 {
133 }
134 
136 {
137  return mActor;
138 }
139 
140 std::vector<ImagePtr> Texture3DSlicerProxyImpl::getImages()
141 {
142  return mImages;
143 }
144 
146 {
147  mCurrentRenderWindow = window;
148 }
149 
151 {
152  if (!mTargetSpaceIsR)
153  {
154  mBB_s = transform(vpMs.inv(), vp);
155  }
156 
157  this->resetGeometryPlane();
158 }
159 
160 void Texture3DSlicerProxyImpl::resetGeometryPlane()
161 {
162  if (mTargetSpaceIsR)
163  {
164  // use largest bb from all volume box vertices projected onto s:
165  Transform3D rMs = mSliceProxy->get_sMr().inv();
166  DoubleBoundingBox3D bb_d = mImages[0]->boundingBox();
167  Transform3D sMd = rMs.inv()*mImages[0]->get_rMd();
168  std::vector<Vector3D> pp_s;
169 
170  for (unsigned x=0; x<2; ++x)
171  for (unsigned y=0; y<2; ++y)
172  for (unsigned z=0; z<2; ++z)
173  {
174  pp_s.push_back(sMd.coord(bb_d.corner(x,y,x)));
175  }
176 
177  mBB_s = DoubleBoundingBox3D::fromCloud(pp_s);
178  mBB_s[4] = 0;
179  mBB_s[5] = 0;
180  }
181 
182  Vector3D origin(mBB_s[0], mBB_s[2], 0);
183  Vector3D p1(mBB_s[1], mBB_s[2], 0);
184  Vector3D p2(mBB_s[0], mBB_s[3], 0);
185 
186  if (mTargetSpaceIsR)
187  {
188  Transform3D rMs = mSliceProxy->get_sMr().inv();
189  p1 = rMs.coord(p1);
190  p2 = rMs.coord(p2);
191  origin = rMs.coord(origin);
192  }
193 
194  if (similar(mBB_s.range()[0] * mBB_s.range()[1], 0.0))
195  {
196  CX_LOG_DEBUG() << "zero-size bounding box in texture slicer- ignoring";
197  return;
198  }
199 
200  createGeometryPlane(p1, p2, origin);
201 }
202 
204 {
205  mPlaneSource->SetPoint1( point1_s.begin() );
206  mPlaneSource->SetPoint2( point2_s.begin() );
207  mPlaneSource->SetOrigin( origin_s.begin() );
208 
209  mPolyDataAlgorithm->Update();
210 
211  updateAndUploadCoordinates();
212 }
213 
214 bool Texture3DSlicerProxyImpl::isNewInputImages(std::vector<ImagePtr> images_raw)
215 {
216  if (mRawImages==images_raw)
217  {
218  return false;
219  }
220 
221  mRawImages = images_raw;
222  return true;
223 }
224 
225 /*
226 void Texture3DSlicerProxyImpl::setImages(std::vector<ImagePtr> images_raw)
227 {
228  if (!this->isNewInputImages(images_raw))
229  {
230  return;
231  }
232 
233  std::vector<ImagePtr> images = processImages(images_raw);
234 
235  for (unsigned i = 0; i < mImages.size(); ++i)
236  {
237  disconnect(mImages[i].get(), SIGNAL(transformChanged()), this, SLOT(transformChangedSlot()));
238  disconnect(mImages[i].get(), SIGNAL(transferFunctionsChanged()), this, SLOT(updateColorAttributeSlot()));
239  disconnect(mImages[i].get(), SIGNAL(vtkImageDataChanged()), this, SLOT(imageChanged()));
240  }
241 
242  mImages = images;
243 
244  //Clear all shaderitems before re-adding them.
245  mShaderCallback->clearShaderItems();
246 
247  for (unsigned i = 0; i < mImages.size(); ++i)
248  {
249  //TODO maybe we should upload the textures here instead???
250  //we have a problem with Kaisa, because it is converted and thus not added to the viewgroup which causes it not to be uploaded
251  //New Kaisa gets new uid with *_u
252  QString imageUid = mImages[i]->getUid();
253 
254  if(mSharedOpenGLContext && !mSharedOpenGLContext->hasUploaded3DTexture(imageUid))
255  {
256  mSharedOpenGLContext->uploadImage(mImages[i]);
257  }
258 
259  if(mSharedOpenGLContext && mSharedOpenGLContext->hasUploaded3DTexture(imageUid))
260  {
261  ShaderCallback::ShaderItemPtr shaderitem = ShaderCallback::ShaderItemPtr(new ShaderCallback::ShaderItem());
262  shaderitem->mTextureUid = imageUid;
263  shaderitem->mTexture = mSharedOpenGLContext->get3DTexture(imageUid);
264  QString textureCoordinatesUid = this->generateTextureCoordinateName(imageUid);
265 
266  if(mSharedOpenGLContext->hasUploadedTextureCoordinates(textureCoordinatesUid))
267  {
268  shaderitem->mTextureCoordinatesUid = textureCoordinatesUid;
269  shaderitem->mTextureCoordinates = mSharedOpenGLContext->getTextureCoordinates(textureCoordinatesUid);
270  }
271 
272  mShaderCallback->add(shaderitem);
273  }
274  else
275  {
276  CX_LOG_WARNING() << "Setting image in Texture3DSlicerProxyImpl which is not uploaded to OpenGL: " << imageUid;
277  }
278 
279  connect(mImages[i].get(), SIGNAL(transformChanged()), this, SLOT(transformChangedSlot()));
280  connect(mImages[i].get(), SIGNAL(transferFunctionsChanged()), this, SLOT(updateColorAttributeSlot()));
281  connect(mImages[i].get(), SIGNAL(vtkImageDataChanged()), this, SLOT(imageChanged()));
282  this->updateCoordinates(i);
283  }
284 
285  this->updateColorAttributeSlot();
286 
287  this->setShaders(); //when number of uploaded textures changes from 0 to 1 we need to set new shader code
288 }
289 */
290 
291 void Texture3DSlicerProxyImpl::uploadImagesToSharedContext(std::vector<ImagePtr> images, SharedOpenGLContextPtr sharedOpenGLContext, ShaderCallbackPtr shaderCallback) const
292 {
293  for (unsigned i = 0; i < images.size(); ++i)
294  {
295  //TODO:
296  //we have a problem with Kaisa, because it is converted and thus not added to the viewgroup which causes it not to be uploaded
297  //New Kaisa gets new uid with *_u
298  QString imageUid = images[i]->getUid();
299 
300  if(sharedOpenGLContext && !sharedOpenGLContext->hasUploadedImage(imageUid))
301  {
302  sharedOpenGLContext->uploadImage(images[i]);
303  }
304 
305  if(sharedOpenGLContext && sharedOpenGLContext->hasUploadedImage(imageUid))
306  {
308  shaderitem->mTextureUid = imageUid;
309  shaderitem->mTexture = sharedOpenGLContext->get3DTextureForImage(imageUid);
310  QString textureCoordinatesUid = this->generateTextureCoordinateName(imageUid);
311 
312  if(sharedOpenGLContext->hasUploadedTextureCoordinates(textureCoordinatesUid))
313  {
314  shaderitem->mTextureCoordinatesUid = textureCoordinatesUid;
315  shaderitem->mTextureCoordinates = sharedOpenGLContext->getTextureCoordinates(textureCoordinatesUid);
316  }
317 
318  shaderCallback->add(shaderitem);
319  }
320  else
321  {
322  CX_LOG_WARNING() << "Setting image in Texture3DSlicerProxyImpl which is not uploaded to OpenGL: " << imageUid;
323  }
324  }
325 }
326 
327 std::vector<ImagePtr> elementsInAButNotInB(std::vector<ImagePtr> A, std::vector<ImagePtr> B)
328 {
329  std::vector<ImagePtr> C;
330  for(int i=0; i<A.size(); ++i)
331  {
332  std::vector<ImagePtr>::iterator it = std::find(B.begin(), B.end(), A[i]);
333 
334  if(it == B.end())
335  {
336  CX_LOG_DEBUG() << "Going to delete: " << A[i]->getUid();
337  C.push_back(A[i]);
338  }
339  }
340 
341  return C;
342 }
343 
344 void Texture3DSlicerProxyImpl::updateAndUploadImages(std::vector<ImagePtr> new_images_raw)
345 {
346  //only unsigned images are supported on the gpu
347  std::vector<ImagePtr> unsigned_images = convertToUnsigned(new_images_raw);
348 
349  //removing unused textures from the gpu
350  std::vector<ImagePtr> to_be_deleted = elementsInAButNotInB(mImages, unsigned_images);
351  for(int i=0; i<to_be_deleted.size(); ++i)
352  {
353  mSharedOpenGLContext->delete3DTextureForImage(to_be_deleted[i]->getUid());
354  mSharedOpenGLContext->delete1DTextureForLUT(to_be_deleted[i]->getUid());
355  }
356 
357  //setup signals and slots
358  for (unsigned i = 0; i < mImages.size(); ++i)
359  {
360  disconnect(mImages[i].get(), SIGNAL(transformChanged()), this, SLOT(transformChangedSlot()));
361  disconnect(mImages[i].get(), SIGNAL(transferFunctionsChanged()), this, SLOT(transferFunctionChangedSlot()));
362  disconnect(mImages[i].get(), SIGNAL(vtkImageDataChanged(QString)), this, SLOT(uploadChangedImage(QString)));
363  }
364 
365  mImages = unsigned_images;
366 
367  for (unsigned i = 0; i < mImages.size(); ++i)
368  {
369  connect(mImages[i].get(), SIGNAL(transformChanged()), this, SLOT(transformChangedSlot()));
370  connect(mImages[i].get(), SIGNAL(transferFunctionsChanged()), this, SLOT(transferFunctionChangedSlot()));
371  connect(mImages[i].get(), SIGNAL(vtkImageDataChanged(QString)), this, SLOT(uploadChangedImage(QString)));
372  }
373 
374  //upload any new images to the gpu
375  this->uploadImagesToSharedContext(mImages, mSharedOpenGLContext, mShaderCallback);
376 }
377 
378 void Texture3DSlicerProxyImpl::setImages(std::vector<ImagePtr> images_raw)
379 {
380  if (!this->isNewInputImages(images_raw))
381  {
382  return;
383  }
384 
385  //Clear all shaderitems before re-adding them.
386  mShaderCallback->clearShaderItems();
387 
388  this->updateAndUploadImages(images_raw);
389 
390  this->updateAndUploadCoordinates();
391 
392  this->updateAndUploadColorAttribute();
393 
394  //when number of uploaded textures changes from 0 to 1 we need to set new shader code
395  this->generateAndSetShaders();
396 }
397 
398 std::vector<ImagePtr> Texture3DSlicerProxyImpl::convertToUnsigned(std::vector<ImagePtr> images_raw)
399 {
400  std::vector<ImagePtr> images(images_raw.size());
401 
402  for (unsigned i=0; i<images.size(); ++i)
403  {
404  images[i] = images_raw[i]->getUnsigned(images_raw[i]);
405  }
406 
407  return images;
408 }
409 
410 
412 {
413  if (mSliceProxy)
414  {
415  disconnect(mSliceProxy.get(), SIGNAL(transformChanged(Transform3D)), this, SLOT(transformChangedSlot()));
416  }
417 
418  mSliceProxy = slicer;
419 
420  if (mSliceProxy)
421  {
422  connect(mSliceProxy.get(), SIGNAL(transformChanged(Transform3D)), this, SLOT(transformChangedSlot()));
423 
424  this->updateAndUploadCoordinates();
425  }
426 }
427 
429 {
430  return mSliceProxy;
431 }
432 
433 QString Texture3DSlicerProxyImpl::getTCoordName(int index)
434 {
435  return "texture"+qstring_cast(index);
436 }
437 
438 QString Texture3DSlicerProxyImpl::generateTextureCoordinateName(QString imageUid) const
439 {
440  QString textureCoordinatesUid = QString(mUid+"_%1").arg(imageUid);
441  return textureCoordinatesUid;
442 }
443 
444 void Texture3DSlicerProxyImpl::uploadTextureCoordinatesToSharedContext(QString image_uid, vtkFloatArrayPtr textureCoordinates, SharedOpenGLContextPtr sharedOpenGLContext, ShaderCallbackPtr shaderCallback) const
445 {
446  if(sharedOpenGLContext && textureCoordinates)
447  {
448  QString textureCoordinatesUid = this->generateTextureCoordinateName(image_uid);
449  sharedOpenGLContext->upload3DTextureCoordinates(textureCoordinatesUid, textureCoordinates);
450 
451  if(sharedOpenGLContext->hasUploadedTextureCoordinates(textureCoordinatesUid))
452  {
453  ShaderCallback::ShaderItemPtr item = shaderCallback->getShaderItem(image_uid);
454 
455  if(item)
456  {
457  item->mTextureCoordinates = sharedOpenGLContext->getTextureCoordinates(textureCoordinatesUid);
458  item->mTextureCoordinatesUid = textureCoordinatesUid;
459  }
460  }
461 
462  /*
463  //DEBUGGING
464  CX_LOG_DEBUG() << "-------------- 1 TESTING DOWNLOAD!!! --------------";
465  vtkImageDataPtr imageData = mSharedOpenGLContext->downloadImageFromTextureBuffer(image->getUid());
466  //REQUIRE(imageData);
467 
468  vtkImageDataPtr imageData0 = image->getBaseVtkImageData();
469 
470  char* imagePtr = static_cast<char*>(imageData->GetScalarPointer());
471  char* imagePtr0 = static_cast<char*>(imageData0->GetScalarPointer());
472 
473  //imageData should now be equal to image0;
474  Eigen::Array3i dims(imageData->GetDimensions());
475  int size = dims[0]*dims[1]*dims[2];
476  for (int i = 0; i < size; ++i)
477  {
478  // std::cout << static_cast<int>(imagePtr[i]) << " ";
479  // std::cout << (unsigned)(imagePtr[i]) << " ";
480  // INFO(i);
481  // REQUIRE(imagePtr[i] == imagePtr0[i]);
482  if(imagePtr[i] != imagePtr0[i])
483  CX_LOG_DEBUG_CHECKPOINT() << i;
484  }
485  std::cout << std::endl;
486  CX_LOG_DEBUG() << "-------------- 2 TESTING DOWNLOAD!!! --------------";
487  //DEBUGGING
488  */
489  }
490  else
491  {
492  CX_LOG_WARNING() << "No mSharedOpenGLContext";
493  }
494 }
495 
496 void Texture3DSlicerProxyImpl::updateAndUploadCoordinates()
497 {
498  if (!mPolyData || !mSliceProxy)
499  {
500  return;
501  }
502 
503  for (unsigned i = 0; i < mImages.size(); ++i)
504  {
505 
506  ImagePtr image = mImages[i];
507  vtkImageDataPtr volume = image->getBaseVtkImageData();
508 
509  // create a bb describing the volume in physical (raw data) space
510  Vector3D origin(volume->GetOrigin());
511  Vector3D spacing(volume->GetSpacing());
512  DoubleBoundingBox3D imageSize(volume->GetExtent());
513 
514  for (int j = 0; j < 3; ++j)
515  {
516  imageSize[2 * j] = origin[j] + spacing[j] * (imageSize[2 * j] - 0.5);
517  imageSize[2 * j + 1] = origin[j] + spacing[j] * (imageSize[2 * j + 1] + 0.5);
518  }
519 
520  // identity bb
521  DoubleBoundingBox3D textureSpace(0.0, 1.0, 0.0, 1.0, 0.0, 1.0);
522 
523  // create transform from slice space to raw data space
524  Transform3D iMs = image->get_rMd().inv() * mSliceProxy->get_sMr().inv();
525 
526  // create transform from image space to texture normalized space
527  Transform3D nMi = createTransformNormalize(imageSize, textureSpace);
528 
529  // total transform from slice space to texture space
530  Transform3D nMs = nMi * iMs;
531 
532  // transform the viewport to texture coordinates (must use coords since bb3D doesnt handle non-axis-aligned transforms)
533  std::vector<Vector3D> plane(4);
534  plane[0] = mBB_s.corner(0, 0, 0);
535  plane[1] = mBB_s.corner(1, 0, 0);
536  plane[2] = mBB_s.corner(0, 1, 0);
537  plane[3] = mBB_s.corner(1, 1, 0);
538 
539  for (unsigned j = 0; j < plane.size(); ++j)
540  {
541  plane[j] = nMs.coord(plane[j]);
542  }
543 
544  if (!mTextureCoordinates)
545  {
546  mTextureCoordinates = vtkFloatArrayPtr::New();
547  mTextureCoordinates->SetNumberOfComponents(3);
548  mTextureCoordinates->Allocate(4 * 3);
549  mTextureCoordinates->InsertNextTuple3(0.0, 0.0, 0.0);
550  mTextureCoordinates->InsertNextTuple3(0.0, 0.0, 0.0);
551  mTextureCoordinates->InsertNextTuple3(0.0, 0.0, 0.0);
552  mTextureCoordinates->InsertNextTuple3(0.0, 0.0, 0.0);
553  mTextureCoordinates->SetName(cstring_cast(getTCoordName(i)));
554  mPolyData->GetPointData()->AddArray(mTextureCoordinates);
555  }
556 
557  for (unsigned j = 0; j < plane.size(); ++j)
558  {
559  mTextureCoordinates->SetTuple3(j, plane[j][0], plane[j][1], plane[j][2]);
560  }
561 
562  mPolyData->Modified();
563 
564  this->uploadTextureCoordinatesToSharedContext(image->getUid(), mTextureCoordinates, mSharedOpenGLContext, mShaderCallback);
565  }
566 }
567 
568 void Texture3DSlicerProxyImpl::uploadColorAttributesToSharedContext(QString imageUid, float llr, vtkLookupTablePtr lut, float window, float level, float alpha, SharedOpenGLContextPtr sharedOpenGLContext, ShaderCallbackPtr shaderCallback) const
569 {
570  QString lutUid = imageUid;
571  ShaderCallback::ShaderItemPtr shaderItem = shaderCallback->getShaderItem(lutUid);
572 
573  sharedOpenGLContext->uploadLUT(lutUid, lut->GetTable());
574 
575  if(sharedOpenGLContext->hasUploadedLUT(lutUid))
576  {
577  if(shaderItem)
578  {
579  shaderItem->mLUT = sharedOpenGLContext->get1DTextureForLUT(lutUid);
580  shaderItem->mLUTUid = lutUid;
581  }
582  }
583 
584  shaderItem->mWindow = window;
585  shaderItem->mLLR = llr;
586  shaderItem->mLevel = level;
587  shaderItem->mAlpha = alpha;
588 }
589 
590 void Texture3DSlicerProxyImpl::updateAndUploadColorAttribute()
591 {
592  for (unsigned i = 0; i < mImages.size(); ++i)
593  {
594  ImagePtr image = mImages[i];
595  QString imageUid = image->getUid();
596 
597  vtkImageDataPtr inputImage = image->getBaseVtkImageData() ;
598  vtkLookupTablePtr lut = image->getLookupTable2D()->getOutputLookupTable();
599 
600  //TODO this is a HACK
601  //for some reason the lut of the image is not marked as modified for the images where the transferfunction is actually modified
602  //that is why we set it here on all luts
603  //this results in that all luts will be uploaded to gpu every time someone changes any transferfunction...
604  //real fix would be to mark the images lut as modified when it actually happens...
605  //lut->GetTable()->Modified();
606 
607  //Generate window, level, llr, alpha
608  int scalarTypeMax = (int)inputImage->GetScalarTypeMax();
609  double imin = lut->GetRange()[0];
610  double imax = lut->GetRange()[1];
611  float window = (float) (imax-imin) / scalarTypeMax;
612  float llr = (float) mImages[i]->getLookupTable2D()->getLLR() / scalarTypeMax;
613  float level = (float) imin/scalarTypeMax + window/2;
614  float alpha = (float) mImages[i]->getLookupTable2D()->getAlpha();
615 
616  this->uploadColorAttributesToSharedContext(imageUid, llr, lut, window, level, alpha, mSharedOpenGLContext, mShaderCallback);
617  }
618 
619  mActor->Modified();
620 }
621 
623 {
624  if (mTargetSpaceIsR)
625  {
626  this->resetGeometryPlane();
627  }
628 
629  this->updateAndUploadCoordinates();
630 }
631 
633 {
634  this->updateAndUploadColorAttribute();
635 }
636 
638 {
639  mActor->Modified();
640 
641  for (unsigned i = 0; i < mImages .size(); ++i)
642  {
643  ImagePtr image = mImages[i];
644  if(mImages[i]->getUid() == uid)
645  {
646  this->mSharedOpenGLContext->uploadImage(image);
647  }
648  }
649 
650 }
651 
652 
653 } //namespace cx
654 
QString qstring_cast(const T &val)
DoubleBoundingBox3D transform(const Transform3D &m, const DoubleBoundingBox3D &bb)
vtkSmartPointer< class vtkActor > vtkActorPtr
Vector3D corner(int x, int y, int z) const
std::vector< ImagePtr > getImages()
vtkSmartPointer< class ShaderCallback > ShaderCallbackPtr
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
boost::shared_ptr< class SliceProxy > SliceProxyPtr
boost::shared_ptr< class Image > ImagePtr
Definition: cxDicomWidget.h:27
std::vector< ImagePtr > elementsInAButNotInB(std::vector< ImagePtr > A, std::vector< ImagePtr > B)
const std::string getVSReplacement_impl(std::string vtk_impl, int numberOfUploadedTextures)
vtkSmartPointer< class vtkFloatArray > vtkFloatArrayPtr
vtkSmartPointer< class vtkRenderWindow > vtkRenderWindowPtr
cstring_cast_Placeholder cstring_cast(const T &val)
const std::string getFS(int numberOfUploadedTextures)
static Texture3DSlicerProxyPtr New(SharedOpenGLContextPtr context)
void setTargetSpaceToR()
use to draw the slice in 3D r space instead of in 2D s space.
static DoubleBoundingBox3D fromCloud(std::vector< Vector3D > cloud)
Transform3D createTransformNormalize(const DoubleBoundingBox3D &in, const DoubleBoundingBox3D &out)
void setViewportData(const Transform3D &vpMs, const DoubleBoundingBox3D &vp)
virtual void setRenderWindow(vtkRenderWindowPtr window)
void setSliceProxy(SliceProxyPtr slicer)
boost::shared_ptr< class SharedOpenGLContext > SharedOpenGLContextPtr
vtkSmartPointer< class vtkTriangleFilter > vtkTriangleFilterPtr
void createGeometryPlane(Vector3D point1_s, Vector3D point2_s, Vector3D origin_s)
void setImages(std::vector< ImagePtr > images)
vtkSmartPointer< class vtkLookupTable > vtkLookupTablePtr
boost::shared_ptr< class Texture3DSlicerProxy > Texture3DSlicerProxyPtr
vtkSmartPointer< class vtkStripper > vtkStripperPtr
Representation of a floating-point bounding box in 3D. The data are stored as {xmin,xmax,ymin,ymax,zmin,zmax}, in order to simplify communication with vtk.
boost::shared_ptr< ShaderItem > ShaderItemPtr
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:42
#define CX_LOG_DEBUG
Definition: cxLogger.h:95
bool similar(const CameraInfo &lhs, const CameraInfo &rhs, double tol)
#define CX_LOG_WARNING
Definition: cxLogger.h:98
const std::string getVSReplacement_dec(std::string vtk_dec, int numberOfUploadedTextures)
vtkSmartPointer< class vtkImageData > vtkImageDataPtr
static Texture3DSlicerProxyPtr New(SharedOpenGLContextPtr context)
Texture3DSlicerProxyImpl(SharedOpenGLContextPtr context)
Namespace for all CustusX production code.