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