Blender  V3.3
extract_mesh_vbo_weights.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2021 Blender Foundation. All rights reserved. */
3 
8 #include "MEM_guardedalloc.h"
9 
10 #include "BKE_deform.h"
11 
12 #include "draw_subdivision.h"
13 #include "extract_mesh.hh"
14 
15 namespace blender::draw {
16 
17 /* ---------------------------------------------------------------------- */
22  float *vbo_data;
24  const MDeformVert *dvert; /* For #Mesh. */
25  int cd_ofs; /* For #BMesh. */
26 };
27 
28 static float evaluate_vertex_weight(const MDeformVert *dvert, const DRW_MeshWeightState *wstate)
29 {
30  /* Error state. */
31  if ((wstate->defgroup_active < 0) && (wstate->defgroup_len > 0)) {
32  return -2.0f;
33  }
34  if (dvert == nullptr) {
35  return (wstate->alert_mode != OB_DRAW_GROUPUSER_NONE) ? -1.0f : 0.0f;
36  }
37 
38  float input = 0.0f;
40  /* Multi-Paint feature */
41  bool is_normalized = (wstate->flags & (DRW_MESH_WEIGHT_STATE_AUTO_NORMALIZE |
44  wstate->defgroup_len,
45  wstate->defgroup_sel,
46  wstate->defgroup_sel_count,
47  is_normalized);
48  /* make it black if the selected groups have no weight on a vertex */
49  if (input == 0.0f) {
50  return -1.0f;
51  }
52  }
53  else {
54  /* default, non tricky behavior */
56 
57  if (input == 0.0f) {
58  switch (wstate->alert_mode) {
60  return -1.0f;
61  break;
63  if (BKE_defvert_is_weight_zero(dvert, wstate->defgroup_len)) {
64  return -1.0f;
65  }
66  break;
67  }
68  }
69  }
70 
71  /* Lock-Relative: display the fraction of current weight vs total unlocked weight. */
74  input, dvert, wstate->defgroup_len, wstate->defgroup_locked, wstate->defgroup_unlocked);
75  }
76 
77  CLAMP(input, 0.0f, 1.0f);
78  return input;
79 }
80 
81 static void extract_weights_init(const MeshRenderData *mr,
82  MeshBatchCache *cache,
83  void *buf,
84  void *tls_data)
85 {
86  GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
87  static GPUVertFormat format = {0};
88  if (format.attr_len == 0) {
90  }
93 
94  MeshExtract_Weight_Data *data = static_cast<MeshExtract_Weight_Data *>(tls_data);
95  data->vbo_data = (float *)GPU_vertbuf_get_data(vbo);
96  data->wstate = &cache->weight_state;
97 
98  if (data->wstate->defgroup_active == -1) {
99  /* Nothing to show. */
100  data->dvert = nullptr;
101  data->cd_ofs = -1;
102  }
103  else if (mr->extract_type == MR_EXTRACT_BMESH) {
104  data->dvert = nullptr;
106  }
107  else {
108  data->dvert = (const MDeformVert *)CustomData_get_layer(&mr->me->vdata, CD_MDEFORMVERT);
109  data->cd_ofs = -1;
110  }
111 }
112 
114  const BMFace *f,
115  const int UNUSED(f_index),
116  void *_data)
117 {
118  MeshExtract_Weight_Data *data = static_cast<MeshExtract_Weight_Data *>(_data);
119  BMLoop *l_iter, *l_first;
120  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
121  do {
122  const int l_index = BM_elem_index_get(l_iter);
123  if (data->cd_ofs != -1) {
124  const MDeformVert *dvert = (const MDeformVert *)BM_ELEM_CD_GET_VOID_P(l_iter->v,
125  data->cd_ofs);
126  data->vbo_data[l_index] = evaluate_vertex_weight(dvert, data->wstate);
127  }
128  else {
129  data->vbo_data[l_index] = evaluate_vertex_weight(nullptr, data->wstate);
130  }
131  } while ((l_iter = l_iter->next) != l_first);
132 }
133 
135  const MPoly *mp,
136  const int UNUSED(mp_index),
137  void *_data)
138 {
139  MeshExtract_Weight_Data *data = static_cast<MeshExtract_Weight_Data *>(_data);
140  const MLoop *mloop = mr->mloop;
141  const int ml_index_end = mp->loopstart + mp->totloop;
142  for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
143  const MLoop *ml = &mloop[ml_index];
144  if (data->dvert != nullptr) {
145  const MDeformVert *dvert = &data->dvert[ml->v];
146  data->vbo_data[ml_index] = evaluate_vertex_weight(dvert, data->wstate);
147  }
148  else {
149  const MDeformVert *dvert = nullptr;
150  data->vbo_data[ml_index] = evaluate_vertex_weight(dvert, data->wstate);
151  }
152  }
153 }
154 
155 static void extract_weights_init_subdiv(const DRWSubdivCache *subdiv_cache,
156  const MeshRenderData *mr,
157  MeshBatchCache *cache,
158  void *buffer,
159  void *_data)
160 {
161  Mesh *coarse_mesh = subdiv_cache->mesh;
162  GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer);
163 
164  static GPUVertFormat format = {0};
165  if (format.attr_len == 0) {
167  }
169 
170  GPUVertBuf *coarse_weights = GPU_vertbuf_calloc();
171  extract_weights_init(mr, cache, coarse_weights, _data);
172 
173  if (mr->extract_type != MR_EXTRACT_BMESH) {
174  for (int i = 0; i < coarse_mesh->totpoly; i++) {
175  const MPoly *mpoly = &coarse_mesh->mpoly[i];
176  extract_weights_iter_poly_mesh(mr, mpoly, i, _data);
177  }
178  }
179  else {
180  BMIter f_iter;
181  BMFace *efa;
182  int face_index = 0;
183  BM_ITER_MESH_INDEX (efa, &f_iter, mr->bm, BM_FACES_OF_MESH, face_index) {
184  extract_weights_iter_poly_bm(mr, efa, face_index, _data);
185  }
186  }
187 
188  draw_subdiv_interp_custom_data(subdiv_cache, coarse_weights, vbo, 1, 0, false);
189 
190  GPU_vertbuf_discard(coarse_weights);
191 }
192 
194 {
195  MeshExtract extractor = {nullptr};
196  extractor.init = extract_weights_init;
200  extractor.data_type = MR_DATA_NONE;
201  extractor.data_size = sizeof(MeshExtract_Weight_Data);
202  extractor.use_threading = true;
203  extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.weights);
204  return extractor;
205 }
206 
209 } // namespace blender::draw
210 
void * CustomData_get_layer(const struct CustomData *data, int type)
int CustomData_get_offset(const struct CustomData *data, int type)
support for deformation groups and hooks.
bool BKE_defvert_is_weight_zero(const struct MDeformVert *dvert, int defgroup_tot)
Definition: deform.c:858
float BKE_defvert_lock_relative_weight(float weight, const struct MDeformVert *dv, int defbase_tot, const bool *defbase_locked, const bool *defbase_unlocked)
Definition: deform.c:939
float BKE_defvert_find_weight(const struct MDeformVert *dvert, int defgroup)
Definition: deform.c:704
float BKE_defvert_multipaint_collective_weight(const struct MDeformVert *dv, int defbase_tot, const bool *defbase_sel, int defbase_tot_sel, bool is_normalized)
Definition: deform.c:894
#define UNUSED(x)
@ CD_MDEFORMVERT
@ OB_DRAW_GROUPUSER_ACTIVE
@ OB_DRAW_GROUPUSER_NONE
@ OB_DRAW_GROUPUSER_ALL
void GPU_vertbuf_discard(GPUVertBuf *)
struct GPUVertBuf GPUVertBuf
GPUVertBuf * GPU_vertbuf_calloc(void)
void GPU_vertbuf_data_alloc(GPUVertBuf *, uint v_len)
#define GPU_vertbuf_init_with_format(verts, format)
void * GPU_vertbuf_get_data(const GPUVertBuf *verts)
void GPU_vertbuf_init_build_on_device(GPUVertBuf *verts, GPUVertFormat *format, uint v_len)
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
Read Guarded memory(de)allocation.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
#define BM_FACE_FIRST_LOOP(p)
Definition: bmesh_class.h:622
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
Definition: bmesh_class.h:541
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:110
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar)
@ BM_FACES_OF_MESH
@ DRW_MESH_WEIGHT_STATE_MULTIPAINT
@ DRW_MESH_WEIGHT_STATE_AUTO_NORMALIZE
@ DRW_MESH_WEIGHT_STATE_LOCK_RELATIVE
@ MR_DATA_NONE
void draw_subdiv_interp_custom_data(const DRWSubdivCache *cache, GPUVertBuf *src_data, GPUVertBuf *dst_data, int dimensions, int dst_offset, bool compress_to_u16)
Extraction of Mesh data into VBO to feed to GPU.
@ MR_EXTRACT_BMESH
Definition: extract_mesh.hh:31
const MeshExtract extract_weights
ccl_global float * buffer
ccl_global KernelShaderEvalInput * input
format
Definition: logImageCore.h:38
static void extract_weights_init_subdiv(const DRWSubdivCache *subdiv_cache, const MeshRenderData *mr, MeshBatchCache *cache, void *buffer, void *_data)
static void extract_weights_iter_poly_mesh(const MeshRenderData *mr, const MPoly *mp, const int UNUSED(mp_index), void *_data)
static void extract_weights_init(const MeshRenderData *mr, MeshBatchCache *cache, void *buf, void *tls_data)
static void extract_weights_iter_poly_bm(const MeshRenderData *UNUSED(mr), const BMFace *f, const int UNUSED(f_index), void *_data)
static float evaluate_vertex_weight(const MDeformVert *dvert, const DRW_MeshWeightState *wstate)
constexpr MeshExtract create_extractor_weights()
struct BMVert * v
Definition: bmesh_class.h:153
struct BMLoop * next
Definition: bmesh_class.h:233
CustomData vdata
Definition: bmesh_class.h:337
struct Mesh * mesh
unsigned int v
DRW_MeshWeightState weight_state
GPUVertBuf * weights
size_t mesh_buffer_offset
eMRDataType data_type
ExtractInitSubdivFn * init_subdiv
size_t data_size
ExtractPolyBMeshFn * iter_poly_bm
ExtractPolyMeshFn * iter_poly_mesh
bool use_threading
ExtractInitFn * init
eMRExtractType extract_type
Definition: extract_mesh.hh:37
const MLoop * mloop
Definition: extract_mesh.hh:76
CustomData vdata
int totpoly
struct MPoly * mpoly