This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/radiosity/intern/source/radpreprocess.c
Kent Mein d0e346d544 updated .c files to include:
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

Just need to finish cpp files now :)

Kent
--
mein@cs.umn.edu
2002-11-25 12:02:15 +00:00

790 lines
15 KiB
C

/* ***************************************
*
* ***** 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"
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
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();
}