[Bf-blender-cvs] [5d70e847dd6] blender2.8: Fix T51604: Support Auto-Smooth in Edit-Mesh and allocate loop_normals in MeshRenderData instead of CustomData

Germano noreply at git.blender.org
Mon Nov 6 17:14:18 CET 2017


Commit: 5d70e847dd6f5182fa67c3b08260fbb5366009b5
Author: Germano
Date:   Mon Nov 6 14:14:07 2017 -0200
Branches: blender2.8
https://developer.blender.org/rB5d70e847dd6f5182fa67c3b08260fbb5366009b5

Fix T51604: Support Auto-Smooth in Edit-Mesh
and allocate loop_normals in MeshRenderData instead of CustomData

Differential Revision: D2907

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

M	source/blender/draw/intern/draw_cache_impl_mesh.c

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

diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index 615b79328b6..8cd0c13faec 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -339,6 +339,33 @@ static void mesh_cd_calc_used_gpu_layers(
 	}
 }
 
+
+static void mesh_render_calc_normals_loop_and_poly(const Mesh *me, const float split_angle, MeshRenderData *rdata)
+{
+	BLI_assert((me->flag & ME_AUTOSMOOTH) != 0);
+
+	int totloop = me->totloop;
+	int totpoly = me->totpoly;
+	float (*loop_normals)[3] = MEM_mallocN(sizeof(*loop_normals) * totloop, __func__);
+	float (*poly_normals)[3] = MEM_mallocN(sizeof(*poly_normals) * totpoly, __func__);
+	short (*clnors)[2] = CustomData_get_layer(&me->ldata, CD_CUSTOMLOOPNORMAL);
+
+	BKE_mesh_calc_normals_poly(
+	        me->mvert, NULL, me->totvert,
+	        me->mloop, me->mpoly, totloop, totpoly, poly_normals, false);
+
+	BKE_mesh_normals_loop_split(
+	        me->mvert, me->totvert, me->medge, me->totedge,
+	        me->mloop, loop_normals, totloop, me->mpoly, poly_normals, totpoly,
+	        true, split_angle, NULL, clnors, NULL);
+
+	rdata->loop_len = totloop;
+	rdata->poly_len = totpoly;
+	rdata->loop_normals = loop_normals;
+	rdata->poly_normals = poly_normals;
+}
+
+
 /**
  * TODO(campbell): 'gpumat_array' may include materials linked to the object.
  * While not default, object materials should be supported.
@@ -354,6 +381,9 @@ static MeshRenderData *mesh_render_data_create_ex(
 
 	CustomData_reset(&rdata->cd.output.ldata);
 
+	const bool is_auto_smooth = (me->flag & ME_AUTOSMOOTH) != 0;
+	const float split_angle = is_auto_smooth ? me->smoothresh : (float)M_PI;
+
 	if (me->edit_btmesh) {
 		BMEditMesh *embm = me->edit_btmesh;
 		BMesh *bm = embm->bm;
@@ -374,7 +404,12 @@ static MeshRenderData *mesh_render_data_create_ex(
 			rdata->tri_len = embm->tottri;
 		}
 		if (types & MR_DATATYPE_LOOP) {
-			rdata->loop_len = bm->totloop;
+			int totloop = bm->totloop;
+			if (is_auto_smooth) {
+				rdata->loop_normals = MEM_mallocN(sizeof(*rdata->loop_normals) * totloop, __func__);
+				BM_loops_calc_normal_vcos(bm, NULL, NULL, NULL, true, split_angle, rdata->loop_normals, NULL, NULL, -1);
+			}
+			rdata->loop_len = totloop;
 			bm_ensure_types |= BM_LOOP;
 		}
 		if (types & MR_DATATYPE_POLY) {
@@ -447,12 +482,12 @@ static MeshRenderData *mesh_render_data_create_ex(
 			BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, rdata->mlooptri);
 		}
 		if (types & MR_DATATYPE_LOOP) {
-			if (me->flag & ME_AUTOSMOOTH) {
-				BKE_mesh_calc_normals_split(me);
-				rdata->loop_normals = CustomData_get_layer(&me->ldata, CD_NORMAL);
-			}
 			rdata->loop_len = me->totloop;
 			rdata->mloop = CustomData_get_layer(&me->ldata, CD_MLOOP);
+
+			if (is_auto_smooth) {
+				mesh_render_calc_normals_loop_and_poly(me, split_angle, rdata);
+			}
 		}
 		if (types & MR_DATATYPE_POLY) {
 			rdata->poly_len = me->totpoly;
@@ -538,8 +573,6 @@ static MeshRenderData *mesh_render_data_create_ex(
 			rdata->orco = NULL;
 		}
 
-		const bool is_auto_smooth = (me->flag & ME_AUTOSMOOTH) != 0;
-
 		/* don't access mesh directly, instead use vars taken from BMesh or Mesh */
 #define me DONT_USE_THIS
 #ifdef  me /* quiet warning */
@@ -665,8 +698,10 @@ static MeshRenderData *mesh_render_data_create_ex(
 				BMesh *bm = em->bm;
 
 				if (is_auto_smooth && rdata->loop_normals == NULL) {
-					/* TODO: split normals, see below */
-					rdata->loop_normals = CustomData_get_layer(cd_ldata, CD_NORMAL);
+					/* Should we store the previous array of `loop_normals` in somewhere? */
+					rdata->loop_len = bm->totloop;
+					rdata->loop_normals = MEM_mallocN(sizeof(*rdata->loop_normals) * rdata->loop_len, __func__);
+					BM_loops_calc_normal_vcos(bm, NULL, NULL, NULL, true, split_angle, rdata->loop_normals, NULL, NULL, -1);
 				}
 
 				bool calc_active_tangent = false;
@@ -683,10 +718,8 @@ static MeshRenderData *mesh_render_data_create_ex(
 #undef me
 
 				if (is_auto_smooth && rdata->loop_normals == NULL) {
-					if (!CustomData_has_layer(cd_ldata, CD_NORMAL)) {
-						BKE_mesh_calc_normals_split(me);
-					}
-					rdata->loop_normals = CustomData_get_layer(cd_ldata, CD_NORMAL);
+					/* Should we store the previous array of `loop_normals` in CustomData? */
+					mesh_render_calc_normals_loop_and_poly(me, split_angle, rdata);
 				}
 
 				bool calc_active_tangent = false;
@@ -777,6 +810,7 @@ static void mesh_render_data_free(MeshRenderData *rdata)
 	MEM_SAFE_FREE(rdata->loose_edges);
 	MEM_SAFE_FREE(rdata->edges_adjacent_polys);
 	MEM_SAFE_FREE(rdata->mlooptri);
+	MEM_SAFE_FREE(rdata->loop_normals);
 	MEM_SAFE_FREE(rdata->poly_normals);
 	MEM_SAFE_FREE(rdata->poly_normals_pack);
 	MEM_SAFE_FREE(rdata->vert_normals_pack);
@@ -1981,12 +2015,18 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_pos_and_normals_ex(
 		GWN_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
 		GWN_vertbuf_attr_get_raw_data(vbo, attr_id.nor, &nor_step);
 
+		float (*lnors)[3] = rdata->loop_normals;
+
 		if (rdata->edit_bmesh) {
-			mesh_render_data_ensure_poly_normals_pack(rdata);
-			mesh_render_data_ensure_vert_normals_pack(rdata);
+			Gwn_PackedNormal *pnors_pack, *vnors_pack;
 
-			Gwn_PackedNormal *pnors_pack = rdata->poly_normals_pack;
-			Gwn_PackedNormal *vnors_pack = rdata->vert_normals_pack;
+			if (lnors == NULL) {
+				mesh_render_data_ensure_poly_normals_pack(rdata);
+				mesh_render_data_ensure_vert_normals_pack(rdata);
+
+				pnors_pack = rdata->poly_normals_pack;
+				vnors_pack = rdata->vert_normals_pack;
+			}
 
 			for (int i = 0; i < tri_len; i++) {
 				const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[i];
@@ -1997,15 +2037,15 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_pos_and_normals_ex(
 					continue;
 				}
 
-				const uint vtri[3] = {
-					BM_elem_index_get(bm_looptri[0]->v),
-					BM_elem_index_get(bm_looptri[1]->v),
-					BM_elem_index_get(bm_looptri[2]->v),
-				};
-
-				if (BM_elem_flag_test(bm_face, BM_ELEM_SMOOTH)) {
+				if (lnors) {
+					for (uint t = 0; t < 3; t++) {
+						const float *nor = lnors[BM_elem_index_get(bm_looptri[t])];
+						*((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = GWN_normal_convert_i10_v3(nor);
+					}
+				}
+				else if (BM_elem_flag_test(bm_face, BM_ELEM_SMOOTH)) {
 					for (uint t = 0; t < 3; t++) {
-						*((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = vnors_pack[vtri[t]];
+						*((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = vnors_pack[BM_elem_index_get(bm_looptri[t]->v)];
 					}
 				}
 				else {
@@ -2021,7 +2061,6 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_pos_and_normals_ex(
 			}
 		}
 		else {
-			float (*lnors)[3] = rdata->loop_normals;
 			if (lnors == NULL) {
 				/* Use normals from vertex. */
 				mesh_render_data_ensure_poly_normals_pack(rdata);



More information about the Bf-blender-cvs mailing list