Blender  V2.93
draw_cache_impl_metaball.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2017 by Blender Foundation.
17  * All rights reserved.
18  */
19 
26 #include "MEM_guardedalloc.h"
27 
28 #include "BLI_math_base.h"
29 #include "BLI_utildefines.h"
30 
31 #include "DNA_meta_types.h"
32 #include "DNA_object_types.h"
33 
34 #include "BKE_curve.h"
35 #include "BKE_mball.h"
36 
37 #include "GPU_batch.h"
38 
39 #include "DRW_render.h"
40 #include "draw_cache_impl.h" /* own include */
41 
42 static void metaball_batch_cache_clear(MetaBall *mb);
43 
44 /* ---------------------------------------------------------------------- */
45 /* MetaBall GPUBatch Cache */
46 
47 typedef struct MetaBallBatchCache {
50 
51  int mat_len;
52 
53  /* Shared */
55 
56  /* Wireframe */
57  struct {
58  GPUBatch *batch;
60 
61  /* Edge detection */
64 
65  /* settings to determine if cache is invalid */
66  bool is_dirty;
67 
68  /* Valid only if edge_detection is up to date. */
71 
72 /* GPUBatch cache management. */
73 
75 {
76  MetaBallBatchCache *cache = mb->batch_cache;
77 
78  if (cache == NULL) {
79  return false;
80  }
81 
82  return cache->is_dirty == false;
83 }
84 
86 {
87  MetaBallBatchCache *cache = mb->batch_cache;
88 
89  if (!cache) {
90  cache = mb->batch_cache = MEM_mallocN(sizeof(*cache), __func__);
91  }
92  cache->batch = NULL;
93  cache->mat_len = 0;
94  cache->shaded_triangles = NULL;
95  cache->is_dirty = false;
96  cache->pos_nor_in_order = NULL;
97  cache->face_wire.batch = NULL;
98  cache->edge_detection = NULL;
99  cache->edges_adj_lines = NULL;
100  cache->is_manifold = false;
101 }
102 
104 {
105  if (!metaball_batch_cache_valid(mb)) {
108  }
109 }
110 
112 {
113  return mb->batch_cache;
114 }
115 
117 {
118  MetaBallBatchCache *cache = mb->batch_cache;
119  if (cache == NULL) {
120  return;
121  }
122  switch (mode) {
124  cache->is_dirty = true;
125  break;
126  default:
127  BLI_assert(0);
128  }
129 }
130 
132 {
133  MetaBallBatchCache *cache = mb->batch_cache;
134  if (!cache) {
135  return;
136  }
137 
143  /* Note: shaded_triangles[0] is already freed by cache->batch */
145  cache->mat_len = 0;
146  cache->is_manifold = false;
147 }
148 
150 {
153 }
154 
156  MetaBallBatchCache *cache,
157  const struct Scene *scene)
158 {
159  if (cache->pos_nor_in_order == NULL) {
160  ListBase *lb = &ob->runtime.curve_cache->disp;
163  }
164  return cache->pos_nor_in_order;
165 }
166 
168 {
169  if (cache->edges_adj_lines == NULL) {
170  ListBase *lb = &ob->runtime.curve_cache->disp;
173  lb, cache->edges_adj_lines, &cache->is_manifold);
174  }
175  return cache->edges_adj_lines;
176 }
177 
178 /* -------------------------------------------------------------------- */
183 {
184  if (!BKE_mball_is_basis(ob)) {
185  return NULL;
186  }
187 
188  MetaBall *mb = ob->data;
190  const DRWContextState *draw_ctx = DRW_context_state_get();
191  const struct Scene *scene = draw_ctx->scene;
192 
193  if (cache->batch == NULL) {
194  ListBase *lb = &ob->runtime.curve_cache->disp;
199  ibo,
201  }
202 
203  return cache->batch;
204 }
205 
207  MetaBall *mb,
208  struct GPUMaterial **UNUSED(gpumat_array),
209  uint gpumat_array_len)
210 {
211  if (!BKE_mball_is_basis(ob)) {
212  return NULL;
213  }
214 
215  BLI_assert(gpumat_array_len == DRW_metaball_material_count_get(mb));
216 
218  if (cache->shaded_triangles == NULL) {
219  cache->mat_len = gpumat_array_len;
220  cache->shaded_triangles = MEM_callocN(sizeof(*cache->shaded_triangles) * cache->mat_len,
221  __func__);
223  for (int i = 1; i < cache->mat_len; i++) {
224  cache->shaded_triangles[i] = NULL;
225  }
226  }
227  return cache->shaded_triangles;
228 }
229 
231 {
232  if (!BKE_mball_is_basis(ob)) {
233  return NULL;
234  }
235 
236  MetaBall *mb = ob->data;
238  const DRWContextState *draw_ctx = DRW_context_state_get();
239  const struct Scene *scene = draw_ctx->scene;
240 
241  if (cache->face_wire.batch == NULL) {
242  ListBase *lb = &ob->runtime.curve_cache->disp;
243 
244  GPUVertBuf *vbo_wiredata = GPU_vertbuf_calloc();
245  DRW_displist_vertbuf_create_wiredata(lb, vbo_wiredata);
246 
249 
253  ibo,
255 
256  GPU_batch_vertbuf_add_ex(cache->face_wire.batch, vbo_wiredata, true);
257  }
258 
259  return cache->face_wire.batch;
260 }
261 
263  bool *r_is_manifold)
264 {
265  if (!BKE_mball_is_basis(ob)) {
266  return NULL;
267  }
268 
269  MetaBall *mb = ob->data;
271  const DRWContextState *draw_ctx = DRW_context_state_get();
272  const struct Scene *scene = draw_ctx->scene;
273 
274  if (cache->edge_detection == NULL) {
279  }
280 
281  if (r_is_manifold) {
282  *r_is_manifold = cache->is_manifold;
283  }
284 
285  return cache->edge_detection;
286 }
287 
289 {
290  if (!BKE_mball_is_basis(ob)) {
291  return NULL;
292  }
293 
294  MetaBall *mb = ob->data;
296  const DRWContextState *draw_ctx = DRW_context_state_get();
297  const struct Scene *scene = draw_ctx->scene;
298 
299  return mball_batch_cache_get_pos_and_normals(ob, cache, scene);
300 }
301 
303 {
304  return max_ii(1, mb->totcol);
305 }
@ BKE_MBALL_BATCH_DIRTY_ALL
Definition: BKE_mball.h:82
bool BKE_mball_is_basis(struct Object *ob)
Test, if ob is a basis meta-ball.
Definition: mball.c:398
#define BLI_assert(a)
Definition: BLI_assert.h:58
MINLINE int max_ii(int a, int b)
unsigned int uint
Definition: BLI_sys_types.h:83
#define UNUSED(x)
Object is a sort of wrapper for general info.
GPUBatch
Definition: GPU_batch.h:93
#define GPU_batch_create(prim, verts, elem)
Definition: GPU_batch.h:107
int GPU_batch_vertbuf_add_ex(GPUBatch *, GPUVertBuf *, bool own_vbo)
Definition: gpu_batch.cc:192
#define GPU_BATCH_DISCARD_SAFE(batch)
Definition: GPU_batch.h:199
GPUBatch * GPU_batch_create_ex(GPUPrimType prim, GPUVertBuf *vert, GPUIndexBuf *elem, eGPUBatchFlag owns_flag)
Definition: gpu_batch.cc:60
@ GPU_BATCH_OWNS_INDEX
Definition: GPU_batch.h:54
struct GPUIndexBuf GPUIndexBuf
#define GPU_INDEXBUF_DISCARD_SAFE(elem)
GPUIndexBuf * GPU_indexbuf_calloc(void)
@ GPU_PRIM_LINES
Definition: GPU_primitive.h:36
@ GPU_PRIM_LINES_ADJ
Definition: GPU_primitive.h:43
@ GPU_PRIM_TRIS
Definition: GPU_primitive.h:37
struct GPUVertBuf GPUVertBuf
GPUVertBuf * GPU_vertbuf_calloc(void)
#define GPU_VERTBUF_DISCARD_SAFE(verts)
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
Scene scene
void DRW_displist_indexbuf_create_edges_adjacency_lines(struct ListBase *lb, struct GPUIndexBuf *ibo, bool *r_is_manifold)
void DRW_displist_vertbuf_create_wiredata(struct ListBase *lb, struct GPUVertBuf *vbo)
void DRW_displist_indexbuf_create_triangles_in_order(struct ListBase *lb, struct GPUIndexBuf *ibo)
void DRW_displist_indexbuf_create_lines_in_order(struct ListBase *lb, struct GPUIndexBuf *ibo)
void DRW_displist_vertbuf_create_pos_and_nor(struct ListBase *lb, struct GPUVertBuf *vbo, const struct Scene *scene)
static GPUIndexBuf * mball_batch_cache_get_edges_adj_lines(Object *ob, MetaBallBatchCache *cache)
void DRW_mball_batch_cache_free(MetaBall *mb)
void DRW_mball_batch_cache_validate(MetaBall *mb)
GPUBatch * DRW_metaball_batch_cache_get_triangles_with_normals(Object *ob)
static GPUVertBuf * mball_batch_cache_get_pos_and_normals(Object *ob, MetaBallBatchCache *cache, const struct Scene *scene)
struct MetaBallBatchCache MetaBallBatchCache
GPUBatch * DRW_metaball_batch_cache_get_wireframes_face(Object *ob)
static void metaball_batch_cache_clear(MetaBall *mb)
GPUBatch ** DRW_metaball_batch_cache_get_surface_shaded(Object *ob, MetaBall *mb, struct GPUMaterial **UNUSED(gpumat_array), uint gpumat_array_len)
static bool metaball_batch_cache_valid(MetaBall *mb)
struct GPUVertBuf * DRW_mball_batch_cache_pos_vertbuf_get(Object *ob)
static void metaball_batch_cache_init(MetaBall *mb)
void DRW_mball_batch_cache_dirty_tag(MetaBall *mb, int mode)
static MetaBallBatchCache * metaball_batch_cache_get(MetaBall *mb)
int DRW_metaball_material_count_get(MetaBall *mb)
struct GPUBatch * DRW_metaball_batch_cache_get_edge_detection(struct Object *ob, bool *r_is_manifold)
const DRWContextState * DRW_context_state_get(void)
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
ListBase disp
Definition: BKE_curve.h:49
struct Scene * scene
Definition: DRW_render.h:745
struct MetaBallBatchCache::@278 face_wire
void * batch_cache
short totcol
struct CurveCache * curve_cache
Object_Runtime runtime
void * data