Fxfire/000755 000316 000311 00000000000 06114643646 012133 5ustar00wrzlgup000000 000000 Fxfire/DiscoMesher/000755 000316 000311 00000000000 06114643462 014334 5ustar00wrzlgup000000 000000 Fxfire/DiscoMesher/Makefile000644 000316 000311 00000001157 06114617245 016000 0ustar00wrzlgup000000 000000 ####################################################################### ## Makefile ## ## ## ## (c) 1992-1994 by Wolfgang Stuerzlinger (wRZL) ## ## This code may be used only for non-commercial purposes ! ## ## Coauthorship of any publications using this code is claimed. ## ####################################################################### OBJ=geom.o disc.o dt.o CC=gcc CFLAGS=-g -J -DASCII -Wall main.exe: $(OBJ) gcc -g -o main.exe *.o -lm -ds en >nul ## ## ## ## (c) 1992-1994 by Wolfgang Stuerzlinger (wRZL) ## ## This code may be used only for non-commercial purposes ! ## ## Coauthorship of any publications using this code is claimed. ## ####################################################################### OBJ=geoFxfire/DiscoMesher/disc.c000644 000316 000311 00000030616 06114617245 015430 0ustar00wrzlgup000000 000000 /**********************************************************************/ /* disco.c */ /* */ /* (c) 1992-1994 by Wolfgang Stuerzlinger (wRZL) */ /* This code may be used only for non-commercial purposes ! */ /* Coauthorship of any publications using this code is claimed. */ /**********************************************************************/ #include #include #include #include #include #include "geom.h" #include "disc.h" /****************************************************************************/ static int ray_intersect_plane(TVector3f *normal,double ndotp,TEdge *edge, double *t) { double ndotd; ndotd = DotVector(*normal,edge->direction); if (ndotd == 0.0) { *t = 1E30; /* far far away */ return(0); } *t = (ndotp - DotVector(*normal,edge->origin)) / ndotd; return(1); } /****************************************************************************/ static void insert_seg2(TDiscL2 **disc2d,TPoint2f *point1,TPoint2f *point2, DISCONTINUITY d,int side) { int project; double temp,np; TVector2f normal,dir; TDiscoSeg *seg; SubVector2(dir,*point2,*point1); NormalizeVector2(temp,dir); if (temp == 0.0) /* zero vector */ return; TurnVector2Left2(normal,dir); np = DotVector2(normal,*point1); seg = (TDiscoSeg *) calloc(1,sizeof(TDiscoSeg)); seg->discontinuity = d; seg->point[0] = *point1; seg->point[1] = *point2; project = FindProject2(normal); seg->t[0] = Projectd1(project,*point1); seg->t[1] = Projectd1(project,*point2); seg->side = side; if (seg->t[0] > seg->t[1]) { /* ensure correct order */ SWAP(seg->t[0],seg->t[1],temp); SWAP(seg->point[0],seg->point[1],dir); seg->side = -seg->side; } if (*disc2d == NULL) { *disc2d = (TDiscL2 *)calloc(1,sizeof(TDiscL2)); (*disc2d)->project = project; } seg->next = (*disc2d)->seg; (*disc2d)->seg = seg; } void free_disco_2d(TDiscL2 *disc2d) { TDiscoSeg *seg,*next; if (disc2d == NULL) return; seg = disc2d->seg; while (seg != NULL) { next = seg->next; free(seg); seg = next; } free(disc2d); } /****************************************************************************/ static int calc_side3d(TPlane *plane,TEdge *edge) { double ndotd,ndoto,t; ndotd = DotVector(plane->normal,edge->direction); ndoto = DotVector(plane->normal,edge->origin); if (ndotd != 0.0) { t = (plane->np - ndoto) / ndotd; if (t <= 0.0) { /* we are only on 1 side! */ if (ndotd > 0.0) return(1); /* towards front */ else return(-1); /* towards back */ } } else { if (ndoto > plane->np) /* lies before */ return(1); else if (ndoto < plane->np) /* lies behind */ return(-1); else /* ray in the plane */ return(0); } return(2); /* on both sides */ } static void insert_bsp(TBSP **bsp,TVector3f *normal,double np,TWedge *wedge) { int side1,side2; if (*bsp == NULL) { *bsp = (TBSP *)calloc(1,sizeof(TBSP)); (*bsp)->plane.normal = *normal; (*bsp)->plane.np = np; (*bsp)->discontinuity = D2; (*bsp)->wedge[0] = wedge; (*bsp)->nWedge = 1; return; } side1 = calc_side3d(&(*bsp)->plane,wedge->edge[0]); side2 = calc_side3d(&(*bsp)->plane,wedge->edge[1]); if (side1 == 2 || side2 == 2) { /* different sides */ insert_bsp(&(*bsp)->front,normal,np,wedge); insert_bsp(&(*bsp)->back,normal,np,wedge); } else if (side1 == 0 && side2 == 0) { /* new wedge */ if ((*bsp)->nWedge > MAXWEDGE) printf("ERROR"); (*bsp)->wedge[(*bsp)->nWedge] = wedge; (*bsp)->nWedge++; } else if (side1 == 0 || side2 == 0) { /* one is in */ if (side1 > 0 || side2 > 0) /* other is front */ insert_bsp(&(*bsp)->front,normal,np,wedge); else /* other is back */ insert_bsp(&(*bsp)->back,normal,np,wedge); } else if (side1 != side2) { /* different sides */ insert_bsp(&(*bsp)->front,normal,np,wedge); insert_bsp(&(*bsp)->back,normal,np,wedge); } else if (side1 > 0) /* front only */ insert_bsp(&(*bsp)->front,normal,np,wedge); else /* back only */ insert_bsp(&(*bsp)->back,normal,np,wedge); } static void gen_wedge(TBSP **bsp,TPoint3f *point,TEdge *edge0,TEdge *edge1, TWedge *wedge) { double temp,np; TVector3f normal; CrossVector(normal,edge0->direction,edge1->direction); NormalizeVector(temp,normal); np = DotVector(normal,*point); wedge->edge[0] = edge0; wedge->edge[1] = edge1; wedge->discontinuity = D2; insert_bsp(bsp,&normal,np,wedge); } /****************************************************************************/ TDisco *calc_disco_mesh(TPolygon *shooter,TPolygon *shader) { int i,j,w,idx,r1,r2; double temp; TDisco *disco; temp = DotVector(shooter->normal,shader->normal); /* same plane? */ if (temp == 1.0 && shooter->ndotp == shader->ndotp) return(NULL); if (temp == -1.0 && shooter->ndotp == -shader->ndotp) return(NULL); disco = (TDisco *)calloc(1,sizeof(TDisco)); disco->nEdges = shooter->n * shader->n; disco->edge = (TEdge *)calloc(disco->nEdges,sizeof(TEdge)); disco->nWedges = disco->nEdges * 2; disco->wedge = (TWedge *)calloc(disco->nWedges,sizeof(TWedge)); /* generate all rays */ for (i = 0; i < shooter->n; i++) { for (j = 0; j < shader->n; j++) { idx = i * shader->n + j; disco->edge[idx].origin = shader->vert[j]; SubVector(disco->edge[idx].direction,shader->vert[j], shooter->vert[i]); NormalizeVector(temp,disco->edge[idx].direction); } } /* now generate all EV wedges */ w = 0; for (i = 0; i < shooter->n; i++) { for (j = 0; j < shader->n; j++) { r1 = i * shader->n + j; r2 = ((i + 1) % shooter->n) * shader->n + j; gen_wedge(&disco->bsp,&shader->vert[j], &disco->edge[r1],&disco->edge[r2],&disco->wedge[w]); w++; } } /* now generate all VE wedges */ for (i = 0; i < shooter->n; i++) { for (j = 0; j < shader->n; j++) { r1 = i * shader->n + j; r2 = i * shader->n + ((j + 1) % shader->n); gen_wedge(&disco->bsp,&shader->vert[j], &disco->edge[r1],&disco->edge[r2],&disco->wedge[w]); w++; } } return(disco); } static void free_bsp(TBSP *bsp) { if (bsp == NULL) return; free_bsp(bsp->front); free_bsp(bsp->back); free(bsp); } void free_disco_mesh(TDisco *disco) { free_bsp(disco->bsp); free(disco->edge); free(disco->wedge); free(disco); } /****************************************************************************/ static void calc_wedges(TBSP *bsp,TPolygon *pp) { int i,behind,front; double np; if (bsp == NULL) return; behind = 0; front = 0; for (i = 0; i < pp->n; i++) { np = DotVector(bsp->plane.normal,pp->vert[i]); if (np < bsp->plane.np) behind++; else if (np > bsp->plane.np) front++; } if (front == pp->n) /* all before */ calc_wedges(bsp->front,pp); else if (behind == pp->n) calc_wedges(bsp->back,pp); else { calc_wedges(bsp->front,pp); calc_wedges(bsp->back,pp); for (i = 0; i < bsp->nWedge; i++) { bsp->wedge[i]->marked = 1; bsp->wedge[i]->edge[0]->marked = 1; bsp->wedge[i]->edge[1]->marked = 1; } } } TDiscL2 *construct_disco(TDisco *disco,TPolygon *pp,TDiscL2 *disc2d) { int i; double t; TVector3f temp; DISCONTINUITY disc; for (i = 0; i < disco->nWedges; i++) disco->wedge[i].marked = 0; calc_wedges(disco->bsp,pp); for (i = 0; i < disco->nEdges; i++) { if (! disco->edge[i].marked) continue; if (DistPt2Plane(disco->edge[i].origin,pp->normal,pp->ndotp) == 0.0) disco->edge[i].inplane = 1; else disco->edge[i].inplane = 0; (void) ray_intersect_plane(&pp->normal,pp->ndotp,&disco->edge[i],&t); temp = disco->edge[i].direction; ScaleVector(temp,t); AddVector(disco->edge[i].intersection,temp,disco->edge[i].origin); Project2d(pp->project,disco->edge[i].intersection, disco->edge[i].intersect2); } for (i = 0; i < disco->nWedges; i++) { if (! disco->wedge[i].marked) continue; disc = disco->wedge[i].discontinuity; if (disco->wedge[i].edge[0]->inplane && disco->wedge[i].edge[1]->inplane) disc = D0; insert_seg2(&disc2d,&disco->wedge[i].edge[0]->intersect2, &disco->wedge[i].edge[1]->intersect2,disc,0); } return(disc2d); } /****************************************************************************/ int find_d0_segments(TPolygon *thePoly,TPolygon *poly,TDiscL2 **disc2d) { int i,side; double d; TPoint3f *p1,*p2; TPoint2f d1,d2,norm,v; d = DotVector(thePoly->normal,poly->normal); if (d == 1.0 || d == -1.0) /* same plane */ return(0); p1 = NULL; for (i = 0; i < poly->n; i++) { if (Inplane(poly->vert[i],thePoly->normal,thePoly->ndotp)) { p1 = &poly->vert[i]; break; } } if (p1 == NULL) /* none found */ return(0); p2 = &poly->vert[(i + 1) % poly->n]; if (! Inplane(*p2,thePoly->normal,thePoly->ndotp)) { if (i != 0) { printf("1+"); /* only 1 vertex inplane? */ return(0); } p2 = &poly->vert[poly->n - 1]; /* p1 = p[0]! */ if (! Inplane(*p2,thePoly->normal,thePoly->ndotp)) { printf("1-"); /* only 1 vertex inplane? */ return(0); } } /* in p1/p2 we have the possible candidate line now! */ Project2d(thePoly->project,*p1,d1); Project2d(thePoly->project,*p2,d2); Project2d(thePoly->project,poly->normal,norm); SubVector2(v,d2,d1); if (DotVector2(norm,v) < 0.0) side = 1; /* right */ else side = -1; /* left */ insert_seg2(disc2d,&d1,&d2,D0,side); return(1); } /****************************************************************************/ int clip_segments(TPoly2 *pp,TDiscL2 *disc2d,TSegment *segs) { int i,flag,idx1,idx2,nSeg; double eps; TDiscoSeg *seg; nSeg = 0; if (disc2d == NULL) return(nSeg); eps = 1.0E-6; /* FIXME: should depend on polygon size */ seg = disc2d->seg; while (seg != NULL) { flag = 0; for (i = 0; i < pp->n; i++) { if (PointNear2(pp->vert[i],seg->point[0],eps)) { idx1 = i; flag++; } else if (PointNear2(pp->vert[i],seg->point[1],eps)) { idx2 = i; flag++; } } if (flag >= 2) { if (idx1 < idx2) idx1 = idx2 - idx1; else idx1 = idx1 - idx2; if (idx1 != 1 && idx1 != pp->n - 1) nSeg++; /* not between adj vertices */ } else { segs[nSeg].point1 = seg->point[0]; segs[nSeg].point2 = seg->point[1]; segs[nSeg].discontinuity = seg->discontinuity; if (clip2poly2(pp,&segs[nSeg].point1,&segs[nSeg].point2)) { flag = 0; for (i = 0; i < pp->n; i++) { if (PointNear2(pp->vert[i],segs[nSeg].point1,eps)) { idx1 = i; flag++; } else if (PointNear2(pp->vert[i],segs[nSeg].point2,eps)) { idx2 = i; flag++; } } if (flag >= 2) { if (idx1 < idx2) idx1 = idx2 - idx1; else idx1 = idx1 - idx2; if (idx1 != 1 && idx1 != pp->n - 1) nSeg++; /* not between adj vertices */ } else nSeg++; } } seg = seg->next; } return(nSeg); } int inside_d0(TDiscL2 *disc2d,TPoint2f *point2) { double side,t; TDiscoSeg *seg; if (disc2d == NULL || disc2d->seg == NULL) return(0); seg = disc2d->seg; if (isonline(point2,&seg->point[0],&seg->point[1])) return(1); side = calc_side(&seg->point[0],&seg->point[1],point2); t = Projectd1(disc2d->project,*point2); /* FIXME */ while (seg != NULL) { if (seg->t[0] <= t && t <= seg->t[1]) { if ((seg->side > 0.0 && side < 0.0) || (seg->side < 0.0 && side > 0.0)) return(0); } seg = seg->next; } return(1); } #define BORDER_SHIFT 1E-4 int move_d0(TPolygon *poly,TDiscL2 *disc2d,TPoint2f *point2,int inside, TVector2f *shift) { int moved; double dist,side,t,np,reflen,len,shiftlen; TDiscoSeg *seg; TVector2f line,norm,move; if (disc2d == NULL) return(0); reflen = 1.0; /* FIXME: should depend on polygon size */ InitPoint2(*shift,0.0,0.0); moved = 0; seg = disc2d->seg; t = Projectd1(disc2d->project,*point2); /* FIXME */ while (seg != NULL) { SubVector2(line,seg->point[1],seg->point[0]); NormalizeVector2(side,line); TurnVector2Left2(norm,line); np = DotVector2(norm,seg->point[0]); dist = DistPt2Line(*point2,norm,np); len = reflen * (seg->side == inside) ? -BORDER_SHIFT : BORDER_SHIFT; if (dist >= len) { /* too near */ if (seg->t[0] <= t && t <= seg->t[1]) { shiftlen = len - dist; move = norm; ScaleVector2(move,shiftlen); AddVector2(*shift,move,*shift); moved = 1; } } seg = seg->next; } return(moved); } (line,seg->point[1],seg->point[0]); NormalizeVector2(side,line); TurnVector2Left2(norm,line); np = DotVectorFxfire/DiscoMesher/disc.h000644 000316 000311 00000003477 06114617245 015442 0ustar00wrzlgup000000 000000 /**********************************************************************/ /* disc.h */ /* */ /* (c) 1992-1994 by Wolfgang Stuerzlinger (wRZL) */ /* This code may be used only for non-commercial purposes ! */ /* Coauthorship of any publications using this code is claimed. */ /**********************************************************************/ #define MAXWEDGE 4 #define MAXSEGS 256 typedef enum DISCONTINUITY { NONE, D0, D1, D2, DINF } DISCONTINUITY; typedef struct TSegment { DISCONTINUITY discontinuity; TPoint2f point1; TPoint2f point2; } TSegment; typedef struct TEdge { char marked; char inplane; TPoint3f origin; /* edge origin */ TVector3f direction; /* edge direction */ TPoint3f intersection; TPoint2f intersect2; } TEdge; typedef struct TWedge { DISCONTINUITY discontinuity; char marked; TEdge *edge[2]; } TWedge; typedef struct TBSP { DISCONTINUITY discontinuity; int nWedge; TPlane plane; TWedge *wedge[MAXWEDGE]; struct TBSP *front; struct TBSP *back; } TBSP; typedef struct TDisco { int nWedges; TWedge *wedge; int nEdges; TEdge *edge; TBSP *bsp; } TDisco; typedef struct TDiscoSeg { DISCONTINUITY discontinuity; int side; TPoint2f point[2]; double t[2]; struct TDiscoSeg *next; } TDiscoSeg; typedef struct TDiscL2 { char project; TLine line; TDiscoSeg *seg; } TDiscL2; /* disc.c */ TDisco *calc_disco_mesh(TPolygon *shooter1,TPolygon *shader); TDiscL2 *construct_disco(TDisco *disco,TPolygon *pp, TDiscL2 *disc2d); int clip_segments(TPoly2 *pp,TDiscL2 *disc2d,TSegment *segs); void free_bsp2(TDiscL2 *disc2d); void free_disco_mesh(TDisco *disco); int find_d0_segments(TPolygon *thePoly,TPolygon *poly,TDiscL2 **disc2d); e; TPoint2f point[2]; double t[2]; struct TDiscoSeg *next; } TDiscoSeg; typedef struct TDiscL2 { char project; TLine line; TDiscoSeg *seg; } TDiscL2; /* disc.c */ TDisco *calc_disco_mFxfire/DiscoMesher/disco.txt000644 000316 000311 00000004406 06114617245 016202 0ustar00wrzlgup000000 000000 /**********************************************************************/ /* disco.txt */ /* */ /* (c) 1992-1994 by Wolfgang Stuerzlinger (wRZL) */ /* This code may be used only for non-commercial purposes ! */ /* Coauthorship of any publications using this code is claimed. */ /**********************************************************************/ TDisco *calc_disco_mesh(TPolygon *shooter,TPolygon *shader); Given a polygon 'shooter' and a polygon 'shader' constructs and returns the corresponding 3d-discontinuity structure (wedges). TDiscL2 *construct_disco(TDisco *disco,TPolygon *pp,TDiscL2 *disc2d); Given a 3d-discontinuity structure 'disco' and a polygon 'pp' accumulates the 2d-discontinuities in disc2d. The 2d-discontinuities are not (!) clipped to the polygon. int clip_segments(TPoly2 *pp,TDiscL2 *disc2d,TSegment *segs); Clips the 2d-discontinuties 'disc2d' to the 2d-polygon 'pp'. Result is are the discontinuity-segments in the array 'segs'. The number of discontinuity-segments is returned. void free_disco_mesh(TDisco *disco); void free_disco_2d(TDiscL2 *disc2d); Frees the memory allocated by calc_disco_mesh or construct_disco. Example: TDisco *disc3d[..]; TDiscL2 *disc2d; TPolygon poly3d,shooter,shader; TPoly2 poly2d; int nSeg; TSegment segs[...]; /* construct 2d polygon from 3d polygon */ FindProject(poly3d.normal,poly3d.project); poly2d.n = poly3d.nPts; for (i = 0; i < poly3d.nPts; i++) Project2d(poly3d.project,poly3d.vert[i],poly2d.vert[i]; /* construct all 3d-discontinuities caused by shooter */ for (all shader) disc3d[shader] = calc_disco_mesh(&shooter,&shader); /* construct all 2d-discos from all 3d-discos for a polygon 'poly3d' and clip the 2d-discos to the polygon */ disc2d = NULL; for (all shader) disc2d = construct_disco(disc3d[shader],&poly3d,disc2d); nSeg = clip_segments(poly2d,disc2d,segs); int find_d0_segments(TPolygon *thePoly,TPolygon *poly,TDiscL2 **disc2d); Find all D0 segments caused by the polygon 'poly' on the polygon 'thePoly'. The result is accumulated in disc2d. Example: disc2d = NULL; for (all polygons) (void) find_d0_segments(thePoly,poly,&disc2d); l 2d-discos from all 3d-discos for a polygon 'poly3d' and clip the 2d-discos to the polygon */ disc2d = NULL; for (all shader) disc2d = construct_disco(disc3d[shader],&poly3d,disc2d); nSeg = clip_segments(poly2d,disc2d,segs); int find_d0_segmenFxfire/DiscoMesher/dt.c000644 000316 000311 00000054451 06114624014 015110 0ustar00wrzlgup000000 000000 /**********************************************************************/ /* Delaunay-Triangulation-Module */ /* */ /* (c) 1992-1994 by Wolfgang Stuerzlinger (wRZL) */ /* thanks to Dani Lischinski for major help/tips */ /* This code may be used only for non-commercial purposes ! */ /* Coauthorship of any publications using this code is claimed. */ /**********************************************************************/ #include "dt.h" #include #include #include #include #include #define SITEALLOC 1000 static TRIANG *_surf; /******************************** geometr2 ************************/ #define v2length_2(v) ((v).x * (v).x + (v).y * (v).y) #define v2dist_2(v1,v2) ((v1).x - (v2).x) * ((v1).x - (v2).x) + \ ((v1).y - (v2).y) * ((v1).y - (v2).y) #define v2dot(v1,v2) ((v1).x * (v2).x + (v1).y * (v2).y) #define v2cross(v1,v2) ((v1).x * (v2).y - (v1).y * (v2).x) #define v2midpnt(v1,v2,v) \ { \ (v).x = ((v1).x + (v2).x) * 0.5; \ (v).y = ((v1).y + (v2).y) * 0.5; \ } #define v2sub(v1,v2,v) \ { \ (v).x = (v1).x - (v2).x; \ (v).y = (v1).y - (v2).y; \ } #define v2add(v1,v2,v) \ { \ (v).x = (v1).x + (v2).x; \ (v).y = (v1).y + (v2).y; \ } #define v2turnl(v1,v) \ { \ (v).x = -(v1).y; \ (v).y = (v1).x; \ } #define v2turnr(v1,v) \ { \ (v).x = (v1).y; \ (v).y = -(v1).x; \ } #define v2divk(v,k) \ { \ (v).x /= (k); \ (v).y /= (k); \ } #define v2normalize(v) \ { \ FLOAT _len = v2length_2(v); \ \ if (_len != 0.0) \ { \ _len = sqrt(_len); \ v2divk(v,_len); \ } \ } #define v2scale(v,s) \ { \ (v).x *= (s); \ (v).y *= (s); \ } #define v2addto(v,v1) \ { \ (v).x += (v1).x; \ (v).y += (v1).y; \ } #define incircle(a,b,c,d) (distcircle(a,b,c,d) > 0.0) DOUBLE distcircle(PNT2 *a,PNT2 *b,PNT2 *c,PNT2 *d) { DOUBLE az,bz,cz,dz,result; az = a->x * a->x + a->y * a->y; bz = b->x * b->x + b->y * b->y; cz = c->x * c->x + c->y * c->y; dz = d->x * d->x + d->y * d->y; result = ( a->y * (bz * c->x + cz * d->x + b->x * dz) + az * (b->x * c->y + b->y * d->x + c->x * d->y) + a->x * (b->y * cz + bz * d->y + c->y * dz) + bz * c->y * d->x + b->x * cz * d->y + b->y * c->x * dz ) - ( az * (b->y * c->x + c->y * d->x + b->x * d->y) + a->x * (bz * c->y + cz * d->y + b->y * dz) + a->y * (b->x * cz + c->x * dz + bz * d->x) + b->y * cz * d->x + bz * c->x * d->y + b->x * c->y * dz ); return(result); } #define calc_ccw(a,b,c) \ ((a->x - c->x) * (b->y - c->y) - (b->x - c->x) * (a->y - c->y)) DOUBLE ccw(PNT2 *a,PNT2 *b,PNT2 *c) /* > 0.0 iff A, B, C form a counterclockwise oriented triangle */ { DOUBLE result; if ((a->x == b->x && a->y == b->y) || (a->x == c->x && a->y == c->y) || (b->x == c->x && b->y == c->y)) return(0.0); result = calc_ccw(a,b,c); if (fabs(result) < 1.0E-10) { /* we need a more stable result */ result += calc_ccw(a,c,b); result += calc_ccw(b,a,c); result += calc_ccw(b,c,a); result += calc_ccw(c,a,b); result += calc_ccw(c,b,a); result /= 6.0; } if (result == -0.0) result = 0.0; return(result); } #define LINE_EPS 1E-6 BOOLEAN approxonline(PNT2 *x,PNT2 *a,PNT2 *b) /* return TRUE if point in LINE_EPS region of line */ { DOUBLE len1,len2,len3,la,lb,lc,dist; VEC2 t; len1 = v2dist_2(*x,*a); len2 = v2dist_2(*x,*b); if (len1 < LINE_EPS * LINE_EPS || len2 < LINE_EPS * LINE_EPS) return(TRUE); v2sub(*b,*a,t); len3 = v2length_2(t); if (len1 > len3 || len2 > len3) return(FALSE); len3 = sqrt(len3); la = t.y / len3; lb = -t.x / len3; lc = -(la * a->x + lb * a->y); dist = la * x->x + lb * x->y + lc; if (fabs(dist) < LINE_EPS) return(TRUE); return(FALSE); } #define SWAP(a,b,t) { t = a; a = b; b = t; } /* use intersect_test before that proc to test if the lines really intersect */ BOOLEAN vintersect(PNT2 *p1,PNT2 *p2,PNT2 *p3,PNT2 *p4,PNT2 *inter) { DOUBLE a1,a2,b1,b2,c1,c2; DOUBLE denom,num; if (approxonline(p1,p3,p4)) { *inter = *p1; return(TRUE); } if (approxonline(p2,p3,p4)) { *inter = *p2; return(TRUE); } a1 = p2->y - p1->y; /* calc: a1 x + b1 y + c1 = 0 */ b1 = p1->x - p2->x; c1 = p2->x * p1->y - p1->x * p2->y; a2 = p4->y - p3->y; /* calc: a2 x + b2 y + c2 = 0 */ b2 = p3->x - p4->x; c2 = p4->x * p3->y - p3->x * p4->y; denom = a1 * b2 - a2 * b1; if (fabs(denom) < 1E-10) /* collinear :-( */ return(FALSE); num = b1 * c2 - b2 * c1; inter->x = num / denom; num = a2 * c1 - a1 * c2; inter->y = num / denom; return(TRUE); } /**************************************************************/ #define NEIGHBOURSIZE 100 static INT n_index; static NEIGHBOURS n_list[NEIGHBOURSIZE]; static VOID free_neighbours(VOID) { n_index = 0; } static NEIGHBOURS *alloc_neighbour_node(SITE_PTR site,DISCONTINUITY d) { NEIGHBOURS *n; if (n_index >= NEIGHBOURSIZE) fprintf(stderr,"No more neighbours\n"); n = &n_list[n_index]; n_index++; n->site = site; n->d = d; n->next = NULL; return(n); } /****************************************************************/ /* Edge storage management*/ /****************************************************************/ #define NYL -1 static VOID delete_all_edges(VOID) { _surf->next_edge = 0; _surf->avail_edge = NYL; _surf->n_edges = 0; } static EDGE_PTR alloc_edge(VOID) { EDGE_PTR ans; _surf->n_edges++; if (_surf->avail_edge == NYL) ans = _surf->next_edge, _surf->next_edge += 4; else ans = _surf->avail_edge, _surf->avail_edge = onext(_surf->avail_edge); return(ans); } static VOID free_edge(EDGE_PTR e) { e ^= e & 3; onext(e) = _surf->avail_edge; _surf->avail_edge = e; _surf->n_edges--; } /****************************************************************/ /* Quad-edge manipulation primitives */ /****************************************************************/ static EDGE_PTR makeedge(SITE_PTR origin,SITE_PTR destination,DISCONTINUITY d) { register EDGE_PTR temp, ans; assert(origin != destination); assert(X(origin) != X(destination) || Y(origin) != Y(destination)); temp = alloc_edge(); ans = temp; disco(ans) = d; onext(temp) = ans; orig(temp) = origin; onext(++temp) = ans + 3; onext(++temp) = ans + 2; orig(temp) = destination; onext(++temp) = ans + 1; Edge(origin) = ans; Edge(destination) = sym(ans); return(ans); } static VOID splice(EDGE_PTR a,EDGE_PTR b) { EDGE_PTR alpha, beta, temp; alpha = rot(onext(a)); beta = rot(onext(b)); temp = onext(alpha); onext(alpha) = onext(beta); onext(beta) = temp; temp = onext(a); onext(a) = onext(b); onext(b) = temp; Edge(orig(a)) = a; Edge(orig(b)) = b; } static VOID swapedge(EDGE_PTR e) { EDGE_PTR a,b,syme; a = oprev(e); syme = sym(e); b = oprev(syme); splice(e, a); splice(syme, b); splice(e, lnext(a)); splice(syme, lnext(b)); orig(e) = dest(a); Edge(orig(a)) = a; /* correct point references */ dest(e) = dest(b); Edge(orig(b)) = b; } static EDGE_PTR connect_left(EDGE_PTR a, EDGE_PTR b,DISCONTINUITY d) { register EDGE_PTR ans; ans = makeedge(dest(a), orig(b),d); splice(ans, lnext(a)); splice(sym(ans), b); return(ans); } static EDGE_PTR connect_right(EDGE_PTR a, EDGE_PTR b,DISCONTINUITY d) { register EDGE_PTR ans; ans = makeedge(dest(a), orig(b),d); splice(ans, sym(a)); splice(sym(ans), oprev(b)); return(ans); } static VOID deleteedge(EDGE_PTR e) /* disconnects e from the rest of the structure and destroys it. */ { if (e == _surf->Last_locate_edge || e == sym(_surf->Last_locate_edge)) _surf->Last_locate_edge = onext(e); Edge(orig(e)) = oprev(e); /* reset point references */ Edge(dest(e)) = lnext(e); splice(e, oprev(e)); splice(sym(e), oprev(sym(e))); free_edge(e); } static VOID splitedge(EDGE_PTR e,SITE_PTR site) { EDGE_PTR t,newe; t = lnext(e); splice(sym(e),t); Edge(orig(t)) = t; /* to make sure it's ok ! */ dest(e) = site; newe = connect_left(e,t,disco(e)); Edge(site) = newe; } /****************************************************************/ /* Quad-edge storage allocation */ /****************************************************************/ #define my_alloc(str_name, str_type, str_cnt) \ if (NULL == ((str_name) = (str_type *) \ malloc ((unsigned) ((str_cnt) * sizeof(str_type))))) \ fprintf(stderr," cannot malloc %s \n",#str_name) static VOID sef_alloc(INT n) { my_alloc(_surf->sa, struct SITE, n ); my_alloc(_surf->org, SITE_PTR, 12*n ); my_alloc(_surf->next, EDGE_PTR, 12*n ); my_alloc(_surf->ei, struct EDGE_INFO, 3*n ); } static VOID sef_free(VOID) { free((char *)_surf->sa); free((char *)_surf->org); free((char *)_surf->next); free((char *)_surf->ei); } static VOID sef_enlarge(INT additional) { INT n; TRIANG old_surf,*temp; old_surf = *_surf; n = _surf->alloced_sites; _surf->alloced_sites += additional; sef_alloc(_surf->alloced_sites); memcpy(_surf->sa,old_surf.sa,sizeof(struct SITE) * n); memcpy(_surf->org,old_surf.org,sizeof(SITE_PTR) * 12 * n); memcpy(_surf->next,old_surf.next,sizeof(EDGE_PTR) * 12 * n); memcpy(_surf->ei,old_surf.ei,sizeof(struct EDGE_INFO) * 3 * n); temp = _surf; _surf = &old_surf; sef_free(); _surf = temp; } /****************************************************************/ /* Site location */ /* find an edge where site lies left or on ! */ /****************************************************************/ #define SITECMP(vec,site) (fabs(vec.x - X(site)) < 1E-16 && \ fabs(vec.y - Y(site)) < 1E-16) static BOOLEAN v_locate ( VEC2 site, EDGE_PTR *edge,SITE_PTR *oldsite ) { register EDGE_PTR e; INT i; i = 0; e = _surf->Last_locate_edge; while (1) { i++; if (SITECMP(site,orig(e))) { *edge = e; *oldsite = orig(e); return(TRUE); } else if (SITECMP(site,dest(e))) { *edge = e; *oldsite = dest(e); return(TRUE); } else if (v_rightof(site,e)) e = sym(e); else if (v_leftoron(site,onext(e))) e = onext(e); else if (v_leftoron(site,dprev(e))) e = dprev(e); else break; } /* As Gordon said: Check it! */ assert(v_leftoron(site,e)); assert(v_leftof(site,lnext(e))); assert(v_leftof(site,lprev(e))); assert(v_rightoron(site,sym(e))); assert(v_rightof(site,dprev(e))); assert(v_rightof(site,onext(e))); assert(dest(lnext(e)) == orig(lprev(e))); assert(dest(onext(e)) == orig(dprev(e))); assert(dest(lnext(e)) == orig(dprev(e))); *edge = e; *oldsite = 0; return(FALSE); } /****************************************************************/ /* Incremental Site Insertion */ /* with a lot of ideas by Dani Lischinski */ /****************************************************************/ /* recursive edge flipping to the right of an edge */ static VOID fix_edge_right(EDGE_PTR *e) { EDGE_PTR f,g; if (disco_edge(*e)) return; f = oprev(*e); g = dnext(*e); if (incircle(&Site(dest(*e)),&Site(dest(onext(*e))),&Site(orig(*e)), &Site(dest(f)))) { swapedge(*e); fix_edge_right(&f); fix_edge_right(&g); } } /* triangulate anew the loop to the left of first */ /* ??? maybe this only works if all vertices lie to the left of last */ /* i.e. the edge preceeding first ??? */ static VOID triangulate_left(EDGE_PTR first) { EDGE_PTR last,a,b,ea,t1,t2; last = lprev(first); while (lnext(lnext(first)) != last) { /* still > triangle */ ea = lnext(first); t1 = first; while (ea != last) { t2 = lnext(ea); if (t2 == last && t1 == first) break; if (leftof(dest(ea),t1)) { if (t1 == first) { first = sym(connect_left(ea,t1,DINF)); t1 = first; } else t1 = sym(connect_left(ea,t1,DINF)); a = oprev(t1); b = dnext(t1); fix_edge_right(&a); fix_edge_right(&b); ea = t2; } else { t1 = ea; ea = t2; } } } a = lnext(last); b = lprev(last); fix_edge_right(&a); fix_edge_right(&b); fix_edge_right(&last); } /****************************************************************/ /* Incremental Delaunay Triangulation Procedure */ /****************************************************************/ /* this one does not flip unflippable edges ! */ static VOID incremental_delaunay(SITE_PTR site,EDGE_PTR edge) { SITE_PTR first; EDGE_PTR e,t,base; EDGE_PTR a,b,c,d; e = edge; /* site lies left or on edge ! */ if (onedge(site,e)) { /* we are on an existing edge */ a = oprev(e); b = dnext(e); c = lnext(e); d = lprev(e); splitedge(e,site); connect_left(e,lprev(e),DINF); connect_left(oprev(e),sym(e),DINF); fix_edge_right(&a); fix_edge_right(&b); fix_edge_right(&c); fix_edge_right(&d); return; } first = orig(e); base = makeedge(first,site,DINF); splice(base,e); do { base = connect_left(e,sym(base),DINF); e = oprev(base); } while (dest(e) != first); while (1) { t = oprev(e); if (flipable(e) && rightof(dest(t),e) && incircle(&origv(e),&destv(t),&destv(e),&Site(site))) { swapedge(e); e = oprev(e); continue; } else if (orig(e) == first) break; e = lprev(onext(e)); } } VOID insert_edge(TRIANG *surf, SITE_PTR a,SITE_PTR b, DISCONTINUITY discontinuity,SITE_PTR *new_sites,INT *n_new) { EDGE_PTR ea,eb,t,ne; SITE_PTR last,cross; VEC2 inter; BOOLEAN inters; if (n_new != NULL) *n_new = 0; /* at the beginning no new stuff */ _surf = surf; ea = Edge(a); /* get edge with a as orig */ eb = Edge(b); /* get edge with b as orig */ last = orig(eb); while (orig(ea) != last) { while (rightof(b,ea) || leftoron(b,onext(ea))) ea = onext(ea); assert(dest(onext(ea)) != last); /*assert(! online(dest(onext(ea)),a,b)); new online approx */ if (online(dest(ea),a,b)) { disco(ea) = discontinuity; ea = sym(ea); continue; } t = ea; while (1) { if (online(dest(lnext(t)),a,b)) { if (lnext(lnext(lnext(t))) == ea) { disco(lnext(lnext(t))) = discontinuity; ea = sym(lnext(t)); break; } else { ne = connect_left(lnext(t),ea,discontinuity); ea = sym(lnext(t)); triangulate_left(lnext(ne)); triangulate_left(oprev(ne)); break; } } else if (leftofline(dest(lnext(t)),a,b)) { /* left not on! */ if (flipable(lnext(t))) deleteedge(lnext(t)); else { /* 2 x-ing disco edges */ inters = vintersect(&origv(lnext(t)),&destv(lnext(t)), &Site(a),&Site(b),&inter); assert(inters); assert(inter.x != X(orig(lnext(t))) || inter.y != Y(orig(lnext(t)))); /* orig not on edge but cross == dest */ assert(inter.x != X(dest(lnext(t))) || inter.y != Y(dest(lnext(t)))); /* dest not on edge but cross = dest */ if (new_sites == NULL) fprintf(stderr,"can't create site for x-ing edges"); if (surf->n_sites == surf->alloced_sites) /* full */ sef_enlarge(SITEALLOC); cross = surf->n_sites++; Site(cross) = inter; Invis(cross) = 0; Info(cross) = NULL; /* has to be set by caller later on */ new_sites[(*n_new)++] = cross; splitedge(lnext(t),cross); ne = connect_left(lnext(t),ea,discontinuity); ea = sym(lnext(t)); triangulate_left(lnext(ne)); triangulate_left(oprev(ne)); break; } } else t = lnext(t); } } } /****************************************************************/ /* Top-level Delaunay Triangulation Procedure */ /****************************************************************/ VOID init_surface(TRIANG **surf,DOUBLE x0,DOUBLE y0,DOUBLE x1,DOUBLE y1) { DOUBLE lenx,leny; EDGE_PTR a,b,c; *surf = (TRIANG *)calloc(sizeof(TRIANG),1); _surf = *surf; _surf->alloced_sites = SITEALLOC; sef_alloc(_surf->alloced_sites); delete_all_edges(); _surf->bbox.min.x = x0; _surf->bbox.min.y = y0; _surf->bbox.max.x = x1; _surf->bbox.max.y = y1; _surf->n_edges = 0; /******************** Generate Basic Mesh **************************/ _surf->n_sites = 4; /* we generate a 10% bigger square */ lenx = (x1 - x0) / 10.0; leny = (y1 - y0) / 10.0; X(0) = x0 - lenx; Y(0) = y0 - leny; Invis(0) = 1; Info(0) = NULL; X(1) = x1 + lenx; Y(1) = y0 - leny; Invis(1) = 1; Info(1) = NULL; X(2) = x1 + lenx; Y(2) = y1 + leny; Invis(2) = 1; Info(2) = NULL; X(3) = x0 - lenx; Y(3) = y1 + leny; Invis(3) = 1; Info(3) = NULL; a = makeedge(0,3,DBDRY); b = makeedge(1,2,DBDRY); c = connect_left(sym(b),a,DBDRY); _surf->One_bndry_edge = sym(c); c = sym(connect_right(rprev(c),c,DINF)); c = connect_left(b,sym(c),DBDRY); _surf->Last_locate_edge = _surf->One_bndry_edge; /* init locate */ } VOID delete_surface(TRIANG *surf) { _surf = surf; sef_free(); } BOOLEAN insert_site(TRIANG *surf,DOUBLE x,DOUBLE y,SITE_PTR *site,VOIDPTR info) { EDGE_PTR e; VEC2 xy; SITE_PTR n; _surf = surf; if (x < _surf->bbox.min.x || x > _surf->bbox.max.x || y < _surf->bbox.min.y || y > _surf->bbox.max.y) { fprintf(stderr,"SITE outside! %g,%g [%g,%g - %g,%g]\n",x,y, _surf->bbox.min.x,_surf->bbox.min.y, _surf->bbox.max.x,_surf->bbox.max.y); return(FALSE); } xy.x = x; xy.y = y; if (v_locate(xy,&e,site)) { /* already there ! */ Info(*site) = info; return(FALSE); } if (surf->n_sites == surf->alloced_sites) /* we're full ! */ sef_enlarge(SITEALLOC); n = surf->n_sites++; Site(n) = xy; Invis(n) = 0; /* it's visible */ Info(n) = info; incremental_delaunay(n,e); *site = n; return(TRUE); } INT locate_point(TRIANG *surf,DOUBLE x,DOUBLE y,SITE_PTR sites[3]) { EDGE_PTR e; SITE_PTR site; VEC2 xy; _surf = surf; if (x < _surf->bbox.min.x || x > _surf->bbox.max.x || y < _surf->bbox.min.y || y > _surf->bbox.max.y) { fprintf(stderr,"POINT outside! %g,%g [%g,%g - %g,%g]\n",x,y, _surf->bbox.min.x,_surf->bbox.min.y, _surf->bbox.max.x,_surf->bbox.max.y); return(0); } xy.x = x; xy.y = y; if (v_locate(xy,&e,&site)) { /* already there */ sites[0] = site; return(1); } sites[0] = orig(e); sites[1] = dest(e); sites[2] = dest(lnext(e)); return(0); } VOID get_coords(TRIANG *surf,SITE_PTR site,DOUBLE *x,DOUBLE *y) { _surf = surf; *x = X(site); *y = Y(site); } VOIDPTR get_info(TRIANG *surf,SITE_PTR site) { _surf = surf; return(Info(site)); } VOID set_info(TRIANG *surf,SITE_PTR site,VOIDPTR info) { _surf = surf; Info(site) = info; } VOID get_neighbours(TRIANG *surf,SITE_PTR site,NEIGHBOURS **neigh) { EDGE_PTR e,t; NEIGHBOURS *n; _surf = surf; free_neighbours(); /* make room */ *neigh = NULL; e = Edge(site); t = e; do { if (! Invis(dest(e))) { n = alloc_neighbour_node(dest(e),disco(e)); n->next = *neigh; *neigh = n; } e = oprev(e); } while (t != e); } LONG for_all_sites(TRIANG *surf,VOID (*siteproc)(TRIANG *surf,SITE_PTR s)) { LONG cnt; SITE_PTR site; _surf = surf; cnt = 0; for (site = 0; site < surf->n_sites; site++) { if (Invis(site)) continue; if (siteproc != NULL) (*siteproc)(surf,site); cnt++; } return(cnt); } LONG for_all_edges(TRIANG *surf, VOID (*edgeproc)(TRIANG *surf,SITE_PTR s1,SITE_PTR s2,DISCONTINUITY d)) { LONG i,cnt; EDGE_PTR e; _surf = surf; if (_surf->avail_edge != -1) fprintf(stderr,"Aw, Shit not all edges are valid !\n"); e = 0; cnt = 0; for (i = 0; i < _surf->n_edges; i++, e += 4) { if (Invis(orig(e)) || Invis(dest(e))) continue; if (edgeproc != NULL) (*edgeproc)(surf,orig(e),dest(e),disco(e)); cnt++; } return(cnt); } LONG for_all_triangles(TRIANG *surf, VOID (*triproc)(TRIANG *surf,SITE_PTR s1,SITE_PTR s2,SITE_PTR s3, DISCONTINUITY d1,DISCONTINUITY d2,DISCONTINUITY d3)) { LONG cnt; EDGE_PTR e,t; SITE_PTR site; _surf = surf; cnt = 0; for (site = 0; site < surf->n_sites; site++) { if (Invis(site)) continue; e = Edge(site); t = e; do { if (! Invis(dest(e)) && ! Invis(dest(onext(e))) && Y(site) < Y(dest(onext(e)))) { if (Y(site) < Y(dest(e)) || (Y(site) == Y(dest(e)) && X(site) < X(dest(e)))) { if (triproc != NULL) { if (rightof(dest(onext(e)),e)) printf("XX"); (*triproc)(surf,site,dest(e),dest(onext(e)), disco(e),disco(lnext(e)),disco(lprev(e))); } cnt++; } } e = oprev(e); } while (t != e); } return(cnt); } VOID flip_flipable_edges(TRIANG *surf,BOOLEAN (*testproc)(VOIDPTR s1,VOIDPTR s2, VOIDPTR s3,VOIDPTR s4)) { INT i; DOUBLE dist1,dist2; EDGE_PTR e; SITE_PTR s1,s2,s3,s4; _surf = surf; if (_surf->avail_edge != -1) fprintf(stderr,"Aw, Shit not all edges are valid !\n"); e = 0; for (i = 0; i < _surf->n_edges; i++, e += 4) { s1 = orig(e); s2 = dest(e); if (disco_edge(e) || Invis(s1) || Invis(s2)) continue; s3 = dest(oprev(e)); /* point on right */ s4 = dest(onext(e)); /* point on left */ dist1 = distcircle(&Site(s1),&Site(s3),&Site(s2),&Site(s4)); dist2 = distcircle(&Site(s3),&Site(s2),&Site(s4),&Site(s1)); if (dist1 >= 0.0 && dist2 >= 0.0) { /* both are inside */ if ((*testproc)(Info(s1),Info(s2),Info(s3),Info(s4))) swapedge(e); } } } e = 0; for (i = 0; i < _surf->n_edges; i++, e += 4) { s1 = orig(e); s2 = dest(e); if (disco_edge(e) || Invis(s1) || Invis(s2)) continue; s3 = dest(oprev(e)); /* point on right */ s4 = dest(onext(e))Fxfire/DiscoMesher/dt.h000644 000316 000311 00000017041 06114617245 015117 0ustar00wrzlgup000000 000000 /**********************************************************************/ /* Delaunay-Triangulation Module */ /* header file */ /* */ /* (c) 1992-1994 by Wolfgang Stuerzlinger (wRZL) */ /* This code may be used only for non-commercial purposes ! */ /* Coauthorship of any publications using this code is claimed. */ /**********************************************************************/ #define VOID void /* VOID f() = procedure */ #define VOIDPTR void * #ifndef NULL #define NULL ((void *)0L) #endif #define PP(x) x #define Const const #define Extern extern #define Register register #define Signed signed #define Static static #define Unsigned unsigned #define Volatile volatile typedef Unsigned int WORD; /* the machine word */ typedef Unsigned char BOOLEAN; typedef Unsigned char BYTE; /* 8 bit unsigned */ typedef Signed char CHAR; /* 8 bit signed */ #if defined(__GNUC__) || ! defined(__STDC__) typedef char UCHAR; /* for Strings */ #else typedef Unsigned char UCHAR; /* for Strings */ #endif typedef Signed short INT; /* 16 bit signed */ typedef Unsigned short UINT; /* 16 bit unsigned */ typedef Signed long LONG; /* 32 bit signed */ typedef Unsigned long ULONG; /* 32 bit unsigned */ typedef double FLOAT; typedef double DOUBLE; #define FALSE ((BOOLEAN) 0) #define TRUE ((BOOLEAN) 1) typedef struct { FLOAT x; FLOAT y; } VEC2, PNT2; typedef struct { PNT2 min; PNT2 max; } BOX2; /******************************************************************************* For a description see the reference for the Quad-edge data structure: Leonidas Guibas and Jorge Stolfi, "Primitives for the manipulation of general subdivisions and the computations of Voronoi diagrams", ACM TOG 4,74-123 (1985) *******************************************************************************/ /**************************** Common data structures **************************/ typedef LONG SITE_PTR; typedef LONG EDGE_PTR; typedef LONG INFO_PTR; typedef enum DISCONTINUITY { DBDRY, DTEMP, D0, D1, D2, DINF } DISCONTINUITY; struct SITE { VEC2 vc; EDGE_PTR edge; BOOLEAN invisible; VOIDPTR info; }; struct EDGE_INFO { DISCONTINUITY disco; }; typedef struct TRIANG { LONG n_sites; LONG n_edges; LONG alloced_sites; struct SITE *sa ; EDGE_PTR *next ; SITE_PTR *org ; struct EDGE_INFO *ei ; EDGE_PTR One_bndry_edge; BOX2 bbox; EDGE_PTR Last_locate_edge; EDGE_PTR next_edge; EDGE_PTR avail_edge; } TRIANG; typedef struct NEIGHBOURS { struct NEIGHBOURS *next; SITE_PTR site; DISCONTINUITY d; } NEIGHBOURS; /******************************************************************************/ /********************** Macros for manipulation of quad-edges *****************/ /* Following edge ordering is used: ** ** ^ ^ \ / ** lnext(e) \ / rprev(e) dprev(e) \ / dnext(e) ** \ / V ** ^ | ** e | sym(e) | ** | V ** ^ / \ ** lprev(e) / \ rnext(e) onext(e) / \ oprev(e) ** / \ V V */ /* SITE_PTR s */ #define X(s) _surf->sa[s].vc.x #define Y(s) _surf->sa[s].vc.y #define Edge(s) _surf->sa[s].edge #define Invis(s) _surf->sa[s].invisible #define Site(s) _surf->sa[s].vc #define Info(s) _surf->sa[s].info /* EDGE_PTR a */ #define sym(a) ((a) ^ 2) #define rot(a) ( (((a) + 1) & 3) | ((a) & ~3) ) #define rotinv(a) ( (((a) + 3) & 3) | ((a) & ~3) ) #define onext(a) _surf->next[a] #define oprev(a) rot(onext(rot(a))) #define lnext(a) rot(onext(rotinv(a))) #define lprev(a) sym(onext(a)) #define rnext(a) rotinv(onext(rot(a))) #define rprev(a) onext(sym(a)) #define dnext(a) sym(onext(sym(a))) #define dprev(a) rotinv(onext(rotinv(a))) #define orig(a) _surf->org[a] #define dest(a) orig(sym(a)) #define left(a) orig(rotinv(a)) #define right(a) orig(rot(a)) #define origv(a) _surf->sa[orig(a)].vc #define destv(a) _surf->sa[dest(a)].vc #define leftv(a) _surf->fa[left(a)].vc #define rightv(a) _surf->fa[right(a)].vc #define info(a) _surf->ei[(a)>>2] #define disco(a) (info(a).disco) /******************************************************************************/ /********************************* MISC ***************************************/ #define flipable(e) (disco(e) > D2) #define disco_edge(e) (disco(e) <= D2) #define rightofline(X,a,b) (ccw(&Site(X),&Site(a),&Site(b))< 0.0) #define rightoronline(X,a,b) (ccw(&Site(X),&Site(a),&Site(b))<=0.0) #define leftofline(X,a,b) (ccw(&Site(X),&Site(a),&Site(b))> 0.0) #define leftoronline(X,a,b) (ccw(&Site(X),&Site(a),&Site(b))>=0.0) /*#define online(X,a,b) (ccw(&Site(X),&Site(a),&Site(b))==0.0)*/ #define online(X,a,b) approxonline(&Site(X),&Site(a),&Site(b)) #define rightof(X,e) (ccw(&Site(X),&origv(e),&destv(e))< 0.0) #define rightoron(X,e) (ccw(&Site(X),&origv(e),&destv(e))<=0.0) #define leftof(X,e) (ccw(&Site(X),&origv(e),&destv(e))> 0.0) #define leftoron(X,e) (ccw(&Site(X),&origv(e),&destv(e))>=0.0) /*#define onedge(X,e) (ccw(&Site(X),&origv(e),&destv(e))==0.0)*/ #define onedge(X,e) approxonline(&Site(X),&origv(e),&destv(e)) #define v_rightofline(X,a,b) (ccw(&X,&a,&b)< 0.0) #define v_rightoronline(X,a,b) (ccw(&X,&a,&b)<=0.0) #define v_leftofline(X,a,b) (ccw(&X,&a,&b)> 0.0) #define v_leftoronline(X,a,b) (ccw(&X,&a,&b)>=0.0) /*#define v_online(X,a,b) (ccw(&X,&a,&b)==0.0)*/ #define v_online(X,a,b) approxonline(&X,&a,&b) #define v_rightof(X,e) (ccw(&X,&origv(e),&destv(e))< 0.0) #define v_rightoron(X,e) (ccw(&X,&origv(e),&destv(e))<=0.0) #define v_leftof(X,e) (ccw(&X,&origv(e),&destv(e))> 0.0) #define v_leftoron(X,e) (ccw(&X,&origv(e),&destv(e))>=0.0) /*#define v_onedge(X,e) (ccw(&X,&origv(e),&destv(e))==0.0)*/ #define v_onedge(X,e) approxonline(&X,&origv(e),&destv(e)) /****************************** PROTOTYPES ***********************************/ VOID init_surface(TRIANG **surf,double x0,double y0,double x1,double y1); VOID delete_surface(TRIANG *surf); BOOLEAN insert_site(TRIANG *surf,double x,double y,SITE_PTR *site,VOIDPTR info); INT locate_point(TRIANG *surf,DOUBLE x,DOUBLE y,SITE_PTR sites[3]); VOID get_coords(TRIANG *surf,SITE_PTR site,double *x,double *y); VOIDPTR get_info(TRIANG *surf,SITE_PTR site); VOID set_info(TRIANG *surf,SITE_PTR site,VOIDPTR info); VOID get_neighbours(TRIANG *surf,SITE_PTR site,NEIGHBOURS **neigh); LONG for_all_sites(TRIANG *surf,VOID (*siteproc)(TRIANG *surf,SITE_PTR s)); LONG for_all_edges(TRIANG *surf, VOID (*edgeproc)(TRIANG *surf,SITE_PTR s1,SITE_PTR s2,DISCONTINUITY d)); LONG for_all_triangles(TRIANG *surf, VOID (*triproc)(TRIANG *surf,SITE_PTR s1,SITE_PTR s2,SITE_PTR s3, DISCONTINUITY d1,DISCONTINUITY d2,DISCONTINUITY d3)); VOID flip_flipable_edges(TRIANG *surf,BOOLEAN (*testproc)(VOIDPTR s1, VOIDPTR s2,VOIDPTR s3,VOIDPTR s4)); VOID insert_edge(TRIANG *surf, SITE_PTR a,SITE_PTR b, DISCONTINUITY discontinuity,SITE_PTR *new_sites,INT *n_new); f, VOID (*edgeproc)(TRIANG *surf,SITE_PTR s1,SITE_PTR s2,DISCONTINUITY d)); LONG for_all_triangles(TRIANG *surf, VOID (*triproc)(TRIANG *surf,SITE_PTR s1,SITE_PTR s2,SITE_PTR s3, DISCONTINUITY d1,DISCONTINUITY d2,DISCONTINUITY d3)); VOID flip_flipable_edges(TRIANG *surf,BOOLEAN (*testproc)(VOIDPTR s1, VOIDPTR s2,VOIDPTR s3,VOIDPTR s4)); VOID insert_edge(TRIANG *surf, SITE_PTR a,SITE_PTR b, DISCONTINUITY discontinuity,SFxfire/DiscoMesher/geom.c000644 000316 000311 00000010116 06114617245 015426 0ustar00wrzlgup000000 000000 /**********************************************************************/ /* geom.c */ /* */ /* (c) 1992-1994 by Wolfgang Stuerzlinger (wRZL) */ /* This code may be used only for non-commercial purposes ! */ /* Coauthorship of any publications using this code is claimed. */ /**********************************************************************/ #include #include #include #include #include #include "geom.h" /********************* clip a line to the surface ***************************/ /* right is > 0.0 */ #define calc_ccw(v1,v2,p) \ ((v2->u - v1->u) * (v1->v - p->v) - (v2->v - v1->v) * (v1->u - p->u)) double calc_side(TPoint2f *v1,TPoint2f *v2,TPoint2f *p) { double side; if ((v1->u == p->u && v1->v == p->v) || (v2->u == p->u && v2->v == p->v)) return(0.0); side = calc_ccw(v1,v2,p); if (fabs(side) < 1E-7) { /* need a more precise result */ side += calc_ccw(v1,p,v2); side += calc_ccw(v2,v1,p); side += calc_ccw(v2,p,v1); side += calc_ccw(p,v1,v2); side += calc_ccw(p,v2,v1); side /= 6.0; } if (side == -0.0) side = 0.0; return(side); } #define LINE_EPS 1E-14 int isonline(TPoint2f *x,TPoint2f *a,TPoint2f *b) /* return TRUE if point in LINE_EPS region of line */ { double len1,len2,len3,la,lb,lc,dist; TVector2f t; len1 = DistPnt2_2(*x,*a); len2 = DistPnt2_2(*x,*b); if (len1 < LINE_EPS * LINE_EPS || len2 < LINE_EPS * LINE_EPS) return(1); SubVector2(t,*a,*b); len3 = DotVector2(t,t); if (len1 > len3 || len2 > len3) return(0); len3 = sqrt(len3); la = t.v / len3; lb = -t.u / len3; lc = -(la * a->u + lb * a->v); dist = la * x->u + lb * x->v + lc; if (fabs(dist) < LINE_EPS) return(1); return(0); } int intersect_lines(TPoint2f *p1,TPoint2f *p2,TPoint2f *p3,TPoint2f *p4, TPoint2f *inter) { double a1,a2,b1,b2,c1,c2; double denom,num; double side1,side2; if (isonline(p1,p3,p4)) { *inter = *p1; return(1); } if (isonline(p2,p3,p4)) { *inter = *p2; return(1); } side1 = calc_side(p3,p4,p1); side2 = calc_side(p3,p4,p2); if (side1 > 0.0 && side2 > 0.0) return(0); if (side1 < 0.0 && side2 < 0.0) return(0); a1 = p2->v - p1->v; /* calc: a1 x + b1 y + c1 = 0 */ b1 = p1->u - p2->u; c1 = p2->u * p1->v - p1->u * p2->v; a2 = p4->v - p3->v; /* calc: a2 x + b2 y + c2 = 0 */ b2 = p3->u - p4->u; c2 = p4->u * p3->v - p3->u * p4->v; denom = a1 * b2 - a2 * b1; if (fabs(denom) < 1E-10) /* collinear :-( */ return(0); num = b1 * c2 - b2 * c1; inter->u = num / denom; num = a2 * c1 - a1 * c2; inter->v = num / denom; if (! isonline(inter,p1,p2)) printf("error 1"); if (! isonline(inter,p3,p4)) printf("error 2"); return(1); } int inside_poly2(TPoly2 *pp,TPoint2f *point2) { int i,mask; double side; TPoint2f *v1,*v2; mask = 0; v1 = &pp->vert[pp->n - 1]; for (i = 0; i < pp->n; i++) { v2 = &pp->vert[i]; side = calc_side(v1,v2,point2); if (side >= 0.0) /* right or online is outside */ mask |= 1 << i; v1 = v2; } return(mask); } int clip2poly2(TPoly2 *pp,TPoint2f *p1,TPoint2f *p2) { int i,mask1,mask2; TPoint2f *v1,*v2,inter; TVector2f temp; mask1 = inside_poly2(pp,p1); mask2 = inside_poly2(pp,p2); if (mask1 == 0 && mask2 == 0) /* both are inside */ return(1); v1 = &pp->vert[pp->n - 1]; for (i = 0; i < pp->n; i++) { v2 = &pp->vert[i]; if (mask1 & mask2) /* either one or both are outside */ return(0); /* on the same side */ if ((mask1 ^ mask2) & (1 << i)) { /* different sides */ if (! intersect_lines(p1,p2,v1,v2,&inter)) printf("Really ?"); if (mask1 & (1 << i)) { /* p1 is outside */ *p1 = inter; mask1 = inside_poly2(pp,p1); /* reclassify */ } else { /* (mask2 & (1 << i)) */ /* p2 is outside */ *p2 = inter; mask2 = inside_poly2(pp,p2); /* reclassify */ } } v1 = v2; } SubVector2(temp,*p2,*p1); if (DotVector2(temp,temp) < 1.0E-6) return(0); /* clipped to nothing */ return(1); } ) & (1 << i)) { /* different sides */ if (! intersect_lines(p1,p2,v1,v2,&inter)) printf("Really ?"); if (mask1 & (1 << i)) { /* p1 is outside */ *p1 = inter; mask1 = inside_poly2(pp,p1); /* reclassify */ } else { /* (mask2 & (1 << i)) */ /* p2 is outside */ *p2 = inter; mask2 = inside_poly2(pp,p2); /* reclassify */ } } v1 = v2; } SubVector2(temp,*p2,*p1); if (DotVector2(temFxfire/DiscoMesher/geom.h000644 000316 000311 00000046462 06114617245 015450 0ustar00wrzlgup000000 000000 /**********************************************************************/ /* geom.h */ /* */ /* (c) 1992-1994 by Wolfgang Stuerzlinger (wRZL) */ /* This code may be used only for non-commercial purposes ! */ /* Coauthorship of any publications using this code is claimed. */ /**********************************************************************/ #define kMaxPolyPoints 16 typedef struct { double u, v; } TPoint2f; typedef struct { float x, y, z; } TPoint3f; /* to save space */ typedef TPoint2f TVector2f; typedef TPoint3f TVector3f; typedef struct TLine { TVector2f normal; double np; } TLine; typedef struct TPlane { TVector3f normal; double np; } TPlane; typedef struct TPolygon { int n; char project; double ndotp; TVector3f normal; TPoint3f vert[kMaxPolyPoints]; } TPolygon; typedef struct TPoly2 { int n; TPoint2f vert[kMaxPolyPoints]; } TPoly2; #define SWAP(a,b,t) { t = a; a = b; b = t; } #ifndef M_PI #define M_PI 3.14159265358979 #endif #define InitPoint(p,x1,y1,z1) (p).x=x1, (p).y=y1, (p).z=z1 #define ZeroVector(a) (a).x = 0.0, (a).y = 0.0, (a).z = 0.0 #define PointEqual(a,b) ((a).x == (b).x && (a).y == (b).y && (a).z == (b).z) #define NegVector(a) (a).x = ((a).x) ? -(a).x : 0.0, \ (a).y = ((a).y) ? -(a).y : 0.0, \ (a).z = ((a).z) ? -(a).z : 0.0 #define AbsVector(c,a) (c).x=fabs((a).x),(c).y=fabs((a).y),(c).z=fabs((a).z) #define AddVector(c,a,b) (c).x=(a).x+(b).x, (c).y=(a).y+(b).y, (c).z=(a).z+(b).z #define SubVector(c,a,b) (c).x=(a).x-(b).x, (c).y=(a).y-(b).y, (c).z=(a).z-(b).z #define CrossVector(c,a,b) (c).x = (a).y*(b).z - (a).z*(b).y, \ (c).y = (a).z*(b).x - (a).x*(b).z, \ (c).z = (a).x*(b).y - (a).y*(b).x #define DotVector(a,b) ((a).x*(b).x + (a).y*(b).y + (a).z*(b).z) #define ScaleVector(c,s) (c).x*=(s), (c).y*=(s), (c).z*=(s) #define NormalizeVector(n,a) ((n)=sqrt(DotVector(a,a)), \ (n)?((a).x/=n, (a).y/=n, (a).z/=n):0.0) #define DistPnt(a,b) sqrt(((b).x - (a).x) * ((b).x - (a).x) + \ ((b).y - (a).y) * ((b).y - (a).y) + ((b).z - (a).z) * ((b).z - (a).z)) #define LenVector(a) sqrt(DotVector(a,a)) #define AvgVector(c,a,b) (c).x=((a).x+(b).x) * 0.5, (c).y=((a).y+(b).y) * 0.5, \ (c).z=((a).z+(b).z) * 0.5 #define VolVector(a,b,c) \ ((a).x*(b).y*(c).z + (a).y*(b).z*(c).x + (a).z*(b).x*(c).y - \ (a).z*(b).y*(c).x - (a).x*(b).z*(c).y - (a).y*(b).x*(c).z) #define DistPt2Plane(p,n,np) (DotVector(n,p) - (np)) #define Inplane(p,n,np) (fabs(DistPt2Plane(p,n,np)) < 1E-14) #define InsideBbox(mini,maxi,p) ((p).x >= (mini).x && (p).x <= (maxi).x && \ (p).y >= (mini).y && (p).y <= (maxi).y && \ (p).z >= (mini).z && (p).z <= (maxi).z) #define MakeBbox(mini,maxi,point) { \ if ((point).x < (mini).x) (mini).x = (point).x; \ else if ((point).x > (maxi).x) (maxi).x = (point).x; \ if ((point).y < (mini).y) (mini).y = (point).y; \ else if ((point).y > (maxi).y) (maxi).y = (point).y; \ if ((point).z < (mini).z) (mini).z = (point).z; \ else if ((point).z > (maxi).z) (maxi).z = (point).z; } #define JoinBbox(min1,max1,min2,max2) { \ if ((min2).x < (min1).x) (min1).x = (min2).x; \ if ((min2).y < (min1).y) (min1).y = (min2).y; \ if ((min2).z < (min1).z) (min1).z = (min2).z; \ if ((max2).x > (max1).x) (max1).x = (max2).x; \ if ((max2).y > (max1).y) (max1).y = (max2).y; \ if ((max2).z > (max1).z) (max1).z = (max2).z; } #define BboxOutside(min1,max1,min2,max2) \ ((min1).x > (max2).x || (min1).y > (max2).y || (min1).z > (max2).z || \ (max1).x < (min2).x || (max1).y < (min2).y || (max1).z < (min2).z) #define FindProject(norm,project) { \ TVector3f _n; \ AbsVector(_n,norm); \ if (_n.x > _n.y && _n.x > _n.z) \ project = ((norm).x >= 0.0) ? 0 : 3; \ else if (_n.y > _n.z) \ project = ((norm).y >= 0.0) ? 4 : 1; \ else \ project = ((norm).z >= 0.0) ? 2 : 5; } #define Project2d(project,d3,d2) switch (project) { \ case 0: (d2).u = (d3).y; (d2).v = (d3).z; break; \ case 1: (d2).u = (d3).x; (d2).v = (d3).z; break; \ case 2: (d2).u = (d3).x; (d2).v = (d3).y; break; \ case 3: (d2).u = -(d3).y; (d2).v = (d3).z; break; \ case 4: (d2).u = -(d3).x; (d2).v = (d3).z; break; \ case 5: (d2).u = -(d3).x; (d2).v = (d3).y; break; } #define Project3d(surf,d2,d3) switch ((surf).project) { \ case 0: (d3).y = (d2).u; (d3).z = (d2).v; \ (d3).x = ((surf).ndotp - (d3).y * (surf).normal.y - \ (d3).z * (surf).normal.z) / (surf).normal.x; break; \ case 1: (d3).x = (d2).u; (d3).z = (d2).v; \ (d3).y = ((surf).ndotp - (d3).x * (surf).normal.x - \ (d3).z * (surf).normal.z) / (surf).normal.y; break; \ case 2: (d3).x = (d2).u; (d3).y = (d2).v; \ (d3).z = ((surf).ndotp - (d3).x * (surf).normal.x - \ (d3).y * (surf).normal.y) / (surf).normal.z; break; \ case 3: (d3).y = -(d2).u; (d3).z = (d2).v; \ (d3).x = ((surf).ndotp - (d3).y * (surf).normal.y - \ (d3).z * (surf).normal.z) / (surf).normal.x; break; \ case 4: (d3).x = -(d2).u; (d3).z = (d2).v; \ (d3).y = ((surf).ndotp - (d3).x * (surf).normal.x - \ (d3).z * (surf).normal.z) / (surf).normal.y; break; \ case 5: (d3).x = -(d2).u; (d3).y = (d2).v; \ (d3).z = ((surf).ndotp - (d3).x * (surf).normal.x - \ (d3).y * (surf).normal.y) / (surf).normal.z; break; } #define InitPoint2(p,x,y) (p).u=x, (p).v=y #define PointEqual2(a,b) ((a).u == (b).u && (a).v == (b).v) #define PointNear2(a,b,eps) (fabs((a).u - (b).u) < (eps) && \ fabs((a).v - (b).v) < (eps)) #define NegVector2(a) (a).u = ((a).u) ? -(a).u : 0.0, \ (a).v = ((a).v) ? -(a).v : 0.0 #define AbsVector2(c,a) (c).u=fabs((a).u),(c).v=fabs((a).v) #define AddVector2(c,a,b) (c).u=(a).u+(b).u, (c).v=(a).v+(b).v #define SubVector2(c,a,b) (c).u=(a).u-(b).u, (c).v=(a).v-(b).v #define ScaleVector2(c,s) (c).u*=(s), (c).v*=(s) #define AvgVector2(c,a,b) (c).u=((a).u+(b).u) * 0.5, (c).v=((a).v+(b).v) * 0.5 #define DotVector2(a,b) ((a).u*(b).u + (a).v*(b).v) #define DistPnt2_2(a,b) sqrt(((b).u - (a).u) * ((b).u - (a).u) + \ ((b).v - (a).v) * ((b).v - (a).v)) #define DistPnt2(a,b) sqrt(DistPnt2_2(a,b)) #define LenVector2(a) sqrt(DotVector2(a,a)) #define CrossVector2(a,b) ((a).u*(b).v - (a).v*(b).u) #define NormalizeVector2(n,a) ((n)=sqrt(DotVector2(a,a)), \ (n)?((a).u/=n, (a).v/=n):0.0) #define TurnVector2Left2(c,a) (c).u = ((a).v)?-(a).v:0.0, (c).v = (a).u #define TurnVector2Right2(c,a) (c).u = (a).v, (c).v = ((a).u)?-(a).u:0.0 #define DistPt2Line(p,n,np) (DotVector2(n,p) - (np)) #define RightofPoints2(v1,v2,p) (calc_side(v1,v2,p) > 0.0) #define OutsideBbox2(mini,maxi,p) ((p).u < (mini).u || (p).u > (maxi).u || \ (p).v < (mini).v || (p).v > (maxi).v) #define InsideBbox2(mini,maxi,p) ((p).u >= (mini).u && (p).u <= (maxi).u && \ (p).v >= (mini).v && (p).v <= (maxi).v) #define BboxOutside2(min1,max1,min2,max2) \ ((min1).u > (max2).u || (min1).v > (max2).v || \ (max1).u < (min2).u || (max1).v < (min2).v) #define MakeBbox2(mini,maxi,point) { \ if ((point).u < (mini).u) (mini).u = (point).u; \ else if ((point).u > (maxi).u) (maxi).u = (point).u; \ if ((point).v < (mini).v) (mini).v = (point).v; \ else if ((point).v > (maxi).v) (maxi).v = (point).v; } #define Projectd1(project,d2) ((project == 0) ? (d2).v : (d2).u) #define FindProject2(d2) ((fabs((d2).u) > fabs((d2).v)) ? 0 : 1) #define Projectd2(project,normal,ndotp,d2,d) if (project == 0) { \ (d2).v = d; (d2).u = (ndotp - (d2).v * (normal).v) / (normal).u; } \ else { (d2).u = d; (d2).v = (ndotp - (d2).u * (normal).u) / (normal).v; } #define sign(x) ((x > 0) ? 1 : ((x < 0) ? -1 : 0)) #define v3pmulm(p1,m,p) \ { \ p.x = (p1).x * m[0][0] + (p1).y * m[1][0] + \ (p1).z * m[2][0] + m[3][0]; \ p.y = (p1).x * m[0][1] + (p1).y * m[1][1] + \ (p1).z * m[2][1] + m[3][1]; \ p.z = (p1).x * m[0][2] + (p1).y * m[1][2] + \ (p1).z * m[2][2] + m[3][2]; \ } #define v4pmulm(p1,m,p,w) \ { \ p.x = p1.x * m[0][0] + p1.y * m[1][0] + \ p1.z * m[2][0] + m[3][0]; \ p.y = p1.x * m[0][1] + p1.y * m[1][1] + \ p1.z * m[2][1] + m[3][1]; \ p.z = p1.x * m[0][2] + p1.y * m[1][2] + \ p1.z * m[2][2] + m[3][2]; \ w = p1.x * m[0][3] + p1.y * m[1][3] + \ p1.z * m[2][3] + m[3][3]; \ } #define v3vmulm(v1,m,v) \ { \ v.x = v1.x * m[0][0] + v1.y * m[1][0] + \ v1.z * m[2][0]; \ v.y = v1.x * m[0][1] + v1.y * m[1][1] + \ v1.z * m[2][1]; \ v.z = v1.x * m[0][2] + v1.y * m[1][2] + \ v1.z * m[2][2]; \ } #define m3trans(xt,yt,zt,one,two) \ { \ one[3][0] += xt; \ one[3][1] += yt; \ one[3][2] += zt; \ two[3][0] -= two[0][0] * xt + two[1][0] * yt + \ two[2][0] * zt; \ two[3][1] -= two[0][1] * xt + two[1][1] * yt + \ two[2][1] * zt; \ two[3][2] -= two[0][2] * xt + two[1][2] * yt + \ two[2][2] * zt; \ } #define m3rotx(alpha,one,two) \ { \ double _t; \ double _s = sin(alpha); \ double _c = cos(alpha); \ \ _t = one[0][1]; \ one[0][1] = _t * _c - one[0][2] * _s; \ one[0][2] = _t * _s + one[0][2] * _c; \ _t = one[1][1]; \ one[1][1] = _t * _c - one[1][2] * _s; \ one[1][2] = _t * _s + one[1][2] * _c; \ _t = one[2][1]; \ one[2][1] = _t * _c - one[2][2] * _s; \ one[2][2] = _t * _s + one[2][2] * _c; \ _t = one[3][1]; \ one[3][1] = _t * _c - one[3][2] * _s; \ one[3][2] = _t * _s + one[3][2] * _c; \ _t = two[1][0]; \ two[1][0] = _t * _c - two[2][0] * _s; \ two[2][0] = _t * _s + two[2][0] * _c; \ _t = two[1][1]; \ two[1][1] = _t * _c - two[2][1] * _s; \ two[2][1] = _t * _s + two[2][1] * _c; \ _t = two[1][2]; \ two[1][2] = _t * _c - two[2][2] * _s; \ two[2][2] = _t * _s + two[2][2] * _c; \ } #define m3roty(alpha,one,two) \ { \ double _t; \ double _s = sin(alpha); \ double _c = cos(alpha); \ \ _t = one[0][0]; \ one[0][0] = _t * _c + one[0][2] * _s; \ one[0][2] = -_t * _s + one[0][2] * _c; \ _t = one[1][0]; \ one[1][0] = _t * _c + one[1][2] * _s; \ one[1][2] = -_t * _s + one[1][2] * _c; \ _t = one[2][0]; \ one[2][0] = _t * _c + one[2][2] * _s; \ one[2][2] = -_t * _s + one[2][2] * _c; \ _t = one[3][0]; \ one[3][0] = _t * _c + one[3][2] * _s; \ one[3][2] = -_t * _s + one[3][2] * _c; \ _t = two[0][0]; \ two[0][0] = _t * _c + two[2][0] * _s; \ two[2][0] = -_t * _s + two[2][0] * _c; \ _t = two[0][1]; \ two[0][1] = _t * _c + two[2][1] * _s; \ two[2][1] = -_t * _s + two[2][1] * _c; \ _t = two[0][2]; \ two[0][2] = _t * _c + two[2][2] * _s; \ two[2][2] = -_t * _s + two[2][2] * _c; \ } #define m3rotz(alpha,one,two) \ { \ double _t; \ double _s = sin(alpha); \ double _c = cos(alpha); \ \ _t = one[0][0]; \ one[0][0] = _t * _c - one[0][1] * _s; \ one[0][1] = _t * _s + one[0][1] * _c; \ _t = one[1][0]; \ one[1][0] = _t * _c - one[1][1] * _s; \ one[1][1] = _t * _s + one[1][1] * _c; \ _t = one[2][0]; \ one[2][0] = _t * _c - one[2][1] * _s; \ one[2][1] = _t * _s + one[2][1] * _c; \ _t = one[3][0]; \ one[3][0] = _t * _c - one[3][1] * _s; \ one[3][1] = _t * _s + one[3][1] * _c; \ _t = two[0][0]; \ two[0][0] = _t * _c - two[1][0] * _s; \ two[1][0] = _t * _s + two[1][0] * _c; \ _t = two[0][1]; \ two[0][1] = _t * _c - two[1][1] * _s; \ two[1][1] = _t * _s + two[1][1] * _c; \ _t = two[0][2]; \ two[0][2] = _t * _c - two[1][2] * _s; \ two[1][2] = _t * _s + two[1][2] * _c; \ } #define m3scale(xs,ys,zs,one,two) \ { \ double _x = 1.0 / (xs); \ double _y = 1.0 / (ys); \ double _z = 1.0 / (zs); \ \ one[0][0] *= xs; \ one[0][1] *= ys; \ one[0][2] *= zs; \ one[1][0] *= xs; \ one[1][1] *= ys; \ one[1][2] *= zs; \ one[2][0] *= xs; \ one[2][1] *= ys; \ one[2][2] *= zs; \ one[3][0] *= xs; \ one[3][1] *= ys; \ one[3][2] *= zs; \ two[0][0] *= _x; \ two[0][1] *= _x; \ two[0][2] *= _x; \ two[1][0] *= _y; \ two[1][1] *= _y; \ two[1][2] *= _y; \ two[2][0] *= _z; \ two[2][1] *= _z; \ two[2][2] *= _z; \ } #ifdef NEVER #define m3mmulm(m1,m2,m)\ {\ m[0][0] =m1[0][0] * m2[0][0] + m1[0][1] * m2[1][0] +\ m1[0][2] * m2[2][0];\ m[0][1] =m1[0][0] * m2[0][1] + m1[0][1] * m2[1][1] +\ m1[0][2] * m2[2][1];\ m[0][2] =m1[0][0] * m2[0][2] + m1[0][1] * m2[1][2] +\ m1[0][2] * m2[2][2];\ m[1][0] =m1[1][0] * m2[0][0] + m1[1][1] * m2[1][0] +\ m1[1][2] * m2[2][0];\ m[1][1] =m1[1][0] * m2[0][1] + m1[1][1] * m2[1][1] +\ m1[1][2] * m2[2][1];\ m[1][2] =m1[1][0] * m2[0][2] + m1[1][1] * m2[1][2] +\ m1[1][2] * m2[2][2];\ m[2][0] =m1[2][0] * m2[0][0] + m1[2][1] * m2[1][0] +\ m1[2][2] * m2[2][0];\ m[2][1] =m1[2][0] * m2[0][1] + m1[2][1] * m2[1][1] +\ m1[2][2] * m2[2][1];\ m[2][2] =m1[2][0] * m2[0][2] + m1[2][1] * m2[1][2] +\ m1[2][2] * m2[2][2];\ m[3][0] =m1[3][0] * m2[0][0] + m1[3][1] * m2[1][0] +\ m1[3][2] * m2[2][0] + m2[3][0];\ m[3][1] =m1[3][0] * m2[0][1] + m1[3][1] * m2[1][1] +\ m1[3][2] * m2[2][1] + m2[3][1];\ m[3][2] =m1[3][0] * m2[0][2] + m1[3][1] * m2[1][2] +\ m1[3][2] * m2[2][2] + m2[3][2];\ } #endif #define m3unit(m)\ { \ m[0][0] = 1.0; m[0][1] = 0.0; m[0][2] = 0.0; \ m[1][0] = 0.0; m[1][1] = 1.0; m[1][2] = 0.0; \ m[2][0] = 0.0; m[2][1] = 0.0; m[2][2] = 1.0; \ m[3][0] = 0.0; m[3][1] = 0.0; m[3][2] = 0.0; \ } #define m3copy(m,m1)\ { \ m1[0][0] = m[0][0]; m1[0][1] = m[0][1]; m1[0][2] = m[0][2]; \ m1[1][0] = m[1][0]; m1[1][1] = m[1][1]; m1[1][2] = m[1][2]; \ m1[2][0] = m[2][0]; m1[3][1] = m[3][1]; m1[2][2] = m[2][2]; \ m1[3][0] = m[3][0]; m1[3][1] = m[3][1]; m1[3][2] = m[3][2]; \ } #define m4unit(m)\ { \ m[0][0] = 1.0; m[0][1] = 0.0; m[0][2] = 0.0; m[0][3] = 0.0; \ m[1][0] = 0.0; m[1][1] = 1.0; m[1][2] = 0.0; m[1][3] = 0.0; \ m[2][0] = 0.0; m[2][1] = 0.0; m[2][2] = 1.0; m[2][3] = 1.0; \ m[3][0] = 0.0; m[3][1] = 0.0; m[3][2] = 0.0; m[3][3] = 0.0; \ } #define m4copy(m,m1)\ { \ m1[0][0] = m[0][0]; m1[0][1] = m[0][1]; \ m1[0][2] = m[0][2]; m1[0][3] = m[0][3]; \ m1[1][0] = m[1][0]; m1[1][1] = m[1][1]; \ m1[1][2] = m[1][2]; m1[1][3] = m[1][3]; \ m1[2][0] = m[2][0]; m1[3][1] = m[3][1]; \ m1[2][2] = m[2][2]; m1[2][3] = m[2][3]; \ m1[3][0] = m[3][0]; m1[3][1] = m[3][1]; \ m1[3][2] = m[3][2]; m1[3][3] = m[3][3]; \ } typedef double mat3[4][3]; typedef double mat4[4][4]; /******************************** prototypes ******************************/ double calc_side(TPoint2f *v1,TPoint2f *v2,TPoint2f *p2); int isonline(TPoint2f *x,TPoint2f *a,TPoint2f *b); int inside_poly2(TPoly2 *ep,TPoint2f *point2); int clip2poly2(TPoly2 *ep,TPoint2f *p1,TPoint2f *p2); m[2][0]; m1[3][1] = m[3][1]; \ m1[2][2] = m[2][2]; m1[2][3] = m[2][3]; \ m1[3][0] = m[3][0]; m1[3][1] = m[3][1]; \ m1[3][2] = m[3][2]; m1[3][3] = m[3][3]; \ } typedef double mat3[4][3]; typedef douFxfire/Fir/000755 000316 000311 00000000000 06114643463 012650 5ustar00wrzlgup000000 000000 Fxfire/Fir/c1.fir000644 000316 000311 00000007602 06114616617 013663 0ustar00wrzlgup000000 000000 % the cornell room camera eye 108 120 400 lookat 108 100 100 up 0 1 0 fov 60 60 clip 1 550 resolution 200 200 parameters threshold 0.004 adaptive_max_subdiv 7 adaptive_threshold 0.5 visibility_rays 4 radiosity_threshold 0.01 minumum_area 10 points 32 0 0 0 216 0 0 216 0 215 0 0 215 0 221 0 216 221 0 216 221 215 0 221 215 85.5 220 90 130.5 220 90 130.5 220 130 85.5 220 130 53.104 0 64.104 109.36 0 96.604 76.86 0 152.896 20.604 0 120.396 53.104 65 64.104 109.36 65 96.604 76.86 65 152.896 20.604 65 120.396 134.104 0 67.104 190.396 0 99.604 157.896 0 155.896 101.604 0 123.396 134.104 130 67.104 190.396 130 99.604 157.896 130 155.896 101.604 130 123.396 85.5 220.01 90 130.5 220.01 90 130.5 220.01 130 85.5 220.01 130 polys 18 4 vertices 4 5 6 7 % ceiling patch_level 2 element_level 2 normal 0 -1 0 diffuse 0.9 0.9 0.9 4 vertices 0 3 2 1 % floor patch_level 1 element_level 1 normal 0 1 0 diffuse 0.9 0.9 0.9 4 vertices 0 4 7 3 % left wall patch_level 2 element_level 2 normal 1 0 0 diffuse 0.8 0.1 0.075 4 vertices 0 1 5 4 % back wall patch_level 2 element_level 2 normal 0 0 1 diffuse 0.9 0.9 0.9 4 vertices 2 6 5 1 % right wall patch_level 2 element_level 2 normal -1 0 0 diffuse 0.075 0.1 0.35 4 vertices 8 9 10 11 % light patch_level 2 element_level 2 normal 0 -1 0 diffuse 0 0 0 emission 1 1 1 4 vertices 28 31 30 29 % backside of light patch_level 1 element_level 1 normal 0 1 0 diffuse 0 0 0 4 vertices 16 19 18 17 % box 1 patch_level 1 element_level 1 normal 0 1 0 diffuse 0.9 0.8 0.1 % 4 vertices 12 13 14 15 % patch_level 1 % element_level 1 % normal 0 -1 0 % diffuse 0 0 0 4 vertices 12 15 19 16 patch_level 1 element_level 1 normal -0.866 0 -0.5 diffuse 0.9 0.8 0.1 4 vertices 12 16 17 13 patch_level 1 element_level 1 normal 0.5 0 -0.866 diffuse 0.9 0.8 0.1 4 vertices 14 13 17 18 patch_level 1 element_level 1 normal 0.866 0 0.5 diffuse 0.9 0.8 0.1 4 vertices 14 18 19 15 patch_level 1 element_level 1 normal -0.5 0 0.866 diffuse 0.9 0.8 0.1 4 vertices 24 27 26 25 % box 2 patch_level 1 element_level 1 normal 0 1 0 diffuse 0.9 0.9 0.9 % 4 vertices 20 21 22 23 % patch_level 1 % element_level 1 % normal 0 -1 0 % diffuse 0 0 0 4 vertices 20 23 27 24 patch_level 1 element_level 1 normal -0.866 0 -0.5 diffuse 0.9 0.9 0.9 4 vertices 20 24 25 21 patch_level 1 element_level 1 normal 0.5 0 -0.866 diffuse 0.9 0.9 0.9 4 vertices 22 21 25 26 patch_level 1 element_level 1 normal 0.866 0 0.5 diffuse 0.9 0.9 0.9 4 vertices 22 26 27 23 patch_level 1 element_level 1 normal -0.5 0 0.866 diffuse 0.9 0.9 0.9 4 vertices 3 7 6 2 % front wall patch_level 2 element_level 2 normal 0 0 -1 diffuse 0 0 0 end l 1 normal 0.5 0 -0.866 diffuse 0.9 0.9 0.9 4 vertices 22 21 25 26 patch_level 1 Fxfire/Fir/clip.fir000644 000316 000311 00000001504 06114616617 014302 0ustar00wrzlgup000000 000000 % simple test scene camera eye 50 0 100 lookat 50 150 0 up 0 0 1 fov 100 100 clip 1 550 resolution 200 200 parameters threshold 0.004 adaptive_max_subdiv 4 adaptive_threshold 0.1 visibility_rays 1 radiosity_threshold 0.5 minumum_area 10000 points 8 0 0 0 100 0 0 100 100 0 0 100 0 0 200 -25 100 200 -25 100 200 75 0 200 75 polys 2 4 vertices 0 1 2 3 % polygon patch_level 1 element_level 4 normal 0 0 1 diffuse 0.3 0.3 0 4 vertices 4 5 6 7 % light patch_level 1 element_level 1 normal 0 -1 0 diffuse 0 0 0 emission 1 1 1 end reshold 0.5 minumum_area 10000 points 8 0 0 0 100 0 0 100 100 0 0 100 0 0 200 -25 100 200 -25 100 200 75 0 200 75 polys 2 Fxfire/Fir/corn.fir000644 000316 000311 00000007570 06114616617 014325 0ustar00wrzlgup000000 000000 % the cornell room camera eye 108 120 400 lookat 108 100 100 up 0 1 0 fov 60 60 clip 1 550 resolution 200 200 parameters threshold 0.004 adaptive_max_subdiv 7 adaptive_threshold 0.5 visibility_rays 4 radiosity_threshold 0.01 minumum_area 10 points 32 0 0 0 216 0 0 216 0 215 0 0 215 0 221 0 216 221 0 216 221 215 0 221 215 85.5 220 90 130.5 220 90 130.5 220 130 85.5 220 130 53.104 0 64.104 109.36 0 96.604 76.86 0 152.896 20.604 0 120.396 53.104 65 64.104 109.36 65 96.604 76.86 65 152.896 20.604 65 120.396 134.104 0 67.104 190.396 0 99.604 157.896 0 155.896 101.604 0 123.396 134.104 130 67.104 190.396 130 99.604 157.896 130 155.896 101.604 130 123.396 85.5 220.01 90 130.5 220.01 90 130.5 220.01 130 85.5 220.01 130 polys 20 4 vertices 4 5 6 7 % ceiling patch_level 2 element_level 4 normal 0 -1 0 diffuse 0.9 0.9 0.9 4 vertices 0 3 2 1 % floor patch_level 3 element_level 5 normal 0 1 0 diffuse 0.9 0.9 0.9 4 vertices 0 4 7 3 % left wall patch_level 2 element_level 4 normal 1 0 0 diffuse 0.8 0.1 0.075 4 vertices 0 1 5 4 % back wall patch_level 2 element_level 4 normal 0 0 1 diffuse 0.9 0.9 0.9 4 vertices 2 6 5 1 % right wall patch_level 2 element_level 4 normal -1 0 0 diffuse 0.075 0.1 0.35 4 vertices 8 9 10 11 % light patch_level 2 element_level 2 normal 0 -1 0 diffuse 0 0 0 emission 1 1 1 4 vertices 28 31 30 29 % backside of light patch_level 1 element_level 1 normal 0 1 0 diffuse 0 0 0 4 vertices 16 19 18 17 % box 1 patch_level 1 element_level 4 normal 0 1 0 diffuse 0.9 0.8 0.1 4 vertices 12 13 14 15 patch_level 1 element_level 1 normal 0 -1 0 diffuse 0 0 0 4 vertices 12 15 19 16 patch_level 1 element_level 4 normal -0.866 0 -0.5 diffuse 0.9 0.8 0.1 4 vertices 12 16 17 13 patch_level 1 element_level 4 normal 0.5 0 -0.866 diffuse 0.9 0.8 0.1 4 vertices 14 13 17 18 patch_level 1 element_level 4 normal 0.866 0 0.5 diffuse 0.9 0.8 0.1 4 vertices 14 18 19 15 patch_level 1 element_level 4 normal -0.5 0 0.866 diffuse 0.9 0.8 0.1 4 vertices 24 27 26 25 % box 2 patch_level 1 element_level 4 normal 0 1 0 diffuse 0.9 0.9 0.9 4 vertices 20 21 22 23 patch_level 1 element_level 1 normal 0 -1 0 diffuse 0 0 0 4 vertices 20 23 27 24 patch_level 1 element_level 4 normal -0.866 0 -0.5 diffuse 0.9 0.9 0.9 4 vertices 20 24 25 21 patch_level 1 element_level 4 normal 0.5 0 -0.866 diffuse 0.9 0.9 0.9 4 vertices 22 21 25 26 patch_level 1 element_level 4 normal 0.866 0 0.5 diffuse 0.9 0.9 0.9 4 vertices 22 26 27 23 patch_level 1 element_level 4 normal -0.5 0 0.866 diffuse 0.9 0.9 0.9 4 vertices 3 7 6 2 % front wall patch_level 2 element_level 2 normal 0 0 -1 diffuse 0 0 0 end l 4 normal 0.5 0 -0.866 diffuse 0.9 0.9 0.9 4 vertices 22 21 25 26 patch_level 1 elemenFxfire/Fir/corn1.fir000644 000316 000311 00000005626 06114616617 014406 0ustar00wrzlgup000000 000000 camera eye 3500 -3500 1700 lookat 2000 2000 1300 up 0 0 1 fov 45 45 clip 1 100000 resolution 200 200 parameters threshold 0.00004 adaptive_max_subdiv 4 adaptive_threshold 0.1 visibility_rays 4 radiosity_threshold 0.01 minumum_area 10 points 28 0 0 0 216 0 0 216 0 215 0 0 215 0 221 0 216 221 0 216 221 215 0 221 215 85.5 219.5 90 130.5 219.5 90 130.5 219.5 130 85.5 219.5 130 53.104 0 64.104 109.36 0 96.604 76.86 0 152.896 20.604 0 120.396 53.104 65 64.104 109.36 65 96.604 76.86 65 152.896 20.604 65 120.396 134.104 0 67.104 190.396 0 99.604 157.896 0 155.896 101.604 0 123.396 134.104 130 67.104 190.396 130 99.604 157.896 130 155.896 101.604 130 123.396 polys 20 4 vertices 4 5 6 7 identifier 1 patch_level 3 element_level 5 normal 0 -1 0 diffuse 0.9 0.9 0.9 4 vertices 0 3 2 1 identifier 2 patch_level 3 element_level 5 normal 0 1 0 diffuse 0.9 0.9 0.9 4 vertices 0 4 7 3 identifier 3 patch_level 3 element_level 5 normal 1 0 0 diffuse 0.8 0.1 0.075 4 vertices 0 1 5 4 identifier 4 patch_level 3 element_level 5 normal 0 0 1 diffuse 0.9 0.9 0.9 4 vertices 1 2 6 5 identifier 5 patch_level 3 element_level 5 normal -1 0 0 diffuse 0.075 0.1 0.35 4 vertices 8 9 10 11 identifier 6 patch_level 1 element_level 2 normal 0 -1 0 diffuse 0 0 0 emission 1.000000 1.000000 1.000000 4 vertices 8 11 10 9 identifier 7 patch_level 1 element_level 2 normal 0 1 0 diffuse 0 0 0 4 vertices 16 19 18 17 identifier 8 patch_level 1 element_level 3 normal 0 1 0 diffuse 0.9 0.8 0.1 4 vertices 12 13 14 15 identifier 9 patch_level 1 element_level 3 normal 0 -1 0 diffuse 0.9 0.8 0.1 4 vertices 12 15 19 16 identifier 10 patch_level 1 element_level 3 normal -0.866027 0 -0.499998 diffuse 0.9 0.8 0.1 4 vertices 12 16 17 13 identifier 11 patch_level 1 element_level 3 normal 0.500238 0 -0.865888 diffuse 0.9 0.8 0.1 4 vertices 13 17 18 14 identifier 12 patch_level 1 element_level 3 normal 0.866027 0 0.499998 diffuse 0.9 0.8 0.1 4 vertices 14 18 19 15 identifier 13 patch_level 1 element_level 3 normal -0.500238 0 0.865888 diffuse 0.9 0.8 0.1 4 vertices 24 27 26 25 identifier 14 patch_level 1 element_level 3 normal 0 1 0 diffuse 0.9 0.9 0.9 4 vertices 20 21 22 23 identifier 15 patch_level 1 element_level 3 normal 0 -1 0 diffuse 0.9 0.9 0.9 4 vertices 20 23 27 24 identifier 16 patch_level 2 element_level 3 normal -0.866027 0 -0.499998 diffuse 0.9 0.9 0.9 4 vertices 20 24 25 21 identifier 17 patch_level 2 element_level 3 normal 0.499998 0 -0.866027 diffuse 0.9 0.9 0.9 4 vertices 21 25 26 22 identifier 18 patch_level 2 element_level 3 normal 0.866027 0 0.499998 diffuse 0.9 0.9 0.9 4 vertices 22 26 27 23 identifier 19 patch_level 2 element_level 3 normal -0.499998 0 0.866027 diffuse 0.9 0.9 0.9 4 vertices 2 3 7 6 identifier 20 patch_level 3 element_level 5 normal 0 0 -1 diffuse 0 0 0 end l 2 element_level 3 normal -0.866027 0 -0.499998 diffuse 0.9 0.9 0.9 4 vertices 20 24 25 21 identifier 17Fxfire/Fir/corn_coarse.fir000644 000316 000311 00000007570 06114616617 015661 0ustar00wrzlgup000000 000000 % the cornell room camera eye 108 120 400 lookat 108 100 100 up 0 1 0 fov 60 60 clip 1 550 resolution 200 200 parameters threshold 0.004 adaptive_max_subdiv 7 adaptive_threshold 0.5 visibility_rays 4 radiosity_threshold 0.01 minumum_area 10 points 32 0 0 0 216 0 0 216 0 215 0 0 215 0 221 0 216 221 0 216 221 215 0 221 215 85.5 220 90 130.5 220 90 130.5 220 130 85.5 220 130 53.104 0 64.104 109.36 0 96.604 76.86 0 152.896 20.604 0 120.396 53.104 65 64.104 109.36 65 96.604 76.86 65 152.896 20.604 65 120.396 134.104 0 67.104 190.396 0 99.604 157.896 0 155.896 101.604 0 123.396 134.104 130 67.104 190.396 130 99.604 157.896 130 155.896 101.604 130 123.396 85.5 220.01 90 130.5 220.01 90 130.5 220.01 130 85.5 220.01 130 polys 20 4 vertices 4 5 6 7 % ceiling patch_level 2 element_level 3 normal 0 -1 0 diffuse 0.9 0.9 0.9 4 vertices 0 3 2 1 % floor patch_level 3 element_level 4 normal 0 1 0 diffuse 0.9 0.9 0.9 4 vertices 0 4 7 3 % left wall patch_level 2 element_level 3 normal 1 0 0 diffuse 0.8 0.1 0.075 4 vertices 0 1 5 4 % back wall patch_level 2 element_level 3 normal 0 0 1 diffuse 0.9 0.9 0.9 4 vertices 2 6 5 1 % right wall patch_level 2 element_level 3 normal -1 0 0 diffuse 0.075 0.1 0.35 4 vertices 8 9 10 11 % light patch_level 2 element_level 1 normal 0 -1 0 diffuse 0 0 0 emission 1 1 1 4 vertices 28 31 30 29 % backside of light patch_level 1 element_level 1 normal 0 1 0 diffuse 0 0 0 4 vertices 16 19 18 17 % box 1 patch_level 1 element_level 2 normal 0 1 0 diffuse 0.9 0.8 0.1 4 vertices 12 13 14 15 patch_level 1 element_level 1 normal 0 -1 0 diffuse 0 0 0 4 vertices 12 15 19 16 patch_level 1 element_level 2 normal -0.866 0 -0.5 diffuse 0.9 0.8 0.1 4 vertices 12 16 17 13 patch_level 1 element_level 2 normal 0.5 0 -0.866 diffuse 0.9 0.8 0.1 4 vertices 14 13 17 18 patch_level 1 element_level 2 normal 0.866 0 0.5 diffuse 0.9 0.8 0.1 4 vertices 14 18 19 15 patch_level 1 element_level 2 normal -0.5 0 0.866 diffuse 0.9 0.8 0.1 4 vertices 24 27 26 25 % box 2 patch_level 1 element_level 2 normal 0 1 0 diffuse 0.9 0.9 0.9 4 vertices 20 21 22 23 patch_level 1 element_level 1 normal 0 -1 0 diffuse 0 0 0 4 vertices 20 23 27 24 patch_level 1 element_level 2 normal -0.866 0 -0.5 diffuse 0.9 0.9 0.9 4 vertices 20 24 25 21 patch_level 1 element_level 2 normal 0.5 0 -0.866 diffuse 0.9 0.9 0.9 4 vertices 22 21 25 26 patch_level 1 element_level 2 normal 0.866 0 0.5 diffuse 0.9 0.9 0.9 4 vertices 22 26 27 23 patch_level 1 element_level 2 normal -0.5 0 0.866 diffuse 0.9 0.9 0.9 4 vertices 3 7 6 2 % front wall patch_level 2 element_level 2 normal 0 0 -1 diffuse 0 0 0 end l 2 normal 0.5 0 -0.866 diffuse 0.9 0.9 0.9 4 vertices 22 21 25 26 patch_level 1 elemenFxfire/Fir/corntri.fir000644 000316 000311 00000015216 06114616617 015040 0ustar00wrzlgup000000 000000 % the cornell room camera eye 108 120 400 lookat 108 100 100 up 0 1 0 fov 60 60 clip 1 550 resolution 200 200 parameters threshold 0.004 adaptive_max_subdiv 8 adaptive_threshold 0.1 visibility_rays 4 radiosity_threshold 0.01 minumum_area 10 points 32 0 0 0 216 0 0 216 0 215 0 0 215 0 221 0 216 221 0 216 221 215 0 221 215 85.5 220 90 130.5 220 90 130.5 220 130 85.5 220 130 53.104 0 64.104 109.36 0 96.604 76.86 0 152.896 20.604 0 120.396 53.104 65 64.104 109.36 65 96.604 76.86 65 152.896 20.604 65 120.396 134.104 0 67.104 190.396 0 99.604 157.896 0 155.896 101.604 0 123.396 134.104 130 67.104 190.396 130 99.604 157.896 130 155.896 101.604 130 123.396 85.5 220 90 130.5 220 90 130.5 220 130 85.5 220 130 polys 40 3 vertices 4 6 7 % ceiling patch_level 2 element_level 4 normal 0 -1 0 diffuse 0.9 0.9 0.9 3 vertices 4 5 6 % ceiling patch_level 2 element_level 4 normal 0 -1 0 diffuse 0.9 0.9 0.9 3 vertices 0 2 1 % floor patch_level 3 element_level 5 normal 0 1 0 diffuse 0.9 0.9 0.9 3 vertices 0 3 2 % floor patch_level 3 element_level 5 normal 0 1 0 diffuse 0.9 0.9 0.9 3 vertices 0 7 3 % left wall patch_level 2 element_level 4 normal 1 0 0 diffuse 0.8 0.1 0.075 3 vertices 0 4 7 % left wall patch_level 2 element_level 4 normal 1 0 0 diffuse 0.8 0.1 0.075 3 vertices 0 5 4 % back wall patch_level 2 element_level 4 normal 0 0 1 diffuse 0.9 0.9 0.9 3 vertices 0 1 5 % back wall patch_level 2 element_level 4 normal 0 0 1 diffuse 0.9 0.9 0.9 3 vertices 2 5 1 % right wall patch_level 2 element_level 4 normal -1 0 0 diffuse 0.075 0.1 0.35 3 vertices 2 6 5 % right wall patch_level 2 element_level 4 normal -1 0 0 diffuse 0.075 0.1 0.35 3 vertices 8 10 11 % light patch_level 2 element_level 2 normal 0 -1 0 diffuse 0 0 0 emission 1 1 1 3 vertices 8 9 10 % light patch_level 2 element_level 2 normal 0 -1 0 diffuse 0 0 0 emission 1 1 1 3 vertices 28 30 29 % backside of light patch_level 1 element_level 1 normal 0 1 0 diffuse 0 0 0 3 vertices 28 31 30 % backside light patch_level 1 element_level 1 normal 0 1 0 diffuse 0 0 0 3 vertices 16 18 17 % box 1 patch_level 1 element_level 4 normal 0 1 0 diffuse 0.9 0.8 0.1 3 vertices 16 19 18 % box 1 patch_level 1 element_level 4 normal 0 1 0 diffuse 0.9 0.8 0.1 3 vertices 12 14 15 patch_level 1 element_level 1 normal 0 -1 0 diffuse 0 0 0 3 vertices 12 13 14 patch_level 1 element_level 1 normal 0 -1 0 diffuse 0 0 0 3 vertices 12 19 16 patch_level 1 element_level 4 normal -0.866 0 -0.5 diffuse 0.9 0.8 0.1 3 vertices 12 15 19 patch_level 1 element_level 4 normal -0.866 0 -0.5 diffuse 0.9 0.8 0.1 3 vertices 12 17 13 patch_level 1 element_level 4 normal 0.5 0 -0.866 diffuse 0.9 0.8 0.1 3 vertices 12 16 17 patch_level 1 element_level 4 normal 0.5 0 -0.866 diffuse 0.9 0.8 0.1 3 vertices 14 17 18 patch_level 1 element_level 4 normal 0.866 0 0.5 diffuse 0.9 0.8 0.1 3 vertices 14 13 17 patch_level 1 element_level 4 normal 0.866 0 0.5 diffuse 0.9 0.8 0.1 3 vertices 14 19 15 patch_level 1 element_level 4 normal -0.5 0 0.866 diffuse 0.9 0.8 0.1 3 vertices 14 18 19 patch_level 1 element_level 4 normal -0.5 0 0.866 diffuse 0.9 0.8 0.1 3 vertices 24 26 25 % box 2 patch_level 1 element_level 4 normal 0 1 0 diffuse 0.9 0.9 0.9 3 vertices 24 27 26 % box 2 patch_level 1 element_level 4 normal 0 1 0 diffuse 0.9 0.9 0.9 3 vertices 20 22 23 patch_level 1 element_level 1 normal 0 -1 0 diffuse 0 0 0 3 vertices 20 21 22 patch_level 1 element_level 1 normal 0 -1 0 diffuse 0 0 0 3 vertices 20 27 24 patch_level 1 element_level 4 normal -0.866 0 -0.5 diffuse 0.9 0.9 0.9 3 vertices 20 23 27 patch_level 1 element_level 4 normal -0.866 0 -0.5 diffuse 0.9 0.9 0.9 3 vertices 20 25 21 patch_level 1 element_level 4 normal 0.5 0 -0.866 diffuse 0.9 0.9 0.9 3 vertices 20 24 25 patch_level 1 element_level 4 normal 0.5 0 -0.866 diffuse 0.9 0.9 0.9 3 vertices 22 25 26 patch_level 1 element_level 4 normal 0.866 0 0.5 diffuse 0.9 0.9 0.9 3 vertices 22 21 25 patch_level 1 element_level 4 normal 0.866 0 0.5 diffuse 0.9 0.9 0.9 3 vertices 22 27 23 patch_level 1 element_level 4 normal -0.5 0 0.866 diffuse 0.9 0.9 0.9 3 vertices 22 26 27 patch_level 1 element_level 4 normal -0.5 0 0.866 diffuse 0.9 0.9 0.9 3 vertices 3 6 2 % front wall patch_level 2 element_level 2 normal 0 0 -1 diffuse 0 0 0 3 vertices 3 7 6 % front wall patch_level 2 element_level 2 normal 0 0 -1 diffuse 0 0 0 end 4 normal -0.5 0 0.866 diffuse 0.9 0.9 0.9 3 vertices 22 26 27 patch_level 1 element_level 4 normal -0.5 0 0.866 diffuse 0.9 0.9 0.9 3 vertices 3 6 2 % front wall patch_level 2 element_level 2 normal 0 0 -1 diffuse 0 0 0 3 verticeFxfire/Fir/cornx.fir000644 000316 000311 00000005661 06114616617 014514 0ustar00wrzlgup000000 000000 camera eye 3500 -3500 1700 lookat 2000 2000 1300 up 0 0 1 fov 45 45 clip 1 100000 resolution 200 200 parameters threshold 0.004 adaptive_max_subdiv 4 adaptive_threshold 0.1 visibility_rays 4 radiosity_threshold 0.01 minumum_area 10 points 32 0 0 0 216 0 0 216 0 215 0 0 215 0 221 0 216 221 0 216 221 215 0 221 215 85.5 219 90 130.5 219 90 130.5 219 130 85.5 219 130 53.104 0 64.104 109.36 0 96.604 76.86 0 152.896 20.604 0 120.396 53.104 65 64.104 109.36 65 96.604 76.86 65 152.896 20.604 65 120.396 134.104 0 67.104 190.396 0 99.604 157.896 0 155.896 101.604 0 123.396 134.104 130 67.104 190.396 130 99.604 157.896 130 155.896 101.604 130 123.396 85.5 220 90 130.5 220 90 130.5 220 130 85.5 220 130 polys 20 4 vertices 4 5 6 7 identifier 1 patch_level 3 element_level 5 normal 0 -1 0 diffuse 0.9 0.9 0.9 4 vertices 0 3 2 1 identifier 2 patch_level 3 element_level 5 normal 0 1 0 diffuse 0.9 0.9 0.9 4 vertices 0 4 7 3 identifier 3 patch_level 3 element_level 5 normal 1 0 0 diffuse 0.8 0.1 0.075 4 vertices 0 1 5 4 identifier 4 patch_level 3 element_level 5 normal 0 0 1 diffuse 0.9 0.9 0.9 4 vertices 1 2 6 5 identifier 5 patch_level 3 element_level 5 normal -1 0 0 diffuse 0.075 0.1 0.35 4 vertices 8 9 10 11 identifier 6 patch_level 1 element_level 1 normal 0 -1 0 diffuse 0 0 0 emission 1 1 1 4 vertices 28 31 30 29 identifier 7 patch_level 1 element_level 2 normal 0 1 0 diffuse 0 0 0 4 vertices 16 19 18 17 identifier 8 patch_level 1 element_level 3 normal 0 1 0 diffuse 0.9 0.8 0.1 4 vertices 12 13 14 15 identifier 9 patch_level 1 element_level 3 normal 0 -1 0 diffuse 0.9 0.8 0.1 4 vertices 12 15 19 16 identifier 10 patch_level 1 element_level 3 normal -0.866027 0 -0.499998 diffuse 0.9 0.8 0.1 4 vertices 12 16 17 13 identifier 11 patch_level 1 element_level 3 normal 0.500238 0 -0.865888 diffuse 0.9 0.8 0.1 4 vertices 13 17 18 14 identifier 12 patch_level 1 element_level 3 normal 0.866027 0 0.499998 diffuse 0.9 0.8 0.1 4 vertices 14 18 19 15 identifier 13 patch_level 1 element_level 3 normal -0.500238 0 0.865888 diffuse 0.9 0.8 0.1 4 vertices 24 27 26 25 identifier 14 patch_level 1 element_level 3 normal 0 1 0 diffuse 0.9 0.9 0.9 4 vertices 20 21 22 23 identifier 15 patch_level 1 element_level 3 normal 0 -1 0 diffuse 0.9 0.9 0.9 4 vertices 20 23 27 24 identifier 16 patch_level 2 element_level 3 normal -0.866027 0 -0.499998 diffuse 0.9 0.9 0.9 4 vertices 20 24 25 21 identifier 17 patch_level 2 element_level 3 normal 0.499998 0 -0.866027 diffuse 0.9 0.9 0.9 4 vertices 21 25 26 22 identifier 18 patch_level 2 element_level 3 normal 0.866027 0 0.499998 diffuse 0.9 0.9 0.9 4 vertices 22 26 27 23 identifier 19 patch_level 2 element_level 3 normal -0.499998 0 0.866027 diffuse 0.9 0.9 0.9 4 vertices 2 3 7 6 identifier 20 patch_level 3 element_level 5 normal 0 0 -1 diffuse 0 0 0 end l 2 element_level 3 normal -0.866027 0 -0.499998 diffuse 0.9 0.9 0.9 4 verticesFxfire/Fir/disco.fir000644 000316 000311 00000007570 06114616613 014461 0ustar00wrzlgup000000 000000 % the cornell room camera eye 108 120 400 lookat 108 100 100 up 0 1 0 fov 60 60 clip 1 550 resolution 200 200 parameters threshold 0.004 adaptive_max_subdiv 7 adaptive_threshold 0.5 visibility_rays 4 radiosity_threshold 0.01 minumum_area 10 points 32 0 0 0 216 0 0 216 0 215 0 0 215 0 221 0 216 221 0 216 221 215 0 221 215 85.5 220 90 130.5 220 90 130.5 220 130 85.5 220 130 53.104 0 64.104 109.36 0 96.604 76.86 0 152.896 20.604 0 120.396 53.104 65 64.104 109.36 65 96.604 76.86 65 152.896 20.604 65 120.396 134.104 0 67.104 190.396 0 99.604 157.896 0 155.896 101.604 0 123.396 134.104 130 67.104 190.396 130 99.604 157.896 130 155.896 101.604 130 123.396 85.5 220.01 90 130.5 220.01 90 130.5 220.01 130 85.5 220.01 130 polys 20 4 vertices 4 5 6 7 % ceiling patch_level 2 element_level 4 normal 0 -1 0 diffuse 0.9 0.9 0.9 4 vertices 0 3 2 1 % floor patch_level 3 element_level 3 normal 0 1 0 diffuse 0.9 0.9 0.9 4 vertices 0 4 7 3 % left wall patch_level 2 element_level 4 normal 1 0 0 diffuse 0.8 0.1 0.075 4 vertices 0 1 5 4 % back wall patch_level 2 element_level 4 normal 0 0 1 diffuse 0.9 0.9 0.9 4 vertices 2 6 5 1 % right wall patch_level 2 element_level 4 normal -1 0 0 diffuse 0.075 0.1 0.35 4 vertices 8 9 10 11 % light patch_level 2 element_level 2 normal 0 -1 0 diffuse 0 0 0 emission 1 1 1 4 vertices 28 31 30 29 % backside of light patch_level 1 element_level 1 normal 0 1 0 diffuse 0 0 0 4 vertices 16 19 18 17 % box 1 patch_level 1 element_level 4 normal 0 1 0 diffuse 0.9 0.8 0.1 4 vertices 12 13 14 15 patch_level 1 element_level 1 normal 0 -1 0 diffuse 0 0 0 4 vertices 12 15 19 16 patch_level 1 element_level 4 normal -0.866 0 -0.5 diffuse 0.9 0.8 0.1 4 vertices 12 16 17 13 patch_level 1 element_level 4 normal 0.5 0 -0.866 diffuse 0.9 0.8 0.1 4 vertices 14 13 17 18 patch_level 1 element_level 4 normal 0.866 0 0.5 diffuse 0.9 0.8 0.1 4 vertices 14 18 19 15 patch_level 1 element_level 4 normal -0.5 0 0.866 diffuse 0.9 0.8 0.1 4 vertices 24 27 26 25 % box 2 patch_level 1 element_level 4 normal 0 1 0 diffuse 0.9 0.9 0.9 4 vertices 20 21 22 23 patch_level 1 element_level 1 normal 0 -1 0 diffuse 0 0 0 4 vertices 20 23 27 24 patch_level 1 element_level 4 normal -0.866 0 -0.5 diffuse 0.9 0.9 0.9 4 vertices 20 24 25 21 patch_level 1 element_level 4 normal 0.5 0 -0.866 diffuse 0.9 0.9 0.9 4 vertices 22 21 25 26 patch_level 1 element_level 4 normal 0.866 0 0.5 diffuse 0.9 0.9 0.9 4 vertices 22 26 27 23 patch_level 1 element_level 4 normal -0.5 0 0.866 diffuse 0.9 0.9 0.9 4 vertices 3 7 6 2 % front wall patch_level 2 element_level 2 normal 0 0 -1 diffuse 0 0 0 end l 4 normal 0.5 0 -0.866 diffuse 0.9 0.9 0.9 4 vertices 22 21 25 26 patch_level 1 elemenFxfire/Fir/shir.fir000644 000316 000311 00000010457 06114616602 014321 0ustar00wrzlgup000000 000000 % the cornell room camera eye 108 120 400 lookat 108 100 100 up 0 1 0 fov 60 60 clip 1 550 resolution 200 200 parameters threshold 0.004 adaptive_max_subdiv 6 adaptive_threshold 0.1 visibility_rays 16 radiosity_threshold 0.01 minumum_area 10 points 32 0 0 0 216 0 0 216 0 215 0 0 215 0 221 0 216 221 0 216 221 215 0 221 215 85.5 220 90 130.5 220 90 130.5 220 130 85.5 220 130 53.104 0 64.104 109.36 0 96.604 76.86 0 152.896 20.604 0 120.396 53.104 65 64.104 109.36 65 96.604 76.86 65 152.896 20.604 65 120.396 134.104 0 67.104 190.396 0 99.604 157.896 0 155.896 101.604 0 123.396 134.104 130 67.104 190.396 130 99.604 157.896 130 155.896 101.604 130 123.396 85.5 220.01 90 130.5 220.01 90 130.5 220.01 130 85.5 220.01 130 polys 20 4 vertices 4 5 6 7 % ceiling patch_level 2 element_level 3 normal 0 -1 0 diffuse 0.5 0.0 0.5 emission 1 0 1 4 vertices 0 3 2 1 % floor patch_level 2 element_level 5 normal 0 1 0 diffuse 0.5 0.0 0.5 emission 1 0 1 4 vertices 0 4 7 3 % left wall patch_level 2 element_level 3 normal 1 0 0 diffuse 0.5 0.0 0.5 emission 1 0 1 4 vertices 0 1 5 4 % back wall patch_level 2 element_level 3 normal 0 0 1 diffuse 0.5 0.0 0.5 emission 1 0 1 4 vertices 2 6 5 1 % right wall patch_level 2 element_level 3 normal -1 0 0 diffuse 0.5 0.0 0.5 emission 1 0 1 4 vertices 8 9 10 11 % light patch_level 2 element_level 3 normal 0 -1 0 diffuse 0.5 0.0 0.5 emission 1 0 1 4 vertices 28 31 30 29 % backside of light patch_level 1 element_level 1 normal 0 1 0 diffuse 0 0 0 4 vertices 16 19 18 17 % box 1 patch_level 1 element_level 3 normal 0 1 0 diffuse 0.5 0.0 0.5 emission 1 0 1 4 vertices 12 13 14 15 patch_level 1 element_level 1 normal 0 -1 0 diffuse 0 0 0 4 vertices 12 15 19 16 patch_level 1 element_level 3 normal -0.866 0 -0.5 diffuse 0.5 0.0 0.5 emission 1 0 1 4 vertices 12 16 17 13 patch_level 1 element_level 3 normal 0.5 0 -0.866 diffuse 0.5 0.0 0.5 emission 1 0 1 4 vertices 14 13 17 18 patch_level 1 element_level 3 normal 0.866 0 0.5 diffuse 0.5 0.0 0.5 emission 1 0 1 4 vertices 14 18 19 15 patch_level 1 element_level 3 normal -0.5 0 0.866 diffuse 0.5 0.0 0.5 emission 1 0 1 4 vertices 24 27 26 25 % box 2 patch_level 1 element_level 3 normal 0 1 0 diffuse 0.5 0.0 0.5 emission 1 0 1 4 vertices 20 21 22 23 patch_level 1 element_level 1 normal 0 -1 0 diffuse 0 0 0 4 vertices 20 23 27 24 patch_level 1 element_level 3 normal -0.866 0 -0.5 diffuse 0.5 0.0 0.5 emission 1 0 1 4 vertices 20 24 25 21 patch_level 1 element_level 3 normal 0.5 0 -0.866 diffuse 0.5 0.0 0.5 emission 1 0 1 4 vertices 22 21 25 26 patch_level 1 element_level 3 normal 0.866 0 0.5 diffuse 0.5 0.0 0.5 emission 1 0 1 4 vertices 22 26 27 23 patch_level 1 element_level 3 normal -0.5 0 0.866 diffuse 0.5 0.0 0.5 emission 1 0 1 4 vertices 3 7 6 2 % front wall patch_level 2 element_level 3 normal 0 0 -1 diffuse 0.5 0.0 0.5 emission 1 0 1 end 22 21 25 26 patch_level 1 element_level 3 normal 0.866 0 0.5 diffuse 0.5 0.0 0.5 emission 1 0 1 4 vertices 22 26 27 23 patch_level 1 Fxfire/Fir/shirsimp.fir000644 000316 000311 00000003745 06114616602 015214 0ustar00wrzlgup000000 000000 % the cornell room camera eye 108 120 400 lookat 108 100 100 up 0 1 0 fov 60 60 clip 1 550 resolution 200 200 parameters threshold 0.0000004 adaptive_max_subdiv 6 adaptive_threshold 0.1 visibility_rays 4 radiosity_threshold 0.001 minumum_area 2000 points 28 0 0 0 216 0 0 216 0 215 0 0 215 0 221 0 216 221 0 216 221 215 0 221 215 85.5 220 90 130.5 220 90 130.5 220 130 85.5 220 130 53.104 0 64.104 109.36 0 96.604 76.86 0 152.896 20.604 0 120.396 53.104 65 64.104 109.36 65 96.604 76.86 65 152.896 20.604 65 120.396 134.104 0 67.104 190.396 0 99.604 157.896 0 155.896 101.604 0 123.396 134.104 130 67.104 190.396 130 99.604 157.896 130 155.896 101.604 130 123.396 polys 6 4 vertices 4 5 6 7 % ceiling patch_level 1 element_level 1 normal 0 -1 0 diffuse 0.5 0.0 0.5 emission 1 0 1 4 vertices 0 3 2 1 % floor patch_level 1 element_level 1 normal 0 1 0 diffuse 0.5 0.0 0.5 emission 1 0 1 4 vertices 0 4 7 3 % left wall patch_level 1 element_level 1 normal 1 0 0 diffuse 0.5 0.0 0.5 emission 1 0 1 4 vertices 0 1 5 4 % back wall patch_level 1 element_level 1 normal 0 0 1 diffuse 0.5 0.0 0.5 emission 1 0 1 4 vertices 2 6 5 1 % right wall patch_level 1 element_level 1 normal -1 0 0 diffuse 0.5 0.0 0.5 emission 1 0 1 4 vertices 3 7 6 2 % front wall patch_level 1 element_level 1 normal 0 0 -1 diffuse 0.5 0.0 0.5 emission 1 0 1 end back wall patch_level Fxfire/Fir/shirstri.fir000644 000316 000311 00000006012 06114616602 015213 0ustar00wrzlgup000000 000000 % the cornell room camera eye 108 120 400 lookat 108 100 100 up 0 1 0 fov 60 60 clip 1 550 resolution 200 200 parameters threshold 0.004 adaptive_max_subdiv 6 adaptive_threshold 0.1 visibility_rays 4 radiosity_threshold 0.01 minumum_area 2000 points 28 0 0 0 216 0 0 216 0 215 0 0 215 0 221 0 216 221 0 216 221 215 0 221 215 85.5 220 90 130.5 220 90 130.5 220 130 85.5 220 130 53.104 0 64.104 109.36 0 96.604 76.86 0 152.896 20.604 0 120.396 53.104 65 64.104 109.36 65 96.604 76.86 65 152.896 20.604 65 120.396 134.104 0 67.104 190.396 0 99.604 157.896 0 155.896 101.604 0 123.396 134.104 130 67.104 190.396 130 99.604 157.896 130 155.896 101.604 130 123.396 polys 12 3 vertices 4 6 7 % ceiling patch_level 1 element_level 1 normal 0 -1 0 diffuse 0.5 0.0 0.5 emission 1 0 1 3 vertices 4 5 6 % ceiling patch_level 1 element_level 1 normal 0 -1 0 diffuse 0.5 0.0 0.5 emission 1 0 1 3 vertices 0 2 1 % floor patch_level 1 element_level 1 normal 0 1 0 diffuse 0.5 0.0 0.5 emission 1 0 1 3 vertices 0 3 2 % floor patch_level 1 element_level 1 normal 0 1 0 diffuse 0.5 0.0 0.5 emission 1 0 1 3 vertices 0 7 3 % left wall patch_level 1 element_level 1 normal 1 0 0 diffuse 0.5 0.0 0.5 emission 1 0 1 3 vertices 0 4 7 % left wall patch_level 1 element_level 1 normal 1 0 0 diffuse 0.5 0.0 0.5 emission 1 0 1 3 vertices 0 5 4 % back wall patch_level 1 element_level 1 normal 0 0 1 diffuse 0.5 0.0 0.5 emission 1 0 1 3 vertices 0 1 5 % back wall patch_level 1 element_level 1 normal 0 0 1 diffuse 0.5 0.0 0.5 emission 1 0 1 3 vertices 2 5 1 % right wall patch_level 1 element_level 1 normal -1 0 0 diffuse 0.5 0.0 0.5 emission 1 0 1 3 vertices 2 6 5 % right wall patch_level 1 element_level 1 normal -1 0 0 diffuse 0.5 0.0 0.5 emission 1 0 1 3 vertices 3 6 2 % front wall patch_level 1 element_level 1 normal 0 0 -1 diffuse 0.5 0.0 0.5 emission 1 0 1 3 vertices 3 7 6 % front wall patch_level 1 element_level 1 normal 0 0 -1 diffuse 0.5 0.0 0.5 emission 1 0 1 end % right wall patch_level 1 element_level 1 normal -1 0 0 diffuse 0.5 0.0 0.5 emission 1 0 1 3 vertices 3 6 2 % front wall patch_level 1 element_level 1 normal 0 0 -1 diffuse 0.5 0.0 0.5 emission 1 0 1 3 vertices 3 7 6 % front wall patch_level 1 element_level 1 normal 0 0 -1 diffuse 0.5 0.0 0.5 emission 1 Fxfire/Fir/t.fir000644 000316 000311 00000001500 06114616627 013613 0ustar00wrzlgup000000 000000 % simple test scene camera eye 160 60 9 lookat 50 50 5 up 0 0 1 fov 90 20 clip 1 550 resolution 200 200 parameters threshold 0.004 adaptive_max_subdiv 4 adaptive_threshold 0.1 visibility_rays 4 radiosity_threshold 0.01 minumum_area 10 points 8 25 25 10 75 25 10 75 75 10 25 75 10 0 0 0 100 0 0 100 100 0 0 100 0 polys 2 4 vertices 0 3 2 1 % light patch_level 1 element_level 1 normal 0 0 -1 diffuse 0 0 0 emission 1 1 1 4 vertices 4 5 6 7 % floor patch_level 1 element_level 4 normal 0 0 1 diffuse 0.3 0.3 0.9 end hreshold 0.01 minumum_area 10 points 8 25 25 10 75 25 10 75 75 10 25 75 10 0 0 0 100 0 0 100 100 0 0 100 0 polys 2 4 vFxfire/Fir/te.fir000644 000316 000311 00000002025 06114616627 013763 0ustar00wrzlgup000000 000000 % simple test scene camera eye 160 60 9 lookat 50 50 5 up 0 0 1 fov 90 20 clip 1 550 resolution 200 200 parameters threshold 0.004 adaptive_max_subdiv 4 adaptive_threshold 0.1 visibility_rays 4 radiosity_threshold 0.01 minumum_area 10 points 12 25 25 10 75 25 10 75 75 10 25 75 10 0 0 0 100 0 0 100 100 0 0 100 0 0 0 1 60 0 1 60 60 1 0 60 1 polys 3 4 vertices 0 3 2 1 % light patch_level 1 element_level 1 normal 0 0 -1 diffuse 0 0 0 emission 1 1 1 4 vertices 4 5 6 7 % floor patch_level 1 element_level 4 normal 0 0 1 diffuse 0.3 0.3 0.9 4 vertices 8 9 10 11 % shader patch_level 1 element_level 1 normal 0 0 1 diffuse 0.8 0.1 0.075 end 60 1 0 60 1 polys 3 4 vertices 0 3 2 1 % light patch_level 1 element_level 1 normal 0 0 -1 diffuse 0 0 0 emission 1 1 1 4 vertices 4 5 6 7 % floor patch_level 1 element_level 4 normal 0 0 1 diffuse 0.3 0.3 0.9 4 vertices 8 9 10 11 % shader patch_level 1 element_level 1 normal 0 0 1 diffuse Fxfire/Fir/te1.fir000644 000316 000311 00000002042 06114616627 014043 0ustar00wrzlgup000000 000000 % simple test scene camera eye 160 60 9 lookat 50 50 5 up 0 0 1 fov 90 20 clip 1 550 resolution 200 200 parameters threshold 0.004 adaptive_max_subdiv 4 adaptive_threshold 0.1 visibility_rays 4 radiosity_threshold 0.01 minumum_area 10 points 13 25 25 10 75 25 10 75 75 10 25 75 10 0 0 0 100 0 0 100 100 0 0 100 0 0 0 1 60 0 1 60 60 1 30 80 1 0 60 1 polys 3 4 vertices 0 3 2 1 % light patch_level 1 element_level 1 normal 0 0 -1 diffuse 0 0 0 emission 1 1 1 4 vertices 4 5 6 7 % floor patch_level 1 element_level 4 normal 0 0 1 diffuse 0.3 0.3 0.9 5 vertices 8 9 10 11 12 % shader patch_level 1 element_level 3 normal 0 0 1 diffuse 0.8 0.1 0.075 end 0 1 0 60 1 polys 3 4 vertices 0 3 2 1 % light patch_level 1 element_level 1 normal 0 0 -1 diffuse 0 0 0 emission 1 1 1 4 vertices 4 5 6 7 % floor patch_level 1 element_level 4 normal 0 0 1 diffuse 0.3 0.3 0.9 5 vertices 8 9 10 11 12 % shader patch_level 1 element_level 3 normal 0 0 1 diFxfire/Fir/test.fir000644 000316 000311 00000002155 06114616627 014336 0ustar00wrzlgup000000 000000 % simple test scene camera eye 110 110 107 lookat 110 0 107 up 0 0 1 fov 90 90 clip 1 550 resolution 200 200 parameters threshold 0.004 adaptive_max_subdiv 8 adaptive_threshold 0.2 visibility_rays 4 radiosity_threshold 0.01 minumum_area 10 points 16 0 0 0 216 0 0 216 0 215 0 0 215 0 221 0 216 221 0 216 221 215 0 221 215 85.5 220 90 130.5 220 90 130.5 220 130 85.5 220 130 53.104 1 64.104 109.36 1 96.604 76.86 1 152.896 20.604 1 120.396 polys 3 4 vertices 8 9 10 11 % light patch_level 1 element_level 1 normal 0 -1 0 diffuse 0 0 0 emission 1 1 1 4 vertices 0 3 2 1 % floor patch_level 1 element_level 3 normal 0 1 0 diffuse 0.8 0.1 0.075 4 vertices 12 15 14 13 % box 1 patch_level 1 element_level 1 normal 0 1 0 diffuse 0.9 0.8 0.1 end 20.604 1 120.396 polys 3 4 vertices 8 9 10 11 % light patch_level 1 element_level 1 normal 0 -1 0 diffuse 0 0 0 emission 1 1 1 4 vertices 0 3 2 1 % floor patch_level 1 element_level 3 normal 0 1 0 diffuse 0.8 0.1 0.075 4 vertices 12 15 14 13 % box 1Fxfire/Fir/tetri.fir000644 000316 000311 00000002234 06114616627 014504 0ustar00wrzlgup000000 000000 % simple test scene camera eye 160 60 9 lookat 50 50 5 up 0 0 1 fov 90 20 clip 1 550 resolution 200 200 parameters threshold 0.004 adaptive_max_subdiv 6 adaptive_threshold 0.1 visibility_rays 4 radiosity_threshold 0.01 minumum_area 10 points 12 15 15 3 85 15 3 85 85 3 15 85 3 0 0 0 100 0 0 100 100 0 0 100 0 0 0 1 60 0 1 60 60 1 0 60 1 polys 3 4 vertices 0 3 2 1 % light patch_level 1 element_level 1 normal 0 0 -1 diffuse 0 0 0 emission 1 1 1 3 vertices 4 6 7 % floor patch_level 1 element_level 2 normal 0 0 1 diffuse 1 1 0 % 3 vertices 4 5 6 % floor % patch_level 1 % element_level 3 % normal 0 0 1 % diffuse 1 1 1 4 vertices 8 9 10 11 % shader patch_level 1 element_level 1 normal 0 0 1 diffuse 0.8 0.1 0.075 end 0 0 -1 diffuse 0 0 0 emission 1 1 1 3 vertices 4 6 7 % floor patch_level 1 element_level 2 normal 0 0 1 diffuse 1 1 0 % 3 vertices 4 5 6 % floor % patch_level 1 % element_level 3 % normal 0 0 1 % diffuse 1 1 1 Fxfire/Fir/tex.fir000644 000316 000311 00000002035 06114616627 014154 0ustar00wrzlgup000000 000000 % simple test scene camera eye 160 60 9 lookat 50 50 5 up 0 0 1 fov 90 20 clip 1 550 resolution 200 200 parameters threshold 0.004 adaptive_max_subdiv 6 adaptive_threshold 0.1 visibility_rays 4 radiosity_threshold 0.01 minumum_area 10 points 12 25 25 10 75 25 10 75 75 10 25 75 10 0 0 0 100 0 0 100 100 0 0 100 0 0 0 0.1 70 0 0.1 70 70 0.1 0 70 0.1 polys 3 4 vertices 0 3 2 1 % light patch_level 1 element_level 1 normal 0 0 -1 diffuse 0 0 0 emission 1 1 1 4 vertices 4 5 6 7 % floor patch_level 1 element_level 2 normal 0 0 1 diffuse 0.3 0.3 0.9 4 vertices 8 9 10 11 % shader patch_level 1 element_level 1 normal 0 0 1 diffuse 0.8 0.1 0.075 end 0.1 0 70 0.1 polys 3 4 vertices 0 3 2 1 % light patch_level 1 element_level 1 normal 0 0 -1 diffuse 0 0 0 emission 1 1 1 4 vertices 4 5 6 7 % floor patch_level 1 element_level 2 normal 0 0 1 diffuse 0.3 0.3 0.9 4 vertices 8 9 10 11 % shader patch_level 1 element_level 1 normal 0 0 1 diffuseFxfire/Fir/tex1.fir000644 000316 000311 00000002016 06114616627 014234 0ustar00wrzlgup000000 000000 % simple test scene camera eye 160 60 9 lookat 50 50 5 up 0 0 1 fov 90 20 clip 1 550 resolution 200 200 parameters threshold 0.004 adaptive_max_subdiv 6 adaptive_threshold 0.1 visibility_rays 4 radiosity_threshold 0.01 minumum_area 10 points 12 -25 25 10 25 25 10 25 75 10 -25 75 10 0 0 0 100 0 0 100 100 0 0 100 0 60 20 0 60 55 0 60 55 10 60 20 10 polys 3 4 vertices 0 3 2 1 % light patch_level 1 element_level 1 normal 0 0 -1 diffuse 0 0 0 emission 1 1 1 4 vertices 4 5 6 7 % floor patch_level 1 element_level 4 normal 0 0 1 diffuse 0.3 0.3 0.9 4 vertices 8 9 10 11 % shader patch_level 1 element_level 1 normal -1 0 0 diffuse 0.8 0.1 0.075 end 55 10 60 20 10 polys 3 4 vertices 0 3 2 1 % light patch_level 1 element_level 1 normal 0 0 -1 diffuse 0 0 0 emission 1 1 1 4 vertices 4 5 6 7 % floor patch_level 1 element_level 4 normal 0 0 1 diffuse 0.3 0.3 0.9 4 vertices 8 9 10 11 % shader patch_level 1 element_level 1 normal -1 0 0 diffuse 0.8 0.Fxfire/Fir/tx.fir000644 000316 000311 00000002163 06114616627 014011 0ustar00wrzlgup000000 000000 % simple test scene camera eye 110 110 107 lookat 110 0 107 up 0 0 1 fov 90 90 clip 1 550 resolution 200 200 parameters threshold 0.004 adaptive_max_subdiv 8 adaptive_threshold 0.2 visibility_rays 64 radiosity_threshold 0.005 minumum_area 10 points 16 0 0 0 216 0 0 216 0 215 0 0 215 0 221 0 216 221 0 216 221 215 0 221 215 85.5 220 90 130.5 220 90 130.5 220 130 85.5 220 130 53.104 50 64.104 109.36 50 96.604 76.86 50 152.896 20.604 50 120.396 polys 3 4 vertices 8 9 10 11 % light patch_level 1 element_level 1 normal 0 -1 0 diffuse 0 0 0 emission 1 1 1 4 vertices 0 3 2 1 % floor patch_level 1 element_level 4 normal 0 1 0 diffuse 0.8 0.1 0.075 4 vertices 12 15 14 13 % box 1 patch_level 1 element_level 1 normal 0 1 0 diffuse 0.9 0.8 0.1 end 20.604 50 120.396 polys 3 4 vertices 8 9 10 11 % light patch_level 1 element_level 1 normal 0 -1 0 diffuse 0 0 0 emission 1 1 1 4 vertices 0 3 2 1 % floor patch_level 1 element_level 4 normal 0 1 0 diffuse 0.8 0.1 0.075 4 vertices 12 15 14 13 %Fxfire/Fir/tx2.fir000644 000316 000311 00000002703 06114616627 014073 0ustar00wrzlgup000000 000000 % simple test scene camera eye 110 110 107.5 lookat 110 0 107.5 up 0 0 1 fov 90 90 clip 1 550 resolution 200 200 parameters threshold 0.004 adaptive_max_subdiv 8 adaptive_threshold 0.2 visibility_rays 16 radiosity_threshold 0.01 minumum_area 10 points 20 0 0 0 216 0 0 216 0 215 0 0 215 0 221 0 216 221 0 216 221 215 0 221 215 85.5 220 90 130.5 220 90 130.5 220 130 85.5 220 130 53.104 50 64.104 109.36 50 96.604 76.86 50 152.896 20.604 50 120.396 134.104 30 37.104 % unused 220 30 69.604 %190.396 30 99.604 157.896 30 125.896 70 30 93.396 %101.604 30 123.396 polys 4 % 4 vertices 8 9 10 11 % light 3 vertices 8 10 11 % light patch_level 1 element_level 1 normal 0 -1 0 diffuse 0 0 0 emission 1 1 1 4 vertices 0 3 2 1 % floor patch_level 1 element_level 3 normal 0 1 0 diffuse 0.8 0.1 0.075 4 vertices 12 15 14 13 % box 1 patch_level 1 element_level 1 normal 0 1 0 diffuse 0.9 0.8 0.1 3 vertices 17 19 18 % box 2 patch_level 1 element_level 1 normal 0 1 0 diffuse 0.9 0.9 0.9 end diffuse 0 0 0 emission 1 1 1 4 verFxfire/Fir/tx3a.fir000644 000316 000311 00000004054 06114616627 014236 0ustar00wrzlgup000000 000000 % simple test scene camera % eye 20 -20 30 % lookat 50 50 5 % up 0 0 1 eye 50 50 51 lookat 50 50 0 up 0 1 0 fov 90 90 clip 1 550 resolution 200 200 parameters threshold 0.004 adaptive_max_subdiv 7 adaptive_threshold 0.2 visibility_rays 16 radiosity_threshold 0.01 minumum_area 10 points 20 0 0 0 % floor 100 0 0 100 100 0 0 100 0 42 40 05 % cube 60 42 05 58 60 05 40 58 05 42 40 20 60 42 20 58 60 20 40 58 20 05 50 40 % light1 32 60 60 25 90 40 22 70 40 % unused 61 41 50 % light2 79 41 40 79 59 40 61 59 50 polys 8 4 vertices 0 1 2 3 % floor patch_level 1 element_level 3 normal 0 0 1 diffuse 0.7 0.7 0.7 3 vertices 12 14 13 %15 % light1 patch_level 1 element_level 1 normal 0.637 -0.318 -0.702 % 0 0 -1 diffuse 0 0 0 emission 1 1 1 4 vertices 16 19 18 17 % light2 patch_level 1 element_level 1 normal -0.88 0 -1.167 diffuse 0 0 0 emission 0.7 0.7 0.7 4 vertices 8 9 10 11 % top patch_level 1 element_level 1 normal 0 0 1 diffuse 0 0 0 4 vertices 4 5 9 8 % front patch_level 1 element_level 1 normal 0 -1 0 diffuse 0 0 0 4 vertices 5 6 10 9 % right patch_level 1 element_level 1 normal 1 0 0 diffuse 0 0 0 4 vertices 6 7 11 10 % back patch_level 1 element_level 1 normal 0 1 0 diffuse 0 0 0 4 vertices 7 4 8 11 % left patch_level 1 element_level 1 normal -1 0 0 diffuse 0 0 0 end ment_level 1 normal 0 -1 0 diffuse 0 0 0 4 vertices 5 6 10 9 % right patch_level 1 element_level 1 normal 1 0 0 diffuse 0 0 0 4 vertices 6 7 11 10 % back patch_level 1 element_level 1 normal 0 1 0 diffuse 0 0 0 4 vertices 7 4 8 11 % left patch_level 1 element_level 1 normal Fxfire/Fir/tx3d.fir000644 000316 000311 00000004062 06114616627 014240 0ustar00wrzlgup000000 000000 % simple test scene camera % eye 20 -20 30 % lookat 50 50 5 % up 0 0 1 eye 50 50 51 lookat 50 50 0 up 0 1 0 fov 90 90 clip 1 550 resolution 200 200 parameters threshold 0.004 adaptive_max_subdiv 6 adaptive_threshold 0.5 visibility_rays 16 radiosity_threshold 0.01 minumum_area 10 points 20 0 0 0 % floor 100 0 0 100 100 0 0 100 0 42 40 05 % cube 60 42 05 58 60 05 40 58 05 42 40 20 60 42 20 58 60 20 40 58 20 05 50 40 % light1 32 60 60 25 90 40 22 70 40 % unused 61 41 50 % light2 79 41 40 79 59 40 61 59 50 polys 8 4 vertices 0 1 2 3 % floor patch_level 1 element_level 3 normal 0 0 1 diffuse 0.7 0.7 0.7 3 vertices 12 14 13 %15 % light1 patch_level 1 element_level 1 normal 0.637 -0.318 -0.702 % 0 0 -1 diffuse 0 0 0 emission 0.5 0.5 0.5 4 vertices 16 19 18 17 % light2 patch_level 1 element_level 1 normal -0.88 0 -1.167 diffuse 0 0 0 emission 0.7 0.7 0.7 4 vertices 8 9 10 11 % top patch_level 1 element_level 1 normal 0 0 1 diffuse 0 0 0 4 vertices 4 5 9 8 % front patch_level 1 element_level 1 normal 0 -1 0 diffuse 0 0 0 4 vertices 5 6 10 9 % right patch_level 1 element_level 1 normal 1 0 0 diffuse 0 0 0 4 vertices 6 7 11 10 % back patch_level 1 element_level 1 normal 0 1 0 diffuse 0 0 0 4 vertices 7 4 8 11 % left patch_level 1 element_level 1 normal -1 0 0 diffuse 0 0 0 end ment_level 1 normal 0 -1 0 diffuse 0 0 0 4 vertices 5 6 10 9 % right patch_level 1 element_level 1 normal 1 0 0 diffuse 0 0 0 4 vertices 6 7 11 10 % back patch_level 1 element_level 1 normal 0 1 0 diffuse 0 0 0 4 vertices 7 4 8 11 % left patch_level 1 element_level 1 normaFxfire/Fir/tx3x.fir000644 000316 000311 00000004055 06114616627 014266 0ustar00wrzlgup000000 000000 % simple test scene camera % eye 20 -20 30 % lookat 50 50 5 % up 0 0 1 eye 50 50 51 lookat 50 50 0 up 0 1 0 fov 90 90 clip 1 550 resolution 200 200 parameters threshold 0.004 adaptive_max_subdiv 7 adaptive_threshold 0.2 visibility_rays 64 radiosity_threshold 0.001 minumum_area 1 points 20 0 0 0 % floor 100 0 0 100 100 0 0 100 0 42 40 05 % cube 60 42 05 58 60 05 40 58 05 42 40 20 60 42 20 58 60 20 40 58 20 05 50 40 % light1 32 60 60 25 90 40 22 70 40 % unused 61 41 50 % light2 79 41 40 79 59 40 61 59 50 polys 8 4 vertices 0 1 2 3 % floor patch_level 1 element_level 10 normal 0 0 1 diffuse 0.7 0.7 0.7 3 vertices 12 14 13 %15 % light1 patch_level 1 element_level 1 normal 0.637 -0.318 -0.702 % 0 0 -1 diffuse 0 0 0 emission 1 1 1 4 vertices 16 19 18 17 % light2 patch_level 1 element_level 1 normal -0.88 0 -1.167 diffuse 0 0 0 emission 0.7 0.7 0.7 4 vertices 8 9 10 11 % top patch_level 1 element_level 1 normal 0 0 1 diffuse 0 0 0 4 vertices 4 5 9 8 % front patch_level 1 element_level 1 normal 0 -1 0 diffuse 0 0 0 4 vertices 5 6 10 9 % right patch_level 1 element_level 1 normal 1 0 0 diffuse 0 0 0 4 vertices 6 7 11 10 % back patch_level 1 element_level 1 normal 0 1 0 diffuse 0 0 0 4 vertices 7 4 8 11 % left patch_level 1 element_level 1 normal -1 0 0 diffuse 0 0 0 end ment_level 1 normal 0 -1 0 diffuse 0 0 0 4 vertices 5 6 10 9 % right patch_level 1 element_level 1 normal 1 0 0 diffuse 0 0 0 4 vertices 6 7 11 10 % back patch_level 1 element_level 1 normal 0 1 0 diffuse 0 0 0 4 vertices 7 4 8 11 % left patch_level 1 element_level 1 normal Fxfire/Makefile000644 000316 000311 00000000450 06114643572 013570 0ustar00wrzlgup000000 000000 CFLAGS = -DPPM -DASCII -g -Wall -DGRAPH CC = gcc FOBJECTS= geom.o spectra.o input.o output.o memory.o \ bsptree.o ff.o disco.o dt.o surface.o subdiv.o sample.o mesh.o \ display.o rad.o main.o all:fxfire fxfire: $(FOBJECTS) $(CC) $(CFLAGS) -o fxfire $(FOBJECTS) -lm clean: rm *.o fxfire @»(l$lµ¯ › ¬4˜ l$µ¯ «óœµ¯ Fkð@»(lXµ¯ › ¬BÔµ'l lTFµ¯ lXFÿ Ä Èµ' µ¯ @bhlXkôµ¯ «ö¨µ¯ @aص¯ Fxfire/README000644 000316 000311 00000004556 06114644365 013024 0ustar00wrzlgup000000 000000 Software available here is provided without any guarantees. All software is provided for non-comerical use only (!), though comercial agreements are possible on request. If you want to use parts of this software please feel free, but include the copyright notice below: ----------------------------------------------------------------------- Copyright (c) by Wolfgang Stuerzlinger (wRZL), 1991-1996. This code may be used only for non-commercial purposes! ----------------------------------------------------------------------- As this software is still evolving, I know of a few bugs in the version available here, which I have fixed since. If you stumble across one and get stuck, send me a message. ------------------------------------------------------------------------- FXFIRE Radiosity System: Usage: fxfire -0 don't insert D0 edges into meshes -a -s and always (re)sample all samples -b length of bsplists for raycasting (0 = full (slow) intersect) -d use Delaunay surface mesh (= voronoi diagrams for areas) -D use Discomeshing -e use exact FF calculation -i number of iterations -o -d and output samples per surface -p output interval in iterations (-1 = no output) -s[num] do adaptive Subdivision [opt. maxlevel] -t avoid T-vertices -u -s but use unrestricted Quadtree -z use random rays for FF's Use the batch script f to make life easier: f corn [options] Input is a .fir file for the format see the examples in the fir/ directory Output is a .pol file, where the polygons and the vertex radiosities are stored for later display. Also a .log file is generated. The directory DiscoMesher contains the discontinuity segment generator as a seperate module, also with some docu. Modules: bsptree.c bsptree to accelerate ray casting disco.c discontinuity segment detection display.c preparation for output t-vertex elim call dt.c Constrained Delaunay Triangulation with Bounded Voronoi Diagram ff.c formfactor calc geom.c geometric helper routines input.c input file read main.c master module memory.c efficient blocked memory allocation output.c output file write rad.c main loop spectra.c color handling sample.c when/how to subdivide adaptively mesh.c surface.c the 3 mesh modules (badly organized - use grep ;-) subdiv.c ment detection display.c preparation for output t-vertex elim call dt.c Constrained Delaunay Triangulation with Bounded Voronoi Diagram ff.Fxfire/bsptree.c000644 000316 000311 00000032401 06114620343 013730 0ustar00wrzlgup000000 000000 /* ========================================================================= bsptree.c ========================================================================= */ #include #include #include "rad.h" #include "geom.h" #define MAX_BSP_DEPTH 21 TBinNode *BSPTree; /* global Variable */ static int allocedobjs; /* number of obj alloced */ static TId cur_shooterId,cur_surfId; /* current shooter / surface */ /* ------------------------------------------------------------------------- link list functions; ------------------------------------------------------------------------- */ #define FirstOfLinkList(node) (node)->root #define NextOfLinkList(obj) (obj)->next static void AddNewToLinkList(TBinNode *node, TSurface *surf) { TGeomObj *newObj; newObj = alloc_obj(); allocedobjs++; newObj->surf = surf; newObj->next = node->root; node->root = newObj; (node->length)++; } static void AddOldToLinkList(TBinNode *node, TGeomObj *obj) { obj->next = node->root; node->root = obj; (node->length)++; } /* ------------------------------------------------------------------------- data structures for a simple stack; ------------------------------------------------------------------------- */ #define STACKSIZE 50 /* supports a BSP tree of upto depth 49 */ typedef struct { TBinNode *node; double min, max; } TStackElem; typedef struct { int stackPtr; TStackElem stack[STACKSIZE]; } TStack; static TStack stack; /* ------------------------------------------------------------------------- stack operations; ------------------------------------------------------------------------- */ static void InitStack(void) { stack.stack[0].node = NULL; stack.stackPtr = 1; } static void push(TBinNode *node, double mini, double maxi) { stack.stack[stack.stackPtr].node = node; stack.stack[stack.stackPtr].min = mini; stack.stack[stack.stackPtr].max = maxi; stack.stackPtr++; } static void pop(TBinNode **node, double *mini, double *maxi) { stack.stackPtr--; *node = stack.stack[stack.stackPtr].node; *mini = stack.stack[stack.stackPtr].min; *maxi = stack.stack[stack.stackPtr].max; } /* ------------------------------------------------------------------------- following functions return the distance between origin of a ray and plane, measured along the direction of the ray; direction is a unit vector; there is a function for each subdivision plane; ------------------------------------------------------------------------- */ static double DistanceToXPlane(TPoint3f *plane, TRay *ray) { if (ray->direction.x == 0.0) return(1.0E300); return((plane->x - ray->origin.x) / ray->direction.x); } static double DistanceToYPlane(TPoint3f *plane, TRay *ray) { if (ray->direction.y == 0.0) return(1.0E300); return((plane->y - ray->origin.y) / ray->direction.y); } static double DistanceToZPlane(TPoint3f *plane, TRay *ray) { if (ray->direction.z == 0.0) return(1.0E300); return((plane->z - ray->origin.z) / ray->direction.z); } /* ------------------------------------------------------------------------- following functions check which of the half space of the two children contains origin and returns that child as near, the other as far; there is a function for each subdivision plane; ------------------------------------------------------------------------- */ static void GetXChildren(TBinNode *currentNode, TRay *ray, TBinNode **near, TBinNode **far) { if (currentNode->child[0]->max.x > ray->origin.x) { *near = currentNode->child[0]; *far = currentNode->child[1]; } else if (currentNode->child[0]->max.x < ray->origin.x) { *far = currentNode->child[0]; *near = currentNode->child[1]; } else { if (ray->direction.x >= 0.0) { *near = currentNode->child[0]; *far = currentNode->child[1]; } else { *far = currentNode->child[0]; *near = currentNode->child[1]; } } } static void GetYChildren(TBinNode *currentNode, TRay *ray, TBinNode **near, TBinNode **far) { if (currentNode->child[0]->max.y > ray->origin.y) { *near = currentNode->child[0]; *far = currentNode->child[1]; } else if (currentNode->child[0]->max.y < ray->origin.y) { *far = currentNode->child[0]; *near = currentNode->child[1]; } else { if (ray->direction.y >= 0.0) { *near = currentNode->child[0]; *far = currentNode->child[1]; } else { *far = currentNode->child[0]; *near = currentNode->child[1]; } } } static void GetZChildren(TBinNode *currentNode, TRay *ray, TBinNode **near, TBinNode **far) { if (currentNode->child[0]->max.z > ray->origin.z) { *near = currentNode->child[0]; *far = currentNode->child[1]; } else if (currentNode->child[0]->max.z < ray->origin.z) { *far = currentNode->child[0]; *near = currentNode->child[1]; } else { if (ray->direction.z >= 0.0) { *near = currentNode->child[0]; *far = currentNode->child[1]; } else { *far = currentNode->child[0]; *near = currentNode->child[1]; } } } /* ------------------------------------------------------------------------- some miscellaneous supporting functions; ------------------------------------------------------------------------- */ static void InitRootNode(TBinNode *node) { TSurface *surf; node->length = 0; node->root = NULL; InitPoint(node->min,1E30,1E30,1E30); InitPoint(node->max,-1E30,-1E30,-1E30); FOR_ALL_TESTSURFS(surf) /* update node extent */ JoinBbox(node->min,node->max,surf->min,surf->max); AddNewToLinkList(node, surf); /* add to node list */ END_ALL_TESTSURFS(surf) } #define Leaf(node) ((node)->child[0] == NULL) static TSurface *RayObjIntersect(TRay *ray, TBinNode *node) { TGeomObj *obj; TSurface *surf; obj = FirstOfLinkList(node); while (obj != NULL) { surf = obj->surf; if (surf->surfId != cur_surfId && surf->surfId != cur_shooterId) { if (intersect(ray,surf)) return(surf); } obj = NextOfLinkList(obj); } return(NULL); } static TSurface *RayIntersectFull(TRay *ray) { TSurface *surf; /* possible shadowing surface */ FOR_ALL_TESTSURFS(surf) if (surf->surfId != cur_surfId && surf->surfId != cur_shooterId) { if (intersect(ray,surf)) return(surf); } END_ALL_TESTSURFS(surf) return(NULL); } /* ------------------------------------------------------------------------- I N T E R F A C E ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- RayTreeIntersect traverses ray through BSPTree and intersects ray with all the objects along the way; ------------------------------------------------------------------------- */ TSurface *RayTreeIntersect(TRay *ray, TBinNode *BSPTree1, TId shooterId, TId surfId) { double dist; TBinNode *currentNode, *nearChild, *farChild; TSurface *hit; cur_shooterId = shooterId; cur_surfId = surfId; /* a teeny weeny bit more as ndotv check may flunk otherwise */ ray->maxDistance *= 1.0 + 1E-6; if (params.bsptreelen == 0) return(RayIntersectFull(ray)); if (! RayBoxIntersect(ray, &BSPTree1->min, &BSPTree1->max)) return(NULL); InitStack(); currentNode = BSPTree1; while (currentNode != NULL) { while (! Leaf(currentNode)) { dist = currentNode->DistanceToDivisionPlane( ¤tNode->child[0]->max, ray); currentNode->GetChildren(currentNode, ray, &nearChild, &farChild); if (dist > ray->maxDistance || dist < 0.0) currentNode = nearChild; else { if (dist < ray->minDistance) currentNode = farChild; else { push(farChild, dist, ray->maxDistance); currentNode = nearChild; ray->maxDistance = dist; } } } hit = RayObjIntersect(ray, currentNode); if (hit != NULL) return(hit); pop(¤tNode, &ray->minDistance, &ray->maxDistance); } return(NULL); } static void split_node(TBinNode *node,TBinNode *child0,TBinNode *child1, int axis,float param) { child0->min = node->min; child0->max = node->max; child0->length = 0; child0->root = NULL; child1->min = node->min; child1->max = node->max; child1->length = 0; child1->root = NULL; if (axis == 0) { /* current subdivision plane is x */ child0->max.x = node->min.x + param * (node->max.x - node->min.x); child1->min.x = child0->max.x; } else if (axis == 1) { /* current subdivision plane is y */ child0->max.y = node->min.y + param * (node->max.y - node->min.y); child1->min.y = child0->max.y; } else { /* current subdivision plane is z */ child0->max.z = node->min.z + param * (node->max.z - node->min.z); child1->min.z = child0->max.z; } } #define MAXSPLITPARAM (1+2+4+8) static float splitparam[MAXSPLITPARAM] = { 0.5, 0.25, 0.75, 0.125, 0.375, 0.625, 0.875, 0.0625, 0.1875, 0.3125, 0.4375, 0.5625, 0.6875, 0.8125, 0.9375 }; static int find_best_split_axis(TBinNode *node,int depth,int *axis,float *param) { int i,j,cnt0,cnt1,cur_best,best,best_axis; double best_param; TGeomObj *obj,*cur_obj; TBinNode child0,child1; best_axis = *axis; best = node->length; best_param = *param; for (i = 0; i < 3; i++) { /* try all axes */ split_node(node,&child0,&child1,i,*param); cnt0 = 0; cnt1 = 0; obj = FirstOfLinkList(node); while (obj != NULL) { cur_obj = obj; obj = NextOfLinkList(obj); if (! BboxOutside(child0.min,child0.max, cur_obj->surf->min,cur_obj->surf->max)) cnt0++; if (! BboxOutside(child1.min,child1.max, cur_obj->surf->min,cur_obj->surf->max)) cnt1++; } cur_best = (cnt0 > cnt1) ? cnt0 : cnt1; /* max lenght of childs */ if (cur_best < best) { /* we are better than old */ best = cur_best; best_axis = i; best_param = *param; } } if (best < node->length) { /* found a good splitting */ *param = best_param; /* quick exit */ *axis = best_axis; return(1); } for (j = 1; j < MAXSPLITPARAM; j++) { /* for all params */ for (i = 0; i < 3; i++) { /* try all axes */ split_node(node,&child0,&child1,i,splitparam[j]); cnt0 = 0; cnt1 = 0; obj = FirstOfLinkList(node); while (obj != NULL) { cur_obj = obj; obj = NextOfLinkList(obj); if (! BboxOutside(child0.min,child0.max, cur_obj->surf->min,cur_obj->surf->max)) cnt0++; if (! BboxOutside(child1.min,child1.max, cur_obj->surf->min,cur_obj->surf->max)) cnt1++; } cur_best = (cnt0 > cnt1) ? cnt0 : cnt1; /* max lenght of childs */ if (cur_best < best) { /* we are better than old */ best = cur_best; best_axis = i; best_param = splitparam[j]; } } } if (best >= node->length) { log_message("@"); return(0); } *param = best_param; *axis = best_axis; return(1); } /* ------------------------------------------------------------------------- Subdivide builds the BSP tree by subdividing along the center of x, y, or z bounds, one each time this function is called; this function calls itself recursively until either the tree is deeper than maxDepth or all of the tree leaves contain less than maxListLength of objects; axis specifies the current subdivision plane (0-x, 1-y, 2-z); ------------------------------------------------------------------------- */ static void Subdivide(TBinNode *node, int depth, int axis) { int i, nextAxis, test0, test1; float param; TGeomObj *obj,*cur_obj; node->child[0] = node->child[1] = NULL; /* init as child */ param = splitparam[0]; /* try 0.5 */ if (node->length > params.bsptreelen && depth < MAX_BSP_DEPTH && find_best_split_axis(node,depth,&axis,¶m)) { if (axis == 0) { /* current subdivision plane is x */ node->DistanceToDivisionPlane = DistanceToXPlane; node->GetChildren = GetXChildren; } else if (axis == 1) { /* current subdivision plane is y */ node->DistanceToDivisionPlane = DistanceToYPlane; node->GetChildren = GetYChildren; } else { /* current subdivision plane is z */ node->DistanceToDivisionPlane = DistanceToZPlane; node->GetChildren = GetZChildren; } for (i = 0; i < 2; i++) node->child[i] = alloc_node(); split_node(node,node->child[0],node->child[1],axis,param); obj = FirstOfLinkList(node); while (obj != NULL) { cur_obj = obj; obj = NextOfLinkList(obj); test0 = BboxOutside(node->child[0]->min,node->child[0]->max, cur_obj->surf->min,cur_obj->surf->max); test1 = BboxOutside(node->child[1]->min,node->child[1]->max, cur_obj->surf->min,cur_obj->surf->max); if (! test0 && ! test1) { AddNewToLinkList(node->child[1], cur_obj->surf); /* copy */ AddOldToLinkList(node->child[0], cur_obj); } else if (! test0) AddOldToLinkList(node->child[0], cur_obj); else if (! test1) AddOldToLinkList(node->child[1], cur_obj); } nextAxis = (axis + 1) % 3; for (i = 0; i < 2; i++) Subdivide(node->child[i], depth + 1, nextAxis); } } /* ------------------------------------------------------------------------- initialize and start the building of BSPtree; ------------------------------------------------------------------------- */ void InitBinTree(TBinNode **BSPTree1) { if (params.bsptreelen == 0) { *BSPTree1 = NULL; return; } *BSPTree1 = alloc_node(); InitRootNode(*BSPTree1); (*BSPTree1)->DistanceToDivisionPlane = NULL; (*BSPTree1)->GetChildren = NULL; log_message("Initial Node: %d objs alloced\n",allocedobjs); Subdivide(*BSPTree1, 0, 0); log_message("\nWhole Tree: %d objs alloced\n",allocedobjs); } and start the building of BSPtree; ------------------------------------------------------------------------- */ void InitBinTree(TBinNode **BSPTree1) { if (params.bsptreelen == 0) { *BSPTree1 = NULL; return; } *BSPTree1 = alloc_node(); InitRFxfire/disco.c000644 000316 000311 00000041100 06114620343 013361 0ustar00wrzlgup000000 000000 /***************************************************************************** * disco.c ******************************************************************************/ #include #include #include #include #include #include "rad.h" #include "geom.h" #include "dt.h" #include "disco.h" #include "log.h" /* FIXME: mark D1 discontinuities */ /****************************************************************************/ static int ray_intersect_plane(TVector3f *normal,double ndotp,TEdge *edge, double *t) { double ndotd; ndotd = DotVector(*normal,edge->direction); if (ndotd == 0.0) { *t = 1E10; /* far far away */ return(0); } *t = (ndotp - DotVector(*normal,edge->origin)) / ndotd; return(1); } /****************************************************************************/ #define setseg(seg1,i1,seg2,i2) { (seg1)->t[i1] = (seg2)->t[i2]; \ (seg1)->point[i1] = (seg2)->point[i2]; } #define combine(seg1,seg2) { \ (seg1)->side = ((seg1)->side == (seg2)->side) ? (seg1)->side : 0; \ (seg1)->discontinuity = ((seg1)->discontinuity <= (seg2)->discontinuity) ? \ (seg1)->discontinuity : (seg2)->discontinuity; } static void insert_new_seg(TDiscoSeg **nodelist,TDiscoSeg *seg) { TDiscoSeg *list,**old,*newd; list = *nodelist; old = nodelist; while (list != NULL && list->t[1] <= seg->t[0]) { old = &(list->next); list = list->next; } if (list == NULL) { /* at end of list */ *old = seg; seg->next = NULL; return; } while (list != NULL && list->t[0] <= seg->t[1]) { if (list->t[1] >= seg->t[1]) { /* seg ends first or = */ if (list->t[0] == seg->t[0]) { /* same start */ if (list->t[1] != seg->t[1]) { /* not equal end */ setseg(list,0,seg,1); *old = seg; seg->next = list; } combine(seg,list); } else if (list->t[0] < seg->t[0]) { /* list starts earlier */ if (list->t[1] != seg->t[1]) { /* not equal end */ newd = (TDiscoSeg *) calloc(1,sizeof(TDiscoSeg)); *newd = *list; setseg(newd,0,seg,1); } setseg(list,1,seg,0); combine(seg,list); seg->next = list->next; list->next = seg; } else { /* list->t[0] > seg->t[0] */ /* seg starts earlier */ if (list->t[1] != seg->t[1]) { /* not equal end */ newd = (TDiscoSeg *) calloc(1,sizeof(TDiscoSeg)); *newd = *list; setseg(newd,0,seg,1); setseg(list,1,seg,1); list->next = newd; } setseg(seg,1,list,0); combine(list,seg); *old = seg; seg->next = list; } return; /* finito */ } else { /* (list->t[1] < seg->t[1]) */ /* list ends first */ if (list->t[0] == seg->t[0]) { /* same start */ setseg(seg,0,list,1); /* shorten seg */ combine(list,seg); } else if (list->t[0] < seg->t[0]) { /* list starts earlier */ newd = (TDiscoSeg *) calloc(1,sizeof(TDiscoSeg)); *newd = *list; setseg(newd,0,seg,0); setseg(seg,0,list,1); setseg(list,1,newd,0); combine(newd,seg); list->next = newd; list = newd; /* jump forward */ } else { /* list->t[0] > seg->t[0] */ /* seg starts earlier */ newd = (TDiscoSeg *) calloc(1,sizeof(TDiscoSeg)); *newd = *seg; setseg(newd,1,list,0); setseg(seg,0,list,1); combine(list,seg); *old = newd; newd->next = list; } } /* more work todo */ old = &(list->next); list = list->next; } error("Haeh???"); } static void insert_bsp2(TBSP2d **bsp,TVector2f *normal,double np, TDiscoSeg *seg) { int side1,side2; double side; if (*bsp == NULL) { *bsp = (TBSP2d *)calloc(1,sizeof(TBSP2d)); (*bsp)->line.normal = *normal; (*bsp)->line.np = np; (*bsp)->project = FindProject2(*normal); seg->next = NULL; (*bsp)->seg = seg; return; } side = DistPt2Line(seg->point[0],(*bsp)->line.normal,(*bsp)->line.np); side1 = sign(side); side = DistPt2Line(seg->point[1],(*bsp)->line.normal,(*bsp)->line.np); side2 = sign(side); if (side1 == 0 && side2 == 0) { /* new segment */ #ifdef CLUDGE seg->next = (*bsp)->seg; (*bsp)->seg = seg; #else insert_new_seg(&((*bsp)->seg),seg); #endif } else if (side1 == 0 || side2 == 0) { /* one is in */ if (side1 > 0 || side2 > 0) /* other is front */ insert_bsp2(&(*bsp)->front,normal,np,seg); else /* other is back */ insert_bsp2(&(*bsp)->back,normal,np,seg); } else if (side1 != side2) { insert_bsp2(&(*bsp)->front,normal,np,seg); insert_bsp2(&(*bsp)->back,normal,np,seg); } else if (side1 > 0) /* front only */ insert_bsp2(&(*bsp)->front,normal,np,seg); else /* back only */ insert_bsp2(&(*bsp)->back,normal,np,seg); } static void insert_seg2(TBSP2d **bsp,TPoint2f *point1,TPoint2f *point2, DISCONTINUITY d,int side) { int project; double temp,np; TVector2f normal,dir; TDiscoSeg *seg; SubVector2(dir,*point2,*point1); NormalizeVector2(temp,dir); if (temp == 0.0) /* zero vector */ return; TurnVector2Left2(normal,dir); np = DotVector2(normal,*point1); seg = (TDiscoSeg *) calloc(1,sizeof(TDiscoSeg)); seg->discontinuity = d; seg->point[0] = *point1; seg->point[1] = *point2; project = FindProject2(normal); seg->t[0] = Projectd1(project,*point1); seg->t[1] = Projectd1(project,*point2); seg->side = side; if (seg->t[0] > seg->t[1]) { /* ensure correct order */ SWAP(seg->t[0],seg->t[1],temp); SWAP(seg->point[0],seg->point[1],dir); seg->side = -seg->side; } #ifdef USE_BSPTREE insert_bsp2(bsp,&normal,np,seg); #else if (*bsp == NULL) { *bsp = (TBSP2d *)calloc(1,sizeof(TBSP2d)); (*bsp)->project = project; } seg->next = (*bsp)->seg; (*bsp)->seg = seg; #endif } void free_bsp2(TBSP2d *bsp) { TDiscoSeg *seg,*next; if (bsp == NULL) return; seg = bsp->seg; while (seg != NULL) { next = seg->next; free(seg); seg = next; } free_bsp2(bsp->front); free_bsp2(bsp->back); free(bsp); } /****************************************************************************/ static int calc_side3d(TPlane *plane,TEdge *edge) { double ndotd,ndoto,t; ndotd = DotVector(plane->normal,edge->direction); ndoto = DotVector(plane->normal,edge->origin); if (ndotd != 0.0) { t = (plane->np - ndoto) / ndotd; if (t <= 0.0) { /* we are only on 1 side! */ if (ndotd > 0.0) return(1); /* towards front */ else return(-1); /* towards back */ } } else { if (ndoto > plane->np) /* lies before */ return(1); else if (ndoto < plane->np) /* lies behind */ return(-1); else /* ray in the plane */ return(0); } return(2); /* on both sides */ } static void insert_bsp(TBSP **bsp,TVector3f *normal,double np,TWedge *wedge) { int side1,side2; if (*bsp == NULL) { *bsp = (TBSP *)calloc(1,sizeof(TBSP)); (*bsp)->plane.normal = *normal; (*bsp)->plane.np = np; (*bsp)->discontinuity = D2; (*bsp)->wedge[0] = wedge; (*bsp)->nWedge = 1; return; } side1 = calc_side3d(&(*bsp)->plane,wedge->edge[0]); side2 = calc_side3d(&(*bsp)->plane,wedge->edge[1]); if (side1 == 2 || side2 == 2) { /* different sides */ insert_bsp(&(*bsp)->front,normal,np,wedge); insert_bsp(&(*bsp)->back,normal,np,wedge); } else if (side1 == 0 && side2 == 0) { /* new wedge */ if ((*bsp)->nWedge > MAXWEDGE) printf("ERROR"); (*bsp)->wedge[(*bsp)->nWedge] = wedge; (*bsp)->nWedge++; } else if (side1 == 0 || side2 == 0) { /* one is in */ if (side1 > 0 || side2 > 0) /* other is front */ insert_bsp(&(*bsp)->front,normal,np,wedge); else /* other is back */ insert_bsp(&(*bsp)->back,normal,np,wedge); } else if (side1 != side2) { /* different sides */ insert_bsp(&(*bsp)->front,normal,np,wedge); insert_bsp(&(*bsp)->back,normal,np,wedge); } else if (side1 > 0) /* front only */ insert_bsp(&(*bsp)->front,normal,np,wedge); else /* back only */ insert_bsp(&(*bsp)->back,normal,np,wedge); } static void gen_wedge(TBSP **bsp,TPoint3f *point,TEdge *edge0,TEdge *edge1, TWedge *wedge) { double temp,np; TVector3f normal; CrossVector(normal,edge0->direction,edge1->direction); NormalizeVector(temp,normal); np = DotVector(normal,*point); wedge->edge[0] = edge0; wedge->edge[1] = edge1; wedge->discontinuity = D2; insert_bsp(bsp,&normal,np,wedge); } /****************************************************************************/ TDisco *calc_disco_mesh(TShooter *shooter1,TSurface *shader) { int i,j,w,idx,r1,r2; double temp; TDisco *disco; temp = DotVector(shooter1->normal,shader->normal); /* same plane? */ if (temp == 1.0 && shooter1->ndotp == shader->ndotp) return(NULL); if (temp == -1.0 && shooter1->ndotp == -shader->ndotp) return(NULL); disco = (TDisco *)calloc(1,sizeof(TDisco)); disco->nEdges = shooter1->pol.n * shader->nPts; disco->edge = (TEdge *)calloc(disco->nEdges,sizeof(TEdge)); disco->nWedges = disco->nEdges * 2; disco->wedge = (TWedge *)calloc(disco->nWedges,sizeof(TWedge)); /* generate all rays */ for (i = 0; i < shooter1->pol.n; i++) { for (j = 0; j < shader->nPts; j++) { idx = i * shader->nPts + j; disco->edge[idx].origin = shader->vert[j]; SubVector(disco->edge[idx].direction,shader->vert[j], shooter1->pol.vert[i]); NormalizeVector(temp,disco->edge[idx].direction); } } /* now generate all EV wedges */ w = 0; for (i = 0; i < shooter1->pol.n; i++) { for (j = 0; j < shader->nPts; j++) { r1 = i * shader->nPts + j; r2 = ((i + 1) % shooter1->pol.n) * shader->nPts + j; gen_wedge(&disco->bsp,&shader->vert[j], &disco->edge[r1],&disco->edge[r2],&disco->wedge[w]); w++; } } /* now generate all VE wedges */ for (i = 0; i < shooter1->pol.n; i++) { for (j = 0; j < shader->nPts; j++) { r1 = i * shader->nPts + j; r2 = i * shader->nPts + ((j + 1) % shader->nPts); gen_wedge(&disco->bsp,&shader->vert[j], &disco->edge[r1],&disco->edge[r2],&disco->wedge[w]); w++; } } return(disco); } static void free_bsp(TBSP *bsp) { if (bsp == NULL) return; free_bsp(bsp->front); free_bsp(bsp->back); free(bsp); } void free_disco_mesh(TDisco *disco) { free_bsp(disco->bsp); free(disco->edge); free(disco->wedge); free(disco); } /****************************************************************************/ static void calc_wedges(TBSP *bsp,TElement *ep) { int i,behind,front; double np; if (bsp == NULL) return; behind = 0; front = 0; /* MAYBE use SurfPoint here ???? */ for (i = 0; i < ep->nPts; i++) { np = DotVector(bsp->plane.normal,ep->sample[i]->point); if (np < bsp->plane.np) behind++; else if (np > bsp->plane.np) front++; } if (front == ep->nPts) /* all before */ calc_wedges(bsp->front,ep); else if (behind == ep->nPts) calc_wedges(bsp->back,ep); else { calc_wedges(bsp->front,ep); calc_wedges(bsp->back,ep); for (i = 0; i < bsp->nWedge; i++) { bsp->wedge[i]->marked = 1; bsp->wedge[i]->edge[0]->marked = 1; bsp->wedge[i]->edge[1]->marked = 1; } } } void construct_disco(TDisco *disco,TElement *ep,TBSP2d **bsp2d) { int i; double t; TVector3f temp; TSurface *surf; DISCONTINUITY disc; for (i = 0; i < disco->nWedges; i++) disco->wedge[i].marked = 0; calc_wedges(disco->bsp,ep); surf = ep->patch->surf; for (i = 0; i < disco->nEdges; i++) { if (! disco->edge[i].marked) continue; if (DistPt2Plane(disco->edge[i].origin,surf->normal,surf->ndotp) == 0.0) disco->edge[i].inplane = 1; else disco->edge[i].inplane = 0; (void) ray_intersect_plane(&surf->normal,surf->ndotp, &disco->edge[i],&t); temp = disco->edge[i].direction; ScaleVector(temp,t); AddVector(disco->edge[i].intersection,temp,disco->edge[i].origin); Project2d(surf->project,disco->edge[i].intersection, disco->edge[i].intersect2); } for (i = 0; i < disco->nWedges; i++) { if (! disco->wedge[i].marked) continue; disc = disco->wedge[i].discontinuity; if (disco->wedge[i].edge[0]->inplane && disco->wedge[i].edge[1]->inplane) disc = D0; insert_seg2(bsp2d,&disco->wedge[i].edge[0]->intersect2, &disco->wedge[i].edge[1]->intersect2,disc,0); } } /****************************************************************************/ int find_d0_segments(TSurface *theSurf,TSurface *surf,TBSP2d **bsp2d) { int i,side; double d; TPoint3f *p1,*p2; TPoint2f d1,d2,norm,v; d = DotVector(theSurf->normal,surf->normal); if (d == 1.0 || d == -1.0) /* same plane */ return(0); p1 = NULL; for (i = 0; i < surf->nPts; i++) { if (Inplane(surf->vert[i],theSurf->normal,theSurf->ndotp)) { p1 = &surf->vert[i]; break; } } if (p1 == NULL) /* none found */ return(0); p2 = &surf->vert[(i + 1) % surf->nPts]; if (! Inplane(*p2,theSurf->normal,theSurf->ndotp)) { if (i != 0) { message("1+"); /* only 1 vertex inplane? */ return(0); } p2 = &surf->vert[surf->nPts - 1]; /* p1 = p[0]! */ if (! Inplane(*p2,theSurf->normal,theSurf->ndotp)) { message("1-"); /* only 1 vertex inplane? */ return(0); } } /* in p1/p2 we have the possible candidate line now! */ Project2d(theSurf->project,*p1,d1); Project2d(theSurf->project,*p2,d2); Project2d(theSurf->project,surf->normal,norm); SubVector2(v,d2,d1); if (DotVector2(norm,v) < 0.0) side = 1; /* right */ else side = -1; /* left */ insert_seg2(bsp2d,&d1,&d2,D0,side); return(1); } /****************************************************************************/ int clip_segments(TSurface *surf,TElement *ep,TBSP2d *bsp,int nSeg, TSegment *segs) { int i,flag,idx1,idx2; double eps; TDiscoSeg *seg; if (bsp == NULL) return(nSeg); eps = DistPnt2(surf->min2,surf->max2) * 1.0E-6; seg = bsp->seg; while (seg != NULL) { flag = 0; for (i = 0; i < ep->nPts; i++) { if (PointNear2(ep->sample[i]->point2,seg->point[0],eps)) { idx1 = i; flag++; } else if (PointNear2(ep->sample[i]->point2,seg->point[1],eps)) { idx2 = i; flag++; } } if (flag >= 2) { if (idx1 < idx2) idx1 = idx2 - idx1; else idx1 = idx1 - idx2; if (idx1 != 1 && idx1 != ep->nPts - 1) nSeg++; /* not between adj vertices */ } else { segs[nSeg].point1 = seg->point[0]; segs[nSeg].point2 = seg->point[1]; segs[nSeg].discontinuity = seg->discontinuity; if (clip2element(ep,&segs[nSeg].point1,&segs[nSeg].point2)) { if (! InsideBbox2(ep->min,ep->max,segs[nSeg].point1) || ! InsideBbox2(ep->min,ep->max,segs[nSeg].point2)) { (void) clip2element(ep,&segs[nSeg].point1, &segs[nSeg].point2); } flag = 0; for (i = 0; i < ep->nPts; i++) { if (PointNear2(ep->sample[i]->point2,segs[nSeg].point1, eps)) { idx1 = i; flag++; } else if (PointNear2(ep->sample[i]->point2, segs[nSeg].point2,eps)) { idx2 = i; flag++; } } if (flag >= 2) { if (idx1 < idx2) idx1 = idx2 - idx1; else idx1 = idx1 - idx2; if (idx1 != 1 && idx1 != ep->nPts - 1) nSeg++; /* not between adj vertices */ } else nSeg++; } } seg = seg->next; } #ifdef USE_BSPTREE nSeg = clip_segments(surf,ep,bsp->front,nSeg,segs); nSeg = clip_segments(surf,ep,bsp->back,nSeg,segs); #endif return(nSeg); } int inside_d0(TBSP2d *bsp,TPoint2f *point2) { double side,t; TDiscoSeg *seg; if (bsp == NULL || bsp->seg == NULL) return(0); seg = bsp->seg; if (isonline(point2,&seg->point[0],&seg->point[1])) return(1); side = calc_side(&seg->point[0],&seg->point[1],point2); t = Projectd1(bsp->project,*point2); /* FIXME */ while (seg != NULL) { if (seg->t[0] <= t && t <= seg->t[1]) { if ((seg->side > 0.0 && side < 0.0) || (seg->side < 0.0 && side > 0.0)) return(0); } seg = seg->next; } return(1); } #define BORDER_SHIFT 1E-4 int move_d0(TSurface *surf,TBSP2d *bsp,TPoint2f *point2,int inside, TVector2f *shift) { int moved; double dist,side,t,np,reflen,len,shiftlen; TDiscoSeg *seg; TVector2f line,norm,move; if (bsp == NULL) return(0); reflen = DistPnt2(surf->min2,surf->max2); /* use diag as reference */ InitPoint2(*shift,0.0,0.0); moved = 0; seg = bsp->seg; t = Projectd1(bsp->project,*point2); /* FIXME */ while (seg != NULL) { SubVector2(line,seg->point[1],seg->point[0]); NormalizeVector2(side,line); TurnVector2Left2(norm,line); np = DotVector2(norm,seg->point[0]); dist = DistPt2Line(*point2,norm,np); len = reflen * (seg->side == inside) ? -BORDER_SHIFT : BORDER_SHIFT; if (dist >= len) { /* too near */ if (seg->t[0] <= t && t <= seg->t[1]) { shiftlen = len - dist; move = norm; ScaleVector2(move,shiftlen); AddVector2(*shift,move,*shift); moved = 1; } } seg = seg->next; } return(moved); } (line,seg->point[1],seg->point[0]); NormalizeVector2(side,line); TurnVector2Left2(norm,line); np = DotVector2(norm,seg->point[0]); dist = DistPt2Line(*point2,norm,np); len = reflen * (seg->side == inside) ? -BORDER_SHIFT : BORDER_SHIFT; if (dist >= len) { /* too near */ if (seg->t[0] <= t && t <= seg->t[1]) { shiftlen = len - dist; move = norm; ScaleVector2(move,shiftlen); AddVector2(*shift,move,*shift); mFxfire/disco.h000644 000316 000311 00000003360 06114620343 013374 0ustar00wrzlgup000000 000000 /***************************************************************************** * disco.h ******************************************************************************/ #define MAXWEDGE 4 #define MAXSEGS 256 typedef struct TSegment { DISCONTINUITY discontinuity; TPoint2f point1; TPoint2f point2; } TSegment; typedef struct TEdge { char marked; char inplane; TPoint3f origin; /* edge origin */ TVector3f direction; /* edge direction */ TPoint3f intersection; TPoint2f intersect2; } TEdge; typedef struct TWedge { DISCONTINUITY discontinuity; char marked; TEdge *edge[2]; } TWedge; typedef struct TBSP { DISCONTINUITY discontinuity; int nWedge; TPlane plane; TWedge *wedge[MAXWEDGE]; struct TBSP *front; struct TBSP *back; } TBSP; typedef struct TDisco { int nWedges; TWedge *wedge; int nEdges; TEdge *edge; TBSP *bsp; } TDisco; typedef struct TDiscoSeg { DISCONTINUITY discontinuity; int side; TPoint2f point[2]; double t[2]; struct TDiscoSeg *next; } TDiscoSeg; typedef struct TBSP2d { char project; TLine line; TDiscoSeg *seg; struct TBSP2d *front; struct TBSP2d *back; } TBSP2d; /* disco.c */ void free_bsp2(TBSP2d *bsp); TDisco *calc_disco_mesh(TShooter *shooter1,TSurface *shader); void free_disco_mesh(TDisco *disco); void construct_disco(TDisco *disco,TElement *ep,TBSP2d **bsp2d); int find_d0_segments(TSurface *theSurf,TSurface *surf,TBSP2d **bsp2d); int clip_segments(TSurface *surf,TElement *ep,TBSP2d *bsp,int nSeg, TSegment *segs); int on_d0(TBSP2d *bsp,TPoint2f *point2); /* subdiv.c */ int triangulate_element(TSurface *surf,TElement *ep,TSegment *segs,int nSeg, VOID (*triproc)(TRIANG *surf,SITE_PTR s1,SITE_PTR s2,SITE_PTR s3, DISCONTINUITY d1,DISCONTINUITY d2,DISCONTINUITY d3)); sco *disco); void construct_disco(TDisco *disco,TElement *ep,TBSP2d **bsp2d); int find_d0_segments(TSurface *theSurf,TSurface *surf,TBSP2d **bsp2d); int clip_segments(TSurface *surf,TElement *ep,TBSP2d *bsp,int nSeg, TSegment *segs); int on_d0(TBSP2d *bsp,TFxfire/display.c000644 000316 000311 00000013024 06114620343 013731 0ustar00wrzlgup000000 000000 /****************************************************************************** * display.c ******************************************************************************/ #include #include #include #include #include "rad.h" #include "geom.h" #include "dt.h" #include "disco.h" #include "log.h" /*#define GEN_LOG_DT*/ /*#define DISPLAYMESH*/ #define MAXTRI 100 #define MAXEDGESAMP 100 typedef struct TTri { TPoint3f pt[3]; TSpectra rad[3]; } TTri; static void GetAmbient(TSpectra* ambient) { double area,temp1; TPatch* pp; TSpectra unshotSum,temp; static int first = 1; static double areaSum; static TSpectra rAvg; if (first) { TSpectra rSum; /* sum area and (area*reflectivity) */ areaSum = 0.0; rSum = black; FOR_ALL_PATCHES(pp) area = pp->area; areaSum += area; SpectraMultK(&pp->surf->reflectance,area,&temp); SpectraAddTo(&rSum,&temp); END_ALL_PATCHES(pp) /* calc 1 / (1 - rSum / areaSum) */ SpectraMultK(&rSum,1.0 / areaSum,&temp); SpectraSub(&white,&temp,&temp); SpectraInv(&temp,&rAvg); /* average reflectivity */ first = 0; } /* sum (unshot radiosity * (area / areaSum)) */ unshotSum = black; FOR_ALL_PATCHES(pp) temp1 = pp->area / areaSum; SpectraMultK(&pp->unshotRad,temp1,&temp); SpectraAddTo(&unshotSum,&temp); END_ALL_PATCHES(pp) /* compute ambient */ SpectraMult(&unshotSum,&rAvg,ambient); } /*****************************************************************************/ static TSurface *cursurf; static int tricnt; static TTri *triangles; static VOID triproc(TRIANG *surf,SITE_PTR s1,SITE_PTR s2,SITE_PTR s3, DISCONTINUITY d1,DISCONTINUITY d2,DISCONTINUITY d3) { TSample *sp; sp = get_info(surf,s1); Project3d(*cursurf,sp->point2,triangles[tricnt].pt[0]); triangles[tricnt].rad[0] = sp->rad; sp = get_info(surf,s2); Project3d(*cursurf,sp->point2,triangles[tricnt].pt[1]); triangles[tricnt].rad[1] = sp->rad; sp = get_info(surf,s3); Project3d(*cursurf,sp->point2,triangles[tricnt].pt[2]); triangles[tricnt].rad[2] = sp->rad; tricnt++; } /*****************************************************************************/ static int avoid_tvertices(TElement *ep,TTri *tri) { int i,nSamples; TSample *samples[MAXEDGESAMP]; TSegment segs[MAXEDGESAMP]; nSamples = 0; FindSamplesOnEdges(ep,ep->patch->surf->elements,samples,&nSamples); if (nSamples == 0) return(0); if (nSamples > MAXEDGESAMP) error("Oh shit!"); for (i = 0; i < nSamples; i++) { segs[i].point1 = samples[i]->point2; segs[i].discontinuity = DINF; /* mark as single sample */ } tricnt = 0; triangles = tri; cursurf = ep->patch->surf; (void) triangulate_element(cursurf,ep,segs,nSamples,triproc); return(tricnt); } void DisplayResults(int iterNr,TView* view,char *filename,int force) { int i,nTri; TElement* ep; TVector3f normal; TSpectra ambient,amb; TPoint3f pts[kMaxPolyPoints]; TSpectra rads[kMaxPolyPoints]; TTri tri[MAXTRI]; GetAmbient(&amb); if (! BeginOutput(iterNr,view,filename,force)) return; FOR_ALL_ELEMENTS(ep) SpectraMult(&amb,&ep->patch->surf->reflectance,&ambient); normal = ep->patch->surf->normal; #ifdef GEN_LOG_DT { char stringx[]="S0000"; sprintf(stringx,"S%d",ep->patch->surf->surfId); log_geom(stringx,ep); } #endif nTri = 0; if (params.tvertices) nTri = avoid_tvertices(ep,tri); if (nTri == 0) { for (i = 0; i < ep->nPts; i++) { #ifdef DISPLAYMESH pts[i] = ep->sample[i]->point; #else Project3d(*ep->patch->surf,ep->sample[i]->point2,pts[i]); #endif rads[i] = ep->sample[i]->rad; } OutputPolygon(iterNr,ep->nPts,pts,&normal,&ep->rad,&ambient, rads,ep->patch->surf->surfId + 1); } else { for (i = 0; i < nTri; i++) OutputPolygon(iterNr,3,tri[i].pt,&normal,&ep->rad,&ambient, tri[i].rad,ep->patch->surf->surfId + 1); } END_ALL_ELEMENTS(ep) EndOutput(); } /********************************* DT output *******************************/ static BOOLEAN testproc(VOIDPTR orig,VOIDPTR dest,VOIDPTR side1,VOIDPTR side2) { double x1,x2; TSpectra diff1,diff2; SpectraSub(&((TSample *)orig)->rad,&((TSample *)dest)->rad,&diff1); SpectraSub(&((TSample *)side1)->rad,&((TSample *)side2)->rad,&diff2); x1 = SpectraAbsSum(&diff1); x2 = SpectraAbsSum(&diff2); if (x1 < x2 || fabs(x1 - x2) < 1E-4) /* not enough difference */ return(FALSE); message("."); return(TRUE); /* flip it */ } static int iteration; static TSpectra amb; static VOID triprocDT(TRIANG *surf,SITE_PTR s1,SITE_PTR s2,SITE_PTR s3, DISCONTINUITY d1,DISCONTINUITY d2,DISCONTINUITY d3) { int i; TSample *sp; TPoint3f pts[3]; TSpectra ambient,rad,rads[3]; sp = get_info(surf,s1); Project3d(*cursurf,sp->point2,pts[0]); rads[0] = sp->rad; sp = get_info(surf,s2); Project3d(*cursurf,sp->point2,pts[1]); rads[1] = sp->rad; sp = get_info(surf,s3); Project3d(*cursurf,sp->point2,pts[2]); rads[2] = sp->rad; rad = rads[0]; for (i = 1; i < 3; i++) SpectraAddTo(&rad,&rads[i]); SpectraMultK(&rad,1.0 / 3.0,&rad); SpectraMult(&amb,&sp->patch->surf->reflectance,&ambient); OutputPolygon(iteration,3,pts,&sp->patch->surf->normal,&rad, &ambient,rads,sp->patch->surf->surfId + 1); } void DisplayResultsDT(int iterNr,TView* view,char *filename,int force) { TSurface *surf; message("flipping"); FOR_ALL_SURFS(surf) flip_flipable_edges(surf->vd,testproc); END_ALL_SURFS(surf) message("\n"); iteration = iterNr; GetAmbient(&amb); if (! BeginOutput(iterNr,view,filename,force)) return; for_all_triangles(surf->vd,triprocDT); /* output all triangles */ EndOutput(); } olygon(iteration,3,pts,&sp->patch->surf->normal,&rad, &ambient,rads,sp->patch->surf->surfId + 1); } void DisplayResultsDT(int iterNr,TView* view,char *filename,int force) { TSurface *surf; message("flipping"); FOR_ALL_SURFS(surf) flip_flipable_edges(surf->vd,testproc); END_ALL_SURFS(surf) message("\n"); iteration = iterNr; GetAmbient(&amb); if (! BeginOutput(iterNr,view,filename,force)) return; for_all_triangles(surf->vd,triprocDT); /* output all triangles */Fxfire/dt.c000644 000316 000311 00000102566 06114623160 012705 0ustar00wrzlgup000000 000000 /**********************************************************************/ /* Delaunay-Triangulation-Module */ /* */ /* (c) 1993 by Wolfgang Stuerzlinger (wRZL) */ /* thanks to Dani Lischinski for major help/tips */ /* This code may be used only for non-commercial purposes ! */ /**********************************************************************/ /* #define DEBUG */ /* FIXME: new memory management !!! */ #include "dt.h" #include #include #include #include #include #define SITEALLOC 1000 static TRIANG *_surf; /******************************** geometr2 ************************/ #define v2length_2(v) ((v).x * (v).x + (v).y * (v).y) #define v2dist_2(v1,v2) ((v1).x - (v2).x) * ((v1).x - (v2).x) + \ ((v1).y - (v2).y) * ((v1).y - (v2).y) #define v2dot(v1,v2) ((v1).x * (v2).x + (v1).y * (v2).y) #define v2cross(v1,v2) ((v1).x * (v2).y - (v1).y * (v2).x) #define v2midpnt(v1,v2,v) \ { \ (v).x = ((v1).x + (v2).x) * 0.5; \ (v).y = ((v1).y + (v2).y) * 0.5; \ } #define v2sub(v1,v2,v) \ { \ (v).x = (v1).x - (v2).x; \ (v).y = (v1).y - (v2).y; \ } #define v2add(v1,v2,v) \ { \ (v).x = (v1).x + (v2).x; \ (v).y = (v1).y + (v2).y; \ } #define v2turnl(v1,v) \ { \ (v).x = -(v1).y; \ (v).y = (v1).x; \ } #define v2turnr(v1,v) \ { \ (v).x = (v1).y; \ (v).y = -(v1).x; \ } #define v2divk(v,k) \ { \ (v).x /= (k); \ (v).y /= (k); \ } #define v2normalize(v) \ { \ FLOAT _len = v2length_2(v); \ \ if (_len != 0.0) \ { \ _len = sqrt(_len); \ v2divk(v,_len); \ } \ } #define v2scale(v,s) \ { \ (v).x *= (s); \ (v).y *= (s); \ } #define v2addto(v,v1) \ { \ (v).x += (v1).x; \ (v).y += (v1).y; \ } #define incircle(a,b,c,d) (distcircle(a,b,c,d) > 0.0) DOUBLE distcircle(PNT2 *a,PNT2 *b,PNT2 *c,PNT2 *d) { DOUBLE az,bz,cz,dz,result; az = a->x * a->x + a->y * a->y; bz = b->x * b->x + b->y * b->y; cz = c->x * c->x + c->y * c->y; dz = d->x * d->x + d->y * d->y; result = ( a->y * (bz * c->x + cz * d->x + b->x * dz) + az * (b->x * c->y + b->y * d->x + c->x * d->y) + a->x * (b->y * cz + bz * d->y + c->y * dz) + bz * c->y * d->x + b->x * cz * d->y + b->y * c->x * dz ) - ( az * (b->y * c->x + c->y * d->x + b->x * d->y) + a->x * (bz * c->y + cz * d->y + b->y * dz) + a->y * (b->x * cz + c->x * dz + bz * d->x) + b->y * cz * d->x + bz * c->x * d->y + b->x * c->y * dz ); return(result); } #define calc_ccw(a,b,c) \ ((a->x - c->x) * (b->y - c->y) - (b->x - c->x) * (a->y - c->y)) DOUBLE ccw(PNT2 *a,PNT2 *b,PNT2 *c) /* > 0.0 iff A, B, C form a counterclockwise oriented triangle */ { DOUBLE result; if ((a->x == b->x && a->y == b->y) || (a->x == c->x && a->y == c->y) || (b->x == c->x && b->y == c->y)) return(0.0); result = calc_ccw(a,b,c); if (fabs(result) < 1.0E-10) { /* we need a more stable result */ result += calc_ccw(a,c,b); result += calc_ccw(b,a,c); result += calc_ccw(b,c,a); result += calc_ccw(c,a,b); result += calc_ccw(c,b,a); result /= 6.0; } if (result == -0.0) result = 0.0; return(result); } #define LINE_EPS 1E-6 BOOLEAN approxonline(PNT2 *x,PNT2 *a,PNT2 *b) /* return TRUE if point in LINE_EPS region of line */ { DOUBLE len1,len2,len3,la,lb,lc,dist; VEC2 t; len1 = v2dist_2(*x,*a); len2 = v2dist_2(*x,*b); if (len1 < LINE_EPS * LINE_EPS || len2 < LINE_EPS * LINE_EPS) return(TRUE); v2sub(*b,*a,t); len3 = v2length_2(t); if (len1 > len3 || len2 > len3) return(FALSE); len3 = sqrt(len3); la = t.y / len3; lb = -t.x / len3; lc = -(la * a->x + lb * a->y); dist = la * x->x + lb * x->y + lc; if (fabs(dist) < LINE_EPS) return(TRUE); return(FALSE); } #define SWAP(a,b,t) { t = a; a = b; b = t; } /* use intersect_test before that proc to test if the lines really intersect */ BOOLEAN vintersect(PNT2 *p1,PNT2 *p2,PNT2 *p3,PNT2 *p4,PNT2 *inter) { DOUBLE a1,a2,b1,b2,c1,c2; DOUBLE denom,num; if (approxonline(p1,p3,p4)) { *inter = *p1; return(TRUE); } if (approxonline(p2,p3,p4)) { *inter = *p2; return(TRUE); } a1 = p2->y - p1->y; /* calc: a1 x + b1 y + c1 = 0 */ b1 = p1->x - p2->x; c1 = p2->x * p1->y - p1->x * p2->y; a2 = p4->y - p3->y; /* calc: a2 x + b2 y + c2 = 0 */ b2 = p3->x - p4->x; c2 = p4->x * p3->y - p3->x * p4->y; denom = a1 * b2 - a2 * b1; if (fabs(denom) < 1E-10) /* collinear :-( */ return(FALSE); num = b1 * c2 - b2 * c1; inter->x = num / denom; num = a2 * c1 - a1 * c2; inter->y = num / denom; return(TRUE); } VOID circle_center(PNT2 *a,PNT2 *b,PNT2 *c,PNT2 *center) /* computes the center of the circle passing through A, B & C. */ { PNT2 ac,bc,temp1,temp2; DOUBLE ac2,bc2,area; v2sub(*a,*c,ac); ac2=v2dot(ac,ac); v2sub(*b,*c,bc); bc2=v2dot(bc,bc); area = v2cross(ac,bc); v2scale(ac,bc2); v2scale(bc,ac2); v2sub(ac,bc,temp1); v2turnr(temp1,temp2); v2scale(temp2,-0.5 / area); v2add(*c,temp2,*center); } /******************************* General macros *******************************/ #ifdef DEBUG #define alive(x) log_message(x) #define log_insert_edge(a,b,d) log_message("E %g %g %g %g\n",X(a),Y(a),X(b),Y(b),dcol[d]) #define log_insert_site(x,y,n) log_message("V %g %g # %d\n",x,y,n) #define log_ccw(a,b,c) log_message("ccw: %g\n",ccw(&Site(a),&Site(b),&Site(c))) #define log_edge(s,e) log_message("%s: %g,%g %g,%g\n",s, \ X(orig(e)),Y(orig(e)),X(dest(e)),Y(dest(e))) int dcol[] = { 11, 12, 13, 14, 15 }; #else #define alive(x) #define log_insert_edge(a,b,d) #define log_insert_site(x,y,n) #define log_ccw(a,b,c) #define log_edge(s,e) #endif /****************************************************************/ /* Neighbour/Voronoi Management */ /****************************************************************/ #define NEIGHBOURSIZE 100 #define VORONOISIZE 100 static INT n_index; static NEIGHBOURS n_list[NEIGHBOURSIZE]; static INT v_index = 0; static VORONOIS v_list[VORONOISIZE]; static VOID free_neighbours(VOID) { n_index = 0; } static NEIGHBOURS *alloc_neighbour_node(SITE_PTR site,DISCONTINUITY d) { NEIGHBOURS *n; if (n_index >= NEIGHBOURSIZE) fprintf(stderr,"No more neighbours\n"); n = &n_list[n_index]; n_index++; n->site = site; n->d = d; n->next = NULL; return(n); } static VOID free_voronois(VOID) { v_index = 0; } /* Double linked list manipulation */ /* insert a node after ring, ring points to new node afterwards ! */ static VOID insert_node(VORONOIS **ring,VEC2 from,VEC2 to,DISCONTINUITY d, INT done) { VORONOIS *node,*temp; if (v_index >= VORONOISIZE) fprintf(stderr,"No more voronois"); node = &v_list[v_index]; v_index++; if (*ring == NULL) { *ring = node; node->next = node; node->prev = node; } else { temp = (*ring)->next; (*ring)->next = node; node->next = temp; temp->prev = node; node->prev = *ring; *ring = node; } node->from = from; node->to = to; node->d = d; node->done = done; } /* delete the node at ring, ring points to next node afterwards */ VOID delete_node(VORONOIS **ring) { VORONOIS *temp; if ((*ring)->next == *ring || (*ring)->next == NULL) { *ring = NULL; /* optional: release *ring */ return; } temp = *ring; temp->next->prev = temp->prev; temp->prev->next = temp->next; *ring = temp->next; /* optional release temp */ } /****************************************************************/ /* Edge storage management*/ /****************************************************************/ #define NYL -1 static VOID delete_all_edges(VOID) { _surf->next_edge = 0; _surf->avail_edge = NYL; _surf->n_edges = 0; } static EDGE_PTR alloc_edge(VOID) { EDGE_PTR ans; _surf->n_edges++; if (_surf->avail_edge == NYL) ans = _surf->next_edge, _surf->next_edge += 4; else ans = _surf->avail_edge, _surf->avail_edge = onext(_surf->avail_edge); return(ans); } static VOID free_edge(EDGE_PTR e) { e ^= e & 3; onext(e) = _surf->avail_edge; _surf->avail_edge = e; _surf->n_edges--; } /****************************************************************/ /* Quad-edge manipulation primitives */ /****************************************************************/ static EDGE_PTR makeedge(SITE_PTR origin,SITE_PTR destination,DISCONTINUITY d) { register EDGE_PTR temp, ans; assert(origin != destination); assert(X(origin) != X(destination) || Y(origin) != Y(destination)); temp = alloc_edge(); ans = temp; disco(ans) = d; onext(temp) = ans; orig(temp) = origin; onext(++temp) = ans + 3; onext(++temp) = ans + 2; orig(temp) = destination; onext(++temp) = ans + 1; Edge(origin) = ans; Edge(destination) = sym(ans); return(ans); } static VOID splice(EDGE_PTR a,EDGE_PTR b) { EDGE_PTR alpha, beta, temp; alpha = rot(onext(a)); beta = rot(onext(b)); temp = onext(alpha); onext(alpha) = onext(beta); onext(beta) = temp; temp = onext(a); onext(a) = onext(b); onext(b) = temp; Edge(orig(a)) = a; Edge(orig(b)) = b; } static VOID swapedge(EDGE_PTR e) { EDGE_PTR a,b,syme; a = oprev(e); syme = sym(e); b = oprev(syme); splice(e, a); splice(syme, b); splice(e, lnext(a)); splice(syme, lnext(b)); orig(e) = dest(a); Edge(orig(a)) = a; /* correct point references */ dest(e) = dest(b); Edge(orig(b)) = b; } static EDGE_PTR connect_left(EDGE_PTR a, EDGE_PTR b,DISCONTINUITY d) { register EDGE_PTR ans; ans = makeedge(dest(a), orig(b),d); splice(ans, lnext(a)); splice(sym(ans), b); return(ans); } static EDGE_PTR connect_right(EDGE_PTR a, EDGE_PTR b,DISCONTINUITY d) { register EDGE_PTR ans; ans = makeedge(dest(a), orig(b),d); splice(ans, sym(a)); splice(sym(ans), oprev(b)); return(ans); } static VOID deleteedge(EDGE_PTR e) /* disconnects e from the rest of the structure and destroys it. */ { if (e == _surf->Last_locate_edge || e == sym(_surf->Last_locate_edge)) _surf->Last_locate_edge = onext(e); Edge(orig(e)) = oprev(e); /* reset point references */ Edge(dest(e)) = lnext(e); splice(e, oprev(e)); splice(sym(e), oprev(sym(e))); free_edge(e); } /* copied from code by Dani Lischinski */ static VOID splitedge(EDGE_PTR e,SITE_PTR site) { EDGE_PTR t,newe; t = lnext(e); splice(sym(e),t); Edge(orig(t)) = t; /* to make sure it's ok ! */ dest(e) = site; newe = connect_left(e,t,disco(e)); Edge(site) = newe; } /****************************************************************/ /* Quad-edge storage allocation */ /****************************************************************/ #define my_alloc(str_name, str_type, str_cnt) \ if (NULL == ((str_name) = (str_type *) \ malloc ((unsigned) ((str_cnt) * sizeof(str_type))))) \ fprintf(stderr," cannot malloc %s \n",#str_name) static VOID sef_alloc(INT n) { my_alloc(_surf->sa, struct SITE, n ); /* FIXME??? */ my_alloc(_surf->org, SITE_PTR, 12*n ); my_alloc(_surf->next, EDGE_PTR, 12*n ); my_alloc(_surf->ei, struct EDGE_INFO, 3*n ); } static VOID sef_free(VOID) { free((char *)_surf->sa); free((char *)_surf->org); free((char *)_surf->next); free((char *)_surf->ei); } static VOID sef_enlarge(INT additional) { INT n; TRIANG old_surf,*temp; old_surf = *_surf; n = _surf->alloced_sites; _surf->alloced_sites += additional; sef_alloc(_surf->alloced_sites); memcpy(_surf->sa,old_surf.sa,sizeof(struct SITE) * n); memcpy(_surf->org,old_surf.org,sizeof(SITE_PTR) * 12 * n); memcpy(_surf->next,old_surf.next,sizeof(EDGE_PTR) * 12 * n); memcpy(_surf->ei,old_surf.ei,sizeof(struct EDGE_INFO) * 3 * n); temp = _surf; _surf = &old_surf; sef_free(); _surf = temp; } /****************************************************************/ /* Site location */ /* find an edge where site lies left or on ! */ /****************************************************************/ #define SITECMP(vec,site) (fabs(vec.x - X(site)) < 1E-16 && \ fabs(vec.y - Y(site)) < 1E-16) static BOOLEAN v_locate ( VEC2 site, EDGE_PTR *edge,SITE_PTR *oldsite ) { register EDGE_PTR e; INT i; i = 0; e = _surf->Last_locate_edge; while (1) { i++; if (SITECMP(site,orig(e))) { *edge = e; *oldsite = orig(e); return(TRUE); } else if (SITECMP(site,dest(e))) { *edge = e; *oldsite = dest(e); return(TRUE); } else if (v_rightof(site,e)) e = sym(e); else if (v_leftoron(site,onext(e))) e = onext(e); else if (v_leftoron(site,dprev(e))) e = dprev(e); else break; } /* As Gordon said: Check it! */ assert(v_leftoron(site,e)); assert(v_leftof(site,lnext(e))); assert(v_leftof(site,lprev(e))); assert(v_rightoron(site,sym(e))); assert(v_rightof(site,dprev(e))); assert(v_rightof(site,onext(e))); assert(dest(lnext(e)) == orig(lprev(e))); assert(dest(onext(e)) == orig(dprev(e))); assert(dest(lnext(e)) == orig(dprev(e))); *edge = e; *oldsite = 0; return(FALSE); } /****************************************************************/ /* Incremental Site Insertion */ /* with a lot of ideas by Dani Lischinski */ /****************************************************************/ /* recursive edge flipping to the right of an edge */ static VOID fix_edge_right(EDGE_PTR *e) { EDGE_PTR f,g; if (disco_edge(*e)) return; f = oprev(*e); g = dnext(*e); if (incircle(&Site(dest(*e)),&Site(dest(onext(*e))),&Site(orig(*e)), &Site(dest(f)))) { swapedge(*e); fix_edge_right(&f); fix_edge_right(&g); } } /* triangulate anew the loop to the left of first */ /* ??? maybe this only works if all vertices lie to the left of last */ /* i.e. the edge preceeding first ??? */ static VOID triangulate_left(EDGE_PTR first) { EDGE_PTR last,a,b,ea,t1,t2; last = lprev(first); while (lnext(lnext(first)) != last) { /* still > triangle */ ea = lnext(first); t1 = first; while (ea != last) { alive("T"); t2 = lnext(ea); if (t2 == last && t1 == first) break; if (leftof(dest(ea),t1)) { if (t1 == first) { first = sym(connect_left(ea,t1,DINF)); t1 = first; } else t1 = sym(connect_left(ea,t1,DINF)); a = oprev(t1); b = dnext(t1); fix_edge_right(&a); fix_edge_right(&b); ea = t2; } else { t1 = ea; ea = t2; } } } a = lnext(last); b = lprev(last); fix_edge_right(&a); fix_edge_right(&b); fix_edge_right(&last); } /****************************************************************/ /* Incremental Delaunay Triangulation Procedure */ /****************************************************************/ /* this one does not flip unflippable edges ! */ static VOID incremental_delaunay(SITE_PTR site,EDGE_PTR edge) { SITE_PTR first; EDGE_PTR e,t,base; EDGE_PTR a,b,c,d; e = edge; /* site lies left or on edge ! */ if (onedge(site,e)) { /* we are on an existing edge */ a = oprev(e); b = dnext(e); c = lnext(e); d = lprev(e); splitedge(e,site); connect_left(e,lprev(e),DINF); connect_left(oprev(e),sym(e),DINF); fix_edge_right(&a); fix_edge_right(&b); fix_edge_right(&c); fix_edge_right(&d); return; } first = orig(e); base = makeedge(first,site,DINF); splice(base,e); do { base = connect_left(e,sym(base),DINF); e = oprev(base); } while (dest(e) != first); while (1) { t = oprev(e); if (flipable(e) && rightof(dest(t),e) && incircle(&origv(e),&destv(t),&destv(e),&Site(site))) { swapedge(e); e = oprev(e); continue; } else if (orig(e) == first) break; e = lprev(onext(e)); } } VOID insert_edge(TRIANG *surf, SITE_PTR a,SITE_PTR b, DISCONTINUITY discontinuity,SITE_PTR *new_sites,INT *n_new) { EDGE_PTR ea,eb,t,ne; SITE_PTR last,cross; VEC2 inter; BOOLEAN inters; log_insert_edge(a,b,discontinuity); if (n_new != NULL) *n_new = 0; /* at the beginning no new stuff */ _surf = surf; ea = Edge(a); /* get edge with a as orig */ eb = Edge(b); /* get edge with b as orig */ alive("."); last = orig(eb); while (orig(ea) != last) { alive("e"); while (rightof(b,ea) || leftoron(b,onext(ea))) ea = onext(ea); assert(dest(onext(ea)) != last); /*assert(! online(dest(onext(ea)),a,b)); new online approx */ log_edge("ea",ea); log_ccw(dest(ea),a,b); if (online(dest(ea),a,b)) { disco(ea) = discontinuity; ea = sym(ea); continue; } t = ea; while (1) { alive("E"); log_edge("t",t); log_edge("lnext(t)",lnext(t)); if (online(dest(lnext(t)),a,b)) { alive("o"); if (lnext(lnext(lnext(t))) == ea) { disco(lnext(lnext(t))) = discontinuity; ea = sym(lnext(t)); break; } else { ne = connect_left(lnext(t),ea,discontinuity); ea = sym(lnext(t)); alive("1"); log_edge("lnext(ne)",lnext(ne)); triangulate_left(lnext(ne)); alive("2"); log_edge("oprev(ne)",oprev(ne)); triangulate_left(oprev(ne)); alive("3"); break; } } else if (leftofline(dest(lnext(t)),a,b)) { /* left not on! */ alive("l"); if (flipable(lnext(t))) deleteedge(lnext(t)); else { /* 2 x-ing disco edges */ inters = vintersect(&origv(lnext(t)),&destv(lnext(t)), &Site(a),&Site(b),&inter); assert(inters); assert(inter.x != X(orig(lnext(t))) || inter.y != Y(orig(lnext(t)))); /* orig not on edge but cross == dest */ assert(inter.x != X(dest(lnext(t))) || inter.y != Y(dest(lnext(t)))); /* dest not on edge but cross = dest */ if (new_sites == NULL) fprintf(stderr,"can't create site for x-ing edges"); if (surf->n_sites == surf->alloced_sites) /* full */ sef_enlarge(SITEALLOC); cross = surf->n_sites++; Site(cross) = inter; Invis(cross) = 0; Info(cross) = NULL; /* has to be set by caller later on */ new_sites[(*n_new)++] = cross; splitedge(lnext(t),cross); ne = connect_left(lnext(t),ea,discontinuity); ea = sym(lnext(t)); alive("4"); log_edge("lnext(ne)",lnext(ne)); triangulate_left(lnext(ne)); alive("5"); log_edge("oprev(ne)",oprev(ne)); triangulate_left(oprev(ne)); alive("6"); break; } } else t = lnext(t); } } } /****************************************************************/ /* Top-level Delaunay Triangulation Procedure */ /****************************************************************/ VOID init_surface(TRIANG **surf,DOUBLE x0,DOUBLE y0,DOUBLE x1,DOUBLE y1) { DOUBLE lenx,leny; EDGE_PTR a,b,c; *surf = (TRIANG *)calloc(sizeof(TRIANG),1); _surf = *surf; _surf->alloced_sites = SITEALLOC; sef_alloc(_surf->alloced_sites); delete_all_edges(); _surf->bbox.min.x = x0; _surf->bbox.min.y = y0; _surf->bbox.max.x = x1; _surf->bbox.max.y = y1; _surf->n_edges = 0; /******************** Generate Basic Mesh **************************/ _surf->n_sites = 4; /* we generate a 10% bigger square */ lenx = (x1 - x0) / 10.0; leny = (y1 - y0) / 10.0; X(0) = x0 - lenx; Y(0) = y0 - leny; Invis(0) = 1; Info(0) = NULL; X(1) = x1 + lenx; Y(1) = y0 - leny; Invis(1) = 1; Info(1) = NULL; X(2) = x1 + lenx; Y(2) = y1 + leny; Invis(2) = 1; Info(2) = NULL; X(3) = x0 - lenx; Y(3) = y1 + leny; Invis(3) = 1; Info(3) = NULL; a = makeedge(0,3,DBDRY); b = makeedge(1,2,DBDRY); c = connect_left(sym(b),a,DBDRY); _surf->One_bndry_edge = sym(c); c = sym(connect_right(rprev(c),c,DINF)); c = connect_left(b,sym(c),DBDRY); _surf->Last_locate_edge = _surf->One_bndry_edge; /* init locate */ } VOID delete_surface(TRIANG *surf) { _surf = surf; sef_free(); } BOOLEAN insert_site(TRIANG *surf,DOUBLE x,DOUBLE y,SITE_PTR *site,VOIDPTR info) { EDGE_PTR e; VEC2 xy; SITE_PTR n; _surf = surf; if (x < _surf->bbox.min.x || x > _surf->bbox.max.x || y < _surf->bbox.min.y || y > _surf->bbox.max.y) { fprintf(stderr,"SITE outside! %g,%g [%g,%g - %g,%g]\n",x,y, _surf->bbox.min.x,_surf->bbox.min.y, _surf->bbox.max.x,_surf->bbox.max.y); return(FALSE); } xy.x = x; xy.y = y; if (v_locate(xy,&e,site)) { /* already there ! */ Info(*site) = info; return(FALSE); } if (surf->n_sites == surf->alloced_sites) /* we're full ! */ sef_enlarge(SITEALLOC); n = surf->n_sites++; Site(n) = xy; Invis(n) = 0; /* it's visible */ Info(n) = info; log_insert_site(x,y,n); incremental_delaunay(n,e); *site = n; return(TRUE); } INT locate_point(TRIANG *surf,DOUBLE x,DOUBLE y,SITE_PTR sites[3]) { EDGE_PTR e; SITE_PTR site; VEC2 xy; _surf = surf; if (x < _surf->bbox.min.x || x > _surf->bbox.max.x || y < _surf->bbox.min.y || y > _surf->bbox.max.y) { fprintf(stderr,"POINT outside! %g,%g [%g,%g - %g,%g]\n",x,y, _surf->bbox.min.x,_surf->bbox.min.y, _surf->bbox.max.x,_surf->bbox.max.y); return(0); } xy.x = x; xy.y = y; if (v_locate(xy,&e,&site)) { /* already there */ sites[0] = site; return(1); } sites[0] = orig(e); sites[1] = dest(e); sites[2] = dest(lnext(e)); return(0); } VOID get_coords(TRIANG *surf,SITE_PTR site,DOUBLE *x,DOUBLE *y) { _surf = surf; *x = X(site); *y = Y(site); } VOIDPTR get_info(TRIANG *surf,SITE_PTR site) { _surf = surf; return(Info(site)); } VOID set_info(TRIANG *surf,SITE_PTR site,VOIDPTR info) { _surf = surf; Info(site) = info; } VOID get_neighbours(TRIANG *surf,SITE_PTR site,NEIGHBOURS **neigh) { EDGE_PTR e,t; NEIGHBOURS *n; _surf = surf; free_neighbours(); /* make room */ *neigh = NULL; e = Edge(site); t = e; do { if (! Invis(dest(e))) { n = alloc_neighbour_node(dest(e),disco(e)); n->next = *neigh; *neigh = n; } e = oprev(e); } while (t != e); } LONG for_all_sites(TRIANG *surf,VOID (*siteproc)(TRIANG *surf,SITE_PTR s)) { LONG cnt; SITE_PTR site; _surf = surf; cnt = 0; for (site = 0; site < surf->n_sites; site++) { if (Invis(site)) continue; if (siteproc != NULL) (*siteproc)(surf,site); cnt++; } return(cnt); } LONG for_all_edges(TRIANG *surf, VOID (*edgeproc)(TRIANG *surf,SITE_PTR s1,SITE_PTR s2,DISCONTINUITY d)) { LONG i,cnt; EDGE_PTR e; _surf = surf; if (_surf->avail_edge != -1) fprintf(stderr,"Aw, Shit not all edges are valid !\n"); e = 0; cnt = 0; for (i = 0; i < _surf->n_edges; i++, e += 4) { if (Invis(orig(e)) || Invis(dest(e))) continue; if (edgeproc != NULL) (*edgeproc)(surf,orig(e),dest(e),disco(e)); cnt++; } return(cnt); } LONG for_all_triangles(TRIANG *surf, VOID (*triproc)(TRIANG *surf,SITE_PTR s1,SITE_PTR s2,SITE_PTR s3, DISCONTINUITY d1,DISCONTINUITY d2,DISCONTINUITY d3)) { LONG cnt; EDGE_PTR e,t; SITE_PTR site; _surf = surf; cnt = 0; for (site = 0; site < surf->n_sites; site++) { if (Invis(site)) continue; e = Edge(site); t = e; do { if (! Invis(dest(e)) && ! Invis(dest(onext(e))) && Y(site) < Y(dest(onext(e)))) { if (Y(site) < Y(dest(e)) || (Y(site) == Y(dest(e)) && X(site) < X(dest(e)))) { if (triproc != NULL) { if (rightof(dest(onext(e)),e)) printf("XX"); (*triproc)(surf,site,dest(e),dest(onext(e)), disco(e),disco(lnext(e)),disco(lprev(e))); } cnt++; } } e = oprev(e); } while (t != e); } return(cnt); } VOID flip_flipable_edges(TRIANG *surf,BOOLEAN (*testproc)(VOIDPTR s1,VOIDPTR s2, VOIDPTR s3,VOIDPTR s4)) { INT i; DOUBLE dist1,dist2; EDGE_PTR e; SITE_PTR s1,s2,s3,s4; _surf = surf; if (_surf->avail_edge != -1) fprintf(stderr,"Aw, Shit not all edges are valid !\n"); e = 0; for (i = 0; i < _surf->n_edges; i++, e += 4) { s1 = orig(e); s2 = dest(e); if (disco_edge(e) || Invis(s1) || Invis(s2)) continue; s3 = dest(oprev(e)); /* point on right */ s4 = dest(onext(e)); /* point on left */ dist1 = distcircle(&Site(s1),&Site(s3),&Site(s2),&Site(s4)); dist2 = distcircle(&Site(s3),&Site(s2),&Site(s4),&Site(s1)); if (dist1 >= 0.0 && dist2 >= 0.0) { /* both are inside */ if ((*testproc)(Info(s1),Info(s2),Info(s3),Info(s4))) swapedge(e); } } } /****************************************************************/ /* Voronoi polygon creation*/ /****************************************************************/ static BOOLEAN intersect_test(VEC2 *from,VEC2 *to,EDGE_PTR e) { if (v_leftoron(*from,e) && /* from lies left or on */ v_rightof(*to,e) && /* to lies right */ v_rightoronline(origv(e),*from,*to) && /* orig lies right or on */ v_leftoronline(destv(e),*from,*to)) /* dest lies left or on */ return(TRUE); return(FALSE); } /* clips the voronoi ring of a site with num_vertex vertices against all disco edges. if flag then we don't clip against e1 */ static VOID voronoiclip(VORONOIS **voron,SITE_PTR site,INT num_vertex, EDGE_PTR e1,EDGE_PTR e2,INT flag) { EDGE_PTR e,t; VORONOIS *v,*v1,*v2; VEC2 center,center1; BOOLEAN inter; v = *voron; if (flag) /* constrained area clip */ e = oprev(e1); /* begin with triangle to the right */ /* of the contrained edge */ else e = e1; /* else use an(y) edge */ while (num_vertex > 0) { alive("C"); assert(v_leftoron(v->from,e)); /* from lies left (or on) */ /* consume all voronoi-edges lying inside (or on) left triangle */ while (v_leftoron(v->to,lnext(e)) && v_leftoron(v->to,lprev(e)) && v_leftoron(v->to,e) && ! v->done) { v = v->next; num_vertex--; } if (v->done || num_vertex == 0) /* this was it ? */ break; /* find edge crossed by voronoi_edge */ t = e; do { if (! v->done && intersect_test(&v->from,&v->to,e)) break; e = lnext(e); } while (t != e); assert(! v->done && intersect_test(&v->from,&v->to,e)); if (flag && e == e2) /* don't even think about trying */ break; /* to clip against that edge */ if (disco_edge(e) && ! v->done) { /* do we have to clip ? */ if (rightof(site,e)) { /* need to clip left ? */ assert(! flag); /* Hopefully never ever */ alive("L"); while (! v->prev->done && v_leftoron(v->from,e)) { /* backup */ v = v->prev; } e = sym(e); /* prepare for clip right ! */ } assert(! v->done); assert(leftoron(site,e)); /* has to be !! */ if (v_onedge(v->from,e)) center = v->from; else { assert(intersect_test(&v->from,&v->to,e)); inter = vintersect(&origv(e),&destv(e),&v->from,&v->to,¢er); assert(inter); } if (center.x == v->from.x && center.y == v->from.y) { delete_node(&v); /* silly case, but NEEDED */ v = v->prev; num_vertex--; } else v->to = center; v1 = v->next; while (v_rightoron(v1->to,e)) { /* kill voronoiedges */ delete_node(&v1); /* on right or on e */ num_vertex--; } if (v_onedge(v1->from,e)) center1 = v1->from; /* test with sym, as we clip other side here ! */ else { assert(intersect_test(&v1->from,&v1->to,sym(e))); inter = vintersect(&origv(e),&destv(e),&v1->from,&v1->to, ¢er1); assert(inter); } v1->from = center1; v2 = v; insert_node(&v2,center,center1,disco(e),0); num_vertex--; /* as we have one vertex less now */ v = v1; e = sym(e); /* turn around so v->from lies left or on */ } /* test if edge ends inside or on triangle to the right of e */ if (v_leftoron(v->to,dnext(e)) && v_leftoron(v->to,oprev(e))) { v = v->next; /* consume it */ num_vertex--; e = sym(e); } else { /* triangle only crossed by voronoi edge */ if (intersect_test(&v->from,&v->to,dnext(e))) e = dnext(e); else if (intersect_test(&v->from,&v->to,oprev(e))) e = oprev(e); else fprintf(stderr,"Error in voronoiclip"); } } *voron = v; } VOID get_voronoi(TRIANG *surf,SITE_PTR site,VORONOIS **voronoi) { INT num_vertex; EDGE_PTR e,first_e,t; VEC2 center,center1,inter; VORONOIS *v,*v1,*saved; BOOLEAN inters; _surf = surf; free_voronois(); /* make room */ v = NULL; e = Edge(site); t = e; do { if (disco_edge(e)) /* look for Discontinuity edges */ break; e = oprev(e); } while (t != e); if (disco_edge(e)) { /* Point on Discontinuity edge(s) */ saved = NULL; first_e = e; do { if (Invis(dest(oprev(e)))) { /* we are outside ! */ do { /* skip those edges ! */ e = oprev(e); } while (Invis(dest(e))); assert(disco(e) == DBDRY); if (e == first_e) /* nothing to do any more */ break; } num_vertex = 0; v = NULL; t = e; /* find first voronoi edge which crosses the disco-edge */ t = oprev(t); cntr(t,¢er); if (v_rightof(center,e)) { /* it's not enough -> gen midpoint */ v2midpnt(origv(e),destv(e),inter); } else { while (! disco_edge(t)) { /* left or on -> wrong side ! */ t = oprev(t); center1 = center; /* save for intersect */ cntr(t,¢er); if (v_rightof(center,e)) /* found a valid vertex ! */ break; } if (v_leftoron(center,e)) { /* stopped on disco edge */ alive("+"); assert(disco_edge(t)); /* weeeell, no vertex at all */ /* -> simulate point on midline of t */ /* as no need that a second vertex exists at all*/ v2sub(destv(t),origv(t),center); /* edge vector */ v2turnl(center,center1); /* turn to left */ v2normalize(center1); /* standard len */ v2scale(center1,10.0); /* make it long ! */ v2midpnt(origv(t),destv(t),center1); v2addto(center1,center); /* gen vertex */ } if (v_onedge(center1,e)) /* avoid silly calculation errors */ inter = center1; else { assert(intersect_test(¢er1,¢er,e)); inters = vintersect(&origv(e),&destv(e),¢er1,¢er, &inter); assert(inters); } } insert_node(&v,origv(e),inter,disco(e),1); /* no clip ! */ insert_node(&v,inter,center,DINF,0); num_vertex++; /* now generate the rest of the voronoi till the next discoedge */ /* maybe we do too much here!, but we will check later on */ while (! disco_edge(t)) { center1 = center; /* save old center */ cntr(oprev(t),¢er); /* calc next point */ insert_node(&v,center1,center,DINF,0); num_vertex++; t = oprev(t); /* next edge */ } /* test if last voronoi edge crosses the disco edge ? */ if (v_leftoron(v->to,t)) { /* it's not enough -> gen midpoint */ if (v_leftof(v->to,t)) { /* to lies left */ v2midpnt(origv(t),destv(t),inter); insert_node(&v,center,inter,DINF,0); num_vertex++; } else /* to lies on ! */ inter = v->to; } else if (v_rightof(v->to,t)) { /* maybe we did too much -> undo */ while (v_rightoron(v->from,t)) { /* right or on */ v1 = v; v = v->prev; delete_node(&v1); assert(v1 != NULL); num_vertex--; }; if (v_onedge(v->to,t)) /* just in that silly case */ inter = v->to; else { assert(intersect_test(&v->from,&v->to,t)); inters = vintersect(&origv(t),&destv(t),&v->from,&v->to, &inter); assert(inters); v->to = inter; } } insert_node(&v,inter,origv(t),disco(t),1); /* last edge */ v = v->next; /* unclippable edge along first disco edge */ if (num_vertex > 0) { /* something to be done ? */ v1 = v; /* save unclippable edge */ v = v->next; /* from is now on e, to is right */ voronoiclip(&v,site,num_vertex,e,t,1); v = v1; /* restore it */ } e = t; /* set new edge for loop */ if (saved != NULL) { v1 = saved->prev; v1->next = v; saved->prev = v->prev; v->prev = v1; saved->prev->next = saved; } else saved = v; } while (e != first_e); v = saved; v->prev->next = NULL; /* convert to list ! */ } else { /* ''normal'' point */ num_vertex = 0; /* first: generate it, simple isn't it */ t = e; first_e = e; /* maybe redundant? */ saved = NULL; cntr(e,¢er); do { center1 = center; cntr(oprev(e),¢er); /* calc next center */ insert_node(&v,center1,center,DINF,0); if (v_leftoron(center1,e) && v_rightof(center,e)) { first_e = e; /* edge crossed by it's voronoi edge */ saved = v; } num_vertex++; e = oprev(e); } while (t != e); assert(saved != NULL); v = saved; voronoiclip(&v,site,num_vertex,first_e,first_e,0); /* no edge Terminator :-) */ v->prev->next = NULL; /* convert to list ! */ } *voronoi = v; } { center1 = center; cntr(oprev(e),¢er); /* calc next center */ insert_node(&v,center1,center,DINF,0); if (v_leftoron(ceFxfire/dt.h000644 000316 000311 00000017630 06114620343 012707 0ustar00wrzlgup000000 000000 /**********************************************************************/ /* Delaunay-Triangulation Module */ /* header file */ /* */ /* (c) 1993 by Wolfgang Stuerzlinger (wRZL) */ /* This code may be used only for non-commercial purposes ! */ /**********************************************************************/ /* inserted from system.h */ #define VOID void /* VOID f() = procedure */ #define VOIDPTR void * #ifndef NULL #define NULL ((void *)0L) #endif #define PP(x) x #define Const const #define Extern extern #define Register register #define Signed signed #define Static static #define Unsigned unsigned #define Volatile volatile typedef Unsigned int WORD; /* the machine word */ typedef Unsigned char BOOLEAN; typedef Unsigned char BYTE; /* 8 bit unsigned */ typedef Signed char CHAR; /* 8 bit signed */ #if defined(__GNUC__) || ! defined(__STDC__) typedef char UCHAR; /* for Strings */ #else typedef Unsigned char UCHAR; /* for Strings */ #endif typedef Signed short INT; /* 16 bit signed */ typedef Unsigned short UINT; /* 16 bit unsigned */ typedef Signed long LONG; /* 32 bit signed */ typedef Unsigned long ULONG; /* 32 bit unsigned */ typedef double FLOAT; typedef double DOUBLE; #define FALSE ((BOOLEAN) 0) #define TRUE ((BOOLEAN) 1) typedef struct { FLOAT x; FLOAT y; } VEC2, PNT2; typedef struct { PNT2 min; PNT2 max; } BOX2; /******************************************************************************/ /* Reference for Quad-edge data structure: Leonidas Guibas and Jorge Stolfi, "Primitives for the manipulation of general subdivisions and the computations of Voronoi diagrams", ACM Transactions on Graphics 4, 74-123 (1985). */ /******************************************************************************/ /**************************** Common data structures **************************/ typedef LONG SITE_PTR; typedef LONG EDGE_PTR; typedef LONG INFO_PTR; typedef enum DISCONTINUITY { DBDRY, DTEMP, D0, D1, D2, DINF } DISCONTINUITY; struct SITE { VEC2 vc; EDGE_PTR edge; BOOLEAN invisible; VOIDPTR info; }; struct EDGE_INFO { DISCONTINUITY disco; }; typedef struct TRIANG { LONG n_sites; LONG n_edges; LONG alloced_sites; struct SITE *sa ; EDGE_PTR *next ; SITE_PTR *org ; struct EDGE_INFO *ei ; EDGE_PTR One_bndry_edge; BOX2 bbox; EDGE_PTR Last_locate_edge; EDGE_PTR next_edge; EDGE_PTR avail_edge; } TRIANG; typedef struct NEIGHBOURS { struct NEIGHBOURS *next; SITE_PTR site; DISCONTINUITY d; } NEIGHBOURS; typedef struct VORONOIS { struct VORONOIS *next; /* as we need a ring ! */ struct VORONOIS *prev; /* but it is split up later on ! */ VEC2 from; VEC2 to; DISCONTINUITY d; INT done; } VORONOIS; /******************************************************************************/ /********************** Macros for manipulation of quad-edges *****************/ /* Following edge ordering is used: ** ** ^ ^ \ / ** lnext(e) \ / rprev(e) dprev(e) \ / dnext(e) ** \ / V ** ^ | ** e | sym(e) | ** | V ** ^ / \ ** lprev(e) / \ rnext(e) onext(e) / \ oprev(e) ** / \ V V */ /* SITE_PTR s */ #define X(s) _surf->sa[s].vc.x #define Y(s) _surf->sa[s].vc.y #define Edge(s) _surf->sa[s].edge #define Invis(s) _surf->sa[s].invisible #define Site(s) _surf->sa[s].vc #define Info(s) _surf->sa[s].info /* EDGE_PTR a */ #define sym(a) ((a) ^ 2) #define rot(a) ( (((a) + 1) & 3) | ((a) & ~3) ) #define rotinv(a) ( (((a) + 3) & 3) | ((a) & ~3) ) #define onext(a) _surf->next[a] #define oprev(a) rot(onext(rot(a))) #define lnext(a) rot(onext(rotinv(a))) #define lprev(a) sym(onext(a)) #define rnext(a) rotinv(onext(rot(a))) #define rprev(a) onext(sym(a)) #define dnext(a) sym(onext(sym(a))) #define dprev(a) rotinv(onext(rotinv(a))) #define orig(a) _surf->org[a] #define dest(a) orig(sym(a)) #define left(a) orig(rotinv(a)) #define right(a) orig(rot(a)) #define origv(a) _surf->sa[orig(a)].vc #define destv(a) _surf->sa[dest(a)].vc #define leftv(a) _surf->fa[left(a)].vc #define rightv(a) _surf->fa[right(a)].vc #define info(a) _surf->ei[(a)>>2] #define disco(a) (info(a).disco) /******************************************************************************/ /********************************* MISC ***************************************/ #define flipable(e) (disco(e) > D2) #define disco_edge(e) (disco(e) <= D2) #define rightofline(X,a,b) (ccw(&Site(X),&Site(a),&Site(b))< 0.0) #define rightoronline(X,a,b) (ccw(&Site(X),&Site(a),&Site(b))<=0.0) #define leftofline(X,a,b) (ccw(&Site(X),&Site(a),&Site(b))> 0.0) #define leftoronline(X,a,b) (ccw(&Site(X),&Site(a),&Site(b))>=0.0) /*#define online(X,a,b) (ccw(&Site(X),&Site(a),&Site(b))==0.0)*/ #define online(X,a,b) approxonline(&Site(X),&Site(a),&Site(b)) #define rightof(X,e) (ccw(&Site(X),&origv(e),&destv(e))< 0.0) #define rightoron(X,e) (ccw(&Site(X),&origv(e),&destv(e))<=0.0) #define leftof(X,e) (ccw(&Site(X),&origv(e),&destv(e))> 0.0) #define leftoron(X,e) (ccw(&Site(X),&origv(e),&destv(e))>=0.0) /*#define onedge(X,e) (ccw(&Site(X),&origv(e),&destv(e))==0.0)*/ #define onedge(X,e) approxonline(&Site(X),&origv(e),&destv(e)) #define v_rightofline(X,a,b) (ccw(&X,&a,&b)< 0.0) #define v_rightoronline(X,a,b) (ccw(&X,&a,&b)<=0.0) #define v_leftofline(X,a,b) (ccw(&X,&a,&b)> 0.0) #define v_leftoronline(X,a,b) (ccw(&X,&a,&b)>=0.0) /*#define v_online(X,a,b) (ccw(&X,&a,&b)==0.0)*/ #define v_online(X,a,b) approxonline(&X,&a,&b) #define v_rightof(X,e) (ccw(&X,&origv(e),&destv(e))< 0.0) #define v_rightoron(X,e) (ccw(&X,&origv(e),&destv(e))<=0.0) #define v_leftof(X,e) (ccw(&X,&origv(e),&destv(e))> 0.0) #define v_leftoron(X,e) (ccw(&X,&origv(e),&destv(e))>=0.0) /*#define v_onedge(X,e) (ccw(&X,&origv(e),&destv(e))==0.0)*/ #define v_onedge(X,e) approxonline(&X,&origv(e),&destv(e)) /* calc center of triangle to the left! of e */ #define cntr(e,center) circle_center(&origv(e),&destv(e), \ &destv(onext(e)),center) /****************************** PROTOTYPES ***********************************/ VOID init_surface(TRIANG **surf,double x0,double y0,double x1,double y1); VOID delete_surface(TRIANG *surf); BOOLEAN insert_site(TRIANG *surf,double x,double y,SITE_PTR *site,VOIDPTR info); INT locate_point(TRIANG *surf,DOUBLE x,DOUBLE y,SITE_PTR sites[3]); VOID get_coords(TRIANG *surf,SITE_PTR site,double *x,double *y); VOIDPTR get_info(TRIANG *surf,SITE_PTR site); VOID set_info(TRIANG *surf,SITE_PTR site,VOIDPTR info); VOID get_neighbours(TRIANG *surf,SITE_PTR site,NEIGHBOURS **neigh); LONG for_all_sites(TRIANG *surf,VOID (*siteproc)(TRIANG *surf,SITE_PTR s)); LONG for_all_edges(TRIANG *surf, VOID (*edgeproc)(TRIANG *surf,SITE_PTR s1,SITE_PTR s2,DISCONTINUITY d)); LONG for_all_triangles(TRIANG *surf, VOID (*triproc)(TRIANG *surf,SITE_PTR s1,SITE_PTR s2,SITE_PTR s3, DISCONTINUITY d1,DISCONTINUITY d2,DISCONTINUITY d3)); VOID flip_flipable_edges(TRIANG *surf,BOOLEAN (*testproc)(VOIDPTR s1, VOIDPTR s2,VOIDPTR s3,VOIDPTR s4)); VOID insert_edge(TRIANG *surf, SITE_PTR a,SITE_PTR b, DISCONTINUITY discontinuity,SITE_PTR *new_sites,INT *n_new); VOID get_voronoi(TRIANG *surf,SITE_PTR site,VORONOIS **voronoi); INUITY d)); LONG for_all_triangles(TRIANG *surf, VOID (*triproc)(TRIANG *surf,SITE_PTR s1,SITE_PTR s2,Fxfire/f000755 000316 000311 00000000133 06114643671 012301 0ustar00wrzlgup000000 000000 echo fire Fir/$1.fir $1 $2 $3 $4 $5 $6 $7 $8 $9 fire Fir/$1.fir $1 $2 $3 $4 $5 $6 $7 $8 $9 _edges(TRIANG *surf,BOOLEAN (*testproc)(VOIDPTR s1, VOIDPTR s2,VOIDPTR s3,VOIDPTR s4)); VOID insert_edge(TRIANG *surf, SITE_PTR a,SITE_PTR b, DISCONTINUITY discontinuity,SITE_PTR *new_sites,INT *n_new); VOID get_voronoi(TRIANG *surf,SITE_PTR site,VORONOIS **voronoi); INUITY dµ¯ «ö for_all_triangles(TRIANG *surf, VOID (*triproc)(TRIANµ¯ «ö¨aÐ_PTR s1,SITE_PTR s2,Fxfire/ff.c000644 000316 000311 00000025266 06114620343 012672 0ustar00wrzlgup000000 000000 /****************************************************************************** * ff.c * * Formfactorcalculations ******************************************************************************/ #include #include #include #include #include "rad.h" #include "geom.h" TShooter shooter; /* current shooter */ static TShooter clipped_shooter; /* shooter clipped to cur surface */ /**************************************************************************/ #define MAXVERT 5 /* allow for clipped quads */ #define MAXSHOOTERSUBDIV 3 /* max 64 visibility rays */ #define MAXSHOOTTREE (1+4+16+64) /* max size of subdiv tree */ typedef struct TShootTree { int nPts; double area; TPoint3f vert[MAXVERT]; TPoint3f center; } TShootTree; static int shoot_size[MAXSHOOTERSUBDIV + 1] = { 1, 4, 16, 64 }; static int shoot_offset[MAXSHOOTERSUBDIV + 1] = { 0, 1, 5, 21 }; static TShootTree shoot_node[MAXSHOOTTREE]; static void init_shoot_tree(int target_level,TPolygon *shoot,TPoint3f *center) { int i,j,k,cur_level,dPts[4]; TShootTree *node,*child; TPoint3f dS[4][4]; if (shoot->n > MAXVERT) error("ff module doesn't support more than %d vertices",MAXVERT); shoot_node[0].nPts = shoot->n; /* init root */ for (i = 0; i < shoot->n; i++) shoot_node[0].vert[i] = shoot->vert[i]; shoot_node[0].center = *center; shoot_node[0].area = areaPoly(shoot->vert,shoot->n); for (cur_level = 0; cur_level < target_level; cur_level++) { node = &shoot_node[shoot_offset[cur_level]]; child = &shoot_node[shoot_offset[cur_level + 1]]; for (i = 0; i < shoot_size[cur_level]; i++) { splitPoly4(node->vert, node->nPts, dS, dPts); for (j = 0; j < 4; j++) { child->nPts = dPts[j]; for (k = 0; k < dPts[j]; k++) child->vert[k] = dS[j][k]; calcCenterPoly(dS[j],dPts[j],&child->center); child->area = areaPoly(dS[j],dPts[j]); child++; } node++; } } } /**************************************************************************/ static TRay ray; /* the ray */ static TSurface *sample_surf; /* for intersection avoidance */ static TSurface *cache; /* cache last hit surface */ static TSurface *shader[MAXSHADER]; /* which surface shade */ static int nShader; /* # of shader Patches */ static TSurface *trace_ray(TPoint3f *to) { int j; TSurface *surf; SubVector(ray.direction,*to,ray.origin); /* init ray parameters */ ray.minDistance = 0.0; NormalizeVector(ray.maxDistance,ray.direction); if (cache != NULL && intersect(&ray,cache)) surf = cache; else surf = RayTreeIntersect(&ray,BSPTree,clipped_shooter.surfId, sample_surf->surfId); cache = surf; if (surf != NULL && nShader <= MAXSHADER) { /* save a shader */ for (j = 0; j < nShader; j++) if (surf == shader[j]) break; if (j == nShader) { /* not found */ if (nShader < MAXSHADER) shader[nShader] = surf; nShader++; } } return(surf); } /**************************************************************************/ #define FUDGE_FAC 1.0E-4 static double computeANFormFactor(TPoint3f *sp_point,TVector3f *sp_normal, TShootTree *node) { int i; double ff,len,dot; TVector3f s,t,sxt,s0; if (params.exactFF == 2) { /* use disk approximation */ SubVector(s,node->center,*sp_point); NormalizeVector(len,s); ff = DotVector(s,*sp_normal) * DotVector(s,clipped_shooter.normal); ff = node->area * fabs(ff) / (M_PI * len * len + node->area); return(ff); } ff = 0.0; SubVector(s,node->vert[node->nPts - 1],*sp_point); NormalizeVector(len,s); s0 = s; for (i = 0; i < node->nPts; i++) { if (i < node->nPts - 1) { SubVector(t,node->vert[i],*sp_point); NormalizeVector(len,t); } else t = s0; CrossVector(sxt,s,t); NormalizeVector(len,sxt); len = DotVector(s,t); if (len > 1.0) len = 0.0; else if (len < -1.0) len = M_PI; else len = acos(len); dot = DotVector(sxt,*sp_normal); ff += len * dot; s = t; } ff /= -2.0 * M_PI; if (ff < 0.0) { if (ff < -FUDGE_FAC) message("ANFF: %g",ff); return(0.0); } else if (ff > 1.0) { if (ff > 1.0 + FUDGE_FAC) message("ANFF: %g",ff); return(1.0); } return(ff); } /*************************** Interface ********************************/ static int ffCalled; /* statistics: # if calls */ static int minSubdivLevel; /* statistics: min subdivlevel */ static int maxSubdivLevel; /* statistics: max subdivlevel */ void BeginFF(TPatch *lightSource) { minSubdivLevel = 100; maxSubdivLevel = 0; ffCalled = 0; SetANShooter(lightSource); } void SetANShooter(TPatch *lightSource) { int i; shooter.surfId = lightSource->surf->surfId; shooter.patchId = lightSource->patchId; shooter.lightsource = lightSource->surf->lightsource; shooter.center = lightSource->center; shooter.normal = lightSource->surf->normal; shooter.ndotp = lightSource->surf->ndotp; shooter.area = lightSource->area; shooter.unshotRad = lightSource->unshotRad; shooter.pol.n = lightSource->nPts; for (i = 0; i < shooter.pol.n; i++) shooter.pol.vert[i] = lightSource->vert[i]; } void EndFF(void) { int i; double rFF,avgFF; TSample *sp; TElement *ep; if (params.delaunay) { rFF = 0.0; FOR_ALL_SAMPLES(sp) /* calc current sample radiosities */ if (sp->patch->surf->sampled) rFF += sp->ff * sp->area / shooter.area; END_ALL_SAMPLES(sp) /* use old areas! */ log_message(", Sum of reciprocal FF's %g\n",rFF); } rFF = 0.0; FOR_ALL_ELEMENTS(ep) if (ep->patch->surf->sampled) { avgFF = 0.0; for (i = 0; i < ep->nPts; i++) avgFF += ep->sample[i]->ff; avgFF /= (double) ep->nPts; rFF += avgFF * ep->area / shooter.area; } END_ALL_ELEMENTS(ep) log_message("Sum of reciprocal FF's: %g\n",rFF); log_message("%d ff calls, %d/%d max/min subdivlevel\n",ffCalled, maxSubdivLevel,minSubdivLevel); } /***********************************************************************/ static int shooter_subdiv_level; /* how deep to subdivide */ static int random_rays; /* for random rays */ static double eps_F; /* minimum formfactor */ static double rand_areas[MAXVERT]; /* for randPolyPoint */ static TSpectra rho_shootRad; /* surface rho times shooter rad */ int NewSampleSurface(TSurface *surf) { int x; int level; double avg_rad; TPlane plane,sPlane; surf->sampled = 0; if (surf->surfId == shooter.surfId)/* can't receive energy sent by itself */ return(0); if (SpectraMax(&surf->reflectance) == 0.0) /* no receiver */ return(0); /************** clip the shooter by the current surface *************/ clipped_shooter = shooter; /* copy all data */ plane.normal = surf->normal; /* construct plane */ plane.np = surf->ndotp; sPlane.normal = shooter.normal; sPlane.np = shooter.ndotp; x = poly_clip_to_plane(&shooter.pol,&clipped_shooter.pol,&sPlane,&plane); if (x == POLY_CLIP_BEHIND) return(0); clipped_shooter.area = areaPoly(clipped_shooter.pol.vert, clipped_shooter.pol.n); if (clipped_shooter.area < 1E-12) /* too small -> ferget it */ return(0); calcCenterPoly(clipped_shooter.pol.vert,clipped_shooter.pol.n, &clipped_shooter.center); SpectraMult(&clipped_shooter.unshotRad,&surf->reflectance, &rho_shootRad); /********************** calc the subdiv level ************************/ avg_rad = SpectraMax(&rho_shootRad); eps_F = params.eps_B / avg_rad; level = (int) sqrt(clipped_shooter.area / params.min_A); if (level > MAXSHOOTERSUBDIV) /* limit the level */ level = MAXSHOOTERSUBDIV; shooter_subdiv_level = level; /* set the maximum level */ if (level > maxSubdivLevel) /* build global maximum */ maxSubdivLevel = level; /************************ init random rays ************************/ if (params.randomrays) { randAreas(clipped_shooter.pol.vert,clipped_shooter.pol.n,rand_areas); random_rays = shoot_size[level]; while (random_rays < params.visibleRays) { level++; random_rays = shoot_size[level]; } } /********************* generate the shooter tree **********************/ init_shoot_tree(level,&clipped_shooter.pol,&clipped_shooter.center); surf->sampled = 1; /* we will generate some samples! */ return(1); } /***********************************************************************/ /* Distrib rad from lightSource to a Sample; result in sp->delta_rad */ void ShootRad2Sample(TSample *sp) { int i,level,count; double ff,visibility; double dist; TShootTree *node; TPoint3f *sp_point; TVector3f *sp_normal; TPoint3f randPoint; sp->ff = 0.0; /* just to make sure */ sp->delta_rad = black; sp->nShader = 0; sp_point = &sp->point; sp_normal = &sp->patch->surf->normal; dist = DistPt2Plane(*sp_point,clipped_shooter.normal,clipped_shooter.ndotp); if (dist <= 0.0) /* sample behind shooter */ return; ffCalled++; ff = computeANFormFactor(sp_point,sp_normal,&shoot_node[0]); if (ff <= 0.0) return; /************ determine how exact to calculate visibility **************/ level = (int) sqrt(ff / eps_F); /* find level used by ff */ if (level > shooter_subdiv_level) /* but use minimum */ level = shooter_subdiv_level; if (level < minSubdivLevel) /* build global minimum */ minSubdivLevel = level; /************************ init the rays *******************************/ sample_surf = sp->patch->surf; /* surface the sample lies on */ ray.origin = *sp_point; /* init the ray */ cache = NULL; /* clear cache */ nShader = 0; /* we are shaded homogenously */ for (i = 0; i < MAXSHADER; i++) shader[i] = NULL; /* init shader info */ /*************************** trace 'em *******************************/ count = 0; if (params.randomrays) { for (i = 0; i < random_rays; i++) { randPointPoly(clipped_shooter.pol.vert,rand_areas, clipped_shooter.pol.n,&randPoint); if (trace_ray(&randPoint) == NULL) count++; } visibility = (double) count / (double) random_rays; } else if (params.exactFF > 0) { ff = 0.0; node = &shoot_node[shoot_offset[level]]; for (i = 0; i < shoot_size[level]; i++) { if (trace_ray(&node->center) == NULL) { ff += computeANFormFactor(sp_point,sp_normal,node); count++; } node++; } visibility = (double) count / (double) shoot_size[level]; } else { node = &shoot_node[shoot_offset[level]]; for (i = 0; i < shoot_size[level]; i++) { if (trace_ray(&node->center) == NULL) count++; node++; } visibility = (double) count / (double) shoot_size[level]; } if (params.exactFF != 1) ff *= visibility; /*************************** set resuts *******************************/ sp->nShader = nShader; /* set shader info */ for (i = 0; i < nShader; i++) sp->shader[i] = shader[i]; if (visibility == 0.0) return; SpectraMultK(&rho_shootRad,ff,&sp->delta_rad); sp->ff = ff; } for (i = 0; i < shoot_size[level]; i++) { if (trace_ray(&node->center) == NULL) count++; node++; } visibility = (double) count / (double) shoot_size[level]; } if (params.exactFF != 1) ff *= visibility; /*************************** set resuts *******************************/ sp->nShader = nShader; /*Fxfire/geom.c000644 000316 000311 00000034451 06114620405 013221 0ustar00wrzlgup000000 000000 /****************************************************************************** * geom.c ******************************************************************************/ #include #include #include #include #include #include "rad.h" #include "geom.h" /********************** intersection routines ***************************/ /* Inspired by: An Efficient Ray/Polygon Intersection by Didier Badouel from "Graphics Gems", Academic Press, 1990 */ int intersect(TRay *ray,TSurface *surf) { int i; double ndotv,t; double alpha,beta; TVector3f point; TVector2f v0,v1,v2; TVector2f point2,pt0; ndotv = DotVector(surf->normal,ray->direction); if (ndotv <= 0.0) /* ray parallel/behind plane */ return(0); t = (surf->ndotp - DotVector(surf->normal,ray->origin)) / ndotv; if (t < ray->minDistance || t > ray->maxDistance) return(0); /* t is now parameter of intersection */ point = ray->direction; /* calculate point */ ScaleVector(point,t); AddVector(point,point,ray->origin); Project2d(surf->project,point,point2); if (OutsideBbox2(surf->min2,surf->max2,point2)) return(0); pt0 = surf->vert2[0]; /* precalculate vectors */ SubVector2(v0,point2,pt0); SubVector2(v2,surf->vert2[1],pt0); /************************ test triangles **********************/ if (surf->nPts != 4) { for (i = 2; i < surf->nPts; i++) { v1 = v2; /* copy old vector */ SubVector2(v2,surf->vert2[i],pt0); if (v1.u == 0.0) { /* edge is vertical */ beta = v0.u / v2.u; if (beta >= 0.0 && beta <= 1.0) { alpha = (v0.v - beta * v2.v) / v1.v; if (alpha >= 0.0 && alpha + beta <= 1.0) return(1); } } else { beta = CrossVector2(v0,v1) / CrossVector2(v2,v1); if (beta >= 0.0 && beta <= 1.0) { alpha = (v0.u - beta * v2.u) / v1.u; if (alpha >= 0.0 && alpha + beta <= 1.0) return(1); } } } } else { v1 = v2; /* copy old vector */ SubVector2(v2,surf->vert2[3],pt0); if (v1.u == 0.0) { /* edge is vertical */ beta = v0.u / v2.u; if (beta >= 0.0 && beta <= 1.0) { alpha = (v0.v - beta * v2.v) / v1.v; if (alpha >= 0.0 && alpha <= 1.0) return(1); } } else { beta = CrossVector2(v0,v1) / CrossVector2(v2,v1); if (beta >= 0.0 && beta <= 1.0) { alpha = (v0.u - beta * v2.u) / v1.u; if (alpha >= 0.0 && alpha <= 1.0) return(1); } } } return(0); } /****************************** ray box test ***************************/ int RayBoxIntersect(TRay *ray, TPoint3f *mini, TPoint3f *maxi) { double t; if (ray->direction.x > 0.0) { t = (maxi->x - ray->origin.x) / ray->direction.x; if (t <= ray->minDistance) return(0); if (t <= ray->maxDistance) ray->maxDistance = t; t = (mini->x - ray->origin.x) / ray->direction.x; if (t >= ray->maxDistance) return(0); if (t >= ray->minDistance) ray->minDistance = t; } else if (ray->direction.x < 0.0) { t = (mini->x - ray->origin.x) / ray->direction.x; if (t <= ray->minDistance) return (0); if (t <= ray->maxDistance) ray->maxDistance = t; t = (maxi->x - ray->origin.x) / ray->direction.x; if (t >= ray->maxDistance) return (0); if (t >= ray->minDistance) ray->minDistance = t; } else { /* ray parallel to x-planes */ if (ray->origin.x <= mini->x || ray->origin.x >= maxi->x) return (0); } if (ray->direction.y > 0.0) { t = (maxi->y - ray->origin.y) / ray->direction.y; if (t <= ray->minDistance) return(0); if (t <= ray->maxDistance) ray->maxDistance = t; t = (mini->y - ray->origin.y) / ray->direction.y; if (t >= ray->maxDistance) return(0); if (t >= ray->minDistance) ray->minDistance = t; } else if (ray->direction.y < 0.0) { t = (mini->y - ray->origin.y) / ray->direction.y; if (t <= ray->minDistance) return (0); if (t <= ray->maxDistance) ray->maxDistance = t; t = (maxi->y - ray->origin.y) / ray->direction.y; if (t >= ray->maxDistance) return (0); if (t >= ray->minDistance) ray->minDistance = t; } else { /* ray parallel to y-planes */ if (ray->origin.y <= mini->y || ray->origin.y >= maxi->y) return (0); } if (ray->direction.z > 0.0) { t = (maxi->z - ray->origin.z) / ray->direction.z; if (t <= ray->minDistance) return(0); if (t <= ray->maxDistance) ray->maxDistance = t; t = (mini->z - ray->origin.z) / ray->direction.z; if (t >= ray->maxDistance) return(0); if (t >= ray->minDistance) ray->minDistance = t; } else if (ray->direction.z < 0.0) { t = (mini->z - ray->origin.z) / ray->direction.z; if (t <= ray->minDistance) return (0); if (t <= ray->maxDistance) ray->maxDistance = t; t = (maxi->z - ray->origin.z) / ray->direction.z; if (t >= ray->maxDistance) return (0); if (t >= ray->minDistance) ray->minDistance = t; } else { /* ray parallel to z-planes */ if (ray->origin.z <= mini->z || ray->origin.z >= maxi->z) return (0); } return(1); } /********************** misc geometric routines ***************************/ void calcCenterPoly(TPoint3f *Q,int nPts,TPoint3f *center) { int i; double one_div; TVector3f c; AddVector(c,Q[0],Q[1]); for (i = 2; i < nPts; i++) { AddVector(c,c,Q[i]); } one_div = 1.0 / nPts; ScaleVector(c,one_div); *center = c; } double areaPoly(TPoint3f *Q,int nPts) { int i; double area,sum_area; TVector3f u,v,uxv; sum_area = 0.0; SubVector(u,Q[1],Q[0]); for (i = 2; i < nPts; i++) { /* sum up the triangles */ v = u; SubVector(u,Q[i],Q[0]); CrossVector(uxv,u,v); area = LenVector(uxv); sum_area += area; } area = sum_area * 0.5; /* as we use triangles */ if (area < 0.0) error("areaPoly: illegal polygon"); return(area); } #define setpoly3(index,a,b,c) dQ[index][0] = a; dQ[index][1] = b; \ dQ[index][2] = c; #define setpoly4(index,a,b,c,d) dQ[index][0] = a; dQ[index][1] = b; \ dQ[index][2] = c; dQ[index][3] = d; void splitPoly4(TPoint3f *Q,int nPts,TPoint3f dQ[4][4],int dPts[4]) { int i,j; double len,best_len; TPoint3f midpnt[4],center; if (nPts > 5) error("Can't split >5-sided polygon"); if (nPts == 3) { for (i = 0; i < 3; i++) { j = (i + 1) % 3; AvgVector(midpnt[i],Q[i],Q[j]); } for (i = 0; i < 4; i++) dPts[i] = 3; setpoly3(0,Q[0],midpnt[0],midpnt[2]); setpoly3(1,midpnt[0],Q[1],midpnt[1]); setpoly3(2,midpnt[2],midpnt[1],Q[2]); setpoly3(3,midpnt[0],midpnt[1],midpnt[2]); } else if (nPts == 4) { for (i = 0; i < 4; i++) { j = (i + 1) % 4; AvgVector(midpnt[i],Q[i],Q[j]); dPts[i] = 4; } AvgVector(center,Q[0],Q[2]); setpoly4(0,Q[0],midpnt[0],center,midpnt[3]); setpoly4(1,midpnt[0],Q[1],midpnt[1],center); setpoly4(2,center,midpnt[1],Q[2],midpnt[2]); setpoly4(3,midpnt[3],center,midpnt[2],Q[3]); } else { j = 0; best_len = 0.0; for (i = 0; i < 5; i++) { len = DistPnt(Q[i],Q[(i + 1) % 5]); if (len > best_len) { j = i; best_len = len; } } AvgVector(midpnt[0],Q[j],Q[(j + 1) % 5]); calcCenterPoly(Q,5,¢er); setpoly4(0,Q[j],midpnt[0],center,Q[(j + 4) % 5]); setpoly4(1,midpnt[0],Q[(j + 1) % 5],Q[(j + 2) % 5],center); setpoly3(2,center,Q[(j + 2) % 5],Q[(j + 3) % 5]); setpoly3(3,Q[(j + 4) % 5],center,Q[(j + 3) % 5]); dPts[0] = 4; dPts[1] = 4; dPts[2] = 3; dPts[3] = 3; } } /********************** random Point in Polygon ***************************/ void randAreas(TPoint3f *Q,int nPts,double *areas) { int i; double area_sum; TVector3f u,v,uxv; /* compute relative areas of the sub-triangles of polygon */ area_sum = 0.0; for (i = 0; i < nPts - 2; i++) { SubVector(u,Q[i + 1],Q[0]); SubVector(v,Q[i + 2],Q[0]); CrossVector(uxv,u,v); areas[i] = fabs(LenVector(uxv)); area_sum += areas[i]; } /* normalize areas so that the sum of all sub-triangles is one */ for (i = 0; i < nPts - 2; i++) areas[i] /= area_sum; } void randPointPoly(TPoint3f *Q,double *areas,int nPts,TPoint3f *rand_point) { int i; double s,t,x,area_sum; TPoint3f temp; s = RandomFloat; t = RandomFloat; area_sum = 0.0; for (i = 0; i < nPts - 2; i++) { area_sum += areas[i]; if (area_sum >= s) break; } /* map 's' into the interval [0,1] */ s = (s - area_sum + areas[i]) / areas[i]; /* map (s,t) to a point in that sub-triangle */ /* a = 1 - t; b = (1 - s) * t; c = s * t; */ t = sqrt(t); x = 1.0 - t; *rand_point = Q[0]; ScaleVector(*rand_point,x); x = (1.0 - s) * t; temp = Q[i + 1]; ScaleVector(temp,x); AddVector(*rand_point,*rand_point,temp); x = s * t; temp = Q[i + 2]; ScaleVector(temp,x); AddVector(*rand_point,*rand_point,temp); } /********************* clip a line to the surface ***************************/ /* right is > 0.0 */ #define calc_ccw(v1,v2,p) \ ((v2->u - v1->u) * (v1->v - p->v) - (v2->v - v1->v) * (v1->u - p->u)) double calc_side(TPoint2f *v1,TPoint2f *v2,TPoint2f *p) { double side; if ((v1->u == p->u && v1->v == p->v) || (v2->u == p->u && v2->v == p->v)) return(0.0); side = calc_ccw(v1,v2,p); if (fabs(side) < 1E-7) { /* need a more precise result */ side += calc_ccw(v1,p,v2); side += calc_ccw(v2,v1,p); side += calc_ccw(v2,p,v1); side += calc_ccw(p,v1,v2); side += calc_ccw(p,v2,v1); side /= 6.0; } if (side == -0.0) side = 0.0; return(side); } #ifdef DOUBLEP #define LINE_EPS 1E-14 #else #define LINE_EPS 1E-6 #endif int isonline(TPoint2f *x,TPoint2f *a,TPoint2f *b) /* return TRUE if point in LINE_EPS region of line */ { double len1,len2,len3,la,lb,lc,dist; TVector2f t; len1 = DistPnt2_2(*x,*a); len2 = DistPnt2_2(*x,*b); if (len1 < LINE_EPS * LINE_EPS || len2 < LINE_EPS * LINE_EPS) return(1); SubVector2(t,*a,*b); len3 = DotVector2(t,t); if (len1 > len3 || len2 > len3) return(0); len3 = sqrt(len3); la = t.v / len3; lb = -t.u / len3; lc = -(la * a->u + lb * a->v); dist = la * x->u + lb * x->v + lc; if (fabs(dist) < LINE_EPS) return(1); return(0); } /* NOTE: the sidenumbering in retval is one less than you expect! */ int inside_element(TElement *ep,TPoint2f *point2) { int i,mask; double side; TPoint2f *v1,*v2; mask = 0; v1 = &ep->sample[ep->nPts - 1]->point2; for (i = 0; i < ep->nPts; i++) { v2 = &ep->sample[i]->point2; side = calc_side(v1,v2,point2); if (side >= 0.0) /* right or online is outside */ mask |= 1 << i; v1 = v2; } return(mask); } int intersect_lines(TPoint2f *p1,TPoint2f *p2,TPoint2f *p3,TPoint2f *p4, TPoint2f *inter) { double a1,a2,b1,b2,c1,c2; double denom,num; double side1,side2; if (isonline(p1,p3,p4)) { *inter = *p1; return(1); } if (isonline(p2,p3,p4)) { *inter = *p2; return(1); } side1 = calc_side(p3,p4,p1); side2 = calc_side(p3,p4,p2); if (side1 > 0.0 && side2 > 0.0) return(0); if (side1 < 0.0 && side2 < 0.0) return(0); a1 = p2->v - p1->v; /* calc: a1 x + b1 y + c1 = 0 */ b1 = p1->u - p2->u; c1 = p2->u * p1->v - p1->u * p2->v; a2 = p4->v - p3->v; /* calc: a2 x + b2 y + c2 = 0 */ b2 = p3->u - p4->u; c2 = p4->u * p3->v - p3->u * p4->v; denom = a1 * b2 - a2 * b1; if (fabs(denom) < 1E-10) /* collinear :-( */ return(0); num = b1 * c2 - b2 * c1; inter->u = num / denom; num = a2 * c1 - a1 * c2; inter->v = num / denom; if (! isonline(inter,p1,p2)) message("%1"); if (! isonline(inter,p3,p4)) message("%2"); return(1); } int clip2element(TElement *ep,TPoint2f *p1,TPoint2f *p2) { int i,mask1,mask2; TPoint2f *v1,*v2,inter; TVector2f temp; mask1 = inside_element(ep,p1); mask2 = inside_element(ep,p2); if (mask1 == 0 && mask2 == 0) /* both are inside */ return(1); v1 = &ep->sample[ep->nPts - 1]->point2; for (i = 0; i < ep->nPts; i++) { v2 = &ep->sample[i]->point2; if (mask1 & mask2) /* either one or both are outside */ return(0); /* on the same side */ if ((mask1 ^ mask2) & (1 << i)) { /* different sides */ if (! intersect_lines(p1,p2,v1,v2,&inter)) message("Really ?"); if (mask1 & (1 << i)) { /* p1 is outside */ *p1 = inter; mask1 = inside_element(ep,p1); /* reclassify */ } else { /* (mask2 & (1 << i)) */ /* p2 is outside */ *p2 = inter; mask2 = inside_element(ep,p2); /* reclassify */ } } v1 = v2; } SubVector2(temp,*p2,*p1); if (DotVector2(temp,temp) < 1.0E-6) return(0); /* clipped to nothing */ return(1); } /********************** Polygon clipper ***************************/ /* * homogeneous 3-D convex polygon clipper * * Adapted to arbitrary planes by wRZL, Oct 1993 * original by Paul Heckbert 1985, Dec 1989 * * poly_clip_to_plane: Clip the convex polygon p1 to the given plane * using the homogeneous screen coordinates (sx, sy, sz, sw) of each vertex, * If polygon is entirely front of plane, then POLY_CLIP_IN is returned. * If polygon is entirely behind of plane, then POLY_CLIP_OUT is returned. * Otherwise, if the polygon is cut by the plane, p1 is modified and * POLY_CLIP_SPLIT is returned. */ int poly_clip_to_plane(TPolygon *p1,TPolygon *p2,TPlane *plane1,TPlane *plane) { int behind,i; double t, tu, tv; TPoint3f temp; TPoint3f *v, *u; static double ndotp[kMaxPolyPoints + 1]; /* adr: from p1->n downto 1 */ if (PointEqual(plane1->normal,plane->normal)) { if (plane1->np == plane->np) { p2->n = 0; return(POLY_CLIP_BEHIND); } } /* count vertices "behind" with respect to the plane */ behind = 0; for (v = p1->vert, i = p1->n; i > 0; i--, v++) { ndotp[i] = DotVector(*v,plane->normal); if (ndotp[i] < plane->np) behind++; } if (behind == 0) { /* check if all vertices are front */ memcpy(p2, p1, sizeof(TPolygon) - (kMaxPolyPoints-p1->n) * sizeof(TPoint3f)); return (POLY_CLIP_FRONT); } if (behind == p1->n) { /* check if all vertices are behind */ p2->n = 0; return (POLY_CLIP_BEHIND); } /* now clip against the plane */ p2->n = 0; u = &p1->vert[p1->n - 1]; /* start with u=vert[n-1], v=vert[0] */ tu = - ndotp[1] + plane->np; for (v = p1->vert, i = p1->n; i > 0; i--, u = v, tu = tv, v++) { /* on old polygon (p1), u is previous vertex, v is current vertex */ /* tv is negative if vertex v is in */ tv = - ndotp[i] + plane->np; if ((tu <= 0.0) ^ (tv <= 0.0)) { /* edge crosses plane */ t = tu / (tu - tv); /* add intersection point to p2 */ SubVector(temp,*v,*u); /* vert[p2->n] = u+t*(v-u) */ ScaleVector(temp,t); AddVector(p2->vert[p2->n],*u,temp); p2->n++; } if (tv <= 0.0) /* vertex v is in, copy it to p2 */ p2->vert[p2->n++] = *v; } if (p2->n == 0) return (POLY_CLIP_BEHIND); return (POLY_CLIP_SPLIT); } t vertex */ /* tv is negative if vertex v is in */ tv = - ndotp[i] + plane->np; if ((tu <= 0.0) ^ (tv <= 0.0)) { /* edge crosses plane */ t = tu / (tu - tv); /* add intersection point to p2 */ SubVFxfire/geom.h000644 000316 000311 00000045532 06114620343 013231 0ustar00wrzlgup000000 000000 #ifndef M_PI #define M_PI 3.14159265358979 #endif #define InitPoint(p,x1,y1,z1) (p).x=x1, (p).y=y1, (p).z=z1 #define ZeroVector(a) (a).x = 0.0, (a).y = 0.0, (a).z = 0.0 #define PointEqual(a,b) ((a).x == (b).x && (a).y == (b).y && (a).z == (b).z) #define NegVector(a) (a).x = ((a).x) ? -(a).x : 0.0, \ (a).y = ((a).y) ? -(a).y : 0.0, \ (a).z = ((a).z) ? -(a).z : 0.0 #define AbsVector(c,a) (c).x=fabs((a).x),(c).y=fabs((a).y),(c).z=fabs((a).z) #define AddVector(c,a,b) (c).x=(a).x+(b).x, (c).y=(a).y+(b).y, (c).z=(a).z+(b).z #define SubVector(c,a,b) (c).x=(a).x-(b).x, (c).y=(a).y-(b).y, (c).z=(a).z-(b).z #define CrossVector(c,a,b) (c).x = (a).y*(b).z - (a).z*(b).y, \ (c).y = (a).z*(b).x - (a).x*(b).z, \ (c).z = (a).x*(b).y - (a).y*(b).x #define DotVector(a,b) ((a).x*(b).x + (a).y*(b).y + (a).z*(b).z) #define ScaleVector(c,s) (c).x*=(s), (c).y*=(s), (c).z*=(s) #define NormalizeVector(n,a) ((n)=sqrt(DotVector(a,a)), \ (n)?((a).x/=n, (a).y/=n, (a).z/=n):0.0) #define DistPnt(a,b) sqrt(((b).x - (a).x) * ((b).x - (a).x) + \ ((b).y - (a).y) * ((b).y - (a).y) + ((b).z - (a).z) * ((b).z - (a).z)) #define LenVector(a) sqrt(DotVector(a,a)) #define AvgVector(c,a,b) (c).x=((a).x+(b).x) * 0.5, (c).y=((a).y+(b).y) * 0.5, \ (c).z=((a).z+(b).z) * 0.5 #define VolVector(a,b,c) \ ((a).x*(b).y*(c).z + (a).y*(b).z*(c).x + (a).z*(b).x*(c).y - \ (a).z*(b).y*(c).x - (a).x*(b).z*(c).y - (a).y*(b).x*(c).z) #define DistPt2Plane(p,n,np) (DotVector(n,p) - (np)) #define Inplane(p,n,np) (fabs(DistPt2Plane(p,n,np)) < 1E-14) #define InsideBbox(mini,maxi,p) ((p).x >= (mini).x && (p).x <= (maxi).x && \ (p).y >= (mini).y && (p).y <= (maxi).y && \ (p).z >= (mini).z && (p).z <= (maxi).z) #define MakeBbox(mini,maxi,point) { \ if ((point).x < (mini).x) (mini).x = (point).x; \ else if ((point).x > (maxi).x) (maxi).x = (point).x; \ if ((point).y < (mini).y) (mini).y = (point).y; \ else if ((point).y > (maxi).y) (maxi).y = (point).y; \ if ((point).z < (mini).z) (mini).z = (point).z; \ else if ((point).z > (maxi).z) (maxi).z = (point).z; } #define JoinBbox(min1,max1,min2,max2) { \ if ((min2).x < (min1).x) (min1).x = (min2).x; \ if ((min2).y < (min1).y) (min1).y = (min2).y; \ if ((min2).z < (min1).z) (min1).z = (min2).z; \ if ((max2).x > (max1).x) (max1).x = (max2).x; \ if ((max2).y > (max1).y) (max1).y = (max2).y; \ if ((max2).z > (max1).z) (max1).z = (max2).z; } #define BboxOutside(min1,max1,min2,max2) \ ((min1).x > (max2).x || (min1).y > (max2).y || (min1).z > (max2).z || \ (max1).x < (min2).x || (max1).y < (min2).y || (max1).z < (min2).z) #define FindProject(norm,project) { \ TVector3f _n; \ AbsVector(_n,norm); \ if (_n.x > _n.y && _n.x > _n.z) \ project = ((norm).x >= 0.0) ? 0 : 3; \ else if (_n.y > _n.z) \ project = ((norm).y >= 0.0) ? 4 : 1; \ else \ project = ((norm).z >= 0.0) ? 2 : 5; } #define Project2d(project,d3,d2) switch (project) { \ case 0: (d2).u = (d3).y; (d2).v = (d3).z; break; \ case 1: (d2).u = (d3).x; (d2).v = (d3).z; break; \ case 2: (d2).u = (d3).x; (d2).v = (d3).y; break; \ case 3: (d2).u = -(d3).y; (d2).v = (d3).z; break; \ case 4: (d2).u = -(d3).x; (d2).v = (d3).z; break; \ case 5: (d2).u = -(d3).x; (d2).v = (d3).y; break; } #define Project3d(surf,d2,d3) switch ((surf).project) { \ case 0: (d3).y = (d2).u; (d3).z = (d2).v; \ (d3).x = ((surf).ndotp - (d3).y * (surf).normal.y - \ (d3).z * (surf).normal.z) / (surf).normal.x; break; \ case 1: (d3).x = (d2).u; (d3).z = (d2).v; \ (d3).y = ((surf).ndotp - (d3).x * (surf).normal.x - \ (d3).z * (surf).normal.z) / (surf).normal.y; break; \ case 2: (d3).x = (d2).u; (d3).y = (d2).v; \ (d3).z = ((surf).ndotp - (d3).x * (surf).normal.x - \ (d3).y * (surf).normal.y) / (surf).normal.z; break; \ case 3: (d3).y = -(d2).u; (d3).z = (d2).v; \ (d3).x = ((surf).ndotp - (d3).y * (surf).normal.y - \ (d3).z * (surf).normal.z) / (surf).normal.x; break; \ case 4: (d3).x = -(d2).u; (d3).z = (d2).v; \ (d3).y = ((surf).ndotp - (d3).x * (surf).normal.x - \ (d3).z * (surf).normal.z) / (surf).normal.y; break; \ case 5: (d3).x = -(d2).u; (d3).y = (d2).v; \ (d3).z = ((surf).ndotp - (d3).x * (surf).normal.x - \ (d3).y * (surf).normal.y) / (surf).normal.z; break; } #define InitPoint2(p,x,y) (p).u=x, (p).v=y #define PointEqual2(a,b) ((a).u == (b).u && (a).v == (b).v) #define PointNear2(a,b,eps) (fabs((a).u - (b).u) < (eps) && \ fabs((a).v - (b).v) < (eps)) #define NegVector2(a) (a).u = ((a).u) ? -(a).u : 0.0, \ (a).v = ((a).v) ? -(a).v : 0.0 #define AbsVector2(c,a) (c).u=fabs((a).u),(c).v=fabs((a).v) #define AddVector2(c,a,b) (c).u=(a).u+(b).u, (c).v=(a).v+(b).v #define SubVector2(c,a,b) (c).u=(a).u-(b).u, (c).v=(a).v-(b).v #define ScaleVector2(c,s) (c).u*=(s), (c).v*=(s) #define AvgVector2(c,a,b) (c).u=((a).u+(b).u) * 0.5, (c).v=((a).v+(b).v) * 0.5 #define DotVector2(a,b) ((a).u*(b).u + (a).v*(b).v) #define DistPnt2_2(a,b) sqrt(((b).u - (a).u) * ((b).u - (a).u) + \ ((b).v - (a).v) * ((b).v - (a).v)) #define DistPnt2(a,b) sqrt(DistPnt2_2(a,b)) #define LenVector2(a) sqrt(DotVector2(a,a)) #define CrossVector2(a,b) ((a).u*(b).v - (a).v*(b).u) #define NormalizeVector2(n,a) ((n)=sqrt(DotVector2(a,a)), \ (n)?((a).u/=n, (a).v/=n):0.0) #define TurnVector2Left2(c,a) (c).u = ((a).v)?-(a).v:0.0, (c).v = (a).u #define TurnVector2Right2(c,a) (c).u = (a).v, (c).v = ((a).u)?-(a).u:0.0 #define DistPt2Line(p,n,np) (DotVector2(n,p) - (np)) #define RightofPoints2(v1,v2,p) (calc_side(v1,v2,p) > 0.0) #define OutsideBbox2(mini,maxi,p) ((p).u < (mini).u || (p).u > (maxi).u || \ (p).v < (mini).v || (p).v > (maxi).v) #define InsideBbox2(mini,maxi,p) ((p).u >= (mini).u && (p).u <= (maxi).u && \ (p).v >= (mini).v && (p).v <= (maxi).v) #define BboxOutside2(min1,max1,min2,max2) \ ((min1).u > (max2).u || (min1).v > (max2).v || \ (max1).u < (min2).u || (max1).v < (min2).v) #define MakeBbox2(mini,maxi,point) { \ if ((point).u < (mini).u) (mini).u = (point).u; \ else if ((point).u > (maxi).u) (maxi).u = (point).u; \ if ((point).v < (mini).v) (mini).v = (point).v; \ else if ((point).v > (maxi).v) (maxi).v = (point).v; } #define Projectd1(project,d2) ((project == 0) ? (d2).v : (d2).u) #define FindProject2(d2) ((fabs((d2).u) > fabs((d2).v)) ? 0 : 1) #define Projectd2(project,normal,ndotp,d2,d) if (project == 0) { \ (d2).v = d; (d2).u = (ndotp - (d2).v * (normal).v) / (normal).u; } \ else { (d2).u = d; (d2).v = (ndotp - (d2).u * (normal).u) / (normal).v; } #define sign(x) ((x > 0) ? 1 : ((x < 0) ? -1 : 0)) #define v3pmulm(p1,m,p) \ { \ p.x = (p1).x * m[0][0] + (p1).y * m[1][0] + \ (p1).z * m[2][0] + m[3][0]; \ p.y = (p1).x * m[0][1] + (p1).y * m[1][1] + \ (p1).z * m[2][1] + m[3][1]; \ p.z = (p1).x * m[0][2] + (p1).y * m[1][2] + \ (p1).z * m[2][2] + m[3][2]; \ } #define v4pmulm(p1,m,p,w) \ { \ p.x = p1.x * m[0][0] + p1.y * m[1][0] + \ p1.z * m[2][0] + m[3][0]; \ p.y = p1.x * m[0][1] + p1.y * m[1][1] + \ p1.z * m[2][1] + m[3][1]; \ p.z = p1.x * m[0][2] + p1.y * m[1][2] + \ p1.z * m[2][2] + m[3][2]; \ w = p1.x * m[0][3] + p1.y * m[1][3] + \ p1.z * m[2][3] + m[3][3]; \ } #define v3vmulm(v1,m,v) \ { \ v.x = v1.x * m[0][0] + v1.y * m[1][0] + \ v1.z * m[2][0]; \ v.y = v1.x * m[0][1] + v1.y * m[1][1] + \ v1.z * m[2][1]; \ v.z = v1.x * m[0][2] + v1.y * m[1][2] + \ v1.z * m[2][2]; \ } #define m3trans(xt,yt,zt,one,two) \ { \ one[3][0] += xt; \ one[3][1] += yt; \ one[3][2] += zt; \ two[3][0] -= two[0][0] * xt + two[1][0] * yt + \ two[2][0] * zt; \ two[3][1] -= two[0][1] * xt + two[1][1] * yt + \ two[2][1] * zt; \ two[3][2] -= two[0][2] * xt + two[1][2] * yt + \ two[2][2] * zt; \ } #define m3rotx(alpha,one,two) \ { \ double _t; \ double _s = sin(alpha); \ double _c = cos(alpha); \ \ _t = one[0][1]; \ one[0][1] = _t * _c - one[0][2] * _s; \ one[0][2] = _t * _s + one[0][2] * _c; \ _t = one[1][1]; \ one[1][1] = _t * _c - one[1][2] * _s; \ one[1][2] = _t * _s + one[1][2] * _c; \ _t = one[2][1]; \ one[2][1] = _t * _c - one[2][2] * _s; \ one[2][2] = _t * _s + one[2][2] * _c; \ _t = one[3][1]; \ one[3][1] = _t * _c - one[3][2] * _s; \ one[3][2] = _t * _s + one[3][2] * _c; \ _t = two[1][0]; \ two[1][0] = _t * _c - two[2][0] * _s; \ two[2][0] = _t * _s + two[2][0] * _c; \ _t = two[1][1]; \ two[1][1] = _t * _c - two[2][1] * _s; \ two[2][1] = _t * _s + two[2][1] * _c; \ _t = two[1][2]; \ two[1][2] = _t * _c - two[2][2] * _s; \ two[2][2] = _t * _s + two[2][2] * _c; \ } #define m3roty(alpha,one,two) \ { \ double _t; \ double _s = sin(alpha); \ double _c = cos(alpha); \ \ _t = one[0][0]; \ one[0][0] = _t * _c + one[0][2] * _s; \ one[0][2] = -_t * _s + one[0][2] * _c; \ _t = one[1][0]; \ one[1][0] = _t * _c + one[1][2] * _s; \ one[1][2] = -_t * _s + one[1][2] * _c; \ _t = one[2][0]; \ one[2][0] = _t * _c + one[2][2] * _s; \ one[2][2] = -_t * _s + one[2][2] * _c; \ _t = one[3][0]; \ one[3][0] = _t * _c + one[3][2] * _s; \ one[3][2] = -_t * _s + one[3][2] * _c; \ _t = two[0][0]; \ two[0][0] = _t * _c + two[2][0] * _s; \ two[2][0] = -_t * _s + two[2][0] * _c; \ _t = two[0][1]; \ two[0][1] = _t * _c + two[2][1] * _s; \ two[2][1] = -_t * _s + two[2][1] * _c; \ _t = two[0][2]; \ two[0][2] = _t * _c + two[2][2] * _s; \ two[2][2] = -_t * _s + two[2][2] * _c; \ } #define m3rotz(alpha,one,two) \ { \ double _t; \ double _s = sin(alpha); \ double _c = cos(alpha); \ \ _t = one[0][0]; \ one[0][0] = _t * _c - one[0][1] * _s; \ one[0][1] = _t * _s + one[0][1] * _c; \ _t = one[1][0]; \ one[1][0] = _t * _c - one[1][1] * _s; \ one[1][1] = _t * _s + one[1][1] * _c; \ _t = one[2][0]; \ one[2][0] = _t * _c - one[2][1] * _s; \ one[2][1] = _t * _s + one[2][1] * _c; \ _t = one[3][0]; \ one[3][0] = _t * _c - one[3][1] * _s; \ one[3][1] = _t * _s + one[3][1] * _c; \ _t = two[0][0]; \ two[0][0] = _t * _c - two[1][0] * _s; \ two[1][0] = _t * _s + two[1][0] * _c; \ _t = two[0][1]; \ two[0][1] = _t * _c - two[1][1] * _s; \ two[1][1] = _t * _s + two[1][1] * _c; \ _t = two[0][2]; \ two[0][2] = _t * _c - two[1][2] * _s; \ two[1][2] = _t * _s + two[1][2] * _c; \ } #define m3scale(xs,ys,zs,one,two) \ { \ double _x = 1.0 / (xs); \ double _y = 1.0 / (ys); \ double _z = 1.0 / (zs); \ \ one[0][0] *= xs; \ one[0][1] *= ys; \ one[0][2] *= zs; \ one[1][0] *= xs; \ one[1][1] *= ys; \ one[1][2] *= zs; \ one[2][0] *= xs; \ one[2][1] *= ys; \ one[2][2] *= zs; \ one[3][0] *= xs; \ one[3][1] *= ys; \ one[3][2] *= zs; \ two[0][0] *= _x; \ two[0][1] *= _x; \ two[0][2] *= _x; \ two[1][0] *= _y; \ two[1][1] *= _y; \ two[1][2] *= _y; \ two[2][0] *= _z; \ two[2][1] *= _z; \ two[2][2] *= _z; \ } #ifdef NEVER #define m3mmulm(m1,m2,m)\ {\ m[0][0] =m1[0][0] * m2[0][0] + m1[0][1] * m2[1][0] +\ m1[0][2] * m2[2][0];\ m[0][1] =m1[0][0] * m2[0][1] + m1[0][1] * m2[1][1] +\ m1[0][2] * m2[2][1];\ m[0][2] =m1[0][0] * m2[0][2] + m1[0][1] * m2[1][2] +\ m1[0][2] * m2[2][2];\ m[1][0] =m1[1][0] * m2[0][0] + m1[1][1] * m2[1][0] +\ m1[1][2] * m2[2][0];\ m[1][1] =m1[1][0] * m2[0][1] + m1[1][1] * m2[1][1] +\ m1[1][2] * m2[2][1];\ m[1][2] =m1[1][0] * m2[0][2] + m1[1][1] * m2[1][2] +\ m1[1][2] * m2[2][2];\ m[2][0] =m1[2][0] * m2[0][0] + m1[2][1] * m2[1][0] +\ m1[2][2] * m2[2][0];\ m[2][1] =m1[2][0] * m2[0][1] + m1[2][1] * m2[1][1] +\ m1[2][2] * m2[2][1];\ m[2][2] =m1[2][0] * m2[0][2] + m1[2][1] * m2[1][2] +\ m1[2][2] * m2[2][2];\ m[3][0] =m1[3][0] * m2[0][0] + m1[3][1] * m2[1][0] +\ m1[3][2] * m2[2][0] + m2[3][0];\ m[3][1] =m1[3][0] * m2[0][1] + m1[3][1] * m2[1][1] +\ m1[3][2] * m2[2][1] + m2[3][1];\ m[3][2] =m1[3][0] * m2[0][2] + m1[3][1] * m2[1][2] +\ m1[3][2] * m2[2][2] + m2[3][2];\ } #endif #define m3unit(m)\ { \ m[0][0] = 1.0; m[0][1] = 0.0; m[0][2] = 0.0; \ m[1][0] = 0.0; m[1][1] = 1.0; m[1][2] = 0.0; \ m[2][0] = 0.0; m[2][1] = 0.0; m[2][2] = 1.0; \ m[3][0] = 0.0; m[3][1] = 0.0; m[3][2] = 0.0; \ } #define m3copy(m,m1)\ { \ m1[0][0] = m[0][0]; m1[0][1] = m[0][1]; m1[0][2] = m[0][2]; \ m1[1][0] = m[1][0]; m1[1][1] = m[1][1]; m1[1][2] = m[1][2]; \ m1[2][0] = m[2][0]; m1[3][1] = m[3][1]; m1[2][2] = m[2][2]; \ m1[3][0] = m[3][0]; m1[3][1] = m[3][1]; m1[3][2] = m[3][2]; \ } #define m4unit(m)\ { \ m[0][0] = 1.0; m[0][1] = 0.0; m[0][2] = 0.0; m[0][3] = 0.0; \ m[1][0] = 0.0; m[1][1] = 1.0; m[1][2] = 0.0; m[1][3] = 0.0; \ m[2][0] = 0.0; m[2][1] = 0.0; m[2][2] = 1.0; m[2][3] = 1.0; \ m[3][0] = 0.0; m[3][1] = 0.0; m[3][2] = 0.0; m[3][3] = 0.0; \ } #define m4copy(m,m1)\ { \ m1[0][0] = m[0][0]; m1[0][1] = m[0][1]; \ m1[0][2] = m[0][2]; m1[0][3] = m[0][3]; \ m1[1][0] = m[1][0]; m1[1][1] = m[1][1]; \ m1[1][2] = m[1][2]; m1[1][3] = m[1][3]; \ m1[2][0] = m[2][0]; m1[3][1] = m[3][1]; \ m1[2][2] = m[2][2]; m1[2][3] = m[2][3]; \ m1[3][0] = m[3][0]; m1[3][1] = m[3][1]; \ m1[3][2] = m[3][2]; m1[3][3] = m[3][3]; \ } typedef double mat3[4][3]; typedef double mat4[4][4]; /******************************** prototypes ******************************/ int intersect(TRay *ray,TSurface *surf); int RayBoxIntersect(TRay *ray, TPoint3f *mini, TPoint3f *maxi); double areaPoly(TPoint3f *Q,int nPts); void calcCenterPoly(TPoint3f *Q,int nPts,TPoint3f *center); void splitPoly4(TPoint3f *Q,int nPts,TPoint3f dQ[4][4],int *dPts); void randAreas(TPoint3f *Q,int nPts,double *areas); void randPointPoly(TPoint3f *Q,double *areas,int nPts,TPoint3f *rand_point); int inside_bbox(TSurface *surf,TPoint3f *point); double calc_side(TPoint2f *v1,TPoint2f *v2,TPoint2f *p2); int isonline(TPoint2f *x,TPoint2f *a,TPoint2f *b); int inside_element(TElement *ep,TPoint2f *point2); int clip2element(TElement *ep,TPoint2f *p1,TPoint2f *p2); int poly_clip_to_plane(TPolygon *p1,TPolygon *p2,TPlane *plane1,TPlane *plane); #define POLY_CLIP_FRONT 0 #define POLY_CLIP_BEHIND 1 #define POLY_CLIP_SPLIT 2 areas); void randPointPoly(TPoint3f *Q,double *areas,int nPts,TPoint3f *rand_point); int inside_bbox(TSurface *surf,TPoint3f *point); double calc_side(TPoint2f *v1,TPFxfire/input.c000644 000316 000311 00000016635 06114620343 013436 0ustar00wrzlgup000000 000000 /***************************************************************************** * input.c ******************************************************************************/ #include #include #include #include #include "rad.h" #include "geom.h" #define read_s_int(s,v) { readstring(s); v = readint(); } #define option_s_int(s,v,d) { if (matchreadstring(s)) v = readint(); \ else v = d; } #define read_s_real(s,v) { readstring(s); v = readreal(); } #define option_s_real(s,v,d) { if (matchreadstring(s)) v = readreal(); \ else v = d; } TVector3f *normalVec; /* array of normals of all surfaces */ static char *token = NULL; static FILE *inputfile; static char inputline[255]; static const char *seperators = " \t"; static int linenumber; static void nexttoken(void) { if (token != NULL) token = strtok(NULL,seperators); if (token == NULL) { /* need new line */ int i,len; char *cmt; do { if (fgets(inputline,250,inputfile) == NULL) { token = NULL; return; } linenumber++; cmt = strchr(inputline,'%'); if (cmt != NULL) *cmt = '\0'; len = strlen(inputline); while (len > 0 && (inputline[len - 1] == '\n' || inputline[len - 1] == ' ' || inputline[len - 1] == '\t')) { len--; inputline[len] = '\0'; } } while (len == 0); /* if empty */ for (i = 0; i < len; i++) { if (inputline[i] >= 'A' && inputline[i] <= 'Z') inputline[i] += 'a' - 'A'; } log_message("%s\n",inputline); token = strtok(inputline,seperators); } } static void openfile(char *filename) { inputfile = fopen(filename,"r"); if (inputfile == NULL) error("can't open %s\n",filename); nexttoken(); } static void closefile(void) { fclose(inputfile); inputfile = NULL; } static void readstring(const char *string) { if (token == NULL || strcmp(token,string) != 0) error("line %d, %s expected\n",linenumber,string); nexttoken(); } static int matchreadstring(const char *string) { if (token == NULL || strcmp(token,string) != 0) return(0); nexttoken(); return(1); } static int readint(void) { int result; if (token == NULL || (*token != '-' && (*token < '0' || *token > '9'))) error("line %d, number expected\n",linenumber); result = atoi(token); nexttoken(); return(result); } static double readreal(void) { double result; if (token == NULL || (*token != '-' && (*token < '0' || *token > '9'))) error("line %d, number expected\n",linenumber); result = atof(token); nexttoken(); return(result); } static void readpoint(TPoint3f *point) { point->x = readreal(); point->y = readreal(); point->z = readreal(); } static void readvec(TVector3f *vec) { vec->x = readreal(); vec->y = readreal(); vec->z = readreal(); } static void readcolor(TSpectra *color) { int i; for (i = 0; i < kNumberOfRadSamples; i++) color->samples[i] = readreal(); } static void readview(TView *view) { readstring("eye"); readpoint(&view->camera); readstring("lookat"); readvec(&view->lookat); readstring("up"); readvec(&view->up); readstring("fov"); view->fovx = readreal(); view->fovy = readreal(); readstring("clip"); view->near_clip = readreal(); view->far_clip = readreal(); readstring("resolution"); view->xRes = readint(); view->yRes = readint(); } static void readparams(void) { readstring("camera"); readview(¶ms.displayView); readstring("parameters"); option_s_real("threshold",params.threshold,0.001); option_s_int("adaptive_max_subdiv",params.maxAdaptiveSubdiv,0); option_s_real("adaptive_threshold",params.subdivPrecision,0.03); option_s_int("visibility_rays",params.visibleRays,8); option_s_real("radiosity_threshold",params.eps_B,0.01); option_s_real("minumum_area",params.min_A,1.0); } static int readquad(TQuad *quad,TPoint3f *points,int numberOfPoints,int surfId) { int i,pntindex,retval,normread; double len,area; TVector3f u,v,uxv; TSpectra temp; retval = 1; quad->surfId = surfId; quad->nPts = readint(); if (quad->nPts > 4) error("line %d: can't handle more than quadrilaterals",linenumber); readstring("vertices"); for (i = 0; i < quad->nPts; i++) { pntindex = readint(); if (pntindex >= numberOfPoints) error("line %d: illegal point index %d",pntindex,linenumber); quad->vert[i] = points[pntindex]; } area = areaPoly(quad->vert,quad->nPts); if (area <= 0.0) { message("%%line %d, zero area polygon\n",linenumber); quad->nPts = 0; retval = 0; } for (i = 0; i < quad->nPts; i++) { /* check identical verts */ if (PointEqual(quad->vert[i],quad->vert[(i + 1) % quad->nPts])) { error("line %d, identical vertices\n",linenumber); retval = 0; } } if (quad->nPts == 4) { /* test for parallelogram */ SubVector(u,quad->vert[1],quad->vert[0]); SubVector(v,quad->vert[2],quad->vert[3]); NormalizeVector(len,u); NormalizeVector(len,v); len = DistPnt(u,v); if (len > 0.001) { error("line %d, not a parallelogram (%g)\n",linenumber,len); retval = 0; } SubVector(u,quad->vert[2],quad->vert[1]); SubVector(v,quad->vert[3],quad->vert[0]); NormalizeVector(len,u); NormalizeVector(len,v); len = DistPnt(u,v); if (len > 0.001) { error("line %d, not a parallelogram (%g)\n",linenumber,len); retval = 0; } } option_s_int("patch_level",quad->patchLevel,1); option_s_int("element_level",quad->elementLevel,1); normread = 0; if (matchreadstring("normal")) { readvec(&quad->normal); NormalizeVector(len,quad->normal); /* so it's normalized */ normread = 1; } SubVector(u,quad->vert[1],quad->vert[0]); NormalizeVector(len,u); SubVector(v,quad->vert[quad->nPts - 1],quad->vert[0]); NormalizeVector(len,v); CrossVector(uxv,u,v); /* recalc normal */ NormalizeVector(len,uxv); if (normread) { len = DistPnt(uxv,quad->normal); if (LenVector(quad->normal) == 0.0) { error("line %d, zero normal vector\n",linenumber); quad->normal = uxv; } else if (len > 0.01) { message("%%line %d, surf %d, NV bad (%g corr: %g,%g,%g)\n", linenumber,surfId,len,u.x,u.y,u.z); quad->normal = uxv; if (len > 1.41422) { /* turn everything around */ NegVector(quad->normal); } } } else quad->normal = uxv; if (matchreadstring("diffuse")) readcolor(&quad->reflectance); else quad->reflectance = black; quad->emission = black; if (matchreadstring("emissions")) { for (i = 0; i < quad->nPts; i++) { readcolor(&temp); SpectraAddTo(&quad->emission,&temp); } SpectraMultK(&quad->emission,1.0 / quad->nPts,&quad->emission); } else if (matchreadstring("emission")) readcolor(&quad->emission); return(retval); } void ReadData(char *filename,TQuad **roomPolys,int *numberOfPolys) { int i,pntnumber,realpol,objcnt,solidcnt; TPoint3f *roomPoints; openfile(filename); readparams(); read_s_int("points",pntnumber); roomPoints = alloc_points(pntnumber); for (i = 0; i < pntnumber; i++) readpoint(&roomPoints[i]); read_s_int("polys",*numberOfPolys); *roomPolys = alloc_quads(*numberOfPolys); realpol = 0; objcnt = 0; solidcnt = 0; for (i = 0; i < *numberOfPolys; i++) { if (matchreadstring("object")) objcnt++; if (matchreadstring("solid")) solidcnt++; (*roomPolys)[realpol].objId = objcnt; (*roomPolys)[realpol].toSample = 1; (*roomPolys)[realpol].toTest = 1; if (readquad(&(*roomPolys)[realpol],roomPoints,pntnumber,realpol)) realpol++; /* pol was o.k. */ } *numberOfPolys = realpol; readstring("end"); closefile(); free(roomPoints); } uads(*numberOfPolys); realpol = 0; objcnt = 0; solidcnt = 0; for (i = 0; i < *numberOfPolys; i+Fxfire/log.h000644 000316 000311 00000001565 06114620343 013061 0ustar00wrzlgup000000 000000 /* log.h */ #define log_sample(sp) log_message("V %g %g\n", \ sp->point2.u,sp->point2.v,sp->point.x,sp->point.y,sp->point.z); #define log_edge(s0,s1,col) log_message("E %g %g %g %g %d D\n",s0->point2.u, \ s0->point2.v,s1->point2.u,s1->point2.v,col); #define log_geom(string,ep) { int _i; log_message("%s\n",string); \ for (_i = 0; _i < ep->nPts; _i++) log_edge(ep->sample[_i], \ ep->sample[(_i + 1) % ep->nPts],ep->discontinuity[_i] + 7); } #define pri_sample(sp) message("V %g %g\n", \ sp->point2.u,sp->point2.v,sp->point.x,sp->point.y,sp->point.z); #define pri_edge(s0,s1,col) message("E %g %g %g %g %d D\n",s0->point2.u, \ s0->point2.v,s1->point2.u,s1->point2.v,col); #define pri_geom(string,ep) { int _i; message("%s\n",string); \ for (_i = 0; _i < ep->nPts; _i++) pri_edge(ep->sample[_i], \ ep->sample[(_i + 1) % ep->nPts],ep->discontinuity[_i] + 7); } ->sample[_i], \ ep->sample[(_i + 1) % ep->nPts],ep->discontinuity[_i] + 7); } #define pri_sample(sp) message("V %g %g\n", \ sp->poinFxfire/main.c000644 000316 000311 00000013217 06114624056 013221 0ustar00wrzlgup000000 000000 /***************************************************************************** * main.c * * This program was hacked out of the GGemsII radiosity program * To be sure the original is hard to recognize in here :-) * * Copyright (C) 1990-1991 Apple Computer, Inc. * All rights reserved. * * 12/1990 S. Eric Chen ******************************************************************************/ #include #include #include #include #include #include #include #include "rad.h" #include "geom.h" TRadParams params; static TQuad *roomPolys; static int numberOfPolys; static void HandleArgs2(int argc,char **argv) { int i,temp; params.bsptreelen = 6; params.d0mesh = 1; params.maxIterations = -1; for (i = 1; i < argc; i++) { if (argv[i][0] != '-') continue; switch (argv[i][1]) { case '0': params.d0mesh = 0; break; case 'a': params.adaptiveSubdiv = 1; params.sampleAllSamples = 1; break; case 'b': params.bsptreelen = atoi(argv[i] + 2); break; case 'd': params.delaunay = 1; break; case 'D': params.discomesh = atoi(argv[i] + 2); if (params.discomesh == 0) params.discomesh = 1; /*params.d0mesh = 0;*/ params.noRestrictQuadtree = 1; break; case 'e': params.exactFF = atoi(argv[i] + 2); if (params.exactFF == 0) params.exactFF = 1; break; case 'i': params.maxIterations = atoi(argv[i] + 2); break; case 'o': params.delaunay = 1; params.outputSites = 1; break; case 'p': params.picture_iteration = atoi(argv[i] + 2); break; case 's': if (params.discomesh == 0) params.noRestrictQuadtree = 0; params.adaptiveSubdiv = 1; temp = atoi(argv[i] + 2); if (temp != 0) /* only if set */ params.maxAdaptiveSubdiv = temp; break; case 't': params.tvertices = 1; /*params.adaptiveSubdiv = 1;*/ break; case 'u': params.noRestrictQuadtree = 1; params.adaptiveSubdiv = 1; break; case 'z': params.randomrays = 1; break; } } if (params.exactFF) message("Exact "); message("FF's with min. %d %srays\n",params.visibleRays, (params.randomrays) ? "random " : ""); if (params.bsptreelen) message("BSP-Tree with max. %d polygons\n",params.bsptreelen); if (params.adaptiveSubdiv) { message("Adaptive subdivision (max. %d)", params.maxAdaptiveSubdiv); message(" %srestricted Quadtree\n", (params.noRestrictQuadtree) ? "un" : ""); if (params.sampleAllSamples) message("no "); message("interpolated samples\n"); } if (params.discomesh) message("Meshing all Discontinuities\n"); else if (params.d0mesh) message("Meshing D0 Discontinuities\n"); } void main(int argc,char **argv) { int i; time_t starttime; double timesum; char inputfile[30],outputfile[30],file[40]; if (argc > 2) { inputfile[0] = '\0'; outputfile[0] = '\0'; for (i = 1; i < argc; i++) /* get inputfilename */ if (argv[i][0] != '-') { strcpy(inputfile,argv[i]); break; } for (i++; i < argc; i++) /* get outputfilename */ if (argv[i][0] != '-') { strcpy(outputfile,argv[i]); break; } if (inputfile[0] == '\0' || outputfile[0] == '\0') argc = 1; /* force usage display */ } if (argc < 3) { fprintf(stderr,"FIRE 0.99 by wRZL\n\n"); fprintf(stderr,"Usage: fire \n"); fprintf(stderr,"-0 don't insert D0 edges into meshes\n"); fprintf(stderr,"-a -s and always sample all samples\n"); fprintf(stderr,"-b length of bsplists (0 = full intersect)\n"); fprintf(stderr,"-d use Delaunay surface mesh\n"); fprintf(stderr,"-D use Discomeshing\n"); fprintf(stderr,"-e use very exact FF calculation\n"); fprintf(stderr,"-i number of iterations\n"); fprintf(stderr,"-o -d and output samples per surface\n"); fprintf(stderr,"-p output interval (-1 = no output)\n"); fprintf(stderr,"-s[num] do adaptive Subdivision [opt. maxlevel]\n"); fprintf(stderr,"-t avoid T-vertices\n"); fprintf(stderr,"-u -s but use unrestricted Quadtree\n"); fprintf(stderr,"-z use random rays for FF's\n"); exit(0); } strcpy(file,outputfile); strcat(file,".log"); params.logfile = fopen(file,"w"); HandleArgs2(argc,argv); /* init params */ starttime = time(NULL); log_message("***inputfile***\n"); ReadData(inputfile,&roomPolys,&numberOfPolys); log_message("***end of inputfile***\n"); InitSurfaces(numberOfPolys,roomPolys); free(roomPolys); InitRad(outputfile); timesum = diff_time(time(NULL),starttime); message("Setup Time: %g sec\n",timesum); flush_log(); timesum += DoRad(); /* do the twist */ message("Total Time: %g sec\n",timesum); CleanUpRad(); } void error(char const *fmt, ...) { va_list arg_ptr; char buffer[512]; va_start(arg_ptr,fmt); vsprintf(buffer,fmt,arg_ptr); va_end(arg_ptr); if (params.logfile != NULL) fprintf(params.logfile,"### ERROR: %s\n",buffer); printf("### ERROR: %s\n",buffer); exit(1); } void message(char const *fmt, ...) { va_list arg_ptr; char buffer[512]; va_start(arg_ptr,fmt); vsprintf(buffer,fmt,arg_ptr); va_end(arg_ptr); if (params.logfile != NULL) fputs(buffer,params.logfile); fputs(buffer,stdout); } void log_message(char const *fmt, ...) { va_list arg_ptr; char buffer[512]; va_start(arg_ptr,fmt); vsprintf(buffer,fmt,arg_ptr); va_end(arg_ptr); if (params.logfile != NULL) fputs(buffer,params.logfile); } void flush_log(void) { fflush(stdout); fflush(params.logfile); } va_start(arg_ptr,fmt); vsprintf(buffer,fmt,arg_ptr); va_end(arg_ptr); if (params.logfile != NULL) fputs(buffer,params.logfile); fputs(buffer,stdout); } void log_message(char const *fmt, ...) { va_list arg_ptr; char buffer[512]; va_start(arg_ptr,fmt); vsprintf(buffer,fmt,arg_ptr); va_end(arg_ptr); if (paramFxfire/memory.c000644 000316 000311 00000010232 06114620343 013572 0ustar00wrzlgup000000 000000 /***************************************************************************** * memory.c ******************************************************************************/ #include #include #include #include "rad.h" static long memory_usage = 0L; #define SAMPLE_BLOCKSIZE 100 static TSample *sample_block = NULL; static int sample_alloced = 0; static int sample_cnt = 0; TSample *alloc_sample(void) { TSample *temp; if (sample_block == NULL || sample_alloced >= SAMPLE_BLOCKSIZE) { sample_block = (TSample *) calloc(sizeof(TSample),SAMPLE_BLOCKSIZE); if (sample_block == NULL) error("no more mem for samples"); memory_usage += sizeof(TSample) * SAMPLE_BLOCKSIZE; sample_cnt++; sample_alloced = 0; } temp = sample_block; sample_alloced++; sample_block++; return(temp); } #define ELEM_BLOCKSIZE 100 static TElement *elem_block = NULL; static int elem_alloced = 0; static int elem_cnt = 0; TElement *alloc_element(void) { TElement *temp; if (elem_block == NULL || elem_alloced >= ELEM_BLOCKSIZE) { elem_block = (TElement *) calloc(sizeof(TElement),ELEM_BLOCKSIZE); if (elem_block == NULL) error("no more mem for elements"); memory_usage += sizeof(TElement) * ELEM_BLOCKSIZE; elem_cnt++; elem_alloced = 0; } temp = elem_block; elem_alloced++; elem_block++; return(temp); } #define PATCH_BLOCKSIZE 100 static TPatch *patch_block = NULL; static int patch_alloced = 0; static int patch_cnt = 0; TPatch *alloc_patch(void) { TPatch *temp; if (patch_block == NULL || patch_alloced >= PATCH_BLOCKSIZE) { patch_block = (TPatch *) calloc(sizeof(TPatch),PATCH_BLOCKSIZE); if (patch_block == NULL) error("no more mem for patchs"); memory_usage += sizeof(TPatch) * PATCH_BLOCKSIZE; patch_cnt++; patch_alloced = 0; } temp = patch_block; patch_alloced++; patch_block++; return(temp); } #define OBJ_BLOCKSIZE 100 static TGeomObj *obj_block = NULL; static int obj_alloced = 0; static obj_cnt = 0; TGeomObj *alloc_obj(void) { TGeomObj *temp; if (obj_block == NULL || obj_alloced >= OBJ_BLOCKSIZE) { obj_block = (TGeomObj *) calloc(sizeof(TGeomObj), OBJ_BLOCKSIZE); if (obj_block == NULL) error("no more mem for objects"); memory_usage += sizeof(TGeomObj) * OBJ_BLOCKSIZE; obj_cnt++; obj_alloced = 0; } temp = obj_block; obj_alloced++; obj_block++; return(temp); } #define NODE_BLOCKSIZE 100 static TBinNode *node_block = NULL; static int node_alloced = 0; static node_cnt = 0; TBinNode *alloc_node(void) { TBinNode *temp; if (node_block == NULL || node_alloced >= NODE_BLOCKSIZE) { node_block = (TBinNode *) calloc(sizeof(TBinNode), NODE_BLOCKSIZE); if (node_block == NULL) error("no more mem for nodes"); memory_usage += sizeof(TBinNode) * NODE_BLOCKSIZE; node_cnt++; node_alloced = 0; } temp = node_block; node_alloced++; node_block++; return(temp); } #define CHILD_BLOCKSIZE 1000 static TElement **child_block = NULL; static int child_alloced = 0; static child_cnt = 0; TElement **alloc_child(int nChild) { TElement **temp; if (child_block == NULL || child_alloced + nChild >= CHILD_BLOCKSIZE) { child_block = (TElement **)calloc(sizeof(TElement *),CHILD_BLOCKSIZE); if (child_block == NULL) error("no more mem for childs"); memory_usage += sizeof(TElement *) * CHILD_BLOCKSIZE; child_cnt++; child_alloced = 0; } temp = child_block; child_alloced += nChild; child_block += nChild; return(temp); } TPoint3f *alloc_points(int number) { TPoint3f *pts; pts = (TPoint3f *) calloc(sizeof(TPoint3f),number); if (pts == NULL) error("no mem to alloc points"); return(pts); } /* will be freed -> therefore no memory usage */ TQuad *alloc_quads(int number) { TQuad *quads; quads = (TQuad *) calloc(sizeof(TQuad),number); if (quads == NULL) error("no mem to alloc quads"); return(quads); } /* will be freed -> therefore no memory usage */ TSurface *alloc_surfs(int number) { TSurface *surfs; surfs = (TSurface *) calloc(sizeof(TSurface),number); if (surfs == NULL) error("no mem to alloc surfs"); memory_usage += sizeof(TSurface) * number; return(surfs); } void memory_statistics(void) { log_message("Memory Usage: %d bytes\n",memory_usage); } uad *quads; quads = (TQuad *) calloc(sizeof(TQuad),number); if (quads == NULL) error("no mem to alloc quads"); return(quads); } /* will be freed -> therefore no memory usage */ TSurface *alloc_surfs(int number) { TSurface *surfs; surfs = (TSurface *) calloc(sizeof(TSurface),number); if (surfs == NULL) error("no mem to alloc surfs"); Fxfire/mesh.c000644 000316 000311 00000032126 06114620343 013224 0ustar00wrzlgup000000 000000 /***************************************************************************** * mesh.c ******************************************************************************/ #include #include #include #include #include #include "rad.h" #include "geom.h" #include "dt.h" #include "disco.h" #include "log.h" #define DISCO_MESH 1 int GenSample(TSample **sample,TPoint2f *point2,TElement *ep,TPatch *patch, TSurface *surf,int find) { int ret; if (find) *sample = FindSample(surf->elements,point2); if (! find || *sample == NULL) { *sample = alloc_sample(); (*sample)->new_sample = 1; (*sample)->next = surf->samples; surf->samples = *sample; /* insert into front of list */ params.nSamples++; if (params.delaunay) insert_site(surf->vd,point2->u,point2->v, (SITE_PTR *)&(*sample)->site_ptr,(char *) *sample); ret = 1; /* new sample */ } else { if (params.delaunay && get_info(surf->vd,(*sample)->site_ptr) == NULL) set_info(surf->vd,(*sample)->site_ptr,(char *) *sample); ret = 0; /* existing old sample */ } (*sample)->patch = patch; (*sample)->point2 = *point2; if (ep != NULL) BorderShift(surf,ep,point2,&(*sample)->point); /* calc the 3d point */ else /* still needs bordershift! */ Project3d(*surf,*point2,(*sample)->point); return(ret); } static int GenElements(TElement *ep,int plevel,int level,TSurface *surf) { int news,i; double t; TSpectra temp; TPatch *pp; plevel--; if (plevel == 0) { /* should generate our patch now */ pp = alloc_patch(); pp->nPts = ep->nPts; pp->surf = surf; pp->next = surf->patches; pp->patchId = params.nPatches; params.nPatches++; surf->patches = pp; for (i = 0; i < pp->nPts; i++) { Project3d(*surf,ep->sample[i]->point2,pp->vert[i]); ep->sample[i]->patch = pp; /* set patch on our Samples */ } pp->area = areaPoly(pp->vert,pp->nPts); calcCenterPoly(pp->vert,pp->nPts,&pp->center); ep->patch = pp; /* set patch from here on ! */ } news = 0; level--; if (level > 0) { /* still a node -> subdiv */ news = SubdivElement4(ep,surf); for (i = 0; i < ep->nPts; i++) { SpectraAdd(&ep->sample[i]->delta_rad, &ep->sample[(i + 1) % ep->nPts]->delta_rad,&temp); SpectraMultK(&temp,0.5,&temp); ep->child[i]->sample[(i + 1) % ep->nPts]->delta_rad = temp; } /* interpolate side-midpoints radiosities */ if (ep->nPts == 4) { temp = ep->sample[0]->delta_rad; /* interpolate midpoint rad */ for (i = 1; i < ep->nChild; i++) SpectraAddTo(&temp,&ep->sample[i]->delta_rad); t = 1.0 / ep->nChild; SpectraMultK(&temp,t,&temp); ep->child[0]->sample[2]->delta_rad = temp; } for (i = 0; i < ep->nChild; i++) news += GenElements(ep->child[i],plevel,level,surf); } return(news); } #define ENLARGE_FAC 1E-5 static void calcBoundingBox(TSurface *surf) { int i; TVector3f diag; surf->min = surf->vert[0]; /* calc surf extent */ surf->max = surf->vert[0]; for (i = 1; i < surf->nPts; i++) { MakeBbox(surf->min,surf->max,surf->vert[i]); } SubVector(diag,surf->max,surf->min); /* enlarge surf extent */ ScaleVector(diag,ENLARGE_FAC); /* by an epsilon */ SubVector(surf->min,surf->min,diag); AddVector(surf->max,surf->max,diag); } static void calc2dCoords(TSurface *surf) { int i; TPoint2f swap2; TPoint3f swap3; FindProject(surf->normal,surf->project); Project2d(surf->project,surf->vert[0],surf->vert2[0]); surf->min2 = surf->vert2[0]; surf->max2 = surf->vert2[0]; for (i = 1; i < surf->nPts; i++) { /* calc 2d coords */ Project2d(surf->project,surf->vert[i],surf->vert2[i]); MakeBbox2(surf->min2,surf->max2,surf->vert2[i]); } if (RightofPoints2(&surf->vert2[0],&surf->vert2[1],&surf->vert2[2])) { SWAP(surf->vert[1],surf->vert[surf->nPts - 1],swap3); SWAP(surf->vert2[1],surf->vert2[surf->nPts - 1],swap2); message("Warning: wrong vertex order in surface %d\n",surf->surfId); } } static void checkPolygon(TPoint3f *pts,int nPts,int surf_num) { double len,len0,len1; TPoint3f new0,new1,old; TVector3f u,v; if (nPts != 4) return; SubVector(u,pts[1],pts[0]); SubVector(v,pts[2],pts[3]); NormalizeVector(len,u); NormalizeVector(len,v); len0 = DistPnt(u,v); if (len0 > 1E-6) { SubVector(u,pts[1],pts[0]); AddVector(new0,pts[3],u); } SubVector(u,pts[2],pts[1]); SubVector(v,pts[3],pts[0]); NormalizeVector(len,u); NormalizeVector(len,v); len1 = DistPnt(u,v); if (len1 > 1E-6) { SubVector(u,pts[3],pts[0]); AddVector(new1,pts[1],u); } if (len0 < 1E-6 && len1 < 1E-6) /* is o.k. */ return; old = pts[2]; if (len0 > 1E-6) { if (len1 > 1E-6) /* both */ AvgVector(pts[2],new0,new1); else pts[2] = new0; } else pts[2] = new1; #ifdef NEVER log_message("surface %d: point %g %g %g moved to %g %g %g\n",surf_num, old.x,old.y,old.z,pts[2].x,pts[2].y,pts[2].z); #endif } static void GenSurface(TQuad *quad,TSurface *pSurf) { int i; double tmp; NormalizeVector(tmp,quad->normal); /* just in case :-) */ pSurf->surfId = quad->surfId; pSurf->objId = quad->objId; pSurf->toSample = quad->toSample; pSurf->toTest = quad ->toTest; pSurf->reflectance = quad->reflectance; for (i = 0; i < quad->nPts; i++) pSurf->vert[i] = quad->vert[i]; pSurf->nPts = quad->nPts; pSurf->area = areaPoly(pSurf->vert,pSurf->nPts); /* calc area */ pSurf->normal = quad->normal; pSurf->ndotp = DotVector(pSurf->normal,pSurf->vert[0]); checkPolygon(pSurf->vert,pSurf->nPts,pSurf->surfId); calcBoundingBox(pSurf); calc2dCoords(pSurf); } #ifdef DISCO_MESH #define MAXELES 100 #define preidx(ep,index) ((index + ep->nPts - 1) % ep->nPts) #define nextidx(ep,index) ((index + 1) % ep->nPts) static int ShiftD0Sample(TSurface *surf,TElement *ep,int sample_index) { int i,news,start_index,nEles; int idx[MAXELES]; TElement *neigh,*startep; TElement *eles[MAXELES]; TSample *sp,*newsample; TVector2f shift,oldshift; sp = ep->sample[sample_index]; startep = NULL; start_index = -1; neigh = ep; do { /* scan ccw */ if (neigh->sample[sample_index] != sp) error("???1???"); if (neigh->discontinuity[preidx(neigh,sample_index)] == D0) { startep = neigh; start_index = sample_index; } neigh = FindSampleElement(surf->elements,sp, neigh->sample[preidx(neigh,sample_index)],&sample_index); } while (neigh != NULL && neigh != ep); if (startep == NULL) return(0); /* no discos for this site */ neigh = startep; /* set current */ sample_index = start_index; nEles = 0; do { /* scan cw */ if (neigh->sample[sample_index] != sp) error("???2???"); eles[nEles] = neigh; idx[nEles] = sample_index; nEles++; neigh = FindSampleElement(surf->elements, neigh->sample[nextidx(neigh,sample_index)],sp,&sample_index); if (neigh != NULL) sample_index = nextidx(neigh,sample_index); /* correct index */ } while (neigh != NULL && neigh != startep); if (nEles > MAXELES) error("Oooo, ooo!"); neigh = startep; sample_index = start_index; news = 0; newsample = sp; CalcBorderShift(surf,neigh->sample[preidx(neigh,sample_index)],sp, &sp->point2,&oldshift); for (i = 0; i < nEles; i++) { neigh = eles[i]; sample_index = idx[i]; neigh->sample[sample_index] = newsample; /* set sample in ele */ if (neigh->discontinuity[sample_index] == D0) { CalcBorderShift(surf,sp,neigh->sample[nextidx(neigh,sample_index)], &sp->point2,&shift); AddVector2(oldshift,shift,oldshift); AddVector2(oldshift,oldshift,sp->point2); Project3d(*surf,oldshift,newsample->point); if (i < nEles - 1) { /* another sector to do */ news += GenSample(&newsample,&sp->point2,ep,NULL,surf,0); newsample->new_sample = 0; /* to avoid unwanted sideeffects */ } oldshift = shift; NegVector2(oldshift); /* reverse our direction for next shift */ } } for (i = 0; i < nEles; i++) eles[i]->sample[idx[i]]->patch = eles[i]->patch; return(news); } #define MAXEDGESAMP 100 static void remove_tvertices(TSurface *surf) { int i,news,nSamples; TElement *ep; TSample *samples[MAXEDGESAMP]; TSegment segs[MAXEDGESAMP]; FOR_ALL_SURF_ELEMENTS(surf,ep) nSamples = 0; /*pri_geom("",ep);*/ FindSamplesOnEdges(ep,surf->elements,samples,&nSamples); /*message("%d",nSamples);*/ if (nSamples > 0) { for (i = 0; i < nSamples; i++) { segs[i].point1 = samples[i]->point2; segs[i].discontinuity = DINF; /* mark as single sample */ } news = triangulate_element(surf,ep,segs,nSamples,NULL); if (news != 0) error("created new sample ???"); ep->leaf = 0; /* 'cause of FindSample/Element */ params.nElements += ep->nChild - 1; /* ep is a node now */ } END_ALL_SURF_ELEMENTS(ep) } #endif static int MeshSurface(TSurface *surf,TQuad *quad) { int i,j,news; TElement *ep; SITE_PTR site[kMaxPolyPoints]; #ifdef DISCO_MESH int nSeg,level,plevel,elevel; TSurface *surf1; TSample *sp; TSegment segs[MAXSEGS]; #endif if (params.delaunay) { /* init the delaunay surface */ init_surface(&surf->vd,surf->min2.u,surf->min2.v, surf->max2.u,surf->max2.v); for (i = 0; i < surf->nPts; i++) (void) insert_site(surf->vd,surf->vert2[i].u, surf->vert2[i].v,&site[i],NULL); for (i = 0; i < surf->nPts; i++) insert_edge(surf->vd,site[i],site[(i + 1) % surf->nPts], D0,NULL,NULL); } ep = alloc_element(); ep->parent = NULL; ep->level = 1; ep->patch = NULL; ep->leaf = 1; /* for the moment */ ep->nPts = surf->nPts; ep->nChild = 0; ep->min = surf->min2; ep->max = surf->max2; news = 0; for (i = 0; i < ep->nPts; i++) { ep->discontinuity[i] = (char) D0; /* outer boundary */ news += GenSample(&ep->sample[i],&surf->vert2[i],NULL,NULL,surf,0); } /* now all is initialized -> therefore we can do the following now */ ep->area = calcAreaElement(ep,surf); for (i = 0; i < ep->nPts; i++) BorderShift(surf,ep,&ep->sample[i]->point2,&ep->sample[i]->point); surf->elements = ep; params.nElements++; /* we generated an element */ for (i = 0; i < ep->nPts; i++) /* init radiosity */ ep->sample[i]->delta_rad = quad->emission; if (SpectraSum(&quad->emission) > 0.0) surf->lightsource = 1; if (! surf->lightsource && SpectraSum(&quad->reflectance) == 0.0) { news += GenElements(ep,1,1,surf); return(news); /* surface just for shadows */ } #ifndef DISCO_MESH news += GenElements(ep,quad->patchLevel,quad->elementLevel,surf); return(news); #else if (! params.d0mesh) { /* no d0 mesh */ news += GenElements(ep,quad->patchLevel,quad->elementLevel,surf); return(news); } surf->d0mesh = NULL; /* find all discontinuities of degree 0 */ FOR_ALL_SURFS(surf1) if (surf1 != surf) (void) find_d0_segments(surf,surf1,&surf->d0mesh); END_ALL_SURFS(surf1) nSeg = clip_segments(surf,ep,surf->d0mesh,0,segs); if (nSeg == 0) { /* no discos to do */ free_bsp2(surf->d0mesh); surf->d0mesh = NULL; news += GenElements(ep,quad->patchLevel,quad->elementLevel,surf); return(news); } message("d%d",nSeg); news += triangulate_element(surf,ep,segs,nSeg,NULL); ep->leaf = 0; /* 'cause of FindSample/Element */ params.nElements += ep->nChild - 1; /* ep is a node now */ FOR_ALL_SURF_SAMPLES(surf,sp) sp->new_sample = 1; END_ALL_SURF_SAMPLES(sp) for (i = 0; i < ep->nChild; i++) { for (j = 0; j < ep->child[i]->nPts; j++) { if (! ep->child[i]->sample[j]->new_sample) continue; ep->child[i]->sample[j]->new_sample = 0; news += ShiftD0Sample(surf,ep->child[i],j); } } for (i = 0; i < ep->nChild; i++) { /* generate patches */ #ifndef NEVER level = floor(log(sqrt(ep->area) / sqrt(ep->child[i]->area)) / log(2.0)) + 1; if (level < quad->patchLevel) plevel = quad->patchLevel - level + 1; else plevel = 1; if (level < quad->elementLevel) elevel = quad->elementLevel - level + 1; else elevel = 1; #else plevel = quad->patchLevel - 1; if (plevel < 1) plevel = 1; elevel = quad->elementLevel - 1; if (elevel < 1) elevel = 1; #endif news += GenElements(ep->child[i],plevel,elevel,surf); } remove_tvertices(surf); return(news); #endif } void InitSurfaces(int nQuads,TQuad *quads) { int i,news; TElement *ep; params.nSurfs = nQuads; /* calculate memory usage */ params.surfs = alloc_surfs(params.nSurfs); params.nPatches = 0; params.nElements = 0; params.nSamples = 0; for (i = 0; i < params.nSurfs; i++) /* generate all surfs */ GenSurface(&quads[i],¶ms.surfs[i]); InitBinTree(&BSPTree); /********************** now the element stuff ***********************/ news = 0; message("Meshing "); for (i = 0; i < params.nSurfs; i++) { /* mesh surfs to sample */ if (params.surfs[i].toSample) { message("."); news += MeshSurface(¶ms.surfs[i],&quads[i]); } } message("\n"); if (news != params.nSamples) error("??? not enough Samples generated"); FOR_ALL_ELEMENTS(ep) /* mark original leaves */ ep->original = 1; END_ALL_ELEMENTS(ep) if (params.delaunay) Recalc_Areas(); /* CheckAllAreas();*/ /* for debugging purposes */ log_message("%5d Surfaces\n",params.nSurfs); log_message("%5d Patches\n",params.nPatches); log_message("%5d Elements\n",params.nElements); log_message("%5d Samples\n",params.nSamples); } s.surfs[i],&quads[i]); } } message("\n"); if (news != params.nSamples) error("??? not enough Samples generated"); FOR_ALL_ELEMENTS(ep) /* mark original leaves */ ep->original = 1; END_ALL_ELEMENTS(ep) if (params.delaunay) Recalc_Areas(); /* CheckAllAreas();*/ /* for debugging purposes */ log_message("%5d Surfaces\n",params.nSurfs); log_message("%5d Patches\n",params.nPatches); log_message("Fxfire/output.c000644 000316 000311 00000004430 06114620343 013625 0ustar00wrzlgup000000 000000 /***************************************************************************** * output.c ******************************************************************************/ #include #include #include "rad.h" static FILE *outfile; static FILE *outfile; int BeginOutput(int iterNr,TView *theView,char *outputfile,int force) { char filename[40]; outfile = NULL; if (params.picture_iteration == -1) /* no output */ return(0); if (params.picture_iteration == 0) { /* 0,1,last */ if (! force && iterNr > 1) return(0); } else if (! force && iterNr > 1 && iterNr != (iterNr / params.picture_iteration) * params.picture_iteration) return(0); sprintf(filename,"%s%03d.pol",outputfile,iterNr); #if defined(MSDOS) && ! defined(ASCII) outfile = fopen(filename,"wb"); #else outfile = fopen(filename,"w"); #endif if (outfile == NULL) return(0); #ifdef ASCII fprintf(outfile,"%g,%g,%g/%g,%g,%g/%g,%g,%g/%g,%g/%g\n", theView->camera.x,theView->camera.y,theView->camera.z, theView->lookat.x,theView->lookat.y,theView->lookat.z, theView->up.x,theView->up.y,theView->up.z, theView->near_clip,theView->far_clip,theView->fovx); #else fwrite(theView,sizeof(TView),1,outfile); #endif return(1); } void OutputPolygon(int iterNr,int nPts,TPoint3f *pts,TVector3f* n, TSpectra *rad,TSpectra *ambient,TSpectra *rads,int surface) { #ifdef ASCII int i; #endif if (outfile == NULL) return; #ifdef ASCII fprintf(outfile,"%d\n",nPts); fprintf(outfile,"%d/%g,%g,%g/%g,%g,%g/%g,%g,%g\n",surface,n->x,n->y,n->z, rad->samples[0],rad->samples[1],rad->samples[2], ambient->samples[0],ambient->samples[1],ambient->samples[2]); for (i = 0; i < nPts; i++) fprintf(outfile,"%g,%g,%g/%g,%g,%g\n",pts[i].x,pts[i].y,pts[i].z, rads[i].samples[0],rads[i].samples[1],rads[i].samples[2]); #else fwrite(&nPts,sizeof(int),1,outfile); fwrite(&surface,sizeof(int),1,outfile); fwrite(n,sizeof(TVector3f),1,outfile); fwrite(rad,sizeof(TSpectra),1,outfile); fwrite(ambient,sizeof(TSpectra),1,outfile); fwrite(pts,sizeof(TPoint3f),nPts,outfile); fwrite(rads,sizeof(TSpectra),nPts,outfile); #endif } void EndOutput(void) { int i; if (outfile == NULL) return; i = 0; #ifdef ASCII fprintf(outfile,"%d\n",i); #else fwrite(&i,sizeof(int),1,outfile); #endif fclose(outfile); } [i].samples[2]); #else fwrite(&nPts,sizeof(int),1,outfile); fwrite(&surface,sizeof(int),1,outfile); fwrite(n,sizeof(TVector3f),1,outfile); fwrite(rad,sizeof(TSpectra),1,outfile); fwrite(ambient,sizeof(TSpectra),1,outfile); fwrFxfire/rad.c000644 000316 000311 00000013456 06114620343 013043 0ustar00wrzlgup000000 000000 /****************************************************************************** * rad.c ******************************************************************************/ #include #include #include #include #include "rad.h" #include "geom.h" #include "dt.h" static double totalEnergy; /* total emitted energy; */ /* used for convergence checking */ /*****************************************************************************/ /* Find the next shooting patch based on the unshot energy of each patch */ /* Return 0 if convergence is reached; otherwise, return 1 */ static int FindShootPatch(TPatch **shootPatch) { double energy, maxEnergy; TSpectra temp; TPatch* pp; maxEnergy = -1.0; /* so at least on sets shootPatch */ *shootPatch = NULL; FOR_ALL_PATCHES(pp) SpectraMultK(&pp->unshotRad,pp->area,&temp); energy = SpectraMax(&temp); if (energy > maxEnergy) { *shootPatch = pp; maxEnergy = energy; } END_ALL_PATCHES(pp) message(", max energy (%3d,%3d): %g\n",(*shootPatch)->patchId, (*shootPatch)->surf->surfId,maxEnergy); /* check convergence */ if (maxEnergy / totalEnergy < params.threshold) return (0); /* converged, i.e. no more good shooter */ return (1); } /*****************************************************************************/ static void UpdateRadiosities(void) { int i; double t; TSpectra avg_rad,delta_rad; TSample *sp; TElement *ep; if (params.delaunay) { Recalc_Areas(); FOR_ALL_SAMPLES(sp) /* update current sample radiosities */ SpectraMultK(&sp->delta_rad,sp->area / sp->patch->area,&delta_rad); SpectraAddTo(&sp->patch->unshotRad,&delta_rad); SpectraAddTo(&sp->rad,&sp->delta_rad); sp->delta_rad = black; END_ALL_SAMPLES(sp) FOR_ALL_ELEMENTS(ep) /* calc element radiosities */ avg_rad = ep->sample[0]->rad; /* calc Element delta rad */ for (i = 1; i < ep->nPts; i++) SpectraAddTo(&avg_rad,&ep->sample[i]->rad); t = 1.0 / (double) ep->nPts; SpectraMultK(&avg_rad,t,&avg_rad); /* build average */ ep->rad = avg_rad; /* new radiosity of element */ END_ALL_ELEMENTS(ep) } else { FOR_ALL_SAMPLES(sp) /* update current sample radiosities */ SpectraAddTo(&sp->rad,&sp->delta_rad); sp->delta_rad = black; END_ALL_SAMPLES(sp) FOR_ALL_ELEMENTS(ep) /* calc element radiosities */ avg_rad = ep->sample[0]->rad; /* calc Element delta rad */ for (i = 1; i < ep->nPts; i++) SpectraAddTo(&avg_rad,&ep->sample[i]->rad); t = 1.0 / (double) ep->nPts; SpectraMultK(&avg_rad,t,&avg_rad); /* build average */ SpectraSub(&avg_rad,&ep->rad,&delta_rad); /* delta_ele_rad ! */ SpectraMultK(&delta_rad,ep->area / ep->patch->area,&delta_rad); SpectraAddTo(&ep->patch->unshotRad,&delta_rad); ep->rad = avg_rad; /* new radiosity of element */ END_ALL_ELEMENTS(ep) } } /*****************************************************************************/ static char outfilename[30]; /* Initialize radiosity based on the input parameters p */ void InitRad(char *outputfile) { TPatch* pp; TSample* sp; TSpectra temp; strcpy(outfilename,outputfile); FOR_ALL_SAMPLES(sp) sp->rad = black; END_ALL_SAMPLES(sp) FOR_ALL_PATCHES(pp) pp->unshotRad = black; /* will be set by UpdateRadiosities */ END_ALL_PATCHES(pp) UpdateRadiosities(); /* calc element/patch radiosities */ /* compute total energy */ totalEnergy = 0.0; FOR_ALL_PATCHES(pp) SpectraMultK(&pp->unshotRad,pp->area,&temp); totalEnergy += SpectraMax(&temp); END_ALL_PATCHES(pp) memory_statistics(); flush_log(); /* to force log file */ if (params.delaunay) DisplayResultsDT(0,¶ms.displayView,outfilename,1); else DisplayResults(0,¶ms.displayView,outfilename,1); if (totalEnergy == 0.0) error("No energy to distribute"); #ifdef CHECK_FF FOR_ALL_SAMPLES(sp) double ffsum = 0.0; FOR_ALL_PATCHES(pp) SetANShooter(pp); ffsum += ComputeANFF(sp); END_ALL_PATCHES(pp) if (ffsum > 1.00001) log_message("WARNING: FF: %f\n",ffsum); if (ffsum < 0.99999) log_message("Sample %d: FF-Sum: %f\n",i,ffsum); END_ALL_SAMPLES(sp) #endif } /* Main iterative loop */ double DoRad(void) { time_t starttime,midtime,midtime1,midtime2; double timesum,timerad,timerad1,timeout,timeff; unsigned int iteration; TPatch *shoot; if (params.maxIterations < 0) params.maxIterations = 0xFFFFFFFF; iteration = 0; timesum = 0.0; while (iteration < params.maxIterations) { iteration++; message("Iteration %3d",iteration); starttime = time(NULL); if (! FindShootPatch(&shoot)) break; /* no bright enough patch */ midtime = time(NULL); DistributeRad2Samples(shoot); /* calc sample radiosities */ midtime1 = time(NULL); shoot->unshotRad = black; /* reset shooter's unshot radiosity */ UpdateRadiosities(); /* calc element/patch radiosities */ midtime2 = time(NULL); if (params.delaunay) DisplayResultsDT(iteration,¶ms.displayView,outfilename,0); else DisplayResults(iteration,¶ms.displayView,outfilename,0); timerad = diff_time(midtime,starttime); timeff = diff_time(midtime1,midtime); timerad1 = diff_time(midtime2,midtime1); timeout = diff_time(time(NULL),midtime2); memory_statistics(); log_message("FF: %g sec, Total Iteration: %g sec, Output %g sec\n", timeff,timeff + timerad + timerad1,timeout); timesum += timeout + timerad + timeff + timerad1; flush_log(); /* to force log file */ } starttime = time(NULL); if (params.delaunay) /* force output */ DisplayResultsDT(iteration,¶ms.displayView,outfilename,1); else DisplayResults(iteration,¶ms.displayView,outfilename,1); timeout = diff_time(time(NULL),starttime); message("Output %g sec\n",timeout); timesum += timeout; flush_log(); /* to force log file */ return(timesum); } /* Clean up */ void CleanUpRad(void) { } += timeout + timerad + timeff + timerad1; flush_log(); /* to force log file */ } starttime = time(NULL); if (params.delaunay) /* force output */ DisplayResultsDT(iteration,¶ms.displayVFxfire/rad.h000644 000316 000311 00000036361 06114622775 013063 0ustar00wrzlgup000000 000000 /***************************************************************************** * rad.h * * This is the headerfile which defines the data structures used in rad.c * * Copyright (C) 1990-1991 Apple Computer, Inc. * All rights reserved. * * 12/1990 S. Eric Chen ******************************************************************************/ #ifndef __RAD__ #define __RAD__ #define MAXSHADER 3 #define MAXTOTALSHADER 4 #define kMaxPolyPoints 16 /* should be enough !?! */ #define kNumberOfRadSamples 3 typedef unsigned int TId; typedef unsigned char TVisMask[8]; #define DOUBLEP #ifdef DOUBLEP typedef struct { double u, v; } TPoint2f; #else typedef struct { float u, v; } TPoint2f; #endif typedef struct { float x, y, z; } TPoint3f; /* to save space */ typedef struct { float samples[kNumberOfRadSamples]; } TSpectra; typedef TPoint2f TVector2f; typedef TPoint3f TVector3f; typedef struct { unsigned char a, r, g, b; } TColor32b; typedef struct TLine { TVector2f normal; double np; } TLine; typedef struct TPlane { TVector3f normal; double np; } TPlane; typedef struct TBox2 { TPoint2f min; TPoint2f max; } TBox2; typedef struct TPolygon { int n; TPoint3f vert[kMaxPolyPoints]; } TPolygon; typedef struct TPoly2 { int n; int level; int leaf; TPoint2f vert[kMaxPolyPoints]; } TPoly2; /* a quadrilateral for the surface initialisations */ typedef struct { TId surfId; /* surface number */ TId objId; /* object number */ char toSample; /* surface to be sampled */ char toTest; /* surface to be tested for visibility */ short radIndex; /* index of rad-proc which gets this surface */ short visIndex; /* index of vis-proc which gets this surface */ int nSamples; /* # of samples */ char nPts; /* # of vertices */ short patchLevel; /* patch subdiv level */ short elementLevel; /* element subdiv level */ TPoint3f vert[4]; /* vertices of the quadrilateral */ TVector3f normal; /* normal of the quadrilateral */ TSpectra reflectance; /* diffuse reflectance of the quadrilateral */ TSpectra emission; /* vertex emission of the quadrilateral */ } TQuad; typedef struct TSurface { TId surfId; /* surface id */ TId objId; /* object id */ char toSample; /* surface to be sampled */ char toTest; /* surface to be tested for visibility */ char lightsource; /* is a lightsource */ char nPts; /* # of vertices 3/4 */ char project; /* axis of projection 03=yz,14=xz,25=xy */ char sampled; /* sampled in current iteration */ double area; /* area */ double ndotp; /* normal dot point */ TVector3f normal; /* normal */ TPoint3f vert[4]; /* vertices */ TPoint3f min, max; /* bounding box of the surface */ TPoint2f vert2[4]; /* 2d vertices */ TPoint2f min2, max2; /* 2d bounding box */ TSpectra reflectance; /* diffuse reflectance of the surface */ struct TPatch *patches; /* list of patches */ struct TElement *elements; /* tree of Elements */ struct TSample *samples; /* list of samples */ struct TDisco *disco; /* disco mesh by current shooter */ struct TBSP2d *d0mesh; /* d0 mesh of surface */ struct TRIANG *vd; /* delaunay triang surface description */ } TSurface; typedef struct TPatch { TId patchId; /* patch id */ int nPts; /* # of vertices 3/4 */ double area; /* area of the patch */ TPoint3f center; /* center of the patch */ TPoint3f vert[4]; /* the 4 corners */ TSpectra unshotRad; /* unshot radiosity of the patch */ TSurface *surf; /* pointer to surface we belong to */ struct TPatch *next; /* next patch */ } TPatch; typedef struct TSample { char exactDeltaRad; /* delta rad was calced (not interpolated) */ char new_sample; /* added by adaptive subdivision */ char nShader; /* # of shader patches */ TSurface *shader[MAXSHADER];/* contains shading patches */ int site_ptr; /* pointer to delaunay data */ TPoint3f point; /* sample location */ TPoint2f point2; /* u,v coord of location */ TSpectra rad; /* radiosity of the sample */ TSpectra delta_rad; /* radiosity due to current lightsource */ TSpectra display_rad; /* radiosity for display */ double ff; /* ff for current lightsource */ double area; /* area of voronoi polygon */ TVisMask vis; /* visibility mask */ TPatch *patch; /* pointer to patch we belong to */ struct TSample *next; /* sample chain per surface */ } TSample; typedef struct TElement { char leaf; /* 1 = leaf, 0 = node */ char level; /* which level in the tree: root=1 */ char nPts; /* # of corners 3/4 */ char nChild; /* # of children */ char original; /* if set: original element from mesh gen */ char marked; /* mark for check of element */ char discontinuity[4]; /* discontinuities of the edges */ double area; /* area of the element */ TSpectra rad; /* leaf: radiosity of the element */ TPoint2f min,max; /* bbox */ TPatch *patch; /* pointer to patch we belong to */ struct TElement *parent; /* the parent node */ struct TElement **child; /* node: pointer to children array */ TSample *sample[4]; /* the corners */ } TElement; typedef struct { TPoint3f camera; /* camera location */ TPoint3f lookat; /* point of interest */ TVector3f up; /* view up vector */ double fovx, fovy; /* field of view in x, y (in degree) */ double near_clip, far_clip; /* dist from camera to the near & far planes */ unsigned short xRes, yRes; /* resolution of the frame buffer */ unsigned long *buffer; /* for output */ } TView; /* Radiosity input parameters */ typedef struct { unsigned long nSurfs; /* number of surfaces */ TSurface *surfs; /* surfaces */ unsigned long nPatches; /* number of patches */ TPatch *patches; /* patches */ unsigned long nSamples; /* current number of samples */ unsigned long nElements;/* number of elements */ unsigned long nTestSurfs; /* # of surfaces which are for visibility */ TSurface *testSurfs; /* surfaces which are tested for visibility */ FILE *logfile; /* logfile */ TView displayView; /* view to display the results */ double threshold; /* convergence threshold (fraction of the total */ /* emitted energy) */ int maxIterations; /* max number of iterations / 0 = forever */ int picture_iteration; /* iteration for picture output /0=all/-1=never */ int adaptiveSubdiv; /* adaptive Subdivision */ int maxAdaptiveSubdiv; /* max subdiv level for adaptive Subdivision */ double subdivPrecision; /* when to stop subdivion */ int visibleRays; /* for anff's: number of ray for visibility */ double eps_B; /* for ff's: minimum Radiosity */ double min_A; /* for ff's: minimum Area */ int exactFF; /* calc exact FF's */ int noRestrictQuadtree; /* use a restricted Quadtree */ int sampleAllSamples; /* don't interpolate nonoriginal subdivisions */ int tvertices; /* !vd: try to avoid t-vertices for output */ int randomrays; /* rtff: use random rays (not midpoint rays) */ int delaunay; /* use delaunaytrig as surface mesh */ int outputSites; /* vd: output sites to vdx-file */ int bsptreelen; /* use bsptree for surface visibilities */ int d0mesh; /* insert all d0 edges into mesh */ int discomesh; /* use discomeshing */ } TRadParams; typedef struct TShooter { TId surfId; /* surface id */ TId patchId; /* patch id */ char lightsource; /* is a lightsource */ TPoint3f center; /* center */ TVector3f normal; /* plane normal */ double ndotp; /* plane NdotP */ double area; /* area */ TSpectra unshotRad; /* unshot Radiosity */ TPolygon pol; /* polgon */ } TShooter; /********************** defines for bsptree *********************/ typedef struct TGeomObj { TSurface *surf; /* pointer to the surface */ struct TGeomObj *next; /* pointer to next primitive */ } TGeomObj; typedef struct { TPoint3f origin; /* ray origin */ TVector3f direction; /* ray direction */ double minDistance; /* min distance */ double maxDistance; /* max distance */ } TRay; typedef struct TBinNode { TPoint3f min, max; /* extent of node */ TGeomObj *root; /* list of enclosed primitives (surfaces) */ int length; /* number of surfaces in link list */ struct TBinNode *child[2]; /* pointers to children nodes, if any */ /* distance to the plane which subdivides the children */ double (*DistanceToDivisionPlane)(TPoint3f *plane, TRay *ray); /* children near/far ordering relative to a input point */ void (*GetChildren)(struct TBinNode *currentNode, TRay *ray, struct TBinNode **near, struct TBinNode **far); } TBinNode; /************************ Global variables *******************************/ extern TRadParams params; /* main.c */ extern TSpectra black,white; /* spectra.c */ extern TShooter shooter; /* ff.c */ extern TBinNode *BSPTree; /* bsptree.c */ extern TVector3f *normalVec; /* input.c */ /***************************** Macros ***********************************/ #ifdef MSDOS #define diff_time(e,s) difftime(e,s) #else #define diff_time(e,s) (double) (e - s) #endif #ifndef RAND_MAX #ifdef sun #define RAND_MAX 2147483647 /* (2^31) - 1*/ #else #define RAND_MAX 32767 /* (2^15) - 1 */ #endif #endif #define RandomFloat ((float)(rand())/(float)RAND_MAX) #define SWAP(a,b,t) { t = a; a = b; b = t; } /********************* MEGA-Macros for Element Loops *********************/ #define FOR_ALL_TESTSURFS(surf) \ { int _j06; \ surf = params.surfs; \ for (_j06 = params.nSurfs; _j06--; surf++) { \ if (surf != NULL && surf->toTest) { #define END_ALL_TESTSURFS(surf) } } } #define FOR_ALL_SURFS(surf) \ { int _j00; \ surf = params.surfs; \ for (_j00 = params.nSurfs; _j00--; surf++) { \ if (surf != NULL && surf->toSample) { #define END_ALL_SURFS(surf) } } } #define FOR_ALL_PATCHES(pp) \ { int _j05; \ for (_j05 = 0; _j05 < params.nSurfs; _j05++) { \ if (¶ms.surfs[_j05] != NULL && params.surfs[_j05].toSample) { \ pp = params.surfs[_j05].patches; \ while (pp != NULL) { #define END_ALL_PATCHES(pp) pp = pp->next; } } } } #define FOR_ALL_SURF_SAMPLES(surf,sp) \ { if (surf != NULL && surf->toSample) { \ sp = surf->samples; \ while (sp != NULL) { #define END_ALL_SURF_SAMPLES(sp) sp = sp->next; } } } #define FOR_ALL_SAMPLES(sp) \ { int _j01; \ for (_j01 = 0; _j01 < params.nSurfs; _j01++) { \ if (¶ms.surfs[_j01] != NULL && params.surfs[_j01].toSample) { \ sp = params.surfs[_j01].samples; \ while (sp != NULL) { #define END_ALL_SAMPLES(sp) sp = sp->next; } } } } #define FOR_ALL_SURF_ELEMENTS(surf,ep) _FOR_ALL_SURF_ELEMENTS(surf,ep,0) #define END_ALL_SURF_ELEMENTS(ep) _END_ALL_SURF_ELEMENTS(ep) #define _FOR_ALL_SURF_ELEMENTS(surf,ep,cond) \ { int _j03; TElement *_old,*_last; \ if (surf != NULL && surf->toSample) { \ ep = surf->elements; _last = NULL; \ while (ep != NULL) { \ if (! ep->leaf && ! cond) { _old = ep; \ if (_last == ep->parent) ep = ep->child[0]; \ else { for (_j03 = 0; _j03 < ep->nChild - 1; _j03++) \ if (_last == ep->child[_j03]) { \ ep = ep->child[_j03 + 1]; break; } \ if (ep == _old) ep = ep->parent; /* not found */ \ } \ _last = _old; continue; } #define _END_ALL_SURF_ELEMENTS(ep) _last = ep; ep = ep->parent; } } } #define FOR_ALL_ELEMENTS(ep) _FOR_ALL_ELEMENTS(ep,0) #define END_ALL_ELEMENTS(ep) _END_ALL_ELEMENTS(ep) #define _FOR_ALL_ELEMENTS(ep,cond) \ { int _j02,_j04; TElement *_old,*_last; \ for (_j02 = 0; _j02 < params.nSurfs; _j02++) { \ if (¶ms.surfs[_j02] != NULL && params.surfs[_j02].toSample) { \ ep = params.surfs[_j02].elements; _last = NULL; \ while (ep != NULL) { \ if (! ep->leaf && ! cond) { _old = ep; \ if (_last == ep->parent) ep = ep->child[0]; \ else { for (_j04 = 0; _j04 < ep->nChild - 1; _j04++) \ if (_last == ep->child[_j04]) { \ ep = ep->child[_j04 + 1]; break; } \ if (ep == _old) ep = ep->parent; /* not found */ \ } \ _last = _old; continue; } #define _END_ALL_ELEMENTS(ep) _last = ep; ep = ep->parent; } } } } /******************************* Prototototypes ******************************/ /* make it C++ friendly */ #ifdef __cplusplus extern "C" { #endif /*__cplusplus*/ /* main.c */ void message(char const *fmt, ...); void flush_log(void); void log_message(char const *fmt, ...); void error(char const *fmt, ...); /* rad.c */ void InitRad(char *outputfile); double DoRad(void); void CleanUpRad(void); /* display.c */ void DisplayResults(int iterNr,TView* view,char *filename,int force); void DisplayResultsDT(int iterNr,TView* view,char *filename,int force); /* sample.c */ void DistributeRad2Samples(TPatch *lightSource); /* ff.c */ int NewSampleSurface(TSurface *surf); void ShootRad2Sample(TSample *sp); void BeginFF(TPatch *lightSource); void EndFF(void); double ComputeANFF(TSample *sp); void SetANShooter(TPatch *lightSource); /* surface.c */ void ComputeWeights(TPoint2f *pts,int nPts,TPoint2f *point2,double *weight); void SurfPoint(TSurface *surf,TPoint2f *point2,TPoint3f *point); TElement *FindElement(TElement *tree,TPoint2f *point2); TSample* FindSample(TElement *tree,TPoint2f *point2); TElement* FindSampleElement(TElement *ep,TSample *sp,TSample *next, int *sample_index); TElement* FindNeighbourElement(TSurface *surf,TElement *ep,int side,int discos); void FindSamplesOnEdges(TElement *ep,TElement *tree,TSample **samples, int *nSamples); int CalcBorderShift(TSurface *surf,TSample *s0,TSample *s1,TPoint2f *point2, TPoint2f *shift); void BorderShift(TSurface *surf,TElement *ep,TPoint2f *point2,TPoint3f *point); void Recalc_Areas(void); void CheckAllAreas(void); /* mesh.c */ int GenSample(TSample **sample,TPoint2f *point2,TElement *ep,TPatch *patch, TSurface *surf,int find); void InitSurfaces(int nQuads,TQuad *quads); /* subdiv.c */ double calcAreaElement(TElement *element,TSurface *surf); int SubdivElement4(TElement *ep,TSurface *surf); int SubdivElementShaders(TElement *ep,TSurface *surf,TSurface **shaders); /* memory.c */ TSample *alloc_sample(void); TElement *alloc_element(void); TPatch *alloc_patch(void); TGeomObj *alloc_obj(void); TBinNode *alloc_node(void); TElement **alloc_child(int nChild); TPoint3f *alloc_points(int number); TQuad *alloc_quads(int number); TSurface *alloc_surfs(int number); TPatch *alloc_patches(int number); void memory_statistics(void); /* spectra.c */ TColor32b SpectraToRGB(TSpectra* spectra); double SpectraSum(TSpectra *spectra); double SpectraMax(TSpectra *spectra); double SpectraAbsSum(TSpectra *spectra); double SpectraAvg(TSpectra *spectra); void SpectraMultK(TSpectra *spectra,double k,TSpectra* result); void SpectraAdd(TSpectra *op1,TSpectra *op2,TSpectra *result); void SpectraAddTo(TSpectra *op1,TSpectra *result); void SpectraSub(TSpectra *op1,TSpectra *op2,TSpectra *result); void SpectraMult(TSpectra *op1,TSpectra *op2,TSpectra *result); void SpectraInv(TSpectra *op,TSpectra *result); /* input.c */ void ReadData(char *filename,TQuad **roomPolys,int *numberOfPolys); /* output.c */ int BeginOutput(int iterNr,TView *theView,char *outputfile,int force); void OutputPolygon(int iterNr,int nPts,TPoint3f *pts,TVector3f* n, TSpectra *rad,TSpectra *ambient,TSpectra *rads,int surface); void EndOutput(void); /* bsptree.c */ TSurface *RayTreeIntersect(TRay *ray, TBinNode *BSPTree1, TId shooterId, TId surfId); void InitBinTree(TBinNode **BSPTree1); #ifdef __cplusplus }; #endif /*__cplusplus*/ #endif /*__RAD__*/ *filename,TQuad **roomPolys,int *numberOfPolys); /* output.c */ int BeginOutput(int iterNr,TView *theView,char *outputfile,int force); void OutputPolygon(int iterNr,int nPts,TPoint3f *pts,TVector3f* n, TSpectra *rad,TSpectra *ambient,TSpectra *rads,int surface); voidFxfire/sample.c000644 000316 000311 00000022101 06114620343 013541 0ustar00wrzlgup000000 000000 /****************************************************************************** * sample.c ******************************************************************************/ #include #include #include #include #include "rad.h" #include "geom.h" #include "dt.h" #include "disco.h" static int added_samples,added_elements,sampled_samples,interpolated_samples; static void interpolateRad(TElement *ep,TPoint2f *loc,TSpectra *rad,int delta) { int i; double weight[kMaxPolyPoints]; TSpectra temp; TPoint2f pts[kMaxPolyPoints]; for (i = 0; i < ep->nPts; i++) pts[i] = ep->sample[i]->point2; ComputeWeights(pts,ep->nPts,loc,weight); *rad = black; for (i = 0; i < ep->nPts; i++) { if (delta) SpectraMultK(&ep->sample[i]->delta_rad,weight[i],&temp); else SpectraMultK(&ep->sample[i]->rad,weight[i],&temp); SpectraAddTo(rad,&temp); } } static void interpolateDeltaRadChildren(TElement *ep,TElement *root) { int i; if (! ep->leaf) { /* go further down */ for (i = 0; i < ep->nChild; i++) interpolateDeltaRadChildren(ep->child[i],root); return; } /* interpolate the samples from the root element but: */ /* never overwrite a sampled (exact) value */ for (i = 0; i < ep->nPts; i++) { if (ep->sample[i]->exactDeltaRad == 0) { interpolateRad(root,&ep->sample[i]->point2, &ep->sample[i]->delta_rad,1); ep->sample[i]->exactDeltaRad = 2; interpolated_samples++; } } } static int minmaxDeltaRad(TElement *ep,double *min_rad,double *max_rad) { int i; double avg; *min_rad = 1.0E6; *max_rad = -1.0E6; for (i = 0; i < ep->nPts; i++) { avg = SpectraAvg(&ep->sample[i]->delta_rad); if (avg > *max_rad) *max_rad = avg; if (avg < *min_rad) *min_rad = avg; } if (*max_rad < 0.01 / 256.0) /* ferget it, way too dark */ return(1); if (*max_rad - *min_rad > *max_rad * params.subdivPrecision) /* inhomogenous */ return(0); return(1); } static int uniformRad(TElement *ep,TSurface **shaders) { int i,j,k,cntshaders,inhomo,allzero; double min_rad,max_rad; TSurface *shader; for (i = 0; i < MAXTOTALSHADER; i++) shaders[i] = NULL; if (ep->level >= params.maxAdaptiveSubdiv) /* no more subdiv needed */ return(1); if (! params.discomesh) return(minmaxDeltaRad(ep,&min_rad,&max_rad)); inhomo = 0; allzero = 1; shader = NULL; for (i = 0; i < ep->nPts; i++) { if (ep->sample[i]->nShader > MAXSHADER) inhomo = 1; if (shader == NULL && ep->sample[i]->nShader > 0) shader = ep->sample[i]->shader[0]; if (ep->sample[i]->ff > 0.0) allzero = 0; } if (allzero) { /* all in shadow */ message("Z"); return(1); } if (inhomo) { /* someone needs more subdiv */ message("I"); return(0); } (void) minmaxDeltaRad(ep,&min_rad,&max_rad); if (max_rad < 0.01 / 256.0) { /* ferget it, way too dark */ message("<"); return(1); } if (shader == NULL) { /* no shader */ if (max_rad - min_rad > max_rad * params.subdivPrecision) { message("i"); /* too inhomogenous */ return(0); } message("n"); return(1); } #ifdef NOT_NOW if (ep->disco_created) { /* was already discomeshed */ for (i = 0; i < ep->nPts; i++) { for (j = 0; j < ep->sample[i]->nShader; j++) { if (ep->sample[i]->shader[j] != shader) { message("m"); return(0); /* more than 1 shader here */ } } } if (max_rad - min_rad > max_rad * params.subdivPrecision * 2.0) { message("Œ"); /* too inhomogenous */ return(0); } message("d"); return(1); } #endif /* find all our shaders */ cntshaders = 0; for (i = 0; i < ep->nPts; i++) { for (j = 0; j < ep->sample[i]->nShader; j++) { for (k = 0; k < cntshaders; k++) { if (ep->sample[i]->shader[j] == shaders[k]) break; /* already there */ } if (k >= cntshaders) { /* not found */ if (cntshaders >= MAXTOTALSHADER) { message("+"); return(0); /* too many shaders */ } shaders[cntshaders] = ep->sample[i]->shader[j]; cntshaders++; /* hey, we have one more now */ } } } message("S%d",cntshaders); return(0); } static int SubdivElement(TElement *ep,TSurface **shaders) { int i,j,news; double t; TSpectra temp; if (params.discomesh && shaders[0] != NULL) { news = SubdivElementShaders(ep,ep->patch->surf,shaders); if (news == -2) { /* no need to subdiv */ message("x"); return(0); } if (news == -1) { /* too complex use old subdiv ! */ message("/"); news = SubdivElement4(ep,ep->patch->surf); return(1); } } else { message("."); news = SubdivElement4(ep,ep->patch->surf); } /* calc sample radiosities (due to old lightsources) for all new samples */ for (i = 0; i < ep->nChild; i++) { for (j = 0; j < ep->child[i]->nPts; j++) { if (ep->child[i]->sample[j]->new_sample) interpolateRad(ep,&ep->child[i]->sample[j]->point2, &ep->child[i]->sample[j]->rad,0); } } /* calc new element radiosities (due to old lightsources) */ for (i = 0; i < ep->nChild; i++) { temp = ep->child[i]->sample[0]->rad; for (j = 1; j < ep->child[i]->nPts; j++) SpectraAddTo(&temp,&ep->child[i]->sample[j]->rad); t = 1.0 / (double) ep->nPts; SpectraMultK(&temp,t,&ep->child[i]->rad); } added_elements += ep->nChild - 1; added_samples += news; return(1); } /******************************************************************************/ static int Element2Subdiv(TElement *ep,TSurface **shaders) { int i; TElement *neigh; shaders[0] = NULL; if (! uniformRad(ep,shaders)) /* not uniform enough */ return(1); shaders[0] = NULL; /* no shader subdiv because of restricted Quadtree */ if (! params.noRestrictQuadtree) { for (i = 0; i < ep->nPts; i++) { neigh = FindNeighbourElement(ep->patch->surf, ep->patch->surf->elements,i,1); if (neigh != NULL && neigh->level > ep->level + 1) return(1); /* I sense something deep nearby */ } } return(0); } /******************************************************************************/ void DistributeRad2Samples(TPatch *lightSource) { int i,j,done; TSample *sp; TElement *ep; TSurface *surf,*shaders[MAXTOTALSHADER]; if (! params.adaptiveSubdiv) { BeginFF(lightSource); FOR_ALL_SURFS(surf) if (NewSampleSurface(surf)) { FOR_ALL_SURF_SAMPLES(surf,sp) ShootRad2Sample(sp); /* do sampling */ END_ALL_SURF_SAMPLES(sp) } END_ALL_SURFS(surf) EndFF(); return; } BeginFF(lightSource); sampled_samples = 0; interpolated_samples = 0; added_elements = 0; added_samples = 0; FOR_ALL_SURFS(surf) surf->disco = NULL; /* reset disco mesh */ FOR_ALL_SURF_SAMPLES(surf,sp) /* reset all samples */ sp->exactDeltaRad = 0; sp->new_sample = 0; END_ALL_SURF_SAMPLES(sp) if (NewSampleSurface(surf)) { /* is valid sample surface */ if (params.sampleAllSamples) { FOR_ALL_SURF_ELEMENTS(surf,ep) /* mark all samples/elements */ ep->marked = 1; for (i = 0; i < ep->nPts; i++) ep->sample[i]->new_sample = 1; END_ALL_SURF_ELEMENTS(ep) } else { /* mark original samples/elements only */ _FOR_ALL_SURF_ELEMENTS(surf,ep,ep->original) ep->marked = 1; for (i = 0; i < ep->nPts; i++) ep->sample[i]->new_sample = 1; _END_ALL_SURF_ELEMENTS(ep) } } END_ALL_SURFS(surf) message("refining "); done = 0; while (! done) { done = 1; /********************** do sampling ****************************/ FOR_ALL_SURFS(surf) if (NewSampleSurface(surf)) { FOR_ALL_SURF_SAMPLES(surf,sp) if (sp->new_sample) { ShootRad2Sample(sp); sp->new_sample = 0; sp->exactDeltaRad = 1; sampled_samples++; } END_ALL_SURF_SAMPLES(sp) } END_ALL_SURFS(surf) /********************** check if refine neccesary *****************/ FOR_ALL_SURFS(surf) if (NewSampleSurface(surf)) { _FOR_ALL_SURF_ELEMENTS(surf,ep,ep->marked) if (Element2Subdiv(ep,shaders)) { if (ep->leaf) { /* gen new element */ if (SubdivElement(ep,shaders)) done = 0; } else { /* go down hierarchy */ for (i = 0; i < ep->nChild; i++) for (j = 0; j < ep->child[i]->nPts; j++) if (ep->child[i]->sample[j]->exactDeltaRad != 1) ep->child[i]->sample[j]->new_sample = 1; done = 0; } if (! done) /* test all new eles */ for (i = 0; i < ep->nChild; i++) ep->child[i]->marked = 1; } else { /* no to be subdivided */ if (! params.sampleAllSamples) interpolateDeltaRadChildren(ep,ep); } /* go down & interpolate */ ep->marked = 0; _END_ALL_SURF_ELEMENTS(ep) } END_ALL_SURFS(surf) if (! done) message(";"); } message("\n"); FOR_ALL_SURFS(surf) /* free disco meshes */ if (surf->disco != NULL) free_disco_mesh(surf->disco); END_ALL_SURFS(surf) if (added_elements) message("added %d Samples, %d Elements\n",added_samples,added_elements); log_message("sampled %d Samples, interpolated %d Samples\n", sampled_samples,interpolated_samples); log_message("Total: %d Samples, %d Elements\n",params.nSamples, params.nElements); EndFF(); } (surf) if (! done) message(";"); } message("\n"); FOR_ALL_SURFS(surf) /* free disco meshes */ if (surf->disco != NULL) free_disco_mesh(surf->disco); END_ALL_SURFS(surf) if (added_elements) message("added %d Samples, %d Elements\n",added_samples,added_elements); log_message("sampled %d Samples, interpolated %d Samples\n", sampled_samples,interpolated_samples); log_message("Total: %d Samples, %d Elements\n",Fxfire/spectra.c000644 000316 000311 00000005636 06114620343 013737 0ustar00wrzlgup000000 000000 /***************************************************************************** * spectra.c ******************************************************************************/ #include #include #include "rad.h" TSpectra black = { { 0.0, 0.0, 0.0 } }; /* for initialization */ TSpectra white = { { 1.0, 1.0, 1.0 } }; /* for initialization */ /* Convert a TSpectra (radiosity) to a TColor32b (rgb color) */ /* Assume the first three samples of the spectra are the r, g, b colors */ /* More elaborated color space transformation could be performed here */ TColor32b SpectraToRGB(TSpectra* spectra) { TColor32b c; TSpectra r; double maxi=1.0; int k; for (k=kNumberOfRadSamples; k--;) { if (spectra->samples[k] > maxi) maxi = spectra->samples[k]; } /* Clip the intensity*/ r = *spectra; if (maxi > 1.0) { for (k=kNumberOfRadSamples; k--; ) r.samples[k] /= maxi; } /* Convert to a 32-bit color; Assume the first 3 samples in TSpectra are the r, g, b colors we want. Otherwise, do color conversion here */ c.a = 0; c.r = (unsigned char) (r.samples[0] * 255.0 + 0.5); c.g = (unsigned char) (r.samples[1] * 255.0 + 0.5); c.b = (unsigned char) (r.samples[2] * 255.0 + 0.5); return c; } double SpectraSum(TSpectra *spectra) { int i; double sum; sum = 0.0; for (i = 0; i < kNumberOfRadSamples; i++) sum += spectra->samples[i]; return(sum); } double SpectraMax(TSpectra *spectra) { int i; double maxi; maxi = 0.0; for (i = 0; i < kNumberOfRadSamples; i++) if (spectra->samples[i] > maxi) maxi = spectra->samples[i]; return(maxi); } double SpectraAbsSum(TSpectra *spectra) { int i; double sum; sum = 0.0; for (i = 0; i < kNumberOfRadSamples; i++) sum += fabs(spectra->samples[i]); return(sum); } double SpectraAvg(TSpectra *spectra) { int i; double sum; sum = 0.0; for (i = 0; i < kNumberOfRadSamples; i++) sum += spectra->samples[i]; sum /= kNumberOfRadSamples; return(sum); } void SpectraMultK(TSpectra *spectra,double k,TSpectra* result) { int i; for (i = 0; i < kNumberOfRadSamples; i++) result->samples[i] = spectra->samples[i] * k; } void SpectraAdd(TSpectra *op1,TSpectra *op2,TSpectra *result) { int i; for (i = 0; i < kNumberOfRadSamples; i++) result->samples[i] = op1->samples[i] + op2->samples[i]; } void SpectraAddTo(TSpectra *result,TSpectra *op1) { int i; for (i = 0; i < kNumberOfRadSamples; i++) result->samples[i] += op1->samples[i]; } void SpectraSub(TSpectra *op1,TSpectra *op2,TSpectra *result) { int i; for (i = 0; i < kNumberOfRadSamples; i++) result->samples[i] = op1->samples[i] - op2->samples[i]; } void SpectraMult(TSpectra *op1,TSpectra *op2,TSpectra *result) { int i; for (i = 0; i < kNumberOfRadSamples; i++) result->samples[i] = op1->samples[i] * op2->samples[i]; } void SpectraInv(TSpectra *op,TSpectra *result) { int i; for (i = 0; i < kNumberOfRadSamples; i++) result->samples[i] = 1.0 / op->samples[i]; } void SpectraSub(TSpectra *op1,TSpectra *op2,TSpectra *result) { int i; for (i = 0; i < kNumbFxfire/subdiv.c000644 000316 000311 00000022452 06114620343 013565 0ustar00wrzlgup000000 000000 /***************************************************************************** * subdiv.c ******************************************************************************/ #include #include #include #include #include "rad.h" #include "geom.h" #include "dt.h" #include "disco.h" #include "log.h" double calcAreaElement(TElement *element,TSurface *surf) { int i; TPoint3f pts[kMaxPolyPoints]; for (i = 0; i < element->nPts; i++) Project3d(*surf,element->sample[i]->point2,pts[i]); return(areaPoly(pts,element->nPts)); } static void alloc_children(TElement *ep,int children,int nPts) { int i; ep->nChild = children; ep->child = alloc_child(children); for (i = 0; i < ep->nChild; i++) { ep->child[i] = alloc_element(); ep->child[i]->parent = ep; ep->child[i]->level = ep->level + 1; ep->child[i]->patch = ep->patch; ep->child[i]->nPts = nPts; ep->child[i]->leaf = 1; } } static void calc_bbox_area(TElement *ep,TSurface *surf) { int i; #ifdef LOG_TRIANGLES for (i = 0; i < ep->nPts; i++) { log_message("%g %g %d\n",ep->sample[i]->point2.u,ep->sample[i]->point2.v, ep->discontinuity[i]); } log_message("\n"); #endif ep->min = ep->sample[0]->point2; /* calc 2d bbox */ ep->max = ep->min; for (i = 1; i < ep->nPts; i++) { MakeBbox2(ep->min,ep->max,ep->sample[i]->point2); } ep->area = calcAreaElement(ep,surf); } /**************************************************************************/ static TElement *curel; static VOID owntriproc(TRIANG *surf,SITE_PTR s1,SITE_PTR s2,SITE_PTR s3, DISCONTINUITY d1,DISCONTINUITY d2,DISCONTINUITY d3) { /* construct a child of curel */ curel->child[curel->nChild]->sample[0] = get_info(surf,s1); curel->child[curel->nChild]->discontinuity[0] = (d1 == DTEMP) ? DINF : d1; curel->child[curel->nChild]->sample[1] = get_info(surf,s2); curel->child[curel->nChild]->discontinuity[1] = (d2 == DTEMP) ? DINF : d2; curel->child[curel->nChild]->sample[2] = get_info(surf,s3); curel->child[curel->nChild]->discontinuity[2] = (d3 == DTEMP) ? DINF : d3; curel->nChild++; } #ifdef DOUBLEP #define EPS 1E-10 #else #define EPS 1E-5 #endif int triangulate_element(TSurface *surf,TElement *ep,TSegment *segs,int nSeg, VOID (*triproc)(TRIANG *surf,SITE_PTR s1,SITE_PTR s2,SITE_PTR s3, DISCONTINUITY d1,DISCONTINUITY d2,DISCONTINUITY d3)) { int i,j,tricnt,newsamples; INT new_sites; double x,y; TPoint2f p; TSample *sample; TRIANG *dt; SITE_PTR site1,site2,sites[MAXSEGS * 3]; DISCONTINUITY disc; newsamples = 0; tricnt = 0; curel = ep; /***************** init surface with corner points *****************/ init_surface(&dt,ep->min.u,ep->min.v,ep->max.u,ep->max.v); for (i = 0; i < ep->nPts; i++) insert_site(dt,ep->sample[i]->point2.u,ep->sample[i]->point2.v, &sites[i],ep->sample[i]); for (i = 0; i < ep->nPts; i++) { disc = ep->discontinuity[i]; if (disc == DINF) disc = DTEMP; insert_edge(dt,sites[i],sites[(i + 1) % ep->nPts],disc,NULL,NULL); } /********************* insert all segs ****************************/ for (i = 0; i < nSeg; i++) { if (segs[i].point1.u < ep->min.u && segs[i].point1.u > ep->min.u - EPS) segs[i].point1.u = ep->min.u; if (segs[i].point1.u > ep->max.u && segs[i].point1.u < ep->max.u + EPS) segs[i].point1.u = ep->max.u; if (segs[i].point1.v < ep->min.v && segs[i].point1.v > ep->min.v - EPS) segs[i].point1.v = ep->min.v; if (segs[i].point1.v > ep->max.v && segs[i].point1.v < ep->max.v + EPS) segs[i].point1.v = ep->max.v; if (segs[i].point2.u < ep->min.u && segs[i].point2.u > ep->min.u - EPS) segs[i].point2.u = ep->min.u; if (segs[i].point2.u > ep->max.u && segs[i].point2.u < ep->max.u + EPS) segs[i].point2.u = ep->max.u; if (segs[i].point2.v < ep->min.v && segs[i].point2.v > ep->min.v - EPS) segs[i].point2.v = ep->min.v; if (segs[i].point2.v > ep->max.v && segs[i].point2.v < ep->max.v + EPS) segs[i].point2.v = ep->max.v; if (locate_point(dt,segs[i].point1.u,segs[i].point1.v,sites)) site1 = sites[0]; else { newsamples += GenSample(&sample,&segs[i].point1,ep,ep->patch, surf,1); insert_site(dt,segs[i].point1.u,segs[i].point1.v,&site1,sample); } if (segs[i].discontinuity == DINF) { /* only sites */ if (newsamples > 0) error("created new Sample"); continue; } if (locate_point(dt,segs[i].point2.u,segs[i].point2.v,sites)) site2 = sites[0]; else { newsamples += GenSample(&sample,&segs[i].point2,ep,ep->patch, surf,1); insert_site(dt,segs[i].point2.u,segs[i].point2.v,&site2,sample); } new_sites = 0; insert_edge(dt,site1,site2,segs[i].discontinuity,sites,&new_sites); for (j = 0; j < new_sites; j++) { if (get_info(dt,sites[j]) == NULL) { /* no existing site */ get_coords(dt,sites[j],&x,&y); InitPoint2(p,x,y); newsamples += GenSample(&sample,&p,ep,ep->patch,surf,1); set_info(dt,sites[j],sample); } } } /********************* now triangulate ****************************/ if (triproc != NULL) { tricnt = for_all_triangles(dt,triproc); /* do custom stuff */ newsamples = tricnt; /* other return */ } else { tricnt = for_all_triangles(dt,NULL); /* count child-triangles */ alloc_children(ep,tricnt,3); /* allocate them */ ep->nChild = 0; /* count as we construct them */ for_all_triangles(dt,owntriproc); /* construct child-triangles */ if (ep->nChild != tricnt) error("bug in triangulate_element"); #ifdef LOG_TRIANGLES log_message("TRIS"); #endif for (i = 0; i < ep->nChild; i++) calc_bbox_area(ep->child[i],surf); } delete_surface(dt); return(newsamples); } /**************************************************************************/ int SubdivElementShaders(TElement *ep,TSurface *surf,TSurface **shaders) { int news,i; TDisco *disco[MAXTOTALSHADER]; TBSP2d *bsp2d; int nSeg; TSegment segs[MAXSEGS * MAXTOTALSHADER]; if (! shooter.lightsource) /* no lightsource: use old subdiv */ return(-1); if (! ep->leaf) error("SubdivElementShader called on node !"); for (i = 0; i < MAXTOTALSHADER && shaders[i] != NULL; i++) { if (shaders[i]->disco != NULL) disco[i] = shaders[i]->disco; else { disco[i] = calc_disco_mesh(&shooter,shaders[i]); if (disco[i] == NULL) error("à"); /* no disco mesh constructible */ shaders[i]->disco = disco[i]; } } bsp2d = NULL; for (i = 0; i < MAXTOTALSHADER && shaders[i] != NULL; i++) construct_disco(disco[i],ep,&bsp2d); nSeg = clip_segments(ep->patch->surf,ep,bsp2d,0,segs); free_bsp2(bsp2d); if (nSeg == 0) return(-2); /* no discontinuities here */ news = triangulate_element(surf,ep,segs,nSeg,NULL); ep->leaf = 0; /* do down here 'cause of FindSample/Element */ params.nElements += ep->nChild - 1; /* ep itself is a node now */ return(news); } /**************************************************************************/ int SubdivElement4(TElement *ep,TSurface *surf) { int news,i,mi; double len,maxlen; TSample *s[5]; TPoint2f mids[5]; if (! ep->leaf) error("SubdivElement4 called on node !"); if (ep->nPts > 4) error("SubdivElement4 only for 3/4 points"); alloc_children(ep,4,ep->nPts); news = 0; for (i = 0; i < ep->nPts; i++) { AvgVector2(mids[i],ep->sample[i]->point2, ep->sample[(i + 1) % ep->nPts]->point2); news += GenSample(&s[i],&mids[i],ep,ep->patch,surf, (ep->discontinuity[i] == D0) ? 0 : 1); } if (ep->nPts == 4) { AvgVector2(mids[4],mids[0],mids[2]); news += GenSample(&s[4],&mids[4],ep,ep->patch,surf,1); for (i = 0; i < 4; i++) { ep->child[i]->sample[i] = ep->sample[i]; /* corners */ ep->child[i]->sample[(i + 1) % 4] = s[i]; ep->child[i]->sample[(i + 2) % 4] = s[4]; /* midpoint */ ep->child[i]->sample[(i + 3) % 4] = s[(i + 3) % 4]; ep->child[i]->discontinuity[i] = ep->discontinuity[i]; ep->child[i]->discontinuity[(i + 1) % 4] = (char) DINF; ep->child[i]->discontinuity[(i + 2) % 4] = (char) DINF; ep->child[i]->discontinuity[(i + 3) % 4] = ep->discontinuity[(i + 3) % 4]; } } else { for (i = 0; i < 3; i++) { ep->child[i]->sample[i] = ep->sample[i]; /* corners */ ep->child[i]->sample[(i + 1) % 3] = s[i]; ep->child[i]->sample[(i + 2) % 3] = s[(i + 2) % 3]; ep->child[i]->discontinuity[i] = ep->discontinuity[i]; ep->child[i]->discontinuity[(i + 1) % 3] = (char) DINF; ep->child[i]->discontinuity[(i + 2) % 3] = ep->discontinuity[(i + 2) % 3]; ep->child[3]->sample[i] = s[(i + 1) % 3]; ep->child[3]->discontinuity[i] = (char) DINF; } maxlen = 0.0; for (i = 0; i < 3; i++) { len = DistPnt2(ep->sample[i]->point2, ep->sample[(i + 1) % 3]->point2); if (len > maxlen) { maxlen = len; mi = i; } } len = DistPnt2(mids[(mi + 1) % 3],mids[(mi + 2) % 3]); maxlen = DistPnt2(mids[mi],ep->sample[(mi + 2) % 3]->point2); if (len > maxlen) { /* twist */ ep->child[(mi + 2) % 3]->sample[(mi + 1) % 3] = s[mi]; ep->child[(mi + 2) % 3]->discontinuity[(mi + 1) % 3] = (char) DINF; ep->child[3]->sample[(mi + 1) % 3] = ep->sample[(mi + 2) % 3]; ep->child[3]->discontinuity[mi] = ep->discontinuity[(mi + 1) % 3]; } } for (i = 0; i < ep->nChild; i++) calc_bbox_area(ep->child[i],surf); ep->leaf = 0; /* do down here 'cause of FindSample/Element */ params.nElements += ep->nChild - 1; /* ep itself is a node now */ return(news); } * twist */ ep->child[(mi + 2) % 3]->sample[(mi + 1) % 3] = s[mi]; ep->child[(mi + 2) % 3]->discontinuity[(mi + 1) % 3] = (char) DINF; ep->child[3]->sample[(mi + 1) % 3] = ep->sample[(mi + 2) % 3]; ep->cFxfire/surface.c000644 000316 000311 00000025236 06114620343 013724 0ustar00wrzlgup000000 000000 /***************************************************************************** * surface.c ******************************************************************************/ #include #include #include #include #include "rad.h" #include "geom.h" #include "dt.h" #include "log.h" /*#define DISPLAYMESH*/ /********************** surface point manipulation **************************/ #define FUDGE 1E-4 void ComputeWeights(TPoint2f *pts,int nPts,TPoint2f *point2,double *weight) { int i,old; TPoint2f temp; TVector2f v0,v1,v2; double alpha,beta,vol2; if (nPts > 4) error("ComputeWeights: can't handle more than quadrilaterals"); for (i = 0; i < nPts; i++) weight[i] = 0.0; old = nPts - 1; for (i = 0; i < nPts; i++) { /* check for the most common case first */ AvgVector2(temp,pts[old],pts[i]); if (PointEqual2(*point2,temp)) { weight[old] = 0.5; weight[i] = 0.5; return; } old = i; } SubVector2(v0,*point2,pts[0]); SubVector2(v1,pts[1],pts[0]); SubVector2(v2,pts[nPts - 1],pts[0]); #ifdef OLDVERSION if (v1.u == 0.0) { /* edge 0_1 is vertical */ beta = v0.u / v2.u; alpha = (v0.v - beta * v2.v) / v1.v; } else { beta = CrossVector2(v0,v1) / CrossVector(v2,v1); alpha = (v0.u - beta * v2.u) / v1.u; } #else vol2 = CrossVector2(v1,v2); /* 2 times vol of triangle */ alpha = CrossVector2(v0,v2) / vol2; beta = CrossVector2(v1,v0) / vol2; #endif if (alpha < -FUDGE || alpha > 1.0 + FUDGE || beta < -FUDGE || beta > 1.0 + FUDGE) message("WARNING: illegal weights %f %f\n",alpha,beta); if (nPts == 3 && alpha + beta > 1.0 + FUDGE) message("WARNING: illegal tri-weights %f %f\n",alpha,beta); if (alpha == -beta) { alpha = 0.0; beta = 0.0; } else { if (alpha < 0.0) alpha = 0.0; else if (alpha > 1.0) alpha = 1.0; if (beta < 0.0) beta = 0.0; else if (beta > 1.0) beta = 1.0; } if (nPts == 3) { weight[0] = (1.0 - alpha - beta); weight[1] = alpha; weight[2] = beta; } else { weight[0] = (1.0 - alpha) * (1.0 - beta); weight[1] = alpha * (1.0 - beta); weight[2] = alpha * beta; weight[3] = (1.0 - alpha) * beta; } } void SurfPoint(TSurface *surf,TPoint2f *point2,TPoint3f *point) { int i; TPoint3f temp; double weight[kMaxPolyPoints]; ComputeWeights(surf->vert2,surf->nPts,point2,weight); ZeroVector(*point); for (i = 0; i < surf->nPts; i++) { temp = surf->vert[i]; ScaleVector(temp,weight[i]); AddVector(*point,*point,temp); } } #define BORDER_SHIFT 1E-4 int CalcBorderShift(TSurface *surf,TSample *s0,TSample *s1,TPoint2f *point2, TPoint2f *shift) { double np,len,dist,shiftlen,reflen; TVector2f side,normal; reflen = DistPnt2(surf->min2,surf->max2); /* use diag as reference */ SubVector2(side,s1->point2,s0->point2); TurnVector2Right2(normal,side); NormalizeVector2(len,normal); np = DotVector2(s0->point2,normal); dist = DistPt2Line(*point2,normal,np); len = reflen * -BORDER_SHIFT; if (dist < len) /* o.k. to our left */ return(0); #ifdef DISPLAYMESH shiftlen = len * 50.0; #else shiftlen = len - dist; /* else we shift it */ #endif if (shiftlen > 0.0) /* as shift_vec should point to left now */ error("Calc Blowup"); *shift = normal; ScaleVector2(*shift,shiftlen); return(1); } void BorderShift(TSurface *surf,TElement *ep,TPoint2f *point2,TPoint3f *point) { int i; TPoint2f shifted,shiftvec; shifted = *point2; for (i = 0; i < ep->nPts; i++) { if (ep->discontinuity[i] != D0) continue; if (CalcBorderShift(surf,ep->sample[i],ep->sample[(i + 1) % ep->nPts], point2,&shiftvec)) AddVector2(shifted,shifted,shiftvec); } Project3d(*surf,shifted,*point); /* calc the 3d point */ } /************************** finders **************************/ TElement *FindElement(TElement *ep,TPoint2f *point2) { int i; TElement *element; if (ep == NULL) return(NULL); if (OutsideBbox2(ep->min,ep->max,*point2)) return(NULL); if (! ep->leaf) { /* look in all subtrees */ for (i = 0; i < ep->nChild; i++) { element = FindElement(ep->child[i],point2); if (element != NULL) return(element); } return(NULL); } for (i = 0; i < ep->nPts; i++) if (RightofPoints2(&ep->sample[i]->point2, &ep->sample[(i + 1) % ep->nPts]->point2,point2)) return(NULL); return(ep); } TSample* FindSample(TElement *ep,TPoint2f *point2) { int i; TSample *sp; if (ep == NULL) return(NULL); if (OutsideBbox2(ep->min,ep->max,*point2)) return(NULL); if (! ep->leaf) { /* look in all subtrees */ for (i = 0; i < ep->nChild; i++) { sp = FindSample(ep->child[i],point2); if (sp != NULL) /* hey, we found it ! */ return(sp); } return(NULL); } for (i = 0; i < ep->nPts; i++) { if (PointEqual2(*point2,ep->sample[i]->point2)) return(ep->sample[i]); /* hey, got it */ #ifdef NEVER if (PointNear2(*point2,ep->sample[i]->point2)) { message(" Near "); return(ep->sample[i]); /* very near */ } #endif } return(NULL); } TElement* FindSampleElement(TElement *ep,TSample *sp,TSample *next, int *sample_index) { int i; TElement *element; if (OutsideBbox2(ep->min,ep->max,sp->point2)) return(NULL); if (OutsideBbox2(ep->min,ep->max,next->point2)) return(NULL); if (! ep->leaf) { /* look in all subtrees */ for (i = 0; i < ep->nChild; i++) { element = FindSampleElement(ep->child[i],sp,next,sample_index); if (element != NULL) return(element); } } else { for (i = 0; i < ep->nPts; i++) /* was: ep->sample[i] == sp && ep->sample[(i + 1) % ep->nPts] == next */ if (PointEqual2(sp->point2,ep->sample[i]->point2) && PointEqual2(next->point2, ep->sample[(i + 1) % ep->nPts]->point2)) { *sample_index = i; return(ep); } } return(NULL); } #define A_LITTLE (1.0 / 65536.0) /* aka subdivlevel 16 */ TElement* FindNeighbourElement(TSurface *surf,TElement *ep,int side,int discos) { TElement *neigh; TPoint2f diff,mid; if (discos && ep->discontinuity[side] == D0) return(NULL); /* no one out there anyway */ SubVector2(mid,ep->sample[(side + 1) % ep->nPts]->point2, ep->sample[side]->point2); TurnVector2Right2(diff,mid); /* rotate 90 degrees */ ScaleVector2(diff,A_LITTLE); /* shrink it */ ScaleVector2(mid,0.31415926); /* somewhere on the way */ AddVector2(mid,ep->sample[side]->point2,mid); AddVector2(mid,mid,diff); /* point a little outside */ neigh = FindElement(surf->elements,&mid); return(neigh); } #define EPSILON 1.0E-3 void FindSamplesOnEdges(TElement *ep,TElement *tree,TSample **samples, int *nSamples) { int i,j,k; double side; TSample *s0,*s1; if (tree == ep) /* not ourselves */ return; if (BboxOutside2(ep->min,ep->max,tree->min,tree->max)) /* outside */ return; /* now we [bbox(ep)] are inside or intersect bbox(tree) */ if (! tree->leaf) { /* go down */ for (i = 0; i < tree->nChild; i++) FindSamplesOnEdges(ep,tree->child[i],samples,nSamples); return; } for (i = 0; i < tree->nPts; i++) { if (OutsideBbox2(ep->min,ep->max,tree->sample[i]->point2)) continue; for (j = 0; j < ep->nPts; j++) { if (PointEqual2(tree->sample[i]->point2,ep->sample[j]->point2)) { j = -1; break; } } if (j == -1) continue; /*pri_sample(tree->sample[i]);*/ s0 = ep->sample[ep->nPts - 1]; for (j = 0; j < ep->nPts; j++) { if (ep->discontinuity[(j + ep->nPts - 1) % ep->nPts] == D0) continue; /* none here ! */ s1 = ep->sample[j]; if (isonline(&tree->sample[i]->point2,&s0->point2,&s1->point2)) { for (k = 0; k < *nSamples; k++) if (PointEqual2(samples[k]->point2, tree->sample[i]->point2)) { k = -1; break; } if (k != -1) { samples[*nSamples] = tree->sample[i]; (*nSamples)++; } } else { side = calc_side(&s0->point2,&s1->point2, &tree->sample[i]->point2); if (side > 0.0) break; /* outside to the right */ } s0 = s1; } /*message("\n");*/ } return; } /************************** stuff for delaunay **************************/ static void CalcSampleArea(TSample *sample) { double area; TPoint2f pnt2; TPoint3f pts[3],first; VORONOIS *v; area = 0.0; Project3d(*sample->patch->surf,sample->point2,pts[0]); get_voronoi(sample->patch->surf->vd,sample->site_ptr,&v); InitPoint2(pnt2,v->from.x,v->from.y); Project3d(*sample->patch->surf,pnt2,pts[1]); first = pts[1]; v = v->next; while (v != NULL) { InitPoint2(pnt2,v->from.x,v->from.y); Project3d(*sample->patch->surf,pnt2,pts[2]); area += areaPoly(pts,3); pts[1] = pts[2]; v = v->next; } pts[2] = first; /* add last triangle */ area += areaPoly(pts,3); sample->area = area; /* save it */ } void Recalc_Areas(void) /* for delaunays */ { TSample *sp; TPatch *pp; FOR_ALL_PATCHES(pp) /* clear all patch areas */ pp->area = 0.0; END_ALL_PATCHES(pp) FOR_ALL_SAMPLES(sp) /* calc patch areas */ CalcSampleArea(sp); /* calc sample areas */ sp->patch->area += sp->area; /* add to patch area */ END_ALL_SAMPLES(sp) } static void CheckPatch(TPatch *pp) { double area_sum; TElement *ep; area_sum = 0.0; FOR_ALL_ELEMENTS(ep) if (ep->patch == pp) area_sum += ep->area; END_ALL_ELEMENTS(ep) if (fabs(area_sum - pp->area) > 1E-4 * area_sum) message("WARNING: Patch %d: Area %g != E-Sum %g: diff %g\n", pp->patchId,pp->area,area_sum,pp->area - area_sum); } static void CheckSurface(TSurface *surf) { double area_sum; TElement *ep; TPatch *pp; area_sum = 0.0; FOR_ALL_SURF_ELEMENTS(surf,ep) area_sum += ep->area; END_ALL_SURF_ELEMENTS(ep) if (fabs(area_sum - surf->area) > 1E-4 * area_sum) message("WARNING: Surface %d: Area %g != E-Sum %g: diff %g\n", surf->surfId,surf->area,area_sum,surf->area - area_sum); area_sum = 0.0; FOR_ALL_PATCHES(pp) /* check patch areas */ if (pp->surf == surf) area_sum += pp->area; END_ALL_PATCHES(pp) if (fabs(area_sum - surf->area) > 1E-4 * area_sum) message("WARNING: Surface %d: Area %g != P-Sum %g: diff %g\n", surf->surfId,surf->area,area_sum,surf->area - area_sum); } void CheckAllAreas(void) { double area; TPatch *pp; TSurface *surf; FOR_ALL_PATCHES(pp) /* check patch/element */ CheckPatch(pp); END_ALL_PATCHES(pp) FOR_ALL_SURFS(surf) CheckSurface(surf); /* check surf/patch&element */ END_ALL_SURFS(surf) if (params.delaunay) { /* check if ok */ FOR_ALL_SURFS(surf) area = 0.0; FOR_ALL_PATCHES(pp) if (pp->surf == surf) area += pp->area; END_ALL_PATCHES(pp) if (fabs(area - surf->area) > 1E-6 * area) message("WARNING: Surface %d: Area %g != PS-Sum %g\n", surf->surfId,surf->area,area); END_ALL_SURFS(surf) } } patch/element */ CheckPatch(pp); END_ALL_PATCHES(pp) FOR_ALL_SURFS(surf) CheckSurface(surf); /* check surf/patch&element */ END_ALL_SURFS(surf) if (params.delaunay) { /* check if ok */ FOR_ALL_SURFS(surf) area = 0.0; FOR_ALL_PATCHES(pp) if (pp->surf == surf) area += pp->area; END_ALL_PATCHES(pp) if (fabs(area -