[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