From 1767b658469b8f5553f53ede10b987dde9d502c6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 23 Oct 2012 03:38:26 +0000 Subject: style cleanup: also rename bmesh_decimate.c --> bmesh_decimate_collapse.c --- source/blender/blenkernel/intern/DerivedMesh.c | 8 +- source/blender/blenkernel/intern/fluidsim.c | 36 +- source/blender/blenkernel/intern/node.c | 2 +- source/blender/blenkernel/intern/pointcache.c | 6 +- source/blender/blenkernel/intern/writeavi.c | 4 +- source/blender/blenlib/intern/BLI_ghash.c | 4 +- source/blender/blenlib/intern/scanfill.c | 2 +- source/blender/blenlib/intern/string_utf8.c | 30 +- source/blender/bmesh/CMakeLists.txt | 2 +- source/blender/bmesh/intern/bmesh_decimate.c | 932 --------------------- source/blender/bmesh/intern/bmesh_decimate.h | 2 +- .../blender/bmesh/intern/bmesh_decimate_collapse.c | 932 +++++++++++++++++++++ source/blender/bmesh/intern/bmesh_mods.c | 2 +- source/blender/editors/animation/keyframes_draw.c | 4 +- source/blender/editors/interface/interface.c | 42 +- .../blender/editors/interface/interface_handlers.c | 12 +- .../blender/editors/interface/interface_layout.c | 2 +- source/blender/editors/metaball/mball_edit.c | 1 - source/blender/editors/object/object_lattice.c | 2 +- source/blender/editors/object/object_relations.c | 6 +- source/blender/editors/object/object_shapekey.c | 2 +- source/blender/editors/object/object_transform.c | 2 +- source/blender/editors/physics/particle_object.c | 11 +- source/blender/editors/physics/physics_fluid.c | 8 +- source/blender/editors/render/render_internal.c | 2 +- source/blender/editors/render/render_opengl.c | 2 +- source/blender/editors/screen/screen_edit.c | 4 +- source/blender/editors/sculpt_paint/paint_image.c | 6 +- source/blender/editors/space_logic/logic_buttons.c | 2 +- source/blender/editors/space_logic/logic_window.c | 6 +- source/blender/editors/space_logic/space_logic.c | 10 +- source/blender/makesrna/intern/rna_access.c | 2 +- source/blender/modifiers/intern/MOD_decimate.c | 2 +- source/blender/nodes/intern/node_socket.c | 22 +- source/blender/render/intern/source/rayshade.c | 4 +- 35 files changed, 1060 insertions(+), 1056 deletions(-) delete mode 100644 source/blender/bmesh/intern/bmesh_decimate.c create mode 100644 source/blender/bmesh/intern/bmesh_decimate_collapse.c (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 9eae8c44776..84691362a93 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -2428,7 +2428,7 @@ static int GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_ static void GetPosition(const SMikkTSpaceContext *pContext, float fPos[], const int face_num, const int vert_index) { - //assert(vert_index>=0 && vert_index<4); + //assert(vert_index >= 0 && vert_index < 4); SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData; const float *co = pMesh->mvert[(&pMesh->mface[face_num].v1)[vert_index]].co; copy_v3_v3(fPos, co); @@ -2436,7 +2436,7 @@ static void GetPosition(const SMikkTSpaceContext *pContext, float fPos[], const static void GetTextureCoordinate(const SMikkTSpaceContext *pContext, float fUV[], const int face_num, const int vert_index) { - //assert(vert_index>=0 && vert_index<4); + //assert(vert_index >= 0 && vert_index < 4); SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData; if (pMesh->mtface != NULL) { @@ -2451,7 +2451,7 @@ static void GetTextureCoordinate(const SMikkTSpaceContext *pContext, float fUV[] static void GetNormal(const SMikkTSpaceContext *pContext, float fNorm[], const int face_num, const int vert_index) { - //assert(vert_index>=0 && vert_index<4); + //assert(vert_index >= 0 && vert_index < 4); SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData; const int smoothnormal = (pMesh->mface[face_num].flag & ME_SMOOTH); @@ -2481,7 +2481,7 @@ static void GetNormal(const SMikkTSpaceContext *pContext, float fNorm[], const i } static void SetTSpace(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fSign, const int face_num, const int iVert) { - //assert(vert_index>=0 && vert_index<4); + //assert(vert_index >= 0 && vert_index < 4); SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData; float *pRes = pMesh->tangent[4 * face_num + iVert]; copy_v3_v3(pRes, fvTangent); diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c index 9be599ac66c..efc9869c5ca 100644 --- a/source/blender/blenkernel/intern/fluidsim.c +++ b/source/blender/blenkernel/intern/fluidsim.c @@ -41,7 +41,7 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_fluidsim.h" -#include "DNA_object_force.h" // for pointcache +#include "DNA_object_force.h" // for pointcache #include "DNA_object_types.h" #include "DNA_particle_types.h" #include "DNA_scene_types.h" // N_T @@ -66,14 +66,14 @@ //------------------------------------------------------------------------------- void initElbeemMesh(struct Scene *scene, struct Object *ob, - int *numVertices, float **vertices, - int *numTriangles, int **triangles, - int useGlobalCoords, int modifierIndex) + int *numVertices, float **vertices, + int *numTriangles, int **triangles, + int useGlobalCoords, int modifierIndex) { DerivedMesh *dm = NULL; MVert *mvert; MFace *mface; - int countTris=0, i, totvert, totface; + int countTris = 0, i, totvert, totface; float *verts; int *tris; @@ -87,35 +87,35 @@ void initElbeemMesh(struct Scene *scene, struct Object *ob, totface = dm->getNumTessFaces(dm); *numVertices = totvert; - verts = MEM_callocN(totvert*3*sizeof(float), "elbeemmesh_vertices"); - for (i=0; iobmat, &verts[i*3]); } + verts = MEM_callocN(totvert * 3 * sizeof(float), "elbeemmesh_vertices"); + for (i = 0; i < totvert; i++) { + copy_v3_v3(&verts[i * 3], mvert[i].co); + if (useGlobalCoords) { mul_m4_v3(ob->obmat, &verts[i * 3]); } } *vertices = verts; - for (i=0; inew_node = NULL; - /* nnode= */ nodeCopyNode(newtree, node); /* sets node->new */ + /* nnode = */ nodeCopyNode(newtree, node); /* sets node->new */ /* make sure we don't copy new nodes again! */ if (node == last) diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index c9b923cde32..5fe9bfdd4bc 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -2377,7 +2377,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra) } } } - if (pid->cache->cached_frames && cfra>=sta && cfra<=end) + if (pid->cache->cached_frames && cfra >= sta && cfra <= end) pid->cache->cached_frames[cfra-sta] = 0; break; } @@ -3378,7 +3378,7 @@ void BKE_ptcache_update_info(PTCacheID *pid) if (cache->flag & PTCACHE_EXTERNAL) { int cfra = cache->startframe; - for (; cfra<=cache->endframe; cfra++) { + for (; cfra <= cache->endframe; cfra++) { if (BKE_ptcache_id_exist(pid, cfra)) totframes++; } @@ -3405,7 +3405,7 @@ void BKE_ptcache_update_info(PTCacheID *pid) else { int cfra = cache->startframe; - for (; cfra<=cache->endframe; cfra++) { + for (; cfra <= cache->endframe; cfra++) { if (BKE_ptcache_id_exist(pid, cfra)) totframes++; } diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c index 1b562415da7..d4428be3faf 100644 --- a/source/blender/blenkernel/intern/writeavi.c +++ b/source/blender/blenkernel/intern/writeavi.c @@ -175,8 +175,8 @@ static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportL avi->interlace = 0; avi->odd_fields = 0; -/* avi->interlace= rd->mode & R_FIELDS; */ -/* avi->odd_fields= (rd->mode & R_ODDFIELD)?1:0; */ +/* avi->interlace = rd->mode & R_FIELDS; */ +/* avi->odd_fields = (rd->mode & R_ODDFIELD) ? 1 : 0; */ printf("Created avi: %s\n", name); return 1; diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index 844407f9e06..0cae9bab531 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -135,7 +135,7 @@ int BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFre BLI_mempool_free(gh->entrypool, e); /* correct but 'e' isn't used before return */ - /* e= n; *//*UNUSED*/ + /* e = n; *//*UNUSED*/ if (p) p->next = n; else gh->buckets[hash] = n; @@ -165,7 +165,7 @@ void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp) BLI_mempool_free(gh->entrypool, e); /* correct but 'e' isn't used before return */ - /* e= n; *//*UNUSED*/ + /* e = n; *//*UNUSED*/ if (p) p->next = n; else gh->buckets[hash] = n; diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c index 7ae27b83e67..2c5e05197ed 100644 --- a/source/blender/blenlib/intern/scanfill.c +++ b/source/blender/blenlib/intern/scanfill.c @@ -662,7 +662,7 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf) if (v1 == v2 || v2 == v3) break; /* printf("test verts %x %x %x\n",v1,v2,v3); */ miny = minf(v1->xy[1], v3->xy[1]); - /* miny= minf(v1->xy[1],v3->xy[1]); */ + /* miny = minf(v1->xy[1],v3->xy[1]); */ sc1 = sc + 1; test = 0; diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c index 2543a1637b2..ac2334e7d8e 100644 --- a/source/blender/blenlib/intern/string_utf8.c +++ b/source/blender/blenlib/intern/string_utf8.c @@ -124,15 +124,15 @@ utf8_error: int BLI_utf8_invalid_strip(char *str, int length) { - int bad_char, tot= 0; + int bad_char, tot = 0; - while ((bad_char= BLI_utf8_invalid_byte(str, length)) != -1) { + while ((bad_char = BLI_utf8_invalid_byte(str, length)) != -1) { str += bad_char; length -= bad_char; if (length == 0) { /* last character bad, strip it */ - *str= '\0'; + *str = '\0'; tot++; break; } @@ -166,9 +166,9 @@ static const size_t utf8_skip_data[256] = { #define BLI_STR_UTF8_CPY(dst, src, maxncpy) \ { \ size_t utf8_size; \ - while (*src != '\0' && (utf8_size= utf8_skip_data[*src]) < maxncpy) { \ + while (*src != '\0' && (utf8_size = utf8_skip_data[*src]) < maxncpy) {\ maxncpy -= utf8_size; \ - switch (utf8_size) { \ + switch (utf8_size) { \ case 6: *dst ++ = *src ++; \ case 5: *dst ++ = *src ++; \ case 4: *dst ++ = *src ++; \ @@ -177,12 +177,12 @@ static const size_t utf8_skip_data[256] = { case 1: *dst ++ = *src ++; \ } \ } \ - *dst= '\0'; \ + *dst = '\0'; \ } (void)0 char *BLI_strncpy_utf8(char *dst, const char *src, size_t maxncpy) { - char *dst_r= dst; + char *dst_r = dst; /* note: currently we don't attempt to deal with invalid utf8 chars */ BLI_STR_UTF8_CPY(dst, src, maxncpy); @@ -266,15 +266,15 @@ size_t BLI_strncpy_wchar_from_utf8(wchar_t *dst_w, const char *src_c, const size } while (*src_c && len < maxcpy) { - size_t step= 0; - unsigned int unicode= BLI_str_utf8_as_unicode_and_size(src_c, &step); + size_t step = 0; + unsigned int unicode = BLI_str_utf8_as_unicode_and_size(src_c, &step); if (unicode != BLI_UTF8_ERR) { - *dst_w= (wchar_t)unicode; + *dst_w = (wchar_t)unicode; src_c += step; } else { *dst_w = '?'; - src_c= BLI_str_find_next_char_utf8(src_c, NULL); + src_c = BLI_str_find_next_char_utf8(src_c, NULL); } dst_w++; len++; @@ -397,13 +397,13 @@ unsigned int BLI_str_utf8_as_unicode_step(const char *p, size_t *index) unsigned char c; p += *index; - c= (unsigned char) *p; + c = (unsigned char) *p; UTF8_COMPUTE (c, mask, len); if (len == -1) { /* when called with NULL end, result will never be NULL, * checks for a NULL character */ - char *p_next= BLI_str_find_next_char_utf8(p, NULL); + char *p_next = BLI_str_find_next_char_utf8(p, NULL); /* will never return the same pointer unless '\0', * eternal loop is prevented */ *index += (size_t)(p_next - p); @@ -420,8 +420,8 @@ unsigned int BLI_str_utf8_as_unicode_step(const char *p, size_t *index) * characters */ UTF8_GET (result, p, i, mask, len, BLI_UTF8_ERR); if (result == BLI_UTF8_ERR) { - len= 1; - result= *p; + len = 1; + result = *p; } /* end warning! */ #else diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt index 1e56314ab6e..3e0985471e1 100644 --- a/source/blender/bmesh/CMakeLists.txt +++ b/source/blender/bmesh/CMakeLists.txt @@ -64,7 +64,7 @@ set(SRC intern/bmesh_construct.h intern/bmesh_core.c intern/bmesh_core.h - intern/bmesh_decimate.c + intern/bmesh_decimate_collapse.c intern/bmesh_decimate.h intern/bmesh_inline.h intern/bmesh_interp.c diff --git a/source/blender/bmesh/intern/bmesh_decimate.c b/source/blender/bmesh/intern/bmesh_decimate.c deleted file mode 100644 index a4be3933a8d..00000000000 --- a/source/blender/bmesh/intern/bmesh_decimate.c +++ /dev/null @@ -1,932 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * 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. - * - * Contributor(s): Campbell Barton - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/bmesh/intern/bmesh_decimate.c - * \ingroup bmesh - * - * BMesh decimator. - */ - -#include - -#include "MEM_guardedalloc.h" - -#include "DNA_scene_types.h" - -#include "BLI_math.h" -#include "BLI_quadric.h" -#include "BLI_heap.h" - -#include "BKE_customdata.h" - -#include "bmesh.h" -#include "bmesh_structure.h" -#include "bmesh_decimate.h" - -/* defines for testing */ -#define USE_CUSTOMDATA -#define USE_TRIANGULATE - -/* these checks are for rare cases that we can't avoid since they are valid meshes still */ -#define USE_SAFETY_CHECKS - -#define BOUNDARY_PRESERVE_WEIGHT 100.0f - -typedef enum CD_UseFlag { - CD_DO_VERT, - CD_DO_EDGE, - CD_DO_LOOP -} CD_UseFlag; - - -/* BMesh Helper Functions - * ********************** */ - -/** - * \param vquadrics must be calloc'd - */ -static void bm_decim_build_quadrics(BMesh *bm, Quadric *vquadrics) -{ - BMIter iter; - BMFace *f; - BMEdge *e; - - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - BMLoop *l_first; - BMLoop *l_iter; - - const float *co = BM_FACE_FIRST_LOOP(f)->v->co; - const float *no = f->no; - const float offset = -dot_v3v3(no, co); - Quadric q; - - BLI_quadric_from_v3_dist(&q, no, offset); - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(l_iter->v)], &q); - } while ((l_iter = l_iter->next) != l_first); - } - - /* boundary edges */ - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - if (UNLIKELY(BM_edge_is_boundary(e))) { - float edge_vector[3]; - float edge_cross[3]; - sub_v3_v3v3(edge_vector, e->v2->co, e->v1->co); - f = e->l->f; - cross_v3_v3v3(edge_cross, edge_vector, f->no); - - if (fabsf(normalize_v3(edge_cross)) > FLT_EPSILON) { - Quadric q; - BLI_quadric_from_v3_dist(&q, edge_cross, -dot_v3v3(edge_cross, e->v1->co)); - BLI_quadric_mul(&q, BOUNDARY_PRESERVE_WEIGHT); - - BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(e->v1)], &q); - BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(e->v2)], &q); - } - } - } -} - - -static void bm_decim_calc_target_co(BMEdge *e, float optimize_co[3], - const Quadric *vquadrics) -{ - /* compute an edge contration target for edge ei - * this is computed by summing it's vertices quadrics and - * optimizing the result. */ - Quadric q; - - BLI_quadric_add_qu_ququ(&q, - &vquadrics[BM_elem_index_get(e->v1)], - &vquadrics[BM_elem_index_get(e->v2)]); - - - if (BLI_quadric_optimize(&q, optimize_co)) { - return; /* all is good */ - } - else { - mid_v3_v3v3(optimize_co, e->v1->co, e->v2->co); - } -} - -static void bm_decim_build_edge_cost_single(BMEdge *e, - const Quadric *vquadrics, const float *vweights, - Heap *eheap, HeapNode **eheap_table) -{ - const Quadric *q1, *q2; - float optimize_co[3]; - float cost; - - if (eheap_table[BM_elem_index_get(e)]) { - BLI_heap_remove(eheap, eheap_table[BM_elem_index_get(e)]); - } - - /* check we can collapse, some edges we better not touch */ - if (BM_edge_is_boundary(e)) { - if (e->l->f->len == 3) { - /* pass */ - } - else { - /* only collapse tri's */ - eheap_table[BM_elem_index_get(e)] = NULL; - return; - } - } - else if (BM_edge_is_manifold(e)) { - if ((e->l->f->len == 3) && (e->l->radial_next->f->len == 3)) { - /* pass */ - } - else { - /* only collapse tri's */ - eheap_table[BM_elem_index_get(e)] = NULL; - return; - } - } - else { - eheap_table[BM_elem_index_get(e)] = NULL; - return; - } - - if (vweights) { - if ((vweights[BM_elem_index_get(e->v1)] < FLT_EPSILON) && - (vweights[BM_elem_index_get(e->v2)] < FLT_EPSILON)) - { - /* skip collapsing this edge */ - eheap_table[BM_elem_index_get(e)] = NULL; - return; - } - } - /* end sanity check */ - - - bm_decim_calc_target_co(e, optimize_co, vquadrics); - - q1 = &vquadrics[BM_elem_index_get(e->v1)]; - q2 = &vquadrics[BM_elem_index_get(e->v2)]; - - if (vweights == NULL) { - cost = (BLI_quadric_evaluate(q1, optimize_co) + - BLI_quadric_evaluate(q2, optimize_co)); - } - else { - cost = ((BLI_quadric_evaluate(q1, optimize_co) * vweights[BM_elem_index_get(e->v1)]) + - (BLI_quadric_evaluate(q2, optimize_co) * vweights[BM_elem_index_get(e->v2)])); - } - // print("COST %.12f\n"); - - eheap_table[BM_elem_index_get(e)] = BLI_heap_insert(eheap, cost, e); -} - -static void bm_decim_build_edge_cost(BMesh *bm, - const Quadric *vquadrics, const float *vweights, - Heap *eheap, HeapNode **eheap_table) -{ - BMIter iter; - BMEdge *e; - unsigned int i; - - BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) { - eheap_table[i] = NULL; /* keep sanity check happy */ - bm_decim_build_edge_cost_single(e, vquadrics, vweights, eheap, eheap_table); - } -} - -#ifdef USE_TRIANGULATE -/* Temp Triangulation - * ****************** */ - -/** - * To keep things simple we can only collapse edges on triangulated data - * (limitation with edge collapse and error calculation functions). - * - * But to avoid annoying users by only giving triangle results, we can - * triangulate, keeping a reference between the faces, then join after - * if the edges don't collapse, this will also allow more choices when - * collapsing edges so even has some advantage over decimating quads - * directly. - * - * \return TRUE if any faces were triangulated. - */ - -static int bm_decim_triangulate_begin(BMesh *bm) -{ -#ifdef USE_SAFETY_CHECKS - const int check_double_edges = TRUE; -#else - const int check_double_edges = FALSE; -#endif - - BMIter iter; - BMFace *f; - // int has_quad; // could optimize this a little - int has_cut = FALSE; - - BLI_assert((bm->elem_index_dirty & BM_VERT) == 0); - - /* first clear loop index values */ - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - BMLoop *l_iter; - BMLoop *l_first; - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - BM_elem_index_set(l_iter, -1); - } while ((l_iter = l_iter->next) != l_first); - - // has_quad |= (f->len == 4) - } - - /* adding new faces as we loop over faces - * is normally best avoided, however in this case its not so bad because any face touched twice - * will already be triangulated*/ - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - if (f->len == 4) { - BMLoop *f_l[4]; - BMLoop *l_a, *l_b; - - { - BMLoop *l_iter = BM_FACE_FIRST_LOOP(f); - - f_l[0] = l_iter; l_iter = l_iter->next; - f_l[1] = l_iter; l_iter = l_iter->next; - f_l[2] = l_iter; l_iter = l_iter->next; - f_l[3] = l_iter; - } - - if (len_squared_v3v3(f_l[0]->v->co, f_l[2]->v->co) < - len_squared_v3v3(f_l[1]->v->co, f_l[3]->v->co)) - { - l_a = f_l[0]; - l_b = f_l[2]; - } - else { - l_a = f_l[1]; - l_b = f_l[3]; - } - - { - BMFace *f_new; - BMLoop *l_new; - - /* warning, NO_DOUBLE option here isn't handled as nice as it could be - * - if there is a quad that has a free standing edge joining it along - * where we want to split the face, there isnt a good way we can handle this. - * currently that edge will get removed when joining the tris back into a quad. */ - f_new = BM_face_split(bm, f, l_a->v, l_b->v, &l_new, NULL, check_double_edges); - - if (f_new) { - /* the value of this doesn't matter, only that the 2 loops match and have unique values */ - const int f_index = BM_elem_index_get(f); - - /* since we just split theres only ever 2 loops */ - BLI_assert(BM_edge_is_manifold(l_new->e)); - - BM_elem_index_set(l_new, f_index); - BM_elem_index_set(l_new->radial_next, f_index); - - BM_face_normal_update(f); - BM_face_normal_update(f_new); - - has_cut = TRUE; - } - } - } - } - - BLI_assert((bm->elem_index_dirty & BM_VERT) == 0); - - if (has_cut) { - /* now triangulation is done we need to correct index values */ - BM_mesh_elem_index_ensure(bm, BM_EDGE | BM_FACE); - } - - return has_cut; -} - -static void bm_decim_triangulate_end(BMesh *bm) -{ - /* decimation finished, now re-join */ - BMIter iter; - BMEdge *e; - - /* boundary edges */ - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - BMLoop *l_a, *l_b; - if (BM_edge_loop_pair(e, &l_a, &l_b)) { - const int l_a_index = BM_elem_index_get(l_a); - if (l_a_index != -1) { - const int l_b_index = BM_elem_index_get(l_b); - if (l_a_index == l_b_index) { - /* highly unlikely to fail, but prevents possible double-ups */ - if (l_a->f->len == 3 && l_b->f->len == 3) { - BMFace *f[2] = {l_a->f, l_b->f}; - BM_faces_join(bm, f, 2, TRUE); - } - } - } - } - } -} - -#endif /* USE_TRIANGULATE */ - -/* Edge Collapse Functions - * *********************** */ - -#ifdef USE_CUSTOMDATA - -/** - * \param v is the target to merge into. - */ -static void bm_edge_collapse_loop_customdata(BMesh *bm, BMLoop *l, BMVert *v_clear, BMVert *v_other, - const float customdata_fac) -{ - /* these don't need to be updated, since they will get removed when the edge collapses */ - BMLoop *l_clear, *l_other; - const int is_manifold = BM_edge_is_manifold(l->e); - int side; - - /* l defines the vert to collapse into */ - - /* first find the loop of 'v_other' thats attached to the face of 'l' */ - if (l->v == v_clear) { - l_clear = l; - l_other = l->next; - } - else { - l_clear = l->next; - l_other = l; - } - - BLI_assert(l_clear->v == v_clear); - BLI_assert(l_other->v == v_other); - - /* now we have both corners of the face 'l->f' */ - for (side = 0; side < 2; side++) { - int is_seam = FALSE; - void *src[2]; - BMFace *f_exit = is_manifold ? l->radial_next->f : NULL; - BMEdge *e_prev = l->e; - BMLoop *l_first; - BMLoop *l_iter; - float w[2]; - - if (side == 0) { - l_iter = l_first = l_clear; - src[0] = l_clear->head.data; - src[1] = l_other->head.data; - - w[0] = customdata_fac; - w[1] = 1.0f - customdata_fac; - } - else { - l_iter = l_first = l_other; - src[0] = l_other->head.data; - src[1] = l_clear->head.data; - - w[0] = 1.0f - customdata_fac; - w[1] = customdata_fac; - } - - // print_v2("weights", w); - - /* WATCH IT! - should NOT reference (_clear or _other) vars for this while loop */ - - /* walk around the fan using 'e_prev' */ - while (((l_iter = BM_vert_step_fan_loop(l_iter, &e_prev)) != l_first) && (l_iter != NULL)) { - int i; - /* quit once we hit the opposite face, if we have one */ - if (f_exit && UNLIKELY(f_exit == l_iter->f)) { - break; - } - - /* break out unless we find a match */ - is_seam = TRUE; - - /* ok. we have a loop. now be smart with it! */ - for (i = 0; i < bm->ldata.totlayer; i++) { - if (CustomData_layer_has_math(&bm->ldata, i)) { - const int offset = bm->ldata.layers[i].offset; - const int type = bm->ldata.layers[i].type; - void *cd_src, *cd_iter; - - /* todo, make nicer macros for this */ - cd_src = (char *)src[0] + offset; - // cd_dst = (char *)src[1] + offset; // UNUSED - cd_iter = (char *)l_iter->head.data + offset; - - /* detect seams */ - if (CustomData_data_equals(type, cd_src, cd_iter)) { - CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, l_iter->head.data); - is_seam = FALSE; - } - } - } - - if (is_seam) { - break; - } - } - } -} -#endif /* USE_CUSTOMDATA */ - -/** - * Check if the collapse will result in a degenerate mesh, - * that is - duplicate edges or faces. - * - * This situation could be checked for when calculating collapse cost - * however its quite slow and a degenerate collapse could eventuate - * after the cost is calculated, so instead, check just before collapsing. - */ - -static void bm_edge_tag_enable(BMEdge *e) -{ - BM_elem_flag_enable(e->v1, BM_ELEM_TAG); - BM_elem_flag_enable(e->v2, BM_ELEM_TAG); - if (e->l) { - BM_elem_flag_enable(e->l->f, BM_ELEM_TAG); - if (e->l != e->l->radial_next) { - BM_elem_flag_enable(e->l->radial_next->f, BM_ELEM_TAG); - } - } -} - -static void bm_edge_tag_disable(BMEdge *e) -{ - BM_elem_flag_disable(e->v1, BM_ELEM_TAG); - BM_elem_flag_disable(e->v2, BM_ELEM_TAG); - if (e->l) { - BM_elem_flag_disable(e->l->f, BM_ELEM_TAG); - if (e->l != e->l->radial_next) { - BM_elem_flag_disable(e->l->radial_next->f, BM_ELEM_TAG); - } - } -} - -static int bm_edge_tag_test(BMEdge *e) -{ - /* is the edge or one of its faces tagged? */ - return (BM_elem_flag_test(e->v1, BM_ELEM_TAG) || - BM_elem_flag_test(e->v2, BM_ELEM_TAG) || - (e->l && (BM_elem_flag_test(e->l->f, BM_ELEM_TAG) || - (e->l != e->l->radial_next && - BM_elem_flag_test(e->l->radial_next->f, BM_ELEM_TAG)))) - ); -} - -/* takes the edges loop */ -BLI_INLINE int bm_edge_is_manifold_or_boundary(BMLoop *l) -{ -#if 0 - /* less optimized version of check below */ - return (BM_edge_is_manifold(l->e) || BM_edge_is_boundary(l->e); -#else - /* if the edge is a boundary it points to its self, else this must be a manifold */ - return LIKELY(l) && LIKELY(l->radial_next->radial_next == l); -#endif -} - -static int bm_edge_collapse_is_degenerate(BMEdge *e_first) -{ - /* simply check that there is no overlap between faces and edges of each vert, - * (excluding the 2 faces attached to 'e' and 'e' its self) */ - - BMEdge *e_iter; - - /* clear flags on both disks */ - e_iter = e_first; - do { - if (!bm_edge_is_manifold_or_boundary(e_iter->l)) { - return TRUE; - } - bm_edge_tag_disable(e_iter); - } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v1)) != e_first); - - e_iter = e_first; - do { - if (!bm_edge_is_manifold_or_boundary(e_iter->l)) { - return TRUE; - } - bm_edge_tag_disable(e_iter); - } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v2)) != e_first); - - /* now enable one side... */ - e_iter = e_first; - do { - bm_edge_tag_enable(e_iter); - } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v1)) != e_first); - - /* ... except for the edge we will collapse, we know thats shared, - * disable this to avoid false positive. We could be smart and never enable these - * face/edge tags in the first place but easier to do this */ - // bm_edge_tag_disable(e_first); - /* do inline... */ - { -#if 0 - BMIter iter; - BMIter liter; - BMLoop *l; - BMVert *v; - BM_ITER_ELEM (l, &liter, e_first, BM_LOOPS_OF_EDGE) { - BM_elem_flag_disable(l->f, BM_ELEM_TAG); - BM_ITER_ELEM (v, &iter, l->f, BM_VERTS_OF_FACE) { - BM_elem_flag_disable(v, BM_ELEM_TAG); - } - } -#else - /* we know each face is a triangle, no looping/iterators needed here */ - - BMLoop *l_radial; - BMLoop *l_face; - - l_radial = e_first->l; - l_face = l_radial; - BLI_assert(l_face->f->len == 3); - BM_elem_flag_disable(l_face->f, BM_ELEM_TAG); - BM_elem_flag_disable((l_face = l_radial)->v, BM_ELEM_TAG); - BM_elem_flag_disable((l_face = l_face->next)->v, BM_ELEM_TAG); - BM_elem_flag_disable(( l_face->next)->v, BM_ELEM_TAG); - l_face = l_radial->radial_next; - if (l_radial != l_face) { - BLI_assert(l_face->f->len == 3); - BM_elem_flag_disable(l_face->f, BM_ELEM_TAG); - BM_elem_flag_disable((l_face = l_radial->radial_next)->v, BM_ELEM_TAG); - BM_elem_flag_disable((l_face = l_face->next)->v, BM_ELEM_TAG); - BM_elem_flag_disable(( l_face->next)->v, BM_ELEM_TAG); - } -#endif - } - - /* and check for overlap */ - e_iter = e_first; - do { - if (bm_edge_tag_test(e_iter)) { - return TRUE; - } - } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v2)) != e_first); - - return FALSE; -} - -/** - * special, highly limited edge collapse function - * intended for speed over flexibiliy. - * can only collapse edges connected to (1, 2) tris. - * - * Important - dont add vert/edge/face data on collapsing! - * - * \param e_clear_other let caller know what edges we remove besides \a e_clear - * \param customdata_flag merge factor, scales from 0 - 1 ('v_clear' -> 'v_other') - */ -static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e_clear_other[2], -#ifdef USE_CUSTOMDATA - const CD_UseFlag customdata_flag, - const float customdata_fac -#else - const CD_UseFlag UNUSED(customdata_flag), - const float UNUSED(customdata_fac) -#endif - ) -{ - BMVert *v_other; - - /* disallow collapsing which results in degenerate cases */ - if (bm_edge_collapse_is_degenerate(e_clear)) { - return FALSE; - } - - v_other = BM_edge_other_vert(e_clear, v_clear); - BLI_assert(v_other != NULL); - - if (BM_edge_is_manifold(e_clear)) { - BMLoop *l_a, *l_b; - BMEdge *e_a_other[2], *e_b_other[2]; - int ok; - - ok = BM_edge_loop_pair(e_clear, &l_a, &l_b); - - BLI_assert(ok == TRUE); - BLI_assert(l_a->f->len == 3); - BLI_assert(l_b->f->len == 3); - - /* keep 'v_clear' 0th */ - if (BM_vert_in_edge(l_a->prev->e, v_clear)) { - e_a_other[0] = l_a->prev->e; - e_a_other[1] = l_a->next->e; - } - else { - e_a_other[1] = l_a->prev->e; - e_a_other[0] = l_a->next->e; - } - - if (BM_vert_in_edge(l_b->prev->e, v_clear)) { - e_b_other[0] = l_b->prev->e; - e_b_other[1] = l_b->next->e; - } - else { - e_b_other[1] = l_b->prev->e; - e_b_other[0] = l_b->next->e; - } - - BLI_assert(BM_edge_share_vert(e_a_other[0], e_b_other[0])); - BLI_assert(BM_edge_share_vert(e_a_other[1], e_b_other[1])); - - /* we could assert this case, but better just bail out */ -#if 0 - BLI_assert(e_a_other[0] != e_b_other[0]); - BLI_assert(e_a_other[0] != e_b_other[1]); - BLI_assert(e_b_other[0] != e_a_other[0]); - BLI_assert(e_b_other[0] != e_a_other[1]); -#endif - /* not totally common but we want to avoid */ - if (ELEM(e_a_other[0], e_b_other[0], e_b_other[1]) || - ELEM(e_a_other[1], e_b_other[0], e_b_other[1])) - { - return FALSE; - } - - r_e_clear_other[0] = BM_elem_index_get(e_a_other[0]); - r_e_clear_other[1] = BM_elem_index_get(e_b_other[0]); - -#ifdef USE_CUSTOMDATA - /* before killing, do customdata */ - if (customdata_flag & CD_DO_VERT) { - BM_data_interp_from_verts(bm, v_other, v_clear, v_other, customdata_fac); - } - if (customdata_flag & CD_DO_EDGE) { - BM_data_interp_from_edges(bm, e_a_other[1], e_a_other[0], e_a_other[1], customdata_fac); - BM_data_interp_from_edges(bm, e_b_other[1], e_b_other[0], e_b_other[1], customdata_fac); - } - if (customdata_flag & CD_DO_LOOP) { - bm_edge_collapse_loop_customdata(bm, e_clear->l, v_clear, v_other, customdata_fac); - bm_edge_collapse_loop_customdata(bm, e_clear->l->radial_next, v_clear, v_other, customdata_fac); - } -#endif - - BM_edge_kill(bm, e_clear); - - BM_vert_splice(bm, v_clear, v_other); - - BM_edge_splice(bm, e_a_other[0], e_a_other[1]); - BM_edge_splice(bm, e_b_other[0], e_b_other[1]); - - // BM_mesh_validate(bm); - - return TRUE; - } - else if (BM_edge_is_boundary(e_clear)) { - /* same as above but only one triangle */ - BMLoop *l_a; - BMEdge *e_a_other[2]; - - l_a = e_clear->l; - - BLI_assert(l_a->f->len == 3); - - /* keep 'v_clear' 0th */ - if (BM_vert_in_edge(l_a->prev->e, v_clear)) { - e_a_other[0] = l_a->prev->e; - e_a_other[1] = l_a->next->e; - } - else { - e_a_other[1] = l_a->prev->e; - e_a_other[0] = l_a->next->e; - } - - r_e_clear_other[0] = BM_elem_index_get(e_a_other[0]); - r_e_clear_other[1] = -1; - -#ifdef USE_CUSTOMDATA - /* before killing, do customdata */ - if (customdata_flag & CD_DO_VERT) { - BM_data_interp_from_verts(bm, v_other, v_clear, v_other, customdata_fac); - } - if (customdata_flag & CD_DO_EDGE) { - BM_data_interp_from_edges(bm, e_a_other[1], e_a_other[0], e_a_other[1], customdata_fac); - } - if (customdata_flag & CD_DO_LOOP) { - bm_edge_collapse_loop_customdata(bm, e_clear->l, v_clear, v_other, customdata_fac); - } -#endif - - BM_edge_kill(bm, e_clear); - - BM_vert_splice(bm, v_clear, v_other); - - BM_edge_splice(bm, e_a_other[0], e_a_other[1]); - - // BM_mesh_validate(bm); - - return TRUE; - } - else { - return FALSE; - } -} - - -/* collapse e the edge, removing e->v2 */ -static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, - Quadric *vquadrics, float *vweights, - Heap *eheap, HeapNode **eheap_table, - const CD_UseFlag customdata_flag) -{ - int e_clear_other[2]; - BMVert *v_other = e->v1; - int v_clear_index = BM_elem_index_get(e->v2); /* the vert is removed so only store the index */ - float optimize_co[3]; - float customdata_fac; - - bm_decim_calc_target_co(e, optimize_co, vquadrics); - - /* use for customdata merging */ - if (LIKELY(compare_v3v3(e->v1->co, e->v2->co, FLT_EPSILON) == FALSE)) { - customdata_fac = line_point_factor_v3(optimize_co, e->v1->co, e->v2->co); - -#if 0 - /* simple test for stupid collapse */ - if (customdata_fac < 0.0 - FLT_EPSILON || customdata_fac > 1.0f + FLT_EPSILON) { - return; - } -#endif - } - else { - /* avoid divide by zero */ - customdata_fac = 0.5f; - } - - if (bm_edge_collapse(bm, e, e->v2, e_clear_other, customdata_flag, customdata_fac)) { - /* update collapse info */ - int i; - - if (vweights) { - const int fac = CLAMPIS(customdata_fac, 0.0f, 1.0f); - vweights[BM_elem_index_get(v_other)] = (vweights[v_clear_index] * (1.0f - fac)) + - (vweights[BM_elem_index_get(v_other)] * fac); - } - - e = NULL; /* paranoid safety check */ - - copy_v3_v3(v_other->co, optimize_co); - - /* remove eheap */ - for (i = 0; i < 2; i++) { - /* highly unlikely 'eheap_table[ke_other[i]]' would be NULL, but do for sanity sake */ - if ((e_clear_other[i] != -1) && (eheap_table[e_clear_other[i]] != NULL)) { - BLI_heap_remove(eheap, eheap_table[e_clear_other[i]]); - eheap_table[e_clear_other[i]] = NULL; - } - } - - /* update vertex quadric, add kept vertex from killed vertex */ - BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(v_other)], &vquadrics[v_clear_index]); - - /* update connected normals */ - - /* in fact face normals are not used for progressive updates, no need to update them */ - // BM_vert_normal_update_all(v); - BM_vert_normal_update(v_other); - - /* update error costs and the eheap */ - if (LIKELY(v_other->e)) { - BMEdge *e_iter; - BMEdge *e_first; - e_iter = e_first = v_other->e; - do { - BLI_assert(BM_edge_find_double(e_iter) == NULL); - bm_decim_build_edge_cost_single(e_iter, vquadrics, vweights, eheap, eheap_table); - } while ((e_iter = bmesh_disk_edge_next(e_iter, v_other)) != e_first); - } - -#if 0 - /* optional, update edges around the vertex face fan */ - { - BMIter liter; - BMLoop *l; - BM_ITER_ELEM (l, &liter, v_other, BM_LOOPS_OF_VERT) { - if (l->f->len == 3) { - BMEdge *e_outer; - if (BM_vert_in_edge(l->prev->e, l->v)) - e_outer = l->next->e; - else - e_outer = l->prev->e; - - BLI_assert(BM_vert_in_edge(e_outer, l->v) == FALSE); - - bm_decim_build_edge_cost_single(e_outer, vquadrics, eheap, eheap_table); - } - } - } - /* end optional update */ -#endif - } -} - - -/* Main Decimate Function - * ********************** */ - -/** - * \brief BM_mesh_decimate - * \param bm The mesh - * \param factor face count multiplier [0 - 1] - * \param vertex_weights Optional array of vertex aligned weights [0 - 1], - * a vertex group is the usual source for this. - */ -void BM_mesh_decimate(BMesh *bm, const float factor, float *vweights) -{ - Heap *eheap; /* edge heap */ - HeapNode **eheap_table; /* edge index aligned table pointing to the eheap */ - Quadric *vquadrics; /* vert index aligned quadrics */ - int tot_edge_orig; - int face_tot_target; - int use_triangulate; - - CD_UseFlag customdata_flag = 0; - -#ifdef USE_TRIANGULATE - /* temp convert quads to triangles */ - use_triangulate = bm_decim_triangulate_begin(bm); -#endif - - - /* alloc vars */ - vquadrics = MEM_callocN(sizeof(Quadric) * bm->totvert, __func__); - /* since some edges may be degenerate, we might be over allocing a little here */ - eheap = BLI_heap_new_ex(bm->totedge); - eheap_table = MEM_callocN(sizeof(HeapNode *) * bm->totedge, __func__); - tot_edge_orig = bm->totedge; - - - /* build initial edge collapse cost data */ - bm_decim_build_quadrics(bm, vquadrics); - - bm_decim_build_edge_cost(bm, vquadrics, vweights, eheap, eheap_table); - - face_tot_target = bm->totface * factor; - bm->elem_index_dirty |= BM_FACE | BM_EDGE | BM_VERT; - - -#ifdef USE_CUSTOMDATA - /* initialize customdata flag, we only need math for loops */ - if (CustomData_has_interp(&bm->vdata)) customdata_flag |= CD_DO_VERT; - if (CustomData_has_interp(&bm->edata)) customdata_flag |= CD_DO_EDGE; - if (CustomData_has_math(&bm->ldata)) customdata_flag |= CD_DO_LOOP; -#endif - - /* iterative edge collapse and maintain the eheap */ - while ((bm->totface > face_tot_target) && (BLI_heap_is_empty(eheap) == FALSE)) { - // const float value = BLI_heap_node_value(BLI_heap_top(eheap)); - BMEdge *e = BLI_heap_popmin(eheap); - BLI_assert(BM_elem_index_get(e) < tot_edge_orig); /* handy to detect corruptions elsewhere */ - - // printf("COST %.10f\n", value); - - /* under normal conditions wont be accessed again, - * but NULL just incase so we don't use freed node */ - eheap_table[BM_elem_index_get(e)] = NULL; - - bm_decim_edge_collapse(bm, e, vquadrics, vweights, eheap, eheap_table, customdata_flag); - } - - -#ifdef USE_TRIANGULATE - /* its possible we only had triangles, skip this step in that case */ - if (LIKELY(use_triangulate)) { - /* temp convert quads to triangles */ - bm_decim_triangulate_end(bm); - } -#endif - - /* free vars */ - MEM_freeN(vquadrics); - MEM_freeN(eheap_table); - BLI_heap_free(eheap, NULL); - - /* testing only */ - // BM_mesh_validate(bm); - - (void)tot_edge_orig; /* quiet release build warning */ -} diff --git a/source/blender/bmesh/intern/bmesh_decimate.h b/source/blender/bmesh/intern/bmesh_decimate.h index 1724bbd16bb..7fafb752e1e 100644 --- a/source/blender/bmesh/intern/bmesh_decimate.h +++ b/source/blender/bmesh/intern/bmesh_decimate.h @@ -27,6 +27,6 @@ * \ingroup bmesh */ -void BM_mesh_decimate(BMesh *bm, const float factor, float *vweights); +void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights); #endif /* __BMESH_DECIMATE_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_decimate_collapse.c b/source/blender/bmesh/intern/bmesh_decimate_collapse.c new file mode 100644 index 00000000000..75fe12a418a --- /dev/null +++ b/source/blender/bmesh/intern/bmesh_decimate_collapse.c @@ -0,0 +1,932 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/bmesh/intern/bmesh_decimate.c + * \ingroup bmesh + * + * BMesh decimator. + */ + +#include + +#include "MEM_guardedalloc.h" + +#include "DNA_scene_types.h" + +#include "BLI_math.h" +#include "BLI_quadric.h" +#include "BLI_heap.h" + +#include "BKE_customdata.h" + +#include "bmesh.h" +#include "bmesh_structure.h" +#include "bmesh_decimate.h" /* own include */ + +/* defines for testing */ +#define USE_CUSTOMDATA +#define USE_TRIANGULATE + +/* these checks are for rare cases that we can't avoid since they are valid meshes still */ +#define USE_SAFETY_CHECKS + +#define BOUNDARY_PRESERVE_WEIGHT 100.0f + +typedef enum CD_UseFlag { + CD_DO_VERT, + CD_DO_EDGE, + CD_DO_LOOP +} CD_UseFlag; + + +/* BMesh Helper Functions + * ********************** */ + +/** + * \param vquadrics must be calloc'd + */ +static void bm_decim_build_quadrics(BMesh *bm, Quadric *vquadrics) +{ + BMIter iter; + BMFace *f; + BMEdge *e; + + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + BMLoop *l_first; + BMLoop *l_iter; + + const float *co = BM_FACE_FIRST_LOOP(f)->v->co; + const float *no = f->no; + const float offset = -dot_v3v3(no, co); + Quadric q; + + BLI_quadric_from_v3_dist(&q, no, offset); + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(l_iter->v)], &q); + } while ((l_iter = l_iter->next) != l_first); + } + + /* boundary edges */ + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + if (UNLIKELY(BM_edge_is_boundary(e))) { + float edge_vector[3]; + float edge_cross[3]; + sub_v3_v3v3(edge_vector, e->v2->co, e->v1->co); + f = e->l->f; + cross_v3_v3v3(edge_cross, edge_vector, f->no); + + if (fabsf(normalize_v3(edge_cross)) > FLT_EPSILON) { + Quadric q; + BLI_quadric_from_v3_dist(&q, edge_cross, -dot_v3v3(edge_cross, e->v1->co)); + BLI_quadric_mul(&q, BOUNDARY_PRESERVE_WEIGHT); + + BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(e->v1)], &q); + BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(e->v2)], &q); + } + } + } +} + + +static void bm_decim_calc_target_co(BMEdge *e, float optimize_co[3], + const Quadric *vquadrics) +{ + /* compute an edge contration target for edge 'e' + * this is computed by summing it's vertices quadrics and + * optimizing the result. */ + Quadric q; + + BLI_quadric_add_qu_ququ(&q, + &vquadrics[BM_elem_index_get(e->v1)], + &vquadrics[BM_elem_index_get(e->v2)]); + + + if (BLI_quadric_optimize(&q, optimize_co)) { + return; /* all is good */ + } + else { + mid_v3_v3v3(optimize_co, e->v1->co, e->v2->co); + } +} + +static void bm_decim_build_edge_cost_single(BMEdge *e, + const Quadric *vquadrics, const float *vweights, + Heap *eheap, HeapNode **eheap_table) +{ + const Quadric *q1, *q2; + float optimize_co[3]; + float cost; + + if (eheap_table[BM_elem_index_get(e)]) { + BLI_heap_remove(eheap, eheap_table[BM_elem_index_get(e)]); + } + + /* check we can collapse, some edges we better not touch */ + if (BM_edge_is_boundary(e)) { + if (e->l->f->len == 3) { + /* pass */ + } + else { + /* only collapse tri's */ + eheap_table[BM_elem_index_get(e)] = NULL; + return; + } + } + else if (BM_edge_is_manifold(e)) { + if ((e->l->f->len == 3) && (e->l->radial_next->f->len == 3)) { + /* pass */ + } + else { + /* only collapse tri's */ + eheap_table[BM_elem_index_get(e)] = NULL; + return; + } + } + else { + eheap_table[BM_elem_index_get(e)] = NULL; + return; + } + + if (vweights) { + if ((vweights[BM_elem_index_get(e->v1)] < FLT_EPSILON) && + (vweights[BM_elem_index_get(e->v2)] < FLT_EPSILON)) + { + /* skip collapsing this edge */ + eheap_table[BM_elem_index_get(e)] = NULL; + return; + } + } + /* end sanity check */ + + + bm_decim_calc_target_co(e, optimize_co, vquadrics); + + q1 = &vquadrics[BM_elem_index_get(e->v1)]; + q2 = &vquadrics[BM_elem_index_get(e->v2)]; + + if (vweights == NULL) { + cost = (BLI_quadric_evaluate(q1, optimize_co) + + BLI_quadric_evaluate(q2, optimize_co)); + } + else { + cost = ((BLI_quadric_evaluate(q1, optimize_co) * vweights[BM_elem_index_get(e->v1)]) + + (BLI_quadric_evaluate(q2, optimize_co) * vweights[BM_elem_index_get(e->v2)])); + } + // print("COST %.12f\n"); + + eheap_table[BM_elem_index_get(e)] = BLI_heap_insert(eheap, cost, e); +} + +static void bm_decim_build_edge_cost(BMesh *bm, + const Quadric *vquadrics, const float *vweights, + Heap *eheap, HeapNode **eheap_table) +{ + BMIter iter; + BMEdge *e; + unsigned int i; + + BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) { + eheap_table[i] = NULL; /* keep sanity check happy */ + bm_decim_build_edge_cost_single(e, vquadrics, vweights, eheap, eheap_table); + } +} + +#ifdef USE_TRIANGULATE +/* Temp Triangulation + * ****************** */ + +/** + * To keep things simple we can only collapse edges on triangulated data + * (limitation with edge collapse and error calculation functions). + * + * But to avoid annoying users by only giving triangle results, we can + * triangulate, keeping a reference between the faces, then join after + * if the edges don't collapse, this will also allow more choices when + * collapsing edges so even has some advantage over decimating quads + * directly. + * + * \return TRUE if any faces were triangulated. + */ + +static int bm_decim_triangulate_begin(BMesh *bm) +{ +#ifdef USE_SAFETY_CHECKS + const int check_double_edges = TRUE; +#else + const int check_double_edges = FALSE; +#endif + + BMIter iter; + BMFace *f; + // int has_quad; // could optimize this a little + int has_cut = FALSE; + + BLI_assert((bm->elem_index_dirty & BM_VERT) == 0); + + /* first clear loop index values */ + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + BMLoop *l_iter; + BMLoop *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + BM_elem_index_set(l_iter, -1); + } while ((l_iter = l_iter->next) != l_first); + + // has_quad |= (f->len == 4) + } + + /* adding new faces as we loop over faces + * is normally best avoided, however in this case its not so bad because any face touched twice + * will already be triangulated*/ + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + if (f->len == 4) { + BMLoop *f_l[4]; + BMLoop *l_a, *l_b; + + { + BMLoop *l_iter = BM_FACE_FIRST_LOOP(f); + + f_l[0] = l_iter; l_iter = l_iter->next; + f_l[1] = l_iter; l_iter = l_iter->next; + f_l[2] = l_iter; l_iter = l_iter->next; + f_l[3] = l_iter; + } + + if (len_squared_v3v3(f_l[0]->v->co, f_l[2]->v->co) < + len_squared_v3v3(f_l[1]->v->co, f_l[3]->v->co)) + { + l_a = f_l[0]; + l_b = f_l[2]; + } + else { + l_a = f_l[1]; + l_b = f_l[3]; + } + + { + BMFace *f_new; + BMLoop *l_new; + + /* warning, NO_DOUBLE option here isn't handled as nice as it could be + * - if there is a quad that has a free standing edge joining it along + * where we want to split the face, there isnt a good way we can handle this. + * currently that edge will get removed when joining the tris back into a quad. */ + f_new = BM_face_split(bm, f, l_a->v, l_b->v, &l_new, NULL, check_double_edges); + + if (f_new) { + /* the value of this doesn't matter, only that the 2 loops match and have unique values */ + const int f_index = BM_elem_index_get(f); + + /* since we just split theres only ever 2 loops */ + BLI_assert(BM_edge_is_manifold(l_new->e)); + + BM_elem_index_set(l_new, f_index); + BM_elem_index_set(l_new->radial_next, f_index); + + BM_face_normal_update(f); + BM_face_normal_update(f_new); + + has_cut = TRUE; + } + } + } + } + + BLI_assert((bm->elem_index_dirty & BM_VERT) == 0); + + if (has_cut) { + /* now triangulation is done we need to correct index values */ + BM_mesh_elem_index_ensure(bm, BM_EDGE | BM_FACE); + } + + return has_cut; +} + +static void bm_decim_triangulate_end(BMesh *bm) +{ + /* decimation finished, now re-join */ + BMIter iter; + BMEdge *e; + + /* boundary edges */ + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + BMLoop *l_a, *l_b; + if (BM_edge_loop_pair(e, &l_a, &l_b)) { + const int l_a_index = BM_elem_index_get(l_a); + if (l_a_index != -1) { + const int l_b_index = BM_elem_index_get(l_b); + if (l_a_index == l_b_index) { + /* highly unlikely to fail, but prevents possible double-ups */ + if (l_a->f->len == 3 && l_b->f->len == 3) { + BMFace *f[2] = {l_a->f, l_b->f}; + BM_faces_join(bm, f, 2, TRUE); + } + } + } + } + } +} + +#endif /* USE_TRIANGULATE */ + +/* Edge Collapse Functions + * *********************** */ + +#ifdef USE_CUSTOMDATA + +/** + * \param v is the target to merge into. + */ +static void bm_edge_collapse_loop_customdata(BMesh *bm, BMLoop *l, BMVert *v_clear, BMVert *v_other, + const float customdata_fac) +{ + /* these don't need to be updated, since they will get removed when the edge collapses */ + BMLoop *l_clear, *l_other; + const int is_manifold = BM_edge_is_manifold(l->e); + int side; + + /* l defines the vert to collapse into */ + + /* first find the loop of 'v_other' thats attached to the face of 'l' */ + if (l->v == v_clear) { + l_clear = l; + l_other = l->next; + } + else { + l_clear = l->next; + l_other = l; + } + + BLI_assert(l_clear->v == v_clear); + BLI_assert(l_other->v == v_other); + + /* now we have both corners of the face 'l->f' */ + for (side = 0; side < 2; side++) { + int is_seam = FALSE; + void *src[2]; + BMFace *f_exit = is_manifold ? l->radial_next->f : NULL; + BMEdge *e_prev = l->e; + BMLoop *l_first; + BMLoop *l_iter; + float w[2]; + + if (side == 0) { + l_iter = l_first = l_clear; + src[0] = l_clear->head.data; + src[1] = l_other->head.data; + + w[0] = customdata_fac; + w[1] = 1.0f - customdata_fac; + } + else { + l_iter = l_first = l_other; + src[0] = l_other->head.data; + src[1] = l_clear->head.data; + + w[0] = 1.0f - customdata_fac; + w[1] = customdata_fac; + } + + // print_v2("weights", w); + + /* WATCH IT! - should NOT reference (_clear or _other) vars for this while loop */ + + /* walk around the fan using 'e_prev' */ + while (((l_iter = BM_vert_step_fan_loop(l_iter, &e_prev)) != l_first) && (l_iter != NULL)) { + int i; + /* quit once we hit the opposite face, if we have one */ + if (f_exit && UNLIKELY(f_exit == l_iter->f)) { + break; + } + + /* break out unless we find a match */ + is_seam = TRUE; + + /* ok. we have a loop. now be smart with it! */ + for (i = 0; i < bm->ldata.totlayer; i++) { + if (CustomData_layer_has_math(&bm->ldata, i)) { + const int offset = bm->ldata.layers[i].offset; + const int type = bm->ldata.layers[i].type; + void *cd_src, *cd_iter; + + /* todo, make nicer macros for this */ + cd_src = (char *)src[0] + offset; + // cd_dst = (char *)src[1] + offset; // UNUSED + cd_iter = (char *)l_iter->head.data + offset; + + /* detect seams */ + if (CustomData_data_equals(type, cd_src, cd_iter)) { + CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, l_iter->head.data); + is_seam = FALSE; + } + } + } + + if (is_seam) { + break; + } + } + } +} +#endif /* USE_CUSTOMDATA */ + +/** + * Check if the collapse will result in a degenerate mesh, + * that is - duplicate edges or faces. + * + * This situation could be checked for when calculating collapse cost + * however its quite slow and a degenerate collapse could eventuate + * after the cost is calculated, so instead, check just before collapsing. + */ + +static void bm_edge_tag_enable(BMEdge *e) +{ + BM_elem_flag_enable(e->v1, BM_ELEM_TAG); + BM_elem_flag_enable(e->v2, BM_ELEM_TAG); + if (e->l) { + BM_elem_flag_enable(e->l->f, BM_ELEM_TAG); + if (e->l != e->l->radial_next) { + BM_elem_flag_enable(e->l->radial_next->f, BM_ELEM_TAG); + } + } +} + +static void bm_edge_tag_disable(BMEdge *e) +{ + BM_elem_flag_disable(e->v1, BM_ELEM_TAG); + BM_elem_flag_disable(e->v2, BM_ELEM_TAG); + if (e->l) { + BM_elem_flag_disable(e->l->f, BM_ELEM_TAG); + if (e->l != e->l->radial_next) { + BM_elem_flag_disable(e->l->radial_next->f, BM_ELEM_TAG); + } + } +} + +static int bm_edge_tag_test(BMEdge *e) +{ + /* is the edge or one of its faces tagged? */ + return (BM_elem_flag_test(e->v1, BM_ELEM_TAG) || + BM_elem_flag_test(e->v2, BM_ELEM_TAG) || + (e->l && (BM_elem_flag_test(e->l->f, BM_ELEM_TAG) || + (e->l != e->l->radial_next && + BM_elem_flag_test(e->l->radial_next->f, BM_ELEM_TAG)))) + ); +} + +/* takes the edges loop */ +BLI_INLINE int bm_edge_is_manifold_or_boundary(BMLoop *l) +{ +#if 0 + /* less optimized version of check below */ + return (BM_edge_is_manifold(l->e) || BM_edge_is_boundary(l->e); +#else + /* if the edge is a boundary it points to its self, else this must be a manifold */ + return LIKELY(l) && LIKELY(l->radial_next->radial_next == l); +#endif +} + +static int bm_edge_collapse_is_degenerate(BMEdge *e_first) +{ + /* simply check that there is no overlap between faces and edges of each vert, + * (excluding the 2 faces attached to 'e' and 'e' its self) */ + + BMEdge *e_iter; + + /* clear flags on both disks */ + e_iter = e_first; + do { + if (!bm_edge_is_manifold_or_boundary(e_iter->l)) { + return TRUE; + } + bm_edge_tag_disable(e_iter); + } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v1)) != e_first); + + e_iter = e_first; + do { + if (!bm_edge_is_manifold_or_boundary(e_iter->l)) { + return TRUE; + } + bm_edge_tag_disable(e_iter); + } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v2)) != e_first); + + /* now enable one side... */ + e_iter = e_first; + do { + bm_edge_tag_enable(e_iter); + } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v1)) != e_first); + + /* ... except for the edge we will collapse, we know thats shared, + * disable this to avoid false positive. We could be smart and never enable these + * face/edge tags in the first place but easier to do this */ + // bm_edge_tag_disable(e_first); + /* do inline... */ + { +#if 0 + BMIter iter; + BMIter liter; + BMLoop *l; + BMVert *v; + BM_ITER_ELEM (l, &liter, e_first, BM_LOOPS_OF_EDGE) { + BM_elem_flag_disable(l->f, BM_ELEM_TAG); + BM_ITER_ELEM (v, &iter, l->f, BM_VERTS_OF_FACE) { + BM_elem_flag_disable(v, BM_ELEM_TAG); + } + } +#else + /* we know each face is a triangle, no looping/iterators needed here */ + + BMLoop *l_radial; + BMLoop *l_face; + + l_radial = e_first->l; + l_face = l_radial; + BLI_assert(l_face->f->len == 3); + BM_elem_flag_disable(l_face->f, BM_ELEM_TAG); + BM_elem_flag_disable((l_face = l_radial)->v, BM_ELEM_TAG); + BM_elem_flag_disable((l_face = l_face->next)->v, BM_ELEM_TAG); + BM_elem_flag_disable(( l_face->next)->v, BM_ELEM_TAG); + l_face = l_radial->radial_next; + if (l_radial != l_face) { + BLI_assert(l_face->f->len == 3); + BM_elem_flag_disable(l_face->f, BM_ELEM_TAG); + BM_elem_flag_disable((l_face = l_radial->radial_next)->v, BM_ELEM_TAG); + BM_elem_flag_disable((l_face = l_face->next)->v, BM_ELEM_TAG); + BM_elem_flag_disable(( l_face->next)->v, BM_ELEM_TAG); + } +#endif + } + + /* and check for overlap */ + e_iter = e_first; + do { + if (bm_edge_tag_test(e_iter)) { + return TRUE; + } + } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v2)) != e_first); + + return FALSE; +} + +/** + * special, highly limited edge collapse function + * intended for speed over flexibiliy. + * can only collapse edges connected to (1, 2) tris. + * + * Important - dont add vert/edge/face data on collapsing! + * + * \param e_clear_other let caller know what edges we remove besides \a e_clear + * \param customdata_flag merge factor, scales from 0 - 1 ('v_clear' -> 'v_other') + */ +static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e_clear_other[2], +#ifdef USE_CUSTOMDATA + const CD_UseFlag customdata_flag, + const float customdata_fac +#else + const CD_UseFlag UNUSED(customdata_flag), + const float UNUSED(customdata_fac) +#endif + ) +{ + BMVert *v_other; + + /* disallow collapsing which results in degenerate cases */ + if (bm_edge_collapse_is_degenerate(e_clear)) { + return FALSE; + } + + v_other = BM_edge_other_vert(e_clear, v_clear); + BLI_assert(v_other != NULL); + + if (BM_edge_is_manifold(e_clear)) { + BMLoop *l_a, *l_b; + BMEdge *e_a_other[2], *e_b_other[2]; + int ok; + + ok = BM_edge_loop_pair(e_clear, &l_a, &l_b); + + BLI_assert(ok == TRUE); + BLI_assert(l_a->f->len == 3); + BLI_assert(l_b->f->len == 3); + + /* keep 'v_clear' 0th */ + if (BM_vert_in_edge(l_a->prev->e, v_clear)) { + e_a_other[0] = l_a->prev->e; + e_a_other[1] = l_a->next->e; + } + else { + e_a_other[1] = l_a->prev->e; + e_a_other[0] = l_a->next->e; + } + + if (BM_vert_in_edge(l_b->prev->e, v_clear)) { + e_b_other[0] = l_b->prev->e; + e_b_other[1] = l_b->next->e; + } + else { + e_b_other[1] = l_b->prev->e; + e_b_other[0] = l_b->next->e; + } + + BLI_assert(BM_edge_share_vert(e_a_other[0], e_b_other[0])); + BLI_assert(BM_edge_share_vert(e_a_other[1], e_b_other[1])); + + /* we could assert this case, but better just bail out */ +#if 0 + BLI_assert(e_a_other[0] != e_b_other[0]); + BLI_assert(e_a_other[0] != e_b_other[1]); + BLI_assert(e_b_other[0] != e_a_other[0]); + BLI_assert(e_b_other[0] != e_a_other[1]); +#endif + /* not totally common but we want to avoid */ + if (ELEM(e_a_other[0], e_b_other[0], e_b_other[1]) || + ELEM(e_a_other[1], e_b_other[0], e_b_other[1])) + { + return FALSE; + } + + r_e_clear_other[0] = BM_elem_index_get(e_a_other[0]); + r_e_clear_other[1] = BM_elem_index_get(e_b_other[0]); + +#ifdef USE_CUSTOMDATA + /* before killing, do customdata */ + if (customdata_flag & CD_DO_VERT) { + BM_data_interp_from_verts(bm, v_other, v_clear, v_other, customdata_fac); + } + if (customdata_flag & CD_DO_EDGE) { + BM_data_interp_from_edges(bm, e_a_other[1], e_a_other[0], e_a_other[1], customdata_fac); + BM_data_interp_from_edges(bm, e_b_other[1], e_b_other[0], e_b_other[1], customdata_fac); + } + if (customdata_flag & CD_DO_LOOP) { + bm_edge_collapse_loop_customdata(bm, e_clear->l, v_clear, v_other, customdata_fac); + bm_edge_collapse_loop_customdata(bm, e_clear->l->radial_next, v_clear, v_other, customdata_fac); + } +#endif + + BM_edge_kill(bm, e_clear); + + BM_vert_splice(bm, v_clear, v_other); + + BM_edge_splice(bm, e_a_other[0], e_a_other[1]); + BM_edge_splice(bm, e_b_other[0], e_b_other[1]); + + // BM_mesh_validate(bm); + + return TRUE; + } + else if (BM_edge_is_boundary(e_clear)) { + /* same as above but only one triangle */ + BMLoop *l_a; + BMEdge *e_a_other[2]; + + l_a = e_clear->l; + + BLI_assert(l_a->f->len == 3); + + /* keep 'v_clear' 0th */ + if (BM_vert_in_edge(l_a->prev->e, v_clear)) { + e_a_other[0] = l_a->prev->e; + e_a_other[1] = l_a->next->e; + } + else { + e_a_other[1] = l_a->prev->e; + e_a_other[0] = l_a->next->e; + } + + r_e_clear_other[0] = BM_elem_index_get(e_a_other[0]); + r_e_clear_other[1] = -1; + +#ifdef USE_CUSTOMDATA + /* before killing, do customdata */ + if (customdata_flag & CD_DO_VERT) { + BM_data_interp_from_verts(bm, v_other, v_clear, v_other, customdata_fac); + } + if (customdata_flag & CD_DO_EDGE) { + BM_data_interp_from_edges(bm, e_a_other[1], e_a_other[0], e_a_other[1], customdata_fac); + } + if (customdata_flag & CD_DO_LOOP) { + bm_edge_collapse_loop_customdata(bm, e_clear->l, v_clear, v_other, customdata_fac); + } +#endif + + BM_edge_kill(bm, e_clear); + + BM_vert_splice(bm, v_clear, v_other); + + BM_edge_splice(bm, e_a_other[0], e_a_other[1]); + + // BM_mesh_validate(bm); + + return TRUE; + } + else { + return FALSE; + } +} + + +/* collapse e the edge, removing e->v2 */ +static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, + Quadric *vquadrics, float *vweights, + Heap *eheap, HeapNode **eheap_table, + const CD_UseFlag customdata_flag) +{ + int e_clear_other[2]; + BMVert *v_other = e->v1; + int v_clear_index = BM_elem_index_get(e->v2); /* the vert is removed so only store the index */ + float optimize_co[3]; + float customdata_fac; + + bm_decim_calc_target_co(e, optimize_co, vquadrics); + + /* use for customdata merging */ + if (LIKELY(compare_v3v3(e->v1->co, e->v2->co, FLT_EPSILON) == FALSE)) { + customdata_fac = line_point_factor_v3(optimize_co, e->v1->co, e->v2->co); + +#if 0 + /* simple test for stupid collapse */ + if (customdata_fac < 0.0 - FLT_EPSILON || customdata_fac > 1.0f + FLT_EPSILON) { + return; + } +#endif + } + else { + /* avoid divide by zero */ + customdata_fac = 0.5f; + } + + if (bm_edge_collapse(bm, e, e->v2, e_clear_other, customdata_flag, customdata_fac)) { + /* update collapse info */ + int i; + + if (vweights) { + const int fac = CLAMPIS(customdata_fac, 0.0f, 1.0f); + vweights[BM_elem_index_get(v_other)] = (vweights[v_clear_index] * (1.0f - fac)) + + (vweights[BM_elem_index_get(v_other)] * fac); + } + + e = NULL; /* paranoid safety check */ + + copy_v3_v3(v_other->co, optimize_co); + + /* remove eheap */ + for (i = 0; i < 2; i++) { + /* highly unlikely 'eheap_table[ke_other[i]]' would be NULL, but do for sanity sake */ + if ((e_clear_other[i] != -1) && (eheap_table[e_clear_other[i]] != NULL)) { + BLI_heap_remove(eheap, eheap_table[e_clear_other[i]]); + eheap_table[e_clear_other[i]] = NULL; + } + } + + /* update vertex quadric, add kept vertex from killed vertex */ + BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(v_other)], &vquadrics[v_clear_index]); + + /* update connected normals */ + + /* in fact face normals are not used for progressive updates, no need to update them */ + // BM_vert_normal_update_all(v); + BM_vert_normal_update(v_other); + + /* update error costs and the eheap */ + if (LIKELY(v_other->e)) { + BMEdge *e_iter; + BMEdge *e_first; + e_iter = e_first = v_other->e; + do { + BLI_assert(BM_edge_find_double(e_iter) == NULL); + bm_decim_build_edge_cost_single(e_iter, vquadrics, vweights, eheap, eheap_table); + } while ((e_iter = bmesh_disk_edge_next(e_iter, v_other)) != e_first); + } + +#if 0 + /* optional, update edges around the vertex face fan */ + { + BMIter liter; + BMLoop *l; + BM_ITER_ELEM (l, &liter, v_other, BM_LOOPS_OF_VERT) { + if (l->f->len == 3) { + BMEdge *e_outer; + if (BM_vert_in_edge(l->prev->e, l->v)) + e_outer = l->next->e; + else + e_outer = l->prev->e; + + BLI_assert(BM_vert_in_edge(e_outer, l->v) == FALSE); + + bm_decim_build_edge_cost_single(e_outer, vquadrics, eheap, eheap_table); + } + } + } + /* end optional update */ +#endif + } +} + + +/* Main Decimate Function + * ********************** */ + +/** + * \brief BM_mesh_decimate + * \param bm The mesh + * \param factor face count multiplier [0 - 1] + * \param vertex_weights Optional array of vertex aligned weights [0 - 1], + * a vertex group is the usual source for this. + */ +void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights) +{ + Heap *eheap; /* edge heap */ + HeapNode **eheap_table; /* edge index aligned table pointing to the eheap */ + Quadric *vquadrics; /* vert index aligned quadrics */ + int tot_edge_orig; + int face_tot_target; + int use_triangulate; + + CD_UseFlag customdata_flag = 0; + +#ifdef USE_TRIANGULATE + /* temp convert quads to triangles */ + use_triangulate = bm_decim_triangulate_begin(bm); +#endif + + + /* alloc vars */ + vquadrics = MEM_callocN(sizeof(Quadric) * bm->totvert, __func__); + /* since some edges may be degenerate, we might be over allocing a little here */ + eheap = BLI_heap_new_ex(bm->totedge); + eheap_table = MEM_callocN(sizeof(HeapNode *) * bm->totedge, __func__); + tot_edge_orig = bm->totedge; + + + /* build initial edge collapse cost data */ + bm_decim_build_quadrics(bm, vquadrics); + + bm_decim_build_edge_cost(bm, vquadrics, vweights, eheap, eheap_table); + + face_tot_target = bm->totface * factor; + bm->elem_index_dirty |= BM_FACE | BM_EDGE | BM_VERT; + + +#ifdef USE_CUSTOMDATA + /* initialize customdata flag, we only need math for loops */ + if (CustomData_has_interp(&bm->vdata)) customdata_flag |= CD_DO_VERT; + if (CustomData_has_interp(&bm->edata)) customdata_flag |= CD_DO_EDGE; + if (CustomData_has_math(&bm->ldata)) customdata_flag |= CD_DO_LOOP; +#endif + + /* iterative edge collapse and maintain the eheap */ + while ((bm->totface > face_tot_target) && (BLI_heap_is_empty(eheap) == FALSE)) { + // const float value = BLI_heap_node_value(BLI_heap_top(eheap)); + BMEdge *e = BLI_heap_popmin(eheap); + BLI_assert(BM_elem_index_get(e) < tot_edge_orig); /* handy to detect corruptions elsewhere */ + + // printf("COST %.10f\n", value); + + /* under normal conditions wont be accessed again, + * but NULL just incase so we don't use freed node */ + eheap_table[BM_elem_index_get(e)] = NULL; + + bm_decim_edge_collapse(bm, e, vquadrics, vweights, eheap, eheap_table, customdata_flag); + } + + +#ifdef USE_TRIANGULATE + /* its possible we only had triangles, skip this step in that case */ + if (LIKELY(use_triangulate)) { + /* temp convert quads to triangles */ + bm_decim_triangulate_end(bm); + } +#endif + + /* free vars */ + MEM_freeN(vquadrics); + MEM_freeN(eheap_table); + BLI_heap_free(eheap, NULL); + + /* testing only */ + // BM_mesh_validate(bm); + + (void)tot_edge_orig; /* quiet release build warning */ +} diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index 91ca7124fc2..a5694ecd920 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -437,7 +437,7 @@ BMFace *BM_face_split_n(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, float cos[ /* bmesh_semv returns in newe the edge going from newv to tv */ copy_v3_v3(newv->co, cos[i]); - /* interpolate the loop data for the loops with v==newv, using orig face */ + /* interpolate the loop data for the loops with (v == newv), using orig face */ for (j = 0; j < 2; j++) { BMEdge *e_iter = (j == 0) ? e : newe; BMLoop *l_iter = e_iter->l; diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c index 9e6301c91f5..e520a95aa95 100644 --- a/source/blender/editors/animation/keyframes_draw.c +++ b/source/blender/editors/animation/keyframes_draw.c @@ -322,7 +322,7 @@ static void nupdate_abk_bezt(void *node, void *data) /* just add the BezTriple to the buffer if there's space, or allocate a new one */ if (abk->numBezts >= MAX_ABK_BUFSIZE) { // TODO: need to allocate new array to cater... - //bezts_extra= MEM_callocN(...); + //bezts_extra = MEM_callocN(...); if (G.debug & G_DEBUG) printf("FIXME: nupdate_abk_bezt() missing case for too many overlapping BezTriples\n"); } @@ -582,7 +582,7 @@ void draw_keyframe_shape(float x, float y, float xscale, float hsize, short sel, } /* tweak size of keyframe shape according to type of keyframe - * - 'proper' keyframes have key_type=0, so get drawn at full size + * - 'proper' keyframes have key_type = 0, so get drawn at full size */ hsize -= 0.5f * key_type; diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index d18c611166f..beb57b44248 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -610,28 +610,28 @@ static int ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBut if (ui_but_equals_old(oldbut, but)) { if (oldbut->active) { #if 0 -// but->flag= oldbut->flag; +// but->flag = oldbut->flag; #else /* exception! redalert flag can't be update from old button. * perhaps it should only copy specific flags rather than all. */ -// but->flag= (oldbut->flag & ~UI_BUT_REDALERT) | (but->flag & UI_BUT_REDALERT); +// but->flag = (oldbut->flag & ~UI_BUT_REDALERT) | (but->flag & UI_BUT_REDALERT); #endif -// but->active= oldbut->active; -// but->pos= oldbut->pos; -// but->ofs= oldbut->ofs; -// but->editstr= oldbut->editstr; -// but->editval= oldbut->editval; -// but->editvec= oldbut->editvec; -// but->editcoba= oldbut->editcoba; -// but->editcumap= oldbut->editcumap; -// but->selsta= oldbut->selsta; -// but->selend= oldbut->selend; -// but->softmin= oldbut->softmin; -// but->softmax= oldbut->softmax; +// but->active = oldbut->active; +// but->pos = oldbut->pos; +// but->ofs = oldbut->ofs; +// but->editstr = oldbut->editstr; +// but->editval = oldbut->editval; +// but->editvec = oldbut->editvec; +// but->editcoba = oldbut->editcoba; +// but->editcumap = oldbut->editcumap; +// but->selsta = oldbut->selsta; +// but->selend = oldbut->selend; +// but->softmin = oldbut->softmin; +// but->softmax = oldbut->softmax; // but->linkto[0] = oldbut->linkto[0]; // but->linkto[1] = oldbut->linkto[1]; found = 1; -// oldbut->active= NULL; +// oldbut->active = NULL; /* move button over from oldblock to new block */ BLI_remlink(&oldblock->buttons, oldbut); @@ -1947,8 +1947,8 @@ void ui_set_but_soft_range(uiBut *but, double value) RNA_property_int_ui_range(&but->rnapoin, but->rnaprop, &imin, &imax, &istep); softmin = (imin == INT_MIN) ? -1e4 : imin; softmax = (imin == INT_MAX) ? 1e4 : imax; - /*step= istep;*/ /*UNUSED*/ - /*precision= 1;*/ /*UNUSED*/ + /*step = istep;*/ /*UNUSED*/ + /*precision = 1;*/ /*UNUSED*/ if (array_len >= 2) { int value_range[2]; @@ -1964,8 +1964,8 @@ void ui_set_but_soft_range(uiBut *but, double value) RNA_property_float_ui_range(&but->rnapoin, but->rnaprop, &fmin, &fmax, &fstep, &fprecision); softmin = (fmin == -FLT_MAX) ? (float)-1e4 : fmin; softmax = (fmax == FLT_MAX) ? (float)1e4 : fmax; - /*step= fstep;*/ /*UNUSED*/ - /*precision= fprecision;*/ /*UNUSED*/ + /*step = fstep;*/ /*UNUSED*/ + /*precision = fprecision;*/ /*UNUSED*/ if (array_len >= 2) { float value_range[2]; @@ -2256,7 +2256,7 @@ void ui_check_but(uiBut *but) /* safety is 4 to enable small number buttons (like 'users') */ - // okwidth= -4 + (BLI_rcti_size_x(&but->rect)); // UNUSED + // okwidth = -4 + (BLI_rcti_size_x(&but->rect)); // UNUSED /* name: */ switch (but->type) { @@ -2439,7 +2439,7 @@ static void ui_block_do_align_but(uiBut *first, short nr) } } - /* rows==0: 1 row, cols==0: 1 column */ + /* rows == 0: 1 row, cols == 0: 1 column */ /* note; how it uses 'flag' in loop below (either set it, or OR it) is confusing */ for (but = first, prev = NULL; but && but->alignnr == nr; prev = but, but = but->next) { diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index ed1a2caab05..445182fb325 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -2157,7 +2157,7 @@ static void ui_blockopen_begin(bContext *C, uiBut *but, uiHandleButtonData *data } /* this makes adjacent blocks auto open from now on */ - //if (but->block->auto_open ==0 ) but->block->auto_open = 1; + //if (but->block->auto_open == 0) but->block->auto_open = 1; } static void ui_blockopen_end(bContext *C, uiBut *but, uiHandleButtonData *data) @@ -2961,7 +2961,7 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event) { - int mx, my /*, click= 0 */; + int mx, my /*, click = 0 */; int retval = WM_UI_HANDLER_CONTINUE; int horizontal = (BLI_rctf_size_x(&but->rect) > BLI_rctf_size_y(&but->rect)); @@ -3747,8 +3747,8 @@ static int ui_numedit_but_CURVE(uiBut *but, uiHandleButtonData *data, int snap, zoomx = BLI_rctf_size_x(&but->rect) / BLI_rctf_size_x(&cumap->curr); zoomy = BLI_rctf_size_y(&but->rect) / BLI_rctf_size_y(&cumap->curr); - /* offsx= cumap->curr.xmin; */ - /* offsy= cumap->curr.ymin; */ + /* offsx = cumap->curr.xmin; */ + /* offsy = cumap->curr.ymin; */ if (snap) { float d[2]; @@ -4078,7 +4078,7 @@ static int ui_numedit_but_WAVEFORM(uiBut *but, uiHandleButtonData *data, int mx, Scopes *scopes = (Scopes *)but->poin; /* rcti rect; */ int changed = 1; - float /* dx, */ dy /* , yfac=1.f */; /* UNUSED */ + float /* dx, */ dy /* , yfac =1.0f */; /* UNUSED */ /* BLI_rcti_rctf_copy(&rect, &but->rect); */ @@ -6027,7 +6027,7 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but) } else { retval = ui_do_button(C, block, but, event); - // retval= WM_UI_HANDLER_BREAK; XXX why ? + // retval = WM_UI_HANDLER_BREAK; XXX why ? } if (data->state == BUTTON_STATE_EXIT) { diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index cf5aed16263..9fac19031de 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -1708,7 +1708,7 @@ static void ui_litem_layout_row(uiLayout *litem) int x, y, w, tot, totw, neww, itemw, minw, itemh, offset; int fixedw, freew, fixedx, freex, flag = 0, lastw = 0; - /* x= litem->x; */ /* UNUSED */ + /* x = litem->x; */ /* UNUSED */ y = litem->y; w = litem->w; totw = 0; diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c index b9018914633..8633a7a9b38 100644 --- a/source/blender/editors/metaball/mball_edit.c +++ b/source/blender/editors/metaball/mball_edit.c @@ -124,7 +124,6 @@ MetaElem *add_metaball_primitive(bContext *UNUSED(C), Object *obedit, float mat[ /* Select or deselect all MetaElements */ static int mball_select_all_exec(bContext *C, wmOperator *op) { - //Scene *scene= CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); MetaBall *mb = (MetaBall *)obedit->data; MetaElem *ml; diff --git a/source/blender/editors/object/object_lattice.c b/source/blender/editors/object/object_lattice.c index ac9c4f7adee..4aa2e825954 100644 --- a/source/blender/editors/object/object_lattice.c +++ b/source/blender/editors/object/object_lattice.c @@ -569,7 +569,7 @@ static void findnearestLattvert__doClosest(void *userData, BPoint *bp, const flo static BPoint *findnearestLattvert(ViewContext *vc, const int mval[2], int sel) { - /* sel==1: selected gets a disadvantage */ + /* (sel == 1): selected gets a disadvantage */ /* in nurb and bezt or bp the nearest is written */ /* return 0 1 2: handlepunt */ struct { BPoint *bp; float dist; int select; float mval_fl[2]; } data = {NULL}; diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index a52f526448f..2511389ebcb 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -667,7 +667,7 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object * NOTE: the old (2.4x) method was to set ob->partype = PARSKEL, creating the virtual modifiers */ ob->partype = PAROBJECT; /* note, dna define, not operator property */ - //ob->partype= PARSKEL; /* note, dna define, not operator property */ + //ob->partype = PARSKEL; /* note, dna define, not operator property */ /* BUT, to keep the deforms, we need a modifier, and then we need to set the object that it uses * - We need to ensure that the modifier we're adding doesn't already exist, so we check this by @@ -1260,7 +1260,7 @@ static int move_to_layer_exec(bContext *C, wmOperator *op) base->object->lay = lay; base->object->flag &= ~SELECT; base->flag &= ~SELECT; - /* if (base->object->type==OB_LAMP) is_lamp = TRUE; */ + /* if (base->object->type == OB_LAMP) is_lamp = TRUE; */ } CTX_DATA_END; } @@ -1710,7 +1710,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, int flag) break; case OB_MESH: ob->data = BKE_mesh_copy(ob->data); - //me= ob->data; + //me = ob->data; //if (me && me->key) // ipo_idnew(me->key->ipo); /* drivers */ break; diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c index 86a55a9b278..2b6d69ca694 100644 --- a/source/blender/editors/object/object_shapekey.c +++ b/source/blender/editors/object/object_shapekey.c @@ -211,7 +211,7 @@ static int object_shape_key_mirror(bContext *C, Object *ob) /* currently editmode isn't supported by mesh so * ignore here for now too */ - /* if (lt->editlatt) lt= lt->editlatt->latt; */ + /* if (lt->editlatt) lt = lt->editlatt->latt; */ for (w = 0; w < lt->pntsw; w++) { for (v = 0; v < lt->pntsv; v++) { diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 457a77528ce..58931d3e341 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -867,7 +867,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) tot_change++; arm->id.flag |= LIB_DOIT; - /* do_inverse_offset= TRUE; */ /* docenter_armature() handles this */ + /* do_inverse_offset = TRUE; */ /* docenter_armature() handles this */ BKE_object_where_is_calc(scene, ob); BKE_pose_where_is(scene, ob); /* needed for bone parents */ diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index a17d84af128..221aad2161c 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -110,11 +110,14 @@ static int particle_system_remove_exec(bContext *C, wmOperator *UNUSED(op)) /* possible this isn't the active object * object_remove_particle_system() clears the mode on the last psys - * */ - if (mode_orig & OB_MODE_PARTICLE_EDIT) - if ((ob->mode & OB_MODE_PARTICLE_EDIT)==0) - if (scene->basact && scene->basact->object==ob) + */ + if (mode_orig & OB_MODE_PARTICLE_EDIT) { + if ((ob->mode & OB_MODE_PARTICLE_EDIT) == 0) { + if (scene->basact && scene->basact->object == ob) { WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL); + } + } + } WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob); WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob); diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index 9306ec79966..88bd4e829f1 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -196,10 +196,10 @@ static void fluidsimPrintChannel(FILE *file, float *channel, int paramsize, char int i, j; int channelSize = paramsize; - if (entries==3) { + if (entries == 3) { elbeemSimplifyChannelVec3(channel, &channelSize); } - else if (entries==1) { + else if (entries == 1) { elbeemSimplifyChannelFloat(channel, &channelSize); } else { @@ -211,7 +211,7 @@ static void fluidsimPrintChannel(FILE *file, float *channel, int paramsize, char fprintf(file, " "); for (j=0;j <= entries;j++) { // also print time value fprintf(file, " %f ", channel[i*(entries + 1) + j]); - if (j==entries-1) { fprintf(file, " "); } + if (j == entries-1) { fprintf(file, " "); } } fprintf(file, "\n"); } @@ -627,7 +627,7 @@ static int fluid_validate_scene(ReportList *reports, Scene *scene, Object *fsDom return 0; } - if (channelObjCount>=255) { + if (channelObjCount >= 255) { BKE_report(reports, RPT_ERROR, "Cannot bake with more then 256 objects"); return 0; } diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 38084773e78..63cf0fcaa31 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -83,7 +83,7 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat /* if renrect argument, we only refresh scanlines */ if (renrect) { - /* if ymax==recty, rendering of layer is ready, we should not draw, other things happen... */ + /* if (ymax == recty), rendering of layer is ready, we should not draw, other things happen... */ if (rr->renlay == NULL || renrect->ymax >= rr->recty) return; diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index ad93859b84d..3cc2f314960 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -175,7 +175,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender) /* render 3d view */ if (rv3d->persp == RV3D_CAMOB && v3d->camera) { - /*int is_ortho= scene->r.mode & R_ORTHO;*/ + /*int is_ortho = scene->r.mode & R_ORTHO;*/ camera = v3d->camera; RE_GetCameraWindow(oglrender->re, camera, scene->r.cfra, winmat); diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 7a349e4a581..ff53a6b9e92 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -1453,10 +1453,10 @@ void ED_screen_set_scene(bContext *C, bScreen *screen, Scene *scene) if (scene != sc->scene) { /* all areas endlocalview */ - // XXX ScrArea *sa= sc->areabase.first; + // XXX ScrArea *sa = sc->areabase.first; // while (sa) { // endlocalview(sa); - // sa= sa->next; + // sa = sa->next; // } sc->scene = scene; } diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index cf3f2ad741b..058b8bb4827 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -783,7 +783,7 @@ static int project_paint_PickColor(const ProjPaintState *ps, float pt[2], float else { //xi = (int)((uv[0]*ibuf->x) + 0.5f); //yi = (int)((uv[1]*ibuf->y) + 0.5f); - //if (xi<0 || xi>=ibuf->x || yi<0 || yi>=ibuf->y) return 0; + //if (xi < 0 || xi >= ibuf->x || yi < 0 || yi >= ibuf->y) return 0; /* wrap */ xi = ((int)(uv[0] * ibuf->x)) % ibuf->x; @@ -903,7 +903,7 @@ static int project_bucket_point_occluded(const ProjPaintState *ps, LinkNode *buc else isect_ret = project_paint_occlude_ptv(pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v2], ps->screenCoords[mf->v3], w, ps->is_ortho); - /* Note, if isect_ret==-1 then we don't want to test the other side of the quad */ + /* Note, if (isect_ret == -1) then we don't want to test the other side of the quad */ if (isect_ret == 0 && mf->v4) { if (do_clip) isect_ret = project_paint_occlude_ptv_clip(ps, mf, pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v3], ps->screenCoords[mf->v4], 1); @@ -5285,7 +5285,7 @@ static void brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata) #define PX_SIZE_FADE_MIN 4.0f Scene *scene = CTX_data_scene(C); - //Brush *brush= image_paint_brush(C); + //Brush *brush = image_paint_brush(C); Paint *paint = paint_get_active_from_context(C); Brush *brush = paint_brush(paint); diff --git a/source/blender/editors/space_logic/logic_buttons.c b/source/blender/editors/space_logic/logic_buttons.c index d37306f9bc5..f6aad6d9e29 100644 --- a/source/blender/editors/space_logic/logic_buttons.c +++ b/source/blender/editors/space_logic/logic_buttons.c @@ -113,7 +113,7 @@ static int cut_links_exec(bContext *C, wmOperator *op) (int)loc[0], (int)loc[1], &mcoords[i][0], &mcoords[i][1]); i++; - if (i>= 256) break; + if (i >= 256) break; } RNA_END; diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c index 4b151734dc7..9ef7359f5de 100644 --- a/source/blender/editors/space_logic/logic_window.c +++ b/source/blender/editors/space_logic/logic_window.c @@ -687,8 +687,8 @@ static ID **get_selected_and_linked_obs(bContext *C, short *count, short scavisf ob= ob->id.next; } - if (*count==0) return NULL; - if (*count>24) *count= 24; /* temporal */ + if (*count == 0) return NULL; + if (*count > 24) *count = 24; /* temporal */ idar= MEM_callocN((*count)*sizeof(void *), "idar"); @@ -706,7 +706,7 @@ static ID **get_selected_and_linked_obs(bContext *C, short *count, short scavisf idar[nr] = (ID *)ob; nr++; } - if (nr>=24) break; + if (nr >= 24) break; ob= ob->id.next; } diff --git a/source/blender/editors/space_logic/space_logic.c b/source/blender/editors/space_logic/space_logic.c index 4ee522952d4..c4ec801d6ed 100644 --- a/source/blender/editors/space_logic/space_logic.c +++ b/source/blender/editors/space_logic/space_logic.c @@ -62,20 +62,20 @@ ARegion *logic_has_buttons_region(ScrArea *sa) { ARegion *ar, *arnew; - ar= BKE_area_find_region_type(sa, RGN_TYPE_UI); + ar = BKE_area_find_region_type(sa, RGN_TYPE_UI); if (ar) return ar; /* add subdiv level; after header */ - ar= BKE_area_find_region_type(sa, RGN_TYPE_HEADER); + ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER); /* is error! */ - if (ar==NULL) return NULL; + if (ar == NULL) return NULL; arnew= MEM_callocN(sizeof(ARegion), "buttons for image"); BLI_insertlinkafter(&sa->regionbase, ar, arnew); - arnew->regiontype= RGN_TYPE_UI; - arnew->alignment= RGN_ALIGN_LEFT; + arnew->regiontype = RGN_TYPE_UI; + arnew->alignment = RGN_ALIGN_LEFT; arnew->flag = RGN_FLAG_HIDDEN; diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 610895002aa..9be54b9855f 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -5219,7 +5219,7 @@ static int rna_function_format_array_length(const char *format, int ofs, int fle lenbuf[idx] = format[ofs]; if (ofs < flen && format[ofs + 1] == ']') { - /* XXX put better error reporting for ofs>=flen or idx over lenbuf capacity */ + /* XXX put better error reporting for (ofs >= flen) or idx over lenbuf capacity */ lenbuf[idx] = '\0'; return atoi(lenbuf); } diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c index a882e4f5854..1cb6853447a 100644 --- a/source/blender/modifiers/intern/MOD_decimate.c +++ b/source/blender/modifiers/intern/MOD_decimate.c @@ -139,7 +139,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, em = DM_to_editbmesh(dm, NULL, FALSE); bm = em->bm; - BM_mesh_decimate(bm, dmd->percent, vweights); + BM_mesh_decimate_collapse(bm, dmd->percent, vweights); if (vweights) { MEM_freeN(vweights); diff --git a/source/blender/nodes/intern/node_socket.c b/source/blender/nodes/intern/node_socket.c index 8b393dd740a..8e49484d1eb 100644 --- a/source/blender/nodes/intern/node_socket.c +++ b/source/blender/nodes/intern/node_socket.c @@ -490,39 +490,39 @@ static bNodeSocket *verify_socket_template(bNodeTree *ntree, bNode *node, int in break; } if (sock) { - sock->type= stemp->type; /* in future, read this from tydefs! */ - if (stemp->limit==0) sock->limit= 0xFFF; - else sock->limit= stemp->limit; + sock->type = stemp->type; /* in future, read this from tydefs! */ + if (stemp->limit == 0) sock->limit= 0xFFF; + else sock->limit = stemp->limit; sock->flag |= stemp->flag; /* Copy the property range and subtype parameters in case the template changed. * NOT copying the actual value here, only button behavior changes! */ switch (sock->type) { - case SOCK_FLOAT: + case SOCK_FLOAT: { bNodeSocketValueFloat *dval= sock->default_value; dval->min = stemp->min; dval->max = stemp->max; dval->subtype = stemp->subtype; + break; } - break; - case SOCK_INT: + case SOCK_INT: { bNodeSocketValueInt *dval= sock->default_value; dval->min = stemp->min; dval->max = stemp->max; dval->subtype = stemp->subtype; + break; } - break; - case SOCK_VECTOR: + case SOCK_VECTOR: { bNodeSocketValueVector *dval= sock->default_value; dval->min = stemp->min; dval->max = stemp->max; dval->subtype = stemp->subtype; + break; } - break; } BLI_remlink(socklist, sock); @@ -600,7 +600,9 @@ void node_verify_socket_templates(bNodeTree *ntree, bNode *node) * This also prevents group node sockets from being removed, without the need to explicitly * check the node type here. */ - if (ntype && ((ntype->inputs && ntype->inputs[0].type>=0) || (ntype->outputs && ntype->outputs[0].type>=0))) { + if (ntype && ((ntype->inputs && ntype->inputs[0].type >= 0) || + (ntype->outputs && ntype->outputs[0].type >= 0))) + { verify_socket_template_list(ntree, node, SOCK_IN, &node->inputs, ntype->inputs); verify_socket_template_list(ntree, node, SOCK_OUT, &node->outputs, ntype->outputs); } diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 042803c150e..ed08f5a16fb 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -564,12 +564,12 @@ static int refraction(float refract[3], const float n[3], const float view[3], f if (dot>0.0f) { index = 1.0f/index; fac= 1.0f - (1.0f - dot*dot)*index*index; - if (fac<= 0.0f) return 0; + if (fac <= 0.0f) return 0; fac= -dot*index + sqrtf(fac); } else { fac= 1.0f - (1.0f - dot*dot)*index*index; - if (fac<= 0.0f) return 0; + if (fac <= 0.0f) return 0; fac= -dot*index - sqrtf(fac); } -- cgit v1.2.3