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> 45 #include <vtkOpenGLPolyDataMapper.h> 57 #include <qtextstream.h> 77 mTargetSpaceIsR =
true;
80 void Texture3DSlicerProxyImpl::generateAndSetShaders()
85 std::string vtk_dec =
"//VTK::PositionVC::Dec";
86 mOpenGLPolyDataMapper->AddShaderReplacement(
97 std::string vtk_impl =
"//VTK::PositionVC::Impl";
98 mOpenGLPolyDataMapper->AddShaderReplacement(
109 mOpenGLPolyDataMapper->SetFragmentShaderCode(
getFS(mShaderCallback->getNumberOfUploadedTextures()).c_str());
113 mSharedOpenGLContext(context)
115 mShaderCallback = ShaderCallbackPtr::New();
117 QString unique_string =
qstring_cast(reinterpret_cast<long>(
this));
118 mUid = QString(
"Texture3DSlicerProxyImpl_%1").arg(unique_string);
119 mTargetSpaceIsR =
false;
121 mActor = vtkActorPtr::New();
123 mOpenGLPolyDataMapper = vtkOpenGLPolyDataMapperPtr::New();
124 mOpenGLPolyDataMapper->AddObserver(vtkCommand::UpdateShaderEvent, mShaderCallback);
126 mPlaneSource = vtkPlaneSourcePtr::New();
129 triangleFilter->SetInputConnection(mPlaneSource->GetOutputPort());
132 stripper->SetInputConnection(triangleFilter->GetOutputPort());
134 mPolyDataAlgorithm = stripper;
135 mPolyDataAlgorithm->Update();
136 mPolyData = mPolyDataAlgorithm->GetOutput();
138 mOpenGLPolyDataMapper->SetInputConnection(mPolyDataAlgorithm->GetOutputPort());
139 mOpenGLPolyDataMapper->SetInputData(mPolyData);
141 this->generateAndSetShaders();
143 mActor->SetMapper(mOpenGLPolyDataMapper);
169 mCurrentRenderWindow = window;
174 if (!mTargetSpaceIsR)
179 this->resetGeometryPlane();
182 void Texture3DSlicerProxyImpl::resetGeometryPlane()
190 std::vector<Vector3D> pp_s;
192 for (
unsigned x=0; x<2; ++x)
193 for (
unsigned y=0; y<2; ++y)
194 for (
unsigned z=0; z<2; ++z)
196 pp_s.push_back(sMd.coord(bb_d.
corner(x,y,x)));
204 Vector3D origin(mBB_s[0], mBB_s[2], 0);
213 origin = rMs.coord(origin);
218 CX_LOG_DEBUG() <<
"zero-size bounding box in texture slicer- ignoring";
227 mPlaneSource->SetPoint1( point1_s.begin() );
228 mPlaneSource->SetPoint2( point2_s.begin() );
229 mPlaneSource->SetOrigin( origin_s.begin() );
231 mPolyDataAlgorithm->Update();
233 updateAndUploadCoordinates();
236 bool Texture3DSlicerProxyImpl::isNewInputImages(std::vector<ImagePtr> images_raw)
238 if (mRawImages==images_raw)
243 mRawImages = images_raw;
315 for (
unsigned i = 0; i < images.size(); ++i)
320 QString imageUid = images[i]->getUid();
322 if(sharedOpenGLContext && !sharedOpenGLContext->hasUploadedImage(imageUid))
324 sharedOpenGLContext->uploadImage(images[i]);
327 if(sharedOpenGLContext && sharedOpenGLContext->hasUploadedImage(imageUid))
330 shaderitem->mTextureUid = imageUid;
331 shaderitem->mTexture = sharedOpenGLContext->get3DTextureForImage(imageUid);
332 QString textureCoordinatesUid = this->generateTextureCoordinateName(imageUid);
334 if(sharedOpenGLContext->hasUploadedTextureCoordinates(textureCoordinatesUid))
336 shaderitem->mTextureCoordinatesUid = textureCoordinatesUid;
337 shaderitem->mTextureCoordinates = sharedOpenGLContext->getTextureCoordinates(textureCoordinatesUid);
340 shaderCallback->add(shaderitem);
344 CX_LOG_WARNING() <<
"Setting image in Texture3DSlicerProxyImpl which is not uploaded to OpenGL: " << imageUid;
351 std::vector<ImagePtr> C;
352 for(
int i=0; i<A.size(); ++i)
354 std::vector<ImagePtr>::iterator it = std::find(B.begin(), B.end(), A[i]);
358 CX_LOG_DEBUG() <<
"Going to delete: " << A[i]->getUid();
366 void Texture3DSlicerProxyImpl::updateAndUploadImages(std::vector<ImagePtr> new_images_raw)
369 std::vector<ImagePtr> unsigned_images = convertToUnsigned(new_images_raw);
373 for(
int i=0; i<to_be_deleted.size(); ++i)
375 mSharedOpenGLContext->delete3DTextureForImage(to_be_deleted[i]->getUid());
376 mSharedOpenGLContext->delete1DTextureForLUT(to_be_deleted[i]->getUid());
380 for (
unsigned i = 0; i < mImages.size(); ++i)
384 disconnect(mImages[i].
get(), SIGNAL(vtkImageDataChanged()),
this, SLOT(
imageChanged()));
387 mImages = unsigned_images;
389 for (
unsigned i = 0; i < mImages.size(); ++i)
393 connect(mImages[i].
get(), SIGNAL(vtkImageDataChanged()),
this, SLOT(
imageChanged()));
397 this->uploadImagesToSharedContext(mImages, mSharedOpenGLContext, mShaderCallback);
402 if (!this->isNewInputImages(images_raw))
408 mShaderCallback->clearShaderItems();
410 this->updateAndUploadImages(images_raw);
412 this->updateAndUploadCoordinates();
414 this->updateAndUploadColorAttribute();
417 this->generateAndSetShaders();
420 std::vector<ImagePtr> Texture3DSlicerProxyImpl::convertToUnsigned(std::vector<ImagePtr> images_raw)
422 std::vector<ImagePtr> images(images_raw.size());
424 for (
unsigned i=0; i<images.size(); ++i)
426 images[i] = images_raw[i]->getUnsigned(images_raw[i]);
440 mSliceProxy = slicer;
446 this->updateAndUploadCoordinates();
455 QString Texture3DSlicerProxyImpl::getTCoordName(
int index)
460 QString Texture3DSlicerProxyImpl::generateTextureCoordinateName(QString imageUid)
const 462 QString textureCoordinatesUid = QString(mUid+
"_%1").arg(imageUid);
463 return textureCoordinatesUid;
468 if(sharedOpenGLContext && textureCoordinates)
470 QString textureCoordinatesUid = this->generateTextureCoordinateName(image_uid);
471 sharedOpenGLContext->upload3DTextureCoordinates(textureCoordinatesUid, textureCoordinates);
473 if(sharedOpenGLContext->hasUploadedTextureCoordinates(textureCoordinatesUid))
479 item->mTextureCoordinates = sharedOpenGLContext->getTextureCoordinates(textureCoordinatesUid);
480 item->mTextureCoordinatesUid = textureCoordinatesUid;
518 void Texture3DSlicerProxyImpl::updateAndUploadCoordinates()
520 if (!mPolyData || !mSliceProxy)
525 for (
unsigned i = 0; i < mImages.size(); ++i)
532 Vector3D origin(volume->GetOrigin());
533 Vector3D spacing(volume->GetSpacing());
536 for (
int j = 0; j < 3; ++j)
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);
546 Transform3D iMs = image->get_rMd().inv() * mSliceProxy->get_sMr().inv();
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);
561 for (
unsigned j = 0; j < plane.size(); ++j)
563 plane[j] = nMs.coord(plane[j]);
566 if (!mTextureCoordinates)
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);
579 for (
unsigned j = 0; j < plane.size(); ++j)
581 mTextureCoordinates->SetTuple3(j, plane[j][0], plane[j][1], plane[j][2]);
584 mPolyData->Modified();
586 this->uploadTextureCoordinatesToSharedContext(image->getUid(), mTextureCoordinates, mSharedOpenGLContext, mShaderCallback);
592 QString lutUid = imageUid;
595 sharedOpenGLContext->uploadLUT(lutUid, lut->GetTable());
597 if(sharedOpenGLContext->hasUploadedLUT(lutUid))
601 shaderItem->mLUT = sharedOpenGLContext->get1DTextureForLUT(lutUid);
602 shaderItem->mLUTUid = lutUid;
606 shaderItem->mWindow = window;
607 shaderItem->mLLR = llr;
608 shaderItem->mLevel = level;
609 shaderItem->mAlpha = alpha;
612 void Texture3DSlicerProxyImpl::updateAndUploadColorAttribute()
614 for (
unsigned i = 0; i < mImages.size(); ++i)
617 QString imageUid = image->getUid();
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();
638 this->uploadColorAttributesToSharedContext(imageUid, llr, lut, window, level, alpha, mSharedOpenGLContext, mShaderCallback);
648 this->resetGeometryPlane();
651 this->updateAndUploadCoordinates();
656 this->updateAndUploadColorAttribute();
QString qstring_cast(const T &val)
SliceProxyPtr getSliceProxy()
DoubleBoundingBox3D transform(const Transform3D &m, const DoubleBoundingBox3D &bb)
vtkSmartPointer< class vtkActor > vtkActorPtr
#define CX_LOG_DEBUG_CHECKPOINT()
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 Image > ImagePtr
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)
void transferFunctionChangedSlot()
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
void transformChangedSlot()
virtual ~Texture3DSlicerProxyImpl()
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.
bool similar(const CameraInfo &lhs, const CameraInfo &rhs, double tol)
const std::string getVSReplacement_dec(std::string vtk_dec, int numberOfUploadedTextures)
static Texture3DSlicerProxyPtr New(SharedOpenGLContextPtr context)
Texture3DSlicerProxyImpl(SharedOpenGLContextPtr context)
Namespace for all CustusX production code.