VTK  9.3.20240327
vtkHardwareSelector.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
2 // SPDX-License-Identifier: BSD-3-Clause
3 /*
4  * @class vtkHardwareSelector
5  * @brief manager for OpenGL-based selection.
6  *
7  * vtkHardwareSelector is a helper that orchestrates color buffer based
8  * selection. This relies on OpenGL.
9  * vtkHardwareSelector can be used to select visible cells or points within a
10  * given rectangle of the RenderWindow.
11  * To use it, call in order:
12  * \li SetRenderer() - to select the renderer in which we
13  * want to select the cells/points.
14  * \li SetArea() - to set the rectangular region in the render window to select
15  * in.
16  * \li SetFieldAssociation() - to select the attribute to select i.e.
17  * cells/points etc.
18  * \li Finally, call Select().
19  * Select will cause the attached vtkRenderer to render in a special color mode,
20  * where each cell/point is given it own color so that later inspection of the
21  * Rendered Pixels can determine what cells are visible. Select() returns a new
22  * vtkSelection instance with the cells/points selected.
23  *
24  * Limitations:
25  * Antialiasing will break this class. If your graphics card settings force
26  * their use this class will return invalid results.
27  *
28  * Only Opaque geometry in Actors is selected from. Assemblies and LODMappers
29  * are not currently supported.
30  *
31  * During selection, visible datasets that can not be selected from are
32  * temporarily hidden so as not to produce invalid indices from their colors.
33  *
34  *
35  * The basic approach this class uses is to invoke render multiple times
36  * (passes) and have the mappers render pass specific information into
37  * the color buffer. For example during the ACTOR_PASS a mapper is
38  * supposed to render it's actor's id into the color buffer as a RGB
39  * value where R is the lower 8 bits, G is the next 8, etc. Giving us 24
40  * bits of unsigned int range.
41  *
42  * The same concept applies to the COMPOSITE_INDEX_PASS and the point and
43  * cell ID passes. As points and cells can easily exceed the 24 bit range
44  * of the color buffer we break them into two 24 bit passes for a total
45  * of 48 bits of range.
46  *
47  * During each pass the mappers render their data into the color buffer,
48  * the hardware selector grabs that buffer and then invokes
49  * ProcessSelectorPixelBuffer on all of the hit props. Giving them, and
50  * their mappers, a chance to modify the pixel buffer.
51  *
52  * Most mappers use this ProcessSelectorPixelBuffers pass to take when
53  * they rendered into the color buffer and convert it into what the
54  * hardware selector is expecting. This is because in some cases it is
55  * far easier and faster to render something else, such as
56  * gl_PrimitiveID or gl_VertexID and then in the processing convert those
57  * values to the appropriate VTK values.
58  *
59  * NOTE: The goal is for mappers to support hardware selection without
60  * having to rebuild any of their VBO/IBOs to maintain fast picking
61  * performance.
62  *
63  * NOTE: This class has a complex interaction with parallel compositing
64  * techniques such as IceT that are used on supercomputers. In those
65  * cases the local nodes render each pass, process it, send it to icet
66  * which composites it, and then must copy the result back to the hardware
67  * selector. Be aware of these interactions if you work on this class.
68  *
69  * NOTE: many mappers support remapping arrays from their local value to
70  * some other provided value. For example ParaView when creating a
71  * polydata from an unstructured grid will create point and cell data
72  * arrays on the polydata that may the polydata point and cell IDs back
73  * to the original unstructured grid's point and cell IDs. The hardware
74  * selection process honors those arrays and will provide the original
75  * unstructured grid point and cell ID when a selection is made.
76  * Likewise there are process and composite arrays that most mappers
77  * support that allow for parallel data generation, delivery, and local
78  * rendering while preserving the original process and composite values
79  * from when the data was distributed. Be aware the process array is a
80  * point data while the composite array is a cell data.
81  *
82  * TODO: This whole selection process could be nicely encapsulated as a
83  * RenderPass that internally renders multiple times with different
84  * settings. That would be my suggestion for the future.
85  *
86  * TODO: The pick method build into renderer could use the ACTOR pass of
87  * this class to do it's work eliminating some confusion and duplicate
88  * code paths.
89  *
90  * TODO: I am not sure where the composite array indirection is used.
91  *
92  *
93  * @sa
94  * vtkOpenGLHardwareSelector
95 
96  @par Online Examples:
97 
98  @htmlonly
99 
100  <div class="examplegrid">
101 
102  <a href="https://examples.vtk.org/site/Cxx/Filtering/ExtractVisibleCells">
103  <div class="examplegrid_container">
104  <img src="https://raw.githubusercontent.com/Kitware/vtk-examples/gh-pages/src/Testing/Baseline//Cxx/Filtering/TestExtractVisibleCells.png">
105  <div class="examplegrid_overlay">
106  <div class="examplegrid_text">ExtractVisibleCells</div>
107  </div>
108  </div>
109  </a>
110 
111  </div>
112 
113  @endhtmlonly
114 
115  @par Tests:
116  @ref c2_vtk_t_vtkHardwareSelector "vtkHardwareSelector (Tests)"
117  */
118 
119 #ifndef vtkHardwareSelector_h
120 #define vtkHardwareSelector_h
121 
122 #include "vtkObject.h"
123 #include "vtkRenderingCoreModule.h" // For export macro
124 
125 #include <string> // for std::string
126 
127 VTK_ABI_NAMESPACE_BEGIN
128 class vtkRenderer;
129 class vtkRenderWindow;
130 class vtkSelection;
131 class vtkProp;
132 class vtkTextureObject;
133 
134 class VTKRENDERINGCORE_EXPORT vtkHardwareSelector : public vtkObject
135 {
136 public:
138 
142  {
143  bool Valid;
145  int PropID;
147  unsigned int CompositeID;
150  : Valid(false)
151  , ProcessID(-1)
152  , PropID(-1)
153  , Prop(nullptr)
154  , CompositeID(0)
155  , AttributeID(-1)
156  {
157  }
158  };
160 
163  void PrintSelf(ostream& os, vtkIndent indent) override;
164 
166 
169  virtual void SetRenderer(vtkRenderer*);
170  vtkGetObjectMacro(Renderer, vtkRenderer);
172 
174 
177  vtkSetVector4Macro(Area, unsigned int);
178  vtkGetVector4Macro(Area, unsigned int);
180 
182 
192  vtkSetMacro(FieldAssociation, int);
193  vtkGetMacro(FieldAssociation, int);
195 
197 
202  vtkSetMacro(UseProcessIdFromData, bool);
203  vtkGetMacro(UseProcessIdFromData, bool);
205 
211 
213 
226  virtual bool CaptureBuffers();
227  PixelInformation GetPixelInformation(const unsigned int display_position[2])
228  {
229  return this->GetPixelInformation(display_position, 0);
230  }
231  PixelInformation GetPixelInformation(const unsigned int display_position[2], int maxDist)
232  {
233  unsigned int temp[2];
234  return this->GetPixelInformation(display_position, maxDist, temp);
235  }
237  const unsigned int display_position[2], int maxDist, unsigned int selected_position[2]);
238  void ClearBuffers() { this->ReleasePixBuffers(); }
239  // raw is before processing
240  unsigned char* GetRawPixelBuffer(int passNo) { return this->RawPixBuffer[passNo]; }
241  unsigned char* GetPixelBuffer(int passNo) { return this->PixBuffer[passNo]; }
243 
248  virtual void RenderCompositeIndex(unsigned int index);
249 
251 
257  virtual void UpdateMaximumCellId(vtkIdType attribid);
258  virtual void UpdateMaximumPointId(vtkIdType attribid);
260 
265  virtual void RenderProcessId(unsigned int processid);
266 
271  int Render(vtkRenderer* renderer, vtkProp** propArray, int propArrayCount);
272 
274 
278  vtkGetMacro(ActorPassOnly, bool);
279  vtkSetMacro(ActorPassOnly, bool);
281 
283 
289  vtkGetMacro(CaptureZValues, bool);
290  vtkSetMacro(CaptureZValues, bool);
292 
294 
297  virtual void BeginRenderProp();
298  virtual void EndRenderProp();
300 
302 
306  vtkSetMacro(ProcessID, int);
307  vtkGetMacro(ProcessID, int);
309 
311 
314  vtkGetVector3Macro(PropColorValue, float);
315  vtkSetVector3Macro(PropColorValue, float);
318 
320 
323  vtkGetMacro(CurrentPass, int);
325 
334  virtual vtkSelection* GenerateSelection() { return GenerateSelection(this->Area); }
335  virtual vtkSelection* GenerateSelection(unsigned int r[4])
336  {
337  return GenerateSelection(r[0], r[1], r[2], r[3]);
338  }
340  unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2);
341 
348  virtual vtkSelection* GeneratePolygonSelection(int* polygonPoints, vtkIdType count);
349 
355 
356  // it is very critical that these passes happen in the right order
357  // this is because of two complexities
358  //
359  // Compositing engines such as iceT send each pass as it
360  // renders. This means
361  //
362  // Mappers use point Ids or cell Id to update the process
363  // and composite ids. So the point and cell id passes
364  // have to happen before the last process and compoite
365  // passes respectively
366  //
367  //
369  {
370  // always must be first so that the prop IDs are set
372  // must always be second for composite mapper
374 
376  POINT_ID_HIGH24, // if needed
377  PROCESS_PASS, // must be after point id pass
378 
380  CELL_ID_HIGH24, // if needed
381 
382  MAX_KNOWN_PASS = CELL_ID_HIGH24,
383  MIN_KNOWN_PASS = ACTOR_PASS
384  };
385 
390 
391  static void Convert(vtkIdType id, float tcoord[3])
392  {
393  tcoord[0] = static_cast<float>((id & 0xff) / 255.0);
394  tcoord[1] = static_cast<float>(((id & 0xff00) >> 8) / 255.0);
395  tcoord[2] = static_cast<float>(((id & 0xff0000) >> 16) / 255.0);
396  }
397 
398  // grab the pixel buffer and save it
399  // typically called internally
400  virtual void SavePixelBuffer(int passNo);
401 
402  // does the selection process have high cell data
403  // requiring a high24 pass
405 
406  // does the selection process have high point data
407  // requiring a high24 pass
409 
410 protected:
413 
414  // Used to notify subclasses when a capture pass is occurring.
415  virtual void PreCapturePass(int pass) { (void)pass; }
416  virtual void PostCapturePass(int pass) { (void)pass; }
417 
418  // Called internally before and after each prop is rendered
419  // for device specific configuration/preparation etc.
420  virtual void BeginRenderProp(vtkRenderWindow*) = 0;
421  virtual void EndRenderProp(vtkRenderWindow*) = 0;
422 
423  double GetZValue(int propid);
424 
425  int Convert(unsigned long offset, unsigned char* pb)
426  {
427  if (!pb)
428  {
429  return 0;
430  }
431  offset = offset * 3;
432  unsigned char rgb[3];
433  rgb[0] = pb[offset];
434  rgb[1] = pb[offset + 1];
435  rgb[2] = pb[offset + 2];
436  int val = 0;
437  val |= rgb[2];
438  val = val << 8;
439  val |= rgb[1];
440  val = val << 8;
441  val |= rgb[0];
442  return val;
443  }
444 
446 
449  int Convert(unsigned int pos[2], unsigned char* pb) { return this->Convert(pos[0], pos[1], pb); }
450  int Convert(int xx, int yy, unsigned char* pb)
451  {
452  if (!pb)
453  {
454  return 0;
455  }
456  int offset = (yy * static_cast<int>(this->Area[2] - this->Area[0] + 1) + xx) * 3;
457  unsigned char rgb[3];
458  rgb[0] = pb[offset];
459  rgb[1] = pb[offset + 1];
460  rgb[2] = pb[offset + 2];
461  int val = 0;
462  val |= rgb[2];
463  val = val << 8;
464  val |= rgb[1];
465  val = val << 8;
466  val |= rgb[0];
467  return val;
468  }
470 
471  vtkIdType GetID(int low24, int mid24, int high16)
472  {
473  vtkIdType val = 0;
474  val |= high16;
475  val = val << 24;
476  val |= mid24;
477  val = val << 24;
478  val |= low24;
479  return val;
480  }
481 
485  virtual bool PassRequired(int pass);
486 
492  bool IsPropHit(int propid);
493 
497  virtual int GetPropID(int idx, vtkProp* vtkNotUsed(prop)) { return idx; }
498 
499  virtual void BeginSelection();
500  virtual void EndSelection();
501 
502  virtual void ProcessPixelBuffers();
503  void BuildPropHitList(unsigned char* rgbData);
504 
506 
511  unsigned int Area[4];
517 
518  // At most 10 passes.
519  unsigned char* PixBuffer[10];
520  unsigned char* RawPixBuffer[10];
525  int PropID;
526  float PropColorValue[3];
527 
529 
531 
532 private:
533  vtkHardwareSelector(const vtkHardwareSelector&) = delete;
534  void operator=(const vtkHardwareSelector&) = delete;
535 
536  class vtkInternals;
537  vtkInternals* Internals;
538 };
539 
540 VTK_ABI_NAMESPACE_END
541 #endif
static vtkHardwareSelector * New()
int Convert(unsigned long offset, unsigned char *pb)
vtkIdType MaximumCellId
Clears all pixel buffers.
virtual void BeginRenderProp()
Called by the mapper before and after rendering each prop.
virtual void UpdateMaximumPointId(vtkIdType attribid)
Called by any vtkMapper or vtkProp subclass to indicate the maximum cell or point attribute ID it use...
virtual void SavePixelBuffer(int passNo)
virtual void EndRenderProp(vtkRenderWindow *)=0
vtkRenderer * Renderer
Clears all pixel buffers.
virtual void EndRenderProp()
Called by the mapper before and after rendering each prop.
unsigned char * GetRawPixelBuffer(int passNo)
It is possible to use the vtkHardwareSelector for a custom picking.
virtual void SetRenderer(vtkRenderer *)
Get/Set the renderer to perform the selection on.
virtual vtkSelection * GenerateSelection(unsigned int r[4])
PixelInformation GetPixelInformation(const unsigned int display_position[2], int maxDist)
It is possible to use the vtkHardwareSelector for a custom picking.
vtkIdType GetID(int low24, int mid24, int high16)
virtual vtkSelection * GenerateSelection(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2)
virtual PixelInformation GetPixelInformation(const unsigned int display_position[2], int maxDist, unsigned int selected_position[2])
It is possible to use the vtkHardwareSelector for a custom picking.
virtual void ProcessPixelBuffers()
vtkProp * GetPropFromID(int id)
returns the prop associated with a ID.
vtkIdType MaximumPointId
Clears all pixel buffers.
int FieldAssociation
Clears all pixel buffers.
~vtkHardwareSelector() override
void ReleasePixBuffers()
Clears all pixel buffers.
virtual void BeginSelection()
virtual void UpdateMaximumCellId(vtkIdType attribid)
Called by any vtkMapper or vtkProp subclass to indicate the maximum cell or point attribute ID it use...
virtual void PreCapturePass(int pass)
virtual bool PassRequired(int pass)
Returns is the pass indicated is needed.
int Convert(int xx, int yy, unsigned char *pb)
pos must be relative to the lower-left corner of this->Area.
virtual void PostCapturePass(int pass)
bool UseProcessIdFromData
Clears all pixel buffers.
bool IsPropHit(int propid)
After the ACTOR_PASS this return true or false depending upon whether the prop was hit in the ACTOR_P...
void SetPropColorValue(vtkIdType val)
Get/Set the color to be used by the prop when drawing.
std::string PassTypeToString(PassTypes type)
Convert a PassTypes enum value to a human readable string.
virtual int GetPropID(int idx, vtkProp *vtkNotUsed(prop))
Return a unique ID for the prop.
int Render(vtkRenderer *renderer, vtkProp **propArray, int propArrayCount)
Called by vtkRenderer to render the selection pass.
void BuildPropHitList(unsigned char *rgbData)
static void Convert(vtkIdType id, float tcoord[3])
int Convert(unsigned int pos[2], unsigned char *pb)
pos must be relative to the lower-left corner of this->Area.
PixelInformation GetPixelInformation(const unsigned int display_position[2])
It is possible to use the vtkHardwareSelector for a custom picking.
virtual void RenderCompositeIndex(unsigned int index)
Called by any vtkMapper or vtkProp subclass to render a composite-index.
virtual void EndSelection()
virtual vtkSelection * GeneratePolygonSelection(int *polygonPoints, vtkIdType count)
Generates the vtkSelection from pixel buffers.
virtual void BeginRenderProp(vtkRenderWindow *)=0
double GetZValue(int propid)
void ClearBuffers()
It is possible to use the vtkHardwareSelector for a custom picking.
vtkSelection * Select()
Perform the selection.
void PrintSelf(ostream &os, vtkIndent indent) override
Methods invoked by print to print information about the object including superclasses.
virtual bool CaptureBuffers()
It is possible to use the vtkHardwareSelector for a custom picking.
virtual vtkSelection * GenerateSelection()
Generates the vtkSelection from pixel buffers.
unsigned char * GetPixelBuffer(int passNo)
It is possible to use the vtkHardwareSelector for a custom picking.
virtual void RenderProcessId(unsigned int processid)
Called by any vtkMapper or subclass to render process id.
a simple class to control print indentation
Definition: vtkIndent.h:108
abstract base class for most VTK objects
Definition: vtkObject.h:161
abstract superclass for all actors, volumes and annotations
Definition: vtkProp.h:65
create a window for renderers to draw into
abstract specification for renderers
Definition: vtkRenderer.h:171
data object that represents a "selection" in VTK.
Definition: vtkSelection.h:159
abstracts an OpenGL texture object.
@ type
Definition: vtkX3D.h:516
@ index
Definition: vtkX3D.h:246
@ offset
Definition: vtkX3D.h:438
@ string
Definition: vtkX3D.h:490
Struct used to return information about a pixel location.
int vtkIdType
Definition: vtkType.h:315
#define VTK_NEWINSTANCE