[Bf-blender-cvs] [0a0cd2454a5] temp-T97352-3d-texturing-seam-bleeding-b: Added testcases.
Jeroen Bakker
noreply at git.blender.org
Wed May 18 11:43:27 CEST 2022
Commit: 0a0cd2454a555e5d6574aff855ff8b1e3b984f9c
Author: Jeroen Bakker
Date: Wed May 18 11:43:22 2022 +0200
Branches: temp-T97352-3d-texturing-seam-bleeding-b
https://developer.blender.org/rB0a0cd2454a555e5d6574aff855ff8b1e3b984f9c
Added testcases.
===================================================================
A source/blender/blenkernel/BKE_uv_islands.hh
M source/blender/blenkernel/BKE_volume_to_mesh.hh
M source/blender/blenkernel/CMakeLists.txt
M source/blender/blenkernel/intern/pbvh_pixels.cc
A source/blender/blenkernel/intern/uv_islands_test.cc
===================================================================
diff --git a/source/blender/blenkernel/BKE_uv_islands.hh b/source/blender/blenkernel/BKE_uv_islands.hh
new file mode 100644
index 00000000000..6af47d029c7
--- /dev/null
+++ b/source/blender/blenkernel/BKE_uv_islands.hh
@@ -0,0 +1,401 @@
+
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#pragma once
+
+#include "BLI_math_vec_types.hh"
+#include "BLI_vector.hh"
+
+#include "DNA_meshdata_types.h"
+
+namespace blender::bke::uv_islands {
+// TODO: primitives can be added twice
+// TODO: Joining uv island should check where the borders could be merged.
+// TODO: this isn't optimized for performance.
+
+struct UVIslandEdge {
+ float2 uv1;
+ float2 uv2;
+
+ UVIslandEdge() : uv1(float2(0.0f, 0.0f)), uv2(float2(0.0f, 0.0f))
+ {
+ }
+
+ UVIslandEdge(const float2 &uv1, const float2 &uv2) : uv1(uv1), uv2(uv2)
+ {
+ }
+
+ bool operator==(const UVIslandEdge &other) const
+ {
+ return (uv1 == other.uv1 && uv2 == other.uv2) || (uv1 == other.uv2 && uv2 == other.uv1);
+ }
+
+ void print() const
+ {
+ printf("UVIslandEdge(float2(%f, %f), float2(%f, %f))\n", uv1.x, uv1.y, uv2.x, uv2.y);
+ }
+};
+
+struct Primitive {
+ uint64_t index;
+ UVIslandEdge edge[3];
+
+ Primitive()
+ {
+ }
+
+ Primitive(uint64_t index,
+ const UVIslandEdge &edge1,
+ const UVIslandEdge &edge2,
+ const UVIslandEdge &edge3)
+ : index(index), edge({edge1, edge2, edge3})
+ {
+ }
+
+ Primitive(uint64_t index, const MLoopTri &tri, const MLoopUV *mloopuv) : index(index)
+ {
+ const float2 uv1(mloopuv[tri.tri[0]].uv);
+ const float2 uv2(mloopuv[tri.tri[1]].uv);
+ const float2 uv3(mloopuv[tri.tri[2]].uv);
+ edge[0] = UVIslandEdge(uv1, uv2);
+ edge[1] = UVIslandEdge(uv2, uv3);
+ edge[2] = UVIslandEdge(uv3, uv1);
+ }
+
+ void print() const
+ {
+ printf(">>>> Primitive(start)\n");
+ for (int i = 0; i < 3; i++) {
+ edge[i].print();
+ }
+ printf("<<<< Primitive(end)\n");
+ }
+};
+
+/* Mapping between generated primitives and original primitives. */
+struct UVIslandPrimitive {
+ uint64_t orig_prim;
+
+ UVIslandPrimitive(uint64_t orig_prim) : orig_prim(orig_prim)
+ {
+ }
+};
+
+class UVIsland {
+ // We might want to use a linked list as there are more edits then reads.
+ Vector<UVIslandEdge> borders;
+ Vector<UVIslandPrimitive> primitives;
+
+ public:
+ void print() const
+ {
+ printf(">>>> UVIsland(start)\n");
+ for (int i = 0; i < borders.size(); i++) {
+ const UVIslandEdge &border = borders[i];
+ printf("island.add(");
+ border.print();
+ printf("); // %d\n", i);
+ }
+ printf("<<<< UVIsland(end)\n");
+ }
+ /* Join a given UVIsland into self by using the given tri as the edges that needs to be merged.
+ */
+ void join(const UVIsland &other, const Primitive &primitive)
+ {
+ printf("Before joining");
+ print();
+ other.print();
+ primitive.print();
+
+ int64_t a_edge_index[3];
+ int64_t b_edge_index[3];
+ for (int i = 0; i < 3; i++) {
+ a_edge_index[i] = borders.first_index_of_try(primitive.edge[i]);
+ b_edge_index[i] = other.borders.first_index_of_try(primitive.edge[i]);
+ }
+
+ // CHeck the number of edges. Based on this a different way should be used for joining.
+ // these are the cases:
+ // * self contains a single edge, other contains a single edge.
+ // * self contains a single edge, other contains a double edge.
+ // * self contains a double edge, other contains a single edge.
+ // * self contains a double edge, other contains a double edge.
+ int a_border_len = 0;
+ int b_border_len = 0;
+ for (int i = 0; i < 3; i++) {
+ if (a_edge_index[i] != -1) {
+ a_border_len += 1;
+ }
+ if (b_edge_index[i] != -1) {
+ b_border_len += 1;
+ }
+ }
+ BLI_assert_msg(a_border_len == 1 || a_border_len == 2, "Incorrect number of borders.");
+ BLI_assert_msg(b_border_len == 1 || b_border_len == 2, "Incorrect number of borders.");
+
+ if (a_border_len == 1 && b_border_len == 1) {
+ printf("1-1 join\n");
+ BLI_assert_unreachable();
+ }
+ if (a_border_len == 1 && b_border_len == 2) {
+ printf("1-2 join\n");
+ BLI_assert_unreachable();
+ }
+ if (a_border_len == 2 && b_border_len == 1) {
+ printf("2-1 join\n");
+ BLI_assert_unreachable();
+ }
+ if (a_border_len == 2 && b_border_len == 2) {
+ printf("2-2 join\n");
+ int common_edge_len = 0;
+ for (int i = 0; i < 3; i++) {
+ if (a_edge_index[i] != -1 && b_edge_index[i] != -1) {
+ common_edge_len++;
+ }
+ }
+
+ Vector<uint64_t> edges_to_remove_from_dst;
+ uint64_t insert;
+ uint64_t start;
+ uint64_t end;
+
+ switch (common_edge_len) {
+ case 0:
+ BLI_assert_unreachable();
+ break;
+
+ case 1: {
+ /* Determine the common edge. */
+ int common_edge = -1;
+ for (int i = 0; i < 3; i++) {
+ if (a_edge_index[i] != -1 && b_edge_index[i] != -1) {
+ BLI_assert(common_edge == -1);
+ common_edge = i;
+ }
+ }
+
+ int next_edge = (common_edge + 1) % 3;
+ int prev_edge = 3 - common_edge - next_edge;
+ BLI_assert(common_edge != -1);
+ int other_b_edge = b_edge_index[next_edge] != -1 ? next_edge : prev_edge;
+
+ // In this case there should be a single common edge. This edge will still be an edge
+ // in the merged island. find the index where to insert the other. find the start and
+ // end to the other to insert.
+ end = b_edge_index[common_edge];
+ start = b_edge_index[other_b_edge];
+
+ int other_a_edge = a_edge_index[next_edge] != -1 ? next_edge : prev_edge;
+ insert = a_edge_index[common_edge];
+ if (other_a_edge == common_edge - 1) {
+ edges_to_remove_from_dst.append(insert);
+ insert--;
+ }
+ break;
+ }
+
+ case 2: {
+ // find edge that isn't common.
+ int unshared_edge = -1;
+ for (int i = 0; i < 3; i++) {
+ if (a_edge_index[i] == -1 || b_edge_index[i] == -1) {
+ unshared_edge = i;
+ }
+ }
+ int next_edge = (unshared_edge + 1) % 3;
+ int prev_edge = 3 - unshared_edge - next_edge;
+ edges_to_remove_from_dst.append(a_edge_index[next_edge]);
+ edges_to_remove_from_dst.append(a_edge_index[prev_edge]);
+ insert = prev_edge;
+
+ break;
+ }
+ }
+
+ // TODO: It could be that different edge should be removed and copies start at other
+ // locations depending on next_edge/prev_edge selection.
+ // TODO: sort_reversed?
+ for (uint64_t index_to_remove : edges_to_remove_from_dst) {
+ borders.remove(index_to_remove);
+ printf("removed %d: ", index_to_remove);
+ print();
+ }
+
+ printf("i:%d s:%d e:%d\n", insert, start, end);
+
+ if (end < start) {
+ // TODO: these loops can be done with a single call and an iterator. For debugging and need
+ // to look how to use the iterators this hasn't been done.
+ for (int i = end - 1; i >= 0; i--) {
+ borders.insert(insert, other.borders[i]);
+ printf("insert: %d->%d", i, insert);
+ print();
+ BLI_assert(borders[insert].uv2 == borders[insert + 1].uv1);
+ }
+ for (int i = other.borders.size() - 1; i > start; i--) {
+ borders.insert(insert, other.borders[i]);
+ printf("insert: %d->%d", i, insert);
+ print();
+ BLI_assert(borders[insert].uv2 == borders[insert + 1].uv1);
+ }
+ }
+ else {
+ for (int i = end; i >= start; i--) {
+ borders.insert(insert, other.borders[i]);
+ printf("insert: %d->%d", i, insert);
+ print();
+ BLI_assert(borders[insert].uv2 == borders[insert + 1].uv1);
+ }
+ }
+ }
+
+ printf("After joining");
+ print();
+
+ BLI_assert(validate());
+ }
+
+ void add(const UVIslandEdge &border)
+ {
+ borders.append(border);
+ }
+
+ void extend_border(const int64_t edge_to_remove,
+ const UVIslandEdge &border1,
+ const UVIslandEdge &border2)
+ {
+ BLI_assert_msg(border1.uv2 == border2.uv1,
+ "Winding order of replacement borders is not correct.");
+ borders[edge_to_remove] = border2;
+ borders.insert(edge_to_remove, border1);
+ BLI_assert(validate());
+ }
+
+ void extend_border(const int64_t edge1_to_remove,
+ const int64_t edge2_to_remove,
+ const UVIslandEdge &border)
+ {
+ borders[edge1_to_remove] = border;
+ borders.remove(edge2_to_remove);
+ BLI_assert(validate());
+ }
+
+ /** Try to extend the border of the uv island by adding the given tri. Returns false when the
+ * border couldn't be extended. This happens when there is no common edge in uv space. */
+ bool extend_border(const Primitive &primitive)
+ {
+ const int64_t edge1_index = borders.first_index_of_try(primitive.edge[0]);
+ const int64_t edge2_index = borders.first_index_of_try(primitive.edge[1]);
+ const int64_t edge3_index = borders.first_index_of_try(primitive.edge[2]);
+ const bool has_edge1 = edge1_index != -1;
+ const bool has_edge2 = edge2_index != -1;
+ const bool has_edge3 = edge3_index != -1;
+
+ if (has_edge1 == false && has_edge2 == false && has_edge3 == false) {
+ /* Cannot extend as there is no common edge with a border. */
+ return false;
+ }
+ if (has_edge1 == false && has_edge2 == false && has_edge3 == true) {
+ extend_border(edge3_index, primitive.edge[0], primitive.edge[1]);
+ return true;
+ }
+ if (has_edge1 == false && has_edge2 == true && has_edge3 == false) {
+ extend_border(edge2_index, primitive.edge[2], primitive.edge[0]);
+ return true;
+ }
+ if (has_edge1 == false && has_edge2 == true && has_edge3 == true) {
+ extend_border(edge2_index, edge3_index, primitive.edge[0]);
+ return true;
+ }
+ if (has_edge1 == true && has_edg
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list