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