Blender V5.0
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
8
10
11#include "BLI_array_utils.hh"
12
13#include "BKE_deform.hh"
14
15#include "draw_subdivision.hh"
16#include "extract_mesh.hh"
17
18namespace blender::draw {
19
20static float evaluate_vertex_weight(const MDeformVert *dvert, const DRW_MeshWeightState *wstate)
21{
22 /* Error state. */
23 if ((wstate->defgroup_active < 0) && (wstate->defgroup_len > 0)) {
24 return -2.0f;
25 }
26
27 float input = 0.0f;
29 /* Multi-Paint feature */
33 wstate->defgroup_len,
34 wstate->defgroup_sel,
35 wstate->defgroup_sel_count,
37 /* make it black if the selected groups have no weight on a vertex */
38 if (input == 0.0f) {
39 return -1.0f;
40 }
41 }
42 else {
43 /* default, non tricky behavior */
45
46 if (input == 0.0f) {
47 switch (wstate->alert_mode) {
49 return -1.0f;
50 break;
52 if (BKE_defvert_is_weight_zero(dvert, wstate->defgroup_len)) {
53 return -1.0f;
54 }
55 break;
56 }
57 }
58 }
59
60 /* Lock-Relative: display the fraction of current weight vs total unlocked weight. */
63 input, dvert, wstate->defgroup_len, wstate->defgroup_locked, wstate->defgroup_unlocked);
64 }
65
66 CLAMP(input, 0.0f, 1.0f);
67 return input;
68}
69
71 const DRW_MeshWeightState &weight_state,
72 MutableSpan<float> vbo_data)
73{
74 const Mesh &mesh = *mr.mesh;
75 const Span<MDeformVert> dverts = mesh.deform_verts();
76 if (dverts.is_empty()) {
77 vbo_data.fill(weight_state.alert_mode == OB_DRAW_GROUPUSER_NONE ? 0.0f : -1.0f);
78 return;
79 }
80
81 Array<float> weights(dverts.size());
82 threading::parallel_for(weights.index_range(), 1024, [&](const IndexRange range) {
83 for (const int vert : range) {
84 weights[vert] = evaluate_vertex_weight(&dverts[vert], &weight_state);
85 }
86 });
87 array_utils::gather(weights.as_span(), mr.corner_verts, vbo_data);
88}
89
90static void extract_weights_bm(const MeshRenderData &mr,
91 const DRW_MeshWeightState &weight_state,
92 MutableSpan<float> vbo_data)
93{
94 const BMesh &bm = *mr.bm;
95 const int offset = CustomData_get_offset(&bm.vdata, CD_MDEFORMVERT);
96 if (offset == -1) {
97 vbo_data.fill(weight_state.alert_mode == OB_DRAW_GROUPUSER_NONE ? 0.0f : -1.0f);
98 return;
99 }
100
101 threading::parallel_for(IndexRange(bm.totface), 2048, [&](const IndexRange range) {
102 for (const int face_index : range) {
103 const BMFace &face = *BM_face_at_index(&const_cast<BMesh &>(bm), face_index);
104 const BMLoop *loop = BM_FACE_FIRST_LOOP(&face);
105 for ([[maybe_unused]] const int i : IndexRange(face.len)) {
106 const int index = BM_elem_index_get(loop);
107 vbo_data[index] = evaluate_vertex_weight(
108 static_cast<const MDeformVert *>(BM_ELEM_CD_GET_VOID_P(loop->v, offset)),
109 &weight_state);
110 loop = loop->next;
111 }
112 }
113 });
114}
115
117{
119 gpu::VertAttrType::SFLOAT_32);
120
123 MutableSpan<float> vbo_data = vbo->data<float>();
124
125 const DRW_MeshWeightState &weight_state = cache.weight_state;
126 if (weight_state.defgroup_active == -1) {
127 vbo_data.fill(weight_state.alert_mode == OB_DRAW_GROUPUSER_NONE ? 0.0f : -1.0f);
128 return vbo;
129 }
130
132 extract_weights_mesh(mr, weight_state, vbo_data);
133 }
134 else {
135 extract_weights_bm(mr, weight_state, vbo_data);
136 }
137 return vbo;
138}
139
141 const DRWSubdivCache &subdiv_cache,
142 const MeshBatchCache &cache)
143{
145 gpu::VertAttrType::SFLOAT_32);
146
149
150 gpu::VertBufPtr coarse_weights = extract_weights(mr, cache);
151 draw_subdiv_interp_custom_data(subdiv_cache, *coarse_weights, *vbo, GPU_COMP_F32, 1, 0);
152 return vbo;
153}
154
155} // 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:1017
bool BKE_defvert_is_weight_zero(const MDeformVert *dvert, int defgroup_tot)
Definition deform.cc:936
float BKE_defvert_find_weight(const MDeformVert *dvert, int defgroup)
Definition deform.cc:774
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:972
#define CLAMP(a, b, c)
@ CD_MDEFORMVERT
@ OB_DRAW_GROUPUSER_ACTIVE
@ OB_DRAW_GROUPUSER_NONE
@ OB_DRAW_GROUPUSER_ALL
blender::gpu::VertBuf * GPU_vertbuf_create_on_device(const GPUVertFormat &format, uint v_len)
static blender::gpu::VertBuf * GPU_vertbuf_create_with_format(const GPUVertFormat &format)
void GPU_vertbuf_data_alloc(blender::gpu::VertBuf &verts, uint v_len)
GPUVertFormat GPU_vertformat_from_attribute(blender::StringRef name, blender::gpu::VertAttrType type)
@ GPU_COMP_F32
BMesh * bm
IndexRange index_range() const
Definition BLI_array.hh:360
constexpr T * data() const
Definition BLI_span.hh:539
constexpr void fill(const T &value) const
Definition BLI_span.hh:517
constexpr int64_t size() const
Definition BLI_span.hh:252
constexpr bool is_empty() const
Definition BLI_span.hh:260
Extraction of Mesh data into VBO to feed to GPU.
#define input
format
void gather(const GVArray &src, const IndexMask &indices, GMutableSpan dst, int64_t grain_size=4096)
void draw_subdiv_interp_custom_data(const DRWSubdivCache &cache, gpu::VertBuf &src_data, gpu::VertBuf &dst_data, GPUVertCompType comp_type, int dimensions, int dst_offset)
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)
static void extract_weights_mesh(const MeshRenderData &mr, const DRW_MeshWeightState &weight_state, MutableSpan< float > vbo_data)
gpu::VertBufPtr extract_weights(const MeshRenderData &mr, const MeshBatchCache &cache)
gpu::VertBufPtr extract_weights_subdiv(const MeshRenderData &mr, const DRWSubdivCache &subdiv_cache, const MeshBatchCache &cache)
std::unique_ptr< gpu::VertBuf, gpu::VertBufDeleter > VertBufPtr
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:93