43 #include <vtkRenderer.h>
44 #include <vtkFloatArray.h>
45 #include <vtkPlaneSource.h>
46 #include <vtkPointData.h>
47 #include <vtkTriangleFilter.h>
48 #include <vtkStripper.h>
49 #include <vtkImageData.h>
50 #include <vtkLookupTable.h>
51 #include <vtkOpenGLRenderWindow.h>
64 #ifndef CX_VTK_OPENGL2
65 #include <vtkPainterPolyDataMapper.h>
75 #if defined(CX_VTK_OPENGL2) || defined(WIN32)
91 vtkOpenGLRenderWindow *context = vtkOpenGLRenderWindow::SafeDownCast(window);
104 mTargetSpaceIsR =
true;
109 mTargetSpaceIsR =
false;
110 mActor = vtkActorPtr::New();
111 mPainter = TextureSlicePainterPtr::New();
112 mPainterPolyDatamapper = vtkPainterPolyDataMapperPtr::New();
114 mPlaneSource = vtkPlaneSourcePtr::New();
117 triangleFilter->SetInputConnection(mPlaneSource->GetOutputPort());
120 stripper->SetInputConnection(triangleFilter->GetOutputPort());
122 mPolyDataAlgorithm = stripper;
123 mPolyDataAlgorithm->Update();
125 mPolyData = mPolyDataAlgorithm->GetOutput();
126 mPolyData->GetPointData()->SetNormals(NULL);
128 mPainter->SetDelegatePainter(mPainterPolyDatamapper->GetPainter());
129 mPainterPolyDatamapper->SetPainter(mPainter);
130 mPainterPolyDatamapper->SetInputData(mPolyData);
131 mActor->SetMapper(mPainterPolyDatamapper);
151 mPainter->setShaderPath(shaderFile);
165 if (!mTargetSpaceIsR)
170 this->resetGeometryPlane();
173 void Texture3DSlicerProxyImpl::resetGeometryPlane()
181 std::vector<Vector3D> pp_s;
182 for (
unsigned x=0; x<2; ++x)
183 for (
unsigned y=0; y<2; ++y)
184 for (
unsigned z=0; z<2; ++z)
185 pp_s.push_back(sMd.coord(bb_d.
corner(x,y,x)));
194 Vector3D origin(mBB_s[0], mBB_s[2], 0);
203 origin = rMs.coord(origin);
218 mPlaneSource->SetPoint1( point1_s.begin() );
219 mPlaneSource->SetPoint2( point2_s.begin() );
220 mPlaneSource->SetOrigin( origin_s.begin() );
222 mPolyDataAlgorithm->Update();
226 for (
unsigned i=0; i<mImages.size(); ++i)
228 updateCoordinates(i);
234 std::vector<ImagePtr> images = processImages(images_raw);
236 for (
unsigned i = 0; i < mImages.size(); ++i)
240 disconnect(mImages[i].
get(), SIGNAL(vtkImageDataChanged()),
this, SLOT(
imageChanged()));
245 for (
unsigned i = 0; i < mImages .size(); ++i)
252 mPainter->SetVolumeBuffer(i, dataBuffer);
256 connect(mImages[i].
get(), SIGNAL(vtkImageDataChanged()),
this, SLOT(
imageChanged()));
257 this->updateCoordinates(i);
261 for (
unsigned i = 0; i < mImages.size(); ++i)
263 mPainterPolyDatamapper->MapDataArrayToMultiTextureAttribute(2 * i,
265 vtkDataObject::FIELD_ASSOCIATION_POINTS);
269 std::vector<ImagePtr> Texture3DSlicerProxyImpl::processImages(std::vector<ImagePtr> images_raw)
271 if(images_raw.size() > mMaxImages)
273 QString errorText = QString(
"Texture3DSlicerProxyImpl: GPU multislicer can't handle more than %1 images. Additional images are not shown.").arg(mMaxImages);
275 images_raw.resize(mMaxImages);
278 std::vector<ImagePtr> images(images_raw.size());
279 for (
unsigned i=0; i<images.size(); ++i)
280 images[i] = images_raw[i]->getUnsigned(images_raw[i]);
290 mSliceProxy = slicer;
294 for (
unsigned i=0; i < mImages.size(); ++i)
296 updateCoordinates(i);
301 QString Texture3DSlicerProxyImpl::getTCoordName(
int index)
306 void Texture3DSlicerProxyImpl::updateCoordinates(
int index)
308 if (!mPolyData || !mSliceProxy)
313 Vector3D origin(volume->GetOrigin());
314 Vector3D spacing(volume->GetSpacing());
315 DoubleBoundingBox3D imageSize(volume->GetExtent());
317 for (
int i = 0; i < 3; ++i)
319 imageSize[2 * i] = origin[i] + spacing[i] * (imageSize[2 * i] - 0.5);
320 imageSize[2 * i + 1] = origin[i] + spacing[i] * (imageSize[2 * i + 1] + 0.5);
324 DoubleBoundingBox3D textureSpace(0.0, 1.0, 0.0, 1.0, 0.0, 1.0);
327 Transform3D iMs = mImages[index]->get_rMd().inv() * mSliceProxy->get_sMr().inv();
333 std::vector<Vector3D> plane(4);
334 plane[0] = mBB_s.
corner(0, 0, 0);
335 plane[1] = mBB_s.
corner(1, 0, 0);
336 plane[2] = mBB_s.
corner(0, 1, 0);
337 plane[3] = mBB_s.
corner(1, 1, 0);
339 for (
unsigned i = 0; i < plane.size(); ++i)
341 plane[i] = nMs.coord(plane[i]);
344 vtkFloatArrayPtr TCoords = vtkFloatArray::SafeDownCast(mPolyData->GetPointData()->GetArray(
349 TCoords = vtkFloatArrayPtr::New();
350 TCoords->SetNumberOfComponents(3);
351 TCoords->Allocate(4 * 3);
352 TCoords->InsertNextTuple3(0.0, 0.0, 0.0);
353 TCoords->InsertNextTuple3(0.0, 0.0, 0.0);
354 TCoords->InsertNextTuple3(0.0, 0.0, 0.0);
355 TCoords->InsertNextTuple3(0.0, 0.0, 0.0);
357 mPolyData->GetPointData()->AddArray(TCoords);
360 for (
unsigned i = 0; i < plane.size(); ++i)
362 TCoords->SetTuple3(i, plane[i][0], plane[i][1], plane[i][2]);
365 mPolyData->Modified();
370 for (
unsigned i = 0; i < mImages.size(); ++i)
375 lut->GetTable()->Modified();
379 if (inputImage->GetNumberOfScalarComponents()==1)
381 mPainter->SetLutBuffer(i, lutBuffer);
384 int scalarTypeMax = (int)inputImage->GetScalarTypeMax();
385 double imin = lut->GetRange()[0];
386 double imax = lut->GetRange()[1];
388 float window = (float) (imax-imin) / scalarTypeMax;
389 float llr = (float) mImages[i]->getLookupTable2D()->getLLR() / scalarTypeMax;
390 float level = (float) imin/scalarTypeMax + window/2;
391 float alpha = (float) mImages[i]->getLookupTable2D()->getAlpha();
393 mPainter->SetColorAttribute(i, window, level, llr, alpha);
401 this->resetGeometryPlane();
409 for (
unsigned i = 0; i < mImages .size(); ++i)
416 mPainter->SetVolumeBuffer(i, dataBuffer);
422 for (
unsigned i=0; i<mImages.size(); ++i)
424 updateCoordinates(i);
429 #endif //CX_VTK_OPENGL2
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)
void transformChangedSlot()
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)
void updateColorAttributeSlot()