Cleanup: blank lines over doxy headers
[blender.git] / source / blender / draw / intern / draw_debug.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Copyright 2018, Blender Foundation.
19  * Contributor(s): Blender Institute
20  *
21  * ***** END GPL LICENSE BLOCK *****
22  *
23  */
24
25 /** \file blender/draw/intern/draw_debug.c
26  *  \ingroup draw
27  *
28  * \brief Simple API to draw debug shapes in the viewport.
29  */
30
31 #include "MEM_guardedalloc.h"
32
33 #include "DNA_object_types.h"
34
35 #include "BKE_object.h"
36
37 #include "BLI_link_utils.h"
38
39 #include "GPU_immediate.h"
40
41 #include "draw_debug.h"
42 #include "draw_manager.h"
43
44 /* --------- Register --------- */
45
46 /* Matrix applied to all points before drawing. Could be a stack if needed. */
47 static float g_modelmat[4][4];
48
49 void DRW_debug_modelmat_reset(void)
50 {
51         unit_m4(g_modelmat);
52 }
53
54 void DRW_debug_modelmat(const float modelmat[4][4])
55 {
56         copy_m4_m4(g_modelmat, modelmat);
57 }
58
59 void DRW_debug_line_v3v3(const float v1[3], const float v2[3], const float color[4])
60 {
61         DRWDebugLine *line = MEM_mallocN(sizeof(DRWDebugLine), "DRWDebugLine");
62         mul_v3_m4v3(line->pos[0], g_modelmat, v1);
63         mul_v3_m4v3(line->pos[1], g_modelmat, v2);
64         copy_v4_v4(line->color, color);
65         BLI_LINKS_PREPEND(DST.debug.lines, line);
66 }
67
68 void DRW_debug_polygon_v3(const float (*v)[3], const int vert_len, const float color[4])
69 {
70         BLI_assert(vert_len > 1);
71
72         for (int i = 0; i < vert_len; ++i) {
73                 DRW_debug_line_v3v3(v[i], v[(i + 1) % vert_len], color);
74         }
75 }
76
77 /* NOTE: g_modelmat is still applied on top. */
78 void DRW_debug_m4(const float m[4][4])
79 {
80         float v0[3] = {0.0f, 0.0f, 0.0f};
81         float v1[3] = {1.0f, 0.0f, 0.0f};
82         float v2[3] = {0.0f, 1.0f, 0.0f};
83         float v3[3] = {0.0f, 0.0f, 1.0f};
84
85         mul_m4_v3(m, v0);
86         mul_m4_v3(m, v1);
87         mul_m4_v3(m, v2);
88         mul_m4_v3(m, v3);
89
90         DRW_debug_line_v3v3(v0, v1, (float[4]){1.0f, 0.0f, 0.0f, 1.0f});
91         DRW_debug_line_v3v3(v0, v2, (float[4]){0.0f, 1.0f, 0.0f, 1.0f});
92         DRW_debug_line_v3v3(v0, v3, (float[4]){0.0f, 0.0f, 1.0f, 1.0f});
93 }
94
95 void DRW_debug_bbox(const BoundBox *bbox, const float color[4])
96 {
97         DRW_debug_line_v3v3(bbox->vec[0], bbox->vec[1], color);
98         DRW_debug_line_v3v3(bbox->vec[1], bbox->vec[2], color);
99         DRW_debug_line_v3v3(bbox->vec[2], bbox->vec[3], color);
100         DRW_debug_line_v3v3(bbox->vec[3], bbox->vec[0], color);
101
102         DRW_debug_line_v3v3(bbox->vec[4], bbox->vec[5], color);
103         DRW_debug_line_v3v3(bbox->vec[5], bbox->vec[6], color);
104         DRW_debug_line_v3v3(bbox->vec[6], bbox->vec[7], color);
105         DRW_debug_line_v3v3(bbox->vec[7], bbox->vec[4], color);
106
107         DRW_debug_line_v3v3(bbox->vec[0], bbox->vec[4], color);
108         DRW_debug_line_v3v3(bbox->vec[1], bbox->vec[5], color);
109         DRW_debug_line_v3v3(bbox->vec[2], bbox->vec[6], color);
110         DRW_debug_line_v3v3(bbox->vec[3], bbox->vec[7], color);
111 }
112
113 void DRW_debug_m4_as_bbox(const float m[4][4], const float color[4], const bool invert)
114 {
115         BoundBox bb;
116         const float min[3] = {-1.0f, -1.0f, -1.0f}, max[3] = {1.0f, 1.0f, 1.0f};
117         float project_matrix[4][4];
118         if (invert) {
119                 invert_m4_m4(project_matrix, m);
120         }
121         else {
122                 copy_m4_m4(project_matrix, m);
123         }
124
125         BKE_boundbox_init_from_minmax(&bb, min, max);
126         for (int i = 0; i < 8; ++i) {
127                 mul_project_m4_v3(project_matrix, bb.vec[i]);
128         }
129         DRW_debug_bbox(&bb, color);
130 }
131
132 void DRW_debug_sphere(const float center[3], const float radius, const float color[4])
133 {
134         float size_mat[4][4];
135         DRWDebugSphere *sphere = MEM_mallocN(sizeof(DRWDebugSphere), "DRWDebugSphere");
136         /* Bake all transform into a Matrix4 */
137         scale_m4_fl(size_mat, radius);
138         copy_m4_m4(sphere->mat, g_modelmat);
139         translate_m4(sphere->mat, center[0], center[1], center[2]);
140         mul_m4_m4m4(sphere->mat, sphere->mat, size_mat);
141
142         copy_v4_v4(sphere->color, color);
143         BLI_LINKS_PREPEND(DST.debug.spheres, sphere);
144 }
145
146 /* --------- Render --------- */
147
148 static void drw_debug_draw_lines(void)
149 {
150         int count = BLI_linklist_count((LinkNode *)DST.debug.lines);
151
152         if (count == 0) {
153                 return;
154         }
155
156         GPUVertFormat *vert_format = immVertexFormat();
157         uint pos = GPU_vertformat_attr_add(vert_format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
158         uint col = GPU_vertformat_attr_add(vert_format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
159
160         immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
161
162         immBegin(GPU_PRIM_LINES, count * 2);
163
164         while (DST.debug.lines) {
165                 void *next = DST.debug.lines->next;
166
167                 immAttr4fv(col, DST.debug.lines->color);
168                 immVertex3fv(pos, DST.debug.lines->pos[0]);
169
170                 immAttr4fv(col, DST.debug.lines->color);
171                 immVertex3fv(pos, DST.debug.lines->pos[1]);
172
173                 MEM_freeN(DST.debug.lines);
174                 DST.debug.lines = next;
175         }
176         immEnd();
177
178         immUnbindProgram();
179 }
180
181 static void drw_debug_draw_spheres(void)
182 {
183         int count = BLI_linklist_count((LinkNode *)DST.debug.spheres);
184
185         if (count == 0) {
186                 return;
187         }
188
189         float one = 1.0f;
190         GPUVertFormat vert_format = {0};
191         uint mat = GPU_vertformat_attr_add(&vert_format, "InstanceModelMatrix", GPU_COMP_F32, 16, GPU_FETCH_FLOAT);
192         uint col = GPU_vertformat_attr_add(&vert_format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
193         uint siz = GPU_vertformat_attr_add(&vert_format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
194
195         GPUVertBuf *inst_vbo = GPU_vertbuf_create_with_format(&vert_format);
196
197         GPU_vertbuf_data_alloc(inst_vbo, count);
198
199         int v = 0;
200         while (DST.debug.spheres) {
201                 void *next = DST.debug.spheres->next;
202
203                 GPU_vertbuf_attr_set(inst_vbo, mat, v, DST.debug.spheres->mat[0]);
204                 GPU_vertbuf_attr_set(inst_vbo, col, v, DST.debug.spheres->color);
205                 GPU_vertbuf_attr_set(inst_vbo, siz, v, &one);
206                 v++;
207
208                 MEM_freeN(DST.debug.spheres);
209                 DST.debug.spheres = next;
210         }
211
212         GPUBatch *empty_sphere = DRW_cache_empty_sphere_get();
213
214         GPUBatch *draw_batch = GPU_batch_create(GPU_PRIM_LINES, empty_sphere->verts[0], NULL);
215         GPU_batch_instbuf_set(draw_batch, inst_vbo, true);
216         GPU_batch_program_set_builtin(draw_batch, GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE);
217
218         GPU_batch_draw(draw_batch);
219         GPU_batch_discard(draw_batch);
220 }
221
222 void drw_debug_draw(void)
223 {
224         drw_debug_draw_lines();
225         drw_debug_draw_spheres();
226 }
227
228 void drw_debug_init(void)
229 {
230         DRW_debug_modelmat_reset();
231 }