| 
									
										
										
										
											2017-11-16 15:12:32 -02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  |  * of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) 2017 by Blender Foundation. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \file draw_cache_impl_metaball.c
 | 
					
						
							|  |  |  |  *  \ingroup draw | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \brief MetaBall API for render engines | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BLI_utildefines.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "DNA_meta_types.h"
 | 
					
						
							|  |  |  | #include "DNA_object_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BKE_curve.h"
 | 
					
						
							|  |  |  | #include "BKE_mball.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "GPU_batch.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-23 18:02:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-16 15:12:32 -02:00
										 |  |  | #include "draw_cache_impl.h"  /* own include */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void metaball_batch_cache_clear(MetaBall *mb); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ---------------------------------------------------------------------- */ | 
					
						
							| 
									
										
										
										
											2018-07-18 00:12:21 +02:00
										 |  |  | /* MetaBall GPUBatch Cache */ | 
					
						
							| 
									
										
										
										
											2017-11-16 15:12:32 -02:00
										 |  |  | 
 | 
					
						
							|  |  |  | typedef struct MetaBallBatchCache { | 
					
						
							| 
									
										
										
										
											2018-07-18 00:12:21 +02:00
										 |  |  | 	GPUBatch *batch; | 
					
						
							|  |  |  | 	GPUBatch **shaded_triangles; | 
					
						
							| 
									
										
										
										
											2018-06-11 08:37:56 +02:00
										 |  |  | 	int mat_len; | 
					
						
							| 
									
										
										
										
											2018-11-23 18:02:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Shared */ | 
					
						
							|  |  |  | 	GPUVertBuf *pos_nor_in_order; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Wireframe */ | 
					
						
							|  |  |  | 	struct { | 
					
						
							| 
									
										
										
										
											2018-12-07 05:03:01 +01:00
										 |  |  | 		GPUBatch *batch; | 
					
						
							| 
									
										
										
										
											2018-11-23 18:02:34 +01:00
										 |  |  | 	} face_wire; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-16 15:12:32 -02:00
										 |  |  | 	/* settings to determine if cache is invalid */ | 
					
						
							|  |  |  | 	bool is_dirty; | 
					
						
							|  |  |  | } MetaBallBatchCache; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-18 00:12:21 +02:00
										 |  |  | /* GPUBatch cache management. */ | 
					
						
							| 
									
										
										
										
											2017-11-16 15:12:32 -02:00
										 |  |  | 
 | 
					
						
							|  |  |  | static bool metaball_batch_cache_valid(MetaBall *mb) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	MetaBallBatchCache *cache = mb->batch_cache; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (cache == NULL) { | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return cache->is_dirty == false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void metaball_batch_cache_init(MetaBall *mb) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	MetaBallBatchCache *cache = mb->batch_cache; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!cache) { | 
					
						
							|  |  |  | 		cache = mb->batch_cache = MEM_mallocN(sizeof(*cache), __func__); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	cache->batch = NULL; | 
					
						
							| 
									
										
										
										
											2018-06-11 08:37:56 +02:00
										 |  |  | 	cache->mat_len = 0; | 
					
						
							|  |  |  | 	cache->shaded_triangles = NULL; | 
					
						
							| 
									
										
										
										
											2017-11-16 15:12:32 -02:00
										 |  |  | 	cache->is_dirty = false; | 
					
						
							| 
									
										
										
										
											2018-11-23 18:02:34 +01:00
										 |  |  | 	cache->pos_nor_in_order = NULL; | 
					
						
							| 
									
										
										
										
											2018-12-07 05:03:01 +01:00
										 |  |  | 	cache->face_wire.batch = NULL; | 
					
						
							| 
									
										
										
										
											2017-11-16 15:12:32 -02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static MetaBallBatchCache *metaball_batch_cache_get(MetaBall *mb) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (!metaball_batch_cache_valid(mb)) { | 
					
						
							|  |  |  | 		metaball_batch_cache_clear(mb); | 
					
						
							|  |  |  | 		metaball_batch_cache_init(mb); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return mb->batch_cache; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-23 10:14:29 -03:00
										 |  |  | void DRW_mball_batch_cache_dirty_tag(MetaBall *mb, int mode) | 
					
						
							| 
									
										
										
										
											2017-11-16 15:12:32 -02:00
										 |  |  | { | 
					
						
							|  |  |  | 	MetaBallBatchCache *cache = mb->batch_cache; | 
					
						
							|  |  |  | 	if (cache == NULL) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	switch (mode) { | 
					
						
							|  |  |  | 		case BKE_MBALL_BATCH_DIRTY_ALL: | 
					
						
							|  |  |  | 			cache->is_dirty = true; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			BLI_assert(0); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void metaball_batch_cache_clear(MetaBall *mb) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	MetaBallBatchCache *cache = mb->batch_cache; | 
					
						
							|  |  |  | 	if (!cache) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-07 05:03:01 +01:00
										 |  |  | 	GPU_BATCH_DISCARD_SAFE(cache->face_wire.batch); | 
					
						
							| 
									
										
										
										
											2018-07-18 00:12:21 +02:00
										 |  |  | 	GPU_BATCH_DISCARD_SAFE(cache->batch); | 
					
						
							| 
									
										
										
										
											2018-11-23 18:02:34 +01:00
										 |  |  | 	GPU_VERTBUF_DISCARD_SAFE(cache->pos_nor_in_order); | 
					
						
							| 
									
										
										
										
											2018-06-11 08:37:56 +02:00
										 |  |  | 	/* Note: shaded_triangles[0] is already freed by cache->batch */ | 
					
						
							|  |  |  | 	MEM_SAFE_FREE(cache->shaded_triangles); | 
					
						
							|  |  |  | 	cache->mat_len = 0; | 
					
						
							| 
									
										
										
										
											2017-11-16 15:12:32 -02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DRW_mball_batch_cache_free(MetaBall *mb) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	metaball_batch_cache_clear(mb); | 
					
						
							|  |  |  | 	MEM_SAFE_FREE(mb->batch_cache); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-23 18:02:34 +01:00
										 |  |  | static GPUVertBuf *mball_batch_cache_get_pos_and_normals(Object *ob, MetaBallBatchCache *cache) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (cache->pos_nor_in_order == NULL) { | 
					
						
							|  |  |  | 		ListBase *lb = &ob->runtime.curve_cache->disp; | 
					
						
							| 
									
										
										
										
											2018-12-14 00:42:16 +01:00
										 |  |  | 		cache->pos_nor_in_order = MEM_callocN(sizeof(GPUVertBuf), __func__); | 
					
						
							|  |  |  | 		DRW_displist_vertbuf_create_pos_and_nor(lb, cache->pos_nor_in_order); | 
					
						
							| 
									
										
										
										
											2018-11-23 18:02:34 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return cache->pos_nor_in_order; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-16 15:12:32 -02:00
										 |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Public Object/MetaBall API
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-18 00:12:21 +02:00
										 |  |  | GPUBatch *DRW_metaball_batch_cache_get_triangles_with_normals(Object *ob) | 
					
						
							| 
									
										
										
										
											2017-11-16 15:12:32 -02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-06-11 08:37:56 +02:00
										 |  |  | 	if (!BKE_mball_is_basis(ob)) { | 
					
						
							| 
									
										
										
										
											2017-11-16 15:12:32 -02:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2018-06-11 08:37:56 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-11-16 15:12:32 -02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	MetaBall *mb = ob->data; | 
					
						
							|  |  |  | 	MetaBallBatchCache *cache = metaball_batch_cache_get(mb); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (cache->batch == NULL) { | 
					
						
							| 
									
										
										
										
											2018-07-30 16:54:40 +02:00
										 |  |  | 		ListBase *lb = &ob->runtime.curve_cache->disp; | 
					
						
							| 
									
										
										
										
											2018-12-14 00:42:16 +01:00
										 |  |  | 		GPUIndexBuf *ibo = MEM_callocN(sizeof(GPUIndexBuf), __func__); | 
					
						
							|  |  |  | 		DRW_displist_indexbuf_create_triangles_in_order(lb, ibo); | 
					
						
							| 
									
										
										
										
											2018-07-18 00:12:21 +02:00
										 |  |  | 		cache->batch = GPU_batch_create_ex( | 
					
						
							|  |  |  | 		        GPU_PRIM_TRIS, | 
					
						
							| 
									
										
										
										
											2018-11-23 18:02:34 +01:00
										 |  |  | 		        mball_batch_cache_get_pos_and_normals(ob, cache), | 
					
						
							| 
									
										
										
										
											2018-12-14 00:42:16 +01:00
										 |  |  | 		        ibo, | 
					
						
							| 
									
										
										
										
											2018-11-23 18:02:34 +01:00
										 |  |  | 		        GPU_BATCH_OWNS_INDEX); | 
					
						
							| 
									
										
										
										
											2017-11-16 15:12:32 -02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return cache->batch; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-06-11 08:37:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-18 00:12:21 +02:00
										 |  |  | GPUBatch **DRW_metaball_batch_cache_get_surface_shaded(Object *ob, MetaBall *mb, struct GPUMaterial **UNUSED(gpumat_array), uint gpumat_array_len) | 
					
						
							| 
									
										
										
										
											2018-06-11 08:37:56 +02:00
										 |  |  | { | 
					
						
							|  |  |  | 	if (!BKE_mball_is_basis(ob)) { | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	MetaBallBatchCache *cache = metaball_batch_cache_get(mb); | 
					
						
							|  |  |  | 	if (cache->shaded_triangles == NULL) { | 
					
						
							|  |  |  | 		cache->mat_len = gpumat_array_len; | 
					
						
							|  |  |  | 		cache->shaded_triangles = MEM_callocN(sizeof(*cache->shaded_triangles) * cache->mat_len, __func__); | 
					
						
							|  |  |  | 		cache->shaded_triangles[0] = DRW_metaball_batch_cache_get_triangles_with_normals(ob); | 
					
						
							|  |  |  | 		for (int i = 1; i < cache->mat_len; ++i) { | 
					
						
							|  |  |  | 			cache->shaded_triangles[i] = NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return cache->shaded_triangles; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-11-23 18:02:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-07 05:03:01 +01:00
										 |  |  | GPUBatch *DRW_metaball_batch_cache_get_wireframes_face(Object *ob) | 
					
						
							| 
									
										
										
										
											2018-11-23 18:02:34 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	if (!BKE_mball_is_basis(ob)) { | 
					
						
							| 
									
										
										
										
											2018-12-07 05:03:01 +01:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2018-11-23 18:02:34 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	MetaBall *mb = ob->data; | 
					
						
							|  |  |  | 	MetaBallBatchCache *cache = metaball_batch_cache_get(mb); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-07 05:03:01 +01:00
										 |  |  | 	if (cache->face_wire.batch == NULL) { | 
					
						
							|  |  |  | 		ListBase *lb = &ob->runtime.curve_cache->disp; | 
					
						
							| 
									
										
										
										
											2018-12-14 02:52:50 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		GPUVertBuf *vbo_pos_nor = MEM_callocN(sizeof(GPUVertBuf), __func__); | 
					
						
							|  |  |  | 		GPUVertBuf *vbo_wireframe_data = MEM_callocN(sizeof(GPUVertBuf), __func__); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		DRW_displist_vertbuf_create_pos_and_nor_and_uv_tess(lb, vbo_pos_nor, NULL); | 
					
						
							|  |  |  | 		DRW_displist_vertbuf_create_wireframe_data_tess(lb, vbo_wireframe_data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		cache->face_wire.batch = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo_pos_nor, NULL, GPU_BATCH_OWNS_VBO); | 
					
						
							|  |  |  | 		GPU_batch_vertbuf_add_ex(cache->face_wire.batch, vbo_wireframe_data, true); | 
					
						
							| 
									
										
										
										
											2018-11-23 18:02:34 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-12-07 05:03:01 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return cache->face_wire.batch; | 
					
						
							| 
									
										
										
										
											2018-11-25 08:01:30 +11:00
										 |  |  | } |