Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastien Montagne <montagne29@wanadoo.fr>2016-02-28 17:29:56 +0300
committerBastien Montagne <montagne29@wanadoo.fr>2016-02-28 17:29:56 +0300
commit877f44162853664791f0ff4fa93f856384d0eed7 (patch)
treeed924b94bebd5cec0ad5455b7e90d481b63ad80a
parentea76ec2866d11156b689287f4190dfe4e79314b2 (diff)
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
-rw-r--r--source/blender/blenkernel/BKE_customdata.h2
-rw-r--r--source/blender/blenkernel/BKE_mesh.h3
-rw-r--r--source/blender/blenkernel/intern/customdata.c29
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c51
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c14
-rw-r--r--source/blender/makesrna/intern/rna_mesh_api.c16
6 files changed, 114 insertions, 1 deletions
diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h
index 0b248be9780..17ad51a7a16 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 f35613f8bf7..b85c605f231 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 c120509b769..1ed7c989075 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 e3b9b21f341..9fdd541813a 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 686f8331ac4..1d734864833 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 1459157112e..a3bc21b0170 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");