VTK 离屏渲染

VTK可以结合QT直接渲染,但这样会需要使用QOpenglWidget,这样会和VTK深度绑定,以后更换渲染引擎的工作量比较大,如果想在普通的QWidget启用VTK渲染,VTK作为后台渲染引擎,与界面分离,后续更换其他引擎或者自己实现引擎工作量比较小,这种技术也可以实现前后端,服务端渲染

vtk 离屏渲染的代码片段 

初始化 initPipleline()

    renderWindow =vtkSmartPointer<vtkRenderWindow>::New();
    renderWindow->SetUseOffScreenBuffers(true);
    //renderWindow->SetDoubleBuffer(false);
    vtkNew<vtkRenderWindowInteractor> interactor;
    renderWindow->SetInteractor(interactor);
    windowToImageFilter = vtkSmartPointer<vtkWindowToImageFilter>::New();
    windowToImageFilter->SetInput(renderWindow);
    windowToImageFilter->SetInputBufferTypeToRGBA();

    vtkNew<vtkRenderer> renderer;
    renderWindow->AddRenderer(renderer);
    vtkNew<vtkInteractorStyleSwitch> style;
    style->SetCurrentStyleToTrackballCamera();
    renderWindow->GetInteractor()->SetInteractorStyle(style);
    renderWindow->SetSize(512, 512);
    renderWindow->BordersOff();
    renderWindow->ShowWindowOff();


    volume=vtkSmartPointer<vtkVolume>::New();

    vtkNew<vtkVolumeProperty> volumeProperty;
    volume->SetProperty(volumeProperty);
    vtkNew<vtkGPUVolumeRayCastMapper> volumeMapper;
    volume->SetMapper(volumeMapper);

绘制

drawImage(QPainter &painter)
{
    // if(!bInit)
    //     return ;

    if(

)
    {
        windowToImageFilter->Update();
        outImage=windowToImageFilter->GetOutput();
        outImage->GetOrigin(outputImageOrigin);
        outImage->GetDimensions(outputDimensions);
        if(outputDimensions[0]>0)
        {
            image=QImage(outputDimensions[0], outputDimensions[1],QImage::Format_RGB32);
            uchar* pdata=(uchar*)outImage->GetScalarPointer();
            for(auto i=0;i<image.height();i++)
            {
                uchar* pSrcLine=pdata+i*image.width()*4;
                uchar* pline=image.scanLine(i);
                for(auto j=0;j<image.width();j++)
                {
                    pline[j*4]=pSrcLine[j*4+2];
                    pline[j*4+1]=pSrcLine[j*4+1];
                    pline[j*4+2]=pSrcLine[j*4];
                }
            }
            //image=QImage((uchar*)outImage->GetScalarPointer(), outputDimensions[0], outputDimensions[1],QImage::Format_RGB32);
        }

        painter.drawImage(image.rect(),image,image.rect());
    }
}

在场景上添加需要绘制的多边形

addPolyData(std::string name, vtkPolyData *polydata)
{
    if(!actorMap.count(name))
    {
        vtkSmartPointer<vtkActor> pactor=vtkSmartPointer<vtkActor>::New();
        vtkNew<vtkPolyDataMapper> mapper;
        mapper->SetInputData(polydata);
        pactor->SetMapper(mapper);
        vtkNew<vtkProperty> property;
        property->SetColor(1.0,0,0);
        property->SetAmbientColor(1.0,0,0);
        property->SetDiffuseColor(1.0,0,0);
        property->SetOpacity(0.7);
        pactor->SetProperty(property);
        getRenderer()->AddActor(pactor);

        int num=256;
        vtkNew<vtkLookupTable> lut;
        lut->SetNumberOfColors(num);
        lut->SetTableRange(0, num-1);
        lut->SetScaleToLinear();
        lut->Build();
        lut->SetTableValue(0, 0, 0, 0, 1);
        vtkNew<vtkNamedColors> nameColors;
        std::map<std::string,vtkColor4ub> colors;
        colors["pelvis"]=nameColors->GetColor4ub("forest_green");
        colors["leftfemur"]=nameColors->GetColor4ub("violet_dark");
        colors["rightfemur"]=nameColors->GetColor4ub("violet_red");
        vtkColor4ub color=colors[name];
        for (int i = 1; i < num; ++i)
        {
            lut->SetTableValue(i, color.GetRed(),color.GetGreen(), color.GetBlue(), 1.0);
         //    int k=nameColors->GetNumberOfColors();

         //    double* color=nameColors->GetColor3d("")
         //    lut->SetTableValue(i,nam)
         //    auto r = randomSequence->GetRangeValue(0.4, 1);
         //    randomSequence->Next();
         //    auto g = randomSequence->GetRangeValue(0.4, 1);
         //    randomSequence->Next();
         //    auto b = randomSequence->GetRangeValue(0.4, 1);
         //    randomSequence->Next();
         //    lut->SetTableValue(i, r, g, b, 1.0);
        }
        mapper->SetLookupTable(lut);

        actorMap[name]=pactor;
    }else
    {
        auto pactor=actorMap[name];
        pactor->GetMapper()->SetInputDataObject(polydata);
    }
    renderWindow->Render();
}
 

在屏幕上添加一个点

addPointWidget(std::string name, std::vector<double> pos)
{
    if(!widgetMap.count(name))
    {
        vtkSmartPointer<vtkSphereWidget> pw=vtkSmartPointer<vtkSphereWidget>::New();
        pw->SetCenter(pos.data());
        pw->SetRadius(5);
        pw->SetScale(false);
        pw->SetTranslation(false);
        pw->SetRepresentationToSurface();
        pw->GetSphereProperty()->SetColor(
            colors->GetColor3d("BurlyWood").GetData());
        pw->SetInteractor(renderWindow->GetInteractor());
        vtkNew<SphereCallback> sphereCallback;
        sphereCallback->view=this;
        pw->AddObserver(vtkCommand::StartInteractionEvent, sphereCallback);
        pw->AddObserver(vtkCommand::InteractionEvent, sphereCallback);
        pw->On();
        widgetMap[name]=pw;
    }else
    {
        vtkSphereWidget* pw=dynamic_cast<vtkSphereWidget*>(widgetMap[name].GetPointer());
        if(pw)
        {
            pw->SetCenter(pos.data());
        }else
        {

        }
    }
    renderWindow->Render();
}

移动点坐标

class SphereCallback : public vtkCallbackCommand
{
public:
    static SphereCallback* New()
    {
        return new SphereCallback;
    }
    SphereCallback()
    {
    }

    virtual void Execute(vtkObject* caller, unsigned long, void*)
    {

        vtkSphereWidget* sphereWidget = reinterpret_cast<vtkSphereWidget*>(caller);

        double center[3];
        sphereWidget->GetCenter(center);
        std::cout << "Center: " << center[0] << " " << center[1] << " " << center[2]
                  << std::endl;
        view->setCrossPosition(center);
    }
    YVolumeView* view=nullptr;
};

绘制QWidget

void YVolumeWidget::mousePressEvent(QMouseEvent *event)
{
    auto interactor=view->renderWindow->GetInteractor();
    interactor->SetEventInformation(event->pos().x(),event->pos().y());
    mouseButton=event->button();
    switch (event->button()) {
    case Qt::LeftButton:
        interactor->LeftButtonPressEvent();
        break;
    case Qt::MiddleButton:
        interactor->MiddleButtonPressEvent();
        break;
    case Qt::RightButton:
        interactor->RightButtonPressEvent();
        break;
    default:
        break;
    }
}

void YVolumeWidget::mouseReleaseEvent(QMouseEvent *event)
{
    auto interactor=view->renderWindow->GetInteractor();
    interactor->SetEventInformation(event->pos().x(),event->pos().y());

    switch (mouseButton) {
    case Qt::LeftButton:
        interactor->LeftButtonReleaseEvent();
        break;
    case Qt::MiddleButton:
        interactor->MiddleButtonReleaseEvent();
        break;
    case Qt::RightButton:
        interactor->RightButtonReleaseEvent();
        break;
    default:
        break;
    }
    mouseButton=Qt::NoButton;
    update();
}

void YVolumeWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
}

void YVolumeWidget::mouseMoveEvent(QMouseEvent *event)
{
    if(mouseButton!=Qt::NoButton)
    {
        auto interactor=view->renderWindow->GetInteractor();
        interactor->SetEventInformation(event->pos().x(),event->pos().y());
        interactor->MouseMoveEvent();
        update();
    }
}

void YVolumeWidget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.fillRect(rect(),QBrush(Qt::black));
    if(view->windowToImageFilter)
    {
        view->windowToImageFilter->Modified();
        view->drawImage(painter);
        QTransform vt;
        vt.translate(width()-50,height()-50);
        orientationMarker.setViewTransform(vt);
        auto camera=view->getRenderer()->GetActiveCamera();
        double vx[3];
        double* vz =camera->GetDirectionOfProjection();
        double* vy =camera->GetViewUp();
        vtkMath::Cross(vy,vz,vx);
        orientationMarker.project(vx,vy,vz);
        orientationMarker.draw(painter);
    }


}

void YVolumeWidget::resizeEvent(QResizeEvent *event)
{

    double r=1;//this->screen()->devicePixelRatio();
    view->setdevicePixelRatio(r);
    view->resize(event->size());
    if(view->renderWindow)
    {
        view->windowToImageFilter->Modified();
    }
}

  • 25
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值