VTK  9.3.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. 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 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;
131  : Valid(false)
132  , ProcessID(-1)
133  , PropID(-1)
134  , Prop(nullptr)
135  , CompositeID(0)
136  , AttributeID(-1)
137  {
138  }
139  };
141 
142  static vtkHardwareSelector* New();
144  void PrintSelf(ostream& os, vtkIndent indent) override;
145 
147 
150  virtual void SetRenderer(vtkRenderer*);
151  vtkGetObjectMacro(Renderer, vtkRenderer);
153 
155 
158  vtkSetVector4Macro(Area, unsigned int);
159  vtkGetVector4Macro(Area, unsigned int);
161 
163 
173  vtkSetMacro(FieldAssociation, int);
174  vtkGetMacro(FieldAssociation, int);
176 
178 
183  vtkSetMacro(UseProcessIdFromData, bool);
184  vtkGetMacro(UseProcessIdFromData, bool);
186 
191  VTK_NEWINSTANCE vtkSelection* Select();
192 
194 
207  virtual bool CaptureBuffers();
208  PixelInformation GetPixelInformation(const unsigned int display_position[2])
209  {
210  return this->GetPixelInformation(display_position, 0);
211  }
212  PixelInformation GetPixelInformation(const unsigned int display_position[2], int maxDist)
213  {
214  unsigned int temp[2];
215  return this->GetPixelInformation(display_position, maxDist, temp);
216  }
217  virtual PixelInformation GetPixelInformation(
218  const unsigned int display_position[2], int maxDist, unsigned int selected_position[2]);
219  void ClearBuffers() { this->ReleasePixBuffers(); }
220  // raw is before processing
221  unsigned char* GetRawPixelBuffer(int passNo) { return this->RawPixBuffer[passNo]; }
222  unsigned char* GetPixelBuffer(int passNo) { return this->PixBuffer[passNo]; }
224 
229  virtual void RenderCompositeIndex(unsigned int index);
230 
232 
238  virtual void UpdateMaximumCellId(vtkIdType attribid);
239  virtual void UpdateMaximumPointId(vtkIdType attribid);
241 
246  virtual void RenderProcessId(unsigned int processid);
247 
252  int Render(vtkRenderer* renderer, vtkProp** propArray, int propArrayCount);
253 
255 
259  vtkGetMacro(ActorPassOnly, bool);
260  vtkSetMacro(ActorPassOnly, bool);
262 
264 
270  vtkGetMacro(CaptureZValues, bool);
271  vtkSetMacro(CaptureZValues, bool);
273 
275 
278  virtual void BeginRenderProp();
279  virtual void EndRenderProp();
281 
283 
287  vtkSetMacro(ProcessID, int);
288  vtkGetMacro(ProcessID, int);
290 
292 
295  vtkGetVector3Macro(PropColorValue, float);
296  vtkSetVector3Macro(PropColorValue, float);
297  void SetPropColorValue(vtkIdType val);
299 
301 
304  vtkGetMacro(CurrentPass, int);
306 
315  virtual vtkSelection* GenerateSelection() { return GenerateSelection(this->Area); }
316  virtual vtkSelection* GenerateSelection(unsigned int r[4])
317  {
318  return GenerateSelection(r[0], r[1], r[2], r[3]);
319  }
320  virtual vtkSelection* GenerateSelection(
321  unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2);
322 
329  virtual vtkSelection* GeneratePolygonSelection(int* polygonPoints, vtkIdType count);
330 
335  vtkProp* GetPropFromID(int id);
336 
337  // it is very critical that these passes happen in the right order
338  // this is because of two complexities
339  //
340  // Compositing engines such as iceT send each pass as it
341  // renders. This means
342  //
343  // Mappers use point Ids or cell Id to update the process
344  // and composite ids. So the point and cell id passes
345  // have to happen before the last process and compoite
346  // passes respectively
347  //
348  //
350  {
351  // always must be first so that the prop IDs are set
353  // must always be second for composite mapper
355 
357  POINT_ID_HIGH24, // if needed
358  PROCESS_PASS, // must be after point id pass
359 
361  CELL_ID_HIGH24, // if needed
362 
363  MAX_KNOWN_PASS = CELL_ID_HIGH24,
364  MIN_KNOWN_PASS = ACTOR_PASS
365  };
366 
370  std::string PassTypeToString(PassTypes type);
371 
372  static void Convert(vtkIdType id, float tcoord[3])
373  {
374  tcoord[0] = static_cast<float>((id & 0xff) / 255.0);
375  tcoord[1] = static_cast<float>(((id & 0xff00) >> 8) / 255.0);
376  tcoord[2] = static_cast<float>(((id & 0xff0000) >> 16) / 255.0);
377  }
378 
379  // grab the pixel buffer and save it
380  // typically called internally
381  virtual void SavePixelBuffer(int passNo);
382 
383  // does the selection process have high cell data
384  // requiring a high24 pass
385  bool HasHighCellIds();
386 
387  // does the selection process have high point data
388  // requiring a high24 pass
389  bool HasHighPointIds();
390 
391 protected:
393  ~vtkHardwareSelector() override;
394 
395  // Used to notify subclasses when a capture pass is occurring.
396  virtual void PreCapturePass(int pass) { (void)pass; }
397  virtual void PostCapturePass(int pass) { (void)pass; }
398 
399  // Called internally before and after each prop is rendered
400  // for device specific configuration/preparation etc.
401  virtual void BeginRenderProp(vtkRenderWindow*) = 0;
402  virtual void EndRenderProp(vtkRenderWindow*) = 0;
403 
404  double GetZValue(int propid);
405 
406  int Convert(unsigned long offset, unsigned char* pb)
407  {
408  if (!pb)
409  {
410  return 0;
411  }
412  offset = offset * 3;
413  unsigned char rgb[3];
414  rgb[0] = pb[offset];
415  rgb[1] = pb[offset + 1];
416  rgb[2] = pb[offset + 2];
417  int val = 0;
418  val |= rgb[2];
419  val = val << 8;
420  val |= rgb[1];
421  val = val << 8;
422  val |= rgb[0];
423  return val;
424  }
425 
427 
430  int Convert(unsigned int pos[2], unsigned char* pb) { return this->Convert(pos[0], pos[1], pb); }
431  int Convert(int xx, int yy, unsigned char* pb)
432  {
433  if (!pb)
434  {
435  return 0;
436  }
437  int offset = (yy * static_cast<int>(this->Area[2] - this->Area[0] + 1) + xx) * 3;
438  unsigned char rgb[3];
439  rgb[0] = pb[offset];
440  rgb[1] = pb[offset + 1];
441  rgb[2] = pb[offset + 2];
442  int val = 0;
443  val |= rgb[2];
444  val = val << 8;
445  val |= rgb[1];
446  val = val << 8;
447  val |= rgb[0];
448  return val;
449  }
451 
452  vtkIdType GetID(int low24, int mid24, int high16)
453  {
454  vtkIdType val = 0;
455  val |= high16;
456  val = val << 24;
457  val |= mid24;
458  val = val << 24;
459  val |= low24;
460  return val;
461  }
462 
466  virtual bool PassRequired(int pass);
467 
473  bool IsPropHit(int propid);
474 
478  virtual int GetPropID(int idx, vtkProp* vtkNotUsed(prop)) { return idx; }
479 
480  virtual void BeginSelection();
481  virtual void EndSelection();
482 
483  virtual void ProcessPixelBuffers();
484  void BuildPropHitList(unsigned char* rgbData);
485 
487 
490  void ReleasePixBuffers();
492  unsigned int Area[4];
498 
499  // At most 10 passes.
500  unsigned char* PixBuffer[10];
501  unsigned char* RawPixBuffer[10];
506  int PropID;
507  float PropColorValue[3];
508 
510 
512 
513 private:
514  vtkHardwareSelector(const vtkHardwareSelector&) = delete;
515  void operator=(const vtkHardwareSelector&) = delete;
516 
517  class vtkInternals;
518  vtkInternals* Internals;
519 };
520 
521 VTK_ABI_NAMESPACE_END
522 #endif
abstract superclass for all actors, volumes and annotations
Definition: vtkProp.h:45
virtual void PostCapturePass(int pass)
abstract base class for most VTK objects
Definition: vtkObject.h:51
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:61
virtual vtkSelection * GenerateSelection(unsigned int r[4])
data object that represents a "selection" in VTK.
Definition: vtkSelection.h:49
int vtkIdType
Definition: vtkType.h:315
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.
a simple class to control print indentation
Definition: vtkIndent.h:28
virtual int GetPropID(int idx, vtkProp *vtkNotUsed(prop))
Return a unique ID for the prop.
void ClearBuffers()
It is possible to use the vtkHardwareSelector for a custom picking.
int Convert(int xx, int yy, unsigned char *pb)
pos must be relative to the lower-left corner of this->Area.
#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
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.