Initial revision

This commit is contained in:
Hans Lambermont
2002-10-12 11:37:38 +00:00
commit 12315f4d0e
1699 changed files with 444708 additions and 0 deletions

View File

@@ -0,0 +1,37 @@
#
# $Id$
#
# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. The Blender
# Foundation also sells licenses for use in proprietary software under
# the Blender License. See http://www.blender.org/BL/ for information
# about this.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
# All rights reserved.
#
# The Original Code is: all of this file.
#
# Contributor(s): none yet.
#
# ***** END GPL/BL DUAL LICENSE BLOCK *****
#
# Makes module object directory and bounces make to subdirectories.
SOURCEDIR = source/blender/radiosity
DIRS = intern
include nan_subdirs.mk

View File

@@ -0,0 +1,170 @@
/* ***************************************
radio.h nov/dec 1992
revised for Blender may 1999
$Id$
***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. The Blender
Foundation also sells licenses for use in proprietary software under
the Blender License. See http://www.blender.org/BL/ for information
about this.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
All rights reserved.
The Original Code is: all of this file.
Contributor(s): none yet.
***** END GPL/BL DUAL LICENSE BLOCK *****
*/
#ifndef RADIO_H
#define RADIO_H
#define RADIO_H
/* type include */
#include "radio_types.h"
extern RadGlobal RG;
/* radfactors.c */
extern float calcStokefactor(RPatch *shoot, RPatch *rp, RNode *rn, float *area);
extern void calcTopfactors(void);
void calcSidefactors(void);
extern void initradiosity(void);
extern void rad_make_hocos(RadView *vw);
extern void hemizbuf(RadView *vw);
extern int makeformfactors(RPatch *shoot);
extern void applyformfactors(RPatch *shoot);
extern RPatch *findshootpatch(void);
extern void setnodeflags(RNode *rn, int flag, int set);
extern void backface_test(RPatch *shoot);
extern void clear_backface_test(void);
extern void progressiverad(void);
extern void minmaxradelem(RNode *rn, float *min, float *max);
extern void minmaxradelemfilt(RNode *rn, float *min, float *max, float *errmin, float *errmax);
extern void subdivideshootElements(int it);
extern void subdivideshootPatches(int it);
extern void inithemiwindows(void);
extern void closehemiwindows(void);
void rad_init_energy(void);
/* radio.c */
void freeAllRad(void);
int rad_phase(void);
void rad_status_str(char *str);
void rad_printstatus(void);
void rad_setlimits(void);
void set_radglobal(void);
void add_radio(void);
void delete_radio(void);
int rad_go(void);
void rad_subdivshootpatch(void);
void rad_subdivshootelem(void);
void rad_limit_subdivide(void);
/* radnode.c */
extern void setnodelimit(float limit);
extern float *mallocVert(void);
extern float *callocVert(void);
extern void freeVert(float *vert);
extern RNode *mallocNode(void);
extern RNode *callocNode(void);
extern void freeNode(RNode *node);
extern void freeNode_recurs(RNode *node);
extern RPatch *mallocPatch(void);
extern RPatch *callocPatch(void);
extern void freePatch(RPatch *patch);
extern void replaceAllNode(RNode *, RNode *);
extern void replaceAllNodeInv(RNode *neighb, RNode *old);
extern void replaceAllNodeUp(RNode *neighb, RNode *old);
extern void replaceTestNode(RNode *, RNode **, RNode *, int , float *);
extern void free_fastAll(void);
/* radnode.c */
extern void start_fastmalloc(char *str);
extern int setvertexpointersNode(RNode *neighb, RNode *node, int level, float **v1, float **v2);
extern float edlen(float *v1, float *v2);
extern void deleteNodes(RNode *node);
extern void subdivideTriNode(RNode *node, RNode *edge);
extern void subdivideNode(RNode *node, RNode *edge);
extern int comparelevel(RNode *node, RNode *nb, int level);
/* radpreprocess.c */
extern void splitconnected(void);
extern int vergedge(const void *v1,const void *v2);
extern void addedge(float *v1, float *v2, EdSort *es);
extern void setedgepointers(void);
extern void rad_collect_meshes(void);
extern void countelem(RNode *rn);
extern void countglobaldata(void);
extern void addelem(RNode ***el, RNode *rn, RPatch *rp);
extern void makeGlobalElemArray(void);
extern void remakeGlobaldata(void);
extern void splitpatch(RPatch *old);
extern void addpatch(RPatch *old, RNode *rn);
extern void converttopatches(void);
extern void make_elements(void);
extern void subdividelamps(void);
extern void maxsizePatches(void);
extern void subdiv_elements(void);
/* radpostprocess.c */
void addaccu(register char *z, register char *t);
void addaccuweight(register char *z, register char *t, int w);
void triaweight(Face *face, int *w1, int *w2, int *w3);
void init_face_tab(void);
Face *addface(void);
void makeface(float *v1, float *v2, float *v3, float *v4, RNode *rn);
void anchorQuadface(RNode *rn, float *v1, float *v2, float *v3, float *v4, int flag);
void anchorTriface(RNode *rn, float *v1, float *v2, float *v3, int flag);
float *findmiddlevertex(RNode *node, RNode *nb, float *v1, float *v2);
void make_face_tab(void);
void filterFaces(void);
void calcfiltrad(RNode *rn, float *cd);
void filterNodes(void);
void removeEqualNodes(short limit);
void rad_addmesh(void);
void rad_replacemesh(void);
/* raddisplay.c */
extern char calculatecolor(float col);
extern void make_node_display(void);
extern void drawnodeWire(RNode *rn);
extern void drawsingnodeWire(RNode *rn);
extern void drawnodeSolid(RNode *rn);
extern void drawnodeGour(RNode *rn);
extern void drawpatch(RPatch *patch, unsigned int col);
extern void drawnode_ext(RNode *rn, unsigned int col);
extern void drawOverflowElem(void);
extern void drawfaceGour(Face *face);
extern void drawfaceSolid(Face *face);
extern void drawfaceWire(Face *face);
extern void drawsquare(float *cent, float size, short cox, short coy);
extern void drawlimits(void);
extern void setcolNode(RNode *rn, unsigned int *col);
extern void pseudoAmb(void);
extern void rad_forcedraw(void);
extern void drawpatch_ext(RPatch *patch, unsigned int col);
extern void RAD_drawall(int depth_is_on);
#endif /* RADIO_H */

View File

@@ -0,0 +1,174 @@
/*
* radio_types.h
*
* $Id$
*
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. The Blender
* Foundation also sells licenses for use in proprietary software under
* the Blender License. See http://www.blender.org/BL/ for information
* about this.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
/* #include "misc_util.h" */ /* for listbase...*/
#ifndef RADIO_TYPES_H
#define RADIO_TYPES_H
#include "DNA_listBase.h"
#include "DNA_material_types.h"
#define DTWIRE 0
#define DTGOUR 2
#define DTSOLID 1
#define PI M_PI
#define RAD_MAXFACETAB 1024
#define RAD_NEXTFACE(a) if( ((a) & 1023)==0 ) face= RG.facebase[(a)>>10]; else face++;
/* RG.phase */
#define RAD_SHOOTE 1
#define RAD_SHOOTP 2
#define RAD_SOLVE 3
typedef struct RadView {
float cam[3], tar[3], up[3];
float wx1, wx2, wy1, wy2;
float mynear, myfar;
float viewmat[4][4], winmat[4][4];
unsigned int *rect, *rectz;
short rectx, recty;
int wid;
} RadView;
/* rn->f */
#define RAD_PATCH 1
#define RAD_SHOOT 2
#define RAD_SUBDIV 4
#define RAD_BACKFACE 8
typedef struct RNode { /* lengte: 76 */
struct RNode *down1, *down2, *up;
struct RNode *ed1, *ed2, *ed3, *ed4;
struct RPatch *par;
char lev1, lev2, lev3, lev4; /* edgelevels */
short type; /* type: 4==QUAD, 3==TRIA */
short f;
float *v1, *v2, *v3, *v4;
float totrad[3], area;
unsigned int col;
} RNode;
typedef struct Elem { /* lengte: 44 */
struct RPatch *par;
short type; /* type: 4==QUAD, 3==TRIA */
short f; /* bit 0: patch, bit 1: shootelement */
float *v1, *v2, *v3, *v4;
float totrad[3], area;
unsigned int col;
} Elem;
typedef struct Face { /* lengte: 24 */
float *v1, *v2, *v3, *v4;
unsigned int col, matindex;
} Face;
/* rp->f1 */
#define RAD_NO_SPLIT 1
typedef struct RPatch {
struct RPatch *next, *prev;
RNode *first; /* first node==patch */
struct Object *from;
int type; /* 3: TRIA, 4: QUAD */
short f, f1; /* flags f: als node, alleen subdiv */
float ref[3], emit[3], unshot[3];
float cent[3], norm[3];
float area;
int matindex;
} RPatch;
typedef struct VeNoCo { /* nodig voor splitconnected */
struct VeNoCo *next;
float *v;
float *n;
float *col;
int flag;
} VeNoCo;
typedef struct EdSort { /* sorteren edges */
float *v1, *v2;
RNode *node;
int nr;
} EdSort;
typedef struct {
struct Radio *radio;
unsigned int *hemibuf;
struct ListBase patchbase;
int totpatch, totelem, totvert, totlamp;
RNode **elem; /* globaal array van alle pointers */
VeNoCo *verts; /* tijdelijk vertices van patches */
float *formfactors; /* een factor per element */
float *topfactors, *sidefactors; /* LUT voor delta's */
int *index; /* LUT voor bovenstaande LUT */
Face **facebase;
int totface;
float min[3], max[3], size[3], cent[3]; /* world */
float maxsize, totenergy;
float patchmin, patchmax;
float elemmin, elemmax;
float radfactor, lostenergy, igamma; /* radfac zit in button, radfactor wordt berekend */
int phase;
/* to preserve materials as used before, max 16 */
Material *matar[MAXMAT];
int totmat;
/* this part is a copy of struct Radio */
short hemires, maxiter;
short drawtype, flag; /* bit 0 en 1: limits laten zien */
short subshootp, subshoote, nodelim, maxsublamp;
int maxnode;
float convergence;
float radfac, gamma; /* voor afbeelden */
} RadGlobal;
#endif /* radio_types.h */

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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 */
}

File diff suppressed because it is too large Load Diff

View File

@@ -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();
}

View File

@@ -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();
}