[Bf-blender-cvs] [644afda7eb6] master: Fix T102543: improve uv unwrapping with n-gons and shared vertices
Chris Blackbourn
noreply at git.blender.org
Tue Dec 6 01:43:39 CET 2022
Commit: 644afda7eb6c58d4ca745b3a16870569913ae0f9
Author: Chris Blackbourn
Date: Tue Dec 6 13:39:02 2022 +1300
Branches: master
https://developer.blender.org/rB644afda7eb6c58d4ca745b3a16870569913ae0f9
Fix T102543: improve uv unwrapping with n-gons and shared vertices
When n-gons share vertices, their triangulation can be non-manifold,
even if the original mesh is manifold.
The UV Unwrapper does not currently work with non-manifold meshes.
This workaround attempts to modify the triangulation of n-gons in
the UV unwrapper to preserve the manifold property.
This change replaces the previous fix for quads, and extends it
to all n-gons.
See T84078 as motivation for this change.
Differential Revision: https://developer.blender.org/D16521
===================================================================
M source/blender/geometry/intern/uv_parametrizer.cc
===================================================================
diff --git a/source/blender/geometry/intern/uv_parametrizer.cc b/source/blender/geometry/intern/uv_parametrizer.cc
index 15b0962d39e..5a363b4bf17 100644
--- a/source/blender/geometry/intern/uv_parametrizer.cc
+++ b/source/blender/geometry/intern/uv_parametrizer.cc
@@ -8,6 +8,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_array.hh"
#include "BLI_boxpack_2d.h"
#include "BLI_convexhull_2d.h"
#include "BLI_ghash.h"
@@ -16,6 +17,7 @@
#include "BLI_polyfill_2d.h"
#include "BLI_polyfill_2d_beautify.h"
#include "BLI_rand.h"
+#include "BLI_vector.hh"
#include "eigen_capi.h"
@@ -1129,23 +1131,7 @@ static bool p_quad_split_direction(ParamHandle *handle, const float **co, const
* depending on floating point errors to decide. */
float bias = 1.0f + 1e-6f;
float fac = len_v3v3(co[0], co[2]) * bias - len_v3v3(co[1], co[3]);
- bool dir = (fac <= 0.0f);
-
- /* The face exists check is there because of a special case:
- * when two quads share three vertices, they can each be split into two triangles,
- * resulting in two identical triangles. For example in Suzanne's nose. */
- if (dir) {
- if (p_face_exists(handle, vkeys, 0, 1, 2) || p_face_exists(handle, vkeys, 0, 2, 3)) {
- return !dir;
- }
- }
- else {
- if (p_face_exists(handle, vkeys, 0, 1, 3) || p_face_exists(handle, vkeys, 1, 2, 3)) {
- return !dir;
- }
- }
-
- return dir;
+ return fac <= 0.0f;
}
/* Construction: boundary filling */
@@ -3895,6 +3881,71 @@ void GEO_uv_parametrizer_face_add(ParamHandle *phandle,
BLI_assert(nverts >= 3);
param_assert(phandle->state == PHANDLE_STATE_ALLOCATED);
+ if (nverts > 3) {
+ /* Protect against (manifold) geometry which has a non-manifold triangulation.
+ * See T102543. */
+
+ blender::Vector<int, 32> permute;
+ permute.reserve(nverts);
+ for (int i = 0; i < nverts; i++) {
+ permute.append_unchecked(i);
+ }
+
+ int i = nverts - 1;
+ while (i >= 0) {
+ /* Just check the "ears" of the n-gon.
+ * For quads, this is sufficient.
+ * For pents and higher, we might miss internal duplicate triangles, but note
+ * that such cases are rare if the source geometry is manifold and non-intersecting. */
+ int pm = permute.size();
+ BLI_assert(pm > 3);
+ int i0 = permute[i];
+ int i1 = permute[(i + 1) % pm];
+ int i2 = permute[(i + 2) % pm];
+ if (!p_face_exists(phandle, vkeys, i0, i1, i2)) {
+ i--; /* ...All good...*/
+ continue;
+ }
+
+ /* An existing triangle has already been inserted. As a heuristic, attempt to add the
+ * *previous* triangle. \note: Should probably call `GEO_uv_parametrizer_face_add` instead of
+ * `p_face_add_construct`. */
+ int iprev = permute[(i + pm - 1) % pm];
+ p_face_add_construct(phandle, key, vkeys, co, uv, iprev, i0, i1, pin, select);
+
+ permute.remove(i);
+ if (permute.size() == 3) {
+ break;
+ }
+ }
+ if (permute.size() != nverts) {
+ int pm = permute.size();
+ /* Add the remaining pm-gon. */
+ blender::Array<ParamKey> vkeys_sub(pm);
+ blender::Array<const float *> co_sub(pm);
+ blender::Array<float *> uv_sub(pm);
+ blender::Array<bool> pin_sub(pm);
+ blender::Array<bool> select_sub(pm);
+ for (int i = 0; i < pm; i++) {
+ int j = permute[i];
+ vkeys_sub[i] = vkeys[j];
+ co_sub[i] = co[j];
+ uv_sub[i] = uv[j];
+ pin_sub[i] = pin && pin[j];
+ select_sub[i] = select && select[j];
+ }
+ p_add_ngon(phandle,
+ key,
+ pm,
+ &vkeys_sub.first(),
+ &co_sub.first(),
+ &uv_sub.first(),
+ &pin_sub.first(),
+ &select_sub.first());
+ return; /* Nothing more to do. */
+ }
+ /* No "ears" have previously been inserted. Continue as normal. */
+ }
if (nverts > 4) {
/* ngon */
p_add_ngon(phandle, key, nverts, vkeys, co, uv, pin, select);
More information about the Bf-blender-cvs
mailing list