| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2011-10-23 17:52:20 +00: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) 2005 by the Blender Foundation. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Contributor(s): Daniel Dunbar | 
					
						
							|  |  |  |  *                 Ton Roosendaal, | 
					
						
							|  |  |  |  *                 Ben Batt, | 
					
						
							|  |  |  |  *                 Brecht Van Lommel, | 
					
						
							|  |  |  |  *                 Campbell Barton | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ***** END GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-29 04:04:27 +00:00
										 |  |  | /** \file blender/modifiers/intern/MOD_array.c
 | 
					
						
							|  |  |  |  *  \ingroup modifiers | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-12 22:33:43 +00:00
										 |  |  | /* Array modifier: duplicates the object multiple times along an axis */ | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-16 05:46:10 +00:00
										 |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-29 04:04:27 +00:00
										 |  |  | #include "BLI_math.h"
 | 
					
						
							| 
									
										
										
										
											2011-05-09 04:06:48 +00:00
										 |  |  | #include "BLI_utildefines.h"
 | 
					
						
							| 
									
										
										
										
											2011-11-16 19:06:38 +00:00
										 |  |  | #include "BLI_string.h"
 | 
					
						
							| 
									
										
										
										
											2010-04-12 22:33:43 +00:00
										 |  |  | #include "BLI_ghash.h"
 | 
					
						
							|  |  |  | #include "BLI_edgehash.h"
 | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-16 05:46:10 +00:00
										 |  |  | #include "DNA_curve_types.h"
 | 
					
						
							|  |  |  | #include "DNA_meshdata_types.h"
 | 
					
						
							|  |  |  | #include "DNA_object_types.h"
 | 
					
						
							| 
									
										
										
										
											2012-02-11 10:15:11 +00:00
										 |  |  | #include "DNA_scene_types.h"
 | 
					
						
							| 
									
										
										
										
											2010-08-16 05:46:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | #include "BKE_cdderivedmesh.h"
 | 
					
						
							|  |  |  | #include "BKE_displist.h"
 | 
					
						
							|  |  |  | #include "BKE_mesh.h"
 | 
					
						
							|  |  |  | #include "BKE_modifier.h"
 | 
					
						
							|  |  |  | #include "BKE_object.h"
 | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | #include "BKE_tessmesh.h"
 | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "depsgraph_private.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-27 06:19:40 +00:00
										 |  |  | #include <ctype.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							| 
									
										
										
										
											2011-02-13 14:16:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | static void initData(ModifierData *md) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	ArrayModifierData *amd = (ArrayModifierData *) md; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* default to 2 duplicates distributed along the x-axis by an
 | 
					
						
							| 
									
										
										
										
											2012-03-09 18:28:30 +00:00
										 |  |  | 	 * offset of 1 object-width | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	amd->start_cap = amd->end_cap = amd->curve_ob = amd->offset_ob = NULL; | 
					
						
							|  |  |  | 	amd->count = 2; | 
					
						
							| 
									
										
										
										
											2012-03-23 20:18:09 +00:00
										 |  |  | 	zero_v3(amd->offset); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	amd->scale[0] = 1; | 
					
						
							|  |  |  | 	amd->scale[1] = amd->scale[2] = 0; | 
					
						
							|  |  |  | 	amd->length = 0; | 
					
						
							|  |  |  | 	amd->merge_dist = 0.01; | 
					
						
							|  |  |  | 	amd->fit_type = MOD_ARR_FIXEDCOUNT; | 
					
						
							|  |  |  | 	amd->offset_type = MOD_ARR_OFF_RELATIVE; | 
					
						
							|  |  |  | 	amd->flags = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void copyData(ModifierData *md, ModifierData *target) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	ArrayModifierData *amd = (ArrayModifierData *) md; | 
					
						
							|  |  |  | 	ArrayModifierData *tamd = (ArrayModifierData *) target; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	tamd->start_cap = amd->start_cap; | 
					
						
							|  |  |  | 	tamd->end_cap = amd->end_cap; | 
					
						
							|  |  |  | 	tamd->curve_ob = amd->curve_ob; | 
					
						
							|  |  |  | 	tamd->offset_ob = amd->offset_ob; | 
					
						
							|  |  |  | 	tamd->count = amd->count; | 
					
						
							| 
									
										
										
										
											2010-04-12 00:36:50 +00:00
										 |  |  | 	copy_v3_v3(tamd->offset, amd->offset); | 
					
						
							|  |  |  | 	copy_v3_v3(tamd->scale, amd->scale); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	tamd->length = amd->length; | 
					
						
							|  |  |  | 	tamd->merge_dist = amd->merge_dist; | 
					
						
							|  |  |  | 	tamd->fit_type = amd->fit_type; | 
					
						
							|  |  |  | 	tamd->offset_type = amd->offset_type; | 
					
						
							|  |  |  | 	tamd->flags = amd->flags; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void foreachObjectLink( | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  |         ModifierData *md, Object *ob, | 
					
						
							|  |  |  |         void (*walk)(void *userData, Object *ob, Object **obpoin), | 
					
						
							|  |  |  |         void *userData) | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	ArrayModifierData *amd = (ArrayModifierData *) md; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	walk(userData, ob, &amd->start_cap); | 
					
						
							|  |  |  | 	walk(userData, ob, &amd->end_cap); | 
					
						
							|  |  |  | 	walk(userData, ob, &amd->curve_ob); | 
					
						
							|  |  |  | 	walk(userData, ob, &amd->offset_ob); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-29 04:04:27 +00:00
										 |  |  | static void updateDepgraph(ModifierData *md, DagForest *forest, | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  |                            struct Scene *UNUSED(scene), Object *UNUSED(ob), DagNode *obNode) | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	ArrayModifierData *amd = (ArrayModifierData *) md; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (amd->start_cap) { | 
					
						
							|  |  |  | 		DagNode *curNode = dag_get_node(forest, amd->start_cap); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		dag_add_relation(forest, curNode, obNode, | 
					
						
							| 
									
										
										
										
											2011-11-11 13:09:14 +00:00
										 |  |  | 		                 DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier"); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if (amd->end_cap) { | 
					
						
							|  |  |  | 		DagNode *curNode = dag_get_node(forest, amd->end_cap); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		dag_add_relation(forest, curNode, obNode, | 
					
						
							| 
									
										
										
										
											2011-11-11 13:09:14 +00:00
										 |  |  | 		                 DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier"); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if (amd->curve_ob) { | 
					
						
							|  |  |  | 		DagNode *curNode = dag_get_node(forest, amd->curve_ob); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		dag_add_relation(forest, curNode, obNode, | 
					
						
							| 
									
										
										
										
											2011-11-11 13:09:14 +00:00
										 |  |  | 		                 DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier"); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if (amd->offset_ob) { | 
					
						
							|  |  |  | 		DagNode *curNode = dag_get_node(forest, amd->offset_ob); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		dag_add_relation(forest, curNode, obNode, | 
					
						
							| 
									
										
										
										
											2011-11-11 13:09:14 +00:00
										 |  |  | 		                 DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier"); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static float vertarray_size(MVert *mvert, int numVerts, int axis) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	float min_co, max_co; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* if there are no vertices, width is 0 */ | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 	if (numVerts == 0) return 0; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* find the minimum and maximum coordinates on the desired axis */ | 
					
						
							|  |  |  | 	min_co = max_co = mvert->co[axis]; | 
					
						
							| 
									
										
										
										
											2012-05-09 09:24:15 +00:00
										 |  |  | 	mvert++; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 	for (i = 1; i < numVerts; ++i, ++mvert) { | 
					
						
							|  |  |  | 		if (mvert->co[axis] < min_co) min_co = mvert->co[axis]; | 
					
						
							|  |  |  | 		if (mvert->co[axis] > max_co) max_co = mvert->co[axis]; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return max_co - min_co; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-28 22:03:46 +00:00
										 |  |  | static int *find_doubles_index_map(BMesh *bm, BMOperator *dupe_op, | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  |                                    const ArrayModifierData *amd, | 
					
						
							|  |  |  |                                    int *index_map_length) | 
					
						
							| 
									
										
										
										
											2012-03-28 22:03:46 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	BMOperator find_op; | 
					
						
							|  |  |  | 	BMOIter oiter; | 
					
						
							|  |  |  | 	BMVert *v, *v2; | 
					
						
							|  |  |  | 	BMElem *ele; | 
					
						
							|  |  |  | 	int *index_map, i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BMO_op_initf(bm, &find_op, | 
					
						
							| 
									
										
										
										
											2012-06-30 15:27:13 +00:00
										 |  |  | 	             "find_doubles verts=%av dist=%f keep_verts=%s", | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	             amd->merge_dist, dupe_op, "geom"); | 
					
						
							| 
									
										
										
										
											2012-03-28 22:03:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	BMO_op_exec(bm, &find_op); | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 	i = 0; | 
					
						
							| 
									
										
										
										
											2012-04-19 11:44:12 +00:00
										 |  |  | 	BMO_ITER (ele, &oiter, bm, dupe_op, "geom", BM_ALL) { | 
					
						
							| 
									
										
										
										
											2012-03-28 22:03:46 +00:00
										 |  |  | 		BM_elem_index_set(ele, i); /* set_dirty */ | 
					
						
							|  |  |  | 		i++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-19 11:44:12 +00:00
										 |  |  | 	BMO_ITER (ele, &oiter, bm, dupe_op, "newout", BM_ALL) { | 
					
						
							| 
									
										
										
										
											2012-03-28 22:03:46 +00:00
										 |  |  | 		BM_elem_index_set(ele, i); /* set_dirty */ | 
					
						
							|  |  |  | 		i++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/* above loops over all, so set all to dirty, if this is somehow
 | 
					
						
							|  |  |  | 	 * setting valid values, this line can be remvoed - campbell */ | 
					
						
							|  |  |  | 	bm->elem_index_dirty |= BM_VERT | BM_EDGE | BM_FACE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	(*index_map_length) = i; | 
					
						
							|  |  |  | 	index_map = MEM_callocN(sizeof(int) * (*index_map_length), "index_map"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*element type argument doesn't do anything here*/ | 
					
						
							| 
									
										
										
										
											2012-04-19 11:44:12 +00:00
										 |  |  | 	BMO_ITER (v, &oiter, bm, &find_op, "targetmapout", 0) { | 
					
						
							| 
									
										
										
										
											2012-03-28 22:03:46 +00:00
										 |  |  | 		v2 = BMO_iter_map_value_p(&oiter); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		index_map[BM_elem_index_get(v)] = BM_elem_index_get(v2) + 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BMO_op_finish(bm, &find_op); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return index_map; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-30 17:30:56 +00:00
										 |  |  | /* Used for start/end cap.
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * this function expects all existing vertices to be tagged, | 
					
						
							|  |  |  |  * so we can know new verts are not tagged. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * All verts will be tagged on exit. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | static void bm_merge_dm_transform(BMesh *bm, DerivedMesh *dm, float mat[4][4], | 
					
						
							|  |  |  |                                   const ArrayModifierData *amd, | 
					
						
							|  |  |  |                                   BMOperator *dupe_op, | 
					
						
							|  |  |  |                                   const char *dupe_slot_name, | 
					
						
							|  |  |  |                                   BMOperator *weld_op) | 
					
						
							| 
									
										
										
										
											2012-03-30 17:30:56 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-06-11 09:41:08 +00:00
										 |  |  | 	BMVert *v, *v2, *v3; | 
					
						
							| 
									
										
										
										
											2012-03-30 17:30:56 +00:00
										 |  |  | 	BMIter iter; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-11 09:41:08 +00:00
										 |  |  | 	/* Add the DerivedMesh's elements to the BMesh. The pre-existing
 | 
					
						
							|  |  |  | 	   elements were already tagged, so the new elements can be | 
					
						
							|  |  |  | 	   identified by not having the BM_ELEM_TAG flag set. */ | 
					
						
							| 
									
										
										
										
											2012-03-30 17:30:56 +00:00
										 |  |  | 	DM_to_bmesh_ex(dm, bm); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (amd->flags & MOD_ARR_MERGE) { | 
					
						
							|  |  |  | 		/* if merging is enabled, find doubles */ | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		BMOIter oiter; | 
					
						
							|  |  |  | 		BMOperator find_op; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		BMO_op_initf(bm, &find_op, | 
					
						
							| 
									
										
										
										
											2012-06-30 15:27:13 +00:00
										 |  |  | 		             "find_doubles verts=%Hv dist=%f keep_verts=%s", | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 		             BM_ELEM_TAG, amd->merge_dist, | 
					
						
							|  |  |  | 		             dupe_op, dupe_slot_name); | 
					
						
							| 
									
										
										
										
											2012-03-30 17:30:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* append the dupe's geom to the findop input verts */ | 
					
						
							|  |  |  | 		BMO_slot_buffer_append(&find_op, "verts", dupe_op, dupe_slot_name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* transform and tag verts */ | 
					
						
							| 
									
										
										
										
											2012-04-19 13:47:58 +00:00
										 |  |  | 		BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { | 
					
						
							| 
									
										
										
										
											2012-03-30 17:30:56 +00:00
										 |  |  | 			if (!BM_elem_flag_test(v, BM_ELEM_TAG)) { | 
					
						
							|  |  |  | 				mul_m4_v3(mat, v->co); | 
					
						
							|  |  |  | 				BM_elem_flag_enable(v, BM_ELEM_TAG); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		BMO_op_exec(bm, &find_op); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* add new merge targets to weld operator */ | 
					
						
							| 
									
										
										
										
											2012-04-19 11:44:12 +00:00
										 |  |  | 		BMO_ITER (v, &oiter, bm, &find_op, "targetmapout", 0) { | 
					
						
							| 
									
										
										
										
											2012-03-30 17:30:56 +00:00
										 |  |  | 			v2 = BMO_iter_map_value_p(&oiter); | 
					
						
							| 
									
										
										
										
											2012-06-11 09:41:08 +00:00
										 |  |  | 			/* check in case the target vertex (v2) is already marked
 | 
					
						
							|  |  |  | 			 * for merging */ | 
					
						
							|  |  |  | 			while ((v3 = BMO_slot_map_ptr_get(bm, weld_op, "targetmap", v2))) { | 
					
						
							|  |  |  | 				v2 = v3; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-03-30 17:30:56 +00:00
										 |  |  | 			BMO_slot_map_ptr_insert(bm, weld_op, "targetmap", v, v2); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		BMO_op_finish(bm, &find_op); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		/* transform and tag verts */ | 
					
						
							| 
									
										
										
										
											2012-04-19 13:47:58 +00:00
										 |  |  | 		BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { | 
					
						
							| 
									
										
										
										
											2012-03-30 17:30:56 +00:00
										 |  |  | 			if (!BM_elem_flag_test(v, BM_ELEM_TAG)) { | 
					
						
							|  |  |  | 				mul_m4_v3(mat, v->co); | 
					
						
							|  |  |  | 				BM_elem_flag_enable(v, BM_ELEM_TAG); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | static void merge_first_last(BMesh *bm, | 
					
						
							|  |  |  |                              const ArrayModifierData *amd, | 
					
						
							|  |  |  |                              BMOperator *dupe_first, | 
					
						
							|  |  |  |                              BMOperator *dupe_last, | 
					
						
							|  |  |  |                              BMOperator *weld_op) | 
					
						
							| 
									
										
										
										
											2012-03-30 17:30:56 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	BMOperator find_op; | 
					
						
							|  |  |  | 	BMOIter oiter; | 
					
						
							|  |  |  | 	BMVert *v, *v2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BMO_op_initf(bm, &find_op, | 
					
						
							| 
									
										
										
										
											2012-06-30 15:27:13 +00:00
										 |  |  | 	             "find_doubles verts=%s dist=%f keep_verts=%s", | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	             dupe_first, "geom", amd->merge_dist, | 
					
						
							|  |  |  | 	             dupe_first, "geom"); | 
					
						
							| 
									
										
										
										
											2012-03-30 17:30:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* append the last dupe's geom to the findop input verts */ | 
					
						
							|  |  |  | 	BMO_slot_buffer_append(&find_op, "verts", dupe_last, "newout"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BMO_op_exec(bm, &find_op); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* add new merge targets to weld operator */ | 
					
						
							| 
									
										
										
										
											2012-04-19 11:44:12 +00:00
										 |  |  | 	BMO_ITER (v, &oiter, bm, &find_op, "targetmapout", 0) { | 
					
						
							| 
									
										
										
										
											2012-03-30 17:30:56 +00:00
										 |  |  | 		v2 = BMO_iter_map_value_p(&oiter); | 
					
						
							|  |  |  | 		BMO_slot_map_ptr_insert(bm, weld_op, "targetmap", v, v2); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BMO_op_finish(bm, &find_op); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-03-28 22:03:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, | 
					
						
							| 
									
										
										
										
											2012-03-11 19:58:56 +00:00
										 |  |  |                                           Scene *scene, Object *ob, DerivedMesh *dm, | 
					
						
							|  |  |  |                                           int UNUSED(initFlags)) | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-02-12 15:02:33 +00:00
										 |  |  | 	DerivedMesh *result; | 
					
						
							| 
									
										
										
										
											2012-03-11 19:58:56 +00:00
										 |  |  | 	BMEditMesh *em = DM_to_editbmesh(dm, NULL, FALSE); | 
					
						
							| 
									
										
										
										
											2012-03-30 17:30:56 +00:00
										 |  |  | 	BMOperator first_dupe_op, dupe_op, old_dupe_op, weld_op; | 
					
						
							| 
									
										
										
										
											2012-03-29 20:58:25 +00:00
										 |  |  | 	BMVert **first_geom = NULL; | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 	int i, j, indexLen; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	/* offset matrix */ | 
					
						
							|  |  |  | 	float offset[4][4]; | 
					
						
							| 
									
										
										
										
											2012-02-13 08:06:44 +00:00
										 |  |  | 	float final_offset[4][4]; | 
					
						
							|  |  |  | 	float tmp_mat[4][4]; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	float length = amd->length; | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 	int count = amd->count, maxVerts; | 
					
						
							|  |  |  | 	int *indexMap = NULL; | 
					
						
							|  |  |  | 	DerivedMesh *start_cap = NULL, *end_cap = NULL; | 
					
						
							|  |  |  | 	MVert *src_mvert; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* need to avoid infinite recursion here */ | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 	if (amd->start_cap && amd->start_cap != ob) | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 		start_cap = mesh_get_derived_final(scene, amd->start_cap, CD_MASK_MESH); | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 	if (amd->end_cap && amd->end_cap != ob) | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 		end_cap = mesh_get_derived_final(scene, amd->end_cap, CD_MASK_MESH); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	unit_m4(offset); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-12 15:02:33 +00:00
										 |  |  | 	src_mvert = dm->getVertArray(dm); | 
					
						
							|  |  |  | 	maxVerts = dm->getNumVerts(dm); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 	if (amd->offset_type & MOD_ARR_OFF_CONST) | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 		add_v3_v3v3(offset[3], offset[3], amd->offset); | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 	if (amd->offset_type & MOD_ARR_OFF_RELATIVE) { | 
					
						
							|  |  |  | 		for (j = 0; j < 3; j++) | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 			offset[3][j] += amd->scale[j] * vertarray_size(src_mvert, maxVerts, j); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 	if ((amd->offset_type & MOD_ARR_OFF_OBJ) && (amd->offset_ob)) { | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 		float obinv[4][4]; | 
					
						
							|  |  |  | 		float result_mat[4][4]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 		if (ob) | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 			invert_m4_m4(obinv, ob->obmat); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			unit_m4(obinv); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		mul_serie_m4(result_mat, offset, | 
					
						
							| 
									
										
										
										
											2011-11-11 13:09:14 +00:00
										 |  |  | 		             obinv, amd->offset_ob->obmat, | 
					
						
							|  |  |  | 		             NULL, NULL, NULL, NULL, NULL); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 		copy_m4_m4(offset, result_mat); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 	if (amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob) { | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 		Curve *cu = amd->curve_ob->data; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 		if (cu) { | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 			float tmp_mat[3][3]; | 
					
						
							|  |  |  | 			float scale; | 
					
						
							| 
									
										
										
										
											2011-12-29 04:04:27 +00:00
										 |  |  | 			 | 
					
						
							| 
									
										
										
										
											2012-05-05 14:03:12 +00:00
										 |  |  | 			BKE_object_to_mat3(amd->curve_ob, tmp_mat); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 			scale = mat3_to_scale(tmp_mat); | 
					
						
							| 
									
										
										
										
											2011-12-29 04:04:27 +00:00
										 |  |  | 				 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 			if (!cu->path) { | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 				cu->flag |= CU_PATH; // needed for path & bevlist
 | 
					
						
							| 
									
										
										
										
											2012-05-07 06:58:03 +00:00
										 |  |  | 				BKE_displist_make_curveTypes(scene, amd->curve_ob, 0); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 			if (cu->path) | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 				length = scale * cu->path->totdist; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* calculate the maximum number of copies which will fit within the
 | 
					
						
							| 
									
										
										
										
											2012-03-09 18:28:30 +00:00
										 |  |  | 	 * prescribed length */ | 
					
						
							| 
									
										
										
										
											2012-04-21 15:11:03 +00:00
										 |  |  | 	if (amd->fit_type == MOD_ARR_FITLENGTH || amd->fit_type == MOD_ARR_FITCURVE) { | 
					
						
							| 
									
										
										
										
											2011-12-29 04:04:27 +00:00
										 |  |  | 		float dist = sqrt(dot_v3v3(offset[3], offset[3])); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 		if (dist > 1e-6f) | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 			/* this gives length = first copy start to last copy end
 | 
					
						
							| 
									
										
										
										
											2012-03-09 18:28:30 +00:00
										 |  |  | 			 * add a tiny offset for floating point rounding errors */ | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 			count = (length + 1e-6f) / dist; | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			/* if the offset has no translation, just make one copy */ | 
					
						
							|  |  |  | 			count = 1; | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 	if (count < 1) | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 		count = 1; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 19:50:45 +00:00
										 |  |  | 	/* calculate the offset matrix of the final copy (for merging) */ | 
					
						
							|  |  |  | 	unit_m4(final_offset); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	for (j = 0; j < count - 1; j++) { | 
					
						
							| 
									
										
										
										
											2012-03-26 19:50:45 +00:00
										 |  |  | 		mult_m4_m4m4(tmp_mat, offset, final_offset); | 
					
						
							|  |  |  | 		copy_m4_m4(final_offset, tmp_mat); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-27 17:39:15 +00:00
										 |  |  | 	/* BMESH_TODO: bumping up the stack level avoids computing the normals
 | 
					
						
							| 
									
										
										
										
											2012-03-09 18:28:30 +00:00
										 |  |  | 	 * after every top-level operator execution (and this modifier has the | 
					
						
							|  |  |  | 	 * potential to execute a *lot* of top-level BMOps. There should be a | 
					
						
							|  |  |  | 	 * cleaner way to do this. One possibility: a "mirror" BMOp would | 
					
						
							|  |  |  | 	 * certainly help by compressing it all into one top-level BMOp that | 
					
						
							|  |  |  | 	 * executes a lot of second-level BMOps. */ | 
					
						
							| 
									
										
										
										
											2011-10-27 17:39:15 +00:00
										 |  |  | 	BMO_push(em->bm, NULL); | 
					
						
							| 
									
										
										
										
											2012-02-27 14:07:19 +00:00
										 |  |  | 	bmesh_edit_begin(em->bm, 0); | 
					
						
							| 
									
										
										
										
											2011-10-27 17:39:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-29 11:31:44 +00:00
										 |  |  | 	if (amd->flags & MOD_ARR_MERGE) | 
					
						
							| 
									
										
										
										
											2012-06-30 15:27:13 +00:00
										 |  |  | 		BMO_op_init(em->bm, &weld_op, "weld_verts"); | 
					
						
							| 
									
										
										
										
											2012-03-30 17:30:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	BMO_op_initf(em->bm, &dupe_op, "dupe geom=%avef"); | 
					
						
							|  |  |  | 	first_dupe_op = dupe_op; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	for (j = 0; j < count - 1; j++) { | 
					
						
							| 
									
										
										
										
											2012-03-28 22:03:46 +00:00
										 |  |  | 		BMVert *v, *v2, *v3; | 
					
						
							| 
									
										
										
										
											2012-03-29 20:58:25 +00:00
										 |  |  | 		BMOpSlot *geom_slot; | 
					
						
							|  |  |  | 		BMOpSlot *newout_slot; | 
					
						
							| 
									
										
										
										
											2012-03-31 12:29:41 +00:00
										 |  |  | 		BMOIter oiter; | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-30 17:30:56 +00:00
										 |  |  | 		if (j != 0) | 
					
						
							| 
									
										
										
										
											2012-03-29 11:31:44 +00:00
										 |  |  | 			BMO_op_initf(em->bm, &dupe_op, "dupe geom=%s", &old_dupe_op, "newout"); | 
					
						
							| 
									
										
										
										
											2012-03-28 22:03:46 +00:00
										 |  |  | 		BMO_op_exec(em->bm, &dupe_op); | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-29 20:58:25 +00:00
										 |  |  | 		geom_slot = BMO_slot_get(&dupe_op, "geom"); | 
					
						
							|  |  |  | 		newout_slot = BMO_slot_get(&dupe_op, "newout"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if ((amd->flags & MOD_ARR_MERGEFINAL) && j == 0) { | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 			int first_geom_bytes = sizeof(BMVert *) * geom_slot->len; | 
					
						
							| 
									
										
										
										
											2012-03-29 20:58:25 +00:00
										 |  |  | 				 | 
					
						
							|  |  |  | 			/* make a copy of the initial geometry ordering so the
 | 
					
						
							| 
									
										
										
										
											2012-04-22 11:54:53 +00:00
										 |  |  | 			 * last duplicate can be merged into it */ | 
					
						
							| 
									
										
										
										
											2012-03-29 20:58:25 +00:00
										 |  |  | 			first_geom = MEM_mallocN(first_geom_bytes, "first_geom"); | 
					
						
							|  |  |  | 			memcpy(first_geom, geom_slot->data.buf, first_geom_bytes); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-31 12:29:41 +00:00
										 |  |  | 		/* apply transformation matrix */ | 
					
						
							| 
									
										
										
										
											2012-04-19 11:44:12 +00:00
										 |  |  | 		BMO_ITER (v, &oiter, em->bm, &dupe_op, "newout", BM_VERT) { | 
					
						
							| 
									
										
										
										
											2012-03-31 12:29:41 +00:00
										 |  |  | 			mul_m4_v3(offset, v->co); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-29 11:31:44 +00:00
										 |  |  | 		if (amd->flags & MOD_ARR_MERGE) { | 
					
						
							|  |  |  | 			/*calculate merge mapping*/ | 
					
						
							|  |  |  | 			if (j == 0) { | 
					
						
							|  |  |  | 				indexMap = find_doubles_index_map(em->bm, &dupe_op, | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 				                                  amd, &indexLen); | 
					
						
							| 
									
										
										
										
											2012-03-29 11:31:44 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-29 11:31:44 +00:00
										 |  |  | 			#define _E(s, i) ((BMVert **)(s)->data.buf)[i]
 | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 			for (i = 0; i < indexLen; i++) { | 
					
						
							| 
									
										
										
										
											2012-03-29 11:31:44 +00:00
										 |  |  | 				if (!indexMap[i]) continue; | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-29 20:58:25 +00:00
										 |  |  | 				/* merge v (from 'newout') into v2 (from old 'geom') */ | 
					
						
							|  |  |  | 				v = _E(newout_slot, i - geom_slot->len); | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 				v2 = _E(geom_slot, indexMap[i] - 1); | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-29 11:31:44 +00:00
										 |  |  | 				/* check in case the target vertex (v2) is already marked
 | 
					
						
							| 
									
										
										
										
											2012-04-21 12:51:47 +00:00
										 |  |  | 				 * for merging */ | 
					
						
							|  |  |  | 				while ((v3 = BMO_slot_map_ptr_get(em->bm, &weld_op, "targetmap", v2))) { | 
					
						
							| 
									
										
										
										
											2012-03-29 11:31:44 +00:00
										 |  |  | 					v2 = v3; | 
					
						
							| 
									
										
										
										
											2012-04-21 12:51:47 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2012-03-28 22:03:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-29 11:31:44 +00:00
										 |  |  | 				BMO_slot_map_ptr_insert(em->bm, &weld_op, "targetmap", v, v2); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-29 11:31:44 +00:00
										 |  |  | 			#undef _E
 | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-30 17:30:56 +00:00
										 |  |  | 		/* already copied earlier, but after executation more slot
 | 
					
						
							| 
									
										
										
										
											2012-04-22 11:54:53 +00:00
										 |  |  | 		 * memory may be allocated */ | 
					
						
							| 
									
										
										
										
											2012-03-30 17:30:56 +00:00
										 |  |  | 		if (j == 0) | 
					
						
							|  |  |  | 			first_dupe_op = dupe_op; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if (j >= 2) | 
					
						
							| 
									
										
										
										
											2012-03-29 11:31:44 +00:00
										 |  |  | 			BMO_op_finish(em->bm, &old_dupe_op); | 
					
						
							| 
									
										
										
										
											2012-03-28 22:03:46 +00:00
										 |  |  | 		old_dupe_op = dupe_op; | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-30 17:30:56 +00:00
										 |  |  | 	if ((amd->flags & MOD_ARR_MERGE) && | 
					
						
							| 
									
										
										
										
											2012-04-02 04:45:44 +00:00
										 |  |  | 	    (amd->flags & MOD_ARR_MERGEFINAL) && | 
					
						
							|  |  |  | 	    (count > 1)) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2012-03-30 17:30:56 +00:00
										 |  |  | 		/* Merge first and last copies. Note that we can't use the
 | 
					
						
							| 
									
										
										
										
											2012-04-02 04:45:44 +00:00
										 |  |  | 		 * indexMap for this because (unless the array is forming a | 
					
						
							|  |  |  | 		 * loop) the offset between first and last is different from | 
					
						
							|  |  |  | 		 * dupe X to dupe X+1. */ | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-30 17:30:56 +00:00
										 |  |  | 		merge_first_last(em->bm, amd, &first_dupe_op, &dupe_op, &weld_op); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-02-13 08:06:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* start capping */ | 
					
						
							| 
									
										
										
										
											2012-04-02 04:45:44 +00:00
										 |  |  | 	if (start_cap || end_cap) { | 
					
						
							| 
									
										
										
										
											2012-04-13 04:02:26 +00:00
										 |  |  | 		BM_mesh_elem_hflag_enable_all(em->bm, BM_VERT, BM_ELEM_TAG, FALSE); | 
					
						
							| 
									
										
										
										
											2012-02-13 08:06:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (start_cap) { | 
					
						
							|  |  |  | 			float startoffset[4][4]; | 
					
						
							|  |  |  | 			invert_m4_m4(startoffset, offset); | 
					
						
							| 
									
										
										
										
											2012-03-30 17:30:56 +00:00
										 |  |  | 			bm_merge_dm_transform(em->bm, start_cap, startoffset, amd, | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 			                      &first_dupe_op, "geom", &weld_op); | 
					
						
							| 
									
										
										
										
											2012-02-13 08:06:44 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (end_cap) { | 
					
						
							|  |  |  | 			float endoffset[4][4]; | 
					
						
							|  |  |  | 			mult_m4_m4m4(endoffset, offset, final_offset); | 
					
						
							| 
									
										
										
										
											2012-03-30 17:30:56 +00:00
										 |  |  | 			bm_merge_dm_transform(em->bm, end_cap, endoffset, amd, | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 			                      &dupe_op, count == 1 ? "geom" : "newout", &weld_op); | 
					
						
							| 
									
										
										
										
											2012-02-13 08:06:44 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/* done capping */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-30 17:30:56 +00:00
										 |  |  | 	/* free remaining dupe operators */ | 
					
						
							|  |  |  | 	BMO_op_finish(em->bm, &first_dupe_op); | 
					
						
							|  |  |  | 	if (count > 2) | 
					
						
							|  |  |  | 		BMO_op_finish(em->bm, &dupe_op); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* run merge operator */ | 
					
						
							| 
									
										
										
										
											2012-03-29 11:31:44 +00:00
										 |  |  | 	if (amd->flags & MOD_ARR_MERGE) { | 
					
						
							| 
									
										
										
										
											2012-03-28 22:03:46 +00:00
										 |  |  | 		BMO_op_exec(em->bm, &weld_op); | 
					
						
							| 
									
										
										
										
											2012-03-29 11:31:44 +00:00
										 |  |  | 		BMO_op_finish(em->bm, &weld_op); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-27 17:39:15 +00:00
										 |  |  | 	/* Bump the stack level back down to match the adjustment up above */ | 
					
						
							|  |  |  | 	BMO_pop(em->bm); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-22 21:12:18 +00:00
										 |  |  | 	BLI_assert(em->looptris == NULL); | 
					
						
							| 
									
										
										
										
											2012-02-12 15:02:33 +00:00
										 |  |  | 	result = CDDM_from_BMEditMesh(em, NULL, FALSE, FALSE); | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-27 13:08:40 +00:00
										 |  |  | 	if ((amd->offset_type & MOD_ARR_OFF_OBJ) && (amd->offset_ob)) { | 
					
						
							|  |  |  | 		/* Update normals in case offset object has rotation. */ | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		/* BMESH_TODO: check if normal recalc needed under any other
 | 
					
						
							| 
									
										
										
										
											2012-04-22 11:54:53 +00:00
										 |  |  | 		 * conditions? */ | 
					
						
							| 
									
										
										
										
											2012-03-27 13:08:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		CDDM_calc_normals(result); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 	BMEdit_Free(em); | 
					
						
							| 
									
										
										
										
											2011-09-12 02:44:17 +00:00
										 |  |  | 	MEM_freeN(em); | 
					
						
							| 
									
										
										
										
											2012-03-26 19:44:25 +00:00
										 |  |  | 	if (indexMap) | 
					
						
							|  |  |  | 		MEM_freeN(indexMap); | 
					
						
							| 
									
										
										
										
											2012-03-29 20:58:25 +00:00
										 |  |  | 	if (first_geom) | 
					
						
							|  |  |  | 		MEM_freeN(first_geom); | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-12 15:02:33 +00:00
										 |  |  | 	return result; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-29 04:04:27 +00:00
										 |  |  | static DerivedMesh *applyModifier(ModifierData *md, Object *ob, | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  |                                   DerivedMesh *dm, | 
					
						
							| 
									
										
										
										
											2012-05-09 15:00:26 +00:00
										 |  |  |                                   ModifierApplyFlag UNUSED(flag)) | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	DerivedMesh *result; | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	ArrayModifierData *amd = (ArrayModifierData *) md; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-29 04:04:27 +00:00
										 |  |  | 	result = arrayModifier_doArray(amd, md->scene, ob, dm, 0); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-21 12:51:47 +00:00
										 |  |  | 	//if (result != dm)
 | 
					
						
							| 
									
										
										
										
											2012-01-06 00:12:24 +00:00
										 |  |  | 	//	CDDM_calc_normals_mapping(result);
 | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-29 04:04:27 +00:00
										 |  |  | static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob, | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  |                                     struct BMEditMesh *UNUSED(editData), | 
					
						
							|  |  |  |                                     DerivedMesh *dm) | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-09 15:00:26 +00:00
										 |  |  | 	return applyModifier(md, ob, dm, MOD_APPLY_USECACHE); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ModifierTypeInfo modifierType_Array = { | 
					
						
							|  |  |  | 	/* name */              "Array", | 
					
						
							|  |  |  | 	/* structName */        "ArrayModifierData", | 
					
						
							|  |  |  | 	/* structSize */        sizeof(ArrayModifierData), | 
					
						
							|  |  |  | 	/* type */              eModifierTypeType_Constructive, | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	/* flags */             eModifierTypeFlag_AcceptsMesh | | 
					
						
							|  |  |  | 	                        eModifierTypeFlag_SupportsMapping | | 
					
						
							|  |  |  | 	                        eModifierTypeFlag_SupportsEditmode | | 
					
						
							|  |  |  | 	                        eModifierTypeFlag_EnableInEditmode | | 
					
						
							|  |  |  | 	                        eModifierTypeFlag_AcceptsCVs, | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* copyData */          copyData, | 
					
						
							| 
									
										
										
										
											2011-03-05 10:29:10 +00:00
										 |  |  | 	/* deformVerts */       NULL, | 
					
						
							|  |  |  | 	/* deformMatrices */    NULL, | 
					
						
							|  |  |  | 	/* deformVertsEM */     NULL, | 
					
						
							|  |  |  | 	/* deformMatricesEM */  NULL, | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	/* applyModifier */     applyModifier, | 
					
						
							|  |  |  | 	/* applyModifierEM */   applyModifierEM, | 
					
						
							|  |  |  | 	/* initData */          initData, | 
					
						
							| 
									
										
										
										
											2011-03-05 10:29:10 +00:00
										 |  |  | 	/* requiredDataMask */  NULL, | 
					
						
							|  |  |  | 	/* freeData */          NULL, | 
					
						
							|  |  |  | 	/* isDisabled */        NULL, | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	/* updateDepgraph */    updateDepgraph, | 
					
						
							| 
									
										
										
										
											2011-03-05 10:29:10 +00:00
										 |  |  | 	/* dependsOnTime */     NULL, | 
					
						
							|  |  |  | 	/* dependsOnNormals */	NULL, | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	/* foreachObjectLink */ foreachObjectLink, | 
					
						
							| 
									
										
										
										
											2011-03-05 10:29:10 +00:00
										 |  |  | 	/* foreachIDLink */     NULL, | 
					
						
							| 
									
										
										
										
											2011-08-12 18:11:22 +00:00
										 |  |  | 	/* foreachTexLink */    NULL, | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | }; |