Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/radiosity')
-rw-r--r--source/blender/radiosity/Makefile37
-rw-r--r--source/blender/radiosity/extern/include/radio.h170
-rw-r--r--source/blender/radiosity/extern/include/radio_types.h174
-rw-r--r--source/blender/radiosity/intern/Makefile37
-rw-r--r--source/blender/radiosity/intern/source/Makefile60
-rw-r--r--source/blender/radiosity/intern/source/raddisplay.c527
-rw-r--r--source/blender/radiosity/intern/source/radfactors.c956
-rw-r--r--source/blender/radiosity/intern/source/radio.c379
-rw-r--r--source/blender/radiosity/intern/source/radnode.c1095
-rw-r--r--source/blender/radiosity/intern/source/radpostprocess.c871
-rw-r--r--source/blender/radiosity/intern/source/radpreprocess.c787
11 files changed, 5093 insertions, 0 deletions
diff --git a/source/blender/radiosity/Makefile b/source/blender/radiosity/Makefile
new file mode 100644
index 00000000000..9bbb20c3db4
--- /dev/null
+++ b/source/blender/radiosity/Makefile
@@ -0,0 +1,37 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+SOURCEDIR = source/blender/radiosity
+DIRS = intern
+
+include nan_subdirs.mk
diff --git a/source/blender/radiosity/extern/include/radio.h b/source/blender/radiosity/extern/include/radio.h
new file mode 100644
index 00000000000..de8fc82195b
--- /dev/null
+++ b/source/blender/radiosity/extern/include/radio.h
@@ -0,0 +1,170 @@
+/* ***************************************
+
+
+
+ radio.h nov/dec 1992
+ revised for Blender may 1999
+
+ $Id$
+
+ ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version. The Blender
+ Foundation also sells licenses for use in proprietary software under
+ the Blender License. See http://www.blender.org/BL/ for information
+ about this.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ All rights reserved.
+
+ The Original Code is: all of this file.
+
+ Contributor(s): none yet.
+
+ ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef RADIO_H
+#define RADIO_H
+#define RADIO_H
+
+/* type include */
+#include "radio_types.h"
+
+extern RadGlobal RG;
+
+/* radfactors.c */
+extern float calcStokefactor(RPatch *shoot, RPatch *rp, RNode *rn, float *area);
+extern void calcTopfactors(void);
+void calcSidefactors(void);
+extern void initradiosity(void);
+extern void rad_make_hocos(RadView *vw);
+extern void hemizbuf(RadView *vw);
+extern int makeformfactors(RPatch *shoot);
+extern void applyformfactors(RPatch *shoot);
+extern RPatch *findshootpatch(void);
+extern void setnodeflags(RNode *rn, int flag, int set);
+extern void backface_test(RPatch *shoot);
+extern void clear_backface_test(void);
+extern void progressiverad(void);
+extern void minmaxradelem(RNode *rn, float *min, float *max);
+extern void minmaxradelemfilt(RNode *rn, float *min, float *max, float *errmin, float *errmax);
+extern void subdivideshootElements(int it);
+extern void subdivideshootPatches(int it);
+extern void inithemiwindows(void);
+extern void closehemiwindows(void);
+void rad_init_energy(void);
+
+/* radio.c */
+void freeAllRad(void);
+int rad_phase(void);
+void rad_status_str(char *str);
+void rad_printstatus(void);
+void rad_setlimits(void);
+void set_radglobal(void);
+void add_radio(void);
+void delete_radio(void);
+int rad_go(void);
+void rad_subdivshootpatch(void);
+void rad_subdivshootelem(void);
+void rad_limit_subdivide(void);
+
+/* radnode.c */
+extern void setnodelimit(float limit);
+extern float *mallocVert(void);
+extern float *callocVert(void);
+extern void freeVert(float *vert);
+extern RNode *mallocNode(void);
+extern RNode *callocNode(void);
+extern void freeNode(RNode *node);
+extern void freeNode_recurs(RNode *node);
+extern RPatch *mallocPatch(void);
+extern RPatch *callocPatch(void);
+extern void freePatch(RPatch *patch);
+extern void replaceAllNode(RNode *, RNode *);
+extern void replaceAllNodeInv(RNode *neighb, RNode *old);
+extern void replaceAllNodeUp(RNode *neighb, RNode *old);
+extern void replaceTestNode(RNode *, RNode **, RNode *, int , float *);
+extern void free_fastAll(void);
+
+/* radnode.c */
+extern void start_fastmalloc(char *str);
+extern int setvertexpointersNode(RNode *neighb, RNode *node, int level, float **v1, float **v2);
+extern float edlen(float *v1, float *v2);
+extern void deleteNodes(RNode *node);
+extern void subdivideTriNode(RNode *node, RNode *edge);
+extern void subdivideNode(RNode *node, RNode *edge);
+extern int comparelevel(RNode *node, RNode *nb, int level);
+
+/* radpreprocess.c */
+extern void splitconnected(void);
+extern int vergedge(const void *v1,const void *v2);
+extern void addedge(float *v1, float *v2, EdSort *es);
+extern void setedgepointers(void);
+extern void rad_collect_meshes(void);
+extern void countelem(RNode *rn);
+extern void countglobaldata(void);
+extern void addelem(RNode ***el, RNode *rn, RPatch *rp);
+extern void makeGlobalElemArray(void);
+extern void remakeGlobaldata(void);
+extern void splitpatch(RPatch *old);
+extern void addpatch(RPatch *old, RNode *rn);
+extern void converttopatches(void);
+extern void make_elements(void);
+extern void subdividelamps(void);
+extern void maxsizePatches(void);
+extern void subdiv_elements(void);
+
+/* radpostprocess.c */
+void addaccu(register char *z, register char *t);
+void addaccuweight(register char *z, register char *t, int w);
+void triaweight(Face *face, int *w1, int *w2, int *w3);
+void init_face_tab(void);
+Face *addface(void);
+void makeface(float *v1, float *v2, float *v3, float *v4, RNode *rn);
+void anchorQuadface(RNode *rn, float *v1, float *v2, float *v3, float *v4, int flag);
+void anchorTriface(RNode *rn, float *v1, float *v2, float *v3, int flag);
+float *findmiddlevertex(RNode *node, RNode *nb, float *v1, float *v2);
+void make_face_tab(void);
+void filterFaces(void);
+void calcfiltrad(RNode *rn, float *cd);
+void filterNodes(void);
+void removeEqualNodes(short limit);
+void rad_addmesh(void);
+void rad_replacemesh(void);
+
+/* raddisplay.c */
+extern char calculatecolor(float col);
+extern void make_node_display(void);
+extern void drawnodeWire(RNode *rn);
+extern void drawsingnodeWire(RNode *rn);
+extern void drawnodeSolid(RNode *rn);
+extern void drawnodeGour(RNode *rn);
+extern void drawpatch(RPatch *patch, unsigned int col);
+extern void drawnode_ext(RNode *rn, unsigned int col);
+extern void drawOverflowElem(void);
+extern void drawfaceGour(Face *face);
+extern void drawfaceSolid(Face *face);
+extern void drawfaceWire(Face *face);
+extern void drawsquare(float *cent, float size, short cox, short coy);
+extern void drawlimits(void);
+extern void setcolNode(RNode *rn, unsigned int *col);
+extern void pseudoAmb(void);
+extern void rad_forcedraw(void);
+extern void drawpatch_ext(RPatch *patch, unsigned int col);
+
+extern void RAD_drawall(int depth_is_on);
+
+#endif /* RADIO_H */
diff --git a/source/blender/radiosity/extern/include/radio_types.h b/source/blender/radiosity/extern/include/radio_types.h
new file mode 100644
index 00000000000..c687188c889
--- /dev/null
+++ b/source/blender/radiosity/extern/include/radio_types.h
@@ -0,0 +1,174 @@
+/*
+ * radio_types.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/* #include "misc_util.h" */ /* for listbase...*/
+
+
+#ifndef RADIO_TYPES_H
+#define RADIO_TYPES_H
+
+#include "DNA_listBase.h"
+#include "DNA_material_types.h"
+
+#define DTWIRE 0
+#define DTGOUR 2
+#define DTSOLID 1
+
+#define PI M_PI
+#define RAD_MAXFACETAB 1024
+#define RAD_NEXTFACE(a) if( ((a) & 1023)==0 ) face= RG.facebase[(a)>>10]; else face++;
+
+/* RG.phase */
+#define RAD_SHOOTE 1
+#define RAD_SHOOTP 2
+#define RAD_SOLVE 3
+
+typedef struct RadView {
+ float cam[3], tar[3], up[3];
+ float wx1, wx2, wy1, wy2;
+ float mynear, myfar;
+ float viewmat[4][4], winmat[4][4];
+ unsigned int *rect, *rectz;
+ short rectx, recty;
+ int wid;
+
+} RadView;
+
+/* rn->f */
+#define RAD_PATCH 1
+#define RAD_SHOOT 2
+#define RAD_SUBDIV 4
+#define RAD_BACKFACE 8
+
+
+typedef struct RNode { /* lengte: 76 */
+ struct RNode *down1, *down2, *up;
+ struct RNode *ed1, *ed2, *ed3, *ed4;
+ struct RPatch *par;
+
+ char lev1, lev2, lev3, lev4; /* edgelevels */
+ short type; /* type: 4==QUAD, 3==TRIA */
+ short f;
+ float *v1, *v2, *v3, *v4;
+ float totrad[3], area;
+
+ unsigned int col;
+} RNode;
+
+
+typedef struct Elem { /* lengte: 44 */
+ struct RPatch *par;
+
+ short type; /* type: 4==QUAD, 3==TRIA */
+ short f; /* bit 0: patch, bit 1: shootelement */
+ float *v1, *v2, *v3, *v4;
+ float totrad[3], area;
+
+ unsigned int col;
+} Elem;
+
+
+typedef struct Face { /* lengte: 24 */
+ float *v1, *v2, *v3, *v4;
+ unsigned int col, matindex;
+} Face;
+
+/* rp->f1 */
+#define RAD_NO_SPLIT 1
+
+typedef struct RPatch {
+ struct RPatch *next, *prev;
+ RNode *first; /* first node==patch */
+
+ struct Object *from;
+
+ int type; /* 3: TRIA, 4: QUAD */
+ short f, f1; /* flags f: als node, alleen subdiv */
+
+ float ref[3], emit[3], unshot[3];
+ float cent[3], norm[3];
+ float area;
+ int matindex;
+
+} RPatch;
+
+
+typedef struct VeNoCo { /* nodig voor splitconnected */
+ struct VeNoCo *next;
+ float *v;
+ float *n;
+ float *col;
+ int flag;
+} VeNoCo;
+
+
+typedef struct EdSort { /* sorteren edges */
+ float *v1, *v2;
+ RNode *node;
+ int nr;
+} EdSort;
+
+typedef struct {
+ struct Radio *radio;
+ unsigned int *hemibuf;
+ struct ListBase patchbase;
+ int totpatch, totelem, totvert, totlamp;
+ RNode **elem; /* globaal array van alle pointers */
+ VeNoCo *verts; /* tijdelijk vertices van patches */
+ float *formfactors; /* een factor per element */
+ float *topfactors, *sidefactors; /* LUT voor delta's */
+ int *index; /* LUT voor bovenstaande LUT */
+ Face **facebase;
+ int totface;
+ float min[3], max[3], size[3], cent[3]; /* world */
+ float maxsize, totenergy;
+ float patchmin, patchmax;
+ float elemmin, elemmax;
+ float radfactor, lostenergy, igamma; /* radfac zit in button, radfactor wordt berekend */
+ int phase;
+ /* to preserve materials as used before, max 16 */
+ Material *matar[MAXMAT];
+ int totmat;
+
+ /* this part is a copy of struct Radio */
+ short hemires, maxiter;
+ short drawtype, flag; /* bit 0 en 1: limits laten zien */
+ short subshootp, subshoote, nodelim, maxsublamp;
+ int maxnode;
+ float convergence;
+ float radfac, gamma; /* voor afbeelden */
+
+} RadGlobal;
+
+#endif /* radio_types.h */
diff --git a/source/blender/radiosity/intern/Makefile b/source/blender/radiosity/intern/Makefile
new file mode 100644
index 00000000000..fde495bed85
--- /dev/null
+++ b/source/blender/radiosity/intern/Makefile
@@ -0,0 +1,37 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+SOURCEDIR = source/blender/radiosity/intern
+DIRS = source
+
+include nan_subdirs.mk
diff --git a/source/blender/radiosity/intern/source/Makefile b/source/blender/radiosity/intern/source/Makefile
new file mode 100644
index 00000000000..e0bb43772c2
--- /dev/null
+++ b/source/blender/radiosity/intern/source/Makefile
@@ -0,0 +1,60 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+#
+# radiosity uses the render lib
+#
+
+LIBNAME = radiosity
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+# not very neat....
+CPPFLAGS += -I../../../blenkernel
+CPPFLAGS += -I../../../blenlib
+CPPFLAGS += -I../../../makesdna
+CPPFLAGS += -I../../../imbuf
+CPPFLAGS += -I../../../
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+# first /include is my own includes, second are the external includes
+# third is the external interface. there should be a nicer way to say this
+CPPFLAGS += -I../include -I../../../include -I../../extern/include
+CPPFLAGS += -I../../../render/extern/include -I../../../misc
+
diff --git a/source/blender/radiosity/intern/source/raddisplay.c b/source/blender/radiosity/intern/source/raddisplay.c
new file mode 100644
index 00000000000..b2689cf2ad6
--- /dev/null
+++ b/source/blender/radiosity/intern/source/raddisplay.c
@@ -0,0 +1,527 @@
+/* ***************************************
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+
+
+
+ raddisplay.c nov/dec 1992
+ may 1999
+
+ - drawing
+ - color calculation for display during solving
+
+ $Id$
+
+ *************************************** */
+
+#include <stdlib.h>
+#include <math.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "BLI_blenlib.h"
+
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "BIF_gl.h"
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "BIF_mywindow.h"
+
+#include "radio.h"
+
+/* Mij afspraak is cpack een getal dat als 0xFFaa66 of zo kan worden
+ * uitgedrukt. Is dus gevoelig voor endian. Met deze define wordt het
+ * altijd goed afgebeeld */
+#define cpack(x) glColor3ub( ((x)&0xFF), (((x)>>8)&0xFF), (((x)>>16)&0xFF) )
+
+char calculatecolor(float col)
+{
+ int b;
+
+ if(RG.gamma==1.0) {
+ b= RG.radfactor*col;
+ }
+ else if(RG.gamma==2.0) {
+ b= RG.radfactor*sqrt(col);
+ }
+ else {
+ b= RG.radfactor*pow(col, RG.igamma);
+ }
+
+ if(b>255) b=255;
+ return b;
+}
+
+void make_node_display()
+{
+ RNode *rn, **el;
+ int a;
+ char *charcol;
+
+ RG.igamma= 1.0/RG.gamma;
+ RG.radfactor= RG.radfac*pow(64*64, RG.igamma);
+
+ el= RG.elem;
+ for(a=RG.totelem; a>0; a--, el++) {
+ rn= *el;
+ charcol= (char *)&( rn->col );
+
+ charcol[3]= calculatecolor(rn->totrad[0]);
+ charcol[2]= calculatecolor(rn->totrad[1]);
+ charcol[1]= calculatecolor(rn->totrad[2]);
+
+ /* gouraudcolor */
+ *(rn->v1+3)= 0;
+ *(rn->v2+3)= 0;
+ *(rn->v3+3)= 0;
+ if(rn->v4) *(rn->v4+3)= 0;
+ }
+
+ el= RG.elem;
+ for(a=RG.totelem; a>0; a--, el++) {
+ rn= *el;
+ addaccuweight( (char *)&(rn->col), (char *)(rn->v1+3), 16 );
+ addaccuweight( (char *)&(rn->col), (char *)(rn->v2+3), 16 );
+ addaccuweight( (char *)&(rn->col), (char *)(rn->v3+3), 16 );
+ if(rn->v4) addaccuweight( (char *)&(rn->col), (char *)(rn->v4+3), 16 );
+ }
+}
+
+void drawnodeWire(RNode *rn)
+{
+
+ if(rn->down1) {
+ drawnodeWire(rn->down1);
+ drawnodeWire(rn->down2);
+ }
+ else {
+ glBegin(GL_LINE_LOOP);
+ glVertex3fv(rn->v1);
+ glVertex3fv(rn->v2);
+ glVertex3fv(rn->v3);
+ if(rn->type==4) glVertex3fv(rn->v4);
+ glEnd();
+ }
+}
+
+void drawsingnodeWire(RNode *rn)
+{
+
+ glBegin(GL_LINE_LOOP);
+ glVertex3fv(rn->v1);
+ glVertex3fv(rn->v2);
+ glVertex3fv(rn->v3);
+ if(rn->type==4) glVertex3fv(rn->v4);
+ glEnd();
+}
+
+void drawnodeSolid(RNode *rn)
+{
+ char *cp;
+
+ if(rn->down1) {
+ drawnodeSolid(rn->down1);
+ drawnodeSolid(rn->down2);
+ }
+ else {
+ cp= (char *)&rn->col;
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glBegin(GL_POLYGON);
+ glVertex3fv(rn->v1);
+ glVertex3fv(rn->v2);
+ glVertex3fv(rn->v3);
+ if(rn->type==4) glVertex3fv(rn->v4);
+ glEnd();
+ }
+}
+
+void drawnodeGour(RNode *rn)
+{
+ char *cp;
+
+ if(rn->down1) {
+ drawnodeGour(rn->down1);
+ drawnodeGour(rn->down2);
+ }
+ else {
+ glBegin(GL_POLYGON);
+ cp= (char *)(rn->v1+3);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(rn->v1);
+
+ cp= (char *)(rn->v2+3);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(rn->v2);
+
+ cp= (char *)(rn->v3+3);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(rn->v3);
+
+ if(rn->type==4) {
+ cp= (char *)(rn->v4+3);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(rn->v4);
+ }
+ glEnd();
+ }
+}
+
+void drawpatch_ext(RPatch *patch, unsigned int col)
+{
+ ScrArea *sa, *oldsa;
+
+ glDrawBuffer(GL_FRONT);
+ if(G.zbuf) glDisable(GL_DEPTH_TEST);
+
+ cpack(col);
+
+ oldsa= curarea;
+
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if (sa->spacetype==SPACE_VIEW3D) {
+ /* hier mywinget() gebruiken: anders wordt in header getekend */
+ if(sa->win != mywinget()) areawinset(sa->win);
+ drawnodeWire(patch->first);
+ }
+ sa= sa->next;
+ }
+
+ if(oldsa && oldsa!=curarea) areawinset(oldsa->win);
+
+ glDrawBuffer(GL_BACK);
+ if(G.zbuf) glEnable(GL_DEPTH_TEST);
+}
+
+void drawnode_ext(RNode *rn, unsigned int col)
+{
+
+ glDrawBuffer(GL_FRONT);
+ if(G.zbuf) glDisable(GL_DEPTH_TEST);
+
+ cpack(col);
+
+ drawnodeWire(rn);
+
+ glDrawBuffer(GL_BACK);
+ if(G.zbuf) glEnable(GL_DEPTH_TEST);
+}
+
+void drawOverflowElem()
+{
+ RNode **el, *rn;
+ float *fp;
+ int a;
+
+ glDrawBuffer(GL_FRONT);
+ if(G.zbuf) glDisable(GL_DEPTH_TEST);
+
+ cpack(0xFF9900);
+
+ el= RG.elem;
+ fp= RG.formfactors;
+ for(a=0; a<RG.totelem; a++, el++, fp++) {
+ if(*fp>1.0) {
+ rn= *el;
+ glBegin(GL_LINE_LOOP);
+ glVertex3fv( rn->v1);
+ glVertex3fv( rn->v2);
+ glVertex3fv( rn->v3);
+ if(rn->type==4) glVertex3fv( rn->v4);
+ glEnd();
+ }
+ }
+
+ glDrawBuffer(GL_BACK);
+ if(G.zbuf) glEnable(GL_DEPTH_TEST);
+}
+
+void drawfaceGour(Face *face)
+{
+ char *cp;
+
+ glBegin(GL_POLYGON);
+ cp= (char *)(face->v1+3);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(face->v1);
+
+ cp= (char *)(face->v2+3);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(face->v2);
+
+ cp= (char *)(face->v3+3);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(face->v3);
+
+ if(face->v4) {
+ cp= (char *)(face->v4+3);
+ glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(face->v4);
+ }
+ glEnd();
+
+}
+
+void drawfaceSolid(Face *face)
+{
+ char *cp;
+
+ cp= (char *)&face->col;
+ glColor3ub(cp[3], cp[2], cp[1]);
+
+ glBegin(GL_POLYGON);
+ glVertex3fv(face->v1);
+ glVertex3fv(face->v2);
+ glVertex3fv(face->v3);
+ if(face->v4) {
+ glVertex3fv(face->v4);
+ }
+ glEnd();
+
+}
+
+void drawfaceWire(Face *face)
+{
+ char *cp;
+
+ cp= (char *)&face->col;
+ glColor3ub(cp[3], cp[2], cp[1]);
+
+ glBegin(GL_LINE_LOOP);
+ glVertex3fv(face->v1);
+ glVertex3fv(face->v2);
+ glVertex3fv(face->v3);
+ if(face->v4) {
+ glVertex3fv(face->v4);
+ }
+ glEnd();
+
+}
+
+void drawsquare(float *cent, float size, short cox, short coy)
+{
+ float vec[3];
+
+ vec[0]= cent[0];
+ vec[1]= cent[1];
+ vec[2]= cent[2];
+
+ glBegin(GL_LINE_LOOP);
+ vec[cox]+= .5*size;
+ vec[coy]+= .5*size;
+ glVertex3fv(vec);
+ vec[coy]-= size;
+ glVertex3fv(vec);
+ vec[cox]-= size;
+ glVertex3fv(vec);
+ vec[coy]+= size;
+ glVertex3fv(vec);
+ glEnd();
+}
+
+void drawlimits()
+{
+ /* centreer rond cent */
+ short cox=0, coy=1;
+
+ if((RG.flag & 3)==2) coy= 2;
+ if((RG.flag & 3)==3) {
+ cox= 1;
+ coy= 2;
+ }
+
+ cpack(0);
+ drawsquare(RG.cent, sqrt(RG.patchmax), cox, coy);
+ drawsquare(RG.cent, sqrt(RG.patchmin), cox, coy);
+
+ drawsquare(RG.cent, sqrt(RG.elemmax), cox, coy);
+ drawsquare(RG.cent, sqrt(RG.elemmin), cox, coy);
+
+ cpack(0xFFFFFF);
+ drawsquare(RG.cent, sqrt(RG.patchmax), cox, coy);
+ drawsquare(RG.cent, sqrt(RG.patchmin), cox, coy);
+ cpack(0xFFFF00);
+ drawsquare(RG.cent, sqrt(RG.elemmax), cox, coy);
+ drawsquare(RG.cent, sqrt(RG.elemmin), cox, coy);
+
+}
+
+void setcolNode(RNode *rn, unsigned int *col)
+{
+
+ if(rn->down1) {
+ setcolNode(rn->down1, col);
+ setcolNode(rn->down2, col);
+ }
+ rn->col= *col;
+
+ *((unsigned int *)rn->v1+3)= *col;
+ *((unsigned int *)rn->v2+3)= *col;
+ *((unsigned int *)rn->v3+3)= *col;
+ if(rn->v4) *((unsigned int *)rn->v4+3)= *col;
+}
+
+void pseudoAmb()
+{
+ RPatch *rp;
+ float fac;
+ char col[4];
+
+ /* zet pseudo ambient kleuren in de nodes */
+
+ rp= RG.patchbase.first;
+ while(rp) {
+
+ if(rp->emit[0]!=0.0 || rp->emit[1]!=0.0 || rp->emit[2]!=0.0) {
+ col[1]= col[2]= col[3]= 255;
+ }
+ else {
+ fac= rp->norm[0]+ rp->norm[1]+ rp->norm[2];
+ fac= 225.0*(3+fac)/6.0;
+
+ col[3]= fac*rp->ref[0];
+ col[2]= fac*rp->ref[1];
+ col[1]= fac*rp->ref[2];
+ }
+
+ setcolNode(rp->first, (unsigned int *)col);
+
+ rp= rp->next;
+ }
+}
+
+void RAD_drawall(int depth_is_on)
+{
+ /* maakt afbeelding van elements of van faces */
+ Face *face = NULL;
+ RNode **el;
+ RPatch *rp;
+ int a;
+
+ if(!depth_is_on) {
+ glEnable(GL_DEPTH_TEST);
+ glClearDepth(1.0); glClear(GL_DEPTH_BUFFER_BIT);
+ }
+
+ if(RG.totface) {
+ if(RG.drawtype==DTGOUR) {
+ glShadeModel(GL_SMOOTH);
+ for(a=0; a<RG.totface; a++) {
+ RAD_NEXTFACE(a);
+
+ drawfaceGour(face);
+ }
+ }
+ else if(RG.drawtype==DTSOLID) {
+ for(a=0; a<RG.totface; a++) {
+ RAD_NEXTFACE(a);
+
+ drawfaceSolid(face);
+ }
+ }
+ else {
+ if(!(get_qual()&LR_SHIFTKEY)) {
+
+ for(a=0; a<RG.totface; a++) {
+ RAD_NEXTFACE(a);
+
+ drawfaceWire(face);
+ }
+ }
+ else {
+ cpack(0);
+ rp= RG.patchbase.first;
+ while(rp) {
+ drawsingnodeWire(rp->first);
+ rp= rp->next;
+ }
+ }
+ }
+ }
+ else {
+ el= RG.elem;
+ if(RG.drawtype==DTGOUR) {
+ glShadeModel(GL_SMOOTH);
+ for(a=RG.totelem; a>0; a--, el++) {
+ drawnodeGour(*el);
+ }
+ }
+ else if(RG.drawtype==DTSOLID) {
+ for(a=RG.totelem; a>0; a--, el++) {
+ drawnodeSolid(*el);
+ }
+ }
+ else {
+ cpack(0);
+ for(a=RG.totelem; a>0; a--, el++) {
+ drawnodeWire(*el);
+ }
+ }
+ }
+ glShadeModel(GL_FLAT);
+
+ if(RG.totpatch) {
+ if(RG.flag & 3) {
+ if(depth_is_on) glDisable(GL_DEPTH_TEST);
+ drawlimits();
+ if(depth_is_on) glEnable(GL_DEPTH_TEST);
+ }
+ }
+ if(!depth_is_on) {
+ glDisable(GL_DEPTH_TEST);
+ }
+}
+
+void rad_forcedraw()
+{
+ ScrArea *sa, *oldsa;
+
+ oldsa= curarea;
+
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if (sa->spacetype==SPACE_VIEW3D) {
+ /* hier mywinget() gebruiken: anders wordt in header getekend */
+ if(sa->win != mywinget()) areawinset(sa->win);
+ scrarea_do_windraw(sa);
+ }
+ sa= sa->next;
+ }
+ screen_swapbuffers();
+
+ if(oldsa && oldsa!=curarea) areawinset(oldsa->win);
+}
+
diff --git a/source/blender/radiosity/intern/source/radfactors.c b/source/blender/radiosity/intern/source/radfactors.c
new file mode 100644
index 00000000000..2f6ac2043c2
--- /dev/null
+++ b/source/blender/radiosity/intern/source/radfactors.c
@@ -0,0 +1,956 @@
+/* ***************************************
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+
+
+
+ formfactors.c nov/dec 1992
+
+ $Id$
+
+ *************************************** */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "BIF_screen.h"
+
+#include "radio.h"
+#include "render.h" /* for `RE_zbufferall_radio and RE_zbufferall_radio */
+#include "blendertimer.h" /* timer functions */
+
+/* locals */
+void rad_setmatrices(RadView *vw);
+void clearsubflagelem(RNode *rn);
+void setsubflagelem(RNode *rn);
+
+RadView hemitop, hemiside;
+
+float calcStokefactor(RPatch *shoot, RPatch *rp, RNode *rn, float *area)
+{
+ float tvec[3], fac;
+ float vec[4][3]; /* vectoren van shootcent naar vertices rp */
+ float cross[4][3]; /* uitprodukten hiervan */
+ float rad[4]; /* hoeken tussen vecs */
+
+ /* test op richting */
+ VecSubf(tvec, shoot->cent, rp->cent);
+ if( tvec[0]*shoot->norm[0]+ tvec[1]*shoot->norm[1]+ tvec[2]*shoot->norm[2]>0.0)
+ return 0.0;
+
+ if(rp->type==4) {
+
+ /* hoekvectors */
+ VecSubf(vec[0], shoot->cent, rn->v1);
+ VecSubf(vec[1], shoot->cent, rn->v2);
+ VecSubf(vec[2], shoot->cent, rn->v3);
+ VecSubf(vec[3], shoot->cent, rn->v4);
+
+ Normalise(vec[0]);
+ Normalise(vec[1]);
+ Normalise(vec[2]);
+ Normalise(vec[3]);
+
+ /* uitprod */
+ Crossf(cross[0], vec[0], vec[1]);
+ Crossf(cross[1], vec[1], vec[2]);
+ Crossf(cross[2], vec[2], vec[3]);
+ Crossf(cross[3], vec[3], vec[0]);
+ Normalise(cross[0]);
+ Normalise(cross[1]);
+ Normalise(cross[2]);
+ Normalise(cross[3]);
+
+ /* hoeken */
+ rad[0]= vec[0][0]*vec[1][0]+ vec[0][1]*vec[1][1]+ vec[0][2]*vec[1][2];
+ rad[1]= vec[1][0]*vec[2][0]+ vec[1][1]*vec[2][1]+ vec[1][2]*vec[2][2];
+ rad[2]= vec[2][0]*vec[3][0]+ vec[2][1]*vec[3][1]+ vec[2][2]*vec[3][2];
+ rad[3]= vec[3][0]*vec[0][0]+ vec[3][1]*vec[0][1]+ vec[3][2]*vec[0][2];
+
+ rad[0]= acos(rad[0]);
+ rad[1]= acos(rad[1]);
+ rad[2]= acos(rad[2]);
+ rad[3]= acos(rad[3]);
+
+ /* Stoke formule */
+ VecMulf(cross[0], rad[0]);
+ VecMulf(cross[1], rad[1]);
+ VecMulf(cross[2], rad[2]);
+ VecMulf(cross[3], rad[3]);
+
+ VECCOPY(tvec, shoot->norm);
+ fac= tvec[0]*cross[0][0]+ tvec[1]*cross[0][1]+ tvec[2]*cross[0][2];
+ fac+= tvec[0]*cross[1][0]+ tvec[1]*cross[1][1]+ tvec[2]*cross[1][2];
+ fac+= tvec[0]*cross[2][0]+ tvec[1]*cross[2][1]+ tvec[2]*cross[2][2];
+ fac+= tvec[0]*cross[3][0]+ tvec[1]*cross[3][1]+ tvec[2]*cross[3][2];
+ }
+ else {
+ /* hoekvectors */
+ VecSubf(vec[0], shoot->cent, rn->v1);
+ VecSubf(vec[1], shoot->cent, rn->v2);
+ VecSubf(vec[2], shoot->cent, rn->v3);
+
+ Normalise(vec[0]);
+ Normalise(vec[1]);
+ Normalise(vec[2]);
+
+ /* uitprod */
+ Crossf(cross[0], vec[0], vec[1]);
+ Crossf(cross[1], vec[1], vec[2]);
+ Crossf(cross[2], vec[2], vec[0]);
+ Normalise(cross[0]);
+ Normalise(cross[1]);
+ Normalise(cross[2]);
+
+ /* hoeken */
+ rad[0]= vec[0][0]*vec[1][0]+ vec[0][1]*vec[1][1]+ vec[0][2]*vec[1][2];
+ rad[1]= vec[1][0]*vec[2][0]+ vec[1][1]*vec[2][1]+ vec[1][2]*vec[2][2];
+ rad[2]= vec[2][0]*vec[0][0]+ vec[2][1]*vec[0][1]+ vec[2][2]*vec[0][2];
+
+ rad[0]= acos(rad[0]);
+ rad[1]= acos(rad[1]);
+ rad[2]= acos(rad[2]);
+
+ /* Stoke formule */
+ VecMulf(cross[0], rad[0]);
+ VecMulf(cross[1], rad[1]);
+ VecMulf(cross[2], rad[2]);
+
+ VECCOPY(tvec, shoot->norm);
+ fac= tvec[0]*cross[0][0]+ tvec[1]*cross[0][1]+ tvec[2]*cross[0][2];
+ fac+= tvec[0]*cross[1][0]+ tvec[1]*cross[1][1]+ tvec[2]*cross[1][2];
+ fac+= tvec[0]*cross[2][0]+ tvec[1]*cross[2][1]+ tvec[2]*cross[2][2];
+ }
+
+ *area= -fac/(2.0*PI);
+ return (*area * (shoot->area/rn->area));
+}
+
+
+void calcTopfactors()
+{
+ float xsq , ysq, xysq;
+ float n;
+ float *fp;
+ int a, b, hres;
+
+ fp = RG.topfactors;
+ hres= RG.hemires/2;
+ n= hres;
+
+ for (a=0; a<hres; a++) {
+
+ ysq= (n- ((float)a+0.5))/n;
+ ysq*= ysq;
+
+ for ( b=0 ; b<hres ; b++ ) {
+
+ xsq= ( n-((float)b+ 0.5) )/n;
+ xsq*= xsq;
+ xysq= xsq+ ysq+ 1.0 ;
+ xysq*= xysq;
+
+ *fp++ = 1.0/(xysq* PI* n*n);
+ }
+ }
+
+}
+
+void calcSidefactors()
+{
+ float xsq , ysq, xysq;
+ float n, y;
+ float *fp;
+ int a, b, hres;
+
+ fp = RG.sidefactors;
+ hres= RG.hemires/2;
+ n= hres;
+
+ for (a=0; a<hres; a++) {
+
+ y= (n- ((float)a+0.5))/n;
+ ysq= y*y;
+
+ for ( b=0 ; b<hres ; b++ ) {
+
+ xsq= ( n-((float)b+ 0.5) )/n;
+ xsq*= xsq;
+ xysq= xsq+ ysq+ 1.0 ;
+ xysq*= xysq;
+
+ *fp++ = y/(xysq* PI* n*n);
+ }
+ }
+
+}
+
+
+void initradiosity()
+{
+ /* alloceert en maakt LUTs voor top/side factors */
+ /* alloceert en maakt index array */
+ int a, hres2;
+
+ if(RG.topfactors) MEM_freeN(RG.topfactors);
+ if(RG.sidefactors) MEM_freeN(RG.sidefactors);
+ if(RG.index) MEM_freeN(RG.index);
+
+ RG.topfactors= MEM_callocN(RG.hemires*RG.hemires, "initradiosity");
+ calcTopfactors();
+ RG.sidefactors= MEM_callocN(RG.hemires*RG.hemires, "initradiosity1");
+ calcSidefactors();
+
+ RG.index= MEM_callocN(4*RG.hemires, "initradiosity3");
+ hres2= RG.hemires/2;
+ for(a=0; a<RG.hemires; a++) {
+ RG.index[a]= a<hres2 ? a: (hres2-1-( a % hres2 ));
+ }
+
+}
+
+void rad_make_hocos(RadView *vw)
+{
+ /* float hoco[4]; */
+ /* int a; */
+
+ /* for(a=0; a< R.totvert;a++) { */
+ /* projectvert(vec, ver->ho); */
+ /* ver->clip = testclip(ver->ho); */
+/* */
+ /* } */
+}
+
+void rad_setmatrices(RadView *vw) /* voor hemi's */
+{
+ float up1[3], len, twist;
+
+ i_lookat(vw->cam[0], vw->cam[1], vw->cam[2], vw->tar[0], vw->tar[1], vw->tar[2], 0, vw->viewmat);
+ up1[0] = vw->viewmat[0][0]*vw->up[0] + vw->viewmat[1][0]*vw->up[1] + vw->viewmat[2][0]*vw->up[2];
+ up1[1] = vw->viewmat[0][1]*vw->up[0] + vw->viewmat[1][1]*vw->up[1] + vw->viewmat[2][1]*vw->up[2];
+ up1[2] = vw->viewmat[0][2]*vw->up[0] + vw->viewmat[1][2]*vw->up[1] + vw->viewmat[2][2]*vw->up[2];
+
+ len= up1[0]*up1[0]+up1[1]*up1[1];
+ if(len>0.0) {
+ twist= -atan2(up1[0], up1[1]);
+ }
+ else twist= 0.0;
+
+ i_lookat(vw->cam[0], vw->cam[1], vw->cam[2], vw->tar[0], vw->tar[1], vw->tar[2], (180.0*twist/M_PI), vw->viewmat);
+
+ /* window matrix was set in inithemiwindows */
+
+}
+
+
+void hemizbuf(RadView *vw)
+{
+ float *factors;
+ unsigned int *rz;
+ int a, b, inda, hres;
+
+ rad_setmatrices(vw);
+ RE_zbufferall_radio(vw, RG.elem, RG.totelem);
+
+ /* factors tellen */
+ if(vw->recty==vw->rectx) factors= RG.topfactors;
+ else factors= RG.sidefactors;
+ hres= RG.hemires/2;
+
+ rz= vw->rect;
+ for(a=0; a<vw->recty; a++) {
+ inda= hres*RG.index[a];
+ for(b=0; b<vw->rectx; b++, rz++) {
+ if(*rz<RG.totelem) {
+ RG.formfactors[*rz]+= factors[inda+RG.index[b]];
+ }
+ }
+ }
+}
+
+int makeformfactors(RPatch *shoot)
+{
+ RNode **re;
+ float len, vec[3], up[3], side[3], tar[5][3], *fp;
+ int a, overfl;
+
+ if(RG.totelem==0) return 0;
+
+ memset(RG.formfactors, 0, 4*RG.totelem);
+
+ /* set up hemiview */
+ /* first: random upvector */
+ do {
+ vec[0]= (float)BLI_drand();
+ vec[1]= (float)BLI_drand();
+ vec[2]= (float)BLI_drand();
+ Crossf(up, shoot->norm, vec);
+ len= Normalise(up);
+ } while(len==0.0 || len>1.0);
+
+ VECCOPY(hemitop.up, up);
+ VECCOPY(hemiside.up, shoot->norm);
+
+ Crossf(side, shoot->norm, up);
+
+ /* five targets */
+ VecAddf(tar[0], shoot->cent, shoot->norm);
+ VecAddf(tar[1], shoot->cent, up);
+ VecSubf(tar[2], shoot->cent, up);
+ VecAddf(tar[3], shoot->cent, side);
+ VecSubf(tar[4], shoot->cent, side);
+
+ /* camera */
+ VECCOPY(hemiside.cam, shoot->cent);
+ VECCOPY(hemitop.cam, shoot->cent);
+
+ /* do it! */
+ VECCOPY(hemitop.tar, tar[0]);
+ hemizbuf(&hemitop);
+
+ for(a=1; a<5; a++) {
+ VECCOPY(hemiside.tar, tar[a]);
+ hemizbuf(&hemiside);
+ }
+
+ /* convert factors to real radiosity */
+ re= RG.elem;
+ fp= RG.formfactors;
+
+ overfl= 0;
+ for(a= RG.totelem; a>0; a--, re++, fp++) {
+
+ if(*fp!=0.0) {
+
+ *fp *= shoot->area/(*re)->area;
+
+ if(*fp>1.0) {
+ overfl= 1;
+ *fp= 1.0001;
+ }
+ }
+ }
+
+ if(overfl) {
+ /*
+ drawOverflowElem();
+ while(get_mbut()&L_MOUSE==0) {
+ if(get_mbut()&M_MOUSE) {
+ viewmove();
+ drawpatch_ext(shoot,0xFF77FF);
+ drawOverflowElem();
+ }
+ }
+ */
+ if(shoot->first->down1) {
+ splitpatch(shoot);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+void applyformfactors(RPatch *shoot)
+{
+ RPatch *rp;
+ RNode **el, *rn;
+ float *fp, *ref, unr, ung, unb, r, g, b, w;
+ int a;
+
+ unr= shoot->unshot[0];
+ ung= shoot->unshot[1];
+ unb= shoot->unshot[2];
+
+ fp= RG.formfactors;
+ el= RG.elem;
+ for(a=0; a<RG.totelem; a++, el++, fp++) {
+ rn= *el;
+ if(*fp!= 0.0) {
+ rp= rn->par;
+ ref= rp->ref;
+
+ r= (*fp)*unr*ref[0];
+ g= (*fp)*ung*ref[1];
+ b= (*fp)*unb*ref[2];
+
+ w= rn->area/rp->area;
+ rn->totrad[0]+= r;
+ rn->totrad[1]+= g;
+ rn->totrad[2]+= b;
+
+ rp->unshot[0]+= w*r;
+ rp->unshot[1]+= w*g;
+ rp->unshot[2]+= w*b;
+ }
+ }
+
+ shoot->unshot[0]= shoot->unshot[1]= shoot->unshot[2]= 0.0;
+}
+
+RPatch *findshootpatch()
+{
+ RPatch *rp, *shoot;
+ float energy, maxenergy;
+
+ shoot= 0;
+ maxenergy= 0.0;
+ rp= RG.patchbase.first;
+ while(rp) {
+ energy= rp->unshot[0]*rp->area;
+ energy+= rp->unshot[1]*rp->area;
+ energy+= rp->unshot[2]*rp->area;
+
+ if(energy>maxenergy) {
+ shoot= rp;
+ maxenergy= energy;
+ }
+ rp= rp->next;
+ }
+
+ if(shoot) {
+ maxenergy/= RG.totenergy;
+ if(maxenergy<RG.convergence) return 0;
+ }
+
+ return shoot;
+}
+
+void setnodeflags(RNode *rn, int flag, int set)
+{
+
+ if(rn->down1) {
+ setnodeflags(rn->down1, flag, set);
+ setnodeflags(rn->down2, flag, set);
+ }
+ else {
+ if(set) rn->f |= flag;
+ else rn->f &= ~flag;
+ }
+}
+
+void backface_test(RPatch *shoot)
+{
+ RPatch *rp;
+ float tvec[3];
+
+ rp= RG.patchbase.first;
+ while(rp) {
+ if(rp!=shoot) {
+
+ VecSubf(tvec, shoot->cent, rp->cent);
+ if( tvec[0]*shoot->norm[0]+ tvec[1]*shoot->norm[1]+ tvec[2]*shoot->norm[2]>0.0) {
+ setnodeflags(rp->first, RAD_BACKFACE, 1);
+ }
+ }
+ rp= rp->next;
+ }
+}
+
+void clear_backface_test()
+{
+ RNode **re;
+ int a;
+
+ re= RG.elem;
+ for(a= RG.totelem-1; a>=0; a--, re++) {
+ (*re)->f &= ~RAD_BACKFACE;
+ }
+
+}
+
+void rad_init_energy()
+{
+ /* call before shooting */
+ /* keep patches and elements, clear all data */
+ RNode **el, *rn;
+ RPatch *rp;
+ int a;
+
+ el= RG.elem;
+ for(a=RG.totelem; a>0; a--, el++) {
+ rn= *el;
+ VECCOPY(rn->totrad, rn->par->emit);
+ }
+
+ RG.totenergy= 0.0;
+ rp= RG.patchbase.first;
+ while(rp) {
+ VECCOPY(rp->unshot, rp->emit);
+
+ RG.totenergy+= rp->unshot[0]*rp->area;
+ RG.totenergy+= rp->unshot[1]*rp->area;
+ RG.totenergy+= rp->unshot[2]*rp->area;
+
+ rp->f= 0;
+
+ rp= rp->next;
+ }
+}
+
+void progressiverad()
+{
+ RPatch *shoot;
+ int it= 0;
+
+ rad_printstatus();
+ rad_init_energy();
+
+ shoot=findshootpatch();
+
+ while( shoot ) {
+
+ setnodeflags(shoot->first, RAD_SHOOT, 1);
+
+ backface_test(shoot);
+
+ drawpatch_ext(shoot, 0x88FF00);
+
+ if( makeformfactors(shoot) ) {
+
+ applyformfactors(shoot);
+
+ it++;
+ set_timecursor(it);
+ if( (it & 3)==1 ) {
+ make_node_display();
+ rad_forcedraw();
+ }
+ setnodeflags(shoot->first, RAD_SHOOT, 0);
+ }
+
+ clear_backface_test();
+
+ if(MISC_test_break()) break;
+ if(RG.maxiter && RG.maxiter<=it) break;
+
+ shoot=findshootpatch();
+
+ }
+
+}
+
+
+/* ************* subdivideshoot *********** */
+
+void minmaxradelem(RNode *rn, float *min, float *max)
+{
+ int c;
+
+ if(rn->down1) {
+ minmaxradelem(rn->down1, min, max);
+ minmaxradelem(rn->down2, min, max);
+ }
+ else {
+ for(c=0; c<3; c++) {
+ min[c]= MIN2(min[c], rn->totrad[c]);
+ max[c]= MAX2(max[c], rn->totrad[c]);
+ }
+ }
+}
+
+void minmaxradelemfilt(RNode *rn, float *min, float *max, float *errmin, float *errmax)
+{
+ float col[3], area;
+ int c;
+
+ if(rn->down1) {
+ minmaxradelemfilt(rn->down1, min, max, errmin, errmax);
+ minmaxradelemfilt(rn->down2, min, max, errmin, errmax);
+ }
+ else {
+ VECCOPY(col, rn->totrad);
+
+ for(c=0; c<3; c++) {
+ min[c]= MIN2(min[c], col[c]);
+ max[c]= MAX2(max[c], col[c]);
+ }
+
+ VecMulf(col, 2.0);
+ area= 2.0;
+ if(rn->ed1) {
+ VecAddf(col, rn->ed1->totrad, col);
+ area+= 1.0;
+ }
+ if(rn->ed2) {
+ VecAddf(col, rn->ed2->totrad, col);
+ area+= 1.0;
+ }
+ if(rn->ed3) {
+ VecAddf(col, rn->ed3->totrad, col);
+ area+= 1.0;
+ }
+ if(rn->ed4) {
+ VecAddf(col, rn->ed4->totrad, col);
+ area+= 1.0;
+ }
+ VecMulf(col, 1.0/area);
+
+ for(c=0; c<3; c++) {
+ errmin[c]= MIN2(errmin[c], col[c]);
+ errmax[c]= MAX2(errmax[c], col[c]);
+ }
+ }
+}
+
+void setsubflagelem(RNode *rn)
+{
+
+ if(rn->down1) {
+ setsubflagelem(rn->down1);
+ setsubflagelem(rn->down2);
+ }
+ else {
+ rn->f |= RAD_SUBDIV;
+ }
+}
+
+void clearsubflagelem(RNode *rn)
+{
+
+ if(rn->down1) {
+ setsubflagelem(rn->down1);
+ setsubflagelem(rn->down2);
+ }
+ else {
+ rn->f &= ~RAD_SUBDIV;
+ }
+}
+
+void subdivideshootElements(int it)
+{
+ RPatch *rp, *shoot;
+ RNode **el, *rn;
+ float *fp, err, stoke, area, min[3], max[3], errmin[3], errmax[3];
+ int a, b, c, d, e, f, contin;
+ int maxlamp;
+
+ if(RG.maxsublamp==0) maxlamp= RG.totlamp;
+ else maxlamp= RG.maxsublamp;
+
+ while(it) {
+ rad_printstatus();
+ rad_init_energy();
+ it--;
+
+ for(a=0; a<maxlamp; a++) {
+ shoot= findshootpatch();
+ if(shoot==0) break;
+
+ set_timecursor(a);
+ drawpatch_ext(shoot, 0x88FF00);
+
+ setnodeflags(shoot->first, RAD_SHOOT, 1);
+ if( makeformfactors(shoot) ) {
+
+ fp= RG.formfactors;
+ el= RG.elem;
+ for(b=RG.totelem; b>0; b--, el++) {
+ rn= *el;
+
+ if( (rn->f & RAD_SUBDIV)==0 && *fp!=0.0) {
+ if(rn->par->emit[0]+rn->par->emit[1]+rn->par->emit[2]==0.0) {
+
+ stoke= calcStokefactor(shoot, rn->par, rn, &area);
+ if(stoke!= 0.0) {
+
+ err= *fp/stoke;
+
+ /* area error */
+ area*=(0.5*RG.hemires*RG.hemires);
+
+ if(area>35.0) {
+ if(err<0.95 || err>1.05) {
+ if(err>0.05) {
+ rn->f |= RAD_SUBDIV;
+ rn->par->f |= RAD_SUBDIV;
+ }
+ }
+ }
+ }
+
+ }
+ }
+
+ fp++;
+
+ }
+
+ applyformfactors(shoot);
+
+ if( (a & 3)==1 ) {
+ make_node_display();
+ rad_forcedraw();
+ }
+
+ setnodeflags(shoot->first, RAD_SHOOT, 0);
+ }
+ else a--;
+
+ if(MISC_test_break()) break;
+ }
+
+ /* test op extreem weinig kleurverloop binnen patch met subdivflag */
+
+ rp= RG.patchbase.first;
+
+ while(rp) {
+ if(rp->f & RAD_SUBDIV) { /* rp heeft elems die moet gesubd */
+ /* minstens 4 levels diep */
+ rn= rp->first->down1;
+ if(rn) {
+ rn= rn->down1;
+ if(rn) {
+ rn= rn->down1;
+ if(rn) rn= rn->down1;
+ }
+ }
+ if(rn) {
+ min[0]= min[1]= min[2]= 1.0e10;
+ max[0]= max[1]= max[2]= -1.0e10;
+ /* errmin en max zijn de gefilterde kleuren */
+ errmin[0]= errmin[1]= errmin[2]= 1.0e10;
+ errmax[0]= errmax[1]= errmax[2]= -1.0e10;
+ minmaxradelemfilt(rp->first, min, max, errmin, errmax);
+
+ /* verschil tussen kleuren klein: toch maar niet subd */
+ /* test ook voor de gefilterde: maar kritischer */
+
+ contin= 0;
+ a= abs( calculatecolor(min[0])-calculatecolor(max[0]));
+ b= abs( calculatecolor(errmin[0])-calculatecolor(errmax[0]));
+ if(a<15 || b<7) {
+ c= abs( calculatecolor(min[1])-calculatecolor(max[1]));
+ d= abs( calculatecolor(errmin[1])-calculatecolor(errmax[1]));
+ if(c<15 || d<7) {
+ e= abs( calculatecolor(min[2])-calculatecolor(max[2]));
+ f= abs( calculatecolor(errmin[2])-calculatecolor(errmax[2]));
+ if(e<15 || f<7) {
+ contin= 1;
+ clearsubflagelem(rp->first);
+ /* printf("%d %d %d %d %d %d\n", a, b, c, d, e, f); */
+ }
+ }
+ }
+ if(contin) {
+ drawpatch_ext(rp, 0xFFFF);
+ }
+ }
+ }
+ rp->f &= ~RAD_SUBDIV;
+ rp= rp->next;
+ }
+
+ contin= 0;
+
+ el= RG.elem;
+ for(b=RG.totelem; b>0; b--, el++) {
+ rn= *el;
+ if(rn->f & RAD_SUBDIV) {
+ rn->f-= RAD_SUBDIV;
+ subdivideNode(rn, 0);
+ if(rn->down1) {
+ subdivideNode(rn->down1, 0);
+ subdivideNode(rn->down2, 0);
+ contin= 1;
+ }
+ }
+ }
+ makeGlobalElemArray();
+
+ if(contin==0 || MISC_test_break()) break;
+ }
+
+ make_node_display();
+}
+
+void subdivideshootPatches(int it)
+{
+ RPatch *rp, *shoot, *next;
+ float *fp, err, stoke, area;
+ int a, contin;
+ int maxlamp;
+
+ if(RG.maxsublamp==0) maxlamp= RG.totlamp;
+ else maxlamp= RG.maxsublamp;
+
+ while(it) {
+ rad_printstatus();
+ rad_init_energy();
+ it--;
+
+ for(a=0; a<maxlamp; a++) {
+ shoot= findshootpatch();
+ if(shoot==0) break;
+
+ set_timecursor(a);
+ drawpatch_ext(shoot, 0x88FF00);
+
+ setnodeflags(shoot->first, RAD_SHOOT, 1);
+
+ if( makeformfactors(shoot) ) {
+
+ fp= RG.formfactors;
+ rp= RG.patchbase.first;
+ while(rp) {
+ if(*fp!=0.0 && rp!=shoot) {
+
+ stoke= calcStokefactor(shoot, rp, rp->first, &area);
+ if(stoke!= 0.0) {
+ if(area>.1) { /* ontvangt patch meer dan (ong)10% van energie? */
+ rp->f= RAD_SUBDIV;
+ }
+ else {
+
+ err= *fp/stoke;
+
+ /* area error */
+ area*=(0.5*RG.hemires*RG.hemires);
+
+ if(area>45.0) {
+ if(err<0.95 || err>1.05) {
+ if(err>0.05) {
+
+ rp->f= RAD_SUBDIV;
+
+ /* if(get_qual()&LR_SHIFTKEY);
+ else {
+ drawpatch_ext(rp, 0xFF77FF);
+
+ printf("Pa hemi %f stoke %f err %f area %f\n", *fp, stoke, err, area);
+
+ while(get_mbut()&L_MOUSE==0);
+ while(get_mbut()&L_MOUSE);
+ }
+ */
+ }
+ }
+ }
+ }
+ }
+ }
+ fp++;
+
+ rp= rp->next;
+ }
+
+ applyformfactors(shoot);
+
+ if( (a & 3)==1 ) {
+ make_node_display();
+ rad_forcedraw();
+ }
+
+ setnodeflags(shoot->first, RAD_SHOOT, 0);
+
+ if(MISC_test_break()) break;
+ }
+ else a--;
+
+ }
+
+ contin= 0;
+
+ rp= RG.patchbase.first;
+ while(rp) {
+ next= rp->next;
+ if(rp->f & RAD_SUBDIV) {
+ if(rp->emit[0]+rp->emit[1]+rp->emit[2]==0.0) {
+ contin= 1;
+ subdivideNode(rp->first, 0);
+ if(rp->first->down1) {
+ subdivideNode(rp->first->down1, 0);
+ subdivideNode(rp->first->down2, 0);
+ }
+ }
+ }
+ rp= next;
+ }
+
+ converttopatches();
+ makeGlobalElemArray();
+
+ if(contin==0 || MISC_test_break()) break;
+ }
+ make_node_display();
+}
+
+void inithemiwindows()
+{
+ RadView *vw;
+
+ /* de hemiwindows */
+ vw= &(hemitop);
+ memset(vw, 0, sizeof(RadView));
+ vw->rectx= RG.hemires;
+ vw->recty= RG.hemires;
+ vw->rectz= MEM_mallocN(4*vw->rectx*vw->recty, "initwindows");
+ vw->rect= MEM_mallocN(4*vw->rectx*vw->recty, "initwindows");
+ vw->mynear= RG.maxsize/2000.0;
+ vw->myfar= 2.0*RG.maxsize;
+ vw->wx1= -vw->mynear;
+ vw->wx2= vw->mynear;
+ vw->wy1= -vw->mynear;
+ vw->wy2= vw->mynear;
+
+ i_window(vw->wx1, vw->wx2, vw->wy1, vw->wy2, vw->mynear, vw->myfar, vw->winmat);
+
+ hemiside= hemitop;
+
+ vw= &(hemiside);
+ vw->recty/= 2;
+ vw->wy1= vw->wy2;
+ vw->wy2= 0.0;
+
+ i_window(vw->wx1, vw->wx2, vw->wy1, vw->wy2, vw->mynear, vw->myfar, vw->winmat);
+
+}
+
+void closehemiwindows()
+{
+
+ if(hemiside.rect) MEM_freeN(hemiside.rect);
+ if(hemiside.rectz) MEM_freeN(hemiside.rectz);
+ hemiside.rectz= 0;
+ hemiside.rect= 0;
+ hemitop.rectz= 0;
+ hemitop.rect= 0;
+}
diff --git a/source/blender/radiosity/intern/source/radio.c b/source/blender/radiosity/intern/source/radio.c
new file mode 100644
index 00000000000..af3797d6c2b
--- /dev/null
+++ b/source/blender/radiosity/intern/source/radio.c
@@ -0,0 +1,379 @@
+/* ***************************************
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+
+
+
+ radio.c nov/dec 1992
+ may 1999
+
+ $Id$
+
+ - mainlus
+ - toetsafhandeling
+
+
+ - PREPROCES
+ - collect meshes
+ - spitconnected (alle vlakken met verschillende kleur en normaal)
+ - setedgepointers (nodes wijzen naar buren)
+
+ - EDITING
+ - min-max patch en min-max elementsize
+ - ahv bovenstaande evt patches subdividen
+ - lampsubdivide
+
+ - als er teveel lampen zijn voor de subdivide shooting:
+ - tijdelijk patches samenvoegen
+ - met de hand aangeven?
+
+ - SUBDIVIDE SHOOTING
+ - behalve laatste shooting bepaalt dit patch-subdivide
+ - als gesubdivide patches nog > 2*minsize : doorgaan
+ - op eind zoveel mogelijk elements maken
+ - ook onthouden of lamp (nog) subdivide veroorzaakt.
+
+ - REFINEMENT SHOOTING
+ - testen op overflows (shootpatch subdividen)
+ - testen op extreme kleur verlopen:
+ - als nog kan: shootpatch subdividen
+ - elements subdividen = overnieuw beginnen ?
+ - ittereren stoppen nadat ?
+
+ - DEFINITIVE SHOOTING
+ - user geeft aan hoeveel vlakken maximaal en itteratie lengte.
+ - nodes omzetten naar minder geheugen-intensief formaat
+ - element- nodes weer samenvoegen waarin niets gebeurt (faces)
+ - elements subdividen waarin veel gebeurt
+
+ *************************************** */
+
+#include <math.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+#include "PIL_time.h"
+
+#include "BLI_blenlib.h"
+
+#include "DNA_object_types.h"
+#include "DNA_radio_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "BIF_screen.h" /* curarea */
+#include "BIF_space.h" /* allqueue */
+
+#include "radio.h"
+#include "mydevice.h"
+
+/* locals? This one was already done in radio.h... */
+/* void rad_status_str(char *str); */
+
+RadGlobal RG= {0, 0};
+
+void freeAllRad()
+{
+ Base *base;
+ extern int Ntotvert, Ntotnode, Ntotpatch;
+
+ /* clear flag that disables drawing the meshes */
+ if(G.scene) {
+ base= (G.scene->base.first);
+ while(base) {
+ if(base->object->type==OB_MESH) {
+ base->flag &= ~OB_RADIO;
+ }
+ base= base->next;
+ }
+ }
+
+ free_fastAll(); /* verts, nodes, patches */
+ RG.patchbase.first= RG.patchbase.last= 0;
+ Ntotvert= Ntotnode= Ntotpatch= 0;
+
+ closehemiwindows(); /* not real windows anymore... */
+ if(RG.elem) MEM_freeN(RG.elem);
+ RG.elem= 0;
+ if(RG.verts) MEM_freeN(RG.verts);
+ RG.verts= 0;
+ if(RG.topfactors) MEM_freeN(RG.topfactors);
+ RG.topfactors= 0;
+ if(RG.sidefactors) MEM_freeN(RG.sidefactors);
+ RG.sidefactors= 0;
+ if(RG.formfactors) MEM_freeN(RG.formfactors);
+ RG.formfactors= 0;
+ if(RG.index) MEM_freeN(RG.index);
+ RG.index= 0;
+ if(RG.facebase) {
+ init_face_tab(); /* frees all tables */
+ MEM_freeN(RG.facebase);
+ RG.facebase= 0;
+ }
+ RG.totelem= RG.totpatch= RG.totvert= RG.totface= RG.totlamp= RG.totmat= 0;
+}
+
+int rad_phase()
+{
+ int flag= 0;
+
+ if(RG.totpatch) flag |= RAD_PHASE_PATCHES;
+ if(RG.totface) flag |= RAD_PHASE_FACES;
+
+ return flag;
+}
+
+void rad_status_str(char *str)
+{
+ extern int totfastmem;
+ int tot;
+ char *phase;
+
+ tot= (RG.totface*sizeof(Face))/1024;
+ tot+= totfastmem/1024;
+
+ if(RG.phase==RAD_SHOOTE) phase= "Phase: ELEMENT SUBD, ";
+ else if(RG.phase==RAD_SHOOTP) phase= "Phase: PATCH SUBD, ";
+ else if(RG.phase==RAD_SOLVE) phase= "Phase: SOLVE, ";
+ else if(RG.totpatch==0) phase= "Phase: COLLECT MESHES ";
+ else if(RG.totface) phase= "Phase: FINISHED, ";
+ else phase= "Phase: INIT, ";
+
+ if(RG.totpatch==0) strcpy(str, phase);
+ else sprintf(str, "%s TotPatch: %d TotElem: %d Emit: %d Faces %d Mem: %d k ", phase, RG.totpatch, RG.totelem, RG.totlamp, RG.totface, tot);
+
+ if(RG.phase==RAD_SOLVE) strcat(str, "(press ESC to stop)");
+}
+
+void rad_printstatus()
+{
+ /* actions always are started from a buttonswindow */
+ scrarea_do_windraw(curarea);
+ screen_swapbuffers();
+}
+
+void rad_setlimits()
+{
+ Radio *rad= G.scene->radio;
+ float fac;
+
+ fac= 0.0005*rad->pama;
+ RG.patchmax= RG.maxsize*fac;
+ RG.patchmax*= RG.patchmax;
+ fac= 0.0005*rad->pami;
+ RG.patchmin= RG.maxsize*fac;
+ RG.patchmin*= RG.patchmin;
+
+ fac= 0.0005*rad->elma;
+ RG.elemmax= RG.maxsize*fac;
+ RG.elemmax*= RG.elemmax;
+ fac= 0.0005*rad->elmi;
+ RG.elemmin= RG.maxsize*fac;
+ RG.elemmin*= RG.elemmin;
+}
+
+void set_radglobal()
+{
+ /* always call before any action is performed */
+ Radio *rad= G.scene->radio;
+
+ if(RG.radio==0) {
+ /* firsttime and to be sure */
+ memset(&RG, 0, sizeof(RadGlobal));
+ }
+
+ if(rad==0) return;
+
+ if(rad != RG.radio) {
+ if(RG.radio) freeAllRad();
+ memset(&RG, 0, sizeof(RadGlobal));
+ RG.radio= rad;
+ }
+
+ RG.hemires= rad->hemires & 0xFFF0;
+ RG.drawtype= rad->drawtype;
+ RG.flag= rad->flag;
+ RG.subshootp= rad->subshootp;
+ RG.subshoote= rad->subshoote;
+ RG.nodelim= rad->nodelim;
+ RG.maxsublamp= rad->maxsublamp;
+ RG.maxnode= 2*rad->maxnode; /* in button:max elem, subdividing! */
+ RG.convergence= rad->convergence/1000.0;
+ RG.radfac= rad->radfac;
+ RG.gamma= rad->gamma;
+ RG.maxiter= rad->maxiter;
+
+ rad_setlimits();
+}
+
+/* called from buttons.c */
+void add_radio()
+{
+ Radio *rad;
+
+ if(G.scene->radio) MEM_freeN(G.scene->radio);
+ rad= G.scene->radio= MEM_callocN(sizeof(Radio), "radio");
+
+ rad->hemires= 300;
+ rad->convergence= 0.1;
+ rad->radfac= 30.0;
+ rad->gamma= 2.0;
+ rad->drawtype= DTSOLID;
+ rad->subshootp= 1;
+ rad->subshoote= 2;
+ rad->maxsublamp= 0;
+
+ rad->pama= 500;
+ rad->pami= 200;
+ rad->elma= 100;
+ rad->elmi= 20;
+ rad->nodelim= 0;
+ rad->maxnode= 10000;
+ rad->flag= 2;
+ set_radglobal();
+}
+
+void delete_radio()
+{
+ freeAllRad();
+ if(G.scene->radio) MEM_freeN(G.scene->radio);
+ G.scene->radio= 0;
+
+ RG.radio= 0;
+}
+
+int rad_go(void) /* return 0 when user escapes */
+{
+ double stime= PIL_check_seconds_timer();
+ int retval;
+ /* firsttime moet vervangen worden door radphase? */
+
+ if(RG.totface) return 0;
+
+ G.afbreek= 0;
+
+ set_radglobal();
+ initradiosity(); /* LUT's */
+ inithemiwindows(); /* views */
+
+ maxsizePatches();
+
+ setnodelimit(RG.patchmin);
+ RG.phase= RAD_SHOOTP;
+ subdivideshootPatches(RG.subshootp);
+
+ setnodelimit(RG.elemmin);
+ RG.phase= RAD_SHOOTE;
+ subdivideshootElements(RG.subshoote);
+
+ setnodelimit(RG.patchmin);
+ subdividelamps();
+
+ setnodelimit(RG.elemmin);
+
+ RG.phase= RAD_SOLVE;
+ subdiv_elements();
+
+ progressiverad();
+
+ removeEqualNodes(RG.nodelim);
+
+ make_face_tab(); /* nu geankerd */
+
+ closehemiwindows();
+ RG.phase= 0;
+
+ stime= PIL_check_seconds_timer()-stime;
+ printf("Radiosity solving time: %dms\n", (int) (stime*1000));
+
+ if(G.afbreek==1) retval= 1;
+ else retval= 0;
+
+ G.afbreek= 0;
+
+ return retval;
+}
+
+void rad_subdivshootpatch()
+{
+
+ if(RG.totface) return;
+
+ G.afbreek= 0;
+
+ set_radglobal();
+ initradiosity(); /* LUT's */
+ inithemiwindows(); /* views */
+
+ subdivideshootPatches(1);
+
+ removeEqualNodes(RG.nodelim);
+ closehemiwindows();
+
+ allqueue(REDRAWVIEW3D, 1);
+}
+
+void rad_subdivshootelem(void)
+{
+
+ if(RG.totface) return;
+
+ G.afbreek= 0;
+
+ set_radglobal();
+ initradiosity(); /* LUT's */
+ inithemiwindows(); /* views */
+
+ subdivideshootElements(1);
+
+ removeEqualNodes(RG.nodelim);
+ closehemiwindows();
+
+ allqueue(REDRAWVIEW3D, 1);
+}
+
+void rad_limit_subdivide()
+{
+
+ if(G.scene->radio==0) return;
+
+ set_radglobal();
+
+ if(RG.totpatch==0) {
+ /* printf("exit: no relevant data\n"); */
+ return;
+ }
+
+ maxsizePatches();
+
+ init_face_tab(); /* free faces */
+}
diff --git a/source/blender/radiosity/intern/source/radnode.c b/source/blender/radiosity/intern/source/radnode.c
new file mode 100644
index 00000000000..b75edc0c2cf
--- /dev/null
+++ b/source/blender/radiosity/intern/source/radnode.c
@@ -0,0 +1,1095 @@
+/* ***************************************
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+
+
+
+ node.c nov/dec 1992
+ may 1999
+
+ $Id$
+
+ *************************************** */
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "BIF_toolbox.h"
+
+#include "radio.h"
+
+/* locals */
+void *malloc_fast(int size);
+void *calloc_fast(int size);
+void free_fast(void *poin, int siz);
+void deleteTriNodes(RNode *node);
+/* lower because of local type define */
+/* void check_mallocgroup(MallocGroup *mg); */
+
+
+/* ********** fastmalloc ************** */
+
+#define MAL_GROUPSIZE 256
+#define MAL_AVAILABLE 1
+#define MAL_FULL 2
+
+
+
+
+ListBase MallocBase= {0, 0};
+int totfastmem= 0;
+
+typedef struct MallocGroup {
+ struct MallocGroup *next, *prev;
+ short size, flag;
+ short curfree, tot;
+ char flags[MAL_GROUPSIZE];
+ char *data;
+} MallocGroup;
+
+/* one more local */
+void check_mallocgroup(MallocGroup *mg);
+
+void check_mallocgroup(MallocGroup *mg)
+{
+ int a;
+ char *cp;
+
+ if(mg->tot==MAL_GROUPSIZE) {
+ mg->flag= MAL_FULL;
+ return;
+ }
+
+ cp= mg->flags;
+
+ if(mg->curfree<MAL_GROUPSIZE-1) {
+ if(cp[mg->curfree+1]==0) {
+ mg->curfree++;
+ return;
+ }
+ }
+ if(mg->curfree>0) {
+ if(cp[mg->curfree-1]==0) {
+ mg->curfree--;
+ return;
+ }
+ }
+
+ for(a=0; a<MAL_GROUPSIZE; a++) {
+ if(cp[a]==0) {
+ mg->curfree= a;
+ return;
+ }
+ }
+ printf("fastmalloc: shouldnt be here\n");
+}
+
+void *malloc_fast(int size)
+{
+ MallocGroup *mg;
+ void *retval;
+
+ mg= MallocBase.last;
+ while(mg) {
+ if(mg->size==size) {
+ if(mg->flag & MAL_AVAILABLE) {
+ mg->flags[mg->curfree]= 1;
+ mg->tot++;
+ retval= mg->data+mg->curfree*mg->size;
+ check_mallocgroup(mg);
+ return retval;
+ }
+ }
+ mg= mg->prev;
+ }
+
+ /* no free block found */
+ mg= MEM_callocN(sizeof(MallocGroup), "mallocgroup");
+ BLI_addtail(&MallocBase, mg);
+ mg->data= MEM_mallocN(MAL_GROUPSIZE*size, "mallocgroupdata");
+ mg->flag= MAL_AVAILABLE;
+ mg->flags[0]= 1;
+ mg->curfree= 1;
+ mg->size= size;
+ mg->tot= 1;
+
+ totfastmem+= sizeof(MallocGroup)+MAL_GROUPSIZE*size;
+
+ return mg->data;
+}
+
+void *calloc_fast(int size)
+{
+ void *poin;
+
+ poin= malloc_fast(size);
+ memset(poin, 0, size);
+
+ return poin;
+}
+
+void free_fast(void *poin, int size)
+{
+ MallocGroup *mg;
+ long val;
+
+ mg= MallocBase.last;
+ while(mg) {
+ if(mg->size==size) {
+ if( ((long)poin) >= ((long)mg->data) ) {
+ if( ((long)poin) < ((long)(mg->data+MAL_GROUPSIZE*size)) ) {
+ val= ((long)poin) - ((long)mg->data);
+ val/= size;
+ mg->curfree= val;
+ mg->flags[val]= 0;
+ mg->flag= MAL_AVAILABLE;
+
+ mg->tot--;
+ if(mg->tot==0) {
+ BLI_remlink(&MallocBase, mg);
+ MEM_freeN(mg->data);
+ MEM_freeN(mg);
+ totfastmem-= sizeof(MallocGroup)+MAL_GROUPSIZE*size;
+ }
+ return;
+ }
+ }
+ }
+ mg= mg->prev;
+ }
+ printf("fast free: pointer not in memlist %p size %d\n",
+ poin, size);
+}
+
+/* security: only one function in a time can use it */
+static char *fastmallocstr= 0;
+
+void free_fastAll()
+{
+ MallocGroup *mg;
+
+ mg= MallocBase.first;
+ while(mg) {
+ BLI_remlink(&MallocBase, mg);
+ MEM_freeN(mg->data);
+ MEM_freeN(mg);
+ mg= MallocBase.first;
+ }
+ totfastmem= 0;
+ fastmallocstr= 0;
+}
+
+void start_fastmalloc(char *str)
+{
+ if(fastmallocstr) {
+ error("Fastmalloc in use: %s", fastmallocstr);
+ return;
+ }
+ fastmallocstr= str;
+}
+
+/* **************************************** */
+
+float nodelimit;
+
+void setnodelimit(float limit)
+{
+ nodelimit= limit;
+
+}
+
+/* ************ GEHEUGENBEHEER *********** */
+
+int Ntotvert=0, Ntotnode=0, Ntotpatch=0;
+
+float *mallocVert()
+{
+ Ntotvert++;
+ return (float *)malloc_fast(16);
+}
+
+float *callocVert()
+{
+ Ntotvert++;
+ return (float *)calloc_fast(16);
+}
+
+void freeVert(float *vert)
+{
+ free_fast(vert, 16);
+ Ntotvert--;
+}
+
+RNode *mallocNode()
+{
+ Ntotnode++;
+ return (RNode *)malloc_fast(sizeof(RNode));
+}
+
+RNode *callocNode()
+{
+ Ntotnode++;
+ return (RNode *)calloc_fast(sizeof(RNode));
+}
+
+void freeNode(RNode *node)
+{
+ free_fast(node, sizeof(RNode));
+ Ntotnode--;
+}
+
+void freeNode_recurs(RNode *node)
+{
+
+ if(node->down1) {
+ freeNode_recurs(node->down1);
+ freeNode_recurs(node->down2);
+ }
+
+ node->down1= node->down2= 0;
+ freeNode(node);
+
+}
+
+RPatch *mallocPatch()
+{
+ Ntotpatch++;
+ return (RPatch *)malloc_fast(sizeof(RPatch));
+}
+
+RPatch *callocPatch()
+{
+ Ntotpatch++;
+ return (RPatch *)calloc_fast(sizeof(RPatch));
+}
+
+void freePatch(RPatch *patch)
+{
+ free_fast(patch, sizeof(RPatch));
+ Ntotpatch--;
+}
+
+/* ************ SUBDIVIDE *********** */
+
+
+void replaceAllNode(RNode *neighb, RNode *newn)
+{
+ /* verandert van alle buren de edgepointers die naar newn->up wijzen in new */
+ int ok= 0;
+
+
+ if(neighb==0) return;
+ if(newn->up==0) return;
+
+ if(neighb->ed1==newn->up) {
+ neighb->ed1= newn;
+ ok= 1;
+ }
+ else if(neighb->ed2==newn->up) {
+ neighb->ed2= newn;
+ ok= 1;
+ }
+ else if(neighb->ed3==newn->up) {
+ neighb->ed3= newn;
+ ok= 1;
+ }
+ else if(neighb->ed4==newn->up) {
+ neighb->ed4= newn;
+ ok= 1;
+ }
+
+ if(ok && neighb->down1) {
+ replaceAllNode(neighb->down1, newn);
+ replaceAllNode(neighb->down2, newn);
+ }
+}
+
+void replaceAllNodeInv(RNode *neighb, RNode *old)
+{
+ /* verandert van alle buren de edgepointers die naar old wijzen in old->up */
+ if(neighb==0) return;
+ if(old->up==0) return;
+
+ if(neighb->ed1==old) {
+ neighb->ed1= old->up;
+ }
+ else if(neighb->ed2==old) {
+ neighb->ed2= old->up;
+ }
+ else if(neighb->ed3==old) {
+ neighb->ed3= old->up;
+ }
+ else if(neighb->ed4==old) {
+ neighb->ed4= old->up;
+ }
+
+ if(neighb->down1) {
+ replaceAllNodeInv(neighb->down1, old);
+ replaceAllNodeInv(neighb->down2, old);
+ }
+}
+
+void replaceAllNodeUp(RNode *neighb, RNode *old)
+{
+ /* verandert van alle buren de edgepointers die naar old wijzen in old->up */
+ if(neighb==0) return;
+ if(old->up==0) return;
+ neighb= neighb->up;
+ if(neighb==0) return;
+
+ if(neighb->ed1==old) {
+ neighb->ed1= old->up;
+ }
+ else if(neighb->ed2==old) {
+ neighb->ed2= old->up;
+ }
+ else if(neighb->ed3==old) {
+ neighb->ed3= old->up;
+ }
+ else if(neighb->ed4==old) {
+ neighb->ed4= old->up;
+ }
+
+ if(neighb->up) {
+ replaceAllNodeUp(neighb, old);
+ }
+}
+
+
+void replaceTestNode(RNode *neighb, RNode **edpp, RNode *newn, int level, float *vert)
+{
+ /* IF neighb->ed wijst naar newn->up
+ * IF edgelevels gelijk
+ IF testvert zit in neighb->ed
+ pointers beide kanten op veranderen
+ ELSE
+ RETURN
+ ELSE
+ IF neighb edgelevel is dieper
+ verander neighb pointer
+
+ */
+ int ok= 0;
+
+ if(neighb==0) return;
+ if(newn->up==0) return;
+
+ if(neighb->ed1==newn->up) {
+ if(neighb->lev1==level) {
+ if(vert==neighb->v1 || vert==neighb->v2) {
+ *edpp= neighb;
+ neighb->ed1= newn;
+ }
+ else return;
+ }
+ else if(neighb->lev1>level) {
+ neighb->ed1= newn;
+ }
+ ok= 1;
+ }
+ else if(neighb->ed2==newn->up) {
+ if(neighb->lev2==level) {
+ if(vert==neighb->v2 || vert==neighb->v3) {
+ *edpp= neighb;
+ neighb->ed2= newn;
+ }
+ else return;
+ }
+ else if(neighb->lev2>level) {
+ neighb->ed2= newn;
+ }
+ ok= 1;
+ }
+ else if(neighb->ed3==newn->up) {
+ if(neighb->lev3==level) {
+ if(neighb->type==3) {
+ if(vert==neighb->v3 || vert==neighb->v1) {
+ *edpp= neighb;
+ neighb->ed3= newn;
+ }
+ else return;
+ }
+ else {
+ if(vert==neighb->v3 || vert==neighb->v4) {
+ *edpp= neighb;
+ neighb->ed3= newn;
+ }
+ else return;
+ }
+ }
+ else if(neighb->lev3>level) {
+ neighb->ed3= newn;
+ }
+ ok= 1;
+ }
+ else if(neighb->ed4==newn->up) {
+ if(neighb->lev4==level) {
+ if(vert==neighb->v4 || vert==neighb->v1) {
+ *edpp= neighb;
+ neighb->ed4= newn;
+ }
+ else return;
+ }
+ else if(neighb->lev4>level) {
+ neighb->ed4= newn;
+ }
+ ok= 1;
+ }
+
+ if(ok && neighb->down1) {
+ replaceTestNode(neighb->down1, edpp, newn, level, vert);
+ replaceTestNode(neighb->down2, edpp, newn, level, vert);
+ }
+
+}
+
+int setvertexpointersNode(RNode *neighb, RNode *node, int level, float **v1, float **v2)
+{
+ /* vergelijkt edgelevels , als gelijk zet het de vertexpointers */
+
+ if(neighb==0) return 0;
+
+ if(neighb->ed1==node) {
+ if(neighb->lev1==level) {
+ *v1= neighb->v1;
+ *v2= neighb->v2;
+ return 1;
+ }
+ }
+ else if(neighb->ed2==node) {
+ if(neighb->lev2==level) {
+ *v1= neighb->v2;
+ *v2= neighb->v3;
+ return 1;
+ }
+ }
+ else if(neighb->ed3==node) {
+ if(neighb->lev3==level) {
+ if(neighb->type==3) {
+ *v1= neighb->v3;
+ *v2= neighb->v1;
+ }
+ else {
+ *v1= neighb->v3;
+ *v2= neighb->v4;
+ }
+ return 1;
+ }
+ }
+ else if(neighb->ed4==node) {
+ if(neighb->lev4==level) {
+ *v1= neighb->v4;
+ *v2= neighb->v1;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+float edlen(float *v1, float *v2)
+{
+ return (v1[0]-v2[0])*(v1[0]-v2[0])+ (v1[1]-v2[1])*(v1[1]-v2[1])+ (v1[2]-v2[2])*(v1[2]-v2[2]);
+}
+
+
+void subdivideTriNode(RNode *node, RNode *edge)
+{
+ RNode *n1, *n2, *up;
+ float fu, fv, fl, *v1, *v2; /* , AreaT3Dfl(); ... from arithb... */
+ int uvl;
+
+ if(node->down1 || node->down2) {
+ /* printf("trinode: subd already done\n"); */
+ return;
+ }
+
+ /* bepaal subdivide richting */
+
+ if(edge==0) {
+ /* areathreshold */
+ if(node->area<nodelimit) return;
+
+ fu= edlen(node->v1, node->v2);
+ fv= edlen(node->v2, node->v3);
+ fl= edlen(node->v3, node->v1);
+
+ if(fu>fv && fu>fl) uvl= 1;
+ else if(fv>fu && fv>fl) uvl= 2;
+ else uvl= 3;
+ }
+ else {
+
+ if(edge==node->ed1) uvl= 1;
+ else if(edge==node->ed2) uvl= 2;
+ else uvl= 3;
+ }
+
+ /* moeten naastliggende nodes dieper? Recursief! */
+ n1= 0;
+ if(uvl==1) {
+ if(node->ed1 && node->ed1->down1==0) n1= node->ed1;
+ }
+ else if(uvl==2) {
+ if(node->ed2 && node->ed2->down1==0) n1= node->ed2;
+ }
+ else {
+ if(node->ed3 && node->ed3->down1==0) n1= node->ed3;
+ }
+ if(n1) {
+ up= node->up;
+ while(up) { /* ook testen op ed4 !!! */
+ if(n1->ed1==up || n1->ed2==up || n1->ed3==up || n1->ed4==up) {
+ subdivideNode(n1, up);
+ break;
+ }
+ up= up->up;
+ }
+ }
+
+ /* Het subdividen */
+ n1= mallocNode();
+ memcpy(n1, node, sizeof(RNode));
+ n2= mallocNode();
+ memcpy(n2, node, sizeof(RNode));
+
+ n1->up= node;
+ n2->up= node;
+
+ node->down1= n1;
+ node->down2= n2;
+
+ /* subdivide edge 1 */
+ if(uvl==1) {
+
+ /* EERSTE NODE krijgt edge 2 */
+ n1->ed3= n2;
+ n1->lev3= 0;
+ replaceAllNode(n1->ed2, n1);
+ n1->lev1++;
+ replaceTestNode(n1->ed1, &(n1->ed1), n1, n1->lev1, n1->v2);
+
+ /* TWEEDE NODE krijgt edge 3 */
+ n2->ed2= n1;
+ n2->lev2= 0;
+ replaceAllNode(n2->ed3, n2);
+ n2->lev1++;
+ replaceTestNode(n2->ed1, &(n2->ed1), n2, n2->lev1, n2->v1);
+
+ /* NIEUWE VERTEX uit edge 1 */
+ if( setvertexpointersNode(n1->ed1, n1, n1->lev1, &v1, &v2) ) { /* nodes hebben gelijke levels */
+ if(v1== n1->v2) {
+ n1->v1= v2;
+ n2->v2= v2;
+ }
+ else {
+ n1->v1= v1;
+ n2->v2= v1;
+ }
+ }
+ else {
+ n1->v1= n2->v2= mallocVert();
+ n1->v1[0]= 0.5*(node->v1[0]+ node->v2[0]);
+ n1->v1[1]= 0.5*(node->v1[1]+ node->v2[1]);
+ n1->v1[2]= 0.5*(node->v1[2]+ node->v2[2]);
+ n1->v1[3]= node->v1[3]; /* color */
+ }
+ }
+ else if(uvl==2) {
+
+ /* EERSTE NODE krijgt edge 1 */
+ n1->ed3= n2;
+ n1->lev3= 0;
+ replaceAllNode(n1->ed1, n1);
+ n1->lev2++;
+ replaceTestNode(n1->ed2, &(n1->ed2), n1, n1->lev2, n1->v2);
+
+ /* TWEEDE NODE krijgt edge 3 */
+ n2->ed1= n1;
+ n2->lev1= 0;
+ replaceAllNode(n2->ed3, n2);
+ n2->lev2++;
+ replaceTestNode(n2->ed2, &(n2->ed2), n2, n2->lev2, n2->v3);
+
+ /* NIEUWE VERTEX uit edge 2 */
+ if( setvertexpointersNode(n1->ed2, n1, n1->lev2, &v1, &v2) ) { /* nodes hebben gelijke levels */
+ if(v1== n1->v2) {
+ n1->v3= v2;
+ n2->v2= v2;
+ }
+ else {
+ n1->v3= v1;
+ n2->v2= v1;
+ }
+ }
+ else {
+ n1->v3= n2->v2= mallocVert();
+ n1->v3[0]= 0.5*(node->v2[0]+ node->v3[0]);
+ n1->v3[1]= 0.5*(node->v2[1]+ node->v3[1]);
+ n1->v3[2]= 0.5*(node->v2[2]+ node->v3[2]);
+ n1->v3[3]= node->v1[3]; /* color */
+ }
+ }
+ else if(uvl==3) {
+
+ /* EERSTE NODE krijgt edge 1 */
+ n1->ed2= n2;
+ n1->lev2= 0;
+ replaceAllNode(n1->ed1, n1);
+ n1->lev3++;
+ replaceTestNode(n1->ed3, &(n1->ed3), n1, n1->lev3, n1->v1);
+
+ /* TWEEDE NODE krijgt edge 2 */
+ n2->ed1= n1;
+ n2->lev1= 0;
+ replaceAllNode(n2->ed2, n2);
+ n2->lev3++;
+ replaceTestNode(n2->ed3, &(n2->ed3), n2, n2->lev3, n2->v3);
+
+ /* NIEUWE VERTEX uit edge 3 */
+ if( setvertexpointersNode(n1->ed3, n1, n1->lev3, &v1, &v2) ) { /* nodes hebben gelijke levels */
+ if(v1== n1->v1) {
+ n1->v3= v2;
+ n2->v1= v2;
+ }
+ else {
+ n1->v3= v1;
+ n2->v1= v1;
+ }
+ }
+ else {
+ n1->v3= n2->v1= mallocVert();
+ n1->v3[0]= 0.5*(node->v1[0]+ node->v3[0]);
+ n1->v3[1]= 0.5*(node->v1[1]+ node->v3[1]);
+ n1->v3[2]= 0.5*(node->v1[2]+ node->v3[2]);
+ n1->v3[3]= node->v3[3]; /* color */
+ }
+ }
+ n1->area= AreaT3Dfl(n1->v1, n1->v2, n1->v3);
+ n2->area= AreaT3Dfl(n2->v1, n2->v2, n2->v3);
+
+}
+
+
+void subdivideNode(RNode *node, RNode *edge)
+{
+ RNode *n1, *n2, *up;
+ float fu, fv, *v1, *v2;/*, AreaQ3Dfl(); ... from arithb... */
+ int uvl;
+
+ if(Ntotnode>RG.maxnode) return;
+
+ if(node->type==3) {
+ subdivideTriNode(node, edge);
+ return;
+ }
+
+ if(node->down1 || node->down2) {
+ /* printf("subdivide Node: already done \n"); */
+ return;
+ }
+
+ /* bepaal subdivide richting */
+
+ if(edge==0) {
+ /* areathreshold */
+ if(node->area<nodelimit) {
+ return;
+ }
+ fu= fabs(node->v1[0]- node->v2[0])+ fabs(node->v1[1]- node->v2[1]) +fabs(node->v1[2]- node->v2[2]);
+ fv= fabs(node->v1[0]- node->v4[0])+ fabs(node->v1[1]- node->v4[1]) +fabs(node->v1[2]- node->v4[2]);
+ if(fu>fv) uvl= 1;
+ else uvl= 2;
+ }
+ else {
+ if(edge==node->ed1 || edge==node->ed3) uvl= 1;
+ else uvl= 2;
+ }
+
+ /* moeten naastliggende nodes dieper? Recursief! */
+ n1= n2= 0;
+ if(uvl==1) {
+ if(node->ed1 && node->ed1->down1==0) n1= node->ed1;
+ if(node->ed3 && node->ed3->down1==0) n2= node->ed3;
+ }
+ else {
+ if(node->ed2 && node->ed2->down1==0) n1= node->ed2;
+ if(node->ed4 && node->ed4->down1==0) n2= node->ed4;
+ }
+ if(n1) {
+ up= node->up;
+ while(up) {
+ if(n1->ed1==up || n1->ed2==up || n1->ed3==up || n1->ed4==up) {
+ /* printf("recurs subd\n"); */
+ subdivideNode(n1, up);
+ break;
+ }
+ up= up->up;
+ }
+ }
+ if(n2) {
+ up= node->up;
+ while(up) {
+ if(n2->ed1==up || n2->ed2==up || n2->ed3==up || n2->ed4==up) {
+ /* printf("recurs subd\n"); */
+ subdivideNode(n2, up);
+ break;
+ }
+ up= up->up;
+ }
+ }
+
+ /* Het subdividen */
+ n1= mallocNode();
+ memcpy(n1, node, sizeof(RNode));
+ n2= mallocNode();
+ memcpy(n2, node, sizeof(RNode));
+
+ n1->up= node;
+ n2->up= node;
+
+ node->down1= n1;
+ node->down2= n2;
+
+ /* subdivide edge 1 en 3 */
+ if(uvl==1) {
+
+ /* EERSTE NODE krijgt edge 2 */
+ n1->ed4= n2;
+ n1->lev4= 0;
+ replaceAllNode(n1->ed2, n1);
+ n1->lev1++;
+ n1->lev3++;
+ replaceTestNode(n1->ed1, &(n1->ed1), n1, n1->lev1, n1->v2);
+ replaceTestNode(n1->ed3, &(n1->ed3), n1, n1->lev3, n1->v3);
+
+ /* TWEEDE NODE krijgt edge 4 */
+ n2->ed2= n1;
+ n2->lev2= 0;
+ replaceAllNode(n2->ed4, n2);
+ n2->lev1++;
+ n2->lev3++;
+ replaceTestNode(n2->ed1, &(n2->ed1), n2, n2->lev1, n2->v1);
+ replaceTestNode(n2->ed3, &(n2->ed3), n2, n2->lev3, n2->v4);
+
+ /* NIEUWE VERTEX uit edge 1 */
+ if( setvertexpointersNode(n1->ed1, n1, n1->lev1, &v1, &v2) ) { /* nodes hebben gelijke levels */
+ if(v1== n1->v2) {
+ n1->v1= v2;
+ n2->v2= v2;
+ }
+ else {
+ n1->v1= v1;
+ n2->v2= v1;
+ }
+ }
+ else {
+ n1->v1= n2->v2= mallocVert();
+ n1->v1[0]= 0.5*(node->v1[0]+ node->v2[0]);
+ n1->v1[1]= 0.5*(node->v1[1]+ node->v2[1]);
+ n1->v1[2]= 0.5*(node->v1[2]+ node->v2[2]);
+ n1->v1[3]= node->v1[3]; /* color */
+ }
+
+ /* NIEUWE VERTEX uit edge 3 */
+ if( setvertexpointersNode(n1->ed3, n1, n1->lev3, &v1, &v2) ) { /* nodes hebben gelijke levels */
+ if(v1== n1->v3) {
+ n1->v4= v2;
+ n2->v3= v2;
+ }
+ else {
+ n1->v4= v1;
+ n2->v3= v1;
+ }
+ }
+ else {
+ n1->v4= n2->v3= mallocVert();
+ n1->v4[0]= 0.5*(node->v3[0]+ node->v4[0]);
+ n1->v4[1]= 0.5*(node->v3[1]+ node->v4[1]);
+ n1->v4[2]= 0.5*(node->v3[2]+ node->v4[2]);
+ n1->v4[3]= node->v4[3]; /* color */
+ }
+ }
+ /* subdivide edge 2 en 4 */
+ else if(uvl==2) {
+
+ /* EERSTE NODE krijgt edge 1 */
+ n1->ed3= n2;
+ n1->lev3= 0;
+ replaceAllNode(n1->ed1, n1);
+ n1->lev2++;
+ n1->lev4++;
+ replaceTestNode(n1->ed2, &(n1->ed2), n1, n1->lev2, n1->v2);
+ replaceTestNode(n1->ed4, &(n1->ed4), n1, n1->lev4, n1->v1);
+
+ /* TWEEDE NODE krijgt edge 3 */
+ n2->ed1= n1;
+ n2->lev1= 0;
+ replaceAllNode(n2->ed3, n2);
+ n2->lev2++;
+ n2->lev4++;
+ replaceTestNode(n2->ed2, &(n2->ed2), n2, n2->lev2, n2->v3);
+ replaceTestNode(n2->ed4, &(n2->ed4), n2, n2->lev4, n2->v4);
+
+ /* NIEUWE VERTEX uit edge 2 */
+ if( setvertexpointersNode(n1->ed2, n1, n1->lev2, &v1, &v2) ) { /* nodes hebben gelijke levels */
+ if(v1== n1->v2) {
+ n1->v3= v2;
+ n2->v2= v2;
+ }
+ else {
+ n1->v3= v1;
+ n2->v2= v1;
+ }
+ }
+ else {
+ n1->v3= n2->v2= mallocVert();
+ n1->v3[0]= 0.5*(node->v2[0]+ node->v3[0]);
+ n1->v3[1]= 0.5*(node->v2[1]+ node->v3[1]);
+ n1->v3[2]= 0.5*(node->v2[2]+ node->v3[2]);
+ n1->v3[3]= node->v3[3]; /* color */
+ }
+
+ /* NIEUWE VERTEX uit edge 4 */
+ if( setvertexpointersNode(n1->ed4, n1, n1->lev4, &v1, &v2) ) { /* nodes hebben gelijke levels */
+ if(v1== n1->v1) {
+ n1->v4= v2;
+ n2->v1= v2;
+ }
+ else {
+ n1->v4= v1;
+ n2->v1= v1;
+ }
+ }
+ else {
+ n1->v4= n2->v1= mallocVert();
+ n1->v4[0]= 0.5*(node->v1[0]+ node->v4[0]);
+ n1->v4[1]= 0.5*(node->v1[1]+ node->v4[1]);
+ n1->v4[2]= 0.5*(node->v1[2]+ node->v4[2]);
+ n1->v4[3]= node->v4[3]; /* color */
+ }
+
+ }
+
+ n1->area= AreaQ3Dfl(n1->v1, n1->v2, n1->v3, n1->v4);
+ n2->area= AreaQ3Dfl(n2->v1, n2->v2, n2->v3, n2->v4);
+
+}
+
+int comparelevel(RNode *node, RNode *nb, int level)
+{
+ /* recursief afdalen: bij diepste node testen */
+ /* return 1 is gelijk of hoger */
+
+ if(nb==0) return 1;
+
+ if(nb->down1) {
+ return 0;
+
+ /* HIER ZIT EEN FOUT, MAAR WELKE? (zonder dit werkt 't ook, maar langzamer)
+ n1= nb->down1;
+ if(n1->ed1==node) return comparelevel(node, n1, level);
+ if(n1->ed2==node) return comparelevel(node, n1, level);
+ if(n1->ed3==node) return comparelevel(node, n1, level);
+ if(n1->ed4==node) return comparelevel(node, n1, level);
+ n1= nb->down2;
+ if(n1->ed1==node) return comparelevel(node, n1, level);
+ if(n1->ed2==node) return comparelevel(node, n1, level);
+ if(n1->ed3==node) return comparelevel(node, n1, level);
+ if(n1->ed4==node) return comparelevel(node, n1, level);
+ printf(" dit kan niet ");
+ return 0;
+ */
+
+ }
+
+ if(nb->down1==0) {
+ /* if(nb->ed1==node) return (nb->lev1<=level); */
+ /* if(nb->ed2==node) return (nb->lev2<=level); */
+ /* if(nb->ed3==node) return (nb->lev3<=level); */
+ /* if(nb->ed4==node) return (nb->lev4<=level); */
+
+ return 1; /* is hogere node */
+ }
+ return 1;
+}
+
+void deleteTriNodes(RNode *node) /* beide kinderen van node */
+{
+ RNode *n1, *n2;
+
+ /* als naastliggende nodes dieper zijn: geen delete */
+ /* enkel twee nodes testen, van andere verandert level niet */
+
+ n1= node->down1;
+ n2= node->down2;
+
+ if(n1==0 || n2==0) return;
+
+ if(n1->down1 || n2->down1) return;
+
+ /* aan edges mag geen gesubdivide node zitten */
+
+ if(n1->ed1 && n1->ed1->down1) return;
+ if(n1->ed2 && n1->ed2->down1) return;
+ if(n1->ed3 && n1->ed3->down1) return;
+
+ if(n2->ed1 && n2->ed1->down1) return;
+ if(n2->ed2 && n2->ed2->down1) return;
+ if(n2->ed3 && n2->ed3->down1) return;
+
+ replaceAllNodeInv(n1->ed1, n1);
+ replaceAllNodeInv(n1->ed2, n1);
+ replaceAllNodeInv(n1->ed3, n1);
+
+ replaceAllNodeUp(n1->ed1, n1);
+ replaceAllNodeUp(n1->ed2, n1);
+ replaceAllNodeUp(n1->ed3, n1);
+
+ replaceAllNodeInv(n2->ed1, n2);
+ replaceAllNodeInv(n2->ed2, n2);
+ replaceAllNodeInv(n2->ed3, n2);
+
+ replaceAllNodeUp(n2->ed1, n2);
+ replaceAllNodeUp(n2->ed2, n2);
+ replaceAllNodeUp(n2->ed3, n2);
+
+ n1->down1= (RNode *)12; /* voor debug */
+ n2->down1= (RNode *)12;
+
+ freeNode(n1);
+ freeNode(n2);
+ node->down1= node->down2= 0;
+
+}
+
+ /* beide kinderen van node */
+void deleteNodes(RNode *node)
+{
+ RNode *n1, *n2;
+
+ /* als naastliggende nodes dieper zijn: geen delete */
+ /* enkel twee nodes testen, van andere verandert level niet */
+
+ if(node->type==3) {
+ deleteTriNodes(node);
+ return;
+ }
+
+ n1= node->down1;
+ n2= node->down2;
+
+ if(n1==0 || n2==0) return;
+
+ if(n1->down1 || n2->down1) return;
+
+ if(n1->ed3==n2) {
+
+ /* aan edges mag geen gesubdivide node zitten */
+
+ if(n1->ed1 && n1->ed1->down1) return;
+ if(n1->ed2 && n1->ed2->down1) return;
+ if(n1->ed4 && n1->ed4->down1) return;
+
+ if(n2->ed2 && n2->ed2->down1) return;
+ if(n2->ed3 && n2->ed3->down1) return;
+ if(n2->ed4 && n2->ed4->down1) return;
+
+ replaceAllNodeInv(n1->ed1, n1);
+ replaceAllNodeInv(n1->ed2, n1);
+ replaceAllNodeInv(n1->ed4, n1);
+
+ replaceAllNodeUp(n1->ed1, n1);
+ replaceAllNodeUp(n1->ed2, n1);
+ replaceAllNodeUp(n1->ed4, n1);
+
+ replaceAllNodeInv(n2->ed2, n2);
+ replaceAllNodeInv(n2->ed3, n2);
+ replaceAllNodeInv(n2->ed4, n2);
+
+ replaceAllNodeUp(n2->ed2, n2);
+ replaceAllNodeUp(n2->ed3, n2);
+ replaceAllNodeUp(n2->ed4, n2);
+
+ n1->down1= (RNode *)12; /* voor debug */
+ n2->down1= (RNode *)12;
+
+ freeNode(n1);
+ freeNode(n2);
+ node->down1= node->down2= 0;
+
+ return;
+ }
+ else if(n1->ed4==n2) {
+
+ if(n1->ed1 && n1->ed1->down1) return;
+ if(n1->ed2 && n1->ed2->down1) return;
+ if(n1->ed3 && n1->ed3->down1) return;
+
+ if(n2->ed1 && n2->ed1->down1) return;
+ if(n2->ed3 && n2->ed3->down1) return;
+ if(n2->ed4 && n2->ed4->down1) return;
+
+ replaceAllNodeInv(n1->ed1, n1);
+ replaceAllNodeInv(n1->ed2, n1);
+ replaceAllNodeInv(n1->ed3, n1);
+
+ replaceAllNodeUp(n1->ed1, n1);
+ replaceAllNodeUp(n1->ed2, n1);
+ replaceAllNodeUp(n1->ed3, n1);
+
+ replaceAllNodeInv(n2->ed1, n2);
+ replaceAllNodeInv(n2->ed3, n2);
+ replaceAllNodeInv(n2->ed4, n2);
+
+ replaceAllNodeUp(n2->ed1, n2);
+ replaceAllNodeUp(n2->ed3, n2);
+ replaceAllNodeUp(n2->ed4, n2);
+
+ n1->down1= (RNode *)12; /* voor debug */
+ n2->down1= (RNode *)12;
+
+ freeNode(n1);
+ freeNode(n2);
+ node->down1= node->down2= 0;
+
+ return;
+ }
+
+}
+
+
diff --git a/source/blender/radiosity/intern/source/radpostprocess.c b/source/blender/radiosity/intern/source/radpostprocess.c
new file mode 100644
index 00000000000..8cbbfb1f4de
--- /dev/null
+++ b/source/blender/radiosity/intern/source/radpostprocess.c
@@ -0,0 +1,871 @@
+/* ***************************************
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+
+
+
+ radpostprocess.c nov/dec 1992
+ may 1999
+
+ - faces
+ - filtering and node-limit
+ - apply to meshes
+ $Id$
+
+ *************************************** */
+
+#include <stdlib.h>
+#include <math.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_radio_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_material.h"
+
+#include "BIF_screen.h" /* waitcursor */
+#include "BIF_editview.h" /* deselectall */
+
+#include "BDR_editobject.h" /* delete_obj */
+
+#include "radio.h"
+
+/* locals? not. done in radio.h... */
+/* void rad_addmesh(void); */
+/* void rad_replacemesh(void); */
+
+void addaccu(register char *z, register char *t)
+{
+ register int div, mul;
+
+ mul= *t;
+ div= mul+1;
+ (*t)++;
+
+ t[1]= (mul*t[1]+z[1])/div;
+ t[2]= (mul*t[2]+z[2])/div;
+ t[3]= (mul*t[3]+z[3])/div;
+
+}
+
+void addaccuweight(register char *z, register char *t, int w)
+{
+ register int div, mul;
+
+ if(w==0) w= 1;
+
+ mul= *t;
+ div= mul+w;
+ if(div>255) return;
+ (*t)= div;
+
+ t[1]= (mul*t[1]+w*z[1])/div;
+ t[2]= (mul*t[2]+w*z[2])/div;
+ t[3]= (mul*t[3]+w*z[3])/div;
+
+}
+
+void triaweight(Face *face, int *w1, int *w2, int *w3)
+{
+ float n1[3], n2[3], n3[3], temp;
+
+ n1[0]= face->v2[0]-face->v1[0];
+ n1[1]= face->v2[1]-face->v1[1];
+ n1[2]= face->v2[2]-face->v1[2];
+ n2[0]= face->v3[0]-face->v2[0];
+ n2[1]= face->v3[1]-face->v2[1];
+ n2[2]= face->v3[2]-face->v2[2];
+ n3[0]= face->v1[0]-face->v3[0];
+ n3[1]= face->v1[1]-face->v3[1];
+ n3[2]= face->v1[2]-face->v3[2];
+ Normalise(n1);
+ Normalise(n2);
+ Normalise(n3);
+ temp= 32.0/(PI);
+ *w1= 0.5+temp*acos(-n1[0]*n3[0]-n1[1]*n3[1]-n1[2]*n3[2]);
+ *w2= 0.5+temp*acos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]);
+ *w3= 0.5+temp*acos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]);
+
+}
+
+
+
+void init_face_tab()
+{
+ int a= 0;
+
+ if(RG.facebase==0) {
+ RG.facebase= MEM_callocN(sizeof(void *)*RAD_MAXFACETAB, "init_face_tab");
+ }
+ for(a=0; a<RAD_MAXFACETAB; a++) {
+ if(RG.facebase[a]==0) break;
+ MEM_freeN(RG.facebase[a]);
+ RG.facebase[a]= 0;
+ }
+ RG.totface= 0;
+}
+
+Face *addface()
+{
+ Face *face;
+ int a;
+
+ if(RG.totface<0 || RG.totface>RAD_MAXFACETAB*1024 ) {
+ printf("error in addface: %d\n", RG.totface);
+ return 0;
+ }
+ a= RG.totface>>10;
+ face= RG.facebase[a];
+ if(face==0) {
+ face= MEM_callocN(1024*sizeof(Face),"addface");
+ RG.facebase[a]= face;
+ }
+ face+= (RG.totface & 1023);
+
+ RG.totface++;
+
+ return face;
+
+}
+
+void makeface(float *v1, float *v2, float *v3, float *v4, RNode *rn)
+{
+ Face *face;
+
+ face= addface();
+ face->v1= v1;
+ face->v2= v2;
+ face->v3= v3;
+ face->v4= v4;
+ face->col= rn->col;
+ face->matindex= rn->par->matindex;
+}
+
+
+void anchorQuadface(RNode *rn, float *v1, float *v2, float *v3, float *v4, int flag)
+{
+
+ switch(flag) {
+ case 1:
+ makeface(rn->v1, v1, rn->v4, 0, rn);
+ makeface(v1, rn->v3, rn->v4, 0, rn);
+ makeface(v1, rn->v2, rn->v3, 0, rn);
+ break;
+ case 2:
+ makeface(rn->v2, v2, rn->v1, 0, rn);
+ makeface(v2, rn->v4, rn->v1, 0, rn);
+ makeface(v2, rn->v3, rn->v4, 0, rn);
+ break;
+ case 4:
+ makeface(rn->v3, v3, rn->v2, 0, rn);
+ makeface(v3, rn->v1, rn->v2, 0, rn);
+ makeface(v3, rn->v4, rn->v1, 0, rn);
+ break;
+ case 8:
+ makeface(rn->v4, v4, rn->v3, 0, rn);
+ makeface(v4, rn->v2, rn->v3, 0, rn);
+ makeface(v4, rn->v1, rn->v2, 0, rn);
+ break;
+
+ case 3:
+ makeface(rn->v1, v1, rn->v4, 0, rn);
+ makeface(v1, v2, rn->v4, 0, rn);
+ makeface(v1, rn->v2, v2, 0, rn);
+ makeface(v2, rn->v3, rn->v4, 0, rn);
+ break;
+ case 6:
+ makeface(rn->v2, v2, rn->v1, 0, rn);
+ makeface(v2, v3, rn->v1, 0, rn);
+ makeface(v2, rn->v3, v3, 0, rn);
+ makeface(v3, rn->v4, rn->v1, 0, rn);
+ break;
+ case 12:
+ makeface(rn->v3, v3, rn->v2, 0, rn);
+ makeface(v3, v4, rn->v2, 0, rn);
+ makeface(v3, rn->v4, v4, 0, rn);
+ makeface(v4, rn->v1, rn->v2, 0, rn);
+ break;
+ case 9:
+ makeface(rn->v4, v4, rn->v3, 0, rn);
+ makeface(v4, v1, rn->v3, 0, rn);
+ makeface(v4, rn->v1, v1, 0, rn);
+ makeface(v1, rn->v2, rn->v3, 0, rn);
+ break;
+
+ case 5:
+ makeface(rn->v1, v1, v3, rn->v4, rn);
+ makeface(v1, rn->v2, rn->v3, v3, rn);
+ break;
+ case 10:
+ makeface(rn->v2, v2, v4, rn->v1, rn);
+ makeface(v2, rn->v3, rn->v4, v4, rn);
+ break;
+
+ case 7:
+ makeface(rn->v1, v1, v3, rn->v4, rn);
+ makeface(v1, v2, v3, 0, rn);
+ makeface(v1, rn->v2, v2, 0, rn);
+ makeface(v2, rn->v3, v3, 0, rn);
+ break;
+ case 14:
+ makeface(rn->v2, v2, v4, rn->v1, rn);
+ makeface(v2, v3, v4, 0, rn);
+ makeface(v2, rn->v3, v3, 0, rn);
+ makeface(v3, rn->v4, v4, 0, rn);
+ break;
+ case 13:
+ makeface(rn->v3, v3, v1, rn->v2, rn);
+ makeface(v3, v4, v1, 0, rn);
+ makeface(v3, rn->v4, v4, 0, rn);
+ makeface(v4, rn->v1, v1, 0, rn);
+ break;
+ case 11:
+ makeface(rn->v4, v4, v2, rn->v3, rn);
+ makeface(v4, v1, v2, 0, rn);
+ makeface(v4, rn->v1, v1, 0, rn);
+ makeface(v1, rn->v2, v2, 0, rn);
+ break;
+
+ case 15:
+ makeface(v1, v2, v3, v4, rn);
+ makeface(v1, rn->v2, v2, 0, rn);
+ makeface(v2, rn->v3, v3, 0, rn);
+ makeface(v3, rn->v4, v4, 0, rn);
+ makeface(v4, rn->v1, v1, 0, rn);
+ break;
+ }
+}
+
+void anchorTriface(RNode *rn, float *v1, float *v2, float *v3, int flag)
+{
+ switch(flag) {
+ case 1:
+ makeface(rn->v1, v1, rn->v3, 0, rn);
+ makeface(v1, rn->v2, rn->v3, 0, rn);
+ break;
+ case 2:
+ makeface(rn->v2, v2, rn->v1, 0, rn);
+ makeface(v2, rn->v3, rn->v1, 0, rn);
+ break;
+ case 4:
+ makeface(rn->v3, v3, rn->v2, 0, rn);
+ makeface(v3, rn->v1, rn->v2, 0, rn);
+ break;
+
+ case 3:
+ makeface(rn->v1, v2, rn->v3, 0, rn);
+ makeface(rn->v1, v1, v2, 0, rn);
+ makeface(v1, rn->v2, v2, 0, rn);
+ break;
+ case 6:
+ makeface(rn->v2, v3, rn->v1, 0, rn);
+ makeface(rn->v2, v2, v3, 0, rn);
+ makeface(v2, rn->v3, v3, 0, rn);
+ break;
+ case 5:
+ makeface(rn->v3, v1, rn->v2, 0, rn);
+ makeface(rn->v3, v3, v1, 0, rn);
+ makeface(v3, rn->v1, v1, 0, rn);
+ break;
+
+ case 7:
+ makeface(v1, v2, v3, 0, rn);
+ makeface(rn->v1, v1, v3, 0, rn);
+ makeface(rn->v2, v2, v1, 0, rn);
+ makeface(rn->v3, v3, v2, 0, rn);
+ break;
+ }
+}
+
+
+float *findmiddlevertex(RNode *node, RNode *nb, float *v1, float *v2)
+{
+ int test= 0;
+
+ if(nb==0) return 0;
+
+ if(nb->ed1==node) {
+ if(nb->v1==v1 || nb->v1==v2) test++;
+ if(nb->v2==v1 || nb->v2==v2) test+=2;
+ if(test==1) return nb->v2;
+ else if(test==2) return nb->v1;
+ }
+ else if(nb->ed2==node) {
+ if(nb->v2==v1 || nb->v2==v2) test++;
+ if(nb->v3==v1 || nb->v3==v2) test+=2;
+ if(test==1) return nb->v3;
+ else if(test==2) return nb->v2;
+ }
+ else if(nb->ed3==node) {
+ if(nb->type==4) {
+ if(nb->v3==v1 || nb->v3==v2) test++;
+ if(nb->v4==v1 || nb->v4==v2) test+=2;
+ if(test==1) return nb->v4;
+ else if(test==2) return nb->v3;
+
+ }
+ else {
+ if(nb->v3==v1 || nb->v3==v2) test++;
+ if(nb->v1==v1 || nb->v1==v2) test+=2;
+ if(test==1) return nb->v1;
+ else if(test==2) return nb->v3;
+ }
+ }
+ else if(nb->ed4==node) {
+ if(nb->v4==v1 || nb->v4==v2) test++;
+ if(nb->v1==v1 || nb->v1==v2) test+=2;
+ if(test==1) return nb->v1;
+ else if(test==2) return nb->v4;
+ }
+ return 0;
+}
+
+void make_face_tab() /* zorgt voor ankers */
+{
+ RNode *rn, **el;
+ Face *face = NULL;
+ float *v1, *v2, *v3, *v4;
+ int a, flag, w1, w2, w3;
+ char *charcol;
+
+ if(RG.totelem==0) return;
+
+ init_face_tab();
+
+ RG.igamma= 1.0/RG.gamma;
+ RG.radfactor= RG.radfac*pow(64*64, RG.igamma);
+
+ /* vlakkleuren omzetten */
+ el= RG.elem;
+ for(a=RG.totelem; a>0; a--, el++) {
+ rn= *el;
+ charcol= (char *)&( rn->col );
+
+ charcol[3]= calculatecolor(rn->totrad[0]);
+ charcol[2]= calculatecolor(rn->totrad[1]);
+ charcol[1]= calculatecolor(rn->totrad[2]);
+ }
+
+ /* nodes aflopen en Face's maken */
+ el= RG.elem;
+ for(a=RG.totelem; a>0; a--, el++) {
+
+ rn= *el;
+
+ rn->v1[3]= 0.0;
+ rn->v2[3]= 0.0;
+ rn->v3[3]= 0.0;
+ if(rn->v4) rn->v4[3]= 0.0;
+
+ /* test edges op subdivide */
+ flag= 0;
+ v1= v2= v3= v4= 0;
+ if(rn->ed1) {
+ v1= findmiddlevertex(rn, rn->ed1->down1, rn->v1, rn->v2);
+ if(v1) flag |= 1;
+ }
+ if(rn->ed2) {
+ v2= findmiddlevertex(rn, rn->ed2->down1, rn->v2, rn->v3);
+ if(v2) flag |= 2;
+ }
+ if(rn->ed3) {
+ if(rn->type==4)
+ v3= findmiddlevertex(rn, rn->ed3->down1, rn->v3, rn->v4);
+ else
+ v3= findmiddlevertex(rn, rn->ed3->down1, rn->v3, rn->v1);
+ if(v3) flag |= 4;
+ }
+ if(rn->ed4) {
+ v4= findmiddlevertex(rn, rn->ed4->down1, rn->v4, rn->v1);
+ if(v4) flag |= 8;
+ }
+
+ /* met flag en vertexpointers kunnen nu Face's gemaakt*/
+
+ if(flag==0) {
+ makeface(rn->v1, rn->v2, rn->v3, rn->v4, rn);
+ }
+ else if(rn->type==4) anchorQuadface(rn, v1, v2, v3, v4, flag);
+ else anchorTriface(rn, v1, v2, v3, flag);
+ }
+
+ /* optellen */
+ for(a=0; a<RG.totface; a++) {
+
+ RAD_NEXTFACE(a);
+
+ if(face->v4) {
+ addaccuweight( (char *)&(face->col), (char *)(face->v1+3), 16 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v2+3), 16 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v3+3), 16 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v4+3), 16 );
+ }
+ else {
+ triaweight(face, &w1, &w2, &w3);
+ addaccuweight( (char *)&(face->col), (char *)(face->v1+3), w1 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v2+3), w2 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v3+3), w3 );
+ }
+ }
+
+}
+
+void filterFaces()
+{
+ /* alle kleuren van vertices in faces en weer terug */
+
+ Face *face = NULL;
+ int a, w1, w2, w3;
+
+ if(RG.totface==0) return;
+
+ /* wissen */
+ for(a=0; a<RG.totface; a++) {
+ RAD_NEXTFACE(a);
+ face->col= 0;
+ }
+
+ /* optellen: punten bij vlakken */
+ for(a=0; a<RG.totface; a++) {
+ RAD_NEXTFACE(a);
+
+ if(face->v4) {
+ addaccuweight( (char *)(face->v1+3), (char *)&(face->col), 16 );
+ addaccuweight( (char *)(face->v2+3), (char *)&(face->col), 16 );
+ addaccuweight( (char *)(face->v3+3), (char *)&(face->col), 16 );
+ addaccuweight( (char *)(face->v4+3), (char *)&(face->col), 16 );
+ }
+ else {
+ triaweight(face, &w1, &w2, &w3);
+ addaccuweight( (char *)(face->v1+3), (char *)&(face->col), w1 );
+ addaccuweight( (char *)(face->v2+3), (char *)&(face->col), w2 );
+ addaccuweight( (char *)(face->v3+3), (char *)&(face->col), w3 );
+ }
+ }
+
+ /* wissen */
+ for(a=0; a<RG.totface; a++) {
+ RAD_NEXTFACE(a);
+ face->v1[3]= 0.0;
+ face->v2[3]= 0.0;
+ face->v3[3]= 0.0;
+ if(face->v4) face->v4[3]= 0.0;
+ }
+
+
+ /* optellen: vlakken bij punten */
+ for(a=0; a<RG.totface; a++) {
+
+ RAD_NEXTFACE(a);
+
+ if(face->v4) {
+ addaccuweight( (char *)&(face->col), (char *)(face->v1+3), 16 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v2+3), 16 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v3+3), 16 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v4+3), 16 );
+ }
+ else {
+ triaweight(face, &w1, &w2, &w3);
+ addaccuweight( (char *)&(face->col), (char *)(face->v1+3), w1 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v2+3), w2 );
+ addaccuweight( (char *)&(face->col), (char *)(face->v3+3), w3 );
+ }
+ }
+}
+
+void calcfiltrad(RNode *rn, float *cd)
+{
+ float area;
+
+ cd[0]= 2.0*rn->totrad[0];
+ cd[1]= 2.0*rn->totrad[1];
+ cd[2]= 2.0*rn->totrad[2];
+ area= 2.0;
+
+ if(rn->ed1) {
+ cd[0]+= rn->ed1->totrad[0];
+ cd[1]+= rn->ed1->totrad[1];
+ cd[2]+= rn->ed1->totrad[2];
+ area+= 1.0;
+ }
+ if(rn->ed2) {
+ cd[0]+= rn->ed2->totrad[0];
+ cd[1]+= rn->ed2->totrad[1];
+ cd[2]+= rn->ed2->totrad[2];
+ area+= 1.0;
+ }
+ if(rn->ed3) {
+ cd[0]+= rn->ed3->totrad[0];
+ cd[1]+= rn->ed3->totrad[1];
+ cd[2]+= rn->ed3->totrad[2];
+ area+= 1.0;
+ }
+ if(rn->ed4) {
+ cd[0]+= rn->ed4->totrad[0];
+ cd[1]+= rn->ed4->totrad[1];
+ cd[2]+= rn->ed4->totrad[2];
+ area+= 1.0;
+ }
+ cd[0]/= area;
+ cd[1]/= area;
+ cd[2]/= area;
+
+}
+
+void filterNodes()
+{
+ /* alle kleuren van nodes in tempblok en weer terug */
+
+ RNode *rn, **el;
+ float *coldata, *cd;
+ int a;
+
+ if(RG.totelem==0) return;
+ /* de upnodes moeten kleur hebben */
+ el= RG.elem;
+ for(a=0; a<RG.totelem; a++, el++) {
+ rn= *el;
+ if(rn->up) {
+ rn->up->totrad[0]= 0.0;
+ rn->up->totrad[1]= 0.0;
+ rn->up->totrad[2]= 0.0;
+ if(rn->up->up) {
+ rn->up->up->totrad[0]= 0.0;
+ rn->up->up->totrad[1]= 0.0;
+ rn->up->up->totrad[2]= 0.0;
+ }
+ }
+ }
+ el= RG.elem;
+ for(a=0; a<RG.totelem; a++, el++) {
+ rn= *el;
+ if(rn->up) {
+ rn->up->totrad[0]+= 0.5*rn->totrad[0];
+ rn->up->totrad[1]+= 0.5*rn->totrad[1];
+ rn->up->totrad[2]+= 0.5*rn->totrad[2];
+ if(rn->up->up) {
+ rn->up->up->totrad[0]+= 0.25*rn->totrad[0];
+ rn->up->up->totrad[1]+= 0.25*rn->totrad[1];
+ rn->up->up->totrad[2]+= 0.25*rn->totrad[2];
+ }
+ }
+ }
+
+ /* met area optellen */
+ cd= coldata= MEM_mallocN(3*4*RG.totelem, "filterNodes");
+ el= RG.elem;
+ for(a=0; a<RG.totelem; a++, el++) {
+ calcfiltrad(*el, cd);
+ cd+= 3;
+ }
+
+ cd= coldata;
+ el= RG.elem;
+ for(a=0; a<RG.totelem; a++, el++) {
+ rn= *el;
+ VECCOPY(rn->totrad, cd);
+ cd+= 3;
+ }
+ MEM_freeN(coldata);
+}
+
+void removeEqualNodes(short limit)
+{
+ /* nodes met kleur gelijk aan elkaar: verwijderen */
+ RNode **el, *rn, *rn1;
+ float thresh, f1, f2;
+ int a, foundone=1, ok;
+ int c1, c2;
+
+ if(limit==0) return;
+
+ thresh= 1.0/(256.0*RG.radfactor);
+ thresh= 3.0*pow(thresh, RG.gamma);
+
+ waitcursor(1);
+
+ while(foundone) {
+ foundone= 0;
+
+ el= RG.elem;
+ for(a=RG.totelem; a>1; a--, el++) {
+ rn= *el;
+ rn1= *(el+1);
+
+ if(rn!=rn->par->first && rn1!=rn1->par->first) {
+ if(rn->up && rn->up==rn1->up) {
+ f1= rn->totrad[0]+ rn->totrad[1]+ rn->totrad[2];
+ f2= rn1->totrad[0]+ rn1->totrad[1]+ rn1->totrad[2];
+
+ ok= 0;
+ if(f1<thresh && f2<thresh) ok= 1;
+ else {
+ c1= calculatecolor(rn->totrad[0]);
+ c2= calculatecolor(rn1->totrad[0]);
+
+ if( abs(c1-c2)<=limit ) {
+ c1= calculatecolor(rn->totrad[1]);
+ c2= calculatecolor(rn1->totrad[1]);
+
+ if( abs(c1-c2)<=limit ) {
+ c1= calculatecolor(rn->totrad[2]);
+ c2= calculatecolor(rn1->totrad[2]);
+
+ if( abs(c1-c2)<=limit ) {
+ ok= 1;
+ }
+ }
+ }
+ }
+
+ if(ok) {
+ rn->up->totrad[0]= 0.5*(rn->totrad[0]+rn1->totrad[0]);
+ rn->up->totrad[1]= 0.5*(rn->totrad[1]+rn1->totrad[1]);
+ rn->up->totrad[2]= 0.5*(rn->totrad[2]+rn1->totrad[2]);
+ rn1= rn->up;
+ deleteNodes(rn1);
+ if(rn1->down1) ;
+ else {
+ foundone++;
+ a--; el++;
+ }
+ }
+ }
+ }
+ }
+ if(foundone) {
+ makeGlobalElemArray();
+ }
+ }
+ waitcursor(0);
+}
+
+#define BLSIZE 32000
+
+void rad_addmesh(void)
+{
+ Face *face = NULL;
+ Object *ob;
+ Mesh *me;
+ MVert *mvert;
+ MFace *mface;
+ Material *ma=0;
+ unsigned int *md, *coldata, *cd;
+ float **fpp, **poindata;
+ float cent[3], min[3], max[3];
+ int a, vcount, vlnr, startf, endf;
+
+ if(RG.totface==0) return;
+
+ /* make sure there's alpha in the color, to distinguish */
+ for(a=0; a<RG.totface; a++) {
+ RAD_NEXTFACE(a);
+ *((unsigned int *)face->v1+3) |= 0x1000000;
+ *((unsigned int *)face->v2+3) |= 0x1000000;
+ *((unsigned int *)face->v3+3) |= 0x1000000;
+ if(face->v4) {
+ *((unsigned int *)face->v4+3) |= 0x1000000;
+ }
+ }
+
+ /* we write in blocks of BLSIZE vertices max */
+ coldata= MEM_mallocN(4*BLSIZE, "writefaces");
+ poindata= MEM_mallocN(sizeof(void *)*BLSIZE, "writefaces1");
+
+ vlnr= 0;
+ endf= 0;
+ while(endf<RG.totface) {
+
+ cd= coldata;
+ fpp= poindata;
+ startf= endf;
+ vcount= 0;
+
+ face= RG.facebase[(startf-1)>>10]+((startf-1) & 1023);
+ for(vlnr=startf; vlnr<RG.totface; vlnr++) {
+ RAD_NEXTFACE(vlnr);
+
+ if( *((unsigned int *)face->v1+3) & 0x1000000 ) { /* is a color */
+ *cd= *((unsigned int *)face->v1+3);
+ *((unsigned int *)face->v1+3) = vcount;
+ *fpp= face->v1;
+ fpp++; vcount++; cd++;
+ }
+ if( *((unsigned int *)face->v2+3) & 0x1000000 ) {
+ *cd= *((unsigned int *)face->v2+3);
+ *((unsigned int *)face->v2+3) = vcount;
+ *fpp= face->v2;
+ fpp++; vcount++; cd++;
+ }
+ if( *((unsigned int *)face->v3+3) & 0x1000000 ) {
+ *cd= *((unsigned int *)face->v3+3);
+ *((unsigned int *)face->v3+3) = vcount;
+ *fpp= face->v3;
+ fpp++; vcount++; cd++;
+ }
+ if(face->v4 && ( *((unsigned int *)face->v4+3) & 0x1000000 ) ) {
+ *cd= *((unsigned int *)face->v4+3);
+ *((unsigned int *)face->v4+3) = vcount;
+ *fpp= face->v4;
+ fpp++; vcount++; cd++;
+ }
+
+ if(vcount>=BLSIZE-4) {
+ vlnr++;
+ break;
+ }
+ }
+
+ /* we now make the Mesh */
+ endf= vlnr;
+
+ ob= add_object(OB_MESH);
+
+ me= ob->data;
+ me->totvert= vcount;
+ me->totface= endf-startf;
+ me->flag= 0;
+ me->mvert= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
+ me->mcol= MEM_callocN(4*me->totface*sizeof(MCol), "mverts");
+ me->mface= MEM_callocN(me->totface*sizeof(MFace), "mface");
+
+
+ /* materials, and set VCOL flag */
+ for(a=0; a<RG.totmat; a++) {
+ assign_material(ob, RG.matar[a], a+1);
+ ma= RG.matar[a];
+ if(ma) ma->mode |= MA_VERTEXCOL;
+ }
+
+ /* verts */
+ mvert= me->mvert;
+ fpp= poindata;
+ for(a=0; a<me->totvert; a++, mvert++, fpp++) {
+ VECCOPY(mvert->co, *fpp);
+ }
+
+ /* faces and mcol */
+ mface= me->mface;
+ md= (unsigned int *)me->mcol;
+
+ face= RG.facebase[(startf-1)>>10]+((startf-1) & 1023);
+ for(a=startf; a<endf; a++, md+=4, mface++) {
+ RAD_NEXTFACE(a);
+ mface->v1= *((unsigned int *)face->v1+3);
+ mface->v2= *((unsigned int *)face->v2+3);
+ mface->v3= *((unsigned int *)face->v3+3);
+ if(face->v4) mface->v4= *((unsigned int *)face->v4+3);
+
+ mface->edcode= 3;
+ test_index_mface(mface, face->v4 ? 4 : 3);
+ mface->mat_nr= face->matindex;
+
+ md[0]= coldata[mface->v1];
+ md[1]= coldata[mface->v2];
+ md[2]= coldata[mface->v3];
+ md[3]= coldata[mface->v4];
+ }
+
+ /* boundbox en centrenew */
+
+ INIT_MINMAX(min, max);
+
+ mvert= me->mvert;
+ for(a=0; a<me->totvert; a++, mvert++) {
+ DO_MINMAX(mvert->co, min, max);
+ }
+
+ cent[0]= (min[0]+max[0])/2.0;
+ cent[1]= (min[1]+max[1])/2.0;
+ cent[2]= (min[2]+max[2])/2.0;
+
+ mvert= me->mvert;
+ for(a=0; a<me->totvert; a++, mvert++) {
+ VecSubf(mvert->co, mvert->co, cent);
+ }
+
+ VECCOPY(ob->loc, cent);
+ tex_space_mesh(me);
+
+ /* restore colors */
+ face= RG.facebase[(startf-1)>>10]+((startf-1) & 1023);
+ for(a=startf; a<endf; a++) {
+ RAD_NEXTFACE(a);
+
+ cd= ((unsigned int *)face->v1+3);
+ if( *cd < 0x1000000 ) *cd= coldata[*cd];
+ cd= ((unsigned int *)face->v2+3);
+ if( *cd < 0x1000000 ) *cd= coldata[*cd];
+ cd= ((unsigned int *)face->v3+3);
+ if( *cd < 0x1000000 ) *cd= coldata[*cd];
+ if(face->v4) {
+ cd= ((unsigned int *)face->v4+3);
+ if( *cd < 0x1000000 ) *cd= coldata[*cd];
+ }
+ }
+ }
+
+ MEM_freeN(coldata);
+ MEM_freeN(poindata);
+
+}
+
+void rad_replacemesh(void)
+{
+ RPatch *rp;
+
+ deselectall();
+
+ rp= RG.patchbase.first;
+ while(rp) {
+ if( exist_object(rp->from)) rp->from->flag |= SELECT;
+ rp= rp->next;
+ }
+
+ copy_objectflags();
+ delete_obj(1);
+
+ rad_addmesh();
+}
+
diff --git a/source/blender/radiosity/intern/source/radpreprocess.c b/source/blender/radiosity/intern/source/radpreprocess.c
new file mode 100644
index 00000000000..c04886ca2fc
--- /dev/null
+++ b/source/blender/radiosity/intern/source/radpreprocess.c
@@ -0,0 +1,787 @@
+ /* ***************************************
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+
+
+
+ preproces.c nov/dec 1992
+ may 1999
+
+ - collect from meshes
+ - countglobaldata()
+ - makeGlobalElemArray()
+
+ $Id$
+
+ *************************************** */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+
+#include "BIF_toolbox.h"
+
+#include "radio.h"
+
+void setparelem(RNode *rn, RPatch *par);
+
+
+
+void splitconnected()
+{
+ /* voor zover de videoscapefile nog gedeelde vertices leverde, worden de vlakken getest
+ * op normaal en kleur. Doe dit door voor elke vertex een normaal en een kleur te onthouden.
+ */
+ RPatch *rp;
+ RNode *rn;
+ VeNoCo *vnc, *next, *vnc1;
+ int a;
+
+ /* test of gesplit moet worden */
+
+ rp= RG.patchbase.first;
+ while(rp) {
+ rn= rp->first;
+ if((rp->f1 & RAD_NO_SPLIT)==0) {
+ for(a=0; a<rp->type; a++) {
+
+ if(a==0) vnc= (VeNoCo *)rn->v1;
+ else if(a==1) vnc= (VeNoCo *)rn->v2;
+ else if(a==2) vnc= (VeNoCo *)rn->v3;
+ else vnc= (VeNoCo *)rn->v4;
+
+ if(vnc->flag==0) {
+ vnc->n= (float *)rp->norm;
+ vnc->col= (float *)rp->ref;
+ vnc->flag= 1;
+ }
+ else { /* mag vlak deze vertex gebruiken voor gouraud? */
+ vnc1= vnc;
+ while(vnc1) {
+ if(VecCompare(vnc1->n, rp->norm, 0.01)) {
+ if(VecCompare(vnc1->col, rp->ref, 0.01)) {
+ break;
+ }
+ }
+ vnc= vnc1;
+ vnc1= vnc1->next;
+ }
+ if(vnc1==0) {
+ vnc1= MEM_mallocN(sizeof(VeNoCo), "splitconn");
+ vnc1->next= 0;
+ vnc1->v= mallocVert();
+ vnc->next= vnc1;
+ VECCOPY(vnc1->v, vnc->v);
+ vnc1->n= (float *)rp->norm;
+ vnc1->col= (float *)rp->ref;
+ }
+ if(a==0) rn->v1= (float *)vnc1;
+ else if(a==1) rn->v2= (float *)vnc1;
+ else if(a==2) rn->v3= (float *)vnc1;
+ else rn->v4= (float *)vnc1;
+ }
+ }
+ }
+ rp= rp->next;
+ }
+ /* de vertexpointers van nodes aanpassen */
+
+ rp= RG.patchbase.first;
+ while(rp) {
+ rn= rp->first;
+ rn->v1= ((VeNoCo *)(rn->v1))->v;
+ rn->v2= ((VeNoCo *)(rn->v2))->v;
+ rn->v3= ((VeNoCo *)(rn->v3))->v;
+ if(rp->type==4) rn->v4= ((VeNoCo *)(rn->v4))->v;
+
+ rp= rp->next;
+ }
+
+
+ /* het hele zaakje vrijgeven */
+ vnc= RG.verts;
+ for(a=0; a<RG.totvert; a++) {
+ vnc1= vnc->next;
+ while(vnc1) {
+ next= vnc1->next;
+ MEM_freeN(vnc1);
+ vnc1= next;
+ }
+ vnc++;
+ }
+ MEM_freeN(RG.verts);
+ RG.verts= 0;
+}
+
+int vergedge(const void *v1,const void *v2)
+{
+ int *e1, *e2;
+
+ e1= (int *)v1;
+ e2= (int *)v2;
+
+ if( e1[0] > e2[0] ) return 1;
+ else if( e1[0] < e2[0] ) return -1;
+ else if( e1[1] > e2[1] ) return 1;
+ else if( e1[1] < e2[1] ) return -1;
+
+ return 0;
+}
+
+
+void addedge(float *v1, float *v2, EdSort *es)
+{
+ if( ((long)v1)<((long)v2) ) {
+ es->v1= v1;
+ es->v2= v2;
+ }
+ else {
+ es->v2= v1;
+ es->v1= v2;
+ }
+}
+
+static void setedge(RNode *node, RNode *nb, int nr, int nrb)
+{
+ switch(nr) {
+ case 1:
+ node->ed1= nb;
+ break;
+ case 2:
+ node->ed2= nb;
+ break;
+ case 3:
+ node->ed3= nb;
+ break;
+ case 4:
+ node->ed4= nb;
+ break;
+ }
+ switch(nrb) {
+ case 1:
+ nb->ed1= node;
+ break;
+ case 2:
+ nb->ed2= node;
+ break;
+ case 3:
+ nb->ed3= node;
+ break;
+ case 4:
+ nb->ed4= node;
+ break;
+ }
+}
+
+void setedgepointers()
+{
+ /* edge-array maken en sorteren */
+ /* paren edges staan bij elkaar: pointers invullen in nodes */
+ EdSort *es, *esblock;
+ RPatch *rp;
+ RNode *rn;
+ int tot= 0;
+
+ rp= RG.patchbase.first;
+ while(rp) {
+ tot+= rp->type;
+ rp= rp->next;
+ }
+
+ if(tot==0) return;
+
+ es=esblock= MEM_mallocN(tot*sizeof(EdSort), "setedgepointers");
+ rp= RG.patchbase.first;
+ while(rp) {
+ rn= rp->first;
+ addedge(rn->v1, rn->v2, es);
+ es->nr= 1;
+ es->node= rn;
+ es++;
+ addedge(rn->v2, rn->v3, es);
+ es->nr= 2;
+ es->node= rn;
+ es++;
+ if(rp->type==3) {
+ addedge(rn->v3, rn->v1, es);
+ es->nr= 3;
+ es->node= rn;
+ es++;
+ }
+ else {
+ addedge(rn->v3, rn->v4, es);
+ es->nr= 3;
+ es->node= rn;
+ es++;
+ addedge(rn->v4, rn->v1, es);
+ es->nr= 4;
+ es->node= rn;
+ es++;
+ }
+ rp= rp->next;
+ }
+
+ qsort(esblock,tot,sizeof(EdSort),vergedge);
+
+ es= esblock;
+ while(tot>0) {
+ if( es->v1== (es+1)->v1 ) {
+ if( es->v2== (es+1)->v2 ) {
+ setedge(es->node, (es+1)->node, es->nr, (es+1)->nr);
+ tot--;
+ es++;
+ }
+ }
+ es++;
+ tot--;
+ }
+
+ MEM_freeN(esblock);
+}
+
+void rad_collect_meshes()
+{
+ extern Material defmaterial;
+ Base *base;
+ Object *ob;
+ Mesh *me;
+ MVert *mvert;
+ MFace *mface;
+ Material *ma = NULL, *noma= NULL;
+ RPatch *rp;
+ RNode *rn;
+ VeNoCo *vnc, **nodevert;
+ float *vd, *v1, *v2, *v3, *v4 = NULL;
+ int a, b, offs, index, matindex;
+
+ if(G.obedit) {
+ error("Unable to perform function in EditMode");
+ return;
+ }
+
+ set_radglobal();
+
+ freeAllRad();
+
+ start_fastmalloc("Radiosity");
+
+ /* count the number of verts */
+ RG.totvert= 0;
+ RG.totface= 0;
+ base= (G.scene->base.first);
+ while(base) {
+ if(((base)->flag & SELECT) && ((base)->lay & G.vd->lay) ) {
+ if(base->object->type==OB_MESH) {
+ base->flag |= OB_RADIO;
+ me= base->object->data;
+ RG.totvert+= me->totvert;
+ }
+ }
+ base= base->next;
+ }
+ if(RG.totvert==0) {
+ error("No vertices");
+ return;
+ }
+ vnc= RG.verts= MEM_callocN(RG.totvert*sizeof(VeNoCo), "readvideoscape1");
+
+ RG.min[0]= RG.min[1]= RG.min[2]= 1.0e20;
+ RG.max[0]= RG.max[1]= RG.max[2]= -1.0e20;
+
+ /* min-max and material array */
+ base= (G.scene->base.first);
+ while(base) {
+ if( ((base)->flag & SELECT) && ((base)->lay & G.vd->lay) ) {
+ if(base->object->type==OB_MESH) {
+ me= base->object->data;
+ mvert= me->mvert;
+ for(a=0; a<me->totvert; a++, mvert++) {
+ vd= mallocVert();
+ VECCOPY(vd, mvert->co);
+ /* Should make MTC its own module... */
+ Mat4MulVecfl(base->object->obmat, vd);
+
+ vnc->v= vd;
+ for(b=0; b<3; b++) {
+ RG.min[b]= MIN2(RG.min[b], vd[b]);
+ RG.max[b]= MAX2(RG.max[b], vd[b]);
+ }
+ vnc++;
+ }
+
+ if(base->object->totcol==0) {
+ if(RG.totmat<MAXMAT) {
+ if(noma==NULL) {
+ noma= add_material("RadioMat");
+ }
+ RG.matar[RG.totmat]= noma;
+ RG.totmat++;
+ }
+ }
+ else {
+ for(a=0; a<base->object->totcol; a++) {
+ if(a+RG.totmat>MAXMAT-1) break;
+ RG.matar[a+RG.totmat]= give_current_material(base->object, a+1);
+ }
+
+ RG.totmat+= base->object->totcol;
+ if (RG.totmat >= MAXMAT) {
+ RG.totmat = MAXMAT - 1;
+ }
+ }
+ }
+ }
+ base= base->next;
+ }
+
+ RG.cent[0]= (RG.min[0]+ RG.max[0])/2;
+ RG.cent[1]= (RG.min[1]+ RG.max[1])/2;
+ RG.cent[2]= (RG.min[2]+ RG.max[2])/2;
+ RG.size[0]= (RG.max[0]- RG.min[0]);
+ RG.size[1]= (RG.max[1]- RG.min[1]);
+ RG.size[2]= (RG.max[2]- RG.min[2]);
+ RG.maxsize= MAX3(RG.size[0],RG.size[1],RG.size[2]);
+
+ /* make patches */
+
+ RG.totelem= 0;
+ RG.totpatch= 0;
+ RG.totlamp= 0;
+ offs= 0;
+ matindex= 0;
+
+ base= (G.scene->base.first);
+ while(base) {
+ if( ((base)->flag & SELECT) && ((base)->lay & G.vd->lay) ) {
+ if(base->object->type==OB_MESH) {
+ ob= base->object;
+ me= ob->data;
+ mface= me->mface;
+
+ index= -1;
+
+ for(a=0; a<me->totface; a++, mface++) {
+ if(mface->v3) {
+
+ rp= callocPatch();
+ BLI_addtail(&(RG.patchbase), rp);
+ rp->from= ob;
+
+ if(mface->v4) rp->type= 4;
+ else rp->type= 3;
+
+ rp->first= rn= callocNode();
+
+ if(mface->flag & ME_SMOOTH) rp->f1= RAD_NO_SPLIT;
+
+ /* temporal: we store the venoco in the node */
+ rn->v1= (float *)(RG.verts+mface->v1+offs);
+ v1= (RG.verts+mface->v1+offs)->v;
+ rn->v2= (float *)(RG.verts+mface->v2+offs);
+ v2= (RG.verts+mface->v2+offs)->v;
+ rn->v3= (float *)(RG.verts+mface->v3+offs);
+ v3= (RG.verts+mface->v3+offs)->v;
+
+ if(mface->v4) {
+ rn->v4= (float *)(RG.verts+mface->v4+offs);
+ v4= (RG.verts+mface->v4+offs)->v;
+ }
+ rn->par= rp;
+ rn->f= RAD_PATCH; /* deze node is Patch */
+ rn->type= rp->type;
+
+ CalcNormFloat(v1, v2, v3, rp->norm);
+ if(rn->type==4) rp->area= AreaQ3Dfl(v1, v2, v3, v4);
+ else rp->area= AreaT3Dfl(v1, v2, v3);
+
+ rn->area= rp->area;
+
+ /* kleur en emit */
+ if(mface->mat_nr != index) {
+ index= mface->mat_nr;
+ ma= give_current_material(ob, index+1);
+ if(ma==0) ma= &defmaterial;
+ }
+ rp->ref[0]= ma->r;
+ rp->ref[1]= ma->g;
+ rp->ref[2]= ma->b;
+
+ if(ma->emit) RG.totlamp++;
+
+ rp->emit[0]= rp->emit[1]= rp->emit[2]= ma->emit;
+ rp->emit[0]*= rp->ref[0];
+ rp->emit[1]*= rp->ref[1];
+ rp->emit[2]*= rp->ref[2];
+
+ nodevert= (VeNoCo **)&(rn->v1);
+ for(b=0; b<rp->type; b++) {
+ rp->cent[0]+= (*nodevert)->v[0];
+ rp->cent[1]+= (*nodevert)->v[1];
+ rp->cent[2]+= (*nodevert)->v[2];
+ nodevert++;
+ }
+ rp->cent[0]/= (float)rp->type;
+ rp->cent[1]/= (float)rp->type;
+ rp->cent[2]/= (float)rp->type;
+
+ /* for reconstruction materials */
+ rp->matindex= matindex+mface->mat_nr;
+ if(rp->matindex>MAXMAT-1) rp->matindex= MAXMAT-1;
+
+ RG.totelem++;
+ RG.totpatch++;
+ }
+ }
+ offs+= me->totvert;
+
+ matindex+= base->object->totcol;
+ if(base->object->totcol==0) matindex++;
+ }
+ }
+ base= base->next;
+ }
+
+ splitconnected();
+ setedgepointers();
+
+ makeGlobalElemArray();
+ pseudoAmb();
+ rad_setlimits();
+}
+
+void setparelem(RNode *rn, RPatch *par)
+{
+
+ if(rn->down1) {
+ setparelem(rn->down1, par);
+ setparelem(rn->down2, par);
+ }
+ else {
+ rn->par= par;
+ }
+}
+
+void countelem(RNode *rn)
+{
+
+ if(rn->down1) {
+ countelem(rn->down1);
+ countelem(rn->down2);
+ }
+ else RG.totelem++;
+}
+
+void countglobaldata()
+{
+ /* telt aantal elements en patches*/
+ RPatch *rp;
+
+ RG.totelem= RG.totpatch= 0;
+
+ rp= RG.patchbase.first;
+ while(rp) {
+ RG.totpatch++;
+ countelem(rp->first);
+ rp= rp->next;
+ }
+}
+
+void addelem(RNode ***el, RNode *rn, RPatch *rp)
+{
+ if(rn->down1) {
+ addelem(el, rn->down1, rp);
+ addelem(el, rn->down2, rp);
+ }
+ else {
+ rn->par= rp;
+ **el= rn;
+ (*el)++;
+ }
+}
+
+void makeGlobalElemArray()
+{
+ /* always called when # of elements change */
+ RPatch *rp;
+ RNode **el;
+
+ countglobaldata();
+
+ if(RG.elem) MEM_freeN(RG.elem);
+ if(RG.totelem) {
+ el= RG.elem= MEM_mallocN(sizeof(void *)*RG.totelem, "makeGlobalElemArray");
+ }
+ else {
+ RG.elem= 0;
+ return;
+ }
+
+ /* recursief elements toevoegen */
+ rp= RG.patchbase.first;
+ while(rp) {
+ addelem(&el, rp->first, rp);
+ rp= rp->next;
+ }
+
+ /* formfactor array */
+ if(RG.formfactors) MEM_freeN(RG.formfactors);
+ if(RG.totelem)
+ RG.formfactors= MEM_mallocN(sizeof(float)*RG.totelem, "formfactors");
+ else
+ RG.formfactors= 0;
+}
+
+void splitpatch(RPatch *old) /* bij overflow gedurende shoot */
+{
+ RNode *rn;
+ float **fpp;
+ RPatch *rp;
+ int a;
+
+ rn= old->first;
+ if(rn->down1==0) return;
+ rn= rn->down1;
+
+ old->unshot[0]/=2.0;
+ old->unshot[1]/=2.0;
+ old->unshot[2]/=2.0;
+ setnodeflags(old->first, 2, 0);
+
+ rp= mallocPatch();
+ *rp= *old;
+ BLI_addhead(&RG.patchbase, rp);
+ rp->first= rn;
+ rp->area= rn->area;
+ rp->cent[0]= rp->cent[1]= rp->cent[2]= 0.0;
+ fpp= &(rn->v1);
+ for(a=0; a<rp->type; a++) {
+ rp->cent[0]+= (*fpp)[0];
+ rp->cent[1]+= (*fpp)[1];
+ rp->cent[2]+= (*fpp)[2];
+ fpp++;
+ }
+ rp->cent[0]/=(float)rp->type;
+ rp->cent[1]/=(float)rp->type;
+ rp->cent[2]/=(float)rp->type;
+
+ setparelem(rn, rp);
+
+ rn= old->first->down2;
+
+ rp= mallocPatch();
+ *rp= *old;
+ BLI_addhead(&RG.patchbase, rp);
+ rp->first= rn;
+ rp->area= rn->area;
+ rp->cent[0]= rp->cent[1]= rp->cent[2]= 0.0;
+ fpp= &(rn->v1);
+ for(a=0; a<rp->type; a++) {
+ rp->cent[0]+= (*fpp)[0];
+ rp->cent[1]+= (*fpp)[1];
+ rp->cent[2]+= (*fpp)[2];
+ fpp++;
+ }
+ rp->cent[0]/=(float)rp->type;
+ rp->cent[1]/=(float)rp->type;
+ rp->cent[2]/=(float)rp->type;
+
+ setparelem(rn, rp);
+
+ BLI_remlink(&RG.patchbase, old);
+ freePatch(old);
+}
+
+
+void addpatch(RPatch *old, RNode *rn)
+{
+ float **fpp;
+ RPatch *rp;
+ int a;
+
+ if(rn->down1) {
+ addpatch(old, rn->down1);
+ addpatch(old, rn->down2);
+ }
+ else {
+ rp= mallocPatch();
+ *rp= *old;
+ BLI_addhead(&RG.patchbase, rp);
+ rp->first= rn;
+
+ rp->area= rn->area;
+ rp->cent[0]= rp->cent[1]= rp->cent[2]= 0.0;
+ fpp= &(rn->v1);
+ for(a=0; a<rp->type; a++) {
+ rp->cent[0]+= (*fpp)[0];
+ rp->cent[1]+= (*fpp)[1];
+ rp->cent[2]+= (*fpp)[2];
+ fpp++;
+ }
+ rp->cent[0]/=(float)rp->type;
+ rp->cent[1]/=(float)rp->type;
+ rp->cent[2]/=(float)rp->type;
+
+ rn->par= rp;
+ }
+}
+
+void converttopatches()
+{
+ /* loopt patcheslijst af, als node gesubdivided: nieuwe patch */
+ RPatch *rp, *next;
+
+ rp= RG.patchbase.first;
+ while(rp) {
+ next= rp->next;
+ if(rp->first->down1) {
+ addpatch(rp, rp->first);
+ BLI_remlink(&RG.patchbase, rp);
+ freePatch(rp);
+ }
+ rp= next;
+ }
+
+}
+
+void subdiv_elements()
+{
+ RNode **el, *rn;
+ int a, toobig= 1;
+
+ rad_init_energy();
+
+ /* eerst maxsize elements */
+
+ while(toobig) {
+ toobig= 0;
+
+ el= RG.elem;
+ for(a=RG.totelem; a>0; a--, el++) {
+ rn= *el;
+ if( rn->totrad[0]==0.0 && rn->totrad[1]==0.0 && rn->totrad[2]==0.0) {
+ if(rn->area>RG.elemmin) {
+ subdivideNode(rn, 0);
+ if(rn->down1 ) {
+ toobig= 1;
+ if(rn->down1->area>RG.elemmin)
+ subdivideNode( rn->down1, 0);
+ if(rn->down2->area>RG.elemmin)
+ subdivideNode( rn->down2, 0);
+ }
+ }
+ }
+ }
+ if(toobig) makeGlobalElemArray();
+ }
+
+ el= RG.elem;
+ for(a=RG.totelem; a>0; a--, el++) {
+ rn= *el;
+ if( rn->totrad[0]==0.0 && rn->totrad[1]==0.0 && rn->totrad[2]==0.0) {
+ subdivideNode(rn, 0);
+ if( rn->down1 ) {
+ subdivideNode( rn->down1, 0);
+ subdivideNode( rn->down2, 0);
+ }
+ }
+ }
+ makeGlobalElemArray();
+}
+
+void subdividelamps()
+{
+ RPatch *rp, *next;
+
+ rp= RG.patchbase.first;
+ while(rp) {
+ next= rp->next;
+ if(rp->emit[0]!=0.0 || rp->emit[1]!=0.0 || rp->emit[2]!=0.0) {
+ subdivideNode( rp->first, 0);
+ if(rp->first->down1) {
+ subdivideNode(rp->first->down1, 0);
+ subdivideNode(rp->first->down2, 0);
+ }
+
+ addpatch(rp, rp->first);
+ BLI_remlink(&RG.patchbase, rp);
+ freePatch(rp);
+ }
+ rp= next;
+ }
+
+}
+
+void maxsizePatches()
+{
+ RPatch *rp;
+ int toobig= 1;
+
+ while(toobig) {
+ toobig= 0;
+ rp= RG.patchbase.first;
+ while(rp) {
+ if(rp->area>RG.patchmax) {
+ subdivideNode( rp->first, 0);
+ if(rp->first->down1) toobig= 1;
+ }
+ rp= rp->next;
+ }
+
+ if(toobig) converttopatches();
+ }
+
+ /* aantal lampen tellen */
+ rp= RG.patchbase.first;
+ RG.totlamp= 0;
+ while(rp) {
+ if(rp->emit[0]!=0.0 || rp->emit[1]!=0.0 || rp->emit[2]!=0.0) {
+ RG.totlamp++;
+ }
+ rp= rp->next;
+ }
+ makeGlobalElemArray();
+}
+
+
+