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);
232 bool Texture3DSlicerProxyImpl::isNewInputImages(std::vector<ImagePtr> images_raw)
234 if (mRawImages==images_raw)
236 mRawImages = images_raw;
242 if (!this->isNewInputImages(images_raw))
245 std::vector<ImagePtr> images = processImages(images_raw);
247 for (
unsigned i = 0; i < mImages.size(); ++i)
251 disconnect(mImages[i].
get(), SIGNAL(vtkImageDataChanged()),
this, SLOT(
imageChanged()));
256 for (
unsigned i = 0; i < mImages .size(); ++i)
263 mPainter->SetVolumeBuffer(i, dataBuffer);
267 connect(mImages[i].
get(), SIGNAL(vtkImageDataChanged()),
this, SLOT(
imageChanged()));
268 this->updateCoordinates(i);
272 mPainterPolyDatamapper->RemoveAllVertexAttributeMappings();
273 for (
unsigned i = 0; i < mImages.size(); ++i)
275 mPainterPolyDatamapper->MapDataArrayToMultiTextureAttribute(2 * i,
277 vtkDataObject::FIELD_ASSOCIATION_POINTS);
281 std::vector<ImagePtr> Texture3DSlicerProxyImpl::processImages(std::vector<ImagePtr> images_raw)
283 if(images_raw.size() > mMaxImages)
285 QString errorText = QString(
"Texture3DSlicerProxyImpl: GPU multislicer can't handle more than %1 images. Additional images are not shown.").arg(mMaxImages);
287 images_raw.resize(mMaxImages);
290 std::vector<ImagePtr> images(images_raw.size());
291 for (
unsigned i=0; i<images.size(); ++i)
292 images[i] = images_raw[i]->getUnsigned(images_raw[i]);
302 mSliceProxy = slicer;
306 for (
unsigned i=0; i < mImages.size(); ++i)
308 updateCoordinates(i);
313 QString Texture3DSlicerProxyImpl::getTCoordName(
int index)
318 void Texture3DSlicerProxyImpl::updateCoordinates(
int index)
320 if (!mPolyData || !mSliceProxy)
325 Vector3D origin(volume->GetOrigin());
326 Vector3D spacing(volume->GetSpacing());
327 DoubleBoundingBox3D imageSize(volume->GetExtent());
329 for (
int i = 0; i < 3; ++i)
331 imageSize[2 * i] = origin[i] + spacing[i] * (imageSize[2 * i] - 0.5);
332 imageSize[2 * i + 1] = origin[i] + spacing[i] * (imageSize[2 * i + 1] + 0.5);
336 DoubleBoundingBox3D textureSpace(0.0, 1.0, 0.0, 1.0, 0.0, 1.0);
339 Transform3D iMs = mImages[index]->get_rMd().inv() * mSliceProxy->get_sMr().inv();
345 std::vector<Vector3D> plane(4);
346 plane[0] = mBB_s.
corner(0, 0, 0);
347 plane[1] = mBB_s.
corner(1, 0, 0);
348 plane[2] = mBB_s.
corner(0, 1, 0);
349 plane[3] = mBB_s.
corner(1, 1, 0);
351 for (
unsigned i = 0; i < plane.size(); ++i)
353 plane[i] = nMs.coord(plane[i]);
356 vtkFloatArrayPtr TCoords = vtkFloatArray::SafeDownCast(mPolyData->GetPointData()->GetArray(
361 TCoords = vtkFloatArrayPtr::New();
362 TCoords->SetNumberOfComponents(3);
363 TCoords->Allocate(4 * 3);
364 TCoords->InsertNextTuple3(0.0, 0.0, 0.0);
365 TCoords->InsertNextTuple3(0.0, 0.0, 0.0);
366 TCoords->InsertNextTuple3(0.0, 0.0, 0.0);
367 TCoords->InsertNextTuple3(0.0, 0.0, 0.0);
369 mPolyData->GetPointData()->AddArray(TCoords);
372 for (
unsigned i = 0; i < plane.size(); ++i)
374 TCoords->SetTuple3(i, plane[i][0], plane[i][1], plane[i][2]);
377 mPolyData->Modified();
382 for (
unsigned i = 0; i < mImages.size(); ++i)
387 lut->GetTable()->Modified();
391 if (inputImage->GetNumberOfScalarComponents()==1)
393 mPainter->SetLutBuffer(i, lutBuffer);
396 int scalarTypeMax = (int)inputImage->GetScalarTypeMax();
397 double imin = lut->GetRange()[0];
398 double imax = lut->GetRange()[1];
400 float window = (float) (imax-imin) / scalarTypeMax;
401 float llr = (float) mImages[i]->getLookupTable2D()->getLLR() / scalarTypeMax;
402 float level = (float) imin/scalarTypeMax + window/2;
403 float alpha = (float) mImages[i]->getLookupTable2D()->getAlpha();
405 mPainter->SetColorAttribute(i, window, level, llr, alpha);
413 this->resetGeometryPlane();
421 for (
unsigned i = 0; i < mImages .size(); ++i)
428 mPainter->SetVolumeBuffer(i, dataBuffer);
434 for (
unsigned i=0; i<mImages.size(); ++i)
436 updateCoordinates(i);
441 #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)
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.
bool similar(const CameraInfo &lhs, const CameraInfo &rhs, double tol)
boost::shared_ptr< class GPUImageLutBuffer > GPUImageLutBufferPtr
GPUImageDataBufferPtr getGPUImageDataBuffer(vtkImageDataPtr volume)
static GPUImageBufferRepository * getInstance()
static bool isSupported(vtkRenderWindowPtr window)
void updateColorAttributeSlot()