Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonioya <blendergit@gmail.com>2018-08-15 17:07:16 +0300
committerAntonioya <blendergit@gmail.com>2018-08-15 21:27:59 +0300
commit8e8d93eb86109988db44730a0107e9da9e870328 (patch)
tree7a4e317f52de4e07d3261817e55a5444be1379f2 /source/blender/draw/engines/gpencil/gpencil_draw_utils.c
parentbb84f7ff5f5268226b4d14e0f1e44a2579354b37 (diff)
GP: Redesign logic of drawing engine for object instance support
The initial design assumed that there was only one object for each unique name, but that was not the case when instances were created. Now, instances are supported and speed has been greatly improved when repetitions are used. As a result of this change, the option to create objects has been removed in the Instances modifier. This option was strange and was also against Blender's design rules, since a modifier should never create objects. The old functionality of the modifier can be achieved with instances. Also, several memory leakage problems that were not previously detected have been eliminated, and especially in the grid and in the drawing process Onion Skin is not supported in multi-user datablocks. Support this, makes incompatible with instances. We need find a solution in the long term, but now it's better keep disabled and make instances work. Anyway, the new instances makes unnecessary to use muli-user datablocks.
Diffstat (limited to 'source/blender/draw/engines/gpencil/gpencil_draw_utils.c')
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_utils.c184
1 files changed, 60 insertions, 124 deletions
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
index 401934b35a7..16412dda3f8 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
@@ -587,7 +587,8 @@ static void gpencil_add_fill_shgroup(
/* add stroke shading group to pass */
static void gpencil_add_stroke_shgroup(GpencilBatchCache *cache, DRWShadingGroup *strokegrp,
Object *ob, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps,
- const float opacity, const float tintcolor[4], const bool onion, const bool custonion)
+ const float opacity, const float tintcolor[4], const bool onion,
+ const bool custonion)
{
float tcolor[4];
float ink[4];
@@ -622,7 +623,7 @@ static void gpencil_add_stroke_shgroup(GpencilBatchCache *cache, DRWShadingGroup
if (cache->is_dirty) {
gpencil_batch_cache_check_free_slots(ob);
if ((gps->totpoints > 1) && (gp_style->mode == GP_STYLE_MODE_LINE)) {
- cache->batch_stroke[cache->cache_idx] = DRW_gpencil_get_stroke_geom(gpf, gps, sthickness, ink);
+ cache->batch_stroke[cache->cache_idx] = DRW_gpencil_get_stroke_geom(gps, sthickness, ink);
}
else {
cache->batch_stroke[cache->cache_idx] = DRW_gpencil_get_point_geom(gps, sthickness, ink);
@@ -742,7 +743,8 @@ static void gpencil_draw_onion_strokes(
static void gpencil_draw_strokes(
GpencilBatchCache *cache, GPENCIL_e_data *e_data, void *vedata, ToolSettings *ts, Object *ob,
bGPdata *gpd, bGPDlayer *gpl, bGPDframe *src_gpf, bGPDframe *derived_gpf,
- const float opacity, const float tintcolor[4], const bool custonion)
+ const float opacity, const float tintcolor[4],
+ const bool custonion, tGPencilObjectCache *cache_ob)
{
GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
@@ -769,6 +771,10 @@ static void gpencil_draw_strokes(
ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, viewmatrix);
copy_m4_m4(derived_gpf->runtime.viewmatrix, viewmatrix);
+ if ((cache_ob != NULL) && (cache_ob->is_dup_ob)) {
+ copy_m4_m4(derived_gpf->runtime.viewmatrix, cache_ob->obmat);
+ }
+
/* apply geometry modifiers */
if ((cache->is_dirty) && (ob->greasepencil_modifiers.first) && (!is_multiedit)) {
if (!stl->storage->simplify_modif) {
@@ -797,7 +803,7 @@ static void gpencil_draw_strokes(
continue;
}
- /* be sure recalc all chache in source stroke to avoid recalculation when frame change
+ /* be sure recalc all cache in source stroke to avoid recalculation when frame change
* and improve fps */
if (src_gps) {
DRW_gpencil_recalc_geometry_caches(ob, gp_style, src_gps);
@@ -859,17 +865,21 @@ static void gpencil_draw_strokes(
/* fill */
if ((fillgrp) && (!stl->storage->simplify_fill)) {
gpencil_add_fill_shgroup(
- cache, fillgrp, ob, gpl, derived_gpf, gps, tintcolor, false, custonion);
+ cache, fillgrp, ob, gpl, derived_gpf, gps,
+ tintcolor, false, custonion);
}
/* stroke */
if (strokegrp) {
gpencil_add_stroke_shgroup(
- cache, strokegrp, ob, gpl, derived_gpf, gps, opacity, tintcolor, false, custonion);
+ cache, strokegrp, ob, gpl, derived_gpf, gps,
+ opacity, tintcolor, false, custonion);
}
}
/* edit points (only in edit mode and not play animation not render) */
- if ((src_gps) && (!playing) && (!is_render)) {
+ if ((draw_ctx->obact == ob) && (src_gps) &&
+ (!playing) && (!is_render) && (!cache_ob->is_dup_ob))
+ {
if (!stl->g_data->shgrps_edit_line) {
stl->g_data->shgrps_edit_line = DRW_shgroup_create(e_data->gpencil_line_sh, psl->edit_pass);
}
@@ -942,11 +952,11 @@ void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, void *vedata, T
/* use unit matrix because the buffer is in screen space and does not need conversion */
if (gpd->runtime.mode == GP_STYLE_MODE_LINE) {
e_data->batch_buffer_stroke = DRW_gpencil_get_buffer_stroke_geom(
- gpd, stl->storage->unit_matrix, lthick);
+ gpd, lthick);
}
else {
e_data->batch_buffer_stroke = DRW_gpencil_get_buffer_point_geom(
- gpd, stl->storage->unit_matrix, lthick);
+ gpd, lthick);
}
DRW_shgroup_call_add(
@@ -1146,8 +1156,10 @@ static void gpencil_draw_onionskins(
}
/* populate a datablock for multiedit (no onions, no modifiers) */
-void DRW_gpencil_populate_multiedit(GPENCIL_e_data *e_data, void *vedata, Scene *scene, Object *ob, bGPdata *gpd)
+void DRW_gpencil_populate_multiedit(GPENCIL_e_data *e_data, void *vedata, Scene *scene, Object *ob,
+ tGPencilObjectCache *cache_ob)
{
+ bGPdata *gpd = (bGPdata *)ob->data;
bGPDframe *gpf = NULL;
GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
@@ -1172,7 +1184,7 @@ void DRW_gpencil_populate_multiedit(GPENCIL_e_data *e_data, void *vedata, Scene
if ((gpf == gpl->actframe) || (gpf->flag & GP_FRAME_SELECT)) {
gpencil_draw_strokes(
cache, e_data, vedata, ts, ob, gpd, gpl, gpf, gpf,
- gpl->opacity, gpl->tintcolor, false);
+ gpl->opacity, gpl->tintcolor, false, cache_ob);
}
}
}
@@ -1181,7 +1193,7 @@ void DRW_gpencil_populate_multiedit(GPENCIL_e_data *e_data, void *vedata, Scene
if (gpf) {
gpencil_draw_strokes(
cache, e_data, vedata, ts, ob, gpd, gpl, gpf, gpf,
- gpl->opacity, gpl->tintcolor, false);
+ gpl->opacity, gpl->tintcolor, false, cache_ob);
}
}
@@ -1191,16 +1203,20 @@ void DRW_gpencil_populate_multiedit(GPENCIL_e_data *e_data, void *vedata, Scene
}
/* helper for populate a complete grease pencil datablock */
-void DRW_gpencil_populate_datablock(GPENCIL_e_data *e_data, void *vedata, Scene *scene, Object *ob, bGPdata *gpd)
+void DRW_gpencil_populate_datablock(
+ GPENCIL_e_data *e_data, void *vedata,
+ Scene *scene, Object *ob,
+ tGPencilObjectCache *cache_ob)
{
GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
const DRWContextState *draw_ctx = DRW_context_state_get();
+ bGPdata *gpd = (bGPdata *)ob->data;
View3D *v3d = draw_ctx->v3d;
int cfra_eval = (int)DEG_get_ctime(draw_ctx->depsgraph);
ToolSettings *ts = scene->toolsettings;
bGPDframe *derived_gpf = NULL;
- const bool main_onion = v3d != NULL ? ((v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) == 0) : true;
- const bool no_onion = (bool)(gpd->flag & GP_DATA_STROKE_WEIGHTMODE) || main_onion;
+ const bool main_onion = v3d != NULL ? (v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) : true;
+ const bool do_onion = (bool)((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && main_onion;
const bool overlay = v3d != NULL ? (bool)((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) : true;
/* check if playing animation */
@@ -1230,17 +1246,21 @@ void DRW_gpencil_populate_datablock(GPENCIL_e_data *e_data, void *vedata, Scene
gpl->runtime.derived_data = (GHash *)BLI_ghash_str_new(gpl->info);
}
- if (BLI_ghash_haskey(gpl->runtime.derived_data, ob->id.name)) {
+ if (BLI_ghash_haskey(gpl->runtime.derived_data,ob->id.name)) {
derived_gpf = BLI_ghash_lookup(gpl->runtime.derived_data, ob->id.name);
}
else {
+ /* verify we have frame duplicated already */
+ if (cache_ob->is_dup_ob) {
+ continue;
+ }
derived_gpf = NULL;
}
if (derived_gpf == NULL) {
cache->is_dirty = true;
}
- if (cache->is_dirty) {
+ if ((!cache_ob->is_dup_ob) && (cache->is_dirty)) {
if (derived_gpf != NULL) {
/* first clear temp data */
if (BLI_ghash_haskey(gpl->runtime.derived_data, ob->id.name)) {
@@ -1258,24 +1278,36 @@ void DRW_gpencil_populate_datablock(GPENCIL_e_data *e_data, void *vedata, Scene
BLI_ghash_reinsert(gpl->runtime.derived_data, ob->id.name, derived_gpf, NULL, NULL);
}
}
-
/* draw onion skins */
- if ((gpd->flag & GP_DATA_SHOW_ONIONSKINS) &&
- (!no_onion) && (overlay) &&
- (gpl->onion_flag & GP_LAYER_ONIONSKIN) &&
- ((!playing) || (gpd->onion_flag & GP_ONION_GHOST_ALWAYS)))
- {
- if ((!stl->storage->is_render) ||
- ((stl->storage->is_render) && (gpd->onion_flag & GP_ONION_GHOST_ALWAYS)))
+ if (!ID_IS_LINKED(&gpd->id)) {
+ ID *orig_id = gpd->id.orig_id;
+ /* GPXX: Now only a datablock with one use is allowed to be compatible
+ * with instances
+ */
+ if ((!cache_ob->is_dup_onion) && (gpd->flag & GP_DATA_SHOW_ONIONSKINS) &&
+ (do_onion) && (gpl->onion_flag & GP_LAYER_ONIONSKIN) &&
+ ((!playing) || (gpd->onion_flag & GP_ONION_GHOST_ALWAYS)) &&
+ (!cache_ob->is_dup_ob) && (orig_id->us <= 1))
{
- gpencil_draw_onionskins(cache, e_data, vedata, ob, gpd, gpl, gpf);
+ if (((!stl->storage->is_render) && (overlay)) ||
+ ((stl->storage->is_render) && (gpd->onion_flag & GP_ONION_GHOST_ALWAYS)))
+ {
+ gpencil_draw_onionskins(cache, e_data, vedata, ob, gpd, gpl, gpf);
+ }
}
}
-
/* draw normal strokes */
+ if (!cache_ob->is_dup_ob) {
+ /* save batch index */
+ gpl->runtime.batch_index = cache->cache_idx;
+ }
+ else {
+ cache->cache_idx = gpl->runtime.batch_index;
+ }
+
gpencil_draw_strokes(
cache, e_data, vedata, ts, ob, gpd, gpl, gpf, derived_gpf,
- gpl->opacity, gpl->tintcolor, false);
+ gpl->opacity, gpl->tintcolor, false, cache_ob);
}
@@ -1286,99 +1318,3 @@ void DRW_gpencil_populate_datablock(GPENCIL_e_data *e_data, void *vedata, Scene
cache->is_dirty = false;
}
-
-/* Helper for gpencil_instance_modifiers()
- * See also MOD_gpencilinstance.c -> bakeModifier()
- */
-static void gp_instance_modifier_make_instances(GPENCIL_StorageList *stl, Object *ob, InstanceGpencilModifierData *mmd)
-{
- /* reset random */
- mmd->rnd[0] = 1;
- int e = 0;
-
- /* Generate instances */
- for (int x = 0; x < mmd->count[0]; x++) {
- for (int y = 0; y < mmd->count[1]; y++) {
- for (int z = 0; z < mmd->count[2]; z++) {
- if ((x == 0) && (y == 0) && (z == 0)) {
- continue;
- }
-
- Object *newob = NULL;
- const int elem_idx[3] = {x, y, z};
- float mat[4][4];
- int sh;
-
- /* original strokes are at index = 0,0,0 */
- if ((x == 0) && (y == 0) && (z == 0)) {
- continue;
- }
-
- /* compute transform for instance */
- BKE_gpencil_instance_modifier_instance_tfm(mmd, elem_idx, mat);
-
- /* add object to cache */
- newob = MEM_dupallocN(ob);
-
- /* Create a unique name or the object hash used in draw will fail.
- * the name must be unique in the hash, not in the scene because
- * the object never is linked to scene and is removed after drawing.
- *
- * It uses special characters to be sure the name cannot be equal
- * to any existing name because UI limits the use of special characters.
- *
- * Name = OB\t_{pointer}_{index}
- */
- sprintf(newob->id.name, "OB\t_%p_%d", &ob, e++);
-
- mul_m4_m4m4(newob->obmat, ob->obmat, mat);
-
- /* apply scale */
- ARRAY_SET_ITEMS(newob->size, mat[0][0], mat[1][1], mat[2][2]);
-
- /* apply shift */
- sh = x;
- if (mmd->lock_axis == GP_LOCKAXIS_Y) {
- sh = y;
- }
- if (mmd->lock_axis == GP_LOCKAXIS_Z) {
- sh = z;
- }
- madd_v3_v3fl(newob->obmat[3], mmd->shift, sh);
-
- /* add temp object to cache */
- stl->g_data->gp_object_cache = gpencil_object_cache_add(
- stl->g_data->gp_object_cache, newob, true,
- &stl->g_data->gp_cache_size, &stl->g_data->gp_cache_used);
- }
- }
- }
-}
-
-/* create instances using instance modifiers */
-void gpencil_instance_modifiers(GPENCIL_StorageList *stl, Object *ob)
-{
- if ((ob) && (ob->data)) {
- bGPdata *gpd = ob->data;
- if (GPENCIL_ANY_EDIT_MODE(gpd)) {
- return;
- }
- }
-
- for (GpencilModifierData *md = ob->greasepencil_modifiers.first; md; md = md->next) {
- if (((md->mode & eGpencilModifierMode_Realtime) && (stl->storage->is_render == false)) ||
- ((md->mode & eGpencilModifierMode_Render) && (stl->storage->is_render == true)))
- {
- if (md->type == eGpencilModifierType_Instance) {
- InstanceGpencilModifierData *mmd = (InstanceGpencilModifierData *)md;
-
- /* Only add instances if the "Make Objects" flag is set
- * FIXME: This is a workaround for z-ordering weirdness when all instances are in the same object
- */
- if (mmd->flag & GP_INSTANCE_MAKE_OBJECTS) {
- gp_instance_modifier_make_instances(stl, ob, mmd);
- }
- }
- }
- }
-}