// // Copyright 2016 Pixar // // Licensed under the Apache License, Version 2.0 (the "Apache License") // with the following modification; you may not use this file except in // compliance with the Apache License and the following modification to it: // Section 6. Trademarks. is deleted and replaced with: // // 6. Trademarks. This License does not grant permission to use the trade // names, trademarks, service marks, or product names of the Licensor // and its affiliates, except as required to comply with Section 4(c) of // the License and to reproduce the content of the NOTICE file. // // You may obtain a copy of the Apache License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the Apache License with the above modification is // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // #ifndef USDGEOM_GENERATED_POINTINSTANCER_H #define USDGEOM_GENERATED_POINTINSTANCER_H /// \file usdGeom/pointInstancer.h #include "pxr/pxr.h" #include "pxr/usd/usdGeom/api.h" #include "pxr/usd/usdGeom/boundable.h" #include "pxr/usd/usd/prim.h" #include "pxr/usd/usd/stage.h" #include "pxr/usd/usdGeom/tokens.h" #include "pxr/base/vt/value.h" #include "pxr/base/gf/vec3d.h" #include "pxr/base/gf/vec3f.h" #include "pxr/base/gf/matrix4d.h" #include "pxr/base/tf/token.h" #include "pxr/base/tf/type.h" PXR_NAMESPACE_OPEN_SCOPE class SdfAssetPath; // -------------------------------------------------------------------------- // // POINTINSTANCER // // -------------------------------------------------------------------------- // /// \class UsdGeomPointInstancer /// /// 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 /// \em 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 \em not a Gprim, since it is not a graphical /// primitive by any stretch of the imagination. It \em is, however, /// Boundable, since we will sometimes want to treat the entire PointInstancer /// similarly to a procedural, from the perspective of inclusion or framing. /// /// \section UsdGeomPointInstancer_varyingTopo 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 \em 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 /// \em 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 \em ids. /// /// We facilitate motion blur for varying-topology particle streams by /// optionally allowing per-instance \em velocities and \em 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 \em positions or \em orientations. /// If not authored, and the bracketing samples have the same length, then we /// will interpolate. /// /// \section UsdGeomPointInstancer_transform Computing an Instance Transform /// /// Each instance's transformation is a combination of the SRT affine transform /// described by its scale, orientation, and position, applied \em 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: /// /// 1. Apply (most locally) the authored transformation for /// prototypes[protoIndices[i]] /// 2. If *scales* is authored, next apply the scaling matrix from *scales[i]* /// 3. If *orientations* is authored: **if *angularVelocities* is authored**, /// first multiply *orientations[i]* by the unit quaternion derived by scaling /// *angularVelocities[i]* by the \ref UsdGeom_PITimeScaling "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*. /// 4. 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*. /// 5. 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 /// \ref UsdGeom_VelocityInterpolation . /// /// \anchor UsdGeom_PITimeScaling /// 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. /// /// Additionally, if *motion:velocityScale* is authored or inherited (see /// UsdGeomMotionAPI::ComputeVelocityScale()), it is used to scale both the /// velocity and angular velocity by a constant value during computation. The /// *motion:velocityScale* attribute is encoded by UsdGeomMotionAPI. /// /// 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 \ref UsdGeom_VelocityInterpolation . /// /// \section UsdGeomPointInstancer_primvars Primvars on PointInstancer /// /// \ref UsdGeomPrimvar "Primvars" authored on a PointInstancer prim should /// always be applied to each instance with \em 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 \em interpolation /// and \em elementSize of the primvar, as follows: /// \li constant or uniform : the entire authored value of the /// primvar should be applied exactly to each instance. /// \li varying, vertex, or faceVarying: the first /// \em elementSize elements of the authored primvar array should be assigned to /// instance zero, the second \em elementSize elements should be assigned to /// instance one, and so forth. /// /// /// \section UsdGeomPointInstancer_masking 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(). /// /// \note If a PointInstancer has no authored \em ids attribute, the masking /// features will still be available, with the integers specifying element /// position in the \em protoIndices array rather than ID. /// /// \subsection UsdGeomPointInstancer_inactiveIds InactiveIds: List-edited, Unvarying Masking /// /// The first masking feature encodes a list of IDs in a list-editable metadatum /// called \em inactiveIds, which, although it does not have any similar /// impact to stage population as \ref UsdPrim::SetActive() "prim activation", /// it shares with that feature that its application is uniform over all time. /// Because it is list-editable, we can \em sparsely add and remove instances /// from it in many layers. /// /// This sparse application pattern makes \em 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() /// /// \subsection UsdGeomPointInstancer_invisibleIds invisibleIds: Animatable Masking /// /// The second masking feature encodes a list of IDs in a time-varying /// Int64Array-valued UsdAttribute called \em invisibleIds , since it shares /// with \ref UsdGeomImageable::GetVisibilityAttr() "Imageable visibility" /// the ability to animate object visibility. /// /// Unlike \em inactiveIds, overriding a set of opinions for \em 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() /// /// \section UsdGeomPointInstancer_protoProcessing Processing and Not Processing Prototypes /// /// Any prim in the scenegraph can be targetted as a prototype by the /// \em 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 \em 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 /// \ref Usd_PrimSpecifiers "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, /// \code /// 01 def PointInstancer "Crowd_Mid" /// 02 { /// 03 rel prototypes = [ , ] /// 04 /// 05 over "Prototypes" /// 06 { /// 07 def "MaleThin_Business" ( /// 08 references = [@MaleGroupA/usd/MaleGroupA.usd@] /// 09 variants = { /// 10 string modelingVariant = "Thin" /// 11 string costumeVariant = "BusinessAttire" /// 12 } /// 13 ) /// 14 { ... } /// 15 /// 16 def "MaleThin_Casual" /// 17 ... /// 18 } /// 19 } /// \endcode /// /// class UsdGeomPointInstancer : public UsdGeomBoundable { public: /// Compile time constant representing what kind of schema this class is. /// /// \sa UsdSchemaType static const UsdSchemaType schemaType = UsdSchemaType::ConcreteTyped; /// Construct a UsdGeomPointInstancer on UsdPrim \p prim . /// Equivalent to UsdGeomPointInstancer::Get(prim.GetStage(), prim.GetPath()) /// for a \em valid \p prim, but will not immediately throw an error for /// an invalid \p prim explicit UsdGeomPointInstancer(const UsdPrim& prim=UsdPrim()) : UsdGeomBoundable(prim) { } /// Construct a UsdGeomPointInstancer on the prim held by \p schemaObj . /// Should be preferred over UsdGeomPointInstancer(schemaObj.GetPrim()), /// as it preserves SchemaBase state. explicit UsdGeomPointInstancer(const UsdSchemaBase& schemaObj) : UsdGeomBoundable(schemaObj) { } /// Destructor. USDGEOM_API virtual ~UsdGeomPointInstancer(); /// Return a vector of names of all pre-declared attributes for this schema /// class and all its ancestor classes. Does not include attributes that /// may be authored by custom/extended methods of the schemas involved. USDGEOM_API static const TfTokenVector & GetSchemaAttributeNames(bool includeInherited=true); /// Return a UsdGeomPointInstancer holding the prim adhering to this /// schema at \p path on \p stage. If no prim exists at \p path on /// \p stage, or if the prim at that path does not adhere to this schema, /// return an invalid schema object. This is shorthand for the following: /// /// \code /// UsdGeomPointInstancer(stage->GetPrimAtPath(path)); /// \endcode /// USDGEOM_API static UsdGeomPointInstancer Get(const UsdStagePtr &stage, const SdfPath &path); /// Attempt to ensure a \a UsdPrim adhering to this schema at \p path /// is defined (according to UsdPrim::IsDefined()) on this stage. /// /// If a prim adhering to this schema at \p path is already defined on this /// stage, return that prim. Otherwise author an \a SdfPrimSpec with /// \a specifier == \a SdfSpecifierDef and this schema's prim type name for /// the prim at \p path at the current EditTarget. Author \a SdfPrimSpec s /// with \p specifier == \a SdfSpecifierDef and empty typeName at the /// current EditTarget for any nonexistent, or existing but not \a Defined /// ancestors. /// /// The given \a path must be an absolute prim path that does not contain /// any variant selections. /// /// If it is impossible to author any of the necessary PrimSpecs, (for /// example, in case \a path cannot map to the current UsdEditTarget's /// namespace) issue an error and return an invalid \a UsdPrim. /// /// Note that this method may return a defined prim whose typeName does not /// specify this schema class, in case a stronger typeName opinion overrides /// the opinion at the current EditTarget. /// USDGEOM_API static UsdGeomPointInstancer Define(const UsdStagePtr &stage, const SdfPath &path); protected: /// Returns the type of schema this class belongs to. /// /// \sa UsdSchemaType USDGEOM_API UsdSchemaType _GetSchemaType() const override; private: // needs to invoke _GetStaticTfType. friend class UsdSchemaRegistry; USDGEOM_API static const TfType &_GetStaticTfType(); static bool _IsTypedSchema(); // override SchemaBase virtuals. USDGEOM_API const TfType &_GetTfType() const override; public: // --------------------------------------------------------------------- // // PROTOINDICES // --------------------------------------------------------------------- // /// Required property. Per-instance index into /// \em 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 | /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->IntArray | USDGEOM_API UsdAttribute GetProtoIndicesAttr() const; /// See GetProtoIndicesAttr(), and also /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create. /// If specified, author \p defaultValue as the attribute's default, /// sparsely (when it makes sense to do so) if \p writeSparsely is \c true - /// the default for \p writeSparsely is \c false. USDGEOM_API UsdAttribute CreateProtoIndicesAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const; public: // --------------------------------------------------------------------- // // IDS // --------------------------------------------------------------------- // /// Ids are optional; if authored, the ids array should be the same /// length as the \em 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 \ref UsdGeomPointInstancer_varyingTopo /// /// | || /// | -- | -- | /// | Declaration | `int64[] ids` | /// | C++ Type | VtArray | /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Int64Array | USDGEOM_API UsdAttribute GetIdsAttr() const; /// See GetIdsAttr(), and also /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create. /// If specified, author \p defaultValue as the attribute's default, /// sparsely (when it makes sense to do so) if \p writeSparsely is \c true - /// the default for \p writeSparsely is \c false. USDGEOM_API UsdAttribute CreateIdsAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const; public: // --------------------------------------------------------------------- // // POSITIONS // --------------------------------------------------------------------- // /// Required property. Per-instance position. See also /// \ref UsdGeomPointInstancer_transform . /// /// | || /// | -- | -- | /// | Declaration | `point3f[] positions` | /// | C++ Type | VtArray | /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Point3fArray | USDGEOM_API UsdAttribute GetPositionsAttr() const; /// See GetPositionsAttr(), and also /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create. /// If specified, author \p defaultValue as the attribute's default, /// sparsely (when it makes sense to do so) if \p writeSparsely is \c true - /// the default for \p writeSparsely is \c false. USDGEOM_API UsdAttribute CreatePositionsAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const; public: // --------------------------------------------------------------------- // // ORIENTATIONS // --------------------------------------------------------------------- // /// 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 \ref UsdGeomPointInstancer_transform . /// /// | || /// | -- | -- | /// | Declaration | `quath[] orientations` | /// | C++ Type | VtArray | /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->QuathArray | USDGEOM_API UsdAttribute GetOrientationsAttr() const; /// See GetOrientationsAttr(), and also /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create. /// If specified, author \p defaultValue as the attribute's default, /// sparsely (when it makes sense to do so) if \p writeSparsely is \c true - /// the default for \p writeSparsely is \c false. USDGEOM_API UsdAttribute CreateOrientationsAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const; public: // --------------------------------------------------------------------- // // SCALES // --------------------------------------------------------------------- // /// If authored, per-instance scale to be applied to /// each instance, before any rotation is applied. /// /// See also \ref UsdGeomPointInstancer_transform . /// /// | || /// | -- | -- | /// | Declaration | `float3[] scales` | /// | C++ Type | VtArray | /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Float3Array | USDGEOM_API UsdAttribute GetScalesAttr() const; /// See GetScalesAttr(), and also /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create. /// If specified, author \p defaultValue as the attribute's default, /// sparsely (when it makes sense to do so) if \p writeSparsely is \c true - /// the default for \p writeSparsely is \c false. USDGEOM_API UsdAttribute CreateScalesAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const; public: // --------------------------------------------------------------------- // // VELOCITIES // --------------------------------------------------------------------- // /// 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 \em protoIndices /// and \em 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 \ref UsdGeomPointInstancer_transform, /// \ref UsdGeom_VelocityInterpolation . /// /// | || /// | -- | -- | /// | Declaration | `vector3f[] velocities` | /// | C++ Type | VtArray | /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Vector3fArray | USDGEOM_API UsdAttribute GetVelocitiesAttr() const; /// See GetVelocitiesAttr(), and also /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create. /// If specified, author \p defaultValue as the attribute's default, /// sparsely (when it makes sense to do so) if \p writeSparsely is \c true - /// the default for \p writeSparsely is \c false. USDGEOM_API UsdAttribute CreateVelocitiesAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const; public: // --------------------------------------------------------------------- // // ACCELERATIONS // --------------------------------------------------------------------- // /// 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 | /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Vector3fArray | USDGEOM_API UsdAttribute GetAccelerationsAttr() const; /// See GetAccelerationsAttr(), and also /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create. /// If specified, author \p defaultValue as the attribute's default, /// sparsely (when it makes sense to do so) if \p writeSparsely is \c true - /// the default for \p writeSparsely is \c false. USDGEOM_API UsdAttribute CreateAccelerationsAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const; public: // --------------------------------------------------------------------- // // ANGULARVELOCITIES // --------------------------------------------------------------------- // /// If authored, per-instance angular velocity vector to be used for /// interoplating orientations. Angular velocities should be considered /// mandatory if both \em protoIndices and \em orientations are animated. /// Angular velocity is measured in degrees per second. To convert /// to degrees per UsdTimeCode, divide by /// UsdStage::GetTimeCodesPerSecond(). /// /// See also \ref UsdGeomPointInstancer_transform . /// /// | || /// | -- | -- | /// | Declaration | `vector3f[] angularVelocities` | /// | C++ Type | VtArray | /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Vector3fArray | USDGEOM_API UsdAttribute GetAngularVelocitiesAttr() const; /// See GetAngularVelocitiesAttr(), and also /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create. /// If specified, author \p defaultValue as the attribute's default, /// sparsely (when it makes sense to do so) if \p writeSparsely is \c true - /// the default for \p writeSparsely is \c false. USDGEOM_API UsdAttribute CreateAngularVelocitiesAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const; public: // --------------------------------------------------------------------- // // INVISIBLEIDS // --------------------------------------------------------------------- // /// A list of id's to make invisible at the evaluation time. /// See \ref UsdGeomPointInstancer_invisibleIds . /// /// | || /// | -- | -- | /// | Declaration | `int64[] invisibleIds = []` | /// | C++ Type | VtArray | /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Int64Array | USDGEOM_API UsdAttribute GetInvisibleIdsAttr() const; /// See GetInvisibleIdsAttr(), and also /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create. /// If specified, author \p defaultValue as the attribute's default, /// sparsely (when it makes sense to do so) if \p writeSparsely is \c true - /// the default for \p writeSparsely is \c false. USDGEOM_API UsdAttribute CreateInvisibleIdsAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const; public: // --------------------------------------------------------------------- // // PROTOTYPES // --------------------------------------------------------------------- // /// 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 \em protoIndices attribute to /// instance that prototype. Since relationships are uniform, this property /// cannot be animated. /// USDGEOM_API UsdRelationship GetPrototypesRel() const; /// See GetPrototypesRel(), and also /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create USDGEOM_API UsdRelationship CreatePrototypesRel() const; public: // ===================================================================== // // Feel free to add custom code below this line, it will be preserved by // the code generator. // // Just remember to: // - Close the class declaration with }; // - Close the namespace with PXR_NAMESPACE_CLOSE_SCOPE // - Close the include guard with #endif // ===================================================================== // // --(BEGIN CUSTOM CODE)-- // --------------------------------------------------------------------- // /// \name Id-based Instance Masking/Pruning /// See \ref UsdGeomPointInstancer_masking /// @{ // --------------------------------------------------------------------- // /// Ensure that the instance identified by \p id is active over all time. /// This activation is encoded sparsely, affecting no other instances. /// /// This does not guarantee that the instance will be rendered, because /// it may still be "invisible" due to \p id being present in the /// \em invisibleIds attribute (see VisId(), InvisId()) USDGEOM_API bool ActivateId(int64_t id) const; /// Ensure that the instances identified by \p ids are active over all time. /// This activation is encoded sparsely, affecting no other instances. /// /// This does not guarantee that the instances will be rendered, because /// each may still be "invisible" due to its presence in the /// \em invisibleIds attribute (see VisId(), InvisId()) USDGEOM_API bool ActivateIds(VtInt64Array const &ids) const; /// Ensure that all instances are active over all time. /// /// This does not guarantee that the instances will be rendered, because /// each may still be "invisible" due to its presence in the /// \em invisibleIds attribute (see VisId(), InvisId()) USDGEOM_API bool ActivateAllIds() const; /// Ensure that the instance identified by \p id is inactive over all time. /// This deactivation is encoded sparsely, affecting no other instances. /// /// A deactivated instance is guaranteed not to render if the renderer /// honors masking. USDGEOM_API bool DeactivateId(int64_t id) const; /// Ensure that the instances identified by \p ids are inactive over all time. /// This deactivation is encoded sparsely, affecting no other instances. /// /// A deactivated instance is guaranteed not to render if the renderer /// honors masking. USDGEOM_API bool DeactivateIds(VtInt64Array const &ids) const; /// Ensure that the instance identified by \p id is visible at \p time. /// This will cause \em invisibleIds to first be broken down (keyed) /// at \p time, causing all animation in weaker layers that the current /// UsdEditTarget to be overridden. Has no effect on any timeSamples other /// than the one at \p time. If the \em invisibleIds attribute is not /// authored or is blocked, this operation is a no-op. /// /// This does not guarantee that the instance will be rendered, because /// it may still be "inactive" due to \p id being present in the /// \em inactivevIds metadata (see ActivateId(), DeactivateId()) USDGEOM_API bool VisId(int64_t id, UsdTimeCode const &time) const; /// Ensure that the instances identified by \p ids are visible at \p time. /// This will cause \em invisibleIds to first be broken down (keyed) /// at \p time, causing all animation in weaker layers that the current /// UsdEditTarget to be overridden. Has no effect on any timeSamples other /// than the one at \p time. If the \em invisibleIds attribute is not /// authored or is blocked, this operation is a no-op. /// /// This does not guarantee that the instances will be rendered, because /// each may still be "inactive" due to \p id being present in the /// \em inactivevIds metadata (see ActivateId(), DeactivateId()) USDGEOM_API bool VisIds(VtInt64Array const &ids, UsdTimeCode const &time) const; /// Ensure that all instances are visible at \p time. /// Operates by authoring an empty array at \p time. /// /// This does not guarantee that the instances will be rendered, because /// each may still be "inactive" due to its id being present in the /// \em inactivevIds metadata (see ActivateId(), DeactivateId()) USDGEOM_API bool VisAllIds(UsdTimeCode const &time) const; /// Ensure that the instance identified by \p id is invisible at \p time. /// This will cause \em invisibleIds to first be broken down (keyed) /// at \p time, causing all animation in weaker layers that the current /// UsdEditTarget to be overridden. Has no effect on any timeSamples other /// than the one at \p time. /// /// An invised instance is guaranteed not to render if the renderer /// honors masking. USDGEOM_API bool InvisId(int64_t id, UsdTimeCode const &time) const; /// Ensure that the instances identified by \p ids are invisible at \p time. /// This will cause \em invisibleIds to first be broken down (keyed) /// at \p time, causing all animation in weaker layers that the current /// UsdEditTarget to be overridden. Has no effect on any timeSamples other /// than the one at \p time. /// /// An invised instance is guaranteed not to render if the renderer /// honors masking. USDGEOM_API bool InvisIds(VtInt64Array const &ids, UsdTimeCode const &time) const; /// Computes a presence mask to be applied to per-instance data arrays /// based on authored \em inactiveIds, \em invisibleIds, and \em ids . /// /// If no \em ids attribute has been authored, then the values in /// \em inactiveIds and \em invisibleIds will be interpreted directly /// as indices of \em protoIndices . /// /// If \p ids is non-NULL, it is assumed to be the id-mapping to apply, /// and must match the length of \em protoIndices at \p time . /// If NULL, we will call GetIdsAttr().Get(time) /// /// \note If all "live" instances at UsdTimeCode \p time pass the mask, /// we will return an empty mask so that clients can trivially /// recognize the common "no masking" case. /// /// The returned mask can be used with ApplyMaskToArray(), and will contain /// a \c true value for every element that should survive. USDGEOM_API std::vector ComputeMaskAtTime(UsdTimeCode time, VtInt64Array const *ids = nullptr) const; /// Contract \p dataArray in-place to contain only the elements whose /// index in \p mask is \c true. /// /// \note an empty \p mask specifies "all pass", in which case \p dataArray /// is trivially unmodified /// /// - It is an error for \p dataArray to be NULL . /// - If \em elementSize times \em mask.size() does not equal /// \em dataArray->size(), warn and fail. /// /// \return true on success, false on failure. /// \sa ComputeMaskAtTime() template static bool ApplyMaskToArray(std::vector const &mask, VtArray *dataArray, const int elementSize = 1); // --------------------------------------------------------------------- // /// @} // --------------------------------------------------------------------- // /// \enum ProtoXformInclusion /// /// Encodes whether to include each prototype's root prim's transformation /// as the most-local component of computed instance transforms. enum ProtoXformInclusion { IncludeProtoXform, //!< Include the transform on the proto's root ExcludeProtoXform //!< Exclude the transform on the proto's root }; /// \enum MaskApplication /// /// Encodes whether to evaluate and apply the PointInstancer's /// mask to computed results. /// \sa ComputeMaskAtTime() enum MaskApplication { ApplyMask, //!< Compute and apply the PointInstancer mask IgnoreMask //!< Ignore the PointInstancer mask }; /// Compute the per-instance, "PointInstancer relative" transforms given /// the positions, scales, orientations, velocities and angularVelocities /// at \p time, as described in \ref UsdGeomPointInstancer_transform . /// /// This will return \c false and leave \p xforms untouched if: /// - \p xforms is NULL /// - one of \p time and \p baseTime is numeric and the other is /// UsdTimeCode::Default() (they must either both be numeric or both be /// default) /// - there is no authored \em protoIndices attribute or \em positions /// attribute /// - the size of any of the per-instance attributes does not match the /// size of \em protoIndices /// - \p doProtoXforms is \c IncludeProtoXform but an index value in /// \em protoIndices is outside the range [0, prototypes.size()) /// - \p applyMask is \c ApplyMask and a mask is set but the size of the /// mask does not match the size of \em protoIndices. /// /// If there is no error, we will return \c true and \p xforms will contain /// the computed transformations. /// /// \param xforms - the out parameter for the transformations. Its size /// will depend on the authored data and \p applyMask /// \param time - UsdTimeCode at which we want to evaluate the transforms /// \param baseTime - required for correct interpolation between samples /// when \em velocities or \em angularVelocities are /// present. If there are samples for \em positions and /// \em velocities at t1 and t2, normal value resolution /// would attempt to interpolate between the two samples, /// and if they could not be interpolated because they /// differ in size (common in cases where velocity is /// authored), will choose the sample at t1. When /// sampling for the purposes of motion-blur, for example, /// it is common, when rendering the frame at t2, to /// sample at [ t2-shutter/2, t2+shutter/2 ] for a /// shutter interval of \em shutter. The first sample /// falls between t1 and t2, but we must sample at t2 /// and apply velocity-based interpolation based on those /// samples to get a correct result. In such scenarios, /// one should provide a \p baseTime of t2 when querying /// \em both samples. If your application does not care /// about off-sample interpolation, it can supply the /// same value for \p baseTime that it does for \p time. /// When \p baseTime is less than or equal to \p time, /// we will choose the lower bracketing timeSample. /// Selecting sample times with respect to baseTime will /// be performed independently for positions and /// orientations. /// \param doProtoXforms - specifies whether to include the root /// transformation of each instance's prototype in the /// instance's transform. Default is to include it, but /// some clients may want to apply the proto transform as /// part of the prototype itself, so they can specify /// \c ExcludeProtoXform instead. /// \param applyMask - specifies whether to apply ApplyMaskToArray() to the /// computed result. The default is \c ApplyMask. USDGEOM_API bool ComputeInstanceTransformsAtTime( VtArray* xforms, const UsdTimeCode time, const UsdTimeCode baseTime, const ProtoXformInclusion doProtoXforms = IncludeProtoXform, const MaskApplication applyMask = ApplyMask) const; /// Compute the per-instance transforms as in /// ComputeInstanceTransformsAtTime, but using multiple sample times. An /// array of matrix arrays is returned where each matrix array contains the /// instance transforms for the corresponding time in \p times . /// /// \param times - A vector containing the UsdTimeCodes at which we want to /// sample. USDGEOM_API bool ComputeInstanceTransformsAtTimes( std::vector>* xformsArray, const std::vector& times, const UsdTimeCode baseTime, const ProtoXformInclusion doProtoXforms = IncludeProtoXform, const MaskApplication applyMask = ApplyMask) const; /// \overload /// Perform the per-instance transform computation as described in /// \ref UsdGeomPointInstancer_transform . This does the same computation as /// the non-static ComputeInstanceTransformsAtTime method, but takes all /// data as parameters rather than accessing authored data. /// /// \param xforms - the out parameter for the transformations. Its size /// will depend on the given data and \p applyMask /// \param stage - the UsdStage /// \param time - time at which we want to evaluate the transforms /// \param protoIndices - array containing all instance prototype indices. /// \param positions - array containing all instance positions. This array /// must be the same size as \p protoIndices . /// \param velocities - array containing all instance velocities. This array /// must be either the same size as \p protoIndices or /// empty. If it is empty, transforms are computed as if /// all velocities were zero in all dimensions. /// \param velocitiesSampleTime - time at which the samples from /// \p velocities were taken. /// \param accelerations - array containing all instance accelerations. /// This array must be either the same size as /// \p protoIndicesor empty. If it is empty, transforms /// are computed as if all accelerations were zero in /// all dimensions. /// \param scales - array containing all instance scales. This array must be /// either the same size as \p protoIndices or empty. If it /// is empty, transforms are computed with no change in /// scale. /// \param orientations - array containing all instance orientations. This /// array must be either the same size as /// \p protoIndices or empty. If it is empty, /// transforms are computed with no change in /// orientation /// \param angularVelocities - array containing all instance angular /// velocities. This array must be either the /// same size as \p protoIndices or empty. If it /// is empty, transforms are computed as if all /// angular velocities were zero in all /// dimensions. /// \param angularVelocitiesSampleTime - time at which the samples from /// \p angularVelocities were taken. /// \param protoPaths - array containing the paths for all instance /// prototypes. If this array is not empty, prototype /// transforms are applied to the instance transforms. /// \param mask - vector containing a mask to apply to the computed result. /// This vector must be either the same size as /// \p protoIndices or empty. If it is empty, no mask is /// applied. /// \param velocityScale - factor used to artificially increase the effect /// of velocity and angular velocity on positions and /// orientations respectively. USDGEOM_API static bool ComputeInstanceTransformsAtTime( VtArray* xforms, UsdStageWeakPtr& stage, UsdTimeCode time, const VtIntArray& protoIndices, const VtVec3fArray& positions, const VtVec3fArray& velocities, UsdTimeCode velocitiesSampleTime, const VtVec3fArray& accelerations, const VtVec3fArray& scales, const VtQuathArray& orientations, const VtVec3fArray& angularVelocities, UsdTimeCode angularVelocitiesSampleTime, const SdfPathVector& protoPaths, const std::vector& mask, float velocityScale = 1.0); private: // Get the authored prototype paths. Fail if there are no authored prototype // paths or the prototype indices are out of bounds. bool _GetPrototypePathsForInstanceTransforms( const VtIntArray& protoIndices, SdfPathVector* protoPaths) const; // Get the authored prototype indices for instance transform computation. // Fail if prototype indices are not authored. bool _GetProtoIndicesForInstanceTransforms( UsdTimeCode baseTime, VtIntArray* protoIndices) const; // Fetches data from attributes specific to UsdGeomPointInstancer // required for instance transform calculations; this includes // protoIndices, protoPaths, and the mask. bool _ComputePointInstancerAttributesPreamble( const UsdTimeCode baseTime, const ProtoXformInclusion doProtoXforms, const MaskApplication applyMask, VtIntArray* protoIndices, SdfPathVector* protoPaths, std::vector* mask) const; public: /// Compute the extent of the point instancer based on the per-instance, /// "PointInstancer relative" transforms at \p time, as described in /// \ref UsdGeomPointInstancer_transform . /// /// If there is no error, we return \c true and \p extent will be the /// tightest bounds we can compute efficiently. If an error occurs, /// \c false will be returned and \p extent will be left untouched. /// /// For now, this uses a UsdGeomBBoxCache with the "default", "proxy", and /// "render" purposes. /// /// \param extent - the out parameter for the extent. On success, it will /// contain two elements representing the min and max. /// \param time - UsdTimeCode at which we want to evaluate the extent /// \param baseTime - required for correct interpolation between samples /// when \em velocities or \em angularVelocities are /// present. If there are samples for \em positions and /// \em velocities at t1 and t2, normal value resolution /// would attempt to interpolate between the two samples, /// and if they could not be interpolated because they /// differ in size (common in cases where velocity is /// authored), will choose the sample at t1. When /// sampling for the purposes of motion-blur, for example, /// it is common, when rendering the frame at t2, to /// sample at [ t2-shutter/2, t2+shutter/2 ] for a /// shutter interval of \em shutter. The first sample /// falls between t1 and t2, but we must sample at t2 /// and apply velocity-based interpolation based on those /// samples to get a correct result. In such scenarios, /// one should provide a \p baseTime of t2 when querying /// \em both samples. If your application does not care /// about off-sample interpolation, it can supply the /// same value for \p baseTime that it does for \p time. /// When \p baseTime is less than or equal to \p time, /// we will choose the lower bracketing timeSample. USDGEOM_API bool ComputeExtentAtTime( VtVec3fArray* extent, const UsdTimeCode time, const UsdTimeCode baseTime) const; /// \overload /// Computes the extent as if the matrix \p transform was first applied. USDGEOM_API bool ComputeExtentAtTime( VtVec3fArray* extent, const UsdTimeCode time, const UsdTimeCode baseTime, const GfMatrix4d& transform) const; /// Compute the extent of the point instancer as in /// \ref ComputeExtentAtTime , but across multiple \p times . This is /// equivalent to, but more efficient than, calling ComputeExtentAtTime /// several times. Each element in \p extents is the computed extent at the /// corresponding time in \p times . /// /// As in \ref ComputeExtentAtTime, if there is no error, we return \c true /// and \p extents will be the tightest bounds we can compute efficiently. /// If an error occurs computing the extent at any time, \c false will be /// returned and \p extents will be left untouched. /// /// \param times - A vector containing the UsdTimeCodes at which we want to /// sample. USDGEOM_API bool ComputeExtentAtTimes( std::vector* extents, const std::vector& times, const UsdTimeCode baseTime) const; /// \overload /// Computes the extent as if the matrix \p transform was first applied at /// each time. USDGEOM_API bool ComputeExtentAtTimes( std::vector* extents, const std::vector& times, const UsdTimeCode baseTime, const GfMatrix4d& transform) const; private: bool _ComputeExtentAtTimePreamble( UsdTimeCode baseTime, VtIntArray* protoIndices, std::vector* mask, UsdRelationship* prototypes, SdfPathVector* protoPaths) const; bool _ComputeExtentFromTransforms( VtVec3fArray* extent, const VtIntArray& protoIndices, const std::vector& mask, const UsdRelationship& prototypes, const SdfPathVector& protoPaths, const VtMatrix4dArray& instanceTransforms, UsdTimeCode time, const GfMatrix4d* transform) const; bool _ComputeExtentAtTime( VtVec3fArray* extent, const UsdTimeCode time, const UsdTimeCode baseTime, const GfMatrix4d* transform) const; bool _ComputeExtentAtTimes( std::vector* extent, const std::vector& times, const UsdTimeCode baseTime, const GfMatrix4d* transform) const; }; template bool UsdGeomPointInstancer::ApplyMaskToArray(std::vector const &mask, VtArray *dataArray, const int elementSize) { if (!dataArray) { TF_CODING_ERROR("NULL dataArray."); return false; } size_t maskSize = mask.size(); if (maskSize == 0 || dataArray->size() == (size_t)elementSize){ return true; } else if ((maskSize * elementSize) != dataArray->size()){ TF_WARN("Input mask's size (%zu) is not compatible with the " "input dataArray (%zu) and elementSize (%d).", maskSize, dataArray->size(), elementSize); return false; } T* beginData = dataArray->data(); T* currData = beginData; size_t numPreserved = 0; for (size_t i = 0; i < maskSize; ++i) { // XXX Could add a fast-path for elementSize == 1 ? if (mask[i]) { for (int j = 0; j < elementSize; ++j) { *currData = beginData[i + j]; ++currData; } numPreserved += elementSize; } } if (numPreserved < dataArray->size()) { dataArray->resize(numPreserved); } return true; } /// Returns true if list ops should be composed with SdfListOp::ApplyOperations() /// Returns false if list ops should be composed with SdfListOp::ComposeOperations(). USDGEOM_API bool UsdGeomPointInstancerApplyNewStyleListOps(); /// Applies a list operation of type \p op using \p items /// over the existing list operation on \p prim with the name /// \p metadataName. USDGEOM_API bool UsdGeomPointInstancerSetOrMergeOverOp(std::vector const &items, SdfListOpType op, UsdPrim const &prim, TfToken const &metadataName); PXR_NAMESPACE_CLOSE_SCOPE #endif