HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
pickTask.h
Go to the documentation of this file.
1 //
2 // Copyright 2019 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef PXR_IMAGING_HDX_PICK_TASK_H
25 #define PXR_IMAGING_HDX_PICK_TASK_H
26 
27 #include "pxr/pxr.h"
28 #include "pxr/imaging/hdx/api.h"
29 
31 #include "pxr/imaging/hd/enums.h"
35 #include "pxr/imaging/hd/task.h"
36 
37 #include "pxr/base/arch/align.h"
39 #include "pxr/base/gf/matrix4d.h"
40 #include "pxr/base/gf/vec2i.h"
41 #include "pxr/base/gf/vec2f.h"
42 #include "pxr/base/gf/vec4i.h"
43 #include "pxr/base/gf/vec4d.h"
44 #include "pxr/usd/sdf/path.h"
45 
46 #include <vector>
47 #include <memory>
48 
50 
51 #define HDX_PICK_TOKENS \
52  /* Task context */ \
53  (pickParams) \
54  \
55  /* Pick target */ \
56  (pickPrimsAndInstances) \
57  (pickFaces) \
58  (pickEdges) \
59  (pickPoints) \
60  \
61  /* Resolve mode */ \
62  (resolveNearestToCamera) \
63  (resolveNearestToCenter) \
64  (resolveUnique) \
65  (resolveAll)
66 
68 
69 class HdStRenderBuffer;
71 using HdStShaderCodeSharedPtr = std::shared_ptr<class HdStShaderCode>;
72 
73 class Hgi;
74 
75 /// Pick task params. This contains render-style state (for example), but is
76 /// augmented by HdxPickTaskContextParams, which is passed in on the task
77 /// context.
79 {
82  , enableSceneMaterials(true)
83  {}
84 
87 };
88 
89 /// Picking hit structure. This is output by the pick task as a record of
90 /// what objects the picking query found.
91 struct HdxPickHit {
97  int edgeIndex;
101  // normalizedDepth is in the range [0,1]. Nb: the pick depth buffer won't
102  // contain items drawn with renderTag "widget" for simplicity.
104 
105  inline bool IsValid() const {
106  return !objectId.IsEmpty();
107  }
108 
109  HDX_API
110  size_t GetHash() const;
111 };
112 
113 using HdxPickHitVector = std::vector<HdxPickHit>;
114 
115 /// Pick task context params. This contains task params that can't come from
116 /// the scene delegate (like resolution mode and pick location, that might
117 /// be resolved late), as well as the picking collection and the output
118 /// hit vector.
119 /// 'pickTarget': The target of the pick operation, which may influence the
120 /// data filled in the HdxPickHit(s).
121 /// The available options are:
122 /// HdxPickTokens->pickPrimsAndInstances
123 /// HdxPickTokens->pickFaces
124 /// HdxPickTokens->pickEdges
125 /// HdxPickTokens->pickPoints
126 ///
127 /// 'resolveMode': Dictates the resolution of which hit(s) are returned in
128 /// 'outHits'.
129 /// The available options are:
130 /// 1. HdxPickTokens->resolveNearestToCamera : Returns the hit whose
131 /// position is nearest to the camera
132 /// 2. HdxPickTokens->resolveNearestToCenter : Returns the hit whose
133 /// position is nearest to center of the pick location/region.
134 /// 3. HdxPickTokens->resolveUnique : Returns the unique hits, by hashing
135 /// the relevant member fields of HdxPickHit. The 'pickTarget'
136 /// influences this operation. For e.g., the subprim indices are ignored
137 /// when the pickTarget is pickPrimsAndInstances.
138 /// 4. HdxPickTokens->resolveAll: Returns all the hits for the pick location
139 /// or region. The number of hits returned depends on the resolution
140 /// used and may have duplicates.
141 ///
143 {
144  using DepthMaskCallback = std::function<void(void)>;
145 
147  : resolution(128, 128)
148  , pickTarget(HdxPickTokens->pickPrimsAndInstances)
149  , resolveMode(HdxPickTokens->resolveNearestToCamera)
150  , doUnpickablesOcclude(false)
151  , viewMatrix(1)
152  , projectionMatrix(1)
153  , clipPlanes()
154  , depthMaskCallback(nullptr)
155  , collection()
156  , outHits(nullptr)
157  {}
158 
165  std::vector<GfVec4d> clipPlanes;
169 };
170 
171 /// \class HdxPickTask
172 ///
173 /// A task for running picking queries against the current scene.
174 /// This task generates an id buffer for a "pick frustum" (normally the
175 /// camera frustum with the near plane narrowed to an (x,y) location and a
176 /// pick radius); then it resolves that id buffer into a series of prim paths.
177 /// The "Hit" output also contains subprim picking results (e.g. picked face,
178 /// edge, point, instance) and the intersection point in scene worldspace.
179 ///
180 /// HdxPickTask takes an HdxPickTaskParams through the scene delegate, and
181 /// HdxPickTaskContextParams through the task context as "pickParams".
182 /// It produces a hit vector, in the task context as "pickHits".
183 class HdxPickTask : public HdTask
184 {
185 public:
186  HDX_API
187  HdxPickTask(HdSceneDelegate* delegate, SdfPath const& id);
188 
189  HDX_API
190  ~HdxPickTask() override;
191 
192  /// Sync the render pass resources
193  HDX_API
194  void Sync(HdSceneDelegate* delegate,
195  HdTaskContext* ctx,
196  HdDirtyBits* dirtyBits) override;
197 
198  /// Prepare the pick task
199  HDX_API
200  void Prepare(HdTaskContext* ctx,
201  HdRenderIndex* renderIndex) override;
202 
203  /// Execute the pick task
204  HDX_API
205  void Execute(HdTaskContext* ctx) override;
206 
207  HDX_API
208  const TfTokenVector &GetRenderTags() const override;
209 
210  /// Utility: Given a UNorm8Vec4 pixel, unpack it into an int32 ID.
211  static inline int DecodeIDRenderColor(unsigned char const idColor[4]) {
212  return (int32_t(idColor[0] & 0xff) << 0) |
213  (int32_t(idColor[1] & 0xff) << 8) |
214  (int32_t(idColor[2] & 0xff) << 16) |
215  (int32_t(idColor[3] & 0xff) << 24);
216  }
217 
218 private:
219  HdxPickTaskParams _params;
220  HdxPickTaskContextParams _contextParams;
221  TfTokenVector _allRenderTags;
222  TfTokenVector _nonWidgetRenderTags;
223 
224  // We need to cache a pointer to the render index so Execute() can
225  // map prim ID to paths.
226  HdRenderIndex *_index;
227 
228  void _InitIfNeeded();
229  void _CreateAovBindings();
230  void _CleanupAovBindings();
231  void _ResizeOrCreateBufferForAOV(
232  const HdRenderPassAovBinding& aovBinding);
233 
234  void _ConditionStencilWithGLCallback(
236  HdRenderBuffer const * depthStencilBuffer);
237 
238  bool _UseOcclusionPass() const;
239  bool _UseWidgetPass() const;
240 
241  template<typename T>
243  _ReadAovBuffer(TfToken const & aovName) const;
244 
245  HdRenderBuffer const * _FindAovBuffer(TfToken const & aovName) const;
246 
247  // Create a shared render pass each for pickables, unpickables, and
248  // widgets (which may draw on top even when occluded).
249  HdRenderPassSharedPtr _pickableRenderPass;
250  HdRenderPassSharedPtr _occluderRenderPass;
251  HdRenderPassSharedPtr _widgetRenderPass;
252 
253  // Having separate render pass states allows us to use different
254  // shader mixins if we choose to (we don't currently).
255  HdRenderPassStateSharedPtr _pickableRenderPassState;
256  HdRenderPassStateSharedPtr _occluderRenderPassState;
257  HdRenderPassStateSharedPtr _widgetRenderPassState;
258 
259  Hgi* _hgi;
260 
261  std::vector<std::unique_ptr<HdStRenderBuffer>> _pickableAovBuffers;
262  HdRenderPassAovBindingVector _pickableAovBindings;
263  HdRenderPassAovBinding _occluderAovBinding;
264  size_t _pickableDepthIndex;
265  TfToken _depthToken;
266  std::unique_ptr<HdStRenderBuffer> _widgetDepthStencilBuffer;
267  HdRenderPassAovBindingVector _widgetAovBindings;
268 
269  HdxPickTask() = delete;
270  HdxPickTask(const HdxPickTask &) = delete;
271  HdxPickTask &operator =(const HdxPickTask &) = delete;
272 };
273 
274 /// A utility class for resolving ID buffers into hits.
276 public:
277 
278  // Pick result takes a tuple of ID buffers:
279  // - (primId, instanceId, elementId, edgeId, pointId)
280  // along with some geometric buffers:
281  // - (depth, Neye)
282  // ... and resolves them into a series of hits, using one of the
283  // algorithms specified below.
284  //
285  // index is used to fill in the HdxPickHit structure;
286  // pickTarget is used to determine what a valid hit is;
287  // viewMatrix, projectionMatrix, depthRange are used for unprojection
288  // to calculate the worldSpaceHitPosition and worldSpaceHitNormal.
289  // bufferSize is the size of the ID buffers, and subRect is the sub-region
290  // of the id buffers to iterate over in the resolution algorithm.
291  //
292  // All buffers need to be the same size, if passed in. It's legal for
293  // only the depth and primId buffers to be provided; everything else is
294  // optional but provides a richer picking result.
295  HDX_API
296  HdxPickResult(int const* primIds,
297  int const* instanceIds,
298  int const* elementIds,
299  int const* edgeIds,
300  int const* pointIds,
301  int const* neyes,
302  float const* depths,
303  HdRenderIndex const *index,
304  TfToken const& pickTarget,
305  GfMatrix4d const& viewMatrix,
306  GfMatrix4d const& projectionMatrix,
307  GfVec2f const& depthRange,
308  GfVec2i const& bufferSize,
309  GfVec4i const& subRect);
310 
311  HDX_API
312  ~HdxPickResult();
313 
314  HDX_API
315  HdxPickResult(HdxPickResult &&);
316  HDX_API
317  HdxPickResult& operator=(HdxPickResult &&);
318 
319  /// Return whether the result was given well-formed parameters.
320  HDX_API
321  bool IsValid() const;
322 
323  /// Return the nearest single hit point. Note that this method may be
324  /// considerably more efficient, as it only needs to construct a single
325  /// Hit object.
326  HDX_API
327  void ResolveNearestToCamera(HdxPickHitVector* allHits) const;
328 
329  /// Return the nearest single hit point from the center of the viewport.
330  /// Note that this method may be considerably more efficient, as it only
331  /// needs to construct a single Hit object.
332  HDX_API
333  void ResolveNearestToCenter(HdxPickHitVector* allHits) const;
334 
335  /// Return all hit points. Note that this may contain redundant objects,
336  /// however it allows access to all depth values for a given object.
337  HDX_API
338  void ResolveAll(HdxPickHitVector* allHits) const;
339 
340  /// Return the set of unique hit points, keeping only the nearest depth
341  /// value.
342  HDX_API
343  void ResolveUnique(HdxPickHitVector* allHits) const;
344 
345 private:
346  bool _ResolveHit(int index, int x, int y, float z, HdxPickHit* hit) const;
347  size_t _GetHash(int index) const;
348  bool _IsValidHit(int index) const;
349 
350  // Provide accessors for all of the ID buffers. Since all but _primIds
351  // are optional, if the buffer doesn't exist just return -1 (== no hit).
352  int _GetPrimId(int index) const {
353  return _primIds ? _primIds[index] : -1;
354  }
355  int _GetInstanceId(int index) const {
356  return _instanceIds ? _instanceIds[index] : -1;
357  }
358  int _GetElementId(int index) const {
359  return _elementIds ? _elementIds[index] : -1;
360  }
361  int _GetEdgeId(int index) const {
362  return _edgeIds ? _edgeIds[index] : -1;
363  }
364  int _GetPointId(int index) const {
365  return _pointIds ? _pointIds[index] : -1;
366  }
367 
368  // Provide an accessor for the normal buffer. If the normal buffer is
369  // provided, this function will unpack the normal. The fallback is
370  // GfVec3f(0.0f).
371  GfVec3f _GetNormal(int index) const;
372 
373  int const* _primIds;
374  int const* _instanceIds;
375  int const* _elementIds;
376  int const* _edgeIds;
377  int const* _pointIds;
378  int const* _neyes;
379  float const* _depths;
380  HdRenderIndex const *_index;
381  TfToken _pickTarget;
382  GfMatrix4d _ndcToWorld;
383  GfMatrix4d _eyeToWorld;
384  GfVec2f _depthRange;
385  GfVec2i _bufferSize;
386  GfVec4i _subRect;
387 };
388 
389 // For sorting, order hits by ndc depth.
390 HDX_API
391 bool operator<(HdxPickHit const& lhs, HdxPickHit const& rhs);
392 
393 // VtValue requirements
394 HDX_API
395 std::ostream& operator<<(std::ostream& out, const HdxPickHit& h);
396 HDX_API
397 bool operator==(const HdxPickHit& lhs,
398  const HdxPickHit& rhs);
399 HDX_API
400 bool operator!=(const HdxPickHit& lhs,
401  const HdxPickHit& rhs);
402 
403 HDX_API
404 std::ostream& operator<<(std::ostream& out, const HdxPickTaskParams& pv);
405 HDX_API
406 bool operator==(const HdxPickTaskParams& lhs,
407  const HdxPickTaskParams& rhs);
408 HDX_API
409 bool operator!=(const HdxPickTaskParams& lhs,
410  const HdxPickTaskParams& rhs);
411 
412 HDX_API
413 std::ostream& operator<<(std::ostream& out, const HdxPickTaskContextParams& pv);
414 HDX_API
415 bool operator==(const HdxPickTaskContextParams& lhs,
416  const HdxPickTaskContextParams& rhs);
417 HDX_API
418 bool operator!=(const HdxPickTaskContextParams& lhs,
419  const HdxPickTaskContextParams& rhs);
421 
422 #endif // PXR_IMAGING_HDX_PICK_TASK_H
bool enableSceneMaterials
Definition: pickTask.h:86
Definition: vec4i.h:61
HdCullStyle cullStyle
Definition: pickTask.h:85
std::shared_ptr< class HdRenderPassState > HdRenderPassStateSharedPtr
Definition: engine.h:42
GfVec3f worldSpaceHitNormal
Definition: pickTask.h:100
std::shared_ptr< class HdStShaderCode > HdStShaderCodeSharedPtr
HdCullStyle
Definition: enums.h:122
HDX_API size_t GetHash() const
Definition: vec2i.h:61
std::shared_ptr< class HdRenderPass > HdRenderPassSharedPtr
Definition: engine.h:41
int edgeIndex
Definition: pickTask.h:97
SdfPath delegateId
Definition: pickTask.h:92
uint32_t HdDirtyBits
Definition: types.h:158
HDX_API void Execute(HdTaskContext *ctx) override
Execute the pick task.
SdfPath objectId
Definition: pickTask.h:93
int pointIndex
Definition: pickTask.h:98
std::vector< HdxPickHit > HdxPickHitVector
Definition: pickTask.h:113
GfVec3f worldSpaceHitPoint
Definition: pickTask.h:99
Definition: vec3f.h:63
HDX_API void ResolveUnique(HdxPickHitVector *allHits) const
bool IsEmpty() const noexcept
Returns true if this is the empty path (SdfPath::EmptyPath()).
Definition: path.h:419
#define HDX_API
Definition: api.h:40
SdfPath instancerId
Definition: pickTask.h:94
HdxPickHitVector * outHits
Definition: pickTask.h:168
#define HDX_PICK_TOKENS
Definition: pickTask.h:51
TF_DECLARE_PUBLIC_TOKENS(HdxPickTokens, HDX_API, HDX_PICK_TOKENS)
GLint GLenum GLint x
Definition: glcorearb.h:409
DepthMaskCallback depthMaskCallback
Definition: pickTask.h:166
HDX_API void ResolveNearestToCenter(HdxPickHitVector *allHits) const
Definition: token.h:87
HDX_API ~HdxPickTask() override
float normalizedDepth
Definition: pickTask.h:103
bool operator!=(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Inequality operator, does exact floating point comparisons.
Definition: Mat3.h:570
GLdouble GLdouble GLdouble z
Definition: glcorearb.h:848
HDX_API ~HdxPickResult()
HDX_API HdxPickResult & operator=(HdxPickResult &&)
std::vector< TfToken > TfTokenVector
Convenience types.
Definition: token.h:442
int instanceIndex
Definition: pickTask.h:95
HDX_API void ResolveAll(HdxPickHitVector *allHits) const
A utility class for resolving ID buffers into hits.
Definition: pickTask.h:275
Definition: task.h:54
Definition: path.h:290
HDX_API const TfTokenVector & GetRenderTags() const override
HDX_API std::ostream & operator<<(std::ostream &out, const HdxPickHit &h)
std::unordered_map< TfToken, VtValue, TfToken::HashFunctor > HdTaskContext
Definition: renderIndex.h:77
GfMatrix4d projectionMatrix
Definition: pickTask.h:164
HDX_API void Sync(HdSceneDelegate *delegate, HdTaskContext *ctx, HdDirtyBits *dirtyBits) override
Sync the render pass resources.
Definition: hgi.h:108
HDX_API void Prepare(HdTaskContext *ctx, HdRenderIndex *renderIndex) override
Prepare the pick task.
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:2002
HDX_API bool IsValid() const
Return whether the result was given well-formed parameters.
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1394
HDX_API HdxPickResult(int const *primIds, int const *instanceIds, int const *elementIds, int const *edgeIds, int const *pointIds, int const *neyes, float const *depths, HdRenderIndex const *index, TfToken const &pickTarget, GfMatrix4d const &viewMatrix, GfMatrix4d const &projectionMatrix, GfVec2f const &depthRange, GfVec2i const &bufferSize, GfVec4i const &subRect)
Definition: vec2f.h:63
GLuint index
Definition: glcorearb.h:786
static int DecodeIDRenderColor(unsigned char const idColor[4])
Utility: Given a UNorm8Vec4 pixel, unpack it into an int32 ID.
Definition: pickTask.h:211
HDX_API bool operator<(HdxPickHit const &lhs, HdxPickHit const &rhs)
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
std::vector< GfVec4d > clipPlanes
Definition: pickTask.h:165
int elementIndex
Definition: pickTask.h:96
std::vector< HdRenderPassAovBinding > HdRenderPassAovBindingVector
Definition: aov.h:154
bool IsValid() const
Definition: pickTask.h:105
HdRprimCollection collection
Definition: pickTask.h:167
HDX_API void ResolveNearestToCamera(HdxPickHitVector *allHits) const
GLint y
Definition: glcorearb.h:103
bool operator==(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Equality operator, does exact floating point comparisons.
Definition: Mat3.h:556
std::function< void(void)> DepthMaskCallback
Definition: pickTask.h:144