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