VTK  9.7.1
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.
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 Tests:
97  @ref c2_vtk_t_vtkHardwareSelector "vtkHardwareSelector (Tests)"
98  */
99 
100 #ifndef vtkHardwareSelector_h
101 #define vtkHardwareSelector_h
102 
103 #include "vtkObject.h"
104 #include "vtkRenderingCoreModule.h" // For export macro
105 
106 #include <string> // for std::string
107 
108 VTK_ABI_NAMESPACE_BEGIN
109 class vtkRenderer;
110 class vtkRenderWindow;
111 class vtkSelection;
112 class vtkProp;
113 class vtkTextureObject;
114 
115 class VTKRENDERINGCORE_EXPORT vtkHardwareSelector : public vtkObject
116 {
117 public:
119 
123  {
124  bool Valid;
126  int PropID;
128  unsigned int CompositeID;
134  : Valid(false)
135  , ProcessID(-1)
136  , PropID(-1)
137  , Prop(nullptr)
138  , CompositeID(0)
139  , AttributeID(-1)
140  , CellGridCellTypeID(-1)
141  , CellGridSourceSpecID(-1)
142  , CellGridTupleID(-1)
143  {
144  }
145  };
147 
148  static vtkHardwareSelector* New();
150  void PrintSelf(ostream& os, vtkIndent indent) override;
151 
153 
156  virtual void SetRenderer(vtkRenderer*);
157  vtkGetObjectMacro(Renderer, vtkRenderer);
159 
161 
164  vtkSetVector4Macro(Area, unsigned int);
165  vtkGetVector4Macro(Area, unsigned int);
167 
169 
179  vtkSetMacro(FieldAssociation, int);
180  vtkGetMacro(FieldAssociation, int);
182 
184 
189  vtkSetMacro(UseProcessIdFromData, bool);
190  vtkGetMacro(UseProcessIdFromData, bool);
192 
197  VTK_NEWINSTANCE vtkSelection* Select();
198 
200 
213  virtual bool CaptureBuffers();
214  PixelInformation GetPixelInformation(const unsigned int display_position[2])
215  {
216  return this->GetPixelInformation(display_position, 0);
217  }
218  PixelInformation GetPixelInformation(const unsigned int display_position[2], int maxDist)
219  {
220  unsigned int temp[2];
221  return this->GetPixelInformation(display_position, maxDist, temp);
222  }
223  virtual PixelInformation GetPixelInformation(
224  const unsigned int display_position[2], int maxDist, unsigned int selected_position[2]);
225  void ClearBuffers() { this->ReleasePixBuffers(); }
226  // raw is before processing
227  unsigned char* GetRawPixelBuffer(int passNo) { return this->RawPixBuffer[passNo]; }
228  unsigned char* GetPixelBuffer(int passNo) { return this->PixBuffer[passNo]; }
230 
235  virtual void RenderCompositeIndex(unsigned int index);
236 
238 
244  virtual void UpdateMaximumCellId(vtkIdType attribid);
245  virtual void UpdateMaximumPointId(vtkIdType attribid);
246  virtual void UpdateMaximumCellGridTupleId(vtkIdType attribid);
248 
253  virtual void RenderProcessId(unsigned int processid);
254 
259  int Render(vtkRenderer* renderer, vtkProp** propArray, int propArrayCount);
260 
262 
266  vtkGetMacro(ActorPassOnly, bool);
267  vtkSetMacro(ActorPassOnly, bool);
269 
271 
277  vtkGetMacro(CaptureZValues, bool);
278  vtkSetMacro(CaptureZValues, bool);
280 
282 
285  virtual void BeginRenderProp();
286  virtual void EndRenderProp();
288 
290 
294  vtkSetMacro(ProcessID, int);
295  vtkGetMacro(ProcessID, int);
297 
299 
302  vtkGetVector3Macro(PropColorValue, float);
303  vtkSetVector3Macro(PropColorValue, float);
304  void SetPropColorValue(vtkIdType val);
306 
308 
311  vtkGetMacro(CurrentPass, int);
313 
322  virtual vtkSelection* GenerateSelection() { return GenerateSelection(this->Area); }
323  virtual vtkSelection* GenerateSelection(unsigned int r[4])
324  {
325  return GenerateSelection(r[0], r[1], r[2], r[3]);
326  }
327  virtual vtkSelection* GenerateSelection(
328  unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2);
329 
336  virtual vtkSelection* GeneratePolygonSelection(int* polygonPoints, vtkIdType count);
337 
342  virtual vtkProp* GetPropFromID(int id);
343 
344  // it is very critical that these passes happen in the right order
345  // this is because of two complexities
346  //
347  // Compositing engines such as iceT send each pass as it
348  // renders. This means
349  //
350  // Mappers use point Ids or cell Id to update the process
351  // and composite ids. So the point and cell id passes
352  // have to happen before the last process and compoite
353  // passes respectively
354  //
356  {
357  // always must be first so that the prop IDs are set
358  ACTOR_PASS = 0,
359  // must always be second for composite mapper
360  COMPOSITE_INDEX_PASS = 1,
361 
362  POINT_ID_LOW24 = 2,
363  POINT_ID_HIGH24 = 3, // if needed
364  PROCESS_PASS = 4, // must be after point id pass
365 
366  CELL_ID_LOW24 = 5,
367  CELL_ID_HIGH24 = 6, // if needed
368 
369  CELLGRID_CELL_TYPE_INDEX_PASS = 7,
370  CELLGRID_SOURCE_INDEX_PASS = 8,
371  CELLGRID_TUPLE_ID_LOW24 = 9,
372  CELLGRID_TUPLE_ID_HIGH24 = 10,
373 
374  MAX_KNOWN_PASS = CELLGRID_TUPLE_ID_HIGH24,
375  MIN_KNOWN_PASS = ACTOR_PASS
376  };
377 
381  std::string PassTypeToString(PassTypes type);
382 
383  static void Convert(vtkIdType id, float tcoord[3])
384  {
385  tcoord[0] = static_cast<float>((id & 0xff) / 255.0);
386  tcoord[1] = static_cast<float>(((id & 0xff00) >> 8) / 255.0);
387  tcoord[2] = static_cast<float>(((id & 0xff0000) >> 16) / 255.0);
388  }
389 
390  // grab the pixel buffer and save it
391  // typically called internally
392  virtual void SavePixelBuffer(int passNo);
393 
394  // does the selection process have high cell data
395  // requiring a high24 pass
396  bool HasHighCellIds();
397 
398  // does the selection process have high point data
399  // requiring a high24 pass
400  bool HasHighPointIds();
401 
402  // deos the selection process have high cell grid tuple ids
403  // requiring a high24 pass
404  bool HasHighCellGridTupleIds();
405 
406 protected:
408  ~vtkHardwareSelector() override;
409 
410  // Used to notify subclasses when a capture pass is occurring.
411  virtual void PreCapturePass(int pass) { (void)pass; }
412  virtual void PostCapturePass(int pass) { (void)pass; }
413 
414  // Called internally before and after each prop is rendered
415  // for device specific configuration/preparation etc.
416  virtual void BeginRenderProp(vtkRenderWindow*) = 0;
417  virtual void EndRenderProp(vtkRenderWindow*) = 0;
418 
419  double GetZValue(int propid);
420 
421  int Convert(unsigned long offset, unsigned char* pb)
422  {
423  if (!pb)
424  {
425  return 0;
426  }
427  offset = offset * 3;
428  unsigned char rgb[3];
429  rgb[0] = pb[offset];
430  rgb[1] = pb[offset + 1];
431  rgb[2] = pb[offset + 2];
432  int val = 0;
433  val |= rgb[2];
434  val = val << 8;
435  val |= rgb[1];
436  val = val << 8;
437  val |= rgb[0];
438  return val;
439  }
440 
442 
445  int Convert(unsigned int pos[2], unsigned char* pb) { return this->Convert(pos[0], pos[1], pb); }
446  virtual int Convert(int xx, int yy, unsigned char* pb)
447  {
448  if (!pb)
449  {
450  return 0;
451  }
452  int offset = (yy * static_cast<int>(this->Area[2] - this->Area[0] + 1) + xx) * 3;
453  unsigned char rgb[3];
454  rgb[0] = pb[offset];
455  rgb[1] = pb[offset + 1];
456  rgb[2] = pb[offset + 2];
457  int val = 0;
458  val |= rgb[2];
459  val = val << 8;
460  val |= rgb[1];
461  val = val << 8;
462  val |= rgb[0];
463  return val;
464  }
466 
467  vtkIdType GetID(int low24, int mid24, int high16)
468  {
469  vtkIdType val = 0;
470  val |= high16;
471  val = val << 24;
472  val |= mid24;
473  val = val << 24;
474  val |= low24;
475  return val;
476  }
477 
481  virtual bool PassRequired(int pass);
482 
488  bool IsPropHit(int propid);
489 
493  virtual int GetPropID(int idx, vtkProp* vtkNotUsed(prop)) { return idx; }
494 
495  virtual void BeginSelection();
496  virtual void EndSelection();
497 
498  virtual void ProcessPixelBuffers();
499  void BuildPropHitList(unsigned char* rgbData);
500 
502 
505  virtual void ReleasePixBuffers();
507  unsigned int Area[4];
514 
515  // At most 11 passes.
516  unsigned char* PixBuffer[11];
517  unsigned char* RawPixBuffer[11];
522  int PropID;
523  float PropColorValue[3];
524 
526 
528 
529 private:
530  vtkHardwareSelector(const vtkHardwareSelector&) = delete;
531  void operator=(const vtkHardwareSelector&) = delete;
532 
533  class vtkInternals;
534  vtkInternals* Internals;
535 };
536 
537 VTK_ABI_NAMESPACE_END
538 #endif
abstract superclass for all actors, volumes and annotations
Definition: vtkProp.h:49
virtual void PostCapturePass(int pass)
abstract base class for most VTK objects
Definition: vtkObject.h:52
void PrintSelf(ostream &os, vtkIndent indent) override
Methods invoked by print to print information about the object including superclasses.
Struct used to return information about a pixel location.
virtual void PreCapturePass(int pass)
PixelInformation GetPixelInformation(const unsigned int display_position[2], int maxDist)
It is possible to use the vtkHardwareSelector for a custom picking.
abstract specification for renderers
Definition: vtkRenderer.h:63
virtual vtkSelection * GenerateSelection(unsigned int r[4])
data object that represents a "selection" in VTK.
Definition: vtkSelection.h:49
int vtkIdType
Definition: vtkType.h:363
bool UseProcessIdFromData
Clears all pixel buffers.
static void Convert(vtkIdType id, float tcoord[3])
int FieldAssociation
Clears all pixel buffers.
vtkIdType MaximumCellId
Clears all pixel buffers.
vtkIdType MaximumCellGridTupleId
Clears all pixel buffers.
a simple class to control print indentation
Definition: vtkIndent.h:28
virtual int Convert(int xx, int yy, unsigned char *pb)
pos must be relative to the lower-left corner of this->Area.
void ClearBuffers()
It is possible to use the vtkHardwareSelector for a custom picking.
#define VTK_NEWINSTANCE
unsigned char * GetPixelBuffer(int passNo)
It is possible to use the vtkHardwareSelector for a custom picking.
abstracts an OpenGL texture object.
vtkIdType GetID(int low24, int mid24, int high16)
create a window for renderers to draw into
virtual int GetPropID(int idx, vtkProp *prop)
Return a unique ID for the prop.
vtkIdType MaximumPointId
Clears all pixel buffers.
vtkRenderer * Renderer
Clears all pixel buffers.
PixelInformation GetPixelInformation(const unsigned int display_position[2])
It is possible to use the vtkHardwareSelector for a custom picking.
virtual vtkSelection * GenerateSelection()
Generates the vtkSelection from pixel buffers.
unsigned char * GetRawPixelBuffer(int passNo)
It is possible to use the vtkHardwareSelector for a custom picking.
static vtkObject * New()
Create an object with Debug turned off, modified time initialized to zero, and reference counting on...
int Convert(unsigned long offset, unsigned char *pb)
int Convert(unsigned int pos[2], unsigned char *pb)
pos must be relative to the lower-left corner of this->Area.