2022-02-11 09:07:11 +11:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
* Copyright 2007 Blender Foundation. All rights reserved. */
|
2012-02-19 18:31:04 +00:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup bmesh
|
2012-02-19 18:31:04 +00:00
|
|
|
*
|
|
|
|
|
* BM construction functions.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
2013-07-28 10:38:25 +00:00
|
|
|
#include "BLI_alloca.h"
|
2012-02-19 18:31:04 +00:00
|
|
|
#include "BLI_math.h"
|
2013-09-05 22:24:12 +00:00
|
|
|
#include "BLI_sort_utils.h"
|
2012-02-19 18:31:04 +00:00
|
|
|
|
|
|
|
|
#include "BKE_customdata.h"
|
|
|
|
|
|
2021-11-09 16:58:45 +11:00
|
|
|
#include "DNA_mesh_types.h"
|
2012-02-19 18:31:04 +00:00
|
|
|
#include "DNA_meshdata_types.h"
|
|
|
|
|
|
|
|
|
|
#include "bmesh.h"
|
2012-03-08 03:25:53 +00:00
|
|
|
#include "intern/bmesh_private.h"
|
2012-02-19 18:31:04 +00:00
|
|
|
|
|
|
|
|
#define SELECT 1
|
|
|
|
|
|
2015-12-24 19:51:41 +11:00
|
|
|
bool BM_verts_from_edges(BMVert **vert_arr, BMEdge **edge_arr, const int len)
|
|
|
|
|
{
|
|
|
|
|
int i, i_prev = len - 1;
|
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
|
vert_arr[i] = BM_edge_share_vert(edge_arr[i_prev], edge_arr[i]);
|
|
|
|
|
if (vert_arr[i] == NULL) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
i_prev = i;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-28 11:45:53 +10:00
|
|
|
bool BM_edges_from_verts(BMEdge **edge_arr, BMVert **vert_arr, const int len)
|
|
|
|
|
{
|
|
|
|
|
int i, i_prev = len - 1;
|
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
|
edge_arr[i_prev] = BM_edge_exists(vert_arr[i_prev], vert_arr[i]);
|
|
|
|
|
if (edge_arr[i_prev] == NULL) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
i_prev = i;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BM_edges_from_verts_ensure(BMesh *bm, BMEdge **edge_arr, BMVert **vert_arr, const int len)
|
|
|
|
|
{
|
|
|
|
|
int i, i_prev = len - 1;
|
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
|
edge_arr[i_prev] = BM_edge_create(
|
|
|
|
|
bm, vert_arr[i_prev], vert_arr[i], NULL, BM_CREATE_NO_DOUBLE);
|
|
|
|
|
i_prev = i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-19 18:31:04 +00:00
|
|
|
/* prototypes */
|
2022-06-01 14:38:06 +10:00
|
|
|
static void bm_loop_attrs_copy(BMesh *bm_src,
|
|
|
|
|
BMesh *bm_dst,
|
|
|
|
|
const BMLoop *l_src,
|
|
|
|
|
BMLoop *l_dst,
|
|
|
|
|
eCustomDataMask mask_exclude);
|
2012-02-19 18:31:04 +00:00
|
|
|
|
2015-04-25 20:15:20 +10:00
|
|
|
BMFace *BM_face_create_quad_tri(BMesh *bm,
|
|
|
|
|
BMVert *v1,
|
|
|
|
|
BMVert *v2,
|
|
|
|
|
BMVert *v3,
|
|
|
|
|
BMVert *v4,
|
|
|
|
|
const BMFace *f_example,
|
|
|
|
|
const eBMCreateFlag create_flag)
|
2012-02-19 18:31:04 +00:00
|
|
|
{
|
|
|
|
|
BMVert *vtar[4] = {v1, v2, v3, v4};
|
2013-08-21 07:51:47 +00:00
|
|
|
return BM_face_create_verts(bm, vtar, v4 ? 4 : 3, f_example, create_flag, true);
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
|
|
2015-11-28 13:37:02 +11:00
|
|
|
void BM_face_copy_shared(BMesh *bm, BMFace *f, BMLoopFilterFunc filter_fn, void *user_data)
|
2012-02-19 18:31:04 +00:00
|
|
|
{
|
2012-04-13 10:37:33 +00:00
|
|
|
BMLoop *l_first;
|
|
|
|
|
BMLoop *l_iter;
|
|
|
|
|
|
2013-08-18 11:44:51 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
|
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
|
|
|
|
|
do {
|
|
|
|
|
BLI_assert(BM_ELEM_API_FLAG_TEST(l_iter, _FLAG_OVERLAP) == 0);
|
|
|
|
|
} while ((l_iter = l_iter->next) != l_first);
|
|
|
|
|
#endif
|
|
|
|
|
|
2012-04-13 10:37:33 +00:00
|
|
|
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
|
|
|
|
|
do {
|
|
|
|
|
BMLoop *l_other = l_iter->radial_next;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-04-13 10:37:33 +00:00
|
|
|
if (l_other && l_other != l_iter) {
|
2013-08-18 11:44:51 +00:00
|
|
|
BMLoop *l_src[2];
|
|
|
|
|
BMLoop *l_dst[2] = {l_iter, l_iter->next};
|
2017-05-06 14:18:31 +10:00
|
|
|
uint j;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-04-13 10:37:33 +00:00
|
|
|
if (l_other->v == l_iter->v) {
|
2013-08-18 11:44:51 +00:00
|
|
|
l_src[0] = l_other;
|
|
|
|
|
l_src[1] = l_other->next;
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2013-08-18 11:44:51 +00:00
|
|
|
l_src[0] = l_other->next;
|
|
|
|
|
l_src[1] = l_other;
|
2012-04-13 10:37:33 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-08-18 11:44:51 +00:00
|
|
|
for (j = 0; j < 2; j++) {
|
|
|
|
|
BLI_assert(l_dst[j]->v == l_src[j]->v);
|
|
|
|
|
if (BM_ELEM_API_FLAG_TEST(l_dst[j], _FLAG_OVERLAP) == 0) {
|
2015-11-28 13:37:02 +11:00
|
|
|
if ((filter_fn == NULL) || filter_fn(l_src[j], user_data)) {
|
2018-11-27 11:39:51 +11:00
|
|
|
bm_loop_attrs_copy(bm, bm, l_src[j], l_dst[j], 0x0);
|
2013-08-18 11:44:51 +00:00
|
|
|
BM_ELEM_API_FLAG_ENABLE(l_dst[j], _FLAG_OVERLAP);
|
|
|
|
|
}
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2012-04-13 10:37:33 +00:00
|
|
|
} while ((l_iter = l_iter->next) != l_first);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-08-18 11:44:51 +00:00
|
|
|
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
|
|
|
|
|
do {
|
|
|
|
|
BM_ELEM_API_FLAG_DISABLE(l_iter, _FLAG_OVERLAP);
|
|
|
|
|
} while ((l_iter = l_iter->next) != l_first);
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-28 07:42:48 +00:00
|
|
|
/**
|
2015-04-25 17:20:59 +10:00
|
|
|
* Given an array of edges,
|
|
|
|
|
* order them using the winding defined by \a v1 & \a v2
|
|
|
|
|
* into \a edges_sort & \a verts_sort.
|
2012-02-19 18:31:04 +00:00
|
|
|
*
|
2015-04-25 17:20:59 +10:00
|
|
|
* All arrays must be \a len long.
|
2012-02-19 18:31:04 +00:00
|
|
|
*/
|
2015-04-25 17:20:59 +10:00
|
|
|
static bool bm_edges_sort_winding(BMVert *v1,
|
|
|
|
|
BMVert *v2,
|
|
|
|
|
BMEdge **edges,
|
|
|
|
|
const int len,
|
|
|
|
|
BMEdge **edges_sort,
|
|
|
|
|
BMVert **verts_sort)
|
2012-02-19 18:31:04 +00:00
|
|
|
{
|
2015-04-25 17:20:59 +10:00
|
|
|
BMEdge *e_iter, *e_first;
|
|
|
|
|
BMVert *v_iter;
|
2013-01-03 08:06:12 +00:00
|
|
|
int i;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-25 17:20:59 +10:00
|
|
|
/* all flags _must_ be cleared on exit! */
|
2012-02-19 18:31:04 +00:00
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
|
BM_ELEM_API_FLAG_ENABLE(edges[i], _FLAG_MF);
|
2015-04-25 17:20:59 +10:00
|
|
|
BM_ELEM_API_FLAG_ENABLE(edges[i]->v1, _FLAG_MV);
|
|
|
|
|
BM_ELEM_API_FLAG_ENABLE(edges[i]->v2, _FLAG_MV);
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-25 17:20:59 +10:00
|
|
|
/* find first edge */
|
2015-04-25 21:14:55 +10:00
|
|
|
i = 0;
|
2015-04-25 17:20:59 +10:00
|
|
|
v_iter = v1;
|
|
|
|
|
e_iter = e_first = v1->e;
|
2012-02-19 18:31:04 +00:00
|
|
|
do {
|
2015-04-25 17:20:59 +10:00
|
|
|
if (BM_ELEM_API_FLAG_TEST(e_iter, _FLAG_MF) && (BM_edge_other_vert(e_iter, v_iter) == v2)) {
|
2015-04-25 21:14:55 +10:00
|
|
|
i = 1;
|
2015-04-25 17:20:59 +10:00
|
|
|
break;
|
2013-01-03 07:53:30 +00:00
|
|
|
}
|
2015-04-25 17:20:59 +10:00
|
|
|
} while ((e_iter = bmesh_disk_edge_next(e_iter, v_iter)) != e_first);
|
2015-04-25 21:14:55 +10:00
|
|
|
if (i == 0) {
|
2015-04-25 17:20:59 +10:00
|
|
|
goto error;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-25 17:20:59 +10:00
|
|
|
i = 0;
|
|
|
|
|
do {
|
|
|
|
|
/* entering loop will always succeed */
|
|
|
|
|
if (BM_ELEM_API_FLAG_TEST(e_iter, _FLAG_MF)) {
|
|
|
|
|
if (UNLIKELY(BM_ELEM_API_FLAG_TEST(v_iter, _FLAG_MV) == false)) {
|
|
|
|
|
/* vert is in loop multiple times */
|
|
|
|
|
goto error;
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-25 17:20:59 +10:00
|
|
|
BM_ELEM_API_FLAG_DISABLE(e_iter, _FLAG_MF);
|
|
|
|
|
edges_sort[i] = e_iter;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-25 17:20:59 +10:00
|
|
|
BM_ELEM_API_FLAG_DISABLE(v_iter, _FLAG_MV);
|
|
|
|
|
verts_sort[i] = v_iter;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-25 17:20:59 +10:00
|
|
|
i += 1;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-25 17:20:59 +10:00
|
|
|
/* walk onto the next vertex */
|
|
|
|
|
v_iter = BM_edge_other_vert(e_iter, v_iter);
|
|
|
|
|
if (i == len) {
|
|
|
|
|
if (UNLIKELY(v_iter != verts_sort[0])) {
|
|
|
|
|
goto error;
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
2015-04-25 17:20:59 +10:00
|
|
|
break;
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-25 17:20:59 +10:00
|
|
|
e_first = e_iter;
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
2015-04-25 17:20:59 +10:00
|
|
|
} while ((e_iter = bmesh_disk_edge_next(e_iter, v_iter)) != e_first);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-25 17:20:59 +10:00
|
|
|
if (i == len) {
|
|
|
|
|
return true;
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
|
|
2015-04-25 17:20:59 +10:00
|
|
|
error:
|
2012-02-19 18:31:04 +00:00
|
|
|
for (i = 0; i < len; i++) {
|
2015-04-25 17:20:59 +10:00
|
|
|
BM_ELEM_API_FLAG_DISABLE(edges[i], _FLAG_MF);
|
|
|
|
|
BM_ELEM_API_FLAG_DISABLE(edges[i]->v1, _FLAG_MV);
|
|
|
|
|
BM_ELEM_API_FLAG_DISABLE(edges[i]->v2, _FLAG_MV);
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
|
|
2015-04-25 17:20:59 +10:00
|
|
|
return false;
|
|
|
|
|
}
|
2012-02-19 18:31:04 +00:00
|
|
|
|
2015-04-25 17:20:59 +10:00
|
|
|
BMFace *BM_face_create_ngon(BMesh *bm,
|
|
|
|
|
BMVert *v1,
|
|
|
|
|
BMVert *v2,
|
|
|
|
|
BMEdge **edges,
|
|
|
|
|
const int len,
|
|
|
|
|
const BMFace *f_example,
|
|
|
|
|
const eBMCreateFlag create_flag)
|
|
|
|
|
{
|
|
|
|
|
BMEdge **edges_sort = BLI_array_alloca(edges_sort, len);
|
|
|
|
|
BMVert **verts_sort = BLI_array_alloca(verts_sort, len);
|
2012-02-19 18:31:04 +00:00
|
|
|
|
2015-04-25 17:20:59 +10:00
|
|
|
BLI_assert(len && v1 && v2 && edges && bm);
|
2012-02-19 18:31:04 +00:00
|
|
|
|
2015-04-25 17:20:59 +10:00
|
|
|
if (bm_edges_sort_winding(v1, v2, edges, len, edges_sort, verts_sort)) {
|
|
|
|
|
return BM_face_create(bm, verts_sort, edges_sort, len, f_example, create_flag);
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-25 20:15:20 +10:00
|
|
|
BMFace *BM_face_create_ngon_verts(BMesh *bm,
|
|
|
|
|
BMVert **vert_arr,
|
|
|
|
|
const int len,
|
|
|
|
|
const BMFace *f_example,
|
|
|
|
|
const eBMCreateFlag create_flag,
|
|
|
|
|
const bool calc_winding,
|
|
|
|
|
const bool create_edges)
|
2013-03-27 05:52:28 +00:00
|
|
|
{
|
|
|
|
|
BMEdge **edge_arr = BLI_array_alloca(edge_arr, len);
|
2017-05-06 14:18:31 +10:00
|
|
|
uint winding[2] = {0, 0};
|
2013-03-27 05:52:28 +00:00
|
|
|
int i, i_prev = len - 1;
|
2013-07-25 18:43:05 +00:00
|
|
|
BMVert *v_winding[2] = {vert_arr[i_prev], vert_arr[0]};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-27 05:52:28 +00:00
|
|
|
BLI_assert(len > 2);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-27 05:52:28 +00:00
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
|
if (create_edges) {
|
|
|
|
|
edge_arr[i] = BM_edge_create(bm, vert_arr[i_prev], vert_arr[i], NULL, BM_CREATE_NO_DOUBLE);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
edge_arr[i] = BM_edge_exists(vert_arr[i_prev], vert_arr[i]);
|
|
|
|
|
if (edge_arr[i] == NULL) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2013-03-27 05:52:28 +00:00
|
|
|
if (calc_winding) {
|
|
|
|
|
/* the edge may exist already and be attached to a face
|
|
|
|
|
* in this case we can find the best winding to use for the new face */
|
|
|
|
|
if (edge_arr[i]->l) {
|
|
|
|
|
BMVert *test_v1, *test_v2;
|
|
|
|
|
/* we want to use the reverse winding to the existing order */
|
|
|
|
|
BM_edge_ordered_verts(edge_arr[i], &test_v2, &test_v1);
|
|
|
|
|
winding[(vert_arr[i_prev] == test_v2)]++;
|
2020-11-06 12:30:59 +11:00
|
|
|
BLI_assert(ELEM(vert_arr[i_prev], test_v2, test_v1));
|
2013-03-27 05:52:28 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2013-03-27 05:52:28 +00:00
|
|
|
i_prev = i;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-27 05:52:28 +00:00
|
|
|
/* --- */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-27 05:52:28 +00:00
|
|
|
if (calc_winding) {
|
|
|
|
|
if (winding[0] < winding[1]) {
|
|
|
|
|
winding[0] = 1;
|
|
|
|
|
winding[1] = 0;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
winding[0] = 0;
|
|
|
|
|
winding[1] = 1;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2013-03-27 05:52:28 +00:00
|
|
|
else {
|
|
|
|
|
winding[0] = 0;
|
|
|
|
|
winding[1] = 1;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-27 05:52:28 +00:00
|
|
|
/* --- */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-27 05:52:28 +00:00
|
|
|
/* create the face */
|
2013-07-25 18:16:55 +00:00
|
|
|
return BM_face_create_ngon(
|
2013-08-21 07:51:47 +00:00
|
|
|
bm, v_winding[winding[0]], v_winding[winding[1]], edge_arr, len, f_example, create_flag);
|
2013-03-27 05:52:28 +00:00
|
|
|
}
|
|
|
|
|
|
2017-01-20 06:06:06 +11:00
|
|
|
void BM_verts_sort_radial_plane(BMVert **vert_arr, int len)
|
2012-03-14 22:57:15 +00:00
|
|
|
{
|
2013-09-05 22:24:12 +00:00
|
|
|
struct SortIntByFloat *vang = BLI_array_alloca(vang, len);
|
2013-08-21 05:20:57 +00:00
|
|
|
BMVert **vert_arr_map = BLI_array_alloca(vert_arr_map, len);
|
2012-03-14 22:57:15 +00:00
|
|
|
|
2019-08-09 05:27:49 +10:00
|
|
|
float nor[3], cent[3];
|
|
|
|
|
int index_tangent = 0;
|
|
|
|
|
BM_verts_calc_normal_from_cloud_ex(vert_arr, len, nor, cent, &index_tangent);
|
|
|
|
|
const float *far = vert_arr[index_tangent]->co;
|
2012-03-14 22:57:15 +00:00
|
|
|
|
2019-08-09 05:27:49 +10:00
|
|
|
/* Now calculate every points angle around the normal (signed). */
|
|
|
|
|
for (int i = 0; i < len; i++) {
|
2017-01-19 07:59:32 +11:00
|
|
|
vang[i].sort_value = angle_signed_on_axis_v3v3v3_v3(far, cent, vert_arr[i]->co, nor);
|
2013-09-05 22:24:12 +00:00
|
|
|
vang[i].data = i;
|
2017-01-20 06:06:06 +11:00
|
|
|
vert_arr_map[i] = vert_arr[i];
|
2012-03-14 22:57:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* sort by angle and magic! - we have our ngon */
|
2013-09-05 22:24:12 +00:00
|
|
|
qsort(vang, len, sizeof(*vang), BLI_sortutil_cmp_float);
|
2012-03-14 22:57:15 +00:00
|
|
|
|
|
|
|
|
/* --- */
|
|
|
|
|
|
2019-08-09 05:27:49 +10:00
|
|
|
for (int i = 0; i < len; i++) {
|
2017-01-20 06:06:06 +11:00
|
|
|
vert_arr[i] = vert_arr_map[vang[i].data];
|
2012-03-14 22:57:15 +00:00
|
|
|
}
|
|
|
|
|
}
|
2012-02-19 18:31:04 +00:00
|
|
|
|
|
|
|
|
/*************************************************************/
|
|
|
|
|
|
2019-11-26 16:19:56 +11:00
|
|
|
static void bm_vert_attrs_copy(
|
2022-06-01 14:38:06 +10:00
|
|
|
BMesh *bm_src, BMesh *bm_dst, const BMVert *v_src, BMVert *v_dst, eCustomDataMask mask_exclude)
|
2012-02-19 18:31:04 +00:00
|
|
|
{
|
2019-11-26 16:19:56 +11:00
|
|
|
if ((bm_src == bm_dst) && (v_src == v_dst)) {
|
2021-07-15 18:23:28 +10:00
|
|
|
BLI_assert_msg(0, "BMVert: source and target match");
|
2012-02-19 18:31:04 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2019-11-26 16:19:56 +11:00
|
|
|
if ((mask_exclude & CD_MASK_NORMAL) == 0) {
|
|
|
|
|
copy_v3_v3(v_dst->no, v_src->no);
|
2018-11-27 11:39:51 +11:00
|
|
|
}
|
2019-11-26 16:19:56 +11:00
|
|
|
CustomData_bmesh_free_block_data_exclude_by_type(&bm_dst->vdata, v_dst->head.data, mask_exclude);
|
|
|
|
|
CustomData_bmesh_copy_data_exclude_by_type(
|
|
|
|
|
&bm_src->vdata, &bm_dst->vdata, v_src->head.data, &v_dst->head.data, mask_exclude);
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
|
|
2019-11-26 16:19:56 +11:00
|
|
|
static void bm_edge_attrs_copy(
|
2022-06-01 14:38:06 +10:00
|
|
|
BMesh *bm_src, BMesh *bm_dst, const BMEdge *e_src, BMEdge *e_dst, eCustomDataMask mask_exclude)
|
2012-02-19 18:31:04 +00:00
|
|
|
{
|
2019-11-26 16:19:56 +11:00
|
|
|
if ((bm_src == bm_dst) && (e_src == e_dst)) {
|
2021-07-15 18:23:28 +10:00
|
|
|
BLI_assert_msg(0, "BMEdge: source and target match");
|
2012-02-19 18:31:04 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2019-11-26 16:19:56 +11:00
|
|
|
CustomData_bmesh_free_block_data_exclude_by_type(&bm_dst->edata, e_dst->head.data, mask_exclude);
|
|
|
|
|
CustomData_bmesh_copy_data_exclude_by_type(
|
|
|
|
|
&bm_src->edata, &bm_dst->edata, e_src->head.data, &e_dst->head.data, mask_exclude);
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
|
|
2019-11-26 16:19:56 +11:00
|
|
|
static void bm_loop_attrs_copy(
|
2022-06-01 14:38:06 +10:00
|
|
|
BMesh *bm_src, BMesh *bm_dst, const BMLoop *l_src, BMLoop *l_dst, eCustomDataMask mask_exclude)
|
2012-02-19 18:31:04 +00:00
|
|
|
{
|
2019-11-26 16:19:56 +11:00
|
|
|
if ((bm_src == bm_dst) && (l_src == l_dst)) {
|
2021-07-15 18:23:28 +10:00
|
|
|
BLI_assert_msg(0, "BMLoop: source and target match");
|
2012-02-19 18:31:04 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2019-11-26 16:19:56 +11:00
|
|
|
CustomData_bmesh_free_block_data_exclude_by_type(&bm_dst->ldata, l_dst->head.data, mask_exclude);
|
|
|
|
|
CustomData_bmesh_copy_data_exclude_by_type(
|
|
|
|
|
&bm_src->ldata, &bm_dst->ldata, l_src->head.data, &l_dst->head.data, mask_exclude);
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
|
|
2019-11-26 16:19:56 +11:00
|
|
|
static void bm_face_attrs_copy(
|
2022-06-01 14:38:06 +10:00
|
|
|
BMesh *bm_src, BMesh *bm_dst, const BMFace *f_src, BMFace *f_dst, eCustomDataMask mask_exclude)
|
2012-02-19 18:31:04 +00:00
|
|
|
{
|
2019-11-26 16:19:56 +11:00
|
|
|
if ((bm_src == bm_dst) && (f_src == f_dst)) {
|
2021-07-15 18:23:28 +10:00
|
|
|
BLI_assert_msg(0, "BMFace: source and target match");
|
2012-02-19 18:31:04 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2019-11-26 16:19:56 +11:00
|
|
|
if ((mask_exclude & CD_MASK_NORMAL) == 0) {
|
|
|
|
|
copy_v3_v3(f_dst->no, f_src->no);
|
2018-11-27 11:39:51 +11:00
|
|
|
}
|
2019-11-26 16:19:56 +11:00
|
|
|
CustomData_bmesh_free_block_data_exclude_by_type(&bm_dst->pdata, f_dst->head.data, mask_exclude);
|
|
|
|
|
CustomData_bmesh_copy_data_exclude_by_type(
|
|
|
|
|
&bm_src->pdata, &bm_dst->pdata, f_src->head.data, &f_dst->head.data, mask_exclude);
|
|
|
|
|
f_dst->mat_nr = f_src->mat_nr;
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
|
|
2015-04-25 20:15:20 +10:00
|
|
|
void BM_elem_attrs_copy_ex(BMesh *bm_src,
|
|
|
|
|
BMesh *bm_dst,
|
|
|
|
|
const void *ele_src_v,
|
|
|
|
|
void *ele_dst_v,
|
2018-11-27 11:39:51 +11:00
|
|
|
const char hflag_mask,
|
2019-11-26 16:19:56 +11:00
|
|
|
const uint64_t cd_mask_exclude)
|
2012-02-19 18:31:04 +00:00
|
|
|
{
|
2021-12-10 21:42:06 +11:00
|
|
|
/* TODO: Special handling for hide flags? */
|
|
|
|
|
/* TODO: swap src/dst args, everywhere else in bmesh does other way round. */
|
|
|
|
|
|
2013-07-11 12:43:34 +00:00
|
|
|
const BMHeader *ele_src = ele_src_v;
|
|
|
|
|
BMHeader *ele_dst = ele_dst_v;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-07-11 12:43:34 +00:00
|
|
|
BLI_assert(ele_src->htype == ele_dst->htype);
|
2013-08-23 13:00:43 +00:00
|
|
|
BLI_assert(ele_src != ele_dst);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-07-11 12:43:34 +00:00
|
|
|
if ((hflag_mask & BM_ELEM_SELECT) == 0) {
|
|
|
|
|
/* First we copy select */
|
|
|
|
|
if (BM_elem_flag_test((BMElem *)ele_src, BM_ELEM_SELECT)) {
|
|
|
|
|
BM_elem_select_set(bm_dst, (BMElem *)ele_dst, true);
|
|
|
|
|
}
|
2012-02-25 20:58:03 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-02-19 18:31:04 +00:00
|
|
|
/* Now we copy flags */
|
2013-07-11 12:43:34 +00:00
|
|
|
if (hflag_mask == 0) {
|
|
|
|
|
ele_dst->hflag = ele_src->hflag;
|
|
|
|
|
}
|
2013-07-24 19:31:58 +00:00
|
|
|
else if (hflag_mask == 0xff) {
|
|
|
|
|
/* pass */
|
|
|
|
|
}
|
2013-07-11 12:43:34 +00:00
|
|
|
else {
|
|
|
|
|
ele_dst->hflag = ((ele_dst->hflag & hflag_mask) | (ele_src->hflag & ~hflag_mask));
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-02-19 18:31:04 +00:00
|
|
|
/* Copy specific attributes */
|
2013-07-11 12:43:34 +00:00
|
|
|
switch (ele_dst->htype) {
|
2012-02-25 20:58:03 +00:00
|
|
|
case BM_VERT:
|
2019-11-26 16:19:56 +11:00
|
|
|
bm_vert_attrs_copy(
|
|
|
|
|
bm_src, bm_dst, (const BMVert *)ele_src, (BMVert *)ele_dst, cd_mask_exclude);
|
2012-02-25 20:58:03 +00:00
|
|
|
break;
|
|
|
|
|
case BM_EDGE:
|
2019-11-26 16:19:56 +11:00
|
|
|
bm_edge_attrs_copy(
|
|
|
|
|
bm_src, bm_dst, (const BMEdge *)ele_src, (BMEdge *)ele_dst, cd_mask_exclude);
|
2012-02-25 20:58:03 +00:00
|
|
|
break;
|
|
|
|
|
case BM_LOOP:
|
2019-11-26 16:19:56 +11:00
|
|
|
bm_loop_attrs_copy(
|
|
|
|
|
bm_src, bm_dst, (const BMLoop *)ele_src, (BMLoop *)ele_dst, cd_mask_exclude);
|
2012-02-25 20:58:03 +00:00
|
|
|
break;
|
|
|
|
|
case BM_FACE:
|
2019-11-26 16:19:56 +11:00
|
|
|
bm_face_attrs_copy(
|
|
|
|
|
bm_src, bm_dst, (const BMFace *)ele_src, (BMFace *)ele_dst, cd_mask_exclude);
|
2012-02-25 20:58:03 +00:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
BLI_assert(0);
|
2013-07-21 08:16:37 +00:00
|
|
|
break;
|
2012-02-25 20:58:03 +00:00
|
|
|
}
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
|
|
2013-07-11 12:43:34 +00:00
|
|
|
void BM_elem_attrs_copy(BMesh *bm_src, BMesh *bm_dst, const void *ele_src, void *ele_dst)
|
|
|
|
|
{
|
|
|
|
|
/* BMESH_TODO, default 'use_flags' to false */
|
2018-11-27 11:39:51 +11:00
|
|
|
BM_elem_attrs_copy_ex(bm_src, bm_dst, ele_src, ele_dst, BM_ELEM_SELECT, 0x0);
|
2013-07-24 19:31:58 +00:00
|
|
|
}
|
|
|
|
|
|
2016-11-14 14:21:15 +11:00
|
|
|
void BM_elem_select_copy(BMesh *bm_dst, void *ele_dst_v, const void *ele_src_v)
|
2013-07-24 19:31:58 +00:00
|
|
|
{
|
|
|
|
|
BMHeader *ele_dst = ele_dst_v;
|
2013-08-13 00:35:23 +00:00
|
|
|
const BMHeader *ele_src = ele_src_v;
|
2013-07-24 19:31:58 +00:00
|
|
|
|
|
|
|
|
BLI_assert(ele_src->htype == ele_dst->htype);
|
|
|
|
|
|
|
|
|
|
if ((ele_src->hflag & BM_ELEM_SELECT) != (ele_dst->hflag & BM_ELEM_SELECT)) {
|
|
|
|
|
BM_elem_select_set(bm_dst, (BMElem *)ele_dst, (ele_src->hflag & BM_ELEM_SELECT) != 0);
|
|
|
|
|
}
|
2013-07-11 12:43:34 +00:00
|
|
|
}
|
|
|
|
|
|
2013-05-26 12:02:29 +00:00
|
|
|
/* helper function for 'BM_mesh_copy' */
|
2015-04-25 20:15:20 +10:00
|
|
|
static BMFace *bm_mesh_copy_new_face(
|
|
|
|
|
BMesh *bm_new, BMesh *bm_old, BMVert **vtable, BMEdge **etable, BMFace *f)
|
2012-02-19 18:31:04 +00:00
|
|
|
{
|
2013-05-25 20:47:06 +00:00
|
|
|
BMLoop **loops = BLI_array_alloca(loops, f->len);
|
|
|
|
|
BMVert **verts = BLI_array_alloca(verts, f->len);
|
|
|
|
|
BMEdge **edges = BLI_array_alloca(edges, f->len);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-05-25 20:47:06 +00:00
|
|
|
BMFace *f_new;
|
|
|
|
|
BMLoop *l_iter, *l_first;
|
|
|
|
|
int j;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-05-25 20:47:06 +00:00
|
|
|
j = 0;
|
|
|
|
|
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
|
|
|
|
|
do {
|
|
|
|
|
loops[j] = l_iter;
|
|
|
|
|
verts[j] = vtable[BM_elem_index_get(l_iter->v)];
|
|
|
|
|
edges[j] = etable[BM_elem_index_get(l_iter->e)];
|
|
|
|
|
j++;
|
|
|
|
|
} while ((l_iter = l_iter->next) != l_first);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-08-21 07:51:47 +00:00
|
|
|
f_new = BM_face_create(bm_new, verts, edges, f->len, NULL, BM_CREATE_SKIP_CD);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-05-25 20:47:06 +00:00
|
|
|
if (UNLIKELY(f_new == NULL)) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-05-25 20:47:06 +00:00
|
|
|
/* use totface in case adding some faces fails */
|
|
|
|
|
BM_elem_index_set(f_new, (bm_new->totface - 1)); /* set_inline */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-11-27 11:39:51 +11:00
|
|
|
BM_elem_attrs_copy_ex(bm_old, bm_new, f, f_new, 0xff, 0x0);
|
2013-07-24 19:31:58 +00:00
|
|
|
f_new->head.hflag = f->head.hflag; /* low level! don't do this for normal api use */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-05-25 20:47:06 +00:00
|
|
|
j = 0;
|
|
|
|
|
l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
|
|
|
|
|
do {
|
|
|
|
|
BM_elem_attrs_copy(bm_old, bm_new, loops[j], l_iter);
|
|
|
|
|
j++;
|
|
|
|
|
} while ((l_iter = l_iter->next) != l_first);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-05-25 20:47:06 +00:00
|
|
|
return f_new;
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-18 21:44:08 +11:00
|
|
|
void BM_mesh_copy_init_customdata_from_mesh_array(BMesh *bm_dst,
|
|
|
|
|
const Mesh *me_src_array[],
|
|
|
|
|
const int me_src_array_len,
|
|
|
|
|
const BMAllocTemplate *allocsize)
|
|
|
|
|
|
2021-11-09 16:58:45 +11:00
|
|
|
{
|
|
|
|
|
if (allocsize == NULL) {
|
|
|
|
|
allocsize = &bm_mesh_allocsize_default;
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-18 21:44:08 +11:00
|
|
|
char cd_flag = 0;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < me_src_array_len; i++) {
|
|
|
|
|
const Mesh *me_src = me_src_array[i];
|
|
|
|
|
if (i == 0) {
|
Mesh: Move hide flags to generic attributes
This commit moves the hide status of mesh vertices, edges, and faces
from the `ME_FLAG` to optional generic boolean attributes. Storing this
data as generic attributes can significantly simplify and improve code,
as described in T95965.
The attributes are called `.hide_vert`, `.hide_edge`, and `.hide_poly`,
using the attribute name semantics discussed in T97452. The `.` prefix
means they are "UI attributes", so they still contain original data
edited by users, but they aren't meant to be accessed procedurally by
the user in arbitrary situations. They are also be hidden in the
spreadsheet and the attribute list by default,
Until 4.0, the attributes are still written to and read from the mesh
in the old way, so neither forward nor backward compatibility are
affected. This means memory requirements will be increased by one byte
per element when the hide status is used. When the flags are removed
completely, requirements will decrease when hiding is unused.
Further notes:
* Some code can be further simplified to skip some processing when the
hide attributes don't exist.
* The data is still stored in flags for `BMesh`, necessitating some
complexity in the conversion to and from `Mesh`.
* Access to the "hide" property of mesh elements in RNA is slower.
The separate boolean arrays should be used where possible.
Ref T95965
Differential Revision: https://developer.blender.org/D14685
2022-08-11 12:54:24 -04:00
|
|
|
CustomData_copy_mesh_to_bmesh(
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
&me_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_SET_DEFAULT, 0);
|
Mesh: Move hide flags to generic attributes
This commit moves the hide status of mesh vertices, edges, and faces
from the `ME_FLAG` to optional generic boolean attributes. Storing this
data as generic attributes can significantly simplify and improve code,
as described in T95965.
The attributes are called `.hide_vert`, `.hide_edge`, and `.hide_poly`,
using the attribute name semantics discussed in T97452. The `.` prefix
means they are "UI attributes", so they still contain original data
edited by users, but they aren't meant to be accessed procedurally by
the user in arbitrary situations. They are also be hidden in the
spreadsheet and the attribute list by default,
Until 4.0, the attributes are still written to and read from the mesh
in the old way, so neither forward nor backward compatibility are
affected. This means memory requirements will be increased by one byte
per element when the hide status is used. When the flags are removed
completely, requirements will decrease when hiding is unused.
Further notes:
* Some code can be further simplified to skip some processing when the
hide attributes don't exist.
* The data is still stored in flags for `BMesh`, necessitating some
complexity in the conversion to and from `Mesh`.
* Access to the "hide" property of mesh elements in RNA is slower.
The separate boolean arrays should be used where possible.
Ref T95965
Differential Revision: https://developer.blender.org/D14685
2022-08-11 12:54:24 -04:00
|
|
|
CustomData_copy_mesh_to_bmesh(
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
&me_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_SET_DEFAULT, 0);
|
Mesh: Move hide flags to generic attributes
This commit moves the hide status of mesh vertices, edges, and faces
from the `ME_FLAG` to optional generic boolean attributes. Storing this
data as generic attributes can significantly simplify and improve code,
as described in T95965.
The attributes are called `.hide_vert`, `.hide_edge`, and `.hide_poly`,
using the attribute name semantics discussed in T97452. The `.` prefix
means they are "UI attributes", so they still contain original data
edited by users, but they aren't meant to be accessed procedurally by
the user in arbitrary situations. They are also be hidden in the
spreadsheet and the attribute list by default,
Until 4.0, the attributes are still written to and read from the mesh
in the old way, so neither forward nor backward compatibility are
affected. This means memory requirements will be increased by one byte
per element when the hide status is used. When the flags are removed
completely, requirements will decrease when hiding is unused.
Further notes:
* Some code can be further simplified to skip some processing when the
hide attributes don't exist.
* The data is still stored in flags for `BMesh`, necessitating some
complexity in the conversion to and from `Mesh`.
* Access to the "hide" property of mesh elements in RNA is slower.
The separate boolean arrays should be used where possible.
Ref T95965
Differential Revision: https://developer.blender.org/D14685
2022-08-11 12:54:24 -04:00
|
|
|
CustomData_copy_mesh_to_bmesh(
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
&me_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_SET_DEFAULT, 0);
|
Mesh: Move hide flags to generic attributes
This commit moves the hide status of mesh vertices, edges, and faces
from the `ME_FLAG` to optional generic boolean attributes. Storing this
data as generic attributes can significantly simplify and improve code,
as described in T95965.
The attributes are called `.hide_vert`, `.hide_edge`, and `.hide_poly`,
using the attribute name semantics discussed in T97452. The `.` prefix
means they are "UI attributes", so they still contain original data
edited by users, but they aren't meant to be accessed procedurally by
the user in arbitrary situations. They are also be hidden in the
spreadsheet and the attribute list by default,
Until 4.0, the attributes are still written to and read from the mesh
in the old way, so neither forward nor backward compatibility are
affected. This means memory requirements will be increased by one byte
per element when the hide status is used. When the flags are removed
completely, requirements will decrease when hiding is unused.
Further notes:
* Some code can be further simplified to skip some processing when the
hide attributes don't exist.
* The data is still stored in flags for `BMesh`, necessitating some
complexity in the conversion to and from `Mesh`.
* Access to the "hide" property of mesh elements in RNA is slower.
The separate boolean arrays should be used where possible.
Ref T95965
Differential Revision: https://developer.blender.org/D14685
2022-08-11 12:54:24 -04:00
|
|
|
CustomData_copy_mesh_to_bmesh(
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
&me_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_SET_DEFAULT, 0);
|
2022-01-18 21:44:08 +11:00
|
|
|
}
|
|
|
|
|
else {
|
Mesh: Move hide flags to generic attributes
This commit moves the hide status of mesh vertices, edges, and faces
from the `ME_FLAG` to optional generic boolean attributes. Storing this
data as generic attributes can significantly simplify and improve code,
as described in T95965.
The attributes are called `.hide_vert`, `.hide_edge`, and `.hide_poly`,
using the attribute name semantics discussed in T97452. The `.` prefix
means they are "UI attributes", so they still contain original data
edited by users, but they aren't meant to be accessed procedurally by
the user in arbitrary situations. They are also be hidden in the
spreadsheet and the attribute list by default,
Until 4.0, the attributes are still written to and read from the mesh
in the old way, so neither forward nor backward compatibility are
affected. This means memory requirements will be increased by one byte
per element when the hide status is used. When the flags are removed
completely, requirements will decrease when hiding is unused.
Further notes:
* Some code can be further simplified to skip some processing when the
hide attributes don't exist.
* The data is still stored in flags for `BMesh`, necessitating some
complexity in the conversion to and from `Mesh`.
* Access to the "hide" property of mesh elements in RNA is slower.
The separate boolean arrays should be used where possible.
Ref T95965
Differential Revision: https://developer.blender.org/D14685
2022-08-11 12:54:24 -04:00
|
|
|
CustomData_merge_mesh_to_bmesh(
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
&me_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_SET_DEFAULT, 0);
|
Mesh: Move hide flags to generic attributes
This commit moves the hide status of mesh vertices, edges, and faces
from the `ME_FLAG` to optional generic boolean attributes. Storing this
data as generic attributes can significantly simplify and improve code,
as described in T95965.
The attributes are called `.hide_vert`, `.hide_edge`, and `.hide_poly`,
using the attribute name semantics discussed in T97452. The `.` prefix
means they are "UI attributes", so they still contain original data
edited by users, but they aren't meant to be accessed procedurally by
the user in arbitrary situations. They are also be hidden in the
spreadsheet and the attribute list by default,
Until 4.0, the attributes are still written to and read from the mesh
in the old way, so neither forward nor backward compatibility are
affected. This means memory requirements will be increased by one byte
per element when the hide status is used. When the flags are removed
completely, requirements will decrease when hiding is unused.
Further notes:
* Some code can be further simplified to skip some processing when the
hide attributes don't exist.
* The data is still stored in flags for `BMesh`, necessitating some
complexity in the conversion to and from `Mesh`.
* Access to the "hide" property of mesh elements in RNA is slower.
The separate boolean arrays should be used where possible.
Ref T95965
Differential Revision: https://developer.blender.org/D14685
2022-08-11 12:54:24 -04:00
|
|
|
CustomData_merge_mesh_to_bmesh(
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
&me_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_SET_DEFAULT, 0);
|
Mesh: Move hide flags to generic attributes
This commit moves the hide status of mesh vertices, edges, and faces
from the `ME_FLAG` to optional generic boolean attributes. Storing this
data as generic attributes can significantly simplify and improve code,
as described in T95965.
The attributes are called `.hide_vert`, `.hide_edge`, and `.hide_poly`,
using the attribute name semantics discussed in T97452. The `.` prefix
means they are "UI attributes", so they still contain original data
edited by users, but they aren't meant to be accessed procedurally by
the user in arbitrary situations. They are also be hidden in the
spreadsheet and the attribute list by default,
Until 4.0, the attributes are still written to and read from the mesh
in the old way, so neither forward nor backward compatibility are
affected. This means memory requirements will be increased by one byte
per element when the hide status is used. When the flags are removed
completely, requirements will decrease when hiding is unused.
Further notes:
* Some code can be further simplified to skip some processing when the
hide attributes don't exist.
* The data is still stored in flags for `BMesh`, necessitating some
complexity in the conversion to and from `Mesh`.
* Access to the "hide" property of mesh elements in RNA is slower.
The separate boolean arrays should be used where possible.
Ref T95965
Differential Revision: https://developer.blender.org/D14685
2022-08-11 12:54:24 -04:00
|
|
|
CustomData_merge_mesh_to_bmesh(
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
&me_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_SET_DEFAULT, 0);
|
Mesh: Move hide flags to generic attributes
This commit moves the hide status of mesh vertices, edges, and faces
from the `ME_FLAG` to optional generic boolean attributes. Storing this
data as generic attributes can significantly simplify and improve code,
as described in T95965.
The attributes are called `.hide_vert`, `.hide_edge`, and `.hide_poly`,
using the attribute name semantics discussed in T97452. The `.` prefix
means they are "UI attributes", so they still contain original data
edited by users, but they aren't meant to be accessed procedurally by
the user in arbitrary situations. They are also be hidden in the
spreadsheet and the attribute list by default,
Until 4.0, the attributes are still written to and read from the mesh
in the old way, so neither forward nor backward compatibility are
affected. This means memory requirements will be increased by one byte
per element when the hide status is used. When the flags are removed
completely, requirements will decrease when hiding is unused.
Further notes:
* Some code can be further simplified to skip some processing when the
hide attributes don't exist.
* The data is still stored in flags for `BMesh`, necessitating some
complexity in the conversion to and from `Mesh`.
* Access to the "hide" property of mesh elements in RNA is slower.
The separate boolean arrays should be used where possible.
Ref T95965
Differential Revision: https://developer.blender.org/D14685
2022-08-11 12:54:24 -04:00
|
|
|
CustomData_merge_mesh_to_bmesh(
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
&me_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_SET_DEFAULT, 0);
|
2022-01-18 21:44:08 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cd_flag |= me_src->cd_flag;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cd_flag |= BM_mesh_cd_flag_from_bmesh(bm_dst);
|
2021-11-09 16:58:45 +11:00
|
|
|
|
|
|
|
|
CustomData_bmesh_init_pool(&bm_dst->vdata, allocsize->totvert, BM_VERT);
|
|
|
|
|
CustomData_bmesh_init_pool(&bm_dst->edata, allocsize->totedge, BM_EDGE);
|
|
|
|
|
CustomData_bmesh_init_pool(&bm_dst->ldata, allocsize->totloop, BM_LOOP);
|
|
|
|
|
CustomData_bmesh_init_pool(&bm_dst->pdata, allocsize->totface, BM_FACE);
|
2022-01-18 21:44:08 +11:00
|
|
|
|
|
|
|
|
BM_mesh_cd_flag_apply(bm_dst, cd_flag);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BM_mesh_copy_init_customdata_from_mesh(BMesh *bm_dst,
|
|
|
|
|
const Mesh *me_src,
|
|
|
|
|
const BMAllocTemplate *allocsize)
|
|
|
|
|
{
|
|
|
|
|
BM_mesh_copy_init_customdata_from_mesh_array(bm_dst, &me_src, 1, allocsize);
|
2021-11-09 16:58:45 +11:00
|
|
|
}
|
|
|
|
|
|
2013-07-11 04:24:36 +00:00
|
|
|
void BM_mesh_copy_init_customdata(BMesh *bm_dst, BMesh *bm_src, const BMAllocTemplate *allocsize)
|
|
|
|
|
{
|
|
|
|
|
if (allocsize == NULL) {
|
|
|
|
|
allocsize = &bm_mesh_allocsize_default;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
CustomData_copy(&bm_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_SET_DEFAULT, 0);
|
|
|
|
|
CustomData_copy(&bm_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_SET_DEFAULT, 0);
|
|
|
|
|
CustomData_copy(&bm_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_SET_DEFAULT, 0);
|
|
|
|
|
CustomData_copy(&bm_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_SET_DEFAULT, 0);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-07-11 04:24:36 +00:00
|
|
|
CustomData_bmesh_init_pool(&bm_dst->vdata, allocsize->totvert, BM_VERT);
|
|
|
|
|
CustomData_bmesh_init_pool(&bm_dst->edata, allocsize->totedge, BM_EDGE);
|
|
|
|
|
CustomData_bmesh_init_pool(&bm_dst->ldata, allocsize->totloop, BM_LOOP);
|
|
|
|
|
CustomData_bmesh_init_pool(&bm_dst->pdata, allocsize->totface, BM_FACE);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-10 11:13:01 -03:00
|
|
|
void BM_mesh_copy_init_customdata_all_layers(BMesh *bm_dst,
|
|
|
|
|
BMesh *bm_src,
|
|
|
|
|
const char htype,
|
|
|
|
|
const BMAllocTemplate *allocsize)
|
|
|
|
|
{
|
|
|
|
|
if (allocsize == NULL) {
|
|
|
|
|
allocsize = &bm_mesh_allocsize_default;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char htypes[4] = {BM_VERT, BM_EDGE, BM_LOOP, BM_FACE};
|
|
|
|
|
BLI_assert(((&bm_dst->vdata + 1) == &bm_dst->edata) &&
|
|
|
|
|
((&bm_dst->vdata + 2) == &bm_dst->ldata) && ((&bm_dst->vdata + 3) == &bm_dst->pdata));
|
|
|
|
|
|
|
|
|
|
BLI_assert(((&allocsize->totvert + 1) == &allocsize->totedge) &&
|
|
|
|
|
((&allocsize->totvert + 2) == &allocsize->totloop) &&
|
|
|
|
|
((&allocsize->totvert + 3) == &allocsize->totface));
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
|
if (!(htypes[i] & htype)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
CustomData *dst = &bm_dst->vdata + i;
|
|
|
|
|
CustomData *src = &bm_src->vdata + i;
|
|
|
|
|
const int size = *(&allocsize->totvert + i);
|
|
|
|
|
|
|
|
|
|
for (int l = 0; l < src->totlayer; l++) {
|
2020-10-20 10:48:05 +02:00
|
|
|
CustomData_add_layer_named(
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
dst, src->layers[l].type, CD_SET_DEFAULT, NULL, 0, src->layers[l].name);
|
2020-10-10 11:13:01 -03:00
|
|
|
}
|
|
|
|
|
CustomData_bmesh_init_pool(dst, size, htypes[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-25 20:47:06 +00:00
|
|
|
BMesh *BM_mesh_copy(BMesh *bm_old)
|
|
|
|
|
{
|
2012-03-01 22:17:04 +00:00
|
|
|
BMesh *bm_new;
|
2013-05-25 20:47:06 +00:00
|
|
|
BMVert *v, *v_new, **vtable = NULL;
|
|
|
|
|
BMEdge *e, *e_new, **etable = NULL;
|
|
|
|
|
BMFace *f, *f_new, **ftable = NULL;
|
2012-04-24 21:19:18 +00:00
|
|
|
BMElem **eletable;
|
2012-02-19 18:31:04 +00:00
|
|
|
BMEditSelection *ese;
|
2013-05-25 20:47:06 +00:00
|
|
|
BMIter iter;
|
|
|
|
|
int i;
|
2013-09-24 03:31:00 +00:00
|
|
|
const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_BM(bm_old);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-02-19 18:31:04 +00:00
|
|
|
/* allocate a bmesh */
|
2016-07-01 19:07:11 +10:00
|
|
|
bm_new = BM_mesh_create(&allocsize,
|
|
|
|
|
&((struct BMeshCreateParams){
|
|
|
|
|
.use_toolflags = bm_old->use_toolflags,
|
|
|
|
|
}));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-07-11 04:24:36 +00:00
|
|
|
BM_mesh_copy_init_customdata(bm_new, bm_old, &allocsize);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-01 22:17:04 +00:00
|
|
|
vtable = MEM_mallocN(sizeof(BMVert *) * bm_old->totvert, "BM_mesh_copy vtable");
|
|
|
|
|
etable = MEM_mallocN(sizeof(BMEdge *) * bm_old->totedge, "BM_mesh_copy etable");
|
|
|
|
|
ftable = MEM_mallocN(sizeof(BMFace *) * bm_old->totface, "BM_mesh_copy ftable");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-05-25 20:47:06 +00:00
|
|
|
BM_ITER_MESH_INDEX (v, &iter, bm_old, BM_VERTS_OF_MESH, i) {
|
2021-06-22 10:42:32 -07:00
|
|
|
/* copy between meshes so can't use 'example' argument */
|
2013-05-26 12:02:29 +00:00
|
|
|
v_new = BM_vert_create(bm_new, v->co, NULL, BM_CREATE_SKIP_CD);
|
2018-11-27 11:39:51 +11:00
|
|
|
BM_elem_attrs_copy_ex(bm_old, bm_new, v, v_new, 0xff, 0x0);
|
2013-07-24 19:31:58 +00:00
|
|
|
v_new->head.hflag = v->head.hflag; /* low level! don't do this for normal api use */
|
2013-05-25 20:47:06 +00:00
|
|
|
vtable[i] = v_new;
|
2012-02-19 18:31:04 +00:00
|
|
|
BM_elem_index_set(v, i); /* set_inline */
|
2013-05-25 20:47:06 +00:00
|
|
|
BM_elem_index_set(v_new, i); /* set_inline */
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
2012-03-01 22:17:04 +00:00
|
|
|
bm_old->elem_index_dirty &= ~BM_VERT;
|
|
|
|
|
bm_new->elem_index_dirty &= ~BM_VERT;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-02-19 18:31:04 +00:00
|
|
|
/* safety check */
|
2012-03-01 22:17:04 +00:00
|
|
|
BLI_assert(i == bm_old->totvert);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-05-25 20:47:06 +00:00
|
|
|
BM_ITER_MESH_INDEX (e, &iter, bm_old, BM_EDGES_OF_MESH, i) {
|
|
|
|
|
e_new = BM_edge_create(bm_new,
|
|
|
|
|
vtable[BM_elem_index_get(e->v1)],
|
|
|
|
|
vtable[BM_elem_index_get(e->v2)],
|
|
|
|
|
e,
|
|
|
|
|
BM_CREATE_SKIP_CD);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-11-27 11:39:51 +11:00
|
|
|
BM_elem_attrs_copy_ex(bm_old, bm_new, e, e_new, 0xff, 0x0);
|
2013-07-24 19:31:58 +00:00
|
|
|
e_new->head.hflag = e->head.hflag; /* low level! don't do this for normal api use */
|
2013-05-25 20:47:06 +00:00
|
|
|
etable[i] = e_new;
|
2012-02-19 18:31:04 +00:00
|
|
|
BM_elem_index_set(e, i); /* set_inline */
|
2013-05-25 20:47:06 +00:00
|
|
|
BM_elem_index_set(e_new, i); /* set_inline */
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
2012-03-01 22:17:04 +00:00
|
|
|
bm_old->elem_index_dirty &= ~BM_EDGE;
|
|
|
|
|
bm_new->elem_index_dirty &= ~BM_EDGE;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-02-19 18:31:04 +00:00
|
|
|
/* safety check */
|
2012-03-01 22:17:04 +00:00
|
|
|
BLI_assert(i == bm_old->totedge);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-05-25 20:47:06 +00:00
|
|
|
BM_ITER_MESH_INDEX (f, &iter, bm_old, BM_FACES_OF_MESH, i) {
|
2012-02-19 18:31:04 +00:00
|
|
|
BM_elem_index_set(f, i); /* set_inline */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-05-25 20:47:06 +00:00
|
|
|
f_new = bm_mesh_copy_new_face(bm_new, bm_old, vtable, etable, f);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-05-25 20:47:06 +00:00
|
|
|
ftable[i] = f_new;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-27 17:14:36 +11:00
|
|
|
if (f == bm_old->act_face) {
|
|
|
|
|
bm_new->act_face = f_new;
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2012-03-01 22:17:04 +00:00
|
|
|
bm_old->elem_index_dirty &= ~BM_FACE;
|
|
|
|
|
bm_new->elem_index_dirty &= ~BM_FACE;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-07-24 19:31:58 +00:00
|
|
|
/* low level! don't do this for normal api use */
|
|
|
|
|
bm_new->totvertsel = bm_old->totvertsel;
|
|
|
|
|
bm_new->totedgesel = bm_old->totedgesel;
|
|
|
|
|
bm_new->totfacesel = bm_old->totfacesel;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-02-19 18:31:04 +00:00
|
|
|
/* safety check */
|
2012-03-01 22:17:04 +00:00
|
|
|
BLI_assert(i == bm_old->totface);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-02-19 18:31:04 +00:00
|
|
|
/* copy over edit selection history */
|
2012-03-01 22:17:04 +00:00
|
|
|
for (ese = bm_old->selected.first; ese; ese = ese->next) {
|
2012-04-24 21:19:18 +00:00
|
|
|
BMElem *ele = NULL;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-04-24 21:19:18 +00:00
|
|
|
switch (ese->htype) {
|
|
|
|
|
case BM_VERT:
|
|
|
|
|
eletable = (BMElem **)vtable;
|
|
|
|
|
break;
|
|
|
|
|
case BM_EDGE:
|
|
|
|
|
eletable = (BMElem **)etable;
|
|
|
|
|
break;
|
|
|
|
|
case BM_FACE:
|
|
|
|
|
eletable = (BMElem **)ftable;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
eletable = NULL;
|
|
|
|
|
break;
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-04-24 21:19:18 +00:00
|
|
|
if (eletable) {
|
|
|
|
|
ele = eletable[BM_elem_index_get(ese->ele)];
|
|
|
|
|
if (ele) {
|
|
|
|
|
BM_select_history_store(bm_new, ele);
|
|
|
|
|
}
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-02-19 18:31:04 +00:00
|
|
|
MEM_freeN(etable);
|
|
|
|
|
MEM_freeN(vtable);
|
|
|
|
|
MEM_freeN(ftable);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-08 16:24:33 +10:00
|
|
|
/* Copy various settings. */
|
|
|
|
|
bm_new->shapenr = bm_old->shapenr;
|
|
|
|
|
bm_new->selectmode = bm_old->selectmode;
|
|
|
|
|
|
2012-03-01 22:17:04 +00:00
|
|
|
return bm_new;
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
|
|
2020-09-04 20:59:13 +02:00
|
|
|
char BM_vert_flag_from_mflag(const char mflag)
|
2012-02-19 18:31:04 +00:00
|
|
|
{
|
Mesh: Move hide flags to generic attributes
This commit moves the hide status of mesh vertices, edges, and faces
from the `ME_FLAG` to optional generic boolean attributes. Storing this
data as generic attributes can significantly simplify and improve code,
as described in T95965.
The attributes are called `.hide_vert`, `.hide_edge`, and `.hide_poly`,
using the attribute name semantics discussed in T97452. The `.` prefix
means they are "UI attributes", so they still contain original data
edited by users, but they aren't meant to be accessed procedurally by
the user in arbitrary situations. They are also be hidden in the
spreadsheet and the attribute list by default,
Until 4.0, the attributes are still written to and read from the mesh
in the old way, so neither forward nor backward compatibility are
affected. This means memory requirements will be increased by one byte
per element when the hide status is used. When the flags are removed
completely, requirements will decrease when hiding is unused.
Further notes:
* Some code can be further simplified to skip some processing when the
hide attributes don't exist.
* The data is still stored in flags for `BMesh`, necessitating some
complexity in the conversion to and from `Mesh`.
* Access to the "hide" property of mesh elements in RNA is slower.
The separate boolean arrays should be used where possible.
Ref T95965
Differential Revision: https://developer.blender.org/D14685
2022-08-11 12:54:24 -04:00
|
|
|
return ((mflag & SELECT) ? BM_ELEM_SELECT : 0);
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
2020-09-04 20:59:13 +02:00
|
|
|
char BM_edge_flag_from_mflag(const short mflag)
|
2012-02-19 18:31:04 +00:00
|
|
|
{
|
2020-09-04 20:59:13 +02:00
|
|
|
return (((mflag & SELECT) ? BM_ELEM_SELECT : 0) | ((mflag & ME_SEAM) ? BM_ELEM_SEAM : 0) |
|
|
|
|
|
((mflag & ME_EDGEDRAW) ? BM_ELEM_DRAW : 0) |
|
Mesh: Move hide flags to generic attributes
This commit moves the hide status of mesh vertices, edges, and faces
from the `ME_FLAG` to optional generic boolean attributes. Storing this
data as generic attributes can significantly simplify and improve code,
as described in T95965.
The attributes are called `.hide_vert`, `.hide_edge`, and `.hide_poly`,
using the attribute name semantics discussed in T97452. The `.` prefix
means they are "UI attributes", so they still contain original data
edited by users, but they aren't meant to be accessed procedurally by
the user in arbitrary situations. They are also be hidden in the
spreadsheet and the attribute list by default,
Until 4.0, the attributes are still written to and read from the mesh
in the old way, so neither forward nor backward compatibility are
affected. This means memory requirements will be increased by one byte
per element when the hide status is used. When the flags are removed
completely, requirements will decrease when hiding is unused.
Further notes:
* Some code can be further simplified to skip some processing when the
hide attributes don't exist.
* The data is still stored in flags for `BMesh`, necessitating some
complexity in the conversion to and from `Mesh`.
* Access to the "hide" property of mesh elements in RNA is slower.
The separate boolean arrays should be used where possible.
Ref T95965
Differential Revision: https://developer.blender.org/D14685
2022-08-11 12:54:24 -04:00
|
|
|
((mflag & ME_SHARP) == 0 ? BM_ELEM_SMOOTH : 0));
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
2020-09-04 20:59:13 +02:00
|
|
|
char BM_face_flag_from_mflag(const char mflag)
|
2012-02-19 18:31:04 +00:00
|
|
|
{
|
2020-09-04 20:59:13 +02:00
|
|
|
return (((mflag & ME_FACE_SEL) ? BM_ELEM_SELECT : 0) |
|
Mesh: Move hide flags to generic attributes
This commit moves the hide status of mesh vertices, edges, and faces
from the `ME_FLAG` to optional generic boolean attributes. Storing this
data as generic attributes can significantly simplify and improve code,
as described in T95965.
The attributes are called `.hide_vert`, `.hide_edge`, and `.hide_poly`,
using the attribute name semantics discussed in T97452. The `.` prefix
means they are "UI attributes", so they still contain original data
edited by users, but they aren't meant to be accessed procedurally by
the user in arbitrary situations. They are also be hidden in the
spreadsheet and the attribute list by default,
Until 4.0, the attributes are still written to and read from the mesh
in the old way, so neither forward nor backward compatibility are
affected. This means memory requirements will be increased by one byte
per element when the hide status is used. When the flags are removed
completely, requirements will decrease when hiding is unused.
Further notes:
* Some code can be further simplified to skip some processing when the
hide attributes don't exist.
* The data is still stored in flags for `BMesh`, necessitating some
complexity in the conversion to and from `Mesh`.
* Access to the "hide" property of mesh elements in RNA is slower.
The separate boolean arrays should be used where possible.
Ref T95965
Differential Revision: https://developer.blender.org/D14685
2022-08-11 12:54:24 -04:00
|
|
|
((mflag & ME_SMOOTH) ? BM_ELEM_SMOOTH : 0));
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
|
|
2020-09-04 20:59:13 +02:00
|
|
|
char BM_vert_flag_to_mflag(BMVert *v)
|
2012-02-19 18:31:04 +00:00
|
|
|
{
|
2020-09-04 20:59:13 +02:00
|
|
|
const char hflag = v->head.hflag;
|
2012-02-19 18:31:04 +00:00
|
|
|
|
Mesh: Move hide flags to generic attributes
This commit moves the hide status of mesh vertices, edges, and faces
from the `ME_FLAG` to optional generic boolean attributes. Storing this
data as generic attributes can significantly simplify and improve code,
as described in T95965.
The attributes are called `.hide_vert`, `.hide_edge`, and `.hide_poly`,
using the attribute name semantics discussed in T97452. The `.` prefix
means they are "UI attributes", so they still contain original data
edited by users, but they aren't meant to be accessed procedurally by
the user in arbitrary situations. They are also be hidden in the
spreadsheet and the attribute list by default,
Until 4.0, the attributes are still written to and read from the mesh
in the old way, so neither forward nor backward compatibility are
affected. This means memory requirements will be increased by one byte
per element when the hide status is used. When the flags are removed
completely, requirements will decrease when hiding is unused.
Further notes:
* Some code can be further simplified to skip some processing when the
hide attributes don't exist.
* The data is still stored in flags for `BMesh`, necessitating some
complexity in the conversion to and from `Mesh`.
* Access to the "hide" property of mesh elements in RNA is slower.
The separate boolean arrays should be used where possible.
Ref T95965
Differential Revision: https://developer.blender.org/D14685
2022-08-11 12:54:24 -04:00
|
|
|
return (((hflag & BM_ELEM_SELECT) ? SELECT : 0));
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
2012-05-22 07:26:45 +00:00
|
|
|
|
2020-09-04 20:59:13 +02:00
|
|
|
short BM_edge_flag_to_mflag(BMEdge *e)
|
2012-02-19 18:31:04 +00:00
|
|
|
{
|
2020-09-04 20:59:13 +02:00
|
|
|
const char hflag = e->head.hflag;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-22 07:26:45 +00:00
|
|
|
return (((hflag & BM_ELEM_SELECT) ? SELECT : 0) | ((hflag & BM_ELEM_SEAM) ? ME_SEAM : 0) |
|
|
|
|
|
((hflag & BM_ELEM_DRAW) ? ME_EDGEDRAW : 0) |
|
|
|
|
|
((hflag & BM_ELEM_SMOOTH) == 0 ? ME_SHARP : 0) |
|
2021-07-16 11:45:52 +10:00
|
|
|
(BM_edge_is_wire(e) ? ME_LOOSEEDGE : 0) | /* not typical */
|
2012-05-22 07:26:45 +00:00
|
|
|
ME_EDGERENDER);
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
2020-09-04 20:59:13 +02:00
|
|
|
char BM_face_flag_to_mflag(BMFace *f)
|
2012-02-19 18:31:04 +00:00
|
|
|
{
|
2020-09-04 20:59:13 +02:00
|
|
|
const char hflag = f->head.hflag;
|
2012-02-19 18:31:04 +00:00
|
|
|
|
|
|
|
|
return (((hflag & BM_ELEM_SELECT) ? ME_FACE_SEL : 0) |
|
Mesh: Move hide flags to generic attributes
This commit moves the hide status of mesh vertices, edges, and faces
from the `ME_FLAG` to optional generic boolean attributes. Storing this
data as generic attributes can significantly simplify and improve code,
as described in T95965.
The attributes are called `.hide_vert`, `.hide_edge`, and `.hide_poly`,
using the attribute name semantics discussed in T97452. The `.` prefix
means they are "UI attributes", so they still contain original data
edited by users, but they aren't meant to be accessed procedurally by
the user in arbitrary situations. They are also be hidden in the
spreadsheet and the attribute list by default,
Until 4.0, the attributes are still written to and read from the mesh
in the old way, so neither forward nor backward compatibility are
affected. This means memory requirements will be increased by one byte
per element when the hide status is used. When the flags are removed
completely, requirements will decrease when hiding is unused.
Further notes:
* Some code can be further simplified to skip some processing when the
hide attributes don't exist.
* The data is still stored in flags for `BMesh`, necessitating some
complexity in the conversion to and from `Mesh`.
* Access to the "hide" property of mesh elements in RNA is slower.
The separate boolean arrays should be used where possible.
Ref T95965
Differential Revision: https://developer.blender.org/D14685
2022-08-11 12:54:24 -04:00
|
|
|
((hflag & BM_ELEM_SMOOTH) ? ME_SMOOTH : 0));
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|