Compare commits
2 Commits
temp-ghost
...
temp-editm
Author | SHA1 | Date | |
---|---|---|---|
9f2a381841 | |||
97e63f5945 |
@@ -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);
|
||||
|
@@ -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) {
|
||||
|
@@ -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
|
||||
|
@@ -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.
|
||||
*
|
||||
|
@@ -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],
|
||||
|
168
source/blender/bmesh/intern/bmesh_mesh_partial.c
Normal file
168
source/blender/bmesh/intern/bmesh_mesh_partial.c
Normal 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);
|
||||
}
|
42
source/blender/bmesh/intern/bmesh_mesh_partial.h
Normal file
42
source/blender/bmesh/intern/bmesh_mesh_partial.h
Normal 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);
|
@@ -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
|
||||
*
|
||||
|
@@ -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);
|
||||
|
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
struct Heap;
|
||||
struct BMesh_PartialInfo;
|
||||
|
||||
#include "BLI_compiler_attrs.h"
|
||||
|
||||
|
@@ -46,6 +46,7 @@
|
||||
* \{ */
|
||||
|
||||
struct ARegion;
|
||||
struct BMesh_PartialInfo;
|
||||
struct Depsgraph;
|
||||
struct NumInput;
|
||||
struct Object;
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
/** \} */
|
||||
|
@@ -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)
|
||||
|
Reference in New Issue
Block a user