36ac0445933964c580fc50bae34239436ef8ff17
[blender.git] / source / blender / radiosity / intern / source / radpostprocess.c
1 /* ***************************************
2  *
3  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. The Blender
9  * Foundation also sells licenses for use in proprietary software under
10  * the Blender License.  See http://www.blender.org/BL/ for information
11  * about this.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL/BL DUAL LICENSE BLOCK *****
30
31
32
33     radpostprocess.c    nov/dec 1992
34                                                 may 1999
35
36     - faces
37     - filtering and node-limit
38     - apply to meshes
39     $Id$
40
41  *************************************** */
42
43 #include <stdlib.h>
44 #include <string.h>
45 #include <math.h>
46
47 #ifdef HAVE_CONFIG_H
48 #include <config.h>
49 #endif
50
51 #include "MEM_guardedalloc.h"
52
53 #include "BLI_blenlib.h"
54 #include "BLI_arithb.h"
55 #include "BIF_toolbox.h"  // notice()
56
57 #include "DNA_material_types.h"
58 #include "DNA_mesh_types.h"
59 #include "DNA_meshdata_types.h"
60 #include "DNA_object_types.h"
61 #include "DNA_radio_types.h"
62
63 #include "BKE_customdata.h"
64 #include "BKE_global.h"
65 #include "BKE_main.h"
66 #include "BKE_material.h"
67 #include "BKE_mesh.h"
68 #include "BKE_object.h"
69 #include "BKE_utildefines.h"
70
71 #include "BIF_screen.h"         /* waitcursor */
72 #include "BIF_editview.h"       /* deselectall */
73
74 #include "BDR_editobject.h"     /* delete_obj */
75
76 #include "radio.h"
77
78 /* locals? not. done in radio.h...  */
79 /*  void rad_addmesh(void); */
80 /*  void rad_replacemesh(void); */
81
82 void addaccu(register char *z, register char *t)
83 {
84         register int div, mul;
85
86         mul= *t;
87         div= mul+1;
88         (*t)++;
89
90         t[1]= (mul*t[1]+z[1])/div;
91         t[2]= (mul*t[2]+z[2])/div;
92         t[3]= (mul*t[3]+z[3])/div;
93
94 }
95
96 void addaccuweight(register char *z, register char *t, int w)
97 {
98         register int div, mul;
99         
100         if(w==0) w= 1;
101         
102         mul= *t;
103         div= mul+w;
104         if(div>255) return;
105         (*t)= div;
106
107         t[1]= (mul*t[1]+w*z[1])/div;
108         t[2]= (mul*t[2]+w*z[2])/div;
109         t[3]= (mul*t[3]+w*z[3])/div;
110
111 }
112
113 void triaweight(Face *face, int *w1, int *w2, int *w3)
114 {
115         float n1[3], n2[3], n3[3], temp;
116
117         n1[0]= face->v2[0]-face->v1[0];
118         n1[1]= face->v2[1]-face->v1[1];
119         n1[2]= face->v2[2]-face->v1[2];
120         n2[0]= face->v3[0]-face->v2[0];
121         n2[1]= face->v3[1]-face->v2[1];
122         n2[2]= face->v3[2]-face->v2[2];
123         n3[0]= face->v1[0]-face->v3[0];
124         n3[1]= face->v1[1]-face->v3[1];
125         n3[2]= face->v1[2]-face->v3[2];
126         Normalise(n1);
127         Normalise(n2);
128         Normalise(n3);
129         temp= 32.0/(PI);
130         *w1= 0.5+temp*acos(-n1[0]*n3[0]-n1[1]*n3[1]-n1[2]*n3[2]);
131         *w2= 0.5+temp*acos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]);
132         *w3= 0.5+temp*acos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]);
133         
134 }
135
136
137
138 void init_face_tab()
139 {
140         int a= 0;
141
142         if(RG.facebase==0) {
143                 RG.facebase= MEM_callocN(sizeof(void *)*RAD_MAXFACETAB, "init_face_tab");
144         }
145         for(a=0; a<RAD_MAXFACETAB; a++) {
146                 if(RG.facebase[a]==0) break;
147                 MEM_freeN(RG.facebase[a]);
148                 RG.facebase[a]= 0;
149         }
150         RG.totface= 0;
151 }
152
153 Face *addface()
154 {
155         Face *face;
156         int a;
157
158         if(RG.totface<0 || RG.totface>RAD_MAXFACETAB*1024 ) {
159                 printf("error in addface: %d\n", RG.totface);
160                 return 0;
161         }
162         a= RG.totface>>10;
163         face= RG.facebase[a];
164         if(face==0) {
165                 face= MEM_callocN(1024*sizeof(Face),"addface");
166                 RG.facebase[a]= face;
167         }
168         face+= (RG.totface & 1023);
169         
170         RG.totface++;
171         
172         return face;
173
174 }
175
176 Face * makeface(float *v1, float *v2, float *v3, float *v4, RNode *rn)
177 {
178         Face *face;
179         
180         face= addface();
181         face->v1= v1;
182         face->v2= v2;
183         face->v3= v3;
184         face->v4= v4;
185         face->col= rn->col;
186         face->matindex= rn->par->matindex;
187         face->orig= rn->orig;
188
189         return face;
190 }
191
192 void anchorQuadface(RNode *rn, float *v1, float *v2, float *v3, float *v4, int flag)
193 {
194         Face *face;
195
196         switch(flag) {
197                 case 1:
198                         face = makeface(rn->v1, v1, rn->v4, NULL, rn);
199                         face = makeface(v1, rn->v3, rn->v4, NULL, rn);
200                         face = makeface(v1, rn->v2, rn->v3, NULL, rn);
201                         break;
202                 case 2:
203                         face = makeface(rn->v2, v2, rn->v1, NULL, rn);
204                         face = makeface(v2, rn->v4, rn->v1, NULL, rn);
205                         face = makeface(v2, rn->v3, rn->v4, NULL, rn);
206                         break;
207                 case 4:
208                         face = makeface(rn->v3, v3, rn->v2, NULL, rn);
209                         face = makeface(v3, rn->v1, rn->v2, NULL, rn);
210                         face = makeface(v3, rn->v4, rn->v1, NULL, rn);
211                         break;
212                 case 8:
213                         face = makeface(rn->v4, v4, rn->v3, NULL, rn);
214                         face = makeface(v4, rn->v2, rn->v3, NULL, rn);
215                         face = makeface(v4, rn->v1, rn->v2, NULL, rn);
216                         break;
217                 case 3:
218                         face = makeface(rn->v1, v1, rn->v4, NULL, rn);
219                         face = makeface(v1, v2, rn->v4, NULL, rn);
220                         face = makeface(v1, rn->v2, v2, NULL, rn);
221                         face = makeface(v2, rn->v3, rn->v4, NULL, rn);
222                         break;
223                 case 6:
224                         face = makeface(rn->v2, v2, rn->v1, NULL, rn);
225                         face = makeface(v2, v3, rn->v1, NULL, rn);
226                         face = makeface(v2, rn->v3, v3, NULL, rn);
227                         face = makeface(v3, rn->v4, rn->v1, NULL, rn);
228                         break;
229                 case 12:
230                         face = makeface(rn->v3, v3, rn->v2, NULL, rn);
231                         face = makeface(v3, v4, rn->v2, NULL, rn);
232                         face = makeface(v3, rn->v4, v4, NULL, rn);
233                         face = makeface(v4, rn->v1, rn->v2, NULL, rn);
234                         break;
235                 case 9:
236                         face = makeface(rn->v4, v4, rn->v3, NULL, rn);
237                         face = makeface(v4, v1, rn->v3, NULL, rn);
238                         face = makeface(v4, rn->v1, v1, NULL, rn);
239                         face = makeface(v1, rn->v2, rn->v3, NULL, rn);
240                         break;
241                 case 5:
242                         face = makeface(rn->v1, v1, v3, rn->v4, rn);
243                         face = makeface(v1, rn->v2, rn->v3, v3, rn);
244                         break;
245                 case 10:
246                         face = makeface(rn->v1, rn->v2, v2, v4, rn);
247                         face = makeface(v4, v2, rn->v3, rn->v4, rn);
248                         break;
249                 case 7:
250                         face = makeface(rn->v1, v1, v3, rn->v4, rn);
251                         face = makeface(v1, v2, v3, NULL, rn);
252                         face = makeface(v1, rn->v2, v2, NULL, rn);
253                         face = makeface(v2, rn->v3, v3, NULL, rn);
254                         break;
255                 case 14:
256                         face = makeface(rn->v2, v2, v4, rn->v1, rn);
257                         face = makeface(v2, v3, v4, NULL, rn);
258                         face = makeface(v2, rn->v3, v3, NULL, rn);
259                         face = makeface(v3, rn->v4, v4, NULL, rn);
260                         break;
261                 case 13:
262                         face = makeface(rn->v3, v3, v1, rn->v2, rn);
263                         face = makeface(v3, v4, v1, NULL, rn);
264                         face = makeface(v3, rn->v4, v4, NULL, rn);
265                         face = makeface(v4, rn->v1, v1, NULL, rn);
266                         break;
267                 case 11:
268                         face = makeface(rn->v4, v4, v2, rn->v3, rn);
269                         face = makeface(v4, v1, v2, NULL, rn);
270                         face = makeface(v4, rn->v1, v1, NULL, rn);
271                         face = makeface(v1, rn->v2, v2, NULL, rn);
272                         break;
273                 case 15:
274                         face = makeface(v1, v2, v3, v4, rn);
275                         face = makeface(v1, rn->v2, v2, NULL, rn);
276                         face = makeface(v2, rn->v3, v3, NULL, rn);
277                         face = makeface(v3, rn->v4, v4, NULL, rn);
278                         face = makeface(v4, rn->v1, v1, NULL, rn);
279                         break;
280         }
281 }
282
283 void anchorTriface(RNode *rn, float *v1, float *v2, float *v3, int flag)
284 {
285         Face *face;
286
287         switch(flag) {
288                 case 1:
289                         face = makeface(rn->v1, v1, rn->v3, NULL, rn);
290                         face = makeface(v1, rn->v2, rn->v3, NULL, rn);
291                         break;
292                 case 2:
293                         face = makeface(rn->v2, v2, rn->v1, NULL, rn);
294                         face = makeface(v2, rn->v3, rn->v1, NULL, rn);
295                         break;
296                 case 4:
297                         face = makeface(rn->v3, v3, rn->v2, NULL, rn);
298                         face = makeface(v3, rn->v1, rn->v2, NULL, rn);
299                         break;
300                 case 3:
301                         face = makeface(rn->v1, v2, rn->v3, NULL, rn);
302                         face = makeface(rn->v1, v1, v2, NULL, rn);
303                         face = makeface(v1, rn->v2, v2, NULL, rn);
304                         break;
305                 case 6:
306                         face = makeface(rn->v2, v3, rn->v1, NULL, rn);
307                         face = makeface(rn->v2, v2, v3, NULL, rn);
308                         face = makeface(v2, rn->v3, v3, NULL, rn);
309                         break;
310                 case 5:
311                         face = makeface(rn->v3, v1, rn->v2, NULL, rn);
312                         face = makeface(rn->v3, v3, v1, NULL, rn);
313                         face = makeface(v3, rn->v1, v1, NULL, rn);
314                         break;
315                         
316                 case 7:
317                         face = makeface(v1, v2, v3, NULL, rn);
318                         face = makeface(rn->v1, v1, v3, NULL, rn);
319                         face = makeface(rn->v2, v2, v1, NULL, rn);
320                         face = makeface(rn->v3, v3, v2, NULL, rn);
321                         break;
322         }       
323 }
324
325
326 float *findmiddlevertex(RNode *node, RNode *nb, float *v1, float *v2)
327 {
328         int test= 0;
329
330         if(nb==0) return 0;
331         
332         if(nb->ed1==node) {
333                 if(nb->v1==v1 || nb->v1==v2) test++;
334                 if(nb->v2==v1 || nb->v2==v2) test+=2;
335                 if(test==1) return nb->v2;
336                 else if(test==2) return nb->v1;
337         }
338         else if(nb->ed2==node) {
339                 if(nb->v2==v1 || nb->v2==v2) test++;
340                 if(nb->v3==v1 || nb->v3==v2) test+=2;
341                 if(test==1) return nb->v3;
342                 else if(test==2) return nb->v2;
343         }
344         else if(nb->ed3==node) {
345                 if(nb->type==4) {
346                         if(nb->v3==v1 || nb->v3==v2) test++;
347                         if(nb->v4==v1 || nb->v4==v2) test+=2;
348                         if(test==1) return nb->v4;
349                         else if(test==2) return nb->v3;
350                 }
351                 else {
352                         if(nb->v3==v1 || nb->v3==v2) test++;
353                         if(nb->v1==v1 || nb->v1==v2) test+=2;
354                         if(test==1) return nb->v1;
355                         else if(test==2) return nb->v3;
356                 }
357         }
358         else if(nb->ed4==node) {
359                 if(nb->v4==v1 || nb->v4==v2) test++;
360                 if(nb->v1==v1 || nb->v1==v2) test+=2;
361                 if(test==1) return nb->v1;
362                 else if(test==2) return nb->v4;
363         }
364         return 0;
365 }
366
367 void make_face_tab()    /* takes care of anchoring */
368 {
369         RNode *rn, **el;
370         Face *face = NULL;
371         float *v1, *v2, *v3, *v4;
372         int a, flag, w1, w2, w3;
373         char *charcol;
374
375         if(RG.totelem==0) return;
376         
377         init_face_tab();
378         
379         RG.igamma= 1.0/RG.gamma;
380         RG.radfactor= RG.radfac*pow(64*64, RG.igamma);
381
382         /* convert face colors */
383         el= RG.elem;
384         for(a=RG.totelem; a>0; a--, el++) {
385                 rn= *el;
386                 charcol= (char *)&( rn->col );
387
388                 charcol[3]= calculatecolor(rn->totrad[0]);
389                 charcol[2]= calculatecolor(rn->totrad[1]);
390                 charcol[1]= calculatecolor(rn->totrad[2]);
391         }
392         
393         /* check nodes and make faces */
394         el= RG.elem;
395         for(a=RG.totelem; a>0; a--, el++) {
396
397                 rn= *el;
398                 
399                 rn->v1[3]= 0.0;
400                 rn->v2[3]= 0.0;
401                 rn->v3[3]= 0.0;
402                 if(rn->v4) rn->v4[3]= 0.0;
403                 
404                 /* test edges for subdivide */
405                 flag= 0;
406                 v1= v2= v3= v4= 0;
407                 if(rn->ed1) {
408                         v1= findmiddlevertex(rn, rn->ed1->down1, rn->v1, rn->v2);
409                         if(v1) flag |= 1;
410                 }
411                 if(rn->ed2) {
412                         v2= findmiddlevertex(rn, rn->ed2->down1, rn->v2, rn->v3);
413                         if(v2) flag |= 2;
414                 }
415                 if(rn->ed3) {
416                         if(rn->type==4)
417                                 v3= findmiddlevertex(rn, rn->ed3->down1, rn->v3, rn->v4);
418                         else
419                                 v3= findmiddlevertex(rn, rn->ed3->down1, rn->v3, rn->v1);
420                         if(v3) flag |= 4;
421                 }
422                 if(rn->ed4) {
423                         v4= findmiddlevertex(rn, rn->ed4->down1, rn->v4, rn->v1);
424                         if(v4) flag |= 8;
425                 }
426                 
427                 /* using flag and vertexpointers now Faces can be made */
428                 
429                 if(flag==0) {
430                         makeface(rn->v1, rn->v2, rn->v3, rn->v4, rn);
431                 }
432                 else if(rn->type==4) anchorQuadface(rn, v1, v2, v3, v4, flag);
433                 else anchorTriface(rn, v1, v2, v3, flag);
434         }
435         
436         /* add */
437         for(a=0; a<RG.totface; a++) {
438                 
439                 RAD_NEXTFACE(a);
440                 
441                 if(face->v4) {
442                         addaccuweight( (char *)&(face->col), (char *)(face->v1+3), 16 );
443                         addaccuweight( (char *)&(face->col), (char *)(face->v2+3), 16 );
444                         addaccuweight( (char *)&(face->col), (char *)(face->v3+3), 16 );
445                         addaccuweight( (char *)&(face->col), (char *)(face->v4+3), 16 );
446                 }
447                 else {
448                         triaweight(face, &w1, &w2, &w3);
449                         addaccuweight( (char *)&(face->col), (char *)(face->v1+3), w1 );
450                         addaccuweight( (char *)&(face->col), (char *)(face->v2+3), w2 );
451                         addaccuweight( (char *)&(face->col), (char *)(face->v3+3), w3 );
452                 }
453         }
454
455 }
456
457 void filterFaces()
458 {
459         /* put vertex colors in faces, and put them back */
460         
461         Face *face = NULL;
462         int a, w1, w2, w3;
463
464         if(RG.totface==0) return;
465
466         /* clear */
467         for(a=0; a<RG.totface; a++) {
468                 RAD_NEXTFACE(a);
469                 face->col= 0;
470         }
471         
472         /* add: vertices with faces */
473         for(a=0; a<RG.totface; a++) {
474                 RAD_NEXTFACE(a);
475                 
476                 if(face->v4) {
477                         addaccuweight( (char *)(face->v1+3), (char *)&(face->col), 16 );
478                         addaccuweight( (char *)(face->v2+3), (char *)&(face->col), 16 );
479                         addaccuweight( (char *)(face->v3+3), (char *)&(face->col), 16 );
480                         addaccuweight( (char *)(face->v4+3), (char *)&(face->col), 16 );
481                 }
482                 else {
483                         triaweight(face, &w1, &w2, &w3);
484                         addaccuweight( (char *)(face->v1+3), (char *)&(face->col), w1 );
485                         addaccuweight( (char *)(face->v2+3), (char *)&(face->col), w2 );
486                         addaccuweight( (char *)(face->v3+3), (char *)&(face->col), w3 );
487                 }
488         }
489         
490         /* clear */
491         for(a=0; a<RG.totface; a++) {
492                 RAD_NEXTFACE(a);
493                 face->v1[3]= 0.0;
494                 face->v2[3]= 0.0;
495                 face->v3[3]= 0.0;
496                 if(face->v4) face->v4[3]= 0.0;
497         }
498
499
500         /* add: faces with vertices */
501         for(a=0; a<RG.totface; a++) {
502                 
503                 RAD_NEXTFACE(a);
504                 
505                 if(face->v4) {
506                         addaccuweight( (char *)&(face->col), (char *)(face->v1+3), 16 );
507                         addaccuweight( (char *)&(face->col), (char *)(face->v2+3), 16 );
508                         addaccuweight( (char *)&(face->col), (char *)(face->v3+3), 16 );
509                         addaccuweight( (char *)&(face->col), (char *)(face->v4+3), 16 );
510                 }
511                 else {
512                         triaweight(face, &w1, &w2, &w3);
513                         addaccuweight( (char *)&(face->col), (char *)(face->v1+3), w1 );
514                         addaccuweight( (char *)&(face->col), (char *)(face->v2+3), w2 );
515                         addaccuweight( (char *)&(face->col), (char *)(face->v3+3), w3 );
516                 }
517         }
518 }
519
520 void calcfiltrad(RNode *rn, float *cd)
521 {
522         float area;
523
524         cd[0]= 2.0*rn->totrad[0];
525         cd[1]= 2.0*rn->totrad[1];
526         cd[2]= 2.0*rn->totrad[2];
527         area= 2.0;
528         
529         if(rn->ed1) {
530                 cd[0]+= rn->ed1->totrad[0];
531                 cd[1]+= rn->ed1->totrad[1];
532                 cd[2]+= rn->ed1->totrad[2];
533                 area+= 1.0;
534         }
535         if(rn->ed2) {
536                 cd[0]+= rn->ed2->totrad[0];
537                 cd[1]+= rn->ed2->totrad[1];
538                 cd[2]+= rn->ed2->totrad[2];
539                 area+= 1.0;
540         }
541         if(rn->ed3) {
542                 cd[0]+= rn->ed3->totrad[0];
543                 cd[1]+= rn->ed3->totrad[1];
544                 cd[2]+= rn->ed3->totrad[2];
545                 area+= 1.0;
546         }
547         if(rn->ed4) {
548                 cd[0]+= rn->ed4->totrad[0];
549                 cd[1]+= rn->ed4->totrad[1];
550                 cd[2]+= rn->ed4->totrad[2];
551                 area+= 1.0;
552         }
553         cd[0]/= area;
554         cd[1]/= area;
555         cd[2]/= area;
556         
557 }
558
559 void filterNodes()
560 {
561         /* colors from nodes in tempblock and back */
562         
563         RNode *rn, **el;
564         float *coldata, *cd;
565         int a;
566
567         if(RG.totelem==0) return;
568         /* the up-nodes need a color */
569         el= RG.elem;
570         for(a=0; a<RG.totelem; a++, el++) {
571                 rn= *el;
572                 if(rn->up) {
573                         rn->up->totrad[0]= 0.0;
574                         rn->up->totrad[1]= 0.0;
575                         rn->up->totrad[2]= 0.0;
576                         if(rn->up->up) {
577                                 rn->up->up->totrad[0]= 0.0;
578                                 rn->up->up->totrad[1]= 0.0;
579                                 rn->up->up->totrad[2]= 0.0;
580                         }
581                 }
582         }
583         el= RG.elem;
584         for(a=0; a<RG.totelem; a++, el++) {
585                 rn= *el;
586                 if(rn->up) {
587                         rn->up->totrad[0]+= 0.5*rn->totrad[0];
588                         rn->up->totrad[1]+= 0.5*rn->totrad[1];
589                         rn->up->totrad[2]+= 0.5*rn->totrad[2];
590                         if(rn->up->up) {
591                                 rn->up->up->totrad[0]+= 0.25*rn->totrad[0];
592                                 rn->up->up->totrad[1]+= 0.25*rn->totrad[1];
593                                 rn->up->up->totrad[2]+= 0.25*rn->totrad[2];
594                         }
595                 }
596         }
597         
598         /* add using area */
599         cd= coldata= MEM_mallocN(3*4*RG.totelem, "filterNodes");
600         el= RG.elem;
601         for(a=0; a<RG.totelem; a++, el++) {
602                 calcfiltrad(*el, cd);
603                 cd+= 3;
604         }
605         
606         cd= coldata;
607         el= RG.elem;
608         for(a=0; a<RG.totelem; a++, el++) {
609                 rn= *el;
610                 VECCOPY(rn->totrad, cd);
611                 cd+= 3;
612         }
613         MEM_freeN(coldata);
614 }
615
616 void removeEqualNodes(short limit)
617 {
618         /* nodes with equal colors: remove */
619         RNode **el, *rn, *rn1;
620         float thresh, f1, f2;
621         int a, foundone=1, ok;
622         int c1, c2;
623         
624         if(limit==0) return;
625         
626         thresh= 1.0/(256.0*RG.radfactor);
627         thresh= 3.0*pow(thresh, RG.gamma);
628         
629         waitcursor(1);
630                 
631         while(foundone) {
632                 foundone= 0;
633                 
634                 el= RG.elem;
635                 for(a=RG.totelem; a>1; a--, el++) {
636                         rn= *el;
637                         rn1= *(el+1);
638                         
639                         if(rn!=rn->par->first && rn1!=rn1->par->first) {
640                                 if(rn->up && rn->up==rn1->up) {
641                                         f1= rn->totrad[0]+ rn->totrad[1]+ rn->totrad[2];
642                                         f2= rn1->totrad[0]+ rn1->totrad[1]+ rn1->totrad[2];
643                                         
644                                         ok= 0;
645                                         if(f1<thresh && f2<thresh) ok= 1;
646                                         else {
647                                                 c1= calculatecolor(rn->totrad[0]);
648                                                 c2= calculatecolor(rn1->totrad[0]);
649                                                 
650                                                 if( abs(c1-c2)<=limit ) {
651                                                         c1= calculatecolor(rn->totrad[1]);
652                                                         c2= calculatecolor(rn1->totrad[1]);
653                                                         
654                                                         if( abs(c1-c2)<=limit ) {
655                                                                 c1= calculatecolor(rn->totrad[2]);
656                                                                 c2= calculatecolor(rn1->totrad[2]);
657                                                                 
658                                                                 if( abs(c1-c2)<=limit ) {
659                                                                         ok= 1;
660                                                                 }
661                                                         }
662                                                 }
663                                         }
664                                         
665                                         if(ok) {
666                                                 rn->up->totrad[0]= 0.5f*(rn->totrad[0]+rn1->totrad[0]);
667                                                 rn->up->totrad[1]= 0.5f*(rn->totrad[1]+rn1->totrad[1]);
668                                                 rn->up->totrad[2]= 0.5f*(rn->totrad[2]+rn1->totrad[2]);
669                                                 rn1= rn->up;
670                                                 deleteNodes(rn1);
671                                                 if(rn1->down1) ;
672                                                 else {
673                                                         foundone++;
674                                                         a--; el++;
675                                                 }
676                                         }
677                                 }
678                         }
679                 }
680                 if(foundone) {
681                         makeGlobalElemArray();
682                 }
683         }
684         waitcursor(0);
685 }
686
687 void rad_addmesh(void)
688 {
689         Face *face = NULL;
690         Object *ob;
691         Mesh *me;
692         MVert *mvert;
693         MFace *mf;
694         Material *ma=0;
695         float **vco, **vertexco;
696         float cent[3], min[3], max[3];
697         int a, nvert, i;
698         unsigned int *mcol;
699         
700         if(RG.totface==0)
701                 return;
702         
703         if(RG.totmat==MAXMAT)
704                 notice("warning: cannot assign more than 16 materials to 1 mesh");
705         
706         /* create the mesh */
707         ob= add_object(OB_MESH);
708         
709         me= ob->data;
710         me->totvert= 0;
711         me->totface= RG.totface;
712         me->flag= 0;
713         me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, 0, NULL, me->totface);
714         me->mcol= CustomData_add_layer(&me->fdata, CD_MCOL, 0, NULL, me->totface);
715
716         CustomData_merge(RG.mfdata, &me->fdata, CD_MASK_MESH, CD_CALLOC, me->totface);
717         mesh_update_customdata_pointers(me);
718
719         /* create materials and set vertex color flag */
720         for(a=0; a<RG.totmat; a++) {
721                 assign_material(ob, RG.matar[a], a+1);
722                 ma= RG.matar[a];
723                 if(ma) ma->mode |= MA_VERTEXCOL;
724         }
725
726         /* copy face data, load Face vertex colors into mcol, with alpha added */
727         mcol= (unsigned int*)me->mcol;
728         for(a=0; a<me->totface; a++, mcol+=4) {
729                 RAD_NEXTFACE(a);
730
731                 CustomData_copy_data(RG.mfdata, &me->fdata, face->orig, a, 1);
732
733                 mcol[0]= *((unsigned int*)face->v1+3) | 0x1000000;
734                 mcol[1]= *((unsigned int*)face->v2+3) | 0x1000000;
735                 mcol[2]= *((unsigned int*)face->v3+3) | 0x1000000;
736                 if(face->v4)
737                         mcol[3]= *((unsigned int*)face->v4+3) | 0x1000000;
738         }
739
740         /* clear Face vertex color memory for vertex index assignment */
741         for(a=0; a<me->totface; a++) {
742                 RAD_NEXTFACE(a);
743
744                 *((unsigned int*)face->v1+3)= ~0;
745                 *((unsigned int*)face->v2+3)= ~0;
746                 *((unsigned int*)face->v3+3)= ~0;
747                 if(face->v4)
748                         *((unsigned int*)face->v4+3)= ~0;
749         }
750
751         /* create faces and create array with pointers to vertex coords */
752         vco= vertexco= MEM_mallocN(sizeof(float *)*4*RG.totface, "radiovertexco");
753         mf= me->mface;
754
755         for(a=0; a<me->totface; a++, mf++) {
756                 RAD_NEXTFACE(a);
757                 nvert= (face->v4)? 4: 3;
758
759                 for(i=0; i<nvert; i++) {
760                         unsigned int *col= ((unsigned int**)&face->v1)[i] + 3;
761
762                         if (*col == ~0) {
763                                 /* vertex has no index yet, so assign one */
764                                 *col= me->totvert;
765                                 *vco= ((float**)&face->v1)[i];
766                                 me->totvert++;
767                                 vco++;
768                         }
769
770                         ((unsigned int*)&mf->v1)[i] = *col;
771                 }
772         }
773
774         /* create vertices */
775         me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, 0, NULL, me->totvert);
776         mvert= me->mvert;
777         for(vco=vertexco, a=0; a<me->totvert; a++, mvert++, vco++) {
778                 VECCOPY(mvert->co, *vco);
779         }
780
781         MEM_freeN(vertexco);
782         
783         /* assign face data */
784         mf= me->mface;
785
786         for(a=0; a<me->totface; a++, mf++ ) {
787                 RNode *orignode;
788                 float w[4][4];
789                 float *subco;
790
791                 RAD_NEXTFACE(a);
792                 nvert= (face->v4)? 4: 3;
793
794                 /* copy */
795                 mf->mat_nr= face->matindex;
796
797                 orignode= RG.mfdatanodes[face->orig];
798
799                 for(i=0; i<nvert; i++) {
800                         subco= (me->mvert + ((unsigned int*)&mf->v1)[i])->co;
801
802                         InterpWeightsQ3Dfl(orignode->v1, orignode->v2, orignode->v3,
803                                 orignode->v4, subco, w[i]);
804                 }
805
806                 CustomData_interp(RG.mfdata, &me->fdata, &face->orig, NULL, (float*)w, 1, a);
807         }
808
809         /* restore vertex colors, and test_index */
810         mf= me->mface;
811         mcol= (unsigned int*)me->mcol;
812         for(a=0; a<me->totface; a++, mf++, mcol+=4) {
813                 RAD_NEXTFACE(a);
814
815                 *((unsigned int*)face->v1+3)= mcol[0];
816                 *((unsigned int*)face->v2+3)= mcol[1];
817                 *((unsigned int*)face->v3+3)= mcol[2];
818                 if(face->v4)
819                         *((unsigned int*)face->v4+3)= mcol[3];
820
821                 test_index_face(mf, &me->fdata, a, face->v4? 4: 3);
822         }
823
824         /* boundbox and centre new */
825         INIT_MINMAX(min, max);
826
827         mvert= me->mvert;
828         for(a=0; a<me->totvert; a++, mvert++) {
829                 DO_MINMAX(mvert->co, min, max);
830         }
831
832         cent[0]= (min[0]+max[0])/2.0f;
833         cent[1]= (min[1]+max[1])/2.0f;
834         cent[2]= (min[2]+max[2])/2.0f;
835
836         mvert= me->mvert;
837         for(a=0; a<me->totvert; a++, mvert++) {
838                 VecSubf(mvert->co, mvert->co, cent);
839         }
840         
841         VECCOPY(ob->loc, cent);
842
843         /* create edges */
844         make_edges(me, 0);
845 }
846
847 void rad_replacemesh(void)
848 {
849         RPatch *rp;
850         
851         deselectall();
852         
853         rp= RG.patchbase.first;
854         while(rp) {
855                 if( exist_object(rp->from)) {
856                         if (rp->from->type == OB_MESH) {
857                                 rp->from->flag |= SELECT;
858                         }
859                 }
860                 rp= rp->next;
861         }
862         
863         copy_objectflags();
864         delete_obj(1);
865         
866         rad_addmesh();
867 }
868