HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
instancer.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_IMAGING_HD_INSTANCER_H
8 #define PXR_IMAGING_HD_INSTANCER_H
9 
10 #include "pxr/pxr.h"
11 #include "pxr/imaging/hd/api.h"
12 #include "pxr/imaging/hd/version.h"
13 #include "pxr/imaging/hd/types.h"
14 
15 #include "pxr/usd/sdf/path.h"
16 
17 #include <mutex>
18 
20 
21 class HdSceneDelegate;
22 class HdRenderIndex;
23 class HdRprim;
24 class HdRenderParam;
25 
26 /// \class HdInstancer
27 ///
28 /// This class exists to facilitate point cloud style instancing. Instancers,
29 /// conceptually, are instructions to draw N objects; for each object, store
30 /// which Rprim you're drawing and what instance-specific primvars you're
31 /// binding.
32 ///
33 /// "/InstancerA": prototypes = ["/sphere", "/cube", "/sphere"];
34 /// hydra:instanceTranslations = [<0,0,0>, <1,0,0>, <0,1,0>]
35 ///
36 /// Hydra stores this in reverse: Rprims store which instancer is drawing them,
37 /// and the instancer stores which indices in that array of N objects are the
38 /// given Rprim.
39 ///
40 /// "/sphere": instancerId = "/InstancerA"
41 /// "/cube": instancerId = "/InstancerA"
42 /// Instancer A: indices("/sphere") = [0, 2]
43 /// indices("/cube") = [1]
44 /// hydra:instanceTranslations = [<0,0,0>, <1,0,0>, <0,1,0>]
45 ///
46 /// Instancing is implemented by the prototype drawing itself multiple times,
47 /// and looking up per-instance data each time based on "indices": so
48 /// "/sphere" would draw itself once with translate=<0,0,0> and once with
49 /// translate=<0,1,0>.
50 ///
51 /// To make things more exciting, instancers can be nested.
52 ///
53 /// "/cube": instancerId = "/InstancerA"
54 /// "/InstancerA": instancerId = "/InstancerB"
55 /// indices("/cube") = [0, 1]
56 /// hydra:instanceTranslations = [<0,0,0>, <1,0,0>]
57 /// "/InstancerB": indices("/InstancerA") = [0, 1]
58 /// hydra:instanceTranslations = [<0,0,0>, <0,1,0>]
59 ///
60 /// In this case, "/cube" draws itself four times, for each of the
61 /// index tuples <0,0>, <0,1>, <1,0>, <1,1> where the first index is
62 /// the index in instancerA, and the second index is in instancerB.
63 ///
64 /// If the same primvar (e.g. "hydra:instanceTranslations") shows up at multiple
65 /// levels of nesting, it's resolved as follows:
66 ///
67 /// Transforms
68 /// ----------
69 ///
70 /// Instance primvars "hydra:instanceTranslations", "hydra:instanceRotations",
71 /// "hydra:instanceScales", and "hydra:instanceTransforms" are used to compute
72 /// the final transform of an instance. "hydra:instanceTranslations" and
73 /// "hydra:instanceScales" are interpreted as vec3: position, and axis-aligned
74 /// scale respectively. "hydra:instanceRotations" is interpreted as a vec4
75 /// quaternion (<real, i, j k>), and "hydra:instanceTransforms" is a 4x4 matrix.
76 /// In the transform computation, everything is converted to a 4x4 matrix.
77 ///
78 /// There are additional transforms: "instancerTransform" comes from
79 /// HdSceneDelegate::GetInstancerTransform(instancer, proto), and represents
80 /// the constant transform between the instancer and the prototype. It
81 /// varies with each level of nesting, but not across instances.
82 ///
83 /// "transform" is the proto Rprim's local transform.
84 ///
85 /// The final instance transform for instance "index" is computed as:
86 ///
87 /// nested_transform(level) = instancerTransform(level) *
88 /// hydra:instanceTranslations(level, index) *
89 /// hydra:instanceRotations(level, index) *
90 /// hydra:instanceScales(level, index) *
91 /// hydra:instanceTransforms(level, index);
92 /// output_transform = product(i : nested-levels - 1 -> 0) {
93 /// nested_transform(i)
94 /// } * transform;
95 ///
96 /// Any transforms not provided by the scene delegate are set to identity.
97 ///
98 /// Class responsibilities
99 /// ======================
100 ///
101 /// HdInstancer's primary role is to track the "indices" arrays for each
102 /// proto used by an instancer, and any provided primvar arrays. The
103 /// implementation is in the renderer-specific instancers, like HdStInstancer.
104 ///
105 /// All data access (aside from local caches) is routed to the HdSceneDelegate.
106 ///
107 
108 class HdInstancer {
109 public:
110  /// Constructor.
111  HD_API
112  HdInstancer(HdSceneDelegate* delegate, SdfPath const& id);
113 
114  HD_API
115  virtual ~HdInstancer();
116 
117  /// Returns the identifier.
118  SdfPath const& GetId() const { return _id; }
119 
120  /// Returns the parent instancer identifier.
121  SdfPath const& GetParentId() const { return _parentId; }
122 
123  HdSceneDelegate* GetDelegate() const { return _delegate; }
124 
125  HD_API
127  HdRprim const& rprim);
128 
129  HD_API
130  static TfTokenVector const & GetBuiltinPrimvarNames();
131 
132  HD_API
133  virtual void Sync(HdSceneDelegate *sceneDelegate,
134  HdRenderParam *renderParam,
135  HdDirtyBits *dirtyBits);
136 
137  HD_API
138  virtual void Finalize(HdRenderParam *renderParam);
139 
140  HD_API
141  virtual HdDirtyBits GetInitialDirtyBitsMask() const;
142 
143  HD_API
144  static void _SyncInstancerAndParents(
145  HdRenderIndex &renderIndex,
146  SdfPath const& instancerId);
147 
148 protected:
149  HD_API
150  void _UpdateInstancer(HdSceneDelegate *delegate,
151  HdDirtyBits *dirtyBits);
152 
153 private:
154  HdSceneDelegate* _delegate;
155  SdfPath _id;
156  SdfPath _parentId;
157 
158  // XXX: This mutex exists for _SyncInstancerAndParents, which will go
159  // away when the render index calls sync on instancers.
160  std::mutex _instanceLock;
161 };
162 
163 
165 
166 #endif // PXR_IMAGING_HD_INSTANCER_H
virtual HD_API void Sync(HdSceneDelegate *sceneDelegate, HdRenderParam *renderParam, HdDirtyBits *dirtyBits)
uint32_t HdDirtyBits
Definition: types.h:143
virtual HD_API ~HdInstancer()
#define HD_API
Definition: api.h:23
HdSceneDelegate * GetDelegate() const
Definition: instancer.h:123
virtual HD_API void Finalize(HdRenderParam *renderParam)
Definition: rprim.h:37
std::vector< TfToken > TfTokenVector
Convenience types.
Definition: token.h:440
Definition: path.h:273
SdfPath const & GetId() const
Returns the identifier.
Definition: instancer.h:118
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
GLuint index
Definition: glcorearb.h:786
virtual HD_API HdDirtyBits GetInitialDirtyBitsMask() const
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
HD_API void _UpdateInstancer(HdSceneDelegate *delegate, HdDirtyBits *dirtyBits)
SdfPath const & GetParentId() const
Returns the parent instancer identifier.
Definition: instancer.h:121
HD_API HdInstancer(HdSceneDelegate *delegate, SdfPath const &id)
Constructor.
static HD_API TfTokenVector const & GetBuiltinPrimvarNames()
static HD_API void _SyncInstancerAndParents(HdRenderIndex &renderIndex, SdfPath const &instancerId)
static HD_API int GetInstancerNumLevels(HdRenderIndex &index, HdRprim const &rprim)