Simple volume rendering.
This commit is contained in:
@@ -10,8 +10,16 @@
|
|||||||
#include <vtkRenderWindowInteractor.h>
|
#include <vtkRenderWindowInteractor.h>
|
||||||
#include <vtkInteractorStyleTrackballCamera.h>
|
#include <vtkInteractorStyleTrackballCamera.h>
|
||||||
#include <vtkCamera.h>
|
#include <vtkCamera.h>
|
||||||
|
#include <vtkImageData.h>
|
||||||
#include <vtkVolume.h>
|
#include <vtkVolume.h>
|
||||||
#include <vtkSmartVolumeMapper.h>
|
#include <vtkVolumeProperty.h>
|
||||||
|
//#include <vtkSmartVolumeMapper.h>
|
||||||
|
#include <vtkFixedPointVolumeRayCastMapper.h>
|
||||||
|
#include <vtkGPUVolumeRayCastMapper.h>
|
||||||
|
#include <vtkPiecewiseFunction.h>
|
||||||
|
#include <vtkColorTransferFunction.h>
|
||||||
|
#include <vtkCornerAnnotation.h>
|
||||||
|
#include <vtkLODProp3D.h>
|
||||||
|
|
||||||
vtkStandardNewMacro(VolumeRenderingViewer);
|
vtkStandardNewMacro(VolumeRenderingViewer);
|
||||||
|
|
||||||
@@ -20,8 +28,48 @@ VolumeRenderingViewer::VolumeRenderingViewer()
|
|||||||
, RenderWindow(nullptr)
|
, RenderWindow(nullptr)
|
||||||
, Renderer(nullptr)
|
, Renderer(nullptr)
|
||||||
, VolumeActor(vtkVolume::New())
|
, VolumeActor(vtkVolume::New())
|
||||||
, VolumeMapper(vtkSmartVolumeMapper::New()){
|
, annotation(vtkCornerAnnotation::New())
|
||||||
this->VolumeActor->SetMapper(this->VolumeMapper);
|
, 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<vtkColorTransferFunction> 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<vtkPiecewiseFunction> opacityFun;
|
||||||
|
opacityFun->AddPoint(100.0, 0.0);
|
||||||
|
opacityFun->AddPoint(125.0, 0.5);
|
||||||
|
opacityFun->AddPoint(200.0, 1.0);
|
||||||
|
|
||||||
|
vtkNew<vtkVolumeProperty> 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() {
|
VolumeRenderingViewer::~VolumeRenderingViewer() {
|
||||||
@@ -33,7 +81,9 @@ VolumeRenderingViewer::~VolumeRenderingViewer() {
|
|||||||
}
|
}
|
||||||
if (this->VolumeActor) {
|
if (this->VolumeActor) {
|
||||||
this->VolumeActor->Delete();
|
this->VolumeActor->Delete();
|
||||||
|
this->annotation->Delete();
|
||||||
this->VolumeActor = nullptr;
|
this->VolumeActor = nullptr;
|
||||||
|
this->annotation = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->Renderer) {
|
if (this->Renderer) {
|
||||||
@@ -72,9 +122,10 @@ void VolumeRenderingViewer::InstallPipeline() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this->Renderer && this->VolumeActor) {
|
if (this->Renderer && this->VolumeActor) {
|
||||||
this->Renderer->AddViewProp(this->VolumeActor);
|
this->Renderer->AddVolume(this->VolumeActor);
|
||||||
this->Renderer->GetActiveCamera()->SetParallelProjection(1);
|
this->Renderer->AddViewProp(annotation);
|
||||||
this->Renderer->SetBackground(0.0, 0.0, 0.0);
|
Renderer->AddObserver(vtkCommand::EndEvent,this,&VolumeRenderingViewer::printFrameRate);
|
||||||
|
this->Renderer->SetBackground(0.3, 0.3, 0.3);
|
||||||
}
|
}
|
||||||
//TODO: annotation for orientation
|
//TODO: annotation for orientation
|
||||||
}
|
}
|
||||||
@@ -88,7 +139,15 @@ void VolumeRenderingViewer::UnInstallPipeline() {
|
|||||||
if (this->RenderWindow && this->Renderer) {
|
if (this->RenderWindow && this->Renderer) {
|
||||||
this->RenderWindow->RemoveRenderer(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) {
|
if (this->Interactor) {
|
||||||
this->Interactor->SetInteractorStyle(nullptr);
|
this->Interactor->SetInteractorStyle(nullptr);
|
||||||
this->Interactor->SetRenderWindow(nullptr);
|
this->Interactor->SetRenderWindow(nullptr);
|
||||||
@@ -109,14 +168,12 @@ void VolumeRenderingViewer::SetupInteractor(vtkRenderWindowInteractor * arg) {
|
|||||||
this->Interactor = arg;
|
this->Interactor = arg;
|
||||||
|
|
||||||
if (this->Interactor) {
|
if (this->Interactor) {
|
||||||
|
Interactor->SetDesiredUpdateRate(60);
|
||||||
this->Interactor->Register(this);
|
this->Interactor->Register(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->InstallPipeline();
|
this->InstallPipeline();
|
||||||
|
|
||||||
if (this->Renderer) {
|
|
||||||
this->Renderer->GetActiveCamera()->ParallelProjectionOn();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VolumeRenderingViewer::SetRenderWindow(vtkRenderWindow *arg) {
|
void VolumeRenderingViewer::SetRenderWindow(vtkRenderWindow *arg) {
|
||||||
@@ -160,11 +217,16 @@ void VolumeRenderingViewer::SetRenderer(vtkRenderer *arg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VolumeRenderingViewer::Render() {
|
void VolumeRenderingViewer::Render() {
|
||||||
if (RenderWindow)RenderWindow->Render();
|
if (RenderWindow){
|
||||||
|
Interactor->Render();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VolumeRenderingViewer::SetInputData(vtkImageData *in) {
|
void VolumeRenderingViewer::SetInputData(vtkImageData *in) {
|
||||||
if (in && in != this->VolumeMapper->GetInput()){
|
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);
|
this->VolumeMapper->SetInputData(in);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -172,3 +234,13 @@ void VolumeRenderingViewer::SetInputData(vtkImageData *in) {
|
|||||||
vtkImageData *VolumeRenderingViewer::GetInput() {
|
vtkImageData *VolumeRenderingViewer::GetInput() {
|
||||||
return this->VolumeMapper->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 );
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,10 +23,12 @@ class vtkInteractorStyle;
|
|||||||
|
|
||||||
class vtkVolume;
|
class vtkVolume;
|
||||||
|
|
||||||
class vtkSmartVolumeMapper;
|
class vtkVolumeMapper;
|
||||||
|
|
||||||
|
class vtkCornerAnnotation;
|
||||||
|
|
||||||
class VolumeRenderingViewer:public vtkObject {
|
class VolumeRenderingViewer:public vtkObject {
|
||||||
|
public:
|
||||||
static VolumeRenderingViewer *New();
|
static VolumeRenderingViewer *New();
|
||||||
|
|
||||||
vtkTypeMacro(VolumeRenderingViewer, vtkObject);
|
vtkTypeMacro(VolumeRenderingViewer, vtkObject);
|
||||||
@@ -78,6 +80,8 @@ protected:
|
|||||||
virtual void InstallPipeline();
|
virtual void InstallPipeline();
|
||||||
|
|
||||||
virtual void UnInstallPipeline();
|
virtual void UnInstallPipeline();
|
||||||
|
|
||||||
|
void printFrameRate();
|
||||||
private:
|
private:
|
||||||
VolumeRenderingViewer(const VolumeRenderingViewer &) = delete;
|
VolumeRenderingViewer(const VolumeRenderingViewer &) = delete;
|
||||||
|
|
||||||
@@ -86,9 +90,11 @@ private:
|
|||||||
vtkRenderWindow *RenderWindow;
|
vtkRenderWindow *RenderWindow;
|
||||||
vtkRenderer *Renderer;
|
vtkRenderer *Renderer;
|
||||||
vtkVolume * VolumeActor;
|
vtkVolume * VolumeActor;
|
||||||
vtkSmartVolumeMapper *VolumeMapper;
|
vtkVolumeMapper *VolumeMapper;
|
||||||
vtkInteractorStyle *InteractorStyle;
|
vtkInteractorStyle *InteractorStyle;
|
||||||
vtkRenderWindowInteractor *Interactor;
|
vtkRenderWindowInteractor *Interactor;
|
||||||
|
vtkCornerAnnotation* annotation;
|
||||||
|
bool gpuMode = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
13
src/src/UI/Widget/ToolBar/VolumeRenderingToolBar.cpp
Normal file
13
src/src/UI/Widget/ToolBar/VolumeRenderingToolBar.cpp
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
//
|
||||||
|
// Created by Krad on 2022/8/16.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "VolumeRenderingToolBar.h"
|
||||||
|
|
||||||
|
VolumeRenderingToolBar::VolumeRenderingToolBar(QWidget *parent) : QToolBar(parent) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
VolumeRenderingToolBar::~VolumeRenderingToolBar() {
|
||||||
|
|
||||||
|
}
|
||||||
19
src/src/UI/Widget/ToolBar/VolumeRenderingToolBar.h
Normal file
19
src/src/UI/Widget/ToolBar/VolumeRenderingToolBar.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
//
|
||||||
|
// Created by Krad on 2022/8/16.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OMEGAV_VOLUMERENDERINGTOOLBAR_H
|
||||||
|
#define OMEGAV_VOLUMERENDERINGTOOLBAR_H
|
||||||
|
|
||||||
|
#include <QToolBar>
|
||||||
|
|
||||||
|
class VolumeRenderingToolBar : public QToolBar {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit VolumeRenderingToolBar(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
~VolumeRenderingToolBar();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //OMEGAV_VOLUMERENDERINGTOOLBAR_H
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "Interaction/ActorDraggableInteractorStyle.h"
|
#include "Interaction/ActorDraggableInteractorStyle.h"
|
||||||
#include "UI/Manager/ImageViewManager.h"
|
#include "UI/Manager/ImageViewManager.h"
|
||||||
#include "UI/Widget/Component/gridpopwidget.h"
|
#include "UI/Widget/Component/gridpopwidget.h"
|
||||||
|
#include "UI/Window/VolumeRenderingWindow.h"
|
||||||
#include "UI/Widget/cine/pqVCRToolbar.h"
|
#include "UI/Widget/cine/pqVCRToolbar.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -173,6 +174,15 @@ void QDicomViewer::initViewOperation() {
|
|||||||
// MPR
|
// MPR
|
||||||
connect(ui->toolBar, &DefaultToolBar::changeSliceOrientation,
|
connect(ui->toolBar, &DefaultToolBar::changeSliceOrientation,
|
||||||
ui->viewContainer->getViewManager(), &ImageViewManager::switchSliceOrientation);
|
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相关
|
//视窗操作?,file open相关
|
||||||
|
|||||||
50
src/src/UI/Window/VolumeRenderingWindow.cpp
Normal file
50
src/src/UI/Window/VolumeRenderingWindow.cpp
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
//
|
||||||
|
// Created by Krad on 2022/8/16.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "VolumeRenderingWindow.h"
|
||||||
|
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <qdebug.h>
|
||||||
|
#include <QVTKOpenGLNativeWidget.h>
|
||||||
|
#include <vtkRenderer.h>
|
||||||
|
#include <vtkGenericOpenGLRenderWindow.h>
|
||||||
|
|
||||||
|
#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<vtkGenericOpenGLRenderWindow>::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<vtkRenderer> 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();
|
||||||
|
}
|
||||||
29
src/src/UI/Window/VolumeRenderingWindow.h
Normal file
29
src/src/UI/Window/VolumeRenderingWindow.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// Created by Krad on 2022/8/16.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OMEGAV_VOLUMERENDERINGWINDOW_H
|
||||||
|
#define OMEGAV_VOLUMERENDERINGWINDOW_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <vtkGenericOpenGLRenderWindow.h >
|
||||||
|
|
||||||
|
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<vtkGenericOpenGLRenderWindow> mRenderWin;
|
||||||
|
|
||||||
|
VolumeRenderingViewer *mViewer;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //OMEGAV_VOLUMERENDERINGWINDOW_H
|
||||||
Reference in New Issue
Block a user