svn merge -r 13452:14721 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[blender.git] / source / blender / blenkernel / intern / multires-firstlevel.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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2006 by Nicholas Bishop
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  *
29  * Deals with the first-level data in multires (edge flags, weights, and UVs)
30  *
31  * multires.h
32  *
33  */
34
35 #include "DNA_customdata_types.h"
36 #include "DNA_mesh_types.h"
37 #include "DNA_meshdata_types.h"
38 #include "DNA_object_types.h"
39 #include "DNA_scene_types.h"
40
41 #include "BIF_editmesh.h"
42
43 #include "BKE_customdata.h"
44 #include "BKE_global.h"
45 #include "BKE_mesh.h"
46 #include "BKE_multires.h"
47
48 #include "BLI_editVert.h"
49
50 #include "MEM_guardedalloc.h"
51
52 #include "blendef.h"
53
54 #include <string.h>
55
56 MDeformVert *subdivide_dverts(MDeformVert *src, MultiresLevel *lvl);
57 MTFace *subdivide_mtfaces(MTFace *src, MultiresLevel *lvl);
58 void multires_update_edge_flags(Mesh *me, EditMesh *em);
59 void eed_to_medge_flag(EditEdge *eed, short *flag, char *crease);
60
61 /***********    Generic     ***********/
62
63 CustomDataMask cdmask(const int type)
64 {
65         if(type == CD_MDEFORMVERT)
66                 return CD_MASK_MDEFORMVERT;
67         else if(type == CD_MTFACE)
68                 return CD_MASK_MTFACE;
69         return -1;
70 }
71
72 char type_ok(const int type)
73 {
74         return (type == CD_MDEFORMVERT) || (type == CD_MTFACE);
75 }
76
77 /* Copy vdata or fdata from Mesh or EditMesh to Multires. */
78 void multires_update_customdata(MultiresLevel *lvl1, EditMesh *em, CustomData *src, CustomData *dst, const int type)
79 {
80         if(src && dst && type_ok(type)) {
81                 const int tot= (type == CD_MDEFORMVERT ? lvl1->totvert : lvl1->totface);
82                 int i;
83                 
84                 CustomData_free(dst, tot);
85                 
86                 if(CustomData_has_layer(src, type)) {
87                         if(em) {
88                                 EditVert *eve= G.editMesh->verts.first;
89                                 EditFace *efa= G.editMesh->faces.first;
90                                 CustomData_copy(src, dst, cdmask(type), CD_CALLOC, tot);
91                                 for(i=0; i<tot; ++i) {
92                                         if(type == CD_MDEFORMVERT) {
93                                                 CustomData_from_em_block(&G.editMesh->vdata, dst, eve->data, i);
94                                                 eve= eve->next;
95                                         }
96                                         else if(type == CD_MTFACE) {
97                                                 CustomData_from_em_block(&G.editMesh->fdata, dst, efa->data, i);
98                                                 efa= efa->next;
99                                         }
100                                 }
101                         }
102                         else
103                                 CustomData_copy(src, dst, cdmask(type), CD_DUPLICATE, tot);
104                 }
105         }
106 }
107
108 /* Uses subdivide_dverts or subdivide_mtfaces to subdivide src to match lvl_end. Does not free src. */
109 void *subdivide_customdata_to_level(void *src, MultiresLevel *lvl_start,
110                                     MultiresLevel *lvl_end, const int type)
111 {
112         if(src && lvl_start && lvl_end && type_ok(type)) {
113                 MultiresLevel *lvl;
114                 void *cr_data= NULL, *pr_data= NULL;
115                 
116                 pr_data= src;
117                 for(lvl= lvl_start; lvl && lvl != lvl_end; lvl= lvl->next) {
118                         if(type == CD_MDEFORMVERT)
119                                 cr_data= subdivide_dverts(pr_data, lvl);
120                         else if(type == CD_MTFACE)
121                                 cr_data= subdivide_mtfaces(pr_data, lvl);
122                         
123                         /* Free previous subdivision level's data */
124                         if(lvl != lvl_start) {
125                                 if(type == CD_MDEFORMVERT)
126                                         free_dverts(pr_data, lvl->totvert);
127                                 else if(type == CD_MTFACE)
128                                         MEM_freeN(pr_data);
129                         }
130
131                         pr_data= cr_data;
132                         cr_data= NULL;
133                 }
134                 
135                 return pr_data;
136         }
137         
138         return NULL;
139 }
140
141 /* Directly copy src into dst (handles both Mesh and EditMesh) */
142 void customdata_to_mesh(Mesh *me, EditMesh *em, CustomData *src, CustomData *dst, const int tot, const int type)
143 {
144         if(me && me->mr && src && dst && type_ok(type)) {
145                 if(em) {
146                         int i;
147                         EditVert *eve= em->verts.first;
148                         EditFace *efa= em->faces.first;
149                         CustomData_copy(src, dst, cdmask(type), CD_CALLOC, 0);
150                         
151                         for(i=0; i<tot; ++i) {
152                                 if(type == CD_MDEFORMVERT) {
153                                         CustomData_to_em_block(src, dst, i, &eve->data);
154                                         eve= eve->next;
155                                 }
156                                 else if(type == CD_MTFACE) {
157                                         CustomData_to_em_block(src, dst, i, &efa->data);
158                                         efa= efa->next;
159                                 }
160                         }
161                 } else {
162                         CustomData_merge(src, dst, cdmask(type), CD_DUPLICATE, tot);
163                 }
164         }
165 }
166
167 /* Subdivide vdata or fdata from Multires into either Mesh or EditMesh. */
168 void multires_customdata_to_mesh(Mesh *me, EditMesh *em, MultiresLevel *lvl, CustomData *src,
169                                  CustomData *dst, const int type)
170 {       
171         if(me && me->mr && lvl && src && dst && type_ok(type) &&
172            CustomData_has_layer(src, type)) {
173                 const int tot= (type == CD_MDEFORMVERT ? lvl->totvert : lvl->totface);
174                 if(lvl == me->mr->levels.first) {
175                         customdata_to_mesh(me, em, src, dst, tot, type);
176                 }
177                 else {
178                         CustomData cdf;
179                         const int count = CustomData_number_of_layers(src, type);
180                         int i;
181                         
182                         /* Construct a new CustomData containing the subdivided data */
183                         CustomData_copy(src, &cdf, cdmask(type), CD_ASSIGN, tot);
184                         for(i=0; i<count; ++i) {
185                                 void *layer= CustomData_get_layer_n(&cdf, type, i);
186                                 CustomData_set_layer_n(&cdf, type, i,
187                                         subdivide_customdata_to_level(layer, me->mr->levels.first, lvl, type));
188                         }
189                         
190                         customdata_to_mesh(me, em, &cdf, dst, tot, type);
191                         CustomData_free(&cdf, tot);
192                 }
193         }
194 }
195
196 /* Subdivide the first-level customdata up to cr_lvl, then delete the original data */
197 void multires_del_lower_customdata(Multires *mr, MultiresLevel *cr_lvl)
198 {
199         MultiresLevel *lvl1= mr->levels.first;
200         MDeformVert *dverts= NULL;
201         CustomData cdf;
202         int i;
203
204         /* dverts */
205         dverts= subdivide_customdata_to_level(CustomData_get(&mr->vdata, 0, CD_MDEFORMVERT),
206                                               lvl1, cr_lvl, CD_MDEFORMVERT);
207         if(dverts) {
208                 CustomData_free_layers(&mr->vdata, CD_MDEFORMVERT, lvl1->totvert);
209                 CustomData_add_layer(&mr->vdata, CD_MDEFORMVERT, CD_ASSIGN, dverts, cr_lvl->totvert);
210         }
211         
212         /* mtfaces */
213         CustomData_copy(&mr->fdata, &cdf, CD_MASK_MTFACE, CD_ASSIGN, cr_lvl->totface);
214         for(i=0; i<CustomData_number_of_layers(&mr->fdata, CD_MTFACE); ++i) {
215                 MTFace *mtfaces=
216                         subdivide_customdata_to_level(CustomData_get_layer_n(&mr->fdata, CD_MTFACE, i),
217                                                       lvl1, cr_lvl, CD_MTFACE);
218                 if(mtfaces)
219                         CustomData_set_layer_n(&cdf, CD_MTFACE, i, mtfaces);
220         }
221         
222         CustomData_free(&mr->fdata, lvl1->totface);
223         mr->fdata= cdf;
224 }
225
226 /* Update all special first-level data, if the first-level is active */
227 void multires_update_first_level(Mesh *me, EditMesh *em)
228 {
229         if(me && me->mr && me->mr->current == 1) {
230                 multires_update_customdata(me->mr->levels.first, em, em ? &em->vdata : &me->vdata,
231                                            &me->mr->vdata, CD_MDEFORMVERT);
232                 multires_update_customdata(me->mr->levels.first, em, em ? &em->fdata : &me->fdata,
233                                            &me->mr->fdata, CD_MTFACE);
234                 multires_update_edge_flags(me, em);
235         }
236 }
237
238 /*********** Multires.edge_flags ***********/
239 void multires_update_edge_flags(Mesh *me, EditMesh *em)
240 {
241         MultiresLevel *lvl= me->mr->levels.first;
242         EditEdge *eed= NULL;
243         int i;
244         
245         if(em) eed= em->edges.first;
246         for(i=0; i<lvl->totedge; ++i) {
247                 if(em) {
248                         me->mr->edge_flags[i]= 0;
249                         eed_to_medge_flag(eed, &me->mr->edge_flags[i], &me->mr->edge_creases[i]);
250                         eed= eed->next;
251                 }
252                 else {
253                         me->mr->edge_flags[i]= me->medge[i].flag;
254                         me->mr->edge_creases[i]= me->medge[i].crease;
255                 }
256         }
257 }
258
259
260
261 /*********** Multires.vdata ***********/
262
263 /* MDeformVert */
264
265 /* Add each weight from in to out. Scale each weight by w. */
266 void multires_add_dvert(MDeformVert *out, const MDeformVert *in, const float w)
267 {
268         if(out && in) {
269                 int i, j;
270                 char found;
271
272                 for(i=0; i<in->totweight; ++i) {
273                         found= 0;
274                         for(j=0; j<out->totweight; ++j) {
275                                 if(out->dw[j].def_nr==in->dw[i].def_nr) {
276                                         out->dw[j].weight += in->dw[i].weight * w;
277                                         found= 1;
278                                 }
279                         }
280                         if(!found) {
281                                 MDeformWeight *newdw= MEM_callocN(sizeof(MDeformWeight)*(out->totweight+1),
282                                                                   "multires dvert");
283                                 if(out->dw) {
284                                         memcpy(newdw, out->dw, sizeof(MDeformWeight)*out->totweight);
285                                         MEM_freeN(out->dw);
286                                 }
287
288                                 out->dw= newdw;
289                                 out->dw[out->totweight].weight= in->dw[i].weight * w;
290                                 out->dw[out->totweight].def_nr= in->dw[i].def_nr;
291
292                                 ++out->totweight;
293                         }
294                 }
295         }
296 }
297
298 /* Takes an input array of dverts and subdivides them (linear) using the topology of lvl */
299 MDeformVert *subdivide_dverts(MDeformVert *src, MultiresLevel *lvl)
300 {
301         if(lvl && lvl->next) {
302                 MDeformVert *out = MEM_callocN(sizeof(MDeformVert)*lvl->next->totvert, "dvert prop array");
303                 int i, j;
304                 
305                 /* Copy lower level */
306                 for(i=0; i<lvl->totvert; ++i)
307                         multires_add_dvert(&out[i], &src[i], 1);
308                 /* Edge verts */
309                 for(i=0; i<lvl->totedge; ++i) {
310                         for(j=0; j<2; ++j)
311                         multires_add_dvert(&out[lvl->totvert+i], &src[lvl->edges[i].v[j]],0.5);
312                 }
313                 
314                 /* Face verts */
315                 for(i=0; i<lvl->totface; ++i) {
316                         for(j=0; j<(lvl->faces[i].v[3]?4:3); ++j)
317                                 multires_add_dvert(&out[lvl->totvert + lvl->totedge + i],
318                                                    &src[lvl->faces[i].v[j]],
319                                                    lvl->faces[i].v[3]?0.25:(1.0f/3.0f));
320                 }
321                 
322                 return out;
323         }
324         
325         return NULL;
326 }
327
328
329
330 /*********** Multires.fdata ***********/
331
332 /* MTFace */
333
334 void multires_uv_avg2(float out[2], const float a[2], const float b[2])
335 {
336         int i;
337         for(i=0; i<2; ++i)
338                 out[i] = (a[i] + b[i]) / 2.0f;
339 }
340
341 /* Takes an input array of mtfaces and subdivides them (linear) using the topology of lvl */
342 MTFace *subdivide_mtfaces(MTFace *src, MultiresLevel *lvl)
343 {
344         if(lvl && lvl->next) {
345                 MTFace *out= MEM_callocN(sizeof(MultiresColFace)*lvl->next->totface,"Multirescolfaces");
346                 int i, j, curf;
347                 
348                 for(i=0, curf=0; i<lvl->totface; ++i) {
349                         const char sides= lvl->faces[i].v[3]?4:3;
350                         float cntr[2]= {0, 0};
351
352                         /* Find average uv coord of the current face */
353                         for(j=0; j<sides; ++j) {
354                                 cntr[0]+= src[i].uv[j][0];
355                                 cntr[1]+= src[i].uv[j][1];
356                         }
357                         cntr[0]/= sides;
358                         cntr[1]/= sides;
359
360                         for(j=0; j<sides; ++j, ++curf) {
361                                 out[curf]= src[i];
362                         
363                                 multires_uv_avg2(out[curf].uv[0], src[i].uv[j], src[i].uv[j==0?sides-1:j-1]);
364                                                   
365                                 out[curf].uv[1][0]= src[i].uv[j][0];
366                                 out[curf].uv[1][1]= src[i].uv[j][1];
367                                 
368                                 multires_uv_avg2(out[curf].uv[2], src[i].uv[j], src[i].uv[j==sides-1?0:j+1]);
369                                                   
370                                 out[curf].uv[3][0]= cntr[0];
371                                 out[curf].uv[3][1]= cntr[1];
372                         }
373                 }
374                 
375                 return out;
376         }
377         
378         return NULL;
379 }
380
381 void multires_delete_layer(Mesh *me, CustomData *cd, const int type, int n)
382 {
383         if(me && me->mr && cd) {
384                 MultiresLevel *lvl1= me->mr->levels.first;
385                 
386                 multires_update_levels(me, 0);
387                 
388                 CustomData_set_layer_active(cd, type, n);
389                 CustomData_free_layer_active(cd, type, lvl1->totface);
390                 
391                 multires_level_to_mesh(OBACT, me, 0);
392         }
393 }
394
395 void multires_add_layer(Mesh *me, CustomData *cd, const int type, const int n)
396 {
397         if(me && me->mr && cd) {
398                 multires_update_levels(me, 0);
399         
400                 if(CustomData_has_layer(cd, type))
401                         CustomData_add_layer(cd, type, CD_DUPLICATE, CustomData_get_layer(cd, type),
402                                              current_level(me->mr)->totface);
403                 else
404                         CustomData_add_layer(cd, type, CD_DEFAULT, NULL, current_level(me->mr)->totface);
405
406                 CustomData_set_layer_active(cd, type, n);
407                 multires_level_to_mesh(OBACT, me, 0);
408         }
409 }