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>
24 #include <vtkOpenGLPolyDataMapper.h>
36 #include <qtextstream.h>
55 mTargetSpaceIsR =
true;
58 void Texture3DSlicerProxyImpl::generateAndSetShaders()
63 std::string vtk_dec =
"//VTK::PositionVC::Dec";
64 mOpenGLPolyDataMapper->AddShaderReplacement(
75 std::string vtk_impl =
"//VTK::PositionVC::Impl";
76 mOpenGLPolyDataMapper->AddShaderReplacement(
87 mOpenGLPolyDataMapper->SetFragmentShaderCode(
getFS(mShaderCallback->getNumberOfUploadedTextures()).c_str());
91 mSharedOpenGLContext(context)
93 mShaderCallback = ShaderCallbackPtr::New();
95 QString unique_string =
qstring_cast(
reinterpret_cast<long>(
this));
96 mUid = QString(
"Texture3DSlicerProxyImpl_%1").arg(unique_string);
97 mTargetSpaceIsR =
false;
99 mActor = vtkActorPtr::New();
101 mOpenGLPolyDataMapper = vtkOpenGLPolyDataMapperPtr::New();
102 mOpenGLPolyDataMapper->AddObserver(vtkCommand::UpdateShaderEvent, mShaderCallback);
104 mPlaneSource = vtkPlaneSourcePtr::New();
107 triangleFilter->SetInputConnection(mPlaneSource->GetOutputPort());
110 stripper->SetInputConnection(triangleFilter->GetOutputPort());
112 mPolyDataAlgorithm = stripper;
113 mPolyDataAlgorithm->Update();
114 mPolyData = mPolyDataAlgorithm->GetOutput();
116 mOpenGLPolyDataMapper->SetInputConnection(mPolyDataAlgorithm->GetOutputPort());
117 mOpenGLPolyDataMapper->SetInputData(mPolyData);
119 this->generateAndSetShaders();
121 mActor->SetMapper(mOpenGLPolyDataMapper);
147 mCurrentRenderWindow = window;
152 if (!mTargetSpaceIsR)
157 this->resetGeometryPlane();
160 void Texture3DSlicerProxyImpl::resetGeometryPlane()
168 std::vector<Vector3D> pp_s;
170 for (
unsigned x=0; x<2; ++x)
171 for (
unsigned y=0; y<2; ++y)
172 for (
unsigned z=0; z<2; ++z)
174 pp_s.push_back(sMd.coord(bb_d.
corner(x,y,x)));
182 Vector3D origin(mBB_s[0], mBB_s[2], 0);
191 origin = rMs.coord(origin);
196 CX_LOG_DEBUG() <<
"zero-size bounding box in texture slicer- ignoring";
205 mPlaneSource->SetPoint1( point1_s.begin() );
206 mPlaneSource->SetPoint2( point2_s.begin() );
207 mPlaneSource->SetOrigin( origin_s.begin() );
209 mPolyDataAlgorithm->Update();
211 updateAndUploadCoordinates();
214 bool Texture3DSlicerProxyImpl::isNewInputImages(std::vector<ImagePtr> images_raw)
216 if (mRawImages==images_raw)
221 mRawImages = images_raw;
293 for (
unsigned i = 0; i < images.size(); ++i)
298 QString imageUid = images[i]->getUid();
300 if(sharedOpenGLContext && !sharedOpenGLContext->hasUploadedImage(imageUid))
302 sharedOpenGLContext->uploadImage(images[i]);
305 if(sharedOpenGLContext && sharedOpenGLContext->hasUploadedImage(imageUid))
308 shaderitem->mTextureUid = imageUid;
309 shaderitem->mTexture = sharedOpenGLContext->get3DTextureForImage(imageUid);
310 QString textureCoordinatesUid = this->generateTextureCoordinateName(imageUid);
312 if(sharedOpenGLContext->hasUploadedTextureCoordinates(textureCoordinatesUid))
314 shaderitem->mTextureCoordinatesUid = textureCoordinatesUid;
315 shaderitem->mTextureCoordinates = sharedOpenGLContext->getTextureCoordinates(textureCoordinatesUid);
318 shaderCallback->add(shaderitem);
322 CX_LOG_WARNING() <<
"Setting image in Texture3DSlicerProxyImpl which is not uploaded to OpenGL: " << imageUid;
329 std::vector<ImagePtr> C;
330 for(
int i=0; i<A.size(); ++i)
332 std::vector<ImagePtr>::iterator it = std::find(B.begin(), B.end(), A[i]);
336 CX_LOG_DEBUG() <<
"Going to delete: " << A[i]->getUid();
344 void Texture3DSlicerProxyImpl::updateAndUploadImages(std::vector<ImagePtr> new_images_raw)
347 std::vector<ImagePtr> unsigned_images = convertToUnsigned(new_images_raw);
351 for(
int i=0; i<to_be_deleted.size(); ++i)
353 mSharedOpenGLContext->delete3DTextureForImage(to_be_deleted[i]->getUid());
354 mSharedOpenGLContext->delete1DTextureForLUT(to_be_deleted[i]->getUid());
358 for (
unsigned i = 0; i < mImages.size(); ++i)
362 disconnect(mImages[i].get(), SIGNAL(vtkImageDataChanged(QString)),
this, SLOT(
uploadChangedImage(QString)));
365 mImages = unsigned_images;
367 for (
unsigned i = 0; i < mImages.size(); ++i)
371 connect(mImages[i].get(), SIGNAL(vtkImageDataChanged(QString)),
this, SLOT(
uploadChangedImage(QString)));
375 this->uploadImagesToSharedContext(mImages, mSharedOpenGLContext, mShaderCallback);
380 if (!this->isNewInputImages(images_raw))
386 mShaderCallback->clearShaderItems();
388 this->updateAndUploadImages(images_raw);
390 this->updateAndUploadCoordinates();
392 this->updateAndUploadColorAttribute();
395 this->generateAndSetShaders();
398 std::vector<ImagePtr> Texture3DSlicerProxyImpl::convertToUnsigned(std::vector<ImagePtr> images_raw)
400 std::vector<ImagePtr> images(images_raw.size());
402 for (
unsigned i=0; i<images.size(); ++i)
404 images[i] = images_raw[i]->getUnsigned(images_raw[i]);
418 mSliceProxy = slicer;
424 this->updateAndUploadCoordinates();
433 QString Texture3DSlicerProxyImpl::getTCoordName(
int index)
438 QString Texture3DSlicerProxyImpl::generateTextureCoordinateName(QString imageUid)
const
440 QString textureCoordinatesUid = QString(mUid+
"_%1").arg(imageUid);
441 return textureCoordinatesUid;
446 if(sharedOpenGLContext && textureCoordinates)
448 QString textureCoordinatesUid = this->generateTextureCoordinateName(image_uid);
449 sharedOpenGLContext->upload3DTextureCoordinates(textureCoordinatesUid, textureCoordinates);
451 if(sharedOpenGLContext->hasUploadedTextureCoordinates(textureCoordinatesUid))
457 item->mTextureCoordinates = sharedOpenGLContext->getTextureCoordinates(textureCoordinatesUid);
458 item->mTextureCoordinatesUid = textureCoordinatesUid;
496 void Texture3DSlicerProxyImpl::updateAndUploadCoordinates()
498 if (!mPolyData || !mSliceProxy)
503 for (
unsigned i = 0; i < mImages.size(); ++i)
510 Vector3D origin(volume->GetOrigin());
511 Vector3D spacing(volume->GetSpacing());
512 DoubleBoundingBox3D imageSize(volume->GetExtent());
514 for (
int j = 0; j < 3; ++j)
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);
521 DoubleBoundingBox3D textureSpace(0.0, 1.0, 0.0, 1.0, 0.0, 1.0);
524 Transform3D iMs = image->get_rMd().inv() * mSliceProxy->get_sMr().inv();
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);
539 for (
unsigned j = 0; j < plane.size(); ++j)
541 plane[j] = nMs.coord(plane[j]);
544 if (!mTextureCoordinates)
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);
557 for (
unsigned j = 0; j < plane.size(); ++j)
559 mTextureCoordinates->SetTuple3(j, plane[j][0], plane[j][1], plane[j][2]);
562 mPolyData->Modified();
564 this->uploadTextureCoordinatesToSharedContext(image->getUid(), mTextureCoordinates, mSharedOpenGLContext, mShaderCallback);
570 QString lutUid = imageUid;
573 sharedOpenGLContext->uploadLUT(lutUid, lut->GetTable());
575 if(sharedOpenGLContext->hasUploadedLUT(lutUid))
579 shaderItem->mLUT = sharedOpenGLContext->get1DTextureForLUT(lutUid);
580 shaderItem->mLUTUid = lutUid;
584 shaderItem->mWindow = window;
585 shaderItem->mLLR = llr;
586 shaderItem->mLevel = level;
587 shaderItem->mAlpha = alpha;
590 void Texture3DSlicerProxyImpl::updateAndUploadColorAttribute()
592 for (
unsigned i = 0; i < mImages.size(); ++i)
595 QString imageUid = image->getUid();
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();
616 this->uploadColorAttributesToSharedContext(imageUid, llr, lut, window, level, alpha, mSharedOpenGLContext, mShaderCallback);
626 this->resetGeometryPlane();
629 this->updateAndUploadCoordinates();
634 this->updateAndUploadColorAttribute();
641 for (
unsigned i = 0; i < mImages .size(); ++i)
644 if(mImages[i]->getUid() == uid)
646 this->mSharedOpenGLContext->uploadImage(image);