Loading...
Searching...
No Matches
gprim.h
1//
2// Copyright 2019 Pixar
3//
4// Licensed under the terms set forth in the LICENSE.txt file available at
5// https://openusd.org/license.
6//
7#ifndef EXT_RMANPKG_PLUGIN_RENDERMAN_PLUGIN_HD_PRMAN_GPRIM_H
8#define EXT_RMANPKG_PLUGIN_RENDERMAN_PLUGIN_HD_PRMAN_GPRIM_H
9
10#include "pxr/pxr.h"
11#include "pxr/imaging/hd/version.h"
12#include "pxr/usd/sdf/types.h"
14
15#include "hdPrman/gprimbase.h"
16#include "hdPrman/renderParam.h"
17#include "hdPrman/instancer.h"
18#include "hdPrman/material.h"
19#include "hdPrman/rixStrings.h"
20#include "hdPrman/utils.h"
21
22#include "Riley.h"
23
24PXR_NAMESPACE_OPEN_SCOPE
25
28template <typename BASE>
29class HdPrman_Gprim : public BASE, public HdPrman_GprimBase
30{
31public:
32 using BaseType = BASE;
33
34 HdPrman_Gprim(SdfPath const& id)
35 : BaseType(id)
36 {
37 }
38
39 ~HdPrman_Gprim() override = default;
40
41 void
42 Finalize(HdRenderParam *renderParam) override
43 {
44 HdPrman_RenderParam *param =
45 static_cast<HdPrman_RenderParam*>(renderParam);
46 const SdfPath& id = BASE::GetId();
47 riley::Riley *riley = param->AcquireRiley();
48 if (!riley) {
49 return;
50 }
51
52 // Release retained conversions of coordSys bindings.
53 param->ReleaseCoordSysBindings(id);
54
55 // Delete instances before deleting the prototypes they use.
56 for (const auto &instId: _instanceIds) {
57 if (instId != riley::GeometryInstanceId::InvalidId()) {
58 riley->DeleteGeometryInstance(
59 riley::GeometryPrototypeId::InvalidId(), instId);
60 }
61 }
62 _instanceIds.clear();
63
64 // delete instances owned by the instancer.
65 if (HdPrmanInstancer* instancer = param->GetInstancer(
66 BASE::GetInstancerId())) {
67 instancer->Depopulate(renderParam, id);
68 }
69
70 for (const auto &protoId: _prototypeIds) {
71 if (protoId != riley::GeometryPrototypeId::InvalidId()) {
72 riley->DeleteGeometryPrototype(protoId);
73 }
74 }
75 _prototypeIds.clear();
76 }
77
78 void Sync(HdSceneDelegate* sceneDelegate,
79 HdRenderParam* renderParam,
80 HdDirtyBits* dirtyBits,
81 TfToken const &reprToken) override;
82
83protected:
84 HdDirtyBits GetInitialDirtyBitsMask() const override = 0;
85
86 HdDirtyBits
87 _PropagateDirtyBits(HdDirtyBits bits) const override
88 {
89 // By default, just return the same dirty bits we recieved.
90 return bits;
91 }
92
93 void
94 _InitRepr(TfToken const &reprToken,
95 HdDirtyBits *dirtyBits) override
96 {
97 TF_UNUSED(reprToken);
98 TF_UNUSED(dirtyBits);
99 // No-op
100 }
101
102 // We override this member function in mesh.cpp to support the creation
103 // of mesh light prototype geometry.
104 virtual bool
105 _PrototypeOnly()
106 {
107 return false;
108 }
109
110 // Provide a fallback material. Default grabs _fallbackMaterial
111 // from the context.
112 virtual riley::MaterialId
113 _GetFallbackMaterial(HdPrman_RenderParam *renderParam)
114 {
115 return renderParam->GetFallbackMaterialId();
116 }
117
118 // Populate primType, primvars, and geometry subsets.
119 // Returns true if successful.
120 virtual bool
121 _ConvertGeometry(
122 HdPrman_RenderParam *renderParam,
123 HdSceneDelegate *sceneDelegate,
124 const SdfPath &id,
125 RtUString *primType,
126 RtPrimVarList *primvars,
127 std::vector<HdGeomSubset> *geomSubsets,
128 std::vector<RtPrimVarList> *geomSubsetPrimvars) = 0;
129
130 // Allow subclasses to inject additional geometry primvars.
131 virtual void
132 _AddPrimvars(RtPrimVarList*) const
133 {
134 // Add nothing by default.
135 }
136
137 // Allow subclasses to contribute additional coordinate system IDs.
138 virtual const std::vector<riley::CoordinateSystemId>&
139 _GetAdditionalCoordSysIds() const
140 {
141 static const std::vector<riley::CoordinateSystemId> empty;
142 return empty;
143 }
144
145 // This class does not support copying.
146 HdPrman_Gprim(const HdPrman_Gprim&) = delete;
147 HdPrman_Gprim &operator =(const HdPrman_Gprim&) = delete;
148
149};
150
151template <typename BASE>
152void
154 HdRenderParam* renderParam,
155 HdDirtyBits* dirtyBits,
156 TfToken const &reprToken)
157{
158 HD_TRACE_FUNCTION();
159 HF_MALLOC_TAG_FUNCTION();
160 TF_UNUSED(reprToken);
161
162 // Check if there are any relevant dirtyBits.
163 // (See the HdChangeTracker::MarkRprimDirty() note regarding
164 // internalDirtyBits used for internal signaling in Hydra.)
165 static const HdDirtyBits internalDirtyBits =
166 HdChangeTracker::InitRepr |
167 HdChangeTracker::Varying |
168 HdChangeTracker::NewRepr |
169 HdChangeTracker::CustomBitsMask;
170 // HdPrman does not make use of the repr concept or customBits.
171 *dirtyBits &= ~(HdChangeTracker::NewRepr | HdChangeTracker::CustomBitsMask);
172 // If no relevant dirtyBits remain, return early to avoid acquiring write
173 // access to Riley, which requires a pause and restart of rendering.
174 if (((*dirtyBits & ~internalDirtyBits)
175 & HdChangeTracker::AllSceneDirtyBits) == 0) {
176 return;
177 }
178
179 HdPrman_RenderParam *param =
180 static_cast<HdPrman_RenderParam*>(renderParam);
181
182 // Riley API.
183 riley::Riley *riley = param->AcquireRiley();
184
185 // Update instance bindings.
186 BASE::_UpdateInstancer(sceneDelegate, dirtyBits);
187
188 // Prim id
189 SdfPath const& id = BASE::GetId();
190 SdfPath const& instancerId = BASE::GetInstancerId();
191 const bool isHdInstance = !instancerId.IsEmpty();
192 SdfPath primPath = sceneDelegate->GetScenePrimPath(id, 0, nullptr);
193
194 // Prman has a default value for identifier:id of 0 (in case of ray miss),
195 // while Hydra treats id -1 as the clear value. We map Prman primId as
196 // (Hydra primId + 1) to get around this, here and in
197 // hdPrman/framebuffer.cpp.
198 const int32_t primId = BASE::GetPrimId() + 1;
199
200 // Sample transform
202 sceneDelegate->SampleTransform(id,
203#if HD_API_VERSION >= 68
204 param->GetShutterInterval()[0],
205 param->GetShutterInterval()[1],
206#endif
207 &xf);
208
209 // Update visibility so thet rprim->IsVisible() will work in render pass
210 if (HdChangeTracker::IsVisibilityDirty(*dirtyBits, id)) {
211 BASE::_UpdateVisibility(sceneDelegate, dirtyBits);
212 }
213
214 // Resolve material binding. Default to fallbackGprimMaterial.
215 if (*dirtyBits & HdChangeTracker::DirtyMaterialId) {
216#if HD_API_VERSION < 37
217 BASE::_SetMaterialId(sceneDelegate->GetRenderIndex().GetChangeTracker(),
218 sceneDelegate->GetMaterialId(id));
219#else
220 BASE::SetMaterialId(sceneDelegate->GetMaterialId(id));
221#endif
222 }
223 riley::MaterialId materialId = _GetFallbackMaterial(param);
224 riley::DisplacementId dispId = riley::DisplacementId::InvalidId();
225 const SdfPath & hdMaterialId = BASE::GetMaterialId();
226 HdPrman_ResolveMaterial(sceneDelegate, hdMaterialId, riley, &materialId, &dispId);
227
228 // Convert (and cache) coordinate systems.
229 riley::CoordinateSystemList coordSysList = {0, nullptr};
230 std::vector<riley::CoordinateSystemId> allCoordSysIds;
231 if (HdPrman_RenderParam::RileyCoordSysIdVecRefPtr convertedCoordSys =
232 param->ConvertAndRetainCoordSysBindings(sceneDelegate, id)) {
233 allCoordSysIds.insert(allCoordSysIds.end(),
234 convertedCoordSys->begin(),
235 convertedCoordSys->end());
236 }
237 // Append any additional coordinate system IDs from subclasses.
238 const auto& additionalCoordSysIds = _GetAdditionalCoordSysIds();
239 allCoordSysIds.insert(allCoordSysIds.end(),
240 additionalCoordSysIds.begin(),
241 additionalCoordSysIds.end());
242 coordSysList.count = allCoordSysIds.size();
243 coordSysList.ids = allCoordSysIds.data();
244
245 // Hydra dirty bits corresponding to PRMan prototype attributes (also called
246 // "primitive variables" but not synonymous with USD primvars). See prman
247 // docs at https://rmanwiki.pixar.com/display/REN24/Primitive+Variables.
248 static const HdDirtyBits prmanProtoAttrBits =
249 HdChangeTracker::DirtyPoints |
250 HdChangeTracker::DirtyNormals |
251 HdChangeTracker::DirtyWidths |
252 HdChangeTracker::DirtyVolumeField |
253 HdChangeTracker::DirtyTopology |
254 HdChangeTracker::DirtyPrimvar;
255
256 // Hydra dirty bits corresponding to prman instance attributes. See prman
257 // docs at https://rmanwiki.pixar.com/display/REN24/Instance+Attributes.
258 static const HdDirtyBits prmanInstAttrBits =
259 HdChangeTracker::DirtyMaterialId |
260 HdChangeTracker::DirtyTransform |
261 HdChangeTracker::DirtyVisibility |
262 HdChangeTracker::DirtyDoubleSided |
263 HdChangeTracker::DirtySubdivTags |
264 HdChangeTracker::DirtyVolumeField |
265 HdChangeTracker::DirtyCategories |
266 HdChangeTracker::DirtyPrimvar;
267
268 // These two bitmasks intersect, so we check them against dirtyBits
269 // prior to clearing either mask.
270 const bool prmanProtoAttrBitsWereSet(*dirtyBits & prmanProtoAttrBits);
271 const bool prmanInstAttrBitsWereSet(*dirtyBits & prmanInstAttrBits);
272
273 //
274 // Create or modify Riley geometry prototype(s).
275 //
276 std::vector<riley::MaterialId> subsetMaterialIds;
277 std::vector<SdfPath> subsetPaths;
278 {
279 RtUString primType;
280 RtPrimVarList primvars;
281 HdGeomSubsets geomSubsets;
282 std::vector<RtPrimVarList> geomSubsetPrimvars;
283 bool ok = _ConvertGeometry(param, sceneDelegate, id,
284 &primType, &primvars,
285 &geomSubsets, &geomSubsetPrimvars);
286 if (!ok) {
287 // We expect a specific error will have already been issued.
288 return;
289 }
290
291 // identifier:object is useful for cryptomatte
292 primvars.SetString(RixStr.k_identifier_object,
293 RtUString(id.GetName().c_str()));
294 for (size_t i=0, n=geomSubsets.size(); i<n; ++i) {
295 primvars.SetString(RixStr.k_identifier_object,
296 RtUString(geomSubsets[i].id.GetName().c_str()));
297 }
298
299// In 2311 and beyond, we can use
300// HdPrman_PreviewSurfacePrimvarsSceneIndexPlugin.
301#if PXR_VERSION < 2311
302 // Transfer material opinions of primvars.
303 HdPrman_TransferMaterialPrimvarOpinions(sceneDelegate, hdMaterialId,
304 primvars);
305#endif // PXR_VERSION < 2311
306
307 // Adjust _prototypeIds array.
308 const size_t oldCount = _prototypeIds.size();
309 const size_t newCount = std::max((size_t) 1, geomSubsets.size());
310 if (newCount != oldCount) {
311 for (const auto &oldPrototypeId: _prototypeIds) {
312 if (oldPrototypeId != riley::GeometryPrototypeId::InvalidId()) {
313 riley->DeleteGeometryPrototype(oldPrototypeId);
314 }
315 }
316 _prototypeIds.resize(newCount,
317 riley::GeometryPrototypeId::InvalidId());
318 }
319
320 _AddPrimvars(&primvars);
321
322 // Update Riley geom prototypes.
323 if (geomSubsets.empty()) {
324 // Common case: no subsets.
325 TF_VERIFY(newCount == 1);
326 TF_VERIFY(_prototypeIds.size() == 1);
327 primvars.SetString(RixStr.k_stats_prototypeIdentifier,
328 RtUString(primPath.GetText()));
329 if (_prototypeIds[0] == riley::GeometryPrototypeId::InvalidId()) {
330 TRACE_SCOPE("riley::CreateGeometryPrototype");
331 _prototypeIds[0] = riley->CreateGeometryPrototype(
332 riley::UserId(
333 stats::AddDataLocation(primPath.GetText()).GetValue()),
334 primType, dispId, primvars);
335 } else if (prmanProtoAttrBitsWereSet) {
336 TRACE_SCOPE("riley::ModifyGeometryPrototype");
337 riley->ModifyGeometryPrototype(primType, _prototypeIds[0],
338 &dispId, &primvars);
339 }
340 } else {
341 // Subsets case.
342 // We resolve materials here, and hold them in subsetMaterialIds:
343 // Displacement networks are passed to the geom prototype;
344 // material networks are passed to the instances.
345 subsetMaterialIds.reserve(geomSubsets.size());
346
347 // We also cache the subset paths for re-use when creating
348 // the instances
349 subsetPaths.reserve(geomSubsets.size());
350
351 for (size_t j=0; j < geomSubsets.size(); ++j) {
352 auto& prototypeId = _prototypeIds[j];
353 HdGeomSubset &subset = geomSubsets[j];
354 RtPrimVarList &subsetPrimvars = geomSubsetPrimvars[j];
355
356 // Convert indices to int32_t and set as k_shade_faceset.
357 std::vector<int32_t> int32Indices(subset.indices.cbegin(),
358 subset.indices.cend());
359 subsetPrimvars.SetIntegerArray(RixStr.k_shade_faceset,
360 int32Indices.data(),
361 int32Indices.size());
362 // Look up material override for the subset (if any)
363 riley::MaterialId subsetMaterialId = materialId;
364 riley::DisplacementId subsetDispId = dispId;
365 if (subset.materialId.IsEmpty()) {
366 subset.materialId = hdMaterialId;
367 }
368 HdPrman_ResolveMaterial(
369 sceneDelegate, subset.materialId,
370 riley, &subsetMaterialId, &subsetDispId);
371 subsetMaterialIds.push_back(subsetMaterialId);
372
373 // Look up the path for the subset
374 const SdfPath subsetPath =
375 sceneDelegate->GetScenePrimPath(subset.id, 0, nullptr);
376 subsetPaths.push_back(subsetPath);
377 subsetPrimvars.SetString(
378 RixStr.k_stats_prototypeIdentifier,
379 RtUString(subsetPath.GetText()));
380
381 if (prototypeId == riley::GeometryPrototypeId::InvalidId()) {
382 TRACE_SCOPE("riley::CreateGeometryPrototype");
383 prototypeId =
384 riley->CreateGeometryPrototype(
385 riley::UserId(
386 stats::AddDataLocation(
387 subsetPath.GetText()).GetValue()),
388 primType, subsetDispId, subsetPrimvars);
389 } else if (prmanProtoAttrBitsWereSet) {
390 TRACE_SCOPE("riley::ModifyGeometryPrototype");
391 riley->ModifyGeometryPrototype(
392 primType, prototypeId,
393 &subsetDispId, &subsetPrimvars);
394 }
395 }
396 }
397 *dirtyBits &= ~prmanProtoAttrBits;
398 }
399
400 //
401 // Stop here, or also create geometry instances?
402 //
403 if (_PrototypeOnly()) {
404 *dirtyBits &= ~HdChangeTracker::AllSceneDirtyBits;
405 return;
406 }
407
408 //
409 // Create or modify Riley geometry instances.
410 //
411
412 // Resolve attributes.
413 RtParamList attrs = param->ConvertAttributes(sceneDelegate, id, true);
414
415 // Add "identifier:id" with the prim id.
416 attrs.SetInteger(RixStr.k_identifier_id, primId);
417
418 // user:__materialid is useful for cryptomatte
419 if(!hdMaterialId.IsEmpty()) {
420 attrs.SetString(RtUString("user:__materialid"), RtUString(hdMaterialId.GetText()));
421 }
422
423 if (!isHdInstance) {
424 // Simple case: Singleton instance.
425 // Convert transform.
427 for (size_t i=0; i < xf.count; ++i) {
428 xf_rt[i] = HdPrman_Utils::GfMatrixToRtMatrix(xf.values[i]);
429 }
430 const riley::Transform xform = {
431 unsigned(xf.count),
432 xf_rt.data(),
433 xf.times.data()};
434
435 // Add "identifier:id2" with the instance number.
436 // XXX Do we want to distinguish facesets here?
437 attrs.SetInteger(RixStr.k_identifier_id2, 0);
438
439 // Adjust _instanceIds array.
440 const size_t oldCount = _instanceIds.size();
441 const size_t newCount = _prototypeIds.size();
442 if (newCount != oldCount) {
443 for (const auto &oldInstanceId: _instanceIds) {
444 if (oldInstanceId != riley::GeometryInstanceId::InvalidId()) {
445 riley->DeleteGeometryInstance(
446 riley::GeometryPrototypeId::InvalidId(), oldInstanceId);
447 }
448 }
449 _instanceIds.resize(
450 newCount,
451 riley::GeometryInstanceId::InvalidId());
452 }
453
454 // Prepend renderTag to grouping:membership
455 param->AddRenderTagToGroupingMembership(
456 sceneDelegate->GetRenderTag(id), attrs);
457
458 // Create or modify Riley instances corresponding to a
459 // singleton Hydra instance.
460 TF_VERIFY(_instanceIds.size() == _prototypeIds.size());
461 for (size_t j=0; j < _prototypeIds.size(); ++j) {
462 auto const& prototypeId = _prototypeIds[j];
463 auto& instanceId = _instanceIds[j];
464 auto instanceMaterialId = materialId;
465 RtParamList finalAttrs = attrs; // copy
466
467 // If a subset path was cached, use it. If not, use the prim path.
468 SdfPath* subsetPath(&primPath);
469 if (!subsetPaths.empty()) {
470 subsetPath = &subsetPaths[j];
471 }
472
473 finalAttrs.SetString(RixStr.k_identifier_name,
474 RtUString(subsetPath->GetText()));
475
476 // If a valid subset material was bound, use it.
477 if (!subsetMaterialIds.empty()) {
478 TF_VERIFY(j < subsetMaterialIds.size());
479 instanceMaterialId = subsetMaterialIds[j];
480 }
481
482 if (instanceId == riley::GeometryInstanceId::InvalidId()) {
483 TRACE_SCOPE("riley::CreateGeometryInstance");
484 instanceId = riley->CreateGeometryInstance(
485 riley::UserId(
486 stats::AddDataLocation(subsetPath->GetText()).GetValue()),
487 riley::GeometryPrototypeId::InvalidId(), prototypeId,
488 instanceMaterialId, coordSysList, xform, finalAttrs);
489 } else if (prmanInstAttrBitsWereSet) {
490 TRACE_SCOPE("riley::ModifyGeometryInstance");
491 riley->ModifyGeometryInstance(
492 riley::GeometryPrototypeId::InvalidId(),
493 instanceId, &instanceMaterialId, &coordSysList, &xform,
494 &finalAttrs);
495 }
496 }
497 *dirtyBits &= ~prmanInstAttrBits;
498 } else if (prmanInstAttrBitsWereSet
499 || HdChangeTracker::IsInstancerDirty(*dirtyBits, instancerId)) {
500 // This gprim is a prototype of a hydra instancer. (It is not itself an
501 // instancer because it is a gprim.) The riley geometry prototypes have
502 // already been synced above, and those are owned by this gprim instance.
503 // We need to tell the hdprman instancer to sync its riley instances for
504 // these riley prototypes.
505 //
506 // We won't make any riley instances here. The hdprman instancer will
507 // own the riley instances instead.
508 //
509 // We only need to do this if dirtyBits says the instancer is dirty.
510
511 HdRenderIndex &renderIndex = sceneDelegate->GetRenderIndex();
512
513 // first, sync the hydra instancer and its parents, from the bottom up.
514 // (note: this is transitional code, it should be done by the render index...)
515 HdInstancer::_SyncInstancerAndParents(renderIndex, instancerId);
516
517 if (subsetMaterialIds.size() == 0) {
518 subsetMaterialIds.push_back(materialId);
519 }
520 if (subsetPaths.size() == 0) {
521 subsetPaths.push_back(primPath);
522 }
523 TF_VERIFY(_prototypeIds.size() == subsetMaterialIds.size() &&
524 _prototypeIds.size() == subsetPaths.size(),
525 "size mismatch (%lu, %lu, %lu)\n", _prototypeIds.size(),
526 subsetMaterialIds.size(), subsetPaths.size());
527
528 // XXX: To avoid a failed verify inside Populate(), we will check the
529 // prototype ids for validity here. We don't usually do this, relying on
530 // Riley to report invalid prototype ids on instance creation. But
531 // Populate() allows and expects an invalid prototype id when instancing
532 // lights, so doing this check here lets us make a more informative
533 // warning. HYD-3206
534 if (std::any_of(_prototypeIds.begin(), _prototypeIds.end(),
535 [](const auto& id){
536 return id == riley::GeometryPrototypeId::InvalidId();
537 })) {
538 TF_WARN("Riley geometry prototype creation failed for "
539 "instanced gprim <%s>; the prim will not be instanced.",
540 id.GetText());
541 } else {
542 // next, tell the hdprman instancer to sync the riley instances
543 HdPrmanInstancer *instancer = static_cast<HdPrmanInstancer*>(
544 renderIndex.GetInstancer(instancerId));
545 if (instancer) {
546 instancer->Populate(
547 renderParam,
548 dirtyBits,
549 id,
550 _prototypeIds,
551 coordSysList,
552 attrs, xf,
553 subsetMaterialIds,
554 subsetPaths);
555 }
556 }
557 }
558 *dirtyBits &= ~HdChangeTracker::AllSceneDirtyBits;
559}
560
561PXR_NAMESPACE_CLOSE_SCOPE
562
563#endif // EXT_RMANPKG_PLUGIN_RENDERMAN_PLUGIN_HD_PRMAN_GPRIM_H
Tracks changes from the HdSceneDelegate, providing invalidation cues to the render engine.
Definition: changeTracker.h:35
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.
Definition: gprimbase.h:22
A mix-in template that adds shared gprim behavior to support various HdRprim types.
Definition: gprim.h:30
The Hydra render index is a flattened representation of the client scene graph, which may be composed...
Definition: renderIndex.h:105
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.
Definition: path.h:281
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()).
Definition: path.h:405
This is a small-vector class with local storage optimization, the local storage can be specified via ...
Definition: smallVector.h:157
Token for efficient comparison, assignment, and hashing of known strings.
Definition: token.h:71
#define TF_WARN(...)
Issue a warning, but continue execution.
Definition: diagnostic.h:132
#define TF_VERIFY(cond, format,...)
Checks a condition and reports an error if it evaluates false.
Definition: diagnostic.h:266
#define TF_UNUSED(x)
Stops compiler from producing unused argument or variable warnings.
Definition: tf.h:168
Describes a subset of a piece of geometry as a set of indices.
Definition: geomSubset.h:23
VtIntArray indices
The list of element indices contained in the subset.
Definition: geomSubset.h:39
SdfPath id
The path used to identify this subset in the scene.
Definition: geomSubset.h:35
SdfPath materialId
The path used to identify this material bound to the subset.
Definition: geomSubset.h:37
An array of a value sampled over time, in struct-of-arrays layout.
Basic Sdf data types.