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