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 
32 #include "pxr/imaging/hd/enums.h"
37 #include "pxr/imaging/hd/task.h"
38 
39 #include "pxr/base/arch/align.h"
41 #include "pxr/base/gf/matrix4d.h"
42 #include "pxr/base/gf/vec2i.h"
43 #include "pxr/base/gf/vec2f.h"
44 #include "pxr/base/gf/vec4i.h"
45 #include "pxr/base/gf/vec4d.h"
46 #include "pxr/usd/sdf/path.h"
47 
48 #include <vector>
49 #include <memory>
50 
52 
53 #define HDX_PICK_TOKENS \
54  /* Task context */ \
55  (pickParams) \
56  \
57  /* Pick target */ \
58  (pickPrimsAndInstances) \
59  (pickFaces) \
60  (pickEdges) \
61  (pickPoints) \
62  (pickPointsAndInstances) \
63  \
64  /* Resolve mode */ \
65  (resolveNearestToCamera) \
66  (resolveNearestToCenter) \
67  (resolveUnique) \
68  (resolveAll)
69 
71 
72 class HdStRenderBuffer;
74 using HdStShaderCodeSharedPtr = std::shared_ptr<class HdStShaderCode>;
75 
76 class Hgi;
77 
78 /// Pick task params. This contains render-style state (for example), but is
79 /// augmented by HdxPickTaskContextParams, which is passed in on the task
80 /// context.
82 {
85  , enableSceneMaterials(true)
86  {}
87 
90 };
91 
92 /// Picking hit structure. This is output by the pick task as a record of
93 /// what objects the picking query found.
94 struct HdxPickHit
95 {
96  /// delegateID of HdSceneDelegate that provided the picked prim.
97  /// Irrelevant for scene indices.
99  /// Path computed from scenePath's in primOrigin data source of
100  /// picked prim and instancers if provided by scene index.
101  /// Otherwise, path in render index.
103  /// Only supported for scene delegates, see HdxPrimOriginInfo for
104  /// scene indices.
112  /// normalizedDepth is in the range [0,1]. Nb: the pick depth buffer won't
113  /// contain items drawn with renderTag "widget" for simplicity.
115 
116  inline bool IsValid() const {
117  return !objectId.IsEmpty();
118  }
119 
120  HDX_API
121  size_t GetHash() const;
122 };
123 
124 using HdxPickHitVector = std::vector<HdxPickHit>;
125 
126 /// Information about an instancer instancing a picked object (or an
127 /// instancer instancing such an instancer and so on).
129 {
130  /// The path of the instancer in the scene index.
132  /// The prim origin data source of the instancer.
133  HdContainerDataSourceHandle instancerPrimOrigin;
134 
135  /// For implicit instancing (native instancing in USD), the path of
136  /// the picked instance in the scene index.
138 
139  /// The prim origin data source of the picked (implicit) instance
140  ///
141  /// Note that typically, exactly one of instancePrimOrigin
142  /// or instancerPrimOrigin will contain data depending on whether
143  /// the instancing at the current level was implicit or not,
144  /// respectively. This is because for implicit instancing, there is no
145  /// authored instancer in the original scene (e.g., no USD instancer
146  /// prim for USD native instancing).
147  ///
148  /// For non-nested implicit instancing, the scenePath of the
149  /// instancePrimOrigin will be an absolute path.
150  /// For nested implicit instancing, the scenePath of the instancePrimOrigin
151  /// is an absolute path for the outer instancer context and a relative
152  /// path otherwise.
153  /// The relative path corresponds to an instance within a prototype that
154  /// was itself instanced. It is relative to the prototype's root.
155  ///
156  HdContainerDataSourceHandle instancePrimOrigin;
157  /// Index of the picked instance.
159 };
160 
161 /// A helper to extract information about the picked prim that allows
162 /// modern applications to identify a prim and, e.g., obtain the scene path
163 /// such as the path of the corresponding UsdPrim.
164 ///
165 /// Note that this helper assumes that we use scene indices and that the
166 /// primOrigin data source was populated for each pickable prim in the
167 /// scene index. Typically, an application will populate the scenePath in the
168 /// primOrigin data source. But the design allows an application to populate
169 /// the primOrigin container data source with arbitrary data that helps to
170 /// give context about a prim and identify the picked prim.
171 ///
172 /// Note that legacy applications using scene delegates cannot use
173 /// HdxPrimOriginInfo and have to translate the scene index path to a scene
174 /// path using the scene delegate API
175 /// HdSceneDelegate::GetScenePrimPath and
176 /// HdSceneDelegate::ConvertIndexPathToCachePath.
177 ///
179 {
180  /// Query terminal scene index of render index for information about
181  /// picked prim.
182  HDX_API
183  static HdxPrimOriginInfo
184  FromPickHit(HdRenderIndex * renderIndex,
185  const HdxPickHit &hit);
186 
187  /// Combines instance scene paths and prim scene path to obtain the full
188  /// scene path.
189  ///
190  /// The scene path is extracted from the prim origin container data
191  /// source by using the given key.
192  ///
193  HDX_API
195  const TfToken &nameInPrimOrigin =
196  HdPrimOriginSchemaTokens->scenePath) const;
197 
198  /// Information about the instancers instancing the picked object.
199  /// The outer most instancer will be first.
200  std::vector<HdxInstancerContext> instancerContexts;
201  /// The prim origin data source for the picked prim if provided
202  /// by the scene index.
203  HdContainerDataSourceHandle primOrigin;
204 };
205 
206 /// Pick task context params. This contains task params that can't come from
207 /// the scene delegate (like resolution mode and pick location, that might
208 /// be resolved late), as well as the picking collection and the output
209 /// hit vector.
210 /// 'pickTarget': The target of the pick operation, which may influence the
211 /// data filled in the HdxPickHit(s).
212 /// The available options are:
213 /// HdxPickTokens->pickPrimsAndInstances
214 /// HdxPickTokens->pickFaces
215 /// HdxPickTokens->pickEdges
216 /// HdxPickTokens->pickPoints
217 /// HdxPickTokens->pickPointsAndInstances
218 ///
219 /// 'resolveMode': Dictates the resolution of which hit(s) are returned in
220 /// 'outHits'.
221 /// The available options are:
222 /// 1. HdxPickTokens->resolveNearestToCamera : Returns the hit whose
223 /// position is nearest to the camera
224 /// 2. HdxPickTokens->resolveNearestToCenter : Returns the hit whose
225 /// position is nearest to center of the pick location/region.
226 /// 3. HdxPickTokens->resolveUnique : Returns the unique hits, by hashing
227 /// the relevant member fields of HdxPickHit. The 'pickTarget'
228 /// influences this operation. For e.g., the subprim indices are ignored
229 /// when the pickTarget is pickPrimsAndInstances.
230 /// 4. HdxPickTokens->resolveAll: Returns all the hits for the pick location
231 /// or region. The number of hits returned depends on the resolution
232 /// used and may have duplicates.
233 ///
235 {
236  using DepthMaskCallback = std::function<void(void)>;
237 
239  : resolution(128, 128)
240  , pickTarget(HdxPickTokens->pickPrimsAndInstances)
241  , resolveMode(HdxPickTokens->resolveNearestToCamera)
242  , doUnpickablesOcclude(false)
243  , viewMatrix(1)
244  , projectionMatrix(1)
245  , clipPlanes()
246  , depthMaskCallback(nullptr)
247  , collection()
248  , outHits(nullptr)
249  {}
250 
257  std::vector<GfVec4d> clipPlanes;
261 };
262 
263 /// \class HdxPickTask
264 ///
265 /// A task for running picking queries against the current scene.
266 /// This task generates an id buffer for a "pick frustum" (normally the
267 /// camera frustum with the near plane narrowed to an (x,y) location and a
268 /// pick radius); then it resolves that id buffer into a series of prim paths.
269 /// The "Hit" output also contains subprim picking results (e.g. picked face,
270 /// edge, point, instance) and the intersection point in scene worldspace.
271 ///
272 /// HdxPickTask takes an HdxPickTaskParams through the scene delegate, and
273 /// HdxPickTaskContextParams through the task context as "pickParams".
274 /// It produces a hit vector, in the task context as "pickHits".
275 class HdxPickTask : public HdTask
276 {
277 public:
278  HDX_API
279  HdxPickTask(HdSceneDelegate* delegate, SdfPath const& id);
280 
281  HDX_API
282  ~HdxPickTask() override;
283 
284  /// Sync the render pass resources
285  HDX_API
286  void Sync(HdSceneDelegate* delegate,
287  HdTaskContext* ctx,
288  HdDirtyBits* dirtyBits) override;
289 
290  /// Prepare the pick task
291  HDX_API
292  void Prepare(HdTaskContext* ctx,
293  HdRenderIndex* renderIndex) override;
294 
295  /// Execute the pick task
296  HDX_API
297  void Execute(HdTaskContext* ctx) override;
298 
299  HDX_API
300  const TfTokenVector &GetRenderTags() const override;
301 
302  /// Utility: Given a UNorm8Vec4 pixel, unpack it into an int32 ID.
303  static inline int DecodeIDRenderColor(unsigned char const idColor[4]) {
304  return (int32_t(idColor[0] & 0xff) << 0) |
305  (int32_t(idColor[1] & 0xff) << 8) |
306  (int32_t(idColor[2] & 0xff) << 16) |
307  (int32_t(idColor[3] & 0xff) << 24);
308  }
309 
310 private:
311  HdxPickTaskParams _params;
312  HdxPickTaskContextParams _contextParams;
313  TfTokenVector _allRenderTags;
314  TfTokenVector _nonWidgetRenderTags;
315 
316  // We need to cache a pointer to the render index so Execute() can
317  // map prim ID to paths.
318  HdRenderIndex *_index;
319 
320  void _InitIfNeeded();
321  void _CreateAovBindings();
322  void _CleanupAovBindings();
323  void _ResizeOrCreateBufferForAOV(
324  const HdRenderPassAovBinding& aovBinding);
325 
326  void _ConditionStencilWithGLCallback(
328  HdRenderBuffer const * depthStencilBuffer);
329 
330  bool _UseOcclusionPass() const;
331  bool _UseWidgetPass() const;
332 
333  template<typename T>
335  _ReadAovBuffer(TfToken const & aovName) const;
336 
337  HdRenderBuffer const * _FindAovBuffer(TfToken const & aovName) const;
338 
339  // Create a shared render pass each for pickables, unpickables, and
340  // widgets (which may draw on top even when occluded).
341  HdRenderPassSharedPtr _pickableRenderPass;
342  HdRenderPassSharedPtr _occluderRenderPass;
343  HdRenderPassSharedPtr _widgetRenderPass;
344 
345  // Having separate render pass states allows us to use different
346  // shader mixins if we choose to (we don't currently).
347  HdRenderPassStateSharedPtr _pickableRenderPassState;
348  HdRenderPassStateSharedPtr _occluderRenderPassState;
349  HdRenderPassStateSharedPtr _widgetRenderPassState;
350 
351  Hgi* _hgi;
352 
353  std::vector<std::unique_ptr<HdStRenderBuffer>> _pickableAovBuffers;
354  HdRenderPassAovBindingVector _pickableAovBindings;
355  HdRenderPassAovBinding _occluderAovBinding;
356  size_t _pickableDepthIndex;
357  TfToken _depthToken;
358  std::unique_ptr<HdStRenderBuffer> _widgetDepthStencilBuffer;
359  HdRenderPassAovBindingVector _widgetAovBindings;
360 
361  HdxPickTask() = delete;
362  HdxPickTask(const HdxPickTask &) = delete;
363  HdxPickTask &operator =(const HdxPickTask &) = delete;
364 };
365 
366 /// A utility class for resolving ID buffers into hits.
368 public:
369 
370  // Pick result takes a tuple of ID buffers:
371  // - (primId, instanceId, elementId, edgeId, pointId)
372  // along with some geometric buffers:
373  // - (depth, Neye)
374  // ... and resolves them into a series of hits, using one of the
375  // algorithms specified below.
376  //
377  // index is used to fill in the HdxPickHit structure;
378  // pickTarget is used to determine what a valid hit is;
379  // viewMatrix, projectionMatrix, depthRange are used for unprojection
380  // to calculate the worldSpaceHitPosition and worldSpaceHitNormal.
381  // bufferSize is the size of the ID buffers, and subRect is the sub-region
382  // of the id buffers to iterate over in the resolution algorithm.
383  //
384  // All buffers need to be the same size, if passed in. It's legal for
385  // only the depth and primId buffers to be provided; everything else is
386  // optional but provides a richer picking result.
387  HDX_API
388  HdxPickResult(int const* primIds,
389  int const* instanceIds,
390  int const* elementIds,
391  int const* edgeIds,
392  int const* pointIds,
393  int const* neyes,
394  float const* depths,
395  HdRenderIndex const *index,
396  TfToken const& pickTarget,
397  GfMatrix4d const& viewMatrix,
398  GfMatrix4d const& projectionMatrix,
399  GfVec2f const& depthRange,
400  GfVec2i const& bufferSize,
401  GfVec4i const& subRect);
402 
403  HDX_API
404  ~HdxPickResult();
405 
406  HDX_API
407  HdxPickResult(HdxPickResult &&);
408  HDX_API
409  HdxPickResult& operator=(HdxPickResult &&);
410 
411  /// Return whether the result was given well-formed parameters.
412  HDX_API
413  bool IsValid() const;
414 
415  /// Return the nearest single hit point. Note that this method may be
416  /// considerably more efficient, as it only needs to construct a single
417  /// Hit object.
418  HDX_API
419  void ResolveNearestToCamera(HdxPickHitVector* allHits) const;
420 
421  /// Return the nearest single hit point from the center of the viewport.
422  /// Note that this method may be considerably more efficient, as it only
423  /// needs to construct a single Hit object.
424  HDX_API
425  void ResolveNearestToCenter(HdxPickHitVector* allHits) const;
426 
427  /// Return all hit points. Note that this may contain redundant objects,
428  /// however it allows access to all depth values for a given object.
429  HDX_API
430  void ResolveAll(HdxPickHitVector* allHits) const;
431 
432  /// Return the set of unique hit points, keeping only the nearest depth
433  /// value.
434  HDX_API
435  void ResolveUnique(HdxPickHitVector* allHits) const;
436 
437 private:
438  bool _ResolveHit(int index, int x, int y, float z, HdxPickHit* hit) const;
439 
440  size_t _GetHash(int index) const;
441  bool _IsValidHit(int index) const;
442 
443  // Provide accessors for all of the ID buffers. Since all but _primIds
444  // are optional, if the buffer doesn't exist just return -1 (== no hit).
445  int _GetPrimId(int index) const {
446  return _primIds ? _primIds[index] : -1;
447  }
448  int _GetInstanceId(int index) const {
449  return _instanceIds ? _instanceIds[index] : -1;
450  }
451  int _GetElementId(int index) const {
452  return _elementIds ? _elementIds[index] : -1;
453  }
454  int _GetEdgeId(int index) const {
455  return _edgeIds ? _edgeIds[index] : -1;
456  }
457  int _GetPointId(int index) const {
458  return _pointIds ? _pointIds[index] : -1;
459  }
460 
461  // Provide an accessor for the normal buffer. If the normal buffer is
462  // provided, this function will unpack the normal. The fallback is
463  // GfVec3f(0.0f).
464  GfVec3f _GetNormal(int index) const;
465 
466  int const* _primIds;
467  int const* _instanceIds;
468  int const* _elementIds;
469  int const* _edgeIds;
470  int const* _pointIds;
471  int const* _neyes;
472  float const* _depths;
473  HdRenderIndex const *_index;
474  TfToken _pickTarget;
475  GfMatrix4d _ndcToWorld;
476  GfMatrix4d _eyeToWorld;
477  GfVec2f _depthRange;
478  GfVec2i _bufferSize;
479  GfVec4i _subRect;
480 };
481 
482 // For sorting, order hits by ndc depth.
483 HDX_API
484 bool operator<(HdxPickHit const& lhs, HdxPickHit const& rhs);
485 
486 // VtValue requirements
487 HDX_API
488 std::ostream& operator<<(std::ostream& out, const HdxPickHit& h);
489 HDX_API
490 bool operator==(const HdxPickHit& lhs,
491  const HdxPickHit& rhs);
492 HDX_API
493 bool operator!=(const HdxPickHit& lhs,
494  const HdxPickHit& rhs);
495 
496 HDX_API
497 std::ostream& operator<<(std::ostream& out, const HdxPickTaskParams& pv);
498 HDX_API
499 bool operator==(const HdxPickTaskParams& lhs,
500  const HdxPickTaskParams& rhs);
501 HDX_API
502 bool operator!=(const HdxPickTaskParams& lhs,
503  const HdxPickTaskParams& rhs);
504 
505 HDX_API
506 std::ostream& operator<<(std::ostream& out, const HdxPickTaskContextParams& pv);
507 HDX_API
508 bool operator==(const HdxPickTaskContextParams& lhs,
509  const HdxPickTaskContextParams& rhs);
510 HDX_API
511 bool operator!=(const HdxPickTaskContextParams& lhs,
512  const HdxPickTaskContextParams& rhs);
514 
515 #endif // PXR_IMAGING_HDX_PICK_TASK_H
bool enableSceneMaterials
Definition: pickTask.h:89
Definition: vec4i.h:60
HdCullStyle cullStyle
Definition: pickTask.h:88
std::shared_ptr< class HdRenderPassState > HdRenderPassStateSharedPtr
Definition: engine.h:42
GfVec3f worldSpaceHitNormal
Definition: pickTask.h:111
std::shared_ptr< class HdStShaderCode > HdStShaderCodeSharedPtr
HdCullStyle
Definition: enums.h:122
int instanceId
Index of the picked instance.
Definition: pickTask.h:158
HDX_API size_t GetHash() const
Definition: vec2i.h:60
std::shared_ptr< class HdRenderPass > HdRenderPassSharedPtr
Definition: engine.h:41
int edgeIndex
Definition: pickTask.h:108
SdfPath delegateId
Definition: pickTask.h:98
uint32_t HdDirtyBits
Definition: types.h:158
HDX_API void Execute(HdTaskContext *ctx) override
Execute the pick task.
SdfPath objectId
Definition: pickTask.h:102
int pointIndex
Definition: pickTask.h:109
std::vector< HdxPickHit > HdxPickHitVector
Definition: pickTask.h:124
GLdouble GLdouble GLdouble z
Definition: glcorearb.h:848
GfVec3f worldSpaceHitPoint
Definition: pickTask.h:110
Definition: vec3f.h:62
HDX_API void ResolveUnique(HdxPickHitVector *allHits) const
bool IsEmpty() const noexcept
Returns true if this is the empty path (SdfPath::EmptyPath()).
Definition: path.h:415
GLint y
Definition: glcorearb.h:103
#define HDX_API
Definition: api.h:40
SdfPath instancerId
Definition: pickTask.h:105
HdxPickHitVector * outHits
Definition: pickTask.h:260
#define HDX_PICK_TOKENS
Definition: pickTask.h:53
TF_DECLARE_PUBLIC_TOKENS(HdxPickTokens, HDX_API, HDX_PICK_TOKENS)
DepthMaskCallback depthMaskCallback
Definition: pickTask.h:258
HDX_API void ResolveNearestToCenter(HdxPickHitVector *allHits) const
Definition: token.h:87
HDX_API ~HdxPickTask() override
float normalizedDepth
Definition: pickTask.h:114
bool operator!=(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Inequality operator, does exact floating point comparisons.
Definition: Mat3.h:556
static HDX_API HdxPrimOriginInfo FromPickHit(HdRenderIndex *renderIndex, const HdxPickHit &hit)
HDX_API ~HdxPickResult()
HDX_API HdxPickResult & operator=(HdxPickResult &&)
std::vector< TfToken > TfTokenVector
Convenience types.
Definition: token.h:457
int instanceIndex
Definition: pickTask.h:106
HDX_API void ResolveAll(HdxPickHitVector *allHits) const
A utility class for resolving ID buffers into hits.
Definition: pickTask.h:367
HDX_API SdfPath GetFullPath(const TfToken &nameInPrimOrigin=HdPrimOriginSchemaTokens->scenePath) const
Definition: task.h:54
Definition: path.h:290
GLint GLenum GLint x
Definition: glcorearb.h:409
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
HdContainerDataSourceHandle primOrigin
Definition: pickTask.h:203
GfMatrix4d projectionMatrix
Definition: pickTask.h:256
HDX_API void Sync(HdSceneDelegate *delegate, HdTaskContext *ctx, HdDirtyBits *dirtyBits) override
Sync the render pass resources.
Definition: hgi.h:110
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:1432
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:62
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:303
HDX_API bool operator<(HdxPickHit const &lhs, HdxPickHit const &rhs)
HdContainerDataSourceHandle instancePrimOrigin
Definition: pickTask.h:156
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
SdfPath instancerSceneIndexPath
The path of the instancer in the scene index.
Definition: pickTask.h:131
std::vector< GfVec4d > clipPlanes
Definition: pickTask.h:257
int elementIndex
Definition: pickTask.h:107
std::vector< HdRenderPassAovBinding > HdRenderPassAovBindingVector
Definition: aov.h:154
bool IsValid() const
Definition: pickTask.h:116
std::vector< HdxInstancerContext > instancerContexts
Definition: pickTask.h:200
HdRprimCollection collection
Definition: pickTask.h:259
HDX_API void ResolveNearestToCamera(HdxPickHitVector *allHits) const
HdContainerDataSourceHandle instancerPrimOrigin
The prim origin data source of the instancer.
Definition: pickTask.h:133
bool operator==(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Equality operator, does exact floating point comparisons.
Definition: Mat3.h:542
SdfPath instanceSceneIndexPath
Definition: pickTask.h:137
std::function< void(void)> DepthMaskCallback
Definition: pickTask.h:236