[Bf-blender-cvs] [877f441] master: BKE_mesh: add polygon flipping tools.

Bastien Montagne noreply at git.blender.org
Sun Feb 28 15:54:10 CET 2016


Commit: 877f44162853664791f0ff4fa93f856384d0eed7
Author: Bastien Montagne
Date:   Sun Feb 28 15:29:56 2016 +0100
Branches: master
https://developer.blender.org/rB877f44162853664791f0ff4fa93f856384d0eed7

BKE_mesh: add polygon flipping tools.

Those new functions invert the winding of polygons, effectively inverting their normals.

A helper was also added to allow swapping two items in customdata layers.

Being able to invert normals outside of BMesh area is very important in several places,
like IO scripts or customnormals modifiers...

Reviewers: campbellbarton

Differential Revision: https://developer.blender.org/D1814

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

M	source/blender/blenkernel/BKE_customdata.h
M	source/blender/blenkernel/BKE_mesh.h
M	source/blender/blenkernel/intern/customdata.c
M	source/blender/blenkernel/intern/mesh_evaluate.c
M	source/blender/makesrna/intern/rna_mesh.c
M	source/blender/makesrna/intern/rna_mesh_api.c

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

diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h
index 0b248be..17ad51a 100644
--- a/source/blender/blenkernel/BKE_customdata.h
+++ b/source/blender/blenkernel/BKE_customdata.h
@@ -260,6 +260,8 @@ void CustomData_bmesh_interp(
  * faces an array of length 4 */
 void CustomData_swap_corners(struct CustomData *data, int index, const int *corner_indices);
 
+void CustomData_swap(struct CustomData *data, const int index_a, const int index_b);
+
 /* gets a pointer to the data element at index from the first layer of type
  * returns NULL if there is no layer of type
  */
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index f35613f..b85c605 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -317,6 +317,9 @@ void BKE_mesh_convert_mfaces_to_mpolys_ex(
         int *r_totloop, int *r_totpoly,
         struct MLoop **r_mloop, struct MPoly **r_mpoly);
 
+void BKE_mesh_polygon_flip(struct MPoly *mpoly, struct MLoop *mloop, struct CustomData *ldata);
+void BKE_mesh_polygons_flip(struct MPoly *mpoly, struct MLoop *mloop, struct CustomData *ldata, int totpoly);
+
 /* flush flags */
 void BKE_mesh_flush_hidden_from_verts_ex(
         const struct MVert *mvert,
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index c120509..1ed7c98 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -2356,6 +2356,35 @@ void CustomData_swap_corners(struct CustomData *data, int index, const int *corn
 	}
 }
 
+/**
+ * Swap two items of given custom data, in all available layers.
+ */
+void CustomData_swap(struct CustomData *data, const int index_a, const int index_b)
+{
+	int i;
+	char buff_static[256];
+
+	if (index_a == index_b) {
+		return;
+	}
+
+	for (i = 0; i < data->totlayer; ++i) {
+		const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type);
+		const size_t size = typeInfo->size;
+		const size_t offset_a = size * index_a;
+		const size_t offset_b = size * index_b;
+
+		void *buff = size <= sizeof(buff_static) ? buff_static : MEM_mallocN(size, __func__);
+		memcpy(buff, POINTER_OFFSET(data->layers[i].data, offset_a), size);
+		memcpy(POINTER_OFFSET(data->layers[i].data, offset_a), POINTER_OFFSET(data->layers[i].data, offset_b), size);
+		memcpy(POINTER_OFFSET(data->layers[i].data, offset_b), buff, size);
+
+		if (buff != buff_static) {
+			MEM_freeN(buff);
+		}
+	}
+}
+
 void *CustomData_get(const CustomData *data, int index, int type)
 {
 	int offset;
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index e3b9b21..9fdd541 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -3200,6 +3200,57 @@ void BKE_mesh_convert_mfaces_to_mpolys_ex(ID *id, CustomData *fdata, CustomData
 }
 /** \} */
 
+/**
+ * Flip (invert winding of) the given \a mpoly, i.e. reverse order of its loops
+ * (keeping the same vertex as 'start point').
+ *
+ * \param mpoly the polygon to flip.
+ * \param mloop the full loops array.
+ * \param ldata the loops custom data.
+ */
+void BKE_mesh_polygon_flip(MPoly *mpoly, MLoop *mloop, CustomData *ldata)
+{
+	int loopstart = mpoly->loopstart;
+	int loopend = loopstart + mpoly->totloop - 1;
+	const bool loops_in_ldata = (CustomData_get_layer(ldata, CD_MLOOP) == mloop);
+
+	/* Note that we keep same start vertex for flipped face. */
+
+	/* We also have to update loops' edge
+	 * (they ell get ther original 'other edge', that is, the original edge of their original previous loop)... */
+	unsigned int prev_edge_index = mloop[loopstart].e;
+	mloop[loopstart].e = mloop[loopend].e;
+
+	for (loopstart++; loopend > loopstart; loopstart++, loopend--) {
+		mloop[loopend].e = mloop[loopend - 1].e;
+		SWAP(unsigned int, mloop[loopstart].e, prev_edge_index);
+
+		if (!loops_in_ldata) {
+			SWAP(MLoop, mloop[loopstart], mloop[loopend]);
+		}
+		CustomData_swap(ldata, loopstart, loopend);
+	}
+	/* Even if we did not swap the other 'pivot' loop, we need to set its swapped edge. */
+	if (loopstart == loopend) {
+		mloop[loopstart].e = prev_edge_index;
+	}
+}
+
+/**
+ * Flip (invert winding of) all polygons (used to inverse their normals).
+ *
+ * \note Invalidates tessalation, caller must handle that.
+ */
+void BKE_mesh_polygons_flip(
+        MPoly *mpoly, MLoop *mloop, CustomData *ldata, int totpoly)
+{
+	MPoly *mp;
+	int i;
+
+	for (mp = mpoly, i = 0; i < totpoly; mp++, i++) {
+		BKE_mesh_polygon_flip(mp, mloop, ldata);
+	}
+}
 
 /* -------------------------------------------------------------------- */
 
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index 686f833..1d73486 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -418,6 +418,14 @@ static float rna_MeshPolygon_area_get(PointerRNA *ptr)
 	return BKE_mesh_calc_poly_area(mp, me->mloop + mp->loopstart, me->mvert);
 }
 
+static void rna_MeshPolygon_flip(ID *id, MPoly *mp)
+{
+	Mesh *me = (Mesh *)id;
+
+	BKE_mesh_polygon_flip(mp, me->mloop, &me->ldata);
+	BKE_mesh_tessface_clear(me);
+}
+
 static void rna_MeshTessFace_normal_get(PointerRNA *ptr, float *values)
 {
 	Mesh *me = rna_mesh(ptr);
@@ -2138,6 +2146,7 @@ static void rna_def_mpolygon(BlenderRNA *brna)
 {
 	StructRNA *srna;
 	PropertyRNA *prop;
+	FunctionRNA *func;
 
 	srna = RNA_def_struct(brna, "MeshPolygon", NULL);
 	RNA_def_struct_sdna(srna, "MPoly");
@@ -2216,6 +2225,11 @@ static void rna_def_mpolygon(BlenderRNA *brna)
 	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
 	RNA_def_property_int_funcs(prop, "rna_MeshPolygon_index_get", NULL, NULL);
 	RNA_def_property_ui_text(prop, "Index", "Index of this polygon");
+
+	func = RNA_def_function(srna, "flip", "rna_MeshPolygon_flip");
+	RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+	RNA_def_function_ui_description(func, "Invert winding of this polygon (flip its normal)");
+
 }
 
 /* mesh.loop_uvs */
diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c
index 1459157..a3bc21b 100644
--- a/source/blender/makesrna/intern/rna_mesh_api.c
+++ b/source/blender/makesrna/intern/rna_mesh_api.c
@@ -200,6 +200,15 @@ static void rna_Mesh_transform(Mesh *mesh, float *mat, int shape_keys)
 	DAG_id_tag_update(&mesh->id, 0);
 }
 
+static void rna_Mesh_flip_normals(Mesh *mesh)
+{
+	BKE_mesh_polygons_flip(mesh->mpoly, mesh->mloop, &mesh->ldata, mesh->totpoly);
+	BKE_mesh_tessface_clear(mesh);
+	BKE_mesh_calc_normals(mesh);
+
+	DAG_id_tag_update(&mesh->id, 0);
+}
+
 #else
 
 void RNA_api_mesh(StructRNA *srna)
@@ -209,11 +218,16 @@ void RNA_api_mesh(StructRNA *srna)
 	const int normals_array_dim[] = {1, 3};
 
 	func = RNA_def_function(srna, "transform", "rna_Mesh_transform");
-	RNA_def_function_ui_description(func, "Transform mesh vertices by a matrix");
+	RNA_def_function_ui_description(func, "Transform mesh vertices by a matrix "
+	                                      "(Warning: inverts normals if matrix is negative)");
 	parm = RNA_def_float_matrix(func, "matrix", 4, 4, NULL, 0.0f, 0.0f, "", "Matrix", 0.0f, 0.0f);
 	RNA_def_property_flag(parm, PROP_REQUIRED);
 	RNA_def_boolean(func, "shape_keys", 0, "", "Transform Shape Keys");
 
+	func = RNA_def_function(srna, "flip_normals", "rna_Mesh_flip_normals");
+	RNA_def_function_ui_description(func, "Invert winding of all polygons "
+	                                      "(clears tessellation, does not handle custom normals)");
+
 	func = RNA_def_function(srna, "calc_normals", "BKE_mesh_calc_normals");
 	RNA_def_function_ui_description(func, "Calculate vertex normals");




More information about the Bf-blender-cvs mailing list