5fc3c506d36fc19ec6095b6be134da6554b363f0
[blender.git] / source / blender / modifiers / intern / MOD_decimate.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software  Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2005 by the Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Daniel Dunbar
22  *                 Ton Roosendaal,
23  *                 Ben Batt,
24  *                 Brecht Van Lommel,
25  *                 Campbell Barton
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  *
29  */
30
31 /** \file blender/modifiers/intern/MOD_decimate.c
32  *  \ingroup modifiers
33  */
34
35
36 #include "DNA_meshdata_types.h"
37
38 #include "BLI_math.h"
39 #include "BLI_utildefines.h"
40
41 #include "BLF_translation.h"
42
43 #include "MEM_guardedalloc.h"
44
45 #include "BKE_mesh.h"
46 #include "BKE_modifier.h"
47 #include "BKE_particle.h"
48 #include "BKE_cdderivedmesh.h"
49
50
51 #ifdef WITH_MOD_DECIMATE
52 #include "LOD_decimation.h"
53 #endif
54
55 #include "MOD_util.h"
56
57 static void initData(ModifierData *md)
58 {
59         DecimateModifierData *dmd = (DecimateModifierData*) md;
60
61         dmd->percent = 1.0;
62 }
63
64 static void copyData(ModifierData *md, ModifierData *target)
65 {
66         DecimateModifierData *dmd = (DecimateModifierData*) md;
67         DecimateModifierData *tdmd = (DecimateModifierData*) target;
68
69         tdmd->percent = dmd->percent;
70 }
71
72 #ifdef WITH_MOD_DECIMATE
73 static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
74                                                 DerivedMesh *derivedData,
75                                                 int UNUSED(useRenderParams),
76                                                 int UNUSED(isFinalCalc))
77 {
78         DecimateModifierData *dmd = (DecimateModifierData*) md;
79         DerivedMesh *dm = derivedData, *result = NULL;
80         MVert *mvert;
81         MFace *mface;
82         LOD_Decimation_Info lod;
83         int totvert, totface;
84         int a, numTris;
85
86         DM_ensure_tessface(dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
87
88         mvert = dm->getVertArray(dm);
89         mface = dm->getTessFaceArray(dm);
90         totvert = dm->getNumVerts(dm);
91         totface = dm->getNumTessFaces(dm);
92
93         numTris = 0;
94         for (a=0; a<totface; a++) {
95                 MFace *mf = &mface[a];
96                 numTris++;
97                 if (mf->v4) numTris++;
98         }
99
100         if(numTris<3) {
101                 modifier_setError(md, TIP_("Modifier requires more than 3 input faces (triangles)."));
102                 dm = CDDM_copy(dm);
103                 return dm;
104         }
105
106         lod.vertex_buffer= MEM_mallocN(3*sizeof(float)*totvert, "vertices");
107         lod.vertex_normal_buffer= MEM_mallocN(3*sizeof(float)*totvert, "normals");
108         lod.triangle_index_buffer= MEM_mallocN(3*sizeof(int)*numTris, "trias");
109         lod.vertex_num= totvert;
110         lod.face_num= numTris;
111
112         for(a=0; a<totvert; a++) {
113                 MVert *mv = &mvert[a];
114                 float *vbCo = &lod.vertex_buffer[a*3];
115                 float *vbNo = &lod.vertex_normal_buffer[a*3];
116
117                 copy_v3_v3(vbCo, mv->co);
118                 normal_short_to_float_v3(vbNo, mv->no);
119         }
120
121         numTris = 0;
122         for(a=0; a<totface; a++) {
123                 MFace *mf = &mface[a];
124                 int *tri = &lod.triangle_index_buffer[3*numTris++];
125                 tri[0]= mf->v1;
126                 tri[1]= mf->v2;
127                 tri[2]= mf->v3;
128
129                 if(mf->v4) {
130                         tri = &lod.triangle_index_buffer[3*numTris++];
131                         tri[0]= mf->v1;
132                         tri[1]= mf->v3;
133                         tri[2]= mf->v4;
134                 }
135         }
136
137         dmd->faceCount = 0;
138         if(LOD_LoadMesh(&lod) ) {
139                 if( LOD_PreprocessMesh(&lod) ) {
140                         /* we assume the decim_faces tells how much to reduce */
141
142                         while(lod.face_num > numTris*dmd->percent) {
143                                 if( LOD_CollapseEdge(&lod)==0) break;
144                         }
145
146                         if(lod.vertex_num>2) {
147                                 result = CDDM_new(lod.vertex_num, 0, lod.face_num, 0, 0);
148                                 dmd->faceCount = lod.face_num;
149                         }
150                         else
151                                 result = CDDM_new(lod.vertex_num, 0, 0, 0, 0);
152
153                         mvert = CDDM_get_verts(result);
154                         for(a=0; a<lod.vertex_num; a++) {
155                                 MVert *mv = &mvert[a];
156                                 float *vbCo = &lod.vertex_buffer[a*3];
157                                 
158                                 copy_v3_v3(mv->co, vbCo);
159                         }
160
161                         if(lod.vertex_num>2) {
162                                 mface = CDDM_get_tessfaces(result);
163                                 for(a=0; a<lod.face_num; a++) {
164                                         MFace *mf = &mface[a];
165                                         int *tri = &lod.triangle_index_buffer[a*3];
166                                         mf->v1 = tri[0];
167                                         mf->v2 = tri[1];
168                                         mf->v3 = tri[2];
169                                         test_index_face(mf, NULL, 0, 3);
170                                 }
171                         }
172
173                         CDDM_calc_edges_tessface(result);
174                 }
175                 else
176                         modifier_setError(md, TIP_("Out of memory."));
177
178                 LOD_FreeDecimationData(&lod);
179         }
180         else
181                 modifier_setError(md, TIP_("Non-manifold mesh as input."));
182
183         MEM_freeN(lod.vertex_buffer);
184         MEM_freeN(lod.vertex_normal_buffer);
185         MEM_freeN(lod.triangle_index_buffer);
186
187         if (result) {
188                 CDDM_tessfaces_to_faces(result); /*builds ngon faces from tess (mface) faces*/
189
190                 return result;
191         }
192         else {
193                 return dm;
194         }
195 }
196 #else // WITH_MOD_DECIMATE
197 static DerivedMesh *applyModifier(ModifierData *UNUSED(md), Object *UNUSED(ob),
198                                                 DerivedMesh *derivedData,
199                                                 int UNUSED(useRenderParams),
200                                                 int UNUSED(isFinalCalc))
201 {
202         return derivedData;
203 }
204 #endif // WITH_MOD_DECIMATE
205
206 ModifierTypeInfo modifierType_Decimate = {
207         /* name */              "Decimate",
208         /* structName */        "DecimateModifierData",
209         /* structSize */        sizeof(DecimateModifierData),
210         /* type */              eModifierTypeType_Nonconstructive,
211         /* flags */             eModifierTypeFlag_AcceptsMesh,
212         /* copyData */          copyData,
213         /* deformVerts */       NULL,
214         /* deformMatrices */    NULL,
215         /* deformVertsEM */     NULL,
216         /* deformMatricesEM */  NULL,
217         /* applyModifier */     applyModifier,
218         /* applyModifierEM */   NULL,
219         /* initData */          initData,
220         /* requiredDataMask */  NULL,
221         /* freeData */          NULL,
222         /* isDisabled */        NULL,
223         /* updateDepgraph */    NULL,
224         /* dependsOnTime */     NULL,
225         /* dependsOnNormals */  NULL,
226         /* foreachObjectLink */ NULL,
227         /* foreachIDLink */     NULL,
228         /* foreachTexLink */    NULL,
229 };