Blender V4.5
gpu_batch_utils.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
8
9#include "MEM_guardedalloc.h"
10
11#include "DNA_vec_types.h"
12
13#include "BLI_math_vector.h"
15#include "BLI_polyfill_2d.h"
16#include "BLI_sort_utils.h"
17#include "BLI_utildefines.h"
18
19#include "GPU_batch.hh"
20#include "GPU_batch_utils.hh" /* own include */
21
22/* -------------------------------------------------------------------- */
25
26blender::gpu::Batch *GPU_batch_tris_from_poly_2d_encoded(const uchar *polys_flat,
27 uint polys_flat_len,
28 const rctf *rect)
29{
30 const uchar(*polys)[2] = reinterpret_cast<const uchar(*)[2]>(polys_flat);
31 const uint polys_len = polys_flat_len / 2;
32 BLI_assert(polys_flat_len == polys_len * 2);
33
34 /* Over alloc in both cases */
35 float(*verts)[2] = static_cast<float(*)[2]>(MEM_mallocN(sizeof(*verts) * polys_len, __func__));
36 float(*verts_step)[2] = verts;
37 uint(*tris)[3] = static_cast<uint(*)[3]>(MEM_mallocN(sizeof(*tris) * polys_len, __func__));
38 uint(*tris_step)[3] = tris;
39
40 const float range_uchar[2] = {
41 (rect ? (rect->xmax - rect->xmin) : 2.0f) / 255.0f,
42 (rect ? (rect->ymax - rect->ymin) : 2.0f) / 255.0f,
43 };
44 const float min_uchar[2] = {
45 (rect ? rect->xmin : -1.0f),
46 (rect ? rect->ymin : -1.0f),
47 };
48
49 uint i_poly = 0;
50 uint i_vert = 0;
51 while (i_poly != polys_len) {
52 for (uint j = 0; j < 2; j++) {
53 verts[i_vert][j] = min_uchar[j] + (float(polys[i_poly][j]) * range_uchar[j]);
54 }
55 i_vert++;
56 i_poly++;
57 if (polys[i_poly - 1][0] == polys[i_poly][0] && polys[i_poly - 1][1] == polys[i_poly][1]) {
58 const uint verts_step_len = (&verts[i_vert]) - verts_step;
59 BLI_assert(verts_step_len >= 3);
60 const uint tris_len = (verts_step_len - 2);
61 BLI_polyfill_calc(verts_step, verts_step_len, -1, tris_step);
62 /* offset indices */
63 if (verts_step != verts) {
64 uint *t = tris_step[0];
65 const uint offset = (verts_step - verts);
66 uint tot = tris_len * 3;
67 while (tot--) {
68 *t += offset;
69 t++;
70 }
71 BLI_assert(t == tris_step[tris_len]);
72 }
73 verts_step += verts_step_len;
74 tris_step += tris_len;
75 i_poly++;
76 /* ignore the duplicate point */
77 }
78 }
79
80 /* We have vertices and tris, make a batch from this. */
81 static GPUVertFormat format = {0};
82 static struct {
83 uint pos;
84 } attr_id;
85 if (format.attr_len == 0) {
87 }
88
89 const uint verts_len = (verts_step - verts);
90 const uint tris_len = (tris_step - tris);
92 GPU_vertbuf_data_alloc(*vbo, verts_len);
93
94 GPUVertBufRaw pos_step;
95 GPU_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
96
97 for (uint i = 0; i < verts_len; i++) {
98 copy_v2_v2(static_cast<float *>(GPU_vertbuf_raw_step(&pos_step)), verts[i]);
99 }
100
102 GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tris_len, verts_len);
103 for (uint i = 0; i < tris_len; i++) {
105 }
107
108 MEM_freeN(tris);
110
111 return GPU_batch_create_ex(
113}
114
115blender::gpu::Batch *GPU_batch_wire_from_poly_2d_encoded(const uchar *polys_flat,
116 uint polys_flat_len,
117 const rctf *rect)
118{
119 const uchar(*polys)[2] = reinterpret_cast<const uchar(*)[2]>(polys_flat);
120 const uint polys_len = polys_flat_len / 2;
121 BLI_assert(polys_flat_len == polys_len * 2);
122
123 /* Over alloc */
124 /* Lines are pairs of (x, y) byte locations packed into an int32_t. */
125 int32_t *lines = MEM_malloc_arrayN<int32_t>(polys_len, __func__);
126 int32_t *lines_step = lines;
127
128 const float range_uchar[2] = {
129 (rect ? (rect->xmax - rect->xmin) : 2.0f) / 255.0f,
130 (rect ? (rect->ymax - rect->ymin) : 2.0f) / 255.0f,
131 };
132 const float min_uchar[2] = {
133 (rect ? rect->xmin : -1.0f),
134 (rect ? rect->ymin : -1.0f),
135 };
136
137 uint i_poly_prev = 0;
138 uint i_poly = 0;
139 while (i_poly != polys_len) {
140 i_poly++;
141 if (polys[i_poly - 1][0] == polys[i_poly][0] && polys[i_poly - 1][1] == polys[i_poly][1]) {
142 const uchar(*polys_step)[2] = polys + i_poly_prev;
143 const uint polys_step_len = i_poly - i_poly_prev;
144 BLI_assert(polys_step_len >= 2);
145 for (uint i_prev = polys_step_len - 1, i = 0; i < polys_step_len; i_prev = i++) {
146 union {
147 uint16_t as_u16[2];
148 uint32_t as_u32;
149 } data;
150 data.as_u16[0] = *((const uint16_t *)polys_step[i_prev]);
151 data.as_u16[1] = *((const uint16_t *)polys_step[i]);
152 if (data.as_u16[0] > data.as_u16[1]) {
153 std::swap(data.as_u16[0], data.as_u16[1]);
154 }
155 *lines_step = data.as_u32;
156 lines_step++;
157 }
158 i_poly++;
159 i_poly_prev = i_poly;
160 /* ignore the duplicate point */
161 }
162 }
163
164 uint lines_len = lines_step - lines;
165
166 /* Hide Lines (we could make optional) */
167 {
168 qsort(lines, lines_len, sizeof(int32_t), BLI_sortutil_cmp_int);
169 lines_step = lines;
170 for (uint i_prev = 0, i = 1; i < lines_len; i_prev = i++) {
171 if (lines[i] != lines[i_prev]) {
172 *lines_step++ = lines[i_prev];
173 }
174 else {
175 i++;
176 }
177 }
178 *lines_step++ = lines[lines_len - 1];
179 lines_len = lines_step - lines;
180 }
181
182 /* We have vertices and tris, make a batch from this. */
183 static GPUVertFormat format = {0};
184 static struct {
185 uint pos;
186 } attr_id;
187 if (format.attr_len == 0) {
189 }
190
192 const uint vbo_len_capacity = lines_len * 2;
193 GPU_vertbuf_data_alloc(*vbo, vbo_len_capacity);
194
195 GPUVertBufRaw pos_step;
196 GPU_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
197
198 for (uint i = 0; i < lines_len; i++) {
199 union {
200 uint8_t as_u8_pair[2][2];
201 uint32_t as_u32;
202 } data;
203 data.as_u32 = lines[i];
204 for (uint k = 0; k < 2; k++) {
205 float *pos_v2 = static_cast<float *>(GPU_vertbuf_raw_step(&pos_step));
206 for (uint j = 0; j < 2; j++) {
207 pos_v2[j] = min_uchar[j] + (float(data.as_u8_pair[k][j]) * range_uchar[j]);
208 }
209 }
210 }
211 BLI_assert(vbo_len_capacity == GPU_vertbuf_raw_used(&pos_step));
212 MEM_freeN(lines);
214}
215
217
218/* -------------------------------------------------------------------- */
221
222blender::gpu::Batch *GPU_batch_unit_cube()
223{
224 using namespace blender;
225
226 static const std::array<float3, 8> bone_box_verts = {
227 float3{1.0f, -1.0f, 1.0f},
228 float3{1.0f, -1.0f, -1.0f},
229 float3{-1.0f, -1.0f, -1.0f},
230 float3{-1.0f, -1.0f, 1.0f},
231 float3{1.0f, 1.0f, 1.0f},
232 float3{1.0f, 1.0f, -1.0f},
233 float3{-1.0f, 1.0f, -1.0f},
234 float3{-1.0f, 1.0f, 1.0f},
235 };
236
237 static const std::array<int3, 12> bone_box_solid_tris = {
238 int3{0, 2, 1}, /* bottom */
239 int3{0, 3, 2},
240
241 int3{0, 1, 5}, /* sides */
242 int3{0, 5, 4},
243
244 int3{1, 2, 6},
245 int3{1, 6, 5},
246
247 int3{2, 3, 7},
248 int3{2, 7, 6},
249
250 int3{3, 0, 4},
251 int3{3, 4, 7},
252
253 int3{4, 5, 6}, /* top */
254 int3{4, 6, 7},
255 };
256
257 GPUVertFormat format = {0};
260
261 const int tri_len = bone_box_solid_tris.size();
262 const int vert_len = bone_box_verts.size();
263
264 GPU_vertbuf_data_alloc(*vbo, vert_len);
265
267 GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tri_len, vert_len);
268
269 int v = 0;
270 for (int i = 0; i < vert_len; i++) {
271 GPU_vertbuf_vert_set(vbo, v++, &bone_box_verts[i]);
272 }
273
274 for (int i = 0; i < tri_len; i++) {
275 const int3 tri_indices = bone_box_solid_tris[i];
276 GPU_indexbuf_add_tri_verts(&elb, tri_indices[0], tri_indices[1], tri_indices[2]);
277 }
278
279 return GPU_batch_create_ex(
281}
282
#define BLI_assert(a)
Definition BLI_assert.h:46
MINLINE void copy_v2_v2(float r[2], const float a[2])
void BLI_polyfill_calc(const float(*coords)[2], unsigned int coords_num, int coords_sign, unsigned int(*r_tris)[3])
int BLI_sortutil_cmp_int(const void *a_, const void *b_)
Definition sort_utils.cc:53
unsigned char uchar
unsigned int uint
#define UNPACK3(a)
blender::gpu::Batch * GPU_batch_create_ex(GPUPrimType primitive_type, blender::gpu::VertBuf *vertex_buf, blender::gpu::IndexBuf *index_buf, eGPUBatchFlag owns_flag)
Definition gpu_batch.cc:51
@ GPU_BATCH_OWNS_INDEX
Definition GPU_batch.hh:50
@ GPU_BATCH_OWNS_VBO
Definition GPU_batch.hh:41
void GPU_indexbuf_init(GPUIndexBufBuilder *, GPUPrimType, uint prim_len, uint vertex_len)
blender::gpu::IndexBuf * GPU_indexbuf_build(GPUIndexBufBuilder *)
void GPU_indexbuf_add_tri_verts(GPUIndexBufBuilder *, uint v1, uint v2, uint v3)
@ GPU_PRIM_LINES
@ GPU_PRIM_TRIS
void GPU_vertbuf_attr_get_raw_data(blender::gpu::VertBuf *, uint a_idx, GPUVertBufRaw *access)
GPU_INLINE void * GPU_vertbuf_raw_step(GPUVertBufRaw *a)
#define GPU_vertbuf_create_with_format(format)
void GPU_vertbuf_vert_set(blender::gpu::VertBuf *verts, uint v_idx, const void *data)
GPU_INLINE uint GPU_vertbuf_raw_used(const GPUVertBufRaw *a)
void GPU_vertbuf_data_alloc(blender::gpu::VertBuf &verts, uint v_len)
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, blender::StringRef name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
Read Guarded memory(de)allocation.
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v
static float verts[][3]
uint pos
struct @242053044010324116347033273112253060004051364061::@373043131300025057314200265134167265161140142363 attr_id
blender::gpu::Batch * GPU_batch_tris_from_poly_2d_encoded(const uchar *polys_flat, uint polys_flat_len, const rctf *rect)
blender::gpu::Batch * GPU_batch_unit_cube()
blender::gpu::Batch * GPU_batch_wire_from_poly_2d_encoded(const uchar *polys_flat, uint polys_flat_len, const rctf *rect)
format
void * MEM_mallocN(size_t len, const char *str)
Definition mallocn.cc:128
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
float xmax
float xmin
float ymax
float ymin
i
Definition text_draw.cc:230