Blender V4.3
extract_mesh_vbo_weights.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2021 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include "BLI_array_utils.hh"
12
13#include "BKE_deform.hh"
14#include "BKE_mesh.hh"
15
16#include "draw_subdivision.hh"
17#include "extract_mesh.hh"
18
19namespace blender::draw {
20
21static float evaluate_vertex_weight(const MDeformVert *dvert, const DRW_MeshWeightState *wstate)
22{
23 /* Error state. */
24 if ((wstate->defgroup_active < 0) && (wstate->defgroup_len > 0)) {
25 return -2.0f;
26 }
27
28 float input = 0.0f;
30 /* Multi-Paint feature */
34 wstate->defgroup_len,
35 wstate->defgroup_sel,
36 wstate->defgroup_sel_count,
38 /* make it black if the selected groups have no weight on a vertex */
39 if (input == 0.0f) {
40 return -1.0f;
41 }
42 }
43 else {
44 /* default, non tricky behavior */
45 input = BKE_defvert_find_weight(dvert, wstate->defgroup_active);
46
47 if (input == 0.0f) {
48 switch (wstate->alert_mode) {
50 return -1.0f;
51 break;
53 if (BKE_defvert_is_weight_zero(dvert, wstate->defgroup_len)) {
54 return -1.0f;
55 }
56 break;
57 }
58 }
59 }
60
61 /* Lock-Relative: display the fraction of current weight vs total unlocked weight. */
64 input, dvert, wstate->defgroup_len, wstate->defgroup_locked, wstate->defgroup_unlocked);
65 }
66
67 CLAMP(input, 0.0f, 1.0f);
68 return input;
69}
70
72 const DRW_MeshWeightState &weight_state,
73 MutableSpan<float> vbo_data)
74{
75 const Mesh &mesh = *mr.mesh;
76 const Span<MDeformVert> dverts = mesh.deform_verts();
77 if (dverts.is_empty()) {
78 vbo_data.fill(weight_state.alert_mode == OB_DRAW_GROUPUSER_NONE ? 0.0f : -1.0f);
79 return;
80 }
81
82 Array<float> weights(dverts.size());
83 threading::parallel_for(weights.index_range(), 1024, [&](const IndexRange range) {
84 for (const int vert : range) {
85 weights[vert] = evaluate_vertex_weight(&dverts[vert], &weight_state);
86 }
87 });
88 array_utils::gather(weights.as_span(), mr.corner_verts, vbo_data);
89}
90
91static void extract_weights_bm(const MeshRenderData &mr,
92 const DRW_MeshWeightState &weight_state,
93 MutableSpan<float> vbo_data)
94{
95 const BMesh &bm = *mr.bm;
96 const int offset = CustomData_get_offset(&bm.vdata, CD_MDEFORMVERT);
97 if (offset == -1) {
98 vbo_data.fill(weight_state.alert_mode == OB_DRAW_GROUPUSER_NONE ? 0.0f : -1.0f);
99 return;
100 }
101
102 threading::parallel_for(IndexRange(bm.totface), 2048, [&](const IndexRange range) {
103 for (const int face_index : range) {
104 const BMFace &face = *BM_face_at_index(&const_cast<BMesh &>(bm), face_index);
105 const BMLoop *loop = BM_FACE_FIRST_LOOP(&face);
106 for ([[maybe_unused]] const int i : IndexRange(face.len)) {
107 const int index = BM_elem_index_get(loop);
108 vbo_data[index] = evaluate_vertex_weight(
109 static_cast<const MDeformVert *>(BM_ELEM_CD_GET_VOID_P(loop->v, offset)),
110 &weight_state);
111 loop = loop->next;
112 }
113 }
114 });
115}
116
118{
119 static GPUVertFormat format = {0};
120 if (format.attr_len == 0) {
122 }
125 MutableSpan<float> vbo_data = vbo.data<float>();
126
127 const DRW_MeshWeightState &weight_state = cache.weight_state;
128 if (weight_state.defgroup_active == -1) {
129 vbo_data.fill(weight_state.alert_mode == OB_DRAW_GROUPUSER_NONE ? 0.0f : -1.0f);
130 return;
131 }
132
133 if (mr.extract_type == MR_EXTRACT_MESH) {
134 extract_weights_mesh(mr, weight_state, vbo_data);
135 }
136 else {
137 extract_weights_bm(mr, weight_state, vbo_data);
138 }
139}
140
142 const DRWSubdivCache &subdiv_cache,
143 const MeshBatchCache &cache,
144 gpu::VertBuf &vbo)
145{
146 static GPUVertFormat format = {0};
147 if (format.attr_len == 0) {
149 }
151
152 gpu::VertBuf *coarse_weights = GPU_vertbuf_calloc();
153 extract_weights(mr, cache, *coarse_weights);
154
155 draw_subdiv_interp_custom_data(subdiv_cache, *coarse_weights, vbo, GPU_COMP_F32, 1, 0);
156
157 GPU_vertbuf_discard(coarse_weights);
158}
159
160} // namespace blender::draw
int CustomData_get_offset(const CustomData *data, eCustomDataType type)
support for deformation groups and hooks.
float BKE_defvert_lock_relative_weight(float weight, const MDeformVert *dv, int defbase_num, const bool *defbase_locked, const bool *defbase_unlocked)
Definition deform.cc:1008
bool BKE_defvert_is_weight_zero(const MDeformVert *dvert, int defgroup_tot)
Definition deform.cc:927
float BKE_defvert_find_weight(const MDeformVert *dvert, int defgroup)
Definition deform.cc:770
float BKE_defvert_multipaint_collective_weight(const MDeformVert *dv, int defbase_num, const bool *defbase_sel, int defbase_sel_num, bool is_normalized)
Definition deform.cc:963
#define CLAMP(a, b, c)
@ CD_MDEFORMVERT
@ OB_DRAW_GROUPUSER_ACTIVE
@ OB_DRAW_GROUPUSER_NONE
@ OB_DRAW_GROUPUSER_ALL
void GPU_vertbuf_init_build_on_device(blender::gpu::VertBuf &verts, const GPUVertFormat &format, uint v_len)
#define GPU_vertbuf_init_with_format(verts, format)
blender::gpu::VertBuf * GPU_vertbuf_calloc()
void GPU_vertbuf_data_alloc(blender::gpu::VertBuf &verts, uint v_len)
void GPU_vertbuf_discard(blender::gpu::VertBuf *)
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
ATTR_WARN_UNUSED_RESULT BMesh * bm
IndexRange index_range() const
Definition BLI_array.hh:349
constexpr void fill(const T &value) const
Definition BLI_span.hh:518
constexpr int64_t size() const
Definition BLI_span.hh:253
constexpr bool is_empty() const
Definition BLI_span.hh:261
MutableSpan< T > data()
Extraction of Mesh data into VBO to feed to GPU.
format
void gather(const GVArray &src, const IndexMask &indices, GMutableSpan dst, int64_t grain_size=4096)
void extract_weights(const MeshRenderData &mr, const MeshBatchCache &cache, gpu::VertBuf &vbo)
static float evaluate_vertex_weight(const MDeformVert *dvert, const DRW_MeshWeightState *wstate)
static void extract_weights_bm(const MeshRenderData &mr, const DRW_MeshWeightState &weight_state, MutableSpan< float > vbo_data)
void extract_weights_subdiv(const MeshRenderData &mr, const DRWSubdivCache &subdiv_cache, const MeshBatchCache &cache, gpu::VertBuf &vbo)
void draw_subdiv_interp_custom_data(const DRWSubdivCache &cache, gpu::VertBuf &src_data, gpu::VertBuf &dst_data, int comp_type, int dimensions, int dst_offset)
static void extract_weights_mesh(const MeshRenderData &mr, const DRW_MeshWeightState &weight_state, MutableSpan< float > vbo_data)
bool is_normalized(const DualQuaternionBase< T > &dq)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:95
CustomData vdata
int totface