Blender V5.0
draw_debug.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2018 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include "BKE_object.hh"
12#include "BLI_math_bits.h"
13#include "BLI_math_matrix.h"
14#include "BLI_math_matrix.hh"
15#include "GPU_batch.hh"
16#include "GPU_debug.hh"
17
19#include "draw_debug.hh"
20#include "draw_shader.hh"
21#include "draw_shader_shared.hh"
22
23namespace blender::draw {
24
25/* -------------------------------------------------------------------- */
28
30{
31 for (int i = 0; i < 2; i++) {
32 vertex_len_.store(0);
33
34 if (cpu_draw_buf_.current() == nullptr) {
35 cpu_draw_buf_.current() = MEM_new<DebugDrawBuf>("DebugDrawBuf-CPU", "DebugDrawBuf-CPU");
36 gpu_draw_buf_.current() = MEM_new<DebugDrawBuf>("DebugDrawBuf-GPU", "DebugDrawBuf-GPU");
37 }
38
39 cpu_draw_buf_.current()->command.vertex_len = 0;
40 cpu_draw_buf_.current()->command.vertex_first = 0;
41 cpu_draw_buf_.current()->command.instance_len = 1;
42 cpu_draw_buf_.current()->command.instance_first_array = 0;
43
44 gpu_draw_buf_.current()->command.vertex_len = 0;
45 gpu_draw_buf_.current()->command.vertex_first = 0;
46 gpu_draw_buf_.current()->command.instance_len = 1;
47 gpu_draw_buf_.current()->command.instance_first_array = 0;
48 gpu_draw_buf_.current()->push_update();
49
50 cpu_draw_buf_.swap();
51 gpu_draw_buf_.swap();
52 }
53
54 gpu_draw_buf_used = false;
55}
56
58{
59#ifdef WITH_DRAW_DEBUG
60 gpu_draw_buf_used = true;
61 return *gpu_draw_buf_.current();
62#else
63 return nullptr;
64#endif
65}
66
67void DebugDraw::clear_gpu_data()
68{
69 for (int i = 0; i < 2; i++) {
70 MEM_SAFE_DELETE(cpu_draw_buf_.current());
71 MEM_SAFE_DELETE(gpu_draw_buf_.current());
72
73 cpu_draw_buf_.swap();
74 gpu_draw_buf_.swap();
75 }
76}
77
79{
81}
82
84
85/* -------------------------------------------------------------------- */
88
89void drw_debug_line(const float3 v1, const float3 v2, const float4 color, const uint lifetime)
90{
92 dd.draw_line(v1, v2, debug_color_pack(color), lifetime);
93}
94
95void drw_debug_polygon(Span<float3> face_verts, const float4 color, const uint lifetime)
96{
97 BLI_assert(!face_verts.is_empty());
100 float3 v0 = face_verts.last();
101 for (auto vert : face_verts) {
102 float3 v1 = vert;
103 dd.draw_line(v0, v1, col, lifetime);
104 v0 = v1;
105 }
106}
107
108void drw_debug_bbox(const BoundBox &bbox, const float4 color, const uint lifetime)
109{
112 dd.draw_line(bbox.vec[0], bbox.vec[1], col, lifetime);
113 dd.draw_line(bbox.vec[1], bbox.vec[2], col, lifetime);
114 dd.draw_line(bbox.vec[2], bbox.vec[3], col, lifetime);
115 dd.draw_line(bbox.vec[3], bbox.vec[0], col, lifetime);
116
117 dd.draw_line(bbox.vec[4], bbox.vec[5], col, lifetime);
118 dd.draw_line(bbox.vec[5], bbox.vec[6], col, lifetime);
119 dd.draw_line(bbox.vec[6], bbox.vec[7], col, lifetime);
120 dd.draw_line(bbox.vec[7], bbox.vec[4], col, lifetime);
121
122 dd.draw_line(bbox.vec[0], bbox.vec[4], col, lifetime);
123 dd.draw_line(bbox.vec[1], bbox.vec[5], col, lifetime);
124 dd.draw_line(bbox.vec[2], bbox.vec[6], col, lifetime);
125 dd.draw_line(bbox.vec[3], bbox.vec[7], col, lifetime);
126}
127
128static Vector<float3> precompute_sphere_points(int circle_resolution)
129{
131 for (auto axis : IndexRange(3)) {
132 for (auto edge : IndexRange(circle_resolution)) {
133 for (auto vert : IndexRange(2)) {
134 const float angle = (2 * M_PI) * (edge + vert) / float(circle_resolution);
135 const float point[3] = {cosf(angle), sinf(angle), 0.0f};
136 result.append(float3(point[(0 + axis) % 3], point[(1 + axis) % 3], point[(2 + axis) % 3]));
137 }
138 }
139 }
140 return result;
141}
142
143void drw_debug_sphere(const float3 center, float radius, const float4 color, const uint lifetime)
144{
146 static Vector<float3> sphere_verts = precompute_sphere_points(16);
147
150 for (auto i : IndexRange(sphere_verts.size() / 2)) {
151 float3 v0 = sphere_verts[i * 2] * radius + center;
152 float3 v1 = sphere_verts[i * 2 + 1] * radius + center;
153 dd.draw_line(v0, v1, col, lifetime);
154 }
155}
156
157void drw_debug_point(const float3 pos, float rad, const float4 col, const uint lifetime)
158{
159 static Vector<float3> point_verts = precompute_sphere_points(4);
160
163 for (auto i : IndexRange(point_verts.size() / 2)) {
164 float3 v0 = point_verts[i * 2] * rad + pos;
165 float3 v1 = point_verts[i * 2 + 1] * rad + pos;
166 dd.draw_line(v0, v1, color, lifetime);
167 }
168}
169
170void drw_debug_matrix(const float4x4 &m4, const uint lifetime)
171{
172 float3 v0 = math::transform_point(m4, float3(0.0f, 0.0f, 0.0f));
173 float3 v1 = math::transform_point(m4, float3(1.0f, 0.0f, 0.0f));
174 float3 v2 = math::transform_point(m4, float3(0.0f, 1.0f, 0.0f));
175 float3 v3 = math::transform_point(m4, float3(0.0f, 0.0f, 1.0f));
176
178 dd.draw_line(v0, v1, debug_color_pack(float4(1.0f, 0.0f, 0.0f, 1.0f)), lifetime);
179 dd.draw_line(v0, v2, debug_color_pack(float4(0.0f, 1.0f, 0.0f, 1.0f)), lifetime);
180 dd.draw_line(v0, v3, debug_color_pack(float4(0.0f, 0.0f, 1.0f, 1.0f)), lifetime);
181}
182
183void drw_debug_matrix_as_bbox(const float4x4 &mat, const float4 color, const uint lifetime)
184{
185 BoundBox bb;
186 std::array<float3, 8> corners = bounds::corners(Bounds<float3>(float3(-1), float3(1)));
187 for (auto i : IndexRange(8)) {
188 mul_project_m4_v3(mat.ptr(), corners[i]);
189 }
190 drw_debug_bbox(bb, color, lifetime);
191}
192
194
195/* -------------------------------------------------------------------- */
199
201{
202 DebugDrawBuf &buf = *cpu_draw_buf_.current();
203 uint index = vertex_len_.fetch_add(2);
204 if (index + 2 < DRW_DEBUG_DRAW_VERT_MAX) {
205 buf.verts[index / 2] = debug_line_make(float_as_uint(v1.x),
206 float_as_uint(v1.y),
207 float_as_uint(v1.z),
208 float_as_uint(v2.x),
209 float_as_uint(v2.y),
210 float_as_uint(v2.z),
211 color,
212 lifetime);
213 buf.command.vertex_len += 2;
214 }
215}
216
218
219/* -------------------------------------------------------------------- */
222
223void DebugDraw::display_lines(View &view)
224{
225 const bool cpu_draw_buf_used = vertex_len_.load() != 0;
226
227 if (!cpu_draw_buf_used && !gpu_draw_buf_used) {
228 return;
229 }
230
232
233 float viewport_size[4];
234 GPU_viewport_size_get_f(viewport_size);
235
239 GPU_shader_uniform_mat4(shader, "persmat", view.persmat().ptr());
240 GPU_shader_uniform_2f(shader, "size_viewport", viewport_size[2], viewport_size[3]);
241
242 if (gpu_draw_buf_used) {
244 /* Reset buffer. */
245 gpu_draw_buf_.next()->command.vertex_len = 0;
246 gpu_draw_buf_.next()->push_update();
247
248 GPU_storagebuf_bind(*gpu_draw_buf_.current(), DRW_DEBUG_DRAW_SLOT);
250 GPU_batch_draw_indirect(batch, *gpu_draw_buf_.current(), 0);
251 GPU_storagebuf_unbind(*gpu_draw_buf_.current());
252 GPU_storagebuf_unbind(*gpu_draw_buf_.next());
254 }
255
256 {
258 /* We might have race condition here (a writer thread might still be outputting vertices).
259 * But that is ok. At worse, we will be missing some vertex data and show 1 corrupted line. */
260 cpu_draw_buf_.current()->command.vertex_len = vertex_len_.load();
261 cpu_draw_buf_.current()->push_update();
262 /* Reset buffer. */
263 cpu_draw_buf_.next()->command.vertex_len = 0;
264 cpu_draw_buf_.next()->push_update();
265
266 GPU_storagebuf_bind(*cpu_draw_buf_.current(), DRW_DEBUG_DRAW_SLOT);
268 GPU_batch_draw_indirect(batch, *cpu_draw_buf_.current(), 0);
269 GPU_storagebuf_unbind(*cpu_draw_buf_.current());
270 GPU_storagebuf_unbind(*cpu_draw_buf_.next());
271
272 /* Read result of lifetime management. */
273 cpu_draw_buf_.next()->read();
274 vertex_len_.store(min_ii(DRW_DEBUG_DRAW_VERT_MAX, cpu_draw_buf_.next()->command.vertex_len));
276 }
277
278 gpu_draw_buf_.swap();
279 cpu_draw_buf_.swap();
280}
281
283{
284 /* Display only on the main thread. Avoid concurrent usage of the resource. */
286
287 GPU_debug_group_begin("DebugDraw");
288
289 display_lines(view);
290
292}
293
295
296} // namespace blender::draw
General operations, lookup, etc. for blender objects.
#define BLI_assert(a)
Definition BLI_assert.h:46
MINLINE int min_ii(int a, int b)
MINLINE unsigned int float_as_uint(float f)
#define M_PI
void mul_project_m4_v3(const float mat[4][4], float vec[3])
unsigned int uint
int BLI_thread_is_main(void)
Definition threads.cc:179
static AppView * view
blender::gpu::Batch * GPU_batch_procedural_lines_get()
Definition gpu_batch.cc:515
void GPU_batch_draw_indirect(blender::gpu::Batch *batch, blender::gpu::StorageBuf *indirect_buf, intptr_t offset)
void GPU_batch_set_shader(blender::gpu::Batch *batch, blender::gpu::Shader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
void GPU_debug_group_end()
Definition gpu_debug.cc:33
void GPU_debug_group_begin(const char *name)
Definition gpu_debug.cc:22
void GPU_shader_uniform_mat4(blender::gpu::Shader *sh, const char *name, const float data[4][4])
void GPU_shader_uniform_2f(blender::gpu::Shader *sh, const char *name, float x, float y)
void GPU_viewport_size_get_f(float coords[4])
Definition gpu_state.cc:273
void GPU_storagebuf_bind(blender::gpu::StorageBuf *ssbo, int slot)
void GPU_storagebuf_unbind(blender::gpu::StorageBuf *ssbo)
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:117
ATTR_WARN_UNUSED_RESULT const BMVert * v2
constexpr const T & last(const int64_t n=0) const
Definition BLI_span.hh:325
constexpr bool is_empty() const
Definition BLI_span.hh:260
int64_t size() const
void display_to_view(View &view)
static DebugDraw & get()
gpu::StorageBuf * gpu_draw_buf_get()
Definition draw_debug.cc:57
void draw_line(float3 v1, float3 v2, uint color, uint lifetime=1)
nullptr float
Simple API to draw debug shapes and log in the viewport.
#define DRW_DEBUG_DRAW_SLOT
#define DRW_DEBUG_DRAW_FEEDBACK_SLOT
blender::gpu::Shader * DRW_shader_debug_draw_display_get()
DRWDebugVertPair debug_line_make(uint in_pos1_x, uint in_pos1_y, uint in_pos1_z, uint in_pos2_x, uint in_pos2_y, uint in_pos2_z, uint in_vert_color, uint in_lifetime)
uint debug_color_pack(float4 v_color)
#define DRW_DEBUG_DRAW_VERT_MAX
@ DRW_STATE_DEPTH_LESS
Definition draw_state.hh:37
@ DRW_STATE_WRITE_DEPTH
Definition draw_state.hh:29
@ DRW_STATE_WRITE_COLOR
Definition draw_state.hh:30
struct @021025263243242147216143265077100330027142264337::@225245033123204053237120173316075113304004012000 batch
uint pos
uint col
std::array< VecBase< T, 3 >, 8 > corners(const Bounds< VecBase< T, 3 > > &bounds)
void drw_debug_bbox(const BoundBox &bbox, const float4 color, const uint lifetime)
void drw_debug_matrix_as_bbox(const float4x4 &mat, const float4 color, const uint lifetime)
void drw_debug_sphere(const float3 center, float radius, const float4 color, const uint lifetime)
void drw_debug_matrix(const float4x4 &m4, const uint lifetime)
void drw_debug_line(const float3 v1, const float3 v2, const float4 color, const uint lifetime)
Definition draw_debug.cc:89
static Vector< float3 > precompute_sphere_points(int circle_resolution)
void drw_debug_polygon(Span< float3 > face_verts, const float4 color, const uint lifetime)
Definition draw_debug.cc:95
void drw_debug_clear()
Definition draw_debug.cc:78
void drw_debug_point(const float3 pos, float rad, const float4 col, const uint lifetime)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
MatBase< float, 4, 4 > float4x4
VecBase< float, 4 > float4
VecBase< float, 3 > float3
#define sinf
#define cosf
float vec[8][3]
DRWDebugVertPair verts[DRW_DEBUG_DRAW_VERT_MAX]
const c_style_mat & ptr() const
static void set(DRWState state=DRW_STATE_DEFAULT)
i
Definition text_draw.cc:230