Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2022-08-26 21:56:43 +0300
committerHans Goudey <h.goudey@me.com>2022-08-26 21:56:50 +0300
commit6bea434c41951686949bcb9abfcabc23ab7fad9f (patch)
tree5abf70e27454804c69b8bdceb612dd7398000f7b /source/blender/bmesh/intern/bmesh_query_uv.cc
parent6a9cf59ce172483c8d6be15984e1d3ca3a60bbd2 (diff)
Cleanup: Move bmesh_query_uv.c to C++
Helpful for D14365.
Diffstat (limited to 'source/blender/bmesh/intern/bmesh_query_uv.cc')
-rw-r--r--source/blender/bmesh/intern/bmesh_query_uv.cc191
1 files changed, 191 insertions, 0 deletions
diff --git a/source/blender/bmesh/intern/bmesh_query_uv.cc b/source/blender/bmesh/intern/bmesh_query_uv.cc
new file mode 100644
index 00000000000..5a725407c6b
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_query_uv.cc
@@ -0,0 +1,191 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/** \file
+ * \ingroup bmesh
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_array.hh"
+#include "BLI_linklist.h"
+#include "BLI_math.h"
+#include "BLI_math_vec_types.hh"
+#include "BLI_utildefines_stack.h"
+
+#include "BKE_customdata.h"
+
+#include "DNA_meshdata_types.h"
+
+#include "bmesh.h"
+#include "intern/bmesh_private.h"
+
+static void uv_aspect(const BMLoop *l,
+ const float aspect[2],
+ const int cd_loop_uv_offset,
+ float r_uv[2])
+{
+ const float *uv = ((const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset))->uv;
+ r_uv[0] = uv[0] * aspect[0];
+ r_uv[1] = uv[1] * aspect[1];
+}
+
+/**
+ * Typically we avoid hiding arguments,
+ * make this an exception since it reads poorly with so many repeated arguments.
+ */
+#define UV_ASPECT(l, r_uv) uv_aspect(l, aspect, cd_loop_uv_offset, r_uv)
+
+void BM_face_uv_calc_center_median_weighted(const BMFace *f,
+ const float aspect[2],
+ const int cd_loop_uv_offset,
+ float r_cent[2])
+{
+ const BMLoop *l_iter;
+ const BMLoop *l_first;
+ float totw = 0.0f;
+ float w_prev;
+
+ zero_v2(r_cent);
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+
+ float uv_prev[2], uv_curr[2];
+ UV_ASPECT(l_iter->prev, uv_prev);
+ UV_ASPECT(l_iter, uv_curr);
+ w_prev = len_v2v2(uv_prev, uv_curr);
+ do {
+ float uv_next[2];
+ UV_ASPECT(l_iter->next, uv_next);
+ const float w_curr = len_v2v2(uv_curr, uv_next);
+ const float w = (w_curr + w_prev);
+ madd_v2_v2fl(r_cent, uv_curr, w);
+ totw += w;
+ w_prev = w_curr;
+ copy_v2_v2(uv_curr, uv_next);
+ } while ((l_iter = l_iter->next) != l_first);
+
+ if (totw != 0.0f) {
+ mul_v2_fl(r_cent, 1.0f / (float)totw);
+ }
+ /* Reverse aspect. */
+ r_cent[0] /= aspect[0];
+ r_cent[1] /= aspect[1];
+}
+
+#undef UV_ASPECT
+
+void BM_face_uv_calc_center_median(const BMFace *f, const int cd_loop_uv_offset, float r_cent[2])
+{
+ const BMLoop *l_iter;
+ const BMLoop *l_first;
+ zero_v2(r_cent);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const MLoopUV *luv = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset);
+ add_v2_v2(r_cent, luv->uv);
+ } while ((l_iter = l_iter->next) != l_first);
+
+ mul_v2_fl(r_cent, 1.0f / (float)f->len);
+}
+
+float BM_face_uv_calc_cross(const BMFace *f, const int cd_loop_uv_offset)
+{
+ blender::Array<blender::float2, BM_DEFAULT_NGON_STACK_SIZE> uvs(f->len);
+ const BMLoop *l_iter;
+ const BMLoop *l_first;
+ int i = 0;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const MLoopUV *luv = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset);
+ uvs[i++] = luv->uv;
+ } while ((l_iter = l_iter->next) != l_first);
+ return cross_poly_v2(reinterpret_cast<const float(*)[2]>(uvs.data()), f->len);
+}
+
+void BM_face_uv_minmax(const BMFace *f, float min[2], float max[2], const int cd_loop_uv_offset)
+{
+ const BMLoop *l_iter;
+ const BMLoop *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const MLoopUV *luv = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset);
+ minmax_v2v2_v2(min, max, luv->uv);
+ } while ((l_iter = l_iter->next) != l_first);
+}
+
+void BM_face_uv_transform(BMFace *f, const float matrix[2][2], const int cd_loop_uv_offset)
+{
+ BMLoop *l_iter;
+ BMLoop *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ MLoopUV *luv = (MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset);
+ mul_m2_v2(matrix, luv->uv);
+ } while ((l_iter = l_iter->next) != l_first);
+}
+
+bool BM_loop_uv_share_edge_check(BMLoop *l_a, BMLoop *l_b, const int cd_loop_uv_offset)
+{
+ BLI_assert(l_a->e == l_b->e);
+ MLoopUV *luv_a_curr = (MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_a, cd_loop_uv_offset);
+ MLoopUV *luv_a_next = (MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_a->next, cd_loop_uv_offset);
+ MLoopUV *luv_b_curr = (MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_b, cd_loop_uv_offset);
+ MLoopUV *luv_b_next = (MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_b->next, cd_loop_uv_offset);
+ if (l_a->v != l_b->v) {
+ std::swap(luv_b_curr, luv_b_next);
+ }
+ return (equals_v2v2(luv_a_curr->uv, luv_b_curr->uv) &&
+ equals_v2v2(luv_a_next->uv, luv_b_next->uv));
+}
+
+bool BM_loop_uv_share_vert_check(BMLoop *l_a, BMLoop *l_b, const int cd_loop_uv_offset)
+{
+ BLI_assert(l_a->v == l_b->v);
+ const MLoopUV *luv_a = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_a, cd_loop_uv_offset);
+ const MLoopUV *luv_b = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_b, cd_loop_uv_offset);
+ if (!equals_v2v2(luv_a->uv, luv_b->uv)) {
+ return false;
+ }
+ return true;
+}
+
+bool BM_edge_uv_share_vert_check(BMEdge *e, BMLoop *l_a, BMLoop *l_b, const int cd_loop_uv_offset)
+{
+ BLI_assert(l_a->v == l_b->v);
+ if (!BM_loop_uv_share_vert_check(l_a, l_b, cd_loop_uv_offset)) {
+ return false;
+ }
+
+ /* No need for NULL checks, these will always succeed. */
+ const BMLoop *l_other_a = BM_loop_other_vert_loop_by_edge(l_a, e);
+ const BMLoop *l_other_b = BM_loop_other_vert_loop_by_edge(l_b, e);
+
+ {
+ const MLoopUV *luv_other_a = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_other_a,
+ cd_loop_uv_offset);
+ const MLoopUV *luv_other_b = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_other_b,
+ cd_loop_uv_offset);
+ if (!equals_v2v2(luv_other_a->uv, luv_other_b->uv)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool BM_face_uv_point_inside_test(const BMFace *f, const float co[2], const int cd_loop_uv_offset)
+{
+ blender::Array<blender::float2, BM_DEFAULT_NGON_STACK_SIZE> projverts(f->len);
+
+ BMLoop *l_iter;
+ int i;
+
+ BLI_assert(BM_face_is_normal_valid(f));
+
+ for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l_iter = l_iter->next) {
+ projverts[i] = ((const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset))->uv;
+ }
+
+ return isect_point_poly_v2(
+ co, reinterpret_cast<const float(*)[2]>(projverts.data()), f->len, false);
+}