|
Blender
V2.59
|
00001 /* 00002 * $Id: MOD_solidify.c 38300 2011-07-11 09:15:20Z blendix $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2005 by the Blender Foundation. 00021 * All rights reserved. 00022 * 00023 * Contributor(s): Daniel Dunbar 00024 * Ton Roosendaal, 00025 * Ben Batt, 00026 * Brecht Van Lommel, 00027 * Campbell Barton 00028 * 00029 * ***** END GPL LICENSE BLOCK ***** 00030 * 00031 */ 00032 00038 #include "DNA_meshdata_types.h" 00039 00040 #include "BLI_math.h" 00041 #include "BLI_edgehash.h" 00042 #include "BLI_utildefines.h" 00043 00044 #include "BKE_cdderivedmesh.h" 00045 #include "BKE_mesh.h" 00046 #include "BKE_particle.h" 00047 #include "BKE_deform.h" 00048 00049 00050 #include "MOD_modifiertypes.h" 00051 #include "MOD_util.h" 00052 00053 #include "MEM_guardedalloc.h" 00054 00055 typedef struct EdgeFaceRef { 00056 int f1; /* init as -1 */ 00057 int f2; 00058 } EdgeFaceRef; 00059 00060 static void dm_calc_normal(DerivedMesh *dm, float (*temp_nors)[3]) 00061 { 00062 int i, numVerts, numEdges, numFaces; 00063 MFace *mface, *mf; 00064 MVert *mvert, *mv; 00065 00066 float (*face_nors)[3]; 00067 float *f_no; 00068 int calc_face_nors= 0; 00069 00070 numVerts = dm->getNumVerts(dm); 00071 numEdges = dm->getNumEdges(dm); 00072 numFaces = dm->getNumFaces(dm); 00073 mface = dm->getFaceArray(dm); 00074 mvert = dm->getVertArray(dm); 00075 00076 /* we don't want to overwrite any referenced layers */ 00077 00078 /* 00079 Dosnt work here! 00080 mv = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT); 00081 cddm->mvert = mv; 00082 */ 00083 00084 face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL); 00085 if(!face_nors) { 00086 calc_face_nors = 1; 00087 face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC, NULL, numFaces); 00088 } 00089 00090 mv = mvert; 00091 mf = mface; 00092 00093 { 00094 EdgeHash *edge_hash = BLI_edgehash_new(); 00095 EdgeHashIterator *edge_iter; 00096 int edge_ref_count = 0; 00097 int ed_v1, ed_v2; /* use when getting the key */ 00098 EdgeFaceRef *edge_ref_array = MEM_callocN(numEdges * sizeof(EdgeFaceRef), "Edge Connectivity"); 00099 EdgeFaceRef *edge_ref; 00100 float edge_normal[3]; 00101 00102 /* This function adds an edge hash if its not there, and adds the face index */ 00103 #define NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(EDV1, EDV2); \ 00104 edge_ref = (EdgeFaceRef *)BLI_edgehash_lookup(edge_hash, EDV1, EDV2); \ 00105 if (!edge_ref) { \ 00106 edge_ref = &edge_ref_array[edge_ref_count]; edge_ref_count++; \ 00107 edge_ref->f1=i; \ 00108 edge_ref->f2=-1; \ 00109 BLI_edgehash_insert(edge_hash, EDV1, EDV2, edge_ref); \ 00110 } else { \ 00111 edge_ref->f2=i; \ 00112 } 00113 00114 for(i = 0; i < numFaces; i++, mf++) { 00115 f_no = face_nors[i]; 00116 00117 if(mf->v4) { 00118 if(calc_face_nors) 00119 normal_quad_v3(f_no, mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co); 00120 00121 NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v1, mf->v2); 00122 NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v2, mf->v3); 00123 NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v3, mf->v4); 00124 NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v4, mf->v1); 00125 } else { 00126 if(calc_face_nors) 00127 normal_tri_v3(f_no, mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co); 00128 00129 NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v1, mf->v2); 00130 NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v2, mf->v3); 00131 NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v3, mf->v1); 00132 } 00133 } 00134 00135 for(edge_iter = BLI_edgehashIterator_new(edge_hash); !BLI_edgehashIterator_isDone(edge_iter); BLI_edgehashIterator_step(edge_iter)) { 00136 /* Get the edge vert indices, and edge value (the face indices that use it)*/ 00137 BLI_edgehashIterator_getKey(edge_iter, (int*)&ed_v1, (int*)&ed_v2); 00138 edge_ref = BLI_edgehashIterator_getValue(edge_iter); 00139 00140 if (edge_ref->f2 != -1) { 00141 /* We have 2 faces using this edge, calculate the edges normal 00142 * using the angle between the 2 faces as a weighting */ 00143 add_v3_v3v3(edge_normal, face_nors[edge_ref->f1], face_nors[edge_ref->f2]); 00144 normalize_v3(edge_normal); 00145 mul_v3_fl(edge_normal, angle_normalized_v3v3(face_nors[edge_ref->f1], face_nors[edge_ref->f2])); 00146 } else { 00147 /* only one face attached to that edge */ 00148 /* an edge without another attached- the weight on this is 00149 * undefined, M_PI/2 is 90d in radians and that seems good enough */ 00150 mul_v3_v3fl(edge_normal, face_nors[edge_ref->f1], M_PI/2); 00151 } 00152 add_v3_v3(temp_nors[ed_v1], edge_normal); 00153 add_v3_v3(temp_nors[ed_v2], edge_normal); 00154 } 00155 BLI_edgehashIterator_free(edge_iter); 00156 BLI_edgehash_free(edge_hash, NULL); 00157 MEM_freeN(edge_ref_array); 00158 } 00159 00160 /* normalize vertex normals and assign */ 00161 for(i = 0; i < numVerts; i++, mv++) { 00162 if(normalize_v3(temp_nors[i]) == 0.0f) { 00163 normal_short_to_float_v3(temp_nors[i], mv->no); 00164 } 00165 } 00166 } 00167 00168 static void initData(ModifierData *md) 00169 { 00170 SolidifyModifierData *smd = (SolidifyModifierData*) md; 00171 smd->offset = 0.01f; 00172 smd->offset_fac = -1.0f; 00173 smd->flag = MOD_SOLIDIFY_RIM; 00174 } 00175 00176 static void copyData(ModifierData *md, ModifierData *target) 00177 { 00178 SolidifyModifierData *smd = (SolidifyModifierData*) md; 00179 SolidifyModifierData *tsmd = (SolidifyModifierData*) target; 00180 tsmd->offset = smd->offset; 00181 tsmd->offset_fac = smd->offset_fac; 00182 tsmd->crease_inner = smd->crease_inner; 00183 tsmd->crease_outer = smd->crease_outer; 00184 tsmd->crease_rim = smd->crease_rim; 00185 tsmd->flag = smd->flag; 00186 strcpy(tsmd->defgrp_name, smd->defgrp_name); 00187 } 00188 00189 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) 00190 { 00191 SolidifyModifierData *smd = (SolidifyModifierData*) md; 00192 CustomDataMask dataMask = 0; 00193 00194 /* ask for vertexgroups if we need them */ 00195 if(smd->defgrp_name[0]) dataMask |= CD_MASK_MDEFORMVERT; 00196 00197 return dataMask; 00198 } 00199 00200 00201 static DerivedMesh *applyModifier(ModifierData *md, Object *ob, 00202 DerivedMesh *dm, 00203 int UNUSED(useRenderParams), 00204 int UNUSED(isFinalCalc)) 00205 { 00206 int i; 00207 DerivedMesh *result; 00208 const SolidifyModifierData *smd = (SolidifyModifierData*) md; 00209 00210 MFace *mf, *mface, *orig_mface; 00211 MEdge *ed, *medge, *orig_medge; 00212 MVert *mv, *mvert, *orig_mvert; 00213 00214 const int numVerts = dm->getNumVerts(dm); 00215 const int numEdges = dm->getNumEdges(dm); 00216 const int numFaces = dm->getNumFaces(dm); 00217 00218 /* only use material offsets if we have 2 or more materials */ 00219 const short mat_nr_max= ob->totcol > 1 ? ob->totcol - 1 : 0; 00220 const short mat_ofs= mat_nr_max ? smd->mat_ofs : 0; 00221 const short mat_ofs_rim= mat_nr_max ? smd->mat_ofs_rim : 0; 00222 00223 /* use for edges */ 00224 int *new_vert_arr= NULL; 00225 int newFaces = 0; 00226 00227 int *new_edge_arr= NULL; 00228 int newEdges = 0; 00229 00230 int *edge_users= NULL; 00231 char *edge_order= NULL; 00232 00233 float (*vert_nors)[3]= NULL; 00234 00235 float const ofs_orig= - (((-smd->offset_fac + 1.0f) * 0.5f) * smd->offset); 00236 float const ofs_new= smd->offset - (((-smd->offset_fac + 1.0f) * 0.5f) * smd->offset); 00237 00238 /* weights */ 00239 MDeformVert *dvert, *dv= NULL; 00240 const int defgrp_invert = ((smd->flag & MOD_SOLIDIFY_VGROUP_INV) != 0); 00241 int defgrp_index; 00242 00243 modifier_get_vgroup(ob, dm, smd->defgrp_name, &dvert, &defgrp_index); 00244 00245 orig_mface = dm->getFaceArray(dm); 00246 orig_medge = dm->getEdgeArray(dm); 00247 orig_mvert = dm->getVertArray(dm); 00248 00249 if(smd->flag & MOD_SOLIDIFY_RIM) { 00250 EdgeHash *edgehash = BLI_edgehash_new(); 00251 EdgeHashIterator *ehi; 00252 int v1, v2; 00253 int eidx; 00254 00255 for(i=0, mv=orig_mvert; i<numVerts; i++, mv++) { 00256 mv->flag &= ~ME_VERT_TMP_TAG; 00257 } 00258 00259 for(i=0, ed=orig_medge; i<numEdges; i++, ed++) { 00260 BLI_edgehash_insert(edgehash, ed->v1, ed->v2, SET_INT_IN_POINTER(i)); 00261 } 00262 00263 #define INVALID_UNUSED -1 00264 #define INVALID_PAIR -2 00265 00266 #define ADD_EDGE_USER(_v1, _v2, edge_ord) \ 00267 eidx= GET_INT_FROM_POINTER(BLI_edgehash_lookup(edgehash, _v1, _v2)); \ 00268 if(edge_users[eidx] == INVALID_UNUSED) { \ 00269 ed= orig_medge + eidx; \ 00270 edge_users[eidx]= (_v1 < _v2) == (ed->v1 < ed->v2) ? i:(i+numFaces); \ 00271 edge_order[eidx]= edge_ord; \ 00272 } else { \ 00273 edge_users[eidx]= INVALID_PAIR; \ 00274 } \ 00275 00276 00277 edge_users= MEM_mallocN(sizeof(int) * numEdges, "solid_mod edges"); 00278 edge_order= MEM_mallocN(sizeof(char) * numEdges, "solid_mod eorder"); 00279 memset(edge_users, INVALID_UNUSED, sizeof(int) * numEdges); 00280 00281 for(i=0, mf=orig_mface; i<numFaces; i++, mf++) { 00282 if(mf->v4) { 00283 ADD_EDGE_USER(mf->v1, mf->v2, 0); 00284 ADD_EDGE_USER(mf->v2, mf->v3, 1); 00285 ADD_EDGE_USER(mf->v3, mf->v4, 2); 00286 ADD_EDGE_USER(mf->v4, mf->v1, 3); 00287 } 00288 else { 00289 ADD_EDGE_USER(mf->v1, mf->v2, 0); 00290 ADD_EDGE_USER(mf->v2, mf->v3, 1); 00291 ADD_EDGE_USER(mf->v3, mf->v1, 2); 00292 } 00293 } 00294 00295 #undef ADD_EDGE_USER 00296 #undef INVALID_UNUSED 00297 #undef INVALID_PAIR 00298 00299 00300 new_edge_arr= MEM_callocN(sizeof(int) * numEdges, "solid_mod arr"); 00301 00302 ehi= BLI_edgehashIterator_new(edgehash); 00303 for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { 00304 eidx= GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi)); 00305 if(edge_users[eidx] >= 0) { 00306 BLI_edgehashIterator_getKey(ehi, &v1, &v2); 00307 orig_mvert[v1].flag |= ME_VERT_TMP_TAG; 00308 orig_mvert[v2].flag |= ME_VERT_TMP_TAG; 00309 new_edge_arr[newFaces]= eidx; 00310 newFaces++; 00311 } 00312 } 00313 BLI_edgehashIterator_free(ehi); 00314 00315 00316 00317 new_vert_arr= MEM_callocN(sizeof(int) * numVerts, "solid_mod new_varr"); 00318 for(i=0, mv=orig_mvert; i<numVerts; i++, mv++) { 00319 if(mv->flag & ME_VERT_TMP_TAG) { 00320 new_vert_arr[newEdges] = i; 00321 newEdges++; 00322 00323 mv->flag &= ~ME_VERT_TMP_TAG; 00324 } 00325 } 00326 00327 BLI_edgehash_free(edgehash, NULL); 00328 } 00329 00330 if(smd->flag & MOD_SOLIDIFY_NORMAL_CALC) { 00331 vert_nors= MEM_callocN(sizeof(float) * numVerts * 3, "mod_solid_vno_hq"); 00332 dm_calc_normal(dm, vert_nors); 00333 } 00334 00335 result = CDDM_from_template(dm, numVerts * 2, (numEdges * 2) + newEdges, (numFaces * 2) + newFaces); 00336 00337 mface = result->getFaceArray(result); 00338 medge = result->getEdgeArray(result); 00339 mvert = result->getVertArray(result); 00340 00341 DM_copy_face_data(dm, result, 0, 0, numFaces); 00342 DM_copy_face_data(dm, result, 0, numFaces, numFaces); 00343 00344 DM_copy_edge_data(dm, result, 0, 0, numEdges); 00345 DM_copy_edge_data(dm, result, 0, numEdges, numEdges); 00346 00347 DM_copy_vert_data(dm, result, 0, 0, numVerts); 00348 DM_copy_vert_data(dm, result, 0, numVerts, numVerts); 00349 00350 { 00351 static int corner_indices[4] = {2, 1, 0, 3}; 00352 int is_quad; 00353 00354 for(i=0, mf=mface+numFaces; i<numFaces; i++, mf++) { 00355 mf->v1 += numVerts; 00356 mf->v2 += numVerts; 00357 mf->v3 += numVerts; 00358 if(mf->v4) 00359 mf->v4 += numVerts; 00360 00361 /* Flip face normal */ 00362 { 00363 is_quad = mf->v4; 00364 SWAP(int, mf->v1, mf->v3); 00365 DM_swap_face_data(result, i+numFaces, corner_indices); 00366 test_index_face(mf, &result->faceData, numFaces, is_quad ? 4:3); 00367 } 00368 00369 if(mat_ofs) { 00370 mf->mat_nr += mat_ofs; 00371 CLAMP(mf->mat_nr, 0, mat_nr_max); 00372 } 00373 } 00374 } 00375 00376 for(i=0, ed=medge+numEdges; i<numEdges; i++, ed++) { 00377 ed->v1 += numVerts; 00378 ed->v2 += numVerts; 00379 } 00380 00381 /* note, copied vertex layers dont have flipped normals yet. do this after applying offset */ 00382 if((smd->flag & MOD_SOLIDIFY_EVEN) == 0) { 00383 /* no even thickness, very simple */ 00384 float scalar_short; 00385 float scalar_short_vgroup; 00386 00387 00388 if(ofs_new != 0.0f) { 00389 scalar_short= scalar_short_vgroup= ofs_new / 32767.0f; 00390 mv= mvert + ((ofs_new >= ofs_orig) ? 0 : numVerts); 00391 dv= dvert; 00392 for(i=0; i<numVerts; i++, mv++) { 00393 if(dv) { 00394 if(defgrp_invert) scalar_short_vgroup = scalar_short * (1.0f - defvert_find_weight(dv, defgrp_index)); 00395 else scalar_short_vgroup = scalar_short * defvert_find_weight(dv, defgrp_index); 00396 dv++; 00397 } 00398 VECADDFAC(mv->co, mv->co, mv->no, scalar_short_vgroup); 00399 } 00400 } 00401 00402 if(ofs_orig != 0.0f) { 00403 scalar_short= scalar_short_vgroup= ofs_orig / 32767.0f; 00404 mv= mvert + ((ofs_new >= ofs_orig) ? numVerts : 0); /* same as above but swapped, intentional use of 'ofs_new' */ 00405 dv= dvert; 00406 for(i=0; i<numVerts; i++, mv++) { 00407 if(dv) { 00408 if(defgrp_invert) scalar_short_vgroup = scalar_short * (1.0f - defvert_find_weight(dv, defgrp_index)); 00409 else scalar_short_vgroup = scalar_short * defvert_find_weight(dv, defgrp_index); 00410 dv++; 00411 } 00412 VECADDFAC(mv->co, mv->co, mv->no, scalar_short_vgroup); 00413 } 00414 } 00415 00416 } 00417 else { 00418 /* make a face normal layer if not present */ 00419 float (*face_nors)[3]; 00420 int face_nors_calc= 0; 00421 00422 /* same as EM_solidify() in editmesh_lib.c */ 00423 float *vert_angles= MEM_callocN(sizeof(float) * numVerts * 2, "mod_solid_pair"); /* 2 in 1 */ 00424 float *vert_accum= vert_angles + numVerts; 00425 float face_angles[4]; 00426 int j, vidx; 00427 00428 face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL); 00429 if(!face_nors) { 00430 face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC, NULL, dm->numFaceData); 00431 face_nors_calc= 1; 00432 } 00433 00434 if(vert_nors==NULL) { 00435 vert_nors= MEM_mallocN(sizeof(float) * numVerts * 3, "mod_solid_vno"); 00436 for(i=0, mv=mvert; i<numVerts; i++, mv++) { 00437 normal_short_to_float_v3(vert_nors[i], mv->no); 00438 } 00439 } 00440 00441 for(i=0, mf=mface; i<numFaces; i++, mf++) { 00442 00443 /* just added, calc the normal */ 00444 if(face_nors_calc) { 00445 if(mf->v4) 00446 normal_quad_v3(face_nors[i], mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co, mvert[mf->v4].co); 00447 else 00448 normal_tri_v3(face_nors[i] , mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co); 00449 } 00450 00451 if(mf->v4) { 00452 angle_quad_v3(face_angles, mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co, mvert[mf->v4].co); 00453 j= 3; 00454 } 00455 else { 00456 angle_tri_v3(face_angles, mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co); 00457 j= 2; 00458 } 00459 00460 do { 00461 vidx = *(&mf->v1 + j); 00462 vert_accum[vidx] += face_angles[j]; 00463 vert_angles[vidx]+= shell_angle_to_dist(angle_normalized_v3v3(vert_nors[vidx], face_nors[i])) * face_angles[j]; 00464 } while(j--); 00465 } 00466 00467 /* vertex group support */ 00468 if(dvert) { 00469 dv= dvert; 00470 if(defgrp_invert) { 00471 for(i=0; i<numVerts; i++, dv++) { 00472 vert_angles[i] *= (1.0f - defvert_find_weight(dv, defgrp_index)); 00473 } 00474 } 00475 else { 00476 for(i=0; i<numVerts; i++, dv++) { 00477 vert_angles[i] *= defvert_find_weight(dv, defgrp_index); 00478 } 00479 } 00480 } 00481 00482 if(ofs_new) { 00483 mv= mvert + ((ofs_new >= ofs_orig) ? 0 : numVerts); 00484 00485 for(i=0; i<numVerts; i++, mv++) { 00486 if(vert_accum[i]) { /* zero if unselected */ 00487 madd_v3_v3fl(mv->co, vert_nors[i], ofs_new * (vert_angles[i] / vert_accum[i])); 00488 } 00489 } 00490 } 00491 00492 if(ofs_orig) { 00493 mv= mvert + ((ofs_new >= ofs_orig) ? numVerts : 0); /* same as above but swapped, intentional use of 'ofs_new' */ 00494 00495 for(i=0; i<numVerts; i++, mv++) { 00496 if(vert_accum[i]) { /* zero if unselected */ 00497 madd_v3_v3fl(mv->co, vert_nors[i], ofs_orig * (vert_angles[i] / vert_accum[i])); 00498 } 00499 } 00500 } 00501 00502 MEM_freeN(vert_angles); 00503 } 00504 00505 if(vert_nors) 00506 MEM_freeN(vert_nors); 00507 00508 /* flip vertex normals for copied verts */ 00509 mv= mvert + numVerts; 00510 for(i=0; i<numVerts; i++, mv++) { 00511 mv->no[0]= -mv->no[0]; 00512 mv->no[1]= -mv->no[1]; 00513 mv->no[2]= -mv->no[2]; 00514 } 00515 00516 if(smd->flag & MOD_SOLIDIFY_RIM) { 00517 00518 00519 /* bugger, need to re-calculate the normals for the new edge faces. 00520 * This could be done in many ways, but probably the quickest way is to calculate the average normals for side faces only. 00521 * Then blend them with the normals of the edge verts. 00522 * 00523 * at the moment its easiest to allocate an entire array for every vertex, even though we only need edge verts - campbell 00524 */ 00525 00526 #define SOLIDIFY_SIDE_NORMALS 00527 00528 #ifdef SOLIDIFY_SIDE_NORMALS 00529 /* annoying to allocate these since we only need the edge verts, */ 00530 float (*edge_vert_nos)[3]= MEM_callocN(sizeof(float) * numVerts * 3, "solidify_edge_nos"); 00531 float nor[3]; 00532 #endif 00533 const unsigned char crease_rim= smd->crease_rim * 255.0f; 00534 const unsigned char crease_outer= smd->crease_outer * 255.0f; 00535 const unsigned char crease_inner= smd->crease_inner * 255.0f; 00536 00537 const int edge_indices[4][4] = { 00538 {1, 0, 0, 1}, 00539 {2, 1, 1, 2}, 00540 {3, 2, 2, 3}, 00541 {0, 3, 3, 0}}; 00542 00543 /* add faces & edges */ 00544 ed= medge + (numEdges * 2); 00545 for(i=0; i<newEdges; i++, ed++) { 00546 ed->v1= new_vert_arr[i]; 00547 ed->v2= new_vert_arr[i] + numVerts; 00548 ed->flag |= ME_EDGEDRAW; 00549 00550 if(crease_rim) 00551 ed->crease= crease_rim; 00552 } 00553 00554 /* faces */ 00555 mf= mface + (numFaces * 2); 00556 for(i=0; i<newFaces; i++, mf++) { 00557 int eidx= new_edge_arr[i]; 00558 int fidx= edge_users[eidx]; 00559 int flip; 00560 00561 if(fidx >= numFaces) { 00562 fidx -= numFaces; 00563 flip= 1; 00564 } 00565 else { 00566 flip= 0; 00567 } 00568 00569 ed= medge + eidx; 00570 00571 /* copy most of the face settings */ 00572 DM_copy_face_data(dm, result, fidx, (numFaces * 2) + i, 1); 00573 00574 if(flip) { 00575 DM_swap_face_data(result, (numFaces * 2) + i, edge_indices[edge_order[eidx]]); 00576 00577 mf->v1= ed->v1; 00578 mf->v2= ed->v2; 00579 mf->v3= ed->v2 + numVerts; 00580 mf->v4= ed->v1 + numVerts; 00581 } 00582 else { 00583 DM_swap_face_data(result, (numFaces * 2) + i, edge_indices[edge_order[eidx]]); 00584 00585 mf->v1= ed->v2; 00586 mf->v2= ed->v1; 00587 mf->v3= ed->v1 + numVerts; 00588 mf->v4= ed->v2 + numVerts; 00589 } 00590 00591 /* use the next material index if option enabled */ 00592 if(mat_ofs_rim) { 00593 mf->mat_nr += mat_ofs_rim; 00594 CLAMP(mf->mat_nr, 0, mat_nr_max); 00595 } 00596 if(crease_outer) { 00597 /* crease += crease_outer; without wrapping */ 00598 unsigned char *cr= (unsigned char *)&(ed->crease); 00599 int tcr= *cr + crease_outer; 00600 *cr= tcr > 255 ? 255 : tcr; 00601 } 00602 00603 if(crease_inner) { 00604 /* crease += crease_inner; without wrapping */ 00605 unsigned char *cr= (unsigned char *)&(medge[numEdges + eidx].crease); 00606 int tcr= *cr + crease_inner; 00607 *cr= tcr > 255 ? 255 : tcr; 00608 } 00609 00610 #ifdef SOLIDIFY_SIDE_NORMALS 00611 normal_quad_v3(nor, mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co, mvert[mf->v4].co); 00612 00613 add_v3_v3(edge_vert_nos[ed->v1], nor); 00614 add_v3_v3(edge_vert_nos[ed->v2], nor); 00615 #endif 00616 } 00617 00618 #ifdef SOLIDIFY_SIDE_NORMALS 00619 ed= medge + (numEdges * 2); 00620 for(i=0; i<newEdges; i++, ed++) { 00621 float nor_cpy[3]; 00622 short *nor_short; 00623 int j; 00624 00625 /* note, only the first vertex (lower half of the index) is calculated */ 00626 normalize_v3_v3(nor_cpy, edge_vert_nos[ed->v1]); 00627 00628 for(j=0; j<2; j++) { /* loop over both verts of the edge */ 00629 nor_short= mvert[*(&ed->v1 + j)].no; 00630 normal_short_to_float_v3(nor, nor_short); 00631 add_v3_v3(nor, nor_cpy); 00632 normalize_v3(nor); 00633 normal_float_to_short_v3(nor_short, nor); 00634 } 00635 } 00636 00637 MEM_freeN(edge_vert_nos); 00638 #endif 00639 00640 MEM_freeN(new_vert_arr); 00641 MEM_freeN(new_edge_arr); 00642 MEM_freeN(edge_users); 00643 MEM_freeN(edge_order); 00644 } 00645 00646 /* must recalculate normals with vgroups since they can displace unevenly [#26888] */ 00647 if(dvert) { 00648 CDDM_calc_normals(result); 00649 } 00650 00651 return result; 00652 } 00653 00654 #undef SOLIDIFY_SIDE_NORMALS 00655 00656 static DerivedMesh *applyModifierEM(ModifierData *md, 00657 Object *ob, 00658 struct EditMesh *UNUSED(editData), 00659 DerivedMesh *derivedData) 00660 { 00661 return applyModifier(md, ob, derivedData, 0, 1); 00662 } 00663 00664 00665 ModifierTypeInfo modifierType_Solidify = { 00666 /* name */ "Solidify", 00667 /* structName */ "SolidifyModifierData", 00668 /* structSize */ sizeof(SolidifyModifierData), 00669 /* type */ eModifierTypeType_Constructive, 00670 00671 /* flags */ eModifierTypeFlag_AcceptsMesh 00672 | eModifierTypeFlag_AcceptsCVs 00673 | eModifierTypeFlag_SupportsMapping 00674 | eModifierTypeFlag_SupportsEditmode 00675 | eModifierTypeFlag_EnableInEditmode, 00676 00677 /* copyData */ copyData, 00678 /* deformVerts */ NULL, 00679 /* deformMatrices */ NULL, 00680 /* deformVertsEM */ NULL, 00681 /* deformMatricesEM */ NULL, 00682 /* applyModifier */ applyModifier, 00683 /* applyModifierEM */ applyModifierEM, 00684 /* initData */ initData, 00685 /* requiredDataMask */ requiredDataMask, 00686 /* freeData */ NULL, 00687 /* isDisabled */ NULL, 00688 /* updateDepgraph */ NULL, 00689 /* dependsOnTime */ NULL, 00690 /* dependsOnNormals */ NULL, 00691 /* foreachObjectLink */ NULL, 00692 /* foreachIDLink */ NULL 00693 };