Simple volume rendering.
This commit is contained in:
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
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 "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相关
|
||||
|
||||
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