VTK  9.0.3
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 composits 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 
109 #ifndef vtkHardwareSelector_h
110 #define vtkHardwareSelector_h
111 
112 #include "vtkObject.h"
113 #include "vtkRenderingCoreModule.h" // For export macro
114 
115 #include <string> // for std::string
116 
117 class vtkRenderer;
118 class vtkRenderWindow;
119 class vtkSelection;
120 class vtkProp;
121 class vtkTextureObject;
122 
123 class VTKRENDERINGCORE_EXPORT vtkHardwareSelector : public vtkObject
124 {
125 public:
127 
131  {
132  bool Valid;
134  int PropID;
136  unsigned int CompositeID;
139  : Valid(false)
140  , ProcessID(-1)
141  , PropID(-1)
142  , Prop(nullptr)
143  , CompositeID(0)
144  , AttributeID(-1)
145  {
146  }
147  };
149 
150 public:
153  void PrintSelf(ostream& os, vtkIndent indent) override;
154 
156 
159  virtual void SetRenderer(vtkRenderer*);
160  vtkGetObjectMacro(Renderer, vtkRenderer);
162 
164 
167  vtkSetVector4Macro(Area, unsigned int);
168  vtkGetVector4Macro(Area, unsigned int);
170 
172 
182  vtkSetMacro(FieldAssociation, int);
183  vtkGetMacro(FieldAssociation, int);
185 
187 
192  vtkSetMacro(UseProcessIdFromData, bool);
193  vtkGetMacro(UseProcessIdFromData, bool);
195 
201 
203 
216  virtual bool CaptureBuffers();
217  PixelInformation GetPixelInformation(const unsigned int display_position[2])
218  {
219  return this->GetPixelInformation(display_position, 0);
220  }
221  PixelInformation GetPixelInformation(const unsigned int display_position[2], int maxDist)
222  {
223  unsigned int temp[2];
224  return this->GetPixelInformation(display_position, maxDist, temp);
225  }
227  const unsigned int display_position[2], int maxDist, unsigned int selected_position[2]);
228  void ClearBuffers() { this->ReleasePixBuffers(); }
229  // raw is before processing
230  unsigned char* GetRawPixelBuffer(int passNo) { return this->RawPixBuffer[passNo]; }
231  unsigned char* GetPixelBuffer(int passNo) { return this->PixBuffer[passNo]; }
233 
238  virtual void RenderCompositeIndex(unsigned int index);
239 
241 
247  virtual void UpdateMaximumCellId(vtkIdType attribid);
248  virtual void UpdateMaximumPointId(vtkIdType attribid);
250 
255  virtual void RenderProcessId(unsigned int processid);
256 
261  int Render(vtkRenderer* renderer, vtkProp** propArray, int propArrayCount);
262 
264 
268  vtkGetMacro(ActorPassOnly, bool);
269  vtkSetMacro(ActorPassOnly, bool);
271 
273 
279  vtkGetMacro(CaptureZValues, bool);
280  vtkSetMacro(CaptureZValues, bool);
282 
284 
287  virtual void BeginRenderProp();
288  virtual void EndRenderProp();
290 
292 
296  vtkSetMacro(ProcessID, int);
297  vtkGetMacro(ProcessID, int);
299 
301 
304  vtkGetVector3Macro(PropColorValue, float);
305  vtkSetVector3Macro(PropColorValue, float);
308 
310 
313  vtkGetMacro(CurrentPass, int);
315 
324  virtual vtkSelection* GenerateSelection() { return GenerateSelection(this->Area); }
325  virtual vtkSelection* GenerateSelection(unsigned int r[4])
326  {
327  return GenerateSelection(r[0], r[1], r[2], r[3]);
328  }
330  unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2);
331 
338  virtual vtkSelection* GeneratePolygonSelection(int* polygonPoints, vtkIdType count);
339 
345 
346  // it is very critical that these passes happen in the right order
347  // this is because of two complexities
348  //
349  // Compositing engines such as iceT send each pass as it
350  // renders. This means
351  //
352  // Mappers use point Ids or cell Id to update the process
353  // and composite ids. So the point and cell id passes
354  // have to happen before the last process and compoite
355  // passes respectively
356  //
357  //
359  {
360  // always must be first so that the prop IDs are set
362  // must always be second for composite mapper
364 
366  POINT_ID_HIGH24, // if needed
367  PROCESS_PASS, // best to be after point id pass
368 
370  CELL_ID_HIGH24, // if needed
371 
372  MAX_KNOWN_PASS = CELL_ID_HIGH24,
373  MIN_KNOWN_PASS = ACTOR_PASS
374  };
375 
380 
381  static void Convert(vtkIdType id, float tcoord[3])
382  {
383  tcoord[0] = static_cast<float>((id & 0xff) / 255.0);
384  tcoord[1] = static_cast<float>(((id & 0xff00) >> 8) / 255.0);
385  tcoord[2] = static_cast<float>(((id & 0xff0000) >> 16) / 255.0);
386  }
387 
388  // grab the pixel buffer and save it
389  // typically called internally
390  virtual void SavePixelBuffer(int passNo);
391 
392 protected:
395 
396  // Used to notify subclasses when a capture pass is occurring.
397  virtual void PreCapturePass(int pass) { (void)pass; }
398  virtual void PostCapturePass(int pass) { (void)pass; }
399 
400  // Called internally before and after each prop is rendered
401  // for device specific configuration/preparation etc.
402  virtual void BeginRenderProp(vtkRenderWindow*) = 0;
403  virtual void EndRenderProp(vtkRenderWindow*) = 0;
404 
405  double GetZValue(int propid);
406 
407  int Convert(unsigned long offset, unsigned char* pb)
408  {
409  if (!pb)
410  {
411  return 0;
412  }
413  offset = offset * 3;
414  unsigned char rgb[3];
415  rgb[0] = pb[offset];
416  rgb[1] = pb[offset + 1];
417  rgb[2] = pb[offset + 2];
418  int val = 0;
419  val |= rgb[2];
420  val = val << 8;
421  val |= rgb[1];
422  val = val << 8;
423  val |= rgb[0];
424  return val;
425  }
426 
428 
431  int Convert(unsigned int pos[2], unsigned char* pb) { return this->Convert(pos[0], pos[1], pb); }
432  int Convert(int xx, int yy, unsigned char* pb)
433  {
434  if (!pb)
435  {
436  return 0;
437  }
438  int offset = (yy * static_cast<int>(this->Area[2] - this->Area[0] + 1) + xx) * 3;
439  unsigned char rgb[3];
440  rgb[0] = pb[offset];
441  rgb[1] = pb[offset + 1];
442  rgb[2] = pb[offset + 2];
443  int val = 0;
444  val |= rgb[2];
445  val = val << 8;
446  val |= rgb[1];
447  val = val << 8;
448  val |= rgb[0];
449  return val;
450  }
452 
453  vtkIdType GetID(int low24, int mid24, int high16)
454  {
455  vtkIdType val = 0;
456  val |= high16;
457  val = val << 24;
458  val |= mid24;
459  val = val << 24;
460  val |= low24;
461  return val;
462  }
463 
467  virtual bool PassRequired(int pass);
468 
474  bool IsPropHit(int propid);
475 
479  virtual int GetPropID(int idx, vtkProp* vtkNotUsed(prop)) { return idx; }
480 
481  virtual void BeginSelection();
482  virtual void EndSelection();
483 
484  virtual void ProcessPixelBuffers();
485  void BuildPropHitList(unsigned char* rgbData);
486 
488 
493  unsigned int Area[4];
499 
500  // At most 10 passes.
501  unsigned char* PixBuffer[10];
502  unsigned char* RawPixBuffer[10];
507  int PropID;
508  float PropColorValue[3];
509 
511 
513 
514 private:
515  vtkHardwareSelector(const vtkHardwareSelector&) = delete;
516  void operator=(const vtkHardwareSelector&) = delete;
517 
518  class vtkInternals;
519  vtkInternals* Internals;
520 };
521 
522 #endif
static vtkHardwareSelector * New()
int Convert(unsigned long offset, unsigned char *pb)
virtual void BeginRenderProp()
Called by the mapper before and after rendering each prop.
virtual void UpdateMaximumPointId(vtkIdType attribid)
virtual void SavePixelBuffer(int passNo)
virtual void EndRenderProp(vtkRenderWindow *)=0
virtual void EndRenderProp()
unsigned char * GetRawPixelBuffer(int passNo)
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)
vtkIdType GetID(int low24, int mid24, int high16)
virtual vtkSelection * GenerateSelection(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2)
virtual void ProcessPixelBuffers()
vtkProp * GetPropFromID(int id)
returns the prop associated with a ID.
~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)
virtual void PostCapturePass(int pass)
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)
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])
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)
vtkSelection * Select()
Perform the selection.
PixelInformation GetPixelInformation(const unsigned int display_position[2], int maxDist, unsigned int selected_position[2])
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)
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:34
abstract base class for most VTK objects
Definition: vtkObject.h:63
abstract superclass for all actors, volumes and annotations
Definition: vtkProp.h:54
create a window for renderers to draw into
abstract specification for renderers
Definition: vtkRenderer.h:68
data object that represents a "selection" in VTK.
Definition: vtkSelection.h:58
abstracts an OpenGL texture object.
@ type
Definition: vtkX3D.h:522
@ index
Definition: vtkX3D.h:252
@ offset
Definition: vtkX3D.h:444
@ string
Definition: vtkX3D.h:496
Struct used to return information about a pixel location.
int vtkIdType
Definition: vtkType.h:338