Fix: Small changes to USD and Alembic curves import

Make both importers work the same way: first building an array
of the new offsets, then comparing the offsets to check if the
topology changed. Previously the USD importer incorrectly
compared curve offsets to USD point counts.

Also:
- Don't unnecessarily set the resolution to the incorrect default.
  The default for the curves system is 12. But it's unnecessary to
  fill the attribute to the default value anyway.
- Use some helper methods to iterate over all curves.
- Use float literal instead of integer.
- Use cast and `copy_from` for positions copy
- Pass Span by value

Pull Request: https://projects.blender.org/blender/blender/pulls/118829
This commit is contained in:
Hans Goudey
2024-02-28 05:05:53 +01:00
committed by Hans Goudey
parent 5ed9c8c9dd
commit 5c5089d651
2 changed files with 26 additions and 62 deletions

View File

@@ -139,18 +139,9 @@ static CurveType get_curve_type(const Alembic::AbcGeom::BasisType basis)
static bool curves_topology_changed(const bke::CurvesGeometry &curves,
Span<int> preprocessed_offsets)
{
/* Offsets have an extra element. */
if (curves.curve_num != preprocessed_offsets.size() - 1) {
if (curves.offsets() != preprocessed_offsets) {
return true;
}
const Span<int> offsets = curves.offsets();
for (const int i_curve : preprocessed_offsets.index_range()) {
if (offsets[i_curve] != preprocessed_offsets[i_curve]) {
return true;
}
}
return false;
}

View File

@@ -41,17 +41,17 @@ static int point_count(int usdCount, CurveType curve_type, bool is_cyclic)
return usdCount;
}
/** Return the sum of the values of each element in `usdCounts`. This is used for precomputing the
* total number of points for all curves in some curve primitive. */
static int accumulate_point_count(const pxr::VtIntArray &usdCounts,
CurveType curve_type,
bool is_cyclic)
static Array<int> calc_curve_offsets(const pxr::VtIntArray &usdCounts,
const CurveType curve_type,
bool is_cyclic)
{
int result = 0;
for (int v : usdCounts) {
result += point_count(v, curve_type, is_cyclic);
Array<int> offsets(usdCounts.size() + 1);
int offset = 0;
for (const int i : offsets.index_range()) {
offsets[i] = offset;
offset += point_count(usdCounts[i], curve_type, is_cyclic);
}
return result;
return offsets;
}
static void add_bezier_control_point(int cp,
@@ -59,7 +59,7 @@ static void add_bezier_control_point(int cp,
MutableSpan<float3> positions,
MutableSpan<float3> handles_left,
MutableSpan<float3> handles_right,
const Span<pxr::GfVec3f> &usdPoints)
const Span<pxr::GfVec3f> usdPoints)
{
if (offset == 0) {
positions[cp] = to_float3(usdPoints[offset]);
@@ -79,27 +79,11 @@ static void add_bezier_control_point(int cp,
}
/** Returns true if the number of curves or the number of curve points in each curve differ. */
static bool curves_topology_changed(const bke::CurvesGeometry &curves,
const pxr::VtIntArray &usdCounts,
CurveType curve_type,
int expected_total_point_num,
bool is_cyclic)
static bool curves_topology_changed(const bke::CurvesGeometry &curves, const Span<int> usd_offsets)
{
if (curves.curves_num() != usdCounts.size()) {
if (curves.offsets() != usd_offsets) {
return true;
}
if (curves.points_num() != expected_total_point_num) {
return true;
}
for (const int curve : curves.curves_range()) {
const int expected_curve_point_num = point_count(usdCounts[curve], curve_type, is_cyclic);
const int current_curve_point_num = curves.curve_offsets[curve];
if (current_curve_point_num != expected_curve_point_num) {
return true;
}
}
return false;
}
@@ -175,17 +159,17 @@ void USDCurvesReader::read_curve_sample(Curves *curves_id, const double motionSa
const CurveType curve_type = get_curve_type(type, basis);
const bool is_cyclic = wrap == pxr::UsdGeomTokens->periodic;
const int num_subcurves = usdCounts.size();
const int num_points = accumulate_point_count(usdCounts, curve_type, is_cyclic);
const int default_resolution = 6;
const int curves_num = usdCounts.size();
const Array<int> new_offsets = calc_curve_offsets(usdCounts, curve_type, is_cyclic);
bke::CurvesGeometry &curves = curves_id->geometry.wrap();
if (curves_topology_changed(curves, usdCounts, curve_type, num_points, is_cyclic)) {
curves.resize(num_points, num_subcurves);
if (curves_topology_changed(curves, new_offsets)) {
curves.resize(new_offsets.last(), curves_num);
}
curves.offsets_for_write().copy_from(new_offsets);
curves.fill_curve_types(curve_type);
curves.resolution_for_write().fill(default_resolution);
if (is_cyclic) {
curves.cyclic_for_write().fill(true);
@@ -196,7 +180,6 @@ void USDCurvesReader::read_curve_sample(Curves *curves_id, const double motionSa
curves.nurbs_orders_for_write().fill(curve_order);
}
MutableSpan<int> offsets = curves.offsets_for_write();
MutableSpan<float3> positions = curves.positions_for_write();
/* Bezier curves require care in filing out their left/right handles. */
@@ -210,12 +193,10 @@ void USDCurvesReader::read_curve_sample(Curves *curves_id, const double motionSa
int usd_point_offset = 0;
int point_offset = 0;
for (const int i : IndexRange(num_subcurves)) {
for (const int i : curves.curves_range()) {
const int usd_point_count = usdCounts[i];
const int point_count = bezier_point_count(usd_point_count, is_cyclic);
offsets[i] = point_offset;
int cp_offset = 0;
for (const int cp : IndexRange(point_count)) {
add_bezier_control_point(cp,
@@ -232,16 +213,8 @@ void USDCurvesReader::read_curve_sample(Curves *curves_id, const double motionSa
}
}
else {
int offset = 0;
for (const int i : IndexRange(num_subcurves)) {
const int num_verts = usdCounts[i];
offsets[i] = offset;
offset += num_verts;
}
for (const int i_point : curves.points_range()) {
positions[i_point] = to_float3(usdPoints[i_point]);
}
static_assert(sizeof(pxr::GfVec3f) == sizeof(float3));
positions.copy_from(Span(usdPoints.data(), usdPoints.size()).cast<float3>());
}
if (!usdWidths.empty()) {
@@ -251,7 +224,7 @@ void USDCurvesReader::read_curve_sample(Curves *curves_id, const double motionSa
pxr::TfToken widths_interp = curve_prim_.GetWidthsInterpolation();
if (widths_interp == pxr::UsdGeomTokens->constant) {
radii.span.fill(usdWidths[0] / 2);
radii.span.fill(usdWidths[0] / 2.0f);
}
else {
const bool is_bezier_vertex_interp = (type == pxr::UsdGeomTokens->cubic &&
@@ -262,13 +235,13 @@ void USDCurvesReader::read_curve_sample(Curves *curves_id, const double motionSa
* Assign the widths as-if it were 'varying' only. */
int usd_point_offset = 0;
int point_offset = 0;
for (const int i : IndexRange(num_subcurves)) {
for (const int i : curves.curves_range()) {
const int usd_point_count = usdCounts[i];
const int point_count = bezier_point_count(usd_point_count, is_cyclic);
int cp_offset = 0;
for (const int cp : IndexRange(point_count)) {
radii.span[point_offset + cp] = usdWidths[usd_point_offset + cp_offset] / 2;
radii.span[point_offset + cp] = usdWidths[usd_point_offset + cp_offset] / 2.0f;
cp_offset += 3;
}
@@ -278,7 +251,7 @@ void USDCurvesReader::read_curve_sample(Curves *curves_id, const double motionSa
}
else {
for (const int i_point : curves.points_range()) {
radii.span[i_point] = usdWidths[i_point] / 2;
radii.span[i_point] = usdWidths[i_point] / 2.0f;
}
}
}