[Bf-blender-cvs] [ec703819c1b] temp-T97352-3d-texturing-seam-bleeding-b2: Add missing segments from a fan.
Jeroen Bakker
noreply at git.blender.org
Tue Jun 14 14:57:00 CEST 2022
Commit: ec703819c1bb00f3003d6e76df749ed4977ced14
Author: Jeroen Bakker
Date: Tue Jun 14 13:11:48 2022 +0200
Branches: temp-T97352-3d-texturing-seam-bleeding-b2
https://developer.blender.org/rBec703819c1bb00f3003d6e76df749ed4977ced14
Add missing segments from a fan.
TODO: Borders should be updated.
===================================================================
M source/blender/blenkernel/BKE_uv_islands.hh
M source/blender/blenkernel/intern/uv_islands.cc
===================================================================
diff --git a/source/blender/blenkernel/BKE_uv_islands.hh b/source/blender/blenkernel/BKE_uv_islands.hh
index 792acd41f00..31f0144539a 100644
--- a/source/blender/blenkernel/BKE_uv_islands.hh
+++ b/source/blender/blenkernel/BKE_uv_islands.hh
@@ -8,6 +8,7 @@
#include "BLI_array.hh"
#include "BLI_edgehash.h"
+#include "BLI_float3x3.hh"
#include "BLI_math.h"
#include "BLI_math_vec_types.hh"
#include "BLI_vector.hh"
@@ -73,6 +74,16 @@ struct MeshPrimitive {
return vertices[0];
}
+ bool has_vertex(const MeshVertex &v) const
+ {
+ for (int i = 0; i < 3; i++) {
+ if (vertices[i].vertex == &v) {
+ return true;
+ }
+ }
+ return false;
+ }
+
MeshUVVert *get_other_uv_vertex(const MeshVertex *v1, const MeshVertex *v2)
{
BLI_assert(vertices[0].vertex == v1 || vertices[1].vertex == v1 || vertices[2].vertex == v1);
@@ -248,6 +259,14 @@ struct UVEdge {
vertex->uv_edges.append_non_duplicates(this);
}
}
+
+ UVVertex *get_other_uv_vertex(const MeshVertex *vertex)
+ {
+ if (vertices[0]->vertex == vertex) {
+ return vertices[1];
+ }
+ return vertices[0];
+ }
};
struct UVPrimitive {
@@ -394,22 +413,25 @@ struct UVBorderEdge {
struct UVBorderCorner {
UVBorderEdge *first;
UVBorderEdge *second;
+ float angle;
- UVBorderCorner(UVBorderEdge *first, UVBorderEdge *second) : first(first), second(second)
+ UVBorderCorner(UVBorderEdge *first, UVBorderEdge *second, float angle)
+ : first(first), second(second), angle(angle)
{
}
float2 uv(float factor)
{
- float2 linear;
- interp_v2_v2v2(linear, first->get_uv_vertex(0)->uv, second->get_uv_vertex(1)->uv, factor);
- float2 origin = second->get_uv_vertex(0)->uv;
+ float2 origin = first->get_uv_vertex(1)->uv;
+ float angle_between = angle * factor;
float desired_len = second->length() * factor + first->length() * (1.0 - factor);
+ float2 v = first->get_uv_vertex(0)->uv - origin;
+ normalize_v2(v);
- float2 dir = linear - origin;
- normalize_v2(dir);
-
- return origin + dir * desired_len;
+ float3x3 rot_mat = float3x3::from_rotation(angle_between);
+ float2 rotated = rot_mat * v;
+ float2 result = rotated * desired_len + first->get_uv_vertex(1)->uv;
+ return result;
}
};
diff --git a/source/blender/blenkernel/intern/uv_islands.cc b/source/blender/blenkernel/intern/uv_islands.cc
index 91bdde22c0e..4728a3e85f1 100644
--- a/source/blender/blenkernel/intern/uv_islands.cc
+++ b/source/blender/blenkernel/intern/uv_islands.cc
@@ -41,10 +41,10 @@ static std::optional<UVBorderCorner> sharpest_border_corner(UVBorder &border, fl
if (edge.flags.extendable == false) {
continue;
}
- float new_radius = border.outside_angle(edge);
- if (new_radius < *r_angle) {
- *r_angle = new_radius;
- result = UVBorderCorner(&border.edges[edge.prev_index], &edge);
+ float new_angle = border.outside_angle(edge);
+ if (new_angle < *r_angle) {
+ *r_angle = new_angle;
+ result = UVBorderCorner(&border.edges[edge.prev_index], &edge, new_angle);
}
}
return result;
@@ -55,10 +55,10 @@ static std::optional<UVBorderCorner> sharpest_border_corner(UVIsland &island)
std::optional<UVBorderCorner> result;
float sharpest_angle = std::numeric_limits<float>::max();
for (UVBorder &border : island.borders) {
- float new_radius;
- std::optional<UVBorderCorner> new_result = sharpest_border_corner(border, &new_radius);
- if (new_radius < sharpest_angle) {
- sharpest_angle = new_radius;
+ float new_angle;
+ std::optional<UVBorderCorner> new_result = sharpest_border_corner(border, &new_angle);
+ if (new_angle < sharpest_angle) {
+ sharpest_angle = new_angle;
result = new_result;
}
}
@@ -101,6 +101,7 @@ struct FanSegment {
}
};
+// TODO: should have InnerEdges and Primitives to reduce complexity in algorithm
struct Fan {
/* Blades of the fan. */
Vector<FanSegment> segments;
@@ -250,6 +251,19 @@ static void add_uv_primitive_shared_uv_edge(UVIsland &island,
island.validate_primitive(island.uv_primitives.last());
}
+static MeshPrimitive *find_fill_border(const MeshVertex &v1,
+ const MeshVertex &v2,
+ const MeshVertex &v3)
+{
+ for (MeshEdge *edge : v1.edges) {
+ for (MeshPrimitive *primitive : edge->primitives) {
+ if (primitive->has_vertex(v1) && primitive->has_vertex(v2) && primitive->has_vertex(v3)) {
+ return primitive;
+ }
+ }
+ }
+ return nullptr;
+}
/**
* Find a primitive that can be used to fill give corner.
* Will return nullptr when no primitive can be found.
@@ -296,7 +310,7 @@ static void add_uv_primitive_fill(UVIsland &island,
uv_primitive.append_to_uv_edges();
uv_primitive.append_to_uv_vertices();
island.uv_primitives.append(uv_primitive);
- island.validate_primitive(island.uv_primitives.last());
+ // island.validate_primitive(island.uv_primitives.last());
}
static void extend_at_vert(UVIsland &island, UVBorderCorner &corner, const MeshData &mesh_data)
@@ -370,20 +384,78 @@ static void extend_at_vert(UVIsland &island, UVBorderCorner &corner, const MeshD
}
else {
UVEdge *current_edge = corner.first->edge;
- FanSegment *last_added = nullptr;
- for (int i = 0; i < num_to_add + 1; i++) {
+ for (int i = 0; i < num_to_add; i++) {
+ float2 old_uv = current_edge->get_other_uv_vertex(uv_vertex->vertex)->uv;
+ MeshVertex *shared_edge_vertex =
+ current_edge->get_other_uv_vertex(uv_vertex->vertex)->vertex;
+
float factor = (i + 1.0f) / (num_to_add + 1.0f);
float2 new_uv = corner.uv(factor);
// Find an segment that contains the 'current edge'.
for (FanSegment &segment : fan.segments) {
- if (!segment.flags.should_be_added) {
+ if (segment.flags.found) {
continue;
}
- last_added = &segment;
+ // Find primitive that shares the current edge and the segment edge.
+ MeshPrimitive *fill_primitive = find_fill_border(
+ *uv_vertex->vertex,
+ *shared_edge_vertex,
+ *segment.primitive->vertices[segment.vert_order[1]].vertex);
+ if (fill_primitive == nullptr) {
+ continue;
+ }
+ MeshVertex *other_prim_vertex =
+ fill_primitive->get_other_uv_vertex(uv_vertex->vertex, shared_edge_vertex)->vertex;
+
+ UVVertex uv_vertex_template;
+ uv_vertex_template.vertex = uv_vertex->vertex;
+ uv_vertex_template.uv = uv_vertex->uv;
+ UVVertex *vertex_1_ptr = island.lookup_or_create(uv_vertex_template);
+ uv_vertex_template.vertex = shared_edge_vertex;
+ uv_vertex_template.uv = old_uv;
+ UVVertex *vertex_2_ptr = island.lookup_or_create(uv_vertex_template);
+ uv_vertex_template.vertex = other_prim_vertex;
+ uv_vertex_template.uv = new_uv;
+ UVVertex *vertex_3_ptr = island.lookup_or_create(uv_vertex_template);
+
+ add_uv_primitive_fill(
+ island, *vertex_1_ptr, *vertex_2_ptr, *vertex_3_ptr, *fill_primitive);
+
+ segment.flags.found = true;
+
+ /* TODO: should be done based on meshvertex */
+ UVPrimitive &new_prim = island.uv_primitives[island.uv_primitives.size() - 1];
+ current_edge = new_prim.get_uv_edge(uv_vertex->uv, new_uv);
+
+ break;
}
}
+
+ {
+ /* Add final segment. */
+ float2 old_uv = current_edge->get_other_uv_vertex(uv_vertex->vertex)->uv;
+ MeshVertex *shared_edge_vertex =
+ current_edge->get_other_uv_vertex(uv_vertex->vertex)->vertex;
+ MeshPrimitive *fill_primitive = find_fill_border(
+ *uv_vertex->vertex, *shared_edge_vertex, *corner.second->get_uv_vertex(1)->vertex);
+ BLI_assert(fill_primitive);
+ MeshVertex *other_prim_vertex =
+ fill_primitive->get_other_uv_vertex(uv_vertex->vertex, shared_edge_vertex)->vertex;
+
+ UVVertex uv_vertex_template;
+ uv_vertex_template.vertex = uv_vertex->vertex;
+ uv_vertex_template.uv = uv_vertex->uv;
+ UVVertex *vertex_1_ptr = island.lookup_or_create(uv_vertex_template);
+ uv_vertex_template.vertex = shared_edge_vertex;
+ uv_vertex_template.uv = old_uv;
+ UVVertex *vertex_2_ptr = island.lookup_or_create(uv_vertex_template);
+ uv_vertex_template.vertex = other_prim_vertex;
+ uv_vertex_template.uv = corner.second->get_uv_vertex(1)->uv;
+ UVVertex *vertex_3_ptr = island.lookup_or_create(uv_vertex_template);
+ add_uv_primitive_fill(island, *vertex_1_ptr, *vertex_2_ptr, *vertex_3_ptr, *fill_primitive);
+ }
}
}
@@ -408,7 +480,7 @@ void UVIsland::extend_border(const UVIslandsMask &mask,
// Debug setting to reduce the extension to a number of iterations as long as not all corner
// cases have been implemented.
- int num_iterations = 6;
+ int num_iterations = 7;
while (num_iterations) {
if (num_iterations == 1) {
printf("Last iteration");
@@ -426,7 +498,7 @@ void UVIsland::extend_border(const UVIslandsMask &mask,
// TODO: extend
extend_at_vert(*this, *extension_corner, mesh_data);
- validate_border();
+ // validate_border();
/* Mark that the vert is extended. Unable to extend twice. */
extension_corner->second->flags.extendable = false;
More information about the Bf-blender-cvs
mailing list