I have some crazy issues in my code, and these issue is:
1) As you see in code below, if I execute it I will got a 3D preview model without sliderWidget. (Fixed)
2) If I change this line from mapper->SetInputConnection(surface->GetOutputPort()); to mapper->SetInputConnection(reader->GetOutputPort()); I will got a sliderWidget but I will not see a 3D model. (Fixed)
3) If I try to set custom key event, its will be work and change value but every change I need to wait until its reload or build 3d dicom (its work like you run and create a 3D model every time not like a slider).
class vtkSliderCallback : public vtkCommand
{
public:
int counter = 1;
static vtkSliderCallback *New()
{
return new vtkSliderCallback;
}
virtual void Execute(vtkObject *caller, unsigned long, void*)
{
vtkSliderWidget *sliderWidget =
reinterpret_cast<vtkSliderWidget*>(caller);
cout << this->counter << endl;
this->SphereSource->SetValue(this->counter++, static_cast<vtkSliderRepresentation *>(sliderWidget->GetRepresentation())->GetValue());
}
vtkSliderCallback():SphereSource(0) {}
vtkMarchingCubes *SphereSource;
};
int main(int argc, char* argv[])
{
// Verify input arguments
if ( argc < 4 )
{
std::cout << "Usage: " << argv[0]
<< " DicomSiresFolder" << " isoValueStep" << " OutputDirectory" << std::endl;
return EXIT_FAILURE;
}
std::string folder = argv[1];
// A sphere
vtkSmartPointer<vtkImageData> volume =
vtkSmartPointer<vtkImageData>::New();
vtkSmartPointer<vtkDICOMImageReader> reader =
vtkSmartPointer<vtkDICOMImageReader>::New();
reader->SetDirectoryName(folder.c_str());
reader->Update();
volume->DeepCopy(reader->GetOutput());
vtkSmartPointer<vtkMarchingCubes> surface =
vtkSmartPointer<vtkMarchingCubes>::New();
surface->SetInputData(volume);
surface->ComputeNormalsOn();
surface->SetValue(0, 400);
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(surface->GetOutputPort());
mapper->ScalarVisibilityOff();
vtkSmartPointer<vtkActor> actor =
vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
actor->GetProperty()->SetInterpolationToFlat();
// A renderer and render window
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
// An interactor
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
// Add the actors to the scene
renderer->AddActor(actor);
// Render an image (lights and cameras are created automatically)
renderWindow->Render();
vtkSmartPointer<vtkSliderRepresentation3D> sliderRep =
vtkSmartPointer<vtkSliderRepresentation3D>::New();
sliderRep->SetMinimumValue(-800.0);
sliderRep->SetMaximumValue(800.0);
sliderRep->SetTitleText("Iso Resolution");
sliderRep->GetPoint1Coordinate()->SetCoordinateSystemToWorld();
sliderRep->GetPoint1Coordinate()->SetValue(-4,6,0);
sliderRep->GetPoint2Coordinate()->SetCoordinateSystemToWorld();
sliderRep->GetPoint2Coordinate()->SetValue(4,6,0);
sliderRep->SetSliderLength(0.075);
sliderRep->SetSliderWidth(0.05);
sliderRep->SetEndCapLength(0.05);
vtkSmartPointer<vtkSliderWidget> sliderWidget =
vtkSmartPointer<vtkSliderWidget>::New();
sliderWidget->SetInteractor(renderWindowInteractor);
sliderWidget->SetRepresentation(sliderRep);
sliderWidget->SetAnimationModeToAnimate();
sliderWidget->EnabledOn();
vtkSmartPointer<vtkSliderCallback> callback =
vtkSmartPointer<vtkSliderCallback>::New();
callback->SphereSource = surface;
sliderWidget->AddObserver(vtkCommand::InteractionEvent,callback);
renderWindowInteractor->Initialize();
renderWindow->Render();
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}
UPDATE:
I Fixed issue on point 1 and 2, but still Issue 3 needed to fix.
Your callback is changing the value for vtkMarchingCube, so you're running a marching cubes every time, so yes, it's rebuilding a mesh every time. As far as I understand what you need to do, one solution can be to precompute vtkMarchingCubes output for all possible values: not elegant (but it could work if you have enough memory).
In any case, use vtkFlyingEdges3D instead of vtkMarchingCubes, it's much faster (it could be fast enough to solve your problem without any other modification).
Related
I am trying to put the example provided by VTK here into a C++ class. This example reads an STL file and visualizes it in a window.
Below is my code for which I get no compiler or run-time error. My input STL file is read correctly but my code exits without producing any visualization of the STL object.
In my C++ class, I organized the VTK example code by separating the reader from the visualizer and putting them into two functions in the class. The visualizer uses a mapper, actor, and a renderer to visualize the STL object. However, I am not able to get the code to visualize my STL object.
The only way I am able to get my C++ class to work is to copy the codes of the function visualize into my readSTL function, then I can see the window with my STL object rendered in it.
Could someone kindly give me some hints how I can perform the visualization in a separate function in the class?
#include <vtkPolyData.h>
#include <vtkSTLReader.h>
#include <vtkSmartPointer.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
class triangulation
{
public:
vtkIdType numberOfFaces;
// Constructor
triangulation(void);
triangulation(std::string filename);
void setFilename(std::string filename);
std::string getFilename(void);
// Getters
vtkSmartPointer<vtkPolyData> getMesh(void);
vtkSmartPointer<vtkCellArray> getPolys(void);
vtkSmartPointer<vtkPoints> getPoints(void);
vtkSmartPointer<vtkDataArray> getDataArray(void);
vtkIdType getNumberofFaces(void);
// Visualizer
void visualize(void);
// Reader
void readSTL(void);
private:
std::string stlFilename;
vtkSmartPointer<vtkPolyData> mesh;
vtkSmartPointer<vtkSTLReader> reader;
vtkSmartPointer<vtkCellArray> polys;
vtkSmartPointer<vtkPoints> points;
vtkSmartPointer<vtkDataArray> dataArray;
};
triangulation::triangulation()
{
//
}
triangulation::triangulation(std::string filename)
{
setFilename(filename);
}
void triangulation::readSTL(void)
{
vtkSmartPointer<vtkSTLReader> reader = vtkSmartPointer<vtkSTLReader>::New();
reader->SetFileName(stlFilename.c_str());
reader->Update();
mesh = reader->GetOutput();
polys = mesh->GetPolys();
points = mesh->GetPoints();
numberOfFaces = mesh->GetNumberOfCells();
}
void triangulation::setFilename(std::string filename)
{
stlFilename = filename;
}
std::string triangulation::getFilename(void)
{
return stlFilename;
}
vtkSmartPointer<vtkPolyData> triangulation::getMesh(void)
{
return mesh;
}
vtkSmartPointer<vtkCellArray> triangulation::getPolys(void)
{
return polys;
}
vtkIdType triangulation::getNumberofFaces(void)
{
return numberOfFaces;
}
vtkSmartPointer<vtkPoints> triangulation::getPoints(void)
{
return points;
}
vtkSmartPointer<vtkDataArray> triangulation::getDataArray(void)
{
return dataArray;
}
void triangulation::visualize(void)
{
// Visualize
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(reader->GetOutputPort());
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
renderer->AddActor(actor);
renderer->SetBackground(.3, .6, .3); // Background color green
renderWindow->Render();
renderWindowInteractor->Start();
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
cout << "Required parameters: Filename" << endl;
return EXIT_FAILURE;
}
std::string inputFilename = argv[1];
cout << inputFilename << endl;
triangulation *tr = new triangulation(inputFilename);
tr->readSTL();
cout << "Number of Faces = " << tr->getNumberofFaces() << endl;
vtkSmartPointer<vtkPolyData> mesh = tr->getMesh();
vtkSmartPointer<vtkCellArray> polys = tr->getPolys();
vtkSmartPointer<vtkPoints> points = tr->getPoints();
vtkSmartPointer<vtkDataArray> data = tr->getDataArray();
//mesh->Print(cout);
// polys->Print(cout);
// points->Print(cout);
// data->Print(cout);
tr->visualize();
delete tr;
return EXIT_SUCCESS;
}
Here is my STL object that I used to test my code:
"myobject.stl":
solid STL generated by MeshLab
facet normal -4.919344e-01 2.986337e-01 8.178133e-01
outer loop
vertex -1.265660e+00 4.756133e+00 1.702858e-01
vertex -1.649185e+00 4.810246e+00 -8.017353e-02
vertex -1.602208e+00 4.484959e+00 6.686619e-02
endloop
endfacet
facet normal -5.898571e-01 2.603427e-01 7.643889e-01
outer loop
vertex -1.861084e+00 4.821712e+00 -2.475956e-01
vertex -1.602208e+00 4.484959e+00 6.686619e-02
vertex -1.649185e+00 4.810246e+00 -8.017353e-02
endloop
endfacet
facet normal -6.398674e-01 2.007942e-01 7.417893e-01
outer loop
vertex -1.861084e+00 4.821712e+00 -2.475956e-01
vertex -1.845646e+00 4.479523e+00 -1.416520e-01
vertex -1.602208e+00 4.484959e+00 6.686619e-02
endloop
endfacet
facet normal -6.901410e-01 1.854371e-01 6.995131e-01
outer loop
vertex -2.043903e+00 4.838252e+00 -4.323493e-01
vertex -1.845646e+00 4.479523e+00 -1.416520e-01
vertex -1.861084e+00 4.821712e+00 -2.475956e-01
endloop
endfacet
endsolid vcg
Your code will work if you simply replace the following line in triangulation::readSTL():
// Problem: local variable 'reader' shadows class member 'reader'.
vtkSmartPointer<vtkSTLReader> reader = vtkSmartPointer<vtkSTLReader>::New();
// Solution:
reader = vtkSmartPointer<vtkSTLReader>::New();
Because the class-member reader remains unintialized, the application crashes with a segfault when it is being accessed in triangulation::visualize().
Hint: you probably would not have encountered this problem if you consequently used this-> or a naming prefix (m_ or _) to refer to class members. See this SO post for some explanations.
Currently, based on the VTK ZBuffer example, I iteratively rotate the 3D model and capture each time the depth map. The issue is that although the model rotates the output images contain all the first depth map.
int main(int argc, char *argv[]){
...variable declaration/initialization
//read off file
offReader->SetFileName(argv[1]);
offReader->Update();
int step = 30; std::string out;
for (int i = 0; i < 3; i++) {
mapper->NewInstance();
actor->NewInstance();
renWin->NewInstance();
renderer->NewInstance();
mapper->SetInputData(polyData);
actor->SetMapper(mapper);
out = std::to_string(i);
actor->RotateZ(step*i);
renWin->AddRenderer(renderer);
renderer->AddActor(actor);
renderer->SetBackground(1, 1, 1);
renWin->Render();
// Create Depth Map
filter->NewInstance();
scale->NewInstance();
imageWriter->NewInstance();
filter->SetInput(renWin);
filter->SetMagnification(3);
filter->SetInputBufferTypeToZBuffer(); //Extract z buffer value
filter->Update();
scale->SetOutputScalarTypeToUnsignedChar();
scale->SetInputConnection(filter->GetOutputPort());
scale->SetShift(0);
scale->SetScale(-255);
scale->Update();
std::string out1 = out + "_depth.bmp";
std::cout << " " << out1 << std::endl;
// Write surface map as a .bmp image
imageWriter->SetFileName(out1.c_str());
imageWriter->SetInputConnection(scale->GetOutputPort());
imageWriter->Update();
imageWriter->Write();
filter->RemoveAllInputs();
scale->RemoveAllInputs();
imageWriter->RemoveAllInputs();
renderer->RemoveActor(actor);
renWin->RemoveRenderer(renderer);
.... remaining script
}
The output depth maps are all identical. 0_depth.bmp, 1_depth.bmp & 2_depth.bmp
Has anyone encountered the same issue? If yes, what could be a potential solution.
Problem solved by introducing a function within the rotation took place. Apparently it was a matter of a variable content update issue, that could be solved in a more straight forward way.
I have a 3D .vtk model that I render and I extract the contour from the resulting image using a vtkContourFilter (using vtk version 7.0.0 on Ubuntu 16.04).
I would like to project it from different perspectives, but as I loop over the different camera positions (I checked that the camera positions are indeed changed) the interactive viewer that launches with each iteration always shows the contour from the first image.
When I output the first few coordinates of the found contour points (which I store as a vtkPolyData) I also noticed that the content in my set of contour points does not change.
I have tried some online suggestions that worked for others, such as adding:
ContFilter->Modified();
ContFilter->Update();
and
polyData->Modified(); // This is the 3D vtkPolyData that I project
and
ContFilter->SetValue(0, 10);
ContFilter->SetValue(0, 255);
As a wild guess I also tried adding:
polyData->Modified();
// Remove old links
renderWindow->RemoveRenderer(renderer);
mapper->RemoveAllInputs();
// Set new links
renderer->SetActiveCamera(camera);
renderWindow->AddRenderer(renderer);
renderer->Modified();
renderer->ResetCameraClippingRange();
renderWindow->Modified();
mapper->SetInputData(polyData);
renderWindow->Render();
within the for loop, before using the ContourFilter, but it still does not update. With that I tried everything I could think of and find online.
This is the relevant code:
// Prepare the rendering environment to project the 3D model to an image from different perspectives
vtkSmartPointer<vtkDataSetMapper> mapper = vtkSmartPointer<vtkDataSetMapper>::New();
mapper->SetInputData(polyData);
mapper->ScalarVisibilityOff();
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
actor->GetProperty()->SetInterpolationToFlat();
vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
renderer->SetBackground(1,1,1);
renderer->AddActor(actor);
vtkSmartPointer<vtkCamera> camera = vtkSmartPointer<vtkCamera>::New();
vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->SetOffScreenRendering(1);
vtkSmartPointer<vtkWindowToImageFilter> windowToImageFilter = vtkSmartPointer<vtkWindowToImageFilter>::New();
vtkSmartPointer<vtkContourFilter> ContFilter = vtkSmartPointer<vtkContourFilter>::New();
vtkSmartPointer<vtkPolyData> contour = vtkSmartPointer<vtkPolyData>::New();
// Loop over the camera positions. At each iteration render/project,
// extract the contour and finally render the 3D model and the found
// contour
double * iPoint;
double * camPos;
double * contourStart;
int nContours;
for(int i=0; i<positions->GetNumberOfPoints(); i++){
// Print the camera position
iPoint = positions->GetPoint(i);
std::cout << iPoint[0] << " " << iPoint[1] << " " << iPoint[2] << std::endl;
//Move camera
camera->SetPosition(iPoint[0], iPoint[1], iPoint[2]);
camera->SetFocalPoint(focalPointOrig[0], focalPointOrig[1], focalPointOrig[2]);
camera->SetViewAngle(viewAngle);
camera->Modified();
camera->SetRoll(90);
// Does this help to update the view?
polyData->Modified();
// Remove old links and set them again
renderWindow->RemoveRenderer(renderer);
mapper->RemoveAllInputs();
renderer->SetActiveCamera(camera);
renderWindow->AddRenderer(renderer);
renderer->Modified();
renderer->ResetCameraClippingRange();
renderWindow->Modified();
// Render/project the data
mapper->SetInputData(polyData);
renderWindow->Render();
// Print camera position for debugging
camera->GetPosition(camPos);
std::cout << camPos[0] << " " << camPos[1] << " " << camPos[2] << std::endl;
// Get the image and apply a contourfilter
windowToImageFilter->SetInput(renderWindow);
windowToImageFilter->Update();
ContFilter->SetInputConnection(windowToImageFilter->GetOutputPort());
// Saw someone do this as a workaround for updating the view
ContFilter->SetValue(0, 10);
ContFilter->SetValue(0, 255);
// Does this help to update the view?
ContFilter->Modified();
//Get the contour from the contourfilter
ContFilter->Update();
contour = ContFilter->GetOutput();
// Print the first points coordinates to see if they changed
contourStart = contour->GetPoint(1);
std::cout << contourStart[0] << " " << contourStart[1] << " " << std::endl;
// Print the number of contours to see if it may be stored as an additional contour
nContours = ContFilter->GetNumberOfContours();
std::cout << nContours << std::endl;
// Render the 3D model and the found contour
actor->GetProperty()->SetColor(0.9,0.9,0.8);
// Create a mapper and actor of the silhouette
vtkSmartPointer<vtkPolyDataMapper> mapper_contour = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper_contour->SetInputData(contour);
// Try this again here
polyData->Modified();
vtkSmartPointer<vtkActor> actor_contour = vtkSmartPointer<vtkActor>::New();
actor_contour->SetMapper(mapper_contour);
actor_contour->GetProperty()->SetLineWidth(2.);
// 2 renderers and a render window
vtkSmartPointer<vtkRenderer> renderer1 = vtkSmartPointer<vtkRenderer>::New();
renderer1->AddActor(actor);
vtkSmartPointer<vtkRenderer> renderer2 = vtkSmartPointer<vtkRenderer>::New();
renderer2->AddActor(actor_contour);
// Set the 3D model renderer to the same perspective but don't change the camera perspective of the contour
renderer1->SetActiveCamera(camera);
// Setup the window
vtkSmartPointer<vtkRenderWindow> renderwindow = vtkSmartPointer<vtkRenderWindow>::New();
renderwindow->SetSize(1600, 800);
renderwindow->AddRenderer(renderer1);
renderer1->SetViewport(0., 0., 0.5, 1.);
renderwindow->AddRenderer(renderer2);
renderer2->SetViewport(0.5, 0., 1., 1.);
// Setup the interactor
vtkSmartPointer<vtkInteractorStyleTrackballCamera> style = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
vtkSmartPointer<vtkRenderWindowInteractor> iren = vtkSmartPointer<vtkRenderWindowInteractor>::New();
iren->SetRenderWindow( renderwindow);
iren->SetInteractorStyle(style);
// Display the coordinate system axes
vtkSmartPointer<vtkAxesActor> axes = vtkSmartPointer<vtkAxesActor>::New();
vtkSmartPointer<vtkOrientationMarkerWidget> widget = vtkSmartPointer<vtkOrientationMarkerWidget>::New();
widget->SetOutlineColor( 0.9300, 0.5700, 0.1300 );
widget->SetOrientationMarker( axes );
widget->SetInteractor( iren );
widget->SetViewport( 0.0, 0.0, 0.4, 0.4 );
widget->SetEnabled( 1 );
widget->InteractiveOn();
// Render the 3D model and the found contour
renderwindow->Render();
iren->Start();
}
Just found the answer.
As mentioned in the warning in the detailed description of the vtkWindowToImageFilter class reference webpage (https://www.vtk.org/doc/nightly/html/classvtkWindowToImageFilter.html), vtkWindows generally do not rerender unless you call their Modified() function. Now my projected views are updated like I wanted.
So I changed
// Get the image and apply a contourfilter
windowToImageFilter->SetInput(renderWindow);
windowToImageFilter->Update();
to
// Get the image and apply a contourfilter
windowToImageFilter->Modified();
windowToImageFilter->SetInput(renderWindow);
windowToImageFilter->Update();
See here the warning text in case the link above ever stops working:
Warning:
A vtkWindow doesn't behave like other parts of the VTK pipeline: its modification time doesn't get updated when an image is rendered. As a result, naive use of vtkWindowToImageFilter will produce an image of the first image that the window rendered, but which is never updated on subsequent window updates. This behavior is unexpected and in general undesirable.
To force an update of the output image, call vtkWindowToImageFilter's Modified method after rendering to the window.
In VTK versions 4 and later, this filter is part of the canonical way to output an image of a window to a file (replacing the obsolete SaveImageAsPPM method for vtkRenderWindows that existed in 3.2 and earlier). Connect this filter to the output of the window, and filter's output to a writer such as vtkPNGWriter.
Reading back alpha planes is dependent on the correct operation of the render window's GetRGBACharPixelData method, which in turn is dependent on the configuration of the window's alpha planes. As of VTK 4.4+, machine-independent behavior is not automatically assured because of these dependencies.
I’m trying to obtain a polyData with only the visible part of a 3D model.
To that extent, I’m passing the original data through a vtkSelectVisiblePoints filter.
I’m using a mock renderer, mapper and actor because I want to post-process the visible points before displaying them.
However, the output of the vtkSelectVisiblePoints filter contains “0” points for some reason…
Using the following example:
http://www.vtk.org/Wiki/VTK/Examples/Cxx/PolyData/SelectVisiblePoints
I came up with the following piece of code:
// Render window and interactor
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->SetSize(800, 800);
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
// Mock renderer, mapper and actor
vtkSmartPointer<vtkRenderer> mockRenderer =
vtkSmartPointer<vtkRenderer>::New();
renderWindow->AddRenderer(mockRenderer);
vtkSmartPointer<vtkPolyDataMapper> mockMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mockMapper->SetInput(reader->GetOutput());
vtkSmartPointer<vtkActor> mockActor = vtkSmartPointer<vtkActor>::New();
mockActor->SetMapper(mockMapper);
mockRenderer->AddActor(mockActor);
// Set camera to the correct position
mockRenderer->GetActiveCamera()->SetPosition(0, -1, 0);
mockRenderer->GetActiveCamera()->SetFocalPoint(0, 0, 0);
mockRenderer->GetActiveCamera()->SetViewUp(0, 1, 0);
mockRenderer->ResetCamera();
vtkSmartPointer<vtkSelectVisiblePoints> selectVisiblePoints =
vtkSmartPointer<vtkSelectVisiblePoints>::New();
selectVisiblePoints->SetInput(reader->GetOutput());
selectVisiblePoints->SetRenderer(mockRenderer);
selectVisiblePoints->Update();
std::cout << "Visible nr of points = " << selectVisiblePoints->GetOutput()->GetNumberOfPoints() << std::endl;
renderWindow->RemoveRenderer(mockRenderer);
… prints 0.
However, if I call renderWindow->Render(), the visible part of the model is correctly displayed...
Am I missing anything...?
The answer was right there, in the documentation of the filter:
Warning You must carefully synchronize the execution of this filter.
The filter refers to a renderer, which is modified every time a render
occurs. Therefore, the filter is always out of date, and always
executes. You may have to perform two rendering passes
It worked as expected if I added the //new lines, like Arnas also suggested in his comment:
vtkSmartPointer<vtkSelectVisiblePoints> selectVisiblePoints =
vtkSmartPointer<vtkSelectVisiblePoints>::New();
selectVisiblePoints->SetInput(originalData);
selectVisiblePoints->SetRenderer(renderer);
selectVisiblePoints->Update();
renderWindow->Render(); // new
selectVisiblePoints->Update(); // new
std::cout << "Visible nr of points = " << selectVisiblePoints->GetOutput()->GetNumberOfPoints() << std::endl;
I'm having a small issue with VTK. When I launch my program, it starts to render and then automatically stops while it should actually keep on rendering.
I cannot see where that error may come from. I wrote an other piece of code for the exact same rendering which works just fine.
So here is the constructor of my class:
Drawing::Drawing(void)
{
translation = vtkSmartPointer<vtkTransform>::New();
ctxView = vtkContextView::New();
win = ctxView->GetRenderWindow();
ren = ctxView->GetRenderer();
cam = ren->GetActiveCamera();
ren->SetBackground(.0,.0,.0);
}
Here is the piece of code not working:
void Drawing::read(){
std::string filename = BUNNY;
// Read all the data from the file
vtkSmartPointer<vtkXMLPolyDataReader> reader =vtkSmartPointer<vtkXMLPolyDataReader>::New();
reader->SetFileName(filename.c_str());
reader->Update();
cout << "File Found and Loaded : " << filename << endl ;
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(reader->GetOutputPort());
mainActor = vtkSmartPointer<vtkActor>::New();
mainActor->SetMapper(mapper);
ren->AddActor(mainActor);
win->PolygonSmoothingOn();
win->Render();
win->Start();
}
And here is the piece of code working:
void otherRead(){
std::string filename = BUNNY;
// Read all the data from the file
vtkSmartPointer<vtkXMLPolyDataReader> reader =vtkSmartPointer<vtkXMLPolyDataReader>::New();
reader->SetFileName(filename.c_str());
reader->Update();
cout << "File Found and Loaded : " << filename << endl ;
// Visualize
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(reader->GetOutputPort());
mainActor = vtkSmartPointer<vtkActor>::New();
mainActor->SetMapper(mapper);
vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
iren->SetRenderWindow(renderWindow);
vtkInteractorStyleMultiTouchCamera *style =
vtkInteractorStyleMultiTouchCamera::New();
iren->SetInteractorStyle(style);
renderer->AddActor(mainActor);
renderer->SetBackground(0,0,0); // Background color green
renderWindow->PolygonSmoothingOn();
renderWindow->Render();
renderWindowInteractor->Start();
}
I don't know if it's a vtk or a c++ problem actually. The output of the not-working piece of code is just a few milliseconds window and then the program exists while the otherRead() gives a normal rendering without exiting the program.
Thanks in advance for the help
So it was indeed a vtk problem. One very basic some might say but still not that easy to figure out when you're starting with vtk.
I'm posting the answer, the documentation is not big on vtk so it might help other newbies. So in fact, the event loop for the window has to be started. It can be done thanks to the following lines:
vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
iren->SetRenderWindow(win);
vtkInteractorStyleMultiTouchCamera *style =
vtkInteractorStyleMultiTouchCamera::New();
iren->SetInteractorStyle(style);
//Start the event loop
iren->Initialize();
iren->Start();
Hope this helps :)