diff options
author | Hans Lambermont <hans@lambermont.dyndns.org> | 2002-10-12 15:37:38 +0400 |
---|---|---|
committer | Hans Lambermont <hans@lambermont.dyndns.org> | 2002-10-12 15:37:38 +0400 |
commit | 12315f4d0e0ae993805f141f64cb8c73c5297311 (patch) | |
tree | 59b45827cd8293cfb727758989c7a74b40183974 /source/blender/radiosity/intern |
Initial revisionv2.25
Diffstat (limited to 'source/blender/radiosity/intern')
-rw-r--r-- | source/blender/radiosity/intern/Makefile | 37 | ||||
-rw-r--r-- | source/blender/radiosity/intern/source/Makefile | 60 | ||||
-rw-r--r-- | source/blender/radiosity/intern/source/raddisplay.c | 527 | ||||
-rw-r--r-- | source/blender/radiosity/intern/source/radfactors.c | 956 | ||||
-rw-r--r-- | source/blender/radiosity/intern/source/radio.c | 379 | ||||
-rw-r--r-- | source/blender/radiosity/intern/source/radnode.c | 1095 | ||||
-rw-r--r-- | source/blender/radiosity/intern/source/radpostprocess.c | 871 | ||||
-rw-r--r-- | source/blender/radiosity/intern/source/radpreprocess.c | 787 |
8 files changed, 4712 insertions, 0 deletions
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(); +} + + + |