[Bf-blender-cvs] [cf811e7828d] soc-2017-normal-tools: Cached lnorspace array and added dirty Mechanic

RohanRathi noreply at git.blender.org
Thu Jun 1 07:34:14 CEST 2017


Commit: cf811e7828d75d9e4b4e83869e60a0069010f68f
Author: RohanRathi
Date:   Thu Jun 1 11:00:56 2017 +0530
Branches: soc-2017-normal-tools
https://developer.blender.org/rBcf811e7828d75d9e4b4e83869e60a0069010f68f

Cached lnorspace array and added dirty Mechanic

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

M	source/blender/blenkernel/intern/editderivedmesh.c
M	source/blender/bmesh/bmesh_class.h
M	source/blender/bmesh/intern/bmesh_mesh.c
M	source/blender/bmesh/intern/bmesh_mesh.h
M	source/blender/bmesh/intern/bmesh_opdefines.c
M	source/blender/bmesh/intern/bmesh_operator_api.h
M	source/blender/editors/mesh/editmesh_tools.c

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

diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index 5591ee2a0d4..47987567349 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -210,7 +210,7 @@ static void emDM_calcLoopNormalsSpaceArray(
 	cd_loop_clnors_offset = clnors_data ? -1 : CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
 
 	BM_loops_calc_normal_vcos(bm, vertexCos, vertexNos, polyNos, use_split_normals, split_angle, loopNos,
-	                          r_lnors_spacearr, clnors_data, cd_loop_clnors_offset);
+	                          r_lnors_spacearr, clnors_data, cd_loop_clnors_offset, false);
 #ifdef DEBUG_CLNORS
 	if (r_lnors_spacearr) {
 		int i;
diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h
index 64a5cad812a..2613759ac9a 100644
--- a/source/blender/bmesh/bmesh_class.h
+++ b/source/blender/bmesh/bmesh_class.h
@@ -20,6 +20,8 @@
  * ***** END GPL LICENSE BLOCK *****
  */
 
+#include "BKE_mesh.h"
+
 #ifndef __BMESH_CLASS_H__
 #define __BMESH_CLASS_H__
 
@@ -253,6 +255,9 @@ typedef struct BMesh {
 	ListBase errorstack;
 
 	void *py_handle;
+
+	MLoopNorSpaceArray bmspacearr;		/* Stores MLoopNorSpaceArray for this BMesh */
+	char spacearr_dirty;
 } BMesh;
 
 /* BMHeader->htype (char) */
@@ -266,6 +271,9 @@ enum {
 #define BM_ALL (BM_VERT | BM_EDGE | BM_LOOP | BM_FACE)
 #define BM_ALL_NOLOOP (BM_VERT | BM_EDGE | BM_FACE)
 
+#define BM_SPACEARR_DIRTY (1 << 1)
+#define BM_SPACEARR_DIRTY_ALL (1 << 2)
+
 /* args for _Generic */
 #define _BM_GENERIC_TYPE_ELEM_NONCONST \
 	void *, BMVert *, BMEdge *, BMLoop *, BMFace *, \
@@ -345,6 +353,9 @@ enum {
 	 * since tools may want to tag verts and
 	 * not have functions clobber them */
 	BM_ELEM_INTERNAL_TAG = (1 << 7),
+
+	/* Space invalid when set */
+	BM_ELEM_LNORSPACE = (1 << 6)
 };
 
 struct BPy_BMGeneric;
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
index d5d9e4abe2c..ef22c22c3b1 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -589,7 +589,7 @@ static bool bm_mesh_loop_check_cyclic_smooth_fan(BMLoop *l_curr)
  * Will use first clnors_data array, and fallback to cd_loop_clnors_offset (use NULL and -1 to not use clnors). */
 static void bm_mesh_loops_calc_normals(
         BMesh *bm, const float (*vcos)[3], const float (*fnos)[3], float (*r_lnos)[3],
-        MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], const int cd_loop_clnors_offset)
+        MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], const int cd_loop_clnors_offset, bool rebuild)
 {
 	BMIter fiter;
 	BMFace *f_curr;
@@ -645,6 +645,9 @@ static void bm_mesh_loops_calc_normals(
 
 		l_curr = l_first = BM_FACE_FIRST_LOOP(f_curr);
 		do {
+			if (rebuild && !BM_elem_flag_test(l_curr, BM_ELEM_LNORSPACE) && !(bm->spacearr_dirty & BM_SPACEARR_DIRTY_ALL))
+				continue;
+
 			/* A smooth edge, we have to check for cyclic smooth fan case.
 			 * If we find a new, never-processed cyclic smooth fan, we can do it now using that loop/edge as
 			 * 'entry point', otherwise we can skip it. */
@@ -960,7 +963,7 @@ void BM_mesh_loop_normals_update(
 void BM_loops_calc_normal_vcos(
         BMesh *bm, const float (*vcos)[3], const float (*vnos)[3], const float (*fnos)[3],
         const bool use_split_normals, const float split_angle, float (*r_lnos)[3],
-        MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], const int cd_loop_clnors_offset)
+        MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], const int cd_loop_clnors_offset, bool rebuild)
 {
 	const bool has_clnors = clnors_data || (cd_loop_clnors_offset != -1);
 
@@ -970,7 +973,7 @@ void BM_loops_calc_normal_vcos(
 		bm_mesh_edges_sharp_tag(bm, vnos, fnos, has_clnors ? (float)M_PI : split_angle, r_lnos);
 
 		/* Finish computing lnos by accumulating face normals in each fan of faces defined by sharp edges. */
-		bm_mesh_loops_calc_normals(bm, vcos, fnos, r_lnos, r_lnors_spacearr, clnors_data, cd_loop_clnors_offset);
+		bm_mesh_loops_calc_normals(bm, vcos, fnos, r_lnos, r_lnors_spacearr, clnors_data, cd_loop_clnors_offset, rebuild);
 	}
 	else {
 		BLI_assert(!r_lnors_spacearr);
@@ -978,6 +981,103 @@ void BM_loops_calc_normal_vcos(
 	}
 }
 
+void BM_lnorspacearr_store(BMesh *bm, float (*r_lnors)[3])
+{
+	if (!CustomData_has_layer(&bm->ldata, CD_CUSTOMLOOPNORMAL)) {
+		BM_data_layer_add(bm, &bm->ldata, CD_CUSTOMLOOPNORMAL);
+	}
+
+	int cd_loop_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
+
+	BM_loops_calc_normal_vcos(bm, NULL, NULL, NULL, true, M_PI, r_lnors, &bm->bmspacearr, NULL, cd_loop_clnors_offset, false);
+}
+
+/* will change later */
+#define CLEAR_SPACEARRAY_THRESHOLD(x) x/2
+
+void BM_lnorspace_invalidate(BMesh *bm, bool inval_all)
+{
+	if (inval_all || bm->totvertsel > CLEAR_SPACEARRAY_THRESHOLD(bm->totvert)) {
+		bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
+		return;
+	}
+	BMVert *v;
+	BMIter viter, fiter, liter;
+	BLI_bitmap *faces = BLI_BITMAP_NEW(bm->totface, __func__);
+
+	if (bm->elem_index_dirty & BM_FACE) {
+		BM_mesh_elem_index_ensure(bm, BM_FACE);
+	}
+
+	BM_ITER_MESH(v, &viter, bm, BM_VERTS_OF_MESH) {
+		if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+
+			BMFace *f;
+			BM_ITER_ELEM(f, &fiter, v, BM_FACES_OF_VERT) {
+				if (!BLI_BITMAP_TEST(faces, BM_elem_index_get(f))) {
+
+					BMLoop *l;
+					BM_ITER_ELEM(l, &liter, f, BM_LOOPS_OF_FACE) {
+						BM_elem_flag_enable(l, BM_ELEM_LNORSPACE);
+					}
+					BLI_BITMAP_ENABLE(faces, BM_elem_index_get(f));
+				}
+			}
+		}
+	}
+}
+
+void BM_lnorspace_rebuild(BMesh *bm, bool preserve_clnor)
+{
+	if (!(bm->spacearr_dirty & (BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL))) {
+		return;
+	}
+	BMFace *f;
+	BMLoop *l;
+	BMIter fiter, liter;
+
+	float(*r_lnors)[3] = MEM_callocN(sizeof(*r_lnors) * bm->totloop, "__func__");
+	float(*oldnors)[3] = MEM_mallocN(sizeof(*oldnors) * bm->totloop, "__func__");
+	int cd_loop_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
+
+	if (bm->elem_index_dirty & BM_LOOP) {
+		BM_mesh_elem_index_ensure(bm, BM_LOOP);
+	}
+
+	if (preserve_clnor) {
+		BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
+
+			BM_ITER_ELEM(l, &liter, f, BM_LOOPS_OF_FACE) {
+				if (BM_elem_flag_test(l, BM_ELEM_LNORSPACE))
+				{
+					short(*clnor)[2] = BM_ELEM_CD_GET_VOID_P(l, cd_loop_clnors_offset);
+					int l_index = BM_elem_index_get(l);
+
+					BKE_lnor_space_custom_data_to_normal(bm->bmspacearr.lspacearr[l_index], *clnor, oldnors[l_index]);
+				}
+			}
+		}
+	}
+	BM_loops_calc_normal_vcos(bm, NULL, NULL, NULL, true, M_PI, r_lnors, &bm->bmspacearr, NULL, cd_loop_clnors_offset, true);
+	MEM_freeN(r_lnors);
+
+	BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
+		BM_ITER_ELEM(l, &liter, f, BM_LOOPS_OF_FACE) {
+
+			if (BM_elem_flag_test(l, BM_ELEM_LNORSPACE)) {
+				if (preserve_clnor) {
+					short(*clnor)[2] = BM_ELEM_CD_GET_VOID_P(l, cd_loop_clnors_offset);
+					int l_index = BM_elem_index_get(l);
+					BKE_lnor_space_custom_normal_to_data(bm->bmspacearr.lspacearr[l_index], oldnors[l_index], *clnor);
+				}
+				BM_elem_flag_disable(l, BM_ELEM_LNORSPACE);
+			}
+		}
+	}
+	MEM_freeN(oldnors);
+	bm->spacearr_dirty &= ~(BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL);
+}
+
 static void UNUSED_FUNCTION(bm_mdisps_space_set)(Object *ob, BMesh *bm, int from, int to)
 {
 	/* switch multires data out of tangent space */
@@ -1094,6 +1194,9 @@ void bmesh_edit_end(BMesh *bm, BMOpTypeFlag type_flag)
 	if ((type_flag & BMO_OPTYPE_FLAG_SELECT_VALIDATE) == 0) {
 		bm->selected = select_history;
 	}
+	if (type_flag & BMO_OPTYPE_FLAG_INVALIDATE_NORMAL_SPACE) {
+		bm->spacearr_dirty |= BM_SPACEARR_DIRTY;
+	}
 }
 
 void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h
index 01f11f6f942..bf1a24d9ce4 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.h
+++ b/source/blender/bmesh/intern/bmesh_mesh.h
@@ -50,7 +50,11 @@ void BM_verts_calc_normal_vcos(BMesh *bm, const float (*fnos)[3], const float (*
 void BM_loops_calc_normal_vcos(
         BMesh *bm, const float (*vcos)[3], const float (*vnos)[3], const float (*pnos)[3],
         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);
+        struct MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], const int cd_loop_clnors_offset,
+		bool rebuild);
+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);
 
 void bmesh_edit_begin(BMesh *bm, const BMOpTypeFlag type_flag);
 void bmesh_edit_end(BMesh *bm, const BMOpTypeFlag type_flag);
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index d2f0fc1721c..3d78ef0dd40 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -116,7 +116,8 @@ static BMOpDefine bmo_smooth_vert_def = {
 	},
 	{{{'\0'}}},  /* no output */
 	bmo_smooth_vert_exec,
-	(BMO_OPTYPE_FLAG_NORMALS_CALC),
+	(BMO_OPTYPE_FLAG_NORMALS_CALC |
+	 BMO_OPTYPE_FLAG_INVALIDATE_NORMAL_SPACE),
 };
 
 /*
diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h
index 30cd1df9c4e..e894d81220e 100644
--- a/source/blender/bmesh/intern/bmesh_operator_api.h
+++ b/source/blender/bmesh/intern/bmesh_operator_api.h
@@ -244,6 +244,7 @@ typedef enum {
 	BMO_OPTYPE_FLAG_NORMALS_CALC        = (1 << 1),
 	BMO_OPTYPE_FLAG_SELECT_FLUSH        = (1 << 2),
 	BMO_OPTYPE_FLAG_SELECT_VALIDATE     = (1 << 3),
+	BMO_OPTYPE_FLAG_INVALIDATE_NORMAL_SPACE	= (1 << 4)
 } BMOpTypeFlag;
 
 typedef struct BMOperator {
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 1f90b60a1f5..c6a0dfd129d 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c


@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list