VTK  9.2.6
vtkHardwareSelector.h
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Visualization Toolkit
4  Module: vtkHardwareSelector.h
5 
6  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7  All rights reserved.
8  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10  This software is distributed WITHOUT ANY WARRANTY; without even
11  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12  PURPOSE. See the above copyright notice for more information.
13 
14 =========================================================================*/
15 /*
16  * @class vtkHardwareSelector
17  * @brief manager for OpenGL-based selection.
18  *
19  * vtkHardwareSelector is a helper that orchestrates color buffer based
20  * selection. This relies on OpenGL.
21  * vtkHardwareSelector can be used to select visible cells or points within a
22  * given rectangle of the RenderWindow.
23  * To use it, call in order:
24  * \li SetRenderer() - to select the renderer in which we
25  * want to select the cells/points.
26  * \li SetArea() - to set the rectangular region in the render window to select
27  * in.
28  * \li SetFieldAssociation() - to select the attribute to select i.e.
29  * cells/points etc.
30  * \li Finally, call Select().
31  * Select will cause the attached vtkRenderer to render in a special color mode,
32  * where each cell/point is given it own color so that later inspection of the
33  * Rendered Pixels can determine what cells are visible. Select() returns a new
34  * vtkSelection instance with the cells/points selected.
35  *
36  * Limitations:
37  * Antialiasing will break this class. If your graphics card settings force
38  * their use this class will return invalid results.
39  *
40  * Only Opaque geometry in Actors is selected from. Assemblies and LODMappers
41  * are not currently supported.
42  *
43  * During selection, visible datasets that can not be selected from are
44  * temporarily hidden so as not to produce invalid indices from their colors.
45  *
46  *
47  * The basic approach this class uses is to invoke render multiple times
48  * (passes) and have the mappers render pass specific information into
49  * the color buffer. For example during the ACTOR_PASS a mapper is
50  * supposed to render it's actor's id into the color buffer as a RGB
51  * value where R is the lower 8 bits, G is the next 8, etc. Giving us 24
52  * bits of unsigned int range.
53  *
54  * The same concept applies to the COMPOSITE_INDEX_PASS and the point and
55  * cell ID passes. As points and cells can easily exceed the 24 bit range
56  * of the color buffer we break them into two 24 bit passes for a total
57  * of 48 bits of range.
58  *
59  * During each pass the mappers render their data into the color buffer,
60  * the hardware selector grabs that buffer and then invokes
61  * ProcessSelectorPixelBuffer on all of the hit props. Giving them, and
62  * their mappers, a chance to modify the pixel buffer.
63  *
64  * Most mappers use this ProcessSelectorPixelBuffers pass to take when
65  * they rendered into the color buffer and convert it into what the
66  * hardware selector is expecting. This is because in some cases it is
67  * far easier and faster to render something else, such as
68  * gl_PrimitiveID or gl_VertexID and then in the processing convert those
69  * values to the appropriate VTK values.
70  *
71  * NOTE: The goal is for mappers to support hardware selection without
72  * having to rebuild any of their VBO/IBOs to maintain fast picking
73  * performance.
74  *
75  * NOTE: This class has a complex interaction with parallel compositing
76  * techniques such as IceT that are used on supercomputers. In those
77  * cases the local nodes render each pass, process it, send it to icet
78  * which composites it, and then must copy the result back to the hardware
79  * selector. Be aware of these interactions if you work on this class.
80  *
81  * NOTE: many mappers support remapping arrays from their local value to
82  * some other provided value. For example ParaView when creating a
83  * polydata from an unstructured grid will create point and cell data
84  * arrays on the polydata that may the polydata point and cell IDs back
85  * to the original unstructured grid's point and cell IDs. The hardware
86  * selection process honors those arrays and will provide the original
87  * unstructured grid point and cell ID when a selection is made.
88  * Likewise there are process and composite arrays that most mappers
89  * support that allow for parallel data generation, delivery, and local
90  * rendering while preserving the original process and composite values
91  * from when the data was distributed. Be aware the process array is a
92  * point data while the composite array is a cell data.
93  *
94  * TODO: This whole selection process could be nicely encapsulated as a
95  * RenderPass that internally renders multiple times with different
96  * settings. That would be my suggestion for the future.
97  *
98  * TODO: The pick method build into renderer could use the ACTOR pass of
99  * this class to do it's work eliminating some confusion and duplicate
100  * code paths.
101  *
102  * TODO: I am not sure where the composite array indirection is used.
103  *
104  *
105  * @sa
106  * vtkOpenGLHardwareSelector
107 
108  @par Tests:
109  @ref c2_vtk_t_vtkHardwareSelector "vtkHardwareSelector (Tests)"
110  */
111 
112 #ifndef vtkHardwareSelector_h
113 #define vtkHardwareSelector_h
114 
115 #include "vtkObject.h"
116 #include "vtkRenderingCoreModule.h" // For export macro
117 
118 #include <string> // for std::string
119 
120 class vtkRenderer;
121 class vtkRenderWindow;
122 class vtkSelection;
123 class vtkProp;
124 class vtkTextureObject;
125 
126 class VTKRENDERINGCORE_EXPORT vtkHardwareSelector : public vtkObject
127 {
128 public:
130 
134  {
135  bool Valid;
137  int PropID;
139  unsigned int CompositeID;
142  : Valid(false)
143  , ProcessID(-1)
144  , PropID(-1)
145  , Prop(nullptr)
146  , CompositeID(0)
147  , AttributeID(-1)
148  {
149  }
150  };
152 
153 public:
154  static vtkHardwareSelector* New();
156  void PrintSelf(ostream& os, vtkIndent indent) override;
157 
159 
162  virtual void SetRenderer(vtkRenderer*);
163  vtkGetObjectMacro(Renderer, vtkRenderer);
165 
167 
170  vtkSetVector4Macro(Area, unsigned int);
171  vtkGetVector4Macro(Area, unsigned int);
173 
175 
185  vtkSetMacro(FieldAssociation, int);
186  vtkGetMacro(FieldAssociation, int);
188 
190 
195  vtkSetMacro(UseProcessIdFromData, bool);
196  vtkGetMacro(UseProcessIdFromData, bool);
198 
203  VTK_NEWINSTANCE vtkSelection* Select();
204 
206 
219  virtual bool CaptureBuffers();
220  PixelInformation GetPixelInformation(const unsigned int display_position[2])
221  {
222  return this->GetPixelInformation(display_position, 0);
223  }
224  PixelInformation GetPixelInformation(const unsigned int display_position[2], int maxDist)
225  {
226  unsigned int temp[2];
227  return this->GetPixelInformation(display_position, maxDist, temp);
228  }
229  PixelInformation GetPixelInformation(
230  const unsigned int display_position[2], int maxDist, unsigned int selected_position[2]);
231  void ClearBuffers() { this->ReleasePixBuffers(); }
232  // raw is before processing
233  unsigned char* GetRawPixelBuffer(int passNo) { return this->RawPixBuffer[passNo]; }
234  unsigned char* GetPixelBuffer(int passNo) { return this->PixBuffer[passNo]; }
236 
241  virtual void RenderCompositeIndex(unsigned int index);
242 
244 
250  virtual void UpdateMaximumCellId(vtkIdType attribid);
251  virtual void UpdateMaximumPointId(vtkIdType attribid);
253 
258  virtual void RenderProcessId(unsigned int processid);
259 
264  int Render(vtkRenderer* renderer, vtkProp** propArray, int propArrayCount);
265 
267 
271  vtkGetMacro(ActorPassOnly, bool);
272  vtkSetMacro(ActorPassOnly, bool);
274 
276 
282  vtkGetMacro(CaptureZValues, bool);
283  vtkSetMacro(CaptureZValues, bool);
285 
287 
290  virtual void BeginRenderProp();
291  virtual void EndRenderProp();
293 
295 
299  vtkSetMacro(ProcessID, int);
300  vtkGetMacro(ProcessID, int);
302 
304 
307  vtkGetVector3Macro(PropColorValue, float);
308  vtkSetVector3Macro(PropColorValue, float);
309  void SetPropColorValue(vtkIdType val);
311 
313 
316  vtkGetMacro(CurrentPass, int);
318 
327  virtual vtkSelection* GenerateSelection() { return GenerateSelection(this->Area); }
328  virtual vtkSelection* GenerateSelection(unsigned int r[4])
329  {
330  return GenerateSelection(r[0], r[1], r[2], r[3]);
331  }
332  virtual vtkSelection* GenerateSelection(
333  unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2);
334 
341  virtual vtkSelection* GeneratePolygonSelection(int* polygonPoints, vtkIdType count);
342 
347  vtkProp* GetPropFromID(int id);
348 
349  // it is very critical that these passes happen in the right order
350  // this is because of two complexities
351  //
352  // Compositing engines such as iceT send each pass as it
353  // renders. This means
354  //
355  // Mappers use point Ids or cell Id to update the process
356  // and composite ids. So the point and cell id passes
357  // have to happen before the last process and compoite
358  // passes respectively
359  //
360  //
362  {
363  // always must be first so that the prop IDs are set
365  // must always be second for composite mapper
367 
369  POINT_ID_HIGH24, // if needed
370  PROCESS_PASS, // must be after point id pass
371 
373  CELL_ID_HIGH24, // if needed
374 
375  MAX_KNOWN_PASS = CELL_ID_HIGH24,
376  MIN_KNOWN_PASS = ACTOR_PASS
377  };
378 
382  std::string PassTypeToString(PassTypes type);
383 
384  static void Convert(vtkIdType id, float tcoord[3])
385  {
386  tcoord[0] = static_cast<float>((id & 0xff) / 255.0);
387  tcoord[1] = static_cast<float>(((id & 0xff00) >> 8) / 255.0);
388  tcoord[2] = static_cast<float>(((id & 0xff0000) >> 16) / 255.0);
389  }
390 
391  // grab the pixel buffer and save it
392  // typically called internally
393  virtual void SavePixelBuffer(int passNo);
394 
395  // does the selection process have high cell data
396  // requiring a high24 pass
397  bool HasHighCellIds();
398 
399  // does the selection process have high point data
400  // requiring a high24 pass
401  bool HasHighPointIds();
402 
403 protected:
405  ~vtkHardwareSelector() override;
406 
407  // Used to notify subclasses when a capture pass is occurring.
408  virtual void PreCapturePass(int pass) { (void)pass; }
409  virtual void PostCapturePass(int pass) { (void)pass; }
410 
411  // Called internally before and after each prop is rendered
412  // for device specific configuration/preparation etc.
413  virtual void BeginRenderProp(vtkRenderWindow*) = 0;
414  virtual void EndRenderProp(vtkRenderWindow*) = 0;
415 
416  double GetZValue(int propid);
417 
418  int Convert(unsigned long offset, unsigned char* pb)
419  {
420  if (!pb)
421  {
422  return 0;
423  }
424  offset = offset * 3;
425  unsigned char rgb[3];
426  rgb[0] = pb[offset];
427  rgb[1] = pb[offset + 1];
428  rgb[2] = pb[offset + 2];
429  int val = 0;
430  val |= rgb[2];
431  val = val << 8;
432  val |= rgb[1];
433  val = val << 8;
434  val |= rgb[0];
435  return val;
436  }
437 
439 
442  int Convert(unsigned int pos[2], unsigned char* pb) { return this->Convert(pos[0], pos[1], pb); }
443  int Convert(int xx, int yy, unsigned char* pb)
444  {
445  if (!pb)
446  {
447  return 0;
448  }
449  int offset = (yy * static_cast<int>(this->Area[2] - this->Area[0] + 1) + xx) * 3;
450  unsigned char rgb[3];
451  rgb[0] = pb[offset];
452  rgb[1] = pb[offset + 1];
453  rgb[2] = pb[offset + 2];
454  int val = 0;
455  val |= rgb[2];
456  val = val << 8;
457  val |= rgb[1];
458  val = val << 8;
459  val |= rgb[0];
460  return val;
461  }
463 
464  vtkIdType GetID(int low24, int mid24, int high16)
465  {
466  vtkIdType val = 0;
467  val |= high16;
468  val = val << 24;
469  val |= mid24;
470  val = val << 24;
471  val |= low24;
472  return val;
473  }
474 
478  virtual bool PassRequired(int pass);
479 
485  bool IsPropHit(int propid);
486 
490  virtual int GetPropID(int idx, vtkProp* vtkNotUsed(prop)) { return idx; }
491 
492  virtual void BeginSelection();
493  virtual void EndSelection();
494 
495  virtual void ProcessPixelBuffers();
496  void BuildPropHitList(unsigned char* rgbData);
497 
499 
502  void ReleasePixBuffers();
504  unsigned int Area[4];
510 
511  // At most 10 passes.
512  unsigned char* PixBuffer[10];
513  unsigned char* RawPixBuffer[10];
518  int PropID;
519  float PropColorValue[3];
520 
522 
524 
525 private:
526  vtkHardwareSelector(const vtkHardwareSelector&) = delete;
527  void operator=(const vtkHardwareSelector&) = delete;
528 
529  class vtkInternals;
530  vtkInternals* Internals;
531 };
532 
533 #endif
abstract superclass for all actors, volumes and annotations
Definition: vtkProp.h:56
virtual void PostCapturePass(int pass)
abstract base class for most VTK objects
Definition: vtkObject.h:62
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:72
virtual vtkSelection * GenerateSelection(unsigned int r[4])
data object that represents a "selection" in VTK.
Definition: vtkSelection.h:59
int vtkIdType
Definition: vtkType.h:332
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:39
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.