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