part 1 of cleaning up my little array macro library to be a formal API. also removed...
[blender.git] / source / blender / bmesh / intern / bmesh_interp.c
1 /**
2  * BME_interp.c    August 2008
3  *
4  *      BM interpolation functions.
5  *
6  * ***** BEGIN GPL LICENSE BLOCK *****
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  * about this.  
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2007 Blender Foundation.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): Geoffrey Bantle.
29  *
30  * ***** END GPL LICENSE BLOCK *****
31  */
32
33 #include "MEM_guardedalloc.h"
34
35 #include "DNA_mesh_types.h"
36 #include "DNA_meshdata_types.h"
37
38 #include "BKE_customdata.h" 
39 #include "BKE_utildefines.h"
40
41 #include "BLI_array.h"
42
43 #include "bmesh.h"
44 #include "bmesh_private.h"
45
46 /*
47  * BME_INTERP.C
48  *
49  * Functions for interpolating data across the surface of a mesh.
50  *
51 */
52
53 /**
54  *                      bmesh_data_interp_from_verts
55  *
56  *  Interpolates per-vertex data from two sources to a target.
57  * 
58  *  Returns -
59  *      Nothing
60  */
61 void BM_Data_Interp_From_Verts(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v, float fac)
62 {
63         void *src[2];
64         float w[2];
65         if (v1->head.data && v2->head.data) {
66                 src[0]= v1->head.data;
67                 src[1]= v2->head.data;
68                 w[0] = 1.0f-fac;
69                 w[1] = fac;
70                 CustomData_bmesh_interp(&bm->vdata, src, w, NULL, 2, v->head.data);
71         }
72 }
73
74 /*
75     BM Data Vert Average
76
77     Sets all the customdata (e.g. vert, loop) associated with a vert
78     to the average of the face regions surrounding it.
79 */
80
81 //CustomData_bmesh_interp(&bm->ldata, src,w, NULL, 2, vloop->head.data);                                
82
83 void BM_Data_Vert_Average(BMesh *bm, BMFace *f)
84 {
85         BMIter iter;
86
87
88 }
89
90 /**
91  *                      bmesh_data_facevert_edgeinterp
92  *
93  *  Walks around the faces of an edge and interpolates the per-face-edge
94  *  data between two sources to a target.
95  * 
96  *  Returns -
97  *      Nothing
98 */
99  
100 void BM_Data_Facevert_Edgeinterp(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v, BMEdge *e1, float fac){
101         void *src[2];
102         float w[2];
103         BMLoop *l=NULL, *v1loop = NULL, *vloop = NULL, *v2loop = NULL;
104         
105         w[1] = 1.0f - fac;
106         w[0] = fac;
107
108         if(!e1->loop) return;
109         l = e1->loop;
110         do{
111                 if(l->v == v1){ 
112                         v1loop = l;
113                         vloop = (BMLoop*)(v1loop->head.next);
114                         v2loop = (BMLoop*)(vloop->head.next);
115                 }else if(l->v == v){
116                         v1loop = (BMLoop*)(l->head.next);
117                         vloop = l;
118                         v2loop = (BMLoop*)(l->head.prev);
119                         
120                 }
121
122                 src[0] = v1loop->head.data;
123                 src[1] = v2loop->head.data;                                     
124
125                 CustomData_bmesh_interp(&bm->ldata, src,w, NULL, 2, vloop->head.data);                          
126                 l = l->radial.next->data;
127         }while(l!=e1->loop);
128 }
129
130 void BM_loops_to_corners(BMesh *bm, Mesh *me, int findex,
131                          BMFace *f, int numTex, int numCol) 
132 {
133         BMLoop *l;
134         BMIter iter;
135         MTFace *texface;
136         MTexPoly *texpoly;
137         MCol *mcol;
138         MLoopCol *mloopcol;
139         MLoopUV *mloopuv;
140         int i, j;
141
142         for(i=0; i < numTex; i++){
143                 texface = CustomData_get_n(&me->fdata, CD_MTFACE, findex, i);
144                 texpoly = CustomData_bmesh_get_n(&bm->pdata, f->head.data, CD_MTEXPOLY, i);
145                 
146                 texface->tpage = texpoly->tpage;
147                 texface->flag = texpoly->flag;
148                 texface->transp = texpoly->transp;
149                 texface->mode = texpoly->mode;
150                 texface->tile = texpoly->tile;
151                 texface->unwrap = texpoly->unwrap;
152
153                 j = 0;
154                 BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
155                         mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
156                         texface->uv[j][0] = mloopuv->uv[0];
157                         texface->uv[j][1] = mloopuv->uv[1];
158
159                         j++;
160                 }
161
162         }
163
164         for(i=0; i < numCol; i++){
165                 mcol = CustomData_get_n(&me->fdata, CD_MCOL, findex, i);
166
167                 j = 0;
168                 BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
169                         mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPCOL, i);
170                         mcol[j].r = mloopcol->r;
171                         mcol[j].g = mloopcol->g;
172                         mcol[j].b = mloopcol->b;
173                         mcol[j].a = mloopcol->a;
174
175                         j++;
176                 }
177         }
178 }
179
180 //static void bmesh_data_interp_from_face(BME_Mesh *bm, BMFace *source, BMFace *target)
181 //{
182 //
183 //}
184 /*insert BM_data_interp_from_face here for mean value coordinates...*/
185
186
187 static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data)
188 {
189         BMIter iter;
190         BLI_mempool *oldpool = olddata->pool;
191         void *block;
192
193         CustomData_bmesh_init_pool(data, data==&bm->ldata ? 2048 : 512);
194
195         if (data == &bm->vdata) {
196                 BMVert *eve;
197                 
198                 BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
199                         block = NULL;
200                         CustomData_bmesh_set_default(data, &block);
201                         CustomData_bmesh_copy_data(olddata, data, eve->head.data, &block);
202                         CustomData_bmesh_free_block(olddata, &eve->head.data);
203                         eve->head.data= block;
204                 }
205         }
206         else if (data == &bm->edata) {
207                 BMEdge *eed;
208
209                 BM_ITER(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) {
210                         block = NULL;
211                         CustomData_bmesh_set_default(data, &block);
212                         CustomData_bmesh_copy_data(olddata, data, eed->head.data, &block);
213                         CustomData_bmesh_free_block(olddata, &eed->head.data);
214                         eed->head.data= block;
215                 }
216         }
217         else if (data == &bm->pdata || data == &bm->ldata) {
218                 BMIter liter;
219                 BMFace *efa;
220                 BMLoop *l;
221
222                 BM_ITER(efa, &iter, bm, BM_FACES_OF_MESH, NULL) {
223                         if (data == &bm->pdata) {
224                                 block = NULL;
225                                 CustomData_bmesh_set_default(data, &block);
226                                 CustomData_bmesh_copy_data(olddata, data, efa->head.data, &block);
227                                 CustomData_bmesh_free_block(olddata, &efa->head.data);
228                                 efa->head.data= block;
229                         }
230
231                         if (data == &bm->ldata) {
232                                 BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, efa) {
233                                         block = NULL;
234                                         CustomData_bmesh_set_default(data, &block);
235                                         CustomData_bmesh_copy_data(olddata, data, l->head.data, &block);
236                                         CustomData_bmesh_free_block(olddata, &l->head.data);
237                                         l->head.data= block;
238                                 }
239                         }
240                 }
241         }
242 }
243
244
245 void BM_add_data_layer(BMesh *bm, CustomData *data, int type)
246 {
247         CustomData olddata;
248
249         olddata= *data;
250         olddata.layers= (olddata.layers)? MEM_dupallocN(olddata.layers): NULL;
251         CustomData_add_layer(data, type, CD_DEFAULT, NULL, 0);
252
253         update_data_blocks(bm, &olddata, data);
254         if (olddata.layers) MEM_freeN(olddata.layers);
255 }
256
257 void BM_free_data_layer(BMesh *bm, CustomData *data, int type)
258 {
259         CustomData olddata;
260
261         olddata= *data;
262         olddata.layers= (olddata.layers)? MEM_dupallocN(olddata.layers): NULL;
263         CustomData_free_layer_active(data, type, 0);
264
265         update_data_blocks(bm, &olddata, data);
266         if (olddata.layers) MEM_freeN(olddata.layers);
267 }