All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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/hd/enums.h"
31 #include "pxr/imaging/hd/renderPass.h"
32 #include "pxr/imaging/hd/renderPassState.h"
33 #include "pxr/imaging/hd/rprimCollection.h"
34 #include "pxr/imaging/hd/task.h"
35 
37 #include "pxr/base/gf/matrix4d.h"
38 #include "pxr/base/gf/vec2i.h"
39 #include "pxr/base/gf/vec2f.h"
40 #include "pxr/base/gf/vec4i.h"
41 #include "pxr/base/gf/vec4d.h"
42 #include "pxr/usd/sdf/path.h"
43 
44 #include <vector>
45 #include <memory>
46 
47 PXR_NAMESPACE_OPEN_SCOPE
48 
49 #define HDX_PICK_TOKENS \
50  /* Task context */ \
51  (pickParams) \
52  \
53  /* Pick target */ \
54  (pickPrimsAndInstances) \
55  (pickFaces) \
56  (pickEdges) \
57  (pickPoints) \
58  \
59  /* Resolve mode */ \
60  (resolveNearestToCamera) \
61  (resolveNearestToCenter) \
62  (resolveUnique) \
63  (resolveAll)
64 
65 TF_DECLARE_PUBLIC_TOKENS(HdxPickTokens, HDX_API, HDX_PICK_TOKENS);
66 
68 
70 using HdStShaderCodeSharedPtr = std::shared_ptr<class HdStShaderCode>;
71 
76 {
78  : cullStyle(HdCullStyleNothing)
79  , enableSceneMaterials(true)
80  {}
81 
82  HdCullStyle cullStyle;
83  bool enableSceneMaterials;
84 };
85 
88 struct HdxPickHit {
89  SdfPath delegateId;
90  SdfPath objectId;
91  SdfPath instancerId;
92  int instanceIndex;
93  int elementIndex;
94  int edgeIndex;
95  int pointIndex;
96  GfVec3f worldSpaceHitPoint;
97  GfVec3f worldSpaceHitNormal;
98  // normalizedDepth is in the range [0,1].
99  float normalizedDepth;
100 
101  inline bool IsValid() const {
102  return !objectId.IsEmpty();
103  }
104 
105  HDX_API
106  size_t GetHash() const;
107 };
108 
109 using HdxPickHitVector = std::vector<HdxPickHit>;
110 
139 {
140  using DepthMaskCallback = std::function<void(void)>;
141 
143  : resolution(128, 128)
144  , pickTarget(HdxPickTokens->pickPrimsAndInstances)
145  , resolveMode(HdxPickTokens->resolveNearestToCamera)
146  , doUnpickablesOcclude(false)
147  , viewMatrix(1)
148  , projectionMatrix(1)
149  , clipPlanes()
150  , depthMaskCallback(nullptr)
151  , collection()
152  , outHits(nullptr)
153  {}
154 
155  GfVec2i resolution;
156  TfToken pickTarget;
157  TfToken resolveMode;
158  bool doUnpickablesOcclude;
159  GfMatrix4d viewMatrix;
160  GfMatrix4d projectionMatrix;
161  std::vector<GfVec4d> clipPlanes;
162  DepthMaskCallback depthMaskCallback;
163  HdRprimCollection collection;
164  HdxPickHitVector *outHits;
165 };
166 
179 class HdxPickTask : public HdTask
180 {
181 public:
182  HDX_API
183  HdxPickTask(HdSceneDelegate* delegate, SdfPath const& id);
184 
185  HDX_API
186  ~HdxPickTask() override;
187 
189  HDX_API
190  void Sync(HdSceneDelegate* delegate,
191  HdTaskContext* ctx,
192  HdDirtyBits* dirtyBits) override;
193 
195  HDX_API
196  void Prepare(HdTaskContext* ctx,
197  HdRenderIndex* renderIndex) override;
198 
200  HDX_API
201  void Execute(HdTaskContext* ctx) override;
202 
203  HDX_API
204  const TfTokenVector &GetRenderTags() const override;
205 
207  static inline int DecodeIDRenderColor(unsigned char const idColor[4]) {
208  return (int32_t(idColor[0] & 0xff) << 0) |
209  (int32_t(idColor[1] & 0xff) << 8) |
210  (int32_t(idColor[2] & 0xff) << 16) |
211  (int32_t(idColor[3] & 0xff) << 24);
212  }
213 
214 private:
215  HdxPickTaskParams _params;
216  HdxPickTaskContextParams _contextParams;
217  TfTokenVector _renderTags;
218 
219  // We need to cache a pointer to the render index so Execute() can
220  // map prim ID to paths.
221  HdRenderIndex *_index;
222 
223  void _InitIfNeeded(GfVec2i const& widthHeight);
224  void _ConditionStencilWithGLCallback(
225  HdxPickTaskContextParams::DepthMaskCallback maskCallback);
226 
227  bool _UseOcclusionPass() const;
228 
229  // Create a shared render pass each for pickables and unpickables
230  HdRenderPassSharedPtr _pickableRenderPass;
231  HdRenderPassSharedPtr _occluderRenderPass;
232 
233  // Having separate render pass states allows us to use different
234  // shader mixins if we choose to (we don't currently).
235  HdRenderPassStateSharedPtr _pickableRenderPassState;
236  HdRenderPassStateSharedPtr _occluderRenderPassState;
237 
238  // A single draw target is shared for all contexts. Since the FBO cannot
239  // be shared, we clone the attachments on each request.
240  GlfDrawTargetRefPtr _drawTarget;
241 
242  HdxPickTask() = delete;
243  HdxPickTask(const HdxPickTask &) = delete;
244  HdxPickTask &operator =(const HdxPickTask &) = delete;
245 };
246 
249 public:
250 
251  // Pick result takes a tuple of ID buffers:
252  // - (primId, instanceId, elementId, edgeId, pointId)
253  // along with some geometric buffers:
254  // - (depth, Neye)
255  // ... and resolves them into a series of hits, using one of the
256  // algorithms specified below.
257  //
258  // index is used to fill in the HdxPickHit structure;
259  // pickTarget is used to determine what a valid hit is;
260  // viewMatrix, projectionMatrix, depthRange are used for unprojection
261  // to calculate the worldSpaceHitPosition and worldSpaceHitNormal.
262  // bufferSize is the size of the ID buffers, and subRect is the sub-region
263  // of the id buffers to iterate over in the resolution algorithm.
264  //
265  // All buffers need to be the same size, if passed in. It's legal for
266  // only the depth and primId buffers to be provided; everything else is
267  // optional but provides a richer picking result.
268  HDX_API
269  HdxPickResult(int const* primIds,
270  int const* instanceIds,
271  int const* elementIds,
272  int const* edgeIds,
273  int const* pointIds,
274  int const* neyes,
275  float const* depths,
276  HdRenderIndex const *index,
277  TfToken const& pickTarget,
278  GfMatrix4d const& viewMatrix,
279  GfMatrix4d const& projectionMatrix,
280  GfVec2f const& depthRange,
281  GfVec2i const& bufferSize,
282  GfVec4i const& subRect);
283 
284  HDX_API
285  ~HdxPickResult();
286 
287  HDX_API
288  HdxPickResult(HdxPickResult &&);
289  HDX_API
290  HdxPickResult& operator=(HdxPickResult &&);
291 
293  HDX_API
294  bool IsValid() const;
295 
299  HDX_API
300  void ResolveNearestToCamera(HdxPickHitVector* allHits) const;
301 
305  HDX_API
306  void ResolveNearestToCenter(HdxPickHitVector* allHits) const;
307 
310  HDX_API
311  void ResolveAll(HdxPickHitVector* allHits) const;
312 
315  HDX_API
316  void ResolveUnique(HdxPickHitVector* allHits) const;
317 
318 private:
319  bool _ResolveHit(int index, int x, int y, float z, HdxPickHit* hit) const;
320  size_t _GetHash(int index) const;
321  bool _IsValidHit(int index) const;
322 
323  // Provide accessors for all of the ID buffers. Since all but _primIds
324  // are optional, if the buffer doesn't exist just return -1 (== no hit).
325  int _GetPrimId(int index) const {
326  return _primIds ? _primIds[index] : -1;
327  }
328  int _GetInstanceId(int index) const {
329  return _instanceIds ? _instanceIds[index] : -1;
330  }
331  int _GetElementId(int index) const {
332  return _elementIds ? _elementIds[index] : -1;
333  }
334  int _GetEdgeId(int index) const {
335  return _edgeIds ? _edgeIds[index] : -1;
336  }
337  int _GetPointId(int index) const {
338  return _pointIds ? _pointIds[index] : -1;
339  }
340 
341  // Provide an accessor for the normal buffer. If the normal buffer is
342  // provided, this function will unpack the normal. The fallback is
343  // GfVec3f(0.0f).
344  GfVec3f _GetNormal(int index) const;
345 
346  int const* _primIds;
347  int const* _instanceIds;
348  int const* _elementIds;
349  int const* _edgeIds;
350  int const* _pointIds;
351  int const* _neyes;
352  float const* _depths;
353  HdRenderIndex const *_index;
354  TfToken _pickTarget;
355  GfMatrix4d _ndcToWorld;
356  GfMatrix4d _eyeToWorld;
357  GfVec2f _depthRange;
358  GfVec2i _bufferSize;
359  GfVec4i _subRect;
360 };
361 
362 // For sorting, order hits by ndc depth.
363 HDX_API
364 bool operator<(HdxPickHit const& lhs, HdxPickHit const& rhs);
365 
366 // VtValue requirements
367 HDX_API
368 std::ostream& operator<<(std::ostream& out, const HdxPickHit& h);
369 HDX_API
370 bool operator==(const HdxPickHit& lhs,
371  const HdxPickHit& rhs);
372 HDX_API
373 bool operator!=(const HdxPickHit& lhs,
374  const HdxPickHit& rhs);
375 
376 HDX_API
377 std::ostream& operator<<(std::ostream& out, const HdxPickTaskParams& pv);
378 HDX_API
379 bool operator==(const HdxPickTaskParams& lhs,
380  const HdxPickTaskParams& rhs);
381 HDX_API
382 bool operator!=(const HdxPickTaskParams& lhs,
383  const HdxPickTaskParams& rhs);
384 
385 HDX_API
386 std::ostream& operator<<(std::ostream& out, const HdxPickTaskContextParams& pv);
387 HDX_API
388 bool operator==(const HdxPickTaskContextParams& lhs,
389  const HdxPickTaskContextParams& rhs);
390 HDX_API
391 bool operator!=(const HdxPickTaskContextParams& lhs,
392  const HdxPickTaskContextParams& rhs);
393 PXR_NAMESPACE_CLOSE_SCOPE
394 
395 #endif // PXR_IMAGING_HDX_PICK_TASK_H
Basic type for a vector of 4 int components.
Definition: vec4i.h:61
The Hydra render index is a flattened representation of the client scene graph, which may be composed...
Definition: renderIndex.h:116
HDX_API void ResolveAll(HdxPickHitVector *allHits) const
Return all hit points.
Pick task params.
Definition: pickTask.h:75
Basic type for a vector of 2 int components.
Definition: vec2i.h:61
Standard pointer typedefs.
Pick task context params.
Definition: pickTask.h:138
HDX_API void ResolveUnique(HdxPickHitVector *allHits) const
Return the set of unique hit points, keeping only the nearest depth value.
Basic type for a vector of 3 float components.
Definition: vec3f.h:63
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)
#define TF_DECLARE_WEAK_AND_REF_PTRS(type)
Define standard weak, ref, and vector pointer types.
Definition: declarePtrs.h:89
A class representing a GL render target with mutliple image attachments.
Definition: drawTarget.h:67
Picking hit structure.
Definition: pickTask.h:88
HDX_API void ResolveNearestToCenter(HdxPickHitVector *allHits) const
Return the nearest single hit point from the center of the viewport.
Token for efficient comparison, assignment, and hashing of known strings.
Definition: token.h:87
HDX_API void ResolveNearestToCamera(HdxPickHitVector *allHits) const
Return the nearest single hit point.
Stores a 4x4 matrix of double elements.
Definition: matrix4d.h:88
Adapter class providing data exchange with the client scene graph.
#define TF_DECLARE_PUBLIC_TOKENS(...)
Macro to define public tokens.
Definition: staticTokens.h:118
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:248
A path value used to locate objects in layers or scenegraphs.
Definition: path.h:288
HDX_API bool IsValid() const
Return whether the result was given well-formed parameters.
static int DecodeIDRenderColor(unsigned char const idColor[4])
Utility: Given a UNorm8Vec4 pixel, unpack it into an int32 ID.
Definition: pickTask.h:207
GF_API std::ostream & operator<<(std::ostream &, const GfBBox3d &)
Output a GfBBox3d using the format [(range) matrix zeroArea].
Basic type for a vector of 2 float components.
Definition: vec2f.h:63
A task for running picking queries against the current scene.
Definition: pickTask.h:179
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.
bool IsEmpty() const noexcept
Returns true if this is the empty path (SdfPath::EmptyPath()).
Definition: path.h:417
HDX_API void Prepare(HdTaskContext *ctx, HdRenderIndex *renderIndex) override
Prepare the pick task.