diff --git a/src/src/Rendering/Viewer/VolumeRenderingViewer.cpp b/src/src/Rendering/Viewer/VolumeRenderingViewer.cpp index 356fb54..bc61718 100644 --- a/src/src/Rendering/Viewer/VolumeRenderingViewer.cpp +++ b/src/src/Rendering/Viewer/VolumeRenderingViewer.cpp @@ -10,8 +10,16 @@ #include #include #include +#include #include -#include +#include +//#include +#include +#include +#include +#include +#include +#include vtkStandardNewMacro(VolumeRenderingViewer); @@ -20,8 +28,48 @@ VolumeRenderingViewer::VolumeRenderingViewer() , RenderWindow(nullptr) , Renderer(nullptr) , VolumeActor(vtkVolume::New()) -, VolumeMapper(vtkSmartVolumeMapper::New()){ - this->VolumeActor->SetMapper(this->VolumeMapper); +, annotation(vtkCornerAnnotation::New()) +, VolumeMapper(vtkFixedPointVolumeRayCastMapper::New()) +, InteractorStyle(nullptr) +, Interactor(nullptr){ + if (gpuMode){ + auto mapper = vtkGPUVolumeRayCastMapper::New(); + mapper->SetUseJittering(1); + VolumeMapper->Delete(); + VolumeMapper = mapper; + } + else{ + auto mapper = vtkFixedPointVolumeRayCastMapper::SafeDownCast(VolumeMapper); + //设置线程数为核心数的两倍,为了可能用到超线程技术 + mapper->SetNumberOfThreads(2*mapper->GetNumberOfThreads()); + mapper->SetAutoAdjustSampleDistances(1); + mapper->SetSampleDistance(1.0); + mapper->SetMaximumImageSampleDistance(4.0); + mapper->SetMinimumImageSampleDistance(1.0); + } + vtkNew colorFun; + colorFun->SetScaleToLinear(); + colorFun->AddRGBPoint(100.0,0.5,0.25,0.125); + colorFun->AddRGBPoint(200.0,1.0,0.9,0.6); + colorFun->AddRGBPoint(300.0,1.0,1.0,1.0); + vtkNew opacityFun; + opacityFun->AddPoint(100.0, 0.0); + opacityFun->AddPoint(125.0, 0.5); + opacityFun->AddPoint(200.0, 1.0); + + vtkNew volumeProperty; + volumeProperty->ShadeOn(); + volumeProperty->SetColor(colorFun); + volumeProperty->SetInterpolationTypeToLinear(); + volumeProperty->SetScalarOpacity(opacityFun); + volumeProperty->SetScalarOpacityUnitDistance(1.0); + + volumeProperty->SetAmbient(0.2); + volumeProperty->SetDiffuse(0.7); + volumeProperty->SetSpecular(0.3); + volumeProperty->SetSpecularPower(8.0); + VolumeActor->SetProperty(volumeProperty); + VolumeActor->SetMapper(VolumeMapper); } VolumeRenderingViewer::~VolumeRenderingViewer() { @@ -33,7 +81,9 @@ VolumeRenderingViewer::~VolumeRenderingViewer() { } if (this->VolumeActor) { this->VolumeActor->Delete(); + this->annotation->Delete(); this->VolumeActor = nullptr; + this->annotation = nullptr; } if (this->Renderer) { @@ -72,9 +122,10 @@ void VolumeRenderingViewer::InstallPipeline() { } if (this->Renderer && this->VolumeActor) { - this->Renderer->AddViewProp(this->VolumeActor); - this->Renderer->GetActiveCamera()->SetParallelProjection(1); - this->Renderer->SetBackground(0.0, 0.0, 0.0); + this->Renderer->AddVolume(this->VolumeActor); + this->Renderer->AddViewProp(annotation); + Renderer->AddObserver(vtkCommand::EndEvent,this,&VolumeRenderingViewer::printFrameRate); + this->Renderer->SetBackground(0.3, 0.3, 0.3); } //TODO: annotation for orientation } @@ -88,7 +139,15 @@ void VolumeRenderingViewer::UnInstallPipeline() { if (this->RenderWindow && this->Renderer) { this->RenderWindow->RemoveRenderer(this->Renderer); } + if (this->Renderer && VolumeActor) { + if (this->Renderer->HasViewProp(VolumeActor)) + { + this->Renderer->RemoveViewProp(VolumeActor); + this->Renderer->RemoveViewProp(annotation); + } + Renderer->RemoveAllObservers(); + } if (this->Interactor) { this->Interactor->SetInteractorStyle(nullptr); this->Interactor->SetRenderWindow(nullptr); @@ -109,14 +168,12 @@ void VolumeRenderingViewer::SetupInteractor(vtkRenderWindowInteractor * arg) { this->Interactor = arg; if (this->Interactor) { + Interactor->SetDesiredUpdateRate(60); this->Interactor->Register(this); } this->InstallPipeline(); - if (this->Renderer) { - this->Renderer->GetActiveCamera()->ParallelProjectionOn(); - } } void VolumeRenderingViewer::SetRenderWindow(vtkRenderWindow *arg) { @@ -160,11 +217,16 @@ void VolumeRenderingViewer::SetRenderer(vtkRenderer *arg) { } void VolumeRenderingViewer::Render() { - if (RenderWindow)RenderWindow->Render(); + if (RenderWindow){ + Interactor->Render(); + } } void VolumeRenderingViewer::SetInputData(vtkImageData *in) { if (in && in != this->VolumeMapper->GetInput()){ + double spacing[3]={0.0, 0.0, 0.0}; + in->GetSpacing(spacing); + printf("set input, spacing: %f, %f, %f\r\n", spacing[0], spacing[1], spacing[2]); this->VolumeMapper->SetInputData(in); } } @@ -172,3 +234,13 @@ void VolumeRenderingViewer::SetInputData(vtkImageData *in) { vtkImageData *VolumeRenderingViewer::GetInput() { return this->VolumeMapper->GetInput(); } + +void VolumeRenderingViewer::printFrameRate() { + + double timeInSeconds = Renderer->GetLastRenderTimeInSeconds(); + double fps = 1.0 / timeInSeconds; + char buff[200]={0}; + sprintf(buff,"FPS:%3.0f", fps); +// sprintf(buff,"FPS:%3.0f,bytes in use:%lld", fps,vtkGPUVolumeRayCastMapper::SafeDownCast(lowresMapper)->GetMaxMemoryInBytes()); + annotation->SetText(0,buff ); +} diff --git a/src/src/Rendering/Viewer/VolumeRenderingViewer.h b/src/src/Rendering/Viewer/VolumeRenderingViewer.h index d5a2442..692d5fd 100644 --- a/src/src/Rendering/Viewer/VolumeRenderingViewer.h +++ b/src/src/Rendering/Viewer/VolumeRenderingViewer.h @@ -23,10 +23,12 @@ class vtkInteractorStyle; class vtkVolume; -class vtkSmartVolumeMapper; +class vtkVolumeMapper; + +class vtkCornerAnnotation; class VolumeRenderingViewer:public vtkObject { - +public: static VolumeRenderingViewer *New(); vtkTypeMacro(VolumeRenderingViewer, vtkObject); @@ -78,6 +80,8 @@ protected: virtual void InstallPipeline(); virtual void UnInstallPipeline(); + + void printFrameRate(); private: VolumeRenderingViewer(const VolumeRenderingViewer &) = delete; @@ -86,9 +90,11 @@ private: vtkRenderWindow *RenderWindow; vtkRenderer *Renderer; vtkVolume * VolumeActor; - vtkSmartVolumeMapper *VolumeMapper; + vtkVolumeMapper *VolumeMapper; vtkInteractorStyle *InteractorStyle; vtkRenderWindowInteractor *Interactor; + vtkCornerAnnotation* annotation; + bool gpuMode = false; }; diff --git a/src/src/UI/Widget/ToolBar/VolumeRenderingToolBar.cpp b/src/src/UI/Widget/ToolBar/VolumeRenderingToolBar.cpp new file mode 100644 index 0000000..5cf8d37 --- /dev/null +++ b/src/src/UI/Widget/ToolBar/VolumeRenderingToolBar.cpp @@ -0,0 +1,13 @@ +// +// Created by Krad on 2022/8/16. +// + +#include "VolumeRenderingToolBar.h" + +VolumeRenderingToolBar::VolumeRenderingToolBar(QWidget *parent) : QToolBar(parent) { + +} + +VolumeRenderingToolBar::~VolumeRenderingToolBar() { + +} diff --git a/src/src/UI/Widget/ToolBar/VolumeRenderingToolBar.h b/src/src/UI/Widget/ToolBar/VolumeRenderingToolBar.h new file mode 100644 index 0000000..d8eac23 --- /dev/null +++ b/src/src/UI/Widget/ToolBar/VolumeRenderingToolBar.h @@ -0,0 +1,19 @@ +// +// Created by Krad on 2022/8/16. +// + +#ifndef OMEGAV_VOLUMERENDERINGTOOLBAR_H +#define OMEGAV_VOLUMERENDERINGTOOLBAR_H + +#include + +class VolumeRenderingToolBar : public QToolBar { + Q_OBJECT +public: + explicit VolumeRenderingToolBar(QWidget *parent = nullptr); + + ~VolumeRenderingToolBar(); +}; + + +#endif //OMEGAV_VOLUMERENDERINGTOOLBAR_H diff --git a/src/src/UI/Window/QDicomViewer.cpp b/src/src/UI/Window/QDicomViewer.cpp index d69ec4b..7f08022 100644 --- a/src/src/UI/Window/QDicomViewer.cpp +++ b/src/src/UI/Window/QDicomViewer.cpp @@ -10,6 +10,7 @@ #include "Interaction/ActorDraggableInteractorStyle.h" #include "UI/Manager/ImageViewManager.h" #include "UI/Widget/Component/gridpopwidget.h" +#include "UI/Window/VolumeRenderingWindow.h" #include "UI/Widget/cine/pqVCRToolbar.h" @@ -173,6 +174,15 @@ void QDicomViewer::initViewOperation() { // MPR connect(ui->toolBar, &DefaultToolBar::changeSliceOrientation, ui->viewContainer->getViewManager(), &ImageViewManager::switchSliceOrientation); + connect(ui->toolBar, &DefaultToolBar::volumeRendering,[=](){ + auto volumeWin = new VolumeRenderingWindow(this); + connect(volumeWin,&QDialog::finished,[=](){ + volumeWin->deleteLater(); + }); + + volumeWin->loadData(ui->viewContainer->getViewManager()->getCurrentView()->getSeriesInstance()); + volumeWin->show(); + }); } //视窗操作?,file open相关 diff --git a/src/src/UI/Window/VolumeRenderingWindow.cpp b/src/src/UI/Window/VolumeRenderingWindow.cpp new file mode 100644 index 0000000..ecd9e04 --- /dev/null +++ b/src/src/UI/Window/VolumeRenderingWindow.cpp @@ -0,0 +1,50 @@ +// +// Created by Krad on 2022/8/16. +// + +#include "VolumeRenderingWindow.h" + +#include +#include +#include +#include +#include + +#include "Common/SeriesImageSet.h" +#include "Rendering/Viewer/VolumeRenderingViewer.h" +#include "UI/Widget/ToolBar/VolumeRenderingToolBar.h" + + +VolumeRenderingWindow::VolumeRenderingWindow(QWidget *parent , Qt::WindowFlags f) +: QDialog(parent, f) +, mRenderWin(vtkSmartPointer::New()) +, mViewer(VolumeRenderingViewer::New()) +{ + setObjectName("volumeWin"); +// setAttribute(Qt::WA_StyleSheetTarget,true); + QVBoxLayout* layout = new QVBoxLayout(this); + layout->setMargin(1); + layout->setSpacing(0); + auto toolBar = new VolumeRenderingToolBar(this); + layout->addWidget(toolBar); + auto widget = new QVTKOpenGLNativeWidget(this); + + vtkNew renderer; + mViewer->SetRenderWindow(mRenderWin); + mViewer->SetRenderer(renderer); + + widget->SetRenderWindow(mRenderWin); + layout->addWidget(widget); + setMinimumSize(680,500); +} + +VolumeRenderingWindow::~VolumeRenderingWindow() { + mViewer->Delete(); + qDebug() << "delete VolumeRenderingWindow"; +} + +void VolumeRenderingWindow::loadData(SeriesImageSet* series){ + mViewer->SetupInteractor(mRenderWin->GetInteractor()); + mViewer->SetInputData(series->GetData()); + mViewer->Render(); +} diff --git a/src/src/UI/Window/VolumeRenderingWindow.h b/src/src/UI/Window/VolumeRenderingWindow.h new file mode 100644 index 0000000..6a055e9 --- /dev/null +++ b/src/src/UI/Window/VolumeRenderingWindow.h @@ -0,0 +1,29 @@ +// +// Created by Krad on 2022/8/16. +// + +#ifndef OMEGAV_VOLUMERENDERINGWINDOW_H +#define OMEGAV_VOLUMERENDERINGWINDOW_H + +#include +#include + +class SeriesImageSet; + +class VolumeRenderingViewer; + +class VolumeRenderingWindow:public QDialog { + Q_OBJECT + +public: + explicit VolumeRenderingWindow(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); + ~VolumeRenderingWindow(); + void loadData(SeriesImageSet* series); +private: + vtkSmartPointer mRenderWin; + + VolumeRenderingViewer *mViewer; +}; + + +#endif //OMEGAV_VOLUMERENDERINGWINDOW_H