[Bf-blender-cvs] [3c6709a] master: Fix T37879: Default UV generation for mesh primitives.

Bastien Montagne noreply at git.blender.org
Sat Dec 5 00:52:56 CET 2015


Commit: 3c6709a63c267dc3cb3898efd9d6466c2300876c
Author: Bastien Montagne
Date:   Fri Dec 4 23:49:55 2015 +0100
Branches: master
https://developer.blender.org/rB3c6709a63c267dc3cb3898efd9d6466c2300876c

Fix T37879: Default UV generation for mesh primitives.

Adds default-generated UVs to mesh primitives (cone, cylinder, icosphere, uvsphere, cube, circle, grid)
when they are added to the scene, since some of them can be pretty awkward to unwrap manually.

Original patch: Liam Mitchell (CommanderCorianderSalamander).
Main review work: Campbell Barton (campbellbarton).
Finalization, fixes and cleanup: Bastien Montagne (mont29).

Reviewers: mont29, #mesh_modeling, campbellbarton

Reviewed By: mont29, campbellbarton

Subscribers: lkruel, campbellbarton, michaelknubben, kevindietrich

Maniphest Tasks: T37879

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

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

M	source/blender/bmesh/intern/bmesh_opdefines.c
M	source/blender/bmesh/intern/bmesh_operators.h
M	source/blender/bmesh/operators/bmo_primitive.c
M	source/blender/editors/include/ED_object.h
M	source/blender/editors/mesh/editmesh_add.c
M	source/blender/editors/object/object_add.c

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

diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index d92bdc6..72a8dac 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -1567,6 +1567,7 @@ static BMOpDefine bmo_create_grid_def = {
 	 {"y_segments",      BMO_OP_SLOT_INT},  /* number of y segments */
 	 {"size",            BMO_OP_SLOT_FLT},  /* size of the grid */
 	 {"matrix",          BMO_OP_SLOT_MAT},  /* matrix to multiply the new geometry with */
+	 {"calc_uvs",        BMO_OP_SLOT_BOOL}, /* calculate default UVs */
 	 {{'\0'}},
 	},
 	/* slots_out */
@@ -1590,6 +1591,7 @@ static BMOpDefine bmo_create_uvsphere_def = {
 	 {"v_segments",      BMO_OP_SLOT_INT}, /* number of v segment */
 	 {"diameter",        BMO_OP_SLOT_FLT}, /* diameter */
 	 {"matrix",          BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */
+	 {"calc_uvs",        BMO_OP_SLOT_BOOL}, /* calculate default UVs */
 	 {{'\0'}},
 	},
 	/* slots_out */
@@ -1612,6 +1614,7 @@ static BMOpDefine bmo_create_icosphere_def = {
 	{{"subdivisions",    BMO_OP_SLOT_INT}, /* how many times to recursively subdivide the sphere */
 	 {"diameter",        BMO_OP_SLOT_FLT}, /* diameter */
 	 {"matrix",          BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */
+	 {"calc_uvs",        BMO_OP_SLOT_BOOL}, /* calculate default UVs */
 	 {{'\0'}},
 	},
 	/* slots_out */
@@ -1658,6 +1661,7 @@ static BMOpDefine bmo_create_cone_def = {
 	 {"diameter2",       BMO_OP_SLOT_FLT},  /* diameter of the opposite */
 	 {"depth",           BMO_OP_SLOT_FLT},  /* distance between ends */
 	 {"matrix",          BMO_OP_SLOT_MAT},  /* matrix to multiply the new geometry with */
+	 {"calc_uvs",        BMO_OP_SLOT_BOOL}, /* calculate default UVs */
 	 {{'\0'}},
 	},
 	/* slots_out */
@@ -1680,6 +1684,7 @@ static BMOpDefine bmo_create_circle_def = {
 	 {"segments",        BMO_OP_SLOT_INT},
 	 {"diameter",        BMO_OP_SLOT_FLT},  /* diameter of one end */
 	 {"matrix",          BMO_OP_SLOT_MAT},  /* matrix to multiply the new geometry with */
+	 {"calc_uvs",        BMO_OP_SLOT_BOOL}, /* calculate default UVs */
 	 {{'\0'}},
 	},
 	/* slots_out */
@@ -1701,6 +1706,7 @@ static BMOpDefine bmo_create_cube_def = {
 	/* slots_in */
 	{{"size",            BMO_OP_SLOT_FLT},  /* size of the cube */
 	 {"matrix",          BMO_OP_SLOT_MAT},  /* matrix to multiply the new geometry with */
+	 {"calc_uvs",        BMO_OP_SLOT_BOOL}, /* calculate default UVs */
 	 {{'\0'}},
 	},
 	/* slots_out */
diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h
index d9961e5..0a4fb1d 100644
--- a/source/blender/bmesh/intern/bmesh_operators.h
+++ b/source/blender/bmesh/intern/bmesh_operators.h
@@ -141,6 +141,14 @@ void BM_mesh_esubdivide(
         const short use_only_quads,
         const int seed);
 
+void BM_mesh_calc_uvs_grid(BMesh *bm, const unsigned int x_segments, const unsigned int y_segments, const short oflag);
+void BM_mesh_calc_uvs_sphere(BMesh *bm, const short oflag);
+void BM_mesh_calc_uvs_circle(BMesh *bm, float mat[4][4], const float radius, const short oflag);
+void BM_mesh_calc_uvs_cone(
+        BMesh *bm, float mat[4][4],
+        const float radius_top, const float radius_bottom, const int segments, const bool cap_ends, const short oflag);
+void BM_mesh_calc_uvs_cube(BMesh *bm, const short oflag);
+
 #include "intern/bmesh_operator_api_inline.h"
 
 #endif /* __BMESH_OPERATORS_H__ */
diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c
index 2108a2c..944f26e 100644
--- a/source/blender/bmesh/operators/bmo_primitive.c
+++ b/source/blender/bmesh/operators/bmo_primitive.c
@@ -30,6 +30,10 @@
 
 #include "BLI_math.h"
 
+#include "BKE_customdata.h"
+
+#include "DNA_meshdata_types.h"
+
 #include "bmesh.h"
 #include "intern/bmesh_operators_private.h"
 
@@ -235,6 +239,7 @@ void bmo_create_grid_exec(BMesh *bm, BMOperator *op)
 	const unsigned int ytot = max_ii(2, BMO_slot_int_get(op->slots_in, "y_segments"));
 	const float xtot_inv2 = 2.0f / (xtot - 1);
 	const float ytot_inv2 = 2.0f / (ytot - 1);
+	const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs");
 
 	BMVert **varr;
 	BMVert *vquad[4];
@@ -265,17 +270,86 @@ void bmo_create_grid_exec(BMesh *bm, BMOperator *op)
 
 	for (y = 1; y < ytot; y++) {
 		for (x = 1; x < xtot; x++) {
+			BMFace *f;
+
 			vquad[0] = varr[XY(x - 1, y - 1)];
 			vquad[1] = varr[XY(x,     y - 1)];
 			vquad[2] = varr[XY(x,         y)];
 			vquad[3] = varr[XY(x - 1,     y)];
 
-			BM_face_create_verts(bm, vquad, 4, NULL, BM_CREATE_NOP, true);
+			f = BM_face_create_verts(bm, vquad, 4, NULL, BM_CREATE_NOP, true);
+			if (calc_uvs) {
+				BMO_elem_flag_enable(bm, f, FACE_MARK);
+			}
 		}
 	}
 
 #undef XY
 
+	if (calc_uvs) {
+		BM_mesh_calc_uvs_grid(bm, xtot, ytot, FACE_MARK);
+	}
+}
+
+/**
+ * Fills first available UVmap with grid-like UVs for all faces OpFlag-ged by given flag.
+ *
+ * \param bm The BMesh to operate on
+ * \param x_segments The x-resolution of the grid
+ * \param y_segments The y-resolution of the grid
+ * \param oflag The flag to check faces with.
+ */
+void BM_mesh_calc_uvs_grid(BMesh *bm, const unsigned int x_segments, const unsigned int y_segments, const short oflag)
+{
+	BMFace *f;
+	BMLoop *l;
+	BMIter iter, liter;
+
+	const float dx = 1.0f / (float)(x_segments - 1);
+	const float dy = 1.0f / (float)(y_segments - 1);
+	float x = 0.0f;
+	float y = 0.0f;
+
+	const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+
+	int loop_index;
+
+	BLI_assert(cd_loop_uv_offset != -1);
+
+	BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+		if (!BMO_elem_flag_test(bm, f, oflag))
+			continue;
+
+		BM_ITER_ELEM_INDEX (l, &liter, f, BM_LOOPS_OF_FACE, loop_index) {
+			MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+
+			switch (loop_index) {
+				case 0:
+					x += dx;
+					break;
+				case 1:
+					y += dy;
+					break;
+				case 2:
+					x -= dx;
+					break;
+				case 3:
+					y -= dy;
+					break;
+				default:
+					break;
+			}
+
+			luv->uv[0] = x;
+			luv->uv[1] = y;
+		}
+
+		x += dx;
+		if (x >= 1.0f) {
+			x = 0.0f;
+			y += dy;
+		}
+	}
 }
 
 void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op)
@@ -283,6 +357,7 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op)
 	const float dia = BMO_slot_float_get(op->slots_in, "diameter");
 	const int seg = BMO_slot_int_get(op->slots_in, "u_segments");
 	const int tot = BMO_slot_int_get(op->slots_in, "v_segments");
+	const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs");
 
 	BMOperator bmop, prevop;
 	BMVert *eve, *preveve;
@@ -358,6 +433,31 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op)
 		BMO_op_callf(bm, op->flag, "remove_doubles verts=%fv dist=%f", VERT_MARK, min_ff(len, len2) / 3.0f);
 	}
 
+	if (calc_uvs) {
+		BMFace *f;
+		BMLoop *l;
+		BMIter fiter, liter;
+
+		/* We cannot tag faces for UVs computing above, so we have to do it now, based on all its vertices
+		 * being tagged. */
+		BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+			bool valid = true;
+
+			BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+				if (!BMO_elem_flag_test(bm, l->v, VERT_MARK)) {
+					valid = false;
+					break;
+				}
+			}
+
+			if (valid) {
+				BMO_elem_flag_enable(bm, f, FACE_MARK);
+			}
+		}
+
+		BM_mesh_calc_uvs_sphere(bm, FACE_MARK);
+	}
+
 	/* and now do imat */
 	BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
 		if (BMO_elem_flag_test(bm, eve, VERT_MARK)) {
@@ -373,6 +473,7 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op)
 	const float dia = BMO_slot_float_get(op->slots_in, "diameter");
 	const float dia_div = dia / 200.0f;
 	const int subdiv = BMO_slot_int_get(op->slots_in, "subdivisions");
+	const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs");
 
 	BMVert *eva[12];
 	BMVert *v;
@@ -431,6 +532,30 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op)
 		BMO_op_finish(bm, &bmop);
 	}
 
+	if (calc_uvs) {
+		BMFace *f;
+		BMIter fiter;
+
+		/* We cannot tag faces for UVs computing above, so we have to do it now, based on all its vertices
+		 * being tagged. */
+		BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+			bool valid = true;
+
+			BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+				if (!BMO_elem_flag_test(bm, l->v, VERT_MARK)) {
+					valid = false;
+					break;
+				}
+			}
+
+			if (valid) {
+				BMO_elem_flag_enable(bm, f, FACE_MARK);
+			}
+		}
+
+		BM_mesh_calc_uvs_sphere(bm, FACE_MARK);
+	}
+
 	/* must transform after because of sphere subdivision */
 	BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
 		if (BMO_elem_flag_test(bm, v, VERT_MARK)) {
@@ -441,6 +566,75 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op)
 	BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
 }
 
+static void bm_mesh_calc_uvs_sphere_face(BMFace *f, float mat_rot[3][3], const int cd_loop_uv_offset)
+{
+	float *uvs[4];
+	BMLoop *l;
+	BMIter iter;
+	float dx;
+	int loop_index, loop_index_max_x;
+
+	BLI_assert(f->len <= 4);
+
+	BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, loop_index) {
+		MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+		float vco[3];
+
+		mul_v3_m3v3(vco, mat_rot, l->v->co);
+		map_to_sphere(&luv->uv[0], &luv->uv[1], vco[0], vco[1], vco[2]);
+
+		uvs[loop_index] = luv->uv;
+	}
+
+	/* Fix awkwardly-wrapping UVs */
+	loop_index_max_x = 0;
+	for (loop_index = 1; loop_index < f->len; loop_index++) {
+		if (uvs[loop_index][0] > uvs[loop_index_max_x][0]) {
+			loop_index_max_x = loop_index;
+		}
+	}
+
+	for (loop_index = 0; loop_index < f->len; loop_index++) {
+		if (loop_index != loop_index_max_x) {
+			dx = uvs[loop_index_max_x][0] - uvs[loop_index][0];
+			if (dx > 0.5f) {
+				uvs[loop_index][0] += 1.0f;
+			}
+		}
+	}
+}
+
+/**
+ * Fills first available UVmap with spherical projected UVs for all faces OpFlag-ged by given flag.
+ *
+ * \param bm The BMesh to operate on
+ * \param oflag The flag to check faces with.
+ */
+void BM_mesh_calc_uvs_sphere(BMesh *bm, const short oflag)
+{
+	BMFace *f;
+	BMIter iter;
+
+	const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldat

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list