1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #include "pxr/usdImaging/usdImaging/primAdapter.h"
25
26 #include "pxr/usdImaging/usdImaging/debugCodes.h"
27 #include "pxr/usdImaging/usdImaging/delegate.h"
28 #include "pxr/usdImaging/usdImaging/indexProxy.h"
29 #include "pxr/usdImaging/usdImaging/resolvedAttributeCache.h"
30 #include "pxr/usdImaging/usdImaging/instancerContext.h"
31
32 #include "pxr/usd/sdf/schema.h"
33 #include "pxr/usd/usd/collectionAPI.h"
34 #include "pxr/usd/usdGeom/primvarsAPI.h"
35
36 #include "pxr/imaging/hd/perfLog.h"
37 #include "pxr/imaging/hd/renderDelegate.h"
38
39 #include "pxr/base/tf/envSetting.h"
40 #include "pxr/base/tf/staticTokens.h"
41 #include "pxr/base/tf/type.h"
42
43 #include <vector>
44
45 PXR_NAMESPACE_OPEN_SCOPE
46
TF_REGISTRY_FUNCTION(TfType)47 TF_REGISTRY_FUNCTION(TfType)
48 {
49 TfType::Define<UsdImagingPrimAdapter>();
50 }
51
52 TF_DEFINE_ENV_SETTING(USDIMAGING_ENABLE_SHARED_XFORM_CACHE, 1,
53 "Enable a shared cache for transforms.");
_IsEnabledXformCache()54 static bool _IsEnabledXformCache() {
55 static bool _v = TfGetEnvSetting(USDIMAGING_ENABLE_SHARED_XFORM_CACHE) == 1;
56 return _v;
57 }
58
59 TF_DEFINE_ENV_SETTING(USDIMAGING_ENABLE_BINDING_CACHE, 1,
60 "Enable a cache for material bindings.");
_IsEnabledBindingCache()61 static bool _IsEnabledBindingCache() {
62 static bool _v = TfGetEnvSetting(USDIMAGING_ENABLE_BINDING_CACHE) == 1;
63 return _v;
64 }
65
66 TF_DEFINE_ENV_SETTING(USDIMAGING_ENABLE_VIS_CACHE, 1,
67 "Enable a cache for visibility.");
_IsEnabledVisCache()68 static bool _IsEnabledVisCache() {
69 static bool _v = TfGetEnvSetting(USDIMAGING_ENABLE_VIS_CACHE) == 1;
70 return _v;
71 }
72
73 TF_DEFINE_ENV_SETTING(USDIMAGING_ENABLE_PURPOSE_CACHE, 1,
74 "Enable a cache for purpose.");
_IsEnabledPurposeCache()75 static bool _IsEnabledPurposeCache() {
76 static bool _v = TfGetEnvSetting(USDIMAGING_ENABLE_PURPOSE_CACHE) == 1;
77 return _v;
78 }
79
80 TF_DEFINE_ENV_SETTING(USDIMAGING_ENABLE_POINT_INSTANCER_INDICES_CACHE, 1,
81 "Enable a cache for point instancer indices.");
_IsEnabledPointInstancerIndicesCache()82 static bool _IsEnabledPointInstancerIndicesCache() {
83 static bool _v = TfGetEnvSetting(USDIMAGING_ENABLE_POINT_INSTANCER_INDICES_CACHE) == 1;
84 return _v;
85 }
86
~UsdImagingPrimAdapter()87 UsdImagingPrimAdapter::~UsdImagingPrimAdapter()
88 {
89 }
90
91 /*static*/
92 bool
ShouldCullSubtree(UsdPrim const & prim)93 UsdImagingPrimAdapter::ShouldCullSubtree(UsdPrim const& prim)
94 {
95 // Skip population of non-imageable prims during population traversal
96 // (although they can still be populated by reference).
97 return (!prim.IsA<UsdGeomImageable>() && !prim.GetTypeName().IsEmpty());
98 }
99
100 /*virtual*/
101 bool
ShouldCullChildren() const102 UsdImagingPrimAdapter::ShouldCullChildren() const
103 {
104 return false;
105 }
106
107 /*virtual*/
108 bool
ShouldIgnoreNativeInstanceSubtrees() const109 UsdImagingPrimAdapter::ShouldIgnoreNativeInstanceSubtrees() const
110 {
111 return false;
112 }
113
114 /*virtual*/
115 bool
IsInstancerAdapter() const116 UsdImagingPrimAdapter::IsInstancerAdapter() const
117 {
118 return false;
119 }
120
121 /*virtual*/
122 bool
CanPopulateUsdInstance() const123 UsdImagingPrimAdapter::CanPopulateUsdInstance() const
124 {
125 return false;
126 }
127
128 /*virtual*/
129 HdDirtyBits
ProcessPrimChange(UsdPrim const & prim,SdfPath const & cachePath,TfTokenVector const & changedFields)130 UsdImagingPrimAdapter::ProcessPrimChange(UsdPrim const& prim,
131 SdfPath const& cachePath,
132 TfTokenVector const& changedFields)
133 {
134 // By default, resync the prim if there are any changes to non-plugin
135 // fields and ignore changes to built-in fields. Schemas typically register
136 // their own plugin metadata fields instead of relying on built-in fields.
137 const SdfSchema& schema = SdfSchema::GetInstance();
138 for (const TfToken& field : changedFields) {
139 const SdfSchema::FieldDefinition* fieldDef =
140 schema.GetFieldDefinition(field);
141 if (fieldDef && fieldDef->IsPlugin()) {
142 return HdChangeTracker::AllDirty;
143 }
144 }
145
146 return HdChangeTracker::Clean;
147 }
148
149 /*virtual*/
150 void
ProcessPrimResync(SdfPath const & cachePath,UsdImagingIndexProxy * index)151 UsdImagingPrimAdapter::ProcessPrimResync(SdfPath const& cachePath,
152 UsdImagingIndexProxy* index)
153 {
154 _RemovePrim(cachePath, index);
155
156 /// XXX(UsdImagingPaths): We use the cachePath directly as the
157 // usdPath here, but should do the proper transformation.
158 // Maybe we could check the primInfo before its removal.
159 SdfPath const& usdPath = cachePath;
160 if (_GetPrim(usdPath)) {
161 // The prim still exists, so repopulate it.
162 index->Repopulate(/*cachePath*/usdPath);
163 }
164 }
165
166 /*virtual*/
167 void
_ResyncDependents(SdfPath const & usdPath,UsdImagingIndexProxy * index)168 UsdImagingPrimAdapter::_ResyncDependents(SdfPath const& usdPath,
169 UsdImagingIndexProxy* index)
170 {
171 auto const range = _delegate->_dependencyInfo.equal_range(usdPath);
172 for (auto it = range.first; it != range.second; ++it) {
173 SdfPath const& depCachePath = it->second;
174 // If _ResyncDependents is called by the resync method of hydra prim
175 // /Foo, there's a strong chance the hydra prim has a declared
176 // dependency on USD prim /Foo. (This is true pretty much except for
177 // instancing cases that aren't expected to call this function).
178 //
179 // In order to avoid infinite loops, if the hydra dependency we get has
180 // the same path as the passed in usdPath, skip resyncing it.
181 if (depCachePath == usdPath) {
182 continue;
183 }
184
185 TF_DEBUG(USDIMAGING_CHANGES)
186 .Msg("<%s> Resyncing dependent %s\n",
187 usdPath.GetText(), depCachePath.GetText());
188
189 UsdImagingDelegate::_HdPrimInfo *primInfo =
190 _delegate->_GetHdPrimInfo(depCachePath);
191 if (primInfo != nullptr &&
192 TF_VERIFY(primInfo->adapter != nullptr)) {
193 primInfo->adapter->ProcessPrimResync(depCachePath, index);
194 }
195 }
196 }
197
198 /*virtual*/
199 void
ProcessPrimRemoval(SdfPath const & cachePath,UsdImagingIndexProxy * index)200 UsdImagingPrimAdapter::ProcessPrimRemoval(SdfPath const& cachePath,
201 UsdImagingIndexProxy* index)
202 {
203 _RemovePrim(cachePath, index);
204 }
205
206 /*virtual*/
207 void
MarkRefineLevelDirty(UsdPrim const & prim,SdfPath const & cachePath,UsdImagingIndexProxy * index)208 UsdImagingPrimAdapter::MarkRefineLevelDirty(UsdPrim const& prim,
209 SdfPath const& cachePath,
210 UsdImagingIndexProxy* index)
211 {
212 }
213
214 /*virtual*/
215 void
MarkReprDirty(UsdPrim const & prim,SdfPath const & cachePath,UsdImagingIndexProxy * index)216 UsdImagingPrimAdapter::MarkReprDirty(UsdPrim const& prim,
217 SdfPath const& cachePath,
218 UsdImagingIndexProxy* index)
219 {
220 }
221
222 /*virtual*/
223 void
MarkCullStyleDirty(UsdPrim const & prim,SdfPath const & cachePath,UsdImagingIndexProxy * index)224 UsdImagingPrimAdapter::MarkCullStyleDirty(UsdPrim const& prim,
225 SdfPath const& cachePath,
226 UsdImagingIndexProxy* index)
227 {
228 }
229
230 /*virtual*/
231 void
MarkRenderTagDirty(UsdPrim const & prim,SdfPath const & cachePath,UsdImagingIndexProxy * index)232 UsdImagingPrimAdapter::MarkRenderTagDirty(UsdPrim const& prim,
233 SdfPath const& cachePath,
234 UsdImagingIndexProxy* index)
235 {
236 }
237
238 /*virtual*/
239 void
MarkTransformDirty(UsdPrim const & prim,SdfPath const & cachePath,UsdImagingIndexProxy * index)240 UsdImagingPrimAdapter::MarkTransformDirty(UsdPrim const& prim,
241 SdfPath const& cachePath,
242 UsdImagingIndexProxy* index)
243 {
244 }
245
246 /*virtual*/
247 void
MarkVisibilityDirty(UsdPrim const & prim,SdfPath const & cachePath,UsdImagingIndexProxy * index)248 UsdImagingPrimAdapter::MarkVisibilityDirty(UsdPrim const& prim,
249 SdfPath const& cachePath,
250 UsdImagingIndexProxy* index)
251 {
252 }
253
254 /*virtual*/
255 void
MarkMaterialDirty(UsdPrim const & prim,SdfPath const & cachePath,UsdImagingIndexProxy * index)256 UsdImagingPrimAdapter::MarkMaterialDirty(UsdPrim const& prim,
257 SdfPath const& cachePath,
258 UsdImagingIndexProxy* index)
259 {
260 }
261
262 /*virtual*/
263 void
MarkLightParamsDirty(UsdPrim const & prim,SdfPath const & cachePath,UsdImagingIndexProxy * index)264 UsdImagingPrimAdapter::MarkLightParamsDirty(UsdPrim const& prim,
265 SdfPath const& cachePath,
266 UsdImagingIndexProxy* index)
267 {
268 }
269
270 /*virtual*/
271 void
MarkWindowPolicyDirty(UsdPrim const & prim,SdfPath const & cachePath,UsdImagingIndexProxy * index)272 UsdImagingPrimAdapter::MarkWindowPolicyDirty(UsdPrim const& prim,
273 SdfPath const& cachePath,
274 UsdImagingIndexProxy* index)
275 {
276 }
277
278 /*virtual*/
279 void
InvokeComputation(SdfPath const & cachePath,HdExtComputationContext * context)280 UsdImagingPrimAdapter::InvokeComputation(SdfPath const& cachePath,
281 HdExtComputationContext* context)
282 {
283 }
284
285 /*virtual*/
286 std::vector<VtArray<TfToken>>
GetInstanceCategories(UsdPrim const & prim)287 UsdImagingPrimAdapter::GetInstanceCategories(UsdPrim const& prim)
288 {
289 return std::vector<VtArray<TfToken>>();
290 }
291
292 /*virtual*/
293 PxOsdSubdivTags
GetSubdivTags(UsdPrim const & prim,SdfPath const & cachePath,UsdTimeCode time) const294 UsdImagingPrimAdapter::GetSubdivTags(UsdPrim const& prim,
295 SdfPath const& cachePath,
296 UsdTimeCode time) const
297 {
298 return PxOsdSubdivTags();
299 }
300
301 /*virtual*/
302 size_t
SampleInstancerTransform(UsdPrim const & instancerPrim,SdfPath const & instancerPath,UsdTimeCode time,size_t maxNumSamples,float * sampleTimes,GfMatrix4d * sampleValues)303 UsdImagingPrimAdapter::SampleInstancerTransform(
304 UsdPrim const& instancerPrim,
305 SdfPath const& instancerPath,
306 UsdTimeCode time,
307 size_t maxNumSamples,
308 float *sampleTimes,
309 GfMatrix4d *sampleValues)
310 {
311 return 0;
312 }
313
314 /*virtual*/
315 GfMatrix4d
GetInstancerTransform(UsdPrim const & instancerPrim,SdfPath const & instancerPath,UsdTimeCode time) const316 UsdImagingPrimAdapter::GetInstancerTransform(
317 UsdPrim const& instancerPrim,
318 SdfPath const& instancerPath,
319 UsdTimeCode time) const
320 {
321 return GfMatrix4d(1.0);
322 }
323
324 /*virtual*/
325 SdfPath
GetInstancerId(UsdPrim const & usdPrim,SdfPath const & cachePath) const326 UsdImagingPrimAdapter::GetInstancerId(
327 UsdPrim const& usdPrim,
328 SdfPath const& cachePath) const
329 {
330 return SdfPath::EmptyPath();
331 }
332
333 /*virtual*/
334 SdfPathVector
GetInstancerPrototypes(UsdPrim const & usdPrim,SdfPath const & cachePath) const335 UsdImagingPrimAdapter::GetInstancerPrototypes(
336 UsdPrim const& usdPrim,
337 SdfPath const& cachePath) const
338 {
339 return SdfPathVector();
340 }
341
342 /*virtual*/
343 size_t
SamplePrimvar(UsdPrim const & usdPrim,SdfPath const & cachePath,TfToken const & key,UsdTimeCode time,size_t maxNumSamples,float * sampleTimes,VtValue * sampleValues,VtIntArray * sampleIndices)344 UsdImagingPrimAdapter::SamplePrimvar(
345 UsdPrim const& usdPrim,
346 SdfPath const& cachePath,
347 TfToken const& key,
348 UsdTimeCode time,
349 size_t maxNumSamples,
350 float *sampleTimes,
351 VtValue *sampleValues,
352 VtIntArray *sampleIndices)
353 {
354 HD_TRACE_FUNCTION();
355
356 if (maxNumSamples == 0) {
357 return 0;
358 }
359
360 // Try as USD primvar.
361 // XXX Here we could use the cache.
362 UsdGeomPrimvarsAPI primvars(usdPrim);
363 UsdGeomPrimvar pv = primvars.FindPrimvarWithInheritance(key);
364
365 GfInterval interval = _GetCurrentTimeSamplingInterval();
366 std::vector<double> timeSamples;
367
368 if (pv && pv.HasValue()) {
369 if (pv.ValueMightBeTimeVarying()) {
370 pv.GetTimeSamplesInInterval(interval, &timeSamples);
371
372 // Add time samples at the boundary conditions
373 timeSamples.push_back(interval.GetMin());
374 timeSamples.push_back(interval.GetMax());
375
376 // Sort here
377 std::sort(timeSamples.begin(), timeSamples.end());
378 timeSamples.erase(
379 std::unique(timeSamples.begin(),
380 timeSamples.end()),
381 timeSamples.end());
382
383 size_t numSamples = timeSamples.size();
384
385 // XXX: We should add caching to the transform computation if this shows
386 // up in profiling, but all of our current caches are cleared on time
387 // change so we'd need to write a new structure.
388 size_t numSamplesToEvaluate = std::min(maxNumSamples, numSamples);
389
390 if (sampleIndices) {
391 for (size_t i=0; i < numSamplesToEvaluate; ++i) {
392 sampleTimes[i] = timeSamples[i] - time.GetValue();
393 if (pv.Get(&sampleValues[i], timeSamples[i])) {
394 if (!pv.GetIndices(&sampleIndices[i], timeSamples[i])) {
395 sampleIndices[i].clear();
396 }
397 }
398 }
399 } else {
400 for (size_t i=0; i < numSamplesToEvaluate; ++i) {
401 sampleTimes[i] = timeSamples[i] - time.GetValue();
402 pv.ComputeFlattened(&sampleValues[i], timeSamples[i]);
403 }
404 }
405 return numSamples;
406 } else {
407 // Return a single sample for non-varying primvars
408 sampleTimes[0] = 0.0f;
409 if (sampleIndices) {
410 if (pv.Get(sampleValues, time)) {
411 if (!pv.GetIndices(sampleIndices, time)) {
412 sampleIndices->clear();
413 }
414 }
415 } else {
416 pv.ComputeFlattened(sampleValues, time);
417 }
418 return 1;
419 }
420 }
421
422 // Try as USD attribute. This handles cases like "points" that
423 // are considered primvars by Hydra but non-primvar attributes by USD.
424 if (UsdAttribute attr = usdPrim.GetAttribute(key)) {
425 if (attr.ValueMightBeTimeVarying()) {
426 attr.GetTimeSamplesInInterval(interval, &timeSamples);
427
428 // Add time samples at the boudary conditions
429 timeSamples.push_back(interval.GetMin());
430 timeSamples.push_back(interval.GetMax());
431
432 // Sort here
433 std::sort(timeSamples.begin(), timeSamples.end());
434 timeSamples.erase(
435 std::unique(timeSamples.begin(),
436 timeSamples.end()),
437 timeSamples.end());
438
439 size_t numSamples = timeSamples.size();
440
441 // XXX: We should add caching to the transform computation if this
442 // shows up in profiling, but all of our current caches are cleared
443 // on time change so we'd need to write a new structure.
444 size_t numSamplesToEvaluate = std::min(maxNumSamples, numSamples);
445 for (size_t i=0; i < numSamplesToEvaluate; ++i) {
446 sampleTimes[i] = timeSamples[i] - time.GetValue();
447 attr.Get(&sampleValues[i], timeSamples[i]);
448 }
449 return numSamples;
450 } else {
451 // Return a single sample for non-varying primvars
452 sampleTimes[0] = 0;
453 attr.Get(sampleValues, time);
454 return 1;
455 }
456 }
457
458 // Fallback for adapters that do not read primvars from USD, but
459 // instead synthesize them -- ex: Cube, Cylinder, Capsule.
460 if (maxNumSamples > 0) {
461 sampleTimes[0] = 0;
462 sampleValues[0] = Get(usdPrim, cachePath, key, time, &sampleIndices[0]);
463 return sampleValues[0].IsEmpty() ? 0 : 1;
464 }
465
466 return 0;
467 }
468
469 /*virtual*/
470 SdfPath
GetScenePrimPath(SdfPath const & cachePath,int instanceIndex,HdInstancerContext * instancerCtx) const471 UsdImagingPrimAdapter::GetScenePrimPath(
472 SdfPath const& cachePath,
473 int instanceIndex,
474 HdInstancerContext *instancerCtx) const
475 {
476 // Note: if we end up here, we're not instanced, since primInfo
477 // holds the instance adapter for instanced gprims.
478 return cachePath;
479 }
480
481 /*virtual*/
482 bool
PopulateSelection(HdSelection::HighlightMode const & mode,SdfPath const & cachePath,UsdPrim const & usdPrim,int const hydraInstanceIndex,VtIntArray const & parentInstanceIndices,HdSelectionSharedPtr const & result) const483 UsdImagingPrimAdapter::PopulateSelection(
484 HdSelection::HighlightMode const& mode,
485 SdfPath const &cachePath,
486 UsdPrim const &usdPrim,
487 int const hydraInstanceIndex,
488 VtIntArray const &parentInstanceIndices,
489 HdSelectionSharedPtr const &result) const
490 {
491 // usdPrim (the original prim selection) might point to a parent node of
492 // this hydra prim; but it's also possible for it to point to dependent
493 // data sources like materials/coord systems/etc. Only apply the highlight
494 // if usdPrim is a parent of cachePath.
495 // Note: this strategy won't work for native instanced prims, but we expect
496 // those to be handled in the instance adapter PopulateSelection.
497 if (!cachePath.HasPrefix(usdPrim.GetPath())) {
498 return false;
499 }
500
501 const SdfPath indexPath = _delegate->ConvertCachePathToIndexPath(cachePath);
502
503 // Insert gprim into the selection map.
504 // If "hydraInstanceIndex" is set, just use that.
505 // Otherwise, parentInstanceIndices either points to an arry of flat indices
506 // to highlight, or (if it's empty) it indicates highlight all indices.
507 if (hydraInstanceIndex != -1) {
508 VtIntArray indices(1, hydraInstanceIndex);
509 result->AddInstance(mode, indexPath, indices);
510 } else if (parentInstanceIndices.size() == 0) {
511 result->AddRprim(mode, indexPath);
512 } else {
513 result->AddInstance(mode, indexPath, parentInstanceIndices);
514 }
515
516 if (TfDebug::IsEnabled(USDIMAGING_SELECTION)) {
517 std::stringstream ss;
518 if (hydraInstanceIndex != -1) {
519 ss << hydraInstanceIndex;
520 } else {
521 ss << parentInstanceIndices;
522 }
523 TF_DEBUG(USDIMAGING_SELECTION).Msg("PopulateSelection: (prim) %s %s\n",
524 indexPath.GetText(), ss.str().c_str());
525 }
526
527 return true;
528 }
529
530 HdVolumeFieldDescriptorVector
GetVolumeFieldDescriptors(UsdPrim const & usdPrim,SdfPath const & id,UsdTimeCode time) const531 UsdImagingPrimAdapter::GetVolumeFieldDescriptors(UsdPrim const& usdPrim,
532 SdfPath const &id,
533 UsdTimeCode time) const
534 {
535 return HdVolumeFieldDescriptorVector();
536 }
537
538 void
SetDelegate(UsdImagingDelegate * delegate)539 UsdImagingPrimAdapter::SetDelegate(UsdImagingDelegate* delegate)
540 {
541 _delegate = delegate;
542 }
543
544 bool
IsChildPath(SdfPath const & path) const545 UsdImagingPrimAdapter::IsChildPath(SdfPath const& path) const
546 {
547 return path.IsPropertyPath();
548 }
549
550 UsdImagingPrimvarDescCache*
_GetPrimvarDescCache() const551 UsdImagingPrimAdapter::_GetPrimvarDescCache() const
552 {
553 return &_delegate->_primvarDescCache;
554 }
555
556 GfMatrix4d
GetRootTransform() const557 UsdImagingPrimAdapter::GetRootTransform() const
558 {
559 return _delegate->GetRootTransform();
560 }
561
562 UsdPrim
_GetPrim(SdfPath const & usdPath) const563 UsdImagingPrimAdapter::_GetPrim(SdfPath const& usdPath) const
564 {
565 // Intentionally not calling _delegate->_GetPrim here because it strictly
566 // requires the prim to exist.
567 return _delegate->_stage->GetPrimAtPath(usdPath);
568 }
569
570 const UsdImagingPrimAdapterSharedPtr&
_GetPrimAdapter(UsdPrim const & prim,bool ignoreInstancing) const571 UsdImagingPrimAdapter::_GetPrimAdapter(UsdPrim const& prim,
572 bool ignoreInstancing) const
573 {
574 return _delegate->_AdapterLookup(prim, ignoreInstancing);
575 }
576
577 const UsdImagingPrimAdapterSharedPtr&
_GetAdapter(TfToken const & adapterKey) const578 UsdImagingPrimAdapter::_GetAdapter(TfToken const& adapterKey) const
579 {
580 return _delegate->_AdapterLookup(adapterKey);
581 }
582
583 SdfPath
_GetPrimPathFromInstancerChain(SdfPathVector const & instancerChain) const584 UsdImagingPrimAdapter::_GetPrimPathFromInstancerChain(
585 SdfPathVector const& instancerChain) const
586 {
587 // The instancer chain is stored more-to-less local. For example:
588 //
589 // ProtoCube <----+
590 // +-- cube | (native instance)
591 // ProtoA | <--+
592 // +-- ProtoCube--+ | (native instance)
593 // PointInstancer |
594 // +-- ProtoA ----------+
595 //
596 // paths =
597 // /__Prototype_1/cube
598 // /__Prototype_2/ProtoCube
599 // /PointInstancer/ProtoA
600 //
601 // This function uses the path chain to recreate the instance path:
602 // /PointInstancer/ProtoA/ProtoCube/cube
603
604 if (instancerChain.size() == 0) {
605 return SdfPath();
606 }
607
608 SdfPath primPath = instancerChain[0];
609
610 // Every path except the last path should be a path in prototype. The idea
611 // is to replace the prototype path with the instance path that comes next
612 // in the chain, and continue until we're back at scene scope.
613 for (size_t i = 1; i < instancerChain.size(); ++i)
614 {
615 UsdPrim prim = _GetPrim(primPath);
616 TF_VERIFY(prim.IsInPrototype());
617
618 UsdPrim prototype = prim;
619 while (!prototype.IsPrototype()) {
620 prototype = prototype.GetParent();
621 }
622 primPath = primPath.ReplacePrefix(
623 prototype.GetPath(), instancerChain[i]);
624 }
625
626 return primPath;
627 }
628
629 UsdTimeCode
_GetTimeWithOffset(float offset) const630 UsdImagingPrimAdapter::_GetTimeWithOffset(float offset) const
631 {
632 return _delegate->GetTimeWithOffset(offset);
633 }
634
635 SdfPath
_ConvertCachePathToIndexPath(const SdfPath & usdPath) const636 UsdImagingPrimAdapter::_ConvertCachePathToIndexPath(const SdfPath &usdPath) const
637 {
638 return _delegate->ConvertCachePathToIndexPath(usdPath);
639 }
640
641 SdfPath
_ConvertIndexPathToCachePath(const SdfPath & indexPath) const642 UsdImagingPrimAdapter::_ConvertIndexPathToCachePath(const SdfPath &indexPath) const
643 {
644 return _delegate->ConvertIndexPathToCachePath(indexPath);
645 }
646
647 TfToken
_GetMaterialBindingPurpose() const648 UsdImagingPrimAdapter::_GetMaterialBindingPurpose() const
649 {
650 return _delegate->GetRenderIndex().GetRenderDelegate()->
651 GetMaterialBindingPurpose();
652 }
653
654 TfTokenVector
_GetMaterialRenderContexts() const655 UsdImagingPrimAdapter::_GetMaterialRenderContexts() const
656 {
657 return _delegate->GetRenderIndex().GetRenderDelegate()->
658 GetMaterialRenderContexts();
659 }
660
661 bool
_IsPrimvarFilteringNeeded() const662 UsdImagingPrimAdapter::_IsPrimvarFilteringNeeded() const
663 {
664 return _delegate->GetRenderIndex().GetRenderDelegate()->
665 IsPrimvarFilteringNeeded();
666 }
667
668
669 TfTokenVector
_GetShaderSourceTypes() const670 UsdImagingPrimAdapter::_GetShaderSourceTypes() const
671 {
672 return _delegate->GetRenderIndex().GetRenderDelegate()->
673 GetShaderSourceTypes();
674 }
675
676 bool
_IsInInvisedPaths(SdfPath const & usdPath) const677 UsdImagingPrimAdapter::_IsInInvisedPaths(SdfPath const& usdPath) const
678 {
679 return _delegate->IsInInvisedPaths(usdPath);
680 }
681
682 void
_MergePrimvar(HdPrimvarDescriptorVector * vec,TfToken const & name,HdInterpolation interp,TfToken const & role,bool indexed) const683 UsdImagingPrimAdapter::_MergePrimvar(
684 HdPrimvarDescriptorVector* vec,
685 TfToken const& name,
686 HdInterpolation interp,
687 TfToken const& role,
688 bool indexed) const
689 {
690 HdPrimvarDescriptor primvar(name, interp, role, indexed);
691 HdPrimvarDescriptorVector::iterator it =
692 std::find(vec->begin(), vec->end(), primvar);
693 if (it == vec->end())
694 vec->push_back(primvar);
695 else
696 *it = primvar;
697 }
698
699 void
_RemovePrimvar(HdPrimvarDescriptorVector * vec,TfToken const & name) const700 UsdImagingPrimAdapter::_RemovePrimvar(
701 HdPrimvarDescriptorVector* vec,
702 TfToken const& name) const
703 {
704 for (HdPrimvarDescriptorVector::iterator it = vec->begin();
705 it != vec->end(); ++it) {
706 if (it->name == name) {
707 vec->erase(it);
708 return;
709 }
710 }
711 }
712
713 /* static */
714 HdInterpolation
_UsdToHdInterpolation(TfToken const & usdInterp)715 UsdImagingPrimAdapter::_UsdToHdInterpolation(TfToken const& usdInterp)
716 {
717 if (usdInterp == UsdGeomTokens->uniform) {
718 return HdInterpolationUniform;
719 } else if (usdInterp == UsdGeomTokens->vertex) {
720 return HdInterpolationVertex;
721 } else if (usdInterp == UsdGeomTokens->varying) {
722 return HdInterpolationVarying;
723 } else if (usdInterp == UsdGeomTokens->faceVarying) {
724 return HdInterpolationFaceVarying;
725 } else if (usdInterp == UsdGeomTokens->constant) {
726 return HdInterpolationConstant;
727 }
728 TF_CODING_ERROR("Unknown USD interpolation %s; treating as constant",
729 usdInterp.GetText());
730 return HdInterpolationConstant;
731 }
732
733 /* static */
734 TfToken
_UsdToHdRole(TfToken const & usdRole)735 UsdImagingPrimAdapter::_UsdToHdRole(TfToken const& usdRole)
736 {
737 if (usdRole == SdfValueRoleNames->Point) {
738 return HdPrimvarRoleTokens->point;
739 } else if (usdRole == SdfValueRoleNames->Normal) {
740 return HdPrimvarRoleTokens->normal;
741 } else if (usdRole == SdfValueRoleNames->Vector) {
742 return HdPrimvarRoleTokens->vector;
743 } else if (usdRole == SdfValueRoleNames->Color) {
744 return HdPrimvarRoleTokens->color;
745 } else if (usdRole == SdfValueRoleNames->TextureCoordinate) {
746 return HdPrimvarRoleTokens->textureCoordinate;
747 }
748 // Empty token means no role specified
749 return TfToken();
750 }
751
752
753 void
_ComputeAndMergePrimvar(UsdPrim const & gprim,UsdGeomPrimvar const & primvar,UsdTimeCode time,HdPrimvarDescriptorVector * primvarDescs,HdInterpolation * interpOverride) const754 UsdImagingPrimAdapter::_ComputeAndMergePrimvar(
755 UsdPrim const& gprim,
756 UsdGeomPrimvar const& primvar,
757 UsdTimeCode time,
758 HdPrimvarDescriptorVector* primvarDescs,
759 HdInterpolation *interpOverride) const
760 {
761 TRACE_FUNCTION();
762
763 VtValue v;
764 TfToken primvarName = primvar.GetPrimvarName();
765
766 // Note: we call Get() here to check if the primvar exists.
767 // We can't call HasValue(), since it won't take time-varying
768 // blocks (from value clips) into account. Get() should be
769 // fast as long as we don't touch the returned data.
770 if (primvar.Get(&v, time)) {
771 HdInterpolation interp = interpOverride ? *interpOverride
772 : _UsdToHdInterpolation(primvar.GetInterpolation());
773 TfToken role = _UsdToHdRole(primvar.GetAttr().GetRoleName());
774 TF_DEBUG(USDIMAGING_SHADERS)
775 .Msg("UsdImaging: found primvar (%s) %s, interp %s\n",
776 gprim.GetPath().GetText(),
777 primvarName.GetText(),
778 TfEnum::GetName(interp).c_str());
779 _MergePrimvar(primvarDescs, primvarName, interp, role,
780 primvar.IsIndexed());
781
782 } else {
783 TF_DEBUG(USDIMAGING_SHADERS)
784 .Msg( "\t\t No primvar on <%s> named %s\n",
785 gprim.GetPath().GetText(), primvarName.GetText());
786 _RemovePrimvar(primvarDescs, primvarName);
787 }
788 }
789
790 namespace {
791
792 // The types of primvar changes expected
793 enum PrimvarChange {
794 PrimvarChangeValue,
795 PrimvarChangeAdd,
796 PrimvarChangeRemove,
797 PrimvarChangeDesc
798 };
799
800 // Maps the primvar changes (above) to the dirty bit that needs to be set.
801 /*static*/
802 HdDirtyBits
_GetDirtyBitsForPrimvarChange(PrimvarChange changeType,HdDirtyBits valueChangeDirtyBit)803 _GetDirtyBitsForPrimvarChange(
804 PrimvarChange changeType,
805 HdDirtyBits valueChangeDirtyBit)
806 {
807 HdDirtyBits dirty = HdChangeTracker::Clean;
808
809 switch (changeType) {
810 case PrimvarChangeAdd:
811 case PrimvarChangeRemove:
812 case PrimvarChangeDesc:
813 {
814 // XXX: Once we have a bit for descriptor changes, we should use
815 // that instead.
816 dirty = HdChangeTracker::DirtyPrimvar;
817 break;
818 }
819 case PrimvarChangeValue:
820 {
821 dirty = valueChangeDirtyBit;
822 break;
823 }
824 default:
825 {
826 TF_CODING_ERROR("Unsupported PrimvarChange %d\n", changeType);
827 }
828 }
829
830 return dirty;
831 }
832
833 // Figure out what changed about the primvar and returns the appropriate dirty
834 // bit.
835 /*static*/
836 PrimvarChange
_ProcessPrimvarChange(bool primvarOnPrim,HdInterpolation primvarInterpOnPrim,TfToken const & primvarName,HdPrimvarDescriptorVector * primvarDescs,SdfPath const & cachePath)837 _ProcessPrimvarChange(bool primvarOnPrim,
838 HdInterpolation primvarInterpOnPrim,
839 TfToken const& primvarName,
840 HdPrimvarDescriptorVector* primvarDescs,
841 SdfPath const& cachePath/*debug*/)
842 {
843 // Determine if primvar is in the value cache.
844 HdPrimvarDescriptorVector::iterator primvarIt = primvarDescs->end();
845 for (HdPrimvarDescriptorVector::iterator it = primvarDescs->begin();
846 it != primvarDescs->end(); it++) {
847 if (it->name == primvarName) {
848 primvarIt = it;
849 break;
850 }
851 }
852 bool primvarInValueCache = primvarIt != primvarDescs->end();
853
854 PrimvarChange changeType = PrimvarChangeValue;
855 if (primvarOnPrim && !primvarInValueCache) {
856 changeType = PrimvarChangeAdd;
857 } else if (!primvarOnPrim && primvarInValueCache) {
858 changeType = PrimvarChangeRemove;
859
860 TF_DEBUG(USDIMAGING_CHANGES).Msg(
861 "Removing primvar descriptor %s for cachePath %s.\n",
862 primvarIt->name.GetText(), cachePath.GetText());
863
864 // Remove the value cache entry.
865 primvarDescs->erase(primvarIt);
866
867 } else if (primvarInValueCache && primvarOnPrim &&
868 (primvarIt->interpolation != primvarInterpOnPrim)) {
869 changeType = PrimvarChangeDesc;
870 }
871
872 return changeType;
873 }
874
875 } // anonymous namespace
876
877 HdDirtyBits
_ProcessNonPrefixedPrimvarPropertyChange(UsdPrim const & prim,SdfPath const & cachePath,TfToken const & propertyName,TfToken const & primvarName,HdInterpolation const & primvarInterp,HdDirtyBits valueChangeDirtyBit) const878 UsdImagingPrimAdapter::_ProcessNonPrefixedPrimvarPropertyChange(
879 UsdPrim const& prim,
880 SdfPath const& cachePath,
881 TfToken const& propertyName,
882 TfToken const& primvarName,
883 HdInterpolation const& primvarInterp,
884 HdDirtyBits valueChangeDirtyBit
885 /*= HdChangeTracker::DirtyPrimvar*/) const
886 {
887 // Determine if primvar exists on the prim.
888 bool primvarOnPrim = false;
889 UsdAttribute attr = prim.GetAttribute(propertyName);
890 if (attr && attr.HasValue()) {
891 // The expectation is that this method is used for "built-in" attributes
892 // that are treated as primvars.
893 if (UsdGeomPrimvar::IsPrimvar(attr)) {
894 TF_CODING_ERROR("Prefixed primvar (%s) with cache path %s should "
895 "use _ProcessPrefixedPrimvarPropertyChange instead.\n",
896 propertyName.GetText(), cachePath.GetText());
897
898 return HdChangeTracker::AllDirty;
899 }
900
901 primvarOnPrim = true;
902 }
903
904 HdPrimvarDescriptorVector& primvarDescs =
905 _GetPrimvarDescCache()->GetPrimvars(cachePath);
906
907 PrimvarChange changeType =
908 _ProcessPrimvarChange(primvarOnPrim, primvarInterp,
909 primvarName, &primvarDescs, cachePath);
910
911 return _GetDirtyBitsForPrimvarChange(changeType, valueChangeDirtyBit);
912 }
913
914 HdDirtyBits
_ProcessPrefixedPrimvarPropertyChange(UsdPrim const & prim,SdfPath const & cachePath,TfToken const & propertyName,HdDirtyBits valueChangeDirtyBit,bool inherited) const915 UsdImagingPrimAdapter::_ProcessPrefixedPrimvarPropertyChange(
916 UsdPrim const& prim,
917 SdfPath const& cachePath,
918 TfToken const& propertyName,
919 HdDirtyBits valueChangeDirtyBit/*= HdChangeTracker::DirtyPrimvar*/,
920 bool inherited/*=true*/) const
921 {
922 // Determine if primvar exists on the prim.
923 bool primvarOnPrim = false;
924 UsdAttribute attr;
925 TfToken interpOnPrim;
926 HdInterpolation hdInterpOnPrim = HdInterpolationConstant;
927 UsdGeomPrimvarsAPI api(prim);
928 if (inherited) {
929 UsdGeomPrimvar pv = api.FindPrimvarWithInheritance(propertyName);
930 attr = pv;
931 if (pv)
932 interpOnPrim = pv.GetInterpolation();
933 } else {
934 UsdGeomPrimvar localPv = api.GetPrimvar(propertyName);
935 attr = localPv;
936 if (localPv)
937 interpOnPrim = localPv.GetInterpolation();
938 }
939 if (attr && attr.HasValue()) {
940 primvarOnPrim = true;
941 hdInterpOnPrim = _UsdToHdInterpolation(interpOnPrim);
942 }
943
944 // Determine if primvar is in the value cache.
945 TfToken primvarName = UsdGeomPrimvar::StripPrimvarsName(propertyName);
946 HdPrimvarDescriptorVector& primvarDescs =
947 _GetPrimvarDescCache()->GetPrimvars(cachePath);
948
949 PrimvarChange changeType = _ProcessPrimvarChange(primvarOnPrim,
950 hdInterpOnPrim,
951 primvarName, &primvarDescs, cachePath);
952
953 return _GetDirtyBitsForPrimvarChange(changeType, valueChangeDirtyBit);
954 }
955
956 UsdImaging_CollectionCache&
_GetCollectionCache() const957 UsdImagingPrimAdapter::_GetCollectionCache() const
958 {
959 return _delegate->_collectionCache;
960 }
961
962 UsdImaging_CoordSysBindingStrategy::value_type
_GetCoordSysBindings(UsdPrim const & prim) const963 UsdImagingPrimAdapter::_GetCoordSysBindings(UsdPrim const& prim) const
964 {
965 return _delegate->_coordSysBindingCache.GetValue(prim);
966 }
967
968 UsdImaging_InheritedPrimvarStrategy::value_type
_GetInheritedPrimvars(UsdPrim const & prim) const969 UsdImagingPrimAdapter::_GetInheritedPrimvars(UsdPrim const& prim) const
970 {
971 return _delegate->_inheritedPrimvarCache.GetValue(prim);
972 }
973
974 bool
_DoesDelegateSupportCoordSys() const975 UsdImagingPrimAdapter::_DoesDelegateSupportCoordSys() const
976 {
977 return _delegate->_coordSysEnabled;
978 }
979
980 bool
_IsVarying(UsdPrim prim,TfToken const & attrName,HdDirtyBits dirtyFlag,TfToken const & perfToken,HdDirtyBits * dirtyFlags,bool isInherited,bool * exists) const981 UsdImagingPrimAdapter::_IsVarying(UsdPrim prim,
982 TfToken const& attrName,
983 HdDirtyBits dirtyFlag,
984 TfToken const& perfToken,
985 HdDirtyBits* dirtyFlags,
986 bool isInherited,
987 bool *exists) const
988 {
989 HD_TRACE_FUNCTION();
990 HF_MALLOC_TAG_FUNCTION();
991
992 if (exists != nullptr) {
993 *exists = false;
994 }
995
996 do {
997 UsdAttribute attr = prim.GetAttribute(attrName);
998
999 if (attr && exists != nullptr) {
1000 *exists = true;
1001 }
1002 if (attr.ValueMightBeTimeVarying()){
1003 (*dirtyFlags) |= dirtyFlag;
1004 HD_PERF_COUNTER_INCR(perfToken);
1005 return true;
1006 }
1007 prim = prim.GetParent();
1008
1009 } while (isInherited && prim.GetPath() != SdfPath::AbsoluteRootPath());
1010
1011 return false;
1012 }
1013
1014 bool
_IsTransformVarying(UsdPrim prim,HdDirtyBits dirtyFlag,TfToken const & perfToken,HdDirtyBits * dirtyFlags) const1015 UsdImagingPrimAdapter::_IsTransformVarying(UsdPrim prim,
1016 HdDirtyBits dirtyFlag,
1017 TfToken const& perfToken,
1018 HdDirtyBits* dirtyFlags) const
1019 {
1020 HD_TRACE_FUNCTION();
1021 HF_MALLOC_TAG_FUNCTION();
1022
1023 UsdImaging_XformCache &xfCache = _delegate->_xformCache;
1024
1025 do {
1026 bool mayXformVary =
1027 xfCache.GetQuery(prim)->TransformMightBeTimeVarying();
1028 if (mayXformVary) {
1029 (*dirtyFlags) |= dirtyFlag;
1030 HD_PERF_COUNTER_INCR(perfToken);
1031 return true;
1032 }
1033
1034 // If the xformable prim resets the transform stack, then
1035 // we don't have to check the variability of ancestor transforms.
1036 bool resetsXformStack = xfCache.GetQuery(prim)->GetResetXformStack();
1037 if (resetsXformStack) {
1038 break;
1039 }
1040
1041 prim = prim.GetParent();
1042
1043 } while (prim.GetPath() != SdfPath::AbsoluteRootPath());
1044
1045 return false;
1046 }
1047
1048 GfMatrix4d
GetTransform(UsdPrim const & prim,SdfPath const & cachePath,UsdTimeCode time,bool ignoreRootTransform) const1049 UsdImagingPrimAdapter::GetTransform(UsdPrim const& prim,
1050 SdfPath const& cachePath,
1051 UsdTimeCode time,
1052 bool ignoreRootTransform) const
1053 {
1054 TRACE_FUNCTION();
1055 HF_MALLOC_TAG_FUNCTION();
1056
1057 UsdImaging_XformCache &xfCache = _delegate->_xformCache;
1058 GfMatrix4d ctm(1.0);
1059
1060 if (_IsEnabledXformCache() && xfCache.GetTime() == time) {
1061 ctm = xfCache.GetValue(prim);
1062 } else {
1063 ctm = UsdImaging_XfStrategy::ComputeTransform(
1064 prim, xfCache.GetRootPath(), time,
1065 _delegate->_rigidXformOverrides);
1066 }
1067
1068 return ignoreRootTransform ? ctm : ctm * GetRootTransform();
1069 }
1070
1071 static
1072 size_t
_GatherAuthoredTransformTimeSamples(UsdPrim const & prim,GfInterval const interval,UsdImaging_XformCache const & xfCache,std::vector<double> * timeSamples)1073 _GatherAuthoredTransformTimeSamples(
1074 UsdPrim const& prim,
1075 GfInterval const interval,
1076 UsdImaging_XformCache const& xfCache,
1077 std::vector<double>* timeSamples)
1078 {
1079 UsdPrim p = prim;
1080 while (p && p.GetPath() != xfCache.GetRootPath()) {
1081 // XXX Add caching here.
1082 if (UsdGeomXformable xf = UsdGeomXformable(p)) {
1083 std::vector<double> localTimeSamples;
1084 xf.GetTimeSamplesInInterval(interval, &localTimeSamples);
1085
1086 // Join timesamples
1087 timeSamples->insert(
1088 timeSamples->end(),
1089 localTimeSamples.begin(),
1090 localTimeSamples.end());
1091 }
1092 p = p.GetParent();
1093 }
1094
1095 // Sort here
1096 std::sort(timeSamples->begin(), timeSamples->end());
1097 timeSamples->erase(
1098 std::unique(timeSamples->begin(),
1099 timeSamples->end()),
1100 timeSamples->end());
1101
1102 return timeSamples->size();
1103 }
1104
1105 GfInterval
_GetCurrentTimeSamplingInterval()1106 UsdImagingPrimAdapter::_GetCurrentTimeSamplingInterval()
1107 {
1108 return _delegate->GetCurrentTimeSamplingInterval();
1109 }
1110
1111 Usd_PrimFlagsConjunction
_GetDisplayPredicate() const1112 UsdImagingPrimAdapter::_GetDisplayPredicate() const
1113 {
1114 return _delegate->_GetDisplayPredicate();
1115 }
1116
1117 Usd_PrimFlagsConjunction
_GetDisplayPredicateForPrototypes() const1118 UsdImagingPrimAdapter::_GetDisplayPredicateForPrototypes() const
1119 {
1120 return _delegate->_GetDisplayPredicateForPrototypes();
1121 }
1122
1123 size_t
SampleTransform(UsdPrim const & prim,SdfPath const & cachePath,UsdTimeCode time,size_t maxNumSamples,float * sampleTimes,GfMatrix4d * sampleValues)1124 UsdImagingPrimAdapter::SampleTransform(
1125 UsdPrim const& prim,
1126 SdfPath const& cachePath,
1127 UsdTimeCode time,
1128 size_t maxNumSamples,
1129 float *sampleTimes,
1130 GfMatrix4d *sampleValues)
1131 {
1132 HD_TRACE_FUNCTION();
1133
1134 if (maxNumSamples == 0) {
1135 return 0;
1136 }
1137
1138 if (!prim) {
1139 // If this is not a literal USD prim, it is an instance of
1140 // other object synthesized by UsdImaging. Just return
1141 // the single transform sample from the ValueCache.
1142 sampleTimes[0] = 0.0;
1143 sampleValues[0] = GetTransform(prim, prim.GetPath(), 0.0);
1144 return 1;
1145 }
1146
1147 GfInterval interval = _GetCurrentTimeSamplingInterval();
1148
1149 // Add time samples at the boudary conditions
1150 std::vector<double> timeSamples;
1151 timeSamples.push_back(interval.GetMin());
1152 timeSamples.push_back(interval.GetMax());
1153
1154 // Gather authored time samples for transforms
1155 size_t numSamples = _GatherAuthoredTransformTimeSamples(
1156 prim,
1157 interval,
1158 _delegate->_xformCache,
1159 &timeSamples);
1160
1161 // XXX: We should add caching to the transform computation if this shows
1162 // up in profiling, but all of our current caches are cleared on time
1163 // change so we'd need to write a new structure.
1164 size_t numSamplesToEvaluate = std::min(maxNumSamples, numSamples);
1165 for (size_t i=0; i < numSamplesToEvaluate; ++i) {
1166 sampleTimes[i] = timeSamples[i] - time.GetValue();
1167 sampleValues[i] = UsdImaging_XfStrategy::ComputeTransform(
1168 prim,
1169 _delegate->_xformCache.GetRootPath(),
1170 timeSamples[i],
1171 _delegate->_rigidXformOverrides)
1172 * _delegate->_rootXf;
1173 }
1174
1175 // Early out if we can't fit the data in the arrays
1176 if (numSamples > maxNumSamples) {
1177 return numSamples;
1178 }
1179
1180 // Optimization.
1181 // Some backends benefit if they can avoid time sample animation
1182 // for fixed transforms. This is difficult to compute explicitly
1183 // due to the hierarchial nature of concated transforms, so we
1184 // do a post-pass sweep to detect static transforms here.
1185 for (size_t i=1; i < numSamples; ++i) {
1186 if (timeSamples[i] != timeSamples[0]) {
1187 return numSamples;
1188 }
1189 }
1190 // All samples are the same, so just return 1.
1191 return 1;
1192 }
1193
1194 VtValue
Get(UsdPrim const & prim,SdfPath const & cachePath,TfToken const & key,UsdTimeCode time,VtIntArray * outIndices) const1195 UsdImagingPrimAdapter::Get(
1196 UsdPrim const& prim,
1197 SdfPath const& cachePath,
1198 TfToken const &key,
1199 UsdTimeCode time,
1200 VtIntArray *outIndices) const
1201 {
1202 UsdAttribute const &attr = prim.GetAttribute(key);
1203 VtValue value;
1204 if (attr) {
1205 attr.Get(&value, time);
1206 }
1207 return value;
1208 }
1209
1210 bool
GetVisible(UsdPrim const & prim,SdfPath const & cachePath,UsdTimeCode time) const1211 UsdImagingPrimAdapter::GetVisible(
1212 UsdPrim const& prim,
1213 SdfPath const& cachePath,
1214 UsdTimeCode time) const
1215 {
1216 TRACE_FUNCTION();
1217
1218 if (_delegate->IsInInvisedPaths(prim.GetPath())) {
1219 return false;
1220 }
1221
1222 UsdImaging_VisCache &visCache = _delegate->_visCache;
1223 if (_IsEnabledVisCache() && visCache.GetTime() == time) {
1224 return visCache.GetValue(prim) == UsdGeomTokens->inherited;
1225 } else {
1226 return UsdImaging_VisStrategy::ComputeVisibility(prim, time)
1227 == UsdGeomTokens->inherited;
1228 }
1229 }
1230
1231 TfToken
GetPurpose(UsdPrim const & prim,SdfPath const & cachePath,TfToken const & instanceInheritablePurpose) const1232 UsdImagingPrimAdapter::GetPurpose(
1233 UsdPrim const& prim,
1234 SdfPath const& cachePath,
1235 TfToken const& instanceInheritablePurpose) const
1236 {
1237 HD_TRACE_FUNCTION();
1238
1239 UsdImaging_PurposeStrategy::value_type purposeInfo =
1240 _IsEnabledPurposeCache() ?
1241 _delegate->_purposeCache.GetValue(prim) :
1242 UsdImaging_PurposeStrategy::ComputePurposeInfo(prim);
1243
1244 // Inherit the instance's purpose if our prim has a fallback purpose and
1245 // there's an instance that provide a purpose to inherit.
1246 if (!purposeInfo.isInheritable &&
1247 !instanceInheritablePurpose.IsEmpty()) {
1248 return instanceInheritablePurpose;
1249 }
1250
1251 return purposeInfo.purpose.IsEmpty() ?
1252 UsdGeomTokens->default_ : purposeInfo.purpose;
1253 }
1254
1255 TfToken
GetInheritablePurpose(UsdPrim const & prim) const1256 UsdImagingPrimAdapter::GetInheritablePurpose(UsdPrim const& prim) const
1257 {
1258 HD_TRACE_FUNCTION();
1259
1260 UsdImaging_PurposeStrategy::value_type purposeInfo =
1261 _IsEnabledPurposeCache() ?
1262 _delegate->_purposeCache.GetValue(prim) :
1263 UsdImaging_PurposeStrategy::ComputePurposeInfo(prim);
1264
1265 return purposeInfo.GetInheritablePurpose();
1266 }
1267
1268 HdCullStyle
GetCullStyle(UsdPrim const & prim,SdfPath const & cachePath,UsdTimeCode time) const1269 UsdImagingPrimAdapter::GetCullStyle(UsdPrim const& prim,
1270 SdfPath const& cachePath,
1271 UsdTimeCode time) const
1272 {
1273 return HdCullStyleDontCare;
1274 }
1275
1276 SdfPath
GetMaterialUsdPath(UsdPrim const & prim) const1277 UsdImagingPrimAdapter::GetMaterialUsdPath(UsdPrim const& prim) const
1278 {
1279 HD_TRACE_FUNCTION();
1280
1281 // No need to worry about time here, since relationships do not have time
1282 // samples.
1283 if (_IsEnabledBindingCache()) {
1284 return _delegate->_materialBindingCache.GetValue(prim);
1285 } else {
1286 return UsdImaging_MaterialStrategy::ComputeMaterialPath(prim,
1287 &_delegate->_materialBindingImplData);
1288 }
1289 }
1290
1291 TfToken
GetModelDrawMode(UsdPrim const & prim)1292 UsdImagingPrimAdapter::GetModelDrawMode(UsdPrim const& prim)
1293 {
1294 return _delegate->_GetModelDrawMode(prim);
1295 }
1296
1297 /*virtual*/
1298 VtValue
GetTopology(UsdPrim const & prim,SdfPath const & cachePath,UsdTimeCode time) const1299 UsdImagingPrimAdapter::GetTopology(UsdPrim const& prim,
1300 SdfPath const& cachePath,
1301 UsdTimeCode time) const
1302 {
1303 return VtValue();
1304 }
1305
1306 /*virtual*/
1307 GfRange3d
GetExtent(UsdPrim const & prim,SdfPath const & cachePath,UsdTimeCode time) const1308 UsdImagingPrimAdapter::GetExtent(UsdPrim const& prim,
1309 SdfPath const& cachePath,
1310 UsdTimeCode time) const
1311 {
1312 return GfRange3d();
1313 }
1314
1315 /*virtual*/
1316 bool
GetDoubleSided(UsdPrim const & prim,SdfPath const & cachePath,UsdTimeCode time) const1317 UsdImagingPrimAdapter::GetDoubleSided(UsdPrim const& prim,
1318 SdfPath const& cachePath,
1319 UsdTimeCode time) const
1320 {
1321 return false;
1322 }
1323
1324 /*virtual*/
1325 SdfPath
GetMaterialId(UsdPrim const & prim,SdfPath const & cachePath,UsdTimeCode time) const1326 UsdImagingPrimAdapter::GetMaterialId(UsdPrim const& prim,
1327 SdfPath const& cachePath,
1328 UsdTimeCode time) const
1329 {
1330 return SdfPath();
1331 }
1332
1333 /*virtual*/
1334 VtValue
GetMaterialResource(UsdPrim const & prim,SdfPath const & cachePath,UsdTimeCode time) const1335 UsdImagingPrimAdapter::GetMaterialResource(UsdPrim const& prim,
1336 SdfPath const& cachePath,
1337 UsdTimeCode time) const
1338 {
1339 return VtValue();
1340 }
1341
1342 /*virtual*/
1343 const TfTokenVector &
GetExtComputationSceneInputNames(SdfPath const & cachePath) const1344 UsdImagingPrimAdapter::GetExtComputationSceneInputNames(
1345 SdfPath const& cachePath) const
1346 {
1347 static TfTokenVector emptyTokenVector;
1348 return emptyTokenVector;
1349 }
1350
1351 /*virtual*/
1352 HdExtComputationInputDescriptorVector
GetExtComputationInputs(UsdPrim const & prim,SdfPath const & cachePath,const UsdImagingInstancerContext * instancerContext) const1353 UsdImagingPrimAdapter::GetExtComputationInputs(
1354 UsdPrim const& prim,
1355 SdfPath const& cachePath,
1356 const UsdImagingInstancerContext* instancerContext) const
1357 {
1358 return HdExtComputationInputDescriptorVector();
1359 }
1360
1361 /*virtual*/
1362 HdExtComputationOutputDescriptorVector
GetExtComputationOutputs(UsdPrim const & prim,SdfPath const & cachePath,const UsdImagingInstancerContext * instancerContext) const1363 UsdImagingPrimAdapter::GetExtComputationOutputs(
1364 UsdPrim const& prim,
1365 SdfPath const& cachePath,
1366 const UsdImagingInstancerContext* instancerContext) const
1367 {
1368 return HdExtComputationOutputDescriptorVector();
1369 }
1370
1371 /*virtual*/
1372 HdExtComputationPrimvarDescriptorVector
GetExtComputationPrimvars(UsdPrim const & prim,SdfPath const & cachePath,HdInterpolation interpolation,const UsdImagingInstancerContext * instancerContext) const1373 UsdImagingPrimAdapter::GetExtComputationPrimvars(
1374 UsdPrim const& prim,
1375 SdfPath const& cachePath,
1376 HdInterpolation interpolation,
1377 const UsdImagingInstancerContext* instancerContext) const
1378 {
1379 return HdExtComputationPrimvarDescriptorVector();
1380 }
1381
1382 /*virtual*/
1383 VtValue
GetExtComputationInput(UsdPrim const & prim,SdfPath const & cachePath,TfToken const & name,UsdTimeCode time,const UsdImagingInstancerContext * instancerContext) const1384 UsdImagingPrimAdapter::GetExtComputationInput(
1385 UsdPrim const& prim,
1386 SdfPath const& cachePath,
1387 TfToken const& name,
1388 UsdTimeCode time,
1389 const UsdImagingInstancerContext* instancerContext) const
1390 {
1391 return VtValue();
1392 }
1393
1394 /*virtual*/
1395 size_t
SampleExtComputationInput(UsdPrim const & prim,SdfPath const & cachePath,TfToken const & name,UsdTimeCode time,const UsdImagingInstancerContext * instancerContext,size_t maxSampleCount,float * sampleTimes,VtValue * sampleValues)1396 UsdImagingPrimAdapter::SampleExtComputationInput(
1397 UsdPrim const& prim,
1398 SdfPath const& cachePath,
1399 TfToken const& name,
1400 UsdTimeCode time,
1401 const UsdImagingInstancerContext* instancerContext,
1402 size_t maxSampleCount,
1403 float *sampleTimes,
1404 VtValue *sampleValues)
1405 {
1406 if (maxSampleCount > 0) {
1407 sampleTimes[0] = 0.0;
1408 sampleValues[0] = GetExtComputationInput(prim, cachePath, name, time,
1409 instancerContext);
1410 return 1;
1411 }
1412 return 0;
1413 }
1414
1415 /*virtual*/
1416 std::string
GetExtComputationKernel(UsdPrim const & prim,SdfPath const & cachePath,const UsdImagingInstancerContext * instancerContext) const1417 UsdImagingPrimAdapter::GetExtComputationKernel(
1418 UsdPrim const& prim,
1419 SdfPath const& cachePath,
1420 const UsdImagingInstancerContext* instancerContext) const
1421 {
1422 return std::string();
1423 }
1424
1425 /*virtual*/
1426 VtValue
GetInstanceIndices(UsdPrim const & instancerPrim,SdfPath const & instancerCachePath,SdfPath const & prototypeCachePath,UsdTimeCode time) const1427 UsdImagingPrimAdapter::GetInstanceIndices(UsdPrim const& instancerPrim,
1428 SdfPath const& instancerCachePath,
1429 SdfPath const& prototypeCachePath,
1430 UsdTimeCode time) const
1431 {
1432 return VtValue();
1433 }
1434
1435 VtArray<VtIntArray>
GetPerPrototypeIndices(UsdPrim const & prim,UsdTimeCode time) const1436 UsdImagingPrimAdapter::GetPerPrototypeIndices(UsdPrim const& prim,
1437 UsdTimeCode time) const
1438 {
1439 TRACE_FUNCTION();
1440
1441 UsdImaging_PointInstancerIndicesCache &indicesCache =
1442 _delegate->_pointInstancerIndicesCache;
1443
1444 if (_IsEnabledPointInstancerIndicesCache() &&
1445 indicesCache.GetTime() == time) {
1446 return indicesCache.GetValue(prim);
1447 } else {
1448 return UsdImaging_PointInstancerIndicesStrategy::
1449 ComputePerPrototypeIndices(prim, time);
1450 }
1451 }
1452
1453 /*virtual*/
1454 GfMatrix4d
GetRelativeInstancerTransform(SdfPath const & instancerPath,SdfPath const & protoInstancerPath,UsdTimeCode time) const1455 UsdImagingPrimAdapter::GetRelativeInstancerTransform(
1456 SdfPath const &instancerPath,
1457 SdfPath const &protoInstancerPath, UsdTimeCode time) const
1458 {
1459 return GfMatrix4d(1);
1460 }
1461
1462 PXR_NAMESPACE_CLOSE_SCOPE
1463
1464