Blender  V2.59
MOD_solidify.c
Go to the documentation of this file.
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 };