Skip to content

Commit

Permalink
[usdImaging] Implement SamplePrimvar for the native instancer adapter.
Browse files Browse the repository at this point in the history
Fixes PixarAnimationStudios#996

(Internal change: 2030572)
  • Loading branch information
tcauchois authored and pixar-oss committed Dec 19, 2019
1 parent 8e70a72 commit 7aa0f5b
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 22 deletions.
139 changes: 117 additions & 22 deletions pxr/usdImaging/usdImaging/instanceAdapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -764,7 +764,6 @@ struct UsdImagingInstanceAdapter::_GatherInstanceTransformTimeSamplesFn
localTimeSamples.begin(),
localTimeSamples.end());
}

}
return true;
}
Expand All @@ -788,6 +787,73 @@ UsdImagingInstanceAdapter::_GatherInstanceTransformsTimeSamples(
return true;
}

struct UsdImagingInstanceAdapter::_GatherInstancePrimvarTimeSamplesFn
{
_GatherInstancePrimvarTimeSamplesFn(
const UsdImagingInstanceAdapter* adapter_,
const GfInterval& interval_,
TfToken const& key_)
: adapter(adapter_), interval(interval_), key(key_)
{ }

void Initialize(size_t numInstances)
{ }

bool operator()(
const std::vector<UsdPrim>& instanceContext, size_t instanceIdx)
{
SdfPathVector instanceChain;
for (UsdPrim const& prim : instanceContext) {
instanceChain.push_back(prim.GetPath());
}
SdfPath instanceChainPath =
adapter->_GetPrimPathFromInstancerChain(instanceChain);
if (UsdPrim instanceProxyPrim =
adapter->_GetPrim(instanceChainPath)) {
UsdImaging_InheritedPrimvarStrategy::value_type
inheritedPrimvarRecord =
adapter->_GetInheritedPrimvars(instanceProxyPrim);
if (inheritedPrimvarRecord) {
for (auto const& pv : inheritedPrimvarRecord->primvars) {
if (pv.GetPrimvarName() == key) {
// At this point, pv is the actual primvar attribute
// for this instantiation of instanceContext.
std::vector<double> localTimeSamples;
pv.GetTimeSamplesInInterval(interval, &localTimeSamples);

// Join timesamples
result.insert(
result.end(),
localTimeSamples.begin(),
localTimeSamples.end());
}
}
}
}
return true;
}

const UsdImagingInstanceAdapter* adapter;
GfInterval interval;
TfToken key;
std::vector<double> result;
};

bool
UsdImagingInstanceAdapter::_GatherInstancePrimvarTimeSamples(
UsdPrim const& instancer,
TfToken const& key,
GfInterval interval,
std::vector<double>* outTimes) const
{
HD_TRACE_FUNCTION();

_GatherInstancePrimvarTimeSamplesFn gatherSamples(this, interval, key);
_RunForAllInstancesToDraw(instancer, &gatherSamples);
outTimes->swap(gatherSamples.result);
return true;
}

struct UsdImagingInstanceAdapter::_IsInstanceTransformVaryingFn
{
_IsInstanceTransformVaryingFn(const UsdImagingInstanceAdapter* adapter_)
Expand Down Expand Up @@ -1540,34 +1606,63 @@ UsdImagingInstanceAdapter::SamplePrimvar(
maxNumSamples, sampleTimes, sampleValues);
}

GfInterval interval = _GetCurrentTimeSamplingInterval();
std::vector<double> timeSamples;
SdfValueTypeName type;

if (key != HdInstancerTokens->instanceTransform) {
// "instanceTransform" is built-in and synthesized, but other primvars
// need to be in the inherited primvar list. Loop through to check
// existence and find the correct type.
_InstancerData const* instrData =
TfMapLookupPtr(_instancerData, usdPrim.GetPath());
if (!instrData) {
return 0;
}
bool found = false;
for (auto const& ipv : instrData->inheritedPrimvars) {
if (ipv.name == key) {
type = ipv.type;
found = true;
break;
}
}
if (!found) {
return 0;
}
}

if (key == HdInstancerTokens->instanceTransform) {
GfInterval interval = _GetCurrentTimeSamplingInterval();
std::vector<double> timeSamples;
_GatherInstanceTransformsTimeSamples(usdPrim, interval, &timeSamples);
timeSamples.push_back(interval.GetMin());
timeSamples.push_back(interval.GetMax());

// Sort here
std::sort(timeSamples.begin(), timeSamples.end());
timeSamples.erase(
std::unique(timeSamples.begin(),
timeSamples.end()),
timeSamples.end());
size_t numSamples = timeSamples.size();

size_t numSamplesToEvaluate = std::min(maxNumSamples, numSamples);
for (size_t i=0; i < numSamplesToEvaluate; ++i) {
sampleTimes[i] = timeSamples[i] - time.GetValue();
} else {
_GatherInstancePrimvarTimeSamples(usdPrim, key, interval, &timeSamples);
}

timeSamples.push_back(interval.GetMin());
timeSamples.push_back(interval.GetMax());

// Sort here
std::sort(timeSamples.begin(), timeSamples.end());
timeSamples.erase(
std::unique(timeSamples.begin(),
timeSamples.end()),
timeSamples.end());
size_t numSamples = timeSamples.size();
size_t numSamplesToEvaluate = std::min(maxNumSamples, numSamples);

for (size_t i=0; i < numSamplesToEvaluate; ++i) {
sampleTimes[i] = timeSamples[i] - time.GetValue();
if (key == HdInstancerTokens->instanceTransform) {
VtMatrix4dArray xf;
_ComputeInstanceTransforms(usdPrim, &xf, timeSamples[i]);
sampleValues[i] = xf;
} else {
VtValue val;
_ComputeInheritedPrimvar(usdPrim, key, type, &val, timeSamples[i]);
sampleValues[i] = val;
}
return numSamples;
} else {
return UsdImagingPrimAdapter::SamplePrimvar(
usdPrim, cachePath, key, time,
maxNumSamples, sampleTimes, sampleValues);
}
return numSamples;
}

PxOsdSubdivTags
Expand Down
8 changes: 8 additions & 0 deletions pxr/usdImaging/usdImaging/instanceAdapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,14 @@ class UsdImagingInstanceAdapter : public UsdImagingPrimAdapter
std::vector<double>* outTimes)
const;

// Gathers the specified primvar time samples given an instancer.
struct _GatherInstancePrimvarTimeSamplesFn;
bool _GatherInstancePrimvarTimeSamples(UsdPrim const& instancer,
TfToken const& key,
GfInterval interval,
std::vector<double>* outTimes)
const;

// Returns true if any of the instances corresponding to the given
// instancer has a varying transform.
struct _IsInstanceTransformVaryingFn;
Expand Down

0 comments on commit 7aa0f5b

Please sign in to comment.