Blender  V2.93
overlay_wireframe.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 
23 #include "DNA_collection_types.h"
24 #include "DNA_mesh_types.h"
25 #include "DNA_particle_types.h"
26 #include "DNA_view3d_types.h"
27 #include "DNA_volume_types.h"
28 
29 #include "BKE_curve.h"
30 #include "BKE_displist.h"
31 #include "BKE_duplilist.h"
32 #include "BKE_editmesh.h"
33 #include "BKE_global.h"
34 #include "BKE_object.h"
35 #include "BKE_paint.h"
36 #include "BKE_particle.h"
37 
38 #include "BLI_hash.h"
39 
40 #include "DRW_render.h"
41 #include "GPU_shader.h"
42 
43 #include "ED_view3d.h"
44 
45 #include "overlay_private.h"
46 
48 {
49  OVERLAY_PrivateData *pd = vedata->stl->pd;
50  const DRWContextState *draw_ctx = DRW_context_state_get();
51  DRWView *default_view = (DRWView *)DRW_view_default_get();
52  pd->view_wires = DRW_view_create_with_zoffset(default_view, draw_ctx->rv3d, 0.5f);
53 }
54 
56 {
57  OVERLAY_PassList *psl = vedata->psl;
58  OVERLAY_TextureList *txl = vedata->txl;
59  OVERLAY_PrivateData *pd = vedata->stl->pd;
60  const DRWContextState *draw_ctx = DRW_context_state_get();
61  DRWShadingGroup *grp = NULL;
62 
63  View3DShading *shading = &draw_ctx->v3d->shading;
64 
65  pd->shdata.wire_step_param = pd->overlay.wireframe_threshold - 254.0f / 255.0f;
67 
68  bool is_wire_shmode = (shading->type == OB_WIRE);
69  bool is_material_shmode = (shading->type > OB_SOLID);
70  bool is_object_color = is_wire_shmode && (shading->wire_color_type == V3D_SHADING_OBJECT_COLOR);
71  bool is_random_color = is_wire_shmode && (shading->wire_color_type == V3D_SHADING_RANDOM_COLOR);
72 
73  const bool use_select = (DRW_state_is_select() || DRW_state_is_depth());
74  GPUShader *wires_sh = use_select ? OVERLAY_shader_wireframe_select() :
76 
77  for (int xray = 0; xray < (is_material_shmode ? 1 : 2); xray++) {
80  DRWPass *pass;
81  GPUTexture **depth_tx = ((!pd->xray_enabled || pd->xray_opacity > 0.0f) &&
82  DRW_state_is_fbo()) ?
83  &txl->temp_depth_tx :
84  &txl->dummy_depth_tx;
85 
86  if (xray == 0) {
88  pass = psl->wireframe_ps;
89  }
90  else {
92  pass = psl->wireframe_xray_ps;
93  }
94 
95  for (int use_coloring = 0; use_coloring < 2; use_coloring++) {
96  pd->wires_grp[xray][use_coloring] = grp = DRW_shgroup_create(wires_sh, pass);
97  DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
98  DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tx);
99  DRW_shgroup_uniform_float_copy(grp, "wireStepParam", pd->shdata.wire_step_param);
100  DRW_shgroup_uniform_float_copy(grp, "wireOpacity", pd->shdata.wire_opacity);
101  DRW_shgroup_uniform_bool_copy(grp, "useColoring", use_coloring);
102  DRW_shgroup_uniform_bool_copy(grp, "isTransform", (G.moving & G_TRANSFORM_OBJ) != 0);
103  DRW_shgroup_uniform_bool_copy(grp, "isObjectColor", is_object_color);
104  DRW_shgroup_uniform_bool_copy(grp, "isRandomColor", is_random_color);
105  DRW_shgroup_uniform_bool_copy(grp, "isHair", false);
106 
107  pd->wires_all_grp[xray][use_coloring] = grp = DRW_shgroup_create(wires_sh, pass);
108  DRW_shgroup_uniform_float_copy(grp, "wireStepParam", 1.0f);
109 
110  pd->wires_hair_grp[xray][use_coloring] = grp = DRW_shgroup_create(wires_sh, pass);
111  DRW_shgroup_uniform_bool_copy(grp, "isHair", true);
112  DRW_shgroup_uniform_float_copy(grp, "wireStepParam", 10.0f);
113  }
114 
115  pd->wires_sculpt_grp[xray] = grp = DRW_shgroup_create(wires_sh, pass);
116  DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tx);
117  DRW_shgroup_uniform_float_copy(grp, "wireStepParam", 10.0f);
118  DRW_shgroup_uniform_bool_copy(grp, "useColoring", false);
119  DRW_shgroup_uniform_bool_copy(grp, "isHair", false);
120  }
121 
122  if (is_material_shmode) {
123  /* Make all drawcalls go into the non-xray shading groups. */
124  for (int use_coloring = 0; use_coloring < 2; use_coloring++) {
125  pd->wires_grp[1][use_coloring] = pd->wires_grp[0][use_coloring];
126  pd->wires_all_grp[1][use_coloring] = pd->wires_all_grp[0][use_coloring];
127  pd->wires_hair_grp[1][use_coloring] = pd->wires_hair_grp[0][use_coloring];
128  }
129  pd->wires_sculpt_grp[1] = pd->wires_sculpt_grp[0];
130  psl->wireframe_xray_ps = NULL;
131  }
132 }
133 
135 {
136  OVERLAY_PrivateData *pd = vedata->stl->pd;
137  const bool is_xray = (ob->dtx & OB_DRAW_IN_FRONT) != 0;
138 
139  Object *dupli_parent = DRW_object_get_dupli_parent(ob);
140  DupliObject *dupli_object = DRW_object_get_dupli(ob);
141 
142  float dupli_mat[4][4];
143  if ((dupli_parent != NULL) && (dupli_object != NULL)) {
144  if (dupli_object->type & OB_DUPLICOLLECTION) {
145  unit_m4(dupli_mat);
146  Collection *collection = dupli_parent->instance_collection;
147  if (collection != NULL) {
148  sub_v3_v3(dupli_mat[3], collection->instance_offset);
149  }
150  mul_m4_m4m4(dupli_mat, dupli_parent->obmat, dupli_mat);
151  }
152  else {
153  copy_m4_m4(dupli_mat, dupli_object->ob->obmat);
154  invert_m4(dupli_mat);
155  mul_m4_m4m4(dupli_mat, ob->obmat, dupli_mat);
156  }
157  }
158  else {
159  unit_m4(dupli_mat);
160  }
161 
162  struct GPUBatch *hairs = DRW_cache_particles_get_hair(ob, psys, NULL);
163 
164  const bool use_coloring = true;
165  DRWShadingGroup *shgrp = DRW_shgroup_create_sub(pd->wires_hair_grp[is_xray][use_coloring]);
166  DRW_shgroup_uniform_vec4_array_copy(shgrp, "hairDupliMatrix", dupli_mat, 4);
167  DRW_shgroup_call_no_cull(shgrp, hairs, ob);
168 }
169 
171  Object *ob,
172  OVERLAY_DupliData *dupli,
173  bool init_dupli)
174 {
175  OVERLAY_PrivateData *pd = vedata->stl->pd;
176  const DRWContextState *draw_ctx = DRW_context_state_get();
177  const bool all_wires = (ob->dtx & OB_DRAW_ALL_EDGES) != 0;
178  const bool is_xray = (ob->dtx & OB_DRAW_IN_FRONT) != 0;
179  const bool is_mesh = ob->type == OB_MESH;
180  const bool is_edit_mode = DRW_object_is_in_edit_mode(ob);
181  bool has_edit_mesh_cage = false;
182  bool is_mesh_verts_only = false;
183  if (is_mesh) {
184  /* TODO: Should be its own function. */
185  Mesh *me = ob->data;
186  if (is_edit_mode) {
187  BLI_assert(me->edit_mesh);
188  BMEditMesh *embm = me->edit_mesh;
189  has_edit_mesh_cage = embm->mesh_eval_cage && (embm->mesh_eval_cage != embm->mesh_eval_final);
190  if (embm->mesh_eval_final) {
191  me = embm->mesh_eval_final;
192  }
193  }
194  is_mesh_verts_only = me->totedge == 0 && me->totvert > 0;
195  }
196 
197  const bool use_wire = !is_mesh_verts_only && ((pd->overlay.flag & V3D_OVERLAY_WIREFRAMES) ||
198  (ob->dtx & OB_DRAWWIRE) || (ob->dt == OB_WIRE));
199 
200  if (use_wire && pd->wireframe_mode && ob->particlesystem.first) {
201  for (ParticleSystem *psys = ob->particlesystem.first; psys != NULL; psys = psys->next) {
203  continue;
204  }
205  ParticleSettings *part = psys->part;
206  const int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as;
207  if (draw_as == PART_DRAW_PATH) {
208  wireframe_hair_cache_populate(vedata, ob, psys);
209  }
210  }
211  }
212 
213  if (ELEM(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
215  float *color;
216  DRW_object_wire_theme_get(ob, draw_ctx->view_layer, &color);
217 
218  struct GPUBatch *geom = NULL;
219  switch (ob->type) {
220  case OB_CURVE:
221  if (!pd->wireframe_mode && !use_wire && ob->runtime.curve_cache &&
223  break;
224  }
226  break;
227  case OB_FONT:
228  if (!pd->wireframe_mode && !use_wire && ob->runtime.curve_cache &&
230  break;
231  }
233  break;
234  case OB_SURF:
235  geom = DRW_cache_surf_edge_wire_get(ob);
236  break;
237  }
238 
239  if (geom) {
240  OVERLAY_extra_wire(cb, geom, ob->obmat, color);
241  }
242  }
243 
244  /* Fast path for duplis. */
245  if (dupli && !init_dupli) {
246  if (dupli->wire_shgrp && dupli->wire_geom) {
247  if (dupli->base_flag == ob->base_flag) {
248  DRW_shgroup_call(dupli->wire_shgrp, dupli->wire_geom, ob);
249  return;
250  }
251  }
252  else {
253  /* Nothing to draw for this dupli. */
254  return;
255  }
256  }
257 
258  if (use_wire && ELEM(ob->type, OB_VOLUME, OB_POINTCLOUD)) {
259  bool draw_as_points = true;
260  if (ob->type == OB_VOLUME) {
261  /* Volume object as points exception. */
262  Volume *volume = ob->data;
263  draw_as_points = volume->display.wireframe_type == VOLUME_WIREFRAME_POINTS;
264  }
265 
266  if (draw_as_points) {
267  float *color;
269  DRW_object_wire_theme_get(ob, draw_ctx->view_layer, &color);
270 
272  if (geom) {
273  OVERLAY_extra_loose_points(cb, geom, ob->obmat, color);
274  }
275  return;
276  }
277  }
278 
279  /* Don't do that in edit Mesh mode, unless there is a modifier preview. */
280  if (use_wire && (!is_mesh || (!is_edit_mode || has_edit_mesh_cage))) {
281  const bool is_sculpt_mode = ((ob->mode & OB_MODE_SCULPT) != 0) && (ob->sculpt != NULL);
282  const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) &&
284  const bool use_coloring = (use_wire && !is_edit_mode && !is_sculpt_mode &&
285  !has_edit_mesh_cage);
286  DRWShadingGroup *shgrp = NULL;
288 
289  if (geom || use_sculpt_pbvh) {
290  if (use_sculpt_pbvh) {
291  shgrp = pd->wires_sculpt_grp[is_xray];
292  }
293  else if (all_wires) {
294  shgrp = pd->wires_all_grp[is_xray][use_coloring];
295  }
296  else {
297  shgrp = pd->wires_grp[is_xray][use_coloring];
298  }
299 
300  if (ob->type == OB_GPENCIL) {
301  /* TODO(fclem): Make GPencil objects have correct bound-box. */
302  DRW_shgroup_call_no_cull(shgrp, geom, ob);
303  }
304  else if (use_sculpt_pbvh) {
305  DRW_shgroup_call_sculpt(shgrp, ob, true, false);
306  }
307  else {
308  DRW_shgroup_call(shgrp, geom, ob);
309  }
310  }
311 
312  if (dupli) {
313  dupli->wire_shgrp = shgrp;
314  dupli->wire_geom = geom;
315  }
316  }
317  else if (is_mesh && (!is_edit_mode || has_edit_mesh_cage)) {
319  float *color;
320  DRW_object_wire_theme_get(ob, draw_ctx->view_layer, &color);
321 
322  /* Draw loose geometry. */
323  if (is_mesh_verts_only) {
324  struct GPUBatch *geom = DRW_cache_mesh_all_verts_get(ob);
325  if (geom) {
326  OVERLAY_extra_loose_points(cb, geom, ob->obmat, color);
327  }
328  }
329  else {
330  struct GPUBatch *geom = DRW_cache_mesh_loose_edges_get(ob);
331  if (geom) {
332  OVERLAY_extra_wire(cb, geom, ob->obmat, color);
333  }
334  }
335  }
336 }
337 
339 {
340  OVERLAY_PassList *psl = data->psl;
341  OVERLAY_PrivateData *pd = data->stl->pd;
342 
345 
347 }
348 
350 {
351  OVERLAY_PassList *psl = data->psl;
352  OVERLAY_PrivateData *pd = data->stl->pd;
353 
354  if (psl->wireframe_xray_ps) {
357 
359  }
360 }
display list (or rather multi purpose list) stuff.
bool BKE_displist_has_faces(const struct ListBase *lb)
@ G_TRANSFORM_OBJ
Definition: BKE_global.h:218
General operations, lookup, etc. for blender objects.
bool BKE_sculptsession_use_pbvh_draw(const struct Object *ob, const struct View3D *v3d)
#define BLI_assert(a)
Definition: BLI_assert.h:58
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:262
bool invert_m4(float R[4][4])
Definition: math_matrix.c:1187
void unit_m4(float m[4][4])
Definition: rct.c:1140
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:95
MINLINE void sub_v3_v3(float r[3], const float a[3])
#define ELEM(...)
Object groups, one object can be in many groups at once.
@ OB_WIRE
@ OB_SOLID
@ OB_MODE_SCULPT
@ OB_DUPLICOLLECTION
@ OB_DRAW_ALL_EDGES
@ OB_DRAW_IN_FRONT
@ OB_DRAWWIRE
@ OB_SURF
@ OB_FONT
@ OB_MESH
@ OB_POINTCLOUD
@ OB_VOLUME
@ OB_CURVE
@ OB_GPENCIL
#define PART_DRAW_PATH
#define PART_DRAW_REND
@ V3D_SHADING_OBJECT_COLOR
@ V3D_SHADING_RANDOM_COLOR
@ V3D_OVERLAY_WIREFRAMES
@ VOLUME_WIREFRAME_POINTS
#define DRW_shgroup_call_no_cull(shgroup, geom, ob)
Definition: DRW_render.h:433
DRWState
Definition: DRW_render.h:312
@ DRW_STATE_WRITE_DEPTH
Definition: DRW_render.h:314
@ DRW_STATE_WRITE_COLOR
Definition: DRW_render.h:315
@ DRW_STATE_DEPTH_LESS_EQUAL
Definition: DRW_render.h:323
@ DRW_STATE_FIRST_VERTEX_CONVENTION
Definition: DRW_render.h:355
#define DRW_PASS_CREATE(pass, state)
Definition: DRW_render.h:593
#define DRW_shgroup_call(shgroup, geom, ob)
Definition: DRW_render.h:420
GPUBatch
Definition: GPU_batch.h:93
struct GPUShader GPUShader
Definition: GPU_shader.h:33
struct GPUTexture GPUTexture
Definition: GPU_texture.h:33
GPUBatch * DRW_cache_curve_edge_wire_get(Object *ob)
Definition: draw_cache.c:2929
GPUBatch * DRW_cache_mesh_all_verts_get(Object *ob)
Definition: draw_cache.c:2835
GPUBatch * DRW_cache_object_face_wireframe_get(Object *ob)
Definition: draw_cache.c:835
GPUBatch * DRW_cache_surf_edge_wire_get(Object *ob)
Definition: draw_cache.c:3187
GPUBatch * DRW_cache_mesh_loose_edges_get(Object *ob)
Definition: draw_cache.c:2847
GPUBatch * DRW_cache_particles_get_hair(Object *object, ParticleSystem *psys, ModifierData *md)
Definition: draw_cache.c:3332
GPUBatch * DRW_cache_text_loose_edges_get(Object *ob)
Definition: draw_cache.c:3121
int DRW_object_wire_theme_get(Object *ob, ViewLayer *view_layer, float **r_color)
Definition: draw_common.c:299
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
struct Object * DRW_object_get_dupli_parent(const Object *UNUSED(ob))
Definition: draw_manager.c:301
bool DRW_state_is_select(void)
bool DRW_state_is_depth(void)
bool DRW_object_is_in_edit_mode(const Object *ob)
Definition: draw_manager.c:204
bool DRW_state_is_fbo(void)
struct DupliObject * DRW_object_get_dupli(const Object *UNUSED(ob))
Definition: draw_manager.c:306
bool DRW_object_is_visible_psys_in_active_context(const Object *object, const ParticleSystem *psys)
Definition: draw_manager.c:271
const DRWContextState * DRW_context_state_get(void)
bool DRW_state_is_image_render(void)
void DRW_shgroup_uniform_float_copy(DRWShadingGroup *shgroup, const char *name, const float value)
void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, const char *name, const GPUUniformBuf *ubo)
const DRWView * DRW_view_default_get(void)
void DRW_shgroup_uniform_vec4_array_copy(DRWShadingGroup *shgroup, const char *name, const float(*value)[4], int arraysize)
void DRW_shgroup_call_sculpt(DRWShadingGroup *shgroup, Object *ob, bool use_wire, bool use_mask)
DRWShadingGroup * DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass)
DRWShadingGroup * DRW_shgroup_create_sub(DRWShadingGroup *shgroup)
void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex)
void DRW_shgroup_uniform_bool_copy(DRWShadingGroup *shgroup, const char *name, const bool value)
void DRW_view_set_active(DRWView *view)
void DRW_draw_pass(DRWPass *pass)
static ulong state[N]
OVERLAY_ExtraCallBuffers * OVERLAY_extra_call_buffer_get(OVERLAY_Data *vedata, Object *ob)
void OVERLAY_extra_loose_points(OVERLAY_ExtraCallBuffers *cb, struct GPUBatch *geom, const float mat[4][4], const float color[4])
void OVERLAY_extra_wire(OVERLAY_ExtraCallBuffers *cb, struct GPUBatch *geom, const float mat[4][4], const float color[4])
GPUShader * OVERLAY_shader_wireframe(bool custom_bias)
GPUShader * OVERLAY_shader_wireframe_select(void)
static void wireframe_hair_cache_populate(OVERLAY_Data *vedata, Object *ob, ParticleSystem *psys)
void OVERLAY_wireframe_in_front_draw(OVERLAY_Data *data)
void OVERLAY_wireframe_draw(OVERLAY_Data *data)
void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata, Object *ob, OVERLAY_DupliData *dupli, bool init_dupli)
void OVERLAY_wireframe_cache_init(OVERLAY_Data *vedata)
void OVERLAY_wireframe_init(OVERLAY_Data *vedata)
struct Mesh * mesh_eval_final
Definition: BKE_editmesh.h:63
struct Mesh * mesh_eval_cage
Definition: BKE_editmesh.h:63
float instance_offset[3]
ListBase disp
Definition: BKE_curve.h:49
struct ViewLayer * view_layer
Definition: DRW_render.h:746
struct View3D * v3d
Definition: DRW_render.h:742
struct RegionView3D * rv3d
Definition: DRW_render.h:741
struct GPUUniformBuf * block_ubo
Definition: draw_common.h:210
struct Object * ob
Definition: BKE_duplilist.h:45
void * first
Definition: DNA_listBase.h:47
struct BMEditMesh * edit_mesh
int totedge
int totvert
OVERLAY_PassList * psl
OVERLAY_StorageList * stl
OVERLAY_TextureList * txl
struct GPUBatch * wire_geom
DRWShadingGroup * wire_shgrp
DRWPass * wireframe_ps
DRWPass * wireframe_xray_ps
OVERLAY_ShadingData shdata
View3DOverlay overlay
struct OVERLAY_PrivateData::@239 antialiasing
DRWShadingGroup * wires_all_grp[2][2]
DRWShadingGroup * wires_hair_grp[2][2]
DRWShadingGroup * wires_grp[2][2]
DRWShadingGroup * wires_sculpt_grp[2]
struct OVERLAY_PrivateData * pd
struct GPUTexture * dummy_depth_tx
struct GPUTexture * temp_depth_tx
struct CurveCache * curve_cache
ListBase particlesystem
struct Collection * instance_collection
short base_flag
Object_Runtime runtime
float obmat[4][4]
struct SculptSession * sculpt
void * data
View3DShading shading
VolumeDisplay display
#define G(x, y, z)