7#ifndef EXT_RMANPKG_25_0_PLUGIN_RENDERMAN_PLUGIN_HD_PRMAN_GPRIM_H
8#define EXT_RMANPKG_25_0_PLUGIN_RENDERMAN_PLUGIN_HD_PRMAN_GPRIM_H
14#include "hdPrman/gprimbase.h"
15#include "hdPrman/renderParam.h"
16#include "hdPrman/instancer.h"
17#include "hdPrman/material.h"
18#include "hdPrman/rixStrings.h"
19#include "hdPrman/utils.h"
23PXR_NAMESPACE_OPEN_SCOPE
27template <
typename BASE>
31 using BaseType = BASE;
43 HdPrman_RenderParam *param =
44 static_cast<HdPrman_RenderParam*
>(renderParam);
45 const SdfPath&
id = BASE::GetId();
46 riley::Riley *riley = param->AcquireRiley();
49 param->ReleaseCoordSysBindings(
id);
52 for (
const auto &instId: _instanceIds) {
53 if (instId != riley::GeometryInstanceId::InvalidId()) {
54 riley->DeleteGeometryInstance(
55 riley::GeometryPrototypeId::InvalidId(), instId);
61 if (HdPrmanInstancer* instancer = param->GetInstancer(
62 BASE::GetInstancerId())) {
63 instancer->Depopulate(renderParam,
id);
66 for (
const auto &protoId: _prototypeIds) {
67 if (protoId != riley::GeometryPrototypeId::InvalidId()) {
68 riley->DeleteGeometryPrototype(protoId);
71 _prototypeIds.clear();
76 HdDirtyBits* dirtyBits,
77 TfToken const &reprToken)
override;
80 HdDirtyBits GetInitialDirtyBitsMask()
const override = 0;
83 _PropagateDirtyBits(HdDirtyBits bits)
const override
90 _InitRepr(
TfToken const &reprToken,
91 HdDirtyBits *dirtyBits)
override
108 virtual riley::MaterialId
109 _GetFallbackMaterial(HdPrman_RenderParam *renderParam)
111 return renderParam->GetFallbackMaterialId();
115 virtual RtPrimVarList
116 _ConvertGeometry(HdPrman_RenderParam *renderParam,
120 std::vector<HdGeomSubset> *geomSubsets) = 0;
128template <
typename BASE>
132 HdDirtyBits* dirtyBits,
136 HF_MALLOC_TAG_FUNCTION();
142 static const HdDirtyBits internalDirtyBits =
143 HdChangeTracker::InitRepr |
144 HdChangeTracker::Varying |
145 HdChangeTracker::NewRepr |
146 HdChangeTracker::CustomBitsMask;
148 *dirtyBits &= ~(HdChangeTracker::NewRepr | HdChangeTracker::CustomBitsMask);
151 if (((*dirtyBits & ~internalDirtyBits)
152 & HdChangeTracker::AllSceneDirtyBits) == 0) {
156 HdPrman_RenderParam *param =
157 static_cast<HdPrman_RenderParam*
>(renderParam);
160 riley::Riley *riley = param->AcquireRiley();
163 BASE::_UpdateInstancer(sceneDelegate, dirtyBits);
166 SdfPath const&
id = BASE::GetId();
167 SdfPath const& instancerId = BASE::GetInstancerId();
168 const bool isHdInstance = !instancerId.
IsEmpty();
175 const int32_t primId = BASE::GetPrimId() + 1;
183 BASE::_UpdateVisibility(sceneDelegate, dirtyBits);
187 if (*dirtyBits & HdChangeTracker::DirtyMaterialId) {
188#if HD_API_VERSION < 37
189 BASE::_SetMaterialId(sceneDelegate->
GetRenderIndex().GetChangeTracker(),
195 riley::MaterialId materialId = _GetFallbackMaterial(param);
196 riley::DisplacementId dispId = riley::DisplacementId::InvalidId();
197 const SdfPath & hdMaterialId = BASE::GetMaterialId();
198 HdPrman_ResolveMaterial(sceneDelegate, hdMaterialId, riley, &materialId, &dispId);
201 riley::CoordinateSystemList coordSysList = {0,
nullptr};
202 if (HdPrman_RenderParam::RileyCoordSysIdVecRefPtr convertedCoordSys =
203 param->ConvertAndRetainCoordSysBindings(sceneDelegate,
id)) {
204 coordSysList.count = convertedCoordSys->size();
205 coordSysList.ids = convertedCoordSys->data();
211 static const HdDirtyBits prmanProtoAttrBits =
212 HdChangeTracker::DirtyPoints |
213 HdChangeTracker::DirtyNormals |
214 HdChangeTracker::DirtyWidths |
215 HdChangeTracker::DirtyTopology;
219 static const HdDirtyBits prmanInstAttrBits =
220 HdChangeTracker::DirtyMaterialId |
221 HdChangeTracker::DirtyTransform |
222 HdChangeTracker::DirtyVisibility |
223 HdChangeTracker::DirtyDoubleSided |
224 HdChangeTracker::DirtySubdivTags |
225 HdChangeTracker::DirtyVolumeField |
226 HdChangeTracker::DirtyCategories |
227 HdChangeTracker::DirtyPrimvar;
232 std::vector<riley::MaterialId> subsetMaterialIds;
233 std::vector<SdfPath> subsetPaths;
236 HdGeomSubsets geomSubsets;
237 RtPrimVarList primvars = _ConvertGeometry(param, sceneDelegate,
id,
238 &primType, &geomSubsets);
241 HdPrman_TransferMaterialPrimvarOpinions(sceneDelegate, hdMaterialId,
245 const size_t oldCount = _prototypeIds.size();
246 const size_t newCount = std::max((
size_t) 1, geomSubsets.size());
247 if (newCount != oldCount) {
248 for (
const auto &oldPrototypeId: _prototypeIds) {
249 if (oldPrototypeId != riley::GeometryPrototypeId::InvalidId()) {
250 riley->DeleteGeometryPrototype(oldPrototypeId);
253 _prototypeIds.resize(newCount,
254 riley::GeometryPrototypeId::InvalidId());
258 if (geomSubsets.empty()) {
262 primvars.SetString(RixStr.k_stats_prototypeIdentifier,
263 RtUString(primPath.
GetText()));
264 if (_prototypeIds[0] == riley::GeometryPrototypeId::InvalidId()) {
266 _prototypeIds[0] = riley->CreateGeometryPrototype(
268 stats::AddDataLocation(primPath.
GetText()).GetValue()),
269 primType, dispId, primvars);
270 }
else if (*dirtyBits & prmanProtoAttrBits) {
272 riley->ModifyGeometryPrototype(primType, _prototypeIds[0],
280 subsetMaterialIds.reserve(geomSubsets.size());
283 subsetPaths.reserve(geomSubsets.size());
285 for (
size_t j=0; j < geomSubsets.size(); ++j) {
286 auto& prototypeId = _prototypeIds[j];
290 std::vector<int32_t> int32Indices(subset.
indices.cbegin(),
292 primvars.SetIntegerArray(RixStr.k_shade_faceset,
294 int32Indices.size());
296 riley::MaterialId subsetMaterialId = materialId;
297 riley::DisplacementId subsetDispId = dispId;
301 HdPrman_ResolveMaterial(sceneDelegate, subset.
materialId,
302 riley, &subsetMaterialId, &subsetDispId);
303 subsetMaterialIds.push_back(subsetMaterialId);
307 subsetPaths.push_back(subsetPath);
308 primvars.SetString(RixStr.k_stats_prototypeIdentifier,
309 RtUString(subsetPath.
GetText()));
311 if (prototypeId == riley::GeometryPrototypeId::InvalidId()) {
314 riley->CreateGeometryPrototype(
316 stats::AddDataLocation(subsetPath.
GetText()).GetValue()),
317 primType, dispId, primvars);
318 }
else if (*dirtyBits & prmanProtoAttrBits) {
320 riley->ModifyGeometryPrototype(primType, prototypeId,
321 &subsetDispId, &primvars);
325 *dirtyBits &= ~prmanProtoAttrBits;
331 if (_PrototypeOnly()) {
341 RtParamList attrs = param->ConvertAttributes(sceneDelegate,
id,
true);
344 attrs.SetInteger(RixStr.k_identifier_id, primId);
350 for (
size_t i=0; i < xf.count; ++i) {
351 xf_rt[i] = HdPrman_Utils::GfMatrixToRtMatrix(xf.values[i]);
353 const riley::Transform xform = {
360 attrs.SetInteger(RixStr.k_identifier_id2, 0);
363 const size_t oldCount = _instanceIds.size();
364 const size_t newCount = _prototypeIds.size();
365 if (newCount != oldCount) {
366 for (
const auto &oldInstanceId: _instanceIds) {
367 if (oldInstanceId != riley::GeometryInstanceId::InvalidId()) {
368 riley->DeleteGeometryInstance(
369 riley::GeometryPrototypeId::InvalidId(), oldInstanceId);
374 riley::GeometryInstanceId::InvalidId());
379 TF_VERIFY(_instanceIds.size() == _prototypeIds.size());
380 for (
size_t j=0; j < _prototypeIds.size(); ++j) {
381 auto const& prototypeId = _prototypeIds[j];
382 auto& instanceId = _instanceIds[j];
383 auto instanceMaterialId = materialId;
384 RtParamList finalAttrs = attrs;
387 SdfPath* subsetPath(&primPath);
388 if (!subsetPaths.empty()) {
389 subsetPath = &subsetPaths[j];
392 finalAttrs.SetString(RixStr.k_identifier_name,
393 RtUString(subsetPath->
GetText()));
396 if (!subsetMaterialIds.empty()) {
398 instanceMaterialId = subsetMaterialIds[j];
402 param->AddRenderTagToGroupingMembership(
405 if (instanceId == riley::GeometryInstanceId::InvalidId()) {
407 instanceId = riley->CreateGeometryInstance(
409 stats::AddDataLocation(subsetPath->
GetText()).GetValue()),
410 riley::GeometryPrototypeId::InvalidId(), prototypeId,
411 instanceMaterialId, coordSysList, xform, finalAttrs);
412 }
else if (*dirtyBits & prmanInstAttrBits) {
414 riley->ModifyGeometryInstance(
415 riley::GeometryPrototypeId::InvalidId(),
416 instanceId, &instanceMaterialId, &coordSysList, &xform,
420 *dirtyBits &= ~prmanInstAttrBits;
421 }
else if ((*dirtyBits & prmanInstAttrBits)
438 HdInstancer::_SyncInstancerAndParents(renderIndex, instancerId);
440 if (subsetMaterialIds.size() == 0) {
441 subsetMaterialIds.push_back(materialId);
443 if (subsetPaths.size() == 0) {
444 subsetPaths.push_back(primPath);
446 TF_VERIFY(_prototypeIds.size() == subsetMaterialIds.size() &&
447 _prototypeIds.size() == subsetPaths.size(),
448 "size mismatch (%lu, %lu, %lu)\n", _prototypeIds.size(),
449 subsetMaterialIds.size(), subsetPaths.size());
452 HdPrmanInstancer *instancer =
static_cast<HdPrmanInstancer*
>(
469PXR_NAMESPACE_CLOSE_SCOPE
Tracks changes from the HdSceneDelegate, providing invalidation cues to the render engine.
static HD_API bool IsInstancerDirty(HdDirtyBits dirtyBits, SdfPath const &id)
Returns true if the dirtyBits has a dirty instancer. id is for perflog.
HD_API bool IsVisibilityDirty(SdfPath const &id)
Returns true if the rprim identified by id has dirty visibility.
A common base class for HdPrman_Gprim types.
A mix-in template that adds shared gprim behavior to support various HdRprim types.
The Hydra render index is a flattened representation of the client scene graph, which may be composed...
HD_API HdInstancer * GetInstancer(SdfPath const &id) const
Returns the instancer of id.
The HdRenderParam is an opaque (to core Hydra) handle, to an object that is obtained from the render ...
Adapter class providing data exchange with the client scene graph.
virtual HD_API TfToken GetRenderTag(SdfPath const &id)
Returns the render tag that will be used to bucket prims during render pass bucketing.
virtual HD_API SdfPath GetMaterialId(SdfPath const &rprimId)
Returns the material ID bound to the rprim rprimId.
virtual HD_API size_t SampleTransform(SdfPath const &id, size_t maxSampleCount, float *sampleTimes, GfMatrix4d *sampleValues)
Store up to maxSampleCount transform samples in *sampleValues.
HdRenderIndex & GetRenderIndex()
Returns the RenderIndex owned by this delegate.
virtual HD_API SdfPath GetScenePrimPath(SdfPath const &rprimId, int instanceIndex, HdInstancerContext *instancerContext=nullptr)
Returns the scene address of the prim corresponding to the given rprim/instance index.
A path value used to locate objects in layers or scenegraphs.
SDF_API const char * GetText() const
Returns the string representation of this path as a c string.
bool IsEmpty() const noexcept
Returns true if this is the empty path (SdfPath::EmptyPath()).
This is a small-vector class with local storage optimization, the local storage can be specified via ...
value_type * data()
Direct access to the underlying array.
Token for efficient comparison, assignment, and hashing of known strings.
#define TF_VERIFY(cond, format,...)
Checks a condition and reports an error if it evaluates false.
#define TF_UNUSED(x)
Stops compiler from producing unused argument or variable warnings.
Describes a subset of a piece of geometry as a set of indices.
VtIntArray indices
The list of element indices contained in the subset.
SdfPath id
The path used to identify this subset in the scene.
SdfPath materialId
The path used to identify this material bound to the subset.
An array of a value sampled over time, in struct-of-arrays layout.
#define TRACE_SCOPE(name)
Records a timestamp when constructed and a timespan event when destructed, using name as the key.