VTK
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 "vtkRenderingCoreModule.h" // For export macro
113 #include "vtkObject.h"
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  };
147 
148 public:
149  static vtkHardwareSelector* New();
151  void PrintSelf(ostream& os, vtkIndent indent) override;
152 
154 
157  virtual void SetRenderer(vtkRenderer*);
158  vtkGetObjectMacro(Renderer, vtkRenderer);
160 
162 
165  vtkSetVector4Macro(Area, unsigned int);
166  vtkGetVector4Macro(Area, unsigned int);
168 
170 
180  vtkSetMacro(FieldAssociation, int);
181  vtkGetMacro(FieldAssociation, int);
183 
185 
190  vtkSetMacro(UseProcessIdFromData, bool);
191  vtkGetMacro(UseProcessIdFromData, bool);
193 
198  vtkSelection* Select();
199 
201 
214  virtual bool CaptureBuffers();
215  PixelInformation GetPixelInformation(const unsigned int display_position[2])
216  { return this->GetPixelInformation(display_position, 0); }
217  PixelInformation GetPixelInformation(const unsigned int display_position[2], int maxDist)
218  { unsigned int temp[2]; return this->GetPixelInformation(display_position, maxDist, temp); }
219  PixelInformation GetPixelInformation(const unsigned int display_position[2],
220  int maxDist, unsigned int selected_position[2]);
222  { this->ReleasePixBuffers(); }
223  // raw is before processing
224  unsigned char *GetRawPixelBuffer(int passNo) { return this->RawPixBuffer[passNo]; }
225  unsigned char *GetPixelBuffer(int passNo) { return this->PixBuffer[passNo]; }
227 
232  virtual void RenderCompositeIndex(unsigned int index);
233 
235 
241  virtual void UpdateMaximumCellId(vtkIdType attribid);
242  virtual void UpdateMaximumPointId(vtkIdType attribid);
244 
249  virtual void RenderProcessId(unsigned int processid);
250 
255  int Render(vtkRenderer* renderer, vtkProp** propArray, int propArrayCount);
256 
258 
262  vtkGetMacro(ActorPassOnly,bool);
263  vtkSetMacro(ActorPassOnly,bool);
265 
267 
273  vtkGetMacro(CaptureZValues,bool);
274  vtkSetMacro(CaptureZValues,bool);
276 
278 
281  virtual void BeginRenderProp();
282  virtual void EndRenderProp();
284 
286 
290  vtkSetMacro(ProcessID, int);
291  vtkGetMacro(ProcessID, int);
293 
295 
298  vtkGetVector3Macro(PropColorValue,float);
299  vtkSetVector3Macro(PropColorValue,float);
300  void SetPropColorValue(vtkIdType val);
302 
304 
307  vtkGetMacro(CurrentPass, int);
309 
319  { return GenerateSelection(this->Area); }
320  virtual vtkSelection* GenerateSelection(unsigned int r[4])
321  { return GenerateSelection(r[0], r[1], r[2], r[3]); }
322  virtual vtkSelection* GenerateSelection(
323  unsigned int x1, unsigned int y1,
324  unsigned int x2, unsigned int y2);
325 
332  virtual vtkSelection* GeneratePolygonSelection(
333  int* polygonPoints, vtkIdType count);
334 
339  vtkProp* GetPropFromID(int id);
340 
341  // it is very critical that these passes happen in the right order
342  // this is because of two complexities
343  //
344  // Compositing engines such as iceT send each pass as it
345  // renders. This means
346  //
347  // Mappers use point Ids or cell Id to update the process
348  // and composite ids. So the point and cell id passes
349  // have to happen before the last process and compoite
350  // passes respectively
351  //
352  //
354  {
355  // always must be first so that the prop IDs are set
357  // must always be second for composite mapper
359 
361  POINT_ID_HIGH24, // if needed
362  PROCESS_PASS, // best to be after point id pass
363 
365  CELL_ID_HIGH24, // if needed
366 
367  MAX_KNOWN_PASS = CELL_ID_HIGH24,
368  MIN_KNOWN_PASS = ACTOR_PASS
369  };
370 
374  std::string PassTypeToString(PassTypes type);
375 
376  static void Convert(int id, float tcoord[3])
377  {
378  tcoord[0] = static_cast<float>((id & 0xff)/255.0);
379  tcoord[1] = static_cast<float>(((id & 0xff00) >> 8)/255.0);
380  tcoord[2] = static_cast<float>(((id & 0xff0000) >> 16)/255.0);
381  }
382 
383  // grab the pixel buffer and save it
384  // typically called internally
385  virtual void SavePixelBuffer(int passNo);
386 
387 protected:
389  ~vtkHardwareSelector() override;
390 
391  // Used to notify subclasses when a capture pass is occurring.
392  virtual void PreCapturePass(int pass) { (void)pass; }
393  virtual void PostCapturePass(int pass) { (void)pass; }
394 
395  // Called internally before and after each prop is rendered
396  // for device specific configuration/preparation etc.
397  virtual void BeginRenderProp(vtkRenderWindow *) = 0;
398  virtual void EndRenderProp(vtkRenderWindow *) = 0;
399 
400  double GetZValue(int propid);
401 
402  int Convert(unsigned long offset, unsigned char* pb)
403  {
404  if (!pb)
405  {
406  return 0;
407  }
408  offset = offset * 3;
409  unsigned char rgb[3];
410  rgb[0] = pb[offset];
411  rgb[1] = pb[offset+1];
412  rgb[2] = pb[offset+2];
413  int val = 0;
414  val |= rgb[2];
415  val = val << 8;
416  val |= rgb[1];
417  val = val << 8;
418  val |= rgb[0];
419  return val;
420  }
421 
423 
426  int Convert(unsigned int pos[2], unsigned char* pb)
427  { return this->Convert(pos[0], pos[1], pb); }
428  int Convert(int xx, int yy, unsigned char* pb)
429  {
430  if (!pb)
431  {
432  return 0;
433  }
434  int offset = (yy * static_cast<int>(this->Area[2]-this->Area[0]+1) + xx) * 3;
435  unsigned char rgb[3];
436  rgb[0] = pb[offset];
437  rgb[1] = pb[offset+1];
438  rgb[2] = pb[offset+2];
439  int val = 0;
440  val |= rgb[2];
441  val = val << 8;
442  val |= rgb[1];
443  val = val << 8;
444  val |= rgb[0];
445  return val;
446  }
448 
449  vtkIdType GetID(int low24, int mid24, int high16)
450  {
451  vtkIdType val = 0;
452  val |= high16;
453  val = val << 24;
454  val |= mid24;
455  val = val << 24;
456  val |= low24;
457  return val;
458  }
459 
463  virtual bool PassRequired(int pass);
464 
470  bool IsPropHit(int propid);
471 
475  virtual int GetPropID(int idx, vtkProp* vtkNotUsed(prop))
476  { return idx; }
477 
478  virtual void BeginSelection();
479  virtual void EndSelection();
480 
481  virtual void ProcessPixelBuffers();
482  void BuildPropHitList(unsigned char* rgbData);
483 
485 
488  void ReleasePixBuffers();
490  unsigned int Area[4];
496 
497  // At most 10 passes.
498  unsigned char* PixBuffer[10];
499  unsigned char* RawPixBuffer[10];
504  int PropID;
505  float PropColorValue[3];
506 
508 
510 
511 private:
512  vtkHardwareSelector(const vtkHardwareSelector&) = delete;
513  void operator=(const vtkHardwareSelector&) = delete;
514 
515  class vtkInternals;
516  vtkInternals* Internals;
517 
518 };
519 
520 #endif
abstract superclass for all actors, volumes and annotations
Definition: vtkProp.h:50
virtual void PostCapturePass(int pass)
abstract base class for most VTK objects
Definition: vtkObject.h:59
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:64
virtual vtkSelection * GenerateSelection(unsigned int r[4])
data object that represents a "selection" in VTK.
Definition: vtkSelection.h:63
int vtkIdType
Definition: vtkType.h:349
bool UseProcessIdFromData
Clears all pixel buffers.
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.
static void Convert(int id, float tcoord[3])
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.
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.
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.
VTKACCELERATORSVTKM_EXPORT vtkm::cont::Field Convert(vtkDataArray *input, int association)