usdrt::UsdGeomPointInstancer
Defined in usdrt/scenegraph/usd/usdGeom/pointInstancer.h
-
class UsdGeomPointInstancer : public usdrt::UsdGeomBoundable
Encodes vectorized instancing of multiple, potentially animated, prototypes (object/instance masters), which can be arbitrary prims/subtrees on a UsdStage.
PointInstancer is a “multi instancer”, as it allows multiple prototypes to be scattered among its “points”. We use a UsdRelationship prototypes to identify and order all of the possible prototypes, by targeting the root prim of each prototype. The ordering imparted by relationships associates a zero-based integer with each prototype, and it is these integers we use to identify the prototype of each instance, compactly, and allowing prototypes to be swapped out without needing to reauthor all of the per-instance data.
The PointInstancer schema is designed to scale to billions of instances, which motivates the choice to split the per-instance transformation into position, (quaternion) orientation, and scales, rather than a 4x4 matrix per-instance. In addition to requiring fewer bytes even if all elements are authored (32 bytes vs 64 for a single-precision 4x4 matrix), we can also be selective about which attributes need to animate over time, for substantial data reduction in many cases.
Note that PointInstancer is not a Gprim, since it is not a graphical primitive by any stretch of the imagination. It is, however, Boundable, since we will sometimes want to treat the entire PointInstancer similarly to a procedural, from the perspective of inclusion or framing.
Varying Instance Identity over Time
PointInstancers originating from simulations often have the characteristic that points/instances are “born”, move around for some time period, and then die (or leave the area of interest). In such cases, billions of instances may be birthed over time, while at any specific time, only a much smaller number are actually alive. To encode this situation efficiently, the simulator may re-use indices in the instance arrays, when a particle dies, its index will be taken over by a new particle that may be birthed in a much different location. This presents challenges both for identity-tracking, and for motion-blur.
We facilitate identity tracking by providing an optional, animatable ids attribute, that specifies the 64 bit integer ID of the particle at each index, at each point in time. If the simulator keeps monotonically increasing a particle-count each time a new particle is birthed, it will serve perfectly as particle ids.
We facilitate motion blur for varying-topology particle streams by optionally allowing per-instance velocities and angularVelocities to be authored. If instance transforms are requested at a time between samples and either of the velocity attributes is authored, then we will not attempt to interpolate samples of positions or orientations. If not authored, and the bracketing samples have the same length, then we will interpolate.
Computing an Instance Transform
Each instance’s transformation is a combination of the SRT affine transform described by its scale, orientation, and position, applied after (i.e. less locally) than the transformation computed at the root of the prototype it is instancing. In other words, to put an instance of a PointInstancer into the space of the PointInstancer’s parent prim:
Apply (most locally) the authored transformation for prototypes[protoIndices[i]]
If scales is authored, next apply the scaling matrix from scales[i]
If orientations is authored: if is authored, first multiply orientations[i] by the unit quaternion derived by scaling angularVelocities[i] by the time differential from the left-bracketing timeSample for orientation to the requested evaluation time t, storing the result in R, else assign R directly from orientations[i]. Apply the rotation matrix derived from R.
Apply the translation derived from positions[i]. If velocities is authored, apply the translation deriving from velocities[i] scaled by the time differential from the left-bracketing timeSample for positions to the requested evaluation time t.
Least locally, apply the transformation authored on the PointInstancer prim itself (or the UsdGeomImageable::ComputeLocalToWorldTransform() of the PointInstancer to put the instance directly into world space)
If neither velocities nor angularVelocities are authored, we fallback to standard position and orientation computation logic (using linear interpolation between timeSamples) as described by UsdGeom_VelocityInterpolation .
Scaling Velocities for Interpolation
When computing time-differentials by which to apply velocity or angularVelocity to positions or orientations, we must scale by ( 1.0 / UsdStage::GetTimeCodesPerSecond() ), because velocities are recorded in units/second, while we are interpolating in UsdTimeCode ordinates.
We provide both high and low-level API’s for dealing with the transformation as a matrix, both will compute the instance matrices using multiple threads; the low-level API allows the client to cache unvarying inputs so that they need not be read duplicately when computing over time.
See also UsdGeom_VelocityInterpolation .
Primvars on PointInstancer
Primvars authored on a PointInstancer prim should always be applied to each instance with constant interpolation at the root of the instance. When you are authoring primvars on a PointInstancer, think about it as if you were authoring them on a point-cloud (e.g. a UsdGeomPoints gprim). The same interpolation rules for points apply here, substituting “instance” for “point”.
In other words, the (constant) value extracted for each instance from the authored primvar value depends on the authored interpolation and elementSize of the primvar, as follows:
constant or uniform : the entire authored value of the primvar should be applied exactly to each instance.
varying, vertex, or faceVarying: the first elementSize elements of the authored primvar array should be assigned to instance zero, the second elementSize elements should be assigned to instance one, and so forth.
Masking Instances: “Deactivating” and Invising
Often a PointInstancer is created “upstream” in a graphics pipeline, and the needs of “downstream” clients necessitate eliminating some of the instances from further consideration. Accomplishing this pruning by re-authoring all of the per-instance attributes is not very attractive, since it may mean destructively editing a large quantity of data. We therefore provide means of “masking” instances by ID, such that the instance data is unmolested, but per-instance transform and primvar data can be retrieved with the no-longer-desired instances eliminated from the (smaller) arrays. PointInstancer allows two independent means of masking instances by ID, each with different features that meet the needs of various clients in a pipeline. Both pruning features’ lists of ID’s are combined to produce the mask returned by ComputeMaskAtTime().
InactiveIds: List-edited, Unvarying Masking
The first masking feature encodes a list of IDs in a list-editable metadatum called inactiveIds, which, although it does not have any similar impact to stage population as prim activation, it shares with that feature that its application is uniform over all time. Because it is list-editable, we can sparsely add and remove instances from it in many layers.
This sparse application pattern makes inactiveIds a good choice when further downstream clients may need to reverse masking decisions made upstream, in a manner that is robust to many kinds of future changes to the upstream data.
See ActivateId(), ActivateIds(), DeactivateId(), DeactivateIds(), ActivateAllIds()
invisibleIds: Animatable Masking
The second masking feature encodes a list of IDs in a time-varying Int64Array-valued UsdAttribute called invisibleIds , since it shares with Imageable visibility the ability to animate object visibility.
Unlike inactiveIds, overriding a set of opinions for invisibleIds is not at all straightforward, because one will, in general need to reauthor (in the overriding layer) all timeSamples for the attribute just to change one Id’s visibility state, so it cannot be authored sparsely. But it can be a very useful tool for situations like encoding pre-computed camera-frustum culling of geometry when either or both of the instances or the camera is animated.
See VisId(), VisIds(), InvisId(), InvisIds(), VisAllIds()
Processing and Not Processing Prototypes
Any prim in the scenegraph can be targeted as a prototype by the prototypes relationship. We do not, however, provide a specific mechanism for identifying prototypes as geometry that should not be drawn (or processed) in their own, local spaces in the scenegraph. We encourage organizing all prototypes as children of the PointInstancer prim that consumes them, and pruning “raw” processing and drawing traversals when they encounter a PointInstancer prim; this is what the UsdGeomBBoxCache and UsdImaging engines do.
There is a pattern one can deploy for organizing the prototypes such that they will automatically be skipped by basic UsdPrim::GetChildren() or UsdPrimRange traversals. Usd prims each have a specifier of “def”, “over”, or “class”. The default traversals skip over prims that are “pure overs” or classes. So to protect prototypes from all generic traversals and processing, place them under a prim that is just an “over”. For example,
01 def PointInstancer "Crowd_Mid" 02 { 03 rel prototypes = [ </Crowd_Mid/Prototypes/MaleThin_Business>, </Crowd_Mid/Prototypes/MaleThin_Casual> ] 04 05 over "Prototypes" 06 { 07 def "MaleThin_Business" ( 08 references = [@MaleGroupA/usd/MaleGroupA.usd@</MaleGroupA>] 09 variants = { 10 string modelingVariant = "Thin" 11 string costumeVariant = "BusinessAttire" 12 } 13 ) 14 { ... } 15 16 def "MaleThin_Casual" 17 ... 18 } 19 }
Note
If a PointInstancer has no authored ids attribute, the masking features will still be available, with the integers specifying element position in the protoIndices array rather than ID.
Public Functions
-
inline explicit UsdGeomPointInstancer(const UsdPrim &prim = UsdPrim())
Construct a UsdGeomPointInstancer on UsdPrim
prim
. Equivalent to UsdGeomPointInstancer::Get(prim.GetStage(), prim.GetPath()) for a validprim
, but will not immediately throw an error for an invalidprim
.
-
inline explicit UsdGeomPointInstancer(const UsdSchemaBase &schemaObj)
Construct a UsdGeomPointInstancer on the prim held by
schemaObj
. Should be preferred over UsdGeomPointInstancer(schemaObj.GetPrim()), as it preserves SchemaBase state.
-
inline virtual ~UsdGeomPointInstancer()
Destructor.
-
inline UsdAttribute GetProtoIndicesAttr() const
Required property. Per-instance index into prototypes relationship that identifies what geometry should be drawn for each instance. Topology attribute - can be animated, but at a potential performance impact for streaming.
Declaration
int[] protoIndices
C++ Type
VtArray<int>
Usd Type
SdfValueTypeNames->IntArray
-
inline UsdAttribute CreateProtoIndicesAttr() const
See GetProtoIndicesAttr(), and also Create vs Get Property Methods for when to use Get vs Create. If specified, author
defaultValue
as the attribute’s default, sparsely (when it makes sense to do so) ifwriteSparsely
istrue
- the default forwriteSparsely
isfalse
.
-
inline UsdAttribute GetIdsAttr() const
Ids are optional; if authored, the ids array should be the same length as the protoIndices array, specifying (at each timeSample if instance identities are changing) the id of each instance. The type is signed intentionally, so that clients can encode some binary state on Id’d instances without adding a separate primvar. See also Varying Instance Identity over Time.
Declaration
int64[] ids
C++ Type
VtArray<int64_t>
Usd Type
SdfValueTypeNames->Int64Array
-
inline UsdAttribute CreateIdsAttr() const
See GetIdsAttr(), and also Create vs Get Property Methods for when to use Get vs Create. If specified, author
defaultValue
as the attribute’s default, sparsely (when it makes sense to do so) ifwriteSparsely
istrue
- the default forwriteSparsely
isfalse
.
-
inline UsdAttribute GetPositionsAttr() const
Required property. Per-instance position. See also Computing an Instance Transform .
Declaration
point3f[] positions
C++ Type
VtArray<GfVec3f>
Usd Type
SdfValueTypeNames->Point3fArray
-
inline UsdAttribute CreatePositionsAttr() const
See GetPositionsAttr(), and also Create vs Get Property Methods for when to use Get vs Create. If specified, author
defaultValue
as the attribute’s default, sparsely (when it makes sense to do so) ifwriteSparsely
istrue
- the default forwriteSparsely
isfalse
.
-
inline UsdAttribute GetOrientationsAttr() const
If authored, per-instance orientation of each instance about its prototype’s origin, represented as a unit length quaternion, which allows us to encode it with sufficient precision in a compact GfQuath.
It is client’s responsibility to ensure that authored quaternions are unit length; the convenience API below for authoring orientations from rotation matrices will ensure that quaternions are unit length, though it will not make any attempt to select the “better (for interpolation
with respect to neighboring samples)” of the two possible quaternions that encode the rotation.
See also Computing an Instance Transform .
Declaration
quath[] orientations
C++ Type
VtArray<GfQuath>
Usd Type
SdfValueTypeNames->QuathArray
-
inline UsdAttribute CreateOrientationsAttr() const
See GetOrientationsAttr(), and also Create vs Get Property Methods for when to use Get vs Create. If specified, author
defaultValue
as the attribute’s default, sparsely (when it makes sense to do so) ifwriteSparsely
istrue
- the default forwriteSparsely
isfalse
.
-
inline UsdAttribute GetScalesAttr() const
If authored, per-instance scale to be applied to each instance, before any rotation is applied.
See also Computing an Instance Transform .
Declaration
float3[] scales
C++ Type
VtArray<GfVec3f>
Usd Type
SdfValueTypeNames->Float3Array
-
inline UsdAttribute CreateScalesAttr() const
See GetScalesAttr(), and also Create vs Get Property Methods for when to use Get vs Create. If specified, author
defaultValue
as the attribute’s default, sparsely (when it makes sense to do so) ifwriteSparsely
istrue
- the default forwriteSparsely
isfalse
.
-
inline UsdAttribute GetVelocitiesAttr() const
If provided, per-instance ‘velocities’ will be used to compute positions between samples for the ‘positions’ attribute, rather than interpolating between neighboring ‘positions’ samples. Velocities should be considered mandatory if both protoIndices and positions are animated. Velocity is measured in position units per second, as per most simulation software. To convert to position units per UsdTimeCode, divide by UsdStage::GetTimeCodesPerSecond().
See also Computing an Instance Transform, UsdGeom_VelocityInterpolation .
Declaration
vector3f[] velocities
C++ Type
VtArray<GfVec3f>
Usd Type
SdfValueTypeNames->Vector3fArray
-
inline UsdAttribute CreateVelocitiesAttr() const
See GetVelocitiesAttr(), and also Create vs Get Property Methods for when to use Get vs Create. If specified, author
defaultValue
as the attribute’s default, sparsely (when it makes sense to do so) ifwriteSparsely
istrue
- the default forwriteSparsely
isfalse
.
-
inline UsdAttribute GetAccelerationsAttr() const
If authored, per-instance ‘accelerations’ will be used with velocities to compute positions between samples for the ‘positions’ attribute rather than interpolating between neighboring ‘positions’ samples. Acceleration is measured in position units per second-squared. To convert to position units per squared UsdTimeCode, divide by the square of UsdStage::GetTimeCodesPerSecond().
Declaration
vector3f[] accelerations
C++ Type
VtArray<GfVec3f>
Usd Type
SdfValueTypeNames->Vector3fArray
-
inline UsdAttribute CreateAccelerationsAttr() const
See GetAccelerationsAttr(), and also Create vs Get Property Methods for when to use Get vs Create. If specified, author
defaultValue
as the attribute’s default, sparsely (when it makes sense to do so) ifwriteSparsely
istrue
- the default forwriteSparsely
isfalse
.
-
inline UsdAttribute GetAngularVelocitiesAttr() const
If authored, per-instance angular velocity vector to be used for interoplating orientations. Angular velocities should be considered mandatory if both protoIndices and orientations are animated. Angular velocity is measured in degrees per second. To convert to degrees per UsdTimeCode, divide by UsdStage::GetTimeCodesPerSecond().
See also Computing an Instance Transform .
Declaration
vector3f[] angularVelocities
C++ Type
VtArray<GfVec3f>
Usd Type
SdfValueTypeNames->Vector3fArray
-
inline UsdAttribute CreateAngularVelocitiesAttr() const
See GetAngularVelocitiesAttr(), and also Create vs Get Property Methods for when to use Get vs Create. If specified, author
defaultValue
as the attribute’s default, sparsely (when it makes sense to do so) ifwriteSparsely
istrue
- the default forwriteSparsely
isfalse
.
-
inline UsdAttribute GetInvisibleIdsAttr() const
A list of id’s to make invisible at the evaluation time. See invisibleIds: Animatable Masking .
Declaration
int64[] invisibleIds = []
C++ Type
VtArray<int64_t>
Usd Type
SdfValueTypeNames->Int64Array
-
inline UsdAttribute CreateInvisibleIdsAttr() const
See GetInvisibleIdsAttr(), and also Create vs Get Property Methods for when to use Get vs Create. If specified, author
defaultValue
as the attribute’s default, sparsely (when it makes sense to do so) ifwriteSparsely
istrue
- the default forwriteSparsely
isfalse
.
-
inline UsdRelationship GetPrototypesRel() const
Required property. Orders and targets the prototype root prims, which can be located anywhere in the scenegraph that is convenient, although we promote organizing prototypes as children of the PointInstancer. The position of a prototype in this relationship defines the value an instance would specify in the protoIndices attribute to instance that prototype. Since relationships are uniform, this property cannot be animated.
-
inline UsdRelationship CreatePrototypesRel() const
See GetPrototypesRel(), and also Create vs Get Property Methods for when to use Get vs Create.
-
inline UsdAttribute GetExtentAttr() const
Extent is a three dimensional range measuring the geometric extent of the authored gprim in its own local space (i.e. its own transform not applied), without accounting for any shader-induced displacement. If any extent value has been authored for a given Boundable, then it should be authored at every timeSample at which geometry-affecting properties are authored, to ensure correct evaluation via ComputeExtent(). If no extent value has been authored, then ComputeExtent() will call the Boundable’s registered ComputeExtentFunction(), which may be expensive, which is why we strongly encourage proper authoring of extent.
An authored extent on a prim which has children is expected to include the extent of all children, as they will be pruned from BBox computation during traversal.
See also
ComputeExtent()
See also
Why Extent and not Bounds ?.
Declaration
float3[] extent
C++ Type
VtArray<GfVec3f>
Usd Type
SdfValueTypeNames->Float3Array
-
inline UsdAttribute CreateExtentAttr() const
See GetExtentAttr(), and also Create vs Get Property Methods for when to use Get vs Create. If specified, author
defaultValue
as the attribute’s default, sparsely (when it makes sense to do so) ifwriteSparsely
istrue
- the default forwriteSparsely
isfalse
.
-
inline UsdAttribute GetXformOpOrderAttr() const
Encodes the sequence of transformation operations in the order in which they should be pushed onto a transform stack while visiting a UsdStage’s prims in a graph traversal that will effect the desired positioning for this prim and its descendant prims.
You should rarely, if ever, need to manipulate this attribute directly. It is managed by the AddXformOp(), SetResetXformStack(), and SetXformOpOrder(), and consulted by GetOrderedXformOps() and GetLocalTransformation().
Declaration
uniform token[] xformOpOrder
C++ Type
VtArray<TfToken>
Usd Type
SdfValueTypeNames->TokenArray
Variability
SdfVariabilityUniform
-
inline UsdAttribute CreateXformOpOrderAttr() const
See GetXformOpOrderAttr(), and also Create vs Get Property Methods for when to use Get vs Create. If specified, author
defaultValue
as the attribute’s default, sparsely (when it makes sense to do so) ifwriteSparsely
istrue
- the default forwriteSparsely
isfalse
.
-
inline UsdAttribute GetVisibilityAttr() const
Visibility is meant to be the simplest form of “pruning” visibility that is supported by most DCC apps. Visibility is animatable, allowing a sub-tree of geometry to be present for some segment of a shot, and absent from others; unlike the action of deactivating geometry prims, invisible geometry is still available for inspection, for positioning, for defining volumes, etc.
Declaration
token visibility = "inherited"
C++ Type
Usd Type
SdfValueTypeNames->Token
Allowed Values
inherited, invisible
-
inline UsdAttribute CreateVisibilityAttr() const
See GetVisibilityAttr(), and also Create vs Get Property Methods for when to use Get vs Create. If specified, author
defaultValue
as the attribute’s default, sparsely (when it makes sense to do so) ifwriteSparsely
istrue
- the default forwriteSparsely
isfalse
.
-
inline UsdAttribute GetPurposeAttr() const
Purpose is a classification of geometry into categories that can each be independently included or excluded from traversals of prims on a stage, such as rendering or bounding-box computation traversals.
See UsdGeom_ImageablePurpose for more detail about how purpose is computed and used.
Declaration
uniform token purpose = "default"
C++ Type
Usd Type
SdfValueTypeNames->Token
Variability
SdfVariabilityUniform
Allowed Values
default, render, proxy, guide
-
inline UsdAttribute CreatePurposeAttr() const
See GetPurposeAttr(), and also Create vs Get Property Methods for when to use Get vs Create. If specified, author
defaultValue
as the attribute’s default, sparsely (when it makes sense to do so) ifwriteSparsely
istrue
- the default forwriteSparsely
isfalse
.
-
inline UsdRelationship GetProxyPrimRel() const
The proxyPrim relationship allows us to link a prim whose purpose is “render” to its (single target) purpose=”proxy” prim. This is entirely optional, but can be useful in several scenarios:
In a pipeline that does pruning (for complexity management) by deactivating prims composed from asset references, when we deactivate a purpose=”render” prim, we will be able to discover and additionally deactivate its associated purpose=”proxy” prim, so that preview renders reflect the pruning accurately.
DCC importers may be able to make more aggressive optimizations for interactive processing and display if they can discover the proxy for a given render prim.
With a little more work, a Hydra-based application will be able to map a picked proxy prim back to its render geometry for selection.
Note
It is only valid to author the proxyPrim relationship on prims whose purpose is “render”.
-
inline UsdRelationship CreateProxyPrimRel() const
See GetProxyPrimRel(), and also Create vs Get Property Methods for when to use Get vs Create.
-
inline explicit operator bool() const
Check if this schema object is compatible with it’s held prim and that the prim is valid.
A typed schema object is compatible if the held prim’s type is or is a subtype of the schema’s type. Based on
prim.IsA()
.An API schema object is compatible if the API is of type SingleApplyAPI or UsdSchemaType::MultipleApplyAPI, and the schema has been applied to the prim. Based on
prim.HasAPI
.This method invokes polymorphic behaviour.
See also
- Returns
True if the help prim is valid, and the schema object is compatible with its held prim.
Public Static Functions
-
static inline UsdGeomPointInstancer Define(const UsdStageRefPtr &stage, const SdfPath &path)
Attempt to ensure a UsdPrim adhering to this schema at
path
is defined (according to UsdPrim::IsDefined()) on this stage.
Public Static Attributes
-
static const UsdSchemaType schemaType = UsdSchemaType::ConcreteTyped
Compile time constant representing what kind of schema this class is.
See also
Protected Functions
-
inline virtual bool _IsCompatible() const
Helper for subclasses to do specific compatibility checking with the given prim. Subclassess may override
_isCompatible
to for example check type compatibility or value compatibility on the prim.Overrides exist for UsdTyped and UsdAPISchemaBase.
This check is called when clients invoke the bool operator.
- Returns
True if the schema object is compatible with its held prim.