44 #include <vtkRenderer.h>
45 #include <vtkFloatArray.h>
46 #include <vtkPlaneSource.h>
47 #include <vtkPointData.h>
48 #include <vtkTriangleFilter.h>
49 #include <vtkStripper.h>
50 #include <vtkImageData.h>
51 #include <vtkPainterPolyDataMapper.h>
52 #include <vtkLookupTable.h>
53 #include <vtkOpenGLRenderWindow.h>
85 vtkOpenGLRenderWindow *context = vtkOpenGLRenderWindow::SafeDownCast(window);
98 mTargetSpaceIsR =
true;
103 mTargetSpaceIsR =
false;
104 mActor = vtkActorPtr::New();
105 mPainter = TextureSlicePainterPtr::New();
106 mPainterPolyDatamapper = vtkPainterPolyDataMapperPtr::New();
108 mPlaneSource = vtkPlaneSourcePtr::New();
111 triangleFilter->SetInputConnection(mPlaneSource->GetOutputPort());
114 stripper->SetInputConnection(triangleFilter->GetOutputPort());
116 mPolyDataAlgorithm = stripper;
117 mPolyDataAlgorithm->Update();
119 mPolyData = mPolyDataAlgorithm->GetOutput();
120 mPolyData->GetPointData()->SetNormals(NULL);
122 mPainter->SetDelegatePainter(mPainterPolyDatamapper->GetPainter());
123 mPainterPolyDatamapper->SetPainter(mPainter);
124 mPainterPolyDatamapper->SetInputData(mPolyData);
125 mActor->SetMapper(mPainterPolyDatamapper);
145 mPainter->setShaderPath(shaderFile);
159 if (!mTargetSpaceIsR)
164 this->resetGeometryPlane();
167 void Texture3DSlicerProxyImpl::resetGeometryPlane()
175 std::vector<Vector3D> pp_s;
176 for (
unsigned x=0; x<2; ++x)
177 for (
unsigned y=0; y<2; ++y)
178 for (
unsigned z=0; z<2; ++z)
179 pp_s.push_back(sMd.coord(bb_d.
corner(x,y,x)));
188 Vector3D origin(mBB_s[0], mBB_s[2], 0);
197 origin = rMs.coord(origin);
212 mPlaneSource->SetPoint1( point1_s.begin() );
213 mPlaneSource->SetPoint2( point2_s.begin() );
214 mPlaneSource->SetOrigin( origin_s.begin() );
216 mPolyDataAlgorithm->Update();
220 for (
unsigned i=0; i<mImages.size(); ++i)
222 updateCoordinates(i);
228 std::vector<ImagePtr> images = processImages(images_raw);
230 for (
unsigned i = 0; i < mImages.size(); ++i)
232 disconnect(mImages[i].
get(), SIGNAL(transformChanged()),
this, SLOT(transformChangedSlot()));
233 disconnect(mImages[i].
get(), SIGNAL(transferFunctionsChanged()),
this, SLOT(updateColorAttributeSlot()));
234 disconnect(mImages[i].
get(), SIGNAL(vtkImageDataChanged()),
this, SLOT(imageChanged()));
239 for (
unsigned i = 0; i < mImages .size(); ++i)
246 mPainter->SetVolumeBuffer(i, dataBuffer);
248 connect(mImages[i].
get(), SIGNAL(transformChanged()),
this, SLOT(transformChangedSlot()));
249 connect(mImages[i].
get(), SIGNAL(transferFunctionsChanged()),
this, SLOT(updateColorAttributeSlot()));
250 connect(mImages[i].
get(), SIGNAL(vtkImageDataChanged()),
this, SLOT(imageChanged()));
251 this->updateCoordinates(i);
253 this->updateColorAttributeSlot();
255 for (
unsigned i = 0; i < mImages.size(); ++i)
257 mPainterPolyDatamapper->MapDataArrayToMultiTextureAttribute(2 * i,
259 vtkDataObject::FIELD_ASSOCIATION_POINTS);
263 std::vector<ImagePtr> Texture3DSlicerProxyImpl::processImages(std::vector<ImagePtr> images_raw)
265 if(images_raw.size() > mMaxImages)
267 QString errorText = QString(
"Texture3DSlicerProxyImpl: GPU multislicer can't handle more than %1 images. Additional images are not shown.").arg(mMaxImages);
269 images_raw.resize(mMaxImages);
272 std::vector<ImagePtr> images(images_raw.size());
273 for (
unsigned i=0; i<images.size(); ++i)
274 images[i] = images_raw[i]->getUnsigned(images_raw[i]);
283 disconnect(mSliceProxy.get(), SIGNAL(transformChanged(
Transform3D)),
this, SLOT(transformChangedSlot()));
284 mSliceProxy = slicer;
287 connect(mSliceProxy.get(), SIGNAL(transformChanged(
Transform3D)),
this, SLOT(transformChangedSlot()));
288 for (
unsigned i=0; i < mImages.size(); ++i)
290 updateCoordinates(i);
295 QString Texture3DSlicerProxyImpl::getTCoordName(
int index)
300 void Texture3DSlicerProxyImpl::updateCoordinates(
int index)
302 if (!mPolyData || !mSliceProxy)
307 Vector3D origin(volume->GetOrigin());
308 Vector3D spacing(volume->GetSpacing());
309 DoubleBoundingBox3D imageSize(volume->GetExtent());
311 for (
int i = 0; i < 3; ++i)
313 imageSize[2 * i] = origin[i] + spacing[i] * (imageSize[2 * i] - 0.5);
314 imageSize[2 * i + 1] = origin[i] + spacing[i] * (imageSize[2 * i + 1] + 0.5);
318 DoubleBoundingBox3D textureSpace(0.0, 1.0, 0.0, 1.0, 0.0, 1.0);
321 Transform3D iMs = mImages[index]->get_rMd().inv() * mSliceProxy->get_sMr().inv();
327 std::vector<Vector3D> plane(4);
328 plane[0] = mBB_s.
corner(0, 0, 0);
329 plane[1] = mBB_s.
corner(1, 0, 0);
330 plane[2] = mBB_s.
corner(0, 1, 0);
331 plane[3] = mBB_s.
corner(1, 1, 0);
333 for (
unsigned i = 0; i < plane.size(); ++i)
335 plane[i] = nMs.coord(plane[i]);
338 vtkFloatArrayPtr TCoords = vtkFloatArray::SafeDownCast(mPolyData->GetPointData()->GetArray(
343 TCoords = vtkFloatArrayPtr::New();
344 TCoords->SetNumberOfComponents(3);
345 TCoords->Allocate(4 * 3);
346 TCoords->InsertNextTuple3(0.0, 0.0, 0.0);
347 TCoords->InsertNextTuple3(0.0, 0.0, 0.0);
348 TCoords->InsertNextTuple3(0.0, 0.0, 0.0);
349 TCoords->InsertNextTuple3(0.0, 0.0, 0.0);
351 mPolyData->GetPointData()->AddArray(TCoords);
354 for (
unsigned i = 0; i < plane.size(); ++i)
356 TCoords->SetTuple3(i, plane[i][0], plane[i][1], plane[i][2]);
359 mPolyData->Modified();
362 void Texture3DSlicerProxyImpl::updateColorAttributeSlot()
364 for (
unsigned i = 0; i < mImages.size(); ++i)
369 lut->GetTable()->Modified();
373 if (inputImage->GetNumberOfScalarComponents()==1)
375 mPainter->SetLutBuffer(i, lutBuffer);
378 int scalarTypeMax = (int)inputImage->GetScalarTypeMax();
379 double imin = lut->GetRange()[0];
380 double imax = lut->GetRange()[1];
382 float window = (float) (imax-imin) / scalarTypeMax;
383 float llr = (float) mImages[i]->getLookupTable2D()->getLLR() / scalarTypeMax;
384 float level = (float) imin/scalarTypeMax + window/2;
385 float alpha = (float) mImages[i]->getLookupTable2D()->getAlpha();
387 mPainter->SetColorAttribute(i, window, level, llr, alpha);
392 void Texture3DSlicerProxyImpl::transformChangedSlot()
395 this->resetGeometryPlane();
399 void Texture3DSlicerProxyImpl::imageChanged()
403 for (
unsigned i = 0; i < mImages .size(); ++i)
410 mPainter->SetVolumeBuffer(i, dataBuffer);
416 for (
unsigned i=0; i<mImages.size(); ++i)
418 updateCoordinates(i);
QString qstring_cast(const T &val)
DoubleBoundingBox3D transform(const Transform3D &m, const DoubleBoundingBox3D &bb)
vtkSmartPointer< class vtkActor > vtkActorPtr
void reportError(QString msg)
Vector3D corner(int x, int y, int z) const
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
static Texture3DSlicerProxyPtr New()
vtkSmartPointer< class vtkFloatArray > vtkFloatArrayPtr
vtkSmartPointer< class vtkRenderWindow > vtkRenderWindowPtr
cstring_cast_Placeholder cstring_cast(const T &val)
void setTargetSpaceToR()
use to draw the slice in 3D r space instead of in 2D s space.
Texture3DSlicerProxyImpl()
void setShaderPath(QString shaderFile)
static DoubleBoundingBox3D fromCloud(std::vector< Vector3D > cloud)
Transform3D createTransformNormalize(const DoubleBoundingBox3D &in, const DoubleBoundingBox3D &out)
bool similar(const DoubleBoundingBox3D &a, const DoubleBoundingBox3D &b, double tol)
GPUImageLutBufferPtr getGPUImageLutBuffer(vtkUnsignedCharArrayPtr lut)
void setViewportData(const Transform3D &vpMs, const DoubleBoundingBox3D &vp)
void setSliceProxy(SliceProxyPtr slicer)
static Texture3DSlicerProxyPtr New()
virtual ~Texture3DSlicerProxyImpl()
static bool LoadRequiredExtensions(vtkOpenGLExtensionManager *mgr)
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
boost::shared_ptr< class GPUImageDataBuffer > GPUImageDataBufferPtr
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.
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
boost::shared_ptr< class GPUImageLutBuffer > GPUImageLutBufferPtr
GPUImageDataBufferPtr getGPUImageDataBuffer(vtkImageDataPtr volume)
static GPUImageBufferRepository * getInstance()
static bool isSupported(vtkRenderWindowPtr window)