Commit: 07c700365b80b9d1a868059f2b70f12c98cb77be
Author: Rohan Rathi
Date:   Sat Aug 12 09:54:52 2017 +0530
Branches: soc-2017-normal-tools
https://developer.blender.org/rB07c700365b80b9d1a868059f2b70f12c98cb77be

Added weighting, sharp edges to average.

Made small UI changes.

===================================================================

M       source/blender/bmesh/intern/bmesh_mesh.c
M       source/blender/bmesh/intern/bmesh_mesh.h
M       source/blender/editors/mesh/editmesh_tools.c

===================================================================

diff --git a/source/blender/bmesh/intern/bmesh_mesh.c 
b/source/blender/bmesh/intern/bmesh_mesh.c
index d9f6352d4ad..956139ebd8f 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -558,7 +558,7 @@ static void bm_mesh_edges_sharp_tag(
 
 /* Check whether gievn loop is part of an unknown-so-far cyclic smooth fan, or 
not.
  * Needed because cyclic smooth fans have no obvious 'entry point', and yet we 
need to walk them once, and only once. */
-static bool bm_mesh_loop_check_cyclic_smooth_fan(BMLoop *l_curr)
+bool bm_mesh_loop_check_cyclic_smooth_fan(BMLoop *l_curr)
 {
        BMLoop *lfan_pivot_next = l_curr;
        BMEdge *e_next = l_curr->e;
@@ -854,7 +854,7 @@ static void bm_mesh_loops_calc_normals(
                                                                clnors_avg[1] 
/= clnors_nbr;
                                                                /* Fix/update 
all clnors of this fan with computed average value. */
                                                                
-                                                               /* Prints 
continuously when merge custom normals, so commenting -Rohan
+                                                               /* Prints 
continuously when merge custom normals, so commenting
                                                                printf("Invalid 
clnors in this fan!\n");*/
 
                                                                while ((clnor = 
BLI_SMALLSTACK_POP(clnors))) {
diff --git a/source/blender/bmesh/intern/bmesh_mesh.h 
b/source/blender/bmesh/intern/bmesh_mesh.h
index 6a079d91144..ba181aeb36d 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.h
+++ b/source/blender/bmesh/intern/bmesh_mesh.h
@@ -52,6 +52,7 @@ void BM_loops_calc_normal_vcos(
         const bool use_split_normals, const float split_angle, float 
(*r_lnos)[3],
         struct MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], 
const int cd_loop_clnors_offset,
                bool rebuild);
+bool bm_mesh_loop_check_cyclic_smooth_fan(BMLoop *l_curr);
 void BM_lnorspacearr_store(BMesh *bm, float (*r_lnors)[3]);
 void BM_lnorspace_invalidate(BMesh *bm, bool inval_all);
 void BM_lnorspace_rebuild(BMesh *bm, bool preserve_clnor);
diff --git a/source/blender/editors/mesh/editmesh_tools.c 
b/source/blender/editors/mesh/editmesh_tools.c
index 16b4167216f..56cfea013e7 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -42,6 +42,7 @@
 #include "DNA_scene_types.h"
 
 #include "BLI_bitmap.h"
+#include "BLI_heap.h"
 #include "BLI_listbase.h"
 #include "BLI_linklist.h"
 #include "BLI_linklist_stack.h"
@@ -6604,7 +6605,7 @@ enum {
 };
 
 static EnumPropertyItem average_method_items[] = {
-       { LOOP_AVERAGE, "Loop", 0, "Loop", "Take Average of vert Normals" },
+       { LOOP_AVERAGE, "Custom Normal", 0, "Custom Normal", "Take Average of 
vert Normals" },
        { FACE_AREA_AVERAGE, "Face Area", 0, "Face Area", "Set all vert normals 
by Face Area"},
        { ANGLE_AVERAGE, "Corner Angle", 0, "Corner Angle", "Set all vert 
normals by Corner Angle" },
        { 0, NULL, 0, NULL, NULL }
@@ -6615,58 +6616,131 @@ static int edbm_average_loop_normals_exec(bContext *C, 
wmOperator *op)
        Object *obedit = CTX_data_edit_object(C);
        BMEditMesh *em = BKE_editmesh_from_object(obedit);
        BMesh *bm = em->bm;
-       BMVert *v;
+       BMFace *f;
+       BMEdge *e;
        BMLoop *l;
-       BMIter viter, liter;
-       int index;
+       BMIter fiter, eiter;
 
        BM_lnorspace_update(bm);
        LoopNormalData *ld = BM_loop_normal_init(bm);
 
        const int average_type = RNA_enum_get(op->ptr, "average_type");
        int cd_clnors_offset = CustomData_get_offset(&bm->ldata, 
CD_CUSTOMLOOPNORMAL);
+       float weight = (float) RNA_int_get(op->ptr, "weight"), threshold = 
RNA_float_get(op->ptr, "threshold");
+       const bool boolean_weights = RNA_boolean_get(op->ptr, 
"boolean_weights");
+       weight = weight / 10.0f;
 
-       float(*vnors)[3] = MEM_callocN(sizeof(*vnors) * bm->totvert, 
"__func__");
-
-       BM_ITER_MESH_INDEX(v, &viter, bm, BM_VERTS_OF_MESH, index) {
-               if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
-                       BM_ITER_ELEM(l, &liter, v, BM_LOOPS_OF_VERT) {
+       if (weight > 1) {
+               weight = (weight - 1) * 10;
+       }
 
-                               float custom_normal[3];
-                               int l_index = BM_elem_index_get(l);
-                               short *clnors_data = BM_ELEM_CD_GET_VOID_P(l, 
cd_clnors_offset);
-                               
BKE_lnor_space_custom_data_to_normal(bm->lnor_spacearr->lspacearr[l_index], 
clnors_data, custom_normal);
+       BM_ITER_MESH(e, &eiter, bm, BM_EDGES_OF_MESH) {
+               BMLoop *l_a, *l_b;
 
-                               if (average_type == FACE_AREA_AVERAGE) {
-                                       copy_v3_v3(custom_normal, l->f->no);
-                                       float face_area = 
BM_face_calc_area(l->f);
-                                       mul_v3_fl(custom_normal, face_area);
-                               }
-                               else if (average_type == ANGLE_AVERAGE)
-                                       copy_v3_v3(custom_normal, l->f->no); {
-                                       float face_angle = 
BM_loop_calc_face_angle(l);
-                                       mul_v3_fl(custom_normal, face_angle);
-                               }
-                               add_v3_v3(vnors[index], custom_normal);
+               BM_elem_flag_disable(e, BM_ELEM_TAG);
+               if (BM_edge_loop_pair(e, &l_a, &l_b)) {
+                       if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) && l_a->v != 
l_b->v) {
+                               BM_elem_flag_enable(e, BM_ELEM_TAG);
                        }
                }
        }
 
-       for (int i = 0; i < bm->totvert; i++) {
-               if (!is_zero_v3(vnors[i]))
-                       normalize_v3(vnors[i]);
-       }
+       Heap *loop_weight = BLI_heap_new();
 
-       BM_ITER_MESH_INDEX(v, &viter, bm, BM_VERTS_OF_MESH, index) {
-               if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
-                       BM_ITER_ELEM(l, &liter, v, BM_LOOPS_OF_VERT) {
-                               int l_index = BM_elem_index_get(l);
-                               short *clnors_data = BM_ELEM_CD_GET_VOID_P(l, 
cd_clnors_offset);
-                               
BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[l_index], 
vnors[index], clnors_data);
+       BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
+               BMLoop *l_curr, *l_first;
+
+               l_curr = l_first = BM_FACE_FIRST_LOOP(f);
+               do {
+                       if (BM_elem_flag_test(l_curr->v, BM_ELEM_SELECT)) {
+                               if (BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) 
&& (BM_elem_flag_test(l_curr, BM_ELEM_TAG) || 
!bm_mesh_loop_check_cyclic_smooth_fan(l_curr)))
+                               {
+                               }
+                               else if (!BM_elem_flag_test(l_curr->e, 
BM_ELEM_TAG) && !BM_elem_flag_test(l_curr->prev->e, BM_ELEM_TAG))
+                               {
+                                       int loop_index = 
BM_elem_index_get(l_curr);
+                                       short *clnors = 
BM_ELEM_CD_GET_VOID_P(l_curr, cd_clnors_offset);
+                                       
BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[loop_index], 
f->no, clnors);
+                               }
+                               else {
+                                       BMVert *v_pivot = l_curr->v;
+                                       BMEdge *e_next;
+                                       const BMEdge *e_org = l_curr->e;
+                                       BMLoop *lfan_pivot, *lfan_pivot_next;
+
+                                       lfan_pivot = l_curr;
+                                       e_next = lfan_pivot->e;
+
+                                       while (true) {
+                                               lfan_pivot_next = 
BM_vert_step_fan_loop(lfan_pivot, &e_next);
+                                               if (lfan_pivot_next) {
+                                                       
BLI_assert(lfan_pivot_next->v == v_pivot);
+                                               }
+                                               else {
+                                                       e_next = (lfan_pivot->e 
== e_next) ? lfan_pivot->prev->e : lfan_pivot->e;
+                                               }
+
+                                               float val = 1.0f;
+                                               if (average_type == 
FACE_AREA_AVERAGE) {
+                                                       val = 1.0f / 
BM_face_calc_area(lfan_pivot->f);
+                                               }
+                                               else if (average_type == 
ANGLE_AVERAGE) {
+                                                       val = 1.0f / 
BM_loop_calc_face_angle(lfan_pivot);
+                                               }
+                                               if (boolean_weights && 
BM_elem_flag_test(lfan_pivot->f, BM_ELEM_SMOOTH)) {
+                                                       val = (float)INT_MAX;
+                                               }
+
+                                               BLI_heap_insert(loop_weight, 
val, lfan_pivot);
+
+                                               if (!BM_elem_flag_test(e_next, 
BM_ELEM_TAG) || (e_next == e_org)) {
+                                                       break;
+                                               }
+                                               lfan_pivot = lfan_pivot_next;
+                                       }
+
+                                       BLI_SMALLSTACK_DECLARE(loops, BMLoop *);
+                                       float wnor[3], avg_normal[3] = { 0 };
+                                       float val = 
BLI_heap_node_value(BLI_heap_top(loop_weight)), count = 0;
+
+                                       while (!BLI_heap_is_empty(loop_weight)) 
{
+                                               float cur_val = 
BLI_heap_node_value(BLI_heap_top(loop_weight));
+                                               if (!compare_ff(val, cur_val, 
threshold)) {
+                                                       count++;
+                                                       val = cur_val;
+                                               }
+                                               l = 
BLI_heap_popmin(loop_weight);
+                                               BLI_SMALLSTACK_PUSH(loops, l);
+
+                                               float n_weight = pow(weight, 
count);
+
+                                               if (average_type == 
LOOP_AVERAGE) {
+                                                       int l_index = 
BM_elem_index_get(l);
+                                                       short *clnors = 
BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
+                                                       
BKE_lnor_space_custom_data_to_normal(bm->lnor_spacearr->lspacearr[l_index], 
clnors, wnor);
+                                               }
+                                               else {
+                                                       copy_v3_v3(wnor, 
l->f->no);
+                                               }
+                                               mul_v3_fl(wnor, (1.0f / 
cur_val) * (1.0f / n_weight));
+                                               add_v3_v3(avg_normal, wnor);
+                                       }
+
+                                       normalize_v3(avg_normal);
+
+                                       while ((l = BLI_SMALLSTACK_POP(loops))) 
{
+                                               int l_index = 
BM_elem_index_get(l);
+                                               short *clnors = 
BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
+                                               
BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[l_index], 
avg_normal, clnors);
+                                       }
+                               }
                        }
-               }
+               } while ((l_curr = l_curr->next) != l_first);
        }
 
+       BLI_heap_free(loop_weight, NULL);
+       MEM_freeN(ld->normal);
+       MEM_freeN(ld);
        EDBM_update_generic(em, true, false);
 
        return OPERATOR_FINISHED;
@@ -6687,6 +6761,13 @@ void MESH_OT_average_loop_normals(struct wmOperatorType 
*ot)
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        ot->prop = RNA_def_enum(ot->srna, "average_type", average_method_items, 
LOOP_AVERAGE, "Type", "Averaging method");
+       RNA_def_property_flag(ot->prop, PROP_HIDDEN);
+
+       ot->prop = RNA_def_int(ot->srna, "weight", 10, 1, 20, "Weight", "Weight 
applied per face", 1, 20);
+
+       ot->prop = RNA_def_float(ot->srna, "threshold", 0.01f, 0, 5, 
"Threshold", "Threshold value for different weights to be considered equal", 0, 
5);
+       
+       ot->prop = RNA_def_boolean(ot->srna, "boolean_weights", 0, "Boolean 
Weights", "Sets weight of smooth faces to 0. Weight of flat faces remains 
unchanged");
 }
 
 /********************** Copy/Paste Loop Normals **********************/

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to