Blender V2.61 - r43446

MOD_remesh.c

Go to the documentation of this file.
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) 2011 by Nicholas Bishop.
00019  *
00020  * ***** END GPL LICENSE BLOCK *****
00021  */
00022 
00027 #include "MEM_guardedalloc.h"
00028 
00029 #include "BLI_math_vector.h"
00030 #include "BLI_utildefines.h"
00031 
00032 #include "BKE_cdderivedmesh.h"
00033 #include "BKE_DerivedMesh.h"
00034 #include "BKE_mesh.h"
00035 
00036 #include "DNA_meshdata_types.h"
00037 #include "DNA_modifier_types.h"
00038 #include "DNA_object_types.h"
00039 
00040 #include "MOD_modifiertypes.h"
00041 
00042 #include <assert.h>
00043 #include <stdlib.h>
00044 #include <string.h>
00045 
00046 #ifdef WITH_MOD_REMESH
00047 #  include "dualcon.h"
00048 #endif
00049 
00050 static void initData(ModifierData *md)
00051 {
00052     RemeshModifierData *rmd = (RemeshModifierData*) md;
00053 
00054     rmd->scale = 0.9;
00055     rmd->depth = 4;
00056     rmd->hermite_num = 1;
00057     rmd->flag = MOD_REMESH_FLOOD_FILL;
00058     rmd->mode = MOD_REMESH_SHARP_FEATURES;
00059     rmd->threshold = 1;
00060 }
00061 
00062 static void copyData(ModifierData *md, ModifierData *target)
00063 {
00064     RemeshModifierData *rmd = (RemeshModifierData*) md;
00065     RemeshModifierData *trmd = (RemeshModifierData*) target;
00066 
00067     trmd->threshold = rmd->threshold;
00068     trmd->scale = rmd->scale;
00069     trmd->hermite_num = rmd->hermite_num;
00070     trmd->depth = rmd->depth;
00071     trmd->flag = rmd->flag;
00072     trmd->mode = rmd->mode;
00073 }
00074 
00075 #ifdef WITH_MOD_REMESH
00076 
00077 static void init_dualcon_mesh(DualConInput *mesh, DerivedMesh *dm)
00078 {
00079     memset(mesh, 0, sizeof(DualConInput));
00080 
00081     mesh->co = (void*)dm->getVertArray(dm);
00082     mesh->co_stride = sizeof(MVert);
00083     mesh->totco = dm->getNumVerts(dm);
00084 
00085     mesh->faces = (void*)dm->getFaceArray(dm);
00086     mesh->face_stride = sizeof(MFace);
00087     mesh->totface = dm->getNumFaces(dm);
00088 
00089     dm->getMinMax(dm, mesh->min, mesh->max);
00090 }
00091 
00092 /* simple structure to hold the output: a CDDM and two counters to
00093    keep track of the current elements */
00094 typedef struct {
00095     DerivedMesh *dm;
00096     int curvert, curface;
00097 } DualConOutput;
00098 
00099 /* allocate and initialize a DualConOutput */
00100 static void *dualcon_alloc_output(int totvert, int totquad)
00101 {
00102     DualConOutput *output;
00103 
00104     if(!(output = MEM_callocN(sizeof(DualConOutput),
00105                               "DualConOutput")))
00106         return NULL;
00107     
00108     output->dm = CDDM_new(totvert, 0, totquad);
00109     return output;
00110 }
00111 
00112 static void dualcon_add_vert(void *output_v, const float co[3])
00113 {
00114     DualConOutput *output = output_v;
00115     DerivedMesh *dm = output->dm;
00116     
00117     assert(output->curvert < dm->getNumVerts(dm));
00118     
00119     copy_v3_v3(CDDM_get_verts(dm)[output->curvert].co, co);
00120     output->curvert++;
00121 }
00122 
00123 static void dualcon_add_quad(void *output_v, const int vert_indices[4])
00124 {
00125     DualConOutput *output = output_v;
00126     DerivedMesh *dm = output->dm;
00127     MFace *mface;
00128     
00129     assert(output->curface < dm->getNumFaces(dm));
00130 
00131     mface = &CDDM_get_faces(dm)[output->curface];
00132     mface->v1 = vert_indices[0];
00133     mface->v2 = vert_indices[1];
00134     mface->v3 = vert_indices[2];
00135     mface->v4 = vert_indices[3];
00136     
00137     if(test_index_face(mface, NULL, 0, 4))
00138         output->curface++;
00139 }
00140 
00141 static DerivedMesh *applyModifier(ModifierData *md,
00142                                   Object *UNUSED(ob),
00143                                   DerivedMesh *dm,
00144                                   int UNUSED(useRenderParams),
00145                                   int UNUSED(isFinalCalc))
00146 {
00147     RemeshModifierData *rmd;
00148     DualConOutput *output;
00149     DualConInput input;
00150     DerivedMesh *result;
00151     DualConFlags flags = 0;
00152     DualConMode mode = 0;
00153 
00154     rmd = (RemeshModifierData*)md;
00155 
00156     init_dualcon_mesh(&input, dm);
00157 
00158     if(rmd->flag & MOD_REMESH_FLOOD_FILL)
00159         flags |= DUALCON_FLOOD_FILL;
00160 
00161     switch(rmd->mode) {
00162     case MOD_REMESH_CENTROID:
00163         mode = DUALCON_CENTROID;
00164         break;
00165     case MOD_REMESH_MASS_POINT:
00166         mode = DUALCON_MASS_POINT;
00167         break;
00168     case MOD_REMESH_SHARP_FEATURES:
00169         mode = DUALCON_SHARP_FEATURES;
00170         break;
00171     }
00172     
00173     output = dualcon(&input,
00174                      dualcon_alloc_output,
00175                      dualcon_add_vert,
00176                      dualcon_add_quad,
00177                      flags,
00178                      mode,
00179                      rmd->threshold,
00180                      rmd->hermite_num,
00181                      rmd->scale,
00182                      rmd->depth);
00183     result = output->dm;
00184     CDDM_lower_num_faces(result, output->curface);
00185     MEM_freeN(output);
00186 
00187     CDDM_calc_edges(result);
00188     CDDM_calc_normals(result);
00189 
00190     return result;
00191 }
00192 
00193 #else /* !WITH_MOD_REMESH */
00194 
00195 static DerivedMesh *applyModifier(ModifierData *UNUSED(md), Object *UNUSED(ob),
00196                         DerivedMesh *derivedData,
00197                         int UNUSED(useRenderParams),
00198                         int UNUSED(isFinalCalc))
00199 {
00200     return derivedData;
00201 }
00202 
00203 #endif /* !WITH_MOD_REMESH */
00204 
00205 ModifierTypeInfo modifierType_Remesh = {
00206     /* name */              "Remesh",
00207     /* structName */        "RemeshModifierData",
00208     /* structSize */        sizeof(RemeshModifierData),
00209     /* type */              eModifierTypeType_Nonconstructive,
00210     /* flags */             eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode,
00211     /* copyData */          copyData,
00212     /* deformVerts */       NULL,
00213     /* deformMatrices */    NULL,
00214     /* deformVertsEM */     NULL,
00215     /* deformMatricesEM */  NULL,
00216     /* applyModifier */     applyModifier,
00217     /* applyModifierEM */   NULL,
00218     /* initData */          initData,
00219     /* requiredDataMask */  NULL,
00220     /* freeData */          NULL,
00221     /* isDisabled */        NULL,
00222     /* updateDepgraph */    NULL,
00223     /* dependsOnTime */     NULL,
00224     /* dependsOnNormals */  NULL,
00225     /* foreachObjectLink */ NULL,
00226     /* foreachIDLink */     NULL,
00227 };