| 
									
										
										
										
											2016-12-28 17:30:58 +01: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) 2005 by the Blender Foundation. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-06 15:42:22 +11:00
										 |  |  | /** \file \ingroup modifiers
 | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-17 13:45:47 +02:00
										 |  |  | #include "DNA_mesh_types.h"
 | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | #include "DNA_meshdata_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BLI_math.h"
 | 
					
						
							|  |  |  | #include "BLI_listbase.h"
 | 
					
						
							|  |  |  | #include "BLI_rand.h"
 | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | #include "BLI_string.h"
 | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | #include "BLI_utildefines.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BKE_effect.h"
 | 
					
						
							|  |  |  | #include "BKE_lattice.h"
 | 
					
						
							|  |  |  | #include "BKE_library_query.h"
 | 
					
						
							| 
									
										
										
										
											2018-05-17 13:45:47 +02:00
										 |  |  | #include "BKE_mesh.h"
 | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | #include "BKE_modifier.h"
 | 
					
						
							|  |  |  | #include "BKE_particle.h"
 | 
					
						
							|  |  |  | #include "BKE_pointcache.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "DEG_depsgraph_build.h"
 | 
					
						
							| 
									
										
										
										
											2018-06-22 15:03:42 +02:00
										 |  |  | #include "DEG_depsgraph_query.h"
 | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-30 15:14:00 +11:00
										 |  |  | #include "MOD_modifiertypes.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | static void initData(ModifierData *md) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pimd->flag = eParticleInstanceFlag_Parents | eParticleInstanceFlag_Unborn | | 
					
						
							|  |  |  | 	             eParticleInstanceFlag_Alive | eParticleInstanceFlag_Dead; | 
					
						
							|  |  |  | 	pimd->psys = 1; | 
					
						
							|  |  |  | 	pimd->position = 1.0f; | 
					
						
							|  |  |  | 	pimd->axis = 2; | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 	pimd->space = eParticleInstanceSpace_World; | 
					
						
							|  |  |  | 	pimd->particle_amount = 1.0f; | 
					
						
							|  |  |  | 	pimd->particle_offset = 0.0f; | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 	STRNCPY(pimd->index_layer_name, ""); | 
					
						
							|  |  |  | 	STRNCPY(pimd->value_layer_name, ""); | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md; | 
					
						
							|  |  |  | 	CustomDataMask dataMask = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (pimd->index_layer_name[0] != '\0' || | 
					
						
							|  |  |  | 	    pimd->value_layer_name[0] != '\0') | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		dataMask |= CD_MASK_MLOOPCOL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return dataMask; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-10 12:14:08 +02:00
										 |  |  | static bool isDisabled(const struct Scene *scene, ModifierData *md, bool useRenderParams) | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md; | 
					
						
							|  |  |  | 	ParticleSystem *psys; | 
					
						
							|  |  |  | 	ModifierData *ob_md; | 
					
						
							| 
									
										
										
										
											2018-04-18 12:04:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 	if (!pimd->ob) | 
					
						
							|  |  |  | 		return true; | 
					
						
							| 
									
										
										
										
											2018-04-18 12:04:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 	psys = BLI_findlink(&pimd->ob->particlesystem, pimd->psys - 1); | 
					
						
							|  |  |  | 	if (psys == NULL) | 
					
						
							|  |  |  | 		return true; | 
					
						
							| 
									
										
										
										
											2018-04-18 12:04:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 	/* If the psys modifier is disabled we cannot use its data.
 | 
					
						
							|  |  |  | 	 * First look up the psys modifier from the object, then check if it is enabled. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	for (ob_md = pimd->ob->modifiers.first; ob_md; ob_md = ob_md->next) { | 
					
						
							|  |  |  | 		if (ob_md->type == eModifierType_ParticleSystem) { | 
					
						
							|  |  |  | 			ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)ob_md; | 
					
						
							|  |  |  | 			if (psmd->psys == psys) { | 
					
						
							|  |  |  | 				int required_mode; | 
					
						
							| 
									
										
										
										
											2018-04-18 12:04:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 				if (useRenderParams) required_mode = eModifierMode_Render; | 
					
						
							|  |  |  | 				else required_mode = eModifierMode_Realtime; | 
					
						
							| 
									
										
										
										
											2018-04-18 12:04:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-21 17:54:12 +02:00
										 |  |  | 				if (!modifier_isEnabled(scene, ob_md, required_mode)) | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 					return true; | 
					
						
							| 
									
										
										
										
											2018-04-18 12:04:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-04-18 12:04:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 	return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-22 12:54:06 +01:00
										 |  |  | static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md; | 
					
						
							|  |  |  | 	if (pimd->ob != NULL) { | 
					
						
							| 
									
										
										
										
											2018-02-22 12:54:06 +01:00
										 |  |  | 		DEG_add_object_relation(ctx->node, pimd->ob, DEG_OB_COMP_TRANSFORM, "Particle Instance Modifier"); | 
					
						
							| 
									
										
										
										
											2018-04-18 13:54:02 +02:00
										 |  |  | 		DEG_add_object_relation(ctx->node, pimd->ob, DEG_OB_COMP_GEOMETRY, "Particle Instance Modifier"); | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-12 08:04:56 +02:00
										 |  |  | static void foreachObjectLink( | 
					
						
							|  |  |  |         ModifierData *md, Object *ob, | 
					
						
							|  |  |  |         ObjectWalkFunc walk, void *userData) | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-31 09:47:59 +01:00
										 |  |  | 	walk(userData, ob, &pimd->ob, IDWALK_CB_NOP); | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | static bool particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *psys, int p) | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 	const bool between = (psys->part->childtype == PART_CHILD_FACES); | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 	ParticleData *pa; | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 	int totpart, randp, minp, maxp; | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 	if (p >= psys->totpart) { | 
					
						
							|  |  |  | 		ChildParticle *cpa = psys->child + (p - psys->totpart); | 
					
						
							| 
									
										
										
										
											2018-06-06 22:17:06 +02:00
										 |  |  | 		pa = psys->particles + (between ? cpa->pa[0] : cpa->parent); | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 		pa = psys->particles + p; | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (pa) { | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 		if (pa->alive == PARS_UNBORN && (pimd->flag & eParticleInstanceFlag_Unborn) == 0) return true; | 
					
						
							|  |  |  | 		if (pa->alive == PARS_ALIVE && (pimd->flag & eParticleInstanceFlag_Alive) == 0) return true; | 
					
						
							|  |  |  | 		if (pa->alive == PARS_DEAD && (pimd->flag & eParticleInstanceFlag_Dead) == 0) return true; | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-04-18 12:04:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 	if (pimd->particle_amount == 1.0f) { | 
					
						
							|  |  |  | 		/* Early output, all particles are to be instanced. */ | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Randomly skip particles based on desired amount of visible particles. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	totpart = psys->totpart + psys->totchild; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* TODO make randomization optional? */ | 
					
						
							|  |  |  | 	randp = (int)(psys_frand(psys, 3578 + p) * totpart) % totpart; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-06 22:17:06 +02:00
										 |  |  | 	minp = (int)(totpart * pimd->particle_offset) % (totpart + 1); | 
					
						
							|  |  |  | 	maxp = (int)(totpart * (pimd->particle_offset + pimd->particle_amount)) % (totpart + 1); | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (maxp > minp) { | 
					
						
							|  |  |  | 		return randp < minp || randp >= maxp; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (maxp < minp) { | 
					
						
							|  |  |  | 		return randp < minp && randp >= maxp; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void store_float_in_vcol(MLoopCol *vcol, float float_value) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-05-07 17:31:28 +02:00
										 |  |  | 	const uchar value = unit_float_to_uchar_clamp(float_value); | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 	vcol->r = vcol->g = vcol->b = value; | 
					
						
							|  |  |  | 	vcol->a = 1.0f; | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-17 13:45:47 +02:00
										 |  |  | static Mesh *applyModifier( | 
					
						
							| 
									
										
										
										
											2018-05-12 08:21:07 +02:00
										 |  |  |         ModifierData *md, const ModifierEvalContext *ctx, | 
					
						
							| 
									
										
										
										
											2018-05-17 13:45:47 +02:00
										 |  |  |         Mesh *mesh) | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-05-17 13:45:47 +02:00
										 |  |  | 	Mesh *result; | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 	ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md; | 
					
						
							| 
									
										
										
										
											2018-06-22 15:03:42 +02:00
										 |  |  | 	struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph); | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 	ParticleSimulationData sim; | 
					
						
							|  |  |  | 	ParticleSystem *psys = NULL; | 
					
						
							|  |  |  | 	ParticleData *pa = NULL; | 
					
						
							|  |  |  | 	MPoly *mpoly, *orig_mpoly; | 
					
						
							|  |  |  | 	MLoop *mloop, *orig_mloop; | 
					
						
							|  |  |  | 	MVert *mvert, *orig_mvert; | 
					
						
							| 
									
										
										
										
											2018-05-08 16:57:07 +02:00
										 |  |  | 	int totvert, totpoly, totloop, totedge; | 
					
						
							| 
									
										
										
										
											2018-05-04 09:20:57 +02:00
										 |  |  | 	int maxvert, maxpoly, maxloop, maxedge, part_end = 0, part_start; | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 	int k, p, p_skip; | 
					
						
							| 
									
										
										
										
											2018-05-01 17:33:04 +02:00
										 |  |  | 	short track = ctx->object->trackflag % 3, trackneg, axis = pimd->axis; | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 	float max_co = 0.0, min_co = 0.0, temp_co[3]; | 
					
						
							|  |  |  | 	float *size = NULL; | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 	float spacemat[4][4]; | 
					
						
							|  |  |  | 	const bool use_parents = pimd->flag & eParticleInstanceFlag_Parents; | 
					
						
							|  |  |  | 	const bool use_children = pimd->flag & eParticleInstanceFlag_Children; | 
					
						
							|  |  |  | 	bool between; | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-01 17:33:04 +02:00
										 |  |  | 	trackneg = ((ctx->object->trackflag > 2) ? 1 : 0); | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-01 17:33:04 +02:00
										 |  |  | 	if (pimd->ob == ctx->object) { | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 		pimd->ob = NULL; | 
					
						
							| 
									
										
										
										
											2018-05-17 13:45:47 +02:00
										 |  |  | 		return mesh; | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (pimd->ob) { | 
					
						
							|  |  |  | 		psys = BLI_findlink(&pimd->ob->particlesystem, pimd->psys - 1); | 
					
						
							|  |  |  | 		if (psys == NULL || psys->totpart == 0) | 
					
						
							| 
									
										
										
										
											2018-05-17 13:45:47 +02:00
										 |  |  | 			return mesh; | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2018-05-17 13:45:47 +02:00
										 |  |  | 		return mesh; | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 	part_start = use_parents ? 0 : psys->totpart; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	part_end = 0; | 
					
						
							|  |  |  | 	if (use_parents) | 
					
						
							|  |  |  | 		part_end += psys->totpart; | 
					
						
							|  |  |  | 	if (use_children) | 
					
						
							|  |  |  | 		part_end += psys->totchild; | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 	if (part_end == 0) | 
					
						
							| 
									
										
										
										
											2018-05-17 13:45:47 +02:00
										 |  |  | 		return mesh; | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-01 17:33:04 +02:00
										 |  |  | 	sim.depsgraph = ctx->depsgraph; | 
					
						
							| 
									
										
										
										
											2018-06-22 15:03:42 +02:00
										 |  |  | 	sim.scene = scene; | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 	sim.ob = pimd->ob; | 
					
						
							|  |  |  | 	sim.psys = psys; | 
					
						
							|  |  |  | 	sim.psmd = psys_get_modifier(pimd->ob, psys); | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 	between = (psys->part->childtype == PART_CHILD_FACES); | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (pimd->flag & eParticleInstanceFlag_UseSize) { | 
					
						
							|  |  |  | 		float *si; | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 		si = size = MEM_calloc_arrayN(part_end, sizeof(float), "particle size array"); | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (pimd->flag & eParticleInstanceFlag_Parents) { | 
					
						
							|  |  |  | 			for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++, si++) | 
					
						
							|  |  |  | 				*si = pa->size; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (pimd->flag & eParticleInstanceFlag_Children) { | 
					
						
							|  |  |  | 			ChildParticle *cpa = psys->child; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			for (p = 0; p < psys->totchild; p++, cpa++, si++) { | 
					
						
							|  |  |  | 				*si = psys_get_child_size(psys, cpa, 0.0f, NULL); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 	switch (pimd->space) { | 
					
						
							|  |  |  | 		case eParticleInstanceSpace_World: | 
					
						
							|  |  |  | 			/* particle states are in world space already */ | 
					
						
							|  |  |  | 			unit_m4(spacemat); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case eParticleInstanceSpace_Local: | 
					
						
							|  |  |  | 			/* get particle states in the particle object's local space */ | 
					
						
							|  |  |  | 			invert_m4_m4(spacemat, pimd->ob->obmat); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			/* should not happen */ | 
					
						
							|  |  |  | 			BLI_assert(false); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-17 13:45:47 +02:00
										 |  |  | 	totvert = mesh->totvert; | 
					
						
							|  |  |  | 	totpoly = mesh->totpoly; | 
					
						
							|  |  |  | 	totloop = mesh->totloop; | 
					
						
							|  |  |  | 	totedge = mesh->totedge; | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* count particles */ | 
					
						
							|  |  |  | 	maxvert = 0; | 
					
						
							|  |  |  | 	maxpoly = 0; | 
					
						
							|  |  |  | 	maxloop = 0; | 
					
						
							| 
									
										
										
										
											2018-05-04 09:20:57 +02:00
										 |  |  | 	maxedge = 0; | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 	for (p = part_start; p < part_end; p++) { | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 		if (particle_skip(pimd, psys, p)) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		maxvert += totvert; | 
					
						
							|  |  |  | 		maxpoly += totpoly; | 
					
						
							|  |  |  | 		maxloop += totloop; | 
					
						
							| 
									
										
										
										
											2018-05-04 09:20:57 +02:00
										 |  |  | 		maxedge += totedge; | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) { | 
					
						
							|  |  |  | 		float min[3], max[3]; | 
					
						
							|  |  |  | 		INIT_MINMAX(min, max); | 
					
						
							| 
									
										
										
										
											2018-05-17 13:45:47 +02:00
										 |  |  | 		BKE_mesh_minmax(mesh, min, max); | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 		min_co = min[track]; | 
					
						
							|  |  |  | 		max_co = max[track]; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-17 13:45:47 +02:00
										 |  |  | 	result = BKE_mesh_new_nomain_from_template(mesh, maxvert, maxedge, 0, maxloop, maxpoly); | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-17 13:45:47 +02:00
										 |  |  | 	mvert = result->mvert; | 
					
						
							|  |  |  | 	orig_mvert = mesh->mvert; | 
					
						
							|  |  |  | 	mpoly = result->mpoly; | 
					
						
							|  |  |  | 	orig_mpoly = mesh->mpoly; | 
					
						
							|  |  |  | 	mloop = result->mloop; | 
					
						
							|  |  |  | 	orig_mloop = mesh->mloop; | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-17 13:45:47 +02:00
										 |  |  | 	MLoopCol *mloopcols_index = CustomData_get_layer_named(&result->ldata, CD_MLOOPCOL, pimd->index_layer_name); | 
					
						
							|  |  |  | 	MLoopCol *mloopcols_value = CustomData_get_layer_named(&result->ldata, CD_MLOOPCOL, pimd->value_layer_name); | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 	int *vert_part_index = NULL; | 
					
						
							|  |  |  | 	float *vert_part_value = NULL; | 
					
						
							|  |  |  | 	if (mloopcols_index != NULL) { | 
					
						
							|  |  |  | 		vert_part_index = MEM_calloc_arrayN(maxvert, sizeof(int), "vertex part index array"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (mloopcols_value) { | 
					
						
							|  |  |  | 		vert_part_value = MEM_calloc_arrayN(maxvert, sizeof(float), "vertex part value array"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (p = part_start, p_skip = 0; p < part_end; p++) { | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 		float prev_dir[3]; | 
					
						
							|  |  |  | 		float frame[4]; /* frame orientation quaternion */ | 
					
						
							| 
									
										
										
										
											2018-06-06 22:17:06 +02:00
										 |  |  | 		float p_random = psys_frand(psys, 77091 + 283 * p); | 
					
						
							| 
									
										
										
										
											2018-04-18 12:04:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 		/* skip particle? */ | 
					
						
							|  |  |  | 		if (particle_skip(pimd, psys, p)) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* set vertices coordinates */ | 
					
						
							|  |  |  | 		for (k = 0; k < totvert; k++) { | 
					
						
							|  |  |  | 			ParticleKey state; | 
					
						
							|  |  |  | 			MVert *inMV; | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 			int vindex = p_skip * totvert + k; | 
					
						
							|  |  |  | 			MVert *mv = mvert + vindex; | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			inMV = orig_mvert + k; | 
					
						
							| 
									
										
										
										
											2018-05-17 13:45:47 +02:00
										 |  |  | 			CustomData_copy_data(&mesh->vdata, &result->vdata, k, p_skip * totvert + k, 1); | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 			*mv = *inMV; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 			if (vert_part_index != NULL) { | 
					
						
							|  |  |  | 				vert_part_index[vindex] = p; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (vert_part_value != NULL) { | 
					
						
							|  |  |  | 				vert_part_value[vindex] = p_random; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 			/*change orientation based on object trackflag*/ | 
					
						
							|  |  |  | 			copy_v3_v3(temp_co, mv->co); | 
					
						
							|  |  |  | 			mv->co[axis] = temp_co[track]; | 
					
						
							|  |  |  | 			mv->co[(axis + 1) % 3] = temp_co[(track + 1) % 3]; | 
					
						
							|  |  |  | 			mv->co[(axis + 2) % 3] = temp_co[(track + 2) % 3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* get particle state */ | 
					
						
							|  |  |  | 			if ((psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) && | 
					
						
							|  |  |  | 			    (pimd->flag & eParticleInstanceFlag_Path)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				float ran = 0.0f; | 
					
						
							|  |  |  | 				if (pimd->random_position != 0.0f) { | 
					
						
							|  |  |  | 					ran = pimd->random_position * BLI_hash_frand(psys->seed + p); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if (pimd->flag & eParticleInstanceFlag_KeepShape) { | 
					
						
							|  |  |  | 					state.time = pimd->position * (1.0f - ran); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else { | 
					
						
							|  |  |  | 					state.time = (mv->co[axis] - min_co) / (max_co - min_co) * pimd->position * (1.0f - ran); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					if (trackneg) | 
					
						
							|  |  |  | 						state.time = 1.0f - state.time; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					mv->co[axis] = 0.0; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 				psys_get_particle_on_path(&sim, p, &state, 1); | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				normalize_v3(state.vel); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				/* Incrementally Rotating Frame (Bishop Frame) */ | 
					
						
							|  |  |  | 				if (k == 0) { | 
					
						
							|  |  |  | 					float hairmat[4][4]; | 
					
						
							|  |  |  | 					float mat[3][3]; | 
					
						
							| 
									
										
										
										
											2018-04-18 12:04:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 					if (p < psys->totpart) | 
					
						
							|  |  |  | 						pa = psys->particles + p; | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 					else { | 
					
						
							|  |  |  | 						ChildParticle *cpa = psys->child + (p - psys->totpart); | 
					
						
							| 
									
										
										
										
											2018-06-06 22:17:06 +02:00
										 |  |  | 						pa = psys->particles + (between ? cpa->pa[0] : cpa->parent); | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2018-05-15 13:26:40 +02:00
										 |  |  | 					psys_mat_hair_to_global(sim.ob, sim.psmd->mesh_final, sim.psys->part->from, pa, hairmat); | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 					copy_m3_m4(mat, hairmat); | 
					
						
							|  |  |  | 					/* to quaternion */ | 
					
						
							|  |  |  | 					mat3_to_quat(frame, mat); | 
					
						
							| 
									
										
										
										
											2018-04-18 12:04:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 					if (pimd->rotation > 0.0f || pimd->random_rotation > 0.0f) { | 
					
						
							| 
									
										
										
										
											2018-06-06 22:17:06 +02:00
										 |  |  | 						float angle = 2.0f * M_PI * (pimd->rotation + pimd->random_rotation * (psys_frand(psys, 19957323 + p) - 0.5f)); | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 						float eul[3] = { 0.0f, 0.0f, angle }; | 
					
						
							|  |  |  | 						float rot[4]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						eul_to_quat(rot, eul); | 
					
						
							|  |  |  | 						mul_qt_qtqt(frame, frame, rot); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 					/* note: direction is same as normal vector currently,
 | 
					
						
							|  |  |  | 					 * but best to keep this separate so the frame can be | 
					
						
							|  |  |  | 					 * rotated later if necessary | 
					
						
							|  |  |  | 					 */ | 
					
						
							|  |  |  | 					copy_v3_v3(prev_dir, state.vel); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else { | 
					
						
							|  |  |  | 					float rot[4]; | 
					
						
							| 
									
										
										
										
											2018-04-18 12:04:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 					/* incrementally rotate along bend direction */ | 
					
						
							|  |  |  | 					rotation_between_vecs_to_quat(rot, prev_dir, state.vel); | 
					
						
							|  |  |  | 					mul_qt_qtqt(frame, rot, frame); | 
					
						
							| 
									
										
										
										
											2018-04-18 12:04:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 					copy_v3_v3(prev_dir, state.vel); | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2018-04-18 12:04:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 				copy_qt_qt(state.rot, frame); | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  | 				/* Absolute Frame (Frenet Frame) */ | 
					
						
							|  |  |  | 				if (state.vel[axis] < -0.9999f || state.vel[axis] > 0.9999f) { | 
					
						
							|  |  |  | 					unit_qt(state.rot); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else { | 
					
						
							|  |  |  | 					float cross[3]; | 
					
						
							|  |  |  | 					float temp[3] = {0.0f, 0.0f, 0.0f}; | 
					
						
							|  |  |  | 					temp[axis] = 1.0f; | 
					
						
							| 
									
										
										
										
											2018-04-18 12:04:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 					cross_v3_v3v3(cross, temp, state.vel); | 
					
						
							| 
									
										
										
										
											2018-04-18 12:04:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 					/* state.vel[axis] is the only component surviving from a dot product with the axis */ | 
					
						
							|  |  |  | 					axis_angle_to_quat(state.rot, cross, saacos(state.vel[axis])); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				state.time = -1.0; | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 				psys_get_particle_state(&sim, p, &state, 1); | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			mul_qt_v3(state.rot, mv->co); | 
					
						
							|  |  |  | 			if (pimd->flag & eParticleInstanceFlag_UseSize) | 
					
						
							|  |  |  | 				mul_v3_fl(mv->co, size[p]); | 
					
						
							|  |  |  | 			add_v3_v3(mv->co, state.co); | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			mul_m4_v3(spacemat, mv->co); | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-04 09:20:57 +02:00
										 |  |  | 		/* create edges and adjust edge vertex indices*/ | 
					
						
							| 
									
										
										
										
											2018-05-17 13:45:47 +02:00
										 |  |  | 		CustomData_copy_data(&mesh->edata, &result->edata, 0, p_skip * totedge, totedge); | 
					
						
							|  |  |  | 		MEdge *me = &result->medge[p_skip * totedge]; | 
					
						
							| 
									
										
										
										
											2018-05-04 09:20:57 +02:00
										 |  |  | 		for (k = 0; k < totedge; k++, me++) { | 
					
						
							|  |  |  | 			me->v1 += p_skip * totvert; | 
					
						
							|  |  |  | 			me->v2 += p_skip * totvert; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 		/* create polys and loops */ | 
					
						
							|  |  |  | 		for (k = 0; k < totpoly; k++) { | 
					
						
							| 
									
										
										
										
											2018-05-04 09:20:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 			MPoly *inMP = orig_mpoly + k; | 
					
						
							|  |  |  | 			MPoly *mp = mpoly + p_skip * totpoly + k; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-17 13:45:47 +02:00
										 |  |  | 			CustomData_copy_data(&mesh->pdata, &result->pdata, k, p_skip * totpoly + k, 1); | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 			*mp = *inMP; | 
					
						
							|  |  |  | 			mp->loopstart += p_skip * totloop; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				MLoop *inML = orig_mloop + inMP->loopstart; | 
					
						
							|  |  |  | 				MLoop *ml = mloop + mp->loopstart; | 
					
						
							|  |  |  | 				int j = mp->totloop; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-17 13:45:47 +02:00
										 |  |  | 				CustomData_copy_data(&mesh->ldata, &result->ldata, inMP->loopstart, mp->loopstart, j); | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 				for (; j; j--, ml++, inML++) { | 
					
						
							|  |  |  | 					ml->v = inML->v + (p_skip * totvert); | 
					
						
							| 
									
										
										
										
											2018-05-04 09:20:57 +02:00
										 |  |  | 					ml->e = inML->e + (p_skip * totedge); | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 					const int ml_index = (ml - mloop); | 
					
						
							|  |  |  | 					if (mloopcols_index != NULL) { | 
					
						
							|  |  |  | 						const int part_index = vert_part_index[ml->v]; | 
					
						
							| 
									
										
										
										
											2018-12-08 15:01:47 +11:00
										 |  |  | 						store_float_in_vcol(&mloopcols_index[ml_index], (float)part_index / (float)(psys->totpart - 1)); | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 					} | 
					
						
							|  |  |  | 					if (mloopcols_value != NULL) { | 
					
						
							|  |  |  | 						const float part_value = vert_part_value[ml->v]; | 
					
						
							|  |  |  | 						store_float_in_vcol(&mloopcols_value[ml_index], part_value); | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		p_skip++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (psys->lattice_deform_data) { | 
					
						
							|  |  |  | 		end_latt_deform(psys->lattice_deform_data); | 
					
						
							|  |  |  | 		psys->lattice_deform_data = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (size) | 
					
						
							|  |  |  | 		MEM_freeN(size); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 	MEM_SAFE_FREE(vert_part_index); | 
					
						
							|  |  |  | 	MEM_SAFE_FREE(vert_part_value); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-17 13:45:47 +02:00
										 |  |  | 	result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ModifierTypeInfo modifierType_ParticleInstance = { | 
					
						
							|  |  |  | 	/* name */              "ParticleInstance", | 
					
						
							|  |  |  | 	/* structName */        "ParticleInstanceModifierData", | 
					
						
							|  |  |  | 	/* structSize */        sizeof(ParticleInstanceModifierData), | 
					
						
							|  |  |  | 	/* type */              eModifierTypeType_Constructive, | 
					
						
							|  |  |  | 	/* flags */             eModifierTypeFlag_AcceptsMesh | | 
					
						
							|  |  |  | 	                        eModifierTypeFlag_SupportsMapping | | 
					
						
							|  |  |  | 	                        eModifierTypeFlag_SupportsEditmode | | 
					
						
							|  |  |  | 	                        eModifierTypeFlag_EnableInEditmode, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-08 15:04:10 +02:00
										 |  |  | 	/* copyData */          modifier_copyData_generic, | 
					
						
							| 
									
										
										
										
											2018-04-18 15:45:54 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* deformVerts_DM */    NULL, | 
					
						
							|  |  |  | 	/* deformMatrices_DM */ NULL, | 
					
						
							|  |  |  | 	/* deformVertsEM_DM */  NULL, | 
					
						
							|  |  |  | 	/* deformMatricesEM_DM*/NULL, | 
					
						
							| 
									
										
										
										
											2018-05-17 13:45:47 +02:00
										 |  |  | 	/* applyModifier_DM */  NULL, | 
					
						
							| 
									
										
										
										
											2018-04-18 15:45:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 	/* deformVerts */       NULL, | 
					
						
							|  |  |  | 	/* deformMatrices */    NULL, | 
					
						
							|  |  |  | 	/* deformVertsEM */     NULL, | 
					
						
							|  |  |  | 	/* deformMatricesEM */  NULL, | 
					
						
							| 
									
										
										
										
											2018-05-17 13:45:47 +02:00
										 |  |  | 	/* applyModifier */     applyModifier, | 
					
						
							| 
									
										
										
										
											2018-04-18 15:45:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 	/* initData */          initData, | 
					
						
							| 
									
										
										
										
											2018-04-18 12:14:28 +02:00
										 |  |  | 	/* requiredDataMask */  requiredDataMask, | 
					
						
							| 
									
										
										
										
											2016-12-28 17:30:58 +01:00
										 |  |  | 	/* freeData */          NULL, | 
					
						
							|  |  |  | 	/* isDisabled */        isDisabled, | 
					
						
							|  |  |  | 	/* updateDepsgraph */   updateDepsgraph, | 
					
						
							|  |  |  | 	/* dependsOnTime */     NULL, | 
					
						
							|  |  |  | 	/* dependsOnNormals */  NULL, | 
					
						
							|  |  |  | 	/* foreachObjectLink */ foreachObjectLink, | 
					
						
							|  |  |  | 	/* foreachIDLink */     NULL, | 
					
						
							|  |  |  | 	/* foreachTexLink */    NULL, | 
					
						
							|  |  |  | }; |