/* * Return a FloatAttribute for points. There are 4 floats per * point, where the first 3 floats are the point's position, * and the 4th float is the weight of the point. */ static FnKat::FloatAttribute _GetPwAttr( const UsdGeomNurbsPatch &nurbsPatch, double currentTime, const std::vector<double>& motionSampleTimes, const bool isMotionBackward) { UsdAttribute weightsAttr = nurbsPatch.GetPointWeightsAttr(); UsdAttribute pointsAttr = nurbsPatch.GetPointsAttr(); if (!pointsAttr) { return FnKat::FloatAttribute(); } FnKat::FloatBuilder pwBuilder(/* tupleSize = */ 4); TF_FOR_ALL(iter, motionSampleTimes) { double relSampleTime = *iter; double time = currentTime + relSampleTime; // Eval points at this motion sample time VtVec3fArray ptArray; pointsAttr.Get(&ptArray, time); // Eval Weights at this motion sample time VtDoubleArray wtArray; weightsAttr.Get(&wtArray, currentTime); bool hasWeights = false; if (ptArray.size() == wtArray.size()) { hasWeights = true; } else if (wtArray.size() > 0) { FnLogWarn("Nurbs Patch " << nurbsPatch.GetPath().GetText() << " has mismatched weights array. Skipping."); return FnKat::FloatAttribute(); } // set the points data in katana at the give motion sample time std::vector<float> &ptVec = pwBuilder.get(isMotionBackward ? PxrUsdKatanaUtils::ReverseTimeSample(relSampleTime) : relSampleTime); ptVec.resize(ptArray.size() * 4); size_t count = 0; for (size_t i = 0; i != ptArray.size(); ++i) { float weight = hasWeights ? wtArray[i] : 1.0f; ptVec[count++] = ptArray[i][0]*weight; ptVec[count++] = ptArray[i][1]*weight; ptVec[count++] = ptArray[i][2]*weight; // the 4th float is the weight of the point ptVec[count++] = weight ; } }
static void testArray() { VtDoubleArray da(60); double val = 1; TF_FOR_ALL(elem, da) *elem = val++; val = 1; for (VtDoubleArray::const_iterator i = da.begin(); i != da.end(); ++i) if (*i != val++) die("iterator"); // Do copy-on-write cases. VtDoubleArray da2 = da; da2[0] = 333.333; if (da2[0] != 333.333 || da[0] == 333.333) die("copy-on-write"); // Try swapping VtDoubleArray daCopy = da; VtDoubleArray da2Copy = da2; da.swap(da2); TF_AXIOM(da == da2Copy); TF_AXIOM(da2 == daCopy); using std::swap; swap(da, da2); TF_AXIOM(da == daCopy); TF_AXIOM(da2 == da2Copy); { // Try default-constructing a VtArray. VtDoubleArray def; TF_AXIOM(def.size() == 0); // Try iterating over the array. std::vector<double> v(def.begin(), def.end()); TF_AXIOM(v.empty()); // Test resizing a default constructed array. def.resize(123); TF_AXIOM(def.size() == 123); } { // Try creating an empty VtArray. VtDoubleArray array(0); TF_AXIOM(array.size() == 0); // Try iterating over the array. std::vector<double> v(array.begin(), array.end()); TF_AXIOM(v.empty()); } { // Array push_back and resize. VtDoubleArray array(0); // Push back on a rank-1 array. TF_AXIOM(array.size() == 0); array.push_back(1.234); TF_AXIOM(array.size() == 1); TF_AXIOM(array[0] == 1.234); array.push_back(2.3456); TF_AXIOM(array.size() == 2); TF_AXIOM(array[0] == 1.234); TF_AXIOM(array[1] == 2.3456); array.pop_back(); TF_AXIOM(array.size() == 1); TF_AXIOM(array[0] == 1.234); // Resize should preserve elements. array.resize(100); TF_AXIOM(array.size() == 100); TF_AXIOM(array[0] == 1.234); TF_AXIOM(array[1] == 0.0); TF_AXIOM(array[50] == 0.0); TF_AXIOM(array[99] == 0.0); for (size_t i = 0; i != 100; ++i) array[i] = i; array.resize(1000); TF_AXIOM(array.size() == 1000); for (size_t i = 0; i != 1000; ++i) { if (i < 100) { TF_AXIOM(array[i] == i); } else { TF_AXIOM(array[i] == 0); } } array.resize(10); TF_AXIOM(array.size() == 10); for (size_t i = 0; i != 10; ++i) { TF_AXIOM(array[i] == i); } array.pop_back(); array.pop_back(); array.pop_back(); array.pop_back(); array.pop_back(); TF_AXIOM(array.size() == 5); } { // Test that mutating shape data doesn't affect copies of an array. VtArray<int> a(4); a._GetShapeData()->otherDims[0] = 4; a._GetShapeData()->otherDims[1] = 0; VtArray<int> b = a; const auto &ca = a; const auto &cb = b; TF_AXIOM(ca._GetShapeData()->otherDims[0] == cb._GetShapeData()->otherDims[0]); TF_AXIOM(ca._GetShapeData()->otherDims[1] == cb._GetShapeData()->otherDims[1]); b._GetShapeData()->otherDims[0] = 2; b._GetShapeData()->otherDims[1] = 2; b._GetShapeData()->otherDims[2] = 0; // Check that a's shape data is unchanged TF_AXIOM(ca._GetShapeData()->otherDims[0] == 4); TF_AXIOM(ca._GetShapeData()->otherDims[1] == 0); // and that b's shape data has been updated as expected. TF_AXIOM(cb._GetShapeData()->otherDims[0] == 2); TF_AXIOM(cb._GetShapeData()->otherDims[1] == 2); TF_AXIOM(cb._GetShapeData()->otherDims[2] == 0); } { // Test initializer lists for VtArrays; VtArray<int> array1({1, 2, 3, 4}); TF_AXIOM(array1.size() == 4); TF_AXIOM(array1[0] == 1); TF_AXIOM(array1[1] == 2); TF_AXIOM(array1[2] == 3); TF_AXIOM(array1[3] == 4); array1.assign({5, 6}); TF_AXIOM(array1.size() == 2); TF_AXIOM(array1[0] == 5); TF_AXIOM(array1[1] == 6); array1.assign({}); TF_AXIOM(array1.size() == 0); array1 = {7, 8, 9}; TF_AXIOM(array1.size() == 3); TF_AXIOM(array1[0] == 7); TF_AXIOM(array1[1] == 8); TF_AXIOM(array1[2] == 9); array1 = {}; TF_AXIOM(array1.size() == 0); VtArray<int> empty({}); TF_AXIOM(empty.size() == 0); auto testImplicit = [](const VtArray<int>& array, size_t size) { TF_AXIOM(array.size() == size); }; testImplicit({1,2,3}, 3); } { // Test VtArray -> TfSpan conversions. const VtIntArray constData({1,2,3,4,5}); { VtIntArray copy(constData); TfSpan<const int> span = copy; // Make sure we didn't detach. TF_AXIOM(span.data() == constData.cdata()); TF_AXIOM(span.size() == static_cast<std::ptrdiff_t>(copy.size())); } { VtIntArray copy(constData); auto span = TfMakeConstSpan(copy); // Make sure we didn't detach. TF_AXIOM(span.data() == constData.cdata()); TF_AXIOM(span.size() == static_cast<std::ptrdiff_t>(copy.size())); } { VtIntArray copy(constData); TfSpan<int> span = copy; // Should have detached. TF_AXIOM(span.data() == copy.cdata() && span.data() != constData.cdata()); TF_AXIOM(span.size() == static_cast<std::ptrdiff_t>(copy.size())); } { VtIntArray copy(constData); auto span = TfMakeSpan(copy); // Should have detached. TF_AXIOM(span.data() == copy.cdata() && span.data() != constData.cdata()); TF_AXIOM(span.size() == static_cast<std::ptrdiff_t>(copy.size())); } } }