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