pickTask.h
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 
30 #include "pxr/imaging/hdSt/textureUtils.h"
31 #include "pxr/imaging/hd/dataSource.h"
32 #include "pxr/imaging/hd/enums.h"
33 #include "pxr/imaging/hd/primOriginSchema.h"
34 #include "pxr/imaging/hd/renderPass.h"
35 #include "pxr/imaging/hd/renderPassState.h"
36 #include "pxr/imaging/hd/rprimCollection.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 
51 PXR_NAMESPACE_OPEN_SCOPE
52 
53 #define HDX_PICK_TOKENS \
54  /* Task context */ \
55  (pickParams) \
56  \
57  /* Pick target */ \
58  (pickPrimsAndInstances) \
59  (pickFaces) \
60  (pickEdges) \
61  (pickPoints) \
62  \
63  /* Resolve mode */ \
64  (resolveNearestToCamera) \
65  (resolveNearestToCenter) \
66  (resolveUnique) \
67  (resolveAll)
68 
69 TF_DECLARE_PUBLIC_TOKENS(HdxPickTokens, HDX_API, HDX_PICK_TOKENS);
70 
71 class HdStRenderBuffer;
73 using HdStShaderCodeSharedPtr = std::shared_ptr<class HdStShaderCode>;
74 
75 class Hgi;
76 
81 {
83  : cullStyle(HdCullStyleNothing)
84  , enableSceneMaterials(true)
85  {}
86 
87  HdCullStyle cullStyle;
88  bool enableSceneMaterials;
89 };
90 
93 struct HdxPickHit
94 {
105  int instanceIndex;
106  int elementIndex;
107  int edgeIndex;
108  int pointIndex;
109  GfVec3f worldSpaceHitPoint;
110  GfVec3f worldSpaceHitNormal;
114 
115  inline bool IsValid() const {
116  return !objectId.IsEmpty();
117  }
118 
119  HDX_API
120  size_t GetHash() const;
121 };
122 
123 using HdxPickHitVector = std::vector<HdxPickHit>;
124 
128 {
132  HdContainerDataSourceHandle instancerPrimOrigin;
133 
137 
155  HdContainerDataSourceHandle instancePrimOrigin;
158 };
159 
178 {
181  HDX_API
182  static HdxPrimOriginInfo
183  FromPickHit(HdRenderIndex * renderIndex,
184  const HdxPickHit &hit);
185 
192  HDX_API
194  const TfToken &nameInPrimOrigin =
195  HdPrimOriginSchemaTokens->scenePath) const;
196 
199  std::vector<HdxInstancerContext> instancerContexts;
202  HdContainerDataSourceHandle primOrigin;
203 };
204 
233 {
234  using DepthMaskCallback = std::function<void(void)>;
235 
237  : resolution(128, 128)
238  , pickTarget(HdxPickTokens->pickPrimsAndInstances)
239  , resolveMode(HdxPickTokens->resolveNearestToCamera)
240  , doUnpickablesOcclude(false)
241  , viewMatrix(1)
242  , projectionMatrix(1)
243  , clipPlanes()
244  , depthMaskCallback(nullptr)
245  , collection()
246  , outHits(nullptr)
247  {}
248 
249  GfVec2i resolution;
250  TfToken pickTarget;
251  TfToken resolveMode;
252  bool doUnpickablesOcclude;
253  GfMatrix4d viewMatrix;
254  GfMatrix4d projectionMatrix;
255  std::vector<GfVec4d> clipPlanes;
256  DepthMaskCallback depthMaskCallback;
257  HdRprimCollection collection;
258  HdxPickHitVector *outHits;
259 };
260 
273 class HdxPickTask : public HdTask
274 {
275 public:
276  HDX_API
277  HdxPickTask(HdSceneDelegate* delegate, SdfPath const& id);
278 
279  HDX_API
280  ~HdxPickTask() override;
281 
283  HDX_API
284  void Sync(HdSceneDelegate* delegate,
285  HdTaskContext* ctx,
286  HdDirtyBits* dirtyBits) override;
287 
289  HDX_API
290  void Prepare(HdTaskContext* ctx,
291  HdRenderIndex* renderIndex) override;
292 
294  HDX_API
295  void Execute(HdTaskContext* ctx) override;
296 
297  HDX_API
298  const TfTokenVector &GetRenderTags() const override;
299 
301  static inline int DecodeIDRenderColor(unsigned char const idColor[4]) {
302  return (int32_t(idColor[0] & 0xff) << 0) |
303  (int32_t(idColor[1] & 0xff) << 8) |
304  (int32_t(idColor[2] & 0xff) << 16) |
305  (int32_t(idColor[3] & 0xff) << 24);
306  }
307 
308 private:
309  HdxPickTaskParams _params;
310  HdxPickTaskContextParams _contextParams;
311  TfTokenVector _allRenderTags;
312  TfTokenVector _nonWidgetRenderTags;
313 
314  // We need to cache a pointer to the render index so Execute() can
315  // map prim ID to paths.
316  HdRenderIndex *_index;
317 
318  void _InitIfNeeded();
319  void _CreateAovBindings();
320  void _CleanupAovBindings();
321  void _ResizeOrCreateBufferForAOV(
322  const HdRenderPassAovBinding& aovBinding);
323 
324  void _ConditionStencilWithGLCallback(
325  HdxPickTaskContextParams::DepthMaskCallback maskCallback,
326  HdRenderBuffer const * depthStencilBuffer);
327 
328  bool _UseOcclusionPass() const;
329  bool _UseWidgetPass() const;
330 
331  template<typename T>
332  HdStTextureUtils::AlignedBuffer<T>
333  _ReadAovBuffer(TfToken const & aovName) const;
334 
335  HdRenderBuffer const * _FindAovBuffer(TfToken const & aovName) const;
336 
337  // Create a shared render pass each for pickables, unpickables, and
338  // widgets (which may draw on top even when occluded).
339  HdRenderPassSharedPtr _pickableRenderPass;
340  HdRenderPassSharedPtr _occluderRenderPass;
341  HdRenderPassSharedPtr _widgetRenderPass;
342 
343  // Having separate render pass states allows us to use different
344  // shader mixins if we choose to (we don't currently).
345  HdRenderPassStateSharedPtr _pickableRenderPassState;
346  HdRenderPassStateSharedPtr _occluderRenderPassState;
347  HdRenderPassStateSharedPtr _widgetRenderPassState;
348 
349  Hgi* _hgi;
350 
351  std::vector<std::unique_ptr<HdStRenderBuffer>> _pickableAovBuffers;
352  HdRenderPassAovBindingVector _pickableAovBindings;
353  HdRenderPassAovBinding _occluderAovBinding;
354  size_t _pickableDepthIndex;
355  TfToken _depthToken;
356  std::unique_ptr<HdStRenderBuffer> _widgetDepthStencilBuffer;
357  HdRenderPassAovBindingVector _widgetAovBindings;
358 
359  HdxPickTask() = delete;
360  HdxPickTask(const HdxPickTask &) = delete;
361  HdxPickTask &operator =(const HdxPickTask &) = delete;
362 };
363 
366 public:
367 
368  // Pick result takes a tuple of ID buffers:
369  // - (primId, instanceId, elementId, edgeId, pointId)
370  // along with some geometric buffers:
371  // - (depth, Neye)
372  // ... and resolves them into a series of hits, using one of the
373  // algorithms specified below.
374  //
375  // index is used to fill in the HdxPickHit structure;
376  // pickTarget is used to determine what a valid hit is;
377  // viewMatrix, projectionMatrix, depthRange are used for unprojection
378  // to calculate the worldSpaceHitPosition and worldSpaceHitNormal.
379  // bufferSize is the size of the ID buffers, and subRect is the sub-region
380  // of the id buffers to iterate over in the resolution algorithm.
381  //
382  // All buffers need to be the same size, if passed in. It's legal for
383  // only the depth and primId buffers to be provided; everything else is
384  // optional but provides a richer picking result.
385  HDX_API
386  HdxPickResult(int const* primIds,
387  int const* instanceIds,
388  int const* elementIds,
389  int const* edgeIds,
390  int const* pointIds,
391  int const* neyes,
392  float const* depths,
393  HdRenderIndex const *index,
394  TfToken const& pickTarget,
395  GfMatrix4d const& viewMatrix,
396  GfMatrix4d const& projectionMatrix,
397  GfVec2f const& depthRange,
398  GfVec2i const& bufferSize,
399  GfVec4i const& subRect);
400 
401  HDX_API
402  ~HdxPickResult();
403 
404  HDX_API
406  HDX_API
407  HdxPickResult& operator=(HdxPickResult &&);
408 
410  HDX_API
411  bool IsValid() const;
412 
416  HDX_API
417  void ResolveNearestToCamera(HdxPickHitVector* allHits) const;
418 
422  HDX_API
423  void ResolveNearestToCenter(HdxPickHitVector* allHits) const;
424 
427  HDX_API
428  void ResolveAll(HdxPickHitVector* allHits) const;
429 
432  HDX_API
433  void ResolveUnique(HdxPickHitVector* allHits) const;
434 
435 private:
436  bool _ResolveHit(int index, int x, int y, float z, HdxPickHit* hit) const;
437 
438  size_t _GetHash(int index) const;
439  bool _IsValidHit(int index) const;
440 
441  // Provide accessors for all of the ID buffers. Since all but _primIds
442  // are optional, if the buffer doesn't exist just return -1 (== no hit).
443  int _GetPrimId(int index) const {
444  return _primIds ? _primIds[index] : -1;
445  }
446  int _GetInstanceId(int index) const {
447  return _instanceIds ? _instanceIds[index] : -1;
448  }
449  int _GetElementId(int index) const {
450  return _elementIds ? _elementIds[index] : -1;
451  }
452  int _GetEdgeId(int index) const {
453  return _edgeIds ? _edgeIds[index] : -1;
454  }
455  int _GetPointId(int index) const {
456  return _pointIds ? _pointIds[index] : -1;
457  }
458 
459  // Provide an accessor for the normal buffer. If the normal buffer is
460  // provided, this function will unpack the normal. The fallback is
461  // GfVec3f(0.0f).
462  GfVec3f _GetNormal(int index) const;
463 
464  int const* _primIds;
465  int const* _instanceIds;
466  int const* _elementIds;
467  int const* _edgeIds;
468  int const* _pointIds;
469  int const* _neyes;
470  float const* _depths;
471  HdRenderIndex const *_index;
472  TfToken _pickTarget;
473  GfMatrix4d _ndcToWorld;
474  GfMatrix4d _eyeToWorld;
475  GfVec2f _depthRange;
476  GfVec2i _bufferSize;
477  GfVec4i _subRect;
478 };
479 
480 // For sorting, order hits by ndc depth.
481 HDX_API
482 bool operator<(HdxPickHit const& lhs, HdxPickHit const& rhs);
483 
484 // VtValue requirements
485 HDX_API
486 std::ostream& operator<<(std::ostream& out, const HdxPickHit& h);
487 HDX_API
488 bool operator==(const HdxPickHit& lhs,
489  const HdxPickHit& rhs);
490 HDX_API
491 bool operator!=(const HdxPickHit& lhs,
492  const HdxPickHit& rhs);
493 
494 HDX_API
495 std::ostream& operator<<(std::ostream& out, const HdxPickTaskParams& pv);
496 HDX_API
497 bool operator==(const HdxPickTaskParams& lhs,
498  const HdxPickTaskParams& rhs);
499 HDX_API
500 bool operator!=(const HdxPickTaskParams& lhs,
501  const HdxPickTaskParams& rhs);
502 
503 HDX_API
504 std::ostream& operator<<(std::ostream& out, const HdxPickTaskContextParams& pv);
505 HDX_API
506 bool operator==(const HdxPickTaskContextParams& lhs,
507  const HdxPickTaskContextParams& rhs);
508 HDX_API
509 bool operator!=(const HdxPickTaskContextParams& lhs,
510  const HdxPickTaskContextParams& rhs);
511 PXR_NAMESPACE_CLOSE_SCOPE
512 
513 #endif // PXR_IMAGING_HDX_PICK_TASK_H
Basic type for a vector of 4 int components.
Definition: vec4i.h:60
The Hydra render index is a flattened representation of the client scene graph, which may be composed...
Definition: renderIndex.h:120
HDX_API void ResolveUnique(HdxPickHitVector *allHits) const
Return the set of unique hit points, keeping only the nearest depth value.
HDX_API bool IsValid() const
Return whether the result was given well-formed parameters.
Pick task params.
Definition: pickTask.h:80
Basic type for a vector of 2 int components.
Definition: vec2i.h:60
Standard pointer typedefs.
Pick task context params.
Definition: pickTask.h:232
SdfPath objectId
Path computed from scenePath's in primOrigin data source of picked prim and instancers if provided by...
Definition: pickTask.h:101
Provide architecture-specific memory-alignment information.
float normalizedDepth
normalizedDepth is in the range [0,1].
Definition: pickTask.h:113
Basic type for a vector of 3 float components.
Definition: vec3f.h:62
AR_API bool operator!=(const ArAssetInfo &lhs, const ArAssetInfo &rhs)
A set of rendering parameters used among render passes.
AR_API bool operator==(const ArAssetInfo &lhs, const ArAssetInfo &rhs)
Picking hit structure.
Definition: pickTask.h:93
Information about an instancer instancing a picked object (or an instancer instancing such an instanc...
Definition: pickTask.h:127
Token for efficient comparison, assignment, and hashing of known strings.
Definition: token.h:87
HDX_API void ResolveNearestToCenter(HdxPickHitVector *allHits) const
Return the nearest single hit point from the center of the viewport.
int instanceId
Index of the picked instance.
Definition: pickTask.h:157
Stores a 4x4 matrix of double elements.
Definition: matrix4d.h:87
Adapter class providing data exchange with the client scene graph.
#define TF_DECLARE_PUBLIC_TOKENS(...)
Macro to define public tokens.
Definition: staticTokens.h:118
HdContainerDataSourceHandle instancePrimOrigin
The prim origin data source of the picked (implicit) instance.
Definition: pickTask.h:155
std::vector< TfToken > TfTokenVector
Convenience types.
Definition: token.h:442
A named, semantic collection of objects.
A utility class for resolving ID buffers into hits.
Definition: pickTask.h:365
A path value used to locate objects in layers or scenegraphs.
Definition: path.h:290
SdfPath delegateId
delegateID of HdSceneDelegate that provided the picked prim.
Definition: pickTask.h:97
static int DecodeIDRenderColor(unsigned char const idColor[4])
Utility: Given a UNorm8Vec4 pixel, unpack it into an int32 ID.
Definition: pickTask.h:301
HdContainerDataSourceHandle instancerPrimOrigin
The prim origin data source of the instancer.
Definition: pickTask.h:132
GF_API std::ostream & operator<<(std::ostream &, const GfBBox3d &)
Output a GfBBox3d using the format [(range) matrix zeroArea].
Hydra Graphics Interface.
Definition: hgi.h:110
SdfPath instancerId
Only supported for scene delegates, see HdxPrimOriginInfo for scene indices.
Definition: pickTask.h:104
A renderpass AOV represents a binding of some output of the rendering process to an output buffer.
Definition: aov.h:117
SdfPath instanceSceneIndexPath
For implicit instancing (native instancing in USD), the path of the picked instance in the scene inde...
Definition: pickTask.h:136
HdContainerDataSourceHandle primOrigin
The prim origin data source for the picked prim if provided by the scene index.
Definition: pickTask.h:202
A helper to extract information about the picked prim that allows modern applications to identify a p...
Definition: pickTask.h:177
Basic type for a vector of 2 float components.
Definition: vec2f.h:62
A task for running picking queries against the current scene.
Definition: pickTask.h:273
A render buffer is a handle to a data resource that can be rendered into, such as a 2d image for a dr...
Definition: renderBuffer.h:49
static HDX_API HdxPrimOriginInfo FromPickHit(HdRenderIndex *renderIndex, const HdxPickHit &hit)
Query terminal scene index of render index for information about picked prim.
SdfPath instancerSceneIndexPath
The path of the instancer in the scene index.
Definition: pickTask.h:130
HDX_API void Execute(HdTaskContext *ctx) override
Execute the pick task.
HDX_API void Sync(HdSceneDelegate *delegate, HdTaskContext *ctx, HdDirtyBits *dirtyBits) override
Sync the render pass resources.
HDX_API void ResolveAll(HdxPickHitVector *allHits) const
Return all hit points.
std::vector< HdxInstancerContext > instancerContexts
Information about the instancers instancing the picked object.
Definition: pickTask.h:199
bool IsEmpty() const noexcept
Returns true if this is the empty path (SdfPath::EmptyPath()).
Definition: path.h:419
HDX_API void ResolveNearestToCamera(HdxPickHitVector *allHits) const
Return the nearest single hit point.
HDX_API SdfPath GetFullPath(const TfToken &nameInPrimOrigin=HdPrimOriginSchemaTokens->scenePath) const
Combines instance scene paths and prim scene path to obtain the full scene path.
HDX_API void Prepare(HdTaskContext *ctx, HdRenderIndex *renderIndex) override
Prepare the pick task.