1
1

Compare commits

...

2 Commits

Author SHA1 Message Date
9f2a381841 Updated based on feedback by @mano-wii
---

Best result so far!
**Benchmarking**
||master|temp branch:
|---|---|---|
|large_mesh_editing:|Average: 6.973309 FPS|Average: 11.112296 FPS
||rdata 9ms iter 33ms (frame 144ms)|rdata 8ms iter 32ms (frame 88ms)
|large_mesh_editing_ledge: |Average: 6.943300 FPS|Average: 10.853841 FPS
||rdata 9ms iter 36ms (frame 144ms)|rdata 8ms iter 35ms (frame 92ms)
```

Here are some things I will change before testing:
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.cc b/source/blender/draw/intern/draw_cache_extract_mesh.cc
index 622ea191a0a..4d7c2e16e3a 100644
--- a/source/blender/draw/intern/draw_cache_extract_mesh.cc
+++ b/source/blender/draw/intern/draw_cache_extract_mesh.cc
@@ -40,7 +40,7 @@
 #include "draw_cache_extract_mesh_private.h"
 #include "draw_cache_inline.h"

-// #define DEBUG_TIME
+#define DEBUG_TIME

 #ifdef DEBUG_TIME
 #  include "PIL_time_utildefines.h"
diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c
index 26d844d4316..2e9109c17ed 100644
--- a/source/blender/editors/transform/transform_convert_mesh.c
+++ b/source/blender/editors/transform/transform_convert_mesh.c
@@ -1698,7 +1698,7 @@ static struct BMesh_PartialInfo *tc_mesh_ensure_partial_update(TransInfo *t,
       tcmd->editmesh_partial_info_prop_size = t->prop_size;
       recalc = false;
     }
-    else if (tcmd->editmesh_partial_info_prop_size != t->prop_size) {
+    else if (tcmd->editmesh_partial_info_prop_size_stored != t->prop_size) {
       BLI_assert(tcmd->editmesh_partial_info_prop_size_stored >
                  tcmd->editmesh_partial_info_prop_size);
       recalc = true;
@@ -1738,7 +1738,8 @@ static struct BMesh_PartialInfo *tc_mesh_ensure_partial_update(TransInfo *t,
   TransDataMirror *td_mirror = tc->data_mirror;
   for (i = 0; i < tc->data_mirror_len; i++, td_mirror++) {
     BMVert *v_mirr = (BMVert *)POINTER_OFFSET(td_mirror->loc_src, -offsetof(BMVert, co));
-    if (BM_elem_flag_test(v_mirr, BM_ELEM_TAG)) {
+    if (BM_elem_flag_test(v_mirr, BM_ELEM_TAG) ||
+        !compare_v3v3(td_mirror->loc, td_mirror->iloc, FLT_EPSILON)) {
       BMVert *v_mirr_other = (BMVert *)td_mirror->extra;
       if (!BM_elem_flag_test(v_mirr_other, BM_ELEM_TAG)) {
         BM_elem_flag_enable(v_mirr_other, BM_ELEM_TAG);

```
2021-06-03 15:25:40 +10:00
97e63f5945 Partial updates 2021-06-03 15:19:43 +10:00
13 changed files with 584 additions and 50 deletions

View File

@@ -33,6 +33,7 @@ extern "C" {
struct BMLoop;
struct BMesh;
struct BMesh_PartialInfo;
struct BoundBox;
struct Depsgraph;
struct Mesh;
@@ -85,6 +86,8 @@ typedef struct BMEditMesh {
/* editmesh.c */
void BKE_editmesh_looptri_calc(BMEditMesh *em);
void BKE_editmesh_looptri_calc_with_partial(BMEditMesh *em, struct BMesh_PartialInfo *bmpinfo);
BMEditMesh *BKE_editmesh_create(BMesh *bm, const bool do_tessellate);
BMEditMesh *BKE_editmesh_copy(BMEditMesh *em);
BMEditMesh *BKE_editmesh_from_object(struct Object *ob);

View File

@@ -149,6 +149,14 @@ void BKE_editmesh_looptri_calc(BMEditMesh *em)
#endif
}
void BKE_editmesh_looptri_calc_with_partial(BMEditMesh *em, struct BMesh_PartialInfo *bmpinfo)
{
BLI_assert(em->tottri == poly_to_tri_count(em->bm->totface, em->bm->totloop));
/* after allocating the em->looptris, we're ready to tessellate */
BM_mesh_calc_tessellation_with_partial(em->bm, em->looptris, bmpinfo);
}
void BKE_editmesh_free_derivedmesh(BMEditMesh *em)
{
if (em->mesh_eval_cage) {

View File

@@ -104,6 +104,8 @@ set(SRC
intern/bmesh_mesh_duplicate.h
intern/bmesh_mesh_tessellate.c
intern/bmesh_mesh_tessellate.h
intern/bmesh_mesh_partial.c
intern/bmesh_mesh_partial.h
intern/bmesh_mesh_validate.c
intern/bmesh_mesh_validate.h
intern/bmesh_mods.c

View File

@@ -40,6 +40,7 @@
#include "atomic_ops.h"
#include "intern/bmesh_mesh_partial.h"
#include "intern/bmesh_private.h"
/* used as an extern, defined in bmesh.h */
@@ -373,15 +374,16 @@ typedef struct BMVertsCalcNormalsData {
float (*vnos)[3];
} BMVertsCalcNormalsData;
static void mesh_verts_calc_normals_accum_cb(void *userdata, MempoolIterData *mp_f)
static void mesh_verts_calc_normals_accum(
BMFace *f,
const float *f_no,
const float (*edgevec)[3],
/* Read-write data, protected by an atomic-based fake spin-lock like system. */
float (*vnos)[3])
{
#define FLT_EQ_NONAN(_fa, _fb) (*((const uint32_t *)&_fa) == *((const uint32_t *)&_fb))
BMVertsCalcNormalsData *data = userdata;
BMFace *f = (BMFace *)mp_f;
const float *f_no = data->fnos ? data->fnos[BM_elem_index_get(f)] : f->no;
BMLoop *l_first, *l_iter;
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
@@ -391,8 +393,8 @@ static void mesh_verts_calc_normals_accum_cb(void *userdata, MempoolIterData *mp
/* calculate the dot product of the two edges that
* meet at the loop's vertex */
e1diff = data->edgevec[BM_elem_index_get(l_iter->prev->e)];
e2diff = data->edgevec[BM_elem_index_get(l_iter->e)];
e1diff = edgevec[BM_elem_index_get(l_iter->prev->e)];
e2diff = edgevec[BM_elem_index_get(l_iter->e)];
dotprod = dot_v3v3(e1diff, e2diff);
/* edge vectors are calculated from e->v1 to e->v2, so
@@ -410,7 +412,7 @@ static void mesh_verts_calc_normals_accum_cb(void *userdata, MempoolIterData *mp
}
/* accumulate weighted face normal into the vertex's normal */
float *v_no = data->vnos ? data->vnos[BM_elem_index_get(l_iter->v)] : l_iter->v->no;
float *v_no = vnos ? vnos[BM_elem_index_get(l_iter->v)] : l_iter->v->no;
/* This block is a lockless threadsafe madd_v3_v3fl.
* It uses the first float of the vector as a sort of cheap spin-lock,
@@ -447,6 +449,14 @@ static void mesh_verts_calc_normals_accum_cb(void *userdata, MempoolIterData *mp
#undef FLT_EQ_NONAN
}
static void mesh_verts_calc_normals_accum_cb(void *userdata, MempoolIterData *mp_f)
{
BMVertsCalcNormalsData *data = userdata;
BMFace *f = (BMFace *)mp_f;
const float *f_no = data->fnos ? data->fnos[BM_elem_index_get(f)] : f->no;
mesh_verts_calc_normals_accum(f, f_no, data->edgevec, data->vnos);
}
static void mesh_verts_calc_normals_normalize_cb(void *userdata, MempoolIterData *mp_v)
{
BMVertsCalcNormalsData *data = userdata;
@@ -492,11 +502,6 @@ static void mesh_faces_calc_normals_cb(void *UNUSED(userdata), MempoolIterData *
BM_face_normal_update(f);
}
/**
* \brief BMesh Compute Normals
*
* Updates the normals of a mesh.
*/
void BM_mesh_normals_update(BMesh *bm)
{
float(*edgevec)[3] = MEM_mallocN(sizeof(*edgevec) * bm->totedge, __func__);
@@ -529,6 +534,111 @@ void BM_mesh_normals_update(BMesh *bm)
MEM_freeN(edgevec);
}
static void mesh_faces_parallel_range_calc_normals_cb(
void *userdata, const int iter, const TaskParallelTLS *__restrict UNUSED(tls))
{
BMFace *f = ((BMFace **)userdata)[iter];
BM_face_normal_update(f);
}
static void mesh_edges_parallel_range_calc_vectors_cb(
void *userdata, const int iter, const TaskParallelTLS *__restrict UNUSED(tls))
{
BMEdge *e = ((BMEdge **)((void **)userdata)[0])[iter];
float *r_edgevec = ((float(*)[3])((void **)userdata)[1])[iter];
sub_v3_v3v3(r_edgevec, e->v1->co, e->v2->co);
normalize_v3(r_edgevec);
}
static void mesh_verts_parallel_range_calc_normals_accum_cb(
void *userdata, const int iter, const TaskParallelTLS *__restrict UNUSED(tls))
{
BMFace *f = ((BMFace **)((void **)userdata)[0])[iter];
const float(*edgevec)[3] = (float(*)[3])((void **)userdata)[1];
mesh_verts_calc_normals_accum(f, f->no, edgevec, NULL);
}
static void mesh_verts_parallel_range_calc_normals_normalize_cb(
void *userdata, const int iter, const TaskParallelTLS *__restrict UNUSED(tls))
{
BMVert *v = ((BMVert **)userdata)[iter];
if (UNLIKELY(normalize_v3(v->no) == 0.0f)) {
normalize_v3_v3(v->no, v->co);
}
}
void BM_mesh_normals_update_with_partial(BMesh *bm, struct BMesh_PartialInfo *bmpinfo)
{
BMVert **verts = bmpinfo->verts;
BMEdge **edges = bmpinfo->edges;
BMFace **faces = bmpinfo->faces;
const int verts_len = bmpinfo->verts_len;
const int edges_len = bmpinfo->edges_len;
const int faces_len = bmpinfo->faces_len;
float(*edgevec)[3] = MEM_mallocN(sizeof(*edgevec) * edges_len, __func__);
for (int i = 0; i < verts_len; i++) {
zero_v3(verts[i]->no);
}
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
{
/* Faces. */
BLI_task_parallel_range(
0, faces_len, faces, mesh_faces_parallel_range_calc_normals_cb, &settings);
}
int *edge_index_value = NULL;
if ((bm->elem_index_dirty & BM_EDGE) == 0) {
edge_index_value = MEM_mallocN(sizeof(*edge_index_value) * edges_len, __func__);
for (int i = 0; i < edges_len; i++) {
BMEdge *e = edges[i];
edge_index_value[i] = BM_elem_index_get(e);
BM_elem_index_set(e, i); /* et_dirty! (restore before this function exits). */
}
}
else {
for (int i = 0; i < edges_len; i++) {
BMEdge *e = edges[i];
BM_elem_index_set(e, i); /* set_dirty! (already dirty) */
}
}
{
/* Verts. */
/* Compute normalized direction vectors for each edge.
* Directions will be used for calculating the weights of the face normals on the vertex
* normals. */
void *data[2] = {edges, edgevec};
BLI_task_parallel_range(
0, edges_len, data, mesh_edges_parallel_range_calc_vectors_cb, &settings);
/* Add weighted face normals to vertices. */
data[0] = faces;
BLI_task_parallel_range(
0, faces_len, data, mesh_verts_parallel_range_calc_normals_accum_cb, &settings);
/* Normalize the accumulated vertex normals. */
BLI_task_parallel_range(
0, verts_len, verts, mesh_verts_parallel_range_calc_normals_normalize_cb, &settings);
}
if (edge_index_value != NULL) {
for (int i = 0; i < edges_len; i++) {
BMEdge *e = edges[i];
BM_elem_index_set(e, edge_index_value[i]); /* set_ok (restore) */
}
MEM_freeN(edge_index_value);
}
MEM_freeN(edgevec);
}
/**
* \brief BMesh Compute Normals from/to external data.
*

View File

@@ -25,6 +25,7 @@
struct BMAllocTemplate;
struct BMLoopNorEditDataArray;
struct MLoopNorSpaceArray;
struct BMesh_PartialInfo;
void BM_mesh_elem_toolflags_ensure(BMesh *bm);
void BM_mesh_elem_toolflags_clear(BMesh *bm);
@@ -41,6 +42,8 @@ void BM_mesh_data_free(BMesh *bm);
void BM_mesh_clear(BMesh *bm);
void BM_mesh_normals_update(BMesh *bm);
void BM_mesh_normals_update_with_partial(BMesh *bm, struct BMesh_PartialInfo *bmpinfo);
void BM_verts_calc_normal_vcos(BMesh *bm,
const float (*fnos)[3],
const float (*vcos)[3],

View File

@@ -0,0 +1,168 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/** \file
* \ingroup bmesh
*
* Duplicate geometry from one mesh from another.
*/
#include "DNA_object_types.h"
#include "MEM_guardedalloc.h"
#include "BLI_alloca.h"
#include "BLI_bitmap.h"
#include "BLI_math_vector.h"
#include "bmesh.h"
#include "intern/bmesh_mesh_partial.h"
#include "intern/bmesh_private.h" /* for element checking */
/* Grow by 1.5x (rounding up). */
#define GROW(len_alloc) ((len_alloc) + ((len_alloc) - ((len_alloc) / 2)))
#define GROW_ARRAY(mem, len_alloc) \
{ \
mem = MEM_reallocN(mem, (sizeof(*mem)) * ((len_alloc) = GROW(len_alloc))); \
} \
((void)0)
#define MAYBE_GROW_ARRAY(mem, len_alloc, index) \
if (UNLIKELY(len_alloc == index)) { \
GROW_ARRAY(mem, len_alloc); \
}
BLI_INLINE bool partial_elem_ensure_vert(struct BMesh_PartialInfo *bmpinfo, BMVert *v)
{
const int i = BM_elem_index_get(v);
if (!BLI_BITMAP_TEST(bmpinfo->verts_tag, i)) {
BLI_BITMAP_ENABLE(bmpinfo->verts_tag, i);
MAYBE_GROW_ARRAY(bmpinfo->verts, bmpinfo->verts_len_alloc, bmpinfo->verts_len);
bmpinfo->verts[bmpinfo->verts_len++] = v;
return true;
}
return false;
}
BLI_INLINE bool partial_elem_ensure_edge(struct BMesh_PartialInfo *bmpinfo, BMEdge *e)
{
const int i = BM_elem_index_get(e);
if (!BLI_BITMAP_TEST(bmpinfo->edges_tag, i)) {
BLI_BITMAP_ENABLE(bmpinfo->edges_tag, i);
MAYBE_GROW_ARRAY(bmpinfo->edges, bmpinfo->edges_len_alloc, bmpinfo->edges_len);
bmpinfo->edges[bmpinfo->edges_len++] = e;
return true;
}
return false;
}
BLI_INLINE bool partial_elem_ensure_face(struct BMesh_PartialInfo *bmpinfo, BMFace *f)
{
const int i = BM_elem_index_get(f);
if (!BLI_BITMAP_TEST(bmpinfo->faces_tag, i)) {
BLI_BITMAP_ENABLE(bmpinfo->faces_tag, i);
MAYBE_GROW_ARRAY(bmpinfo->faces, bmpinfo->faces_len_alloc, bmpinfo->faces_len);
bmpinfo->faces[bmpinfo->faces_len++] = f;
return true;
}
return false;
}
struct BMesh_PartialInfo *BM_mesh_partial_info_create_from_verts(
BMesh *bm, const int verts_len, bool (*filter_fn)(BMVert *, void *user_data), void *user_data)
{
struct BMesh_PartialInfo *bmpinfo = MEM_callocN(sizeof(*bmpinfo), __func__);
bmpinfo->verts_len_alloc = verts_len;
bmpinfo->verts = MEM_mallocN((sizeof(BMVert *) * verts_len), __func__);
bmpinfo->edges_len_alloc = verts_len;
bmpinfo->edges = MEM_mallocN((sizeof(BMEdge *) * bmpinfo->edges_len_alloc), __func__);
bmpinfo->faces_len_alloc = verts_len;
bmpinfo->faces = MEM_mallocN((sizeof(BMFace *) * bmpinfo->faces_len_alloc), __func__);
bmpinfo->verts_tag = BLI_BITMAP_NEW((size_t)bm->totvert, __func__);
bmpinfo->edges_tag = BLI_BITMAP_NEW((size_t)bm->totedge, __func__);
bmpinfo->faces_tag = BLI_BITMAP_NEW((size_t)bm->totface, __func__);
/* Set vert inline. */
BM_mesh_elem_index_ensure(bm, (BM_EDGE | BM_FACE));
{
BMVert *v;
BMIter iter;
int i;
BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
BM_elem_index_set(v, i); /* set_inline */
if (!filter_fn(v, user_data)) {
continue;
}
BMEdge *e_iter = v->e;
if (e_iter != NULL) {
/* Loop over edges. */
BMEdge *e_first = v->e;
do {
BMLoop *l_iter = e_iter->l;
if (e_iter->l != NULL) {
BMLoop *l_first = e_iter->l;
/* Loop over radial loops. */
do {
if (l_iter->v == v) {
partial_elem_ensure_face(bmpinfo, l_iter->f);
}
} while ((l_iter = l_iter->radial_next) != l_first);
}
} while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
}
}
}
for (int i = 0; i < bmpinfo->faces_len; i++) {
BMFace *f = bmpinfo->faces[i];
BMLoop *l_iter, *l_first;
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
if (!partial_elem_ensure_vert(bmpinfo, l_iter->v)) {
continue;
}
BMVert *v = l_iter->v;
BMEdge *e_first = v->e;
BMEdge *e_iter = e_first;
do {
if (e_iter->l) {
partial_elem_ensure_edge(bmpinfo, e_iter);
}
} while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
} while ((l_iter = l_iter->next) != l_first);
/* End indirect loop. */
}
MEM_freeN(bmpinfo->verts_tag);
MEM_freeN(bmpinfo->edges_tag);
MEM_freeN(bmpinfo->faces_tag);
return bmpinfo;
}
void BM_mesh_partial_info_destroy(struct BMesh_PartialInfo *bmpinfo)
{
MEM_freeN(bmpinfo->verts);
MEM_freeN(bmpinfo->edges);
MEM_freeN(bmpinfo->faces);
MEM_freeN(bmpinfo);
}

View File

@@ -0,0 +1,42 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#pragma once
/** \file
* \ingroup bmesh
*/
#include "bmesh.h"
struct BMesh_PartialInfo {
BMVert **verts;
BMEdge **edges;
BMFace **faces;
int verts_len, verts_len_alloc;
int edges_len, edges_len_alloc;
int faces_len, faces_len_alloc;
/* Only for building. */
uint *verts_tag;
uint *edges_tag;
uint *faces_tag;
};
struct BMesh_PartialInfo *BM_mesh_partial_info_create_from_verts(
BMesh *bm, const int verts_len, bool (*filter_fn)(BMVert *, void *user_data), void *user_data);
void BM_mesh_partial_info_destroy(struct BMesh_PartialInfo *bmpinfo);

View File

@@ -36,6 +36,8 @@
#include "bmesh.h"
#include "bmesh_tools.h"
#include "intern/bmesh_mesh_partial.h"
/* -------------------------------------------------------------------- */
/** \name Default Mesh Tessellation
* \{ */
@@ -151,6 +153,32 @@ void BM_mesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3])
/** \} */
void BM_mesh_calc_tessellation_with_partial(BMesh *bm,
BMLoop *(*looptris)[3],
struct BMesh_PartialInfo *bmpinfo)
{
const int faces_len = bmpinfo->faces_len;
BMFace **faces = bmpinfo->faces;
MemArena *pf_arena = NULL;
/* This could potentially cause a lot of excessive looping. */
BM_mesh_elem_index_ensure(bm, BM_LOOP | BM_FACE);
for (int index = 0; index < faces_len; index++) {
BMFace *f = faces[index];
BMLoop *l = BM_FACE_FIRST_LOOP(faces[index]);
const int offset = BM_elem_index_get(l) - (BM_elem_index_get(f) * 2);
mesh_calc_tessellation_for_face(looptris + offset, faces[index], &pf_arena);
}
if (pf_arena) {
BLI_memarena_free(pf_arena);
pf_arena = NULL;
}
}
/* -------------------------------------------------------------------- */
/** \name Beauty Mesh Tessellation
*

View File

@@ -22,3 +22,7 @@
void BM_mesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3]);
void BM_mesh_calc_tessellation_beauty(BMesh *bm, BMLoop *(*looptris)[3]);
void BM_mesh_calc_tessellation_with_partial(BMesh *bm,
BMLoop *(*looptris)[3],
struct BMesh_PartialInfo *bmpinfo);

View File

@@ -21,6 +21,7 @@
*/
struct Heap;
struct BMesh_PartialInfo;
#include "BLI_compiler_attrs.h"

View File

@@ -46,6 +46,7 @@
* \{ */
struct ARegion;
struct BMesh_PartialInfo;
struct Depsgraph;
struct NumInput;
struct Object;

View File

@@ -48,6 +48,62 @@
#include "transform_convert.h"
#include "intern/bmesh_mesh_partial.h"
/* -------------------------------------------------------------------- */
/** \name Container TransCustomData Creation
* \{ */
static void tc_mesh_xxx_free_fn(struct TransInfo *t,
struct TransDataContainer *tc,
struct TransCustomData *custom_data);
struct TransCustomDataLayer;
static void tc_mesh_customdata_free(struct TransCustomDataLayer *tcld);
struct TransCustomDataMesh {
struct TransCustomDataLayer *tcld;
struct BMesh_PartialInfo *editmesh_partial_info;
float editmesh_partial_info_prop_size_stored;
float editmesh_partial_info_prop_size;
};
static struct TransCustomDataMesh *tc_mesh_xxx_ensure(TransDataContainer *tc)
{
struct TransCustomDataMesh *tcmd = tc->custom.type.data;
BLI_assert(tc->custom.type.data == NULL || tc->custom.type.free_cb == tc_mesh_xxx_free_fn);
if (tc->custom.type.data == NULL) {
tc->custom.type.data = MEM_callocN(sizeof(struct TransCustomDataMesh), __func__);
tc->custom.type.free_cb = tc_mesh_xxx_free_fn;
tcmd = tc->custom.type.data;
}
return tcmd;
}
static void tc_mesh_xxx_free(struct TransCustomDataMesh *tcmd)
{
if (tcmd->tcld != NULL) {
tc_mesh_customdata_free(tcmd->tcld);
}
if (tcmd->editmesh_partial_info != NULL) {
BM_mesh_partial_info_destroy(tcmd->editmesh_partial_info);
}
MEM_freeN(tcmd);
}
static void tc_mesh_xxx_free_fn(struct TransInfo *UNUSED(t),
struct TransDataContainer *UNUSED(tc),
struct TransCustomData *custom_data)
{
struct TransCustomDataMesh *tcmd = custom_data->data;
tc_mesh_xxx_free(tcmd);
custom_data->data = NULL;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Container TransCustomData Creation
* \{ */
@@ -83,33 +139,6 @@ struct TransCustomDataLayer {
bool use_merge_group;
};
static void tc_mesh_customdatacorrect_free_fn(struct TransInfo *UNUSED(t),
struct TransDataContainer *UNUSED(tc),
struct TransCustomData *custom_data)
{
struct TransCustomDataLayer *tcld = custom_data->data;
bmesh_edit_end(tcld->bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
if (tcld->bm_origfaces) {
BM_mesh_free(tcld->bm_origfaces);
}
if (tcld->origfaces) {
BLI_ghash_free(tcld->origfaces, NULL, NULL);
}
if (tcld->merge_group.origverts) {
BLI_ghash_free(tcld->merge_group.origverts, NULL, NULL);
}
if (tcld->arena) {
BLI_memarena_free(tcld->arena);
}
if (tcld->merge_group.customdatalayer_map) {
MEM_freeN(tcld->merge_group.customdatalayer_map);
}
MEM_freeN(tcld);
custom_data->data = NULL;
}
#define USE_FACE_SUBSTITUTE
#ifdef USE_FACE_SUBSTITUTE
# define FACE_SUBSTITUTE_INDEX INT_MIN
@@ -350,9 +379,32 @@ static void tc_mesh_customdata_create(TransDataContainer *tc, const bool use_mer
return;
}
BLI_assert(tc->custom.type.data == NULL);
tc->custom.type.data = customdatacorrect;
tc->custom.type.free_cb = tc_mesh_customdatacorrect_free_fn;
struct TransCustomDataMesh *tcmd = tc_mesh_xxx_ensure(tc);
BLI_assert(tcmd->tcld == NULL);
tcmd->tcld = customdatacorrect;
}
static void tc_mesh_customdata_free(struct TransCustomDataLayer *tcld)
{
bmesh_edit_end(tcld->bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
if (tcld->bm_origfaces) {
BM_mesh_free(tcld->bm_origfaces);
}
if (tcld->origfaces) {
BLI_ghash_free(tcld->origfaces, NULL, NULL);
}
if (tcld->merge_group.origverts) {
BLI_ghash_free(tcld->merge_group.origverts, NULL, NULL);
}
if (tcld->arena) {
BLI_memarena_free(tcld->arena);
}
if (tcld->merge_group.customdatalayer_map) {
MEM_freeN(tcld->merge_group.customdatalayer_map);
}
MEM_freeN(tcld);
}
void transform_convert_mesh_customdatacorrect_init(TransInfo *t)
@@ -390,7 +442,11 @@ void transform_convert_mesh_customdatacorrect_init(TransInfo *t)
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
if (tc->custom.type.data != NULL) {
tc_mesh_customdatacorrect_free_fn(t, tc, &tc->custom.type);
struct TransCustomDataMesh *tcmd = tc->custom.type.data;
if (tcmd && tcmd->tcld) {
tc_mesh_customdata_free(tcmd->tcld);
tcmd->tcld = NULL;
}
}
tc_mesh_customdata_create(tc, use_merge_group);
@@ -555,10 +611,11 @@ static void tc_mesh_customdatacorrect_apply_vert(struct TransCustomDataLayer *tc
static void tc_mesh_customdatacorrect_apply(TransDataContainer *tc, bool is_final)
{
if (!tc->custom.type.data) {
struct TransCustomDataMesh *tcmd = tc->custom.type.data;
struct TransCustomDataLayer *tcld = tcmd ? tcmd->tcld : NULL;
if (tcld == NULL) {
return;
}
struct TransCustomDataLayer *tcld = tc->custom.type.data;
const bool use_merge_group = tcld->use_merge_group;
struct TransCustomDataMergeGroup *merge_data = tcld->merge_group.data;
@@ -590,7 +647,8 @@ static void tc_mesh_customdatacorrect_apply(TransDataContainer *tc, bool is_fina
static void tc_mesh_customdatacorrect_restore(struct TransInfo *t)
{
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
struct TransCustomDataLayer *tcld = tc->custom.type.data;
struct TransCustomDataMesh *tcmd = tc->custom.type.data;
struct TransCustomDataLayer *tcld = tcmd ? tcmd->tcld : NULL;
if (!tcld) {
continue;
}
@@ -1617,6 +1675,91 @@ void createTransEditVerts(TransInfo *t)
/** \name Recalc Mesh Data
* \{ */
static bool bm_vert_tag_filter_fn(BMVert *v, void *UNUSED(user_data))
{
return BM_elem_flag_test(v, BM_ELEM_TAG);
}
static struct BMesh_PartialInfo *tc_mesh_ensure_partial_update(TransInfo *t,
TransDataContainer *tc)
{
struct TransCustomDataMesh *tcmd = tc_mesh_xxx_ensure(tc);
bool recalc;
if (tcmd->editmesh_partial_info) {
if (tcmd->editmesh_partial_info_prop_size < t->prop_size) {
/* Size increase, simply recalculate. */
recalc = true;
}
else if (tcmd->editmesh_partial_info_prop_size > t->prop_size) {
/* Size decreased, first use this partial data since reducing the size will transform
* geometry which needs recalculating. */
tcmd->editmesh_partial_info_prop_size_stored = tcmd->editmesh_partial_info_prop_size;
tcmd->editmesh_partial_info_prop_size = t->prop_size;
recalc = false;
}
else if (tcmd->editmesh_partial_info_prop_size_stored != t->prop_size) {
BLI_assert(tcmd->editmesh_partial_info_prop_size_stored >
tcmd->editmesh_partial_info_prop_size);
recalc = true;
}
else {
recalc = false;
}
if (!recalc) {
printf("Ruse\n");
return tcmd->editmesh_partial_info;
}
printf("REcalc\n");
BM_mesh_partial_info_destroy(tcmd->editmesh_partial_info);
tcmd->editmesh_partial_info = NULL;
}
BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
{
BMIter iter;
BMVert *v;
BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
BM_elem_flag_disable(v, BM_ELEM_TAG);
}
}
int verts_len = 0;
int i;
TransData *td;
for (i = 0, td = tc->data; i < tc->data_len; i++, td++) {
if (td->factor != 0.0f) {
BMVert *v = (BMVert *)td->extra;
BM_elem_flag_enable(v, BM_ELEM_TAG);
verts_len += 1;
}
}
TransDataMirror *td_mirror = tc->data_mirror;
for (i = 0; i < tc->data_mirror_len; i++, td_mirror++) {
BMVert *v_mirr = (BMVert *)POINTER_OFFSET(td_mirror->loc_src, -offsetof(BMVert, co));
if (BM_elem_flag_test(v_mirr, BM_ELEM_TAG)) {
BMVert *v_mirr_other = (BMVert *)td_mirror->extra;
if (!BM_elem_flag_test(v_mirr_other, BM_ELEM_TAG) ||
equals_v3v3(td_mirror->loc, td_mirror->iloc)) {
BM_elem_flag_enable(v_mirr_other, BM_ELEM_TAG);
verts_len += 1;
}
}
}
tcmd->editmesh_partial_info = BM_mesh_partial_info_create_from_verts(
em->bm, verts_len, bm_vert_tag_filter_fn, NULL);
tcmd->editmesh_partial_info_prop_size = t->prop_size;
tcmd->editmesh_partial_info_prop_size_stored = t->prop_size;
return tcmd->editmesh_partial_info;
}
static void tc_mesh_transdata_mirror_apply(TransDataContainer *tc)
{
if (tc->use_mirror_axis_any) {
@@ -1652,6 +1795,10 @@ static void tc_mesh_transdata_mirror_apply(TransDataContainer *tc)
}
}
#include "BKE_global.h"
#include "PIL_time.h"
#include "PIL_time_utildefines.h"
void recalcData_mesh(TransInfo *t)
{
bool is_canceling = t->state == TRANS_CANCEL;
@@ -1678,8 +1825,23 @@ void recalcData_mesh(TransInfo *t)
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
DEG_id_tag_update(tc->obedit->data, ID_RECALC_GEOMETRY);
BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
EDBM_mesh_normals_update(em);
BKE_editmesh_looptri_calc(em);
if (G.debug_value == 666) {
TIMEIT_START(a);
EDBM_mesh_normals_update(em);
BKE_editmesh_looptri_calc(em);
TIMEIT_END(a);
}
else {
struct BMesh_PartialInfo *editmesh_partial_info = tc_mesh_ensure_partial_update(t, tc);
TIMEIT_START(b);
/* This tags affected faces. */
BM_mesh_normals_update_with_partial(em->bm, editmesh_partial_info);
BKE_editmesh_looptri_calc_with_partial(em, editmesh_partial_info);
TIMEIT_END(b);
}
}
}
/** \} */

View File

@@ -64,6 +64,8 @@
#include "transform_orientations.h"
#include "transform_snap.h"
#include "intern/bmesh_mesh_partial.h"
/* ************************** GENERICS **************************** */
void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis, short options)