PauloCarvalhoRJ / gammaray

GammaRay: a graphical interface to GSLib and other geomodeling algorithms. *NEW* in May, 6th: Drift analysis.
Other
39 stars 15 forks source link

VTK 9: the pick marker is not positioned on the picked location, instead it is now placed in a plane orthogonal to the camera. #273

Open PauloCarvalhoRJ opened 2 years ago

PauloCarvalhoRJ commented 2 years ago

This defect was introduced by VTK 9.

PauloCarvalhoRJ commented 2 years ago

Reported bug in VTK discussion forum: https://discourse.vtk.org/t/vtkproppicker-in-vtk-9-1-is-now-returning-wrong-world-coordinates/8061

PauloCarvalhoRJ commented 2 years ago

Also an issue opened in VTK upstream: https://gitlab.kitware.com/vtk/vtk/-/issues/18503 .

PauloCarvalhoRJ commented 2 years ago

Prepare a minimum example reproducing the issue and post it to the forums above. Suggestion: use the working pick example as a starting point: https://kitware.github.io/vtk-examples/site/Cxx/Picking/CellPicking/ (it even reports the world coordinates).

PauloCarvalhoRJ commented 2 years ago

Rewriting VTK's vtkRenderer::GetZ(int x, int y) solves the issue:

// Given a pixel location, return the Z value
double vtkRenderer::GetZ(int x, int y)
{
  double z;

  // use a hardware selector beacuse calling this->RenderWindow->GetZbufferData(int,int,int,int) directly
  // from here always results in a z-buffer value of 1.0, meaning it is using a cleared depth buffer.
  {
      vtkNew<vtkHardwareSelector> hsel;
      hsel->SetActorPassOnly(true);
      hsel->SetCaptureZValues(true);
      hsel->SetRenderer(this);
      hsel->SetArea(x, y, x, y);
      vtkSmartPointer<vtkSelection> sel;
      sel.TakeReference(hsel->Select());

      // find the closest z-buffer value
      if (sel && sel->GetNode(0))
      {
        vtkProp* closestProp = nullptr;
        double closestDepth = 1.0;
        unsigned int numPicked = sel->GetNumberOfNodes();
        for (unsigned int pIdx = 0; pIdx < numPicked; pIdx++)
        {
          vtkSelectionNode* selnode = sel->GetNode(pIdx);
          double adepth = selnode->GetProperties()->Get(vtkSelectionNode::ZBUFFER_VALUE());
          if (adepth < closestDepth)
            closestDepth = adepth;
        }
        z = closestDepth;
      }
  }

  return z;
}

Calling vtkRenderWindow::GetZbufferData(int,int,int,int) in that context always results in Z-buffer values of 1.0, meaning the depth buffer is reset in that context.

PauloCarvalhoRJ commented 2 years ago

Merge request to fix issue in VTK source code: https://gitlab.kitware.com/vtk/vtk/-/merge_requests/9125

PauloCarvalhoRJ commented 2 years ago

GammaRay branch to generate the figures that appear in the discussion threads: https://github.com/PauloCarvalhoRJ/gammaray/tree/DebugVTK9PickingIssue .

PauloCarvalhoRJ commented 9 months ago

It seems the problem maybe related to whether the VTK rendering window has two or more renderers: https://discourse.vtk.org/t/vtkproppicker-in-vtk-9-1-is-now-returning-wrong-world-coordinates/8061/41?u=paulo_carvalho