Blender V4.3
draw_sculpt.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "draw_sculpt.hh"
10
11#include "draw_attributes.hh"
12
13#include "BKE_attribute.hh"
14#include "BKE_mesh_types.hh"
15#include "BKE_paint.hh"
16
17#include "DRW_pbvh.hh"
18
19namespace blender::draw {
20
22{
23 static float3 colors[9] = {
24 {1.0f, 0.2f, 0.2f},
25 {0.2f, 1.0f, 0.2f},
26 {0.2f, 0.2f, 1.0f},
27 {1.0f, 1.0f, 0.2f},
28 {0.2f, 1.0f, 1.0f},
29 {1.0f, 0.2f, 1.0f},
30 {1.0f, 0.7f, 0.2f},
31 {0.2f, 1.0f, 0.7f},
32 {0.7f, 0.2f, 1.0f},
33 };
34
35 return colors[debug_index % 9];
36}
37
39 const bool use_wire,
41{
42 /* pbvh::Tree should always exist for non-empty meshes, created by depsgraph eval. */
43 bke::pbvh::Tree *pbvh = ob->sculpt ? const_cast<bke::pbvh::Tree *>(bke::object::pbvh_get(*ob)) :
44 nullptr;
45 if (!pbvh) {
46 return {};
47 }
48
49 /* TODO(Miguel Pozo): Don't use global context. */
50 const DRWContextState *drwctx = DRW_context_state_get();
51 RegionView3D *rv3d = drwctx->rv3d;
52 const bool navigating = rv3d && (rv3d->rflag & RV3D_NAVIGATING);
53
54 Paint *paint = nullptr;
55 if (drwctx->evil_C != nullptr) {
57 }
58
59 /* Frustum planes to show only visible pbvh::Tree nodes. */
60 float4 draw_planes[6];
61 PBVHFrustumPlanes draw_frustum = {reinterpret_cast<float(*)[4]>(draw_planes), 6};
62 float4 update_planes[6];
63 PBVHFrustumPlanes update_frustum = {reinterpret_cast<float(*)[4]>(update_planes), 6};
64
65 /* TODO: take into account partial redraw for clipping planes. */
67 /* Transform clipping planes to object space. Transforming a plane with a
68 * 4x4 matrix is done by multiplying with the transpose inverse.
69 * The inverse cancels out here since we transform by inverse(obmat). */
70 float4x4 tmat = math::transpose(ob->object_to_world());
71 for (int i : IndexRange(6)) {
72 draw_planes[i] = tmat * draw_planes[i];
73 update_planes[i] = draw_planes[i];
74 }
75
76 if (paint && (paint->flags & PAINT_SCULPT_DELAY_UPDATES)) {
77 if (navigating) {
78 bke::pbvh::get_frustum_planes(*pbvh, &update_frustum);
79 }
80 else {
81 bke::pbvh::set_frustum_planes(*pbvh, &update_frustum);
82 }
83 }
84
85 /* Fast mode to show low poly multires while navigating. */
86 bool fast_mode = false;
87 if (paint && (paint->flags & PAINT_FAST_NAVIGATE)) {
88 fast_mode = navigating;
89 }
90
91 /* Update draw buffers only for visible nodes while painting.
92 * But do update them otherwise so navigating stays smooth. */
93 bool update_only_visible = rv3d && !(rv3d->rflag & RV3D_PAINTING);
94 if (paint && (paint->flags & PAINT_SCULPT_DELAY_UPDATES)) {
95 update_only_visible = true;
96 }
97
98 bke::pbvh::update_normals_from_eval(*const_cast<Object *>(ob), *pbvh);
99
101
102 IndexMaskMemory memory;
103 const IndexMask visible_nodes = bke::pbvh::search_nodes(
104 *pbvh, memory, [&](const bke::pbvh::Node &node) {
105 return !BKE_pbvh_node_fully_hidden_get(node) &&
106 BKE_pbvh_node_frustum_contain_AABB(&node, &draw_frustum);
107 });
108
109 const IndexMask nodes_to_update = update_only_visible ? visible_nodes :
110 bke::pbvh::all_leaf_nodes(*pbvh, memory);
111
112 Span<gpu::Batch *> batches;
113 if (use_wire) {
114 batches = draw_data.ensure_lines_batches(*ob, {{}, fast_mode}, nodes_to_update);
115 }
116 else {
117 batches = draw_data.ensure_tris_batches(*ob, {attrs, fast_mode}, nodes_to_update);
118 }
119
120 const Span<int> material_indices = draw_data.ensure_material_indices(*ob);
121
122 Vector<SculptBatch> result_batches(visible_nodes.size());
123 visible_nodes.foreach_index([&](const int i, const int pos) {
124 result_batches[pos] = {};
125 result_batches[pos].batch = batches[i];
126 result_batches[pos].material_slot = material_indices.is_empty() ? 0 : material_indices[i];
127 result_batches[pos].debug_index = pos;
128 });
129
130 return result_batches;
131}
132
134{
136
139 if (features & SCULPT_BATCH_MASK) {
141 }
142 if (features & SCULPT_BATCH_FACE_SET) {
144 }
145
146 const Mesh *mesh = BKE_object_get_original_mesh(ob);
147 const bke::AttributeAccessor attributes = mesh->attributes();
148
149 if (features & SCULPT_BATCH_VERTEX_COLOR) {
150 if (const char *name = mesh->active_color_attribute) {
151 if (const std::optional<bke::AttributeMetaData> meta_data = attributes.lookup_meta_data(
152 name))
153 {
154 attrs.append(pbvh::GenericRequest{name, meta_data->data_type, meta_data->domain});
155 }
156 }
157 }
158
159 if (features & SCULPT_BATCH_UV) {
160 if (const char *name = CustomData_get_active_layer_name(&mesh->corner_data, CD_PROP_FLOAT2)) {
162 }
163 }
164
165 return sculpt_batches_get_ex(ob, features & SCULPT_BATCH_WIREFRAME, attrs);
166}
167
170{
171 BLI_assert(ob->type == OB_MESH);
172 const Mesh *mesh = static_cast<const Mesh *>(ob->data);
173
174 DRW_Attributes draw_attrs;
175 DRW_MeshCDMask cd_needed;
176 DRW_mesh_get_attributes(*ob, *mesh, materials.data(), materials.size(), &draw_attrs, &cd_needed);
177
179
182
183 for (int i = 0; i < draw_attrs.num_requests; i++) {
184 const DRW_AttributeRequest &req = draw_attrs.requests[i];
186 }
187
188 /* UV maps are not in attribute requests. */
189 for (uint i = 0; i < 32; i++) {
190 if (cd_needed.uv & (1 << i)) {
191 int layer_i = CustomData_get_layer_index_n(&mesh->corner_data, CD_PROP_FLOAT2, i);
192 CustomDataLayer *layer = layer_i != -1 ? mesh->corner_data.layers + layer_i : nullptr;
193 if (layer) {
195 }
196 }
197 }
198
199 return sculpt_batches_get_ex(ob, false, attrs);
200}
201
202} // namespace blender::draw
int CustomData_get_layer_index_n(const CustomData *data, eCustomDataType type, int n)
const char * CustomData_get_active_layer_name(const CustomData *data, eCustomDataType type)
Mesh * BKE_object_get_original_mesh(const Object *object)
Paint * BKE_paint_get_active_from_context(const bContext *C)
Definition paint.cc:477
bool BKE_pbvh_node_fully_hidden_get(const blender::bke::pbvh::Node &node)
Definition pbvh.cc:1542
bool BKE_pbvh_node_frustum_contain_AABB(const blender::bke::pbvh::Node *node, const PBVHFrustumPlanes *frustum)
Definition pbvh.cc:2354
#define BLI_assert(a)
Definition BLI_assert.h:50
unsigned int uint
@ CD_PROP_FLOAT2
@ OB_MESH
@ PAINT_SCULPT_DELAY_UPDATES
@ PAINT_FAST_NAVIGATE
@ RV3D_PAINTING
@ RV3D_NAVIGATING
constexpr bool is_empty() const
Definition BLI_span.hh:261
void append(const T &value)
std::unique_ptr< DrawCache > draw_data
virtual Span< int > ensure_material_indices(const Object &object)=0
virtual Span< gpu::Batch * > ensure_lines_batches(const Object &object, const ViewportRequest &request, const IndexMask &nodes_to_update)=0
virtual Span< gpu::Batch * > ensure_tris_batches(const Object &object, const ViewportRequest &request, const IndexMask &nodes_to_update)=0
void foreach_index(Fn &&fn) const
Utilities for rendering attributes.
const DRWContextState * DRW_context_state_get()
const DRWView * DRW_view_default_get()
void DRW_view_frustum_planes_get(const DRWView *view, float planes[6][4])
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:2846
IndexMask search_nodes(const Tree &pbvh, IndexMaskMemory &memory, FunctionRef< bool(const Node &)> filter_fn)
Definition pbvh.cc:2647
void set_frustum_planes(Tree &pbvh, PBVHFrustumPlanes *planes)
Definition pbvh.cc:2409
IndexMask all_leaf_nodes(const Tree &pbvh, IndexMaskMemory &memory)
Definition pbvh.cc:2612
void update_normals_from_eval(Object &object_eval, Tree &pbvh)
Definition pbvh.cc:1065
void get_frustum_planes(const Tree &pbvh, PBVHFrustumPlanes *planes)
Definition pbvh.cc:2417
DrawCache & ensure_draw_data(std::unique_ptr< bke::pbvh::DrawCache > &ptr)
Definition draw_pbvh.cc:247
Vector< SculptBatch > sculpt_batches_get(const Object *ob, SculptBatchFeature features)
static Vector< SculptBatch > sculpt_batches_get_ex(const Object *ob, const bool use_wire, const Span< pbvh::AttributeRequest > attrs)
@ SCULPT_BATCH_VERTEX_COLOR
Vector< SculptBatch > sculpt_batches_per_material_get(const Object *ob, Span< const GPUMaterial * > materials)
void DRW_mesh_get_attributes(const Object &object, const Mesh &mesh, const GPUMaterial *const *gpumat_array, int gpumat_array_len, DRW_Attributes *r_attrs, DRW_MeshCDMask *r_cd_needed)
MatBase< T, NumCol, NumRow > transpose(const MatBase< T, NumRow, NumCol > &mat)
const bContext * evil_C
RegionView3D * rv3d
struct SculptSession * sculpt
DRW_AttributeRequest requests[GPU_MAX_ATTR]