I planed to show the 3D model’s bounds in the display coordinate and update it if the user rotates and zooms in/out in real-time. I’m curious about if the display bounds touch with the 3D model.
The display bounds are shown as a red rectangle in the render window, our 3D model is a simple cone.
We can find that the display bounds may be far away from the model as the view direction changed.
main.cpp
#include <iostream>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkActor.h>
#include <vtkConeSource.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderWindowInteractor.h>
#include "CustomIteractorStyle.h"
#define vtkSPtr vtkSmartPointer
#define vtkSPtrNew(Var, Type) vtkSPtr<Type> Var = vtkSPtr<Type>::New();
using namespace std;
int main()
{
vtkSPtrNew( cone, vtkConeSource );
vtkSPtrNew( mapper, vtkPolyDataMapper );
mapper->SetInputConnection( cone->GetOutputPort() );
vtkSPtrNew( actor, vtkActor );
actor->SetMapper( mapper );
vtkSPtrNew( renderer, vtkRenderer );
renderer->AddActor(actor);
renderer->SetBackground( 0, 0, 0 );
vtkSPtrNew( renderWindow, vtkRenderWindow );
renderWindow->AddRenderer( renderer );
vtkSPtrNew( renderWindowInteractor, vtkRenderWindowInteractor );
renderWindowInteractor->SetRenderWindow( renderWindow );
renderer->ResetCamera();
renderWindow->Render();
vtkSPtrNew( iteractorStyle, CustomIteractorStyle );
iteractorStyle->Setm_ConeActor( actor );
iteractorStyle->Setm_Renderer( renderer );
renderWindowInteractor->SetInteractorStyle( iteractorStyle );
renderWindowInteractor->Start();
return 0;
}
CustomIteractorStyle.h
#pragma once
#include <iostream>
#include <vtkSmartPointer.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkActor.h>
#include <vtkActor2D.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkTransform.h>
#define CPP_SET_MACRO(name,type) \
void Set##name(type _arg) \
{ \
if (this->name != _arg) \
{ \
this->name = _arg; \
} \
}
#define vtkSPtr vtkSmartPointer
#define vtkSPtrNew(Var, Type) vtkSPtr<Type> Var = vtkSPtr<Type>::New();
class CustomIteractorStyle: public vtkInteractorStyleTrackballCamera
{
public:
static CustomIteractorStyle *New(){ return new CustomIteractorStyle(); }
void OnMouseWheelForward() override;
void OnMouseWheelBackward() override;
void OnMouseMove() override;
CPP_SET_MACRO( m_ConeActor, vtkActor *)
CPP_SET_MACRO( m_Renderer, vtkRenderer* )
protected:
void ComputeDisplayBds( double *resultBounds, vtkSmartPointer<vtkActor> actor );
void UpdateDisplayBds();
CustomIteractorStyle();
~CustomIteractorStyle() override;
vtkSmartPointer<vtkActor2D> m_Actor2DDebug;
vtkActor *m_ConeActor;
vtkRenderer *m_Renderer;
};
CustomIteractorStyle.cpp
#include "CustomIteractorStyle.h"
#include <vtkCoordinate.h>
#include <vtkPolyDataMapper2D.h>
#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty2D.h>
void CustomIteractorStyle::OnMouseWheelForward()
{
vtkInteractorStyleTrackballCamera::OnMouseWheelForward();
UpdateDisplayBds();
}
void CustomIteractorStyle::OnMouseWheelBackward()
{
vtkInteractorStyleTrackballCamera::OnMouseWheelBackward();
UpdateDisplayBds();
}
void CustomIteractorStyle::OnMouseMove()
{
vtkInteractorStyleTrackballCamera::OnMouseMove();
UpdateDisplayBds();
}
void CustomIteractorStyle::ComputeDisplayBds(double *resultBounds, vtkSmartPointer<vtkActor> actor)
{
double *bounds = actor->GetBounds();
double coordinate[8][3] =
{
bounds[0], bounds[2], bounds[4],
bounds[0], bounds[3], bounds[4],
bounds[0], bounds[2], bounds[5],
bounds[0], bounds[3], bounds[5],
bounds[1], bounds[2], bounds[4],
bounds[1], bounds[3], bounds[4],
bounds[1], bounds[2], bounds[5],
bounds[1], bounds[3], bounds[5],
};
double displayBounds[6] = { VTK_DOUBLE_MAX, VTK_DOUBLE_MIN, VTK_DOUBLE_MAX,
VTK_DOUBLE_MIN, VTK_DOUBLE_MAX, VTK_DOUBLE_MIN };
for (int i = 0; i < 8; i++)
{
double tmp[4] = { coordinate[i][0], coordinate[i][1], coordinate[i][2], 0 };
m_Renderer->SetWorldPoint( tmp );
m_Renderer->WorldToDisplay();
double displayPoint[3];
m_Renderer->GetDisplayPoint( displayPoint );
if (displayPoint[0] < displayBounds[0])
displayBounds[0] = displayPoint[0];
if (displayPoint[0] > displayBounds[1])
displayBounds[1] = displayPoint[0];
if (displayPoint[1] < displayBounds[2])
displayBounds[2] = displayPoint[1];
if (displayPoint[1] > displayBounds[3])
displayBounds[3] = displayPoint[1];
if (displayPoint[2] < displayBounds[4])
displayBounds[4] = displayPoint[2];
if (displayPoint[2] > displayBounds[5])
displayBounds[5] = displayPoint[2];
}
for( int i = 0; i < 6; ++i )
{
resultBounds[i] = displayBounds[i];
}
// -------------- debug ----------------
// ==== start to draw line ====
vtkSmartPointer<vtkPoints> points =
vtkSmartPointer<vtkPoints>::New();
points->InsertNextPoint( displayBounds[0], displayBounds[2], 0 );
points->InsertNextPoint( displayBounds[1], displayBounds[2], 0 );
points->InsertNextPoint( displayBounds[1], displayBounds[3], 0 );
points->InsertNextPoint( displayBounds[0], displayBounds[3], 0 );
vtkSmartPointer<vtkCellArray> cells =
vtkSmartPointer<vtkCellArray>::New();
vtkIdType line0[2] = {0, 1};
cells->InsertNextCell(2, line0);
vtkIdType line1[2] = {1, 2};
cells->InsertNextCell(2, line1);
vtkIdType line2[2] = {2, 3};
cells->InsertNextCell(2, line2);
vtkIdType line3[2] = {3, 0};
cells->InsertNextCell(2, line3);
vtkSmartPointer<vtkPolyData> polydata =
vtkSmartPointer<vtkPolyData>::New();
polydata->SetPoints(points);
polydata->SetLines(cells);
polydata->Modified();
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputData(polydata);
mapper->Update();
vtkSmartPointer<vtkCoordinate> coordinateIns =
vtkSmartPointer<vtkCoordinate>::New();
coordinateIns->SetCoordinateSystemToDisplay();
vtkSmartPointer<vtkPolyDataMapper2D> mapper2D =
vtkSmartPointer<vtkPolyDataMapper2D>::New();
mapper2D->SetInputData(polydata);
mapper2D->SetTransformCoordinate(coordinateIns);
mapper2D->Update();
m_Actor2DDebug->SetMapper( mapper2D );
m_Actor2DDebug->GetProperty()->SetColor( 1, 0, 0 );
// -------------- finish: debug ----------------
}
void CustomIteractorStyle::UpdateDisplayBds()
{
double displayBds[6];
ComputeDisplayBds( displayBds, m_ConeActor );
m_Renderer->AddActor2D( m_Actor2DDebug );
}
CustomIteractorStyle::CustomIteractorStyle()
{
m_ConeActor = nullptr;
m_Renderer = nullptr;
m_Actor2DDebug = vtkSmartPointer<vtkActor2D>::New();
}
CustomIteractorStyle::~CustomIteractorStyle()
{
m_ConeActor = nullptr;
}
[…] I had tried to show display coordinate bounds of the 3D model in the article VTK: Show Display Bounds. […]
[…] two old posts about draw display bounding box, VTK: Show Display Bounds After Project Points and VTK: Show Display Bounds. But they didn’t give me a statisfy result.In this post, I find feature edges of the mesh […]