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