Blender V5.0
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 &format, "pos", blender::gpu::VertAttrType::SFLOAT_32_32);
88 }
89
90 const uint verts_len = (verts_step - verts);
91 const uint tris_len = (tris_step - tris);
93 GPU_vertbuf_data_alloc(*vbo, verts_len);
94
95 GPUVertBufRaw pos_step;
96 GPU_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
97
98 for (uint i = 0; i < verts_len; i++) {
99 copy_v2_v2(static_cast<float *>(GPU_vertbuf_raw_step(&pos_step)), verts[i]);
100 }
101
103 GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tris_len, verts_len);
104 for (uint i = 0; i < tris_len; i++) {
106 }
108
109 MEM_freeN(tris);
111
112 return GPU_batch_create_ex(
114}
115
116blender::gpu::Batch *GPU_batch_wire_from_poly_2d_encoded(const uchar *polys_flat,
117 uint polys_flat_len,
118 const rctf *rect)
119{
120 const uchar(*polys)[2] = reinterpret_cast<const uchar(*)[2]>(polys_flat);
121 const uint polys_len = polys_flat_len / 2;
122 BLI_assert(polys_flat_len == polys_len * 2);
123
124 /* Over alloc */
125 /* Lines are pairs of (x, y) byte locations packed into an int32_t. */
126 int32_t *lines = MEM_malloc_arrayN<int32_t>(polys_len, __func__);
127 int32_t *lines_step = lines;
128
129 const float range_uchar[2] = {
130 (rect ? (rect->xmax - rect->xmin) : 2.0f) / 255.0f,
131 (rect ? (rect->ymax - rect->ymin) : 2.0f) / 255.0f,
132 };
133 const float min_uchar[2] = {
134 (rect ? rect->xmin : -1.0f),
135 (rect ? rect->ymin : -1.0f),
136 };
137
138 uint i_poly_prev = 0;
139 uint i_poly = 0;
140 while (i_poly != polys_len) {
141 i_poly++;
142 if (polys[i_poly - 1][0] == polys[i_poly][0] && polys[i_poly - 1][1] == polys[i_poly][1]) {
143 const uchar(*polys_step)[2] = polys + i_poly_prev;
144 const uint polys_step_len = i_poly - i_poly_prev;
145 BLI_assert(polys_step_len >= 2);
146 for (uint i_prev = polys_step_len - 1, i = 0; i < polys_step_len; i_prev = i++) {
147 union {
148 uint16_t as_u16[2];
149 uint32_t as_u32;
150 } data;
151 data.as_u16[0] = *((const uint16_t *)polys_step[i_prev]);
152 data.as_u16[1] = *((const uint16_t *)polys_step[i]);
153 if (data.as_u16[0] > data.as_u16[1]) {
154 std::swap(data.as_u16[0], data.as_u16[1]);
155 }
156 *lines_step = data.as_u32;
157 lines_step++;
158 }
159 i_poly++;
160 i_poly_prev = i_poly;
161 /* ignore the duplicate point */
162 }
163 }
164
165 uint lines_len = lines_step - lines;
166
167 /* Hide Lines (we could make optional) */
168 {
169 qsort(lines, lines_len, sizeof(int32_t), BLI_sortutil_cmp_int);
170 lines_step = lines;
171 for (uint i_prev = 0, i = 1; i < lines_len; i_prev = i++) {
172 if (lines[i] != lines[i_prev]) {
173 *lines_step++ = lines[i_prev];
174 }
175 else {
176 i++;
177 }
178 }
179 *lines_step++ = lines[lines_len - 1];
180 lines_len = lines_step - lines;
181 }
182
183 /* We have vertices and tris, make a batch from this. */
184 static GPUVertFormat format = {0};
185 static struct {
186 uint pos;
187 } attr_id;
188 if (format.attr_len == 0) {
190 &format, "pos", blender::gpu::VertAttrType::SFLOAT_32_32);
191 }
192
194 const uint vbo_len_capacity = lines_len * 2;
195 GPU_vertbuf_data_alloc(*vbo, vbo_len_capacity);
196
197 GPUVertBufRaw pos_step;
198 GPU_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
199
200 for (uint i = 0; i < lines_len; i++) {
201 union {
202 uint8_t as_u8_pair[2][2];
203 uint32_t as_u32;
204 } data;
205 data.as_u32 = lines[i];
206 for (uint k = 0; k < 2; k++) {
207 float *pos_v2 = static_cast<float *>(GPU_vertbuf_raw_step(&pos_step));
208 for (uint j = 0; j < 2; j++) {
209 pos_v2[j] = min_uchar[j] + (float(data.as_u8_pair[k][j]) * range_uchar[j]);
210 }
211 }
212 }
213 BLI_assert(vbo_len_capacity == GPU_vertbuf_raw_used(&pos_step));
214 MEM_freeN(lines);
216}
217
219
220/* -------------------------------------------------------------------- */
223
224blender::gpu::Batch *GPU_batch_unit_cube()
225{
226 using namespace blender;
227
228 static const std::array<float3, 8> bone_box_verts = {
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 float3{-1.0f, 1.0f, -1.0f},
236 float3{-1.0f, 1.0f, 1.0f},
237 };
238
239 static const std::array<int3, 12> bone_box_solid_tris = {
240 int3{0, 2, 1}, /* bottom */
241 int3{0, 3, 2},
242
243 int3{0, 1, 5}, /* sides */
244 int3{0, 5, 4},
245
246 int3{1, 2, 6},
247 int3{1, 6, 5},
248
249 int3{2, 3, 7},
250 int3{2, 7, 6},
251
252 int3{3, 0, 4},
253 int3{3, 4, 7},
254
255 int3{4, 5, 6}, /* top */
256 int3{4, 6, 7},
257 };
258
259 GPUVertFormat format = {0};
260 GPU_vertformat_attr_add(&format, "pos", gpu::VertAttrType::SFLOAT_32_32_32);
262
263 const int tri_len = bone_box_solid_tris.size();
264 const int vert_len = bone_box_verts.size();
265
266 GPU_vertbuf_data_alloc(*vbo, vert_len);
267
269 GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tri_len, vert_len);
270
271 int v = 0;
272 for (int i = 0; i < vert_len; i++) {
273 GPU_vertbuf_vert_set(vbo, v++, &bone_box_verts[i]);
274 }
275
276 for (int i = 0; i < tri_len; i++) {
277 const int3 tri_indices = bone_box_solid_tris[i];
278 GPU_indexbuf_add_tri_verts(&elb, tri_indices[0], tri_indices[1], tri_indices[2]);
279 }
280
281 return GPU_batch_create_ex(
283}
284
#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, GPUBatchFlag owns_flag)
Definition gpu_batch.cc:51
@ GPU_BATCH_OWNS_INDEX
Definition GPU_batch.hh:46
@ GPU_BATCH_OWNS_VBO
Definition GPU_batch.hh:42
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)
void GPU_vertbuf_vert_set(blender::gpu::VertBuf *verts, uint v_idx, const void *data)
static blender::gpu::VertBuf * GPU_vertbuf_create_with_format(const GPUVertFormat &format)
GPU_INLINE uint GPU_vertbuf_raw_used(const GPUVertBufRaw *a)
void GPU_vertbuf_data_alloc(blender::gpu::VertBuf &verts, uint v_len)
uint GPU_vertformat_attr_add(GPUVertFormat *format, blender::StringRef name, blender::gpu::VertAttrType type)
Read Guarded memory(de)allocation.
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v
nullptr float
static float verts[][3]
uint pos
struct @021025263243242147216143265077100330027142264337::@240232116316110053135047106323056371161236243121 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