[Bf-blender-cvs] [781995a09c0] blender2.8: Edit UVs: Refactor drawing Edit UV in Image Editor

Clément Foucault noreply at git.blender.org
Mon Oct 1 15:20:56 CEST 2018


Commit: 781995a09c0b52ad2fd073510c2f7dc52383d461
Author: Clément Foucault
Date:   Sat Sep 29 19:42:09 2018 +0200
Branches: blender2.8
https://developer.blender.org/rB781995a09c0b52ad2fd073510c2f7dc52383d461

Edit UVs: Refactor drawing Edit UV in Image Editor

NOTE: This commit only concern edit UVs and not the "shadow" mesh displayed
when texture painting. This will be address in a future commit.

We now cache the uv mesh in the mesh batch cache and only reupload data on
changes.

Update could be more granular (and a bit faster) but it's not our main
concern ATM.

This should fix problem caused by the IMM api used to draw large meshes.
This makes performance skyrocket compared to previous implementation.
There is still a big CPU bottleneck when not in sync selection mode but it
is not related to the drawing function directly.

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

M	source/blender/draw/intern/draw_cache_impl.h
M	source/blender/draw/intern/draw_cache_impl_mesh.c
M	source/blender/editors/uvedit/uvedit_draw.c
M	source/blender/gpu/CMakeLists.txt
M	source/blender/gpu/GPU_shader.h
M	source/blender/gpu/intern/gpu_shader.c
A	source/blender/gpu/shaders/gpu_shader_2D_edituvs_edges_vert.glsl
A	source/blender/gpu/shaders/gpu_shader_2D_edituvs_facedots_vert.glsl
A	source/blender/gpu/shaders/gpu_shader_2D_edituvs_faces_vert.glsl
A	source/blender/gpu/shaders/gpu_shader_2D_edituvs_points_vert.glsl
A	source/blender/gpu/shaders/gpu_shader_2D_edituvs_stretch_vert.glsl
A	source/blender/gpu/shaders/gpu_shader_point_varying_color_varying_outline_aa_frag.glsl

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

diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h
index 4bd0046a48a..9ce994adbc0 100644
--- a/source/blender/draw/intern/draw_cache_impl.h
+++ b/source/blender/draw/intern/draw_cache_impl.h
@@ -36,6 +36,7 @@ struct ListBase;
 struct ModifierData;
 struct ParticleSystem;
 struct PTCacheEdit;
+struct SpaceImage;
 
 struct Curve;
 struct Lattice;
@@ -156,6 +157,20 @@ void DRW_mesh_batch_cache_get_wireframes_face_texbuf(
 
 void DRW_mesh_cache_sculpt_coords_ensure(struct Mesh *me);
 
+enum {
+	UVEDIT_EDGES          = (1 << 0),
+	UVEDIT_DATA           = (1 << 1),
+	UVEDIT_FACEDOTS       = (1 << 2),
+	UVEDIT_FACES          = (1 << 3),
+	UVEDIT_STRETCH_ANGLE  = (1 << 4),
+	UVEDIT_STRETCH_AREA   = (1 << 5),
+	UVEDIT_SYNC_SEL       = (1 << 6),
+};
+
+void DRW_mesh_cache_uvedit(
+        struct Object *me, struct SpaceImage *sima, struct Scene *scene, uchar state,
+        struct GPUBatch **faces, struct GPUBatch **edges, struct GPUBatch **verts, struct GPUBatch **facedots);
+
 /* Edit mesh bitflags (is this the right place?) */
 
 enum {
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index 6a324aa078f..9d3543a0d20 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -31,6 +31,7 @@
 
 #include "MEM_guardedalloc.h"
 
+#include "BLI_buffer.h"
 #include "BLI_utildefines.h"
 #include "BLI_math_vector.h"
 #include "BLI_math_bits.h"
@@ -42,6 +43,7 @@
 #include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
 #include "DNA_object_types.h"
+#include "DNA_space_types.h"
 
 #include "BKE_customdata.h"
 #include "BKE_deform.h"
@@ -60,6 +62,10 @@
 
 #include "DRW_render.h"
 
+#include "ED_image.h"
+#include "ED_mesh.h"
+#include "ED_uvedit.h"
+
 #include "draw_cache_impl.h"  /* own include */
 
 static void mesh_batch_cache_clear(Mesh *me);
@@ -1672,6 +1678,24 @@ typedef struct MeshBatchCache {
 	GPUBatch *overlay_weight_verts;
 	GPUBatch *overlay_paint_edges;
 
+	/* 2D/UV edit */
+	GPUVertBuf *edituv_pos;
+	GPUVertBuf *edituv_area;
+	GPUVertBuf *edituv_angle;
+	GPUVertBuf *edituv_data;
+
+	GPUIndexBuf *edituv_visible_faces;
+	GPUIndexBuf *edituv_visible_edges;
+
+	GPUBatch *edituv_faces_strech_area;
+	GPUBatch *edituv_faces_strech_angle;
+	GPUBatch *edituv_faces;
+	GPUBatch *edituv_edges;
+	GPUBatch *edituv_verts;
+	GPUBatch *edituv_facedots;
+
+	char edituv_state;
+
 	/* arrays of bool uniform names (and value) that will be use to
 	 * set srgb conversion for auto attribs.*/
 	char *auto_layer_names;
@@ -1807,6 +1831,26 @@ static void mesh_batch_cache_discard_shaded_tri(MeshBatchCache *cache)
 	MEM_SAFE_FREE(cache->auto_layer_is_srgb);
 }
 
+static void mesh_batch_cache_discard_uvedit(MeshBatchCache *cache)
+{
+	GPU_VERTBUF_DISCARD_SAFE(cache->edituv_pos);
+	GPU_VERTBUF_DISCARD_SAFE(cache->edituv_area);
+	GPU_VERTBUF_DISCARD_SAFE(cache->edituv_angle);
+	GPU_VERTBUF_DISCARD_SAFE(cache->edituv_data);
+
+	GPU_INDEXBUF_DISCARD_SAFE(cache->edituv_visible_faces);
+	GPU_INDEXBUF_DISCARD_SAFE(cache->edituv_visible_edges);
+
+	GPU_BATCH_DISCARD_SAFE(cache->edituv_faces_strech_area);
+	GPU_BATCH_DISCARD_SAFE(cache->edituv_faces_strech_angle);
+	GPU_BATCH_DISCARD_SAFE(cache->edituv_faces);
+	GPU_BATCH_DISCARD_SAFE(cache->edituv_edges);
+	GPU_BATCH_DISCARD_SAFE(cache->edituv_verts);
+	GPU_BATCH_DISCARD_SAFE(cache->edituv_facedots);
+
+	cache->edituv_state = 0;
+}
+
 void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode)
 {
 	MeshBatchCache *cache = me->runtime.batch_cache;
@@ -1833,12 +1877,15 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode)
 			GPU_BATCH_DISCARD_SAFE(cache->facedot_with_select_id);
 			GPU_BATCH_DISCARD_SAFE(cache->edges_with_select_id);
 			GPU_BATCH_DISCARD_SAFE(cache->verts_with_select_id);
+			/* Because visible UVs depends on edit mode selection, discard everything. */
+			mesh_batch_cache_discard_uvedit(cache);
 			break;
 		case BKE_MESH_BATCH_DIRTY_ALL:
 			cache->is_dirty = true;
 			break;
 		case BKE_MESH_BATCH_DIRTY_SHADING:
 			mesh_batch_cache_discard_shaded_tri(cache);
+			mesh_batch_cache_discard_uvedit(cache);
 			break;
 		case BKE_MESH_BATCH_DIRTY_SCULPT_COORDS:
 			cache->is_sculpt_points_tag = true;
@@ -1952,6 +1999,8 @@ static void mesh_batch_cache_clear(Mesh *me)
 
 	mesh_batch_cache_discard_shaded_tri(cache);
 
+	mesh_batch_cache_discard_uvedit(cache);
+
 	if (cache->texpaint_triangles) {
 		for (int i = 0; i < cache->mat_len; ++i) {
 			GPU_BATCH_DISCARD_SAFE(cache->texpaint_triangles[i]);
@@ -4528,4 +4577,416 @@ void DRW_mesh_cache_sculpt_coords_ensure(Mesh *me)
 	}
 }
 
+static uchar mesh_batch_cache_validate_edituvs(MeshBatchCache *cache, uchar state)
+{
+	if ((cache->edituv_state & UVEDIT_SYNC_SEL) != (state & UVEDIT_SYNC_SEL)) {
+		mesh_batch_cache_discard_uvedit(cache);
+		return state;
+	}
+	else {
+		return ((cache->edituv_state & state) ^ state);
+	}
+}
+
+/* Compute 3D & 2D areas and their sum. */
+BLI_INLINE void edit_uv_preprocess_stretch_area(
+        float (*tf_uv)[2], BMFace *efa, const float asp[2], const int cd_loop_uv_offset, uint fidx,
+        float *totarea, float *totuvarea, float (*faces_areas)[2])
+{
+	BMLoop *l;
+	BMIter liter;
+	int i;
+	BM_ITER_ELEM_INDEX(l, &liter, efa, BM_LOOPS_OF_FACE, i) {
+		MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+		mul_v2_v2v2(tf_uv[i], luv->uv, asp);
+	}
+	faces_areas[fidx][0] = BM_face_calc_area(efa);
+	faces_areas[fidx][1] = area_poly_v2(tf_uv, efa->len);
+
+	*totarea += faces_areas[fidx][0];
+	*totuvarea += faces_areas[fidx][1];
+}
+
+BLI_INLINE float edit_uv_get_stretch_area(float area, float uvarea)
+{
+	if (area < FLT_EPSILON || uvarea < FLT_EPSILON) {
+		return 1.0f;
+	}
+	else if (area > uvarea) {
+		return 1.0f - (uvarea / area);
+	}
+	else {
+		return 1.0f - (area / uvarea);
+	}
+}
+
+/* Compute face's normalized contour vectors. */
+BLI_INLINE void edit_uv_preprocess_stretch_angle(
+        float (*auv)[2], float (*av)[3], const int cd_loop_uv_offset, BMFace *efa, float asp[2])
+{
+	BMLoop *l;
+	BMIter liter;
+	int i;
+	BM_ITER_ELEM_INDEX(l, &liter, efa, BM_LOOPS_OF_FACE, i) {
+		MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+		MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_uv_offset);
+
+		sub_v2_v2v2(auv[i], luv_prev->uv, luv->uv);
+		mul_v2_v2(auv[i], asp);
+		normalize_v2(auv[i]);
+
+		sub_v3_v3v3(av[i], l->prev->v->co, l->v->co);
+		normalize_v3(av[i]);
+	}
+}
+
+BLI_INLINE float edit_uv_get_loop_stretch_angle(
+        const float auv0[2], const float auv1[2], const float av0[3], const float av1[3])
+{
+	float uvang = angle_normalized_v2v2(auv0, auv1);
+	float ang = angle_normalized_v3v3(av0, av1);
+	float stretch = fabsf(uvang - ang) / (float)M_PI;
+	return 1.0f - pow2f(1.0f - stretch);
+}
+
+#define VERTEX_SELECT (1 << 0)
+#define VERTEX_PINNED (1 << 1)
+#define FACE_SELECT (1 << 2)
+#define FACE_ACTIVE (1 << 3)
+#define EDGE_SELECT (1 << 4)
+
+BLI_INLINE uchar edit_uv_get_face_flag(BMFace *efa, BMFace *efa_act, const int cd_loop_uv_offset, Scene *scene)
+{
+	uchar flag = 0;
+	flag |= uvedit_face_select_test(scene, efa, cd_loop_uv_offset) ? FACE_SELECT : 0;
+	flag |= (efa == efa_act) ? FACE_ACTIVE : 0;
+	return flag;
+}
+
+BLI_INLINE uchar edit_uv_get_loop_flag(BMLoop *l, const int cd_loop_uv_offset, Scene *scene)
+{
+	MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+	uchar flag = 0;
+	flag |= uvedit_uv_select_test(scene, l, cd_loop_uv_offset) ? VERTEX_SELECT : 0;
+	flag |= uvedit_edge_select_test(scene, l, cd_loop_uv_offset) ? EDGE_SELECT : 0;
+	flag |= (luv->flag & MLOOPUV_PINNED) ? VERTEX_PINNED : 0;
+	return flag;
+}
+
+static struct EditUVFormatIndex {
+	uint uvs, area, angle, flag, fdots_uvs, fdots_flag;
+} uv_attr_id = {0};
+
+static void uvedit_fill_buffer_data(
+        Object *ob, struct SpaceImage *sima, Scene *scene, uchar state, MeshBatchCache *cache,
+        GPUIndexBufBuilder *elb_faces, GPUIndexBufBuilder *elb_edges, GPUVertBuf **facedots_vbo)
+{
+	Mesh *me = ob->data;
+	BMEditMesh *embm = me->edit_btmesh;
+	BMesh *bm = embm->bm;
+	BMIter iter, liter;
+	BMFace *efa;
+	BMLoop *l;
+	MLoopUV *luv;
+	uint vidx, fidx, i;
+	float (*faces_areas)[2] = NULL;
+	float asp[2];
+	float totarea = 0.0f, totuvarea = 0.0f;
+	const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+	Image *ima = sima->image;
+	BMFace *efa_act = EDBM_uv_active_face_get(embm, false, false); /* will be set to NULL if hidden */
+
+	if (state & (UVEDIT_STRETCH_AREA | UVEDIT_STRETCH_ANGLE)) {
+		ED_space_image_get_uv_aspect(sima, &asp[0], &asp[1]);
+	}
+
+	BLI_buffer_declare_static(vec3f, vec3_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
+	BLI_buffer_declare_static(vec2f, vec2_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
+
+	if (state & UVEDIT_STRETCH_AREA) {
+		faces_areas = MEM_mallocN(sizeof(float) * 2 * bm->totface, "EDITUV faces areas");
+	}
+
+	/* Preprocess */
+	fidx = 0;
+	BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
+		/* Tag hidden faces */
+		BM_elem_flag_set(efa, BM_ELEM_TAG, uvedit_face_visible_test(scene, ob, ima, efa));
+
+		if ((state & UVEDIT_STRETCH_AREA) &&
+			BM_elem_flag_test(efa, BM_ELEM_TAG))
+		{
+			const int efa_len = efa->len;
+			float (*tf_uv)[2] = (float (*)[2])BLI_buffer_reinit_data(&vec2_buf, vec2f, efa_len);
+			edit_uv_preprocess_stretch_area(tf_uv, efa, asp, cd_loop_uv_offset, fidx++,
+			                                &totarea, &totuvarea, faces_areas);
+		}
+	}
+
+	vidx = 0;
+	fidx = 0;
+	BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
+		const int efa_len = efa->len;
+		float fdot[2] = {0.0f, 0.0f};
+		float (*av)[3], (*auv)[2];
+		ushort area_stretch;
+		/* Skip hidden faces. */
+		if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
+			continue;
+
+		uchar face_flag = edit_uv_get_face_flag(efa, efa_act, cd_loop_uv_offset, scene);
+		/* Face preprocess */
+		if (state & UVEDIT_STRETCH_AREA) {
+			area_stretch = edit_uv_get_stretch_area(faces_areas[fidx][0] / totarea,
+			                                        faces_areas[fidx][1] / totuvarea) * 65534.0f;
+		}
+		if (state & UVEDIT_STRETCH_ANGLE) {
+			av  = (float (*)[3])BLI_buffer_reinit_data(&vec3_buf, vec3f

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list