Skip to content

Commit

Permalink
Update UsdGeomPrimvar::ComputeFlattened() to consider elementSize
Browse files Browse the repository at this point in the history
(Internal change: 2297892)
  • Loading branch information
diyajoy authored and pixar-oss committed Oct 26, 2023
1 parent de07491 commit f7cfdb1
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 45 deletions.
56 changes: 34 additions & 22 deletions pxr/usd/usdGeom/primvar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ template <typename ArrayType>
bool
UsdGeomPrimvar::_ComputeFlattenedArray(const VtValue &attrVal,
const VtIntArray &indices,
int elementSize,
VtValue *value,
std::string *errorString)
{
Expand All @@ -328,7 +329,7 @@ UsdGeomPrimvar::_ComputeFlattenedArray(const VtValue &attrVal,

ArrayType result;
if (_ComputeFlattenedHelper(attrVal.UncheckedGet<ArrayType>(), indices,
&result, errorString)) {
elementSize, &result, errorString)) {
*value = VtValue::Take(result);
}

Expand Down Expand Up @@ -358,7 +359,7 @@ UsdGeomPrimvar::ComputeFlattened(VtValue *value, UsdTimeCode time) const
}

std::string errStr;
bool res = ComputeFlattened(value, attrVal, indices, &errStr);
bool res = ComputeFlattened(value, attrVal, indices, GetElementSize(), &errStr);
if (!errStr.empty()) {
TF_WARN("For primvar %s: %s",
UsdDescribe(_attr).c_str(), errStr.c_str());
Expand All @@ -372,6 +373,17 @@ UsdGeomPrimvar::ComputeFlattened(
const VtValue &attrVal,
const VtIntArray &indices,
std::string *errStr)
{
return ComputeFlattened(value, attrVal, indices, 1, errStr);
}

bool
UsdGeomPrimvar::ComputeFlattened(
VtValue *value,
const VtValue &attrVal,
const VtIntArray &indices,
int elementSize,
std::string *errStr)
{
// If the primvar attr value is not an array simply return the
// attribute value.
Expand All @@ -382,28 +394,28 @@ UsdGeomPrimvar::ComputeFlattened(

// Handle all known supported array value types.
bool foundSupportedType =
_ComputeFlattenedArray<VtVec2fArray>(attrVal, indices, value, errStr) ||
_ComputeFlattenedArray<VtVec2dArray>(attrVal, indices, value, errStr) ||
_ComputeFlattenedArray<VtVec2iArray>(attrVal, indices, value, errStr) ||
_ComputeFlattenedArray<VtVec2hArray>(attrVal, indices, value, errStr) ||
_ComputeFlattenedArray<VtVec3fArray>(attrVal, indices, value, errStr) ||
_ComputeFlattenedArray<VtVec3dArray>(attrVal, indices, value, errStr) ||
_ComputeFlattenedArray<VtVec3iArray>(attrVal, indices, value, errStr) ||
_ComputeFlattenedArray<VtVec3hArray>(attrVal, indices, value, errStr) ||
_ComputeFlattenedArray<VtVec4fArray>(attrVal, indices, value, errStr) ||
_ComputeFlattenedArray<VtVec4dArray>(attrVal, indices, value, errStr) ||
_ComputeFlattenedArray<VtVec4iArray>(attrVal, indices, value, errStr) ||
_ComputeFlattenedArray<VtVec4hArray>(attrVal, indices, value, errStr) ||
_ComputeFlattenedArray<VtMatrix3dArray>(attrVal, indices, value,
_ComputeFlattenedArray<VtVec2fArray>(attrVal, indices, elementSize, value, errStr) ||
_ComputeFlattenedArray<VtVec2dArray>(attrVal, indices, elementSize, value, errStr) ||
_ComputeFlattenedArray<VtVec2iArray>(attrVal, indices, elementSize, value, errStr) ||
_ComputeFlattenedArray<VtVec2hArray>(attrVal, indices, elementSize, value, errStr) ||
_ComputeFlattenedArray<VtVec3fArray>(attrVal, indices, elementSize, value, errStr) ||
_ComputeFlattenedArray<VtVec3dArray>(attrVal, indices, elementSize, value, errStr) ||
_ComputeFlattenedArray<VtVec3iArray>(attrVal, indices, elementSize, value, errStr) ||
_ComputeFlattenedArray<VtVec3hArray>(attrVal, indices, elementSize, value, errStr) ||
_ComputeFlattenedArray<VtVec4fArray>(attrVal, indices, elementSize, value, errStr) ||
_ComputeFlattenedArray<VtVec4dArray>(attrVal, indices, elementSize, value, errStr) ||
_ComputeFlattenedArray<VtVec4iArray>(attrVal, indices, elementSize, value, errStr) ||
_ComputeFlattenedArray<VtVec4hArray>(attrVal, indices, elementSize, value, errStr) ||
_ComputeFlattenedArray<VtMatrix3dArray>(attrVal, indices, elementSize, value,
errStr) ||
_ComputeFlattenedArray<VtMatrix4dArray>(attrVal, indices, value,
_ComputeFlattenedArray<VtMatrix4dArray>(attrVal, indices, elementSize, value,
errStr) ||
_ComputeFlattenedArray<VtStringArray>(attrVal, indices, value, errStr)||
_ComputeFlattenedArray<VtDoubleArray>(attrVal, indices, value, errStr)||
_ComputeFlattenedArray<VtIntArray>(attrVal, indices, value, errStr) ||
_ComputeFlattenedArray<VtUIntArray>(attrVal, indices, value, errStr) ||
_ComputeFlattenedArray<VtFloatArray>(attrVal, indices, value, errStr) ||
_ComputeFlattenedArray<VtHalfArray>(attrVal, indices, value, errStr);
_ComputeFlattenedArray<VtStringArray>(attrVal, indices, elementSize, value, errStr)||
_ComputeFlattenedArray<VtDoubleArray>(attrVal, indices, elementSize, value, errStr)||
_ComputeFlattenedArray<VtIntArray>(attrVal, indices, elementSize, value, errStr) ||
_ComputeFlattenedArray<VtUIntArray>(attrVal, indices, elementSize, value, errStr) ||
_ComputeFlattenedArray<VtFloatArray>(attrVal, indices, elementSize, value, errStr) ||
_ComputeFlattenedArray<VtHalfArray>(attrVal, indices, elementSize, value, errStr);

if (!foundSupportedType && errStr) {
std::string thisErr = TfStringPrintf(
Expand Down
75 changes: 52 additions & 23 deletions pxr/usd/usdGeom/primvar.h
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,8 @@ class UsdGeomPrimvar
bool ComputeFlattened(VtValue *value,
UsdTimeCode time=UsdTimeCode::Default()) const;

/// Computes the flattened value of \p attrValue given \p indices.
/// Computes the flattened value of \p attrValue given \p indices, assuming
/// an elementSize of 1.
///
/// This method is a static convenience function that performs the main
/// work of ComputeFlattened above without needing an instance of a
Expand All @@ -624,7 +625,24 @@ class UsdGeomPrimvar
static bool ComputeFlattened(VtValue *value, const VtValue &attrVal,
const VtIntArray &indices,
std::string *errString);


/// Computes the flattened value of \p attrValue given \p indices and
/// \p elementSize.
///
/// This method is a static convenience function that performs the main
/// work of ComputeFlattened above without needing an instance of a
/// UsdGeomPrimvar.
///
/// Returns \c false if the value contained in \p attrVal is not a supported
/// type for flattening. Otherwise returns \c true. The output
/// \p errString variable may be populated with an error string if an error
/// is encountered during flattening.
USDGEOM_API
static bool ComputeFlattened(VtValue *value, const VtValue &attrVal,
const VtIntArray &indices,
int elementSize,
std::string *errString);


/// @}

Expand Down Expand Up @@ -756,6 +774,7 @@ class UsdGeomPrimvar
template<typename ScalarType>
static bool _ComputeFlattenedHelper(const VtArray<ScalarType> &authored,
const VtIntArray &indices,
int elementSize,
VtArray<ScalarType> *value,
std::string *errString);

Expand All @@ -764,6 +783,7 @@ class UsdGeomPrimvar
template <typename ArrayType>
static bool _ComputeFlattenedArray(const VtValue &attrVal,
const VtIntArray &indices,
int elementSize,
VtValue *value,
std::string *errString);

Expand Down Expand Up @@ -823,7 +843,7 @@ UsdGeomPrimvar::ComputeFlattened(VtArray<ScalarType> *value, UsdTimeCode time) c
return false;

std::string errString;
bool res = _ComputeFlattenedHelper(authored, indices, value, &errString);
bool res = _ComputeFlattenedHelper(authored, indices, GetElementSize(), value, &errString);
if (!errString.empty()) {
TF_WARN("For primvar %s: %s",
UsdDescribe(_attr).c_str(), errString.c_str());
Expand All @@ -835,44 +855,53 @@ template<typename ScalarType>
bool
UsdGeomPrimvar::_ComputeFlattenedHelper(const VtArray<ScalarType> &authored,
const VtIntArray &indices,
int elementSize,
VtArray<ScalarType> *value,
std::string *errString)
{
value->resize(indices.size());
TF_VERIFY(elementSize >= 1);
value->resize(indices.size() * elementSize);
bool success = true;

std::vector<size_t> invalidIndexPositions;
for (size_t i=0; i < indices.size(); i++) {
int index = indices[i];
if (index >= 0 && (size_t)index < authored.size()) {
(*value)[i] = authored[index];
} else {
if (indices[i] < 0 || static_cast<size_t>((indices[i] + 1) * elementSize) > authored.size()) {
invalidIndexPositions.push_back(i);
success = false;
continue;
}

const size_t indicesIdx = indices[i] * elementSize;
const size_t valuesIdx = i * elementSize;
for (size_t j=0; j < static_cast<size_t>(elementSize); j++) {
size_t index = indicesIdx + j;
(*value)[valuesIdx + j] = authored[index];
}
}

if (!invalidIndexPositions.empty()) {
std::vector<std::string> invalidPositionsStrVec;
if (!invalidIndexPositions.empty() && errString) {
*errString = TfStringPrintf(
"Found %ld invalid indices into authored array of size %ld with"
" element size of %i:",
invalidIndexPositions.size(),
authored.size(), elementSize);

// Print a maximum of 5 invalid index positions.
size_t numElementsToPrint = std::min(invalidIndexPositions.size(),
size_t(5));
invalidPositionsStrVec.reserve(numElementsToPrint);
for (size_t i = 0; i < numElementsToPrint ; ++i) {
invalidPositionsStrVec.push_back(
TfStringify(invalidIndexPositions[i]));
}

if (errString) {
*errString = TfStringPrintf(
"Found %ld invalid indices at positions [%s%s] that are out of "
"range [0,%ld).", invalidIndexPositions.size(),
TfStringJoin(invalidPositionsStrVec, ", ").c_str(),
invalidIndexPositions.size() > 5 ? ", ..." : "",
authored.size());
int invalidIndex = indices[invalidIndexPositions[i]];
int authoredStartIndex = invalidIndex * elementSize;

*errString += TfStringPrintf(
"\n\t Invalid index %i at position %ld refers to %s of the"
" authored array, which is out of bounds",
invalidIndex,
invalidIndexPositions[i],
elementSize == 1 ? TfStringPrintf("index %i", authoredStartIndex).c_str()
: TfStringPrintf("indices [%i,...,%i]", authoredStartIndex, authoredStartIndex + elementSize - 1).c_str());
}
}

return success;
}

Expand Down
20 changes: 20 additions & 0 deletions pxr/usd/usdGeom/testenv/testUsdGeomPrimvar.py
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,26 @@ def test_PrimvarsAPI(self):
self.assertFalse(oBasePrimvar2.IsIndexed())
self.assertTrue(oBasePrimvar2.GetIndicesAttr().GetResolveInfo().ValueIsBlocked())

# Make sure ComputeFlattened works correctly
_2darr = gp_pv.CreatePrimvar('sphereHarmonics', Sdf.ValueTypeNames.FloatArray)
arrVals = Vt.FloatArray([0, 1, 2, 3, 4, 5, 6, 7, 8])
arrIdxs = Vt.IntArray([0, 1, 2, 0, 1, 2])
self.assertTrue( _2darr.Set(arrVals))
self.assertTrue(_2darr.SetIndices(arrIdxs))
self.assertTrue(_2darr.IsIndexed())

self.assertTrue(_2darr.SetElementSize(1))
self.assertEqual(_2darr.ComputeFlattened(), [0, 1, 2, 0, 1, 2])

self.assertTrue(_2darr.SetElementSize(2))
self.assertEqual(_2darr.ComputeFlattened(), [0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5])

self.assertTrue(_2darr.SetElementSize(3))
self.assertEqual(_2darr.ComputeFlattened(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8])

self.assertTrue(_2darr.SetElementSize(4))
self.assertEqual(_2darr.ComputeFlattened(), None)

def test_Bug124579(self):
from pxr import Usd
from pxr import UsdGeom
Expand Down

0 comments on commit f7cfdb1

Please sign in to comment.