cache customdata checks to avoid looking up on each call to mesh_loops_to_mface_corners()
[blender.git] / source / blender / modifiers / intern / MOD_ngoninterp.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_mask.c
32  *  \ingroup modifiers
33  */
34
35 #include <string.h>
36
37 #include "MEM_guardedalloc.h"
38
39 #include "BLI_utildefines.h"
40 #include "BLI_ghash.h"
41 #include "BLI_array.h"
42 #include "BLI_smallhash.h"
43 #include "BLI_edgehash.h"
44 #include "BLI_math.h"
45
46 #include "DNA_armature_types.h"
47 #include "DNA_meshdata_types.h"
48 #include "DNA_modifier_types.h"
49 #include "DNA_object_types.h"
50
51 #include "BKE_cdderivedmesh.h"
52 #include "BKE_mesh.h"
53 #include "BKE_modifier.h"
54 #include "BKE_deform.h"
55
56 #include "depsgraph_private.h"
57
58 #include "MOD_util.h"
59
60 static void copyData(ModifierData *md, ModifierData *target)
61 {
62         NgonInterpModifierData *mmd = (NgonInterpModifierData*) md;
63         NgonInterpModifierData *tmmd = (NgonInterpModifierData*) target;
64         
65         tmmd->resolution = mmd->resolution;
66 }
67
68 static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
69                                                 DerivedMesh *derivedData,
70                                                 int UNUSED(useRenderParams),
71                                                 int UNUSED(isFinalCalc))
72 {
73         NgonInterpModifierData *nmd= (NgonInterpModifierData *)md;
74         DerivedMesh *dm= derivedData;
75         DerivedMesh *cddm, *dummy;
76         MFace *mf;
77         MPoly *mpoly;
78         MLoop *mloop;
79         MFace *mface = NULL, *mf2;
80         MVert *mvert = NULL, *omvert;
81         BLI_array_declare(mface);
82         BLI_array_declare(mvert);
83         int *verts=NULL, *loops=NULL;
84         BLI_array_declare(verts);
85         BLI_array_declare(loops);
86         float *w = NULL, (*cos)[3] = NULL;
87         BLI_array_declare(w);
88         BLI_array_declare(cos);
89         int *origv = NULL, *origf = NULL, *of, *ov;
90         BLI_array_declare(origv);
91         BLI_array_declare(origf);
92         DerivedMesh *copy = NULL;
93         int i;
94
95         int numTex;
96         int numCol;
97         int hasWCol;
98
99         if (nmd->resolution <= 0)
100                 return dm;
101         
102         if (!CDDM_Check(dm)) {
103                 dm = copy = CDDM_copy(dm, 0);
104         }
105         
106         CDDM_recalc_tesselation(dm);
107         
108         mf = dm->getTessFaceArray(dm);
109         of = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
110         mpoly = CDDM_get_polys(dm);
111         mloop = CDDM_get_loops(dm);
112         
113         /*eek!*/
114         if (!of)
115                 return dm;
116
117         /*create a dummy mesh to compute interpolated loops on*/
118         dummy = CDDM_from_template(dm, 0, 0, 0, 3, 0);
119
120         /* CustomData we check must match what is passed to mesh_loops_to_mface_corners() */
121         numTex = CustomData_number_of_layers(&dm->polyData, CD_MTEXPOLY);
122         numCol = CustomData_number_of_layers(&dummy->loopData, CD_MLOOPCOL);
123         hasWCol = CustomData_has_layer(&dummy->loopData, CD_WEIGHT_MLOOPCOL);
124
125         /*copy original verts here, so indices stay correct*/
126         omvert = dm->getVertArray(dm);
127         ov = dm->getVertDataArray(dm, CD_ORIGINDEX);
128         for (i=0; i<dm->numVertData; i++) {
129                 BLI_array_append(mvert, omvert[i]);
130                 BLI_array_append(origv, ov ? ov[i] : i);
131         }
132         
133         for (i=0; i<dm->numTessFaceData; i++, mf++, of++) {
134                 int x, y, x2;
135                 float fac;
136                 
137                 BLI_array_empty(verts);
138                 
139 #define NG_MAKE_VERT(orig)\
140                 BLI_array_append(mvert, omvert[orig]);\
141                 BLI_array_append(origv, ov ? ov[orig] : orig);\
142                 BLI_array_append(verts, BLI_array_count(mvert)-1);
143
144 #define NG_MAKE_VERTCO(orig, coord) NG_MAKE_VERT(orig); copy_v3_v3(mvert[BLI_array_count(mvert)-1].co, coord)
145
146                 y = 0;
147                 fac = 1.0f / (float)(nmd->resolution + 1);
148                 for (x=0; x<nmd->resolution+2; x++) {
149                         float co1[3], co2[3], co3[3];
150                         
151                         sub_v3_v3v3(co1, omvert[mf->v1].co, omvert[mf->v3].co);
152                         sub_v3_v3v3(co2, omvert[mf->v2].co, omvert[mf->v3].co);
153                         
154                         mul_v3_fl(co1, 1.0f - fac*x);
155                         mul_v3_fl(co2, 1.0f - fac*x);
156                         
157                         add_v3_v3(co1, omvert[mf->v3].co);
158                         add_v3_v3(co2, omvert[mf->v3].co);
159
160                         if (x == 0) {
161                                 BLI_array_append(verts, mf->v1);
162                         } else if (x == nmd->resolution+1) {
163                                 BLI_array_append(verts, mf->v3);
164                         } else {
165                                 NG_MAKE_VERTCO(mf->v1, co1);
166                         }
167                         
168                         for (x2=0; x2<(nmd->resolution-x); x2++) {
169                                 sub_v3_v3v3(co3, co1, co2);
170                                 mul_v3_fl(co3, 1.0f - (1.0f/(float)(nmd->resolution-x+1))*(x2+1));
171                                 add_v3_v3(co3, co2);
172                                 
173                                 NG_MAKE_VERTCO(mf->v2, co3);
174                         }
175                         
176                         if (x == 0) {
177                                 BLI_array_append(verts, mf->v2);
178                         } else if (x != nmd->resolution+1) {
179                                 NG_MAKE_VERTCO(mf->v1, co2);
180                         }
181                 }
182                 
183                 y = 0;
184                 for (x=0; x<BLI_array_count(verts)-2; x++) {
185                         int v1, v2, v3;
186                         
187                         if (x2 == nmd->resolution-y+1) {
188                                 x2 = 0;
189                                 y++;
190                                 continue;
191                         } else {
192                                 /*int lindex[3] = {0, 1, 2};*/ /*UNUSED*/
193                                 
194                                 v1 = verts[x];
195                                 v2 = verts[x+1];
196                                 v3 = verts[x+(nmd->resolution-y)+2];
197                                 
198                                 BLI_array_growone(mface);
199                                 BLI_array_growone(origf);
200                                 
201                                 /*make first face*/
202                                 origf[BLI_array_count(origf)-1] = *of;
203                                 mf2 = mface + BLI_array_count(mface)-1;
204                                 *mf2 = *mf;
205                                 
206                                 mf2->v1 = v1;
207                                 mf2->v2 = v2;
208                                 mf2->v3 = v3;
209                                 mf2->v4 = 0;
210                                 
211                                 if (x2 != nmd->resolution-y) {
212                                         /*make second face*/
213                                         BLI_array_growone(mface);
214                                         BLI_array_growone(origf);
215                                         
216                                         origf[BLI_array_count(origf)-1] = *of;
217                                         mf2 = mface + BLI_array_count(mface)-1;
218                                         *mf2 = *mf;
219                                         
220                                         mf2->v1 = verts[x+(nmd->resolution-y)+3];
221                                         mf2->v2 = v3;
222                                         mf2->v3 = v2;
223                                         mf2->v4 = 0;
224                                 }
225                         }
226                         
227                         x2++;
228                 }
229         }
230                 
231         cddm = CDDM_from_template(dm, BLI_array_count(mvert), dm->numEdgeData, BLI_array_count(mface), 0, 0);
232         
233         mf2 = mface;
234         for (i=0; i<BLI_array_count(mface); i++, mf2++) {
235                 MPoly *mp = mpoly + *of;
236                 MLoop *ml;
237                 float co[3], cent[3] = {0.0f, 0.0f, 0.0f};
238                 int j, lindex[4] = {0, 1, 2}; /* only ever use 3 in this case */
239                 
240                 BLI_array_empty(w);
241                 BLI_array_empty(cos);
242                 BLI_array_empty(loops);
243                 
244                 mp = mpoly + origf[i];
245                 ml = mloop + mp->loopstart;
246                 for (j=0; j<mp->totloop; j++, ml++) {
247                         BLI_array_growone(cos);
248                         BLI_array_growone(w);
249                         BLI_array_append(loops, j+mp->loopstart);
250                         copy_v3_v3(cos[j], mvert[ml->v].co);
251                 }
252                 
253                 /*scale source face coordinates a bit, so points sitting directly on an
254                   edge will work.*/
255                 mul_v3_fl(cent, 1.0f/(float)(mp->totloop));
256                 for (j=0; j<mp->totloop; j++) {
257                         sub_v3_v3(cos[j], cent);
258                         mul_v3_fl(cos[j], 1.0f+FLT_EPSILON*1500.0f);
259                         add_v3_v3(cos[j], cent);
260                 }
261
262                 copy_v3_v3(co, (mvert + mf2->v1)->co);
263                 interp_weights_poly_v3(w, cos, mp->totloop, co);
264                 CustomData_interp(&dm->loopData, &dummy->loopData, loops, w, NULL, mp->totloop, 0);
265                 
266                 copy_v3_v3(co, (mvert + mf2->v2)->co);
267                 interp_weights_poly_v3(w, cos, mp->totloop, co);
268                 CustomData_interp(&dm->loopData, &dummy->loopData, loops, w, NULL, mp->totloop, 1);
269         
270                 copy_v3_v3(co, (mvert + mf2->v3)->co);
271                 interp_weights_poly_v3(w, cos, mp->totloop, co);
272                 CustomData_interp(&dm->loopData, &dummy->loopData, loops, w, NULL, mp->totloop, 2);
273                 
274                 mesh_loops_to_mface_corners(&cddm->faceData, &dummy->loopData, &dm->polyData,
275                                             lindex, i, origf[i], 3,
276                                             numTex, numCol, hasWCol);
277         }
278         
279         CustomData_copy_data(&dm->vertData, &cddm->vertData, 0, 0, dm->numVertData);
280         CustomData_copy_data(&dm->edgeData, &cddm->edgeData, 0, 0, dm->numEdgeData);
281         
282         CDDM_set_mface(cddm, mface);
283         CDDM_set_mvert(cddm, mvert);
284         
285         /*set origindex pointer*/
286         MEM_freeN(CustomData_get_layer(&cddm->faceData, CD_ORIGINDEX));
287         CustomData_set_layer(&cddm->faceData, CD_MFACE, mface);
288         
289         if (CustomData_has_layer(&cddm->vertData, CD_ORIGINDEX))
290                 CustomData_set_layer(&cddm->vertData, CD_ORIGINDEX, origv);
291
292         CustomData_set_layer(&cddm->faceData, CD_ORIGINDEX, origf);
293
294         BLI_array_free(cos);
295         BLI_array_free(w);
296         
297         dummy->needsFree = 1;
298         dummy->release(dummy);
299         
300         /*create polys from mface triangles*/
301         dummy = cddm;
302         cddm = CDDM_copy(cddm, 1);
303         dummy->needsFree = 1;
304         dummy->release(dummy);
305         
306         if (copy) {
307                 copy->needsFree = 1;
308                 copy->release(dm);
309                 copy = copy;
310         }
311
312         return cddm;
313 }
314
315
316 ModifierTypeInfo modifierType_NgonInterp = {
317         /* name */              "NgonInterp",
318         /* structName */        "NgonInterpModifierData",
319         /* structSize */        sizeof(NgonInterpModifierData),
320         /* type */              eModifierTypeType_Constructive,
321         /* flags */             eModifierTypeFlag_AcceptsMesh|eModifierTypeFlag_SupportsMapping|eModifierTypeFlag_SupportsEditmode,
322
323         /* copyData */          copyData,
324         /* deformVerts */       0,
325         /* deformMatrices */    0,
326         /* deformVertsEM */     0,
327         /* deformMatricesEM */  0,
328         /* applyModifier */     applyModifier,
329         /* applyModifierEM */   0,
330         /* initData */          0,
331         /* requiredDataMask */  0,
332         /* freeData */          0,
333         /* isDisabled */        0,
334         /* updateDepgraph */    0,
335         /* dependsOnTime */     0,
336         /* dependsOnNormals */  0,
337         /* foreachObjectLink */ 0,
338         /* foreachIDLink */     0,
339 };
340