1 //
2 // Copyright 2016 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 USDGEOM_GENERATED_POINTINSTANCER_H
25 #define USDGEOM_GENERATED_POINTINSTANCER_H
26 
27 /// \file usdGeom/pointInstancer.h
28 
29 #include "pxr/pxr.h"
30 #include "pxr/usd/usdGeom/api.h"
31 #include "pxr/usd/usdGeom/boundable.h"
32 #include "pxr/usd/usd/prim.h"
33 #include "pxr/usd/usd/stage.h"
34 #include "pxr/usd/usdGeom/tokens.h"
35 
36 #include "pxr/base/vt/value.h"
37 
38 #include "pxr/base/gf/vec3d.h"
39 #include "pxr/base/gf/vec3f.h"
40 #include "pxr/base/gf/matrix4d.h"
41 
42 #include "pxr/base/tf/token.h"
43 #include "pxr/base/tf/type.h"
44 
45 PXR_NAMESPACE_OPEN_SCOPE
46 
47 class SdfAssetPath;
48 
49 // -------------------------------------------------------------------------- //
50 // POINTINSTANCER                                                             //
51 // -------------------------------------------------------------------------- //
52 
53 /// \class UsdGeomPointInstancer
54 ///
55 /// Encodes vectorized instancing of multiple, potentially
56 /// animated, prototypes (object/instance masters), which can be arbitrary
57 /// prims/subtrees on a UsdStage.
58 ///
59 /// PointInstancer is a "multi instancer", as it allows multiple prototypes
60 /// to be scattered among its "points".  We use a UsdRelationship
61 /// \em prototypes to identify and order all of the possible prototypes, by
62 /// targeting the root prim of each prototype.  The ordering imparted by
63 /// relationships associates a zero-based integer with each prototype, and
64 /// it is these integers we use to identify the prototype of each instance,
65 /// compactly, and allowing prototypes to be swapped out without needing to
66 /// reauthor all of the per-instance data.
67 ///
68 /// The PointInstancer schema is designed to scale to billions of instances,
69 /// which motivates the choice to split the per-instance transformation into
70 /// position, (quaternion) orientation, and scales, rather than a
71 /// 4x4 matrix per-instance.  In addition to requiring fewer bytes even if
72 /// all elements are authored (32 bytes vs 64 for a single-precision 4x4
73 /// matrix), we can also be selective about which attributes need to animate
74 /// over time, for substantial data reduction in many cases.
75 ///
76 /// Note that PointInstancer is \em not a Gprim, since it is not a graphical
77 /// primitive by any stretch of the imagination. It \em is, however,
78 /// Boundable, since we will sometimes want to treat the entire PointInstancer
79 /// similarly to a procedural, from the perspective of inclusion or framing.
80 ///
81 /// \section UsdGeomPointInstancer_varyingTopo Varying Instance Identity over Time
82 ///
83 /// PointInstancers originating from simulations often have the characteristic
84 /// that points/instances are "born", move around for some time period, and then
85 /// die (or leave the area of interest). In such cases, billions of instances
86 /// may be birthed over time, while at any \em specific time, only a much
87 /// smaller number are actually alive.  To encode this situation efficiently,
88 /// the simulator may re-use indices in the instance arrays, when a particle
89 /// dies, its index will be taken over by a new particle that may be birthed in
90 /// a much different location.  This presents challenges both for
91 /// identity-tracking, and for motion-blur.
92 ///
93 /// We facilitate identity tracking by providing an optional, animatable
94 /// \em ids attribute, that specifies the 64 bit integer ID of the particle
95 /// at each index, at each point in time.  If the simulator keeps monotonically
96 /// increasing a particle-count each time a new particle is birthed, it will
97 /// serve perfectly as particle \em ids.
98 ///
99 /// We facilitate motion blur for varying-topology particle streams by
100 /// optionally allowing per-instance \em velocities and \em angularVelocities
101 /// to be authored.  If instance transforms are requested at a time between
102 /// samples and either of the velocity attributes is authored, then we will
103 /// not attempt to interpolate samples of \em positions or \em orientations.
104 /// If not authored, and the bracketing samples have the same length, then we
105 /// will interpolate.
106 ///
107 /// \section UsdGeomPointInstancer_transform Computing an Instance Transform
108 ///
109 /// Each instance's transformation is a combination of the SRT affine transform
110 /// described by its scale, orientation, and position, applied \em after
111 /// (i.e. less locally) than the transformation computed at the root of the
112 /// prototype it is instancing.  In other words, to put an instance of a
113 /// PointInstancer into the space of the PointInstancer's parent prim:
114 ///
115 /// 1. Apply (most locally) the authored transformation for
116 /// <em>prototypes[protoIndices[i]]</em>
117 /// 2. If *scales* is authored, next apply the scaling matrix from *scales[i]*
118 /// 3. If *orientations* is authored: **if *angularVelocities* is authored**,
119 /// first multiply *orientations[i]* by the unit quaternion derived by scaling
120 /// *angularVelocities[i]* by the \ref UsdGeom_PITimeScaling "time differential"
121 /// from the left-bracketing timeSample for *orientation* to the requested
122 /// evaluation time *t*, storing the result in *R*, **else** assign *R*
123 /// directly from *orientations[i]*.  Apply the rotation matrix derived
124 /// from *R*.
125 /// 4. Apply the translation derived from *positions[i]*. If *velocities* is
126 /// authored, apply the translation deriving from *velocities[i]* scaled by
127 /// the time differential from the left-bracketing timeSample for *positions*
128 /// to the requested evaluation time *t*.
129 /// 5. Least locally, apply the transformation authored on the PointInstancer
130 /// prim itself (or the UsdGeomImageable::ComputeLocalToWorldTransform() of the
131 /// PointInstancer to put the instance directly into world space)
132 ///
133 /// If neither *velocities* nor *angularVelocities* are authored, we fallback to
134 /// standard position and orientation computation logic (using linear
135 /// interpolation between timeSamples) as described by
136 /// \ref UsdGeom_VelocityInterpolation .
137 ///
138 /// \anchor UsdGeom_PITimeScaling
139 /// <b>Scaling Velocities for Interpolation</b>
140 ///
141 /// When computing time-differentials by which to apply velocity or
142 /// angularVelocity to positions or orientations, we must scale by
143 /// ( 1.0 / UsdStage::GetTimeCodesPerSecond() ), because velocities are recorded
144 /// in units/second, while we are interpolating in UsdTimeCode ordinates.
145 ///
146 /// Additionally, if *motion:velocityScale* is authored or inherited (see
147 /// UsdGeomMotionAPI::ComputeVelocityScale()), it is used to scale both the
148 /// velocity and angular velocity by a constant value during computation. The
149 /// *motion:velocityScale* attribute is encoded by UsdGeomMotionAPI.
150 ///
151 /// We provide both high and low-level API's for dealing with the
152 /// transformation as a matrix, both will compute the instance matrices using
153 /// multiple threads; the low-level API allows the client to cache unvarying
154 /// inputs so that they need not be read duplicately when computing over
155 /// time.
156 ///
157 /// See also \ref UsdGeom_VelocityInterpolation .
158 ///
159 /// \section UsdGeomPointInstancer_primvars Primvars on PointInstancer
160 ///
161 /// \ref UsdGeomPrimvar "Primvars" authored on a PointInstancer prim should
162 /// always be applied to each instance with \em constant interpolation at
163 /// the root of the instance.  When you are authoring primvars on a
164 /// PointInstancer, think about it as if you were authoring them on a
165 /// point-cloud (e.g. a UsdGeomPoints gprim).  The same
166 /// <A HREF="http://renderman.pixar.com/resources/current/rps/appnote.22.html#classSpecifiers">interpolation rules for points</A> apply here, substituting
167 /// "instance" for "point".
168 ///
169 /// In other words, the (constant) value extracted for each instance
170 /// from the authored primvar value depends on the authored \em interpolation
171 /// and \em elementSize of the primvar, as follows:
172 /// \li <b>constant</b> or <b>uniform</b> : the entire authored value of the
173 /// primvar should be applied exactly to each instance.
174 /// \li <b>varying</b>, <b>vertex</b>, or <b>faceVarying</b>: the first
175 /// \em elementSize elements of the authored primvar array should be assigned to
176 /// instance zero, the second \em elementSize elements should be assigned to
177 /// instance one, and so forth.
178 ///
179 ///
180 /// \section UsdGeomPointInstancer_masking Masking Instances: "Deactivating" and Invising
181 ///
182 /// Often a PointInstancer is created "upstream" in a graphics pipeline, and
183 /// the needs of "downstream" clients necessitate eliminating some of the
184 /// instances from further consideration.  Accomplishing this pruning by
185 /// re-authoring all of the per-instance attributes is not very attractive,
186 /// since it may mean destructively editing a large quantity of data.  We
187 /// therefore provide means of "masking" instances by ID, such that the
188 /// instance data is unmolested, but per-instance transform and primvar data
189 /// can be retrieved with the no-longer-desired instances eliminated from the
190 /// (smaller) arrays.  PointInstancer allows two independent means of masking
191 /// instances by ID, each with different features that meet the needs of
192 /// various clients in a pipeline.  Both pruning features' lists of ID's are
193 /// combined to produce the mask returned by ComputeMaskAtTime().
194 ///
195 /// \note If a PointInstancer has no authored \em ids attribute, the masking
196 /// features will still be available, with the integers specifying element
197 /// position in the \em protoIndices array rather than ID.
198 ///
199 /// \subsection UsdGeomPointInstancer_inactiveIds InactiveIds: List-edited, Unvarying Masking
200 ///
201 /// The first masking feature encodes a list of IDs in a list-editable metadatum
202 /// called \em inactiveIds, which, although it does not have any similar
203 /// impact to stage population as \ref UsdPrim::SetActive() "prim activation",
204 /// it shares with that feature that its application is uniform over all time.
205 /// Because it is list-editable, we can \em sparsely add and remove instances
206 /// from it in many layers.
207 ///
208 /// This sparse application pattern makes \em inactiveIds a good choice when
209 /// further downstream clients may need to reverse masking decisions made
210 /// upstream, in a manner that is robust to many kinds of future changes to
211 /// the upstream data.
212 ///
213 /// See ActivateId(), ActivateIds(), DeactivateId(), DeactivateIds(),
214 /// ActivateAllIds()
215 ///
216 /// \subsection UsdGeomPointInstancer_invisibleIds invisibleIds: Animatable Masking
217 ///
218 /// The second masking feature encodes a list of IDs in a time-varying
219 /// Int64Array-valued UsdAttribute called \em invisibleIds , since it shares
220 /// with \ref UsdGeomImageable::GetVisibilityAttr() "Imageable visibility"
221 /// the ability to animate object visibility.
222 ///
223 /// Unlike \em inactiveIds, overriding a set of opinions for \em invisibleIds
224 /// is not at all straightforward, because one will, in general need to
225 /// reauthor (in the overriding layer) **all** timeSamples for the attribute
226 /// just to change one Id's visibility state, so it cannot be authored
227 /// sparsely.  But it can be a very useful tool for situations like encoding
228 /// pre-computed camera-frustum culling of geometry when either or both of
229 /// the instances or the camera is animated.
230 ///
231 /// See VisId(), VisIds(), InvisId(), InvisIds(), VisAllIds()
232 ///
233 /// \section UsdGeomPointInstancer_protoProcessing Processing and Not Processing Prototypes
234 ///
235 /// Any prim in the scenegraph can be targeted as a prototype by the
236 /// \em prototypes relationship.  We do not, however, provide a specific
237 /// mechanism for identifying prototypes as geometry that should not be drawn
238 /// (or processed) in their own, local spaces in the scenegraph.  We
239 /// encourage organizing all prototypes as children of the PointInstancer
240 /// prim that consumes them, and pruning "raw" processing and drawing
241 /// traversals when they encounter a PointInstancer prim; this is what the
242 /// UsdGeomBBoxCache and UsdImaging engines do.
243 ///
244 /// There \em is a pattern one can deploy for organizing the prototypes
245 /// such that they will automatically be skipped by basic UsdPrim::GetChildren()
246 /// or UsdPrimRange traversals.  Usd prims each have a
247 /// \ref Usd_PrimSpecifiers "specifier" of "def", "over", or "class".  The
248 /// default traversals skip over prims that are "pure overs" or classes.  So
249 /// to protect prototypes from all generic traversals and processing, place
250 /// them under a prim that is just an "over".  For example,
251 /// \code
252 /// 01 def PointInstancer "Crowd_Mid"
253 /// 02 {
254 /// 03     rel prototypes = [ </Crowd_Mid/Prototypes/MaleThin_Business>, </Crowd_Mid/Prototypes/MaleTine_Casual> ]
255 /// 04
256 /// 05     over "Prototypes"
257 /// 06     {
258 /// 07          def "MaleThin_Business" (
259 /// 08              references = [@MaleGroupA/usd/MaleGroupA.usd@</MaleGroupA>]
260 /// 09              variants = {
261 /// 10                  string modelingVariant = "Thin"
262 /// 11                  string costumeVariant = "BusinessAttire"
263 /// 12              }
264 /// 13          )
265 /// 14          { ... }
266 /// 15
267 /// 16          def "MaleThin_Casual"
268 /// 17          ...
269 /// 18     }
270 /// 19 }
271 /// \endcode
272 ///
273 ///
274 class UsdGeomPointInstancer : public UsdGeomBoundable
275 {
276 public:
277     /// Compile time constant representing what kind of schema this class is.
278     ///
279     /// \sa UsdSchemaKind
280     static const UsdSchemaKind schemaKind = UsdSchemaKind::ConcreteTyped;
281 
282     /// Construct a UsdGeomPointInstancer on UsdPrim \p prim .
283     /// Equivalent to UsdGeomPointInstancer::Get(prim.GetStage(), prim.GetPath())
284     /// for a \em valid \p prim, but will not immediately throw an error for
285     /// an invalid \p prim
286     explicit UsdGeomPointInstancer(const UsdPrim& prim=UsdPrim())
UsdGeomBoundable(prim)287         : UsdGeomBoundable(prim)
288     {
289     }
290 
291     /// Construct a UsdGeomPointInstancer on the prim held by \p schemaObj .
292     /// Should be preferred over UsdGeomPointInstancer(schemaObj.GetPrim()),
293     /// as it preserves SchemaBase state.
UsdGeomPointInstancer(const UsdSchemaBase & schemaObj)294     explicit UsdGeomPointInstancer(const UsdSchemaBase& schemaObj)
295         : UsdGeomBoundable(schemaObj)
296     {
297     }
298 
299     /// Destructor.
300     USDGEOM_API
301     virtual ~UsdGeomPointInstancer();
302 
303     /// Return a vector of names of all pre-declared attributes for this schema
304     /// class and all its ancestor classes.  Does not include attributes that
305     /// may be authored by custom/extended methods of the schemas involved.
306     USDGEOM_API
307     static const TfTokenVector &
308     GetSchemaAttributeNames(bool includeInherited=true);
309 
310     /// Return a UsdGeomPointInstancer holding the prim adhering to this
311     /// schema at \p path on \p stage.  If no prim exists at \p path on
312     /// \p stage, or if the prim at that path does not adhere to this schema,
313     /// return an invalid schema object.  This is shorthand for the following:
314     ///
315     /// \code
316     /// UsdGeomPointInstancer(stage->GetPrimAtPath(path));
317     /// \endcode
318     ///
319     USDGEOM_API
320     static UsdGeomPointInstancer
321     Get(const UsdStagePtr &stage, const SdfPath &path);
322 
323     /// Attempt to ensure a \a UsdPrim adhering to this schema at \p path
324     /// is defined (according to UsdPrim::IsDefined()) on this stage.
325     ///
326     /// If a prim adhering to this schema at \p path is already defined on this
327     /// stage, return that prim.  Otherwise author an \a SdfPrimSpec with
328     /// \a specifier == \a SdfSpecifierDef and this schema's prim type name for
329     /// the prim at \p path at the current EditTarget.  Author \a SdfPrimSpec s
330     /// with \p specifier == \a SdfSpecifierDef and empty typeName at the
331     /// current EditTarget for any nonexistent, or existing but not \a Defined
332     /// ancestors.
333     ///
334     /// The given \a path must be an absolute prim path that does not contain
335     /// any variant selections.
336     ///
337     /// If it is impossible to author any of the necessary PrimSpecs, (for
338     /// example, in case \a path cannot map to the current UsdEditTarget's
339     /// namespace) issue an error and return an invalid \a UsdPrim.
340     ///
341     /// Note that this method may return a defined prim whose typeName does not
342     /// specify this schema class, in case a stronger typeName opinion overrides
343     /// the opinion at the current EditTarget.
344     ///
345     USDGEOM_API
346     static UsdGeomPointInstancer
347     Define(const UsdStagePtr &stage, const SdfPath &path);
348 
349 protected:
350     /// Returns the kind of schema this class belongs to.
351     ///
352     /// \sa UsdSchemaKind
353     USDGEOM_API
354     UsdSchemaKind _GetSchemaKind() const override;
355 
356 private:
357     // needs to invoke _GetStaticTfType.
358     friend class UsdSchemaRegistry;
359     USDGEOM_API
360     static const TfType &_GetStaticTfType();
361 
362     static bool _IsTypedSchema();
363 
364     // override SchemaBase virtuals.
365     USDGEOM_API
366     const TfType &_GetTfType() const override;
367 
368 public:
369     // --------------------------------------------------------------------- //
370     // PROTOINDICES
371     // --------------------------------------------------------------------- //
372     /// <b>Required property</b>. Per-instance index into
373     /// \em prototypes relationship that identifies what geometry should be
374     /// drawn for each instance.  <b>Topology attribute</b> - can be animated,
375     /// but at a potential performance impact for streaming.
376     ///
377     /// | ||
378     /// | -- | -- |
379     /// | Declaration | `int[] protoIndices` |
380     /// | C++ Type | VtArray<int> |
381     /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->IntArray |
382     USDGEOM_API
383     UsdAttribute GetProtoIndicesAttr() const;
384 
385     /// See GetProtoIndicesAttr(), and also
386     /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create.
387     /// If specified, author \p defaultValue as the attribute's default,
388     /// sparsely (when it makes sense to do so) if \p writeSparsely is \c true -
389     /// the default for \p writeSparsely is \c false.
390     USDGEOM_API
391     UsdAttribute CreateProtoIndicesAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const;
392 
393 public:
394     // --------------------------------------------------------------------- //
395     // IDS
396     // --------------------------------------------------------------------- //
397     /// Ids are optional; if authored, the ids array should be the same
398     /// length as the \em protoIndices array, specifying (at each timeSample if
399     /// instance identities are changing) the id of each instance. The
400     /// type is signed intentionally, so that clients can encode some
401     /// binary state on Id'd instances without adding a separate primvar.
402     /// See also \ref UsdGeomPointInstancer_varyingTopo
403     ///
404     /// | ||
405     /// | -- | -- |
406     /// | Declaration | `int64[] ids` |
407     /// | C++ Type | VtArray<int64_t> |
408     /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Int64Array |
409     USDGEOM_API
410     UsdAttribute GetIdsAttr() const;
411 
412     /// See GetIdsAttr(), and also
413     /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create.
414     /// If specified, author \p defaultValue as the attribute's default,
415     /// sparsely (when it makes sense to do so) if \p writeSparsely is \c true -
416     /// the default for \p writeSparsely is \c false.
417     USDGEOM_API
418     UsdAttribute CreateIdsAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const;
419 
420 public:
421     // --------------------------------------------------------------------- //
422     // POSITIONS
423     // --------------------------------------------------------------------- //
424     /// <b>Required property</b>. Per-instance position.  See also
425     /// \ref UsdGeomPointInstancer_transform .
426     ///
427     /// | ||
428     /// | -- | -- |
429     /// | Declaration | `point3f[] positions` |
430     /// | C++ Type | VtArray<GfVec3f> |
431     /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Point3fArray |
432     USDGEOM_API
433     UsdAttribute GetPositionsAttr() const;
434 
435     /// See GetPositionsAttr(), and also
436     /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create.
437     /// If specified, author \p defaultValue as the attribute's default,
438     /// sparsely (when it makes sense to do so) if \p writeSparsely is \c true -
439     /// the default for \p writeSparsely is \c false.
440     USDGEOM_API
441     UsdAttribute CreatePositionsAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const;
442 
443 public:
444     // --------------------------------------------------------------------- //
445     // ORIENTATIONS
446     // --------------------------------------------------------------------- //
447     /// If authored, per-instance orientation of each instance about its
448     /// prototype's origin, represented as a unit length quaternion, which
449     /// allows us to encode it with sufficient precision in a compact GfQuath.
450     ///
451     /// It is client's responsibility to ensure that authored quaternions are
452     /// unit length; the convenience API below for authoring orientations from
453     /// rotation matrices will ensure that quaternions are unit length, though
454     /// it will not make any attempt to select the "better (for interpolation
455     /// with respect to neighboring samples)" of the two possible quaternions
456     /// that encode the rotation.
457     ///
458     /// See also \ref UsdGeomPointInstancer_transform .
459     ///
460     /// | ||
461     /// | -- | -- |
462     /// | Declaration | `quath[] orientations` |
463     /// | C++ Type | VtArray<GfQuath> |
464     /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->QuathArray |
465     USDGEOM_API
466     UsdAttribute GetOrientationsAttr() const;
467 
468     /// See GetOrientationsAttr(), and also
469     /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create.
470     /// If specified, author \p defaultValue as the attribute's default,
471     /// sparsely (when it makes sense to do so) if \p writeSparsely is \c true -
472     /// the default for \p writeSparsely is \c false.
473     USDGEOM_API
474     UsdAttribute CreateOrientationsAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const;
475 
476 public:
477     // --------------------------------------------------------------------- //
478     // SCALES
479     // --------------------------------------------------------------------- //
480     /// If authored, per-instance scale to be applied to
481     /// each instance, before any rotation is applied.
482     ///
483     /// See also \ref UsdGeomPointInstancer_transform .
484     ///
485     /// | ||
486     /// | -- | -- |
487     /// | Declaration | `float3[] scales` |
488     /// | C++ Type | VtArray<GfVec3f> |
489     /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Float3Array |
490     USDGEOM_API
491     UsdAttribute GetScalesAttr() const;
492 
493     /// See GetScalesAttr(), and also
494     /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create.
495     /// If specified, author \p defaultValue as the attribute's default,
496     /// sparsely (when it makes sense to do so) if \p writeSparsely is \c true -
497     /// the default for \p writeSparsely is \c false.
498     USDGEOM_API
499     UsdAttribute CreateScalesAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const;
500 
501 public:
502     // --------------------------------------------------------------------- //
503     // VELOCITIES
504     // --------------------------------------------------------------------- //
505     /// If provided, per-instance 'velocities' will be used to
506     /// compute positions between samples for the 'positions' attribute,
507     /// rather than interpolating between neighboring 'positions' samples.
508     /// Velocities should be considered mandatory if both \em protoIndices
509     /// and \em positions are animated.  Velocity is measured in position
510     /// units per second, as per most simulation software. To convert to
511     /// position units per UsdTimeCode, divide by
512     /// UsdStage::GetTimeCodesPerSecond().
513     ///
514     /// See also \ref UsdGeomPointInstancer_transform,
515     /// \ref UsdGeom_VelocityInterpolation .
516     ///
517     /// | ||
518     /// | -- | -- |
519     /// | Declaration | `vector3f[] velocities` |
520     /// | C++ Type | VtArray<GfVec3f> |
521     /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Vector3fArray |
522     USDGEOM_API
523     UsdAttribute GetVelocitiesAttr() const;
524 
525     /// See GetVelocitiesAttr(), and also
526     /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create.
527     /// If specified, author \p defaultValue as the attribute's default,
528     /// sparsely (when it makes sense to do so) if \p writeSparsely is \c true -
529     /// the default for \p writeSparsely is \c false.
530     USDGEOM_API
531     UsdAttribute CreateVelocitiesAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const;
532 
533 public:
534     // --------------------------------------------------------------------- //
535     // ACCELERATIONS
536     // --------------------------------------------------------------------- //
537     /// If authored, per-instance 'accelerations' will be used with
538     /// velocities to compute positions between samples for the 'positions'
539     /// attribute rather than interpolating between neighboring 'positions'
540     /// samples. Acceleration is measured in position units per second-squared.
541     /// To convert to position units per squared UsdTimeCode, divide by the
542     /// square of UsdStage::GetTimeCodesPerSecond().
543     ///
544     /// | ||
545     /// | -- | -- |
546     /// | Declaration | `vector3f[] accelerations` |
547     /// | C++ Type | VtArray<GfVec3f> |
548     /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Vector3fArray |
549     USDGEOM_API
550     UsdAttribute GetAccelerationsAttr() const;
551 
552     /// See GetAccelerationsAttr(), and also
553     /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create.
554     /// If specified, author \p defaultValue as the attribute's default,
555     /// sparsely (when it makes sense to do so) if \p writeSparsely is \c true -
556     /// the default for \p writeSparsely is \c false.
557     USDGEOM_API
558     UsdAttribute CreateAccelerationsAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const;
559 
560 public:
561     // --------------------------------------------------------------------- //
562     // ANGULARVELOCITIES
563     // --------------------------------------------------------------------- //
564     /// If authored, per-instance angular velocity vector to be used for
565     /// interoplating orientations.  Angular velocities should be considered
566     /// mandatory if both \em protoIndices and \em orientations are animated.
567     /// Angular velocity is measured in <b>degrees</b> per second. To convert
568     /// to degrees per UsdTimeCode, divide by
569     /// UsdStage::GetTimeCodesPerSecond().
570     ///
571     /// See also \ref UsdGeomPointInstancer_transform .
572     ///
573     /// | ||
574     /// | -- | -- |
575     /// | Declaration | `vector3f[] angularVelocities` |
576     /// | C++ Type | VtArray<GfVec3f> |
577     /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Vector3fArray |
578     USDGEOM_API
579     UsdAttribute GetAngularVelocitiesAttr() const;
580 
581     /// See GetAngularVelocitiesAttr(), and also
582     /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create.
583     /// If specified, author \p defaultValue as the attribute's default,
584     /// sparsely (when it makes sense to do so) if \p writeSparsely is \c true -
585     /// the default for \p writeSparsely is \c false.
586     USDGEOM_API
587     UsdAttribute CreateAngularVelocitiesAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const;
588 
589 public:
590     // --------------------------------------------------------------------- //
591     // INVISIBLEIDS
592     // --------------------------------------------------------------------- //
593     /// A list of id's to make invisible at the evaluation time.
594     /// See \ref UsdGeomPointInstancer_invisibleIds .
595     ///
596     /// | ||
597     /// | -- | -- |
598     /// | Declaration | `int64[] invisibleIds = []` |
599     /// | C++ Type | VtArray<int64_t> |
600     /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Int64Array |
601     USDGEOM_API
602     UsdAttribute GetInvisibleIdsAttr() const;
603 
604     /// See GetInvisibleIdsAttr(), and also
605     /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create.
606     /// If specified, author \p defaultValue as the attribute's default,
607     /// sparsely (when it makes sense to do so) if \p writeSparsely is \c true -
608     /// the default for \p writeSparsely is \c false.
609     USDGEOM_API
610     UsdAttribute CreateInvisibleIdsAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const;
611 
612 public:
613     // --------------------------------------------------------------------- //
614     // PROTOTYPES
615     // --------------------------------------------------------------------- //
616     /// <b>Required property</b>. Orders and targets the prototype root
617     /// prims, which can be located anywhere in the scenegraph that is convenient,
618     /// although we promote organizing prototypes as children of the
619     /// PointInstancer.  The position of a prototype in this relationship defines
620     /// the value an instance would specify in the \em protoIndices attribute to
621     /// instance that prototype. Since relationships are uniform, this property
622     /// cannot be animated.
623     ///
624     USDGEOM_API
625     UsdRelationship GetPrototypesRel() const;
626 
627     /// See GetPrototypesRel(), and also
628     /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create
629     USDGEOM_API
630     UsdRelationship CreatePrototypesRel() const;
631 
632 public:
633     // ===================================================================== //
634     // Feel free to add custom code below this line, it will be preserved by
635     // the code generator.
636     //
637     // Just remember to:
638     //  - Close the class declaration with };
639     //  - Close the namespace with PXR_NAMESPACE_CLOSE_SCOPE
640     //  - Close the include guard with #endif
641     // ===================================================================== //
642     // --(BEGIN CUSTOM CODE)--
643 
644     // --------------------------------------------------------------------- //
645     /// \name Id-based Instance Masking/Pruning
646     /// See \ref UsdGeomPointInstancer_masking
647     /// @{
648     // --------------------------------------------------------------------- //
649 
650     /// Ensure that the instance identified by \p id is active over all time.
651     /// This activation is encoded sparsely, affecting no other instances.
652     ///
653     /// This does not guarantee that the instance will be rendered, because
654     /// it may still be "invisible" due to \p id being present in the
655     /// \em invisibleIds attribute (see VisId(), InvisId())
656     USDGEOM_API
657     bool ActivateId(int64_t id) const;
658 
659     /// Ensure that the instances identified by \p ids are active over all time.
660     /// This activation is encoded sparsely, affecting no other instances.
661     ///
662     /// This does not guarantee that the instances will be rendered, because
663     /// each may still be "invisible" due to its presence in the
664     /// \em invisibleIds attribute (see VisId(), InvisId())
665     USDGEOM_API
666     bool ActivateIds(VtInt64Array const &ids) const;
667 
668     /// Ensure that all instances are active over all time.
669     ///
670     /// This does not guarantee that the instances will be rendered, because
671     /// each may still be "invisible" due to its presence in the
672     /// \em invisibleIds attribute (see VisId(), InvisId())
673     USDGEOM_API
674     bool ActivateAllIds() const;
675 
676     /// Ensure that the instance identified by \p id is inactive over all time.
677     /// This deactivation is encoded sparsely, affecting no other instances.
678     ///
679     /// A deactivated instance is guaranteed not to render if the renderer
680     /// honors masking.
681     USDGEOM_API
682     bool DeactivateId(int64_t id) const;
683 
684     /// Ensure that the instances identified by \p ids are inactive over all time.
685     /// This deactivation is encoded sparsely, affecting no other instances.
686     ///
687     /// A deactivated instance is guaranteed not to render if the renderer
688     /// honors masking.
689     USDGEOM_API
690     bool DeactivateIds(VtInt64Array const &ids) const;
691 
692 
693     /// Ensure that the instance identified by \p id is visible at \p time.
694     /// This will cause \em invisibleIds to first be broken down (keyed)
695     /// at \p time, causing all animation in weaker layers that the current
696     /// UsdEditTarget to be overridden.  Has no effect on any timeSamples other
697     /// than the one at \p time.  If the \em invisibleIds attribute is not
698     /// authored or is blocked, this operation is a no-op.
699     ///
700     /// This does not guarantee that the instance will be rendered, because
701     /// it may still be "inactive" due to \p id being present in the
702     /// \em inactivevIds metadata (see ActivateId(), DeactivateId())
703     USDGEOM_API
704     bool VisId(int64_t id, UsdTimeCode const &time) const;
705 
706     /// Ensure that the instances identified by \p ids are visible at \p time.
707     /// This will cause \em invisibleIds to first be broken down (keyed)
708     /// at \p time, causing all animation in weaker layers that the current
709     /// UsdEditTarget to be overridden.  Has no effect on any timeSamples other
710     /// than the one at \p time.  If the \em invisibleIds attribute is not
711     /// authored or is blocked, this operation is a no-op.
712     ///
713     /// This does not guarantee that the instances will be rendered, because
714     /// each may still be "inactive" due to \p id being present in the
715     /// \em inactivevIds metadata (see ActivateId(), DeactivateId())
716     USDGEOM_API
717     bool VisIds(VtInt64Array const &ids, UsdTimeCode const &time) const;
718 
719     /// Ensure that all instances are visible at \p time.
720     /// Operates by authoring an empty array at \p time.
721     ///
722     /// This does not guarantee that the instances will be rendered, because
723     /// each may still be "inactive" due to its id being present in the
724     /// \em inactivevIds metadata (see ActivateId(), DeactivateId())
725     USDGEOM_API
726     bool VisAllIds(UsdTimeCode const &time) const;
727 
728     /// Ensure that the instance identified by \p id is invisible at \p time.
729     /// This will cause \em invisibleIds to first be broken down (keyed)
730     /// at \p time, causing all animation in weaker layers that the current
731     /// UsdEditTarget to be overridden.  Has no effect on any timeSamples other
732     /// than the one at \p time.
733     ///
734     /// An invised instance is guaranteed not to render if the renderer
735     /// honors masking.
736     USDGEOM_API
737     bool InvisId(int64_t id, UsdTimeCode const &time) const;
738 
739     /// Ensure that the instances identified by \p ids are invisible at \p time.
740     /// This will cause \em invisibleIds to first be broken down (keyed)
741     /// at \p time, causing all animation in weaker layers that the current
742     /// UsdEditTarget to be overridden.  Has no effect on any timeSamples other
743     /// than the one at \p time.
744     ///
745     /// An invised instance is guaranteed not to render if the renderer
746     /// honors masking.
747     USDGEOM_API
748     bool InvisIds(VtInt64Array const &ids, UsdTimeCode const &time) const;
749 
750     /// Computes a presence mask to be applied to per-instance data arrays
751     /// based on authored \em inactiveIds, \em invisibleIds, and \em ids .
752     ///
753     /// If no \em ids attribute has been authored, then the values in
754     /// \em inactiveIds and \em invisibleIds will be interpreted directly
755     /// as indices of \em protoIndices .
756     ///
757     /// If \p ids is non-NULL, it is assumed to be the id-mapping to apply,
758     /// and must match the length of \em protoIndices at \p time .
759     /// If NULL, we will call GetIdsAttr().Get(time)
760     ///
761     /// \note If all "live" instances at UsdTimeCode \p time pass the mask,
762     /// we will return an <b>empty</b> mask so that clients can trivially
763     /// recognize the common "no masking" case.
764     ///
765     /// The returned mask can be used with ApplyMaskToArray(), and will contain
766     /// a \c true value for every element that should survive.
767     USDGEOM_API
768     std::vector<bool> ComputeMaskAtTime(UsdTimeCode time,
769                                         VtInt64Array const *ids = nullptr) const;
770 
771     /// Contract \p dataArray in-place to contain only the elements whose
772     /// index in \p mask is \c true.
773     ///
774     /// \note an empty \p mask specifies "all pass", in which case \p dataArray
775     /// is trivially unmodified
776     ///
777     ///  - It is an error for \p dataArray to be NULL .
778     ///  - If \em elementSize times \em mask.size() does not equal
779     ///  \em dataArray->size(), warn and fail.
780     ///
781     /// \return true on success, false on failure.
782     /// \sa ComputeMaskAtTime()
783     template <class T>
784     static bool ApplyMaskToArray(std::vector<bool> const &mask,
785                           VtArray<T> *dataArray,
786                           const int elementSize = 1);
787 
788     // --------------------------------------------------------------------- //
789     /// @}
790     // --------------------------------------------------------------------- //
791 
792     /// \enum ProtoXformInclusion
793     ///
794     /// Encodes whether to include each prototype's root prim's transformation
795     /// as the most-local component of computed instance transforms.
796     enum ProtoXformInclusion {
797         IncludeProtoXform, //!< Include the transform on the proto's root
798         ExcludeProtoXform  //!< Exclude the transform on the proto's root
799     };
800 
801 
802     /// \enum MaskApplication
803     ///
804     /// Encodes whether to evaluate and apply the PointInstancer's
805     /// mask to computed results.
806     /// \sa ComputeMaskAtTime()
807     enum MaskApplication {
808         ApplyMask,    //!< Compute and apply the PointInstancer mask
809         IgnoreMask    //!< Ignore the PointInstancer mask
810     };
811 
812 
813     /// Compute the per-instance, "PointInstancer relative" transforms given
814     /// the positions, scales, orientations, velocities and angularVelocities
815     /// at \p time, as described in \ref UsdGeomPointInstancer_transform .
816     ///
817     /// This will return \c false and leave \p xforms untouched if:
818     /// - \p xforms is NULL
819     /// - one of \p time and \p baseTime is numeric and the other is
820     ///   UsdTimeCode::Default() (they must either both be numeric or both be
821     ///   default)
822     /// - there is no authored \em protoIndices attribute or \em positions
823     ///   attribute
824     /// - the size of any of the per-instance attributes does not match the
825     ///   size of \em protoIndices
826     /// - \p doProtoXforms is \c IncludeProtoXform but an index value in
827     ///   \em protoIndices is outside the range [0, prototypes.size())
828     /// - \p applyMask is \c ApplyMask and a mask is set but the size of the
829     ///   mask does not match the size of \em protoIndices.
830     ///
831     /// If there is no error, we will return \c true and \p xforms will contain
832     /// the computed transformations.
833     ///
834     /// \param xforms - the out parameter for the transformations.  Its size
835     ///                 will depend on the authored data and \p applyMask
836     /// \param time - UsdTimeCode at which we want to evaluate the transforms
837     /// \param baseTime - required for correct interpolation between samples
838     ///                   when \em velocities or \em angularVelocities are
839     ///                   present. If there are samples for \em positions and
840     ///                   \em velocities at t1 and t2, normal value resolution
841     ///                   would attempt to interpolate between the two samples,
842     ///                   and if they could not be interpolated because they
843     ///                   differ in size (common in cases where velocity is
844     ///                   authored), will choose the sample at t1.  When
845     ///                   sampling for the purposes of motion-blur, for example,
846     ///                   it is common, when rendering the frame at t2, to
847     ///                   sample at [ t2-shutter/2, t2+shutter/2 ] for a
848     ///                   shutter interval of \em shutter.  The first sample
849     ///                   falls between t1 and t2, but we must sample at t2
850     ///                   and apply velocity-based interpolation based on those
851     ///                   samples to get a correct result.  In such scenarios,
852     ///                   one should provide a \p baseTime of t2 when querying
853     ///                   \em both samples. If your application does not care
854     ///                   about off-sample interpolation, it can supply the
855     ///                   same value for \p baseTime that it does for \p time.
856     ///                   When \p baseTime is less than or equal to \p time,
857     ///                   we will choose the lower bracketing timeSample.
858     ///                   Selecting sample times with respect to baseTime will
859     ///                   be performed independently for positions and
860     ///                   orientations.
861     /// \param doProtoXforms - specifies whether to include the root
862     ///                   transformation of each instance's prototype in the
863     ///                   instance's transform.  Default is to include it, but
864     ///                   some clients may want to apply the proto transform as
865     ///                   part of the prototype itself, so they can specify
866     ///                   \c ExcludeProtoXform instead.
867     /// \param applyMask - specifies whether to apply ApplyMaskToArray() to the
868     ///                    computed result.  The default is \c ApplyMask.
869     USDGEOM_API
870     bool
871     ComputeInstanceTransformsAtTime(
872         VtArray<GfMatrix4d>* xforms,
873         const UsdTimeCode time,
874         const UsdTimeCode baseTime,
875         const ProtoXformInclusion doProtoXforms = IncludeProtoXform,
876         const MaskApplication applyMask = ApplyMask) const;
877 
878     /// Compute the per-instance transforms as in
879     /// ComputeInstanceTransformsAtTime, but using multiple sample times. An
880     /// array of matrix arrays is returned where each matrix array contains the
881     /// instance transforms for the corresponding time in \p times .
882     ///
883     /// \param times - A vector containing the UsdTimeCodes at which we want to
884     ///                sample.
885     USDGEOM_API
886     bool
887     ComputeInstanceTransformsAtTimes(
888         std::vector<VtArray<GfMatrix4d>>* xformsArray,
889         const std::vector<UsdTimeCode>& times,
890         const UsdTimeCode baseTime,
891         const ProtoXformInclusion doProtoXforms = IncludeProtoXform,
892         const MaskApplication applyMask = ApplyMask) const;
893 
894     /// \overload
895     /// Perform the per-instance transform computation as described in
896     /// \ref UsdGeomPointInstancer_transform . This does the same computation as
897     /// the non-static ComputeInstanceTransformsAtTime method, but takes all
898     /// data as parameters rather than accessing authored data.
899     ///
900     /// \param xforms - the out parameter for the transformations.  Its size
901     ///                 will depend on the given data and \p applyMask
902     /// \param stage - the UsdStage
903     /// \param time - time at which we want to evaluate the transforms
904     /// \param protoIndices - array containing all instance prototype indices.
905     /// \param positions - array containing all instance positions. This array
906     ///                    must be the same size as \p protoIndices .
907     /// \param velocities - array containing all instance velocities. This array
908     ///                     must be either the same size as \p protoIndices or
909     ///                     empty. If it is empty, transforms are computed as if
910     ///                     all velocities were zero in all dimensions.
911     /// \param velocitiesSampleTime - time at which the samples from
912     ///                               \p velocities were taken.
913     /// \param accelerations - array containing all instance accelerations.
914     ///                     This array must be either the same size as
915     ///                     \p protoIndicesor empty. If it is empty, transforms
916     ///                     are computed as if all accelerations were zero in
917     ///                     all dimensions.
918     /// \param scales - array containing all instance scales. This array must be
919     ///                 either the same size as \p protoIndices or empty. If it
920     ///                 is empty, transforms are computed with no change in
921     ///                 scale.
922     /// \param orientations - array containing all instance orientations. This
923     ///                       array must be either the same size as
924     ///                       \p protoIndices or empty. If it is empty,
925     ///                       transforms are computed with no change in
926     ///                       orientation
927     /// \param angularVelocities - array containing all instance angular
928     ///                            velocities. This array must be either the
929     ///                            same size as \p protoIndices or empty. If it
930     ///                            is empty, transforms are computed as if all
931     ///                            angular velocities were zero in all
932     ///                            dimensions.
933     /// \param angularVelocitiesSampleTime - time at which the samples from
934     ///                                      \p angularVelocities were taken.
935     /// \param protoPaths - array containing the paths for all instance
936     ///                     prototypes. If this array is not empty, prototype
937     ///                     transforms are applied to the instance transforms.
938     /// \param mask - vector containing a mask to apply to the computed result.
939     ///               This vector must be either the same size as
940     ///               \p protoIndices or empty. If it is empty, no mask is
941     ///               applied.
942     /// \param velocityScale - factor used to artificially increase the effect
943     ///                        of velocity and angular velocity on positions and
944     ///                        orientations respectively.
945     USDGEOM_API
946     static bool
947     ComputeInstanceTransformsAtTime(
948         VtArray<GfMatrix4d>* xforms,
949         UsdStageWeakPtr& stage,
950         UsdTimeCode time,
951         const VtIntArray& protoIndices,
952         const VtVec3fArray& positions,
953         const VtVec3fArray& velocities,
954         UsdTimeCode velocitiesSampleTime,
955         const VtVec3fArray& accelerations,
956         const VtVec3fArray& scales,
957         const VtQuathArray& orientations,
958         const VtVec3fArray& angularVelocities,
959         UsdTimeCode angularVelocitiesSampleTime,
960         const SdfPathVector& protoPaths,
961         const std::vector<bool>& mask,
962         float velocityScale = 1.0);
963 
964 private:
965 
966     // Get the authored prototype paths. Fail if there are no authored prototype
967     // paths or the prototype indices are out of bounds.
968     bool _GetPrototypePathsForInstanceTransforms(
969         const VtIntArray& protoIndices,
970         SdfPathVector* protoPaths) const;
971 
972     // Get the authored prototype indices for instance transform computation.
973     // Fail if prototype indices are not authored.
974     bool _GetProtoIndicesForInstanceTransforms(
975         UsdTimeCode baseTime,
976         VtIntArray* protoIndices) const;
977 
978     // Fetches data from attributes specific to UsdGeomPointInstancer
979     // required for instance transform calculations; this includes
980     // protoIndices, protoPaths, and the mask.
981     bool _ComputePointInstancerAttributesPreamble(
982         const UsdTimeCode baseTime,
983         const ProtoXformInclusion doProtoXforms,
984         const MaskApplication applyMask,
985         VtIntArray* protoIndices,
986         SdfPathVector* protoPaths,
987         std::vector<bool>* mask) const;
988 
989 public:
990 
991     /// Compute the extent of the point instancer based on the per-instance,
992     /// "PointInstancer relative" transforms at \p time, as described in
993     /// \ref UsdGeomPointInstancer_transform .
994     ///
995     /// If there is no error, we return \c true and \p extent will be the
996     /// tightest bounds we can compute efficiently.  If an error occurs,
997     /// \c false will be returned and \p extent will be left untouched.
998     ///
999     /// For now, this uses a UsdGeomBBoxCache with the "default", "proxy", and
1000     /// "render" purposes.
1001     ///
1002     /// \param extent - the out parameter for the extent.  On success, it will
1003     ///                 contain two elements representing the min and max.
1004     /// \param time - UsdTimeCode at which we want to evaluate the extent
1005     /// \param baseTime - required for correct interpolation between samples
1006     ///                   when \em velocities or \em angularVelocities are
1007     ///                   present. If there are samples for \em positions and
1008     ///                   \em velocities at t1 and t2, normal value resolution
1009     ///                   would attempt to interpolate between the two samples,
1010     ///                   and if they could not be interpolated because they
1011     ///                   differ in size (common in cases where velocity is
1012     ///                   authored), will choose the sample at t1.  When
1013     ///                   sampling for the purposes of motion-blur, for example,
1014     ///                   it is common, when rendering the frame at t2, to
1015     ///                   sample at [ t2-shutter/2, t2+shutter/2 ] for a
1016     ///                   shutter interval of \em shutter.  The first sample
1017     ///                   falls between t1 and t2, but we must sample at t2
1018     ///                   and apply velocity-based interpolation based on those
1019     ///                   samples to get a correct result.  In such scenarios,
1020     ///                   one should provide a \p baseTime of t2 when querying
1021     ///                   \em both samples. If your application does not care
1022     ///                   about off-sample interpolation, it can supply the
1023     ///                   same value for \p baseTime that it does for \p time.
1024     ///                   When \p baseTime is less than or equal to \p time,
1025     ///                   we will choose the lower bracketing timeSample.
1026     USDGEOM_API
1027     bool ComputeExtentAtTime(
1028                         VtVec3fArray* extent,
1029                         const UsdTimeCode time,
1030                         const UsdTimeCode baseTime) const;
1031 
1032     /// \overload
1033     /// Computes the extent as if the matrix \p transform was first applied.
1034     USDGEOM_API
1035     bool ComputeExtentAtTime(
1036                         VtVec3fArray* extent,
1037                         const UsdTimeCode time,
1038                         const UsdTimeCode baseTime,
1039                         const GfMatrix4d& transform) const;
1040 
1041     /// Compute the extent of the point instancer as in
1042     /// \ref ComputeExtentAtTime , but across multiple \p times . This is
1043     /// equivalent to, but more efficient than, calling ComputeExtentAtTime
1044     /// several times. Each element in \p extents is the computed extent at the
1045     /// corresponding time in \p times .
1046     ///
1047     /// As in \ref ComputeExtentAtTime, if there is no error, we return \c true
1048     /// and \p extents will be the tightest bounds we can compute efficiently.
1049     /// If an error occurs computing the extent at any time, \c false will be
1050     /// returned and \p extents will be left untouched.
1051     ///
1052     /// \param times - A vector containing the UsdTimeCodes at which we want to
1053     ///                sample.
1054     USDGEOM_API
1055     bool ComputeExtentAtTimes(
1056                         std::vector<VtVec3fArray>* extents,
1057                         const std::vector<UsdTimeCode>& times,
1058                         const UsdTimeCode baseTime) const;
1059 
1060     /// \overload
1061     /// Computes the extent as if the matrix \p transform was first applied at
1062     /// each time.
1063     USDGEOM_API
1064     bool ComputeExtentAtTimes(
1065                         std::vector<VtVec3fArray>* extents,
1066                         const std::vector<UsdTimeCode>& times,
1067                         const UsdTimeCode baseTime,
1068                         const GfMatrix4d& transform) const;
1069 
1070     /// Returns the number of instances as defined by the size of the
1071     /// _protoIndices_ array at _timeCode_.
1072     ///
1073     /// \snippetdoc snippets.dox GetCount
1074     /// \sa GetProtoIndicesAttr()
1075     USDGEOM_API
1076     size_t GetInstanceCount(UsdTimeCode timeCode = UsdTimeCode::Default()) const;
1077 
1078 private:
1079 
1080     bool _ComputeExtentAtTimePreamble(
1081         UsdTimeCode baseTime,
1082         VtIntArray* protoIndices,
1083         std::vector<bool>* mask,
1084         UsdRelationship* prototypes,
1085         SdfPathVector* protoPaths) const;
1086 
1087     bool _ComputeExtentFromTransforms(
1088         VtVec3fArray* extent,
1089         const VtIntArray& protoIndices,
1090         const std::vector<bool>& mask,
1091         const UsdRelationship& prototypes,
1092         const SdfPathVector& protoPaths,
1093         const VtMatrix4dArray& instanceTransforms,
1094         UsdTimeCode time,
1095         const GfMatrix4d* transform) const;
1096 
1097     bool _ComputeExtentAtTime(
1098         VtVec3fArray* extent,
1099         const UsdTimeCode time,
1100         const UsdTimeCode baseTime,
1101         const GfMatrix4d* transform) const;
1102 
1103     bool _ComputeExtentAtTimes(
1104         std::vector<VtVec3fArray>* extent,
1105         const std::vector<UsdTimeCode>& times,
1106         const UsdTimeCode baseTime,
1107         const GfMatrix4d* transform) const;
1108 };
1109 
1110 template <class T>
1111 bool
ApplyMaskToArray(std::vector<bool> const & mask,VtArray<T> * dataArray,const int elementSize)1112 UsdGeomPointInstancer::ApplyMaskToArray(std::vector<bool> const &mask,
1113                                         VtArray<T> *dataArray,
1114                                         const int elementSize)
1115 {
1116     if (!dataArray) {
1117         TF_CODING_ERROR("NULL dataArray.");
1118         return false;
1119     }
1120     size_t maskSize = mask.size();
1121     if (maskSize == 0 || dataArray->size() == (size_t)elementSize){
1122         return true;
1123     }
1124     else if ((maskSize * elementSize) != dataArray->size()){
1125         TF_WARN("Input mask's size (%zu) is not compatible with the "
1126                 "input dataArray (%zu) and elementSize (%d).",
1127                 maskSize, dataArray->size(), elementSize);
1128         return false;
1129     }
1130 
1131     T* beginData = dataArray->data();
1132     T* currData = beginData;
1133     size_t numPreserved = 0;
1134     for (size_t i = 0; i < maskSize; ++i) {
1135         // XXX Could add a fast-path for elementSize == 1 ?
1136         if (mask[i]) {
1137             for (int j = 0; j < elementSize; ++j) {
1138                 *currData = beginData[i + j];
1139                 ++currData;
1140             }
1141             numPreserved += elementSize;
1142         }
1143     }
1144     if (numPreserved < dataArray->size()) {
1145         dataArray->resize(numPreserved);
1146     }
1147     return true;
1148 }
1149 
1150 /// Returns true if list ops should be composed with SdfListOp::ApplyOperations()
1151 /// Returns false if list ops should be composed with SdfListOp::ComposeOperations().
1152 USDGEOM_API
1153 bool
1154 UsdGeomPointInstancerApplyNewStyleListOps();
1155 
1156 /// Applies a list operation of type \p op using \p items
1157 /// over the existing list operation on \p prim with the name
1158 /// \p metadataName.
1159 USDGEOM_API
1160 bool
1161 UsdGeomPointInstancerSetOrMergeOverOp(std::vector<int64_t> const &items,
1162                                       SdfListOpType op,
1163                                       UsdPrim const &prim,
1164                                       TfToken const &metadataName);
1165 
1166 PXR_NAMESPACE_CLOSE_SCOPE
1167 
1168 #endif
1169