| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2011-10-23 17:52:20 +00:00
										 |  |  |  * ***** BEGIN GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  |  * of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software  Foundation, | 
					
						
							|  |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) 2005 by the Blender Foundation. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Contributor(s): Daniel Dunbar | 
					
						
							|  |  |  |  *                 Ton Roosendaal, | 
					
						
							|  |  |  |  *                 Ben Batt, | 
					
						
							|  |  |  |  *                 Brecht Van Lommel, | 
					
						
							|  |  |  |  *                 Campbell Barton | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ***** END GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-25 13:57:17 +00:00
										 |  |  | /** \file blender/modifiers/intern/MOD_solidify.c
 | 
					
						
							|  |  |  |  *  \ingroup modifiers | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-12 22:33:43 +00:00
										 |  |  | #include "DNA_meshdata_types.h"
 | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-28 09:47:24 +00:00
										 |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-09 04:06:48 +00:00
										 |  |  | #include "BLI_utildefines.h"
 | 
					
						
							| 
									
										
										
										
											2010-04-12 00:36:50 +00:00
										 |  |  | #include "BLI_math.h"
 | 
					
						
							|  |  |  | #include "BLI_edgehash.h"
 | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | #include "BLI_array.h"
 | 
					
						
							| 
									
										
										
										
											2011-10-19 23:10:54 +00:00
										 |  |  | #include "BLI_string.h"
 | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "BKE_cdderivedmesh.h"
 | 
					
						
							|  |  |  | #include "BKE_mesh.h"
 | 
					
						
							|  |  |  | #include "BKE_particle.h"
 | 
					
						
							|  |  |  | #include "BKE_deform.h"
 | 
					
						
							| 
									
										
										
										
											2011-01-07 19:18:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | #include "MOD_modifiertypes.h"
 | 
					
						
							| 
									
										
										
										
											2011-07-11 09:15:20 +00:00
										 |  |  | #include "MOD_util.h"
 | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct EdgeFaceRef { | 
					
						
							|  |  |  | 	int f1; /* init as -1 */ | 
					
						
							|  |  |  | 	int f2; | 
					
						
							|  |  |  | } EdgeFaceRef; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void dm_calc_normal(DerivedMesh *dm, float (*temp_nors)[3]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i, numVerts, numEdges, numFaces; | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 	MPoly *mpoly, *mp; | 
					
						
							|  |  |  | 	MLoop *mloop, *ml; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	MVert *mvert, *mv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	float (*face_nors)[3]; | 
					
						
							|  |  |  | 	float *f_no; | 
					
						
							|  |  |  | 	int calc_face_nors= 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	numVerts = dm->getNumVerts(dm); | 
					
						
							|  |  |  | 	numEdges = dm->getNumEdges(dm); | 
					
						
							| 
									
										
										
										
											2011-11-29 13:01:51 +00:00
										 |  |  | 	numFaces = dm->getNumPolys(dm); | 
					
						
							| 
									
										
										
										
											2012-01-23 21:04:56 +00:00
										 |  |  | 	mpoly = dm->getPolyArray(dm); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	mvert = dm->getVertArray(dm); | 
					
						
							| 
									
										
										
										
											2012-01-23 21:04:56 +00:00
										 |  |  | 	mloop = dm->getLoopArray(dm); | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	/* we don't want to overwrite any referenced layers */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							| 
									
										
										
										
											2011-12-19 08:26:53 +00:00
										 |  |  | 	Doesn't work here! | 
					
						
							|  |  |  | 	mv = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, numVerts); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	cddm->mvert = mv; | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 	face_nors = CustomData_get_layer(&dm->polyData, CD_NORMAL); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	if(!face_nors) { | 
					
						
							|  |  |  | 		calc_face_nors = 1; | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 		face_nors = CustomData_add_layer(&dm->polyData, CD_NORMAL, CD_CALLOC, NULL, numFaces); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mv = mvert; | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 	mp = mpoly; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		EdgeHash *edge_hash = BLI_edgehash_new(); | 
					
						
							|  |  |  | 		EdgeHashIterator *edge_iter; | 
					
						
							|  |  |  | 		int edge_ref_count = 0; | 
					
						
							| 
									
										
										
										
											2011-12-28 10:06:10 +00:00
										 |  |  | 		unsigned int ed_v1, ed_v2; /* use when getting the key */ | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 		EdgeFaceRef *edge_ref_array = MEM_callocN(numEdges * sizeof(EdgeFaceRef), "Edge Connectivity"); | 
					
						
							|  |  |  | 		EdgeFaceRef *edge_ref; | 
					
						
							|  |  |  | 		float edge_normal[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* This function adds an edge hash if its not there, and adds the face index */ | 
					
						
							|  |  |  | #define NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(EDV1, EDV2); \
 | 
					
						
							| 
									
										
										
										
											2011-12-28 07:10:27 +00:00
										 |  |  | 			{ \ | 
					
						
							| 
									
										
										
										
											2011-12-28 10:06:10 +00:00
										 |  |  | 				const unsigned int ml_v1 = EDV1; \ | 
					
						
							|  |  |  | 				const unsigned int ml_v2 = EDV2; \ | 
					
						
							|  |  |  | 				edge_ref = (EdgeFaceRef *)BLI_edgehash_lookup(edge_hash, ml_v1, ml_v2); \ | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 				if (!edge_ref) { \ | 
					
						
							|  |  |  | 					edge_ref = &edge_ref_array[edge_ref_count]; edge_ref_count++; \ | 
					
						
							| 
									
										
										
										
											2011-12-28 07:10:27 +00:00
										 |  |  | 					edge_ref->f1 = i; \ | 
					
						
							|  |  |  | 					edge_ref->f2 =- 1; \ | 
					
						
							| 
									
										
										
										
											2011-12-28 10:06:10 +00:00
										 |  |  | 					BLI_edgehash_insert(edge_hash, ml_v1, ml_v2, edge_ref); \ | 
					
						
							| 
									
										
										
										
											2011-12-28 07:10:27 +00:00
										 |  |  | 				} \ | 
					
						
							|  |  |  | 				else { \ | 
					
						
							| 
									
										
										
										
											2011-12-28 10:06:10 +00:00
										 |  |  | 					edge_ref->f2 = i; \ | 
					
						
							| 
									
										
										
										
											2011-12-28 07:10:27 +00:00
										 |  |  | 				} \ | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		/* --- end define --- */ | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 		for(i = 0; i < numFaces; i++, mp++) { | 
					
						
							|  |  |  | 			int j; | 
					
						
							|  |  |  | 			 | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 			f_no = face_nors[i]; | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 			if(calc_face_nors) | 
					
						
							|  |  |  | 				mesh_calc_poly_normal(mp, mloop+mp->loopstart, mvert, f_no); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 			ml = mloop + mp->loopstart; | 
					
						
							| 
									
										
										
										
											2011-12-28 07:10:27 +00:00
										 |  |  | 			for (j=0; j<mp->totloop; j++, ml++) { | 
					
						
							|  |  |  | 				NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(ml->v, ME_POLY_LOOP_NEXT(mloop, mp, j)->v); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for(edge_iter = BLI_edgehashIterator_new(edge_hash); !BLI_edgehashIterator_isDone(edge_iter); BLI_edgehashIterator_step(edge_iter)) { | 
					
						
							| 
									
										
										
										
											2011-01-18 01:58:19 +00:00
										 |  |  | 			/* Get the edge vert indices, and edge value (the face indices that use it)*/ | 
					
						
							| 
									
										
										
										
											2011-12-28 10:06:10 +00:00
										 |  |  | 			BLI_edgehashIterator_getKey(edge_iter, &ed_v1, &ed_v2); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 			edge_ref = BLI_edgehashIterator_getValue(edge_iter); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (edge_ref->f2 != -1) { | 
					
						
							|  |  |  | 				/* We have 2 faces using this edge, calculate the edges normal
 | 
					
						
							|  |  |  | 				 * using the angle between the 2 faces as a weighting */ | 
					
						
							|  |  |  | 				add_v3_v3v3(edge_normal, face_nors[edge_ref->f1], face_nors[edge_ref->f2]); | 
					
						
							|  |  |  | 				normalize_v3(edge_normal); | 
					
						
							|  |  |  | 				mul_v3_fl(edge_normal, angle_normalized_v3v3(face_nors[edge_ref->f1], face_nors[edge_ref->f2])); | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				/* only one face attached to that edge */ | 
					
						
							|  |  |  | 				/* an edge without another attached- the weight on this is
 | 
					
						
							|  |  |  | 				 * undefined, M_PI/2 is 90d in radians and that seems good enough */ | 
					
						
							| 
									
										
										
										
											2010-04-12 00:36:50 +00:00
										 |  |  | 				mul_v3_v3fl(edge_normal, face_nors[edge_ref->f1], M_PI/2); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			add_v3_v3(temp_nors[ed_v1], edge_normal); | 
					
						
							|  |  |  | 			add_v3_v3(temp_nors[ed_v2], edge_normal); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		BLI_edgehashIterator_free(edge_iter); | 
					
						
							|  |  |  | 		BLI_edgehash_free(edge_hash, NULL); | 
					
						
							|  |  |  | 		MEM_freeN(edge_ref_array); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* normalize vertex normals and assign */ | 
					
						
							|  |  |  | 	for(i = 0; i < numVerts; i++, mv++) { | 
					
						
							|  |  |  | 		if(normalize_v3(temp_nors[i]) == 0.0f) { | 
					
						
							|  |  |  | 			normal_short_to_float_v3(temp_nors[i], mv->no); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  |   | 
					
						
							|  |  |  | static void initData(ModifierData *md) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	SolidifyModifierData *smd = (SolidifyModifierData*) md; | 
					
						
							|  |  |  | 	smd->offset = 0.01f; | 
					
						
							| 
									
										
										
										
											2010-07-14 08:24:24 +00:00
										 |  |  | 	smd->offset_fac = -1.0f; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	smd->flag = MOD_SOLIDIFY_RIM; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  |   | 
					
						
							|  |  |  | static void copyData(ModifierData *md, ModifierData *target) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	SolidifyModifierData *smd = (SolidifyModifierData*) md; | 
					
						
							|  |  |  | 	SolidifyModifierData *tsmd = (SolidifyModifierData*) target; | 
					
						
							|  |  |  | 	tsmd->offset = smd->offset; | 
					
						
							|  |  |  | 	tsmd->offset_fac = smd->offset_fac; | 
					
						
							|  |  |  | 	tsmd->crease_inner = smd->crease_inner; | 
					
						
							|  |  |  | 	tsmd->crease_outer = smd->crease_outer; | 
					
						
							|  |  |  | 	tsmd->crease_rim = smd->crease_rim; | 
					
						
							|  |  |  | 	tsmd->flag = smd->flag; | 
					
						
							| 
									
										
										
										
											2011-10-19 23:10:54 +00:00
										 |  |  | 	BLI_strncpy(tsmd->defgrp_name, smd->defgrp_name, sizeof(tsmd->defgrp_name)); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-14 06:29:17 +00:00
										 |  |  | static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) | 
					
						
							| 
									
										
										
										
											2010-06-03 22:08:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	SolidifyModifierData *smd = (SolidifyModifierData*) md; | 
					
						
							|  |  |  | 	CustomDataMask dataMask = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ask for vertexgroups if we need them */ | 
					
						
							| 
									
										
										
										
											2010-10-21 01:55:39 +00:00
										 |  |  | 	if(smd->defgrp_name[0]) dataMask |= CD_MASK_MDEFORMVERT; | 
					
						
							| 
									
										
										
										
											2010-06-03 22:08:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return dataMask; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-14 06:29:17 +00:00
										 |  |  | static DerivedMesh *applyModifier(ModifierData *md, Object *ob,  | 
					
						
							|  |  |  | 						DerivedMesh *dm, | 
					
						
							|  |  |  | 						int UNUSED(useRenderParams), | 
					
						
							|  |  |  | 						int UNUSED(isFinalCalc)) | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							| 
									
										
										
										
											2012-01-19 23:51:40 +00:00
										 |  |  | 	DerivedMesh *result; | 
					
						
							| 
									
										
										
										
											2010-10-21 04:21:09 +00:00
										 |  |  | 	const SolidifyModifierData *smd = (SolidifyModifierData*) md; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	MVert *mv, *mvert, *orig_mvert; | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 	MEdge *ed, *medge, *orig_medge; | 
					
						
							|  |  |  | 	MLoop *ml, *mloop, *orig_mloop; | 
					
						
							|  |  |  | 	MPoly *mp, *mpoly, *orig_mpoly; | 
					
						
							| 
									
										
										
										
											2010-10-21 04:21:09 +00:00
										 |  |  | 	const int numVerts = dm->getNumVerts(dm); | 
					
						
							|  |  |  | 	const int numEdges = dm->getNumEdges(dm); | 
					
						
							| 
									
										
										
										
											2011-11-29 13:01:51 +00:00
										 |  |  | 	const int numFaces = dm->getNumPolys(dm); | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 	int numLoops=0, newLoops=0, newFaces=0, newEdges=0; | 
					
						
							|  |  |  | 	int j; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2011-03-03 05:09:07 +00:00
										 |  |  | 	/* only use material offsets if we have 2 or more materials  */ | 
					
						
							|  |  |  | 	const short mat_nr_max= ob->totcol > 1 ? ob->totcol - 1 : 0; | 
					
						
							|  |  |  | 	const short mat_ofs= mat_nr_max ? smd->mat_ofs : 0; | 
					
						
							| 
									
										
										
										
											2011-08-28 21:20:10 +00:00
										 |  |  | 	/* const short mat_ofs_rim= mat_nr_max ? smd->mat_ofs_rim : 0; */ /* UNUSED */ | 
					
						
							| 
									
										
										
										
											2011-03-03 05:09:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	/* use for edges */ | 
					
						
							|  |  |  | 	int *new_vert_arr= NULL; | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 	BLI_array_declare(new_vert_arr); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	int *new_edge_arr= NULL; | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 	BLI_array_declare(new_edge_arr); | 
					
						
							|  |  |  | 	int *old_vert_arr = MEM_callocN(sizeof(int)*numVerts, "old_vert_arr in solidify"); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	int *edge_users= NULL; | 
					
						
							|  |  |  | 	char *edge_order= NULL; | 
					
						
							| 
									
										
										
										
											2011-06-01 19:30:19 +00:00
										 |  |  | 	int *edge_origIndex; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	float (*vert_nors)[3]= NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-14 06:43:58 +00:00
										 |  |  | 	const float ofs_orig=				- (((-smd->offset_fac + 1.0f) * 0.5f) * smd->offset); | 
					
						
							|  |  |  | 	const float ofs_new= smd->offset	- (((-smd->offset_fac + 1.0f) * 0.5f) * smd->offset); | 
					
						
							|  |  |  | 	const float offset_fac_vg= smd->offset_fac_vg; | 
					
						
							|  |  |  | 	const float offset_fac_vg_inv= 1.0f - smd->offset_fac_vg; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* weights */ | 
					
						
							| 
									
										
										
										
											2011-07-11 09:15:20 +00:00
										 |  |  | 	MDeformVert *dvert, *dv= NULL; | 
					
						
							| 
									
										
										
										
											2010-10-21 04:21:09 +00:00
										 |  |  | 	const int defgrp_invert = ((smd->flag & MOD_SOLIDIFY_VGROUP_INV) != 0); | 
					
						
							| 
									
										
										
										
											2011-07-11 09:15:20 +00:00
										 |  |  | 	int defgrp_index; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-11 09:15:20 +00:00
										 |  |  | 	modifier_get_vgroup(ob, dm, smd->defgrp_name, &dvert, &defgrp_index); | 
					
						
							| 
									
										
										
										
											2012-01-19 23:51:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 	numLoops = dm->numLoopData; | 
					
						
							|  |  |  | 	newLoops = 0; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2012-01-19 23:51:40 +00:00
										 |  |  | 	orig_mvert = dm->getVertArray(dm); | 
					
						
							|  |  |  | 	orig_medge = dm->getEdgeArray(dm); | 
					
						
							|  |  |  | 	orig_mloop = dm->getLoopArray(dm); | 
					
						
							|  |  |  | 	orig_mpoly = dm->getPolyArray(dm); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if(smd->flag & MOD_SOLIDIFY_RIM) { | 
					
						
							|  |  |  | 		EdgeHash *edgehash = BLI_edgehash_new(); | 
					
						
							|  |  |  | 		EdgeHashIterator *ehi; | 
					
						
							| 
									
										
										
										
											2011-12-28 10:06:10 +00:00
										 |  |  | 		unsigned int v1, v2; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 		int eidx; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for(i=0, mv=orig_mvert; i<numVerts; i++, mv++) { | 
					
						
							|  |  |  | 			mv->flag &= ~ME_VERT_TMP_TAG; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for(i=0, ed=orig_medge; i<numEdges; i++, ed++) { | 
					
						
							|  |  |  | 			BLI_edgehash_insert(edgehash, ed->v1, ed->v2, SET_INT_IN_POINTER(i)); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define INVALID_UNUSED -1
 | 
					
						
							|  |  |  | #define INVALID_PAIR -2
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define ADD_EDGE_USER(_v1, _v2, edge_ord) \
 | 
					
						
							| 
									
										
										
										
											2011-12-28 07:10:27 +00:00
										 |  |  | 		{ \ | 
					
						
							|  |  |  | 			const unsigned int ml_v1 = _v1; \ | 
					
						
							|  |  |  | 			const unsigned int ml_v2 = _v2; \ | 
					
						
							|  |  |  | 			eidx= GET_INT_FROM_POINTER(BLI_edgehash_lookup(edgehash, ml_v1, ml_v2)); \ | 
					
						
							|  |  |  | 			if(edge_users[eidx] == INVALID_UNUSED) { \ | 
					
						
							|  |  |  | 				ed= orig_medge + eidx; \ | 
					
						
							|  |  |  | 				edge_users[eidx] = (ml_v1 < ml_v2) == (ed->v1 < ed->v2) ? i : (i + numFaces); \ | 
					
						
							|  |  |  | 				edge_order[eidx] = edge_ord; \ | 
					
						
							|  |  |  | 			} \ | 
					
						
							|  |  |  | 			else { \ | 
					
						
							|  |  |  | 				edge_users[eidx] = INVALID_PAIR; \ | 
					
						
							|  |  |  | 			} \ | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		edge_users= MEM_mallocN(sizeof(int) * numEdges, "solid_mod edges"); | 
					
						
							|  |  |  | 		edge_order= MEM_mallocN(sizeof(char) * numEdges, "solid_mod eorder"); | 
					
						
							|  |  |  | 		memset(edge_users, INVALID_UNUSED, sizeof(int) * numEdges); | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 		 | 
					
						
							|  |  |  | 		for (i=0, mp=orig_mpoly; i<numFaces; i++, mp++) { | 
					
						
							|  |  |  | 			MLoop *ml; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			for (ml=orig_mloop + mp->loopstart, j=0; j<mp->totloop; ml++, j++) { | 
					
						
							| 
									
										
										
										
											2011-12-28 07:10:27 +00:00
										 |  |  | 				ADD_EDGE_USER(ml->v, ME_POLY_LOOP_NEXT(orig_mloop, mp, j)->v, j); | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 			}	 | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #undef ADD_EDGE_USER
 | 
					
						
							|  |  |  | #undef INVALID_UNUSED
 | 
					
						
							|  |  |  | #undef INVALID_PAIR
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ehi= BLI_edgehashIterator_new(edgehash); | 
					
						
							|  |  |  | 		for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { | 
					
						
							| 
									
										
										
										
											2011-02-20 15:48:01 +00:00
										 |  |  | 			eidx= GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi)); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 			if(edge_users[eidx] >= 0) { | 
					
						
							|  |  |  | 				BLI_edgehashIterator_getKey(ehi, &v1, &v2); | 
					
						
							|  |  |  | 				orig_mvert[v1].flag |= ME_VERT_TMP_TAG; | 
					
						
							|  |  |  | 				orig_mvert[v2].flag |= ME_VERT_TMP_TAG; | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 				BLI_array_append(new_edge_arr, eidx); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 				newFaces++; | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 				newLoops += 4; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		BLI_edgehashIterator_free(ehi); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for(i=0, mv=orig_mvert; i<numVerts; i++, mv++) { | 
					
						
							|  |  |  | 			if(mv->flag & ME_VERT_TMP_TAG) { | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 				old_vert_arr[i] = BLI_array_count(new_vert_arr); | 
					
						
							|  |  |  | 				BLI_array_append(new_vert_arr, i); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 				newEdges++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				mv->flag &= ~ME_VERT_TMP_TAG; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		BLI_edgehash_free(edgehash, NULL); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(smd->flag & MOD_SOLIDIFY_NORMAL_CALC) { | 
					
						
							|  |  |  | 		vert_nors= MEM_callocN(sizeof(float) * numVerts * 3, "mod_solid_vno_hq"); | 
					
						
							|  |  |  | 		dm_calc_normal(dm, vert_nors); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 	result = CDDM_from_template(dm, numVerts * 2, (numEdges * 2) + newEdges, 0, (numLoops*2) + newLoops, (numFaces * 2) + newFaces); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 	mpoly = CDDM_get_polys(result); | 
					
						
							|  |  |  | 	mloop = CDDM_get_loops(result); | 
					
						
							|  |  |  | 	medge = CDDM_get_edges(result); | 
					
						
							|  |  |  | 	mvert = CDDM_get_verts(result); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	DM_copy_edge_data(dm, result, 0, 0, numEdges); | 
					
						
							|  |  |  | 	DM_copy_edge_data(dm, result, 0, numEdges, numEdges); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	DM_copy_vert_data(dm, result, 0, 0, numVerts); | 
					
						
							|  |  |  | 	DM_copy_vert_data(dm, result, 0, numVerts, numVerts); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 	DM_copy_loop_data(dm, result, 0, 0, numLoops); | 
					
						
							|  |  |  | 	DM_copy_loop_data(dm, result, 0, numLoops, numLoops); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-29 05:09:54 +00:00
										 |  |  | 	DM_copy_poly_data(dm, result, 0, 0, numFaces); | 
					
						
							|  |  |  | 	DM_copy_poly_data(dm, result, 0, numFaces, numFaces); | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/*flip normals*/ | 
					
						
							|  |  |  | 	mp = mpoly + numFaces; | 
					
						
							|  |  |  | 	for (i=0; i<dm->numPolyData; i++, mp++) { | 
					
						
							|  |  |  | 		MLoop *ml2; | 
					
						
							|  |  |  | 		int e; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ml2 = mloop + mp->loopstart + dm->numLoopData; | 
					
						
							|  |  |  | 		for (j=0; j<mp->totloop; j++) { | 
					
						
							|  |  |  | 			CustomData_copy_data(&dm->loopData, &result->loopData, mp->loopstart+j,  | 
					
						
							|  |  |  | 			                     mp->loopstart+(mp->totloop-j-1)+dm->numLoopData, 1); | 
					
						
							| 
									
										
										
										
											2011-03-03 05:09:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			if(mat_ofs) { | 
					
						
							| 
									
										
										
										
											2011-04-15 01:19:13 +00:00
										 |  |  | 				mp->mat_nr += mat_ofs; | 
					
						
							|  |  |  | 				CLAMP(mp->mat_nr, 0, mat_nr_max); | 
					
						
							| 
									
										
										
										
											2011-03-03 05:09:07 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		e = ml2[0].e; | 
					
						
							|  |  |  | 		for (j=0; j<mp->totloop-1; j++) { | 
					
						
							|  |  |  | 			ml2[j].e = ml2[j+1].e; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		ml2[mp->totloop-1].e = e; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		mp->loopstart += dm->numLoopData; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		for (j=0; j<mp->totloop; j++) { | 
					
						
							|  |  |  | 			ml2[j].e += numEdges; | 
					
						
							|  |  |  | 			ml2[j].v += numVerts; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(i=0, ed=medge+numEdges; i<numEdges; i++, ed++) { | 
					
						
							|  |  |  | 		ed->v1 += numVerts; | 
					
						
							|  |  |  | 		ed->v2 += numVerts; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* note, copied vertex layers dont have flipped normals yet. do this after applying offset */ | 
					
						
							|  |  |  | 	if((smd->flag & MOD_SOLIDIFY_EVEN) == 0) { | 
					
						
							|  |  |  | 		/* no even thickness, very simple */ | 
					
						
							|  |  |  | 		float scalar_short; | 
					
						
							|  |  |  | 		float scalar_short_vgroup; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if(ofs_new != 0.0f) { | 
					
						
							|  |  |  | 			scalar_short= scalar_short_vgroup= ofs_new / 32767.0f; | 
					
						
							|  |  |  | 			mv= mvert + ((ofs_new >= ofs_orig) ? 0 : numVerts); | 
					
						
							|  |  |  | 			dv= dvert; | 
					
						
							|  |  |  | 			for(i=0; i<numVerts; i++, mv++) { | 
					
						
							|  |  |  | 				if(dv) { | 
					
						
							| 
									
										
										
										
											2011-08-14 06:43:58 +00:00
										 |  |  | 					if(defgrp_invert)	scalar_short_vgroup = 1.0f - defvert_find_weight(dv, defgrp_index); | 
					
						
							|  |  |  | 					else				scalar_short_vgroup = defvert_find_weight(dv, defgrp_index); | 
					
						
							|  |  |  | 					scalar_short_vgroup= (offset_fac_vg + (scalar_short_vgroup * offset_fac_vg_inv)) * scalar_short; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 					dv++; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				VECADDFAC(mv->co, mv->co, mv->no, scalar_short_vgroup); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if(ofs_orig != 0.0f) { | 
					
						
							|  |  |  | 			scalar_short= scalar_short_vgroup= ofs_orig / 32767.0f; | 
					
						
							|  |  |  | 			mv= mvert + ((ofs_new >= ofs_orig) ? numVerts : 0); /* same as above but swapped, intentional use of 'ofs_new' */ | 
					
						
							|  |  |  | 			dv= dvert; | 
					
						
							|  |  |  | 			for(i=0; i<numVerts; i++, mv++) { | 
					
						
							|  |  |  | 				if(dv) { | 
					
						
							| 
									
										
										
										
											2011-08-14 06:43:58 +00:00
										 |  |  | 					if(defgrp_invert)	scalar_short_vgroup = 1.0f - defvert_find_weight(dv, defgrp_index); | 
					
						
							|  |  |  | 					else				scalar_short_vgroup = defvert_find_weight(dv, defgrp_index); | 
					
						
							|  |  |  | 					scalar_short_vgroup= (offset_fac_vg + (scalar_short_vgroup * offset_fac_vg_inv)) * scalar_short; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 					dv++; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				VECADDFAC(mv->co, mv->co, mv->no, scalar_short_vgroup); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		/* make a face normal layer if not present */ | 
					
						
							|  |  |  | 		float (*face_nors)[3]; | 
					
						
							|  |  |  | 		int face_nors_calc= 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* same as EM_solidify() in editmesh_lib.c */ | 
					
						
							|  |  |  | 		float *vert_angles= MEM_callocN(sizeof(float) * numVerts * 2, "mod_solid_pair"); /* 2 in 1 */ | 
					
						
							|  |  |  | 		float *vert_accum= vert_angles + numVerts; | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 		float *face_angles = NULL; | 
					
						
							| 
									
										
										
										
											2011-11-29 04:11:17 +00:00
										 |  |  | 		BLI_array_staticdeclare(face_angles, 16); /* BM_NGON_STACK_SIZE */ | 
					
						
							| 
									
										
										
										
											2011-02-20 15:48:01 +00:00
										 |  |  | 		int j, vidx; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 		face_nors = CustomData_get_layer(&dm->polyData, CD_NORMAL); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 		if(!face_nors) { | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 			face_nors = CustomData_add_layer(&dm->polyData, CD_NORMAL, CD_CALLOC, NULL, dm->numPolyData); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 			face_nors_calc= 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if(vert_nors==NULL) { | 
					
						
							|  |  |  | 			vert_nors= MEM_mallocN(sizeof(float) * numVerts * 3, "mod_solid_vno"); | 
					
						
							|  |  |  | 			for(i=0, mv=mvert; i<numVerts; i++, mv++) { | 
					
						
							|  |  |  | 				normal_short_to_float_v3(vert_nors[i], mv->no); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 		for (i=0, mp=mpoly; i<numFaces; i++, mp++) { | 
					
						
							| 
									
										
										
										
											2011-12-28 04:43:29 +00:00
										 |  |  | 			mesh_calc_poly_normal(mp, &mloop[mp->loopstart], mvert, face_nors[i]); | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 			 | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 			/* just added, calc the normal */ | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 			BLI_array_empty(face_angles); | 
					
						
							|  |  |  | 			for (j=0, ml=mloop+mp->loopstart; j<mp->totloop; j++, ml++) { | 
					
						
							| 
									
										
										
										
											2011-12-28 07:10:27 +00:00
										 |  |  | 				MLoop *ml_prev = ME_POLY_LOOP_PREV(mloop, mp, j); | 
					
						
							|  |  |  | 				MLoop *ml_next = ME_POLY_LOOP_NEXT(mloop, mp, j); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 				float e1[3], e2[3], angle; | 
					
						
							|  |  |  | 				 | 
					
						
							| 
									
										
										
										
											2011-12-28 07:10:27 +00:00
										 |  |  | 				sub_v3_v3v3(e1, mvert[ml_next->v].co, mvert[ml->v].co); | 
					
						
							|  |  |  | 				sub_v3_v3v3(e2, mvert[ml_prev->v].co, mvert[ml->v].co); | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 				angle = M_PI - angle_normalized_v3v3(e1, e2); | 
					
						
							|  |  |  | 				BLI_array_append(face_angles, angle); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 			 | 
					
						
							|  |  |  | 			for (j=0, ml=mloop+mp->loopstart; j<mp->totloop; j++, ml++) { | 
					
						
							|  |  |  | 				vidx = ml->v; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 				vert_accum[vidx] += face_angles[j]; | 
					
						
							|  |  |  | 				vert_angles[vidx]+= shell_angle_to_dist(angle_normalized_v3v3(vert_nors[vidx], face_nors[i])) * face_angles[j]; | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 		BLI_array_free(face_angles); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* vertex group support */ | 
					
						
							|  |  |  | 		if(dvert) { | 
					
						
							| 
									
										
										
										
											2011-08-14 06:43:58 +00:00
										 |  |  | 			float scalar; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 			dv= dvert; | 
					
						
							|  |  |  | 			if(defgrp_invert) { | 
					
						
							|  |  |  | 				for(i=0; i<numVerts; i++, dv++) { | 
					
						
							| 
									
										
										
										
											2011-08-14 06:43:58 +00:00
										 |  |  | 					scalar= 1.0f - defvert_find_weight(dv, defgrp_index); | 
					
						
							|  |  |  | 					scalar= offset_fac_vg + (scalar * offset_fac_vg_inv); | 
					
						
							|  |  |  | 					vert_angles[i] *= scalar; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				for(i=0; i<numVerts; i++, dv++) { | 
					
						
							| 
									
										
										
										
											2011-08-14 06:43:58 +00:00
										 |  |  | 					scalar= defvert_find_weight(dv, defgrp_index); | 
					
						
							|  |  |  | 					scalar= offset_fac_vg + (scalar * offset_fac_vg_inv); | 
					
						
							|  |  |  | 					vert_angles[i] *= scalar; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if(ofs_new) { | 
					
						
							|  |  |  | 			mv= mvert + ((ofs_new >= ofs_orig) ? 0 : numVerts); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			for(i=0; i<numVerts; i++, mv++) { | 
					
						
							|  |  |  | 				if(vert_accum[i]) { /* zero if unselected */ | 
					
						
							|  |  |  | 					madd_v3_v3fl(mv->co, vert_nors[i], ofs_new * (vert_angles[i] / vert_accum[i])); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if(ofs_orig) { | 
					
						
							|  |  |  | 			mv= mvert + ((ofs_new >= ofs_orig) ? numVerts : 0); /* same as above but swapped, intentional use of 'ofs_new' */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			for(i=0; i<numVerts; i++, mv++) { | 
					
						
							|  |  |  | 				if(vert_accum[i]) { /* zero if unselected */ | 
					
						
							|  |  |  | 					madd_v3_v3fl(mv->co, vert_nors[i], ofs_orig * (vert_angles[i] / vert_accum[i])); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		MEM_freeN(vert_angles); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(vert_nors) | 
					
						
							|  |  |  | 		MEM_freeN(vert_nors); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* flip vertex normals for copied verts */ | 
					
						
							|  |  |  | 	mv= mvert + numVerts; | 
					
						
							|  |  |  | 	for(i=0; i<numVerts; i++, mv++) { | 
					
						
							|  |  |  | 		mv->no[0]= -mv->no[0]; | 
					
						
							|  |  |  | 		mv->no[1]= -mv->no[1]; | 
					
						
							|  |  |  | 		mv->no[2]= -mv->no[2]; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(smd->flag & MOD_SOLIDIFY_RIM) { | 
					
						
							| 
									
										
										
										
											2011-09-22 16:57:16 +00:00
										 |  |  | 		int *origindex; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 		 | 
					
						
							|  |  |  | 		/* bugger, need to re-calculate the normals for the new edge faces.
 | 
					
						
							|  |  |  | 		 * This could be done in many ways, but probably the quickest way is to calculate the average normals for side faces only. | 
					
						
							|  |  |  | 		 * Then blend them with the normals of the edge verts. | 
					
						
							|  |  |  | 		 *  | 
					
						
							|  |  |  | 		 * at the moment its easiest to allocate an entire array for every vertex, even though we only need edge verts - campbell | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | #define SOLIDIFY_SIDE_NORMALS
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef SOLIDIFY_SIDE_NORMALS
 | 
					
						
							|  |  |  | 		/* annoying to allocate these since we only need the edge verts, */ | 
					
						
							|  |  |  | 		float (*edge_vert_nos)[3]= MEM_callocN(sizeof(float) * numVerts * 3, "solidify_edge_nos"); | 
					
						
							|  |  |  | 		float nor[3]; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 		const unsigned char crease_rim= smd->crease_rim * 255.0f; | 
					
						
							|  |  |  | 		const unsigned char crease_outer= smd->crease_outer * 255.0f; | 
					
						
							|  |  |  | 		const unsigned char crease_inner= smd->crease_inner * 255.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* add faces & edges */ | 
					
						
							| 
									
										
										
										
											2011-09-22 16:57:16 +00:00
										 |  |  | 		origindex= result->getEdgeDataArray(result, CD_ORIGINDEX); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 		ed= medge + (numEdges * 2); | 
					
						
							|  |  |  | 		for(i=0; i<newEdges; i++, ed++) { | 
					
						
							|  |  |  | 			ed->v1= new_vert_arr[i]; | 
					
						
							|  |  |  | 			ed->v2= new_vert_arr[i] + numVerts; | 
					
						
							|  |  |  | 			ed->flag |= ME_EDGEDRAW; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-22 16:57:16 +00:00
										 |  |  | 			origindex[numEdges * 2 + i]= ORIGINDEX_NONE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 			if(crease_rim) | 
					
						
							|  |  |  | 				ed->crease= crease_rim; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* faces */ | 
					
						
							| 
									
										
										
										
											2011-10-27 12:17:02 +00:00
										 |  |  | 		edge_origIndex = origindex; | 
					
						
							| 
									
										
										
										
											2011-11-29 05:09:54 +00:00
										 |  |  | 		origindex = DM_get_poly_data_layer(result, CD_ORIGINDEX); | 
					
						
							| 
									
										
										
										
											2011-06-01 19:30:19 +00:00
										 |  |  | 		 | 
					
						
							| 
									
										
										
										
											2011-10-27 12:17:02 +00:00
										 |  |  | 		mp = mpoly + (numFaces * 2); | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 		ml = mloop + (numLoops * 2); | 
					
						
							|  |  |  | 		j = 0; | 
					
						
							|  |  |  | 		for(i=0; i<newFaces; i++, mp++) { | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 			int eidx= new_edge_arr[i]; | 
					
						
							|  |  |  | 			int fidx= edge_users[eidx]; | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 			int flip, k1, k2; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			if(fidx >= numFaces) { | 
					
						
							|  |  |  | 				fidx -= numFaces; | 
					
						
							|  |  |  | 				flip= 1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				flip= 0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			ed= medge + eidx; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* copy most of the face settings */ | 
					
						
							| 
									
										
										
										
											2011-11-29 05:09:54 +00:00
										 |  |  | 			DM_copy_poly_data(dm, result, fidx, (numFaces * 2) + i, 1); | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 			mp->loopstart = j+numLoops*2; | 
					
						
							| 
									
										
										
										
											2011-06-01 19:30:19 +00:00
										 |  |  | 			mp->flag = mpoly[fidx].flag; | 
					
						
							| 
									
										
										
										
											2012-01-17 13:18:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-17 13:26:59 +00:00
										 |  |  | 			/* notice we use 'mp->totloop' which is later overwritten,
 | 
					
						
							|  |  |  | 			 * we could lookup the original face but theres no point since this is a copy | 
					
						
							|  |  |  | 			 * and will have the same value, just take care when changing order of assignment */ | 
					
						
							|  |  |  | 			k1 = mpoly[fidx].loopstart + ((edge_order[eidx] + 1) % mp->totloop); | 
					
						
							|  |  |  | 			k2 = mpoly[fidx].loopstart +  (edge_order[eidx]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			mp->totloop = 4; | 
					
						
							| 
									
										
										
										
											2012-01-17 13:18:23 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			CustomData_copy_data(&dm->loopData, &result->loopData, k1, numLoops*2+j+0, 1); | 
					
						
							|  |  |  | 			CustomData_copy_data(&dm->loopData, &result->loopData, k2, numLoops*2+j+1, 1); | 
					
						
							|  |  |  | 			CustomData_copy_data(&dm->loopData, &result->loopData, k2, numLoops*2+j+2, 1); | 
					
						
							|  |  |  | 			CustomData_copy_data(&dm->loopData, &result->loopData, k1, numLoops*2+j+3, 1); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 			if(flip) { | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 				ml[j].v = ed->v1; | 
					
						
							|  |  |  | 				ml[j++].e = eidx; | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				ml[j].v = ed->v2; | 
					
						
							|  |  |  | 				ml[j++].e = numEdges*2 + old_vert_arr[ed->v2]; | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				ml[j].v = ed->v2+numVerts; | 
					
						
							|  |  |  | 				ml[j++].e = eidx+numEdges; | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				ml[j].v = ed->v1+numVerts; | 
					
						
							|  |  |  | 				ml[j++].e = numEdges*2 + old_vert_arr[ed->v1]; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							| 
									
										
										
										
											2012-01-17 13:18:23 +00:00
										 |  |  | 				ml[j].v = ed->v2; | 
					
						
							|  |  |  | 				ml[j++].e = eidx; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				ml[j].v = ed->v1; | 
					
						
							|  |  |  | 				ml[j++].e = numEdges*2 + old_vert_arr[ed->v1]; | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				ml[j].v = ed->v1+numVerts; | 
					
						
							|  |  |  | 				ml[j++].e = eidx+numEdges; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				ml[j].v = ed->v2+numVerts; | 
					
						
							|  |  |  | 				ml[j++].e = numEdges*2 + old_vert_arr[ed->v2]; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2010-06-13 13:56:13 +00:00
										 |  |  | 			 | 
					
						
							| 
									
										
										
										
											2011-06-01 19:30:19 +00:00
										 |  |  | 			if (edge_origIndex) { | 
					
						
							|  |  |  | 				edge_origIndex[ml[j-3].e] = ORIGINDEX_NONE; | 
					
						
							|  |  |  | 				edge_origIndex[ml[j-1].e] = ORIGINDEX_NONE; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-03-06 22:10:33 +00:00
										 |  |  | 			if(crease_outer) { | 
					
						
							|  |  |  | 				/* crease += crease_outer; without wrapping */ | 
					
						
							|  |  |  | 				unsigned char *cr= (unsigned char *)&(ed->crease); | 
					
						
							|  |  |  | 				int tcr= *cr + crease_outer; | 
					
						
							|  |  |  | 				*cr= tcr > 255 ? 255 : tcr; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			if(crease_inner) { | 
					
						
							| 
									
										
										
										
											2011-03-06 22:10:33 +00:00
										 |  |  | 				/* crease += crease_inner; without wrapping */ | 
					
						
							|  |  |  | 				unsigned char *cr= (unsigned char *)&(medge[numEdges + eidx].crease); | 
					
						
							|  |  |  | 				int tcr= *cr + crease_inner; | 
					
						
							|  |  |  | 				*cr= tcr > 255 ? 255 : tcr; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | #ifdef SOLIDIFY_SIDE_NORMALS
 | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 			normal_quad_v3(nor, mvert[ml[j-4].v].co, mvert[ml[j-3].v].co, mvert[ml[j-2].v].co, mvert[ml[j-1].v].co); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			add_v3_v3(edge_vert_nos[ed->v1], nor); | 
					
						
							|  |  |  | 			add_v3_v3(edge_vert_nos[ed->v2], nor); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | #ifdef SOLIDIFY_SIDE_NORMALS
 | 
					
						
							|  |  |  | 		ed= medge + (numEdges * 2); | 
					
						
							|  |  |  | 		for(i=0; i<newEdges; i++, ed++) { | 
					
						
							|  |  |  | 			float nor_cpy[3]; | 
					
						
							|  |  |  | 			short *nor_short; | 
					
						
							|  |  |  | 			int j; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			/* note, only the first vertex (lower half of the index) is calculated */ | 
					
						
							|  |  |  | 			normalize_v3_v3(nor_cpy, edge_vert_nos[ed->v1]); | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			for(j=0; j<2; j++) { /* loop over both verts of the edge */ | 
					
						
							|  |  |  | 				nor_short= mvert[*(&ed->v1 + j)].no; | 
					
						
							|  |  |  | 				normal_short_to_float_v3(nor, nor_short); | 
					
						
							|  |  |  | 				add_v3_v3(nor, nor_cpy); | 
					
						
							|  |  |  | 				normalize_v3(nor); | 
					
						
							|  |  |  | 				normal_float_to_short_v3(nor_short, nor); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		MEM_freeN(edge_vert_nos); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-17 04:12:53 +00:00
										 |  |  | 		BLI_array_free(new_vert_arr); | 
					
						
							|  |  |  | 		BLI_array_free(new_edge_arr); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 		MEM_freeN(edge_users); | 
					
						
							|  |  |  | 		MEM_freeN(edge_order); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 	if (old_vert_arr) | 
					
						
							|  |  |  | 		MEM_freeN(old_vert_arr); | 
					
						
							| 
									
										
										
										
											2011-04-15 01:19:13 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2011-04-12 12:59:37 +00:00
										 |  |  | 	/* must recalculate normals with vgroups since they can displace unevenly [#26888] */ | 
					
						
							|  |  |  | 	if(dvert) { | 
					
						
							| 
									
										
										
										
											2012-01-20 13:25:54 +00:00
										 |  |  | 		CDDM_calc_normals(result); | 
					
						
							| 
									
										
										
										
											2011-04-12 12:59:37 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-01-19 23:51:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-03 00:25:01 +00:00
										 |  |  | 	return result; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #undef SOLIDIFY_SIDE_NORMALS
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static DerivedMesh *applyModifierEM(ModifierData *md, | 
					
						
							|  |  |  | 							 Object *ob, | 
					
						
							| 
									
										
										
										
											2011-04-15 01:19:13 +00:00
										 |  |  | 							 struct BMEditMesh *UNUSED(editData), | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 							 DerivedMesh *derivedData) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return applyModifier(md, ob, derivedData, 0, 1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ModifierTypeInfo modifierType_Solidify = { | 
					
						
							|  |  |  | 	/* name */              "Solidify", | 
					
						
							|  |  |  | 	/* structName */        "SolidifyModifierData", | 
					
						
							|  |  |  | 	/* structSize */        sizeof(SolidifyModifierData), | 
					
						
							|  |  |  | 	/* type */              eModifierTypeType_Constructive, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* flags */             eModifierTypeFlag_AcceptsMesh | 
					
						
							|  |  |  | 							| eModifierTypeFlag_AcceptsCVs | 
					
						
							|  |  |  | 							| eModifierTypeFlag_SupportsMapping | 
					
						
							|  |  |  | 							| eModifierTypeFlag_SupportsEditmode | 
					
						
							|  |  |  | 							| eModifierTypeFlag_EnableInEditmode, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* copyData */          copyData, | 
					
						
							| 
									
										
										
										
											2011-02-20 15:48:01 +00:00
										 |  |  | 	/* deformVerts */       NULL, | 
					
						
							|  |  |  | 	/* deformMatrices */    NULL, | 
					
						
							|  |  |  | 	/* deformVertsEM */     NULL, | 
					
						
							|  |  |  | 	/* deformMatricesEM */  NULL, | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	/* applyModifier */     applyModifier, | 
					
						
							|  |  |  | 	/* applyModifierEM */   applyModifierEM, | 
					
						
							|  |  |  | 	/* initData */          initData, | 
					
						
							| 
									
										
										
										
											2010-06-03 22:08:14 +00:00
										 |  |  | 	/* requiredDataMask */  requiredDataMask, | 
					
						
							| 
									
										
										
										
											2011-02-20 15:48:01 +00:00
										 |  |  | 	/* freeData */          NULL, | 
					
						
							|  |  |  | 	/* isDisabled */        NULL, | 
					
						
							|  |  |  | 	/* updateDepgraph */    NULL, | 
					
						
							|  |  |  | 	/* dependsOnTime */     NULL, | 
					
						
							|  |  |  | 	/* dependsOnNormals */	NULL, | 
					
						
							|  |  |  | 	/* foreachObjectLink */ NULL, | 
					
						
							| 
									
										
										
										
											2011-08-12 18:11:22 +00:00
										 |  |  | 	/* foreachIDLink */     NULL, | 
					
						
							|  |  |  | 	/* foreachTexLink */    NULL, | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | }; |