Simple volume rendering.

This commit is contained in:
Krad
2022-08-22 09:33:28 +08:00
parent 727e4b7563
commit 15461446c5
7 changed files with 212 additions and 13 deletions

View File

@@ -10,8 +10,16 @@
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkCamera.h>
#include <vtkImageData.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);
@@ -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<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() {
@@ -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 );
}

View File

@@ -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;
};

View File

@@ -0,0 +1,13 @@
//
// Created by Krad on 2022/8/16.
//
#include "VolumeRenderingToolBar.h"
VolumeRenderingToolBar::VolumeRenderingToolBar(QWidget *parent) : QToolBar(parent) {
}
VolumeRenderingToolBar::~VolumeRenderingToolBar() {
}

View 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

View File

@@ -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相关

View 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();
}

View 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