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:
authormano-wii <germano.costa@ig.com.br>2019-08-15 16:31:54 +0300
committermano-wii <germano.costa@ig.com.br>2019-08-15 16:31:54 +0300
commit4d320f43133b02a43212b017eecdb390476189f2 (patch)
tree33ce479a4f9185724dcce31f4b70b335161c2b32 /source/blender/draw/engines/select
parent261a02fc596db0e91667d4e3af9204b165ec4006 (diff)
Edit Mesh Selection: Refactor: Redraw idmap buffer at runtime with only objects inside the rect
But in the future the selection code may also be used in object mode (eg for snapping). So to avoid using too much VRAM resources, it is good to avoid drawing all objects in the viewport. The solution was to create an array with only objects that are detected within the selection area. If the selection operator is modal, objects already detected are not removed from the array until view3d is moved or orbited. To detect the object, its BoundBox is tested. Since the Select Engine does not have a dedicated depth texture, whenever a new object is "found" the depth of the objects in the array already drawn is redrawn. Reviewers: campbellbarton, fclem Reviewed By: fclem Differential Revision: https://developer.blender.org/D5435
Diffstat (limited to 'source/blender/draw/engines/select')
-rw-r--r--source/blender/draw/engines/select/select_draw_utils.c44
-rw-r--r--source/blender/draw/engines/select/select_engine.c145
-rw-r--r--source/blender/draw/engines/select/select_private.h6
3 files changed, 160 insertions, 35 deletions
diff --git a/source/blender/draw/engines/select/select_draw_utils.c b/source/blender/draw/engines/select/select_draw_utils.c
index b65a158cdcf..268cd60a8aa 100644
--- a/source/blender/draw/engines/select/select_draw_utils.c
+++ b/source/blender/draw/engines/select/select_draw_utils.c
@@ -23,6 +23,8 @@
*/
#include "BKE_editmesh.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
#include "DNA_mesh_types.h"
#include "DNA_scene_types.h"
@@ -42,7 +44,7 @@
/** \name Draw Utilities
* \{ */
-void draw_select_framebuffer_select_id_setup(struct SELECTID_Context *select_ctx)
+static void select_id_framebuffer_setup(struct SELECTID_Context *select_ctx)
{
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
int size[2];
@@ -73,6 +75,32 @@ void draw_select_framebuffer_select_id_setup(struct SELECTID_Context *select_ctx
}
}
+/* Remove all tags from drawn or culled objects. */
+void select_id_context_clear(struct SELECTID_Context *select_ctx)
+{
+ select_ctx->objects_drawn_len = 0;
+ select_ctx->index_drawn_len = 1;
+ select_id_framebuffer_setup(select_ctx);
+ GPU_framebuffer_bind(select_ctx->framebuffer_select_id);
+ GPU_framebuffer_clear_color_depth(
+ select_ctx->framebuffer_select_id, (const float[4]){0.0f}, 1.0f);
+}
+
+void select_id_object_min_max(Object *obj, float r_min[3], float r_max[3])
+{
+ BoundBox *bb;
+ BMEditMesh *em = BKE_editmesh_from_object(obj);
+ if (em) {
+ /* Use Object Texture Space. */
+ bb = BKE_mesh_texspace_get(em->mesh_eval_cage, NULL, NULL, NULL);
+ }
+ else {
+ bb = BKE_object_boundbox_get(obj);
+ }
+ copy_v3_v3(r_min, bb->vec[0]);
+ copy_v3_v3(r_max, bb->vec[6]);
+}
+
short select_id_get_object_select_mode(Scene *scene, Object *ob)
{
short r_select_mode = 0;
@@ -132,7 +160,7 @@ static void draw_select_id_edit_mesh(SELECTID_StorageList *stl,
if (draw_facedot) {
struct GPUBatch *geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(me);
- DRW_shgroup_call(face_shgrp, geom_facedots, ob);
+ DRW_shgroup_call_no_cull(face_shgrp, geom_facedots, ob);
}
*r_face_offset = initial_offset + em->bm->totface;
}
@@ -141,14 +169,14 @@ static void draw_select_id_edit_mesh(SELECTID_StorageList *stl,
face_shgrp = stl->g_data->shgrp_face_unif;
*r_face_offset = initial_offset;
}
- DRW_shgroup_call(face_shgrp, geom_faces, ob);
+ DRW_shgroup_call_no_cull(face_shgrp, geom_faces, ob);
/* Unlike faces, only draw edges if edge select mode. */
if (select_mode & SCE_SELECT_EDGE) {
struct GPUBatch *geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me);
DRWShadingGroup *edge_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_edge);
DRW_shgroup_uniform_int_copy(edge_shgrp, "offset", *(int *)r_face_offset);
- DRW_shgroup_call(edge_shgrp, geom_edges, ob);
+ DRW_shgroup_call_no_cull(edge_shgrp, geom_edges, ob);
*r_edge_offset = *r_face_offset + em->bm->totedge;
}
else {
@@ -162,7 +190,7 @@ static void draw_select_id_edit_mesh(SELECTID_StorageList *stl,
struct GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me);
DRWShadingGroup *vert_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_vert);
DRW_shgroup_uniform_int_copy(vert_shgrp, "offset", *(int *)r_edge_offset);
- DRW_shgroup_call(vert_shgrp, geom_verts, ob);
+ DRW_shgroup_call_no_cull(vert_shgrp, geom_verts, ob);
*r_vert_offset = *r_edge_offset + em->bm->totvert;
}
else {
@@ -192,13 +220,13 @@ static void draw_select_id_mesh(SELECTID_StorageList *stl,
face_shgrp = stl->g_data->shgrp_face_unif;
*r_face_offset = initial_offset;
}
- DRW_shgroup_call(face_shgrp, geom_faces, ob);
+ DRW_shgroup_call_no_cull(face_shgrp, geom_faces, ob);
if (select_mode & SCE_SELECT_EDGE) {
struct GPUBatch *geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me);
DRWShadingGroup *edge_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_edge);
DRW_shgroup_uniform_int_copy(edge_shgrp, "offset", *(int *)r_face_offset);
- DRW_shgroup_call(edge_shgrp, geom_edges, ob);
+ DRW_shgroup_call_no_cull(edge_shgrp, geom_edges, ob);
*r_edge_offset = *r_face_offset + me->totedge;
}
else {
@@ -209,7 +237,7 @@ static void draw_select_id_mesh(SELECTID_StorageList *stl,
struct GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me);
DRWShadingGroup *vert_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_vert);
DRW_shgroup_uniform_int_copy(vert_shgrp, "offset", *r_edge_offset);
- DRW_shgroup_call(vert_shgrp, geom_verts, ob);
+ DRW_shgroup_call_no_cull(vert_shgrp, geom_verts, ob);
*r_vert_offset = *r_edge_offset + me->totvert;
}
else {
diff --git a/source/blender/draw/engines/select/select_engine.c b/source/blender/draw/engines/select/select_engine.c
index 67e926452b9..f437efe0c41 100644
--- a/source/blender/draw/engines/select/select_engine.c
+++ b/source/blender/draw/engines/select/select_engine.c
@@ -31,6 +31,11 @@
#include "DRW_engine.h"
#include "DRW_select_buffer.h"
+#include "DRW_select_buffer.h"
+
+#include "draw_cache_impl.h"
+#include "draw_manager.h"
+
#include "select_private.h"
#include "select_engine.h"
@@ -41,6 +46,7 @@
static struct {
SELECTID_Shaders sh_data[GPU_SHADER_CFG_LEN];
struct SELECTID_Context context;
+ uint runtime_new_objects;
} e_data = {{{NULL}}}; /* Engine data */
/* Shaders */
@@ -90,8 +96,23 @@ static void select_engine_init(void *vedata)
}
{
+ /* Create view from a subregion */
+ const DRWView *view_default = DRW_view_default_get();
+ float viewmat[4][4], winmat[4][4], winmat_subregion[4][4];
+ DRW_view_viewmat_get(view_default, viewmat, false);
+ DRW_view_winmat_get(view_default, winmat, false);
+ projmat_from_subregion(winmat,
+ (int[2]){draw_ctx->ar->winx, draw_ctx->ar->winy},
+ e_data.context.last_rect.xmin,
+ e_data.context.last_rect.xmax,
+ e_data.context.last_rect.ymin,
+ e_data.context.last_rect.ymax,
+ winmat_subregion);
+
+ stl->g_data->view_subregion = DRW_view_create(viewmat, winmat_subregion, NULL, NULL, NULL);
+
/* Create view with depth offset */
- stl->g_data->view_faces = (DRWView *)DRW_view_default_get();
+ stl->g_data->view_faces = (DRWView *)view_default;
stl->g_data->view_edges = DRW_view_create_with_zoffset(draw_ctx->rv3d, 1.0f);
stl->g_data->view_verts = DRW_view_create_with_zoffset(draw_ctx->rv3d, 1.1f);
}
@@ -107,11 +128,19 @@ static void select_cache_init(void *vedata)
if (e_data.context.select_mode == -1) {
e_data.context.select_mode = select_id_get_object_select_mode(draw_ctx->scene,
- OBACT(draw_ctx->view_layer));
+ draw_ctx->obact);
BLI_assert(e_data.context.select_mode != 0);
}
{
+ psl->depth_only_pass = DRW_pass_create("Depth Only Pass", DRW_STATE_DEFAULT);
+ stl->g_data->shgrp_depth_only = DRW_shgroup_create(sh_data->select_id_uniform,
+ psl->depth_only_pass);
+
+ if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
+ DRW_shgroup_state_enable(stl->g_data->shgrp_depth_only, DRW_STATE_CLIP_PLANES);
+ }
+
psl->select_id_face_pass = DRW_pass_create("Face Pass", DRW_STATE_DEFAULT);
if (e_data.context.select_mode & SCE_SELECT_FACE) {
@@ -157,29 +186,82 @@ static void select_cache_init(void *vedata)
}
}
- e_data.context.last_object_drawn = 0;
- e_data.context.last_index_drawn = 1;
+ /* Check if the viewport has changed. */
+ float(*persmat)[4] = draw_ctx->rv3d->persmat;
+ e_data.context.is_dirty = !compare_m4m4(e_data.context.persmat, persmat, FLT_EPSILON);
+ if (e_data.context.is_dirty) {
+ copy_m4_m4(e_data.context.persmat, persmat);
+ select_id_context_clear(&e_data.context);
+ }
+ e_data.runtime_new_objects = 0;
}
static void select_cache_populate(void *vedata, Object *ob)
{
+ SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl;
const DRWContextState *draw_ctx = DRW_context_state_get();
- struct ObjectOffsets *base_ofs =
- &e_data.context.index_offsets[e_data.context.last_object_drawn++];
-
- uint offset = e_data.context.last_index_drawn;
-
- select_id_draw_object(vedata,
- draw_ctx->v3d,
- ob,
- e_data.context.select_mode,
- offset,
- &base_ofs->vert,
- &base_ofs->edge,
- &base_ofs->face);
-
- base_ofs->offset = offset;
- e_data.context.last_index_drawn = base_ofs->vert;
+
+ SELECTID_ObjectData *sel_data = (SELECTID_ObjectData *)DRW_drawdata_get(
+ &ob->id, &draw_engine_select_type);
+
+ if (!e_data.context.is_dirty && sel_data && sel_data->is_drawn) {
+ /* The object indices have already been drawn. Fill depth pass.
+ * Opti: Most of the time this depth pass is not used. */
+ struct Mesh *me = ob->data;
+ struct GPUBatch *geom_faces;
+ if (e_data.context.select_mode & SCE_SELECT_FACE) {
+ geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me);
+ }
+ else {
+ geom_faces = DRW_mesh_batch_cache_get_surface(me);
+ }
+ DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_faces, ob->obmat);
+
+ if (e_data.context.select_mode & SCE_SELECT_EDGE) {
+ struct GPUBatch *geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me);
+ DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_edges, ob->obmat);
+ }
+
+ if (e_data.context.select_mode & SCE_SELECT_VERTEX) {
+ struct GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me);
+ DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_verts, ob->obmat);
+ }
+ return;
+ }
+
+ float min[3], max[3];
+ select_id_object_min_max(ob, min, max);
+
+ if (DRW_culling_min_max_test(stl->g_data->view_subregion, ob->obmat, min, max)) {
+ if (sel_data == NULL) {
+ sel_data = (SELECTID_ObjectData *)DRW_drawdata_ensure(
+ &ob->id, &draw_engine_select_type, sizeof(SELECTID_ObjectData), NULL, NULL);
+ }
+ sel_data->drawn_index = e_data.context.objects_drawn_len;
+ sel_data->is_drawn = true;
+
+ struct ObjectOffsets *ob_offsets =
+ &e_data.context.index_offsets[e_data.context.objects_drawn_len];
+
+ uint offset = e_data.context.index_drawn_len;
+ select_id_draw_object(vedata,
+ draw_ctx->v3d,
+ ob,
+ e_data.context.select_mode,
+ offset,
+ &ob_offsets->vert,
+ &ob_offsets->edge,
+ &ob_offsets->face);
+
+ ob_offsets->offset = offset;
+ e_data.context.index_drawn_len = ob_offsets->vert;
+ e_data.context.objects_drawn[e_data.context.objects_drawn_len] = ob;
+ e_data.context.objects_drawn_len++;
+ e_data.runtime_new_objects++;
+ }
+ else if (sel_data) {
+ sel_data->is_drawn = false;
+ }
}
static void select_draw_scene(void *vedata)
@@ -187,17 +269,26 @@ static void select_draw_scene(void *vedata)
SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl;
SELECTID_PassList *psl = ((SELECTID_Data *)vedata)->psl;
- /* Setup framebuffer */
- draw_select_framebuffer_select_id_setup(&e_data.context);
- GPU_framebuffer_bind(e_data.context.framebuffer_select_id);
+ if (!e_data.runtime_new_objects) {
+ /* Nothing new needs to be drawn. */
+ return;
+ }
/* dithering and AA break color coding, so disable */
glDisable(GL_DITHER);
- GPU_framebuffer_clear_color_depth(
- e_data.context.framebuffer_select_id, (const float[4]){0.0f}, 1.0f);
-
DRW_view_set_active(stl->g_data->view_faces);
+
+ if (!DRW_pass_is_empty(psl->depth_only_pass)) {
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ GPU_framebuffer_bind(dfbl->depth_only_fb);
+ GPU_framebuffer_clear_depth(dfbl->depth_only_fb, 1.0f);
+ DRW_draw_pass(psl->depth_only_pass);
+ }
+
+ /* Setup framebuffer */
+ GPU_framebuffer_bind(e_data.context.framebuffer_select_id);
+
DRW_draw_pass(psl->select_id_face_pass);
if (e_data.context.select_mode & SCE_SELECT_EDGE) {
@@ -221,7 +312,9 @@ static void select_engine_free(void)
DRW_TEXTURE_FREE_SAFE(e_data.context.texture_u32);
GPU_FRAMEBUFFER_FREE_SAFE(e_data.context.framebuffer_select_id);
+ MEM_SAFE_FREE(e_data.context.objects);
MEM_SAFE_FREE(e_data.context.index_offsets);
+ MEM_SAFE_FREE(e_data.context.objects_drawn);
}
/** \} */
diff --git a/source/blender/draw/engines/select/select_private.h b/source/blender/draw/engines/select/select_private.h
index d95b14ff2b6..e48ce4314ae 100644
--- a/source/blender/draw/engines/select/select_private.h
+++ b/source/blender/draw/engines/select/select_private.h
@@ -32,6 +32,7 @@ typedef struct SELECTID_StorageList {
} SELECTID_StorageList;
typedef struct SELECTID_PassList {
+ struct DRWPass *depth_only_pass;
struct DRWPass *select_id_face_pass;
struct DRWPass *select_id_edge_pass;
struct DRWPass *select_id_vert_pass;
@@ -52,18 +53,21 @@ typedef struct SELECTID_Shaders {
} SELECTID_Shaders;
typedef struct SELECTID_PrivateData {
+ DRWShadingGroup *shgrp_depth_only;
DRWShadingGroup *shgrp_face_unif;
DRWShadingGroup *shgrp_face_flat;
DRWShadingGroup *shgrp_edge;
DRWShadingGroup *shgrp_vert;
+ DRWView *view_subregion;
DRWView *view_faces;
DRWView *view_edges;
DRWView *view_verts;
} SELECTID_PrivateData; /* Transient data */
/* select_draw_utils.c */
-void draw_select_framebuffer_select_id_setup(struct SELECTID_Context *r_select_ctx);
+void select_id_context_clear(struct SELECTID_Context *select_ctx);
+void select_id_object_min_max(struct Object *obj, float r_min[3], float r_max[3]);
short select_id_get_object_select_mode(Scene *scene, Object *ob);
void select_id_draw_object(void *vedata,
View3D *v3d,