[Bf-blender-cvs] [82e3302f448] greasepencil-object: Create a cache to drawing objects

Antonio Vazquez noreply at git.blender.org
Sun May 21 16:30:16 CEST 2017


Commit: 82e3302f448a153011259a776ed38d7ff4f3b6e3
Author: Antonio Vazquez
Date:   Sun May 21 16:28:56 2017 +0200
Branches: greasepencil-object
https://developer.blender.org/rB82e3302f448a153011259a776ed38d7ff4f3b6e3

Create a cache to drawing objects

Due speciall requirements for 2D drawing, the GP objects must be drawn after be sorteed by zdepth value.

We cannot use a simple GPU zdepth because this override the current layer/strokes order and the artists need to keep these controls as primary sorting method instead of GPU zdepth.

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

M	source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
M	source/blender/draw/engines/gpencil/gpencil_engine.c
M	source/blender/draw/engines/gpencil/gpencil_engine.h

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

diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
index 38b2bf0bbe6..4b05799778c 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
@@ -31,6 +31,7 @@
 #include "BKE_gpencil.h"
 #include "BKE_image.h"
 #include "ED_gpencil.h"
+#include "ED_view3d.h"
 
 #include "DNA_gpencil_types.h"
 #include "DNA_view3d_types.h"
@@ -48,6 +49,76 @@
 #include "IMB_imbuf_types.h"
 
 
+/* allocate cache to store GP objects */
+tGPencilObjectCache *gpencil_object_cache_allocate(tGPencilObjectCache *cache, int *gp_cache_size, int *gp_cache_used)
+{
+	tGPencilObjectCache *p = NULL;
+
+	/* By default a cache is created with one block with a predefined number of free slots,
+	if the size is not enough, the cache is reallocated adding a new block of free slots.
+	This is done in order to keep cache small */
+	if (*gp_cache_used + 1 > *gp_cache_size) {
+		if ((*gp_cache_size == 0) || (cache == NULL)) {
+			p = MEM_callocN(sizeof(struct tGPencilObjectCache) * GP_CACHE_BLOCK_SIZE, "tGPencilObjectCache");
+			*gp_cache_size = GP_CACHE_BLOCK_SIZE;
+		}
+		else {
+			*gp_cache_size += GP_CACHE_BLOCK_SIZE;
+			p = MEM_recallocN(cache, sizeof(struct tGPencilObjectCache) * *gp_cache_size);
+		}
+		cache = p;
+	}
+	return cache;
+}
+
+/* add a gpencil object to cache to defer drawing */
+void gpencil_object_cache_add(tGPencilObjectCache *cache, RegionView3D *rv3d, Object *ob, int *gp_cache_used)
+{
+	/* save object */
+	cache[*gp_cache_used].ob = ob;
+
+	/* calculate zdepth from point of view */
+	float zdepth = 0.0;
+	if (rv3d->is_persp) {
+		zdepth = ED_view3d_calc_zfac(rv3d, ob->loc, NULL);
+	}
+	else {
+		zdepth = -dot_v3v3(rv3d->viewinv[2], ob->loc);
+	}
+	cache[*gp_cache_used].zdepth = zdepth;
+
+	/* increase slots used in cache */
+	++*gp_cache_used;
+}
+
+/* helper function to sort gpencil objects using qsort */
+static int gpencil_object_cache_compare_zdepth(const void *a1, const void *a2)
+{
+	const tGPencilObjectCache *ps1 = a1, *ps2 = a2;
+
+	if (ps1->zdepth > ps2->zdepth) return 1;
+	else if (ps1->zdepth < ps2->zdepth) return -1;
+
+	return 0;
+}
+
+/* draw objects in cache from back to from */
+void gpencil_object_cache_draw(GPENCIL_e_data *e_data, GPENCIL_Data *vedata, ToolSettings *ts,
+	Scene *scene, tGPencilObjectCache *cache, int gp_cache_used)
+{
+	if (gp_cache_used > 0) {
+		/* sort by zdepth */
+		qsort(cache, gp_cache_used, sizeof(tGPencilObjectCache), gpencil_object_cache_compare_zdepth);
+		/* inverse loop to draw from back to front */
+		for (int i = gp_cache_used; i > 0; --i) {
+			Object *ob = cache[i - 1].ob;
+			DRW_gpencil_populate_datablock(e_data, vedata, scene, ob, ts, ob->gpd);
+		}
+	}
+	/* free memory */
+	MEM_SAFE_FREE(cache);
+}
+
 /* verify if cache is valid */
 static bool gpencil_batch_cache_valid(bGPdata *gpd, int cfra)
 {
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index 1a35acb8bfb..bc5c2d10447 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -124,6 +124,11 @@ static void GPENCIL_cache_init(void *vedata)
 	}
 
 	{
+		/* init gp objects cache */
+		stl->g_data->gp_cache_used = 0;
+		stl->g_data->gp_cache_size = 0;
+		stl->g_data->gp_object_cache = NULL;
+
 		/* Stroke pass */
 		DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_DEPTH_LESS;
 		psl->stroke_pass = DRW_pass_create("Gpencil Stroke Pass", state);
@@ -149,6 +154,7 @@ static void GPENCIL_cache_populate(void *vedata, Object *ob)
 	GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
 	const DRWContextState *draw_ctx = DRW_context_state_get();
 	Scene *scene = draw_ctx->scene;
+	RegionView3D *rv3d = draw_ctx->rv3d;
 	ToolSettings *ts = scene->toolsettings;
 
 	/* scene datablock (only once) */
@@ -162,12 +168,15 @@ static void GPENCIL_cache_populate(void *vedata, Object *ob)
 		}
 	}
 
-	/* object datablock */
+	/* object datablock (this is not draw now) */
 	if (ob->type == OB_GPENCIL && ob->gpd) {
 		if (G.debug_value == 668) {
 			printf("GPENCIL_cache_populate: Object\n");
 		}
-		DRW_gpencil_populate_datablock(&e_data, vedata, scene, ob, ts, ob->gpd);
+		/* allocate memory for saving gp objects */
+		stl->g_data->gp_object_cache = gpencil_object_cache_allocate(stl->g_data->gp_object_cache, &stl->g_data->gp_cache_size, &stl->g_data->gp_cache_used);
+		/* add for drawing later */
+		gpencil_object_cache_add(stl->g_data->gp_object_cache, rv3d, ob, &stl->g_data->gp_cache_used);
 	}
 }
 
@@ -178,6 +187,15 @@ static void GPENCIL_cache_finish(void *vedata)
 	}
 
 	GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+	const DRWContextState *draw_ctx = DRW_context_state_get();
+	Scene *scene = draw_ctx->scene;
+	RegionView3D *rv3d = draw_ctx->rv3d;
+	ToolSettings *ts = scene->toolsettings;
+
+	/* Draw all pending objects sorted by object location zdepth.For GP objects, the order of drawing 
+	   is decided by location of the object that is used as a pivot point */
+	gpencil_object_cache_draw(&e_data, vedata, ts, scene, stl->g_data->gp_object_cache, stl->g_data->gp_cache_used);
+
 	stl->g_data->scene_draw = false;
 }
 
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h
index c9cb7256528..96053b81a36 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.h
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.h
@@ -31,6 +31,16 @@
 #define MAX_GPENCIL_MAT 65536
 #define GPENCIL_MIN_BATCH_SLOTS_CHUNK 8
 
+ /* *********** OBJECTS CACHE *********** */
+ /* TODO: this could be a system parameter in userprefs screen */
+#define GPENCIL_CACHE_BLOCK_SIZE 8 
+
+ /* used to sort gpencil objects */
+typedef struct tGPencilObjectCache {
+	Object *ob;
+	float zdepth;
+} tGPencilObjectCache;
+
  /* *********** LISTS *********** */
 typedef struct GPENCIL_Storage {
 	int pal_id; /* total elements */
@@ -83,6 +93,10 @@ typedef struct g_data {
 	DRWShadingGroup *shgrps_drawing_stroke;
 	DRWShadingGroup *shgrps_drawing_fill;
 	bool scene_draw;
+
+	int gp_cache_used;
+	int gp_cache_size;
+	tGPencilObjectCache *gp_object_cache;
 } g_data; /* Transient data */
 
 typedef struct GPENCIL_e_data {
@@ -137,4 +151,8 @@ void gpencil_batch_cache_clear(struct bGPdata *gpd);
 
 bool gpencil_can_draw_stroke(struct RegionView3D *rv3d, const struct bGPDframe *gpf, const struct bGPDstroke *gps);
 
+struct tGPencilObjectCache *gpencil_object_cache_allocate(struct tGPencilObjectCache *cache, int *gp_cache_size, int *gp_cache_used);
+void gpencil_object_cache_add(struct tGPencilObjectCache *cache, struct RegionView3D *rv3d, struct Object *ob, int *gp_cache_used);
+void gpencil_object_cache_draw(struct GPENCIL_e_data *e_data, struct GPENCIL_Data *vedata, struct ToolSettings *ts, struct Scene *scene, struct tGPencilObjectCache *cache, int gp_cache_used);
+
 #endif /* __GPENCIL_ENGINE_H__ */




More information about the Bf-blender-cvs mailing list