We can find that vtkOrientedGlyphContourRepresentation supports to set 3D model always above other objects.
// Create the contour widget
vtkSmartPointer<vtkContourWidget> contourWidget =
vtkSmartPointer<vtkContourWidget>::New();
// Override the default representation for the contour widget to customize its look
vtkSmartPointer<vtkOrientedGlyphContourRepresentation> contourRepresentation =
vtkSmartPointer<vtkOrientedGlyphContourRepresentation>::New();
// ...
contourWidget->SetRepresentation(contourRepresentation);
contourRepresentation->SetAlwaysOnTop( true );
I readed the code source of vtkOrientedGlyphContourRepresentation about AlwaysOnTop
, and found that there is polygon offset controling object’s z buffer.
void vtkOrientedGlyphContourRepresentation::BuildRepresentation()
{
// Make sure we are up to date with any changes made in the placer
this->UpdateContour();
if (this->AlwaysOnTop)
{
// max value 65536 so we subtract 66000 to make sure we are
// zero or negative
this->LinesMapper->SetRelativeCoincidentTopologyLineOffsetParameters(0,-66000);
this->LinesMapper->SetRelativeCoincidentTopologyPolygonOffsetParameters(0,-66000);
this->LinesMapper->SetRelativeCoincidentTopologyPointOffsetParameter(-66000);
So we can simulate the operation to make a model awalys on the top.
Here is a simple example that a red sphere on the center of a big cone, we can see the sphere no matter how we rotating the scene.
#include <iostream>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkActor.h>
#include <vtkConeSource.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkPolyDataMapper.h>
#include <vtkSphereSource.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkProperty.h>
#include <vtkLineSource.h>
#define vtkSPtr vtkSmartPointer
#define vtkSPtrNew(Var, Type) vtkSPtr<Type> Var = vtkSPtr<Type>::New();
using namespace std;
int main()
{
vtkSPtrNew( sphere, vtkSphereSource );
sphere->SetCenter( 0, 0, 0 );
sphere->SetRadius( 1 );
sphere->Update();
vtkSPtrNew( sphereMapper, vtkPolyDataMapper );
// set mapper to make sphere always on top
const double units0 = -66000;
sphereMapper->SetInputData( sphere->GetOutput() );
sphereMapper->SetResolveCoincidentTopologyToPolygonOffset();
sphereMapper->SetRelativeCoincidentTopologyLineOffsetParameters(0, units0);
sphereMapper->SetRelativeCoincidentTopologyPolygonOffsetParameters(0, units0);
sphereMapper->SetRelativeCoincidentTopologyPointOffsetParameter(units0);
vtkSPtrNew( sphereActor, vtkActor );
sphereActor->SetMapper( sphereMapper );
sphereActor->GetProperty()->SetColor( 1, 0, 0 );
vtkSPtrNew( cone, vtkConeSource );
cone->SetRadius( 2 );
cone->SetHeight( 4 );
cone->Update();
vtkSPtrNew( coneMapper, vtkPolyDataMapper );
coneMapper->SetInputData( cone->GetOutput() );
vtkSPtrNew( coneActor, vtkActor );
coneActor->SetMapper( coneMapper );
vtkSPtrNew( renderer, vtkRenderer );
renderer->AddActor( coneActor );
renderer->AddActor( sphereActor );
renderer->SetBackground( 0, 0, 0 );
vtkSPtrNew( renderWindow, vtkRenderWindow );
renderWindow->AddRenderer( renderer );
vtkSPtrNew( renderWindowInteractor, vtkRenderWindowInteractor );
renderWindowInteractor->SetRenderWindow( renderWindow );
renderer->ResetCamera();
renderWindow->Render();
renderWindowInteractor->Start();
return 0;
}
If we set PolygonOffset for all actor’s mappers, which model will be on the top?
The result depends on the order renderer add actors.
const double units0 = -66000;
sphereMapper->SetInputData( sphere->GetOutput() );
sphereMapper->SetResolveCoincidentTopologyToPolygonOffset();
sphereMapper->SetRelativeCoincidentTopologyLineOffsetParameters(0, units0);
sphereMapper->SetRelativeCoincidentTopologyPolygonOffsetParameters(0, units0);
sphereMapper->SetRelativeCoincidentTopologyPointOffsetParameter(units0);
vtkSPtrNew( sphereActor, vtkActor );
sphereActor->SetMapper( sphereMapper );
vtkSPtrNew( coneMapper, vtkPolyDataMapper );
coneMapper->SetResolveCoincidentTopologyToPolygonOffset();
coneMapper->SetRelativeCoincidentTopologyLineOffsetParameters(0, units0);
coneMapper->SetRelativeCoincidentTopologyPolygonOffsetParameters(0, units0);
coneMapper->SetRelativeCoincidentTopologyPointOffsetParameter(units0);
coneMapper->SetInputData( cone->GetOutput() );
vtkSPtrNew( coneActor, vtkActor );
coneActor->SetMapper( coneMapper );
vtkSPtrNew( renderer, vtkRenderer );
renderer->AddActor( sphereActor );
renderer->AddActor( coneActor );
The cone is above sphere because the coneActor was the last one that put in the renderer.
[…] a way to keep a few special models awalys on the top layer in 3D scene. The relative post: https://www.weiy.city/2020/03/make-model-always-on-top/. But it will fail to shift polygons, lines, and points sometimes, eg. when we are in the […]
If I still want to keep the occlusion effect at other angles, how should I do it?
That scene is not “always on top”. Just use normal setting for mapper.
Because I use vtkContourWidget and vtkOrientedGlyphContourRepresentation to draw area lines on the OBJ model, if I don’t use AlwaysOnTopOn(), some lines will be on the back of the model, but I use AlwaysOnTopOn(), and there is no occlusion effect。I now try to use sampling to increase the number of points, but this leads to lines that are not very smooth
Yep, we need to change points to make sure occlusion effect. For some edge points, we can project them to the surface of obj model to get the effect you want.
Yes, thanks for your reply