From 033d1d242d905befb1ca7175329949fec7385ffa Mon Sep 17 00:00:00 2001 From: Ink Open Source Date: Tue, 30 Jun 2026 12:47:56 -0700 Subject: [PATCH] Set derivatives to non-zero default values in stroke subtraction. As anti-aliasing is not yet handled, `Subtract` sets anti-aliasing label to `kInterior` to effectively turn off anti-aliasing for new edges. Unfortunately, the zero values for the derivative still causes divisions-by-zero, resulting in artifacts (small cracks in the shape, missing textures, etc.). PiperOrigin-RevId: 940606592 --- ink/strokes/internal/BUILD.bazel | 1 + ink/strokes/internal/stroke_subtraction.cc | 11 +++++++++++ ink/strokes/internal/stroke_subtraction.h | 2 +- ink/strokes/internal/stroke_subtraction_test.cc | 8 ++++---- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/ink/strokes/internal/BUILD.bazel b/ink/strokes/internal/BUILD.bazel index 6b5e99f6..402e82a7 100644 --- a/ink/strokes/internal/BUILD.bazel +++ b/ink/strokes/internal/BUILD.bazel @@ -754,6 +754,7 @@ cc_library( "//ink/types:small_array", "@abseil-cpp//absl/container:flat_hash_map", "@abseil-cpp//absl/container:inlined_vector", + "@abseil-cpp//absl/log:absl_check", "@abseil-cpp//absl/status", "@abseil-cpp//absl/status:statusor", "@abseil-cpp//absl/types:span", diff --git a/ink/strokes/internal/stroke_subtraction.cc b/ink/strokes/internal/stroke_subtraction.cc index 6c064747..1e7ff1e5 100644 --- a/ink/strokes/internal/stroke_subtraction.cc +++ b/ink/strokes/internal/stroke_subtraction.cc @@ -24,6 +24,7 @@ #include "absl/container/flat_hash_map.h" #include "absl/container/inlined_vector.h" +#include "absl/log/absl_check.h" #include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/types/span.h" @@ -144,7 +145,17 @@ void AddVertex(MutableMesh& mutable_mesh, Point position, const std::array& weights) { uint32_t new_index = mutable_mesh.VertexCount(); mutable_mesh.AppendVertex(position); + const MeshFormat& format = mutable_mesh.Format(); + ABSL_DCHECK_EQ(triangle_attrs.size(), format.Attributes().size()); for (uint32_t attr = 0; attr < triangle_attrs.size(); ++attr) { + MeshFormat::AttributeId id = format.Attributes()[attr].id; + // Set derivatives to 1.0 to avoid divisions-by-zero in the shader. + if (id == MeshFormat::AttributeId::kSideDerivative || + id == MeshFormat::AttributeId::kForwardDerivative) { + mutable_mesh.SetFloatVertexAttribute(new_index, attr, {1.0f, 1.0f}); + continue; + } + const auto& vals = triangle_attrs[attr]; if (vals[0].Size() == 0) continue; uint8_t count = vals[0].Size(); diff --git a/ink/strokes/internal/stroke_subtraction.h b/ink/strokes/internal/stroke_subtraction.h index 9001b461..4c33ad37 100644 --- a/ink/strokes/internal/stroke_subtraction.h +++ b/ink/strokes/internal/stroke_subtraction.h @@ -38,7 +38,7 @@ namespace ink::strokes_internal { // input mesh. The attributes of vertices in the returned mesh are obtained // by linearly interpolating the attributes of the input mesh, except for // anti-aliasing attributes (kSideLabel, kSideDerivative, kForwardLabel, -// kForwardDerivative), which are set to zero. +// kForwardDerivative), which are set to default values. absl::StatusOr Subtract(const PartitionedMesh& mesh_a, const AffineTransform& transform_a, const PartitionedMesh& mesh_b, diff --git a/ink/strokes/internal/stroke_subtraction_test.cc b/ink/strokes/internal/stroke_subtraction_test.cc index 91b4b452..1a2d9e6a 100644 --- a/ink/strokes/internal/stroke_subtraction_test.cc +++ b/ink/strokes/internal/stroke_subtraction_test.cc @@ -219,9 +219,9 @@ TEST(StrokeSubtractionTest, TriangleMinusTriangle) { result_mesh.FloatVertexAttribute(*index_X1, 2).Values(), ElementsAre(FloatEq(0.5f), FloatEq(0.5f), FloatEq(0.0f), FloatEq(1.0f))); EXPECT_THAT(result_mesh.FloatVertexAttribute(*index_X1, 3).Values(), - ElementsAre(FloatEq(0.0f), FloatEq(0.0f))); + ElementsAre(FloatEq(1.0f), FloatEq(1.0f))); EXPECT_THAT(result_mesh.FloatVertexAttribute(*index_X1, 4).Values(), - ElementsAre(FloatEq(0.0f), FloatEq(0.0f))); + ElementsAre(FloatEq(1.0f), FloatEq(1.0f))); std::optional index_X2 = FindVertexIndex(result_mesh, X2); ASSERT_TRUE(index_X2.has_value()); @@ -231,9 +231,9 @@ TEST(StrokeSubtractionTest, TriangleMinusTriangle) { result_mesh.FloatVertexAttribute(*index_X2, 2).Values(), ElementsAre(FloatEq(0.0f), FloatEq(0.5f), FloatEq(0.5f), FloatEq(1.0f))); EXPECT_THAT(result_mesh.FloatVertexAttribute(*index_X2, 3).Values(), - ElementsAre(FloatEq(0.0f), FloatEq(0.0f))); + ElementsAre(FloatEq(1.0f), FloatEq(1.0f))); EXPECT_THAT(result_mesh.FloatVertexAttribute(*index_X2, 4).Values(), - ElementsAre(FloatEq(0.0f), FloatEq(0.0f))); + ElementsAre(FloatEq(1.0f), FloatEq(1.0f))); } TEST(StrokeSubtractionTest, AttributeInterpolation) {