Blender  V2.93
select_engine.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * Copyright 2019, Blender Foundation.
17  */
18 
25 #include "DNA_screen_types.h"
26 
27 #include "UI_resources.h"
28 
29 #include "DRW_engine.h"
30 #include "DRW_select_buffer.h"
31 
32 #include "draw_cache_impl.h"
33 #include "draw_manager.h"
34 
35 #include "select_engine.h"
36 #include "select_private.h"
37 
38 #define SELECT_ENGINE "SELECT_ENGINE"
39 
40 /* *********** STATIC *********** */
41 
42 static struct {
45 
49 } e_data = {NULL}; /* Engine data */
50 
51 /* Shaders */
52 extern char datatoc_common_view_lib_glsl[];
54 extern char datatoc_selection_id_frag_glsl[];
55 
56 /* -------------------------------------------------------------------- */
61 {
63  int size[2];
64  size[0] = GPU_texture_width(dtxl->depth);
65  size[1] = GPU_texture_height(dtxl->depth);
66 
67  if (e_data.framebuffer_select_id == NULL) {
68  e_data.framebuffer_select_id = GPU_framebuffer_create("framebuffer_select_id");
69  }
70 
71  if ((e_data.texture_u32 != NULL) && ((GPU_texture_width(e_data.texture_u32) != size[0]) ||
72  (GPU_texture_height(e_data.texture_u32) != size[1]))) {
73  GPU_texture_free(e_data.texture_u32);
74  e_data.texture_u32 = NULL;
75  }
76 
77  /* Make sure the depth texture is attached.
78  * It may disappear when loading another Blender session. */
79  GPU_framebuffer_texture_attach(e_data.framebuffer_select_id, dtxl->depth, 0, 0);
80 
81  if (e_data.texture_u32 == NULL) {
82  e_data.texture_u32 = GPU_texture_create_2d(
83  "select_buf_ids", size[0], size[1], 1, GPU_R32UI, NULL);
84  GPU_framebuffer_texture_attach(e_data.framebuffer_select_id, e_data.texture_u32, 0, 0);
85 
86  GPU_framebuffer_check_valid(e_data.framebuffer_select_id, NULL);
87  }
88 }
89 
92 /* -------------------------------------------------------------------- */
96 static void select_engine_init(void *vedata)
97 {
98  const DRWContextState *draw_ctx = DRW_context_state_get();
99  eGPUShaderConfig sh_cfg = draw_ctx->sh_cfg;
100 
101  SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl;
102  SELECTID_Shaders *sh_data = &e_data.sh_data[sh_cfg];
103 
104  /* Prepass */
105  if (!sh_data->select_id_flat) {
106  const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg];
108  .vert = (const char *[]){sh_cfg_data->lib,
111  NULL},
112  .frag = (const char *[]){datatoc_selection_id_frag_glsl, NULL},
113  .defs = (const char *[]){sh_cfg_data->def, NULL},
114  });
115  }
116  if (!sh_data->select_id_uniform) {
117  const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg];
119  .vert = (const char *[]){sh_cfg_data->lib,
122  NULL},
123  .frag = (const char *[]){datatoc_selection_id_frag_glsl, NULL},
124  .defs = (const char *[]){sh_cfg_data->def, "#define UNIFORM_ID\n", NULL},
125  });
126  }
127 
128  if (!stl->g_data) {
129  /* Alloc transient pointers */
130  stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
131  }
132 
133  {
134  /* Create view from a subregion */
135  const DRWView *view_default = DRW_view_default_get();
136  float viewmat[4][4], winmat[4][4], winmat_subregion[4][4];
137  DRW_view_viewmat_get(view_default, viewmat, false);
138  DRW_view_winmat_get(view_default, winmat, false);
139  projmat_from_subregion(winmat,
140  (int[2]){draw_ctx->region->winx, draw_ctx->region->winy},
141  e_data.context.last_rect.xmin,
142  e_data.context.last_rect.xmax,
143  e_data.context.last_rect.ymin,
144  e_data.context.last_rect.ymax,
145  winmat_subregion);
146 
147  stl->g_data->view_subregion = DRW_view_create(viewmat, winmat_subregion, NULL, NULL, NULL);
148 
149  /* Create view with depth offset */
150  stl->g_data->view_faces = (DRWView *)view_default;
151  stl->g_data->view_edges = DRW_view_create_with_zoffset(view_default, draw_ctx->rv3d, 1.0f);
152  stl->g_data->view_verts = DRW_view_create_with_zoffset(view_default, draw_ctx->rv3d, 1.1f);
153  }
154 }
155 
156 static void select_cache_init(void *vedata)
157 {
158  SELECTID_PassList *psl = ((SELECTID_Data *)vedata)->psl;
159  SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl;
160  SELECTID_PrivateData *pd = stl->g_data;
161 
162  const DRWContextState *draw_ctx = DRW_context_state_get();
163  SELECTID_Shaders *sh = &e_data.sh_data[draw_ctx->sh_cfg];
164 
165  if (e_data.context.select_mode == -1) {
166  e_data.context.select_mode = select_id_get_object_select_mode(draw_ctx->scene,
167  draw_ctx->obact);
168  BLI_assert(e_data.context.select_mode != 0);
169  }
170 
172  state |= RV3D_CLIPPING_ENABLED(draw_ctx->v3d, draw_ctx->rv3d) ? DRW_STATE_CLIP_PLANES : 0;
173 
174  {
177 
179  if (e_data.context.select_mode & SCE_SELECT_FACE) {
181  }
182  else {
185  }
186 
187  if (e_data.context.select_mode & SCE_SELECT_EDGE) {
189 
191  }
192 
193  if (e_data.context.select_mode & SCE_SELECT_VERTEX) {
197  }
198  }
199 
200  /* Check if the viewport has changed. */
201  float(*persmat)[4] = draw_ctx->rv3d->persmat;
202  e_data.context.is_dirty = !compare_m4m4(e_data.context.persmat, persmat, FLT_EPSILON);
203 
204  if (!e_data.context.is_dirty) {
205  /* Check if any of the drawn objects have been transformed. */
206  Object **ob = &e_data.context.objects_drawn[0];
207  for (uint i = e_data.context.objects_drawn_len; i--; ob++) {
209  if (data && (data->recalc & ID_RECALC_TRANSFORM) != 0) {
210  data->recalc &= ~ID_RECALC_TRANSFORM;
211  e_data.context.is_dirty = true;
212  }
213  }
214  }
215 
216  if (e_data.context.is_dirty) {
217  /* Remove all tags from drawn or culled objects. */
218  copy_m4_m4(e_data.context.persmat, persmat);
219  e_data.context.objects_drawn_len = 0;
220  e_data.context.index_drawn_len = 1;
222  GPU_framebuffer_bind(e_data.framebuffer_select_id);
223  GPU_framebuffer_clear_color_depth(e_data.framebuffer_select_id, (const float[4]){0.0f}, 1.0f);
224  }
225  e_data.runtime_new_objects = 0;
226 }
227 
228 static void select_cache_populate(void *vedata, Object *ob)
229 {
230  SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl;
231  const DRWContextState *draw_ctx = DRW_context_state_get();
232 
234  &ob->id, &draw_engine_select_type);
235 
236  if (!e_data.context.is_dirty && sel_data && sel_data->is_drawn) {
237  /* The object indices have already been drawn. Fill depth pass.
238  * Opti: Most of the time this depth pass is not used. */
239  struct Mesh *me = ob->data;
240  if (e_data.context.select_mode & SCE_SELECT_FACE) {
242  DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_faces, ob->obmat);
243  }
244  else if (ob->dt >= OB_SOLID) {
245 #ifdef USE_CAGE_OCCLUSION
247 #else
248  struct GPUBatch *geom_faces = DRW_mesh_batch_cache_get_surface(me);
249 #endif
250  DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_faces, ob->obmat);
251  }
252 
253  if (e_data.context.select_mode & SCE_SELECT_EDGE) {
255  DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_edges, ob->obmat);
256  }
257 
258  if (e_data.context.select_mode & SCE_SELECT_VERTEX) {
260  DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_verts, ob->obmat);
261  }
262  return;
263  }
264 
265  float min[3], max[3];
267 
269  if (sel_data == NULL) {
272  }
273  sel_data->dd.recalc = 0;
274  sel_data->drawn_index = e_data.context.objects_drawn_len;
275  sel_data->is_drawn = true;
276 
277  struct ObjectOffsets *ob_offsets =
278  &e_data.context.index_offsets[e_data.context.objects_drawn_len];
279 
280  uint offset = e_data.context.index_drawn_len;
281  select_id_draw_object(vedata,
282  draw_ctx->v3d,
283  ob,
284  e_data.context.select_mode,
285  offset,
286  &ob_offsets->vert,
287  &ob_offsets->edge,
288  &ob_offsets->face);
289 
290  ob_offsets->offset = offset;
291  e_data.context.index_drawn_len = ob_offsets->vert;
292  e_data.context.objects_drawn[e_data.context.objects_drawn_len] = ob;
293  e_data.context.objects_drawn_len++;
294  e_data.runtime_new_objects++;
295  }
296  else if (sel_data) {
297  sel_data->is_drawn = false;
298  }
299 }
300 
301 static void select_draw_scene(void *vedata)
302 {
303  SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl;
304  SELECTID_PassList *psl = ((SELECTID_Data *)vedata)->psl;
305 
306  if (!e_data.runtime_new_objects) {
307  /* Nothing new needs to be drawn. */
308  return;
309  }
310 
312 
313  if (!DRW_pass_is_empty(psl->depth_only_pass)) {
316  GPU_framebuffer_clear_depth(dfbl->depth_only_fb, 1.0f);
318  }
319 
320  /* Setup framebuffer */
321  GPU_framebuffer_bind(e_data.framebuffer_select_id);
322 
324 
325  if (e_data.context.select_mode & SCE_SELECT_EDGE) {
328  }
329 
330  if (e_data.context.select_mode & SCE_SELECT_VERTEX) {
333  }
334 }
335 
336 static void select_engine_free(void)
337 {
338  for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) {
339  SELECTID_Shaders *sh_data = &e_data.sh_data[sh_data_index];
342  }
343 
344  DRW_TEXTURE_FREE_SAFE(e_data.texture_u32);
345  GPU_FRAMEBUFFER_FREE_SAFE(e_data.framebuffer_select_id);
346  MEM_SAFE_FREE(e_data.context.objects);
347  MEM_SAFE_FREE(e_data.context.index_offsets);
348  MEM_SAFE_FREE(e_data.context.objects_drawn);
349 }
350 
353 /* -------------------------------------------------------------------- */
358 
360  NULL,
361  NULL,
362  N_("Select ID"),
368  NULL,
370  NULL,
371  NULL,
372  NULL,
373  NULL,
374 };
375 
376 /* Note: currently unused, we may want to register so we can see this when debugging the view. */
377 
379  NULL,
380  NULL,
382  N_("Select ID"),
384  NULL,
385  NULL,
386  NULL,
387  NULL,
388  NULL,
389  NULL,
390  NULL,
392  {NULL, NULL, NULL},
393 };
394 
397 /* -------------------------------------------------------------------- */
402 {
403  return &e_data.context;
404 }
405 
407 {
408  return e_data.framebuffer_select_id;
409 }
410 
412 {
413  return e_data.texture_u32;
414 }
415 
418 #undef SELECT_ENGINE
typedef float(TangentPoint)[2]
#define BLI_assert(a)
Definition: BLI_assert.h:58
void projmat_from_subregion(const float projmat[4][4], const int win_size[2], const int x_min, const int x_max, const int y_min, const int y_max, float r_projmat[4][4])
Definition: math_geom.c:5031
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:95
bool compare_m4m4(const float mat1[4][4], const float mat2[4][4], float limit)
Definition: math_matrix.c:1406
unsigned int uint
Definition: BLI_sys_types.h:83
#define ARRAY_SIZE(arr)
#define N_(msgid)
@ ID_RECALC_TRANSFORM
Definition: DNA_ID.h:599
@ OB_SOLID
#define SCE_SELECT_FACE
#define SCE_SELECT_VERTEX
#define SCE_SELECT_EDGE
#define RV3D_CLIPPING_ENABLED(v3d, rv3d)
DRWState
Definition: DRW_render.h:312
@ DRW_STATE_CLIP_PLANES
Definition: DRW_render.h:354
@ DRW_STATE_FIRST_VERTEX_CONVENTION
Definition: DRW_render.h:355
#define DRW_SHADER_FREE_SAFE(shader)
Definition: DRW_render.h:279
#define DRW_PASS_CREATE(pass, state)
Definition: DRW_render.h:593
#define DRW_shgroup_call_obmat(shgroup, geom, obmat)
Definition: DRW_render.h:424
#define DRW_STATE_DEFAULT
Definition: DRW_render.h:360
#define DRW_VIEWPORT_DATA_SIZE(ty)
Definition: DRW_render.h:97
#define DRW_TEXTURE_FREE_SAFE(tex)
Definition: DRW_render.h:180
GPUBatch
Definition: GPU_batch.h:93
struct GPUFrameBuffer GPUFrameBuffer
#define GPU_FRAMEBUFFER_FREE_SAFE(fb)
bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
GPUFrameBuffer * GPU_framebuffer_create(const char *name)
eGPUShaderConfig
Definition: GPU_shader.h:391
const GPUShaderConfigData GPU_shader_cfg_data[GPU_SHADER_CFG_LEN]
#define GPU_shader_create_from_arrays(...)
Definition: GPU_shader.h:69
#define GPU_SHADER_CFG_LEN
Definition: GPU_shader.h:395
int GPU_texture_height(const GPUTexture *tex)
Definition: gpu_texture.cc:532
struct GPUTexture GPUTexture
Definition: GPU_texture.h:33
int GPU_texture_width(const GPUTexture *tex)
Definition: gpu_texture.cc:527
void GPU_texture_free(GPUTexture *tex)
Definition: gpu_texture.cc:508
GPUTexture * GPU_texture_create_2d(const char *name, int w, int h, int mip_len, eGPUTextureFormat format, const float *data)
Definition: gpu_texture.cc:250
@ GPU_R32UI
Definition: GPU_texture.h:109
#define MEM_SAFE_FREE(v)
#define RE_USE_STEREO_VIEWPORT
Definition: RE_engine.h:65
#define RE_INTERNAL
Definition: RE_engine.h:57
#define RE_USE_GPU_CONTEXT
Definition: RE_engine.h:66
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
struct GPUBatch * DRW_mesh_batch_cache_get_triangles_with_select_id(struct Mesh *me)
struct GPUBatch * DRW_mesh_batch_cache_get_edges_with_select_id(struct Mesh *me)
struct GPUBatch * DRW_mesh_batch_cache_get_verts_with_select_id(struct Mesh *me)
struct GPUBatch * DRW_mesh_batch_cache_get_surface(struct Mesh *me)
struct DRW_Global G_draw
Definition: draw_common.c:45
DRWView * DRW_view_create_with_zoffset(const DRWView *parent_view, const RegionView3D *rv3d, float offset)
Definition: draw_common.c:271
DrawData * DRW_drawdata_ensure(ID *id, DrawEngineType *engine_type, size_t size, DrawDataInitCb init_cb, DrawDataFreeCb free_cb)
Definition: draw_manager.c:899
DefaultFramebufferList * DRW_viewport_framebuffer_list_get(void)
Definition: draw_manager.c:697
const DRWContextState * DRW_context_state_get(void)
DrawData * DRW_drawdata_get(ID *id, DrawEngineType *engine_type)
Definition: draw_manager.c:883
DefaultTextureList * DRW_viewport_texture_list_get(void)
Definition: draw_manager.c:702
void DRW_shgroup_uniform_float_copy(DRWShadingGroup *shgroup, const char *name, const float value)
const DRWView * DRW_view_default_get(void)
void DRW_view_winmat_get(const DRWView *view, float mat[4][4], bool inverse)
void DRW_shgroup_uniform_int_copy(DRWShadingGroup *shgroup, const char *name, const int value)
bool DRW_pass_is_empty(DRWPass *pass)
DRWView * DRW_view_create(const float viewmat[4][4], const float winmat[4][4], const float(*culling_viewmat)[4], const float(*culling_winmat)[4], DRWCallVisibilityFn *visibility_fn)
DRWShadingGroup * DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass)
void DRW_view_viewmat_get(const DRWView *view, float mat[4][4], bool inverse)
void DRW_view_set_active(DRWView *view)
void DRW_draw_pass(DRWPass *pass)
bool DRW_culling_min_max_test(const DRWView *view, float obmat[4][4], float min[3], float max[3])
void GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int mip)
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static ulong state[N]
short select_id_get_object_select_mode(Scene *scene, Object *ob)
void select_id_object_min_max(Object *obj, float r_min[3], float r_max[3])
void select_id_draw_object(void *vedata, View3D *v3d, Object *ob, short select_mode, uint initial_offset, uint *r_vert_offset, uint *r_edge_offset, uint *r_face_offset)
char datatoc_selection_id_frag_glsl[]
DrawEngineType draw_engine_select_type
struct GPUTexture * texture_u32
Definition: select_engine.c:44
SELECTID_Shaders sh_data[GPU_SHADER_CFG_LEN]
Definition: select_engine.c:46
struct SELECTID_Context * DRW_select_engine_context_get(void)
struct GPUFrameBuffer * framebuffer_select_id
Definition: select_engine.c:43
static void select_cache_populate(void *vedata, Object *ob)
static void select_cache_init(void *vedata)
char datatoc_selection_id_3D_vert_glsl[]
char datatoc_common_view_lib_glsl[]
RenderEngineType DRW_engine_viewport_select_type
GPUFrameBuffer * DRW_engine_select_framebuffer_get(void)
static void select_engine_framebuffer_setup(void)
Definition: select_engine.c:60
uint runtime_new_objects
Definition: select_engine.c:48
static const DrawEngineDataSize select_data_size
static void select_engine_free(void)
static struct @255 e_data
GPUTexture * DRW_engine_select_texture_get(void)
static void select_draw_scene(void *vedata)
static void select_engine_init(void *vedata)
Definition: select_engine.c:96
#define SELECT_ENGINE
Definition: select_engine.c:38
struct SELECTID_Context context
Definition: select_engine.c:47
#define min(a, b)
Definition: sort.c:51
struct Object * obact
Definition: DRW_render.h:749
struct Scene * scene
Definition: DRW_render.h:745
eGPUShaderConfig sh_cfg
Definition: DRW_render.h:759
struct View3D * v3d
Definition: DRW_render.h:742
struct ARegion * region
Definition: DRW_render.h:740
struct RegionView3D * rv3d
Definition: DRW_render.h:741
GlobalsUboStorage block
Definition: draw_common.h:208
struct GPUFrameBuffer * depth_only_fb
struct GPUTexture * depth
int recalc
Definition: DNA_ID.h:55
const char * lib
Definition: GPU_shader.h:398
const char * def
Definition: GPU_shader.h:399
float obmat[4][4]
void * data
float persmat[4][4]
struct DRWPass * depth_only_pass
struct DRWPass * select_id_vert_pass
struct DRWPass * select_id_face_pass
struct DRWPass * select_id_edge_pass
DRWShadingGroup * shgrp_face_unif
DRWShadingGroup * shgrp_edge
DRWShadingGroup * shgrp_depth_only
DRWShadingGroup * shgrp_face_flat
DRWShadingGroup * shgrp_vert
struct GPUShader * select_id_uniform
struct GPUShader * select_id_flat
struct SELECTID_PrivateData * g_data
float max