| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * ***** BEGIN GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 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. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Contributor(s): Blender Foundation, Mike Erwin, Dalai Felinto | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ***** END GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \file draw_cache_impl_particles.c
 | 
					
						
							|  |  |  |  *  \ingroup draw | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \brief Particle API for render engines | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 12:30:20 +02:00
										 |  |  | #include "DRW_render.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BLI_utildefines.h"
 | 
					
						
							|  |  |  | #include "BLI_math_vector.h"
 | 
					
						
							| 
									
										
										
										
											2017-11-14 17:00:10 +11:00
										 |  |  | #include "BLI_string.h"
 | 
					
						
							| 
									
										
										
										
											2017-06-22 19:19:55 +02:00
										 |  |  | #include "BLI_ghash.h"
 | 
					
						
							| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-22 19:19:55 +02:00
										 |  |  | #include "DNA_modifier_types.h"
 | 
					
						
							| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | #include "DNA_particle_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BKE_particle.h"
 | 
					
						
							| 
									
										
										
										
											2017-06-22 19:19:55 +02:00
										 |  |  | #include "BKE_DerivedMesh.h"
 | 
					
						
							| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "GPU_batch.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-06 12:07:27 +02:00
										 |  |  | #include "DEG_depsgraph_query.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | #include "draw_cache_impl.h"  /* own include */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void particle_batch_cache_clear(ParticleSystem *psys); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ---------------------------------------------------------------------- */ | 
					
						
							| 
									
										
										
										
											2017-06-19 20:18:04 +10:00
										 |  |  | /* Particle Gwn_Batch Cache */ | 
					
						
							| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | typedef struct ParticleBatchCache { | 
					
						
							| 
									
										
										
										
											2017-06-19 20:18:04 +10:00
										 |  |  | 	Gwn_VertBuf *pos; | 
					
						
							| 
									
										
										
										
											2018-04-10 17:38:33 +02:00
										 |  |  | 	Gwn_IndexBuf *indices; | 
					
						
							| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-19 20:18:04 +10:00
										 |  |  | 	Gwn_Batch *hairs; | 
					
						
							| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-10 17:38:33 +02:00
										 |  |  | 	int elems_count; | 
					
						
							| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | 	int point_count; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* settings to determine if cache is invalid */ | 
					
						
							|  |  |  | 	bool is_dirty; | 
					
						
							|  |  |  | } ParticleBatchCache; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-19 20:18:04 +10:00
										 |  |  | /* Gwn_Batch cache management. */ | 
					
						
							| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | static bool particle_batch_cache_valid(ParticleSystem *psys) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ParticleBatchCache *cache = psys->batch_cache; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (cache == NULL) { | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (cache->is_dirty == false) { | 
					
						
							|  |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void particle_batch_cache_init(ParticleSystem *psys) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ParticleBatchCache *cache = psys->batch_cache; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!cache) { | 
					
						
							|  |  |  | 		cache = psys->batch_cache = MEM_callocN(sizeof(*cache), __func__); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		memset(cache, 0, sizeof(*cache)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cache->is_dirty = false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ParticleBatchCache *particle_batch_cache_get(ParticleSystem *psys) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (!particle_batch_cache_valid(psys)) { | 
					
						
							|  |  |  | 		particle_batch_cache_clear(psys); | 
					
						
							|  |  |  | 		particle_batch_cache_init(psys); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return psys->batch_cache; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DRW_particle_batch_cache_dirty(ParticleSystem *psys, int mode) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ParticleBatchCache *cache = psys->batch_cache; | 
					
						
							|  |  |  | 	if (cache == NULL) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	switch (mode) { | 
					
						
							|  |  |  | 		case BKE_PARTICLE_BATCH_DIRTY_ALL: | 
					
						
							|  |  |  | 			cache->is_dirty = true; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			BLI_assert(0); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void particle_batch_cache_clear(ParticleSystem *psys) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ParticleBatchCache *cache = psys->batch_cache; | 
					
						
							|  |  |  | 	if (!cache) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-19 20:18:04 +10:00
										 |  |  | 	GWN_BATCH_DISCARD_SAFE(cache->hairs); | 
					
						
							| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-19 20:18:04 +10:00
										 |  |  | 	GWN_VERTBUF_DISCARD_SAFE(cache->pos); | 
					
						
							| 
									
										
										
										
											2018-04-10 17:38:33 +02:00
										 |  |  | 	GWN_INDEXBUF_DISCARD_SAFE(cache->indices); | 
					
						
							| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DRW_particle_batch_cache_free(ParticleSystem *psys) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	particle_batch_cache_clear(psys); | 
					
						
							|  |  |  | 	MEM_SAFE_FREE(psys->batch_cache); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void ensure_seg_pt_count(ParticleSystem *psys, ParticleBatchCache *cache) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-04-10 17:38:33 +02:00
										 |  |  | 	if (cache->pos == NULL || cache->indices == NULL) { | 
					
						
							|  |  |  | 		cache->elems_count = 0; | 
					
						
							| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | 		cache->point_count = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (psys->pathcache && (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) { | 
					
						
							|  |  |  | 			for (int i = 0; i < psys->totpart; i++) { | 
					
						
							|  |  |  | 				ParticleCacheKey *path = psys->pathcache[i]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-16 17:42:14 +02:00
										 |  |  | 				if (path->segments > 0) { | 
					
						
							| 
									
										
										
										
											2018-04-10 17:38:33 +02:00
										 |  |  | 					cache->elems_count += path->segments + 2; | 
					
						
							| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | 					cache->point_count += path->segments + 1; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (psys->childcache) { | 
					
						
							|  |  |  | 			int child_count = psys->totchild * psys->part->disp / 100; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			for (int i = 0; i < child_count; i++) { | 
					
						
							|  |  |  | 				ParticleCacheKey *path = psys->childcache[i]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-16 17:42:14 +02:00
										 |  |  | 				if (path->segments > 0) { | 
					
						
							| 
									
										
										
										
											2018-04-10 17:38:33 +02:00
										 |  |  | 					cache->elems_count += path->segments + 2; | 
					
						
							| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | 					cache->point_count += path->segments + 1; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-19 20:18:04 +10:00
										 |  |  | /* Gwn_Batch cache usage. */ | 
					
						
							| 
									
										
										
										
											2017-06-22 19:19:55 +02:00
										 |  |  | static void particle_batch_cache_ensure_pos_and_seg(ParticleSystem *psys, ModifierData *md, ParticleBatchCache *cache) | 
					
						
							| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-04-10 17:38:33 +02:00
										 |  |  | 	if (cache->pos != NULL && cache->indices != NULL) { | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int curr_point = 0; | 
					
						
							|  |  |  | 	ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	GWN_VERTBUF_DISCARD_SAFE(cache->pos); | 
					
						
							| 
									
										
										
										
											2018-04-10 17:38:33 +02:00
										 |  |  | 	GWN_INDEXBUF_DISCARD_SAFE(cache->indices); | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	static Gwn_VertFormat format = { 0 }; | 
					
						
							|  |  |  | 	static struct { uint pos, tan, ind; } attr_id; | 
					
						
							|  |  |  | 	unsigned int *uv_id = NULL; | 
					
						
							| 
									
										
										
										
											2018-05-08 12:40:07 +02:00
										 |  |  | 	int num_uv_layers = 0; | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 	MTFace **mtfaces = NULL; | 
					
						
							|  |  |  | 	float (**parent_uvs)[2] = NULL; | 
					
						
							|  |  |  | 	bool simple = psys->part->childtype == PART_CHILD_PARTICLES; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-08 12:40:07 +02:00
										 |  |  | 	if (psmd != NULL) { | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 		if (CustomData_has_layer(&psmd->dm_final->loopData, CD_MLOOPUV)) { | 
					
						
							| 
									
										
										
										
											2018-05-08 12:40:07 +02:00
										 |  |  | 			num_uv_layers = CustomData_number_of_layers(&psmd->dm_final->loopData, CD_MLOOPUV); | 
					
						
							| 
									
										
										
										
											2017-06-22 19:19:55 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-06-22 19:19:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 	GWN_vertformat_clear(&format); | 
					
						
							| 
									
										
										
										
											2017-06-22 19:19:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 	/* initialize vertex format */ | 
					
						
							|  |  |  | 	attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); | 
					
						
							|  |  |  | 	attr_id.tan = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); | 
					
						
							|  |  |  | 	attr_id.ind = GWN_vertformat_attr_add(&format, "ind", GWN_COMP_I32, 1, GWN_FETCH_INT); | 
					
						
							| 
									
										
										
										
											2017-06-22 19:19:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 	if (psmd) { | 
					
						
							| 
									
										
										
										
											2018-05-08 12:40:07 +02:00
										 |  |  | 		uv_id = MEM_mallocN(sizeof(*uv_id) * num_uv_layers, "UV attrib format"); | 
					
						
							| 
									
										
										
										
											2017-06-22 19:19:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-08 12:40:07 +02:00
										 |  |  | 		for (int i = 0; i < num_uv_layers; i++) { | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 			const char *name = CustomData_get_layer_name(&psmd->dm_final->loopData, CD_MLOOPUV, i); | 
					
						
							|  |  |  | 			char uuid[32]; | 
					
						
							| 
									
										
										
										
											2017-06-22 19:19:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 			BLI_snprintf(uuid, sizeof(uuid), "u%u", BLI_ghashutil_strhash_p(name)); | 
					
						
							|  |  |  | 			uv_id[i] = GWN_vertformat_attr_add(&format, uuid, GWN_COMP_F32, 2, GWN_FETCH_FLOAT); | 
					
						
							| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 	cache->pos = GWN_vertbuf_create_with_format(&format); | 
					
						
							|  |  |  | 	GWN_vertbuf_data_alloc(cache->pos, cache->point_count); | 
					
						
							| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 	Gwn_IndexBufBuilder elb; | 
					
						
							| 
									
										
										
										
											2018-04-10 17:38:33 +02:00
										 |  |  | 	GWN_indexbuf_init_ex(&elb, GWN_PRIM_LINE_STRIP, cache->elems_count, cache->point_count, true); | 
					
						
							| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-08 12:40:07 +02:00
										 |  |  | 	if (num_uv_layers) { | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 		DM_ensure_tessface(psmd->dm_final); | 
					
						
							| 
									
										
										
										
											2018-05-08 12:40:07 +02:00
										 |  |  | 		mtfaces = MEM_mallocN(sizeof(*mtfaces) * num_uv_layers, "Faces UV layers"); | 
					
						
							|  |  |  | 		for (int i = 0; i < num_uv_layers; i++) { | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 			mtfaces[i] = (MTFace *)CustomData_get_layer_n(&psmd->dm_final->faceData, CD_MTFACE, i); | 
					
						
							| 
									
										
										
										
											2017-06-22 19:19:55 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-06-22 19:19:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 	if (psys->pathcache && (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) { | 
					
						
							|  |  |  | 		if (simple) { | 
					
						
							|  |  |  | 			parent_uvs = MEM_callocN(sizeof(*parent_uvs) * psys->totpart, "Parent particle UVs"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		for (int i = 0; i < psys->totpart; i++) { | 
					
						
							|  |  |  | 			ParticleCacheKey *path = psys->pathcache[i]; | 
					
						
							| 
									
										
										
										
											2018-05-08 12:36:20 +02:00
										 |  |  | 			if (path->segments <= 0) { | 
					
						
							|  |  |  | 				continue; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			float tangent[3]; | 
					
						
							|  |  |  | 			int from = psmd ? psmd->psys->part->from : 0; | 
					
						
							|  |  |  | 			float (*uv)[2] = NULL; | 
					
						
							|  |  |  | 			if (psmd != NULL) { | 
					
						
							| 
									
										
										
										
											2018-05-08 12:40:07 +02:00
										 |  |  | 				uv = MEM_callocN(sizeof(*uv) * num_uv_layers, "Particle UVs"); | 
					
						
							| 
									
										
										
										
											2018-05-08 12:36:20 +02:00
										 |  |  | 				if (simple) { | 
					
						
							|  |  |  | 					parent_uvs[i] = uv; | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2018-05-08 12:36:20 +02:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			if (ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) { | 
					
						
							|  |  |  | 				ParticleData *particle = &psys->particles[i]; | 
					
						
							|  |  |  | 				int num = particle->num_dmcache; | 
					
						
							|  |  |  | 				if (num == DMCACHE_NOTFOUND) { | 
					
						
							|  |  |  | 					if (particle->num < psmd->dm_final->getNumTessFaces(psmd->dm_final)) { | 
					
						
							|  |  |  | 						num = particle->num; | 
					
						
							| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2018-05-08 12:36:20 +02:00
										 |  |  | 				if (num != DMCACHE_NOTFOUND) { | 
					
						
							|  |  |  | 					MFace *mface = psmd->dm_final->getTessFaceData(psmd->dm_final, num, CD_MFACE); | 
					
						
							| 
									
										
										
										
											2018-05-08 12:40:07 +02:00
										 |  |  | 					for (int j = 0; j < num_uv_layers; j++) { | 
					
						
							| 
									
										
										
										
											2018-05-08 12:36:20 +02:00
										 |  |  | 						psys_interpolate_uvs(mtfaces[j] + num, mface->v4, particle->fuv, uv[j]); | 
					
						
							| 
									
										
										
										
											2017-06-22 19:19:55 +02:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2018-05-08 12:36:20 +02:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			for (int j = 0; j < path->segments; j++) { | 
					
						
							|  |  |  | 				if (j == 0) { | 
					
						
							|  |  |  | 					sub_v3_v3v3(tangent, path[j + 1].co, path[j].co); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else { | 
					
						
							|  |  |  | 					sub_v3_v3v3(tangent, path[j + 1].co, path[j - 1].co); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				GWN_vertbuf_attr_set(cache->pos, attr_id.pos, curr_point, path[j].co); | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 				GWN_vertbuf_attr_set(cache->pos, attr_id.tan, curr_point, tangent); | 
					
						
							|  |  |  | 				GWN_vertbuf_attr_set(cache->pos, attr_id.ind, curr_point, &i); | 
					
						
							| 
									
										
										
										
											2018-05-08 12:36:20 +02:00
										 |  |  | 				if (psmd != NULL) { | 
					
						
							| 
									
										
										
										
											2018-05-08 12:40:07 +02:00
										 |  |  | 					for (int k = 0; k < num_uv_layers; k++) { | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 						GWN_vertbuf_attr_set(cache->pos, uv_id[k], curr_point, uv[k]); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2018-04-10 17:38:33 +02:00
										 |  |  | 				GWN_indexbuf_add_generic_vert(&elb, curr_point); | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 				curr_point++; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-05-08 12:36:20 +02:00
										 |  |  | 			sub_v3_v3v3(tangent, path[path->segments].co, path[path->segments - 1].co); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			GWN_vertbuf_attr_set(cache->pos, attr_id.pos, curr_point, path[path->segments].co); | 
					
						
							|  |  |  | 			GWN_vertbuf_attr_set(cache->pos, attr_id.tan, curr_point, tangent); | 
					
						
							|  |  |  | 			GWN_vertbuf_attr_set(cache->pos, attr_id.ind, curr_point, &i); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (psmd != NULL) { | 
					
						
							| 
									
										
										
										
											2018-05-08 12:40:07 +02:00
										 |  |  | 				for (int k = 0; k < num_uv_layers; k++) { | 
					
						
							| 
									
										
										
										
											2018-05-08 12:36:20 +02:00
										 |  |  | 					GWN_vertbuf_attr_set(cache->pos, uv_id[k], curr_point, uv[k]); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if (!simple) { | 
					
						
							|  |  |  | 					MEM_freeN(uv); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			/* Finish the segment and add restart primitive. */ | 
					
						
							|  |  |  | 			GWN_indexbuf_add_generic_vert(&elb, curr_point); | 
					
						
							|  |  |  | 			GWN_indexbuf_add_primitive_restart(&elb); | 
					
						
							|  |  |  | 			curr_point++; | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-06-22 19:19:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 	if (psys->childcache) { | 
					
						
							|  |  |  | 		int child_count = psys->totchild * psys->part->disp / 100; | 
					
						
							| 
									
										
										
										
											2018-05-08 12:36:20 +02:00
										 |  |  | 		if (simple && parent_uvs == NULL) { | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 			parent_uvs = MEM_callocN(sizeof(*parent_uvs) * psys->totpart, "Parent particle UVs"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		for (int i = 0, x = psys->totpart; i < child_count; i++, x++) { | 
					
						
							|  |  |  | 			ParticleCacheKey *path = psys->childcache[i]; | 
					
						
							| 
									
										
										
										
											2018-05-08 12:36:20 +02:00
										 |  |  | 			if (path->segments <= 0) { | 
					
						
							|  |  |  | 				continue; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-05-08 12:40:07 +02:00
										 |  |  | 			float tangent[3]; | 
					
						
							| 
									
										
										
										
											2018-05-08 12:36:20 +02:00
										 |  |  | 			int from = psmd ? psmd->psys->part->from : 0; | 
					
						
							|  |  |  | 			float (*uv)[2] = NULL; | 
					
						
							|  |  |  | 			if (!simple) { | 
					
						
							| 
									
										
										
										
											2018-05-08 12:40:07 +02:00
										 |  |  | 				if (psmd != NULL) { | 
					
						
							|  |  |  | 					uv = MEM_callocN(sizeof(*uv) * num_uv_layers, "Particle UVs"); | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2018-05-08 12:36:20 +02:00
										 |  |  | 				if (ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) { | 
					
						
							|  |  |  | 					ChildParticle *particle = &psys->child[i]; | 
					
						
							|  |  |  | 					int num = particle->num; | 
					
						
							|  |  |  | 					if (num != DMCACHE_NOTFOUND) { | 
					
						
							|  |  |  | 						MFace *mface = psmd->dm_final->getTessFaceData(psmd->dm_final, num, CD_MFACE); | 
					
						
							| 
									
										
										
										
											2018-05-08 12:40:07 +02:00
										 |  |  | 						for (int j = 0; j < num_uv_layers; j++) { | 
					
						
							| 
									
										
										
										
											2018-05-08 12:36:20 +02:00
										 |  |  | 							psys_interpolate_uvs(mtfaces[j] + num, mface->v4, particle->fuv, uv[j]); | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2018-05-08 12:36:20 +02:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			else if (!parent_uvs[psys->child[i].parent]) { | 
					
						
							| 
									
										
										
										
											2018-05-08 12:40:07 +02:00
										 |  |  | 				if (psmd != NULL) { | 
					
						
							| 
									
										
										
										
											2018-05-08 13:55:23 +02:00
										 |  |  | 					uv = parent_uvs[psys->child[i].parent] = MEM_callocN(sizeof(*uv) * num_uv_layers, "Particle UVs"); | 
					
						
							| 
									
										
										
										
											2018-05-08 12:40:07 +02:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2018-05-08 12:36:20 +02:00
										 |  |  | 				if (ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) { | 
					
						
							|  |  |  | 					ParticleData *particle = &psys->particles[psys->child[i].parent]; | 
					
						
							|  |  |  | 					int num = particle->num_dmcache; | 
					
						
							|  |  |  | 					if (num == DMCACHE_NOTFOUND) { | 
					
						
							|  |  |  | 						if (particle->num < psmd->dm_final->getNumTessFaces(psmd->dm_final)) { | 
					
						
							|  |  |  | 							num = particle->num; | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2018-05-08 12:36:20 +02:00
										 |  |  | 					if (num != DMCACHE_NOTFOUND) { | 
					
						
							|  |  |  | 						MFace *mface = psmd->dm_final->getTessFaceData(psmd->dm_final, num, CD_MFACE); | 
					
						
							| 
									
										
										
										
											2018-05-08 12:40:07 +02:00
										 |  |  | 						for (int j = 0; j < num_uv_layers; j++) { | 
					
						
							| 
									
										
										
										
											2018-05-08 13:55:23 +02:00
										 |  |  | 							psys_interpolate_uvs(mtfaces[j] + num, mface->v4, particle->fuv, uv[j]); | 
					
						
							| 
									
										
										
										
											2017-06-22 19:19:55 +02:00
										 |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2018-05-08 12:36:20 +02:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			for (int j = 0; j < path->segments; j++) { | 
					
						
							|  |  |  | 				if (j == 0) { | 
					
						
							|  |  |  | 					sub_v3_v3v3(tangent, path[j + 1].co, path[j].co); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else { | 
					
						
							|  |  |  | 					sub_v3_v3v3(tangent, path[j + 1].co, path[j - 1].co); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				GWN_vertbuf_attr_set(cache->pos, attr_id.pos, curr_point, path[j].co); | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 				GWN_vertbuf_attr_set(cache->pos, attr_id.tan, curr_point, tangent); | 
					
						
							|  |  |  | 				GWN_vertbuf_attr_set(cache->pos, attr_id.ind, curr_point, &x); | 
					
						
							| 
									
										
										
										
											2018-05-08 12:36:20 +02:00
										 |  |  | 				if (psmd != NULL) { | 
					
						
							| 
									
										
										
										
											2018-05-08 12:40:07 +02:00
										 |  |  | 					for (int k = 0; k < num_uv_layers; k++) { | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 						GWN_vertbuf_attr_set(cache->pos, uv_id[k], curr_point, | 
					
						
							|  |  |  | 						                     simple ? parent_uvs[psys->child[i].parent][k] : uv[k]); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2018-04-10 17:38:33 +02:00
										 |  |  | 				GWN_indexbuf_add_generic_vert(&elb, curr_point); | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 				curr_point++; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-05-08 12:36:20 +02:00
										 |  |  | 			sub_v3_v3v3(tangent, path[path->segments].co, path[path->segments - 1].co); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			GWN_vertbuf_attr_set(cache->pos, attr_id.pos, curr_point, path[path->segments].co); | 
					
						
							|  |  |  | 			GWN_vertbuf_attr_set(cache->pos, attr_id.tan, curr_point, tangent); | 
					
						
							|  |  |  | 			GWN_vertbuf_attr_set(cache->pos, attr_id.ind, curr_point, &x); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (psmd != NULL) { | 
					
						
							| 
									
										
										
										
											2018-05-08 12:40:07 +02:00
										 |  |  | 				for (int k = 0; k < num_uv_layers; k++) { | 
					
						
							| 
									
										
										
										
											2018-05-08 12:36:20 +02:00
										 |  |  | 					GWN_vertbuf_attr_set(cache->pos, uv_id[k], curr_point, | 
					
						
							|  |  |  | 					                     simple ? parent_uvs[psys->child[i].parent][k] : uv[k]); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if (!simple) { | 
					
						
							|  |  |  | 					MEM_freeN(uv); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			/* Finish the segment and add restart primitive. */ | 
					
						
							|  |  |  | 			GWN_indexbuf_add_generic_vert(&elb, curr_point); | 
					
						
							|  |  |  | 			GWN_indexbuf_add_primitive_restart(&elb); | 
					
						
							|  |  |  | 			curr_point++; | 
					
						
							| 
									
										
										
										
											2017-06-22 19:19:55 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-05-08 12:36:20 +02:00
										 |  |  | 	/* Cleanup. */ | 
					
						
							|  |  |  | 	if (parent_uvs != NULL) { | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 		for (int i = 0; i < psys->totpart; i++) { | 
					
						
							|  |  |  | 			MEM_SAFE_FREE(parent_uvs[i]); | 
					
						
							| 
									
										
										
										
											2017-06-22 19:19:55 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 		MEM_freeN(parent_uvs); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-05-08 12:40:07 +02:00
										 |  |  | 	if (num_uv_layers) { | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 		MEM_freeN(mtfaces); | 
					
						
							| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-05-08 12:36:20 +02:00
										 |  |  | 	if (psmd != NULL) { | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 		MEM_freeN(uv_id); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-04-10 17:38:33 +02:00
										 |  |  | 	cache->indices = GWN_indexbuf_build(&elb); | 
					
						
							| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 12:30:20 +02:00
										 |  |  | static void particle_batch_cache_ensure_pos(Object *object, ParticleSystem *psys, ParticleBatchCache *cache) | 
					
						
							| 
									
										
										
										
											2017-05-19 17:13:48 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 	if (cache->pos != NULL) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-05-19 17:13:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 	static Gwn_VertFormat format = { 0 }; | 
					
						
							|  |  |  | 	static unsigned pos_id, rot_id, val_id; | 
					
						
							|  |  |  | 	int i, curr_point; | 
					
						
							|  |  |  | 	ParticleData *pa; | 
					
						
							| 
									
										
										
										
											2018-03-29 12:30:20 +02:00
										 |  |  | 	ParticleKey state; | 
					
						
							|  |  |  | 	ParticleSimulationData sim = {NULL}; | 
					
						
							|  |  |  | 	const DRWContextState *draw_ctx = DRW_context_state_get(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-06 12:07:27 +02:00
										 |  |  | 	sim.depsgraph = draw_ctx->depsgraph; | 
					
						
							| 
									
										
										
										
											2018-03-29 12:30:20 +02:00
										 |  |  | 	sim.scene = draw_ctx->scene; | 
					
						
							|  |  |  | 	sim.ob = object; | 
					
						
							|  |  |  | 	sim.psys = psys; | 
					
						
							|  |  |  | 	sim.psmd = psys_get_modifier(object, psys); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (psys->part->phystype == PART_PHYS_KEYED) { | 
					
						
							|  |  |  | 		if (psys->flag & PSYS_KEYED) { | 
					
						
							|  |  |  | 			psys_count_keyed_targets(&sim); | 
					
						
							|  |  |  | 			if (psys->totkeyed == 0) | 
					
						
							|  |  |  | 				return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-05-23 16:56:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 	GWN_VERTBUF_DISCARD_SAFE(cache->pos); | 
					
						
							| 
									
										
										
										
											2018-04-10 17:38:33 +02:00
										 |  |  | 	GWN_INDEXBUF_DISCARD_SAFE(cache->indices); | 
					
						
							| 
									
										
										
										
											2017-05-23 16:56:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 	if (format.attrib_ct == 0) { | 
					
						
							|  |  |  | 		/* initialize vertex format */ | 
					
						
							|  |  |  | 		pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); | 
					
						
							|  |  |  | 		rot_id = GWN_vertformat_attr_add(&format, "rot", GWN_COMP_F32, 4, GWN_FETCH_FLOAT); | 
					
						
							|  |  |  | 		val_id = GWN_vertformat_attr_add(&format, "val", GWN_COMP_F32, 1, GWN_FETCH_FLOAT); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cache->pos = GWN_vertbuf_create_with_format(&format); | 
					
						
							|  |  |  | 	GWN_vertbuf_data_alloc(cache->pos, psys->totpart); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (curr_point = 0, i = 0, pa = psys->particles; i < psys->totpart; i++, pa++) { | 
					
						
							| 
									
										
										
										
											2018-04-06 12:07:27 +02:00
										 |  |  | 		state.time = DEG_get_ctime(draw_ctx->depsgraph); | 
					
						
							| 
									
										
										
										
											2018-03-29 12:30:20 +02:00
										 |  |  | 		if (!psys_get_particle_state(&sim, curr_point, &state, 0)) { | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 12:30:20 +02:00
										 |  |  | 		float val; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		GWN_vertbuf_attr_set(cache->pos, pos_id, curr_point, pa->state.co); | 
					
						
							|  |  |  | 		GWN_vertbuf_attr_set(cache->pos, rot_id, curr_point, pa->state.rot); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		switch (psys->part->draw_col) { | 
					
						
							|  |  |  | 			case PART_DRAW_COL_VEL: | 
					
						
							|  |  |  | 				val = len_v3(pa->state.vel) / psys->part->color_vec_max; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case PART_DRAW_COL_ACC: | 
					
						
							|  |  |  | 				val = len_v3v3(pa->state.vel, pa->prev_state.vel) / ((pa->state.time - pa->prev_state.time) * psys->part->color_vec_max); | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			default: | 
					
						
							|  |  |  | 				val = -1.0f; | 
					
						
							|  |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2017-05-19 17:13:48 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-03-29 12:30:20 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		GWN_vertbuf_attr_set(cache->pos, val_id, curr_point, &val); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		curr_point++; | 
					
						
							| 
									
										
										
										
											2017-05-19 17:13:48 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-03-29 10:33:02 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (curr_point != psys->totpart) { | 
					
						
							|  |  |  | 		GWN_vertbuf_data_resize(cache->pos, curr_point); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-05-19 17:13:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-22 19:19:55 +02:00
										 |  |  | Gwn_Batch *DRW_particles_batch_cache_get_hair(ParticleSystem *psys, ModifierData *md) | 
					
						
							| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | { | 
					
						
							|  |  |  | 	ParticleBatchCache *cache = particle_batch_cache_get(psys); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (cache->hairs == NULL) { | 
					
						
							|  |  |  | 		ensure_seg_pt_count(psys, cache); | 
					
						
							| 
									
										
										
										
											2017-06-22 19:19:55 +02:00
										 |  |  | 		particle_batch_cache_ensure_pos_and_seg(psys, md, cache); | 
					
						
							| 
									
										
										
										
											2018-04-10 17:38:33 +02:00
										 |  |  | 		cache->hairs = GWN_batch_create(GWN_PRIM_LINE_STRIP, cache->pos, cache->indices); | 
					
						
							| 
									
										
										
										
											2017-05-09 16:23:47 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return cache->hairs; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-05-19 17:13:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 12:30:20 +02:00
										 |  |  | Gwn_Batch *DRW_particles_batch_cache_get_dots(Object *object, ParticleSystem *psys) | 
					
						
							| 
									
										
										
										
											2017-05-19 17:13:48 +02:00
										 |  |  | { | 
					
						
							|  |  |  | 	ParticleBatchCache *cache = particle_batch_cache_get(psys); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (cache->hairs == NULL) { | 
					
						
							| 
									
										
										
										
											2018-03-29 12:30:20 +02:00
										 |  |  | 		particle_batch_cache_ensure_pos(object, psys, cache); | 
					
						
							| 
									
										
										
										
											2017-06-19 20:18:04 +10:00
										 |  |  | 		cache->hairs = GWN_batch_create(GWN_PRIM_POINTS, cache->pos, NULL); | 
					
						
							| 
									
										
										
										
											2017-05-19 17:13:48 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return cache->hairs; | 
					
						
							|  |  |  | } |