| 
									
										
										
										
											2011-02-23 10:52:22 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +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, | 
					
						
							| 
									
										
										
										
											2010-02-12 13:34:04 +00:00
										 |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) 2004 by Blender Foundation | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is: all of this file. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Contributor(s): none yet. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ***** END GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-27 20:29:51 +00:00
										 |  |  | /** \file blender/editors/mesh/meshtools.c
 | 
					
						
							|  |  |  |  *  \ingroup edmesh | 
					
						
							| 
									
										
										
										
											2012-12-19 04:49:32 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * meshtools.c: no editmode (violated already :), mirror & join), | 
					
						
							|  |  |  |  * tools operating on meshes | 
					
						
							| 
									
										
										
										
											2011-02-27 20:29:51 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-19 22:17:30 +00:00
										 |  |  | #include "DNA_mesh_types.h"
 | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | #include "DNA_key_types.h"
 | 
					
						
							|  |  |  | #include "DNA_material_types.h"
 | 
					
						
							| 
									
										
										
										
											2012-06-24 20:18:32 +00:00
										 |  |  | #include "DNA_modifier_types.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | #include "DNA_object_types.h"
 | 
					
						
							|  |  |  | #include "DNA_scene_types.h"
 | 
					
						
							| 
									
										
										
										
											2012-12-23 02:04:38 +00:00
										 |  |  | #include "DNA_screen_types.h"
 | 
					
						
							|  |  |  | #include "DNA_view3d_types.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | #include "BLI_math.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | #include "BLI_blenlib.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-13 01:36:24 +11:00
										 |  |  | #include "BLI_kdtree.h"
 | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | #include "BKE_context.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | #include "BKE_depsgraph.h"
 | 
					
						
							| 
									
										
										
										
											2010-08-22 14:15:28 +00:00
										 |  |  | #include "BKE_deform.h"
 | 
					
						
							| 
									
										
										
										
											2009-11-28 04:04:01 +00:00
										 |  |  | #include "BKE_DerivedMesh.h"
 | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | #include "BKE_key.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | #include "BKE_library.h"
 | 
					
						
							|  |  |  | #include "BKE_main.h"
 | 
					
						
							|  |  |  | #include "BKE_mesh.h"
 | 
					
						
							|  |  |  | #include "BKE_material.h"
 | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | #include "BKE_report.h"
 | 
					
						
							| 
									
										
										
										
											2013-04-13 20:31:52 +00:00
										 |  |  | #include "BKE_editmesh.h"
 | 
					
						
							| 
									
										
										
										
											2010-10-25 08:03:05 +00:00
										 |  |  | #include "BKE_multires.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "ED_mesh.h"
 | 
					
						
							|  |  |  | #include "ED_object.h"
 | 
					
						
							| 
									
										
										
										
											2009-01-05 15:19:31 +00:00
										 |  |  | #include "ED_view3d.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | #include "WM_api.h"
 | 
					
						
							|  |  |  | #include "WM_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | /* * ********************** no editmode!!! *********** */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | /*********************** JOIN ***************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | /* join selected meshes into the active mesh, context sensitive
 | 
					
						
							| 
									
										
										
										
											2012-03-03 16:31:46 +00:00
										 |  |  |  * return 0 if no join is made (error) and 1 if the join is done */ | 
					
						
							| 
									
										
										
										
											2009-07-11 10:20:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | int join_mesh_exec(bContext *C, wmOperator *op) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	Main *bmain = CTX_data_main(C); | 
					
						
							|  |  |  | 	Scene *scene = CTX_data_scene(C); | 
					
						
							|  |  |  | 	Object *ob = CTX_data_active_object(C); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	Material **matar, *ma; | 
					
						
							|  |  |  | 	Mesh *me; | 
					
						
							| 
									
										
										
										
											2011-01-13 04:53:55 +00:00
										 |  |  | 	MVert *mvert, *mv; | 
					
						
							|  |  |  | 	MEdge *medge = NULL; | 
					
						
							| 
									
										
										
										
											2011-02-27 06:19:40 +00:00
										 |  |  | 	MPoly *mpoly = NULL; | 
					
						
							|  |  |  | 	MLoop *mloop = NULL; | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	Key *key, *nkey = NULL; | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 	KeyBlock *kb, *okb, *kbn; | 
					
						
							| 
									
										
										
										
											2012-09-18 14:29:01 +00:00
										 |  |  | 	float imat[4][4], cmat[4][4], *fp1, *fp2; | 
					
						
							| 
									
										
										
										
											2013-07-10 09:55:10 +00:00
										 |  |  | 	int a, b, totcol, totmat = 0, totedge = 0, totvert = 0; | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	int totloop = 0, totpoly = 0, vertofs, *matmap = NULL; | 
					
						
							|  |  |  | 	int i, j, index, haskey = 0, edgeofs, loopofs, polyofs; | 
					
						
							| 
									
										
										
										
											2013-07-10 09:55:10 +00:00
										 |  |  | 	bool ok = false; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	bDeformGroup *dg, *odg; | 
					
						
							|  |  |  | 	MDeformVert *dvert; | 
					
						
							| 
									
										
										
										
											2009-07-16 06:27:37 +00:00
										 |  |  | 	CustomData vdata, edata, fdata, ldata, pdata; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 	if (scene->obedit) { | 
					
						
							| 
									
										
										
										
											2012-10-26 17:32:50 +00:00
										 |  |  | 		BKE_report(op->reports, RPT_WARNING, "Cannot join while in edit mode"); | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 		return OPERATOR_CANCELLED; | 
					
						
							| 
									
										
										
										
											2010-11-10 01:40:24 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 	/* ob is the object we are adding geometry to */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	if (!ob || ob->type != OB_MESH) { | 
					
						
							| 
									
										
										
										
											2010-12-21 15:10:09 +00:00
										 |  |  | 		BKE_report(op->reports, RPT_WARNING, "Active object is not a mesh"); | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 		return OPERATOR_CANCELLED; | 
					
						
							| 
									
										
										
										
											2010-11-10 01:40:24 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* count & check */ | 
					
						
							| 
									
										
										
										
											2012-04-30 16:22:40 +00:00
										 |  |  | 	CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		if (base->object->type == OB_MESH) { | 
					
						
							|  |  |  | 			me = base->object->data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			totvert += me->totvert; | 
					
						
							|  |  |  | 			totedge += me->totedge; | 
					
						
							|  |  |  | 			totloop += me->totloop; | 
					
						
							|  |  |  | 			totpoly += me->totpoly; | 
					
						
							|  |  |  | 			totmat += base->object->totcol; | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 			 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 			if (base->object == ob) | 
					
						
							| 
									
										
										
										
											2013-07-10 09:55:10 +00:00
										 |  |  | 				ok = true; | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 			 | 
					
						
							|  |  |  | 			/* check for shapekeys */ | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 			if (me->key) | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 				haskey++; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 	CTX_DATA_END; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* that way the active object is always selected */  | 
					
						
							| 
									
										
										
										
											2013-07-10 09:55:10 +00:00
										 |  |  | 	if (ok == false) { | 
					
						
							| 
									
										
										
										
											2010-12-21 15:10:09 +00:00
										 |  |  | 		BKE_report(op->reports, RPT_WARNING, "Active object is not a selected mesh"); | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 		return OPERATOR_CANCELLED; | 
					
						
							| 
									
										
										
										
											2010-11-10 01:40:24 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 	/* only join meshes if there are verts to join, there aren't too many, and we only had one mesh selected */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	me = (Mesh *)ob->data; | 
					
						
							|  |  |  | 	key = me->key; | 
					
						
							| 
									
										
										
										
											2010-11-10 01:40:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	if (totvert == 0 || totvert == me->totvert) { | 
					
						
							| 
									
										
										
										
											2010-12-21 15:10:09 +00:00
										 |  |  | 		BKE_report(op->reports, RPT_WARNING, "No mesh data to join"); | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 		return OPERATOR_CANCELLED; | 
					
						
							| 
									
										
										
										
											2010-11-10 01:40:24 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 	if (totvert > MESH_MAX_VERTS) { | 
					
						
							| 
									
										
										
										
											2012-10-18 16:25:58 +00:00
										 |  |  | 		BKE_reportf(op->reports, RPT_WARNING, "Joining results in %d vertices, limit is %ld", totvert, MESH_MAX_VERTS); | 
					
						
							|  |  |  | 		return OPERATOR_CANCELLED; | 
					
						
							| 
									
										
										
										
											2010-11-10 01:40:24 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-27 05:38:48 +00:00
										 |  |  | 	/* remove tessface to ensure we don't hold references to invalid faces */ | 
					
						
							| 
									
										
										
										
											2012-10-25 08:48:05 +00:00
										 |  |  | 	BKE_mesh_tessface_clear(me); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	/* new material indices and material array */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	matar = MEM_callocN(sizeof(void *) * totmat, "join_mesh matar"); | 
					
						
							|  |  |  | 	if (totmat) matmap = MEM_callocN(sizeof(int) * totmat, "join_mesh matmap"); | 
					
						
							|  |  |  | 	totcol = ob->totcol; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* obact materials in new main array, is nicer start! */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	for (a = 0; a < ob->totcol; a++) { | 
					
						
							|  |  |  | 		matar[a] = give_current_material(ob, a + 1); | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 		id_us_plus((ID *)matar[a]); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		/* increase id->us : will be lowered later */ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 	/* - if destination mesh had shapekeys, move them somewhere safe, and set up placeholders
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	 *  with arrays that are large enough to hold shapekey data for all meshes | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 	 * -	if destination mesh didn't have shapekeys, but we encountered some in the meshes we're  | 
					
						
							|  |  |  | 	 *	joining, set up a new keyblock and assign to the mesh | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 	if (key) { | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 		/* make a duplicate copy that will only be used here... (must remember to free it!) */ | 
					
						
							| 
									
										
										
										
											2012-05-05 14:03:12 +00:00
										 |  |  | 		nkey = BKE_key_copy(key); | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 		 | 
					
						
							|  |  |  | 		/* for all keys in old block, clear data-arrays */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		for (kb = key->block.first; kb; kb = kb->next) { | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 			if (kb->data) MEM_freeN(kb->data); | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 			kb->data = MEM_callocN(sizeof(float) * 3 * totvert, "join_shapekey"); | 
					
						
							|  |  |  | 			kb->totelem = totvert; | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 	else if (haskey) { | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 		/* add a new key-block and add to the mesh */ | 
					
						
							| 
									
										
										
										
											2012-09-19 10:12:07 +00:00
										 |  |  | 		key = me->key = BKE_key_add((ID *)me); | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 		key->type = KEY_RELATIVE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* first pass over objects - copying materials and vertexgroups across */ | 
					
						
							| 
									
										
										
										
											2012-04-30 16:22:40 +00:00
										 |  |  | 	CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 		/* only act if a mesh, and not the one we're joining to */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		if ((ob != base->object) && (base->object->type == OB_MESH)) { | 
					
						
							|  |  |  | 			me = base->object->data; | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 			 | 
					
						
							|  |  |  | 			/* Join this object's vertex groups to the base one's */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 			for (dg = base->object->defbase.first; dg; dg = dg->next) { | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 				/* See if this group exists in the object (if it doesn't, add it to the end) */ | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 				if (!defgroup_find_name(ob, dg->name)) { | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 					odg = MEM_callocN(sizeof(bDeformGroup), "join deformGroup"); | 
					
						
							|  |  |  | 					memcpy(odg, dg, sizeof(bDeformGroup)); | 
					
						
							|  |  |  | 					BLI_addtail(&ob->defbase, odg); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 			if (ob->defbase.first && ob->actdef == 0) | 
					
						
							|  |  |  | 				ob->actdef = 1; | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 			 | 
					
						
							|  |  |  | 			 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 			if (me->totvert) { | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 				/* Add this object's materials to the base one's if they don't exist already (but only if limits not exceeded yet) */ | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 				if (totcol < MAXMAT) { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 					for (a = 1; a <= base->object->totcol; a++) { | 
					
						
							|  |  |  | 						ma = give_current_material(base->object, a); | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 						for (b = 0; b < totcol; b++) { | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 							if (ma == matar[b]) break; | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 						if (b == totcol) { | 
					
						
							|  |  |  | 							matar[b] = ma; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 							if (ma) { | 
					
						
							| 
									
										
										
										
											2011-04-26 07:17:21 +00:00
										 |  |  | 								id_us_plus(&ma->id); | 
					
						
							|  |  |  | 							} | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 							totcol++; | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 						if (totcol >= MAXMAT) | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 							break; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				/* if this mesh has shapekeys, check if destination mesh already has matching entries too */ | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 				if (me->key && key) { | 
					
						
							| 
									
										
										
										
											2012-09-19 12:11:28 +00:00
										 |  |  | 					/* for remapping KeyBlock.relative */ | 
					
						
							|  |  |  | 					int      *index_map = MEM_mallocN(sizeof(int)        * me->key->totkey, __func__); | 
					
						
							|  |  |  | 					KeyBlock **kb_map   = MEM_mallocN(sizeof(KeyBlock *) * me->key->totkey, __func__); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					for (kb = me->key->block.first, i = 0; kb; kb = kb->next, i++) { | 
					
						
							|  |  |  | 						BLI_assert(i < me->key->totkey); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						kbn = BKE_keyblock_find_name(key, kb->name); | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 						/* if key doesn't exist in destination mesh, add it */ | 
					
						
							| 
									
										
										
										
											2012-09-19 12:11:28 +00:00
										 |  |  | 						if (kbn) { | 
					
						
							|  |  |  | 							index_map[i] = BLI_findindex(&key->block, kbn); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						else { | 
					
						
							|  |  |  | 							index_map[i] = key->totkey; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-19 10:12:07 +00:00
										 |  |  | 							kbn = BKE_keyblock_add(key, kb->name); | 
					
						
							| 
									
										
										
										
											2012-09-19 12:11:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 							BKE_keyblock_copy_settings(kbn, kb); | 
					
						
							| 
									
										
										
										
											2012-09-18 14:29:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-12 11:50:43 +00:00
										 |  |  | 							/* adjust settings to fit (allocate a new data-array) */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 							kbn->data = MEM_callocN(sizeof(float) * 3 * totvert, "joined_shapekey"); | 
					
						
							| 
									
										
										
										
											2012-10-21 05:46:41 +00:00
										 |  |  | 							kbn->totelem = totvert; | 
					
						
							| 
									
										
										
										
											2012-09-18 14:29:01 +00:00
										 |  |  | 		 | 
					
						
							| 
									
										
										
										
											2012-07-07 22:51:57 +00:00
										 |  |  | 							/* XXX 2.5 Animato */ | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | #if 0
 | 
					
						
							|  |  |  | 							/* also, copy corresponding ipo-curve to ipo-block if applicable */ | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 							if (me->key->ipo && key->ipo) { | 
					
						
							| 
									
										
										
										
											2012-07-07 22:51:57 +00:00
										 |  |  | 								/* FIXME... this is a luxury item! */ | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 								puts("FIXME: ignoring IPO's when joining shapekeys on Meshes for now..."); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 							} | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2012-09-19 12:11:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 						kb_map[i] = kbn; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					/* remap relative index values */ | 
					
						
							|  |  |  | 					for (kb = me->key->block.first, i = 0; kb; kb = kb->next, i++) { | 
					
						
							|  |  |  | 						if (LIKELY(kb->relative < me->key->totkey)) {  /* sanity check, should always be true */ | 
					
						
							|  |  |  | 							kb_map[i]->relative = index_map[kb->relative]; | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2012-09-19 12:11:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					MEM_freeN(index_map); | 
					
						
							|  |  |  | 					MEM_freeN(kb_map); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 	CTX_DATA_END; | 
					
						
							| 
									
										
										
										
											2012-09-19 12:11:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 	/* setup new data for destination mesh */ | 
					
						
							| 
									
										
										
										
											2012-10-31 09:50:24 +00:00
										 |  |  | 	CustomData_reset(&vdata); | 
					
						
							|  |  |  | 	CustomData_reset(&edata); | 
					
						
							|  |  |  | 	CustomData_reset(&fdata); | 
					
						
							|  |  |  | 	CustomData_reset(&ldata); | 
					
						
							|  |  |  | 	CustomData_reset(&pdata); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	mvert = CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert); | 
					
						
							|  |  |  | 	medge = CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge); | 
					
						
							|  |  |  | 	mloop = CustomData_add_layer(&ldata, CD_MLOOP, CD_CALLOC, NULL, totloop); | 
					
						
							|  |  |  | 	mpoly = CustomData_add_layer(&pdata, CD_MPOLY, CD_CALLOC, NULL, totpoly); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vertofs = 0; | 
					
						
							|  |  |  | 	edgeofs = 0; | 
					
						
							|  |  |  | 	loopofs = 0; | 
					
						
							|  |  |  | 	polyofs = 0; | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* inverse transform for all selected meshes in this object */ | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 	invert_m4_m4(imat, ob->obmat); | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2012-04-30 16:22:40 +00:00
										 |  |  | 	CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 		/* only join if this is a mesh */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		if (base->object->type == OB_MESH) { | 
					
						
							|  |  |  | 			me = base->object->data; | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 			 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 			if (me->totvert) { | 
					
						
							| 
									
										
										
										
											2013-02-27 05:38:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				/* merge customdata flag */ | 
					
						
							|  |  |  | 				((Mesh *)ob->data)->cd_flag |= me->cd_flag; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 				/* standard data */ | 
					
						
							|  |  |  | 				CustomData_merge(&me->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert); | 
					
						
							| 
									
										
										
										
											2013-09-21 05:42:34 +00:00
										 |  |  | 				CustomData_copy_data_named(&me->vdata, &vdata, 0, vertofs, me->totvert); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 				 | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 				/* vertex groups */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 				dvert = CustomData_get(&vdata, vertofs, CD_MDEFORMVERT); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 				 | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 				/* NB: vertex groups here are new version */ | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 				if (dvert) { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 					for (i = 0; i < me->totvert; i++) { | 
					
						
							|  |  |  | 						for (j = 0; j < dvert[i].totweight; j++) { | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 							/*	Find the old vertex group */ | 
					
						
							|  |  |  | 							odg = BLI_findlink(&base->object->defbase, dvert[i].dw[j].def_nr); | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 							if (odg) { | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 								/*	Search for a match in the new object, and set new index */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 								for (dg = ob->defbase.first, index = 0; dg; dg = dg->next, index++) { | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 									if (!strcmp(dg->name, odg->name)) { | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 										dvert[i].dw[j].def_nr = index; | 
					
						
							|  |  |  | 										break; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 									} | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				 | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 				/* if this is the object we're merging into, no need to do anything */ | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 				if (base->object != ob) { | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 					/* watch this: switch matmul order really goes wrong */ | 
					
						
							| 
									
										
										
										
											2013-05-26 18:36:25 +00:00
										 |  |  | 					mul_m4_m4m4(cmat, imat, base->object->obmat); | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 					 | 
					
						
							|  |  |  | 					/* transform vertex coordinates into new space */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 					for (a = 0, mv = mvert; a < me->totvert; a++, mv++) { | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 						mul_m4_v3(cmat, mv->co); | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 					} | 
					
						
							|  |  |  | 					 | 
					
						
							|  |  |  | 					/* for each shapekey in destination mesh:
 | 
					
						
							|  |  |  | 					 *	- if there's a matching one, copy it across (will need to transform vertices into new space...) | 
					
						
							|  |  |  | 					 *	- otherwise, just copy own coordinates of mesh (no need to transform vertex coordinates into new space) | 
					
						
							|  |  |  | 					 */ | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 					if (key) { | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 						/* if this mesh has any shapekeys, check first, otherwise just copy coordinates */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 						for (kb = key->block.first; kb; kb = kb->next) { | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 							/* get pointer to where to write data for this mesh in shapekey's data array */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 							fp1 = ((float *)kb->data) + (vertofs * 3); | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 							 | 
					
						
							|  |  |  | 							/* check if this mesh has such a shapekey */ | 
					
						
							| 
									
										
										
										
											2012-09-19 12:11:28 +00:00
										 |  |  | 							okb = me->key ? BKE_keyblock_find_name(me->key, kb->name) : NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 							if (okb) { | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 								/* copy this mesh's shapekey to the destination shapekey (need to transform first) */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 								fp2 = ((float *)(okb->data)); | 
					
						
							|  |  |  | 								for (a = 0; a < me->totvert; a++, fp1 += 3, fp2 += 3) { | 
					
						
							| 
									
										
										
										
											2012-03-09 06:04:17 +00:00
										 |  |  | 									copy_v3_v3(fp1, fp2); | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 									mul_m4_v3(cmat, fp1); | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							else { | 
					
						
							|  |  |  | 								/* copy this mesh's vertex coordinates to the destination shapekey */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 								mv = mvert; | 
					
						
							|  |  |  | 								for (a = 0; a < me->totvert; a++, fp1 += 3, mv++) { | 
					
						
							| 
									
										
										
										
											2012-03-09 06:04:17 +00:00
										 |  |  | 									copy_v3_v3(fp1, mv->co); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 				else { | 
					
						
							|  |  |  | 					/* for each shapekey in destination mesh:
 | 
					
						
							|  |  |  | 					 *	- if it was an 'original', copy the appropriate data from nkey | 
					
						
							|  |  |  | 					 *	- otherwise, copy across plain coordinates (no need to transform coordinates) | 
					
						
							|  |  |  | 					 */ | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 					if (key) { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 						for (kb = key->block.first; kb; kb = kb->next) { | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 							/* get pointer to where to write data for this mesh in shapekey's data array */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 							fp1 = ((float *)kb->data) + (vertofs * 3); | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 							 | 
					
						
							|  |  |  | 							/* check if this was one of the original shapekeys */ | 
					
						
							| 
									
										
										
										
											2012-09-23 23:30:01 +00:00
										 |  |  | 							okb = nkey ? BKE_keyblock_find_name(nkey, kb->name) : NULL; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 							if (okb) { | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 								/* copy this mesh's shapekey to the destination shapekey */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 								fp2 = ((float *)(okb->data)); | 
					
						
							|  |  |  | 								for (a = 0; a < me->totvert; a++, fp1 += 3, fp2 += 3) { | 
					
						
							| 
									
										
										
										
											2012-03-09 06:04:17 +00:00
										 |  |  | 									copy_v3_v3(fp1, fp2); | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							else { | 
					
						
							|  |  |  | 								/* copy base-coordinates to the destination shapekey */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 								mv = mvert; | 
					
						
							|  |  |  | 								for (a = 0; a < me->totvert; a++, fp1 += 3, mv++) { | 
					
						
							| 
									
										
										
										
											2012-03-09 06:04:17 +00:00
										 |  |  | 									copy_v3_v3(fp1, mv->co); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				 | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 				/* advance mvert pointer to end of base mesh's data */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 				mvert += me->totvert; | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 			if (me->totedge) { | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 				CustomData_merge(&me->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge); | 
					
						
							| 
									
										
										
										
											2013-09-21 05:42:34 +00:00
										 |  |  | 				CustomData_copy_data_named(&me->edata, &edata, 0, edgeofs, me->totedge); | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 				 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 				for (a = 0; a < me->totedge; a++, medge++) { | 
					
						
							|  |  |  | 					medge->v1 += vertofs; | 
					
						
							|  |  |  | 					medge->v2 += vertofs; | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-16 06:27:37 +00:00
										 |  |  | 			if (me->totloop) { | 
					
						
							| 
									
										
										
										
											2012-06-24 20:18:32 +00:00
										 |  |  | 				if (base->object != ob) { | 
					
						
							|  |  |  | 					MultiresModifierData *mmd; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-31 00:52:12 +00:00
										 |  |  | 					multiresModifier_prepare_join(scene, base->object, ob); | 
					
						
							| 
									
										
										
										
											2012-06-24 20:18:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-19 23:17:44 +00:00
										 |  |  | 					if ((mmd = get_multires_modifier(scene, base->object, true))) { | 
					
						
							|  |  |  | 						ED_object_iter_other(bmain, base->object, true, | 
					
						
							| 
									
										
										
										
											2012-09-19 12:11:28 +00:00
										 |  |  | 						                     ED_object_multires_update_totlevels_cb, | 
					
						
							|  |  |  | 						                     &mmd->totlvl); | 
					
						
							| 
									
										
										
										
											2012-06-24 20:18:32 +00:00
										 |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2011-03-31 00:52:12 +00:00
										 |  |  | 				 | 
					
						
							| 
									
										
										
										
											2009-07-16 06:27:37 +00:00
										 |  |  | 				CustomData_merge(&me->ldata, &ldata, CD_MASK_MESH, CD_DEFAULT, totloop); | 
					
						
							| 
									
										
										
										
											2013-09-21 05:42:34 +00:00
										 |  |  | 				CustomData_copy_data_named(&me->ldata, &ldata, 0, loopofs, me->totloop); | 
					
						
							| 
									
										
										
										
											2009-07-16 06:27:37 +00:00
										 |  |  | 				 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 				for (a = 0; a < me->totloop; a++, mloop++) { | 
					
						
							| 
									
										
										
										
											2009-07-16 06:27:37 +00:00
										 |  |  | 					mloop->v += vertofs; | 
					
						
							|  |  |  | 					mloop->e += edgeofs; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 			 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 			if (me->totpoly) { | 
					
						
							| 
									
										
										
										
											2012-09-14 06:17:14 +00:00
										 |  |  | 				if (totmat) { | 
					
						
							|  |  |  | 					/* make mapping for materials */ | 
					
						
							|  |  |  | 					for (a = 1; a <= base->object->totcol; a++) { | 
					
						
							|  |  |  | 						ma = give_current_material(base->object, a); | 
					
						
							| 
									
										
										
										
											2009-07-16 06:27:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-14 06:17:14 +00:00
										 |  |  | 						for (b = 0; b < totcol; b++) { | 
					
						
							|  |  |  | 							if (ma == matar[b]) { | 
					
						
							|  |  |  | 								matmap[a - 1] = b; | 
					
						
							|  |  |  | 								break; | 
					
						
							|  |  |  | 							} | 
					
						
							| 
									
										
										
										
											2009-07-16 06:27:37 +00:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2012-09-14 06:17:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-16 06:27:37 +00:00
										 |  |  | 				CustomData_merge(&me->pdata, &pdata, CD_MASK_MESH, CD_DEFAULT, totpoly); | 
					
						
							| 
									
										
										
										
											2013-09-21 05:42:34 +00:00
										 |  |  | 				CustomData_copy_data_named(&me->pdata, &pdata, 0, polyofs, me->totpoly); | 
					
						
							| 
									
										
										
										
											2009-07-16 06:27:37 +00:00
										 |  |  | 				 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 				for (a = 0; a < me->totpoly; a++, mpoly++) { | 
					
						
							| 
									
										
										
										
											2009-07-16 06:27:37 +00:00
										 |  |  | 					mpoly->loopstart += loopofs; | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 					mpoly->mat_nr = matmap ? matmap[(int)mpoly->mat_nr] : 0; | 
					
						
							| 
									
										
										
										
											2009-07-16 06:27:37 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 				 | 
					
						
							| 
									
										
										
										
											2011-02-23 00:01:50 +00:00
										 |  |  | 				polyofs += me->totpoly; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-07-16 06:27:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-23 00:01:50 +00:00
										 |  |  | 			/* these are used for relinking (cannot be set earlier, 
 | 
					
						
							|  |  |  | 			 * or else reattaching goes wrong) | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 			 */ | 
					
						
							|  |  |  | 			vertofs += me->totvert; | 
					
						
							| 
									
										
										
										
											2011-02-23 00:01:50 +00:00
										 |  |  | 			edgeofs += me->totedge; | 
					
						
							|  |  |  | 			loopofs += me->totloop; | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 			 | 
					
						
							|  |  |  | 			/* free base, now that data is merged */ | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 			if (base->object != ob) | 
					
						
							| 
									
										
										
										
											2010-08-01 12:47:49 +00:00
										 |  |  | 				ED_base_object_free_and_unlink(bmain, scene, base); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 	CTX_DATA_END; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 	/* return to mesh we're merging to */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	me = ob->data; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	CustomData_free(&me->vdata, me->totvert); | 
					
						
							|  |  |  | 	CustomData_free(&me->edata, me->totedge); | 
					
						
							| 
									
										
										
										
											2009-07-16 06:27:37 +00:00
										 |  |  | 	CustomData_free(&me->ldata, me->totloop); | 
					
						
							|  |  |  | 	CustomData_free(&me->pdata, me->totpoly); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	me->totvert = totvert; | 
					
						
							|  |  |  | 	me->totedge = totedge; | 
					
						
							|  |  |  | 	me->totloop = totloop; | 
					
						
							|  |  |  | 	me->totpoly = totpoly; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	me->vdata = vdata; | 
					
						
							|  |  |  | 	me->edata = edata; | 
					
						
							|  |  |  | 	me->ldata = ldata; | 
					
						
							|  |  |  | 	me->pdata = pdata; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-25 08:48:05 +00:00
										 |  |  | 	/* tessface data removed above, no need to update */ | 
					
						
							| 
									
										
										
										
											2013-03-17 19:55:10 +00:00
										 |  |  | 	BKE_mesh_update_customdata_pointers(me, false); | 
					
						
							| 
									
										
										
										
											2013-02-15 12:08:01 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* update normals in case objects with non-uniform scale are joined */ | 
					
						
							| 
									
										
										
										
											2013-05-28 14:23:07 +00:00
										 |  |  | 	BKE_mesh_calc_normals(me); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* old material array */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	for (a = 1; a <= ob->totcol; a++) { | 
					
						
							|  |  |  | 		ma = ob->mat[a - 1]; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 		if (ma) ma->id.us--; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	for (a = 1; a <= me->totcol; a++) { | 
					
						
							|  |  |  | 		ma = me->mat[a - 1]; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 		if (ma) ma->id.us--; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 	if (ob->mat) MEM_freeN(ob->mat); | 
					
						
							|  |  |  | 	if (ob->matbits) MEM_freeN(ob->matbits); | 
					
						
							|  |  |  | 	if (me->mat) MEM_freeN(me->mat); | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	ob->mat = me->mat = NULL; | 
					
						
							|  |  |  | 	ob->matbits = NULL; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 	if (totcol) { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		me->mat = matar; | 
					
						
							|  |  |  | 		ob->mat = MEM_callocN(sizeof(void *) * totcol, "join obmatar"); | 
					
						
							|  |  |  | 		ob->matbits = MEM_callocN(sizeof(char) * totcol, "join obmatbits"); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 	else | 
					
						
							|  |  |  | 		MEM_freeN(matar); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	ob->totcol = me->totcol = totcol; | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-10 06:29:10 +00:00
										 |  |  | 	if (matmap) MEM_freeN(matmap); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* other mesh users */ | 
					
						
							| 
									
										
										
										
											2013-04-18 08:58:21 +00:00
										 |  |  | 	test_object_materials(bmain, (ID *)me); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 	/* free temp copy of destination shapekeys (if applicable) */ | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 	if (nkey) { | 
					
						
							| 
									
										
										
										
											2012-07-07 22:51:57 +00:00
										 |  |  | 		/* XXX 2.5 Animato */ | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | #if 0
 | 
					
						
							|  |  |  | 		/* free it's ipo too - both are not actually freed from memory yet as ID-blocks */ | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 		if (nkey->ipo) { | 
					
						
							| 
									
										
										
										
											2012-05-05 14:03:12 +00:00
										 |  |  | 			BKE_ipo_free(nkey->ipo); | 
					
						
							| 
									
										
										
										
											2010-08-01 12:47:49 +00:00
										 |  |  | 			BLI_remlink(&bmain->ipo, nkey->ipo); | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 			MEM_freeN(nkey->ipo); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 		 | 
					
						
							| 
									
										
										
										
											2012-05-05 14:03:12 +00:00
										 |  |  | 		BKE_key_free(nkey); | 
					
						
							| 
									
										
										
										
											2010-08-01 12:47:49 +00:00
										 |  |  | 		BLI_remlink(&bmain->key, nkey); | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 		MEM_freeN(nkey); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2012-09-19 12:11:28 +00:00
										 |  |  | 	/* ensure newly inserted keys are time sorted */ | 
					
						
							|  |  |  | 	if (key && (key->type != KEY_RELATIVE)) { | 
					
						
							|  |  |  | 		BKE_key_sort(key); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-21 19:33:04 +00:00
										 |  |  | 	DAG_relations_tag_update(bmain);   // removed objects, need to rebuild dag
 | 
					
						
							| 
									
										
										
										
											2010-11-10 01:40:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2013-03-21 14:18:17 +00:00
										 |  |  | 	ED_object_editmode_enter(C, EM_WAITCURSOR); | 
					
						
							|  |  |  | 	ED_object_editmode_exit(C, EM_FREEDATA | EM_WAITCURSOR | EM_DO_UNDO); | 
					
						
							| 
									
										
										
										
											2010-11-10 01:40:24 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  | 	/* toggle editmode using lower level functions so this can be called from python */ | 
					
						
							| 
									
										
										
										
											2013-07-22 10:44:24 +00:00
										 |  |  | 	EDBM_mesh_make(scene->toolsettings, ob); | 
					
						
							| 
									
										
										
										
											2012-03-29 01:41:56 +00:00
										 |  |  | 	EDBM_mesh_load(ob); | 
					
						
							| 
									
										
										
										
											2012-03-27 04:46:52 +00:00
										 |  |  | 	EDBM_mesh_free(me->edit_btmesh); | 
					
						
							| 
									
										
										
										
											2011-02-27 06:19:40 +00:00
										 |  |  | 	MEM_freeN(me->edit_btmesh); | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	me->edit_btmesh = NULL; | 
					
						
							|  |  |  | 	DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA); | 
					
						
							| 
									
										
										
										
											2010-11-10 01:40:24 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 	return OPERATOR_FINISHED; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-28 04:04:01 +00:00
										 |  |  | /*********************** JOIN AS SHAPES ***************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Append selected meshes vertex locations as shapes of the active mesh, 
 | 
					
						
							| 
									
										
										
										
											2012-03-03 16:31:46 +00:00
										 |  |  |  * return 0 if no join is made (error) and 1 of the join is done */ | 
					
						
							| 
									
										
										
										
											2009-11-28 04:04:01 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | int join_mesh_shapes_exec(bContext *C, wmOperator *op) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	Scene *scene = CTX_data_scene(C); | 
					
						
							|  |  |  | 	Object *ob = CTX_data_active_object(C); | 
					
						
							|  |  |  | 	Mesh *me = (Mesh *)ob->data; | 
					
						
							|  |  |  | 	Mesh *selme = NULL; | 
					
						
							|  |  |  | 	DerivedMesh *dm = NULL; | 
					
						
							|  |  |  | 	Key *key = me->key; | 
					
						
							| 
									
										
										
										
											2009-11-28 04:04:01 +00:00
										 |  |  | 	KeyBlock *kb; | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	int ok = 0, nonequal_verts = 0; | 
					
						
							| 
									
										
										
										
											2009-11-28 04:04:01 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2012-04-30 16:22:40 +00:00
										 |  |  | 	CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-11-28 04:04:01 +00:00
										 |  |  | 		if (base->object == ob) continue; | 
					
						
							|  |  |  | 		 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		if (base->object->type == OB_MESH) { | 
					
						
							| 
									
										
										
										
											2009-11-28 04:04:01 +00:00
										 |  |  | 			selme = (Mesh *)base->object->data; | 
					
						
							|  |  |  | 			 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 			if (selme->totvert == me->totvert) | 
					
						
							| 
									
										
										
										
											2009-11-28 04:04:01 +00:00
										 |  |  | 				ok++; | 
					
						
							|  |  |  | 			else | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 				nonequal_verts = 1; | 
					
						
							| 
									
										
										
										
											2009-11-28 04:04:01 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	CTX_DATA_END; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (!ok) { | 
					
						
							|  |  |  | 		if (nonequal_verts) | 
					
						
							| 
									
										
										
										
											2011-09-19 12:26:20 +00:00
										 |  |  | 			BKE_report(op->reports, RPT_WARNING, "Selected meshes must have equal numbers of vertices"); | 
					
						
							| 
									
										
										
										
											2009-11-28 04:04:01 +00:00
										 |  |  | 		else | 
					
						
							| 
									
										
										
										
											2011-09-19 12:26:20 +00:00
										 |  |  | 			BKE_report(op->reports, RPT_WARNING, "No additional selected meshes with equal vertex count to join"); | 
					
						
							| 
									
										
										
										
											2009-11-28 04:04:01 +00:00
										 |  |  | 		return OPERATOR_CANCELLED; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 	if (key == NULL) { | 
					
						
							| 
									
										
										
										
											2012-09-19 10:12:07 +00:00
										 |  |  | 		key = me->key = BKE_key_add((ID *)me); | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		key->type = KEY_RELATIVE; | 
					
						
							| 
									
										
										
										
											2009-11-28 04:04:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-02 16:05:54 +00:00
										 |  |  | 		/* first key added, so it was the basis. initialize it with the existing mesh */ | 
					
						
							| 
									
										
										
										
											2012-09-19 10:12:07 +00:00
										 |  |  | 		kb = BKE_keyblock_add(key, NULL); | 
					
						
							|  |  |  | 		BKE_key_convert_from_mesh(me, kb); | 
					
						
							| 
									
										
										
										
											2009-11-28 04:04:01 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* now ready to add new keys from selected meshes */ | 
					
						
							| 
									
										
										
										
											2012-04-30 16:22:40 +00:00
										 |  |  | 	CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-11-28 04:04:01 +00:00
										 |  |  | 		if (base->object == ob) continue; | 
					
						
							|  |  |  | 		 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		if (base->object->type == OB_MESH) { | 
					
						
							| 
									
										
										
										
											2009-11-28 04:04:01 +00:00
										 |  |  | 			selme = (Mesh *)base->object->data; | 
					
						
							|  |  |  | 			 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 			if (selme->totvert == me->totvert) { | 
					
						
							| 
									
										
										
										
											2009-11-28 04:04:01 +00:00
										 |  |  | 				dm = mesh_get_derived_deform(scene, base->object, CD_MASK_BAREMESH); | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				if (!dm) continue; | 
					
						
							|  |  |  | 					 | 
					
						
							| 
									
										
										
										
											2012-09-19 10:12:07 +00:00
										 |  |  | 				kb = BKE_keyblock_add(key, base->object->id.name + 2); | 
					
						
							| 
									
										
										
										
											2009-11-28 04:04:01 +00:00
										 |  |  | 				 | 
					
						
							|  |  |  | 				DM_to_meshkey(dm, me, kb); | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				dm->release(dm); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	CTX_DATA_END; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); | 
					
						
							| 
									
										
										
										
											2009-11-28 04:04:01 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	return OPERATOR_FINISHED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-13 01:36:24 +11:00
										 |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /* Mesh Mirror (Spatial) */ | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-13 01:36:24 +11:00
										 |  |  | /** \name Mesh Spatial Mirror API
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-13 01:36:24 +11:00
										 |  |  | #define KD_THRESH      0.00002f
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-13 01:36:24 +11:00
										 |  |  | static struct { void *tree; } MirrKdStore = {NULL}; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* mode is 's' start, or 'e' end, or 'u' use */ | 
					
						
							|  |  |  | /* if end, ob can be NULL */ | 
					
						
							| 
									
										
										
										
											2014-03-13 01:46:21 +11:00
										 |  |  | int ED_mesh_mirror_spatial_table(Object *ob, BMEditMesh *em, const float co[3], char mode) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	if (mode == 'u') {        /* use table */ | 
					
						
							| 
									
										
										
										
											2014-03-13 01:36:24 +11:00
										 |  |  | 		if (MirrKdStore.tree == NULL) | 
					
						
							| 
									
										
										
										
											2014-03-13 01:46:21 +11:00
										 |  |  | 			ED_mesh_mirror_spatial_table(ob, em, NULL, 's'); | 
					
						
							| 
									
										
										
										
											2011-12-20 10:05:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-13 01:36:24 +11:00
										 |  |  | 		if (MirrKdStore.tree) { | 
					
						
							|  |  |  | 			KDTreeNearest nearest; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			i = BLI_kdtree_find_nearest(MirrKdStore.tree, co, NULL, &nearest); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (i != -1) { | 
					
						
							|  |  |  | 				if (nearest.dist < KD_THRESH) { | 
					
						
							|  |  |  | 					return i; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	else if (mode == 's') {   /* start table */ | 
					
						
							|  |  |  | 		Mesh *me = ob->data; | 
					
						
							| 
									
										
										
										
											2014-03-13 01:36:24 +11:00
										 |  |  | 		int totvert; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-13 01:36:24 +11:00
										 |  |  | 		if (MirrKdStore.tree) /* happens when entering this call without ending it */ | 
					
						
							| 
									
										
										
										
											2014-03-13 01:46:21 +11:00
										 |  |  | 			ED_mesh_mirror_spatial_table(ob, em, co, 'e'); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		if (em && me->edit_btmesh == em) { | 
					
						
							| 
									
										
										
										
											2014-03-13 01:36:24 +11:00
										 |  |  | 			totvert = em->bm->totvert; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-10-21 05:46:41 +00:00
										 |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2014-03-13 01:36:24 +11:00
										 |  |  | 			totvert = me->totvert; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-03-13 01:36:24 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		MirrKdStore.tree = BLI_kdtree_new(totvert); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		if (em && me->edit_btmesh == em) { | 
					
						
							| 
									
										
										
										
											2014-03-13 01:36:24 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-16 16:18:08 +00:00
										 |  |  | 			BMVert *eve; | 
					
						
							|  |  |  | 			BMIter iter; | 
					
						
							| 
									
										
										
										
											2014-03-13 01:36:24 +11:00
										 |  |  | 			int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* this needs to be valid for index lookups later (callers need) */ | 
					
						
							|  |  |  | 			BM_mesh_elem_table_ensure(em->bm, BM_VERT); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-13 01:36:24 +11:00
										 |  |  | 			BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) { | 
					
						
							|  |  |  | 				BLI_kdtree_insert(MirrKdStore.tree, i, eve->co, NULL); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-10-21 05:46:41 +00:00
										 |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			MVert *mvert; | 
					
						
							| 
									
										
										
										
											2014-03-13 01:36:24 +11:00
										 |  |  | 			int i; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			 | 
					
						
							| 
									
										
										
										
											2014-03-13 01:36:24 +11:00
										 |  |  | 			for (i = 0, mvert = me->mvert; i < me->totvert; i++, mvert++) { | 
					
						
							|  |  |  | 				BLI_kdtree_insert(MirrKdStore.tree, i, mvert->co, NULL); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-03-13 01:36:24 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		BLI_kdtree_balance(MirrKdStore.tree); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	else if (mode == 'e') { /* end table */ | 
					
						
							| 
									
										
										
										
											2014-03-13 01:36:24 +11:00
										 |  |  | 		if (MirrKdStore.tree) { | 
					
						
							|  |  |  | 			BLI_kdtree_free(MirrKdStore.tree); | 
					
						
							|  |  |  | 			MirrKdStore.tree = NULL; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-03-13 01:36:24 +11:00
										 |  |  | 	else { | 
					
						
							|  |  |  | 		BLI_assert(0); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-13 01:36:24 +11:00
										 |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /* Mesh Mirror (Topology) */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \name Mesh Topology Mirror API
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-07 00:22:10 +00:00
										 |  |  | static MirrTopoStore_t mesh_topo_store = {NULL, -1. - 1, -1}; | 
					
						
							| 
									
										
										
										
											2010-02-17 19:50:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* mode is 's' start, or 'e' end, or 'u' use */ | 
					
						
							|  |  |  | /* if end, ob can be NULL */ | 
					
						
							| 
									
										
										
										
											2011-12-16 07:27:56 +00:00
										 |  |  | /* note, is supposed return -1 on error, which callers are currently checking for, but is not used so far */ | 
					
						
							| 
									
										
										
										
											2014-03-13 01:46:21 +11:00
										 |  |  | int ED_mesh_mirror_topo_table(Object *ob, char mode) | 
					
						
							| 
									
										
										
										
											2010-02-17 19:50:42 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	if (mode == 'u') {        /* use table */ | 
					
						
							| 
									
										
										
										
											2011-12-20 10:05:58 +00:00
										 |  |  | 		if (ED_mesh_mirrtopo_recalc_check(ob->data, ob->mode, &mesh_topo_store)) { | 
					
						
							| 
									
										
										
										
											2014-03-13 01:46:21 +11:00
										 |  |  | 			ED_mesh_mirror_topo_table(ob, 's'); | 
					
						
							| 
									
										
										
										
											2010-02-17 19:50:42 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-12-20 10:05:58 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	else if (mode == 's') { /* start table */ | 
					
						
							| 
									
										
										
										
											2013-03-19 23:17:44 +00:00
										 |  |  | 		ED_mesh_mirrtopo_init(ob->data, ob->mode, &mesh_topo_store, false); | 
					
						
							| 
									
										
										
										
											2011-12-20 10:05:58 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	else if (mode == 'e') { /* end table */ | 
					
						
							| 
									
										
										
										
											2011-12-20 10:05:58 +00:00
										 |  |  | 		ED_mesh_mirrtopo_free(&mesh_topo_store); | 
					
						
							| 
									
										
										
										
											2010-02-17 19:50:42 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-03-13 01:36:24 +11:00
										 |  |  | 	else { | 
					
						
							|  |  |  | 		BLI_assert(0); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-17 19:50:42 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-13 01:36:24 +11:00
										 |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-27 05:59:41 +00:00
										 |  |  | static int mesh_get_x_mirror_vert_spatial(Object *ob, int index) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	Mesh *me = ob->data; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	MVert *mvert; | 
					
						
							|  |  |  | 	float vec[3]; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	mvert = me->mvert + index; | 
					
						
							|  |  |  | 	vec[0] = -mvert->co[0]; | 
					
						
							|  |  |  | 	vec[1] = mvert->co[1]; | 
					
						
							|  |  |  | 	vec[2] = mvert->co[2]; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2014-03-13 01:46:21 +11:00
										 |  |  | 	return ED_mesh_mirror_spatial_table(ob, NULL, vec, 'u'); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-17 19:50:42 +00:00
										 |  |  | static int mesh_get_x_mirror_vert_topo(Object *ob, int index) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-03-13 01:46:21 +11:00
										 |  |  | 	if (ED_mesh_mirror_topo_table(ob, 'u') == -1) | 
					
						
							| 
									
										
										
										
											2010-02-17 19:50:42 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-20 10:05:58 +00:00
										 |  |  | 	return mesh_topo_store.index_lookup[index]; | 
					
						
							| 
									
										
										
										
											2010-02-17 19:50:42 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-28 17:13:09 +00:00
										 |  |  | int mesh_get_x_mirror_vert(Object *ob, int index, const bool use_topology) | 
					
						
							| 
									
										
										
										
											2010-02-17 19:50:42 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-06-28 17:13:09 +00:00
										 |  |  | 	if (use_topology) { | 
					
						
							| 
									
										
										
										
											2010-02-17 19:50:42 +00:00
										 |  |  | 		return mesh_get_x_mirror_vert_topo(ob, index); | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2012-06-27 05:59:41 +00:00
										 |  |  | 		return mesh_get_x_mirror_vert_spatial(ob, index); | 
					
						
							| 
									
										
										
										
											2010-02-17 19:50:42 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-27 05:59:41 +00:00
										 |  |  | static BMVert *editbmesh_get_x_mirror_vert_spatial(Object *ob, BMEditMesh *em, const float co[3]) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	float vec[3]; | 
					
						
							| 
									
										
										
										
											2014-03-13 01:36:24 +11:00
										 |  |  | 	int i; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* ignore nan verts */ | 
					
						
							| 
									
										
										
										
											2013-03-19 23:17:44 +00:00
										 |  |  | 	if ((finite(co[0]) == false) || | 
					
						
							|  |  |  | 	    (finite(co[1]) == false) || | 
					
						
							|  |  |  | 	    (finite(co[2]) == false)) | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	vec[0] = -co[0]; | 
					
						
							|  |  |  | 	vec[1] = co[1]; | 
					
						
							|  |  |  | 	vec[2] = co[2]; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2014-03-13 01:46:21 +11:00
										 |  |  | 	i = ED_mesh_mirror_spatial_table(ob, em, vec, 'u'); | 
					
						
							| 
									
										
										
										
											2014-03-13 01:36:24 +11:00
										 |  |  | 	if (i != -1) { | 
					
						
							|  |  |  | 		return BM_vert_at_index(em->bm, i); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-27 06:19:40 +00:00
										 |  |  | static BMVert *editbmesh_get_x_mirror_vert_topo(Object *ob, struct BMEditMesh *em, BMVert *eve, int index) | 
					
						
							| 
									
										
										
										
											2010-02-17 19:50:42 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-12-16 07:27:56 +00:00
										 |  |  | 	intptr_t poinval; | 
					
						
							| 
									
										
										
										
											2014-03-13 01:46:21 +11:00
										 |  |  | 	if (ED_mesh_mirror_topo_table(ob, 'u') == -1) | 
					
						
							| 
									
										
										
										
											2010-02-17 19:50:42 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-28 19:53:45 +00:00
										 |  |  | 	if (index == -1) { | 
					
						
							| 
									
										
										
										
											2011-02-27 06:19:40 +00:00
										 |  |  | 		BMIter iter; | 
					
						
							|  |  |  | 		BMVert *v; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		index = 0; | 
					
						
							| 
									
										
										
										
											2012-04-19 13:47:58 +00:00
										 |  |  | 		BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) { | 
					
						
							| 
									
										
										
										
											2011-02-27 06:19:40 +00:00
										 |  |  | 			if (v == eve) | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			index++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if (index == em->bm->totvert) { | 
					
						
							| 
									
										
										
										
											2010-09-28 19:53:45 +00:00
										 |  |  | 			return NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-02-17 19:50:42 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	poinval = mesh_topo_store.index_lookup[index]; | 
					
						
							| 
									
										
										
										
											2010-02-17 19:50:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 	if (poinval != -1) | 
					
						
							| 
									
										
										
										
											2011-02-27 06:19:40 +00:00
										 |  |  | 		return (BMVert *)(poinval); | 
					
						
							| 
									
										
										
										
											2010-02-17 19:50:42 +00:00
										 |  |  | 	return NULL; | 
					
						
							| 
									
										
										
										
											2010-10-16 02:40:31 +00:00
										 |  |  | }	 | 
					
						
							| 
									
										
										
										
											2010-02-17 19:50:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-28 17:13:09 +00:00
										 |  |  | BMVert *editbmesh_get_x_mirror_vert(Object *ob, struct BMEditMesh *em, BMVert *eve, const float co[3], int index, const bool use_topology) | 
					
						
							| 
									
										
										
										
											2010-02-17 19:50:42 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-06-28 17:13:09 +00:00
										 |  |  | 	if (use_topology) { | 
					
						
							| 
									
										
										
										
											2011-02-27 06:19:40 +00:00
										 |  |  | 		return editbmesh_get_x_mirror_vert_topo(ob, em, eve, index); | 
					
						
							| 
									
										
										
										
											2012-02-06 09:39:47 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2012-06-27 05:59:41 +00:00
										 |  |  | 		return editbmesh_get_x_mirror_vert_spatial(ob, em, co); | 
					
						
							| 
									
										
										
										
											2010-02-17 19:50:42 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-17 07:03:13 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Wrapper for objectmode/editmode. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2013-10-28 02:05:33 +00:00
										 |  |  |  * call #BM_mesh_elem_table_ensure first for editmesh. | 
					
						
							| 
									
										
										
										
											2013-09-17 07:03:13 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | int ED_mesh_mirror_get_vert(Object *ob, int index) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Mesh *me = ob->data; | 
					
						
							|  |  |  | 	BMEditMesh *em = me->edit_btmesh; | 
					
						
							|  |  |  | 	bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0; | 
					
						
							|  |  |  | 	int index_mirr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (em) { | 
					
						
							|  |  |  | 		BMVert *eve, *eve_mirr; | 
					
						
							| 
									
										
										
										
											2013-10-28 02:05:33 +00:00
										 |  |  | 		eve = BM_vert_at_index(em->bm, index); | 
					
						
							| 
									
										
										
										
											2013-09-17 07:03:13 +00:00
										 |  |  | 		eve_mirr = editbmesh_get_x_mirror_vert(ob, em, eve, eve->co, index, use_topology); | 
					
						
							|  |  |  | 		index_mirr = eve_mirr ? BM_elem_index_get(eve_mirr) : -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		 index_mirr = mesh_get_x_mirror_vert(ob, index, use_topology); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return index_mirr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-06 09:39:47 +00:00
										 |  |  | #if 0
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-11 02:14:43 +00:00
										 |  |  | static float *editmesh_get_mirror_uv(BMEditMesh *em, int axis, float *uv, float *mirrCent, float *face_cent) | 
					
						
							| 
									
										
										
										
											2010-02-17 19:50:42 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	float vec[2]; | 
					
						
							|  |  |  | 	float cent_vec[2]; | 
					
						
							|  |  |  | 	float cent[2]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ignore nan verts */ | 
					
						
							|  |  |  | 	if (isnan(uv[0]) || !finite(uv[0]) || | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	    isnan(uv[1]) || !finite(uv[1]) | 
					
						
							|  |  |  | 	    ) | 
					
						
							| 
									
										
										
										
											2010-02-17 19:50:42 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (axis) { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		vec[0] = uv[0]; | 
					
						
							|  |  |  | 		vec[1] = -((uv[1]) - mirrCent[1]) + mirrCent[1]; | 
					
						
							| 
									
										
										
										
											2010-02-17 19:50:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		cent_vec[0] = face_cent[0]; | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		cent_vec[1] = -((face_cent[1]) - mirrCent[1]) + mirrCent[1]; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		vec[0] = -((uv[0]) - mirrCent[0]) + mirrCent[0]; | 
					
						
							|  |  |  | 		vec[1] = uv[1]; | 
					
						
							| 
									
										
										
										
											2010-02-17 19:50:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		cent_vec[0] = -((face_cent[0]) - mirrCent[0]) + mirrCent[0]; | 
					
						
							| 
									
										
										
										
											2010-02-17 19:50:42 +00:00
										 |  |  | 		cent_vec[1] = face_cent[1]; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* TODO - Optimize */ | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2011-02-27 06:19:40 +00:00
										 |  |  | 		BMIter iter; | 
					
						
							|  |  |  | 		BMFace *efa; | 
					
						
							|  |  |  | 		 | 
					
						
							| 
									
										
										
										
											2012-04-19 13:47:58 +00:00
										 |  |  | 		BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | 
					
						
							| 
									
										
										
										
											2013-05-10 06:46:32 +00:00
										 |  |  | 			uv_poly_center(efa, cent, cd_loop_uv_offset); | 
					
						
							| 
									
										
										
										
											2011-02-27 06:19:40 +00:00
										 |  |  | 			 | 
					
						
							| 
									
										
										
										
											2012-07-21 15:27:40 +00:00
										 |  |  | 			if ( (fabsf(cent[0] - cent_vec[0]) < 0.001f) && (fabsf(cent[1] - cent_vec[1]) < 0.001f) ) { | 
					
						
							| 
									
										
										
										
											2011-02-27 06:19:40 +00:00
										 |  |  | 				BMIter liter; | 
					
						
							|  |  |  | 				BMLoop *l; | 
					
						
							|  |  |  | 				 | 
					
						
							| 
									
										
										
										
											2012-04-19 13:47:58 +00:00
										 |  |  | 				BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | 
					
						
							| 
									
										
										
										
											2011-02-27 06:19:40 +00:00
										 |  |  | 					MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); | 
					
						
							| 
									
										
										
										
											2012-07-21 15:27:40 +00:00
										 |  |  | 					if ( (fabsf(luv->uv[0] - vec[0]) < 0.001f) && (fabsf(luv->uv[1] - vec[1]) < 0.001f) ) { | 
					
						
							| 
									
										
										
										
											2011-02-27 06:19:40 +00:00
										 |  |  | 						return luv->uv; | 
					
						
							|  |  |  | 								 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2010-02-17 19:50:42 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-06 09:39:47 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-03 17:05:21 +00:00
										 |  |  | static unsigned int mirror_facehash(const void *ptr) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	const MFace *mf = ptr; | 
					
						
							| 
									
										
										
										
											2012-12-21 05:07:26 +00:00
										 |  |  | 	unsigned int v0, v1; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 	if (mf->v4) { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		v0 = MIN4(mf->v1, mf->v2, mf->v3, mf->v4); | 
					
						
							|  |  |  | 		v1 = MAX4(mf->v1, mf->v2, mf->v3, mf->v4); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		v0 = MIN3(mf->v1, mf->v2, mf->v3); | 
					
						
							|  |  |  | 		v1 = MAX3(mf->v1, mf->v2, mf->v3); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	return ((v0 * 39) ^ (v1 * 31)); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int mirror_facerotation(MFace *a, MFace *b) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 	if (b->v4) { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		if (a->v1 == b->v1 && a->v2 == b->v2 && a->v3 == b->v3 && a->v4 == b->v4) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			return 0; | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		else if (a->v4 == b->v1 && a->v1 == b->v2 && a->v2 == b->v3 && a->v3 == b->v4) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			return 1; | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		else if (a->v3 == b->v1 && a->v4 == b->v2 && a->v1 == b->v3 && a->v2 == b->v4) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			return 2; | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		else if (a->v2 == b->v1 && a->v3 == b->v2 && a->v4 == b->v3 && a->v1 == b->v4) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			return 3; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		if (a->v1 == b->v1 && a->v2 == b->v2 && a->v3 == b->v3) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			return 0; | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		else if (a->v3 == b->v1 && a->v1 == b->v2 && a->v2 == b->v3) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			return 1; | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		else if (a->v2 == b->v1 && a->v3 == b->v2 && a->v1 == b->v3) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			return 2; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-03 17:05:21 +00:00
										 |  |  | static int mirror_facecmp(const void *a, const void *b) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	return (mirror_facerotation((MFace *)a, (MFace *)b) == -1); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-15 14:39:18 +00:00
										 |  |  | /* BMESH_TODO, convert to MPoly (functions above also) */ | 
					
						
							| 
									
										
										
										
											2009-05-18 08:46:04 +00:00
										 |  |  | int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	Mesh *me = ob->data; | 
					
						
							|  |  |  | 	MVert *mv, *mvert = me->mvert; | 
					
						
							|  |  |  | 	MFace mirrormf, *mf, *hashmf, *mface = me->mface; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	GHash *fhash; | 
					
						
							| 
									
										
										
										
											2013-06-28 17:13:09 +00:00
										 |  |  | 	const bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	int *mirrorverts, *mirrorfaces; | 
					
						
							|  |  |  | 	int a; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	mirrorverts = MEM_callocN(sizeof(int) * me->totvert, "MirrorVerts"); | 
					
						
							|  |  |  | 	mirrorfaces = MEM_callocN(sizeof(int) * 2 * me->totface, "MirrorFaces"); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-13 01:46:21 +11:00
										 |  |  | 	ED_mesh_mirror_spatial_table(ob, em, NULL, 's'); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	for (a = 0, mv = mvert; a < me->totvert; a++, mv++) | 
					
						
							| 
									
										
										
										
											2013-06-28 17:13:09 +00:00
										 |  |  | 		mirrorverts[a] = mesh_get_x_mirror_vert(ob, a, use_topology); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-13 01:46:21 +11:00
										 |  |  | 	ED_mesh_mirror_spatial_table(ob, em, NULL, 'e'); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-24 17:33:47 +00:00
										 |  |  | 	fhash = BLI_ghash_new_ex(mirror_facehash, mirror_facecmp, "mirror_facehash gh", me->totface); | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	for (a = 0, mf = mface; a < me->totface; a++, mf++) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		BLI_ghash_insert(fhash, mf, mf); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	for (a = 0, mf = mface; a < me->totface; a++, mf++) { | 
					
						
							|  |  |  | 		mirrormf.v1 = mirrorverts[mf->v3]; | 
					
						
							|  |  |  | 		mirrormf.v2 = mirrorverts[mf->v2]; | 
					
						
							|  |  |  | 		mirrormf.v3 = mirrorverts[mf->v1]; | 
					
						
							|  |  |  | 		mirrormf.v4 = (mf->v4) ? mirrorverts[mf->v4] : 0; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* make sure v4 is not 0 if a quad */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		if (mf->v4 && mirrormf.v4 == 0) { | 
					
						
							| 
									
										
										
										
											2011-12-27 03:54:23 +00:00
										 |  |  | 			SWAP(unsigned int, mirrormf.v1, mirrormf.v3); | 
					
						
							|  |  |  | 			SWAP(unsigned int, mirrormf.v2, mirrormf.v4); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		hashmf = BLI_ghash_lookup(fhash, &mirrormf); | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 		if (hashmf) { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 			mirrorfaces[a * 2] = hashmf - mface; | 
					
						
							|  |  |  | 			mirrorfaces[a * 2 + 1] = mirror_facerotation(&mirrormf, hashmf); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 			mirrorfaces[a * 2] = -1; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BLI_ghash_free(fhash, NULL, NULL); | 
					
						
							|  |  |  | 	MEM_freeN(mirrorverts); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return mirrorfaces; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-09-06 23:50:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* selection, vertex and face */ | 
					
						
							|  |  |  | /* returns 0 if not found, otherwise 1 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * Face selection in object mode, | 
					
						
							|  |  |  |  * currently only weight-paint and vertex-paint use this. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2013-03-19 23:17:44 +00:00
										 |  |  |  * \return boolean true == Found | 
					
						
							| 
									
										
										
										
											2012-09-06 23:50:28 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2013-03-19 23:17:44 +00:00
										 |  |  | bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], unsigned int *index, int size) | 
					
						
							| 
									
										
										
										
											2012-09-06 23:50:28 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	ViewContext vc; | 
					
						
							| 
									
										
										
										
											2012-12-23 01:54:11 +00:00
										 |  |  | 	Mesh *me = ob->data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BLI_assert(me && GS(me->id.name) == ID_ME); | 
					
						
							| 
									
										
										
										
											2012-09-06 23:50:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!me || me->totpoly == 0) | 
					
						
							| 
									
										
										
										
											2013-03-19 23:17:44 +00:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2012-09-06 23:50:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-07 00:58:00 +00:00
										 |  |  | 	view3d_set_viewcontext(C, &vc); | 
					
						
							| 
									
										
										
										
											2012-09-06 23:50:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-07 00:58:00 +00:00
										 |  |  | 	if (size) { | 
					
						
							|  |  |  | 		/* sample rect to increase chances of selecting, so that when clicking
 | 
					
						
							| 
									
										
										
										
											2012-09-06 23:50:28 +00:00
										 |  |  | 		 * on an edge in the backbuf, we can still select a face */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-10 01:22:19 +00:00
										 |  |  | 		float dummy_dist; | 
					
						
							| 
									
										
										
										
											2012-09-07 00:58:00 +00:00
										 |  |  | 		*index = view3d_sample_backbuf_rect(&vc, mval, size, 1, me->totpoly + 1, &dummy_dist, 0, NULL, NULL); | 
					
						
							| 
									
										
										
										
											2012-09-06 23:50:28 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		/* sample only on the exact position */ | 
					
						
							|  |  |  | 		*index = view3d_sample_backbuf(&vc, mval[0], mval[1]); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-20 15:07:57 +00:00
										 |  |  | 	if ((*index) == 0 || (*index) > (unsigned int)me->totpoly) | 
					
						
							| 
									
										
										
										
											2013-03-19 23:17:44 +00:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2012-09-06 23:50:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	(*index)--; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-19 23:17:44 +00:00
										 |  |  | 	return true; | 
					
						
							| 
									
										
										
										
											2012-09-06 23:50:28 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2013-11-01 01:14:36 +00:00
										 |  |  | static void ed_mesh_pick_face_vert__mpoly_find( | 
					
						
							|  |  |  |         /* context */ | 
					
						
							|  |  |  |         struct ARegion *ar, const float mval[2], | 
					
						
							|  |  |  |         /* mesh data */ | 
					
						
							|  |  |  |         DerivedMesh *dm, MPoly *mp, MLoop *mloop, | 
					
						
							|  |  |  |         /* return values */ | 
					
						
							|  |  |  |         float *r_len_best, int *r_v_idx_best) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const MLoop *ml; | 
					
						
							|  |  |  | 	int j = mp->totloop; | 
					
						
							|  |  |  | 	for (ml = &mloop[mp->loopstart]; j--; ml++) { | 
					
						
							|  |  |  | 		float co[3], sco[2], len; | 
					
						
							|  |  |  | 		const int v_idx = ml->v; | 
					
						
							|  |  |  | 		dm->getVertCo(dm, v_idx, co); | 
					
						
							|  |  |  | 		if (ED_view3d_project_float_object(ar, co, sco, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { | 
					
						
							|  |  |  | 			len = len_manhattan_v2v2(mval, sco); | 
					
						
							|  |  |  | 			if (len < *r_len_best) { | 
					
						
							|  |  |  | 				*r_len_best = len; | 
					
						
							|  |  |  | 				*r_v_idx_best = v_idx; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-09-07 05:54:54 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Use when the back buffer stores face index values. but we want a vert. | 
					
						
							|  |  |  |  * This gets the face then finds the closest vertex to mval. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2013-03-19 23:17:44 +00:00
										 |  |  | bool ED_mesh_pick_face_vert(bContext *C, Object *ob, const int mval[2], unsigned int *index, int size) | 
					
						
							| 
									
										
										
										
											2012-09-07 05:54:54 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	unsigned int poly_index; | 
					
						
							| 
									
										
										
										
											2012-12-23 01:54:11 +00:00
										 |  |  | 	Mesh *me = ob->data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BLI_assert(me && GS(me->id.name) == ID_ME); | 
					
						
							| 
									
										
										
										
											2012-09-07 05:54:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-23 01:54:11 +00:00
										 |  |  | 	if (ED_mesh_pick_face(C, ob, mval, &poly_index, size)) { | 
					
						
							| 
									
										
										
										
											2012-09-07 05:54:54 +00:00
										 |  |  | 		Scene *scene = CTX_data_scene(C); | 
					
						
							|  |  |  | 		struct ARegion *ar = CTX_wm_region(C); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* derived mesh to find deformed locations */ | 
					
						
							| 
									
										
										
										
											2013-11-01 01:14:36 +00:00
										 |  |  | 		DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		int v_idx_best = ORIGINDEX_NONE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* find the vert closest to 'mval' */ | 
					
						
							|  |  |  | 		const float mval_f[2] = {UNPACK2(mval)}; | 
					
						
							|  |  |  | 		float len_best = FLT_MAX; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		MPoly *dm_mpoly; | 
					
						
							|  |  |  | 		MLoop *dm_mloop; | 
					
						
							|  |  |  | 		unsigned int dm_mpoly_tot; | 
					
						
							|  |  |  | 		const int *index_mp_to_orig; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		dm_mpoly = dm->getPolyArray(dm); | 
					
						
							|  |  |  | 		dm_mloop = dm->getLoopArray(dm); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		dm_mpoly_tot = dm->getNumPolys(dm); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* tag all verts using this face */ | 
					
						
							|  |  |  | 		if (index_mp_to_orig) { | 
					
						
							|  |  |  | 			unsigned int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			for (i = 0; i < dm_mpoly_tot; i++) { | 
					
						
							|  |  |  | 				if (index_mp_to_orig[i] == poly_index) { | 
					
						
							|  |  |  | 					ed_mesh_pick_face_vert__mpoly_find( | 
					
						
							|  |  |  | 					        ar, mval_f, | 
					
						
							|  |  |  | 					        dm, &dm_mpoly[i], dm_mloop, | 
					
						
							|  |  |  | 					        &len_best, &v_idx_best); | 
					
						
							| 
									
										
										
										
											2012-09-07 05:54:54 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2013-11-01 01:14:36 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			if (poly_index < dm_mpoly_tot) { | 
					
						
							|  |  |  | 				ed_mesh_pick_face_vert__mpoly_find( | 
					
						
							|  |  |  | 				        ar, mval_f, | 
					
						
							|  |  |  | 				        dm, &dm_mpoly[poly_index], dm_mloop, | 
					
						
							|  |  |  | 				        &len_best, &v_idx_best); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* map 'dm -> me' index if possible */ | 
					
						
							|  |  |  | 		if (v_idx_best != ORIGINDEX_NONE) { | 
					
						
							|  |  |  | 			const int *index_mv_to_orig; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			index_mv_to_orig = dm->getVertDataArray(dm, CD_ORIGINDEX); | 
					
						
							|  |  |  | 			if (index_mv_to_orig) { | 
					
						
							|  |  |  | 				v_idx_best = index_mv_to_orig[v_idx_best]; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-09-07 05:54:54 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		dm->release(dm); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-01 01:14:36 +00:00
										 |  |  | 		if ((v_idx_best != ORIGINDEX_NONE) && (v_idx_best < me->totvert)) { | 
					
						
							| 
									
										
										
										
											2012-09-07 05:54:54 +00:00
										 |  |  | 			*index = v_idx_best; | 
					
						
							| 
									
										
										
										
											2013-03-19 23:17:44 +00:00
										 |  |  | 			return true; | 
					
						
							| 
									
										
										
										
											2012-09-07 05:54:54 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-19 23:17:44 +00:00
										 |  |  | 	return false; | 
					
						
							| 
									
										
										
										
											2012-09-07 05:54:54 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2012-09-06 23:50:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * Vertex selection in object mode, | 
					
						
							|  |  |  |  * currently only weight paint uses this. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2013-03-19 23:17:44 +00:00
										 |  |  |  * \return boolean true == Found | 
					
						
							| 
									
										
										
										
											2012-09-06 23:50:28 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-12-23 02:32:03 +00:00
										 |  |  | typedef struct VertPickData { | 
					
						
							|  |  |  | 	const MVert *mvert; | 
					
						
							|  |  |  | 	const float *mval_f;  /* [2] */ | 
					
						
							|  |  |  | 	ARegion *ar; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* runtime */ | 
					
						
							|  |  |  | 	float len_best; | 
					
						
							|  |  |  | 	int v_idx_best; | 
					
						
							|  |  |  | } VertPickData; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void ed_mesh_pick_vert__mapFunc(void *userData, int index, const float co[3], | 
					
						
							|  |  |  |                                        const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	VertPickData *data = userData; | 
					
						
							|  |  |  | 	if ((data->mvert[index].flag & ME_HIDE) == 0) { | 
					
						
							|  |  |  | 		float sco[2]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (ED_view3d_project_float_object(data->ar, co, sco, V3D_PROJ_TEST_CLIP_DEFAULT) == V3D_PROJ_RET_OK) { | 
					
						
							|  |  |  | 			const float len = len_manhattan_v2v2(data->mval_f, sco); | 
					
						
							|  |  |  | 			if (len < data->len_best) { | 
					
						
							|  |  |  | 				data->len_best = len; | 
					
						
							|  |  |  | 				data->v_idx_best = index; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-03-19 23:17:44 +00:00
										 |  |  | bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int *index, int size, bool use_zbuf) | 
					
						
							| 
									
										
										
										
											2012-09-06 23:50:28 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	ViewContext vc; | 
					
						
							| 
									
										
										
										
											2012-12-23 01:54:11 +00:00
										 |  |  | 	Mesh *me = ob->data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BLI_assert(me && GS(me->id.name) == ID_ME); | 
					
						
							| 
									
										
										
										
											2012-09-06 23:50:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!me || me->totvert == 0) | 
					
						
							| 
									
										
										
										
											2013-03-19 23:17:44 +00:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2012-09-06 23:50:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-07 00:58:00 +00:00
										 |  |  | 	view3d_set_viewcontext(C, &vc); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-23 01:54:11 +00:00
										 |  |  | 	if (use_zbuf) { | 
					
						
							|  |  |  | 		if (size > 0) { | 
					
						
							|  |  |  | 			/* sample rect to increase chances of selecting, so that when clicking
 | 
					
						
							|  |  |  | 			 * on an face in the backbuf, we can still select a vert */ | 
					
						
							| 
									
										
										
										
											2012-09-06 23:50:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-23 01:54:11 +00:00
										 |  |  | 			float dummy_dist; | 
					
						
							|  |  |  | 			*index = view3d_sample_backbuf_rect(&vc, mval, size, 1, me->totvert + 1, &dummy_dist, 0, NULL, NULL); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			/* sample only on the exact position */ | 
					
						
							|  |  |  | 			*index = view3d_sample_backbuf(&vc, mval[0], mval[1]); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-20 15:07:57 +00:00
										 |  |  | 		if ((*index) == 0 || (*index) > (unsigned int)me->totvert) | 
					
						
							| 
									
										
										
										
											2013-03-19 23:17:44 +00:00
										 |  |  | 			return false; | 
					
						
							| 
									
										
										
										
											2012-12-23 01:54:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		(*index)--; | 
					
						
							| 
									
										
										
										
											2012-09-06 23:50:28 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2012-12-23 01:54:11 +00:00
										 |  |  | 		/* derived mesh to find deformed locations */ | 
					
						
							|  |  |  | 		DerivedMesh *dm = mesh_get_derived_final(vc.scene, ob, CD_MASK_BAREMESH); | 
					
						
							| 
									
										
										
										
											2012-12-23 02:32:03 +00:00
										 |  |  | 		ARegion *ar = vc.ar; | 
					
						
							|  |  |  | 		RegionView3D *rv3d = ar->regiondata; | 
					
						
							| 
									
										
										
										
											2012-09-06 23:50:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-23 02:32:03 +00:00
										 |  |  | 		/* find the vert closest to 'mval' */ | 
					
						
							|  |  |  | 		const float mval_f[2] = {(float)mval[0], | 
					
						
							|  |  |  | 		                         (float)mval[1]}; | 
					
						
							| 
									
										
										
										
											2012-09-06 23:50:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-07 03:55:21 +00:00
										 |  |  | 		VertPickData data = {NULL}; | 
					
						
							| 
									
										
										
										
											2012-12-23 02:32:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		ED_view3d_init_mats_rv3d(ob, rv3d); | 
					
						
							| 
									
										
										
										
											2012-12-23 01:54:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (dm == NULL) { | 
					
						
							| 
									
										
										
										
											2013-03-19 23:17:44 +00:00
										 |  |  | 			return false; | 
					
						
							| 
									
										
										
										
											2012-12-23 01:54:11 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-23 02:32:03 +00:00
										 |  |  | 		/* setup data */ | 
					
						
							|  |  |  | 		data.mvert = me->mvert; | 
					
						
							|  |  |  | 		data.ar = ar; | 
					
						
							|  |  |  | 		data.mval_f = mval_f; | 
					
						
							|  |  |  | 		data.len_best = FLT_MAX; | 
					
						
							|  |  |  | 		data.v_idx_best = -1; | 
					
						
							| 
									
										
										
										
											2012-12-23 02:04:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-22 22:59:47 +00:00
										 |  |  | 		dm->foreachMappedVert(dm, ed_mesh_pick_vert__mapFunc, &data, DM_FOREACH_NOP); | 
					
						
							| 
									
										
										
										
											2012-12-23 01:54:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		dm->release(dm); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-23 02:32:03 +00:00
										 |  |  | 		if (data.v_idx_best == -1) { | 
					
						
							| 
									
										
										
										
											2013-03-19 23:17:44 +00:00
										 |  |  | 			return false; | 
					
						
							| 
									
										
										
										
											2012-12-23 01:54:11 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-12-23 02:32:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		*index = data.v_idx_best; | 
					
						
							| 
									
										
										
										
											2012-12-23 01:54:11 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-09-06 23:50:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-19 23:17:44 +00:00
										 |  |  | 	return true; | 
					
						
							| 
									
										
										
										
											2012-09-06 23:50:28 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2013-06-24 04:41:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MDeformVert *ED_mesh_active_dvert_get_em(Object *ob, BMVert **r_eve) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (ob->mode & OB_MODE_EDIT && ob->type == OB_MESH && ob->defbase.first) { | 
					
						
							|  |  |  | 		Mesh *me = ob->data; | 
					
						
							| 
									
										
										
										
											2013-06-24 04:51:56 +00:00
										 |  |  | 		BMesh *bm = me->edit_btmesh->bm; | 
					
						
							|  |  |  | 		const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT); | 
					
						
							| 
									
										
										
										
											2013-06-24 04:41:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (cd_dvert_offset != -1) { | 
					
						
							| 
									
										
										
										
											2013-06-24 04:51:56 +00:00
										 |  |  | 			BMVert *eve = BM_mesh_active_vert_get(bm); | 
					
						
							| 
									
										
										
										
											2013-06-24 04:41:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-24 04:51:56 +00:00
										 |  |  | 			if (eve) { | 
					
						
							| 
									
										
										
										
											2013-06-24 04:41:03 +00:00
										 |  |  | 				if (r_eve) *r_eve = eve; | 
					
						
							|  |  |  | 				return BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (r_eve) *r_eve = NULL; | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MDeformVert *ED_mesh_active_dvert_get_ob(Object *ob, int *r_index) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Mesh *me = ob->data; | 
					
						
							|  |  |  | 	int index = BKE_mesh_mselect_active_get(me, ME_VSEL); | 
					
						
							|  |  |  | 	if (r_index) *r_index = index; | 
					
						
							|  |  |  | 	if (index == -1 || me->dvert == NULL) { | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		return me->dvert + index; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MDeformVert *ED_mesh_active_dvert_get_only(Object *ob) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (ob->type == OB_MESH) { | 
					
						
							|  |  |  | 		if (ob->mode & OB_MODE_EDIT) { | 
					
						
							|  |  |  | 			return ED_mesh_active_dvert_get_em(ob, NULL); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			return ED_mesh_active_dvert_get_ob(ob, NULL); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |