HDK
|
#include <primvar.h>
Public Member Functions | |
UsdGeomPrimvar () | |
USDGEOM_API | UsdGeomPrimvar (const UsdGeomPrimvar &other) |
Copy construct. More... | |
USDGEOM_API UsdGeomPrimvar & | operator= (const UsdGeomPrimvar &other) |
Copy assign. More... | |
USDGEOM_API | UsdGeomPrimvar (const UsdAttribute &attr) |
USDGEOM_API TfToken | GetInterpolation () const |
USDGEOM_API bool | SetInterpolation (const TfToken &interpolation) |
USDGEOM_API bool | HasAuthoredInterpolation () const |
USDGEOM_API int | GetElementSize () const |
USDGEOM_API bool | SetElementSize (int eltSize) |
USDGEOM_API bool | HasAuthoredElementSize () const |
USDGEOM_API void | GetDeclarationInfo (TfToken *name, SdfValueTypeName *typeName, TfToken *interpolation, int *elementSize) const |
template<> | |
USDGEOM_API bool | Get (std::string *value, UsdTimeCode time) const |
template<> | |
USDGEOM_API bool | Get (VtStringArray *value, UsdTimeCode time) const |
template<> | |
USDGEOM_API bool | Get (VtValue *value, UsdTimeCode time) const |
UsdAttribute API | |
operator UsdAttribute const & () const | |
UsdAttribute const & | GetAttr () const |
Explicit UsdAttribute extractor. More... | |
bool | IsDefined () const |
bool | HasValue () const |
bool | HasAuthoredValue () const |
operator bool () const | |
TfToken const & | GetName () const |
USDGEOM_API TfToken | GetPrimvarName () const |
USDGEOM_API bool | NameContainsNamespaces () const |
TfToken | GetBaseName () const |
TfToken | GetNamespace () const |
std::vector< std::string > | SplitName () const |
SdfValueTypeName | GetTypeName () const |
template<typename T > | |
bool | Get (T *value, UsdTimeCode time=UsdTimeCode::Default()) const |
template<typename T > | |
bool | Set (const T &value, UsdTimeCode time=UsdTimeCode::Default()) const |
Set the attribute value of the Primvar at time . More... | |
USDGEOM_API bool | GetTimeSamples (std::vector< double > *times) const |
USDGEOM_API bool | GetTimeSamplesInInterval (const GfInterval &interval, std::vector< double > *times) const |
USDGEOM_API bool | ValueMightBeTimeVarying () const |
Id attribute API | |
Often there is the need to identify a prim within a scene (e.g. a mesh on which a procedural should operate, or a shader to inherit). A string or string[] -typed primvar can be turned into an "Id Path" primvar by calling SetIdTarget() with the path of any object on the current stage. When the primvar is subsequently queried via Get(), the returned value will be the stringified value of the targeted object's path in whatever namespace is defined by the querying stage's root layer. In other words, authoring an Id primvar into a published model will return the path-to-target in the model, but when the model is referenced into a larger scene, it will return the complete scene path. This works by adding a paired UsdRelationship in a ":idFrom" namespace "below" the string primvar. Get() evaluates UsdRelationship::GetForwardedTargets() to determine the id-string. Thus, this mechanism will always produce a unique identifier for every object in a scene, regardless of how many times an asset is referenced into a scene. Providing a mesh with a unique identifier primvar can be especially useful for renderers that allow plugins/shaders access to processed scene data based on user-provided string identifiers. If an Id primvar has both an authored string value and a SetIdTarget()'d target, the target path takes precedence. Currently Id primvars can have only a single target, so the only useful interpolation is constant. | |
USDGEOM_API bool | IsIdTarget () const |
USDGEOM_API bool | SetIdTarget (const SdfPath &path) const |
Static Public Member Functions | |
static USDGEOM_API bool | IsPrimvar (const UsdAttribute &attr) |
static USDGEOM_API bool | IsValidPrimvarName (const TfToken &name) |
static USDGEOM_API TfToken | StripPrimvarsName (const TfToken &name) |
static USDGEOM_API bool | IsValidInterpolation (const TfToken &interpolation) |
Friends | |
class | UsdGeomImageable |
class | UsdGeomPrimvarsAPI |
bool | operator== (const UsdGeomPrimvar &lhs, const UsdGeomPrimvar &rhs) |
bool | operator!= (const UsdGeomPrimvar &lhs, const UsdGeomPrimvar &rhs) |
bool | operator< (const UsdGeomPrimvar &lhs, const UsdGeomPrimvar &rhs) |
template<typename HashState > | |
void | TfHashAppend (HashState &h, const UsdGeomPrimvar &obj) |
size_t | hash_value (const UsdGeomPrimvar &obj) |
Indexed primvars API | |
For non-constant values of interpolation, it is often the case that the same value is repeated many times in the array value of a primvar. An indexed primvar can be used in such cases to optimize for data storage if the primvar's interpolation is uniform, varying, or vertex. For faceVarying primvars, however, indexing serves a higher purpose (and should be used only for this purpose, since renderers and OpenSubdiv will assume it) of establishing a surface topology for the primvar. That is, faceVarying primvars use indexing to unambiguously define discontinuities in their functions at edges and vertices. Please see the OpenSubdiv documentation on FaceVarying Primvars for more information. To create an indexed primvar, the value of the attribute associated with the primvar is set to an array consisting of all the unique values that appear in the primvar array. A separate namespaced "indices" attribute is set to an integer array containing indices into the array with all the unique elements. The final value of the primvar is computed using the indices array and the attribute value array. | |
USDGEOM_API bool | SetIndices (const VtIntArray &indices, UsdTimeCode time=UsdTimeCode::Default()) const |
USDGEOM_API bool | GetIndices (VtIntArray *indices, UsdTimeCode time=UsdTimeCode::Default()) const |
USDGEOM_API void | BlockIndices () const |
USDGEOM_API bool | IsIndexed () const |
USDGEOM_API UsdAttribute | GetIndicesAttr () const |
USDGEOM_API UsdAttribute | CreateIndicesAttr () const |
USDGEOM_API bool | SetUnauthoredValuesIndex (int unauthoredValuesIndex) const |
USDGEOM_API int | GetUnauthoredValuesIndex () const |
template<typename ScalarType > | |
bool | ComputeFlattened (VtArray< ScalarType > *value, UsdTimeCode time=UsdTimeCode::Default()) const |
USDGEOM_API bool | ComputeFlattened (VtValue *value, UsdTimeCode time=UsdTimeCode::Default()) const |
static USDGEOM_API bool | ComputeFlattened (VtValue *value, const VtValue &attrVal, const VtIntArray &indices, std::string *errString) |
static USDGEOM_API bool | ComputeFlattened (VtValue *value, const VtValue &attrVal, const VtIntArray &indices, int elementSize, std::string *errString) |
Schema wrapper for UsdAttribute for authoring and introspecting attributes that are primvars.
UsdGeomPrimvar provides API for authoring and retrieving the additional data required to encode an attribute as a "Primvar", which is a convenient contraction of RenderMan's "Primitive Variable" concept, which is represented in Alembic as "arbitrary geometry parameters" (arbGeomParams).
This includes the attribute's interpolation across the primitive (which RenderMan refers to as its class specifier and Alembic as its "geometry scope"); it also includes the attribute's elementSize, which states how many values in the value array must be aggregated for each element on the primitive. An attribute's TypeName also factors into the encoding of Primvar.
There are three key aspects of Primvar identity:
The UsdGeomPrimvarsAPI schema provides a complete interface for creating and querying prims for primvars.
The only way to create a new Primvar in scene description is by calling UsdGeomPrimvarsAPI::CreatePrimvar(). One cannot "enhance" or "promote" an already existing attribute into a Primvar, because doing so may require a namespace edit to rename the attribute, which cannot, in general, be done within a single UsdEditContext. Instead, create a new UsdGeomPrimvar of the desired name using UsdGeomPrimvarsAPI::CreatePrimvar(), and then copy the existing attribute onto the new UsdGeomPrimvar.
Primvar names can contain arbitrary sub-namespaces. The behavior of UsdGeomImageable::GetPrimvar(TfToken const &name) is to prepend "primvars:" onto 'name' if it is not already a prefix, and return the result, which means we do not have any ambiguity between the primvars "primvars:nsA:foo" and "primvars:nsB:foo". There are reserved keywords that may not be used as the base names of primvars, and attempting to create Primvars of these names will result in a coding error. The reserved keywords are tokens the Primvar uses internally to encode various features, such as the "indices" keyword used by Indexed Primvars.
If a client wishes to access an already-extant attribute as a Primvar, (which may or may not actually be valid Primvar), they can use the speculative constructor; typically, a primvar is only "interesting" if it additionally provides a value. This might look like:
or, because Get() returns true
if and only if it found a value:
As discussed in greater detail in Indexed Primvars, primvars can optionally contain a (possibly time-varying) indexing attribute that establishes a sharing topology for elements of the primvar. Consumers can always chose to ignore the possibility of indexed data by exclusively using the ComputeFlattened() API. If a client wishes to preserve indexing in their processing of a primvar, we suggest a pattern like the following, which accounts for the fact that a stronger layer can block a primvar's indexing from a weaker layer, via UsdGeomPrimvar::BlockIndices():
UsdGeomPrimvar presents a small slice of the UsdAttribute API - enough to extract the data that comprises the "Declaration info", and get/set of the attribute value. A UsdGeomPrimvar also auto-converts to UsdAttribute, so you can pass a UsdGeomPrimvar to any function that accepts a UsdAttribute or const-ref thereto.
There are no limitations imposed on the allowable scene description types for Primvars; it is the responsibility of each consuming client to perform renderer-specific conversions, if need be (the USD distribution will include reference RenderMan conversion utilities).
A note about type plurality of Primvars: It is legitimate for a Primvar to be of scalar or array type, and again, consuming clients must be prepared to accommodate both. However, while it is not possible, in all cases, for USD to prevent one from changing the type of an attribute in different layers or variants of an asset, it is never a good idea to do so. This is relevant because, except in a few special cases, it is not possible to encode an interpolation of any value greater than constant without providing multiple (i.e. array) data values. Therefore, if there is any possibility that downstream clients might need to change a Primvar's interpolation, the Primvar-creator should encode it as an array rather than a scalar.
Why allow scalar values at all, then? First, sometimes it brings clarity to (use of) a shader's API to acknowledge that some parameters are meant to be single-valued over a shaded primitive. Second, many DCC's provide far richer affordances for editing scalars than they do array values, and we feel it is safer to let the content creator make the decision/tradeoff of which kind of flexibility is more relevant, rather than leaving it to an importer/exporter pair to interpret.
Also, like all attributes, Primvars can be time-sampled, and values can be authored and consumed just as any other attribute. There is currently no validation that the length of value arrays matches to the size required by a gprim's topology, interpolation, and elementSize.
For consumer convenience, we provide GetDeclarationInfo(), which returns all the type information (other than topology) needed to compute the required array size, which is also all the information required to prepare the Primvar's value for consumption by a renderer.
UsdGeomPrimvar has an explicit bool operator that validates that the attribute IsDefined() and thus valid for querying and authoring values and metadata. This is a fairly expensive query that we do not cache, so if client code retains UsdGeomPrimvar objects, it should manage its object validity closely, for performance. An ideal pattern is to listen for UsdNotice::StageContentsChanged notifications, and revalidate/refetch its retained UsdGeomPrimvar s only then, and otherwise use them without validity checking.
In the following explanation of the meaning of the various kinds/levels of Primvar interpolation, each bolded bullet gives the name of the token in UsdGeomTokens that provides the value. So to set a Primvar's interpolation to "varying", one would:
Reprinted and adapted from the RPS documentation, which contains further details, interpolation describes how the Primvar will be interpolated over the uv parameter space of a surface primitive (or curve or pointcloud). The possible values are:
Just as UsdSchemaBase and its subclasses provide the pattern for how to layer schema onto the generic UsdPrim object, UsdGeomPrimvar provides an example of how to layer schema onto a generic UsdAttribute object. In both cases, the schema object wraps and contains the UsdObject.
Constant interpolation primvar values can be inherited down namespace. That is, a primvar value set on a prim will also apply to any child prims, unless those children have their own opinions about those named primvars. For complete details on how primvars inherit, see usdGeom_PrimvarInheritance .
USDGEOM_API UsdGeomPrimvar::UsdGeomPrimvar | ( | const UsdGeomPrimvar & | other | ) |
Copy construct.
|
explicit |
Speculative constructor that will produce a valid UsdGeomPrimvar when attr
already represents an attribute that is Primvar, and produces an invalid Primvar otherwise (i.e. operator bool() will return false).
Calling UsdGeomPrimvar::IsPrimvar(attr)
will return the same truth value as this constructor, but if you plan to subsequently use the Primvar anyways, just use this constructor, as demonstrated in the class documentation.
USDGEOM_API void UsdGeomPrimvar::BlockIndices | ( | ) | const |
Block the indices that were previously set. This effectively makes an indexed primvar no longer indexed. This is useful when overriding an existing primvar.
bool UsdGeomPrimvar::ComputeFlattened | ( | VtArray< ScalarType > * | value, |
UsdTimeCode | time = UsdTimeCode::Default() |
||
) | const |
Computes the flattened value of the primvar at time
.
If the primvar is not indexed or if the value type of this primvar is a scalar, this returns the authored value, which is the same as Get(). Hence, it's safe to call ComputeFlattened() on non-indexed primvars.
USDGEOM_API bool UsdGeomPrimvar::ComputeFlattened | ( | VtValue * | value, |
UsdTimeCode | time = UsdTimeCode::Default() |
||
) | const |
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. Computes the flattened value of the primvar at time
as a VtValue.
If the primvar is not indexed or if the value type of this primvar is a scalar, this returns the authored value, which is the same as Get(). Hence, it's safe to call ComputeFlattened() on non-indexed primvars.
|
static |
Computes the flattened value of attrValue
given indices
, assuming an elementSize of 1.
This method is a static convenience function that performs the main work of ComputeFlattened above without needing an instance of a UsdGeomPrimvar.
Returns false
if the value contained in attrVal
is not a supported type for flattening. Otherwise returns true
. The output errString
variable may be populated with an error string if an error is encountered during flattening.
|
static |
Computes the flattened value of attrValue
given indices
and elementSize
.
This method is a static convenience function that performs the main work of ComputeFlattened above without needing an instance of a UsdGeomPrimvar.
Returns false
if the value contained in attrVal
is not a supported type for flattening. Otherwise returns true
. The output errString
variable may be populated with an error string if an error is encountered during flattening.
USDGEOM_API UsdAttribute UsdGeomPrimvar::CreateIndicesAttr | ( | ) | const |
Returns the existing indices attribute if the primvar is indexed or creates a new one.
|
inline |
Get the attribute value of the Primvar at time
.
USDGEOM_API bool UsdGeomPrimvar::Get | ( | std::string * | value, |
UsdTimeCode | time | ||
) | const |
USDGEOM_API bool UsdGeomPrimvar::Get | ( | VtStringArray * | value, |
UsdTimeCode | time | ||
) | const |
USDGEOM_API bool UsdGeomPrimvar::Get | ( | VtValue * | value, |
UsdTimeCode | time | ||
) | const |
|
inline |
Explicit UsdAttribute extractor.
|
inline |
USDGEOM_API void UsdGeomPrimvar::GetDeclarationInfo | ( | TfToken * | name, |
SdfValueTypeName * | typeName, | ||
TfToken * | interpolation, | ||
int * | elementSize | ||
) | const |
Convenience function for fetching all information required to properly declare this Primvar. The name
returned is the "client name", stripped of the "primvars" namespace, i.e. equivalent to GetPrimvarName()
May also be more efficient than querying key individually.
USDGEOM_API int UsdGeomPrimvar::GetElementSize | ( | ) | const |
Return the "element size" for this Primvar, which is 1 if unauthored. If this Primvar's type is not an array type, (e.g. "Vec3f[]"), then elementSize is irrelevant.
ElementSize does not generally encode the length of an array-type primvar, and rarely needs to be authored. ElementSize can be thought of as a way to create an "aggregate interpolatable type", by dictating how many consecutive elements in the value array should be taken as an atomic element to be interpolated over a gprim.
For example, spherical harmonics are often represented as a collection of nine floating-point coefficients, and the coefficients need to be sampled across a gprim's surface: a perfect case for primvars. However, USD has no float9
datatype. But we can communicate the aggregation of nine floats successfully to renderers by declaring a simple float-array valued primvar, and setting its elementSize to 9. To author a uniform spherical harmonic primvar on a Mesh of 42 faces, the primvar's array value would contain 9*42 = 378 float elements.
USDGEOM_API bool UsdGeomPrimvar::GetIndices | ( | VtIntArray * | indices, |
UsdTimeCode | time = UsdTimeCode::Default() |
||
) | const |
Returns the value of the indices array associated with the indexed primvar at time
.
USDGEOM_API UsdAttribute UsdGeomPrimvar::GetIndicesAttr | ( | ) | const |
Returns a valid indices attribute if the primvar is indexed. Returns an invalid attribute otherwise.
USDGEOM_API TfToken UsdGeomPrimvar::GetInterpolation | ( | ) | const |
Return the Primvar's interpolation, which is UsdGeomTokens->constant if unauthored
Interpolation determines how the Primvar interpolates over a geometric primitive. See Interpolation of Geometric Primitive Variables
|
inline |
|
inline |
USDGEOM_API TfToken UsdGeomPrimvar::GetPrimvarName | ( | ) | const |
Returns the primvar's name, devoid of the "primvars:" namespace. This is the name by which clients should refer to the primvar, if not by its full attribute name - i.e. they should not, in general, use GetBaseName(). In the error condition in which this Primvar object is not backed by a properly namespaced UsdAttribute, return an empty TfToken.
USDGEOM_API bool UsdGeomPrimvar::GetTimeSamples | ( | std::vector< double > * | times | ) | const |
Populates a vector with authored sample times for this primvar. Returns false on error.
This considers any timeSamples authored on the associated "indices" attribute if the primvar is indexed.
USDGEOM_API bool UsdGeomPrimvar::GetTimeSamplesInInterval | ( | const GfInterval & | interval, |
std::vector< double > * | times | ||
) | const |
Populates a vector with authored sample times in interval
.
This considers any timeSamples authored on the associated "indices" attribute if the primvar is indexed.
|
inline |
USDGEOM_API int UsdGeomPrimvar::GetUnauthoredValuesIndex | ( | ) | const |
Returns the index that represents unauthored values in the indices array.
USDGEOM_API bool UsdGeomPrimvar::HasAuthoredElementSize | ( | ) | const |
Has elementSize been explicitly authored on this Primvar?
USDGEOM_API bool UsdGeomPrimvar::HasAuthoredInterpolation | ( | ) | const |
Has interpolation been explicitly authored on this Primvar?
|
inline |
|
inline |
|
inline |
Return true if the underlying UsdAttribute::IsDefined(), and in addition the attribute is identified as a Primvar. Does not imply that the primvar provides a value
USDGEOM_API bool UsdGeomPrimvar::IsIdTarget | ( | ) | const |
Returns true if the primvar is an Id primvar.
USDGEOM_API bool UsdGeomPrimvar::IsIndexed | ( | ) | const |
Returns true if the primvar is indexed, i.e., if it has an associated "indices" attribute.
If you are going to query the indices anyways, prefer to simply consult the return-value of GetIndices(), which will be more efficient.
|
static |
Test whether a given UsdAttribute represents valid Primvar, which implies that creating a UsdGeomPrimvar from the attribute will succeed.
Success implies that attr.IsDefined()
is true.
|
static |
Validate that the provided interpolation
is a valid setting for interpolation as defined by Interpolation of Geometric Primitive Variables.
|
static |
Test whether a given name
represents a valid name of a primvar, which implies that creating a UsdGeomPrimvar with the given name will succeed.
USDGEOM_API bool UsdGeomPrimvar::NameContainsNamespaces | ( | ) | const |
Does this primvar contain any namespaces other than the "primvars:" namespace?
Some clients may only wish to consume primvars that have no extra namespaces in their names, for ease of translating to other systems that do not allow namespaces.
|
inlineexplicit |
Return true if this Primvar is valid for querying and authoring values and metadata, which is identically equivalent to IsDefined().
|
inline |
Allow UsdGeomPrimvar to auto-convert to UsdAttribute, so you can pass a UsdGeomPrimvar to any function that accepts a UsdAttribute or const-ref thereto.
USDGEOM_API UsdGeomPrimvar& UsdGeomPrimvar::operator= | ( | const UsdGeomPrimvar & | other | ) |
Copy assign.
|
inline |
USDGEOM_API bool UsdGeomPrimvar::SetElementSize | ( | int | eltSize | ) |
Set the elementSize for this Primvar.
Errors and returns false if eltSize
less than 1.
USDGEOM_API bool UsdGeomPrimvar::SetIdTarget | ( | const SdfPath & | path | ) | const |
This primvar must be of String or StringArray type for this method to succeed. If not, a coding error is raised.
USDGEOM_API bool UsdGeomPrimvar::SetIndices | ( | const VtIntArray & | indices, |
UsdTimeCode | time = UsdTimeCode::Default() |
||
) | const |
USDGEOM_API bool UsdGeomPrimvar::SetInterpolation | ( | const TfToken & | interpolation | ) |
Set the Primvar's interpolation.
Errors and returns false if interpolation
is out of range as defined by IsValidInterpolation(). No attempt is made to validate that the Primvar's value contains the right number of elements to match its interpolation to its topology.
USDGEOM_API bool UsdGeomPrimvar::SetUnauthoredValuesIndex | ( | int | unauthoredValuesIndex | ) | const |
Set the index that represents unauthored values in the indices array.
Some apps (like Maya) allow you to author primvars sparsely over a surface. Since most apps can't handle sparse primvars, Maya needs to provide a value even for the elements it didn't author. This metadatum provides a way to recover the information in apps that do support sparse authoring / representation of primvars.
The fallback value of unauthoredValuesIndex is -1, which indicates that there are no unauthored values.
|
inline |
|
static |
Returns the name
, devoid of the "primvars:" token if present, otherwise returns the name
unchanged
USDGEOM_API bool UsdGeomPrimvar::ValueMightBeTimeVarying | ( | ) | const |
Return true if it is possible, but not certain, that this primvar's value changes over time, false otherwise.
This considers time-varyingness of the associated "indices" attribute if the primvar is indexed.
|
friend |
|
friend |
|
friend |
|
friend |
Equality comparison. Return true if lhs and rhs represent the same UsdGeomPrimvar, false otherwise.
|
friend |
|
friend |
|
friend |