split viewport for Qt and VtkViewer

This commit is contained in:
AndreaRigoni
2026-03-17 15:29:07 +00:00
parent 4569407d18
commit e6e0bccffb
7 changed files with 345 additions and 233 deletions

228
src/Vtk/vtkViewport.cpp Normal file
View File

@@ -0,0 +1,228 @@
#include "vtkViewport.h"
#include <vtkAxes.h>
#include <vtkAxesActor.h>
#include <vtkCamera.h>
#include <vtkCameraOrientationWidget.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkObjectFactory.h>
#include <vtkPlaneSource.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSmartPointer.h>
#include <vtkNew.h>
#include <vtkTextProperty.h>
#include <vtkPolyDataMapper.h>
#include <vtkNamedColors.h>
#include <vtkProperty.h>
#include <vtkCallbackCommand.h>
#include <vtkMath.h>
#include <vtkActor.h>
#include <cmath>
namespace uLib {
namespace Vtk {
Viewport::Viewport()
: m_Renderer(vtkRenderer::New())
, m_Annotation(vtkCornerAnnotation::New())
, m_Marker(vtkOrientationMarkerWidget::New())
, m_CameraWidget(nullptr)
, m_Colors(vtkNamedColors::New())
{
}
Viewport::~Viewport()
{
if (m_Renderer) {
m_Renderer->RemoveAllViewProps();
m_Renderer->Clear();
}
if (m_Annotation) m_Annotation->Delete();
if (m_Marker) m_Marker->Delete();
if (m_CameraWidget) m_CameraWidget->Delete();
if (m_Renderer) m_Renderer->Delete();
if (m_Colors) m_Colors->Delete();
}
void Viewport::SetupPipeline(vtkRenderWindowInteractor* iren)
{
if (!iren) return;
// Trackball-camera interaction style
vtkNew<vtkInteractorStyleTrackballCamera> style;
iren->SetInteractorStyle(style);
// Corner annotation
m_Annotation->GetTextProperty()->SetColor(1, 1, 1);
m_Annotation->GetTextProperty()->SetFontFamilyToArial();
m_Annotation->GetTextProperty()->SetOpacity(0.5);
m_Annotation->SetMaximumFontSize(10);
m_Annotation->SetText(0, "uLib VTK Viewer - OpenCMT all right reserved.");
m_Renderer->AddViewProp(m_Annotation);
// Orientation axes marker (bottom-left corner)
vtkNew<vtkAxesActor> axes;
m_Marker->SetInteractor(iren);
m_Marker->SetOrientationMarker(axes);
m_Marker->SetViewport(0.0, 0.0, 0.2, 0.2);
m_Marker->SetEnabled(true);
m_Marker->InteractiveOff();
// Grid Plane centered at (0,0,0)
m_GridSource = vtkSmartPointer<vtkPlaneSource>::New();
m_GridActor = vtkSmartPointer<vtkActor>::New();
vtkNew<vtkPolyDataMapper> gridMapper;
gridMapper->SetInputConnection(m_GridSource->GetOutputPort());
m_GridActor->SetMapper(gridMapper);
m_GridActor->GetProperty()->SetRepresentationToWireframe();
m_GridActor->GetProperty()->SetColor(0.4, 0.4, 0.4);
m_GridActor->GetProperty()->SetLighting(0);
m_GridActor->GetProperty()->SetOpacity(0.5);
m_GridActor->PickableOff();
m_Renderer->AddActor(m_GridActor);
// Global Origin Axes
m_OriginAxes = vtkSmartPointer<vtkAxes>::New();
m_OriginAxes->SetScaleFactor(1.0); // will be updated
vtkNew<vtkPolyDataMapper> axesMapper;
axesMapper->SetInputConnection(m_OriginAxes->GetOutputPort());
m_OriginAxesActor = vtkSmartPointer<vtkActor>::New();
m_OriginAxesActor->SetMapper(axesMapper);
m_OriginAxesActor->PickableOff();
m_Renderer->AddActor(m_OriginAxesActor);
UpdateGrid();
// Observe interactor to update grid during interaction
vtkNew<vtkCallbackCommand> interactionCallback;
interactionCallback->SetClientData(this);
interactionCallback->SetCallback([](vtkObject*, unsigned long, void* clientdata, void*){
static_cast<Viewport*>(clientdata)->UpdateGrid();
});
iren->AddObserver(vtkCommand::InteractionEvent, interactionCallback);
m_Renderer->GetActiveCamera()->AddObserver(vtkCommand::ModifiedEvent, interactionCallback);
// Camera-orientation widget (VTK >= 9)
#if VTK_MAJOR_VERSION >= 9
m_CameraWidget = vtkCameraOrientationWidget::New();
m_CameraWidget->SetParentRenderer(m_Renderer);
m_CameraWidget->SetInteractor(iren);
m_CameraWidget->On();
#endif
m_Renderer->SetBackground(0.15, 0.15, 0.15);
m_Renderer->ResetCamera();
}
void Viewport::Reset()
{
ZoomAuto();
Render();
}
void Viewport::ZoomAuto()
{
if (m_Renderer) {
m_Renderer->ResetCameraClippingRange();
m_Renderer->ResetCamera();
}
}
void Viewport::AddPuppet(Puppet& prop)
{
prop.ConnectRenderer(m_Renderer);
prop.ConnectInteractor(GetInteractor());
Render();
}
void Viewport::RemovePuppet(Puppet& prop)
{
prop.DisconnectRenderer(m_Renderer);
Render();
}
void Viewport::addProp(vtkProp* prop)
{
if (m_Renderer) {
m_Renderer->AddActor(prop);
Render();
}
}
void Viewport::RemoveProp(vtkProp* prop)
{
if (m_Renderer) {
m_Renderer->RemoveViewProp(prop);
Render();
}
}
void Viewport::UpdateGrid()
{
if (!m_Renderer || !m_GridSource) return;
vtkCamera* camera = m_Renderer->GetActiveCamera();
if (!camera) return;
// Determine the "scale" of the view (how many units are visible vertically)
double viewHeight;
if (camera->GetParallelProjection()) {
viewHeight = 2.0 * camera->GetParallelScale();
} else {
double distance = camera->GetDistance();
// ViewAngle is height angle in degrees
double angleRad = camera->GetViewAngle() * vtkMath::Pi() / 180.0;
viewHeight = 2.0 * distance * std::tan(angleRad / 2.0);
}
if (viewHeight <= 0) viewHeight = 1.0;
// We want roughly 5-15 grid divisions visible.
// Spacing should be a power of 10 (1mm, 1cm, 10cm, 1m, 10m...)
double log10Spacing = std::floor(std::log10(viewHeight / 5.0));
double spacing = std::pow(10.0, log10Spacing);
// Get current focal point to center the grid near what we're looking at
double focalPoint[3];
camera->GetFocalPoint(focalPoint);
// Align center to spacing
double centerX = std::round(focalPoint[0] / spacing) * spacing;
double centerY = std::round(focalPoint[1] / spacing) * spacing;
// Number of lines: enough to cover the screen even if aspect ratio is wide
// or if we rotate. 20x20 is usually plenty.
int numLines = 20;
double halfSize = (numLines / 2.0) * spacing;
double xmin = centerX - halfSize;
double xmax = centerX + halfSize;
double ymin = centerY - halfSize;
double ymax = centerY + halfSize;
// Update Plane Source
m_GridSource->SetOrigin(xmin, ymin, 0.0);
m_GridSource->SetPoint1(xmax, ymin, 0.0);
m_GridSource->SetPoint2(xmin, ymax, 0.0);
m_GridSource->SetXResolution(numLines);
m_GridSource->SetYResolution(numLines);
m_GridSource->Update();
if (m_OriginAxes) {
m_OriginAxes->SetScaleFactor(spacing);
}
}
} // namespace Vtk
} // namespace uLib